Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/client/purchases.ts
1503 views
1
/*
2
Functions for interfacing with the purchases functionality.
3
4
TODO/DEPRECATE: this module is mostly pointless since I moved essentially
5
all of this code to @cocalc/frontend/purchases/api, which is much better
6
since it can also be used directly by our nextjs app, and also is
7
scoped better. That said quotaModal is here.
8
*/
9
10
import type { Service } from "@cocalc/util/db-schema/purchases";
11
import { redux } from "@cocalc/frontend/app-framework";
12
import { once } from "@cocalc/util/async-utils";
13
import type { ProjectQuota } from "@cocalc/util/db-schema/purchase-quotas";
14
import * as purchasesApi from "@cocalc/frontend/purchases/api";
15
import type { Changes as EditLicenseChanges } from "@cocalc/util/purchases/cost-to-edit-license";
16
import { round2up } from "@cocalc/util/misc";
17
import type { WebappClient } from "./client";
18
19
export class PurchasesClient {
20
api: typeof purchasesApi;
21
client: WebappClient;
22
23
constructor(client: WebappClient) {
24
this.api = purchasesApi;
25
this.client = client;
26
}
27
async getQuotas(): Promise<{
28
minBalance: number;
29
services: { [service: string]: number };
30
}> {
31
return await purchasesApi.getQuotas();
32
}
33
34
async getBalance(): Promise<number> {
35
return await this.client.conat_client.hub.purchases.getBalance();
36
}
37
38
async getSpendRate(): Promise<number> {
39
return await purchasesApi.getSpendRate();
40
}
41
42
async getClosingDates(): Promise<{ last: Date; next: Date }> {
43
return await purchasesApi.getClosingDates();
44
}
45
46
async setQuota(
47
service: Service,
48
value: number,
49
): Promise<{ global: number; services: { [service: string]: number } }> {
50
return await purchasesApi.setQuota(service, value);
51
}
52
53
async isPurchaseAllowed(
54
service: Service,
55
cost?: number,
56
): Promise<{ allowed: boolean; reason?: string; chargeAmount?: number }> {
57
return await purchasesApi.isPurchaseAllowed(service, cost);
58
}
59
60
async getPurchases(opts: {
61
thisMonth?: boolean; // if true, limit and offset are ignored
62
limit?: number;
63
offset?: number;
64
service?: Service;
65
project_id?: string;
66
group?: boolean;
67
}) {
68
return await purchasesApi.getPurchases(opts);
69
}
70
71
async editLicense(opts: { license_id: string; changes: EditLicenseChanges }) {
72
return await purchasesApi.editLicense(opts);
73
}
74
75
async getInvoice(invoice_id: string) {
76
return await purchasesApi.getInvoice(invoice_id);
77
}
78
79
async getCostPerDay(opts: { limit?: number; offset?: number }) {
80
return await purchasesApi.getCostPerDay(opts);
81
}
82
83
async quotaModal({
84
service,
85
cost,
86
allowed,
87
reason,
88
cost_per_hour,
89
}: {
90
service?: Service;
91
// cost = how much you have to have available in your account
92
cost?: number;
93
allowed?: boolean;
94
reason?: string;
95
// the rate if this is a pay-as-you-go metered purchase.
96
cost_per_hour?: number;
97
} = {}): Promise<void> {
98
const actions = redux.getActions("billing");
99
actions.setState({
100
pay_as_you_go: {
101
showModal: true,
102
service,
103
cost: cost != null ? round2up(cost) : cost,
104
reason,
105
allowed,
106
cost_per_hour,
107
} as any,
108
});
109
await waitUntilPayAsYouGoModalCloses();
110
}
111
112
async getCustomer() {
113
return await purchasesApi.getCustomer();
114
}
115
116
async getChargesByService() {
117
return await purchasesApi.getChargesByService();
118
}
119
120
async getCurrentCheckoutSession() {
121
return await purchasesApi.getCurrentCheckoutSession();
122
}
123
124
async getUnpaidInvoices(): Promise<any[]> {
125
return await purchasesApi.getUnpaidInvoices();
126
}
127
128
async getServiceCost(service: Service): Promise<any> {
129
return await purchasesApi.getServiceCost(service);
130
}
131
132
async getMinimumPayment(): Promise<number> {
133
return await purchasesApi.getMinimumPayment();
134
}
135
136
async setPayAsYouGoProjectQuotas(project_id: string, quota: ProjectQuota) {
137
await purchasesApi.setPayAsYouGoProjectQuotas(project_id, quota);
138
}
139
140
async getPayAsYouGoMaxProjectQuotas(): Promise<ProjectQuota> {
141
return await purchasesApi.getPayAsYouGoMaxProjectQuotas();
142
}
143
144
async getPayAsYouGoPricesProjectQuotas(): Promise<{
145
cores: number;
146
disk_quota: number;
147
memory: number;
148
member_host: number;
149
}> {
150
return await purchasesApi.getPayAsYouGoPricesProjectQuotas();
151
}
152
153
// this is only used in the nextjs store app right now...
154
async getShoppingCartCheckoutParams() {
155
return await purchasesApi.getShoppingCartCheckoutParams();
156
}
157
158
async adminGetMinBalance(account_id: string): Promise<number> {
159
return await purchasesApi.adminGetMinBalance(account_id);
160
}
161
162
async adminSetMinBalance(account_id: string, minBalance: number) {
163
await purchasesApi.adminSetMinBalance(account_id, minBalance);
164
}
165
166
async getLicense(license_id: string) {
167
return await purchasesApi.getLicense({ license_id });
168
}
169
170
async renewSubscription(
171
subscription_id: number,
172
): Promise<{ purchase_id: number | null }> {
173
return await purchasesApi.renewSubscription(subscription_id);
174
}
175
176
async getLiveSubscriptions() {
177
return await purchasesApi.getLiveSubscriptions();
178
}
179
}
180
181
async function waitUntilPayAsYouGoModalCloses() {
182
const store = redux.getStore("billing");
183
while (true) {
184
await once(store, "change");
185
if (!store.getIn(["pay_as_you_go", "showModal"])) {
186
return;
187
}
188
}
189
}
190
191