@goweekdays/core 2.11.11 → 2.11.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +98 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +98 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -5435,6 +5435,7 @@ var schemaSubscriptionCompute = Joi20.object({
|
|
|
5435
5435
|
seats: Joi20.number().integer().min(1).required(),
|
|
5436
5436
|
plan: Joi20.string().hex().length(24).required(),
|
|
5437
5437
|
promoCode: Joi20.string().optional().allow("", null),
|
|
5438
|
+
nextPromoCode: Joi20.string().optional().allow("", null),
|
|
5438
5439
|
org: Joi20.string().hex().length(24).required()
|
|
5439
5440
|
});
|
|
5440
5441
|
var schemaSubscribe = Joi20.object({
|
|
@@ -5453,6 +5454,7 @@ var schema2 = {
|
|
|
5453
5454
|
};
|
|
5454
5455
|
var schemaSubscription = Joi20.object({
|
|
5455
5456
|
...schema2,
|
|
5457
|
+
billingPeriodStart: Joi20.date().optional().allow("", null),
|
|
5456
5458
|
org: Joi20.string().hex().length(24).required(),
|
|
5457
5459
|
orgName: Joi20.string().optional().allow("", null),
|
|
5458
5460
|
currency: Joi20.string().length(3).required(),
|
|
@@ -5499,9 +5501,11 @@ function modelSubscription(data) {
|
|
|
5499
5501
|
amount: data.amount,
|
|
5500
5502
|
currency: data.currency,
|
|
5501
5503
|
billingCycle: data.billingCycle,
|
|
5502
|
-
promoCode: data.promoCode,
|
|
5504
|
+
promoCode: data.promoCode ?? "",
|
|
5505
|
+
nextPromoCode: data.nextPromoCode ?? "",
|
|
5503
5506
|
status: data.status ?? "active",
|
|
5504
5507
|
retry: data.retry ?? 0,
|
|
5508
|
+
billingPeriodStart: data.billingPeriodStart,
|
|
5505
5509
|
nextBillingDate: data.nextBillingDate,
|
|
5506
5510
|
createdAt: data.createdAt ?? /* @__PURE__ */ new Date(),
|
|
5507
5511
|
updatedAt: data.updatedAt ?? ""
|
|
@@ -5822,7 +5826,9 @@ function useSubscriptionRepo() {
|
|
|
5822
5826
|
paidSeats: Joi21.number().integer().min(0).optional(),
|
|
5823
5827
|
amount: Joi21.number().positive().optional().allow(0),
|
|
5824
5828
|
promoCode: Joi21.string().max(50).optional().allow("", null),
|
|
5829
|
+
nextPromoCode: Joi21.string().max(50).optional().allow("", null),
|
|
5825
5830
|
status: Joi21.string().valid("active", "due", "overdue", "suspended").optional().allow("", null),
|
|
5831
|
+
billingPeriodStart: Joi21.date().optional().allow("", null),
|
|
5826
5832
|
nextBillingDate: Joi21.date().optional().allow("", null)
|
|
5827
5833
|
});
|
|
5828
5834
|
const { error } = validation.validate(options);
|
|
@@ -5992,7 +5998,17 @@ var schemaSubscriptionTransaction = Joi22.object({
|
|
|
5992
5998
|
"promo-expired",
|
|
5993
5999
|
"promo-updated"
|
|
5994
6000
|
).required(),
|
|
5995
|
-
|
|
6001
|
+
metadata: Joi22.object({
|
|
6002
|
+
additionalSeats: Joi22.number().integer().min(1).optional(),
|
|
6003
|
+
seats: Joi22.number().integer().min(0).optional(),
|
|
6004
|
+
paidSeats: Joi22.number().integer().min(0).optional(),
|
|
6005
|
+
plan: Joi22.string().hex().length(24).optional(),
|
|
6006
|
+
promoCode: Joi22.string().optional().allow("", null),
|
|
6007
|
+
nextPromoCode: Joi22.string().optional().allow("", null),
|
|
6008
|
+
billingPeriodStart: Joi22.date().optional().allow("", null),
|
|
6009
|
+
nextBillingDate: Joi22.date().optional().allow("", null)
|
|
6010
|
+
}).optional(),
|
|
6011
|
+
description: Joi22.string().optional().allow("", null),
|
|
5996
6012
|
createdBy: Joi22.string().hex().length(24).required(),
|
|
5997
6013
|
createdByName: Joi22.string().optional().allow("", null)
|
|
5998
6014
|
});
|
|
@@ -6030,6 +6046,7 @@ function modelSubscriptionTransaction(data) {
|
|
|
6030
6046
|
amount: data.amount,
|
|
6031
6047
|
currency: data.currency,
|
|
6032
6048
|
type: data.type,
|
|
6049
|
+
metadata: data.metadata ?? {},
|
|
6033
6050
|
description: data.description ?? "",
|
|
6034
6051
|
createdBy: data.createdBy,
|
|
6035
6052
|
createdByName: data.createdByName,
|
|
@@ -8444,13 +8461,42 @@ function useSubscriptionService() {
|
|
|
8444
8461
|
case "fixed":
|
|
8445
8462
|
return Math.min(seats, limit) * (promo.fixedRate ?? 0) + Math.max(seats - limit, 0) * planPrice;
|
|
8446
8463
|
case "flat":
|
|
8447
|
-
return (promo.flatRate ?? 0) + Math.max(seats - limit
|
|
8464
|
+
return (promo.flatRate ?? 0) + Math.max(0, seats - limit) * planPrice;
|
|
8448
8465
|
case "volume":
|
|
8449
8466
|
return promo.tiers?.length ? calculateVolumeTierAmount(promo.tiers, 1, seats, planPrice) : planPrice * seats;
|
|
8450
8467
|
default:
|
|
8451
8468
|
return planPrice * seats;
|
|
8452
8469
|
}
|
|
8453
8470
|
}
|
|
8471
|
+
function computeAdditionalSeatAmount(additionalSeats, planPrice, promo, paidSeats) {
|
|
8472
|
+
if (additionalSeats <= 0)
|
|
8473
|
+
return 0;
|
|
8474
|
+
if (!promo) {
|
|
8475
|
+
return additionalSeats * planPrice;
|
|
8476
|
+
}
|
|
8477
|
+
const limit = promo.seats && promo.seats > 0 ? promo.seats : Infinity;
|
|
8478
|
+
switch (promo.type) {
|
|
8479
|
+
case "flat": {
|
|
8480
|
+
const chargeableSeats = Math.max(0, paidSeats + additionalSeats - limit) - Math.max(0, paidSeats - limit);
|
|
8481
|
+
return chargeableSeats * planPrice;
|
|
8482
|
+
}
|
|
8483
|
+
case "fixed": {
|
|
8484
|
+
const promoSeatsLeft = Math.max(0, limit - paidSeats);
|
|
8485
|
+
const promoSeats = Math.min(additionalSeats, promoSeatsLeft);
|
|
8486
|
+
const normalSeats = additionalSeats - promoSeats;
|
|
8487
|
+
return promoSeats * (promo.fixedRate ?? 0) + normalSeats * planPrice;
|
|
8488
|
+
}
|
|
8489
|
+
case "volume":
|
|
8490
|
+
return promo.tiers?.length ? calculateVolumeTierAmount(
|
|
8491
|
+
promo.tiers,
|
|
8492
|
+
paidSeats + 1,
|
|
8493
|
+
additionalSeats,
|
|
8494
|
+
planPrice
|
|
8495
|
+
) : additionalSeats * planPrice;
|
|
8496
|
+
default:
|
|
8497
|
+
return additionalSeats * planPrice;
|
|
8498
|
+
}
|
|
8499
|
+
}
|
|
8454
8500
|
function computeProration(subscription, seats, plan, promo) {
|
|
8455
8501
|
const additionalSeats = Math.max(0, seats - subscription.paidSeats);
|
|
8456
8502
|
if (additionalSeats === 0)
|
|
@@ -8464,10 +8510,11 @@ function useSubscriptionService() {
|
|
|
8464
8510
|
const cycleDays = plan.billingCycle === "yearly" ? 365 : 30;
|
|
8465
8511
|
if (daysRemaining === 0)
|
|
8466
8512
|
return 0;
|
|
8467
|
-
const additionalAmount =
|
|
8513
|
+
const additionalAmount = computeAdditionalSeatAmount(
|
|
8468
8514
|
additionalSeats,
|
|
8469
8515
|
plan.price,
|
|
8470
|
-
promo
|
|
8516
|
+
promo,
|
|
8517
|
+
subscription.paidSeats
|
|
8471
8518
|
);
|
|
8472
8519
|
return additionalAmount / cycleDays * daysRemaining;
|
|
8473
8520
|
}
|
|
@@ -8483,7 +8530,6 @@ function useSubscriptionService() {
|
|
|
8483
8530
|
const isNew = !existingSubscription;
|
|
8484
8531
|
const isPromoChange = !!existingSubscription && value.promoCode !== void 0 && value.promoCode !== existingSubscription.promoCode;
|
|
8485
8532
|
const isSeatIncrease = !!existingSubscription && value.seats > existingSubscription.seats;
|
|
8486
|
-
const isSeatDecrease = !!existingSubscription && value.seats < existingSubscription.seats;
|
|
8487
8533
|
if (isPromoChange && isSeatIncrease) {
|
|
8488
8534
|
throw new BadRequestError41(
|
|
8489
8535
|
"Cannot change promo code while increasing seats. Perform actions separately."
|
|
@@ -8553,7 +8599,8 @@ function useSubscriptionService() {
|
|
|
8553
8599
|
if (!membership) {
|
|
8554
8600
|
throw new BadRequestError41("User is not a member of the organization.");
|
|
8555
8601
|
}
|
|
8556
|
-
const
|
|
8602
|
+
const billingPeriodStart = /* @__PURE__ */ new Date();
|
|
8603
|
+
const nextBillingDate = new Date(billingPeriodStart);
|
|
8557
8604
|
nextBillingDate.setDate(nextBillingDate.getDate() + 30);
|
|
8558
8605
|
const { subscriptionAmount, currency } = await computeFee({
|
|
8559
8606
|
seats: value.seats,
|
|
@@ -8578,6 +8625,7 @@ function useSubscriptionService() {
|
|
|
8578
8625
|
amount: subscriptionAmount,
|
|
8579
8626
|
currency,
|
|
8580
8627
|
billingCycle: plan.billingCycle,
|
|
8628
|
+
billingPeriodStart,
|
|
8581
8629
|
nextBillingDate,
|
|
8582
8630
|
promoCode: value.promoCode
|
|
8583
8631
|
},
|
|
@@ -8681,7 +8729,17 @@ function useSubscriptionService() {
|
|
|
8681
8729
|
currency,
|
|
8682
8730
|
subscription: subscription._id?.toString() ?? "",
|
|
8683
8731
|
createdBy: value.user,
|
|
8684
|
-
createdByName: `${userData.firstName} ${userData.lastName}
|
|
8732
|
+
createdByName: `${userData.firstName} ${userData.lastName}`,
|
|
8733
|
+
metadata: {
|
|
8734
|
+
additionalSeats,
|
|
8735
|
+
seats: value.seats,
|
|
8736
|
+
paidSeats,
|
|
8737
|
+
plan: value.plan ?? "",
|
|
8738
|
+
promoCode: subscription.promoCode ?? "",
|
|
8739
|
+
nextPromoCode: subscription.nextPromoCode ?? "",
|
|
8740
|
+
billingPeriodStart: subscription.billingPeriodStart,
|
|
8741
|
+
nextBillingDate: subscription.nextBillingDate
|
|
8742
|
+
}
|
|
8685
8743
|
},
|
|
8686
8744
|
session
|
|
8687
8745
|
);
|
|
@@ -8746,7 +8804,7 @@ function useSubscriptionService() {
|
|
|
8746
8804
|
});
|
|
8747
8805
|
await updateById(
|
|
8748
8806
|
subscription._id?.toString() ?? "",
|
|
8749
|
-
{
|
|
8807
|
+
{ nextPromoCode: value.promoCode ?? "" },
|
|
8750
8808
|
session
|
|
8751
8809
|
);
|
|
8752
8810
|
if (subscription.promoCode) {
|
|
@@ -8757,7 +8815,7 @@ function useSubscriptionService() {
|
|
|
8757
8815
|
{
|
|
8758
8816
|
promo: promo._id,
|
|
8759
8817
|
org: value.org,
|
|
8760
|
-
usedBy:
|
|
8818
|
+
usedBy: value.user
|
|
8761
8819
|
},
|
|
8762
8820
|
session
|
|
8763
8821
|
);
|
|
@@ -8765,12 +8823,19 @@ function useSubscriptionService() {
|
|
|
8765
8823
|
await addTransaction(
|
|
8766
8824
|
{
|
|
8767
8825
|
type: "promo-updated",
|
|
8768
|
-
description: `
|
|
8826
|
+
description: `Promo code ${value.promoCode || "removed"} scheduled to take effect on the next billing cycle.`,
|
|
8769
8827
|
amount: 0,
|
|
8770
|
-
currency,
|
|
8828
|
+
currency: subscription.currency,
|
|
8771
8829
|
subscription: subscription._id?.toString() ?? "",
|
|
8772
8830
|
createdBy: value.user,
|
|
8773
|
-
|
|
8831
|
+
metadata: {
|
|
8832
|
+
seats: subscription.seats,
|
|
8833
|
+
paidSeats: subscription.paidSeats,
|
|
8834
|
+
promoCode: subscription.promoCode,
|
|
8835
|
+
nextPromoCode: value.promoCode ?? "",
|
|
8836
|
+
billingPeriodStart: subscription.billingPeriodStart,
|
|
8837
|
+
nextBillingDate: subscription.nextBillingDate
|
|
8838
|
+
}
|
|
8774
8839
|
},
|
|
8775
8840
|
session
|
|
8776
8841
|
);
|
|
@@ -8930,39 +8995,43 @@ function useSubscriptionService() {
|
|
|
8930
8995
|
}
|
|
8931
8996
|
const ledgerBill = await getByInvoice(invoiceId);
|
|
8932
8997
|
if (!ledgerBill) {
|
|
8933
|
-
throw new BadRequestError41(
|
|
8934
|
-
"Ledger bill not found for the given invoice ID."
|
|
8935
|
-
);
|
|
8998
|
+
throw new BadRequestError41("Ledger bill not found.");
|
|
8936
8999
|
}
|
|
8937
9000
|
const orgId = String(ledgerBill.org);
|
|
8938
|
-
const org = await getOrgById(orgId);
|
|
8939
|
-
if (!org) {
|
|
8940
|
-
throw new BadRequestError41("Organization not found for the ledger bill.");
|
|
8941
|
-
}
|
|
8942
9001
|
const subscription = await getByOrg(orgId);
|
|
8943
9002
|
if (!subscription) {
|
|
8944
|
-
throw new BadRequestError41("Subscription not found
|
|
9003
|
+
throw new BadRequestError41("Subscription not found.");
|
|
8945
9004
|
}
|
|
8946
9005
|
const plan = await getDefaultPlan();
|
|
8947
9006
|
if (!plan) {
|
|
8948
|
-
throw new BadRequestError41("
|
|
9007
|
+
throw new BadRequestError41("Plan not found.");
|
|
8949
9008
|
}
|
|
8950
9009
|
const session = useAtlas18.getClient()?.startSession();
|
|
8951
9010
|
if (!session) {
|
|
8952
|
-
throw new
|
|
9011
|
+
throw new InternalServerError22("Unable to start database session.");
|
|
8953
9012
|
}
|
|
8954
9013
|
try {
|
|
8955
9014
|
session.startTransaction();
|
|
8956
|
-
const
|
|
8957
|
-
const nextBillingDate =
|
|
9015
|
+
const billingPeriodStart = /* @__PURE__ */ new Date();
|
|
9016
|
+
const nextBillingDate = new Date(billingPeriodStart);
|
|
8958
9017
|
nextBillingDate.setMonth(nextBillingDate.getMonth() + 1);
|
|
9018
|
+
const effectivePromoCode = subscription.nextPromoCode || subscription.promoCode;
|
|
9019
|
+
const promo = effectivePromoCode ? await getPromoByCode(effectivePromoCode) : null;
|
|
9020
|
+
const monthlyAmount = computeMonthlyAmount(
|
|
9021
|
+
subscription.seats,
|
|
9022
|
+
plan.price,
|
|
9023
|
+
promo
|
|
9024
|
+
);
|
|
8959
9025
|
await updateById(
|
|
8960
|
-
|
|
9026
|
+
subscription._id?.toString() ?? "",
|
|
8961
9027
|
{
|
|
8962
9028
|
status: "active",
|
|
9029
|
+
billingPeriodStart,
|
|
8963
9030
|
nextBillingDate,
|
|
8964
9031
|
paidSeats: subscription.seats,
|
|
8965
|
-
amount:
|
|
9032
|
+
amount: Math.round(monthlyAmount * 100) / 100,
|
|
9033
|
+
promoCode: effectivePromoCode,
|
|
9034
|
+
nextPromoCode: ""
|
|
8966
9035
|
},
|
|
8967
9036
|
session
|
|
8968
9037
|
);
|
|
@@ -8973,14 +9042,7 @@ function useSubscriptionService() {
|
|
|
8973
9042
|
return "Successfully processed paid invoice.";
|
|
8974
9043
|
} catch (error2) {
|
|
8975
9044
|
await session.abortTransaction();
|
|
8976
|
-
|
|
8977
|
-
level: "error",
|
|
8978
|
-
message: `Failed to process paid invoice ${invoiceId}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
8979
|
-
});
|
|
8980
|
-
if (error2 instanceof AppError20) {
|
|
8981
|
-
throw error2;
|
|
8982
|
-
}
|
|
8983
|
-
throw new InternalServerError22("Failed to process paid invoice.");
|
|
9045
|
+
throw error2;
|
|
8984
9046
|
} finally {
|
|
8985
9047
|
session.endSession();
|
|
8986
9048
|
}
|
|
@@ -9520,6 +9582,7 @@ function useOrgService() {
|
|
|
9520
9582
|
paidSeats: value.seats,
|
|
9521
9583
|
currency: plan.currency,
|
|
9522
9584
|
billingCycle: plan.billingCycle,
|
|
9585
|
+
billingPeriodStart: currentDate,
|
|
9523
9586
|
nextBillingDate
|
|
9524
9587
|
},
|
|
9525
9588
|
session
|