@goweekdays/core 2.11.1 → 2.11.3
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 +13 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +110 -96
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +110 -96
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @goweekdays/core
|
|
2
2
|
|
|
3
|
+
## 2.11.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2bb4eb2: Add orgName to subscription and refactor service logic
|
|
8
|
+
|
|
9
|
+
## 2.11.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- d27a91f: Fix seat decrease billing logic in subscription service
|
|
14
|
+
- 69837e4: Allow zero amount in subscription schema and fix promo calc
|
|
15
|
+
|
|
3
16
|
## 2.11.1
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -5446,13 +5446,14 @@ var schemaSubscribe = import_joi20.default.object({
|
|
|
5446
5446
|
var schema2 = {
|
|
5447
5447
|
seats: import_joi20.default.number().integer().min(1).required(),
|
|
5448
5448
|
paidSeats: import_joi20.default.number().integer().min(0).required(),
|
|
5449
|
-
amount: import_joi20.default.number().positive().required(),
|
|
5449
|
+
amount: import_joi20.default.number().positive().required().allow(0),
|
|
5450
5450
|
promoCode: import_joi20.default.string().optional().allow("", null),
|
|
5451
5451
|
nextBillingDate: import_joi20.default.date().optional().allow("", null)
|
|
5452
5452
|
};
|
|
5453
5453
|
var schemaSubscription = import_joi20.default.object({
|
|
5454
5454
|
...schema2,
|
|
5455
5455
|
org: import_joi20.default.string().hex().length(24).required(),
|
|
5456
|
+
orgName: import_joi20.default.string().optional().allow("", null),
|
|
5456
5457
|
currency: import_joi20.default.string().length(3).required(),
|
|
5457
5458
|
billingCycle: import_joi20.default.string().valid("monthly", "yearly").required()
|
|
5458
5459
|
});
|
|
@@ -5491,6 +5492,7 @@ function modelSubscription(data) {
|
|
|
5491
5492
|
return {
|
|
5492
5493
|
_id: data._id,
|
|
5493
5494
|
org: data.org,
|
|
5495
|
+
orgName: data.orgName ?? "",
|
|
5494
5496
|
seats: data.seats,
|
|
5495
5497
|
paidSeats: data.paidSeats,
|
|
5496
5498
|
amount: data.amount,
|
|
@@ -8286,7 +8288,6 @@ function usePromoController() {
|
|
|
8286
8288
|
// src/resources/subscription/subscription.service.ts
|
|
8287
8289
|
function useSubscriptionService() {
|
|
8288
8290
|
const {
|
|
8289
|
-
getById,
|
|
8290
8291
|
updateById,
|
|
8291
8292
|
getByStatus,
|
|
8292
8293
|
updateStatusById,
|
|
@@ -8354,10 +8355,10 @@ function useSubscriptionService() {
|
|
|
8354
8355
|
if (promo) {
|
|
8355
8356
|
switch (promo.type) {
|
|
8356
8357
|
case "fixed":
|
|
8357
|
-
monthlyAmount = Math.max(
|
|
8358
|
+
monthlyAmount = Math.max(promo.fixedRate ?? 0, 0) * value.seats;
|
|
8358
8359
|
break;
|
|
8359
8360
|
case "flat":
|
|
8360
|
-
monthlyAmount = Math.max(
|
|
8361
|
+
monthlyAmount = Math.max((promo.flatRate ?? 0) / value.seats, 0) * value.seats;
|
|
8361
8362
|
break;
|
|
8362
8363
|
case "volume": {
|
|
8363
8364
|
if (promo.tiers && promo.tiers.length > 0) {
|
|
@@ -8419,14 +8420,17 @@ function useSubscriptionService() {
|
|
|
8419
8420
|
proratedAmount = dailyRate * daysRemaining;
|
|
8420
8421
|
}
|
|
8421
8422
|
}
|
|
8423
|
+
const isDecrease = existingSubscription && value.seats < existingSubscription.paidSeats;
|
|
8422
8424
|
return {
|
|
8423
8425
|
// The monthly fee for the next billing cycle
|
|
8424
8426
|
monthlyAmount: Math.round(monthlyAmount * 100) / 100,
|
|
8425
8427
|
// The prorated amount to charge now for mid-cycle seat additions
|
|
8426
8428
|
proratedAmount: Math.round(proratedAmount * 100) / 100,
|
|
8427
8429
|
// The new subscription.amount for updates
|
|
8428
|
-
//
|
|
8429
|
-
|
|
8430
|
+
// - Seat increase with proration: existing amount + prorated
|
|
8431
|
+
// - Seat decrease: keep existing amount (decrease takes effect next cycle)
|
|
8432
|
+
// - Same day change or no proration: use monthlyAmount
|
|
8433
|
+
subscriptionAmount: existingSubscription ? proratedAmount > 0 ? Math.round((existingSubscription.amount + proratedAmount) * 100) / 100 : isDecrease ? Math.round(existingSubscription.amount * 100) / 100 : Math.round(monthlyAmount * 100) / 100 : Math.round(monthlyAmount * 100) / 100,
|
|
8430
8434
|
currency: plan.currency
|
|
8431
8435
|
};
|
|
8432
8436
|
}
|
|
@@ -8435,34 +8439,38 @@ function useSubscriptionService() {
|
|
|
8435
8439
|
if (error) {
|
|
8436
8440
|
throw new import_utils44.BadRequestError(`Invalid subscription data: ${error.message}`);
|
|
8437
8441
|
}
|
|
8438
|
-
const existingSubscription = await getByOrg(value.org);
|
|
8439
|
-
if (existingSubscription) {
|
|
8440
|
-
throw new import_utils44.BadRequestError("Organization already has a subscription.");
|
|
8441
|
-
}
|
|
8442
|
-
const plan = await getPlanById(value.plan);
|
|
8443
|
-
if (!plan) {
|
|
8444
|
-
throw new import_utils44.BadRequestError("Plan not found.");
|
|
8445
|
-
}
|
|
8446
|
-
const userData = await getUserById(value.user);
|
|
8447
|
-
if (!userData) {
|
|
8448
|
-
throw new import_utils44.BadRequestError("User not found.");
|
|
8449
|
-
}
|
|
8450
|
-
const membership = await getMembershipByApp({
|
|
8451
|
-
user: value.user,
|
|
8452
|
-
org: value.org,
|
|
8453
|
-
app: "org"
|
|
8454
|
-
});
|
|
8455
|
-
if (!membership) {
|
|
8456
|
-
throw new import_utils44.BadRequestError("User is not a member of the organization.");
|
|
8457
|
-
}
|
|
8458
|
-
const nextBillingDate = /* @__PURE__ */ new Date();
|
|
8459
|
-
nextBillingDate.setMonth(nextBillingDate.getMonth() + 1);
|
|
8460
8442
|
const session = import_utils44.useAtlas.getClient()?.startSession();
|
|
8461
8443
|
if (!session) {
|
|
8462
8444
|
throw new import_utils44.InternalServerError("Unable to start database session.");
|
|
8463
8445
|
}
|
|
8464
8446
|
try {
|
|
8465
8447
|
session.startTransaction();
|
|
8448
|
+
const org = await getOrgById(value.org);
|
|
8449
|
+
if (!org) {
|
|
8450
|
+
throw new import_utils44.BadRequestError("Organization not found.");
|
|
8451
|
+
}
|
|
8452
|
+
const existingSubscription = await getByOrg(value.org);
|
|
8453
|
+
if (existingSubscription) {
|
|
8454
|
+
throw new import_utils44.BadRequestError("Organization already has a subscription.");
|
|
8455
|
+
}
|
|
8456
|
+
const plan = await getPlanById(value.plan);
|
|
8457
|
+
if (!plan) {
|
|
8458
|
+
throw new import_utils44.BadRequestError("Plan not found.");
|
|
8459
|
+
}
|
|
8460
|
+
const userData = await getUserById(value.user);
|
|
8461
|
+
if (!userData) {
|
|
8462
|
+
throw new import_utils44.BadRequestError("User not found.");
|
|
8463
|
+
}
|
|
8464
|
+
const membership = await getMembershipByApp({
|
|
8465
|
+
user: value.user,
|
|
8466
|
+
org: value.org,
|
|
8467
|
+
app: "org"
|
|
8468
|
+
});
|
|
8469
|
+
if (!membership) {
|
|
8470
|
+
throw new import_utils44.BadRequestError("User is not a member of the organization.");
|
|
8471
|
+
}
|
|
8472
|
+
const nextBillingDate = /* @__PURE__ */ new Date();
|
|
8473
|
+
nextBillingDate.setMonth(nextBillingDate.getMonth() + 1);
|
|
8466
8474
|
const { subscriptionAmount, currency } = await computeFee({
|
|
8467
8475
|
seats: value.seats,
|
|
8468
8476
|
promoCode: value.promoCode,
|
|
@@ -8472,6 +8480,7 @@ function useSubscriptionService() {
|
|
|
8472
8480
|
const subId = await _add(
|
|
8473
8481
|
{
|
|
8474
8482
|
org: value.org,
|
|
8483
|
+
orgName: org.name,
|
|
8475
8484
|
seats: value.seats,
|
|
8476
8485
|
paidSeats: value.seats,
|
|
8477
8486
|
// Initial seats are considered "paid" for proration purposes
|
|
@@ -8516,39 +8525,44 @@ function useSubscriptionService() {
|
|
|
8516
8525
|
if (error) {
|
|
8517
8526
|
throw new import_utils44.BadRequestError(error.message);
|
|
8518
8527
|
}
|
|
8519
|
-
const subscription = await getByOrg(value.org);
|
|
8520
|
-
if (!subscription) {
|
|
8521
|
-
throw new import_utils44.BadRequestError("Subscription not found");
|
|
8522
|
-
}
|
|
8523
|
-
if (subscription.seats === value.seats) {
|
|
8524
|
-
throw new import_utils44.BadRequestError(
|
|
8525
|
-
"Failed to update subscription, no changes detected."
|
|
8526
|
-
);
|
|
8527
|
-
}
|
|
8528
|
-
const userData = await getUserById(value.user);
|
|
8529
|
-
if (!userData) {
|
|
8530
|
-
throw new import_utils44.BadRequestError("User not found.");
|
|
8531
|
-
}
|
|
8532
|
-
const membership = await getMembershipByApp({
|
|
8533
|
-
user: value.user,
|
|
8534
|
-
org: value.org,
|
|
8535
|
-
app: "org"
|
|
8536
|
-
});
|
|
8537
|
-
if (!membership) {
|
|
8538
|
-
throw new import_utils44.BadRequestError("User is not a member of the organization.");
|
|
8539
|
-
}
|
|
8540
|
-
const { subscriptionAmount, proratedAmount, currency } = await computeFee(
|
|
8541
|
-
value
|
|
8542
|
-
);
|
|
8543
8528
|
const session = import_utils44.useAtlas.getClient()?.startSession();
|
|
8544
8529
|
if (!session) {
|
|
8545
8530
|
throw new import_utils44.InternalServerError("Unable to start database session.");
|
|
8546
8531
|
}
|
|
8547
|
-
const seatIncreased = value.seats > subscription.paidSeats;
|
|
8548
|
-
const additionalSeats = value.seats - subscription.paidSeats;
|
|
8549
|
-
const paidSeats = seatIncreased ? value.seats : subscription.paidSeats;
|
|
8550
8532
|
try {
|
|
8551
8533
|
session.startTransaction();
|
|
8534
|
+
const subscription = await getByOrg(value.org);
|
|
8535
|
+
if (!subscription) {
|
|
8536
|
+
throw new import_utils44.BadRequestError("Subscription not found");
|
|
8537
|
+
}
|
|
8538
|
+
if (subscription.seats === value.seats) {
|
|
8539
|
+
throw new import_utils44.BadRequestError(
|
|
8540
|
+
"Failed to update subscription, no changes detected."
|
|
8541
|
+
);
|
|
8542
|
+
}
|
|
8543
|
+
const userData = await getUserById(value.user);
|
|
8544
|
+
if (!userData) {
|
|
8545
|
+
throw new import_utils44.BadRequestError("User not found.");
|
|
8546
|
+
}
|
|
8547
|
+
const membership = await getMembershipByApp({
|
|
8548
|
+
user: value.user,
|
|
8549
|
+
org: value.org,
|
|
8550
|
+
app: "org"
|
|
8551
|
+
});
|
|
8552
|
+
if (!membership) {
|
|
8553
|
+
throw new import_utils44.BadRequestError("User is not a member of the organization.");
|
|
8554
|
+
}
|
|
8555
|
+
const { subscriptionAmount, proratedAmount, currency } = await computeFee(
|
|
8556
|
+
{
|
|
8557
|
+
seats: value.seats,
|
|
8558
|
+
promoCode: value.promoCode ?? "",
|
|
8559
|
+
plan: value.plan ?? "",
|
|
8560
|
+
org: value.org
|
|
8561
|
+
}
|
|
8562
|
+
);
|
|
8563
|
+
const seatIncreased = value.seats > subscription.paidSeats;
|
|
8564
|
+
const additionalSeats = value.seats - subscription.paidSeats;
|
|
8565
|
+
const paidSeats = seatIncreased ? value.seats : subscription.paidSeats;
|
|
8552
8566
|
await updateById(
|
|
8553
8567
|
subscription._id?.toString() ?? "",
|
|
8554
8568
|
{ seats: value.seats, amount: subscriptionAmount, paidSeats },
|
|
@@ -8582,53 +8596,53 @@ function useSubscriptionService() {
|
|
|
8582
8596
|
if (error) {
|
|
8583
8597
|
throw new import_utils44.BadRequestError(error.message);
|
|
8584
8598
|
}
|
|
8585
|
-
const subscription = await getByOrg(value.org);
|
|
8586
|
-
if (!subscription) {
|
|
8587
|
-
throw new import_utils44.BadRequestError("Subscription not found");
|
|
8588
|
-
}
|
|
8589
|
-
if (subscription.promoCode === value.promoCode) {
|
|
8590
|
-
throw new import_utils44.BadRequestError(
|
|
8591
|
-
"Failed to update subscription, no changes detected."
|
|
8592
|
-
);
|
|
8593
|
-
}
|
|
8594
|
-
let promo = null;
|
|
8595
|
-
if (value.promoCode) {
|
|
8596
|
-
promo = await getPromoByCode(value.promoCode);
|
|
8597
|
-
if (!promo) {
|
|
8598
|
-
throw new import_utils44.BadRequestError("Promo code not found.");
|
|
8599
|
-
}
|
|
8600
|
-
}
|
|
8601
|
-
const userData = await getUserById(value.user);
|
|
8602
|
-
if (!userData) {
|
|
8603
|
-
throw new import_utils44.BadRequestError("User not found.");
|
|
8604
|
-
}
|
|
8605
|
-
const membership = await getMembershipByApp({
|
|
8606
|
-
user: value.user,
|
|
8607
|
-
org: value.org,
|
|
8608
|
-
app: "org"
|
|
8609
|
-
});
|
|
8610
|
-
if (!membership) {
|
|
8611
|
-
throw new import_utils44.BadRequestError("User is not a member of the organization.");
|
|
8612
|
-
}
|
|
8613
|
-
const plan = await getDefaultPlan();
|
|
8614
|
-
if (!plan) {
|
|
8615
|
-
throw new import_utils44.BadRequestError("Plan not found.");
|
|
8616
|
-
}
|
|
8617
|
-
const { subscriptionAmount, currency } = await computeFee(
|
|
8618
|
-
{
|
|
8619
|
-
seats: subscription.seats,
|
|
8620
|
-
promoCode: value.promoCode ?? "",
|
|
8621
|
-
plan: plan._id?.toString() ?? "",
|
|
8622
|
-
org: value.org
|
|
8623
|
-
},
|
|
8624
|
-
true
|
|
8625
|
-
);
|
|
8626
8599
|
const session = import_utils44.useAtlas.getClient()?.startSession();
|
|
8627
8600
|
if (!session) {
|
|
8628
8601
|
throw new import_utils44.InternalServerError("Unable to start database session.");
|
|
8629
8602
|
}
|
|
8630
8603
|
try {
|
|
8631
8604
|
session.startTransaction();
|
|
8605
|
+
const subscription = await getByOrg(value.org);
|
|
8606
|
+
if (!subscription) {
|
|
8607
|
+
throw new import_utils44.BadRequestError("Subscription not found");
|
|
8608
|
+
}
|
|
8609
|
+
if (subscription.promoCode === value.promoCode) {
|
|
8610
|
+
throw new import_utils44.BadRequestError(
|
|
8611
|
+
"Failed to update subscription, no changes detected."
|
|
8612
|
+
);
|
|
8613
|
+
}
|
|
8614
|
+
let promo = null;
|
|
8615
|
+
if (value.promoCode) {
|
|
8616
|
+
promo = await getPromoByCode(value.promoCode);
|
|
8617
|
+
if (!promo) {
|
|
8618
|
+
throw new import_utils44.BadRequestError("Promo code not found.");
|
|
8619
|
+
}
|
|
8620
|
+
}
|
|
8621
|
+
const userData = await getUserById(value.user);
|
|
8622
|
+
if (!userData) {
|
|
8623
|
+
throw new import_utils44.BadRequestError("User not found.");
|
|
8624
|
+
}
|
|
8625
|
+
const membership = await getMembershipByApp({
|
|
8626
|
+
user: value.user,
|
|
8627
|
+
org: value.org,
|
|
8628
|
+
app: "org"
|
|
8629
|
+
});
|
|
8630
|
+
if (!membership) {
|
|
8631
|
+
throw new import_utils44.BadRequestError("User is not a member of the organization.");
|
|
8632
|
+
}
|
|
8633
|
+
const plan = await getDefaultPlan();
|
|
8634
|
+
if (!plan) {
|
|
8635
|
+
throw new import_utils44.BadRequestError("Plan not found.");
|
|
8636
|
+
}
|
|
8637
|
+
const { subscriptionAmount, currency } = await computeFee(
|
|
8638
|
+
{
|
|
8639
|
+
seats: subscription.seats,
|
|
8640
|
+
promoCode: value.promoCode ?? "",
|
|
8641
|
+
plan: plan._id?.toString() ?? "",
|
|
8642
|
+
org: value.org
|
|
8643
|
+
},
|
|
8644
|
+
true
|
|
8645
|
+
);
|
|
8632
8646
|
await updateById(
|
|
8633
8647
|
subscription._id?.toString() ?? "",
|
|
8634
8648
|
{ promoCode: value.promoCode ?? "", amount: subscriptionAmount },
|