@goweekdays/core 2.9.0 → 2.10.0

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
@@ -156,6 +156,7 @@ __export(src_exports, {
156
156
  usePlanController: () => usePlanController,
157
157
  usePlanRepo: () => usePlanRepo,
158
158
  usePlanService: () => usePlanService,
159
+ usePromoController: () => usePromoController,
159
160
  usePromoRepo: () => usePromoRepo,
160
161
  useRoleController: () => useRoleController,
161
162
  useRoleRepo: () => useRoleRepo,
@@ -1266,6 +1267,7 @@ function useMemberRepo() {
1266
1267
  await collection.createIndexes([
1267
1268
  { key: { name: 1 } },
1268
1269
  { key: { status: 1 } },
1270
+ { key: { org: 1 } },
1269
1271
  { key: { name: "text", orgName: "text" }, name: "text_index" },
1270
1272
  {
1271
1273
  key: {
@@ -1971,6 +1973,38 @@ function useMemberRepo() {
1971
1973
  );
1972
1974
  }
1973
1975
  }
1976
+ async function updateStatusByOrg(org, status, session) {
1977
+ const { error } = import_joi4.default.object({
1978
+ org: import_joi4.default.string().hex().length(24).required(),
1979
+ status: import_joi4.default.string().valid("active", "suspended").required()
1980
+ }).validate({ org, status });
1981
+ if (error) {
1982
+ throw new import_utils7.BadRequestError(error.message);
1983
+ }
1984
+ try {
1985
+ org = new import_mongodb7.ObjectId(org);
1986
+ } catch (error2) {
1987
+ throw new import_utils7.BadRequestError("Invalid organization ID.");
1988
+ }
1989
+ try {
1990
+ await collection.updateMany(
1991
+ { org, status: { $ne: "deleted" }, app: { $ne: "org" } },
1992
+ {
1993
+ $set: {
1994
+ status,
1995
+ updatedAt: /* @__PURE__ */ new Date()
1996
+ }
1997
+ },
1998
+ { session }
1999
+ );
2000
+ delCachedData();
2001
+ return "Successfully updated member statuses by organization.";
2002
+ } catch (error2) {
2003
+ throw new import_utils7.InternalServerError(
2004
+ "Internal server error, failed to update member statuses."
2005
+ );
2006
+ }
2007
+ }
1974
2008
  return {
1975
2009
  createIndexes,
1976
2010
  add,
@@ -1988,7 +2022,8 @@ function useMemberRepo() {
1988
2022
  getByApp,
1989
2023
  updateRoleById,
1990
2024
  updateStatusById,
1991
- deleteById
2025
+ deleteById,
2026
+ updateStatusByOrg
1992
2027
  };
1993
2028
  }
1994
2029
 
@@ -3578,8 +3613,13 @@ function useAppService() {
3578
3613
  },
3579
3614
  {
3580
3615
  code: "job",
3581
- name: "jobs",
3616
+ name: "Jobs",
3582
3617
  description: "Job listings and recruitment services."
3618
+ },
3619
+ {
3620
+ code: "circle",
3621
+ name: "Circle",
3622
+ description: "Community-based rotational system"
3583
3623
  }
3584
3624
  ];
3585
3625
  const session = import_utils17.useAtlas.getClient()?.startSession();
@@ -4397,7 +4437,8 @@ var schema = {
4397
4437
  name: import_joi15.default.string().max(255).required(),
4398
4438
  description: import_joi15.default.string().max(1024).optional().allow("", null),
4399
4439
  email: import_joi15.default.string().email().max(255).required(),
4400
- contact: import_joi15.default.string().max(50).optional().allow("", null)
4440
+ contact: import_joi15.default.string().max(50).optional().allow("", null),
4441
+ promoCode: import_joi15.default.string().max(50).optional().allow("", null)
4401
4442
  };
4402
4443
  var schemaOrg = import_joi15.default.object({
4403
4444
  ...schema,
@@ -4431,6 +4472,7 @@ function modelOrg(value) {
4431
4472
  email: value.email,
4432
4473
  contact: value.contact,
4433
4474
  createdBy: value.createdBy,
4475
+ promoCode: value.promoCode ?? "",
4434
4476
  status: value.status ?? "active",
4435
4477
  createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
4436
4478
  updatedAt: "",
@@ -5463,7 +5505,7 @@ function useSubscriptionRepo() {
5463
5505
  search = "",
5464
5506
  status = "active"
5465
5507
  } = {}) {
5466
- page = page < 1 ? page - 1 : page;
5508
+ page = page > 0 ? page - 1 : page;
5467
5509
  const query = { status };
5468
5510
  const cacheKeyOptions = {
5469
5511
  page,
@@ -7549,6 +7591,7 @@ function useSubscriptionService() {
7549
7591
  }
7550
7592
  }
7551
7593
  const { getOverdueForSuspension } = useSubscriptionRepo();
7594
+ const { updateStatusByOrg } = useMemberRepo();
7552
7595
  async function processSuspensions() {
7553
7596
  const DAYS_OVERDUE = 7;
7554
7597
  while (true) {
@@ -7570,8 +7613,10 @@ function useSubscriptionService() {
7570
7613
  session.startTransaction();
7571
7614
  await updateStatusById(subId, "suspended", session);
7572
7615
  await updateRetryById(subId, 0, session);
7573
- if (subscription.org) {
7574
- await updateOrgStatusById(subscription.org, "suspended", session);
7616
+ const orgId = String(subscription.org);
7617
+ if (orgId) {
7618
+ await updateOrgStatusById(orgId, "suspended", session);
7619
+ await updateStatusByOrg(orgId, "suspended", session);
7575
7620
  }
7576
7621
  await session.commitTransaction();
7577
7622
  import_utils39.logger.log({
@@ -7635,6 +7680,7 @@ function useSubscriptionService() {
7635
7680
  session
7636
7681
  );
7637
7682
  await updateOrgStatusById(orgId, "active", session);
7683
+ await updateStatusByOrg(orgId, "active", session);
7638
7684
  await updateLedgerStatusById(String(ledgerBill._id), "paid", session);
7639
7685
  await session.commitTransaction();
7640
7686
  return "Successfully processed paid invoice.";
@@ -7714,7 +7760,8 @@ function useSubscriptionController() {
7714
7760
  const validation = import_joi33.default.object({
7715
7761
  page: import_joi33.default.number().min(1).max(100).optional().allow(null, "").default(1),
7716
7762
  limit: import_joi33.default.number().min(1).max(100).optional().allow(null, "").default(10),
7717
- status: import_joi33.default.string().valid("active", "suspended").optional().default("active")
7763
+ status: import_joi33.default.string().valid("active", "suspended").optional().default("active"),
7764
+ search: import_joi33.default.string().optional().allow("", null)
7718
7765
  });
7719
7766
  const query = req.query;
7720
7767
  const { error, value } = validation.validate(query);
@@ -8205,6 +8252,14 @@ function useOrgService() {
8205
8252
  }
8206
8253
  const { getById, updateStatusById: updateVerificationStatus } = useVerificationRepo();
8207
8254
  const { add: addLedgerBilling } = useLedgerBillingRepo();
8255
+ const MailerConfig = {
8256
+ host: MAILER_TRANSPORT_HOST,
8257
+ port: MAILER_TRANSPORT_PORT,
8258
+ secure: MAILER_TRANSPORT_SECURE,
8259
+ email: MAILER_EMAIL,
8260
+ password: MAILER_PASSWORD
8261
+ };
8262
+ const mailer = new import_utils44.useMailer(MailerConfig);
8208
8263
  async function addWithVerification(id) {
8209
8264
  const { error } = import_joi36.default.string().hex().required().validate(id);
8210
8265
  if (error) {
@@ -8316,6 +8371,28 @@ function useOrgService() {
8316
8371
  },
8317
8372
  session
8318
8373
  );
8374
+ const filePath = (0, import_utils44.getDirectory)(
8375
+ __dirname,
8376
+ "./public/handlebars/org-created"
8377
+ );
8378
+ const emailContent = (0, import_utils44.compileHandlebar)({
8379
+ context: {
8380
+ app: APP_ORG,
8381
+ organization_name: verification.metadata.orgName
8382
+ },
8383
+ filePath
8384
+ });
8385
+ mailer.sendMail({
8386
+ to: verification.email,
8387
+ subject: "Welcome to GoWeekdays - Your Organization is Ready",
8388
+ html: emailContent,
8389
+ from: "GoWeekdays"
8390
+ }).catch((error2) => {
8391
+ import_utils44.logger.log({
8392
+ level: "error",
8393
+ message: `Error sending user invite email: ${error2}`
8394
+ });
8395
+ });
8319
8396
  await session?.commitTransaction();
8320
8397
  return "Successfully created organization with verification.";
8321
8398
  } catch (error2) {
@@ -11110,8 +11187,7 @@ function useFileController() {
11110
11187
  var import_joi45 = __toESM(require("joi"));
11111
11188
  var schemaPromo = import_joi45.default.object({
11112
11189
  code: import_joi45.default.string().min(3).max(50).required(),
11113
- description: import_joi45.default.string().max(255).optional().allow("", null),
11114
- type: import_joi45.default.string().valid("flat", "fixed", "tiered").required(),
11190
+ type: import_joi45.default.string().valid("flat", "fixed", "volume").required(),
11115
11191
  flatRate: import_joi45.default.number().positive().when("type", {
11116
11192
  is: "flat",
11117
11193
  then: import_joi45.default.required(),
@@ -11133,9 +11209,12 @@ var schemaPromo = import_joi45.default.object({
11133
11209
  then: import_joi45.default.required(),
11134
11210
  otherwise: import_joi45.default.forbidden()
11135
11211
  }),
11136
- currency: import_joi45.default.string().length(3).required(),
11137
- startDate: import_joi45.default.date().required(),
11138
- endDate: import_joi45.default.date().greater(import_joi45.default.ref("startDate")).optional().allow(null, "")
11212
+ currency: import_joi45.default.string().length(3).allow("PHP").required(),
11213
+ startDate: import_joi45.default.date().optional().allow(null, ""),
11214
+ endDate: import_joi45.default.date().greater(import_joi45.default.ref("startDate")).optional().allow(null, ""),
11215
+ apps: import_joi45.default.array().items(import_joi45.default.string()).optional().allow(null),
11216
+ seats: import_joi45.default.number().integer().min(0).optional().allow(null, 0),
11217
+ usage: import_joi45.default.number().integer().min(0).optional().allow(null, 0)
11139
11218
  });
11140
11219
  function modelPromo(data) {
11141
11220
  const { error } = schemaPromo.validate(data);
@@ -11145,17 +11224,17 @@ function modelPromo(data) {
11145
11224
  return {
11146
11225
  _id: data._id,
11147
11226
  code: data.code,
11148
- description: data.description ?? "",
11149
11227
  type: data.type,
11150
11228
  flatRate: data.flatRate ?? 0,
11151
11229
  fixedRate: data.fixedRate ?? 0,
11152
11230
  tiers: data.tiers ?? [],
11153
11231
  currency: data.currency,
11154
- startDate: data.startDate ?? /* @__PURE__ */ new Date(),
11232
+ startDate: data.startDate ?? "",
11155
11233
  endDate: data.endDate ?? "",
11156
- assignedTo: data.assignedTo ?? "",
11234
+ seats: data.seats ?? 0,
11235
+ usage: data.usage ?? 0,
11236
+ apps: data.apps ?? [],
11157
11237
  status: data.status ?? "active",
11158
- assignedAt: data.assignedAt ?? "",
11159
11238
  createdAt: data.createdAt ?? /* @__PURE__ */ new Date(),
11160
11239
  updatedAt: data.updatedAt ?? "",
11161
11240
  deletedAt: data.deletedAt ?? ""
@@ -11171,7 +11250,7 @@ function usePromoRepo() {
11171
11250
  if (!db) {
11172
11251
  throw new import_utils61.InternalServerError("Unable to connect to server.");
11173
11252
  }
11174
- const namespace_collection = "users";
11253
+ const namespace_collection = "promos";
11175
11254
  const collection = db.collection(namespace_collection);
11176
11255
  const { getCache, setCache, delNamespace } = (0, import_utils61.useCache)(namespace_collection);
11177
11256
  function delCachedData() {
@@ -11222,7 +11301,7 @@ function usePromoRepo() {
11222
11301
  search = "",
11223
11302
  status = "active"
11224
11303
  } = {}) {
11225
- page = page < 1 ? page - 1 : page;
11304
+ page = page > 0 ? page - 1 : page;
11226
11305
  const query = { status };
11227
11306
  const cacheKeyOptions = {
11228
11307
  page,
@@ -11336,6 +11415,31 @@ function usePromoRepo() {
11336
11415
  throw new import_utils61.InternalServerError("Failed to get promo.");
11337
11416
  }
11338
11417
  }
11418
+ async function updateById(_id, options) {
11419
+ const { error: errorId } = import_joi46.default.string().hex().length(24).required().validate(_id);
11420
+ if (errorId) {
11421
+ throw new Error(`Invalid promo ID: ${errorId.message}`);
11422
+ }
11423
+ const { error } = schemaPromo.validate(options);
11424
+ if (error) {
11425
+ throw new Error(`Invalid promo ID: ${error.message}`);
11426
+ }
11427
+ try {
11428
+ _id = new import_mongodb26.ObjectId(_id);
11429
+ } catch (error2) {
11430
+ throw new import_utils61.BadRequestError("Invalid promo ID.");
11431
+ }
11432
+ try {
11433
+ await collection.updateOne(
11434
+ { _id },
11435
+ { $set: { ...options, updatedAt: /* @__PURE__ */ new Date() } }
11436
+ );
11437
+ delCachedData();
11438
+ return "Successfully updated promo.";
11439
+ } catch (error2) {
11440
+ throw new import_utils61.InternalServerError("Failed to update promo.");
11441
+ }
11442
+ }
11339
11443
  async function deleteById(_id) {
11340
11444
  const { error } = import_joi46.default.string().hex().length(24).required().validate(_id);
11341
11445
  if (error) {
@@ -11369,80 +11473,75 @@ function usePromoRepo() {
11369
11473
  getAll,
11370
11474
  getByCode,
11371
11475
  getById,
11476
+ updateById,
11372
11477
  deleteById
11373
11478
  };
11374
11479
  }
11375
11480
 
11376
- // src/resources/job-post/job.post.model.ts
11481
+ // src/resources/promo/promo.controller.ts
11482
+ var import_joi49 = __toESM(require("joi"));
11483
+ var import_utils65 = require("@goweekdays/utils");
11484
+
11485
+ // src/resources/promo/promo.service.ts
11486
+ var import_utils64 = require("@goweekdays/utils");
11487
+
11488
+ // src/resources/promo/promo.usage.repository.ts
11489
+ var import_utils63 = require("@goweekdays/utils");
11490
+
11491
+ // src/resources/promo/promo.usage.model.ts
11377
11492
  var import_utils62 = require("@goweekdays/utils");
11378
11493
  var import_joi47 = __toESM(require("joi"));
11379
11494
  var import_mongodb27 = require("mongodb");
11380
- var schemaJobPost = import_joi47.default.object({
11381
- _id: import_joi47.default.string().hex().optional(),
11382
- org: import_joi47.default.string().hex().required(),
11383
- title: import_joi47.default.string().trim().required(),
11384
- setup: import_joi47.default.string().trim().required(),
11385
- location: import_joi47.default.string().trim().required(),
11386
- type: import_joi47.default.string().trim().required(),
11387
- description: import_joi47.default.string().trim().required(),
11388
- status: import_joi47.default.string().trim().optional().allow("", null),
11389
- createdAt: import_joi47.default.date().optional(),
11390
- updatedAt: import_joi47.default.date().optional(),
11391
- deletedAt: import_joi47.default.date().optional()
11495
+ var schemaPromoUsage = import_joi47.default.object({
11496
+ promo: import_joi47.default.string().hex().length(24).required(),
11497
+ org: import_joi47.default.string().hex().length(24).required(),
11498
+ usedBy: import_joi47.default.string().email().required()
11392
11499
  });
11393
- var schemaJobPostUpdate = import_joi47.default.object({
11394
- _id: import_joi47.default.string().hex().required(),
11395
- title: import_joi47.default.string().trim().required(),
11396
- setup: import_joi47.default.string().trim().required(),
11397
- location: import_joi47.default.string().trim().required(),
11398
- type: import_joi47.default.string().trim().required(),
11399
- description: import_joi47.default.string().trim().required()
11400
- });
11401
- function modelJobPost(value) {
11402
- const { error } = schemaJobPost.validate(value);
11500
+ function modelPromoUsage(value) {
11501
+ const { error } = schemaPromoUsage.validate(value);
11403
11502
  if (error) {
11404
- throw new import_utils62.BadRequestError(`Invalid job post: ${error.message}`);
11503
+ throw new Error(`Invalid Promo Usage model: ${error.message}`);
11405
11504
  }
11406
- if (!value._id) {
11505
+ if (value._id && typeof value._id === "string") {
11407
11506
  try {
11408
- value._id = new import_mongodb27.ObjectId();
11507
+ value._id = new import_mongodb27.ObjectId(value._id);
11409
11508
  } catch (error2) {
11410
- throw new import_utils62.BadRequestError("Invalid job post ID.");
11509
+ throw new import_utils62.BadRequestError("Invalid Promo Usage _id");
11411
11510
  }
11412
11511
  }
11413
- try {
11414
- value.org = new import_mongodb27.ObjectId(value.org);
11415
- } catch (error2) {
11416
- throw new import_utils62.BadRequestError("Invalid Org ID");
11512
+ if (typeof value.promo === "string") {
11513
+ try {
11514
+ value.promo = new import_mongodb27.ObjectId(value.promo);
11515
+ } catch (error2) {
11516
+ throw new import_utils62.BadRequestError("Invalid Promo Usage promo");
11517
+ }
11518
+ }
11519
+ if (typeof value.org === "string") {
11520
+ try {
11521
+ value.org = new import_mongodb27.ObjectId(value.org);
11522
+ } catch (error2) {
11523
+ throw new import_utils62.BadRequestError("Invalid Promo Usage org");
11524
+ }
11417
11525
  }
11418
11526
  return {
11419
11527
  _id: value._id,
11528
+ promo: value.promo,
11420
11529
  org: value.org,
11421
- title: value.title,
11422
- setup: value.setup,
11423
- location: value.location,
11424
- type: value.type,
11425
- description: value.description,
11426
- status: value.status ?? "draft",
11427
- createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
11428
- updatedAt: value.updatedAt,
11429
- deletedAt: value.deletedAt
11530
+ usedBy: value.usedBy,
11531
+ createdAt: value.createdAt ? new Date(value.createdAt) : /* @__PURE__ */ new Date(),
11532
+ updatedAt: value.updatedAt ?? ""
11430
11533
  };
11431
11534
  }
11432
11535
 
11433
- // src/resources/job-post/job.post.controller.ts
11434
- var import_joi49 = __toESM(require("joi"));
11435
- var import_utils65 = require("@goweekdays/utils");
11436
-
11437
- // src/resources/job-post/job.post.repository.ts
11438
- var import_utils63 = require("@goweekdays/utils");
11536
+ // src/resources/promo/promo.usage.repository.ts
11537
+ var import_joi48 = __toESM(require("joi"));
11439
11538
  var import_mongodb28 = require("mongodb");
11440
- function useJobPostRepo() {
11539
+ function usePromoUsageRepo() {
11441
11540
  const db = import_utils63.useAtlas.getDb();
11442
11541
  if (!db) {
11443
- throw new import_utils63.BadRequestError("Unable to connect to server.");
11542
+ throw new import_utils63.InternalServerError("Unable to connect to server.");
11444
11543
  }
11445
- const namespace_collection = "job.posts";
11544
+ const namespace_collection = "promo.usages";
11446
11545
  const collection = db.collection(namespace_collection);
11447
11546
  const { getCache, setCache, delNamespace } = (0, import_utils63.useCache)(namespace_collection);
11448
11547
  function delCachedData() {
@@ -11461,185 +11560,686 @@ function useJobPostRepo() {
11461
11560
  async function createIndexes() {
11462
11561
  try {
11463
11562
  await collection.createIndexes([
11464
- { key: { title: 1 } },
11465
- { key: { setup: 1 } },
11466
- { key: { location: 1 } },
11467
- { key: { type: 1 } },
11468
11563
  {
11469
- key: {
11470
- title: "text",
11471
- setup: "text",
11472
- location: "text",
11473
- type: "text"
11474
- },
11475
- name: "jobpost_text_search"
11564
+ key: { promo: 1, org: 1 },
11565
+ name: "promo_org_index"
11566
+ },
11567
+ {
11568
+ key: { usedBy: 1 },
11569
+ name: "usedBy_index"
11476
11570
  }
11477
11571
  ]);
11478
- return "Successfully created job post indexes.";
11479
11572
  } catch (error) {
11480
- throw new import_utils63.BadRequestError("Failed to create job post indexes.");
11481
11573
  }
11482
11574
  }
11483
- async function add(value, session) {
11575
+ async function add(value) {
11484
11576
  try {
11485
- value = modelJobPost(value);
11486
- const res = await collection.insertOne(value, { session });
11577
+ value = modelPromoUsage(value);
11578
+ await collection.insertOne(value);
11487
11579
  delCachedData();
11488
- return res.insertedId;
11580
+ return "Successfully added promo usage.";
11489
11581
  } catch (error) {
11490
- import_utils63.logger.log({
11491
- level: "error",
11492
- message: error.message
11493
- });
11494
- throw new import_utils63.BadRequestError(`Failed to create job post: ${error.message}`);
11582
+ throw new import_utils63.InternalServerError("Failed to add promo usage.");
11495
11583
  }
11496
11584
  }
11497
11585
  async function getAll({
11498
- search = "",
11499
11586
  page = 1,
11500
11587
  limit = 10,
11501
- status = "active"
11588
+ promo,
11589
+ org
11502
11590
  } = {}) {
11503
- page = page > 0 ? page - 1 : 0;
11504
- const query = { status };
11505
- if (search) {
11506
- query.$text = { $search: search };
11507
- }
11508
- const cacheKey = (0, import_utils63.makeCacheKey)(namespace_collection, {
11509
- search,
11591
+ page = page > 0 ? page - 1 : page;
11592
+ const query = {};
11593
+ const cacheKeyOptions = {
11510
11594
  page,
11511
11595
  limit,
11512
- status
11513
- });
11514
- import_utils63.logger.log({
11515
- level: "info",
11516
- message: `Cache key for getAll job posts: ${cacheKey}`
11517
- });
11596
+ promo,
11597
+ org,
11598
+ tag: "getAll"
11599
+ };
11600
+ if (promo) {
11601
+ try {
11602
+ query.promo = new import_mongodb28.ObjectId(promo);
11603
+ } catch (error) {
11604
+ throw new import_utils63.BadRequestError("Invalid promo ID.");
11605
+ }
11606
+ }
11607
+ if (org) {
11608
+ try {
11609
+ query.org = new import_mongodb28.ObjectId(org);
11610
+ } catch (error) {
11611
+ throw new import_utils63.BadRequestError("Invalid org ID.");
11612
+ }
11613
+ }
11614
+ const cacheKey = (0, import_utils63.makeCacheKey)(namespace_collection, cacheKeyOptions);
11518
11615
  try {
11519
- const cached = await getCache(cacheKey);
11520
- if (cached) {
11521
- import_utils63.logger.log({
11522
- level: "info",
11523
- message: `Cache hit for getAll job posts: ${cacheKey}`
11524
- });
11525
- return cached;
11616
+ const cachedData = await getCache(cacheKey);
11617
+ if (cachedData) {
11618
+ return cachedData;
11526
11619
  }
11527
11620
  const items = await collection.aggregate([
11528
11621
  { $match: query },
11529
11622
  { $skip: page * limit },
11530
- { $limit: limit },
11531
- {
11532
- $project: {
11533
- _id: 1,
11534
- title: 1,
11535
- setup: 1,
11536
- location: 1,
11537
- type: 1,
11538
- createdAt: 1
11539
- }
11540
- }
11623
+ { $limit: limit }
11541
11624
  ]).toArray();
11542
11625
  const length = await collection.countDocuments(query);
11543
11626
  const data = (0, import_utils63.paginate)(items, page, limit, length);
11544
- setCache(cacheKey, data, 600).then(() => {
11627
+ setCache(cacheKey, data).then(() => {
11545
11628
  import_utils63.logger.log({
11546
11629
  level: "info",
11547
- message: `Cache set for getAll job posts: ${cacheKey}`
11630
+ message: `Cache set for getAll promo usage: ${cacheKey}`
11548
11631
  });
11549
11632
  }).catch((err) => {
11550
11633
  import_utils63.logger.log({
11551
11634
  level: "error",
11552
- message: `Failed to set cache for getAll job posts: ${err.message}`
11635
+ message: `Failed to set cache for getAll promo usage: ${err.message}`
11553
11636
  });
11554
11637
  });
11555
11638
  return data;
11556
11639
  } catch (error) {
11557
- import_utils63.logger.log({ level: "error", message: `${error}` });
11558
- throw error;
11640
+ throw new import_utils63.InternalServerError("Failed to get promo usages.");
11559
11641
  }
11560
11642
  }
11561
- async function getJobPostsByOrg({
11562
- search = "",
11563
- page = 1,
11564
- limit = 10,
11565
- org = "",
11566
- status = "active"
11567
- } = {}) {
11568
- page = page > 0 ? page - 1 : 0;
11569
- try {
11570
- org = new import_mongodb28.ObjectId(org);
11571
- } catch (error) {
11572
- throw new import_utils63.BadRequestError("Invalid organization ID.");
11643
+ async function getByPromo(promo) {
11644
+ const { error } = import_joi48.default.string().hex().length(24).required().validate(promo);
11645
+ if (error) {
11646
+ throw new Error(`Invalid promo ID: ${error.message}`);
11573
11647
  }
11574
- const query = { org, status };
11575
- const cacheKeyOptions = {
11576
- org: String(org),
11577
- status,
11578
- limit,
11579
- page
11580
- };
11581
- if (search) {
11582
- cacheKeyOptions.search = search;
11583
- query.$text = { $search: search };
11648
+ try {
11649
+ promo = new import_mongodb28.ObjectId(promo);
11650
+ } catch (error2) {
11651
+ throw new import_utils63.BadRequestError("Invalid promo ID.");
11584
11652
  }
11585
11653
  try {
11586
- const cacheKey = (0, import_utils63.makeCacheKey)(namespace_collection, cacheKeyOptions);
11587
- const cached = await getCache(
11588
- cacheKey
11589
- );
11590
- if (cached) {
11591
- import_utils63.logger.log({
11592
- level: "info",
11593
- message: `Cache hit for getJobPostsByOrg : ${cacheKey}`
11594
- });
11595
- return cached;
11654
+ const cacheKey = (0, import_utils63.makeCacheKey)(namespace_collection, {
11655
+ promo: String(promo),
11656
+ tag: "getByPromoId"
11657
+ });
11658
+ const cachedData = await getCache(cacheKey);
11659
+ if (cachedData) {
11660
+ return cachedData;
11596
11661
  }
11597
- const items = await collection.aggregate([
11598
- { $match: query },
11599
- { $skip: page * limit },
11600
- { $limit: limit },
11601
- {
11602
- $project: {
11603
- _id: 1,
11604
- title: 1,
11605
- setup: 1,
11606
- location: 1,
11607
- type: 1,
11608
- createdAt: 1
11609
- }
11610
- }
11611
- ]).toArray();
11612
- const length = await collection.countDocuments(query);
11613
- const data = (0, import_utils63.paginate)(items, page, limit, length);
11614
- setCache(cacheKey, data, 300).then(() => {
11662
+ const data = await collection.findOne({ promo });
11663
+ setCache(cacheKey, data).then(() => {
11615
11664
  import_utils63.logger.log({
11616
11665
  level: "info",
11617
- message: `Cache set for getJobPostsByOrg: ${cacheKey}`
11666
+ message: `Cache set for getByPromoId promo usage: ${cacheKey}`
11618
11667
  });
11619
11668
  }).catch((err) => {
11620
11669
  import_utils63.logger.log({
11621
11670
  level: "error",
11622
- message: `Failed to set cache for getJobPostsByOrg: ${err.message}`
11671
+ message: `Failed to set cache for getByPromoId promo usage: ${err.message}`
11623
11672
  });
11624
11673
  });
11625
11674
  return data;
11626
- } catch (error) {
11627
- throw new import_utils63.InternalServerError(
11628
- "Internal server error, failed to retrieve job posts."
11629
- );
11675
+ } catch (error2) {
11676
+ throw new import_utils63.InternalServerError("Failed to get promo usages.");
11630
11677
  }
11631
11678
  }
11632
11679
  async function getById(_id) {
11680
+ const { error } = import_joi48.default.string().hex().length(24).required().validate(_id);
11681
+ if (error) {
11682
+ throw new Error(`Invalid promo usage ID: ${error.message}`);
11683
+ }
11633
11684
  try {
11634
11685
  _id = new import_mongodb28.ObjectId(_id);
11686
+ } catch (error2) {
11687
+ throw new import_utils63.BadRequestError("Invalid promo usage ID.");
11688
+ }
11689
+ try {
11690
+ const cacheKey = (0, import_utils63.makeCacheKey)(namespace_collection, {
11691
+ _id: String(_id),
11692
+ tag: "getById"
11693
+ });
11694
+ const cachedData = await getCache(cacheKey);
11695
+ if (cachedData) {
11696
+ return cachedData;
11697
+ }
11698
+ const data = await collection.findOne({ _id });
11699
+ setCache(cacheKey, data).then(() => {
11700
+ import_utils63.logger.log({
11701
+ level: "info",
11702
+ message: `Cache set for getById promo usage: ${cacheKey}`
11703
+ });
11704
+ }).catch((err) => {
11705
+ import_utils63.logger.log({
11706
+ level: "error",
11707
+ message: `Failed to set cache for getById promo usage: ${err.message}`
11708
+ });
11709
+ });
11710
+ return data;
11711
+ } catch (error2) {
11712
+ throw new import_utils63.InternalServerError("Failed to get promo usage.");
11713
+ }
11714
+ }
11715
+ async function getByOrgId(orgId) {
11716
+ const { error } = import_joi48.default.string().hex().length(24).required().validate(orgId);
11717
+ if (error) {
11718
+ throw new Error(`Invalid org ID: ${error.message}`);
11719
+ }
11720
+ try {
11721
+ orgId = new import_mongodb28.ObjectId(orgId);
11722
+ } catch (error2) {
11723
+ throw new import_utils63.BadRequestError("Invalid org ID.");
11724
+ }
11725
+ try {
11726
+ const cacheKey = (0, import_utils63.makeCacheKey)(namespace_collection, {
11727
+ org: String(orgId),
11728
+ tag: "getByOrgId"
11729
+ });
11730
+ const cachedData = await getCache(cacheKey);
11731
+ if (cachedData) {
11732
+ return cachedData;
11733
+ }
11734
+ const data = await collection.find({ org: orgId }).toArray();
11735
+ setCache(cacheKey, data).then(() => {
11736
+ import_utils63.logger.log({
11737
+ level: "info",
11738
+ message: `Cache set for getByOrgId promo usage: ${cacheKey}`
11739
+ });
11740
+ }).catch((err) => {
11741
+ import_utils63.logger.log({
11742
+ level: "error",
11743
+ message: `Failed to set cache for getByOrgId promo usage: ${err.message}`
11744
+ });
11745
+ });
11746
+ return data;
11747
+ } catch (error2) {
11748
+ throw new import_utils63.InternalServerError("Failed to get promo usages.");
11749
+ }
11750
+ }
11751
+ async function countByPromoId(promoId) {
11752
+ const { error } = import_joi48.default.string().hex().length(24).required().validate(promoId);
11753
+ if (error) {
11754
+ throw new Error(`Invalid promo ID: ${error.message}`);
11755
+ }
11756
+ try {
11757
+ promoId = new import_mongodb28.ObjectId(promoId);
11758
+ } catch (error2) {
11759
+ throw new import_utils63.BadRequestError("Invalid promo ID.");
11760
+ }
11761
+ try {
11762
+ const cacheKey = (0, import_utils63.makeCacheKey)(namespace_collection, {
11763
+ promo: String(promoId),
11764
+ tag: "countByPromoId"
11765
+ });
11766
+ const cachedData = await getCache(cacheKey);
11767
+ if (cachedData !== null && cachedData !== void 0) {
11768
+ return cachedData;
11769
+ }
11770
+ const count = await collection.countDocuments({ promo: promoId });
11771
+ setCache(cacheKey, count).then(() => {
11772
+ import_utils63.logger.log({
11773
+ level: "info",
11774
+ message: `Cache set for countByPromoId promo usage: ${cacheKey}`
11775
+ });
11776
+ }).catch((err) => {
11777
+ import_utils63.logger.log({
11778
+ level: "error",
11779
+ message: `Failed to set cache for countByPromoId promo usage: ${err.message}`
11780
+ });
11781
+ });
11782
+ return count;
11783
+ } catch (error2) {
11784
+ throw new import_utils63.InternalServerError("Failed to count promo usages.");
11785
+ }
11786
+ }
11787
+ async function deleteById(_id) {
11788
+ const { error } = import_joi48.default.string().hex().length(24).required().validate(_id);
11789
+ if (error) {
11790
+ throw new Error(`Invalid promo usage ID: ${error.message}`);
11791
+ }
11792
+ try {
11793
+ _id = new import_mongodb28.ObjectId(_id);
11794
+ } catch (error2) {
11795
+ throw new import_utils63.BadRequestError("Invalid promo usage ID.");
11796
+ }
11797
+ try {
11798
+ const result = await collection.deleteOne({ _id });
11799
+ if (result.deletedCount === 0) {
11800
+ throw new import_utils63.InternalServerError("Failed to delete promo usage.");
11801
+ }
11802
+ delCachedData();
11803
+ return "Successfully deleted promo usage.";
11804
+ } catch (error2) {
11805
+ if (error2 instanceof import_utils63.AppError) {
11806
+ throw error2;
11807
+ }
11808
+ throw new import_utils63.InternalServerError("Failed to delete promo usage.");
11809
+ }
11810
+ }
11811
+ return {
11812
+ createIndexes,
11813
+ add,
11814
+ getAll,
11815
+ getByPromo,
11816
+ getById,
11817
+ getByOrgId,
11818
+ countByPromoId,
11819
+ deleteById
11820
+ };
11821
+ }
11822
+
11823
+ // src/resources/promo/promo.service.ts
11824
+ function usePromoService() {
11825
+ const { getByPromo } = usePromoUsageRepo();
11826
+ const { deleteById: _deleteById } = usePromoRepo();
11827
+ async function deleteById(id) {
11828
+ const usage = await getByPromo(id);
11829
+ if (usage) {
11830
+ throw new import_utils64.BadRequestError("Failed to delete, promo is in use.");
11831
+ }
11832
+ try {
11833
+ await _deleteById(id);
11834
+ return "Successfully deleted promo.";
11635
11835
  } catch (error) {
11636
- throw new import_utils63.BadRequestError("Invalid ID.");
11836
+ if (error instanceof import_utils64.AppError) {
11837
+ throw error;
11838
+ }
11839
+ throw new import_utils64.BadRequestError("Failed to delete promo.");
11637
11840
  }
11638
- const cacheKey = (0, import_utils63.makeCacheKey)(namespace_collection, { _id: String(_id) });
11841
+ }
11842
+ return {
11843
+ deleteById
11844
+ };
11845
+ }
11846
+
11847
+ // src/resources/promo/promo.controller.ts
11848
+ function usePromoController() {
11849
+ const {
11850
+ add: _add,
11851
+ getAll: _getAll,
11852
+ getByCode: _getByCode,
11853
+ getById: _getById,
11854
+ updateById: _updateById
11855
+ } = usePromoRepo();
11856
+ async function add(req, res, next) {
11857
+ const value = req.body;
11858
+ const { error } = schemaPromo.validate(value);
11859
+ if (error) {
11860
+ next(new import_utils65.BadRequestError(error.message));
11861
+ return;
11862
+ }
11863
+ try {
11864
+ const message = await _add(value);
11865
+ res.json({ message });
11866
+ return;
11867
+ } catch (error2) {
11868
+ next(error2);
11869
+ }
11870
+ }
11871
+ async function getAll(req, res, next) {
11872
+ const status = req.query.status ?? "active";
11873
+ const search = req.query.search ?? "";
11874
+ const page = Number(req.query.page) ?? 1;
11875
+ const limit = Number(req.query.limit) ?? 10;
11876
+ const validation = import_joi49.default.object({
11877
+ status: import_joi49.default.string().required(),
11878
+ search: import_joi49.default.string().optional().allow("", null),
11879
+ page: import_joi49.default.number().required(),
11880
+ limit: import_joi49.default.number().required()
11881
+ });
11882
+ const { error } = validation.validate({ status, search, page, limit });
11883
+ if (error) {
11884
+ next(new import_utils65.BadRequestError(error.message));
11885
+ return;
11886
+ }
11887
+ try {
11888
+ const promos = await _getAll({ status, search, page, limit });
11889
+ res.json(promos);
11890
+ return;
11891
+ } catch (error2) {
11892
+ next(error2);
11893
+ }
11894
+ }
11895
+ async function getByCode(req, res, next) {
11896
+ const code = req.params.code;
11897
+ const validation = import_joi49.default.string().min(3).max(50).required();
11898
+ const { error } = validation.validate(code);
11899
+ if (error) {
11900
+ next(new import_utils65.BadRequestError(error.message));
11901
+ return;
11902
+ }
11903
+ try {
11904
+ const promo = await _getByCode(code);
11905
+ res.json(promo);
11906
+ return;
11907
+ } catch (error2) {
11908
+ next(error2);
11909
+ }
11910
+ }
11911
+ async function getById(req, res, next) {
11912
+ const id = req.params.id;
11913
+ const validation = import_joi49.default.string().hex().length(24).required();
11914
+ const { error } = validation.validate(id);
11915
+ if (error) {
11916
+ next(new import_utils65.BadRequestError(error.message));
11917
+ return;
11918
+ }
11919
+ try {
11920
+ const promo = await _getById(id);
11921
+ res.json(promo);
11922
+ return;
11923
+ } catch (error2) {
11924
+ next(error2);
11925
+ }
11926
+ }
11927
+ async function updateById(req, res, next) {
11928
+ const id = req.params.id;
11929
+ const value = req.body;
11930
+ const validationId = import_joi49.default.string().hex().length(24).required();
11931
+ const { error: errorId } = validationId.validate(id);
11932
+ if (errorId) {
11933
+ next(new import_utils65.BadRequestError(errorId.message));
11934
+ return;
11935
+ }
11936
+ const { error } = schemaPromo.validate(value);
11937
+ if (error) {
11938
+ next(new import_utils65.BadRequestError(error.message));
11939
+ return;
11940
+ }
11941
+ try {
11942
+ const message = await _updateById(id, value);
11943
+ res.json({ message });
11944
+ return;
11945
+ } catch (error2) {
11946
+ next(error2);
11947
+ }
11948
+ }
11949
+ const { deleteById: _deleteById } = usePromoService();
11950
+ async function deleteById(req, res, next) {
11951
+ const id = req.params.id;
11952
+ const validation = import_joi49.default.string().hex().length(24).required();
11953
+ const { error } = validation.validate(id);
11954
+ if (error) {
11955
+ next(new import_utils65.BadRequestError(error.message));
11956
+ return;
11957
+ }
11958
+ try {
11959
+ const message = await _deleteById(id);
11960
+ res.json({ message });
11961
+ return;
11962
+ } catch (error2) {
11963
+ next(error2);
11964
+ }
11965
+ }
11966
+ return {
11967
+ add,
11968
+ getAll,
11969
+ getByCode,
11970
+ getById,
11971
+ updateById,
11972
+ deleteById
11973
+ };
11974
+ }
11975
+
11976
+ // src/resources/job-post/job.post.model.ts
11977
+ var import_utils66 = require("@goweekdays/utils");
11978
+ var import_joi50 = __toESM(require("joi"));
11979
+ var import_mongodb29 = require("mongodb");
11980
+ var schemaJobPost = import_joi50.default.object({
11981
+ _id: import_joi50.default.string().hex().optional(),
11982
+ org: import_joi50.default.string().hex().required(),
11983
+ title: import_joi50.default.string().trim().required(),
11984
+ setup: import_joi50.default.string().trim().required(),
11985
+ location: import_joi50.default.string().trim().required(),
11986
+ type: import_joi50.default.string().trim().required(),
11987
+ description: import_joi50.default.string().trim().required(),
11988
+ status: import_joi50.default.string().trim().optional().allow("", null),
11989
+ createdAt: import_joi50.default.date().optional(),
11990
+ updatedAt: import_joi50.default.date().optional(),
11991
+ deletedAt: import_joi50.default.date().optional()
11992
+ });
11993
+ var schemaJobPostUpdate = import_joi50.default.object({
11994
+ _id: import_joi50.default.string().hex().required(),
11995
+ title: import_joi50.default.string().trim().required(),
11996
+ setup: import_joi50.default.string().trim().required(),
11997
+ location: import_joi50.default.string().trim().required(),
11998
+ type: import_joi50.default.string().trim().required(),
11999
+ description: import_joi50.default.string().trim().required()
12000
+ });
12001
+ function modelJobPost(value) {
12002
+ const { error } = schemaJobPost.validate(value);
12003
+ if (error) {
12004
+ throw new import_utils66.BadRequestError(`Invalid job post: ${error.message}`);
12005
+ }
12006
+ if (!value._id) {
12007
+ try {
12008
+ value._id = new import_mongodb29.ObjectId();
12009
+ } catch (error2) {
12010
+ throw new import_utils66.BadRequestError("Invalid job post ID.");
12011
+ }
12012
+ }
12013
+ try {
12014
+ value.org = new import_mongodb29.ObjectId(value.org);
12015
+ } catch (error2) {
12016
+ throw new import_utils66.BadRequestError("Invalid Org ID");
12017
+ }
12018
+ return {
12019
+ _id: value._id,
12020
+ org: value.org,
12021
+ title: value.title,
12022
+ setup: value.setup,
12023
+ location: value.location,
12024
+ type: value.type,
12025
+ description: value.description,
12026
+ status: value.status ?? "draft",
12027
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
12028
+ updatedAt: value.updatedAt,
12029
+ deletedAt: value.deletedAt
12030
+ };
12031
+ }
12032
+
12033
+ // src/resources/job-post/job.post.controller.ts
12034
+ var import_joi52 = __toESM(require("joi"));
12035
+ var import_utils69 = require("@goweekdays/utils");
12036
+
12037
+ // src/resources/job-post/job.post.repository.ts
12038
+ var import_utils67 = require("@goweekdays/utils");
12039
+ var import_mongodb30 = require("mongodb");
12040
+ function useJobPostRepo() {
12041
+ const db = import_utils67.useAtlas.getDb();
12042
+ if (!db) {
12043
+ throw new import_utils67.BadRequestError("Unable to connect to server.");
12044
+ }
12045
+ const namespace_collection = "job.posts";
12046
+ const collection = db.collection(namespace_collection);
12047
+ const { getCache, setCache, delNamespace } = (0, import_utils67.useCache)(namespace_collection);
12048
+ function delCachedData() {
12049
+ delNamespace().then(() => {
12050
+ import_utils67.logger.log({
12051
+ level: "info",
12052
+ message: `Cache namespace cleared for ${namespace_collection}`
12053
+ });
12054
+ }).catch((err) => {
12055
+ import_utils67.logger.log({
12056
+ level: "error",
12057
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
12058
+ });
12059
+ });
12060
+ }
12061
+ async function createIndexes() {
12062
+ try {
12063
+ await collection.createIndexes([
12064
+ { key: { title: 1 } },
12065
+ { key: { setup: 1 } },
12066
+ { key: { location: 1 } },
12067
+ { key: { type: 1 } },
12068
+ {
12069
+ key: {
12070
+ title: "text",
12071
+ setup: "text",
12072
+ location: "text",
12073
+ type: "text"
12074
+ },
12075
+ name: "jobpost_text_search"
12076
+ }
12077
+ ]);
12078
+ return "Successfully created job post indexes.";
12079
+ } catch (error) {
12080
+ throw new import_utils67.BadRequestError("Failed to create job post indexes.");
12081
+ }
12082
+ }
12083
+ async function add(value, session) {
12084
+ try {
12085
+ value = modelJobPost(value);
12086
+ const res = await collection.insertOne(value, { session });
12087
+ delCachedData();
12088
+ return res.insertedId;
12089
+ } catch (error) {
12090
+ import_utils67.logger.log({
12091
+ level: "error",
12092
+ message: error.message
12093
+ });
12094
+ throw new import_utils67.BadRequestError(`Failed to create job post: ${error.message}`);
12095
+ }
12096
+ }
12097
+ async function getAll({
12098
+ search = "",
12099
+ page = 1,
12100
+ limit = 10,
12101
+ status = "active"
12102
+ } = {}) {
12103
+ page = page > 0 ? page - 1 : 0;
12104
+ const query = { status };
12105
+ if (search) {
12106
+ query.$text = { $search: search };
12107
+ }
12108
+ const cacheKey = (0, import_utils67.makeCacheKey)(namespace_collection, {
12109
+ search,
12110
+ page,
12111
+ limit,
12112
+ status
12113
+ });
12114
+ import_utils67.logger.log({
12115
+ level: "info",
12116
+ message: `Cache key for getAll job posts: ${cacheKey}`
12117
+ });
11639
12118
  try {
11640
12119
  const cached = await getCache(cacheKey);
11641
12120
  if (cached) {
11642
- import_utils63.logger.log({
12121
+ import_utils67.logger.log({
12122
+ level: "info",
12123
+ message: `Cache hit for getAll job posts: ${cacheKey}`
12124
+ });
12125
+ return cached;
12126
+ }
12127
+ const items = await collection.aggregate([
12128
+ { $match: query },
12129
+ { $skip: page * limit },
12130
+ { $limit: limit },
12131
+ {
12132
+ $project: {
12133
+ _id: 1,
12134
+ title: 1,
12135
+ setup: 1,
12136
+ location: 1,
12137
+ type: 1,
12138
+ createdAt: 1
12139
+ }
12140
+ }
12141
+ ]).toArray();
12142
+ const length = await collection.countDocuments(query);
12143
+ const data = (0, import_utils67.paginate)(items, page, limit, length);
12144
+ setCache(cacheKey, data, 600).then(() => {
12145
+ import_utils67.logger.log({
12146
+ level: "info",
12147
+ message: `Cache set for getAll job posts: ${cacheKey}`
12148
+ });
12149
+ }).catch((err) => {
12150
+ import_utils67.logger.log({
12151
+ level: "error",
12152
+ message: `Failed to set cache for getAll job posts: ${err.message}`
12153
+ });
12154
+ });
12155
+ return data;
12156
+ } catch (error) {
12157
+ import_utils67.logger.log({ level: "error", message: `${error}` });
12158
+ throw error;
12159
+ }
12160
+ }
12161
+ async function getJobPostsByOrg({
12162
+ search = "",
12163
+ page = 1,
12164
+ limit = 10,
12165
+ org = "",
12166
+ status = "active"
12167
+ } = {}) {
12168
+ page = page > 0 ? page - 1 : 0;
12169
+ try {
12170
+ org = new import_mongodb30.ObjectId(org);
12171
+ } catch (error) {
12172
+ throw new import_utils67.BadRequestError("Invalid organization ID.");
12173
+ }
12174
+ const query = { org, status };
12175
+ const cacheKeyOptions = {
12176
+ org: String(org),
12177
+ status,
12178
+ limit,
12179
+ page
12180
+ };
12181
+ if (search) {
12182
+ cacheKeyOptions.search = search;
12183
+ query.$text = { $search: search };
12184
+ }
12185
+ try {
12186
+ const cacheKey = (0, import_utils67.makeCacheKey)(namespace_collection, cacheKeyOptions);
12187
+ const cached = await getCache(
12188
+ cacheKey
12189
+ );
12190
+ if (cached) {
12191
+ import_utils67.logger.log({
12192
+ level: "info",
12193
+ message: `Cache hit for getJobPostsByOrg : ${cacheKey}`
12194
+ });
12195
+ return cached;
12196
+ }
12197
+ const items = await collection.aggregate([
12198
+ { $match: query },
12199
+ { $skip: page * limit },
12200
+ { $limit: limit },
12201
+ {
12202
+ $project: {
12203
+ _id: 1,
12204
+ title: 1,
12205
+ setup: 1,
12206
+ location: 1,
12207
+ type: 1,
12208
+ createdAt: 1
12209
+ }
12210
+ }
12211
+ ]).toArray();
12212
+ const length = await collection.countDocuments(query);
12213
+ const data = (0, import_utils67.paginate)(items, page, limit, length);
12214
+ setCache(cacheKey, data, 300).then(() => {
12215
+ import_utils67.logger.log({
12216
+ level: "info",
12217
+ message: `Cache set for getJobPostsByOrg: ${cacheKey}`
12218
+ });
12219
+ }).catch((err) => {
12220
+ import_utils67.logger.log({
12221
+ level: "error",
12222
+ message: `Failed to set cache for getJobPostsByOrg: ${err.message}`
12223
+ });
12224
+ });
12225
+ return data;
12226
+ } catch (error) {
12227
+ throw new import_utils67.InternalServerError(
12228
+ "Internal server error, failed to retrieve job posts."
12229
+ );
12230
+ }
12231
+ }
12232
+ async function getById(_id) {
12233
+ try {
12234
+ _id = new import_mongodb30.ObjectId(_id);
12235
+ } catch (error) {
12236
+ throw new import_utils67.BadRequestError("Invalid ID.");
12237
+ }
12238
+ const cacheKey = (0, import_utils67.makeCacheKey)(namespace_collection, { _id: String(_id) });
12239
+ try {
12240
+ const cached = await getCache(cacheKey);
12241
+ if (cached) {
12242
+ import_utils67.logger.log({
11643
12243
  level: "info",
11644
12244
  message: `Cache hit for getById job post: ${cacheKey}`
11645
12245
  });
@@ -11647,37 +12247,37 @@ function useJobPostRepo() {
11647
12247
  }
11648
12248
  const result = await collection.findOne({ _id });
11649
12249
  if (!result) {
11650
- throw new import_utils63.BadRequestError("Job post not found.");
12250
+ throw new import_utils67.BadRequestError("Job post not found.");
11651
12251
  }
11652
12252
  setCache(cacheKey, result, 300).then(() => {
11653
- import_utils63.logger.log({
12253
+ import_utils67.logger.log({
11654
12254
  level: "info",
11655
12255
  message: `Cache set for job post by id: ${cacheKey}`
11656
12256
  });
11657
12257
  }).catch((err) => {
11658
- import_utils63.logger.log({
12258
+ import_utils67.logger.log({
11659
12259
  level: "error",
11660
12260
  message: `Failed to set cache for job post by id: ${err.message}`
11661
12261
  });
11662
12262
  });
11663
12263
  return result;
11664
12264
  } catch (error) {
11665
- if (error instanceof import_utils63.AppError) {
12265
+ if (error instanceof import_utils67.AppError) {
11666
12266
  throw error;
11667
12267
  } else {
11668
- throw new import_utils63.InternalServerError("Failed to get job post.");
12268
+ throw new import_utils67.InternalServerError("Failed to get job post.");
11669
12269
  }
11670
12270
  }
11671
12271
  }
11672
12272
  async function updateById(_id, options) {
11673
12273
  const { error } = schemaJobPostUpdate.validate({ ...options, _id });
11674
12274
  if (error) {
11675
- throw new import_utils63.BadRequestError(error.message);
12275
+ throw new import_utils67.BadRequestError(error.message);
11676
12276
  }
11677
12277
  try {
11678
- _id = new import_mongodb28.ObjectId(_id);
12278
+ _id = new import_mongodb30.ObjectId(_id);
11679
12279
  } catch (error2) {
11680
- throw new import_utils63.BadRequestError("Invalid JobPost ID.");
12280
+ throw new import_utils67.BadRequestError("Invalid JobPost ID.");
11681
12281
  }
11682
12282
  try {
11683
12283
  await collection.updateOne(
@@ -11687,14 +12287,14 @@ function useJobPostRepo() {
11687
12287
  delCachedData();
11688
12288
  return "Successfully updated job post.";
11689
12289
  } catch (error2) {
11690
- throw new import_utils63.InternalServerError("Failed to update job post.");
12290
+ throw new import_utils67.InternalServerError("Failed to update job post.");
11691
12291
  }
11692
12292
  }
11693
12293
  async function deleteById(_id, session) {
11694
12294
  try {
11695
- _id = new import_mongodb28.ObjectId(_id);
12295
+ _id = new import_mongodb30.ObjectId(_id);
11696
12296
  } catch (error) {
11697
- throw new import_utils63.BadRequestError("Invalid ID.");
12297
+ throw new import_utils67.BadRequestError("Invalid ID.");
11698
12298
  }
11699
12299
  try {
11700
12300
  await collection.updateOne(
@@ -11711,7 +12311,35 @@ function useJobPostRepo() {
11711
12311
  delCachedData();
11712
12312
  return "Successfully deleted job post.";
11713
12313
  } catch (error) {
11714
- throw new import_utils63.InternalServerError("Failed to delete job post.");
12314
+ throw new import_utils67.InternalServerError("Failed to delete job post.");
12315
+ }
12316
+ }
12317
+ async function updateStatusById(_id, status) {
12318
+ try {
12319
+ _id = new import_mongodb30.ObjectId(_id);
12320
+ } catch (error) {
12321
+ throw new import_utils67.BadRequestError("Invalid ID.");
12322
+ }
12323
+ try {
12324
+ const result = await collection.updateOne(
12325
+ { _id },
12326
+ {
12327
+ $set: {
12328
+ status,
12329
+ updatedAt: /* @__PURE__ */ new Date()
12330
+ }
12331
+ }
12332
+ );
12333
+ if (result.matchedCount === 0) {
12334
+ throw new import_utils67.BadRequestError("Job post not found.");
12335
+ }
12336
+ delCachedData();
12337
+ return "Successfully updated job post status.";
12338
+ } catch (error) {
12339
+ if (error instanceof import_utils67.AppError) {
12340
+ throw error;
12341
+ }
12342
+ throw new import_utils67.InternalServerError("Failed to update job post status.");
11715
12343
  }
11716
12344
  }
11717
12345
  return {
@@ -11721,28 +12349,29 @@ function useJobPostRepo() {
11721
12349
  getJobPostsByOrg,
11722
12350
  getById,
11723
12351
  updateById,
11724
- deleteById
12352
+ deleteById,
12353
+ updateStatusById
11725
12354
  };
11726
12355
  }
11727
12356
 
11728
12357
  // src/resources/job-post/job.post.service.ts
11729
- var import_utils64 = require("@goweekdays/utils");
11730
- var import_joi48 = __toESM(require("joi"));
12358
+ var import_utils68 = require("@goweekdays/utils");
12359
+ var import_joi51 = __toESM(require("joi"));
11731
12360
  function useJobPostService() {
11732
12361
  const { deleteById: _deleteById } = useJobPostRepo();
11733
12362
  async function deleteById(id) {
11734
- const { error } = import_joi48.default.string().hex().required().validate(id);
12363
+ const { error } = import_joi51.default.string().hex().required().validate(id);
11735
12364
  if (error) {
11736
- throw new import_utils64.BadRequestError(error.message);
12365
+ throw new import_utils68.BadRequestError(error.message);
11737
12366
  }
11738
12367
  try {
11739
12368
  await _deleteById(id);
11740
12369
  return "Successfully deleted job post.";
11741
12370
  } catch (error2) {
11742
- if (error2 instanceof import_utils64.AppError) {
12371
+ if (error2 instanceof import_utils68.AppError) {
11743
12372
  throw error2;
11744
12373
  } else {
11745
- throw new import_utils64.InternalServerError("Failed to delete job post.");
12374
+ throw new import_utils68.InternalServerError("Failed to delete job post.");
11746
12375
  }
11747
12376
  }
11748
12377
  }
@@ -11758,15 +12387,16 @@ function useJobPostController() {
11758
12387
  getAll: _getAll,
11759
12388
  getJobPostsByOrg: _getJobPostsByOrg,
11760
12389
  getById: _getById,
11761
- updateById: _updateById
12390
+ updateById: _updateById,
12391
+ updateStatusById: _updateStatusById
11762
12392
  } = useJobPostRepo();
11763
12393
  const { deleteById: _deleteById } = useJobPostService();
11764
12394
  async function add(req, res, next) {
11765
12395
  const value = req.body;
11766
12396
  const { error } = schemaJobPost.validate(value);
11767
12397
  if (error) {
11768
- next(new import_utils65.BadRequestError(error.message));
11769
- import_utils65.logger.info(`Controller: ${error.message}`);
12398
+ next(new import_utils69.BadRequestError(error.message));
12399
+ import_utils69.logger.info(`Controller: ${error.message}`);
11770
12400
  return;
11771
12401
  }
11772
12402
  try {
@@ -11779,11 +12409,11 @@ function useJobPostController() {
11779
12409
  }
11780
12410
  async function getAll(req, res, next) {
11781
12411
  const query = req.query;
11782
- const validation = import_joi49.default.object({
11783
- page: import_joi49.default.number().min(1).optional().allow("", null),
11784
- limit: import_joi49.default.number().min(1).optional().allow("", null),
11785
- search: import_joi49.default.string().optional().allow("", null),
11786
- status: import_joi49.default.string().optional()
12412
+ const validation = import_joi52.default.object({
12413
+ page: import_joi52.default.number().min(1).optional().allow("", null),
12414
+ limit: import_joi52.default.number().min(1).optional().allow("", null),
12415
+ search: import_joi52.default.string().optional().allow("", null),
12416
+ status: import_joi52.default.string().optional()
11787
12417
  });
11788
12418
  const { error } = validation.validate(query);
11789
12419
  const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
@@ -11792,16 +12422,16 @@ function useJobPostController() {
11792
12422
  const status = req.query.status ?? "active";
11793
12423
  const isPageNumber = isFinite(page);
11794
12424
  if (!isPageNumber) {
11795
- next(new import_utils65.BadRequestError("Invalid page number."));
12425
+ next(new import_utils69.BadRequestError("Invalid page number."));
11796
12426
  return;
11797
12427
  }
11798
12428
  const isLimitNumber = isFinite(limit);
11799
12429
  if (!isLimitNumber) {
11800
- next(new import_utils65.BadRequestError("Invalid limit number."));
12430
+ next(new import_utils69.BadRequestError("Invalid limit number."));
11801
12431
  return;
11802
12432
  }
11803
12433
  if (error) {
11804
- next(new import_utils65.BadRequestError(error.message));
12434
+ next(new import_utils69.BadRequestError(error.message));
11805
12435
  return;
11806
12436
  }
11807
12437
  try {
@@ -11820,24 +12450,24 @@ function useJobPostController() {
11820
12450
  const org = req.params.org ?? "";
11821
12451
  const isPageNumber = isFinite(page);
11822
12452
  if (!isPageNumber) {
11823
- next(new import_utils65.BadRequestError("Invalid page number."));
12453
+ next(new import_utils69.BadRequestError("Invalid page number."));
11824
12454
  return;
11825
12455
  }
11826
12456
  const isLimitNumber = isFinite(limit);
11827
12457
  if (!isLimitNumber) {
11828
- next(new import_utils65.BadRequestError("Invalid limit number."));
12458
+ next(new import_utils69.BadRequestError("Invalid limit number."));
11829
12459
  return;
11830
12460
  }
11831
- const validation = import_joi49.default.object({
11832
- org: import_joi49.default.string().hex().required(),
11833
- page: import_joi49.default.number().min(1).optional().allow("", null),
11834
- limit: import_joi49.default.number().min(1).optional().allow("", null),
11835
- search: import_joi49.default.string().optional().allow("", null),
11836
- status: import_joi49.default.string().optional()
12461
+ const validation = import_joi52.default.object({
12462
+ org: import_joi52.default.string().hex().required(),
12463
+ page: import_joi52.default.number().min(1).optional().allow("", null),
12464
+ limit: import_joi52.default.number().min(1).optional().allow("", null),
12465
+ search: import_joi52.default.string().optional().allow("", null),
12466
+ status: import_joi52.default.string().optional()
11837
12467
  });
11838
12468
  const { error } = validation.validate({ org, page, limit, search, status });
11839
12469
  if (error) {
11840
- next(new import_utils65.BadRequestError(error.message));
12470
+ next(new import_utils69.BadRequestError(error.message));
11841
12471
  return;
11842
12472
  }
11843
12473
  try {
@@ -11850,12 +12480,12 @@ function useJobPostController() {
11850
12480
  }
11851
12481
  async function getById(req, res, next) {
11852
12482
  const id = req.params.id;
11853
- const validation = import_joi49.default.object({
11854
- id: import_joi49.default.string().hex().required()
12483
+ const validation = import_joi52.default.object({
12484
+ id: import_joi52.default.string().hex().required()
11855
12485
  });
11856
12486
  const { error } = validation.validate({ id });
11857
12487
  if (error) {
11858
- next(new import_utils65.BadRequestError(error.message));
12488
+ next(new import_utils69.BadRequestError(error.message));
11859
12489
  return;
11860
12490
  }
11861
12491
  try {
@@ -11871,7 +12501,7 @@ function useJobPostController() {
11871
12501
  const payload = req.body;
11872
12502
  const { error } = schemaJobPostUpdate.validate({ _id, ...payload });
11873
12503
  if (error) {
11874
- next(new import_utils65.BadRequestError(error.message));
12504
+ next(new import_utils69.BadRequestError(error.message));
11875
12505
  return;
11876
12506
  }
11877
12507
  try {
@@ -11885,7 +12515,7 @@ function useJobPostController() {
11885
12515
  async function deleteById(req, res, next) {
11886
12516
  const id = req.params.id;
11887
12517
  if (!id) {
11888
- next(new import_utils65.BadRequestError("Job Post ID is required."));
12518
+ next(new import_utils69.BadRequestError("Job Post ID is required."));
11889
12519
  return;
11890
12520
  }
11891
12521
  try {
@@ -11896,13 +12526,34 @@ function useJobPostController() {
11896
12526
  next(error);
11897
12527
  }
11898
12528
  }
12529
+ async function updateStatusById(req, res, next) {
12530
+ const id = req.params.id;
12531
+ const status = req.params.status;
12532
+ const validation = import_joi52.default.object({
12533
+ id: import_joi52.default.string().hex().required(),
12534
+ status: import_joi52.default.string().valid("draft", "open", "paused", "in-review", "closed").required()
12535
+ });
12536
+ const { error } = validation.validate({ id, status });
12537
+ if (error) {
12538
+ next(new import_utils69.BadRequestError(error.message));
12539
+ return;
12540
+ }
12541
+ try {
12542
+ const message = await _updateStatusById(id, status);
12543
+ res.json({ message });
12544
+ return;
12545
+ } catch (error2) {
12546
+ next(error2);
12547
+ }
12548
+ }
11899
12549
  return {
11900
12550
  add,
11901
12551
  getAll,
11902
12552
  getJobPostsByOrg,
11903
12553
  getById,
11904
12554
  updateById,
11905
- deleteById
12555
+ deleteById,
12556
+ updateStatusById
11906
12557
  };
11907
12558
  }
11908
12559
  // Annotate the CommonJS export names for ESM import in node:
@@ -12033,6 +12684,7 @@ function useJobPostController() {
12033
12684
  usePlanController,
12034
12685
  usePlanRepo,
12035
12686
  usePlanService,
12687
+ usePromoController,
12036
12688
  usePromoRepo,
12037
12689
  useRoleController,
12038
12690
  useRoleRepo,