@goweekdays/core 2.11.3 → 2.11.5

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @goweekdays/core
2
2
 
3
+ ## 2.11.5
4
+
5
+ ### Patch Changes
6
+
7
+ - cb8aa36: Enhance promo usage tracking and seat limit logic
8
+
9
+ ## 2.11.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 2697ef3: Refactor subscription amount calculation logic
14
+
3
15
  ## 2.11.3
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -470,6 +470,33 @@ declare function usePromoController(): {
470
470
  deleteById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
471
471
  };
472
472
 
473
+ type TPromoUsage = {
474
+ _id?: ObjectId;
475
+ promo: ObjectId;
476
+ org: ObjectId | string;
477
+ usedBy: string;
478
+ status?: "active" | "inactive";
479
+ createdAt?: Date | string;
480
+ updatedAt?: Date | string;
481
+ };
482
+
483
+ declare function usePromoUsageRepo(): {
484
+ createIndexes: () => Promise<void>;
485
+ add: (value: TPromoUsage, session?: ClientSession) => Promise<string>;
486
+ getAll: ({ page, limit, promo, org, }?: {
487
+ page?: number | undefined;
488
+ limit?: number | undefined;
489
+ promo?: string | undefined;
490
+ org?: string | undefined;
491
+ }) => Promise<TPaginate<TPromoUsage>>;
492
+ getByPromo: (promo: string | ObjectId) => Promise<TPromoUsage | null>;
493
+ getById: (_id: string | ObjectId) => Promise<TPromoUsage | null>;
494
+ getByOrgId: (orgId: string | ObjectId) => Promise<TPromoUsage[]>;
495
+ countByPromoId: (promoId: string | ObjectId) => Promise<number>;
496
+ updateStatusByOrgId: (orgId: string | ObjectId, status: "active" | "inactive", session?: ClientSession) => Promise<string>;
497
+ deleteById: (_id: string | ObjectId) => Promise<string>;
498
+ };
499
+
473
500
  type TRole = {
474
501
  _id?: ObjectId;
475
502
  id?: string | ObjectId;
@@ -1255,4 +1282,4 @@ declare const XENDIT_BASE_URL: string;
1255
1282
  declare const DOMAIN: string;
1256
1283
  declare const APP_ORG: string;
1257
1284
 
1258
- export { ACCESS_TOKEN_EXPIRY, ACCESS_TOKEN_SECRET, APP_ACCOUNT, APP_MAIN, APP_ORG, DEFAULT_USER_EMAIL, DEFAULT_USER_FIRST_NAME, DEFAULT_USER_LAST_NAME, DEFAULT_USER_PASSWORD, DOMAIN, MAILER_EMAIL, MAILER_PASSWORD, MAILER_TRANSPORT_HOST, MAILER_TRANSPORT_PORT, MAILER_TRANSPORT_SECURE, MBuilding, MBuildingUnit, MFile, MONGO_DB, MONGO_URI, PAYPAL_API_URL, PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PAYPAL_WEBHOOK_ID, PORT, PaypalWebhookHeaders, REDIS_HOST, REDIS_PASSWORD, REDIS_PORT, REFRESH_TOKEN_EXPIRY, REFRESH_TOKEN_SECRET, SECRET_KEY, SPACES_ACCESS_KEY, SPACES_BUCKET, SPACES_ENDPOINT, SPACES_REGION, SPACES_SECRET_KEY, TApp, TBuilding, TBuildingUnit, TCounter, TFile, TJobPost, TLedgerBill, TMember, TOrg, TPermission, TPermissionGroup, TPlan, TPromo, TRole, TSubscribe, TSubscription, TSubscriptionTransaction, TUser, TVerification, TVerificationMetadata, VERIFICATION_FORGET_PASSWORD_DURATION, VERIFICATION_USER_INVITE_DURATION, XENDIT_BASE_URL, XENDIT_SECRET_KEY, currencies, isDev, ledgerBillStatuses, ledgerBillTypes, modelApp, modelJobPost, modelLedgerBill, modelMember, modelOrg, modelPermission, modelPermissionGroup, modelPlan, modelPromo, modelRole, modelSubscription, modelSubscriptionTransaction, modelUser, modelVerification, schemaApp, schemaAppUpdate, schemaBuilding, schemaBuildingUnit, schemaInviteMember, schemaJobPost, schemaJobPostUpdate, schemaLedgerBill, schemaLedgerBillingSummary, schemaMember, schemaMemberRole, schemaMemberStatus, schemaOrg, schemaOrgAdd, schemaOrgUpdate, schemaPermission, schemaPermissionGroup, schemaPermissionGroupUpdate, schemaPermissionUpdate, schemaPlan, schemaPromo, schemaRole, schemaRoleUpdate, schemaSubscribe, schemaSubscription, schemaSubscriptionCompute, schemaSubscriptionPromoCode, schemaSubscriptionSeats, schemaSubscriptionTransaction, schemaSubscriptionUpdate, schemaUpdateOptions, schemaUser, schemaVerification, transactionSchema, useAppController, useAppRepo, useAppService, useAuthController, useAuthService, useBuildingController, useBuildingRepo, useBuildingService, useBuildingUnitController, useBuildingUnitRepo, useBuildingUnitService, useCounterModel, useCounterRepo, useFileController, useFileRepo, useFileService, useGitHubService, useJobPostController, useJobPostRepo, useJobPostService, useLedgerBillingController, useLedgerBillingRepo, useMemberController, useMemberRepo, useOrgController, useOrgRepo, useOrgService, usePaypalService, usePermissionController, usePermissionGroupController, usePermissionGroupRepo, usePermissionGroupService, usePermissionRepo, usePermissionService, usePlanController, usePlanRepo, usePlanService, usePromoController, usePromoRepo, useRoleController, useRoleRepo, useRoleService, useSubscriptionController, useSubscriptionRepo, useSubscriptionService, useSubscriptionTransactionController, useSubscriptionTransactionRepo, useUserController, useUserRepo, useUserService, useUtilController, useVerificationController, useVerificationRepo, useVerificationService };
1285
+ export { ACCESS_TOKEN_EXPIRY, ACCESS_TOKEN_SECRET, APP_ACCOUNT, APP_MAIN, APP_ORG, DEFAULT_USER_EMAIL, DEFAULT_USER_FIRST_NAME, DEFAULT_USER_LAST_NAME, DEFAULT_USER_PASSWORD, DOMAIN, MAILER_EMAIL, MAILER_PASSWORD, MAILER_TRANSPORT_HOST, MAILER_TRANSPORT_PORT, MAILER_TRANSPORT_SECURE, MBuilding, MBuildingUnit, MFile, MONGO_DB, MONGO_URI, PAYPAL_API_URL, PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PAYPAL_WEBHOOK_ID, PORT, PaypalWebhookHeaders, REDIS_HOST, REDIS_PASSWORD, REDIS_PORT, REFRESH_TOKEN_EXPIRY, REFRESH_TOKEN_SECRET, SECRET_KEY, SPACES_ACCESS_KEY, SPACES_BUCKET, SPACES_ENDPOINT, SPACES_REGION, SPACES_SECRET_KEY, TApp, TBuilding, TBuildingUnit, TCounter, TFile, TJobPost, TLedgerBill, TMember, TOrg, TPermission, TPermissionGroup, TPlan, TPromo, TRole, TSubscribe, TSubscription, TSubscriptionTransaction, TUser, TVerification, TVerificationMetadata, VERIFICATION_FORGET_PASSWORD_DURATION, VERIFICATION_USER_INVITE_DURATION, XENDIT_BASE_URL, XENDIT_SECRET_KEY, currencies, isDev, ledgerBillStatuses, ledgerBillTypes, modelApp, modelJobPost, modelLedgerBill, modelMember, modelOrg, modelPermission, modelPermissionGroup, modelPlan, modelPromo, modelRole, modelSubscription, modelSubscriptionTransaction, modelUser, modelVerification, schemaApp, schemaAppUpdate, schemaBuilding, schemaBuildingUnit, schemaInviteMember, schemaJobPost, schemaJobPostUpdate, schemaLedgerBill, schemaLedgerBillingSummary, schemaMember, schemaMemberRole, schemaMemberStatus, schemaOrg, schemaOrgAdd, schemaOrgUpdate, schemaPermission, schemaPermissionGroup, schemaPermissionGroupUpdate, schemaPermissionUpdate, schemaPlan, schemaPromo, schemaRole, schemaRoleUpdate, schemaSubscribe, schemaSubscription, schemaSubscriptionCompute, schemaSubscriptionPromoCode, schemaSubscriptionSeats, schemaSubscriptionTransaction, schemaSubscriptionUpdate, schemaUpdateOptions, schemaUser, schemaVerification, transactionSchema, useAppController, useAppRepo, useAppService, useAuthController, useAuthService, useBuildingController, useBuildingRepo, useBuildingService, useBuildingUnitController, useBuildingUnitRepo, useBuildingUnitService, useCounterModel, useCounterRepo, useFileController, useFileRepo, useFileService, useGitHubService, useJobPostController, useJobPostRepo, useJobPostService, useLedgerBillingController, useLedgerBillingRepo, useMemberController, useMemberRepo, useOrgController, useOrgRepo, useOrgService, usePaypalService, usePermissionController, usePermissionGroupController, usePermissionGroupRepo, usePermissionGroupService, usePermissionRepo, usePermissionService, usePlanController, usePlanRepo, usePlanService, usePromoController, usePromoRepo, usePromoUsageRepo, useRoleController, useRoleRepo, useRoleService, useSubscriptionController, useSubscriptionRepo, useSubscriptionService, useSubscriptionTransactionController, useSubscriptionTransactionRepo, useUserController, useUserRepo, useUserService, useUtilController, useVerificationController, useVerificationRepo, useVerificationService };
package/dist/index.js CHANGED
@@ -161,6 +161,7 @@ __export(src_exports, {
161
161
  usePlanService: () => usePlanService,
162
162
  usePromoController: () => usePromoController,
163
163
  usePromoRepo: () => usePromoRepo,
164
+ usePromoUsageRepo: () => usePromoUsageRepo,
164
165
  useRoleController: () => useRoleController,
165
166
  useRoleRepo: () => useRoleRepo,
166
167
  useRoleService: () => useRoleService,
@@ -5810,7 +5811,7 @@ function useSubscriptionRepo() {
5810
5811
  const validation = import_joi21.default.object({
5811
5812
  seats: import_joi21.default.number().integer().min(1).optional().allow("", null),
5812
5813
  paidSeats: import_joi21.default.number().integer().min(0).optional(),
5813
- amount: import_joi21.default.number().positive().optional(),
5814
+ amount: import_joi21.default.number().positive().optional().allow(0),
5814
5815
  promoCode: import_joi21.default.string().max(50).optional().allow("", null),
5815
5816
  status: import_joi21.default.string().valid("active", "due", "overdue", "suspended").optional().allow("", null),
5816
5817
  nextBillingDate: import_joi21.default.date().optional().allow("", null)
@@ -7803,7 +7804,8 @@ var import_mongodb23 = require("mongodb");
7803
7804
  var schemaPromoUsage = import_joi34.default.object({
7804
7805
  promo: import_joi34.default.string().hex().length(24).required(),
7805
7806
  org: import_joi34.default.string().hex().length(24).required(),
7806
- usedBy: import_joi34.default.string().email().required()
7807
+ usedBy: import_joi34.default.string().email().required(),
7808
+ status: import_joi34.default.string().valid("active", "inactive").optional()
7807
7809
  });
7808
7810
  function modelPromoUsage(value) {
7809
7811
  const { error } = schemaPromoUsage.validate(value);
@@ -7817,14 +7819,14 @@ function modelPromoUsage(value) {
7817
7819
  throw new import_utils40.BadRequestError("Invalid Promo Usage _id");
7818
7820
  }
7819
7821
  }
7820
- if (typeof value.promo === "string") {
7822
+ if (value.promo && typeof value.promo === "string") {
7821
7823
  try {
7822
7824
  value.promo = new import_mongodb23.ObjectId(value.promo);
7823
7825
  } catch (error2) {
7824
7826
  throw new import_utils40.BadRequestError("Invalid Promo Usage promo");
7825
7827
  }
7826
7828
  }
7827
- if (typeof value.org === "string") {
7829
+ if (value.org && typeof value.org === "string") {
7828
7830
  try {
7829
7831
  value.org = new import_mongodb23.ObjectId(value.org);
7830
7832
  } catch (error2) {
@@ -7836,6 +7838,7 @@ function modelPromoUsage(value) {
7836
7838
  promo: value.promo,
7837
7839
  org: value.org,
7838
7840
  usedBy: value.usedBy,
7841
+ status: value.status ?? "active",
7839
7842
  createdAt: value.createdAt ? new Date(value.createdAt) : /* @__PURE__ */ new Date(),
7840
7843
  updatedAt: value.updatedAt ?? ""
7841
7844
  };
@@ -7868,6 +7871,9 @@ function usePromoUsageRepo() {
7868
7871
  async function createIndexes() {
7869
7872
  try {
7870
7873
  await collection.createIndexes([
7874
+ {
7875
+ key: { status: 1 }
7876
+ },
7871
7877
  {
7872
7878
  key: { promo: 1, org: 1 },
7873
7879
  name: "promo_org_index"
@@ -7880,10 +7886,10 @@ function usePromoUsageRepo() {
7880
7886
  } catch (error) {
7881
7887
  }
7882
7888
  }
7883
- async function add(value) {
7889
+ async function add(value, session) {
7884
7890
  try {
7885
7891
  value = modelPromoUsage(value);
7886
- await collection.insertOne(value);
7892
+ await collection.insertOne(value, { session });
7887
7893
  delCachedData();
7888
7894
  return "Successfully added promo usage.";
7889
7895
  } catch (error) {
@@ -8075,7 +8081,10 @@ function usePromoUsageRepo() {
8075
8081
  if (cachedData !== null && cachedData !== void 0) {
8076
8082
  return cachedData;
8077
8083
  }
8078
- const count = await collection.countDocuments({ promo: promoId });
8084
+ const count = await collection.countDocuments({
8085
+ promo: promoId,
8086
+ status: "active"
8087
+ });
8079
8088
  setCache(cacheKey, count).then(() => {
8080
8089
  import_utils41.logger.log({
8081
8090
  level: "info",
@@ -8092,6 +8101,28 @@ function usePromoUsageRepo() {
8092
8101
  throw new import_utils41.InternalServerError("Failed to count promo usages.");
8093
8102
  }
8094
8103
  }
8104
+ async function updateStatusByOrgId(orgId, status, session) {
8105
+ const { error } = import_joi35.default.string().hex().length(24).required().validate(orgId);
8106
+ if (error) {
8107
+ throw new import_utils41.BadRequestError(`Invalid org ID: ${error.message}`);
8108
+ }
8109
+ try {
8110
+ orgId = new import_mongodb24.ObjectId(orgId);
8111
+ } catch (error2) {
8112
+ throw new import_utils41.BadRequestError("Invalid org ID.");
8113
+ }
8114
+ try {
8115
+ await collection.updateMany(
8116
+ { org: orgId, status: "active" },
8117
+ { $set: { status, updatedAt: /* @__PURE__ */ new Date() } },
8118
+ { session }
8119
+ );
8120
+ delCachedData();
8121
+ return "Successfully updated promo usage status.";
8122
+ } catch (error2) {
8123
+ throw new import_utils41.InternalServerError("Failed to update promo usage status.");
8124
+ }
8125
+ }
8095
8126
  async function deleteById(_id) {
8096
8127
  const { error } = import_joi35.default.string().hex().length(24).required().validate(_id);
8097
8128
  if (error) {
@@ -8124,6 +8155,7 @@ function usePromoUsageRepo() {
8124
8155
  getById,
8125
8156
  getByOrgId,
8126
8157
  countByPromoId,
8158
+ updateStatusByOrgId,
8127
8159
  deleteById
8128
8160
  };
8129
8161
  }
@@ -8300,6 +8332,11 @@ function useSubscriptionService() {
8300
8332
  const { getDefault: getDefaultPlan, getById: getPlanById } = usePlanRepo();
8301
8333
  const { getById: getOrgById, updateStatusById: updateOrgStatusById } = useOrgRepo();
8302
8334
  const { getByCode: getPromoByCode } = usePromoRepo();
8335
+ const {
8336
+ countByPromoId,
8337
+ add: addPromoUsage,
8338
+ updateStatusByOrgId: updatePromoUsageStatusByOrgId
8339
+ } = usePromoUsageRepo();
8303
8340
  const { getByApp: getMembershipByApp } = useMemberRepo();
8304
8341
  function calculateVolumeTierAmount(tiers, startSeat, seatCount, fallbackRate) {
8305
8342
  const sortedTiers = [...tiers].sort((a, b) => a.minSeats - b.minSeats);
@@ -8350,16 +8387,33 @@ function useSubscriptionService() {
8350
8387
  if (!promo) {
8351
8388
  throw new import_utils44.BadRequestError("Promo code not found.");
8352
8389
  }
8390
+ if (promo.usage && promo.usage > 0) {
8391
+ const currentUsageCount = await countByPromoId(
8392
+ promo._id?.toString() ?? ""
8393
+ );
8394
+ const isAlreadyUsingPromo = existingSubscription?.promoCode === promoCode;
8395
+ if (!isAlreadyUsingPromo && currentUsageCount >= promo.usage) {
8396
+ throw new import_utils44.BadRequestError(
8397
+ "Promo code has reached its maximum usage limit."
8398
+ );
8399
+ }
8400
+ }
8353
8401
  }
8354
8402
  let monthlyAmount = plan.price * value.seats;
8355
8403
  if (promo) {
8404
+ const promoSeatLimit = promo.seats && promo.seats > 0 ? promo.seats : Infinity;
8356
8405
  switch (promo.type) {
8357
- case "fixed":
8358
- monthlyAmount = Math.max(promo.fixedRate ?? 0, 0) * value.seats;
8406
+ case "fixed": {
8407
+ const promoSeats = Math.min(value.seats, promoSeatLimit);
8408
+ const standardSeats = Math.max(value.seats - promoSeatLimit, 0);
8409
+ monthlyAmount = Math.max(promo.fixedRate ?? 0, 0) * promoSeats + plan.price * standardSeats;
8359
8410
  break;
8360
- case "flat":
8361
- monthlyAmount = Math.max((promo.flatRate ?? 0) / value.seats, 0) * value.seats;
8411
+ }
8412
+ case "flat": {
8413
+ const standardSeats = Math.max(value.seats - promoSeatLimit, 0);
8414
+ monthlyAmount = (promo.flatRate ?? 0) + plan.price * standardSeats;
8362
8415
  break;
8416
+ }
8363
8417
  case "volume": {
8364
8418
  if (promo.tiers && promo.tiers.length > 0) {
8365
8419
  monthlyAmount = calculateVolumeTierAmount(
@@ -8402,17 +8456,32 @@ function useSubscriptionService() {
8402
8456
  plan.price
8403
8457
  );
8404
8458
  } else if (promo?.type === "fixed") {
8405
- const discountedPricePerSeat = Math.max(
8406
- plan.price - (promo.fixedRate ?? 0),
8407
- 0
8459
+ const promoSeatLimit = promo.seats && promo.seats > 0 ? promo.seats : Infinity;
8460
+ const startSeat = existingSubscription.paidSeats + 1;
8461
+ const endSeat = value.seats;
8462
+ const promoSeatsInRange = Math.max(
8463
+ 0,
8464
+ Math.min(promoSeatLimit, endSeat) - startSeat + 1
8408
8465
  );
8409
- additionalSeatsAmount = discountedPricePerSeat * additionalSeats;
8410
- } else if (promo?.type === "flat") {
8411
- const effectivePricePerSeat = Math.max(
8412
- plan.price - (promo.flatRate ?? 0) / value.seats,
8413
- 0
8466
+ const standardSeatsInRange = Math.max(
8467
+ 0,
8468
+ additionalSeats - promoSeatsInRange
8414
8469
  );
8415
- additionalSeatsAmount = effectivePricePerSeat * additionalSeats;
8470
+ additionalSeatsAmount = (promo.fixedRate ?? 0) * promoSeatsInRange + plan.price * standardSeatsInRange;
8471
+ } else if (promo?.type === "flat") {
8472
+ const promoSeatLimit = promo.seats && promo.seats > 0 ? promo.seats : Infinity;
8473
+ const startSeat = existingSubscription.paidSeats + 1;
8474
+ const endSeat = value.seats;
8475
+ if (startSeat > promoSeatLimit) {
8476
+ additionalSeatsAmount = plan.price * additionalSeats;
8477
+ } else {
8478
+ const seatsStillCoveredByFlat = Math.max(
8479
+ 0,
8480
+ Math.min(promoSeatLimit, endSeat) - startSeat + 1
8481
+ );
8482
+ const seatsAtPlanPrice = additionalSeats - seatsStillCoveredByFlat;
8483
+ additionalSeatsAmount = plan.price * seatsAtPlanPrice;
8484
+ }
8416
8485
  } else {
8417
8486
  additionalSeatsAmount = plan.price * additionalSeats;
8418
8487
  }
@@ -8420,17 +8489,24 @@ function useSubscriptionService() {
8420
8489
  proratedAmount = dailyRate * daysRemaining;
8421
8490
  }
8422
8491
  }
8423
- const isDecrease = existingSubscription && value.seats < existingSubscription.paidSeats;
8492
+ const isIncrease = existingSubscription && value.seats > existingSubscription.paidSeats;
8493
+ let subscriptionAmount;
8494
+ if (!existingSubscription) {
8495
+ subscriptionAmount = Math.round(monthlyAmount * 100) / 100;
8496
+ } else if (proratedAmount > 0) {
8497
+ subscriptionAmount = Math.round((existingSubscription.amount + proratedAmount) * 100) / 100;
8498
+ } else if (isIncrease) {
8499
+ subscriptionAmount = Math.round(monthlyAmount * 100) / 100;
8500
+ } else {
8501
+ subscriptionAmount = Math.round(existingSubscription.amount * 100) / 100;
8502
+ }
8424
8503
  return {
8425
8504
  // The monthly fee for the next billing cycle
8426
8505
  monthlyAmount: Math.round(monthlyAmount * 100) / 100,
8427
8506
  // The prorated amount to charge now for mid-cycle seat additions
8428
8507
  proratedAmount: Math.round(proratedAmount * 100) / 100,
8429
8508
  // The new subscription.amount for updates
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,
8509
+ subscriptionAmount,
8434
8510
  currency: plan.currency
8435
8511
  };
8436
8512
  }
@@ -8477,6 +8553,13 @@ function useSubscriptionService() {
8477
8553
  org: value.org,
8478
8554
  plan: value.plan
8479
8555
  });
8556
+ let promo = null;
8557
+ if (value.promoCode) {
8558
+ promo = await getPromoByCode(value.promoCode);
8559
+ if (!promo) {
8560
+ throw new import_utils44.BadRequestError("Promo code not found.");
8561
+ }
8562
+ }
8480
8563
  const subId = await _add(
8481
8564
  {
8482
8565
  org: value.org,
@@ -8492,6 +8575,16 @@ function useSubscriptionService() {
8492
8575
  },
8493
8576
  session
8494
8577
  );
8578
+ if (promo && promo._id) {
8579
+ await addPromoUsage(
8580
+ {
8581
+ promo: promo._id,
8582
+ org: value.org,
8583
+ usedBy: userData.email
8584
+ },
8585
+ session
8586
+ );
8587
+ }
8495
8588
  await addTransaction(
8496
8589
  {
8497
8590
  type: "initiate",
@@ -8648,6 +8741,19 @@ function useSubscriptionService() {
8648
8741
  { promoCode: value.promoCode ?? "", amount: subscriptionAmount },
8649
8742
  session
8650
8743
  );
8744
+ if (subscription.promoCode) {
8745
+ await updatePromoUsageStatusByOrgId(value.org, "inactive", session);
8746
+ }
8747
+ if (promo && promo._id) {
8748
+ await addPromoUsage(
8749
+ {
8750
+ promo: promo._id,
8751
+ org: value.org,
8752
+ usedBy: userData.email
8753
+ },
8754
+ session
8755
+ );
8756
+ }
8651
8757
  await addTransaction(
8652
8758
  {
8653
8759
  type: "promo-updated",
@@ -13531,6 +13637,7 @@ function useJobPostController() {
13531
13637
  usePlanService,
13532
13638
  usePromoController,
13533
13639
  usePromoRepo,
13640
+ usePromoUsageRepo,
13534
13641
  useRoleController,
13535
13642
  useRoleRepo,
13536
13643
  useRoleService,