Skip to content

Commit f2d0515

Browse files
committed
make sure that current price is used for new purchases of licenses
1 parent 06c18a4 commit f2d0515

File tree

5 files changed

+31
-19
lines changed

5 files changed

+31
-19
lines changed

src/packages/frontend/purchases/edit-license.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import type { Changes } from "@cocalc/util/purchases/cost-to-edit-license";
2323
import { isEqual } from "lodash";
2424
import { webapp_client } from "@cocalc/frontend/webapp-client";
2525
import { compute_cost } from "@cocalc/util/licenses/purchase/compute-cost";
26+
import { CURRENT_VERSION } from "@cocalc/util/licenses/purchase/consts";
2627

2728
interface Props {
2829
license_id: string;
@@ -112,6 +113,7 @@ export default function EditLicense({ license_id, refresh }: Props) {
112113
}
113114
subInfo.start = null;
114115
subInfo.end = null;
116+
subInfo.version = CURRENT_VERSION;
115117
setModifiedSubscriptionCost(compute_cost(subInfo).cost);
116118
}
117119
} catch (err) {
@@ -258,7 +260,7 @@ export default function EditLicense({ license_id, refresh }: Props) {
258260
modifiedSubscriptionCost != null &&
259261
modifiedSubscriptionCost != subscription.cost && (
260262
<>
261-
cost:{" "}
263+
cost at current rates:{" "}
262264
<b>
263265
{currency(modifiedSubscriptionCost)}/
264266
{subscription.interval}
@@ -270,17 +272,18 @@ export default function EditLicense({ license_id, refresh }: Props) {
270272
{subscription?.cost != null && (
271273
<div>
272274
{" "}
273-
Current cost: {currency(subscription?.cost)}/
274-
{subscription.interval}.
275+
What you currently pay: {currency(subscription?.cost)}/
276+
{subscription.interval}
275277
</div>
276278
)}
277279
{subscription != null &&
278280
modifiedSubscriptionCost != null &&
279281
modifiedSubscriptionCost != subscription.cost && (
280282
<div>
281283
<b>
282-
New cost: {currency(modifiedSubscriptionCost)}/
283-
{subscription.interval}.
284+
New cost after changes:{" "}
285+
{currency(modifiedSubscriptionCost)}/
286+
{subscription.interval}
284287
</b>
285288
</div>
286289
)}

src/packages/frontend/site-licenses/site-license-public-info.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ export const SiteLicensePublicInfoTable: React.FC<PropsTable> = (
342342
if (rec.expired) {
343343
return (
344344
<>
345-
Expired {when}.{delimiter}Could update {runLimit} running{" "}
345+
Expired {when}.{delimiter}Could upgrade {runLimit} running{" "}
346346
{plural(runLimit, "project")}.
347347
</>
348348
);

src/packages/util/licenses/purchase/cost-versions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const COST = {
5858
disk: 0.1,
5959
non_pre_factor: 3.5,
6060
},
61-
COST_MULTIPLIER: 1,
61+
COST_MULTIPLIER: 0.9,
6262
NONMEMBER_DENSITY: 2,
6363
ACADEMIC_DISCOUNT: 0.6,
6464
DISK_FACTOR: 10,

src/packages/util/licenses/purchase/purchase-info.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { CURRENT_VERSION } from "./consts";
77
import type { Date0 } from "@cocalc/util/types/store";
88
import dayjs from "dayjs";
99

10+
// this ALWAYS returns purchaseInfo that is the *current* version.
1011
export default function getPurchaseInfo(
1112
conf: SiteLicenseDescriptionDB,
1213
): PurchaseInfo {

src/packages/util/purchases/cost-to-edit-license.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { LicenseIdleTimeouts } from "@cocalc/util/consts/site-license";
99
import type { Uptime } from "@cocalc/util/consts/site-license";
1010
import { MAX } from "@cocalc/util/licenses/purchase/consts";
1111
import { round2up } from "../misc";
12+
import { CURRENT_VERSION } from "@cocalc/util/licenses/purchase/consts";
1213

1314
export interface Changes {
1415
end?: Date;
@@ -104,7 +105,9 @@ export default function costToEditLicense(
104105
log("editLicense with start date updated:", { origInfo });
105106

106107
// Make copy of data with modified params.
107-
const modifiedInfo = cloneDeep(origInfo);
108+
// modifiedInfo uses the current default pricing algorithm, since that the cost today
109+
// to make this purchase, hence changing version below.
110+
const modifiedInfo = { ...cloneDeep(origInfo), version: CURRENT_VERSION };
108111
if (changes.start != null) {
109112
modifiedInfo.start = changes.start;
110113
}
@@ -222,6 +225,8 @@ export default function costToEditLicense(
222225
log({ modifiedInfo });
223226

224227
// Determine price for the change
228+
229+
// the value of the license the user currently owned. The pricing algorithm version is important here.
225230
const currentValue = currentLicenseValue(origInfo);
226231

227232
if (numChanges > 0 && modifiedInfo.type == "quota") {
@@ -234,6 +239,9 @@ export default function costToEditLicense(
234239
delete modifiedInfo.cost_per_hour;
235240
}
236241

242+
// Determine price for the modified license they would like to switch to.
243+
// modifiedInfo uses the current default pricing algorithm, since that the cost today
244+
// to make this purchase, hence changing version below.
237245
const modifiedValue = currentLicenseValue(modifiedInfo);
238246
// cost can be negative, when we give user a refund.
239247
// **We round away from zero!** The reason is because
@@ -288,17 +296,17 @@ function currentLicenseValue(info: PurchaseInfo): number {
288296
// Perhaps we won't raise rates before switching to a full
289297
// pay as you go model....
290298

291-
// if (info.cost_per_hour) {
292-
// // if this is set, we use it to compute the value
293-
// // The value is cost_per_hour times the number of hours left until info.end.
294-
// const end = dayjs(info.end);
295-
// const start = dayjs(info.start);
296-
// const hoursRemaining = end.diff(start, "hours", true);
297-
// // the hoursRemaining can easily be *negative* if info.end is
298-
// // in the past.
299-
// // However the value of a license is never negative, so we max with 0.
300-
// return Math.max(0, hoursRemaining * info.cost_per_hour);
301-
// }
299+
// if (info.cost_per_hour) {
300+
// // if this is set, we use it to compute the value
301+
// // The value is cost_per_hour times the number of hours left until info.end.
302+
// const end = dayjs(info.end);
303+
// const start = dayjs(info.start);
304+
// const hoursRemaining = end.diff(start, "hours", true);
305+
// // the hoursRemaining can easily be *negative* if info.end is
306+
// // in the past.
307+
// // However the value of a license is never negative, so we max with 0.
308+
// return Math.max(0, hoursRemaining * info.cost_per_hour);
309+
// }
302310

303311
// Compute value using the current rate.
304312
// As mentioned above, we can keep old rates if/when we change the rate,

0 commit comments

Comments
 (0)