Path: blob/master/src/packages/frontend/client/purchases.ts
1503 views
/*1Functions for interfacing with the purchases functionality.23TODO/DEPRECATE: this module is mostly pointless since I moved essentially4all of this code to @cocalc/frontend/purchases/api, which is much better5since it can also be used directly by our nextjs app, and also is6scoped better. That said quotaModal is here.7*/89import type { Service } from "@cocalc/util/db-schema/purchases";10import { redux } from "@cocalc/frontend/app-framework";11import { once } from "@cocalc/util/async-utils";12import type { ProjectQuota } from "@cocalc/util/db-schema/purchase-quotas";13import * as purchasesApi from "@cocalc/frontend/purchases/api";14import type { Changes as EditLicenseChanges } from "@cocalc/util/purchases/cost-to-edit-license";15import { round2up } from "@cocalc/util/misc";16import type { WebappClient } from "./client";1718export class PurchasesClient {19api: typeof purchasesApi;20client: WebappClient;2122constructor(client: WebappClient) {23this.api = purchasesApi;24this.client = client;25}26async getQuotas(): Promise<{27minBalance: number;28services: { [service: string]: number };29}> {30return await purchasesApi.getQuotas();31}3233async getBalance(): Promise<number> {34return await this.client.conat_client.hub.purchases.getBalance();35}3637async getSpendRate(): Promise<number> {38return await purchasesApi.getSpendRate();39}4041async getClosingDates(): Promise<{ last: Date; next: Date }> {42return await purchasesApi.getClosingDates();43}4445async setQuota(46service: Service,47value: number,48): Promise<{ global: number; services: { [service: string]: number } }> {49return await purchasesApi.setQuota(service, value);50}5152async isPurchaseAllowed(53service: Service,54cost?: number,55): Promise<{ allowed: boolean; reason?: string; chargeAmount?: number }> {56return await purchasesApi.isPurchaseAllowed(service, cost);57}5859async getPurchases(opts: {60thisMonth?: boolean; // if true, limit and offset are ignored61limit?: number;62offset?: number;63service?: Service;64project_id?: string;65group?: boolean;66}) {67return await purchasesApi.getPurchases(opts);68}6970async editLicense(opts: { license_id: string; changes: EditLicenseChanges }) {71return await purchasesApi.editLicense(opts);72}7374async getInvoice(invoice_id: string) {75return await purchasesApi.getInvoice(invoice_id);76}7778async getCostPerDay(opts: { limit?: number; offset?: number }) {79return await purchasesApi.getCostPerDay(opts);80}8182async quotaModal({83service,84cost,85allowed,86reason,87cost_per_hour,88}: {89service?: Service;90// cost = how much you have to have available in your account91cost?: number;92allowed?: boolean;93reason?: string;94// the rate if this is a pay-as-you-go metered purchase.95cost_per_hour?: number;96} = {}): Promise<void> {97const actions = redux.getActions("billing");98actions.setState({99pay_as_you_go: {100showModal: true,101service,102cost: cost != null ? round2up(cost) : cost,103reason,104allowed,105cost_per_hour,106} as any,107});108await waitUntilPayAsYouGoModalCloses();109}110111async getCustomer() {112return await purchasesApi.getCustomer();113}114115async getChargesByService() {116return await purchasesApi.getChargesByService();117}118119async getCurrentCheckoutSession() {120return await purchasesApi.getCurrentCheckoutSession();121}122123async getUnpaidInvoices(): Promise<any[]> {124return await purchasesApi.getUnpaidInvoices();125}126127async getServiceCost(service: Service): Promise<any> {128return await purchasesApi.getServiceCost(service);129}130131async getMinimumPayment(): Promise<number> {132return await purchasesApi.getMinimumPayment();133}134135async setPayAsYouGoProjectQuotas(project_id: string, quota: ProjectQuota) {136await purchasesApi.setPayAsYouGoProjectQuotas(project_id, quota);137}138139async getPayAsYouGoMaxProjectQuotas(): Promise<ProjectQuota> {140return await purchasesApi.getPayAsYouGoMaxProjectQuotas();141}142143async getPayAsYouGoPricesProjectQuotas(): Promise<{144cores: number;145disk_quota: number;146memory: number;147member_host: number;148}> {149return await purchasesApi.getPayAsYouGoPricesProjectQuotas();150}151152// this is only used in the nextjs store app right now...153async getShoppingCartCheckoutParams() {154return await purchasesApi.getShoppingCartCheckoutParams();155}156157async adminGetMinBalance(account_id: string): Promise<number> {158return await purchasesApi.adminGetMinBalance(account_id);159}160161async adminSetMinBalance(account_id: string, minBalance: number) {162await purchasesApi.adminSetMinBalance(account_id, minBalance);163}164165async getLicense(license_id: string) {166return await purchasesApi.getLicense({ license_id });167}168169async renewSubscription(170subscription_id: number,171): Promise<{ purchase_id: number | null }> {172return await purchasesApi.renewSubscription(subscription_id);173}174175async getLiveSubscriptions() {176return await purchasesApi.getLiveSubscriptions();177}178}179180async function waitUntilPayAsYouGoModalCloses() {181const store = redux.getStore("billing");182while (true) {183await once(store, "change");184if (!store.getIn(["pay_as_you_go", "showModal"])) {185return;186}187}188}189190191