@goweekdays/core 2.9.0 → 2.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/index.d.ts +35 -11
- package/dist/index.js +1319 -284
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1427 -367
- package/dist/index.mjs.map +1 -1
- package/dist/public/handlebars/org-created.hbs +13 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -496,15 +496,15 @@ import {
|
|
|
496
496
|
AppError as AppError22,
|
|
497
497
|
BadRequestError as BadRequestError45,
|
|
498
498
|
InternalServerError as InternalServerError25,
|
|
499
|
-
logger as
|
|
499
|
+
logger as logger25
|
|
500
500
|
} from "@goweekdays/utils";
|
|
501
501
|
|
|
502
502
|
// src/resources/verification/verification.service.ts
|
|
503
503
|
import {
|
|
504
|
-
useMailer,
|
|
505
|
-
compileHandlebar,
|
|
506
|
-
logger as
|
|
507
|
-
getDirectory,
|
|
504
|
+
useMailer as useMailer2,
|
|
505
|
+
compileHandlebar as compileHandlebar2,
|
|
506
|
+
logger as logger24,
|
|
507
|
+
getDirectory as getDirectory2,
|
|
508
508
|
BadRequestError as BadRequestError44,
|
|
509
509
|
NotFoundError as NotFoundError3,
|
|
510
510
|
InternalServerError as InternalServerError24,
|
|
@@ -923,7 +923,7 @@ import {
|
|
|
923
923
|
InternalServerError as InternalServerError22,
|
|
924
924
|
NotFoundError as NotFoundError2,
|
|
925
925
|
hashPassword,
|
|
926
|
-
logger as
|
|
926
|
+
logger as logger23,
|
|
927
927
|
makeCacheKey as makeCacheKey14,
|
|
928
928
|
useAtlas as useAtlas18,
|
|
929
929
|
useCache as useCache15,
|
|
@@ -1154,6 +1154,7 @@ function useMemberRepo() {
|
|
|
1154
1154
|
await collection.createIndexes([
|
|
1155
1155
|
{ key: { name: 1 } },
|
|
1156
1156
|
{ key: { status: 1 } },
|
|
1157
|
+
{ key: { org: 1 } },
|
|
1157
1158
|
{ key: { name: "text", orgName: "text" }, name: "text_index" },
|
|
1158
1159
|
{
|
|
1159
1160
|
key: {
|
|
@@ -1859,6 +1860,38 @@ function useMemberRepo() {
|
|
|
1859
1860
|
);
|
|
1860
1861
|
}
|
|
1861
1862
|
}
|
|
1863
|
+
async function updateStatusByOrg(org, status, session) {
|
|
1864
|
+
const { error } = Joi4.object({
|
|
1865
|
+
org: Joi4.string().hex().length(24).required(),
|
|
1866
|
+
status: Joi4.string().valid("active", "suspended").required()
|
|
1867
|
+
}).validate({ org, status });
|
|
1868
|
+
if (error) {
|
|
1869
|
+
throw new BadRequestError7(error.message);
|
|
1870
|
+
}
|
|
1871
|
+
try {
|
|
1872
|
+
org = new ObjectId7(org);
|
|
1873
|
+
} catch (error2) {
|
|
1874
|
+
throw new BadRequestError7("Invalid organization ID.");
|
|
1875
|
+
}
|
|
1876
|
+
try {
|
|
1877
|
+
await collection.updateMany(
|
|
1878
|
+
{ org, status: { $ne: "deleted" }, app: { $ne: "org" } },
|
|
1879
|
+
{
|
|
1880
|
+
$set: {
|
|
1881
|
+
status,
|
|
1882
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1883
|
+
}
|
|
1884
|
+
},
|
|
1885
|
+
{ session }
|
|
1886
|
+
);
|
|
1887
|
+
delCachedData();
|
|
1888
|
+
return "Successfully updated member statuses by organization.";
|
|
1889
|
+
} catch (error2) {
|
|
1890
|
+
throw new InternalServerError5(
|
|
1891
|
+
"Internal server error, failed to update member statuses."
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1862
1895
|
return {
|
|
1863
1896
|
createIndexes,
|
|
1864
1897
|
add,
|
|
@@ -1876,7 +1909,8 @@ function useMemberRepo() {
|
|
|
1876
1909
|
getByApp,
|
|
1877
1910
|
updateRoleById,
|
|
1878
1911
|
updateStatusById,
|
|
1879
|
-
deleteById
|
|
1912
|
+
deleteById,
|
|
1913
|
+
updateStatusByOrg
|
|
1880
1914
|
};
|
|
1881
1915
|
}
|
|
1882
1916
|
|
|
@@ -3508,8 +3542,13 @@ function useAppService() {
|
|
|
3508
3542
|
},
|
|
3509
3543
|
{
|
|
3510
3544
|
code: "job",
|
|
3511
|
-
name: "
|
|
3545
|
+
name: "Jobs",
|
|
3512
3546
|
description: "Job listings and recruitment services."
|
|
3547
|
+
},
|
|
3548
|
+
{
|
|
3549
|
+
code: "circle",
|
|
3550
|
+
name: "Circle",
|
|
3551
|
+
description: "Community-based rotational system"
|
|
3513
3552
|
}
|
|
3514
3553
|
];
|
|
3515
3554
|
const session = useAtlas9.getClient()?.startSession();
|
|
@@ -4327,7 +4366,8 @@ var schema = {
|
|
|
4327
4366
|
name: Joi15.string().max(255).required(),
|
|
4328
4367
|
description: Joi15.string().max(1024).optional().allow("", null),
|
|
4329
4368
|
email: Joi15.string().email().max(255).required(),
|
|
4330
|
-
contact: Joi15.string().max(50).optional().allow("", null)
|
|
4369
|
+
contact: Joi15.string().max(50).optional().allow("", null),
|
|
4370
|
+
promoCode: Joi15.string().max(50).optional().allow("", null)
|
|
4331
4371
|
};
|
|
4332
4372
|
var schemaOrg = Joi15.object({
|
|
4333
4373
|
...schema,
|
|
@@ -4361,6 +4401,7 @@ function modelOrg(value) {
|
|
|
4361
4401
|
email: value.email,
|
|
4362
4402
|
contact: value.contact,
|
|
4363
4403
|
createdBy: value.createdBy,
|
|
4404
|
+
promoCode: value.promoCode ?? "",
|
|
4364
4405
|
status: value.status ?? "active",
|
|
4365
4406
|
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
4366
4407
|
updatedAt: "",
|
|
@@ -4720,7 +4761,14 @@ function useOrgRepo() {
|
|
|
4720
4761
|
}
|
|
4721
4762
|
|
|
4722
4763
|
// src/resources/organization/organization.service.ts
|
|
4723
|
-
import {
|
|
4764
|
+
import {
|
|
4765
|
+
BadRequestError as BadRequestError40,
|
|
4766
|
+
compileHandlebar,
|
|
4767
|
+
getDirectory,
|
|
4768
|
+
logger as logger22,
|
|
4769
|
+
useAtlas as useAtlas17,
|
|
4770
|
+
useMailer
|
|
4771
|
+
} from "@goweekdays/utils";
|
|
4724
4772
|
|
|
4725
4773
|
// src/resources/member/member.controller.ts
|
|
4726
4774
|
import Joi19 from "joi";
|
|
@@ -5419,7 +5467,7 @@ function useSubscriptionRepo() {
|
|
|
5419
5467
|
search = "",
|
|
5420
5468
|
status = "active"
|
|
5421
5469
|
} = {}) {
|
|
5422
|
-
page = page
|
|
5470
|
+
page = page > 0 ? page - 1 : page;
|
|
5423
5471
|
const query = { status };
|
|
5424
5472
|
const cacheKeyOptions = {
|
|
5425
5473
|
page,
|
|
@@ -7548,6 +7596,7 @@ function useSubscriptionService() {
|
|
|
7548
7596
|
}
|
|
7549
7597
|
}
|
|
7550
7598
|
const { getOverdueForSuspension } = useSubscriptionRepo();
|
|
7599
|
+
const { updateStatusByOrg } = useMemberRepo();
|
|
7551
7600
|
async function processSuspensions() {
|
|
7552
7601
|
const DAYS_OVERDUE = 7;
|
|
7553
7602
|
while (true) {
|
|
@@ -7569,8 +7618,10 @@ function useSubscriptionService() {
|
|
|
7569
7618
|
session.startTransaction();
|
|
7570
7619
|
await updateStatusById(subId, "suspended", session);
|
|
7571
7620
|
await updateRetryById(subId, 0, session);
|
|
7572
|
-
|
|
7573
|
-
|
|
7621
|
+
const orgId = String(subscription.org);
|
|
7622
|
+
if (orgId) {
|
|
7623
|
+
await updateOrgStatusById(orgId, "suspended", session);
|
|
7624
|
+
await updateStatusByOrg(orgId, "suspended", session);
|
|
7574
7625
|
}
|
|
7575
7626
|
await session.commitTransaction();
|
|
7576
7627
|
logger21.log({
|
|
@@ -7634,6 +7685,7 @@ function useSubscriptionService() {
|
|
|
7634
7685
|
session
|
|
7635
7686
|
);
|
|
7636
7687
|
await updateOrgStatusById(orgId, "active", session);
|
|
7688
|
+
await updateStatusByOrg(orgId, "active", session);
|
|
7637
7689
|
await updateLedgerStatusById(String(ledgerBill._id), "paid", session);
|
|
7638
7690
|
await session.commitTransaction();
|
|
7639
7691
|
return "Successfully processed paid invoice.";
|
|
@@ -7713,7 +7765,8 @@ function useSubscriptionController() {
|
|
|
7713
7765
|
const validation = Joi33.object({
|
|
7714
7766
|
page: Joi33.number().min(1).max(100).optional().allow(null, "").default(1),
|
|
7715
7767
|
limit: Joi33.number().min(1).max(100).optional().allow(null, "").default(10),
|
|
7716
|
-
status: Joi33.string().valid("active", "suspended").optional().default("active")
|
|
7768
|
+
status: Joi33.string().valid("active", "suspended").optional().default("active"),
|
|
7769
|
+
search: Joi33.string().optional().allow("", null)
|
|
7717
7770
|
});
|
|
7718
7771
|
const query = req.query;
|
|
7719
7772
|
const { error, value } = validation.validate(query);
|
|
@@ -8208,6 +8261,14 @@ function useOrgService() {
|
|
|
8208
8261
|
}
|
|
8209
8262
|
const { getById, updateStatusById: updateVerificationStatus } = useVerificationRepo();
|
|
8210
8263
|
const { add: addLedgerBilling } = useLedgerBillingRepo();
|
|
8264
|
+
const MailerConfig = {
|
|
8265
|
+
host: MAILER_TRANSPORT_HOST,
|
|
8266
|
+
port: MAILER_TRANSPORT_PORT,
|
|
8267
|
+
secure: MAILER_TRANSPORT_SECURE,
|
|
8268
|
+
email: MAILER_EMAIL,
|
|
8269
|
+
password: MAILER_PASSWORD
|
|
8270
|
+
};
|
|
8271
|
+
const mailer = new useMailer(MailerConfig);
|
|
8211
8272
|
async function addWithVerification(id) {
|
|
8212
8273
|
const { error } = Joi36.string().hex().required().validate(id);
|
|
8213
8274
|
if (error) {
|
|
@@ -8319,6 +8380,28 @@ function useOrgService() {
|
|
|
8319
8380
|
},
|
|
8320
8381
|
session
|
|
8321
8382
|
);
|
|
8383
|
+
const filePath = getDirectory(
|
|
8384
|
+
__dirname,
|
|
8385
|
+
"./public/handlebars/org-created"
|
|
8386
|
+
);
|
|
8387
|
+
const emailContent = compileHandlebar({
|
|
8388
|
+
context: {
|
|
8389
|
+
app: APP_ORG,
|
|
8390
|
+
organization_name: verification.metadata.orgName
|
|
8391
|
+
},
|
|
8392
|
+
filePath
|
|
8393
|
+
});
|
|
8394
|
+
mailer.sendMail({
|
|
8395
|
+
to: verification.email,
|
|
8396
|
+
subject: "Welcome to GoWeekdays - Your Organization is Ready",
|
|
8397
|
+
html: emailContent,
|
|
8398
|
+
from: "GoWeekdays"
|
|
8399
|
+
}).catch((error2) => {
|
|
8400
|
+
logger22.log({
|
|
8401
|
+
level: "error",
|
|
8402
|
+
message: `Error sending user invite email: ${error2}`
|
|
8403
|
+
});
|
|
8404
|
+
});
|
|
8322
8405
|
await session?.commitTransaction();
|
|
8323
8406
|
return "Successfully created organization with verification.";
|
|
8324
8407
|
} catch (error2) {
|
|
@@ -8779,9 +8862,9 @@ function useUserService() {
|
|
|
8779
8862
|
const cacheKey = makeCacheKey14("users", { user: _id });
|
|
8780
8863
|
try {
|
|
8781
8864
|
useCache15().delCache(cacheKey).then(() => {
|
|
8782
|
-
|
|
8865
|
+
logger23.info(`Cache cleared for user: ${_id}`);
|
|
8783
8866
|
}).catch((error) => {
|
|
8784
|
-
|
|
8867
|
+
logger23.error(`Failed to clear cache for user: ${_id}`, error);
|
|
8785
8868
|
});
|
|
8786
8869
|
await _updateName({ _id, firstName, lastName }, session);
|
|
8787
8870
|
await updateMemberName(
|
|
@@ -9116,7 +9199,7 @@ function useVerificationService() {
|
|
|
9116
9199
|
email: MAILER_EMAIL,
|
|
9117
9200
|
password: MAILER_PASSWORD
|
|
9118
9201
|
};
|
|
9119
|
-
const mailer = new
|
|
9202
|
+
const mailer = new useMailer2(MailerConfig);
|
|
9120
9203
|
const {
|
|
9121
9204
|
add,
|
|
9122
9205
|
getById: _getById,
|
|
@@ -9150,8 +9233,8 @@ function useVerificationService() {
|
|
|
9150
9233
|
if (user) {
|
|
9151
9234
|
value.type = "member-invite";
|
|
9152
9235
|
const res2 = await add(value);
|
|
9153
|
-
const filePath2 =
|
|
9154
|
-
const emailContent2 =
|
|
9236
|
+
const filePath2 = getDirectory2(dir, "./public/handlebars/member-invite");
|
|
9237
|
+
const emailContent2 = compileHandlebar2({
|
|
9155
9238
|
context: {
|
|
9156
9239
|
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
9157
9240
|
link: `${APP_MAIN}/verify/member-invite/${res2}`,
|
|
@@ -9165,7 +9248,7 @@ function useVerificationService() {
|
|
|
9165
9248
|
html: emailContent2,
|
|
9166
9249
|
from: "GoWeekdays"
|
|
9167
9250
|
}).catch((error) => {
|
|
9168
|
-
|
|
9251
|
+
logger24.log({
|
|
9169
9252
|
level: "error",
|
|
9170
9253
|
message: `Error sending user invite email: ${error}`
|
|
9171
9254
|
});
|
|
@@ -9173,8 +9256,8 @@ function useVerificationService() {
|
|
|
9173
9256
|
return res2;
|
|
9174
9257
|
}
|
|
9175
9258
|
const res = await add(value);
|
|
9176
|
-
const filePath =
|
|
9177
|
-
const emailContent =
|
|
9259
|
+
const filePath = getDirectory2(dir, "./public/handlebars/user-invite");
|
|
9260
|
+
const emailContent = compileHandlebar2({
|
|
9178
9261
|
context: {
|
|
9179
9262
|
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
9180
9263
|
link: `${APP_MAIN}/verify/invitation/${res}`
|
|
@@ -9187,7 +9270,7 @@ function useVerificationService() {
|
|
|
9187
9270
|
html: emailContent,
|
|
9188
9271
|
from: "GoWeekdays"
|
|
9189
9272
|
}).catch((error) => {
|
|
9190
|
-
|
|
9273
|
+
logger24.log({
|
|
9191
9274
|
level: "error",
|
|
9192
9275
|
message: `Error sending user invite email: ${error}`
|
|
9193
9276
|
});
|
|
@@ -9208,8 +9291,8 @@ function useVerificationService() {
|
|
|
9208
9291
|
try {
|
|
9209
9292
|
const res = await add(value);
|
|
9210
9293
|
const dir = __dirname;
|
|
9211
|
-
const filePath =
|
|
9212
|
-
const emailContent =
|
|
9294
|
+
const filePath = getDirectory2(dir, "./public/handlebars/forget-password");
|
|
9295
|
+
const emailContent = compileHandlebar2({
|
|
9213
9296
|
context: {
|
|
9214
9297
|
validity: VERIFICATION_FORGET_PASSWORD_DURATION,
|
|
9215
9298
|
link: `${APP_MAIN}/reset-password/${res}`
|
|
@@ -9222,7 +9305,7 @@ function useVerificationService() {
|
|
|
9222
9305
|
from: "GoWeekdays",
|
|
9223
9306
|
html: emailContent
|
|
9224
9307
|
}).catch((error) => {
|
|
9225
|
-
|
|
9308
|
+
logger24.log({
|
|
9226
9309
|
level: "error",
|
|
9227
9310
|
message: `Error sending forget password email: ${error}`
|
|
9228
9311
|
});
|
|
@@ -9352,7 +9435,7 @@ function useVerificationService() {
|
|
|
9352
9435
|
return _id;
|
|
9353
9436
|
} catch (error) {
|
|
9354
9437
|
await session?.abortTransaction();
|
|
9355
|
-
|
|
9438
|
+
logger24.log({
|
|
9356
9439
|
level: "info",
|
|
9357
9440
|
message: `Error verifying user invitation: ${error}`
|
|
9358
9441
|
});
|
|
@@ -9398,8 +9481,8 @@ function useVerificationService() {
|
|
|
9398
9481
|
};
|
|
9399
9482
|
const res = await add(value);
|
|
9400
9483
|
const dir = __dirname;
|
|
9401
|
-
const filePath =
|
|
9402
|
-
const emailContent =
|
|
9484
|
+
const filePath = getDirectory2(dir, "./public/handlebars/sign-up");
|
|
9485
|
+
const emailContent = compileHandlebar2({
|
|
9403
9486
|
context: {
|
|
9404
9487
|
validity: "5 minutes",
|
|
9405
9488
|
link: `${APP_MAIN}/sign-up/${res}`
|
|
@@ -9412,7 +9495,7 @@ function useVerificationService() {
|
|
|
9412
9495
|
html: emailContent,
|
|
9413
9496
|
from: "GoWeekdays"
|
|
9414
9497
|
}).catch((error) => {
|
|
9415
|
-
|
|
9498
|
+
logger24.log({
|
|
9416
9499
|
level: "error",
|
|
9417
9500
|
message: `Error sending user invite email: ${error}`
|
|
9418
9501
|
});
|
|
@@ -9455,8 +9538,8 @@ function useVerificationService() {
|
|
|
9455
9538
|
if (user) {
|
|
9456
9539
|
verificationData.type = "member-invite";
|
|
9457
9540
|
const verificationId2 = await add(verificationData);
|
|
9458
|
-
const filePath2 =
|
|
9459
|
-
const emailContent2 =
|
|
9541
|
+
const filePath2 = getDirectory2(dir, "./public/handlebars/member-invite");
|
|
9542
|
+
const emailContent2 = compileHandlebar2({
|
|
9460
9543
|
context: {
|
|
9461
9544
|
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
9462
9545
|
link: `${APP_MAIN}/verify/member-invite/${verificationId2}`,
|
|
@@ -9470,7 +9553,7 @@ function useVerificationService() {
|
|
|
9470
9553
|
html: emailContent2,
|
|
9471
9554
|
from: "GoWeekdays"
|
|
9472
9555
|
}).catch((error2) => {
|
|
9473
|
-
|
|
9556
|
+
logger24.log({
|
|
9474
9557
|
level: "error",
|
|
9475
9558
|
message: `Error sending user invite email: ${error2}`
|
|
9476
9559
|
});
|
|
@@ -9478,8 +9561,8 @@ function useVerificationService() {
|
|
|
9478
9561
|
return verificationId2;
|
|
9479
9562
|
}
|
|
9480
9563
|
const verificationId = await add(verificationData);
|
|
9481
|
-
const filePath =
|
|
9482
|
-
const emailContent =
|
|
9564
|
+
const filePath = getDirectory2(dir, "./public/handlebars/user-invite");
|
|
9565
|
+
const emailContent = compileHandlebar2({
|
|
9483
9566
|
context: {
|
|
9484
9567
|
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
9485
9568
|
link: `${APP_MAIN}/verify/invitation/${verificationId}`
|
|
@@ -9492,7 +9575,7 @@ function useVerificationService() {
|
|
|
9492
9575
|
html: emailContent,
|
|
9493
9576
|
from: "GoWeekdays"
|
|
9494
9577
|
}).catch((error2) => {
|
|
9495
|
-
|
|
9578
|
+
logger24.log({
|
|
9496
9579
|
level: "error",
|
|
9497
9580
|
message: `Error sending user invite email: ${error2}`
|
|
9498
9581
|
});
|
|
@@ -9550,8 +9633,8 @@ function useVerificationService() {
|
|
|
9550
9633
|
};
|
|
9551
9634
|
const res = await add(value);
|
|
9552
9635
|
const dir = __dirname;
|
|
9553
|
-
const filePath =
|
|
9554
|
-
const emailContent =
|
|
9636
|
+
const filePath = getDirectory2(dir, "./public/handlebars/forget-password");
|
|
9637
|
+
const emailContent = compileHandlebar2({
|
|
9555
9638
|
context: {
|
|
9556
9639
|
validity: VERIFICATION_FORGET_PASSWORD_DURATION,
|
|
9557
9640
|
link: `${APP_MAIN}/reset-password/${res}`
|
|
@@ -9564,7 +9647,7 @@ function useVerificationService() {
|
|
|
9564
9647
|
from: "GoWeekdays",
|
|
9565
9648
|
html: emailContent
|
|
9566
9649
|
}).catch((error2) => {
|
|
9567
|
-
|
|
9650
|
+
logger24.log({
|
|
9568
9651
|
level: "error",
|
|
9569
9652
|
message: `Error sending forget password email: ${error2}`
|
|
9570
9653
|
});
|
|
@@ -9680,7 +9763,7 @@ function useAuthController() {
|
|
|
9680
9763
|
res.cookie("sid", session.sid, cookieOptions).cookie("user", session.user, cookieOptions).json({ message: "Login successful" });
|
|
9681
9764
|
return;
|
|
9682
9765
|
} catch (error2) {
|
|
9683
|
-
|
|
9766
|
+
logger25.log({
|
|
9684
9767
|
level: "error",
|
|
9685
9768
|
message: `Error during login: ${error2.message}`
|
|
9686
9769
|
});
|
|
@@ -9716,7 +9799,7 @@ function useAuthController() {
|
|
|
9716
9799
|
}
|
|
9717
9800
|
|
|
9718
9801
|
// src/resources/building/building.model.ts
|
|
9719
|
-
import { BadRequestError as BadRequestError46, logger as
|
|
9802
|
+
import { BadRequestError as BadRequestError46, logger as logger26 } from "@goweekdays/utils";
|
|
9720
9803
|
import Joi41 from "joi";
|
|
9721
9804
|
import { ObjectId as ObjectId22 } from "mongodb";
|
|
9722
9805
|
var schemaBuilding = Joi41.object({
|
|
@@ -9760,7 +9843,7 @@ var schemaUpdateOptions = Joi41.object({
|
|
|
9760
9843
|
function MBuilding(value) {
|
|
9761
9844
|
const { error } = schemaBuilding.validate(value);
|
|
9762
9845
|
if (error) {
|
|
9763
|
-
|
|
9846
|
+
logger26.info(`Building Model: ${error.message}`);
|
|
9764
9847
|
throw new BadRequestError46(error.message);
|
|
9765
9848
|
}
|
|
9766
9849
|
if (value._id && typeof value._id === "string") {
|
|
@@ -9790,7 +9873,7 @@ function MBuilding(value) {
|
|
|
9790
9873
|
function MBuildingUnit(value) {
|
|
9791
9874
|
const { error } = schemaBuildingUnit.validate(value);
|
|
9792
9875
|
if (error) {
|
|
9793
|
-
|
|
9876
|
+
logger26.info(`Building Unit Model: ${error.message}`);
|
|
9794
9877
|
throw new BadRequestError46(error.message);
|
|
9795
9878
|
}
|
|
9796
9879
|
if (value._id && typeof value._id === "string") {
|
|
@@ -9836,7 +9919,7 @@ import {
|
|
|
9836
9919
|
AppError as AppError23,
|
|
9837
9920
|
BadRequestError as BadRequestError47,
|
|
9838
9921
|
InternalServerError as InternalServerError26,
|
|
9839
|
-
logger as
|
|
9922
|
+
logger as logger27,
|
|
9840
9923
|
makeCacheKey as makeCacheKey15,
|
|
9841
9924
|
paginate as paginate13,
|
|
9842
9925
|
useAtlas as useAtlas20,
|
|
@@ -9869,7 +9952,7 @@ function useBuildingRepo() {
|
|
|
9869
9952
|
delCachedData();
|
|
9870
9953
|
return res.insertedId;
|
|
9871
9954
|
} catch (error) {
|
|
9872
|
-
|
|
9955
|
+
logger27.log({
|
|
9873
9956
|
level: "error",
|
|
9874
9957
|
message: error.message
|
|
9875
9958
|
});
|
|
@@ -9899,7 +9982,7 @@ function useBuildingRepo() {
|
|
|
9899
9982
|
delCachedData();
|
|
9900
9983
|
return res;
|
|
9901
9984
|
} catch (error) {
|
|
9902
|
-
|
|
9985
|
+
logger27.log({
|
|
9903
9986
|
level: "error",
|
|
9904
9987
|
message: error.message
|
|
9905
9988
|
});
|
|
@@ -9945,14 +10028,14 @@ function useBuildingRepo() {
|
|
|
9945
10028
|
if (status !== "active")
|
|
9946
10029
|
cacheParams.status = status;
|
|
9947
10030
|
const cacheKey = makeCacheKey15(namespace_collection, cacheParams);
|
|
9948
|
-
|
|
10031
|
+
logger27.log({
|
|
9949
10032
|
level: "info",
|
|
9950
10033
|
message: `Cache key for getAll buildings: ${cacheKey}`
|
|
9951
10034
|
});
|
|
9952
10035
|
try {
|
|
9953
10036
|
const cached = await getCache(cacheKey);
|
|
9954
10037
|
if (cached) {
|
|
9955
|
-
|
|
10038
|
+
logger27.log({
|
|
9956
10039
|
level: "info",
|
|
9957
10040
|
message: `Cache hit for getAll buildings: ${cacheKey}`
|
|
9958
10041
|
});
|
|
@@ -9967,19 +10050,19 @@ function useBuildingRepo() {
|
|
|
9967
10050
|
const length = await collection.countDocuments(query);
|
|
9968
10051
|
const data = paginate13(items, page, limit, length);
|
|
9969
10052
|
setCache(cacheKey, data, 600).then(() => {
|
|
9970
|
-
|
|
10053
|
+
logger27.log({
|
|
9971
10054
|
level: "info",
|
|
9972
10055
|
message: `Cache set for getAll buildings: ${cacheKey}`
|
|
9973
10056
|
});
|
|
9974
10057
|
}).catch((err) => {
|
|
9975
|
-
|
|
10058
|
+
logger27.log({
|
|
9976
10059
|
level: "error",
|
|
9977
10060
|
message: `Failed to set cache for getAll buildings: ${err.message}`
|
|
9978
10061
|
});
|
|
9979
10062
|
});
|
|
9980
10063
|
return data;
|
|
9981
10064
|
} catch (error) {
|
|
9982
|
-
|
|
10065
|
+
logger27.log({ level: "error", message: `${error}` });
|
|
9983
10066
|
throw error;
|
|
9984
10067
|
}
|
|
9985
10068
|
}
|
|
@@ -9993,7 +10076,7 @@ function useBuildingRepo() {
|
|
|
9993
10076
|
try {
|
|
9994
10077
|
const cached = await getCache(cacheKey);
|
|
9995
10078
|
if (cached) {
|
|
9996
|
-
|
|
10079
|
+
logger27.log({
|
|
9997
10080
|
level: "info",
|
|
9998
10081
|
message: `Cache hit for getById building: ${cacheKey}`
|
|
9999
10082
|
});
|
|
@@ -10003,12 +10086,12 @@ function useBuildingRepo() {
|
|
|
10003
10086
|
_id
|
|
10004
10087
|
});
|
|
10005
10088
|
setCache(cacheKey, result, 300).then(() => {
|
|
10006
|
-
|
|
10089
|
+
logger27.log({
|
|
10007
10090
|
level: "info",
|
|
10008
10091
|
message: `Cache set for building by id: ${cacheKey}`
|
|
10009
10092
|
});
|
|
10010
10093
|
}).catch((err) => {
|
|
10011
|
-
|
|
10094
|
+
logger27.log({
|
|
10012
10095
|
level: "error",
|
|
10013
10096
|
message: `Failed to set cache for building by id: ${err.message}`
|
|
10014
10097
|
});
|
|
@@ -10036,7 +10119,7 @@ function useBuildingRepo() {
|
|
|
10036
10119
|
delCachedData();
|
|
10037
10120
|
return res;
|
|
10038
10121
|
} catch (error) {
|
|
10039
|
-
|
|
10122
|
+
logger27.log({
|
|
10040
10123
|
level: "error",
|
|
10041
10124
|
message: error.message
|
|
10042
10125
|
});
|
|
@@ -10049,12 +10132,12 @@ function useBuildingRepo() {
|
|
|
10049
10132
|
}
|
|
10050
10133
|
function delCachedData() {
|
|
10051
10134
|
delNamespace().then(() => {
|
|
10052
|
-
|
|
10135
|
+
logger27.log({
|
|
10053
10136
|
level: "info",
|
|
10054
10137
|
message: `Cache namespace cleared for ${namespace_collection}`
|
|
10055
10138
|
});
|
|
10056
10139
|
}).catch((err) => {
|
|
10057
|
-
|
|
10140
|
+
logger27.log({
|
|
10058
10141
|
level: "error",
|
|
10059
10142
|
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
10060
10143
|
});
|
|
@@ -10078,7 +10161,7 @@ import {
|
|
|
10078
10161
|
AppError as AppError24,
|
|
10079
10162
|
BadRequestError as BadRequestError48,
|
|
10080
10163
|
InternalServerError as InternalServerError27,
|
|
10081
|
-
logger as
|
|
10164
|
+
logger as logger28,
|
|
10082
10165
|
makeCacheKey as makeCacheKey16,
|
|
10083
10166
|
paginate as paginate14,
|
|
10084
10167
|
useAtlas as useAtlas21,
|
|
@@ -10120,12 +10203,12 @@ function useBuildingUnitRepo() {
|
|
|
10120
10203
|
}
|
|
10121
10204
|
function delCachedData() {
|
|
10122
10205
|
delNamespace().then(() => {
|
|
10123
|
-
|
|
10206
|
+
logger28.log({
|
|
10124
10207
|
level: "info",
|
|
10125
10208
|
message: `Cache namespace cleared for ${namespace_collection}`
|
|
10126
10209
|
});
|
|
10127
10210
|
}).catch((err) => {
|
|
10128
|
-
|
|
10211
|
+
logger28.log({
|
|
10129
10212
|
level: "error",
|
|
10130
10213
|
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
10131
10214
|
});
|
|
@@ -10138,7 +10221,7 @@ function useBuildingUnitRepo() {
|
|
|
10138
10221
|
delCachedData();
|
|
10139
10222
|
return res.insertedId;
|
|
10140
10223
|
} catch (error) {
|
|
10141
|
-
|
|
10224
|
+
logger28.log({
|
|
10142
10225
|
level: "error",
|
|
10143
10226
|
message: error.message
|
|
10144
10227
|
});
|
|
@@ -10168,7 +10251,7 @@ function useBuildingUnitRepo() {
|
|
|
10168
10251
|
delCachedData();
|
|
10169
10252
|
return res;
|
|
10170
10253
|
} catch (error2) {
|
|
10171
|
-
|
|
10254
|
+
logger28.log({
|
|
10172
10255
|
level: "error",
|
|
10173
10256
|
message: error2.message
|
|
10174
10257
|
});
|
|
@@ -10198,7 +10281,7 @@ function useBuildingUnitRepo() {
|
|
|
10198
10281
|
delCachedData();
|
|
10199
10282
|
return res;
|
|
10200
10283
|
} catch (error2) {
|
|
10201
|
-
|
|
10284
|
+
logger28.log({
|
|
10202
10285
|
level: "error",
|
|
10203
10286
|
message: error2.message
|
|
10204
10287
|
});
|
|
@@ -10255,14 +10338,14 @@ function useBuildingUnitRepo() {
|
|
|
10255
10338
|
if (status !== "active")
|
|
10256
10339
|
cacheParams.status = status;
|
|
10257
10340
|
const cacheKey = makeCacheKey16(namespace_collection, cacheParams);
|
|
10258
|
-
|
|
10341
|
+
logger28.log({
|
|
10259
10342
|
level: "info",
|
|
10260
10343
|
message: `Cache key for getAll building units: ${cacheKey}`
|
|
10261
10344
|
});
|
|
10262
10345
|
try {
|
|
10263
10346
|
const cached = await getCache(cacheKey);
|
|
10264
10347
|
if (cached) {
|
|
10265
|
-
|
|
10348
|
+
logger28.log({
|
|
10266
10349
|
level: "info",
|
|
10267
10350
|
message: `Cache hit for getAll building units: ${cacheKey}`
|
|
10268
10351
|
});
|
|
@@ -10277,19 +10360,19 @@ function useBuildingUnitRepo() {
|
|
|
10277
10360
|
const length = await collection.countDocuments(query);
|
|
10278
10361
|
const data = paginate14(items, page, limit, length);
|
|
10279
10362
|
setCache(cacheKey, data, 600).then(() => {
|
|
10280
|
-
|
|
10363
|
+
logger28.log({
|
|
10281
10364
|
level: "info",
|
|
10282
10365
|
message: `Cache set for getAll building units: ${cacheKey}`
|
|
10283
10366
|
});
|
|
10284
10367
|
}).catch((err) => {
|
|
10285
|
-
|
|
10368
|
+
logger28.log({
|
|
10286
10369
|
level: "error",
|
|
10287
10370
|
message: `Failed to set cache for getAll building units: ${err.message}`
|
|
10288
10371
|
});
|
|
10289
10372
|
});
|
|
10290
10373
|
return data;
|
|
10291
10374
|
} catch (error) {
|
|
10292
|
-
|
|
10375
|
+
logger28.log({ level: "error", message: `${error}` });
|
|
10293
10376
|
throw error;
|
|
10294
10377
|
}
|
|
10295
10378
|
}
|
|
@@ -10303,7 +10386,7 @@ function useBuildingUnitRepo() {
|
|
|
10303
10386
|
try {
|
|
10304
10387
|
const cached = await getCache(cacheKey);
|
|
10305
10388
|
if (cached) {
|
|
10306
|
-
|
|
10389
|
+
logger28.log({
|
|
10307
10390
|
level: "info",
|
|
10308
10391
|
message: `Cache hit for getById building unit: ${cacheKey}`
|
|
10309
10392
|
});
|
|
@@ -10317,12 +10400,12 @@ function useBuildingUnitRepo() {
|
|
|
10317
10400
|
throw new BadRequestError48("Building unit not found.");
|
|
10318
10401
|
}
|
|
10319
10402
|
setCache(cacheKey, result, 300).then(() => {
|
|
10320
|
-
|
|
10403
|
+
logger28.log({
|
|
10321
10404
|
level: "info",
|
|
10322
10405
|
message: `Cache set for building unit by id: ${cacheKey}`
|
|
10323
10406
|
});
|
|
10324
10407
|
}).catch((err) => {
|
|
10325
|
-
|
|
10408
|
+
logger28.log({
|
|
10326
10409
|
level: "error",
|
|
10327
10410
|
message: `Failed to set cache for building unit by id: ${err.message}`
|
|
10328
10411
|
});
|
|
@@ -10349,7 +10432,7 @@ function useBuildingUnitRepo() {
|
|
|
10349
10432
|
try {
|
|
10350
10433
|
const cached = await getCache(cacheKey);
|
|
10351
10434
|
if (cached) {
|
|
10352
|
-
|
|
10435
|
+
logger28.log({
|
|
10353
10436
|
level: "info",
|
|
10354
10437
|
message: `Cache hit for getById building unit: ${cacheKey}`
|
|
10355
10438
|
});
|
|
@@ -10361,12 +10444,12 @@ function useBuildingUnitRepo() {
|
|
|
10361
10444
|
status: "active"
|
|
10362
10445
|
});
|
|
10363
10446
|
setCache(cacheKey, result, 300).then(() => {
|
|
10364
|
-
|
|
10447
|
+
logger28.log({
|
|
10365
10448
|
level: "info",
|
|
10366
10449
|
message: `Cache set for building unit by id: ${cacheKey}`
|
|
10367
10450
|
});
|
|
10368
10451
|
}).catch((err) => {
|
|
10369
|
-
|
|
10452
|
+
logger28.log({
|
|
10370
10453
|
level: "error",
|
|
10371
10454
|
message: `Failed to set cache for building unit by id: ${err.message}`
|
|
10372
10455
|
});
|
|
@@ -10392,7 +10475,7 @@ function useBuildingUnitRepo() {
|
|
|
10392
10475
|
try {
|
|
10393
10476
|
const cached = await getCache(cacheKey);
|
|
10394
10477
|
if (cached) {
|
|
10395
|
-
|
|
10478
|
+
logger28.log({
|
|
10396
10479
|
level: "info",
|
|
10397
10480
|
message: `Cache hit for getById building unit: ${cacheKey}`
|
|
10398
10481
|
});
|
|
@@ -10403,12 +10486,12 @@ function useBuildingUnitRepo() {
|
|
|
10403
10486
|
status: "active"
|
|
10404
10487
|
});
|
|
10405
10488
|
setCache(cacheKey, result, 300).then(() => {
|
|
10406
|
-
|
|
10489
|
+
logger28.log({
|
|
10407
10490
|
level: "info",
|
|
10408
10491
|
message: `Cache set for building unit by id: ${cacheKey}`
|
|
10409
10492
|
});
|
|
10410
10493
|
}).catch((err) => {
|
|
10411
|
-
|
|
10494
|
+
logger28.log({
|
|
10412
10495
|
level: "error",
|
|
10413
10496
|
message: `Failed to set cache for building unit by id: ${err.message}`
|
|
10414
10497
|
});
|
|
@@ -10437,7 +10520,7 @@ function useBuildingUnitRepo() {
|
|
|
10437
10520
|
delCachedData();
|
|
10438
10521
|
return "Room/Facility deleted successfully.";
|
|
10439
10522
|
} catch (error) {
|
|
10440
|
-
|
|
10523
|
+
logger28.log({
|
|
10441
10524
|
level: "error",
|
|
10442
10525
|
message: error.message
|
|
10443
10526
|
});
|
|
@@ -10520,7 +10603,7 @@ function useBuildingService() {
|
|
|
10520
10603
|
}
|
|
10521
10604
|
|
|
10522
10605
|
// src/resources/building/building.controller.ts
|
|
10523
|
-
import { BadRequestError as BadRequestError50, logger as
|
|
10606
|
+
import { BadRequestError as BadRequestError50, logger as logger29 } from "@goweekdays/utils";
|
|
10524
10607
|
import Joi42 from "joi";
|
|
10525
10608
|
function useBuildingController() {
|
|
10526
10609
|
const { getAll: _getAll, getById: _getById, add: _add } = useBuildingRepo();
|
|
@@ -10537,7 +10620,7 @@ function useBuildingController() {
|
|
|
10537
10620
|
const { error } = validation.validate(value);
|
|
10538
10621
|
if (error) {
|
|
10539
10622
|
next(new BadRequestError50(error.message));
|
|
10540
|
-
|
|
10623
|
+
logger29.info(`Controller: ${error.message}`);
|
|
10541
10624
|
return;
|
|
10542
10625
|
}
|
|
10543
10626
|
try {
|
|
@@ -10562,7 +10645,7 @@ function useBuildingController() {
|
|
|
10562
10645
|
const { error } = validation.validate({ id, value });
|
|
10563
10646
|
if (error) {
|
|
10564
10647
|
next(new BadRequestError50(error.message));
|
|
10565
|
-
|
|
10648
|
+
logger29.info(`Controller: ${error.message}`);
|
|
10566
10649
|
return;
|
|
10567
10650
|
}
|
|
10568
10651
|
try {
|
|
@@ -10892,7 +10975,7 @@ function useCounterModel(db) {
|
|
|
10892
10975
|
}
|
|
10893
10976
|
|
|
10894
10977
|
// src/resources/counter/counter.repository.ts
|
|
10895
|
-
import { useAtlas as useAtlas24, useCache as useCache18, makeCacheKey as makeCacheKey17, logger as
|
|
10978
|
+
import { useAtlas as useAtlas24, useCache as useCache18, makeCacheKey as makeCacheKey17, logger as logger30 } from "@goweekdays/utils";
|
|
10896
10979
|
function useCounterRepo() {
|
|
10897
10980
|
const db = useAtlas24.getDb();
|
|
10898
10981
|
if (!db) {
|
|
@@ -10903,12 +10986,12 @@ function useCounterRepo() {
|
|
|
10903
10986
|
const { getCache, setCache, delNamespace } = useCache18(namespace_collection);
|
|
10904
10987
|
function delCachedData() {
|
|
10905
10988
|
delNamespace().then(() => {
|
|
10906
|
-
|
|
10989
|
+
logger30.log({
|
|
10907
10990
|
level: "info",
|
|
10908
10991
|
message: `Cache namespace cleared for ${namespace_collection}`
|
|
10909
10992
|
});
|
|
10910
10993
|
}).catch((err) => {
|
|
10911
|
-
|
|
10994
|
+
logger30.log({
|
|
10912
10995
|
level: "error",
|
|
10913
10996
|
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
10914
10997
|
});
|
|
@@ -10956,7 +11039,7 @@ function useCounterRepo() {
|
|
|
10956
11039
|
try {
|
|
10957
11040
|
const cached = await getCache(cacheKey);
|
|
10958
11041
|
if (cached) {
|
|
10959
|
-
|
|
11042
|
+
logger30.log({
|
|
10960
11043
|
level: "info",
|
|
10961
11044
|
message: `Cache hit for getByType counter: ${cacheKey}`
|
|
10962
11045
|
});
|
|
@@ -10965,12 +11048,12 @@ function useCounterRepo() {
|
|
|
10965
11048
|
const data = await collection.findOne({ type });
|
|
10966
11049
|
if (data) {
|
|
10967
11050
|
setCache(cacheKey, data, 300).then(() => {
|
|
10968
|
-
|
|
11051
|
+
logger30.log({
|
|
10969
11052
|
level: "info",
|
|
10970
11053
|
message: `Cache set for counter by type: ${cacheKey}`
|
|
10971
11054
|
});
|
|
10972
11055
|
}).catch((err) => {
|
|
10973
|
-
|
|
11056
|
+
logger30.log({
|
|
10974
11057
|
level: "error",
|
|
10975
11058
|
message: `Failed to set cache for counter by type: ${err.message}`
|
|
10976
11059
|
});
|
|
@@ -10990,7 +11073,7 @@ function useCounterRepo() {
|
|
|
10990
11073
|
}
|
|
10991
11074
|
|
|
10992
11075
|
// src/resources/file/file.service.ts
|
|
10993
|
-
import { logger as
|
|
11076
|
+
import { logger as logger31, useS3 as useS32, useAtlas as useAtlas25 } from "@goweekdays/utils";
|
|
10994
11077
|
import cron2 from "node-cron";
|
|
10995
11078
|
import * as fs from "fs";
|
|
10996
11079
|
function useFileService() {
|
|
@@ -11063,12 +11146,12 @@ function useFileService() {
|
|
|
11063
11146
|
const file = files[index];
|
|
11064
11147
|
try {
|
|
11065
11148
|
await deleteFile(file._id.toString());
|
|
11066
|
-
await
|
|
11149
|
+
await logger31.log({
|
|
11067
11150
|
level: "info",
|
|
11068
11151
|
message: "Successfully deleted draft files."
|
|
11069
11152
|
});
|
|
11070
11153
|
} catch (error) {
|
|
11071
|
-
|
|
11154
|
+
logger31.log({
|
|
11072
11155
|
level: "info",
|
|
11073
11156
|
message: "Successfully deleted draft files."
|
|
11074
11157
|
});
|
|
@@ -11139,8 +11222,7 @@ function useFileController() {
|
|
|
11139
11222
|
import Joi45 from "joi";
|
|
11140
11223
|
var schemaPromo = Joi45.object({
|
|
11141
11224
|
code: Joi45.string().min(3).max(50).required(),
|
|
11142
|
-
|
|
11143
|
-
type: Joi45.string().valid("flat", "fixed", "tiered").required(),
|
|
11225
|
+
type: Joi45.string().valid("flat", "fixed", "volume").required(),
|
|
11144
11226
|
flatRate: Joi45.number().positive().when("type", {
|
|
11145
11227
|
is: "flat",
|
|
11146
11228
|
then: Joi45.required(),
|
|
@@ -11162,9 +11244,12 @@ var schemaPromo = Joi45.object({
|
|
|
11162
11244
|
then: Joi45.required(),
|
|
11163
11245
|
otherwise: Joi45.forbidden()
|
|
11164
11246
|
}),
|
|
11165
|
-
currency: Joi45.string().length(3).required(),
|
|
11166
|
-
startDate: Joi45.date().
|
|
11167
|
-
endDate: Joi45.date().greater(Joi45.ref("startDate")).optional().allow(null, "")
|
|
11247
|
+
currency: Joi45.string().length(3).allow("PHP").required(),
|
|
11248
|
+
startDate: Joi45.date().optional().allow(null, ""),
|
|
11249
|
+
endDate: Joi45.date().greater(Joi45.ref("startDate")).optional().allow(null, ""),
|
|
11250
|
+
apps: Joi45.array().items(Joi45.string()).optional().allow(null),
|
|
11251
|
+
seats: Joi45.number().integer().min(0).optional().allow(null, 0),
|
|
11252
|
+
usage: Joi45.number().integer().min(0).optional().allow(null, 0)
|
|
11168
11253
|
});
|
|
11169
11254
|
function modelPromo(data) {
|
|
11170
11255
|
const { error } = schemaPromo.validate(data);
|
|
@@ -11174,17 +11259,17 @@ function modelPromo(data) {
|
|
|
11174
11259
|
return {
|
|
11175
11260
|
_id: data._id,
|
|
11176
11261
|
code: data.code,
|
|
11177
|
-
description: data.description ?? "",
|
|
11178
11262
|
type: data.type,
|
|
11179
11263
|
flatRate: data.flatRate ?? 0,
|
|
11180
11264
|
fixedRate: data.fixedRate ?? 0,
|
|
11181
11265
|
tiers: data.tiers ?? [],
|
|
11182
11266
|
currency: data.currency,
|
|
11183
|
-
startDate: data.startDate ??
|
|
11267
|
+
startDate: data.startDate ?? "",
|
|
11184
11268
|
endDate: data.endDate ?? "",
|
|
11185
|
-
|
|
11269
|
+
seats: data.seats ?? 0,
|
|
11270
|
+
usage: data.usage ?? 0,
|
|
11271
|
+
apps: data.apps ?? [],
|
|
11186
11272
|
status: data.status ?? "active",
|
|
11187
|
-
assignedAt: data.assignedAt ?? "",
|
|
11188
11273
|
createdAt: data.createdAt ?? /* @__PURE__ */ new Date(),
|
|
11189
11274
|
updatedAt: data.updatedAt ?? "",
|
|
11190
11275
|
deletedAt: data.deletedAt ?? ""
|
|
@@ -11196,7 +11281,7 @@ import {
|
|
|
11196
11281
|
AppError as AppError26,
|
|
11197
11282
|
BadRequestError as BadRequestError54,
|
|
11198
11283
|
InternalServerError as InternalServerError29,
|
|
11199
|
-
logger as
|
|
11284
|
+
logger as logger32,
|
|
11200
11285
|
makeCacheKey as makeCacheKey18,
|
|
11201
11286
|
paginate as paginate15,
|
|
11202
11287
|
useAtlas as useAtlas26,
|
|
@@ -11209,17 +11294,17 @@ function usePromoRepo() {
|
|
|
11209
11294
|
if (!db) {
|
|
11210
11295
|
throw new InternalServerError29("Unable to connect to server.");
|
|
11211
11296
|
}
|
|
11212
|
-
const namespace_collection = "
|
|
11297
|
+
const namespace_collection = "promos";
|
|
11213
11298
|
const collection = db.collection(namespace_collection);
|
|
11214
11299
|
const { getCache, setCache, delNamespace } = useCache19(namespace_collection);
|
|
11215
11300
|
function delCachedData() {
|
|
11216
11301
|
delNamespace().then(() => {
|
|
11217
|
-
|
|
11302
|
+
logger32.log({
|
|
11218
11303
|
level: "info",
|
|
11219
11304
|
message: `Cache namespace cleared for ${namespace_collection}`
|
|
11220
11305
|
});
|
|
11221
11306
|
}).catch((err) => {
|
|
11222
|
-
|
|
11307
|
+
logger32.log({
|
|
11223
11308
|
level: "error",
|
|
11224
11309
|
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
11225
11310
|
});
|
|
@@ -11260,7 +11345,7 @@ function usePromoRepo() {
|
|
|
11260
11345
|
search = "",
|
|
11261
11346
|
status = "active"
|
|
11262
11347
|
} = {}) {
|
|
11263
|
-
page = page
|
|
11348
|
+
page = page > 0 ? page - 1 : page;
|
|
11264
11349
|
const query = { status };
|
|
11265
11350
|
const cacheKeyOptions = {
|
|
11266
11351
|
page,
|
|
@@ -11286,12 +11371,12 @@ function usePromoRepo() {
|
|
|
11286
11371
|
const length = await collection.countDocuments(query);
|
|
11287
11372
|
const data = paginate15(items, page, limit, length);
|
|
11288
11373
|
setCache(cacheKey, data).then(() => {
|
|
11289
|
-
|
|
11374
|
+
logger32.log({
|
|
11290
11375
|
level: "info",
|
|
11291
11376
|
message: `Cache set for getAll promo: ${cacheKey}`
|
|
11292
11377
|
});
|
|
11293
11378
|
}).catch((err) => {
|
|
11294
|
-
|
|
11379
|
+
logger32.log({
|
|
11295
11380
|
level: "error",
|
|
11296
11381
|
message: `Failed to set cache for getAll promo: ${err.message}`
|
|
11297
11382
|
});
|
|
@@ -11320,12 +11405,12 @@ function usePromoRepo() {
|
|
|
11320
11405
|
status: { $ne: "deleted" }
|
|
11321
11406
|
});
|
|
11322
11407
|
setCache(cacheKey, data).then(() => {
|
|
11323
|
-
|
|
11408
|
+
logger32.log({
|
|
11324
11409
|
level: "info",
|
|
11325
11410
|
message: `Cache set for getByCode promo: ${cacheKey}`
|
|
11326
11411
|
});
|
|
11327
11412
|
}).catch((err) => {
|
|
11328
|
-
|
|
11413
|
+
logger32.log({
|
|
11329
11414
|
level: "error",
|
|
11330
11415
|
message: `Failed to set cache for getByCode promo: ${err.message}`
|
|
11331
11416
|
});
|
|
@@ -11359,12 +11444,12 @@ function usePromoRepo() {
|
|
|
11359
11444
|
status: { $ne: "deleted" }
|
|
11360
11445
|
});
|
|
11361
11446
|
setCache(cacheKey, data).then(() => {
|
|
11362
|
-
|
|
11447
|
+
logger32.log({
|
|
11363
11448
|
level: "info",
|
|
11364
11449
|
message: `Cache set for getById promo: ${cacheKey}`
|
|
11365
11450
|
});
|
|
11366
11451
|
}).catch((err) => {
|
|
11367
|
-
|
|
11452
|
+
logger32.log({
|
|
11368
11453
|
level: "error",
|
|
11369
11454
|
message: `Failed to set cache for getById promo: ${err.message}`
|
|
11370
11455
|
});
|
|
@@ -11374,6 +11459,31 @@ function usePromoRepo() {
|
|
|
11374
11459
|
throw new InternalServerError29("Failed to get promo.");
|
|
11375
11460
|
}
|
|
11376
11461
|
}
|
|
11462
|
+
async function updateById(_id, options) {
|
|
11463
|
+
const { error: errorId } = Joi46.string().hex().length(24).required().validate(_id);
|
|
11464
|
+
if (errorId) {
|
|
11465
|
+
throw new Error(`Invalid promo ID: ${errorId.message}`);
|
|
11466
|
+
}
|
|
11467
|
+
const { error } = schemaPromo.validate(options);
|
|
11468
|
+
if (error) {
|
|
11469
|
+
throw new Error(`Invalid promo ID: ${error.message}`);
|
|
11470
|
+
}
|
|
11471
|
+
try {
|
|
11472
|
+
_id = new ObjectId26(_id);
|
|
11473
|
+
} catch (error2) {
|
|
11474
|
+
throw new BadRequestError54("Invalid promo ID.");
|
|
11475
|
+
}
|
|
11476
|
+
try {
|
|
11477
|
+
await collection.updateOne(
|
|
11478
|
+
{ _id },
|
|
11479
|
+
{ $set: { ...options, updatedAt: /* @__PURE__ */ new Date() } }
|
|
11480
|
+
);
|
|
11481
|
+
delCachedData();
|
|
11482
|
+
return "Successfully updated promo.";
|
|
11483
|
+
} catch (error2) {
|
|
11484
|
+
throw new InternalServerError29("Failed to update promo.");
|
|
11485
|
+
}
|
|
11486
|
+
}
|
|
11377
11487
|
async function deleteById(_id) {
|
|
11378
11488
|
const { error } = Joi46.string().hex().length(24).required().validate(_id);
|
|
11379
11489
|
if (error) {
|
|
@@ -11407,99 +11517,94 @@ function usePromoRepo() {
|
|
|
11407
11517
|
getAll,
|
|
11408
11518
|
getByCode,
|
|
11409
11519
|
getById,
|
|
11520
|
+
updateById,
|
|
11410
11521
|
deleteById
|
|
11411
11522
|
};
|
|
11412
11523
|
}
|
|
11413
11524
|
|
|
11414
|
-
// src/resources/
|
|
11525
|
+
// src/resources/promo/promo.controller.ts
|
|
11526
|
+
import Joi49 from "joi";
|
|
11527
|
+
import { BadRequestError as BadRequestError58 } from "@goweekdays/utils";
|
|
11528
|
+
|
|
11529
|
+
// src/resources/promo/promo.service.ts
|
|
11530
|
+
import { AppError as AppError28, BadRequestError as BadRequestError57 } from "@goweekdays/utils";
|
|
11531
|
+
|
|
11532
|
+
// src/resources/promo/promo.usage.repository.ts
|
|
11533
|
+
import {
|
|
11534
|
+
AppError as AppError27,
|
|
11535
|
+
BadRequestError as BadRequestError56,
|
|
11536
|
+
InternalServerError as InternalServerError30,
|
|
11537
|
+
logger as logger33,
|
|
11538
|
+
makeCacheKey as makeCacheKey19,
|
|
11539
|
+
paginate as paginate16,
|
|
11540
|
+
useAtlas as useAtlas27,
|
|
11541
|
+
useCache as useCache20
|
|
11542
|
+
} from "@goweekdays/utils";
|
|
11543
|
+
|
|
11544
|
+
// src/resources/promo/promo.usage.model.ts
|
|
11415
11545
|
import { BadRequestError as BadRequestError55 } from "@goweekdays/utils";
|
|
11416
11546
|
import Joi47 from "joi";
|
|
11417
11547
|
import { ObjectId as ObjectId27 } from "mongodb";
|
|
11418
|
-
var
|
|
11419
|
-
|
|
11420
|
-
org: Joi47.string().hex().required(),
|
|
11421
|
-
|
|
11422
|
-
setup: Joi47.string().trim().required(),
|
|
11423
|
-
location: Joi47.string().trim().required(),
|
|
11424
|
-
type: Joi47.string().trim().required(),
|
|
11425
|
-
description: Joi47.string().trim().required(),
|
|
11426
|
-
status: Joi47.string().trim().optional().allow("", null),
|
|
11427
|
-
createdAt: Joi47.date().optional(),
|
|
11428
|
-
updatedAt: Joi47.date().optional(),
|
|
11429
|
-
deletedAt: Joi47.date().optional()
|
|
11430
|
-
});
|
|
11431
|
-
var schemaJobPostUpdate = Joi47.object({
|
|
11432
|
-
_id: Joi47.string().hex().required(),
|
|
11433
|
-
title: Joi47.string().trim().required(),
|
|
11434
|
-
setup: Joi47.string().trim().required(),
|
|
11435
|
-
location: Joi47.string().trim().required(),
|
|
11436
|
-
type: Joi47.string().trim().required(),
|
|
11437
|
-
description: Joi47.string().trim().required()
|
|
11548
|
+
var schemaPromoUsage = Joi47.object({
|
|
11549
|
+
promo: Joi47.string().hex().length(24).required(),
|
|
11550
|
+
org: Joi47.string().hex().length(24).required(),
|
|
11551
|
+
usedBy: Joi47.string().email().required()
|
|
11438
11552
|
});
|
|
11439
|
-
function
|
|
11440
|
-
const { error } =
|
|
11553
|
+
function modelPromoUsage(value) {
|
|
11554
|
+
const { error } = schemaPromoUsage.validate(value);
|
|
11441
11555
|
if (error) {
|
|
11442
|
-
throw new
|
|
11556
|
+
throw new Error(`Invalid Promo Usage model: ${error.message}`);
|
|
11443
11557
|
}
|
|
11444
|
-
if (
|
|
11558
|
+
if (value._id && typeof value._id === "string") {
|
|
11445
11559
|
try {
|
|
11446
|
-
value._id = new ObjectId27();
|
|
11560
|
+
value._id = new ObjectId27(value._id);
|
|
11447
11561
|
} catch (error2) {
|
|
11448
|
-
throw new BadRequestError55("Invalid
|
|
11562
|
+
throw new BadRequestError55("Invalid Promo Usage _id");
|
|
11449
11563
|
}
|
|
11450
11564
|
}
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11565
|
+
if (typeof value.promo === "string") {
|
|
11566
|
+
try {
|
|
11567
|
+
value.promo = new ObjectId27(value.promo);
|
|
11568
|
+
} catch (error2) {
|
|
11569
|
+
throw new BadRequestError55("Invalid Promo Usage promo");
|
|
11570
|
+
}
|
|
11571
|
+
}
|
|
11572
|
+
if (typeof value.org === "string") {
|
|
11573
|
+
try {
|
|
11574
|
+
value.org = new ObjectId27(value.org);
|
|
11575
|
+
} catch (error2) {
|
|
11576
|
+
throw new BadRequestError55("Invalid Promo Usage org");
|
|
11577
|
+
}
|
|
11455
11578
|
}
|
|
11456
11579
|
return {
|
|
11457
11580
|
_id: value._id,
|
|
11581
|
+
promo: value.promo,
|
|
11458
11582
|
org: value.org,
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
type: value.type,
|
|
11463
|
-
description: value.description,
|
|
11464
|
-
status: value.status ?? "draft",
|
|
11465
|
-
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
11466
|
-
updatedAt: value.updatedAt,
|
|
11467
|
-
deletedAt: value.deletedAt
|
|
11583
|
+
usedBy: value.usedBy,
|
|
11584
|
+
createdAt: value.createdAt ? new Date(value.createdAt) : /* @__PURE__ */ new Date(),
|
|
11585
|
+
updatedAt: value.updatedAt ?? ""
|
|
11468
11586
|
};
|
|
11469
11587
|
}
|
|
11470
11588
|
|
|
11471
|
-
// src/resources/
|
|
11472
|
-
import
|
|
11473
|
-
import { BadRequestError as BadRequestError58, logger as logger33 } from "@goweekdays/utils";
|
|
11474
|
-
|
|
11475
|
-
// src/resources/job-post/job.post.repository.ts
|
|
11476
|
-
import {
|
|
11477
|
-
AppError as AppError27,
|
|
11478
|
-
BadRequestError as BadRequestError56,
|
|
11479
|
-
useAtlas as useAtlas27,
|
|
11480
|
-
useCache as useCache20,
|
|
11481
|
-
makeCacheKey as makeCacheKey19,
|
|
11482
|
-
paginate as paginate16,
|
|
11483
|
-
logger as logger32,
|
|
11484
|
-
InternalServerError as InternalServerError30
|
|
11485
|
-
} from "@goweekdays/utils";
|
|
11589
|
+
// src/resources/promo/promo.usage.repository.ts
|
|
11590
|
+
import Joi48 from "joi";
|
|
11486
11591
|
import { ObjectId as ObjectId28 } from "mongodb";
|
|
11487
|
-
function
|
|
11592
|
+
function usePromoUsageRepo() {
|
|
11488
11593
|
const db = useAtlas27.getDb();
|
|
11489
11594
|
if (!db) {
|
|
11490
|
-
throw new
|
|
11595
|
+
throw new InternalServerError30("Unable to connect to server.");
|
|
11491
11596
|
}
|
|
11492
|
-
const namespace_collection = "
|
|
11597
|
+
const namespace_collection = "promo.usages";
|
|
11493
11598
|
const collection = db.collection(namespace_collection);
|
|
11494
11599
|
const { getCache, setCache, delNamespace } = useCache20(namespace_collection);
|
|
11495
11600
|
function delCachedData() {
|
|
11496
11601
|
delNamespace().then(() => {
|
|
11497
|
-
|
|
11602
|
+
logger33.log({
|
|
11498
11603
|
level: "info",
|
|
11499
11604
|
message: `Cache namespace cleared for ${namespace_collection}`
|
|
11500
11605
|
});
|
|
11501
11606
|
}).catch((err) => {
|
|
11502
|
-
|
|
11607
|
+
logger33.log({
|
|
11503
11608
|
level: "error",
|
|
11504
11609
|
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
11505
11610
|
});
|
|
@@ -11508,76 +11613,605 @@ function useJobPostRepo() {
|
|
|
11508
11613
|
async function createIndexes() {
|
|
11509
11614
|
try {
|
|
11510
11615
|
await collection.createIndexes([
|
|
11511
|
-
{ key: { title: 1 } },
|
|
11512
|
-
{ key: { setup: 1 } },
|
|
11513
|
-
{ key: { location: 1 } },
|
|
11514
|
-
{ key: { type: 1 } },
|
|
11515
11616
|
{
|
|
11516
|
-
key: {
|
|
11517
|
-
|
|
11518
|
-
|
|
11519
|
-
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
name: "jobpost_text_search"
|
|
11617
|
+
key: { promo: 1, org: 1 },
|
|
11618
|
+
name: "promo_org_index"
|
|
11619
|
+
},
|
|
11620
|
+
{
|
|
11621
|
+
key: { usedBy: 1 },
|
|
11622
|
+
name: "usedBy_index"
|
|
11523
11623
|
}
|
|
11524
11624
|
]);
|
|
11525
|
-
return "Successfully created job post indexes.";
|
|
11526
11625
|
} catch (error) {
|
|
11527
|
-
throw new BadRequestError56("Failed to create job post indexes.");
|
|
11528
11626
|
}
|
|
11529
11627
|
}
|
|
11530
|
-
async function add(value
|
|
11628
|
+
async function add(value) {
|
|
11531
11629
|
try {
|
|
11532
|
-
value =
|
|
11533
|
-
|
|
11630
|
+
value = modelPromoUsage(value);
|
|
11631
|
+
await collection.insertOne(value);
|
|
11534
11632
|
delCachedData();
|
|
11535
|
-
return
|
|
11633
|
+
return "Successfully added promo usage.";
|
|
11536
11634
|
} catch (error) {
|
|
11537
|
-
|
|
11538
|
-
level: "error",
|
|
11539
|
-
message: error.message
|
|
11540
|
-
});
|
|
11541
|
-
throw new BadRequestError56(`Failed to create job post: ${error.message}`);
|
|
11635
|
+
throw new InternalServerError30("Failed to add promo usage.");
|
|
11542
11636
|
}
|
|
11543
11637
|
}
|
|
11544
11638
|
async function getAll({
|
|
11545
|
-
search = "",
|
|
11546
11639
|
page = 1,
|
|
11547
11640
|
limit = 10,
|
|
11548
|
-
|
|
11641
|
+
promo,
|
|
11642
|
+
org
|
|
11549
11643
|
} = {}) {
|
|
11550
|
-
page = page > 0 ? page - 1 :
|
|
11551
|
-
const query = {
|
|
11552
|
-
|
|
11553
|
-
query.$text = { $search: search };
|
|
11554
|
-
}
|
|
11555
|
-
const cacheKey = makeCacheKey19(namespace_collection, {
|
|
11556
|
-
search,
|
|
11644
|
+
page = page > 0 ? page - 1 : page;
|
|
11645
|
+
const query = {};
|
|
11646
|
+
const cacheKeyOptions = {
|
|
11557
11647
|
page,
|
|
11558
11648
|
limit,
|
|
11559
|
-
|
|
11560
|
-
|
|
11561
|
-
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11649
|
+
promo,
|
|
11650
|
+
org,
|
|
11651
|
+
tag: "getAll"
|
|
11652
|
+
};
|
|
11653
|
+
if (promo) {
|
|
11654
|
+
try {
|
|
11655
|
+
query.promo = new ObjectId28(promo);
|
|
11656
|
+
} catch (error) {
|
|
11657
|
+
throw new BadRequestError56("Invalid promo ID.");
|
|
11658
|
+
}
|
|
11659
|
+
}
|
|
11660
|
+
if (org) {
|
|
11661
|
+
try {
|
|
11662
|
+
query.org = new ObjectId28(org);
|
|
11663
|
+
} catch (error) {
|
|
11664
|
+
throw new BadRequestError56("Invalid org ID.");
|
|
11665
|
+
}
|
|
11666
|
+
}
|
|
11667
|
+
const cacheKey = makeCacheKey19(namespace_collection, cacheKeyOptions);
|
|
11565
11668
|
try {
|
|
11566
|
-
const
|
|
11567
|
-
if (
|
|
11568
|
-
|
|
11569
|
-
level: "info",
|
|
11570
|
-
message: `Cache hit for getAll job posts: ${cacheKey}`
|
|
11571
|
-
});
|
|
11572
|
-
return cached;
|
|
11669
|
+
const cachedData = await getCache(cacheKey);
|
|
11670
|
+
if (cachedData) {
|
|
11671
|
+
return cachedData;
|
|
11573
11672
|
}
|
|
11574
11673
|
const items = await collection.aggregate([
|
|
11575
11674
|
{ $match: query },
|
|
11576
11675
|
{ $skip: page * limit },
|
|
11577
|
-
{ $limit: limit }
|
|
11676
|
+
{ $limit: limit }
|
|
11677
|
+
]).toArray();
|
|
11678
|
+
const length = await collection.countDocuments(query);
|
|
11679
|
+
const data = paginate16(items, page, limit, length);
|
|
11680
|
+
setCache(cacheKey, data).then(() => {
|
|
11681
|
+
logger33.log({
|
|
11682
|
+
level: "info",
|
|
11683
|
+
message: `Cache set for getAll promo usage: ${cacheKey}`
|
|
11684
|
+
});
|
|
11685
|
+
}).catch((err) => {
|
|
11686
|
+
logger33.log({
|
|
11687
|
+
level: "error",
|
|
11688
|
+
message: `Failed to set cache for getAll promo usage: ${err.message}`
|
|
11689
|
+
});
|
|
11690
|
+
});
|
|
11691
|
+
return data;
|
|
11692
|
+
} catch (error) {
|
|
11693
|
+
throw new InternalServerError30("Failed to get promo usages.");
|
|
11694
|
+
}
|
|
11695
|
+
}
|
|
11696
|
+
async function getByPromo(promo) {
|
|
11697
|
+
const { error } = Joi48.string().hex().length(24).required().validate(promo);
|
|
11698
|
+
if (error) {
|
|
11699
|
+
throw new Error(`Invalid promo ID: ${error.message}`);
|
|
11700
|
+
}
|
|
11701
|
+
try {
|
|
11702
|
+
promo = new ObjectId28(promo);
|
|
11703
|
+
} catch (error2) {
|
|
11704
|
+
throw new BadRequestError56("Invalid promo ID.");
|
|
11705
|
+
}
|
|
11706
|
+
try {
|
|
11707
|
+
const cacheKey = makeCacheKey19(namespace_collection, {
|
|
11708
|
+
promo: String(promo),
|
|
11709
|
+
tag: "getByPromoId"
|
|
11710
|
+
});
|
|
11711
|
+
const cachedData = await getCache(cacheKey);
|
|
11712
|
+
if (cachedData) {
|
|
11713
|
+
return cachedData;
|
|
11714
|
+
}
|
|
11715
|
+
const data = await collection.findOne({ promo });
|
|
11716
|
+
setCache(cacheKey, data).then(() => {
|
|
11717
|
+
logger33.log({
|
|
11718
|
+
level: "info",
|
|
11719
|
+
message: `Cache set for getByPromoId promo usage: ${cacheKey}`
|
|
11720
|
+
});
|
|
11721
|
+
}).catch((err) => {
|
|
11722
|
+
logger33.log({
|
|
11723
|
+
level: "error",
|
|
11724
|
+
message: `Failed to set cache for getByPromoId promo usage: ${err.message}`
|
|
11725
|
+
});
|
|
11726
|
+
});
|
|
11727
|
+
return data;
|
|
11728
|
+
} catch (error2) {
|
|
11729
|
+
throw new InternalServerError30("Failed to get promo usages.");
|
|
11730
|
+
}
|
|
11731
|
+
}
|
|
11732
|
+
async function getById(_id) {
|
|
11733
|
+
const { error } = Joi48.string().hex().length(24).required().validate(_id);
|
|
11734
|
+
if (error) {
|
|
11735
|
+
throw new Error(`Invalid promo usage ID: ${error.message}`);
|
|
11736
|
+
}
|
|
11737
|
+
try {
|
|
11738
|
+
_id = new ObjectId28(_id);
|
|
11739
|
+
} catch (error2) {
|
|
11740
|
+
throw new BadRequestError56("Invalid promo usage ID.");
|
|
11741
|
+
}
|
|
11742
|
+
try {
|
|
11743
|
+
const cacheKey = makeCacheKey19(namespace_collection, {
|
|
11744
|
+
_id: String(_id),
|
|
11745
|
+
tag: "getById"
|
|
11746
|
+
});
|
|
11747
|
+
const cachedData = await getCache(cacheKey);
|
|
11748
|
+
if (cachedData) {
|
|
11749
|
+
return cachedData;
|
|
11750
|
+
}
|
|
11751
|
+
const data = await collection.findOne({ _id });
|
|
11752
|
+
setCache(cacheKey, data).then(() => {
|
|
11753
|
+
logger33.log({
|
|
11754
|
+
level: "info",
|
|
11755
|
+
message: `Cache set for getById promo usage: ${cacheKey}`
|
|
11756
|
+
});
|
|
11757
|
+
}).catch((err) => {
|
|
11758
|
+
logger33.log({
|
|
11759
|
+
level: "error",
|
|
11760
|
+
message: `Failed to set cache for getById promo usage: ${err.message}`
|
|
11761
|
+
});
|
|
11762
|
+
});
|
|
11763
|
+
return data;
|
|
11764
|
+
} catch (error2) {
|
|
11765
|
+
throw new InternalServerError30("Failed to get promo usage.");
|
|
11766
|
+
}
|
|
11767
|
+
}
|
|
11768
|
+
async function getByOrgId(orgId) {
|
|
11769
|
+
const { error } = Joi48.string().hex().length(24).required().validate(orgId);
|
|
11770
|
+
if (error) {
|
|
11771
|
+
throw new Error(`Invalid org ID: ${error.message}`);
|
|
11772
|
+
}
|
|
11773
|
+
try {
|
|
11774
|
+
orgId = new ObjectId28(orgId);
|
|
11775
|
+
} catch (error2) {
|
|
11776
|
+
throw new BadRequestError56("Invalid org ID.");
|
|
11777
|
+
}
|
|
11778
|
+
try {
|
|
11779
|
+
const cacheKey = makeCacheKey19(namespace_collection, {
|
|
11780
|
+
org: String(orgId),
|
|
11781
|
+
tag: "getByOrgId"
|
|
11782
|
+
});
|
|
11783
|
+
const cachedData = await getCache(cacheKey);
|
|
11784
|
+
if (cachedData) {
|
|
11785
|
+
return cachedData;
|
|
11786
|
+
}
|
|
11787
|
+
const data = await collection.find({ org: orgId }).toArray();
|
|
11788
|
+
setCache(cacheKey, data).then(() => {
|
|
11789
|
+
logger33.log({
|
|
11790
|
+
level: "info",
|
|
11791
|
+
message: `Cache set for getByOrgId promo usage: ${cacheKey}`
|
|
11792
|
+
});
|
|
11793
|
+
}).catch((err) => {
|
|
11794
|
+
logger33.log({
|
|
11795
|
+
level: "error",
|
|
11796
|
+
message: `Failed to set cache for getByOrgId promo usage: ${err.message}`
|
|
11797
|
+
});
|
|
11798
|
+
});
|
|
11799
|
+
return data;
|
|
11800
|
+
} catch (error2) {
|
|
11801
|
+
throw new InternalServerError30("Failed to get promo usages.");
|
|
11802
|
+
}
|
|
11803
|
+
}
|
|
11804
|
+
async function countByPromoId(promoId) {
|
|
11805
|
+
const { error } = Joi48.string().hex().length(24).required().validate(promoId);
|
|
11806
|
+
if (error) {
|
|
11807
|
+
throw new Error(`Invalid promo ID: ${error.message}`);
|
|
11808
|
+
}
|
|
11809
|
+
try {
|
|
11810
|
+
promoId = new ObjectId28(promoId);
|
|
11811
|
+
} catch (error2) {
|
|
11812
|
+
throw new BadRequestError56("Invalid promo ID.");
|
|
11813
|
+
}
|
|
11814
|
+
try {
|
|
11815
|
+
const cacheKey = makeCacheKey19(namespace_collection, {
|
|
11816
|
+
promo: String(promoId),
|
|
11817
|
+
tag: "countByPromoId"
|
|
11818
|
+
});
|
|
11819
|
+
const cachedData = await getCache(cacheKey);
|
|
11820
|
+
if (cachedData !== null && cachedData !== void 0) {
|
|
11821
|
+
return cachedData;
|
|
11822
|
+
}
|
|
11823
|
+
const count = await collection.countDocuments({ promo: promoId });
|
|
11824
|
+
setCache(cacheKey, count).then(() => {
|
|
11825
|
+
logger33.log({
|
|
11826
|
+
level: "info",
|
|
11827
|
+
message: `Cache set for countByPromoId promo usage: ${cacheKey}`
|
|
11828
|
+
});
|
|
11829
|
+
}).catch((err) => {
|
|
11830
|
+
logger33.log({
|
|
11831
|
+
level: "error",
|
|
11832
|
+
message: `Failed to set cache for countByPromoId promo usage: ${err.message}`
|
|
11833
|
+
});
|
|
11834
|
+
});
|
|
11835
|
+
return count;
|
|
11836
|
+
} catch (error2) {
|
|
11837
|
+
throw new InternalServerError30("Failed to count promo usages.");
|
|
11838
|
+
}
|
|
11839
|
+
}
|
|
11840
|
+
async function deleteById(_id) {
|
|
11841
|
+
const { error } = Joi48.string().hex().length(24).required().validate(_id);
|
|
11842
|
+
if (error) {
|
|
11843
|
+
throw new Error(`Invalid promo usage ID: ${error.message}`);
|
|
11844
|
+
}
|
|
11845
|
+
try {
|
|
11846
|
+
_id = new ObjectId28(_id);
|
|
11847
|
+
} catch (error2) {
|
|
11848
|
+
throw new BadRequestError56("Invalid promo usage ID.");
|
|
11849
|
+
}
|
|
11850
|
+
try {
|
|
11851
|
+
const result = await collection.deleteOne({ _id });
|
|
11852
|
+
if (result.deletedCount === 0) {
|
|
11853
|
+
throw new InternalServerError30("Failed to delete promo usage.");
|
|
11854
|
+
}
|
|
11855
|
+
delCachedData();
|
|
11856
|
+
return "Successfully deleted promo usage.";
|
|
11857
|
+
} catch (error2) {
|
|
11858
|
+
if (error2 instanceof AppError27) {
|
|
11859
|
+
throw error2;
|
|
11860
|
+
}
|
|
11861
|
+
throw new InternalServerError30("Failed to delete promo usage.");
|
|
11862
|
+
}
|
|
11863
|
+
}
|
|
11864
|
+
return {
|
|
11865
|
+
createIndexes,
|
|
11866
|
+
add,
|
|
11867
|
+
getAll,
|
|
11868
|
+
getByPromo,
|
|
11869
|
+
getById,
|
|
11870
|
+
getByOrgId,
|
|
11871
|
+
countByPromoId,
|
|
11872
|
+
deleteById
|
|
11873
|
+
};
|
|
11874
|
+
}
|
|
11875
|
+
|
|
11876
|
+
// src/resources/promo/promo.service.ts
|
|
11877
|
+
function usePromoService() {
|
|
11878
|
+
const { getByPromo } = usePromoUsageRepo();
|
|
11879
|
+
const { deleteById: _deleteById } = usePromoRepo();
|
|
11880
|
+
async function deleteById(id) {
|
|
11881
|
+
const usage = await getByPromo(id);
|
|
11882
|
+
if (usage) {
|
|
11883
|
+
throw new BadRequestError57("Failed to delete, promo is in use.");
|
|
11884
|
+
}
|
|
11885
|
+
try {
|
|
11886
|
+
await _deleteById(id);
|
|
11887
|
+
return "Successfully deleted promo.";
|
|
11888
|
+
} catch (error) {
|
|
11889
|
+
if (error instanceof AppError28) {
|
|
11890
|
+
throw error;
|
|
11891
|
+
}
|
|
11892
|
+
throw new BadRequestError57("Failed to delete promo.");
|
|
11893
|
+
}
|
|
11894
|
+
}
|
|
11895
|
+
return {
|
|
11896
|
+
deleteById
|
|
11897
|
+
};
|
|
11898
|
+
}
|
|
11899
|
+
|
|
11900
|
+
// src/resources/promo/promo.controller.ts
|
|
11901
|
+
function usePromoController() {
|
|
11902
|
+
const {
|
|
11903
|
+
add: _add,
|
|
11904
|
+
getAll: _getAll,
|
|
11905
|
+
getByCode: _getByCode,
|
|
11906
|
+
getById: _getById,
|
|
11907
|
+
updateById: _updateById
|
|
11908
|
+
} = usePromoRepo();
|
|
11909
|
+
async function add(req, res, next) {
|
|
11910
|
+
const value = req.body;
|
|
11911
|
+
const { error } = schemaPromo.validate(value);
|
|
11912
|
+
if (error) {
|
|
11913
|
+
next(new BadRequestError58(error.message));
|
|
11914
|
+
return;
|
|
11915
|
+
}
|
|
11916
|
+
try {
|
|
11917
|
+
const message = await _add(value);
|
|
11918
|
+
res.json({ message });
|
|
11919
|
+
return;
|
|
11920
|
+
} catch (error2) {
|
|
11921
|
+
next(error2);
|
|
11922
|
+
}
|
|
11923
|
+
}
|
|
11924
|
+
async function getAll(req, res, next) {
|
|
11925
|
+
const status = req.query.status ?? "active";
|
|
11926
|
+
const search = req.query.search ?? "";
|
|
11927
|
+
const page = Number(req.query.page) ?? 1;
|
|
11928
|
+
const limit = Number(req.query.limit) ?? 10;
|
|
11929
|
+
const validation = Joi49.object({
|
|
11930
|
+
status: Joi49.string().required(),
|
|
11931
|
+
search: Joi49.string().optional().allow("", null),
|
|
11932
|
+
page: Joi49.number().required(),
|
|
11933
|
+
limit: Joi49.number().required()
|
|
11934
|
+
});
|
|
11935
|
+
const { error } = validation.validate({ status, search, page, limit });
|
|
11936
|
+
if (error) {
|
|
11937
|
+
next(new BadRequestError58(error.message));
|
|
11938
|
+
return;
|
|
11939
|
+
}
|
|
11940
|
+
try {
|
|
11941
|
+
const promos = await _getAll({ status, search, page, limit });
|
|
11942
|
+
res.json(promos);
|
|
11943
|
+
return;
|
|
11944
|
+
} catch (error2) {
|
|
11945
|
+
next(error2);
|
|
11946
|
+
}
|
|
11947
|
+
}
|
|
11948
|
+
async function getByCode(req, res, next) {
|
|
11949
|
+
const code = req.params.code;
|
|
11950
|
+
const validation = Joi49.string().min(3).max(50).required();
|
|
11951
|
+
const { error } = validation.validate(code);
|
|
11952
|
+
if (error) {
|
|
11953
|
+
next(new BadRequestError58(error.message));
|
|
11954
|
+
return;
|
|
11955
|
+
}
|
|
11956
|
+
try {
|
|
11957
|
+
const promo = await _getByCode(code);
|
|
11958
|
+
res.json(promo);
|
|
11959
|
+
return;
|
|
11960
|
+
} catch (error2) {
|
|
11961
|
+
next(error2);
|
|
11962
|
+
}
|
|
11963
|
+
}
|
|
11964
|
+
async function getById(req, res, next) {
|
|
11965
|
+
const id = req.params.id;
|
|
11966
|
+
const validation = Joi49.string().hex().length(24).required();
|
|
11967
|
+
const { error } = validation.validate(id);
|
|
11968
|
+
if (error) {
|
|
11969
|
+
next(new BadRequestError58(error.message));
|
|
11970
|
+
return;
|
|
11971
|
+
}
|
|
11972
|
+
try {
|
|
11973
|
+
const promo = await _getById(id);
|
|
11974
|
+
res.json(promo);
|
|
11975
|
+
return;
|
|
11976
|
+
} catch (error2) {
|
|
11977
|
+
next(error2);
|
|
11978
|
+
}
|
|
11979
|
+
}
|
|
11980
|
+
async function updateById(req, res, next) {
|
|
11981
|
+
const id = req.params.id;
|
|
11982
|
+
const value = req.body;
|
|
11983
|
+
const validationId = Joi49.string().hex().length(24).required();
|
|
11984
|
+
const { error: errorId } = validationId.validate(id);
|
|
11985
|
+
if (errorId) {
|
|
11986
|
+
next(new BadRequestError58(errorId.message));
|
|
11987
|
+
return;
|
|
11988
|
+
}
|
|
11989
|
+
const { error } = schemaPromo.validate(value);
|
|
11990
|
+
if (error) {
|
|
11991
|
+
next(new BadRequestError58(error.message));
|
|
11992
|
+
return;
|
|
11993
|
+
}
|
|
11994
|
+
try {
|
|
11995
|
+
const message = await _updateById(id, value);
|
|
11996
|
+
res.json({ message });
|
|
11997
|
+
return;
|
|
11998
|
+
} catch (error2) {
|
|
11999
|
+
next(error2);
|
|
12000
|
+
}
|
|
12001
|
+
}
|
|
12002
|
+
const { deleteById: _deleteById } = usePromoService();
|
|
12003
|
+
async function deleteById(req, res, next) {
|
|
12004
|
+
const id = req.params.id;
|
|
12005
|
+
const validation = Joi49.string().hex().length(24).required();
|
|
12006
|
+
const { error } = validation.validate(id);
|
|
12007
|
+
if (error) {
|
|
12008
|
+
next(new BadRequestError58(error.message));
|
|
12009
|
+
return;
|
|
12010
|
+
}
|
|
12011
|
+
try {
|
|
12012
|
+
const message = await _deleteById(id);
|
|
12013
|
+
res.json({ message });
|
|
12014
|
+
return;
|
|
12015
|
+
} catch (error2) {
|
|
12016
|
+
next(error2);
|
|
12017
|
+
}
|
|
12018
|
+
}
|
|
12019
|
+
return {
|
|
12020
|
+
add,
|
|
12021
|
+
getAll,
|
|
12022
|
+
getByCode,
|
|
12023
|
+
getById,
|
|
12024
|
+
updateById,
|
|
12025
|
+
deleteById
|
|
12026
|
+
};
|
|
12027
|
+
}
|
|
12028
|
+
|
|
12029
|
+
// src/resources/job-post/job.post.model.ts
|
|
12030
|
+
import { BadRequestError as BadRequestError59 } from "@goweekdays/utils";
|
|
12031
|
+
import Joi50 from "joi";
|
|
12032
|
+
import { ObjectId as ObjectId29 } from "mongodb";
|
|
12033
|
+
var schemaJobPost = Joi50.object({
|
|
12034
|
+
_id: Joi50.string().hex().optional(),
|
|
12035
|
+
org: Joi50.string().hex().required(),
|
|
12036
|
+
orgName: Joi50.string().optional().allow("", null),
|
|
12037
|
+
title: Joi50.string().trim().required(),
|
|
12038
|
+
setup: Joi50.string().trim().required(),
|
|
12039
|
+
location: Joi50.string().trim().required(),
|
|
12040
|
+
type: Joi50.string().trim().required(),
|
|
12041
|
+
minSalary: Joi50.number().optional(),
|
|
12042
|
+
maxSalary: Joi50.number().optional(),
|
|
12043
|
+
currency: Joi50.string().trim().optional(),
|
|
12044
|
+
payPeriod: Joi50.string().trim().optional(),
|
|
12045
|
+
description: Joi50.string().trim().required(),
|
|
12046
|
+
status: Joi50.string().trim().optional().allow("", null),
|
|
12047
|
+
createdAt: Joi50.date().optional(),
|
|
12048
|
+
updatedAt: Joi50.date().optional(),
|
|
12049
|
+
deletedAt: Joi50.date().optional()
|
|
12050
|
+
});
|
|
12051
|
+
var schemaJobPostUpdate = Joi50.object({
|
|
12052
|
+
_id: Joi50.string().hex().required(),
|
|
12053
|
+
title: Joi50.string().trim().required(),
|
|
12054
|
+
setup: Joi50.string().trim().required(),
|
|
12055
|
+
location: Joi50.string().trim().required(),
|
|
12056
|
+
type: Joi50.string().trim().required(),
|
|
12057
|
+
minSalary: Joi50.number().optional(),
|
|
12058
|
+
maxSalary: Joi50.number().optional(),
|
|
12059
|
+
currency: Joi50.string().trim().optional(),
|
|
12060
|
+
payPeriod: Joi50.string().trim().optional(),
|
|
12061
|
+
description: Joi50.string().trim().required()
|
|
12062
|
+
});
|
|
12063
|
+
function modelJobPost(value) {
|
|
12064
|
+
const { error } = schemaJobPost.validate(value);
|
|
12065
|
+
if (error) {
|
|
12066
|
+
throw new BadRequestError59(`Invalid job post: ${error.message}`);
|
|
12067
|
+
}
|
|
12068
|
+
if (!value._id) {
|
|
12069
|
+
try {
|
|
12070
|
+
value._id = new ObjectId29();
|
|
12071
|
+
} catch (error2) {
|
|
12072
|
+
throw new BadRequestError59("Invalid job post ID.");
|
|
12073
|
+
}
|
|
12074
|
+
}
|
|
12075
|
+
try {
|
|
12076
|
+
value.org = new ObjectId29(value.org);
|
|
12077
|
+
} catch (error2) {
|
|
12078
|
+
throw new BadRequestError59("Invalid Org ID");
|
|
12079
|
+
}
|
|
12080
|
+
return {
|
|
12081
|
+
_id: value._id,
|
|
12082
|
+
org: value.org,
|
|
12083
|
+
orgName: value.orgName ?? "",
|
|
12084
|
+
title: value.title,
|
|
12085
|
+
setup: value.setup,
|
|
12086
|
+
location: value.location,
|
|
12087
|
+
type: value.type,
|
|
12088
|
+
minSalary: value.minSalary,
|
|
12089
|
+
maxSalary: value.maxSalary ?? 0,
|
|
12090
|
+
currency: value.currency ?? "PHP",
|
|
12091
|
+
payPeriod: value.payPeriod ?? "monthly",
|
|
12092
|
+
description: value.description,
|
|
12093
|
+
status: value.status ?? "draft",
|
|
12094
|
+
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
12095
|
+
updatedAt: value.updatedAt ?? "",
|
|
12096
|
+
deletedAt: value.deletedAt ?? ""
|
|
12097
|
+
};
|
|
12098
|
+
}
|
|
12099
|
+
|
|
12100
|
+
// src/resources/job-post/job.post.controller.ts
|
|
12101
|
+
import Joi53 from "joi";
|
|
12102
|
+
import { BadRequestError as BadRequestError64, logger as logger36 } from "@goweekdays/utils";
|
|
12103
|
+
|
|
12104
|
+
// src/resources/job-post/job.post.repository.ts
|
|
12105
|
+
import {
|
|
12106
|
+
AppError as AppError29,
|
|
12107
|
+
BadRequestError as BadRequestError60,
|
|
12108
|
+
useAtlas as useAtlas28,
|
|
12109
|
+
useCache as useCache21,
|
|
12110
|
+
makeCacheKey as makeCacheKey20,
|
|
12111
|
+
paginate as paginate17,
|
|
12112
|
+
logger as logger34,
|
|
12113
|
+
InternalServerError as InternalServerError31
|
|
12114
|
+
} from "@goweekdays/utils";
|
|
12115
|
+
import { ObjectId as ObjectId30 } from "mongodb";
|
|
12116
|
+
function useJobPostRepo() {
|
|
12117
|
+
const db = useAtlas28.getDb();
|
|
12118
|
+
if (!db) {
|
|
12119
|
+
throw new BadRequestError60("Unable to connect to server.");
|
|
12120
|
+
}
|
|
12121
|
+
const namespace_collection = "job.posts";
|
|
12122
|
+
const collection = db.collection(namespace_collection);
|
|
12123
|
+
const { getCache, setCache, delNamespace } = useCache21(namespace_collection);
|
|
12124
|
+
function delCachedData() {
|
|
12125
|
+
delNamespace().then(() => {
|
|
12126
|
+
logger34.log({
|
|
12127
|
+
level: "info",
|
|
12128
|
+
message: `Cache namespace cleared for ${namespace_collection}`
|
|
12129
|
+
});
|
|
12130
|
+
}).catch((err) => {
|
|
12131
|
+
logger34.log({
|
|
12132
|
+
level: "error",
|
|
12133
|
+
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
12134
|
+
});
|
|
12135
|
+
});
|
|
12136
|
+
}
|
|
12137
|
+
async function createIndexes() {
|
|
12138
|
+
try {
|
|
12139
|
+
await collection.createIndexes([
|
|
12140
|
+
{ key: { title: 1 } },
|
|
12141
|
+
{ key: { setup: 1 } },
|
|
12142
|
+
{ key: { location: 1 } },
|
|
12143
|
+
{ key: { type: 1 } },
|
|
12144
|
+
{
|
|
12145
|
+
key: {
|
|
12146
|
+
title: "text",
|
|
12147
|
+
setup: "text",
|
|
12148
|
+
location: "text",
|
|
12149
|
+
type: "text"
|
|
12150
|
+
},
|
|
12151
|
+
name: "jobpost_text_search"
|
|
12152
|
+
}
|
|
12153
|
+
]);
|
|
12154
|
+
return "Successfully created job post indexes.";
|
|
12155
|
+
} catch (error) {
|
|
12156
|
+
throw new BadRequestError60("Failed to create job post indexes.");
|
|
12157
|
+
}
|
|
12158
|
+
}
|
|
12159
|
+
async function add(value, session) {
|
|
12160
|
+
try {
|
|
12161
|
+
value = modelJobPost(value);
|
|
12162
|
+
const res = await collection.insertOne(value, { session });
|
|
12163
|
+
delCachedData();
|
|
12164
|
+
return res.insertedId;
|
|
12165
|
+
} catch (error) {
|
|
12166
|
+
logger34.log({
|
|
12167
|
+
level: "error",
|
|
12168
|
+
message: error.message
|
|
12169
|
+
});
|
|
12170
|
+
throw new BadRequestError60(`Failed to create job post: ${error.message}`);
|
|
12171
|
+
}
|
|
12172
|
+
}
|
|
12173
|
+
async function getAll({
|
|
12174
|
+
search = "",
|
|
12175
|
+
page = 1,
|
|
12176
|
+
limit = 10,
|
|
12177
|
+
status = "active"
|
|
12178
|
+
} = {}) {
|
|
12179
|
+
page = page > 0 ? page - 1 : 0;
|
|
12180
|
+
const query = { status };
|
|
12181
|
+
if (search) {
|
|
12182
|
+
query.$text = { $search: search };
|
|
12183
|
+
}
|
|
12184
|
+
const cacheKey = makeCacheKey20(namespace_collection, {
|
|
12185
|
+
search,
|
|
12186
|
+
page,
|
|
12187
|
+
limit,
|
|
12188
|
+
status
|
|
12189
|
+
});
|
|
12190
|
+
logger34.log({
|
|
12191
|
+
level: "info",
|
|
12192
|
+
message: `Cache key for getAll job posts: ${cacheKey}`
|
|
12193
|
+
});
|
|
12194
|
+
try {
|
|
12195
|
+
const cached = await getCache(cacheKey);
|
|
12196
|
+
if (cached) {
|
|
12197
|
+
logger34.log({
|
|
12198
|
+
level: "info",
|
|
12199
|
+
message: `Cache hit for getAll job posts: ${cacheKey}`
|
|
12200
|
+
});
|
|
12201
|
+
return cached;
|
|
12202
|
+
}
|
|
12203
|
+
const items = await collection.aggregate([
|
|
12204
|
+
{ $match: query },
|
|
12205
|
+
{ $skip: page * limit },
|
|
12206
|
+
{ $limit: limit },
|
|
11578
12207
|
{
|
|
11579
12208
|
$project: {
|
|
11580
12209
|
_id: 1,
|
|
12210
|
+
orgName: 1,
|
|
12211
|
+
minSalary: 1,
|
|
12212
|
+
maxSalary: 1,
|
|
12213
|
+
currency: 1,
|
|
12214
|
+
payPeriod: 1,
|
|
11581
12215
|
title: 1,
|
|
11582
12216
|
setup: 1,
|
|
11583
12217
|
location: 1,
|
|
@@ -11587,36 +12221,30 @@ function useJobPostRepo() {
|
|
|
11587
12221
|
}
|
|
11588
12222
|
]).toArray();
|
|
11589
12223
|
const length = await collection.countDocuments(query);
|
|
11590
|
-
const data =
|
|
12224
|
+
const data = paginate17(items, page, limit, length);
|
|
11591
12225
|
setCache(cacheKey, data, 600).then(() => {
|
|
11592
|
-
|
|
12226
|
+
logger34.log({
|
|
11593
12227
|
level: "info",
|
|
11594
12228
|
message: `Cache set for getAll job posts: ${cacheKey}`
|
|
11595
12229
|
});
|
|
11596
12230
|
}).catch((err) => {
|
|
11597
|
-
|
|
12231
|
+
logger34.log({
|
|
11598
12232
|
level: "error",
|
|
11599
12233
|
message: `Failed to set cache for getAll job posts: ${err.message}`
|
|
11600
12234
|
});
|
|
11601
12235
|
});
|
|
11602
12236
|
return data;
|
|
11603
12237
|
} catch (error) {
|
|
11604
|
-
|
|
12238
|
+
logger34.log({ level: "error", message: `${error}` });
|
|
11605
12239
|
throw error;
|
|
11606
12240
|
}
|
|
11607
12241
|
}
|
|
11608
|
-
async function getJobPostsByOrg({
|
|
11609
|
-
search = "",
|
|
11610
|
-
page = 1,
|
|
11611
|
-
limit = 10,
|
|
11612
|
-
org = "",
|
|
11613
|
-
status = "active"
|
|
11614
|
-
} = {}) {
|
|
12242
|
+
async function getJobPostsByOrg({ search = "", page = 1, limit = 10, org = "", status = "active" } = {}) {
|
|
11615
12243
|
page = page > 0 ? page - 1 : 0;
|
|
11616
12244
|
try {
|
|
11617
|
-
org = new
|
|
12245
|
+
org = new ObjectId30(org);
|
|
11618
12246
|
} catch (error) {
|
|
11619
|
-
throw new
|
|
12247
|
+
throw new BadRequestError60("Invalid organization ID.");
|
|
11620
12248
|
}
|
|
11621
12249
|
const query = { org, status };
|
|
11622
12250
|
const cacheKeyOptions = {
|
|
@@ -11626,203 +12254,500 @@ function useJobPostRepo() {
|
|
|
11626
12254
|
page
|
|
11627
12255
|
};
|
|
11628
12256
|
if (search) {
|
|
11629
|
-
cacheKeyOptions.search = search;
|
|
12257
|
+
cacheKeyOptions.search = search;
|
|
12258
|
+
query.$text = { $search: search };
|
|
12259
|
+
}
|
|
12260
|
+
try {
|
|
12261
|
+
const cacheKey = makeCacheKey20(namespace_collection, cacheKeyOptions);
|
|
12262
|
+
const cached = await getCache(
|
|
12263
|
+
cacheKey
|
|
12264
|
+
);
|
|
12265
|
+
if (cached) {
|
|
12266
|
+
logger34.log({
|
|
12267
|
+
level: "info",
|
|
12268
|
+
message: `Cache hit for getJobPostsByOrg : ${cacheKey}`
|
|
12269
|
+
});
|
|
12270
|
+
return cached;
|
|
12271
|
+
}
|
|
12272
|
+
const items = await collection.aggregate([
|
|
12273
|
+
{ $match: query },
|
|
12274
|
+
{ $skip: page * limit },
|
|
12275
|
+
{ $limit: limit },
|
|
12276
|
+
{
|
|
12277
|
+
$project: {
|
|
12278
|
+
_id: 1,
|
|
12279
|
+
title: 1,
|
|
12280
|
+
setup: 1,
|
|
12281
|
+
location: 1,
|
|
12282
|
+
type: 1,
|
|
12283
|
+
createdAt: 1
|
|
12284
|
+
}
|
|
12285
|
+
}
|
|
12286
|
+
]).toArray();
|
|
12287
|
+
const length = await collection.countDocuments(query);
|
|
12288
|
+
const data = paginate17(items, page, limit, length);
|
|
12289
|
+
setCache(cacheKey, data, 300).then(() => {
|
|
12290
|
+
logger34.log({
|
|
12291
|
+
level: "info",
|
|
12292
|
+
message: `Cache set for getJobPostsByOrg: ${cacheKey}`
|
|
12293
|
+
});
|
|
12294
|
+
}).catch((err) => {
|
|
12295
|
+
logger34.log({
|
|
12296
|
+
level: "error",
|
|
12297
|
+
message: `Failed to set cache for getJobPostsByOrg: ${err.message}`
|
|
12298
|
+
});
|
|
12299
|
+
});
|
|
12300
|
+
return data;
|
|
12301
|
+
} catch (error) {
|
|
12302
|
+
throw new InternalServerError31(
|
|
12303
|
+
"Internal server error, failed to retrieve job posts."
|
|
12304
|
+
);
|
|
12305
|
+
}
|
|
12306
|
+
}
|
|
12307
|
+
async function getById(_id) {
|
|
12308
|
+
try {
|
|
12309
|
+
_id = new ObjectId30(_id);
|
|
12310
|
+
} catch (error) {
|
|
12311
|
+
throw new BadRequestError60("Invalid ID.");
|
|
12312
|
+
}
|
|
12313
|
+
const cacheKey = makeCacheKey20(namespace_collection, { _id: String(_id) });
|
|
12314
|
+
try {
|
|
12315
|
+
const cached = await getCache(cacheKey);
|
|
12316
|
+
if (cached) {
|
|
12317
|
+
logger34.log({
|
|
12318
|
+
level: "info",
|
|
12319
|
+
message: `Cache hit for getById job post: ${cacheKey}`
|
|
12320
|
+
});
|
|
12321
|
+
return cached;
|
|
12322
|
+
}
|
|
12323
|
+
const result = await collection.findOne({ _id });
|
|
12324
|
+
if (!result) {
|
|
12325
|
+
throw new BadRequestError60("Job post not found.");
|
|
12326
|
+
}
|
|
12327
|
+
setCache(cacheKey, result, 300).then(() => {
|
|
12328
|
+
logger34.log({
|
|
12329
|
+
level: "info",
|
|
12330
|
+
message: `Cache set for job post by id: ${cacheKey}`
|
|
12331
|
+
});
|
|
12332
|
+
}).catch((err) => {
|
|
12333
|
+
logger34.log({
|
|
12334
|
+
level: "error",
|
|
12335
|
+
message: `Failed to set cache for job post by id: ${err.message}`
|
|
12336
|
+
});
|
|
12337
|
+
});
|
|
12338
|
+
return result;
|
|
12339
|
+
} catch (error) {
|
|
12340
|
+
if (error instanceof AppError29) {
|
|
12341
|
+
throw error;
|
|
12342
|
+
} else {
|
|
12343
|
+
throw new InternalServerError31("Failed to get job post.");
|
|
12344
|
+
}
|
|
12345
|
+
}
|
|
12346
|
+
}
|
|
12347
|
+
async function updateById(_id, options) {
|
|
12348
|
+
const { error } = schemaJobPostUpdate.validate({ ...options, _id });
|
|
12349
|
+
if (error) {
|
|
12350
|
+
throw new BadRequestError60(error.message);
|
|
12351
|
+
}
|
|
12352
|
+
try {
|
|
12353
|
+
_id = new ObjectId30(_id);
|
|
12354
|
+
} catch (error2) {
|
|
12355
|
+
throw new BadRequestError60("Invalid JobPost ID.");
|
|
12356
|
+
}
|
|
12357
|
+
try {
|
|
12358
|
+
await collection.updateOne(
|
|
12359
|
+
{ _id },
|
|
12360
|
+
{ $set: { ...options, updatedAt: /* @__PURE__ */ new Date() } }
|
|
12361
|
+
);
|
|
12362
|
+
delCachedData();
|
|
12363
|
+
return "Successfully updated job post.";
|
|
12364
|
+
} catch (error2) {
|
|
12365
|
+
throw new InternalServerError31("Failed to update job post.");
|
|
12366
|
+
}
|
|
12367
|
+
}
|
|
12368
|
+
async function deleteById(_id, session) {
|
|
12369
|
+
try {
|
|
12370
|
+
_id = new ObjectId30(_id);
|
|
12371
|
+
} catch (error) {
|
|
12372
|
+
throw new BadRequestError60("Invalid ID.");
|
|
12373
|
+
}
|
|
12374
|
+
try {
|
|
12375
|
+
await collection.updateOne(
|
|
12376
|
+
{ _id },
|
|
12377
|
+
{
|
|
12378
|
+
$set: {
|
|
12379
|
+
status: "deleted",
|
|
12380
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
12381
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
12382
|
+
}
|
|
12383
|
+
},
|
|
12384
|
+
{ session }
|
|
12385
|
+
);
|
|
12386
|
+
delCachedData();
|
|
12387
|
+
return "Successfully deleted job post.";
|
|
12388
|
+
} catch (error) {
|
|
12389
|
+
throw new InternalServerError31("Failed to delete job post.");
|
|
12390
|
+
}
|
|
12391
|
+
}
|
|
12392
|
+
async function updateStatusById(_id, status) {
|
|
12393
|
+
try {
|
|
12394
|
+
_id = new ObjectId30(_id);
|
|
12395
|
+
} catch (error) {
|
|
12396
|
+
throw new BadRequestError60("Invalid ID.");
|
|
12397
|
+
}
|
|
12398
|
+
try {
|
|
12399
|
+
const result = await collection.updateOne(
|
|
12400
|
+
{ _id },
|
|
12401
|
+
{
|
|
12402
|
+
$set: {
|
|
12403
|
+
status,
|
|
12404
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
12405
|
+
}
|
|
12406
|
+
}
|
|
12407
|
+
);
|
|
12408
|
+
if (result.matchedCount === 0) {
|
|
12409
|
+
throw new BadRequestError60("Job post not found.");
|
|
12410
|
+
}
|
|
12411
|
+
delCachedData();
|
|
12412
|
+
return "Successfully updated job post status.";
|
|
12413
|
+
} catch (error) {
|
|
12414
|
+
if (error instanceof AppError29) {
|
|
12415
|
+
throw error;
|
|
12416
|
+
}
|
|
12417
|
+
throw new InternalServerError31("Failed to update job post status.");
|
|
12418
|
+
}
|
|
12419
|
+
}
|
|
12420
|
+
return {
|
|
12421
|
+
createIndexes,
|
|
12422
|
+
add,
|
|
12423
|
+
getAll,
|
|
12424
|
+
getJobPostsByOrg,
|
|
12425
|
+
getById,
|
|
12426
|
+
updateById,
|
|
12427
|
+
deleteById,
|
|
12428
|
+
updateStatusById
|
|
12429
|
+
};
|
|
12430
|
+
}
|
|
12431
|
+
|
|
12432
|
+
// src/resources/job-post/job.post.service.ts
|
|
12433
|
+
import {
|
|
12434
|
+
AppError as AppError31,
|
|
12435
|
+
BadRequestError as BadRequestError63,
|
|
12436
|
+
InternalServerError as InternalServerError33,
|
|
12437
|
+
useAtlas as useAtlas30
|
|
12438
|
+
} from "@goweekdays/utils";
|
|
12439
|
+
import Joi52 from "joi";
|
|
12440
|
+
|
|
12441
|
+
// src/resources/job-post/job.post.attr.repository.ts
|
|
12442
|
+
import {
|
|
12443
|
+
AppError as AppError30,
|
|
12444
|
+
BadRequestError as BadRequestError62,
|
|
12445
|
+
InternalServerError as InternalServerError32,
|
|
12446
|
+
logger as logger35,
|
|
12447
|
+
makeCacheKey as makeCacheKey21,
|
|
12448
|
+
paginate as paginate18,
|
|
12449
|
+
useAtlas as useAtlas29,
|
|
12450
|
+
useCache as useCache22
|
|
12451
|
+
} from "@goweekdays/utils";
|
|
12452
|
+
|
|
12453
|
+
// src/resources/job-post/job.post.attr.model.ts
|
|
12454
|
+
import { BadRequestError as BadRequestError61 } from "@goweekdays/utils";
|
|
12455
|
+
import Joi51 from "joi";
|
|
12456
|
+
import { ObjectId as ObjectId31 } from "mongodb";
|
|
12457
|
+
var schemaJobPostAttr = Joi51.string().min(2).max(100).required();
|
|
12458
|
+
function modelJobPostAttr(value) {
|
|
12459
|
+
const { error } = schemaJobPostAttr.validate(value.name);
|
|
12460
|
+
if (error) {
|
|
12461
|
+
throw new BadRequestError61(`Invalid job post attribute: ${error.message}`);
|
|
12462
|
+
}
|
|
12463
|
+
if (value._id && typeof value._id === "string") {
|
|
12464
|
+
try {
|
|
12465
|
+
value._id = new ObjectId31(value._id);
|
|
12466
|
+
} catch (error2) {
|
|
12467
|
+
throw new BadRequestError61(`Invalid job post attribute id: ${error2}`);
|
|
12468
|
+
}
|
|
12469
|
+
}
|
|
12470
|
+
return {
|
|
12471
|
+
_id: value._id,
|
|
12472
|
+
name: value.name,
|
|
12473
|
+
createdAt: value.createdAt ?? /* @__PURE__ */ new Date()
|
|
12474
|
+
};
|
|
12475
|
+
}
|
|
12476
|
+
|
|
12477
|
+
// src/resources/job-post/job.post.attr.repository.ts
|
|
12478
|
+
function useJobPostAttrRepo(namespace_collection) {
|
|
12479
|
+
const db = useAtlas29.getDb();
|
|
12480
|
+
if (!db) {
|
|
12481
|
+
throw new BadRequestError62("Unable to connect to server.");
|
|
12482
|
+
}
|
|
12483
|
+
const collection = db.collection(namespace_collection);
|
|
12484
|
+
const { getCache, setCache, delNamespace } = useCache22(namespace_collection);
|
|
12485
|
+
function delCachedData() {
|
|
12486
|
+
delNamespace().then(() => {
|
|
12487
|
+
logger35.log({
|
|
12488
|
+
level: "info",
|
|
12489
|
+
message: `Cache namespace cleared for ${namespace_collection}`
|
|
12490
|
+
});
|
|
12491
|
+
}).catch((err) => {
|
|
12492
|
+
logger35.log({
|
|
12493
|
+
level: "error",
|
|
12494
|
+
message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
|
|
12495
|
+
});
|
|
12496
|
+
});
|
|
12497
|
+
}
|
|
12498
|
+
async function createIndexes() {
|
|
12499
|
+
try {
|
|
12500
|
+
await collection.createIndexes([
|
|
12501
|
+
{ key: { name: 1 } },
|
|
12502
|
+
{ key: { createdAt: 1 } },
|
|
12503
|
+
{ key: { name: "text" } },
|
|
12504
|
+
{ key: { name: 1 }, unique: true, name: "unique_location" }
|
|
12505
|
+
]);
|
|
12506
|
+
return "Successfully created job post location indexes.";
|
|
12507
|
+
} catch (error) {
|
|
12508
|
+
throw new BadRequestError62("Failed to create job post location indexes.");
|
|
12509
|
+
}
|
|
12510
|
+
}
|
|
12511
|
+
async function add(value, session) {
|
|
12512
|
+
try {
|
|
12513
|
+
value = modelJobPostAttr(value);
|
|
12514
|
+
const res = await collection.insertOne(value, { session });
|
|
12515
|
+
delCachedData();
|
|
12516
|
+
return res.insertedId;
|
|
12517
|
+
} catch (error) {
|
|
12518
|
+
logger35.log({
|
|
12519
|
+
level: "error",
|
|
12520
|
+
message: error.message
|
|
12521
|
+
});
|
|
12522
|
+
throw new BadRequestError62(
|
|
12523
|
+
`Failed to create job post location: ${error.message}`
|
|
12524
|
+
);
|
|
12525
|
+
}
|
|
12526
|
+
}
|
|
12527
|
+
async function getAll({ search = "", page = 1, limit = 10 } = {}) {
|
|
12528
|
+
page = page > 0 ? page - 1 : 0;
|
|
12529
|
+
const query = {};
|
|
12530
|
+
if (search) {
|
|
11630
12531
|
query.$text = { $search: search };
|
|
11631
12532
|
}
|
|
12533
|
+
const cacheKey = makeCacheKey21(namespace_collection, {
|
|
12534
|
+
search,
|
|
12535
|
+
page,
|
|
12536
|
+
limit
|
|
12537
|
+
});
|
|
12538
|
+
logger35.log({
|
|
12539
|
+
level: "info",
|
|
12540
|
+
message: `Cache key for getAll job post locations: ${cacheKey}`
|
|
12541
|
+
});
|
|
11632
12542
|
try {
|
|
11633
|
-
const
|
|
11634
|
-
const cached = await getCache(
|
|
11635
|
-
cacheKey
|
|
11636
|
-
);
|
|
12543
|
+
const cached = await getCache(cacheKey);
|
|
11637
12544
|
if (cached) {
|
|
11638
|
-
|
|
12545
|
+
logger35.log({
|
|
11639
12546
|
level: "info",
|
|
11640
|
-
message: `Cache hit for
|
|
12547
|
+
message: `Cache hit for getAll job post locations: ${cacheKey}`
|
|
11641
12548
|
});
|
|
11642
12549
|
return cached;
|
|
11643
12550
|
}
|
|
11644
|
-
|
|
12551
|
+
let items = await collection.aggregate([
|
|
11645
12552
|
{ $match: query },
|
|
11646
12553
|
{ $skip: page * limit },
|
|
11647
|
-
{ $limit: limit }
|
|
11648
|
-
{
|
|
11649
|
-
$project: {
|
|
11650
|
-
_id: 1,
|
|
11651
|
-
title: 1,
|
|
11652
|
-
setup: 1,
|
|
11653
|
-
location: 1,
|
|
11654
|
-
type: 1,
|
|
11655
|
-
createdAt: 1
|
|
11656
|
-
}
|
|
11657
|
-
}
|
|
12554
|
+
{ $limit: limit }
|
|
11658
12555
|
]).toArray();
|
|
12556
|
+
if (items) {
|
|
12557
|
+
items = items.map((item) => item.name);
|
|
12558
|
+
}
|
|
11659
12559
|
const length = await collection.countDocuments(query);
|
|
11660
|
-
const data =
|
|
11661
|
-
setCache(cacheKey, data,
|
|
11662
|
-
|
|
12560
|
+
const data = paginate18(items, page, limit, length);
|
|
12561
|
+
setCache(cacheKey, data, 600).then(() => {
|
|
12562
|
+
logger35.log({
|
|
11663
12563
|
level: "info",
|
|
11664
|
-
message: `Cache set for
|
|
12564
|
+
message: `Cache set for getAll job post locations: ${cacheKey}`
|
|
11665
12565
|
});
|
|
11666
12566
|
}).catch((err) => {
|
|
11667
|
-
|
|
12567
|
+
logger35.log({
|
|
11668
12568
|
level: "error",
|
|
11669
|
-
message: `Failed to set cache for
|
|
12569
|
+
message: `Failed to set cache for getAll job post locations: ${err.message}`
|
|
11670
12570
|
});
|
|
11671
12571
|
});
|
|
11672
12572
|
return data;
|
|
11673
12573
|
} catch (error) {
|
|
11674
|
-
|
|
11675
|
-
|
|
11676
|
-
);
|
|
12574
|
+
logger35.log({ level: "error", message: `${error}` });
|
|
12575
|
+
throw error;
|
|
11677
12576
|
}
|
|
11678
12577
|
}
|
|
11679
|
-
async function
|
|
11680
|
-
|
|
11681
|
-
|
|
11682
|
-
|
|
11683
|
-
|
|
11684
|
-
}
|
|
11685
|
-
const cacheKey = makeCacheKey19(namespace_collection, { _id: String(_id) });
|
|
12578
|
+
async function getByName(name) {
|
|
12579
|
+
const cacheKey = makeCacheKey21(namespace_collection, {
|
|
12580
|
+
name,
|
|
12581
|
+
tag: "by-name"
|
|
12582
|
+
});
|
|
11686
12583
|
try {
|
|
11687
12584
|
const cached = await getCache(cacheKey);
|
|
11688
12585
|
if (cached) {
|
|
11689
|
-
|
|
12586
|
+
logger35.log({
|
|
11690
12587
|
level: "info",
|
|
11691
|
-
message: `Cache hit for getById job post: ${cacheKey}`
|
|
12588
|
+
message: `Cache hit for getById job post location: ${cacheKey}`
|
|
11692
12589
|
});
|
|
11693
12590
|
return cached;
|
|
11694
12591
|
}
|
|
11695
|
-
const result = await collection.findOne({
|
|
11696
|
-
if (!result) {
|
|
11697
|
-
throw new BadRequestError56("Job post not found.");
|
|
11698
|
-
}
|
|
12592
|
+
const result = await collection.findOne({ name });
|
|
11699
12593
|
setCache(cacheKey, result, 300).then(() => {
|
|
11700
|
-
|
|
12594
|
+
logger35.log({
|
|
11701
12595
|
level: "info",
|
|
11702
|
-
message: `Cache set for job post by
|
|
12596
|
+
message: `Cache set for job post by location: ${cacheKey}`
|
|
11703
12597
|
});
|
|
11704
12598
|
}).catch((err) => {
|
|
11705
|
-
|
|
12599
|
+
logger35.log({
|
|
11706
12600
|
level: "error",
|
|
11707
|
-
message: `Failed to set cache for job post by
|
|
12601
|
+
message: `Failed to set cache for job post by location: ${err.message}`
|
|
11708
12602
|
});
|
|
11709
12603
|
});
|
|
11710
12604
|
return result;
|
|
11711
12605
|
} catch (error) {
|
|
11712
|
-
if (error instanceof
|
|
12606
|
+
if (error instanceof AppError30) {
|
|
11713
12607
|
throw error;
|
|
11714
12608
|
} else {
|
|
11715
|
-
throw new
|
|
12609
|
+
throw new InternalServerError32("Failed to get job post.");
|
|
11716
12610
|
}
|
|
11717
12611
|
}
|
|
11718
12612
|
}
|
|
11719
|
-
async function updateById(_id, options) {
|
|
11720
|
-
const { error } = schemaJobPostUpdate.validate({ ...options, _id });
|
|
11721
|
-
if (error) {
|
|
11722
|
-
throw new BadRequestError56(error.message);
|
|
11723
|
-
}
|
|
11724
|
-
try {
|
|
11725
|
-
_id = new ObjectId28(_id);
|
|
11726
|
-
} catch (error2) {
|
|
11727
|
-
throw new BadRequestError56("Invalid JobPost ID.");
|
|
11728
|
-
}
|
|
11729
|
-
try {
|
|
11730
|
-
await collection.updateOne(
|
|
11731
|
-
{ _id },
|
|
11732
|
-
{ $set: { ...options, updatedAt: /* @__PURE__ */ new Date() } }
|
|
11733
|
-
);
|
|
11734
|
-
delCachedData();
|
|
11735
|
-
return "Successfully updated job post.";
|
|
11736
|
-
} catch (error2) {
|
|
11737
|
-
throw new InternalServerError30("Failed to update job post.");
|
|
11738
|
-
}
|
|
11739
|
-
}
|
|
11740
|
-
async function deleteById(_id, session) {
|
|
11741
|
-
try {
|
|
11742
|
-
_id = new ObjectId28(_id);
|
|
11743
|
-
} catch (error) {
|
|
11744
|
-
throw new BadRequestError56("Invalid ID.");
|
|
11745
|
-
}
|
|
11746
|
-
try {
|
|
11747
|
-
await collection.updateOne(
|
|
11748
|
-
{ _id },
|
|
11749
|
-
{
|
|
11750
|
-
$set: {
|
|
11751
|
-
status: "deleted",
|
|
11752
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
11753
|
-
deletedAt: /* @__PURE__ */ new Date()
|
|
11754
|
-
}
|
|
11755
|
-
},
|
|
11756
|
-
{ session }
|
|
11757
|
-
);
|
|
11758
|
-
delCachedData();
|
|
11759
|
-
return "Successfully deleted job post.";
|
|
11760
|
-
} catch (error) {
|
|
11761
|
-
throw new InternalServerError30("Failed to delete job post.");
|
|
11762
|
-
}
|
|
11763
|
-
}
|
|
11764
12613
|
return {
|
|
11765
12614
|
createIndexes,
|
|
12615
|
+
delCachedData,
|
|
11766
12616
|
add,
|
|
11767
12617
|
getAll,
|
|
11768
|
-
|
|
11769
|
-
getById,
|
|
11770
|
-
updateById,
|
|
11771
|
-
deleteById
|
|
12618
|
+
getByName
|
|
11772
12619
|
};
|
|
11773
12620
|
}
|
|
11774
12621
|
|
|
11775
12622
|
// src/resources/job-post/job.post.service.ts
|
|
11776
|
-
import {
|
|
11777
|
-
AppError as AppError28,
|
|
11778
|
-
BadRequestError as BadRequestError57,
|
|
11779
|
-
InternalServerError as InternalServerError31
|
|
11780
|
-
} from "@goweekdays/utils";
|
|
11781
|
-
import Joi48 from "joi";
|
|
11782
12623
|
function useJobPostService() {
|
|
11783
|
-
const {
|
|
12624
|
+
const {
|
|
12625
|
+
add: _add,
|
|
12626
|
+
deleteById: _deleteById,
|
|
12627
|
+
getById: _getById,
|
|
12628
|
+
updateStatusById: _updateStatusById
|
|
12629
|
+
} = useJobPostRepo();
|
|
12630
|
+
const { getById: getOrgById } = useOrgRepo();
|
|
12631
|
+
const { getByName: getLocationByName, add: addLocation } = useJobPostAttrRepo("job.post.locations");
|
|
12632
|
+
const { getByName: getJobTitleByName, add: addJobTitle } = useJobPostAttrRepo("job.post.titles");
|
|
12633
|
+
const { getByName: getCurrencyByName, add: addCurrency } = useJobPostAttrRepo(
|
|
12634
|
+
"job.post.currencies"
|
|
12635
|
+
);
|
|
12636
|
+
async function add(value) {
|
|
12637
|
+
const session = useAtlas30.getClient()?.startSession();
|
|
12638
|
+
if (!session) {
|
|
12639
|
+
throw new InternalServerError33("Failed to start database session.");
|
|
12640
|
+
}
|
|
12641
|
+
try {
|
|
12642
|
+
session.startTransaction();
|
|
12643
|
+
const org = await getOrgById(String(value.org));
|
|
12644
|
+
if (!org) {
|
|
12645
|
+
throw new BadRequestError63("Organization not found.");
|
|
12646
|
+
}
|
|
12647
|
+
const location = await getLocationByName(value.location);
|
|
12648
|
+
if (!location) {
|
|
12649
|
+
await addLocation({ name: value.location }, session);
|
|
12650
|
+
}
|
|
12651
|
+
const jobTitle = await getJobTitleByName(value.title);
|
|
12652
|
+
if (!jobTitle) {
|
|
12653
|
+
await addJobTitle({ name: value.title }, session);
|
|
12654
|
+
}
|
|
12655
|
+
if (value.currency) {
|
|
12656
|
+
const currency = await getCurrencyByName(value.currency);
|
|
12657
|
+
if (!currency) {
|
|
12658
|
+
await addCurrency({ name: value.currency }, session);
|
|
12659
|
+
}
|
|
12660
|
+
}
|
|
12661
|
+
value.orgName = org.name;
|
|
12662
|
+
await _add(value, session);
|
|
12663
|
+
await session.commitTransaction();
|
|
12664
|
+
return "Successfully created job post.";
|
|
12665
|
+
} catch (error) {
|
|
12666
|
+
await session.abortTransaction();
|
|
12667
|
+
if (error instanceof AppError31) {
|
|
12668
|
+
throw error;
|
|
12669
|
+
}
|
|
12670
|
+
throw new InternalServerError33("Failed to create job post.");
|
|
12671
|
+
} finally {
|
|
12672
|
+
await session.endSession();
|
|
12673
|
+
}
|
|
12674
|
+
}
|
|
11784
12675
|
async function deleteById(id) {
|
|
11785
|
-
const { error } =
|
|
12676
|
+
const { error } = Joi52.string().hex().required().validate(id);
|
|
11786
12677
|
if (error) {
|
|
11787
|
-
throw new
|
|
12678
|
+
throw new BadRequestError63(error.message);
|
|
11788
12679
|
}
|
|
11789
12680
|
try {
|
|
11790
12681
|
await _deleteById(id);
|
|
11791
12682
|
return "Successfully deleted job post.";
|
|
11792
12683
|
} catch (error2) {
|
|
11793
|
-
if (error2 instanceof
|
|
12684
|
+
if (error2 instanceof AppError31) {
|
|
11794
12685
|
throw error2;
|
|
11795
12686
|
} else {
|
|
11796
|
-
throw new
|
|
12687
|
+
throw new InternalServerError33("Failed to delete job post.");
|
|
12688
|
+
}
|
|
12689
|
+
}
|
|
12690
|
+
}
|
|
12691
|
+
async function updateStatusById(id, newStatus) {
|
|
12692
|
+
const jobPost = await _getById(id);
|
|
12693
|
+
if (!jobPost) {
|
|
12694
|
+
throw new BadRequestError63("Job post not found.");
|
|
12695
|
+
}
|
|
12696
|
+
const currentStatus = jobPost.status ?? "draft";
|
|
12697
|
+
const allowedTransitions = {
|
|
12698
|
+
draft: ["open", "in-review", "deleted"],
|
|
12699
|
+
open: ["paused", "closed"],
|
|
12700
|
+
paused: ["open", "in-review", "deleted"],
|
|
12701
|
+
"in-review": ["open"],
|
|
12702
|
+
closed: ["open", "in-review", "draft", "deleted"]
|
|
12703
|
+
};
|
|
12704
|
+
const allowed = allowedTransitions[currentStatus];
|
|
12705
|
+
if (!allowed || !allowed.includes(newStatus)) {
|
|
12706
|
+
throw new BadRequestError63(
|
|
12707
|
+
`Cannot change status from "${currentStatus}" to "${newStatus}".`
|
|
12708
|
+
);
|
|
12709
|
+
}
|
|
12710
|
+
try {
|
|
12711
|
+
await _updateStatusById(id, newStatus);
|
|
12712
|
+
return "Successfully updated job post status.";
|
|
12713
|
+
} catch (error) {
|
|
12714
|
+
if (error instanceof AppError31) {
|
|
12715
|
+
throw error;
|
|
11797
12716
|
}
|
|
12717
|
+
throw new InternalServerError33("Failed to update job post status.");
|
|
11798
12718
|
}
|
|
11799
12719
|
}
|
|
11800
12720
|
return {
|
|
11801
|
-
|
|
12721
|
+
add,
|
|
12722
|
+
deleteById,
|
|
12723
|
+
updateStatusById
|
|
11802
12724
|
};
|
|
11803
12725
|
}
|
|
11804
12726
|
|
|
11805
12727
|
// src/resources/job-post/job.post.controller.ts
|
|
11806
12728
|
function useJobPostController() {
|
|
11807
12729
|
const {
|
|
11808
|
-
add: _add,
|
|
11809
12730
|
getAll: _getAll,
|
|
11810
12731
|
getJobPostsByOrg: _getJobPostsByOrg,
|
|
11811
12732
|
getById: _getById,
|
|
11812
12733
|
updateById: _updateById
|
|
11813
12734
|
} = useJobPostRepo();
|
|
11814
|
-
const {
|
|
12735
|
+
const {
|
|
12736
|
+
add: _add,
|
|
12737
|
+
deleteById: _deleteById,
|
|
12738
|
+
updateStatusById: _updateStatusById
|
|
12739
|
+
} = useJobPostService();
|
|
11815
12740
|
async function add(req, res, next) {
|
|
11816
12741
|
const value = req.body;
|
|
11817
12742
|
const { error } = schemaJobPost.validate(value);
|
|
11818
12743
|
if (error) {
|
|
11819
|
-
next(new
|
|
11820
|
-
|
|
12744
|
+
next(new BadRequestError64(error.message));
|
|
12745
|
+
logger36.info(`Controller: ${error.message}`);
|
|
11821
12746
|
return;
|
|
11822
12747
|
}
|
|
11823
12748
|
try {
|
|
11824
|
-
const
|
|
11825
|
-
res.json({ message
|
|
12749
|
+
const message = await _add(value);
|
|
12750
|
+
res.json({ message });
|
|
11826
12751
|
return;
|
|
11827
12752
|
} catch (error2) {
|
|
11828
12753
|
next(error2);
|
|
@@ -11830,29 +12755,29 @@ function useJobPostController() {
|
|
|
11830
12755
|
}
|
|
11831
12756
|
async function getAll(req, res, next) {
|
|
11832
12757
|
const query = req.query;
|
|
11833
|
-
const validation =
|
|
11834
|
-
page:
|
|
11835
|
-
limit:
|
|
11836
|
-
search:
|
|
11837
|
-
status:
|
|
12758
|
+
const validation = Joi53.object({
|
|
12759
|
+
page: Joi53.number().min(1).optional().allow("", null),
|
|
12760
|
+
limit: Joi53.number().min(1).optional().allow("", null),
|
|
12761
|
+
search: Joi53.string().optional().allow("", null),
|
|
12762
|
+
status: Joi53.string().optional()
|
|
11838
12763
|
});
|
|
11839
12764
|
const { error } = validation.validate(query);
|
|
11840
12765
|
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
11841
12766
|
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
11842
12767
|
const search = req.query.search ?? "";
|
|
11843
|
-
const status = req.query.status ?? "
|
|
12768
|
+
const status = req.query.status ?? "open";
|
|
11844
12769
|
const isPageNumber = isFinite(page);
|
|
11845
12770
|
if (!isPageNumber) {
|
|
11846
|
-
next(new
|
|
12771
|
+
next(new BadRequestError64("Invalid page number."));
|
|
11847
12772
|
return;
|
|
11848
12773
|
}
|
|
11849
12774
|
const isLimitNumber = isFinite(limit);
|
|
11850
12775
|
if (!isLimitNumber) {
|
|
11851
|
-
next(new
|
|
12776
|
+
next(new BadRequestError64("Invalid limit number."));
|
|
11852
12777
|
return;
|
|
11853
12778
|
}
|
|
11854
12779
|
if (error) {
|
|
11855
|
-
next(new
|
|
12780
|
+
next(new BadRequestError64(error.message));
|
|
11856
12781
|
return;
|
|
11857
12782
|
}
|
|
11858
12783
|
try {
|
|
@@ -11871,28 +12796,34 @@ function useJobPostController() {
|
|
|
11871
12796
|
const org = req.params.org ?? "";
|
|
11872
12797
|
const isPageNumber = isFinite(page);
|
|
11873
12798
|
if (!isPageNumber) {
|
|
11874
|
-
next(new
|
|
12799
|
+
next(new BadRequestError64("Invalid page number."));
|
|
11875
12800
|
return;
|
|
11876
12801
|
}
|
|
11877
12802
|
const isLimitNumber = isFinite(limit);
|
|
11878
12803
|
if (!isLimitNumber) {
|
|
11879
|
-
next(new
|
|
12804
|
+
next(new BadRequestError64("Invalid limit number."));
|
|
11880
12805
|
return;
|
|
11881
12806
|
}
|
|
11882
|
-
const validation =
|
|
11883
|
-
org:
|
|
11884
|
-
page:
|
|
11885
|
-
limit:
|
|
11886
|
-
search:
|
|
11887
|
-
status:
|
|
12807
|
+
const validation = Joi53.object({
|
|
12808
|
+
org: Joi53.string().hex().required(),
|
|
12809
|
+
page: Joi53.number().min(1).optional().allow("", null),
|
|
12810
|
+
limit: Joi53.number().min(1).optional().allow("", null),
|
|
12811
|
+
search: Joi53.string().optional().allow("", null),
|
|
12812
|
+
status: Joi53.string().optional()
|
|
11888
12813
|
});
|
|
11889
12814
|
const { error } = validation.validate({ org, page, limit, search, status });
|
|
11890
12815
|
if (error) {
|
|
11891
|
-
next(new
|
|
12816
|
+
next(new BadRequestError64(error.message));
|
|
11892
12817
|
return;
|
|
11893
12818
|
}
|
|
11894
12819
|
try {
|
|
11895
|
-
const jobPosts = await _getJobPostsByOrg({
|
|
12820
|
+
const jobPosts = await _getJobPostsByOrg({
|
|
12821
|
+
org,
|
|
12822
|
+
page,
|
|
12823
|
+
limit,
|
|
12824
|
+
search,
|
|
12825
|
+
status
|
|
12826
|
+
});
|
|
11896
12827
|
res.json(jobPosts);
|
|
11897
12828
|
return;
|
|
11898
12829
|
} catch (error2) {
|
|
@@ -11901,12 +12832,12 @@ function useJobPostController() {
|
|
|
11901
12832
|
}
|
|
11902
12833
|
async function getById(req, res, next) {
|
|
11903
12834
|
const id = req.params.id;
|
|
11904
|
-
const validation =
|
|
11905
|
-
id:
|
|
12835
|
+
const validation = Joi53.object({
|
|
12836
|
+
id: Joi53.string().hex().required()
|
|
11906
12837
|
});
|
|
11907
12838
|
const { error } = validation.validate({ id });
|
|
11908
12839
|
if (error) {
|
|
11909
|
-
next(new
|
|
12840
|
+
next(new BadRequestError64(error.message));
|
|
11910
12841
|
return;
|
|
11911
12842
|
}
|
|
11912
12843
|
try {
|
|
@@ -11922,7 +12853,7 @@ function useJobPostController() {
|
|
|
11922
12853
|
const payload = req.body;
|
|
11923
12854
|
const { error } = schemaJobPostUpdate.validate({ _id, ...payload });
|
|
11924
12855
|
if (error) {
|
|
11925
|
-
next(new
|
|
12856
|
+
next(new BadRequestError64(error.message));
|
|
11926
12857
|
return;
|
|
11927
12858
|
}
|
|
11928
12859
|
try {
|
|
@@ -11936,7 +12867,7 @@ function useJobPostController() {
|
|
|
11936
12867
|
async function deleteById(req, res, next) {
|
|
11937
12868
|
const id = req.params.id;
|
|
11938
12869
|
if (!id) {
|
|
11939
|
-
next(new
|
|
12870
|
+
next(new BadRequestError64("Job Post ID is required."));
|
|
11940
12871
|
return;
|
|
11941
12872
|
}
|
|
11942
12873
|
try {
|
|
@@ -11947,13 +12878,141 @@ function useJobPostController() {
|
|
|
11947
12878
|
next(error);
|
|
11948
12879
|
}
|
|
11949
12880
|
}
|
|
12881
|
+
async function updateStatusById(req, res, next) {
|
|
12882
|
+
const id = req.params.id;
|
|
12883
|
+
const status = req.params.status;
|
|
12884
|
+
const validation = Joi53.object({
|
|
12885
|
+
id: Joi53.string().hex().required(),
|
|
12886
|
+
status: Joi53.string().valid("draft", "open", "paused", "in-review", "closed").required()
|
|
12887
|
+
});
|
|
12888
|
+
const { error } = validation.validate({ id, status });
|
|
12889
|
+
if (error) {
|
|
12890
|
+
next(new BadRequestError64(error.message));
|
|
12891
|
+
return;
|
|
12892
|
+
}
|
|
12893
|
+
try {
|
|
12894
|
+
const message = await _updateStatusById(id, status);
|
|
12895
|
+
res.json({ message });
|
|
12896
|
+
return;
|
|
12897
|
+
} catch (error2) {
|
|
12898
|
+
next(error2);
|
|
12899
|
+
}
|
|
12900
|
+
}
|
|
12901
|
+
const { getAll: _getAllLocation } = useJobPostAttrRepo("job.post.locations");
|
|
12902
|
+
async function getLocations(req, res, next) {
|
|
12903
|
+
const query = req.query;
|
|
12904
|
+
const validation = Joi53.object({
|
|
12905
|
+
page: Joi53.number().min(1).optional().allow("", null),
|
|
12906
|
+
limit: Joi53.number().min(1).optional().allow("", null),
|
|
12907
|
+
search: Joi53.string().optional().allow("", null)
|
|
12908
|
+
});
|
|
12909
|
+
const { error } = validation.validate(query);
|
|
12910
|
+
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
12911
|
+
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
12912
|
+
const search = req.query.search ?? "";
|
|
12913
|
+
const isPageNumber = isFinite(page);
|
|
12914
|
+
if (!isPageNumber) {
|
|
12915
|
+
next(new BadRequestError64("Invalid page number."));
|
|
12916
|
+
return;
|
|
12917
|
+
}
|
|
12918
|
+
const isLimitNumber = isFinite(limit);
|
|
12919
|
+
if (!isLimitNumber) {
|
|
12920
|
+
next(new BadRequestError64("Invalid limit number."));
|
|
12921
|
+
return;
|
|
12922
|
+
}
|
|
12923
|
+
if (error) {
|
|
12924
|
+
next(new BadRequestError64(error.message));
|
|
12925
|
+
return;
|
|
12926
|
+
}
|
|
12927
|
+
try {
|
|
12928
|
+
const locations = await _getAllLocation({ page, limit, search });
|
|
12929
|
+
res.json(locations);
|
|
12930
|
+
return;
|
|
12931
|
+
} catch (error2) {
|
|
12932
|
+
next(error2);
|
|
12933
|
+
}
|
|
12934
|
+
}
|
|
12935
|
+
const { getAll: _getAllJobTitles } = useJobPostAttrRepo("job.post.titles");
|
|
12936
|
+
async function getJobTitles(req, res, next) {
|
|
12937
|
+
const query = req.query;
|
|
12938
|
+
const validation = Joi53.object({
|
|
12939
|
+
page: Joi53.number().min(1).optional().allow("", null),
|
|
12940
|
+
limit: Joi53.number().min(1).optional().allow("", null),
|
|
12941
|
+
search: Joi53.string().optional().allow("", null)
|
|
12942
|
+
});
|
|
12943
|
+
const { error } = validation.validate(query);
|
|
12944
|
+
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
12945
|
+
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
12946
|
+
const search = req.query.search ?? "";
|
|
12947
|
+
const isPageNumber = isFinite(page);
|
|
12948
|
+
if (!isPageNumber) {
|
|
12949
|
+
next(new BadRequestError64("Invalid page number."));
|
|
12950
|
+
return;
|
|
12951
|
+
}
|
|
12952
|
+
const isLimitNumber = isFinite(limit);
|
|
12953
|
+
if (!isLimitNumber) {
|
|
12954
|
+
next(new BadRequestError64("Invalid limit number."));
|
|
12955
|
+
return;
|
|
12956
|
+
}
|
|
12957
|
+
if (error) {
|
|
12958
|
+
next(new BadRequestError64(error.message));
|
|
12959
|
+
return;
|
|
12960
|
+
}
|
|
12961
|
+
try {
|
|
12962
|
+
const locations = await _getAllJobTitles({ page, limit, search });
|
|
12963
|
+
res.json(locations);
|
|
12964
|
+
return;
|
|
12965
|
+
} catch (error2) {
|
|
12966
|
+
next(error2);
|
|
12967
|
+
}
|
|
12968
|
+
}
|
|
12969
|
+
const { getAll: _getAllCurrencies } = useJobPostAttrRepo(
|
|
12970
|
+
"job.post.currencies"
|
|
12971
|
+
);
|
|
12972
|
+
async function getCurrencies(req, res, next) {
|
|
12973
|
+
const query = req.query;
|
|
12974
|
+
const validation = Joi53.object({
|
|
12975
|
+
page: Joi53.number().min(1).optional().allow("", null),
|
|
12976
|
+
limit: Joi53.number().min(1).optional().allow("", null),
|
|
12977
|
+
search: Joi53.string().optional().allow("", null)
|
|
12978
|
+
});
|
|
12979
|
+
const { error } = validation.validate(query);
|
|
12980
|
+
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
12981
|
+
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
12982
|
+
const search = req.query.search ?? "";
|
|
12983
|
+
const isPageNumber = isFinite(page);
|
|
12984
|
+
if (!isPageNumber) {
|
|
12985
|
+
next(new BadRequestError64("Invalid page number."));
|
|
12986
|
+
return;
|
|
12987
|
+
}
|
|
12988
|
+
const isLimitNumber = isFinite(limit);
|
|
12989
|
+
if (!isLimitNumber) {
|
|
12990
|
+
next(new BadRequestError64("Invalid limit number."));
|
|
12991
|
+
return;
|
|
12992
|
+
}
|
|
12993
|
+
if (error) {
|
|
12994
|
+
next(new BadRequestError64(error.message));
|
|
12995
|
+
return;
|
|
12996
|
+
}
|
|
12997
|
+
try {
|
|
12998
|
+
const locations = await _getAllCurrencies({ page, limit, search });
|
|
12999
|
+
res.json(locations);
|
|
13000
|
+
return;
|
|
13001
|
+
} catch (error2) {
|
|
13002
|
+
next(error2);
|
|
13003
|
+
}
|
|
13004
|
+
}
|
|
11950
13005
|
return {
|
|
11951
13006
|
add,
|
|
11952
13007
|
getAll,
|
|
11953
13008
|
getJobPostsByOrg,
|
|
11954
13009
|
getById,
|
|
11955
13010
|
updateById,
|
|
11956
|
-
deleteById
|
|
13011
|
+
deleteById,
|
|
13012
|
+
updateStatusById,
|
|
13013
|
+
getLocations,
|
|
13014
|
+
getJobTitles,
|
|
13015
|
+
getCurrencies
|
|
11957
13016
|
};
|
|
11958
13017
|
}
|
|
11959
13018
|
export {
|
|
@@ -12083,6 +13142,7 @@ export {
|
|
|
12083
13142
|
usePlanController,
|
|
12084
13143
|
usePlanRepo,
|
|
12085
13144
|
usePlanService,
|
|
13145
|
+
usePromoController,
|
|
12086
13146
|
usePromoRepo,
|
|
12087
13147
|
useRoleController,
|
|
12088
13148
|
useRoleRepo,
|