@goweekdays/core 0.0.11 → 0.0.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/dist/index.js CHANGED
@@ -11342,8 +11342,10 @@ __export(src_exports, {
11342
11342
  MMember: () => MMember,
11343
11343
  MONGO_DB: () => MONGO_DB,
11344
11344
  MONGO_URI: () => MONGO_URI,
11345
+ MOrder: () => MOrder,
11345
11346
  MOrg: () => MOrg,
11346
11347
  MPaymentMethod: () => MPaymentMethod,
11348
+ MPromoCode: () => MPromoCode,
11347
11349
  MRole: () => MRole,
11348
11350
  MSubscription: () => MSubscription,
11349
11351
  MToken: () => MToken,
@@ -11371,6 +11373,7 @@ __export(src_exports, {
11371
11373
  XENDIT_BASE_URL: () => XENDIT_BASE_URL,
11372
11374
  XENDIT_SECRET_KEY: () => XENDIT_SECRET_KEY,
11373
11375
  isDev: () => isDev,
11376
+ schema: () => schema2,
11374
11377
  useAddressController: () => useAddressController,
11375
11378
  useAddressRepo: () => useAddressRepo,
11376
11379
  useAuthController: () => useAuthController,
@@ -11388,12 +11391,16 @@ __export(src_exports, {
11388
11391
  useFileRepo: () => useFileRepo,
11389
11392
  useFileService: () => useFileService,
11390
11393
  useMemberRepo: () => useMemberRepo,
11394
+ useOrderController: () => useOrderController,
11395
+ useOrderRepo: () => useOrderRepo,
11391
11396
  useOrgController: () => useOrgController,
11392
11397
  useOrgRepo: () => useOrgRepo,
11393
11398
  useOrgService: () => useOrgService,
11394
11399
  usePaymentMethodController: () => usePaymentMethodController,
11395
11400
  usePaymentMethodRepo: () => usePaymentMethodRepo,
11396
11401
  usePaymentMethodService: () => usePaymentMethodService,
11402
+ usePromoCodeController: () => usePromoCodeController,
11403
+ usePromoCodeRepo: () => usePromoCodeRepo,
11397
11404
  useRoleController: () => useRoleController,
11398
11405
  useRoleRepo: () => useRoleRepo,
11399
11406
  useRoleService: () => useRoleService,
@@ -12438,10 +12445,10 @@ var import_utils8 = require("@goweekdays/utils");
12438
12445
  var import_joi2 = __toESM(require("joi"));
12439
12446
  var import_mongodb8 = require("mongodb");
12440
12447
  function MMember(value) {
12441
- const schema = import_joi2.default.object({
12448
+ const schema3 = import_joi2.default.object({
12442
12449
  _id: import_joi2.default.string().hex().optional().allow("", null),
12443
- org: import_joi2.default.string().hex().required(),
12444
- orgName: import_joi2.default.string().required(),
12450
+ org: import_joi2.default.string().hex().optional().allow("", null),
12451
+ orgName: import_joi2.default.string().optional().allow("", null),
12445
12452
  name: import_joi2.default.string().required(),
12446
12453
  user: import_joi2.default.string().hex().required(),
12447
12454
  role: import_joi2.default.string().hex().required(),
@@ -12450,7 +12457,7 @@ function MMember(value) {
12450
12457
  updatedAt: import_joi2.default.string().optional().allow("", null),
12451
12458
  deletedAt: import_joi2.default.string().optional().allow("", null)
12452
12459
  });
12453
- const { error } = schema.validate(value);
12460
+ const { error } = schema3.validate(value);
12454
12461
  if (error) {
12455
12462
  throw new import_utils8.BadRequestError(error.message);
12456
12463
  }
@@ -12477,8 +12484,8 @@ function MMember(value) {
12477
12484
  }
12478
12485
  return {
12479
12486
  _id: value._id,
12480
- org: value.org,
12481
- orgName: value.orgName,
12487
+ org: value.org ?? "",
12488
+ orgName: value.orgName ?? "",
12482
12489
  name: value.name,
12483
12490
  user: value.user,
12484
12491
  role: value.role,
@@ -13520,7 +13527,10 @@ function useRoleRepo() {
13520
13527
  }
13521
13528
  async function createUniqueIndex() {
13522
13529
  try {
13523
- await collection.createIndex({ name: 1, type: 1 }, { unique: true });
13530
+ await collection.createIndex(
13531
+ { name: 1, type: 1, org: 1 },
13532
+ { unique: true }
13533
+ );
13524
13534
  } catch (error) {
13525
13535
  throw new import_utils14.InternalServerError("Failed to create unique index on role.");
13526
13536
  }
@@ -13534,7 +13544,7 @@ function useRoleRepo() {
13534
13544
  import_utils14.logger.log({ level: "error", message: `${error}` });
13535
13545
  const isDuplicated = error.message.includes("duplicate");
13536
13546
  if (isDuplicated) {
13537
- throw new import_utils14.BadRequestError("Item role already exists");
13547
+ throw new import_utils14.BadRequestError("Role already exists");
13538
13548
  }
13539
13549
  throw new import_utils14.InternalServerError("Failed to create role.");
13540
13550
  }
@@ -15527,36 +15537,75 @@ function useCommentController() {
15527
15537
 
15528
15538
  // src/models/subscription.model.ts
15529
15539
  var import_utils27 = require("@goweekdays/utils");
15540
+ var import_joi11 = __toESM(require("joi"));
15530
15541
  var import_mongodb20 = require("mongodb");
15531
15542
  function MSubscription(value) {
15532
- if (value._id) {
15533
- try {
15534
- value._id = new import_mongodb20.ObjectId(value._id);
15535
- } catch (error) {
15536
- throw new import_utils27.BadRequestError("Invalid ID.");
15537
- }
15538
- }
15539
- if (value.user) {
15540
- try {
15541
- value.user = new import_mongodb20.ObjectId(value.user);
15542
- } catch (error) {
15543
- throw new import_utils27.BadRequestError("Invalid user ID.");
15544
- }
15545
- }
15546
- if (value.org) {
15547
- try {
15548
- value.org = new import_mongodb20.ObjectId(value.org);
15549
- } catch (error) {
15550
- throw new import_utils27.BadRequestError("Invalid org ID.");
15543
+ const schema3 = import_joi11.default.object({
15544
+ _id: import_joi11.default.string().hex().optional().allow("", null),
15545
+ user: import_joi11.default.string().hex().optional().allow("", null),
15546
+ org: import_joi11.default.string().hex().optional().allow("", null),
15547
+ customerId: import_joi11.default.string().required(),
15548
+ paymentMethodId: import_joi11.default.string().required(),
15549
+ amount: import_joi11.default.number().positive().min(0).required(),
15550
+ currency: import_joi11.default.string().required(),
15551
+ description: import_joi11.default.string().optional().allow("", null),
15552
+ promoCode: import_joi11.default.string().optional().allow("", null),
15553
+ type: import_joi11.default.string().valid("organization", "affiliate").required(),
15554
+ seats: import_joi11.default.number().optional().min(0).allow(null, ""),
15555
+ status: import_joi11.default.string().optional().allow("", null),
15556
+ billingCycle: import_joi11.default.string().valid("monthly", "yearly").required(),
15557
+ // Ensure valid values
15558
+ nextBillingDate: import_joi11.default.date().optional(),
15559
+ lastPaymentStatus: import_joi11.default.string().optional().allow("", null),
15560
+ failedAttempts: import_joi11.default.number().optional().allow("", null),
15561
+ createdAt: import_joi11.default.date().optional(),
15562
+ updatedAt: import_joi11.default.string().optional().allow("", null),
15563
+ deletedAt: import_joi11.default.string().optional().allow("", null)
15564
+ }).custom((value2, helpers) => {
15565
+ if (!value2.user && !value2.org) {
15566
+ return helpers.error("any.invalid", {
15567
+ message: "Either user or org is required."
15568
+ });
15551
15569
  }
15552
- }
15570
+ return value2;
15571
+ });
15572
+ const { error } = schema3.validate(value);
15573
+ if (error) {
15574
+ throw new import_utils27.BadRequestError(error.details[0].message);
15575
+ }
15576
+ if (value._id)
15577
+ value._id = new import_mongodb20.ObjectId(value._id);
15578
+ if (value.user)
15579
+ value.user = new import_mongodb20.ObjectId(value.user);
15580
+ if (value.org)
15581
+ value.org = new import_mongodb20.ObjectId(value.org);
15582
+ const createdAt = value.createdAt ? new Date(value.createdAt) : /* @__PURE__ */ new Date();
15583
+ const nextBillingDate = new Date(createdAt);
15584
+ if (value.billingCycle === "monthly") {
15585
+ nextBillingDate.setMonth(nextBillingDate.getMonth() + 1);
15586
+ } else if (value.billingCycle === "yearly") {
15587
+ nextBillingDate.setFullYear(nextBillingDate.getFullYear() + 1);
15588
+ }
15589
+ nextBillingDate.setDate(nextBillingDate.getDate() + 1);
15553
15590
  return {
15554
15591
  _id: value._id,
15555
15592
  user: value.user ?? "",
15556
15593
  org: value.org ?? "",
15557
- subscriptionId: value.subscriptionId,
15594
+ customerId: value.customerId,
15595
+ paymentMethodId: value.paymentMethodId,
15596
+ amount: value.amount,
15597
+ currency: value.currency,
15598
+ description: value.description ?? "",
15599
+ type: value.type,
15600
+ promoCode: value.promoCode ?? "",
15601
+ seats: value.seats ?? 0,
15558
15602
  status: "active",
15559
- createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
15603
+ billingCycle: value.billingCycle,
15604
+ nextBillingDate: nextBillingDate.toISOString(),
15605
+ // Fixed nextBillingDate logic
15606
+ lastPaymentStatus: value.lastPaymentStatus ?? "success",
15607
+ failedAttempts: value.failedAttempts ?? 0,
15608
+ createdAt: createdAt.toISOString(),
15560
15609
  updatedAt: value.updatedAt ?? "",
15561
15610
  deletedAt: value.deletedAt ?? ""
15562
15611
  };
@@ -15565,6 +15614,7 @@ function MSubscription(value) {
15565
15614
  // src/repositories/subscription.repository.ts
15566
15615
  var import_utils28 = require("@goweekdays/utils");
15567
15616
  var import_mongodb21 = require("mongodb");
15617
+ var import_joi12 = __toESM(require("joi"));
15568
15618
  function useSubscriptionRepo() {
15569
15619
  const db = import_utils28.useAtlas.getDb();
15570
15620
  if (!db) {
@@ -15584,7 +15634,10 @@ function useSubscriptionRepo() {
15584
15634
  }
15585
15635
  async function createUniqueIndex() {
15586
15636
  try {
15587
- await collection.createIndex({ user: 1, status: 1 }, { unique: true });
15637
+ await collection.createIndex(
15638
+ { user: 1, org: 1, status: 1 },
15639
+ { unique: true }
15640
+ );
15588
15641
  } catch (error) {
15589
15642
  throw new import_utils28.BadRequestError(
15590
15643
  "Failed to create unique index on subscription."
@@ -15597,6 +15650,7 @@ function useSubscriptionRepo() {
15597
15650
  const res = await collection.insertOne(value, { session });
15598
15651
  return res.insertedId;
15599
15652
  } catch (error) {
15653
+ console.log(error);
15600
15654
  throw new import_utils28.BadRequestError("Failed to create subscription.");
15601
15655
  }
15602
15656
  }
@@ -15624,6 +15678,36 @@ function useSubscriptionRepo() {
15624
15678
  throw new import_utils28.BadRequestError("Failed to get subscription by ID.");
15625
15679
  }
15626
15680
  }
15681
+ async function getByAffiliateUserId(user) {
15682
+ try {
15683
+ user = new import_mongodb21.ObjectId(user);
15684
+ } catch (error) {
15685
+ throw new import_utils28.BadRequestError("Invalid user ID.");
15686
+ }
15687
+ try {
15688
+ return await collection.findOne({
15689
+ user,
15690
+ type: "affiliate"
15691
+ });
15692
+ } catch (error) {
15693
+ throw new import_utils28.BadRequestError("Failed to get subscription by ID.");
15694
+ }
15695
+ }
15696
+ async function getByOrgId(org) {
15697
+ try {
15698
+ org = new import_mongodb21.ObjectId(org);
15699
+ } catch (error) {
15700
+ throw new import_utils28.BadRequestError("Invalid org ID.");
15701
+ }
15702
+ try {
15703
+ return await collection.findOne({
15704
+ org,
15705
+ type: "organization"
15706
+ });
15707
+ } catch (error) {
15708
+ throw new import_utils28.BadRequestError("Failed to get subscription by ID.");
15709
+ }
15710
+ }
15627
15711
  async function getBySubscriptionId(subscriptionId) {
15628
15712
  try {
15629
15713
  return await collection.findOne({ subscriptionId });
@@ -15673,6 +15757,112 @@ function useSubscriptionRepo() {
15673
15757
  throw new import_utils28.BadRequestError("Failed to update subscription status.");
15674
15758
  }
15675
15759
  }
15760
+ async function getDueSubscriptions(BATCH_SIZE = 100) {
15761
+ const today = /* @__PURE__ */ new Date();
15762
+ today.setUTCHours(0, 0, 0, 0);
15763
+ try {
15764
+ return await collection.find({
15765
+ status: "active",
15766
+ nextBillingDate: { $lte: today }
15767
+ }).sort({ nextBillingDate: 1 }).limit(BATCH_SIZE).toArray();
15768
+ } catch (error) {
15769
+ throw new import_utils28.BadRequestError("Failed to get due subscriptions.");
15770
+ }
15771
+ }
15772
+ async function getFailedSubscriptions(BATCH_SIZE = 100, maxAttempts = 3) {
15773
+ try {
15774
+ return await collection.find({
15775
+ lastPaymentStatus: "failed",
15776
+ failedAttempts: { $lt: maxAttempts }
15777
+ }).limit(BATCH_SIZE).toArray();
15778
+ } catch (error) {
15779
+ throw new import_utils28.BadRequestError("Failed to get failed subscriptions.");
15780
+ }
15781
+ }
15782
+ async function processSuccessfulPayment(value, session) {
15783
+ const schema3 = import_joi12.default.object({
15784
+ _id: import_joi12.default.string().hex().required(),
15785
+ nextBillingDate: import_joi12.default.date().required()
15786
+ });
15787
+ const { error } = schema3.validate(value);
15788
+ if (error) {
15789
+ throw new import_utils28.BadRequestError(error.message);
15790
+ }
15791
+ try {
15792
+ value._id = new import_mongodb21.ObjectId(value._id);
15793
+ } catch (error2) {
15794
+ throw new import_utils28.BadRequestError("Invalid ID.");
15795
+ }
15796
+ const date = value.nextBillingDate;
15797
+ try {
15798
+ await collection.updateOne(
15799
+ { _id: value._id },
15800
+ {
15801
+ $set: {
15802
+ nextBillingDate: new Date(
15803
+ new Date(date).setMonth(new Date(date).getMonth() + 1)
15804
+ ).toISOString(),
15805
+ lastPaymentStatus: "success",
15806
+ failedAttempts: 0
15807
+ }
15808
+ },
15809
+ { session }
15810
+ );
15811
+ return "Successfully updated subscription.";
15812
+ } catch (_) {
15813
+ throw new import_utils28.BadRequestError("Failed to update subscription.");
15814
+ }
15815
+ }
15816
+ async function markSubscriptionAsFailed({ _id, failed } = {}, session) {
15817
+ const schema3 = import_joi12.default.object({
15818
+ _id: import_joi12.default.string().hex().required()
15819
+ });
15820
+ const { error } = schema3.validate({ _id });
15821
+ if (error) {
15822
+ throw new import_utils28.BadRequestError(error.message);
15823
+ }
15824
+ try {
15825
+ _id = new import_mongodb21.ObjectId(_id);
15826
+ } catch (error2) {
15827
+ throw new import_utils28.BadRequestError("Invalid ID.");
15828
+ }
15829
+ const updateOptions = {
15830
+ $inc: { failedAttempts: 1 }
15831
+ };
15832
+ if (failed) {
15833
+ updateOptions.$set = { lastPaymentStatus: "failed" };
15834
+ }
15835
+ try {
15836
+ return await collection.updateOne({ _id }, updateOptions, { session });
15837
+ } catch (error2) {
15838
+ throw new import_utils28.BadRequestError("Failed to update subscription.");
15839
+ }
15840
+ }
15841
+ async function markSubscriptionAsCanceled(_id, session) {
15842
+ const schema3 = import_joi12.default.object({
15843
+ _id: import_joi12.default.string().hex().required()
15844
+ });
15845
+ const { error } = schema3.validate({ _id });
15846
+ if (error) {
15847
+ throw new import_utils28.BadRequestError(error.message);
15848
+ }
15849
+ try {
15850
+ _id = new import_mongodb21.ObjectId(_id);
15851
+ } catch (error2) {
15852
+ throw new import_utils28.BadRequestError("Invalid ID.");
15853
+ }
15854
+ try {
15855
+ return await collection.updateOne(
15856
+ { _id },
15857
+ {
15858
+ $set: { status: "canceled" }
15859
+ },
15860
+ { session }
15861
+ );
15862
+ } catch (error2) {
15863
+ throw new import_utils28.BadRequestError("Failed to update subscription.");
15864
+ }
15865
+ }
15676
15866
  return {
15677
15867
  createIndex,
15678
15868
  createUniqueIndex,
@@ -15681,12 +15871,19 @@ function useSubscriptionRepo() {
15681
15871
  getBySubscriptionId,
15682
15872
  getByUserId,
15683
15873
  getSubscriptions,
15684
- updateStatus
15874
+ updateStatus,
15875
+ getByOrgId,
15876
+ getByAffiliateUserId,
15877
+ getDueSubscriptions,
15878
+ getFailedSubscriptions,
15879
+ processSuccessfulPayment,
15880
+ markSubscriptionAsFailed,
15881
+ markSubscriptionAsCanceled
15685
15882
  };
15686
15883
  }
15687
15884
 
15688
15885
  // src/services/subscription.service.ts
15689
- var import_utils62 = require("@goweekdays/utils");
15886
+ var import_utils64 = require("@goweekdays/utils");
15690
15887
 
15691
15888
  // node_modules/axios/lib/helpers/bind.js
15692
15889
  function bind(fn, thisArg) {
@@ -18560,7 +18757,7 @@ validators.spelling = function spelling(correctSpelling) {
18560
18757
  return true;
18561
18758
  };
18562
18759
  };
18563
- function assertOptions(options, schema, allowUnknown) {
18760
+ function assertOptions(options, schema3, allowUnknown) {
18564
18761
  if (typeof options !== "object") {
18565
18762
  throw new AxiosError_default("options must be an object", AxiosError_default.ERR_BAD_OPTION_VALUE);
18566
18763
  }
@@ -18568,7 +18765,7 @@ function assertOptions(options, schema, allowUnknown) {
18568
18765
  let i = keys.length;
18569
18766
  while (i-- > 0) {
18570
18767
  const opt = keys[i];
18571
- const validator = schema[opt];
18768
+ const validator = schema3[opt];
18572
18769
  if (validator) {
18573
18770
  const value = options[opt];
18574
18771
  const result = value === void 0 || validator(value, opt, options);
@@ -18992,6 +19189,7 @@ var {
18992
19189
  // src/services/xendit.service.ts
18993
19190
  var import_utils55 = require("@goweekdays/utils");
18994
19191
  var import_mongodb22 = require("mongodb");
19192
+ var import_joi13 = __toESM(require("joi"));
18995
19193
  function useXenditService() {
18996
19194
  const basicAuth = Buffer.from(`${XENDIT_SECRET_KEY}:`).toString("base64");
18997
19195
  const axios2 = axios_default.create({
@@ -19150,7 +19348,8 @@ function useXenditService() {
19150
19348
  amount = 0,
19151
19349
  paymentMethod = "",
19152
19350
  description = "",
19153
- interval = "MONTH"
19351
+ interval = "MONTH",
19352
+ seats = 1
19154
19353
  } = {}) {
19155
19354
  try {
19156
19355
  const res = await axios2.post("/recurring/plans", {
@@ -19183,7 +19382,9 @@ function useXenditService() {
19183
19382
  },
19184
19383
  failed_cycle_action: "STOP",
19185
19384
  immediate_action_type: "FULL_AMOUNT",
19186
- metadata: null,
19385
+ metadata: {
19386
+ seats
19387
+ },
19187
19388
  description
19188
19389
  });
19189
19390
  return res.data;
@@ -19210,6 +19411,52 @@ function useXenditService() {
19210
19411
  throw new import_utils55.BadRequestError("Failed to get subscription status.");
19211
19412
  }
19212
19413
  }
19414
+ async function getSubscription(id) {
19415
+ try {
19416
+ const res = await axios2.get(`/recurring/plans/${id}`);
19417
+ return res.data;
19418
+ } catch (error) {
19419
+ throw new import_utils55.BadRequestError("Failed to get subscription.");
19420
+ }
19421
+ }
19422
+ async function getSubscriptionCycles(id) {
19423
+ try {
19424
+ const res = await axios2.get(`/recurring/plans/${id}/cycles`);
19425
+ return res.data;
19426
+ } catch (error) {
19427
+ throw new import_utils55.BadRequestError("Failed to get subscription cycles.");
19428
+ }
19429
+ }
19430
+ async function pay(value) {
19431
+ try {
19432
+ const schema3 = import_joi13.default.object({
19433
+ amount: import_joi13.default.number().positive().min(0).required(),
19434
+ currency: import_joi13.default.string().required(),
19435
+ payment_method_id: import_joi13.default.string().required(),
19436
+ customer_id: import_joi13.default.string().required(),
19437
+ description: import_joi13.default.string().optional().allow("", null),
19438
+ metadata: import_joi13.default.object().optional()
19439
+ });
19440
+ const { error } = schema3.validate(value);
19441
+ if (error) {
19442
+ throw new import_utils55.BadRequestError(error.message);
19443
+ }
19444
+ const res = await axios2.post("/payment_requests", {
19445
+ amount: value.amount,
19446
+ currency: value.currency,
19447
+ payment_method_id: value.payment_method_id,
19448
+ customer_id: value.customer_id,
19449
+ description: value.description ?? "",
19450
+ metadata: value.metadata ?? {}
19451
+ });
19452
+ return res.data;
19453
+ } catch (error) {
19454
+ if (error instanceof import_utils55.AppError) {
19455
+ throw error;
19456
+ }
19457
+ throw new import_utils55.BadRequestError("Failed to initiate payment request.");
19458
+ }
19459
+ }
19213
19460
  return {
19214
19461
  createCustomer,
19215
19462
  linkPaymentMethodEWallet,
@@ -19218,7 +19465,10 @@ function useXenditService() {
19218
19465
  linkPaymentMethodCard,
19219
19466
  eWalletSubsequentPayment,
19220
19467
  checkSubscriptionStatus,
19221
- cancelSubscription
19468
+ cancelSubscription,
19469
+ getSubscription,
19470
+ getSubscriptionCycles,
19471
+ pay
19222
19472
  };
19223
19473
  }
19224
19474
 
@@ -19253,7 +19503,8 @@ function MPaymentMethod(value) {
19253
19503
  paymentId: value.paymentId ?? "",
19254
19504
  customerId: value.customerId ?? "",
19255
19505
  number: value.number,
19256
- expiry: value.expiry ?? "",
19506
+ month_expiry: value.month_expiry ?? "",
19507
+ year_expiry: value.year_expiry ?? "",
19257
19508
  cvv: value.cvv ?? "",
19258
19509
  status: value.status ?? "active",
19259
19510
  createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
@@ -19405,23 +19656,23 @@ var import_utils59 = require("@goweekdays/utils");
19405
19656
 
19406
19657
  // src/models/organization.model.ts
19407
19658
  var import_utils58 = require("@goweekdays/utils");
19408
- var import_joi11 = __toESM(require("joi"));
19659
+ var import_joi14 = __toESM(require("joi"));
19409
19660
  var import_mongodb25 = require("mongodb");
19410
19661
  function MOrg(value) {
19411
- const schema = import_joi11.default.object({
19412
- _id: import_joi11.default.string().hex().optional().allow("", null),
19413
- name: import_joi11.default.string().required(),
19414
- email: import_joi11.default.string().email().required(),
19415
- contact: import_joi11.default.string().required(),
19416
- type: import_joi11.default.string().required(),
19417
- busInst: import_joi11.default.string().optional().allow("", null),
19418
- description: import_joi11.default.string().optional().allow("", null),
19419
- status: import_joi11.default.string().optional().allow("", null),
19420
- createdAt: import_joi11.default.string().optional().allow("", null),
19421
- updatedAt: import_joi11.default.string().optional().allow("", null),
19422
- deletedAt: import_joi11.default.string().optional().allow("", null)
19662
+ const schema3 = import_joi14.default.object({
19663
+ _id: import_joi14.default.string().hex().optional().allow("", null),
19664
+ name: import_joi14.default.string().required(),
19665
+ email: import_joi14.default.string().email().required(),
19666
+ contact: import_joi14.default.string().required(),
19667
+ type: import_joi14.default.string().required(),
19668
+ busInst: import_joi14.default.string().optional().allow("", null),
19669
+ description: import_joi14.default.string().optional().allow("", null),
19670
+ status: import_joi14.default.string().optional().allow("", null),
19671
+ createdAt: import_joi14.default.string().optional().allow("", null),
19672
+ updatedAt: import_joi14.default.string().optional().allow("", null),
19673
+ deletedAt: import_joi14.default.string().optional().allow("", null)
19423
19674
  });
19424
- const { error } = schema.validate(value);
19675
+ const { error } = schema3.validate(value);
19425
19676
  if (error) {
19426
19677
  throw new import_utils58.BadRequestError(error.message);
19427
19678
  }
@@ -19710,27 +19961,198 @@ function useAddressRepo() {
19710
19961
  };
19711
19962
  }
19712
19963
 
19964
+ // src/repositories/order.repository.ts
19965
+ var import_utils63 = require("@goweekdays/utils");
19966
+
19967
+ // src/models/order.model.ts
19968
+ var import_mongodb29 = require("mongodb");
19969
+
19970
+ // src/validations/order.schema.ts
19971
+ var import_joi15 = __toESM(require("joi"));
19972
+ var schema = import_joi15.default.object({
19973
+ _id: import_joi15.default.string().hex().optional().allow("", null),
19974
+ payment: import_joi15.default.string().required(),
19975
+ user: import_joi15.default.string().hex().required(),
19976
+ org: import_joi15.default.string().hex().optional().allow("", null),
19977
+ type: import_joi15.default.string().required(),
19978
+ amount: import_joi15.default.number().positive().min(0).required(),
19979
+ currency: import_joi15.default.string().required(),
19980
+ description: import_joi15.default.string().optional().allow("", null),
19981
+ metadata: import_joi15.default.object({
19982
+ subscriptionId: import_joi15.default.string().hex().optional().allow("", null),
19983
+ cycle: import_joi15.default.number().optional().allow("", null),
19984
+ seats: import_joi15.default.number().optional().allow("", null),
19985
+ promoCode: import_joi15.default.string().optional().allow("", null)
19986
+ }).optional().allow("", null),
19987
+ status: import_joi15.default.string().optional().allow("", null),
19988
+ createdAt: import_joi15.default.string().optional().allow("", null),
19989
+ updatedAt: import_joi15.default.string().optional().allow("", null),
19990
+ deletedAt: import_joi15.default.string().optional().allow("", null)
19991
+ });
19992
+
19993
+ // src/models/order.model.ts
19994
+ var import_utils62 = require("@goweekdays/utils");
19995
+ function MOrder(value) {
19996
+ const { error } = schema.validate(value);
19997
+ if (error) {
19998
+ throw new import_utils62.BadRequestError(error.message);
19999
+ }
20000
+ if (value._id) {
20001
+ try {
20002
+ value._id = new import_mongodb29.ObjectId(value._id);
20003
+ } catch (error2) {
20004
+ throw new import_utils62.BadRequestError("Invalid ID.");
20005
+ }
20006
+ }
20007
+ if (value.user) {
20008
+ try {
20009
+ value.user = new import_mongodb29.ObjectId(value.user);
20010
+ } catch (error2) {
20011
+ throw new import_utils62.BadRequestError("Invalid user ID.");
20012
+ }
20013
+ }
20014
+ if (value.org) {
20015
+ try {
20016
+ value.org = new import_mongodb29.ObjectId(value.org);
20017
+ } catch (error2) {
20018
+ throw new import_utils62.BadRequestError("Invalid org ID.");
20019
+ }
20020
+ }
20021
+ if (value.metadata?.subscriptionId) {
20022
+ try {
20023
+ value.metadata.subscriptionId = new import_mongodb29.ObjectId(
20024
+ value.metadata.subscriptionId
20025
+ );
20026
+ } catch (error2) {
20027
+ throw new import_utils62.BadRequestError("Invalid subscription ID.");
20028
+ }
20029
+ }
20030
+ return {
20031
+ _id: value._id,
20032
+ payment: value.payment,
20033
+ user: value.user ?? "",
20034
+ org: value.org ?? "",
20035
+ type: value.type,
20036
+ amount: value.amount,
20037
+ currency: value.currency,
20038
+ description: value.description ?? "",
20039
+ metadata: value.metadata ?? {},
20040
+ status: value.status ?? "succeeded",
20041
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
20042
+ updatedAt: value.updatedAt ?? "",
20043
+ deletedAt: value.deletedAt ?? ""
20044
+ };
20045
+ }
20046
+
20047
+ // src/repositories/order.repository.ts
20048
+ var import_mongodb30 = require("mongodb");
20049
+ function useOrderRepo() {
20050
+ const db = import_utils63.useAtlas.getDb();
20051
+ if (!db) {
20052
+ throw new import_utils63.InternalServerError("Unable to connect to server.");
20053
+ }
20054
+ const collection = db.collection("orders");
20055
+ function createIndex() {
20056
+ try {
20057
+ collection.createIndexes([
20058
+ { key: { "metadata.subscriptionId": 1 } },
20059
+ { key: { status: 1 } },
20060
+ { key: { type: 1 } }
20061
+ ]);
20062
+ } catch (error) {
20063
+ throw new Error("Failed to create index for promo code.");
20064
+ }
20065
+ }
20066
+ function add(value, session) {
20067
+ try {
20068
+ value = MOrder(value);
20069
+ collection.insertOne(value, { session });
20070
+ } catch (error) {
20071
+ import_utils63.logger.log({ level: "error", message: `${error}` });
20072
+ if (error instanceof import_utils63.AppError) {
20073
+ throw error;
20074
+ }
20075
+ throw new import_utils63.InternalServerError("Internal server error.");
20076
+ }
20077
+ }
20078
+ async function getOrders({
20079
+ search = "",
20080
+ page = 1,
20081
+ limit = 10,
20082
+ sort = {},
20083
+ status = "active",
20084
+ type = "",
20085
+ id = ""
20086
+ } = {}) {
20087
+ page = page > 0 ? page - 1 : 0;
20088
+ const query = { status };
20089
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
20090
+ if (search) {
20091
+ query.$text = { $search: search };
20092
+ }
20093
+ if (type) {
20094
+ query.type = type;
20095
+ }
20096
+ if (id) {
20097
+ try {
20098
+ query["metadata.subscriptionId"] = new import_mongodb30.ObjectId(id);
20099
+ } catch (error) {
20100
+ throw new import_utils63.BadRequestError("Invalid subscription ID.");
20101
+ }
20102
+ }
20103
+ try {
20104
+ const items = await collection.aggregate([
20105
+ { $match: query },
20106
+ { $sort: sort },
20107
+ { $skip: page * limit },
20108
+ { $limit: limit }
20109
+ ]).toArray();
20110
+ const length = await collection.countDocuments(query);
20111
+ return (0, import_utils63.paginate)(items, page, limit, length);
20112
+ } catch (error) {
20113
+ import_utils63.logger.log({ level: "error", message: `${error}` });
20114
+ throw new import_utils63.InternalServerError("Internal server error.");
20115
+ }
20116
+ }
20117
+ return {
20118
+ createIndex,
20119
+ add,
20120
+ getOrders
20121
+ };
20122
+ }
20123
+
19713
20124
  // src/services/subscription.service.ts
19714
20125
  function useSubscriptionService() {
19715
- const { getByUserId: _getByUserId, add } = useSubscriptionRepo();
20126
+ const {
20127
+ getByUserId: _getByUserId,
20128
+ add,
20129
+ getByOrgId: _getByOrgId,
20130
+ getDueSubscriptions,
20131
+ processSuccessfulPayment,
20132
+ markSubscriptionAsFailed,
20133
+ getFailedSubscriptions,
20134
+ markSubscriptionAsCanceled
20135
+ } = useSubscriptionRepo();
19716
20136
  const { getUserById: _getUserByUserId, updateUserFieldById } = useUserRepo();
19717
- const { initSubscription, checkSubscriptionStatus } = useXenditService();
19718
- const { add: addPaymentMethod, getByPaymentMethodId } = usePaymentMethodRepo();
20137
+ const {
20138
+ checkSubscriptionStatus,
20139
+ getSubscription,
20140
+ getSubscriptionCycles,
20141
+ pay
20142
+ } = useXenditService();
20143
+ const { add: addPaymentMethod } = usePaymentMethodRepo();
19719
20144
  const { add: addOrg } = useOrgRepo();
19720
20145
  const { add: addAddress } = useAddressRepo();
19721
20146
  const { addRole } = useRoleRepo();
19722
20147
  const { add: addMember } = useMemberRepo();
20148
+ const { add: addOrder } = useOrderRepo();
19723
20149
  async function createOrgSubscription(value) {
19724
- const session = import_utils62.useAtlas.getClient()?.startSession();
20150
+ const session = import_utils64.useAtlas.getClient()?.startSession();
19725
20151
  session?.startTransaction();
19726
20152
  try {
19727
20153
  const _user = await _getUserByUserId(value.user);
19728
20154
  if (!_user) {
19729
- throw new import_utils62.BadRequestError("User not found.");
19730
- }
19731
- const payment = await getByPaymentMethodId(value.payment_method_id);
19732
- if (!payment) {
19733
- throw new import_utils62.BadRequestError("Payment method not found.");
20155
+ throw new import_utils64.BadRequestError("User not found.");
19734
20156
  }
19735
20157
  const org = await addOrg(value.organization, session);
19736
20158
  const role = await addRole(
@@ -19759,64 +20181,118 @@ function useSubscriptionService() {
19759
20181
  session
19760
20182
  );
19761
20183
  }
19762
- payment.user = "";
19763
- payment.org = org;
19764
- delete payment._id;
19765
- await addPaymentMethod(payment, session);
19766
- value.billingAddress.org = org;
19767
- await addAddress(value.billingAddress, session);
19768
- const subscription = await initSubscription({
19769
- customer: value.customer_id,
19770
- paymentMethod: value.payment_method_id,
19771
- amount: value.amount,
19772
- description: "GoWeekdays Organization Monthly Subscription."
19773
- });
19774
- await add(
20184
+ await addPaymentMethod(
19775
20185
  {
19776
20186
  org,
19777
- subscriptionId: subscription.id
20187
+ paymentId: value.payment_method_id,
20188
+ customerId: value.customer_id,
20189
+ type: value.payment_method_type,
20190
+ name: value.payment_method_channel,
20191
+ number: value.payment_method_number,
20192
+ month_expiry: value.payment_method_expiry_month,
20193
+ year_expiry: value.payment_method_expiry_year,
20194
+ cvv: value.payment_method_cvv
19778
20195
  },
19779
20196
  session
19780
20197
  );
19781
- await session?.commitTransaction();
19782
- return "Subscription created successfully.";
19783
- } catch (error) {
20198
+ value.billingAddress.org = org;
20199
+ await addAddress(value.billingAddress, session);
20200
+ const description = "GoWeekdays Organization Monthly Subscription.";
20201
+ const subscription = await add(
20202
+ {
20203
+ org: org.toString(),
20204
+ customerId: value.customer_id,
20205
+ paymentMethodId: value.payment_method_id,
20206
+ amount: value.amount,
20207
+ currency: value.currency,
20208
+ type: "organization",
20209
+ description,
20210
+ seats: value.seats,
20211
+ billingCycle: "monthly"
20212
+ },
20213
+ session
20214
+ );
20215
+ const payment = await pay({
20216
+ customer_id: value.customer_id,
20217
+ payment_method_id: value.payment_method_id,
20218
+ amount: value.amount,
20219
+ currency: value.currency,
20220
+ description
20221
+ });
20222
+ await addOrder(
20223
+ {
20224
+ payment: payment.id,
20225
+ user: value.user,
20226
+ org: org.toString(),
20227
+ type: "organization",
20228
+ amount: value.amount,
20229
+ currency: value.currency,
20230
+ description,
20231
+ metadata: { subscriptionId: subscription.toString() }
20232
+ },
20233
+ session
20234
+ );
20235
+ await session?.commitTransaction();
20236
+ return {
20237
+ message: "Subscription created successfully.",
20238
+ data: { org: org.toString() }
20239
+ };
20240
+ } catch (error) {
19784
20241
  await session?.abortTransaction();
19785
20242
  throw error;
19786
20243
  } finally {
19787
20244
  session?.endSession();
19788
20245
  }
19789
20246
  }
19790
- async function createAffiliateSubscription({
19791
- user = "",
19792
- amount = 0,
19793
- payment_method_id = "",
19794
- customer_id = ""
19795
- } = {}) {
19796
- const session = import_utils62.useAtlas.getClient()?.startSession();
20247
+ async function createAffiliateSubscription(value) {
20248
+ const session = import_utils64.useAtlas.getClient()?.startSession();
19797
20249
  session?.startTransaction();
19798
20250
  try {
19799
- const _user = await _getUserByUserId(user);
20251
+ const _user = await _getUserByUserId(value.user);
19800
20252
  if (!_user) {
19801
- throw new import_utils62.BadRequestError("User not found.");
20253
+ throw new import_utils64.BadRequestError("User not found.");
19802
20254
  }
19803
- const subscription = await initSubscription({
19804
- customer: customer_id,
19805
- paymentMethod: payment_method_id,
19806
- amount,
19807
- description: "GoWeekdays Affiliate Annual Subscription.",
19808
- interval: "YEAR"
19809
- });
19810
- await add(
20255
+ await addAddress(value.billingAddress, session);
20256
+ const description = "GoWeekdays affiliate yearly Subscription.";
20257
+ const subscription = await add(
19811
20258
  {
19812
- user,
19813
- subscriptionId: subscription.id
20259
+ user: value.user,
20260
+ customerId: value.customer_id,
20261
+ paymentMethodId: value.payment_method_id,
20262
+ amount: value.amount,
20263
+ currency: value.currency,
20264
+ type: "affiliate",
20265
+ description,
20266
+ billingCycle: "yearly"
20267
+ },
20268
+ session
20269
+ );
20270
+ let payment = {};
20271
+ if (value.amount) {
20272
+ payment = await pay({
20273
+ customer_id: value.customer_id,
20274
+ payment_method_id: value.payment_method_id,
20275
+ amount: value.amount,
20276
+ currency: value.currency,
20277
+ description
20278
+ });
20279
+ }
20280
+ await addOrder(
20281
+ {
20282
+ payment: payment.id,
20283
+ user: value.user,
20284
+ type: "affiliate",
20285
+ amount: value.amount,
20286
+ currency: value.currency,
20287
+ description,
20288
+ metadata: { subscriptionId: subscription.toString() }
19814
20289
  },
19815
20290
  session
19816
20291
  );
19817
20292
  await session?.commitTransaction();
19818
20293
  return "Subscription created successfully.";
19819
20294
  } catch (error) {
20295
+ console.log(error);
19820
20296
  await session?.abortTransaction();
19821
20297
  throw error;
19822
20298
  } finally {
@@ -19827,9 +20303,10 @@ function useSubscriptionService() {
19827
20303
  try {
19828
20304
  const subscription = await _getByUserId(id);
19829
20305
  if (!subscription) {
19830
- throw new import_utils62.BadRequestError("Subscription not found.");
20306
+ throw new import_utils64.BadRequestError("Subscription not found.");
19831
20307
  }
19832
- return subscription;
20308
+ const customerSubscription = await getSubscription(id);
20309
+ return customerSubscription;
19833
20310
  } catch (error) {
19834
20311
  throw error;
19835
20312
  }
@@ -19842,57 +20319,204 @@ function useSubscriptionService() {
19842
20319
  );
19843
20320
  return status;
19844
20321
  } catch (error) {
19845
- throw new import_utils62.BadRequestError("Failed to fetch subscription status");
20322
+ throw new import_utils64.BadRequestError("Failed to fetch subscription status");
19846
20323
  }
19847
20324
  }
20325
+ async function processSubscriptions(batchSize = 100) {
20326
+ while (true) {
20327
+ const subscriptions = await getDueSubscriptions(batchSize);
20328
+ if (subscriptions.length === 0) {
20329
+ import_utils64.logger.log({
20330
+ level: "info",
20331
+ message: "No more subscriptions to process."
20332
+ });
20333
+ break;
20334
+ }
20335
+ await Promise.allSettled(
20336
+ subscriptions.map(async (sub) => {
20337
+ const session = import_utils64.useAtlas.getClient()?.startSession();
20338
+ session?.startTransaction();
20339
+ try {
20340
+ const payment = await pay({
20341
+ customer_id: sub.customerId,
20342
+ payment_method_id: sub.paymentMethodId,
20343
+ amount: sub.amount,
20344
+ currency: sub.currency,
20345
+ description: "GoWeekdays Monthly Subscription"
20346
+ });
20347
+ await addOrder(
20348
+ {
20349
+ payment: payment.id,
20350
+ user: sub.user,
20351
+ org: sub.org,
20352
+ type: "organization",
20353
+ amount: sub.amount,
20354
+ currency: sub.currency,
20355
+ description: "GoWeekdays Monthly Subscription",
20356
+ metadata: { subscriptionId: sub._id }
20357
+ },
20358
+ session
20359
+ );
20360
+ await processSuccessfulPayment(
20361
+ { _id: sub._id, nextBillingDate: sub.nextBillingDate },
20362
+ session
20363
+ );
20364
+ await session?.commitTransaction();
20365
+ import_utils64.logger.log({
20366
+ level: "info",
20367
+ message: `Processed subscription ${sub._id} successfully.`
20368
+ });
20369
+ } catch (error) {
20370
+ await session?.abortTransaction();
20371
+ import_utils64.logger.log({
20372
+ level: "error",
20373
+ message: `Failed to process ${sub._id}: ${error}`
20374
+ });
20375
+ await markSubscriptionAsFailed({
20376
+ _id: String(sub._id),
20377
+ failed: true
20378
+ });
20379
+ } finally {
20380
+ session?.endSession();
20381
+ }
20382
+ })
20383
+ );
20384
+ import_utils64.logger.log({
20385
+ level: "info",
20386
+ message: "Processed a batch of subscriptions."
20387
+ });
20388
+ }
20389
+ }
20390
+ async function retryFailedPayments(batchSize = 100) {
20391
+ let hasMore = true;
20392
+ while (hasMore) {
20393
+ const failedSubs = await getFailedSubscriptions(batchSize);
20394
+ if (failedSubs.length === 0) {
20395
+ hasMore = false;
20396
+ break;
20397
+ }
20398
+ await Promise.allSettled(
20399
+ failedSubs.map(async (sub) => {
20400
+ const session = import_utils64.useAtlas.getClient()?.startSession();
20401
+ session?.startTransaction();
20402
+ try {
20403
+ const payment = await pay({
20404
+ customer_id: sub.customerId,
20405
+ payment_method_id: sub.paymentMethodId,
20406
+ amount: sub.amount,
20407
+ currency: sub.currency,
20408
+ description: "GoWeekdays Monthly Subscription - Retry"
20409
+ });
20410
+ await addOrder(
20411
+ {
20412
+ payment: payment.id,
20413
+ user: sub.user,
20414
+ org: sub.org,
20415
+ type: "organization",
20416
+ amount: sub.amount,
20417
+ currency: sub.currency,
20418
+ description: "GoWeekdays Monthly Subscription",
20419
+ metadata: { subscriptionId: sub._id }
20420
+ },
20421
+ session
20422
+ );
20423
+ await processSuccessfulPayment(
20424
+ { _id: sub._id, nextBillingDate: sub.nextBillingDate },
20425
+ session
20426
+ );
20427
+ await session?.commitTransaction();
20428
+ import_utils64.logger.log({
20429
+ level: "info",
20430
+ message: `Successfully retried subscription ${sub._id}.`
20431
+ });
20432
+ } catch (error) {
20433
+ await session?.abortTransaction();
20434
+ import_utils64.logger.log({
20435
+ level: "error",
20436
+ message: `Retry failed for ${sub._id}: ${error}`
20437
+ });
20438
+ await markSubscriptionAsFailed({ _id: String(sub._id) });
20439
+ if (sub.failedAttempts && sub.failedAttempts + 1 >= 3) {
20440
+ await markSubscriptionAsCanceled(String(sub._id));
20441
+ import_utils64.logger.log({
20442
+ level: "info",
20443
+ message: `Subscription ${sub._id} canceled after max retry attempts.`
20444
+ });
20445
+ }
20446
+ } finally {
20447
+ session?.endSession();
20448
+ }
20449
+ })
20450
+ );
20451
+ import_utils64.logger.log({
20452
+ level: "info",
20453
+ message: `Processed batch of ${failedSubs.length}.`
20454
+ });
20455
+ }
20456
+ import_utils64.logger.log({ level: "info", message: "All failed payments retried." });
20457
+ }
19848
20458
  return {
19849
20459
  getByUserId,
19850
20460
  getStatusByUser,
19851
20461
  createAffiliateSubscription,
19852
- createOrgSubscription
20462
+ createOrgSubscription,
20463
+ processSubscriptions,
20464
+ retryFailedPayments
19853
20465
  };
19854
20466
  }
19855
20467
 
19856
20468
  // src/controllers/subscription.controller.ts
19857
- var import_joi13 = __toESM(require("joi"));
19858
- var import_utils63 = require("@goweekdays/utils");
20469
+ var import_joi17 = __toESM(require("joi"));
20470
+ var import_utils65 = require("@goweekdays/utils");
19859
20471
 
19860
20472
  // src/validations/subscription.schema.ts
19861
- var import_joi12 = __toESM(require("joi"));
20473
+ var import_joi16 = __toESM(require("joi"));
19862
20474
  function useSubscriptionSchema() {
19863
- const schema = import_joi12.default.object({
19864
- user: import_joi12.default.string().required(),
19865
- amount: import_joi12.default.number().required(),
19866
- customer_id: import_joi12.default.string().required(),
19867
- payment_method_id: import_joi12.default.string().required(),
19868
- currency: import_joi12.default.string().optional().allow("", null),
19869
- organization: import_joi12.default.object({
19870
- name: import_joi12.default.string().required(),
19871
- description: import_joi12.default.string().optional().allow("", null),
19872
- type: import_joi12.default.string().allow("personal", "business").required(),
19873
- email: import_joi12.default.string().email().required(),
19874
- contact: import_joi12.default.string().required(),
19875
- busInst: import_joi12.default.string().optional().allow(null, "")
19876
- }).required(),
19877
- billingAddress: import_joi12.default.object({
19878
- type: import_joi12.default.string().required(),
19879
- country: import_joi12.default.string().required(),
19880
- address: import_joi12.default.string().required(),
19881
- continuedAddress: import_joi12.default.string().optional().allow(null, ""),
19882
- city: import_joi12.default.string().required(),
19883
- province: import_joi12.default.string().required(),
19884
- postalCode: import_joi12.default.string().required(),
19885
- taxId: import_joi12.default.string().optional().allow(null, "")
20475
+ const schema3 = import_joi16.default.object({
20476
+ user: import_joi16.default.string().required().min(0),
20477
+ amount: import_joi16.default.number().required(),
20478
+ customer_id: import_joi16.default.string().required(),
20479
+ payment_method_id: import_joi16.default.string().required(),
20480
+ payment_method_type: import_joi16.default.string().required(),
20481
+ payment_method_number: import_joi16.default.string().required(),
20482
+ payment_method_channel: import_joi16.default.string().required(),
20483
+ payment_method_month_expiry: import_joi16.default.string().optional().allow(null, ""),
20484
+ payment_method_year_expiry: import_joi16.default.string().optional().allow(null, ""),
20485
+ payment_method_cvv: import_joi16.default.string().optional().allow(null, ""),
20486
+ currency: import_joi16.default.string().optional().allow("", null),
20487
+ seats: import_joi16.default.number().optional().min(0).allow(null),
20488
+ organization: import_joi16.default.object({
20489
+ name: import_joi16.default.string().required(),
20490
+ description: import_joi16.default.string().optional().allow("", null),
20491
+ type: import_joi16.default.string().allow("personal", "business").required(),
20492
+ email: import_joi16.default.string().email().required(),
20493
+ contact: import_joi16.default.string().required(),
20494
+ busInst: import_joi16.default.string().optional().allow(null, "")
20495
+ }).optional().allow({}),
20496
+ billingAddress: import_joi16.default.object({
20497
+ type: import_joi16.default.string().required(),
20498
+ country: import_joi16.default.string().required(),
20499
+ address: import_joi16.default.string().required(),
20500
+ continuedAddress: import_joi16.default.string().optional().allow(null, ""),
20501
+ city: import_joi16.default.string().required(),
20502
+ province: import_joi16.default.string().required(),
20503
+ postalCode: import_joi16.default.string().required(),
20504
+ taxId: import_joi16.default.string().optional().allow(null, "")
19886
20505
  }).required()
19887
20506
  });
19888
20507
  return {
19889
- schema
20508
+ schema: schema3
19890
20509
  };
19891
20510
  }
19892
20511
 
19893
20512
  // src/controllers/subscription.controller.ts
19894
20513
  function useSubscriptionController() {
19895
- const { add: _add, getSubscriptions: _getSubscriptions } = useSubscriptionRepo();
20514
+ const {
20515
+ add: _add,
20516
+ getSubscriptions: _getSubscriptions,
20517
+ getByAffiliateUserId: _getByAffiliateUserId,
20518
+ getByOrgId: _getByOrgId
20519
+ } = useSubscriptionRepo();
19896
20520
  const {
19897
20521
  getByUserId: _getByUserId,
19898
20522
  getStatusByUser: _getStatusByUser,
@@ -19901,13 +20525,13 @@ function useSubscriptionController() {
19901
20525
  } = useSubscriptionService();
19902
20526
  async function add(req, res, next) {
19903
20527
  const value = req.body;
19904
- const validation = import_joi13.default.object({
19905
- user: import_joi13.default.string().required(),
19906
- subscriptionId: import_joi13.default.string().required()
20528
+ const validation = import_joi17.default.object({
20529
+ user: import_joi17.default.string().required(),
20530
+ subscriptionId: import_joi17.default.string().required()
19907
20531
  });
19908
20532
  const { error } = validation.validate(value);
19909
20533
  if (error) {
19910
- next(new import_utils63.BadRequestError(error.message));
20534
+ next(new import_utils65.BadRequestError(error.message));
19911
20535
  }
19912
20536
  try {
19913
20537
  const value2 = req.body;
@@ -19920,10 +20544,10 @@ function useSubscriptionController() {
19920
20544
  }
19921
20545
  async function getByUserId(req, res, next) {
19922
20546
  const id = req.params.id;
19923
- const validation = import_joi13.default.string().required();
20547
+ const validation = import_joi17.default.string().required();
19924
20548
  const { error } = validation.validate(id);
19925
20549
  if (error) {
19926
- next(new import_utils63.BadRequestError(error.message));
20550
+ next(new import_utils65.BadRequestError(error.message));
19927
20551
  }
19928
20552
  try {
19929
20553
  const subscription = await _getByUserId(id);
@@ -19933,18 +20557,48 @@ function useSubscriptionController() {
19933
20557
  next(error2);
19934
20558
  }
19935
20559
  }
20560
+ async function getByAffiliateUserId(req, res, next) {
20561
+ const id = req.params.id;
20562
+ const validation = import_joi17.default.string().required();
20563
+ const { error } = validation.validate(id);
20564
+ if (error) {
20565
+ next(new import_utils65.BadRequestError(error.message));
20566
+ }
20567
+ try {
20568
+ const subscription = await _getByAffiliateUserId(id);
20569
+ res.json(subscription);
20570
+ return;
20571
+ } catch (error2) {
20572
+ next(error2);
20573
+ }
20574
+ }
20575
+ async function getByOrgId(req, res, next) {
20576
+ const id = req.params.id;
20577
+ const validation = import_joi17.default.string().required();
20578
+ const { error } = validation.validate(id);
20579
+ if (error) {
20580
+ next(new import_utils65.BadRequestError(error.message));
20581
+ }
20582
+ try {
20583
+ const subscription = await _getByOrgId(id);
20584
+ res.json(subscription);
20585
+ return;
20586
+ } catch (error2) {
20587
+ next(error2);
20588
+ }
20589
+ }
19936
20590
  async function getSubscriptions(req, res, next) {
19937
20591
  const status = req.query.status ?? "";
19938
20592
  const search = req.query.search ?? "";
19939
20593
  const page = Number(req.query.page) ?? 1;
19940
- const validation = import_joi13.default.object({
19941
- status: import_joi13.default.string().required(),
19942
- search: import_joi13.default.string().optional().allow("", null),
19943
- page: import_joi13.default.number().required()
20594
+ const validation = import_joi17.default.object({
20595
+ status: import_joi17.default.string().required(),
20596
+ search: import_joi17.default.string().optional().allow("", null),
20597
+ page: import_joi17.default.number().required()
19944
20598
  });
19945
20599
  const { error } = validation.validate({ status, search, page });
19946
20600
  if (error) {
19947
- next(new import_utils63.BadRequestError(error.message));
20601
+ next(new import_utils65.BadRequestError(error.message));
19948
20602
  }
19949
20603
  try {
19950
20604
  const subscriptions = await _getSubscriptions({ status, search, page });
@@ -19956,10 +20610,10 @@ function useSubscriptionController() {
19956
20610
  }
19957
20611
  async function getSubscriptionStatus(req, res, next) {
19958
20612
  const id = req.params.id;
19959
- const validation = import_joi13.default.string().required();
20613
+ const validation = import_joi17.default.string().required();
19960
20614
  const { error } = validation.validate(id);
19961
20615
  if (error) {
19962
- next(new import_utils63.BadRequestError(error.message));
20616
+ next(new import_utils65.BadRequestError(error.message));
19963
20617
  }
19964
20618
  try {
19965
20619
  const status = await _getStatusByUser(id);
@@ -19969,37 +20623,17 @@ function useSubscriptionController() {
19969
20623
  next(error2);
19970
20624
  }
19971
20625
  }
20626
+ const { schema: subscriptionSchema } = useSubscriptionSchema();
19972
20627
  async function createAffiliateSubscription(req, res, next) {
19973
- const amount = req.body.amount ?? 0;
19974
- const payment_method_id = req.body.payment_method_id ?? "";
19975
- const customer_id = req.body.customer_id ?? "";
19976
- const currency = req.body.currency ?? "PHP";
19977
- const user = req.headers["user"];
19978
- const validation = import_joi13.default.object({
19979
- user: import_joi13.default.string().required(),
19980
- amount: import_joi13.default.number().required(),
19981
- customer_id: import_joi13.default.string().required(),
19982
- payment_method_id: import_joi13.default.string().required(),
19983
- currency: import_joi13.default.string().optional().allow("", null)
19984
- });
19985
- const { error } = validation.validate({
19986
- user,
19987
- amount,
19988
- customer_id,
19989
- payment_method_id,
19990
- currency
19991
- });
20628
+ const value = req.body;
20629
+ value.user = req.headers["user"];
20630
+ const { error } = subscriptionSchema.validate(value);
19992
20631
  if (error) {
19993
- next(new import_utils63.BadRequestError(error.message));
20632
+ next(new import_utils65.BadRequestError(error.message));
19994
20633
  return;
19995
20634
  }
19996
20635
  try {
19997
- const id = await _createAffiliateSubscription({
19998
- user,
19999
- amount,
20000
- customer_id,
20001
- payment_method_id
20002
- });
20636
+ const id = await _createAffiliateSubscription(value);
20003
20637
  res.json({ message: "Successfully added subscription.", id });
20004
20638
  return;
20005
20639
  } catch (error2) {
@@ -20008,18 +20642,17 @@ function useSubscriptionController() {
20008
20642
  return;
20009
20643
  }
20010
20644
  }
20011
- const { schema: subscriptionSchema } = useSubscriptionSchema();
20012
20645
  async function createOrgSubscription(req, res, next) {
20013
20646
  const value = req.body;
20014
20647
  value.user = req.headers["user"];
20015
20648
  const { error } = subscriptionSchema.validate(value);
20016
20649
  if (error) {
20017
- next(new import_utils63.BadRequestError(error.message));
20650
+ next(new import_utils65.BadRequestError(error.message));
20018
20651
  return;
20019
20652
  }
20020
20653
  try {
20021
- const id = await _createOrgSubscription(value);
20022
- res.json({ message: "Successfully added subscription.", id });
20654
+ const _res = await _createOrgSubscription(value);
20655
+ res.json(_res);
20023
20656
  return;
20024
20657
  } catch (error2) {
20025
20658
  next(error2);
@@ -20029,6 +20662,8 @@ function useSubscriptionController() {
20029
20662
  return {
20030
20663
  add,
20031
20664
  getByUserId,
20665
+ getByOrgId,
20666
+ getByAffiliateUserId,
20032
20667
  getSubscriptions,
20033
20668
  getSubscriptionStatus,
20034
20669
  createAffiliateSubscription,
@@ -20037,7 +20672,7 @@ function useSubscriptionController() {
20037
20672
  }
20038
20673
 
20039
20674
  // src/services/payment-method.service.ts
20040
- var import_utils64 = require("@goweekdays/utils");
20675
+ var import_utils66 = require("@goweekdays/utils");
20041
20676
  function usePaymentMethodService() {
20042
20677
  const { createCustomer, linkPaymentMethodEWallet, linkPaymentMethodCard } = useXenditService();
20043
20678
  const { getUserById } = useUserRepo();
@@ -20090,7 +20725,7 @@ function usePaymentMethodService() {
20090
20725
  failure_return_url = "",
20091
20726
  cancel_return_url = ""
20092
20727
  } = {}) {
20093
- const session = import_utils64.useAtlas.getClient()?.startSession();
20728
+ const session = import_utils66.useAtlas.getClient()?.startSession();
20094
20729
  session?.startTransaction();
20095
20730
  try {
20096
20731
  const customerData = {
@@ -20100,10 +20735,10 @@ function usePaymentMethodService() {
20100
20735
  if (user) {
20101
20736
  const _user = await getUserById(user);
20102
20737
  if (!_user) {
20103
- throw new import_utils64.BadRequestError("User not found.");
20738
+ throw new import_utils66.BadRequestError("User not found.");
20104
20739
  }
20105
20740
  if (!_user._id) {
20106
- throw new import_utils64.BadRequestError("Invalid user ID.");
20741
+ throw new import_utils66.BadRequestError("Invalid user ID.");
20107
20742
  }
20108
20743
  customerData.email = _user.email;
20109
20744
  customerData.given_names = _user.firstName;
@@ -20112,7 +20747,7 @@ function usePaymentMethodService() {
20112
20747
  if (org) {
20113
20748
  const _org = await getOrgById(org);
20114
20749
  if (!_org) {
20115
- throw new import_utils64.BadRequestError("Organization not found.");
20750
+ throw new import_utils66.BadRequestError("Organization not found.");
20116
20751
  }
20117
20752
  customerData.email = _org.email;
20118
20753
  customerData.given_names = _org.name;
@@ -20126,20 +20761,6 @@ function usePaymentMethodService() {
20126
20761
  failure_return_url,
20127
20762
  cancel_return_url
20128
20763
  });
20129
- await add(
20130
- {
20131
- user,
20132
- org,
20133
- type,
20134
- status: "active",
20135
- paymentId: paymentMethod.id,
20136
- customerId: customer.id,
20137
- name: paymentMethod.type,
20138
- number: mobile_number
20139
- },
20140
- session
20141
- );
20142
- await session?.commitTransaction();
20143
20764
  return {
20144
20765
  paymentMethod: paymentMethod.id,
20145
20766
  customer: customer.id,
@@ -20164,15 +20785,15 @@ function usePaymentMethodService() {
20164
20785
  cardholder_name = "",
20165
20786
  currency = "PHP"
20166
20787
  } = {}) {
20167
- const session = import_utils64.useAtlas.getClient()?.startSession();
20788
+ const session = import_utils66.useAtlas.getClient()?.startSession();
20168
20789
  session?.startTransaction();
20169
20790
  try {
20170
20791
  const _user = await getUserById(user);
20171
20792
  if (!_user) {
20172
- throw new import_utils64.BadRequestError("User not found.");
20793
+ throw new import_utils66.BadRequestError("User not found.");
20173
20794
  }
20174
20795
  if (!_user._id) {
20175
- throw new import_utils64.BadRequestError("Invalid user ID.");
20796
+ throw new import_utils66.BadRequestError("Invalid user ID.");
20176
20797
  }
20177
20798
  const result = await linkPaymentMethodCard({
20178
20799
  card_number,
@@ -20212,8 +20833,8 @@ function usePaymentMethodService() {
20212
20833
  }
20213
20834
 
20214
20835
  // src/controllers/payment-method.controller.ts
20215
- var import_joi14 = __toESM(require("joi"));
20216
- var import_utils65 = require("@goweekdays/utils");
20836
+ var import_joi18 = __toESM(require("joi"));
20837
+ var import_utils67 = require("@goweekdays/utils");
20217
20838
  function usePaymentMethodController() {
20218
20839
  const { linkEWallet: _linkEWallet, linkCard: _linkCard } = usePaymentMethodService();
20219
20840
  async function linkEWallet(req, res, next) {
@@ -20224,14 +20845,14 @@ function usePaymentMethodController() {
20224
20845
  const success_return_url = req.body.success_return_url ?? "";
20225
20846
  const failure_return_url = req.body.failure_return_url ?? "";
20226
20847
  const cancel_return_url = req.body.cancel_return_url ?? "";
20227
- const validation = import_joi14.default.object({
20228
- user: import_joi14.default.string().hex().optional().allow("", null),
20229
- org: import_joi14.default.string().hex().optional().allow("", null),
20230
- mobile_number: import_joi14.default.string().required(),
20231
- type: import_joi14.default.string().valid("GCASH", "PAYMAYA").required(),
20232
- success_return_url: import_joi14.default.string().uri().required(),
20233
- failure_return_url: import_joi14.default.string().uri().required(),
20234
- cancel_return_url: import_joi14.default.string().uri().required()
20848
+ const validation = import_joi18.default.object({
20849
+ user: import_joi18.default.string().hex().optional().allow("", null),
20850
+ org: import_joi18.default.string().hex().optional().allow("", null),
20851
+ mobile_number: import_joi18.default.string().required(),
20852
+ type: import_joi18.default.string().valid("GCASH", "PAYMAYA").required(),
20853
+ success_return_url: import_joi18.default.string().uri().required(),
20854
+ failure_return_url: import_joi18.default.string().uri().required(),
20855
+ cancel_return_url: import_joi18.default.string().uri().required()
20235
20856
  }).custom((value, helpers) => {
20236
20857
  if (!value.user && !value.org) {
20237
20858
  return helpers.error("any.invalid", {
@@ -20250,7 +20871,7 @@ function usePaymentMethodController() {
20250
20871
  cancel_return_url
20251
20872
  });
20252
20873
  if (error) {
20253
- next(new import_utils65.BadRequestError(error.message));
20874
+ next(new import_utils67.BadRequestError(error.message));
20254
20875
  }
20255
20876
  try {
20256
20877
  const result = await _linkEWallet({
@@ -20279,17 +20900,17 @@ function usePaymentMethodController() {
20279
20900
  const failure_return_url = req.body.failure_return_url ?? "";
20280
20901
  const cardType = req.body.cardType ?? "";
20281
20902
  const user = req.headers["user"] ?? "";
20282
- const validation = import_joi14.default.object({
20283
- cardNumber: import_joi14.default.string().required(),
20284
- expiryMonth: import_joi14.default.string().required(),
20285
- expiryYear: import_joi14.default.string().required(),
20286
- cvv: import_joi14.default.string().required(),
20287
- cardholderName: import_joi14.default.string().required(),
20288
- currency: import_joi14.default.string().optional().allow("", null),
20289
- success_return_url: import_joi14.default.string().uri().required(),
20290
- failure_return_url: import_joi14.default.string().uri().required(),
20291
- cardType: import_joi14.default.string().required(),
20292
- user: import_joi14.default.string().hex().required()
20903
+ const validation = import_joi18.default.object({
20904
+ cardNumber: import_joi18.default.string().required(),
20905
+ expiryMonth: import_joi18.default.string().required(),
20906
+ expiryYear: import_joi18.default.string().required(),
20907
+ cvv: import_joi18.default.string().required(),
20908
+ cardholderName: import_joi18.default.string().required(),
20909
+ currency: import_joi18.default.string().optional().allow("", null),
20910
+ success_return_url: import_joi18.default.string().uri().required(),
20911
+ failure_return_url: import_joi18.default.string().uri().required(),
20912
+ cardType: import_joi18.default.string().required(),
20913
+ user: import_joi18.default.string().hex().required()
20293
20914
  });
20294
20915
  const { error } = validation.validate({
20295
20916
  user,
@@ -20304,7 +20925,7 @@ function usePaymentMethodController() {
20304
20925
  failure_return_url
20305
20926
  });
20306
20927
  if (error) {
20307
- next(new import_utils65.BadRequestError(error.message));
20928
+ next(new import_utils67.BadRequestError(error.message));
20308
20929
  }
20309
20930
  try {
20310
20931
  const result = await _linkCard({
@@ -20328,12 +20949,12 @@ function usePaymentMethodController() {
20328
20949
  const { getByUser: _getByUser, getByOrg: _getByOrg } = usePaymentMethodRepo();
20329
20950
  async function getByUser(req, res, next) {
20330
20951
  const user = req.params.user ?? "";
20331
- const validation = import_joi14.default.object({
20332
- user: import_joi14.default.string().hex().required()
20952
+ const validation = import_joi18.default.object({
20953
+ user: import_joi18.default.string().hex().required()
20333
20954
  });
20334
20955
  const { error } = validation.validate({ user });
20335
20956
  if (error) {
20336
- next(new import_utils65.BadRequestError(error.message));
20957
+ next(new import_utils67.BadRequestError(error.message));
20337
20958
  }
20338
20959
  try {
20339
20960
  const result = await _getByUser(user);
@@ -20344,12 +20965,12 @@ function usePaymentMethodController() {
20344
20965
  }
20345
20966
  async function getByOrg(req, res, next) {
20346
20967
  const org = req.params.org ?? "";
20347
- const validation = import_joi14.default.object({
20348
- org: import_joi14.default.string().hex().required()
20968
+ const validation = import_joi18.default.object({
20969
+ org: import_joi18.default.string().hex().required()
20349
20970
  });
20350
20971
  const { error } = validation.validate({ org });
20351
20972
  if (error) {
20352
- next(new import_utils65.BadRequestError(error.message));
20973
+ next(new import_utils67.BadRequestError(error.message));
20353
20974
  }
20354
20975
  try {
20355
20976
  const result = await _getByOrg(org);
@@ -20367,27 +20988,27 @@ function usePaymentMethodController() {
20367
20988
  }
20368
20989
 
20369
20990
  // src/controllers/address.controller.ts
20370
- var import_utils66 = require("@goweekdays/utils");
20371
- var import_joi15 = __toESM(require("joi"));
20991
+ var import_utils68 = require("@goweekdays/utils");
20992
+ var import_joi19 = __toESM(require("joi"));
20372
20993
  function useAddressController() {
20373
20994
  const { add: _add, getByUserId: _getByUserId } = useAddressRepo();
20374
20995
  async function add(req, res, next) {
20375
20996
  const value = req.body;
20376
- const validation = import_joi15.default.object({
20377
- type: import_joi15.default.string().required(),
20378
- user: import_joi15.default.string().hex().optional().allow("", null),
20379
- org: import_joi15.default.string().hex().optional().allow("", null),
20380
- country: import_joi15.default.string().required(),
20381
- address: import_joi15.default.string().required(),
20382
- continuedAddress: import_joi15.default.string().optional().allow("", null),
20383
- city: import_joi15.default.string().required(),
20384
- province: import_joi15.default.string().required(),
20385
- postalCode: import_joi15.default.string().required(),
20386
- taxId: import_joi15.default.string().optional().allow("", null)
20997
+ const validation = import_joi19.default.object({
20998
+ type: import_joi19.default.string().required(),
20999
+ user: import_joi19.default.string().hex().optional().allow("", null),
21000
+ org: import_joi19.default.string().hex().optional().allow("", null),
21001
+ country: import_joi19.default.string().required(),
21002
+ address: import_joi19.default.string().required(),
21003
+ continuedAddress: import_joi19.default.string().optional().allow("", null),
21004
+ city: import_joi19.default.string().required(),
21005
+ province: import_joi19.default.string().required(),
21006
+ postalCode: import_joi19.default.string().required(),
21007
+ taxId: import_joi19.default.string().optional().allow("", null)
20387
21008
  });
20388
21009
  const { error } = validation.validate(value);
20389
21010
  if (error) {
20390
- next(new import_utils66.BadRequestError(error.message));
21011
+ next(new import_utils68.BadRequestError(error.message));
20391
21012
  }
20392
21013
  try {
20393
21014
  const value2 = req.body;
@@ -20400,15 +21021,15 @@ function useAddressController() {
20400
21021
  }
20401
21022
  async function getByUserId(req, res, next) {
20402
21023
  const user = req.params.user;
20403
- const validation = import_joi15.default.string().hex().required();
21024
+ const validation = import_joi19.default.string().hex().required();
20404
21025
  const { error } = validation.validate(user);
20405
21026
  if (error) {
20406
- next(new import_utils66.BadRequestError(error.message));
21027
+ next(new import_utils68.BadRequestError(error.message));
20407
21028
  }
20408
21029
  try {
20409
21030
  const address = await _getByUserId(user);
20410
21031
  if (!address) {
20411
- next(new import_utils66.NotFoundError("Address not found."));
21032
+ next(new import_utils68.NotFoundError("Address not found."));
20412
21033
  return;
20413
21034
  }
20414
21035
  res.json(address);
@@ -20424,19 +21045,19 @@ function useAddressController() {
20424
21045
  }
20425
21046
 
20426
21047
  // src/services/organization.service.ts
20427
- var import_utils67 = require("@goweekdays/utils");
21048
+ var import_utils69 = require("@goweekdays/utils");
20428
21049
  function useOrgService() {
20429
21050
  const { add: addOrg } = useOrgRepo();
20430
21051
  const { addRole } = useRoleRepo();
20431
21052
  const { add: addMember } = useMemberRepo();
20432
21053
  const { getUserById } = useUserRepo();
20433
21054
  async function createOrg({ user = "", name = "", description = "" } = {}) {
20434
- const session = import_utils67.useAtlas.getClient()?.startSession();
21055
+ const session = import_utils69.useAtlas.getClient()?.startSession();
20435
21056
  session?.startTransaction();
20436
21057
  try {
20437
21058
  const _user = await getUserById(user);
20438
21059
  if (!_user) {
20439
- throw new import_utils67.NotFoundError("User not found.");
21060
+ throw new import_utils69.NotFoundError("User not found.");
20440
21061
  }
20441
21062
  const org = await addOrg(
20442
21063
  {
@@ -20479,25 +21100,25 @@ function useOrgService() {
20479
21100
  }
20480
21101
 
20481
21102
  // src/controllers/organization.controller.ts
20482
- var import_utils68 = require("@goweekdays/utils");
20483
- var import_joi16 = __toESM(require("joi"));
21103
+ var import_utils70 = require("@goweekdays/utils");
21104
+ var import_joi20 = __toESM(require("joi"));
20484
21105
  function useOrgController() {
20485
21106
  const { createOrg: _createOrg } = useOrgService();
20486
21107
  const { getByUserId: _getByUserId } = useMemberRepo();
20487
21108
  const { getByName: _getByName } = useOrgRepo();
20488
21109
  async function createOrg(req, res, next) {
20489
21110
  const value = req.body;
20490
- const validation = import_joi16.default.object({
20491
- name: import_joi16.default.string().required(),
20492
- type: import_joi16.default.string().required(),
20493
- email: import_joi16.default.string().email().required(),
20494
- contact: import_joi16.default.string().required(),
20495
- description: import_joi16.default.string().required(),
20496
- user: import_joi16.default.string().hex().required()
21111
+ const validation = import_joi20.default.object({
21112
+ name: import_joi20.default.string().required(),
21113
+ type: import_joi20.default.string().required(),
21114
+ email: import_joi20.default.string().email().required(),
21115
+ contact: import_joi20.default.string().required(),
21116
+ description: import_joi20.default.string().required(),
21117
+ user: import_joi20.default.string().hex().required()
20497
21118
  });
20498
21119
  const { error } = validation.validate(value);
20499
21120
  if (error) {
20500
- next(new import_utils68.BadRequestError(error.message));
21121
+ next(new import_utils70.BadRequestError(error.message));
20501
21122
  return;
20502
21123
  }
20503
21124
  try {
@@ -20515,23 +21136,23 @@ function useOrgController() {
20515
21136
  const user = req.headers["user"];
20516
21137
  const isPageNumber = isFinite(page);
20517
21138
  if (!isPageNumber) {
20518
- next(new import_utils68.BadRequestError("Invalid page number."));
21139
+ next(new import_utils70.BadRequestError("Invalid page number."));
20519
21140
  return;
20520
21141
  }
20521
21142
  const isLimitNumber = isFinite(limit);
20522
21143
  if (!isLimitNumber) {
20523
- next(new import_utils68.BadRequestError("Invalid limit number."));
21144
+ next(new import_utils70.BadRequestError("Invalid limit number."));
20524
21145
  return;
20525
21146
  }
20526
- const validation = import_joi16.default.object({
20527
- user: import_joi16.default.string().hex().required(),
20528
- page: import_joi16.default.number().min(1).optional().allow("", null),
20529
- limit: import_joi16.default.number().min(1).optional().allow("", null),
20530
- search: import_joi16.default.string().optional().allow("", null)
21147
+ const validation = import_joi20.default.object({
21148
+ user: import_joi20.default.string().hex().required(),
21149
+ page: import_joi20.default.number().min(1).optional().allow("", null),
21150
+ limit: import_joi20.default.number().min(1).optional().allow("", null),
21151
+ search: import_joi20.default.string().optional().allow("", null)
20531
21152
  });
20532
21153
  const { error } = validation.validate({ user, page, limit, search });
20533
21154
  if (error) {
20534
- next(new import_utils68.BadRequestError(error.message));
21155
+ next(new import_utils70.BadRequestError(error.message));
20535
21156
  return;
20536
21157
  }
20537
21158
  try {
@@ -20544,12 +21165,12 @@ function useOrgController() {
20544
21165
  }
20545
21166
  async function getByName(req, res, next) {
20546
21167
  const name = req.params.name;
20547
- const validation = import_joi16.default.object({
20548
- name: import_joi16.default.string().required()
21168
+ const validation = import_joi20.default.object({
21169
+ name: import_joi20.default.string().required()
20549
21170
  });
20550
21171
  const { error } = validation.validate({ name });
20551
21172
  if (error) {
20552
- next(new import_utils68.BadRequestError(error.message));
21173
+ next(new import_utils70.BadRequestError(error.message));
20553
21174
  return;
20554
21175
  }
20555
21176
  try {
@@ -20566,6 +21187,274 @@ function useOrgController() {
20566
21187
  getByName
20567
21188
  };
20568
21189
  }
21190
+
21191
+ // src/validations/promo-code.schema.ts
21192
+ var import_joi21 = __toESM(require("joi"));
21193
+ var promoTypeSchema = import_joi21.default.string().valid("tiered", "fixed").required();
21194
+ var promoTierSchema = import_joi21.default.object({
21195
+ min: import_joi21.default.number().integer().min(1).required(),
21196
+ max: import_joi21.default.number().integer().min(import_joi21.default.ref("min")).allow(0).required(),
21197
+ price: import_joi21.default.number().positive().required()
21198
+ });
21199
+ var schema2 = import_joi21.default.object({
21200
+ code: import_joi21.default.string().trim().uppercase().required(),
21201
+ description: import_joi21.default.string().trim().optional(),
21202
+ type: promoTypeSchema,
21203
+ tiers: import_joi21.default.alternatives().conditional("type", {
21204
+ is: "tiered",
21205
+ then: import_joi21.default.array().items(promoTierSchema).min(1).required(),
21206
+ otherwise: import_joi21.default.forbidden()
21207
+ }),
21208
+ fixed_rate: import_joi21.default.alternatives().conditional("type", {
21209
+ is: "fixed",
21210
+ then: import_joi21.default.number().required().min(0),
21211
+ otherwise: import_joi21.default.number().integer().allow(0)
21212
+ }),
21213
+ expiresAt: import_joi21.default.string().optional().allow(null, "")
21214
+ });
21215
+
21216
+ // src/models/promo-code.model.ts
21217
+ var import_utils71 = require("@goweekdays/utils");
21218
+ function MPromoCode(data) {
21219
+ const { error } = schema2.validate(data);
21220
+ if (error) {
21221
+ throw new import_utils71.BadRequestError(error.message);
21222
+ }
21223
+ return {
21224
+ _id: data._id,
21225
+ code: data.code,
21226
+ description: data.description ?? "",
21227
+ type: data.type,
21228
+ tiers: data.tiers ?? [],
21229
+ fixed_rate: data.fixed_rate ?? 0,
21230
+ appliesTo: data.appliesTo ?? "",
21231
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
21232
+ expiresAt: data.expiresAt ?? "",
21233
+ assignedTo: data.assignedTo,
21234
+ status: data.status ?? "active"
21235
+ };
21236
+ }
21237
+
21238
+ // src/repositories/promo-code.repository.ts
21239
+ var import_utils72 = require("@goweekdays/utils");
21240
+ var import_joi22 = __toESM(require("joi"));
21241
+ function usePromoCodeRepo() {
21242
+ const db = import_utils72.useAtlas.getDb();
21243
+ if (!db) {
21244
+ throw new import_utils72.InternalServerError("Unable to connect to server.");
21245
+ }
21246
+ const collection = db.collection("promo-codes");
21247
+ async function createIndex() {
21248
+ try {
21249
+ await collection.createIndexes([
21250
+ { key: { code: 1 } },
21251
+ { key: { type: 1 } }
21252
+ ]);
21253
+ } catch (error) {
21254
+ throw new Error("Failed to create index for promo code.");
21255
+ }
21256
+ }
21257
+ async function createUniqueIndex() {
21258
+ try {
21259
+ await collection.createIndexes([
21260
+ { key: { code: 1, type: 1 }, unique: true }
21261
+ ]);
21262
+ } catch (error) {
21263
+ throw new Error("Failed to create unique index for promo code.");
21264
+ }
21265
+ }
21266
+ async function add(value) {
21267
+ try {
21268
+ value = MPromoCode(value);
21269
+ await collection.insertOne(value);
21270
+ } catch (error) {
21271
+ import_utils72.logger.log({ level: "error", message: `${error}` });
21272
+ const isDuplicated = error.message.includes("duplicate");
21273
+ if (isDuplicated) {
21274
+ throw new import_utils72.BadRequestError("Promo code already exists.");
21275
+ }
21276
+ throw new import_utils72.InternalServerError("Internal server error.");
21277
+ }
21278
+ }
21279
+ async function getByCode(code) {
21280
+ const schema3 = import_joi22.default.object({
21281
+ code: import_joi22.default.string().trim().required()
21282
+ });
21283
+ const { error } = schema3.validate({ code });
21284
+ if (error) {
21285
+ throw new import_utils72.BadRequestError(error.message);
21286
+ }
21287
+ try {
21288
+ return await collection.findOne({ code });
21289
+ } catch (error2) {
21290
+ throw new import_utils72.InternalServerError("Internal server error.");
21291
+ }
21292
+ }
21293
+ async function getPromoCodes({
21294
+ search = "",
21295
+ page = 1,
21296
+ limit = 10,
21297
+ sort = {},
21298
+ status = "active",
21299
+ type = ""
21300
+ } = {}) {
21301
+ page = page > 0 ? page - 1 : 0;
21302
+ const query = { status };
21303
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
21304
+ if (search) {
21305
+ query.$text = { $search: search };
21306
+ }
21307
+ if (type) {
21308
+ query.type = type;
21309
+ }
21310
+ try {
21311
+ const items = await collection.aggregate([
21312
+ { $match: query },
21313
+ { $sort: sort },
21314
+ { $skip: page * limit },
21315
+ { $limit: limit }
21316
+ ]).toArray();
21317
+ const length = await collection.countDocuments(query);
21318
+ return (0, import_utils72.paginate)(items, page, limit, length);
21319
+ } catch (error) {
21320
+ import_utils72.logger.log({ level: "error", message: `${error}` });
21321
+ throw new import_utils72.InternalServerError("Internal server error.");
21322
+ }
21323
+ }
21324
+ return {
21325
+ createIndex,
21326
+ createUniqueIndex,
21327
+ add,
21328
+ getByCode,
21329
+ getPromoCodes
21330
+ };
21331
+ }
21332
+
21333
+ // src/controllers/promo-code.controller.ts
21334
+ var import_utils73 = require("@goweekdays/utils");
21335
+ var import_joi23 = __toESM(require("joi"));
21336
+ function usePromoCodeController() {
21337
+ const {
21338
+ add: _add,
21339
+ getByCode: _getByCode,
21340
+ getPromoCodes: _getPromoCodes
21341
+ } = usePromoCodeRepo();
21342
+ async function add(req, res, next) {
21343
+ const data = req.body;
21344
+ const { error } = schema2.validate(data);
21345
+ if (error) {
21346
+ next(new import_utils73.BadRequestError(error.message));
21347
+ return;
21348
+ }
21349
+ try {
21350
+ await _add(data);
21351
+ res.json({ message: "Successfully added promo code." });
21352
+ return;
21353
+ } catch (error2) {
21354
+ if (error2 instanceof import_utils73.AppError) {
21355
+ next(error2);
21356
+ } else {
21357
+ next(new import_utils73.InternalServerError(error2));
21358
+ }
21359
+ }
21360
+ }
21361
+ async function getByCode(req, res, next) {
21362
+ const code = req.params.code;
21363
+ const validation = import_joi23.default.string().required();
21364
+ const { error } = validation.validate(code);
21365
+ if (error) {
21366
+ next(new import_utils73.BadRequestError(error.message));
21367
+ return;
21368
+ }
21369
+ try {
21370
+ const promoCode = await _getByCode(code);
21371
+ res.json({ promoCode });
21372
+ return;
21373
+ } catch (error2) {
21374
+ if (error2 instanceof import_utils73.AppError) {
21375
+ next(error2);
21376
+ } else {
21377
+ next(new import_utils73.InternalServerError(error2));
21378
+ }
21379
+ }
21380
+ }
21381
+ async function getPromoCodes(req, res, next) {
21382
+ const page = req.query.page ? Number(req.query.page) : 1;
21383
+ const limit = req.query.limit ? Number(req.query.limit) : 10;
21384
+ const search = req.query.search;
21385
+ const status = req.query.status;
21386
+ const validation = import_joi23.default.object({
21387
+ page: import_joi23.default.number().required(),
21388
+ limit: import_joi23.default.number().integer().optional().min(10).max(100),
21389
+ search: import_joi23.default.string().optional().allow(""),
21390
+ status: import_joi23.default.string().required()
21391
+ });
21392
+ const { error } = validation.validate({ page, limit, search, status });
21393
+ if (error) {
21394
+ next(new import_utils73.BadRequestError(error.message));
21395
+ return;
21396
+ }
21397
+ try {
21398
+ const promoCodes = await _getPromoCodes({
21399
+ page,
21400
+ limit,
21401
+ search,
21402
+ status
21403
+ });
21404
+ res.json(promoCodes);
21405
+ return;
21406
+ } catch (error2) {
21407
+ next(error2);
21408
+ }
21409
+ }
21410
+ return {
21411
+ add,
21412
+ getByCode,
21413
+ getPromoCodes
21414
+ };
21415
+ }
21416
+
21417
+ // src/controllers/order.controller.ts
21418
+ var import_utils74 = require("@goweekdays/utils");
21419
+ var import_joi24 = __toESM(require("joi"));
21420
+ function useOrderController() {
21421
+ const { getOrders: _getOrders } = useOrderRepo();
21422
+ async function getOrders(req, res, next) {
21423
+ const page = req.query.page ?? 1;
21424
+ const limit = req.query.limit ?? 10;
21425
+ const search = req.query.search ?? "";
21426
+ const status = req.query.status ?? "succeeded";
21427
+ const id = req.query.id ?? "";
21428
+ const validation = import_joi24.default.object({
21429
+ page: import_joi24.default.number().required(),
21430
+ limit: import_joi24.default.number().required().min(10),
21431
+ search: import_joi24.default.string().optional().allow("", null),
21432
+ status: import_joi24.default.string().optional().allow("", null),
21433
+ id: import_joi24.default.string().hex().optional().allow("", null)
21434
+ });
21435
+ const { error } = validation.validate({ page, limit, search, status, id });
21436
+ if (error) {
21437
+ next(new import_utils74.BadRequestError(error.message));
21438
+ return;
21439
+ }
21440
+ try {
21441
+ const orders = await _getOrders({
21442
+ page: parseInt(page),
21443
+ limit: parseInt(limit),
21444
+ search,
21445
+ status,
21446
+ id
21447
+ });
21448
+ res.json(orders);
21449
+ return;
21450
+ } catch (error2) {
21451
+ next(error2);
21452
+ }
21453
+ }
21454
+ return {
21455
+ getOrders
21456
+ };
21457
+ }
20569
21458
  // Annotate the CommonJS export names for ESM import in node:
20570
21459
  0 && (module.exports = {
20571
21460
  ACCESS_TOKEN_EXPIRY,
@@ -20589,8 +21478,10 @@ function useOrgController() {
20589
21478
  MMember,
20590
21479
  MONGO_DB,
20591
21480
  MONGO_URI,
21481
+ MOrder,
20592
21482
  MOrg,
20593
21483
  MPaymentMethod,
21484
+ MPromoCode,
20594
21485
  MRole,
20595
21486
  MSubscription,
20596
21487
  MToken,
@@ -20618,6 +21509,7 @@ function useOrgController() {
20618
21509
  XENDIT_BASE_URL,
20619
21510
  XENDIT_SECRET_KEY,
20620
21511
  isDev,
21512
+ schema,
20621
21513
  useAddressController,
20622
21514
  useAddressRepo,
20623
21515
  useAuthController,
@@ -20635,12 +21527,16 @@ function useOrgController() {
20635
21527
  useFileRepo,
20636
21528
  useFileService,
20637
21529
  useMemberRepo,
21530
+ useOrderController,
21531
+ useOrderRepo,
20638
21532
  useOrgController,
20639
21533
  useOrgRepo,
20640
21534
  useOrgService,
20641
21535
  usePaymentMethodController,
20642
21536
  usePaymentMethodRepo,
20643
21537
  usePaymentMethodService,
21538
+ usePromoCodeController,
21539
+ usePromoCodeRepo,
20644
21540
  useRoleController,
20645
21541
  useRoleRepo,
20646
21542
  useRoleService,