@iservice365/module-hygiene 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/index.d.ts +118 -8
- package/dist/index.js +665 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +674 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -33,14 +33,19 @@ __export(src_exports, {
|
|
|
33
33
|
MArea: () => MArea,
|
|
34
34
|
MAreaChecklist: () => MAreaChecklist,
|
|
35
35
|
MParentChecklist: () => MParentChecklist,
|
|
36
|
+
MRequestItem: () => MRequestItem,
|
|
37
|
+
MStock: () => MStock,
|
|
36
38
|
MSupply: () => MSupply,
|
|
37
39
|
MUnit: () => MUnit,
|
|
38
40
|
allowedChecklistStatus: () => allowedChecklistStatus,
|
|
41
|
+
allowedRequestItemStatus: () => allowedRequestItemStatus,
|
|
39
42
|
allowedStatus: () => allowedStatus,
|
|
40
43
|
allowedTypes: () => allowedTypes,
|
|
41
44
|
areaChecklistSchema: () => areaChecklistSchema,
|
|
42
45
|
areaSchema: () => areaSchema,
|
|
43
46
|
parentChecklistSchema: () => parentChecklistSchema,
|
|
47
|
+
requestItemSchema: () => requestItemSchema,
|
|
48
|
+
stockSchema: () => stockSchema,
|
|
44
49
|
supplySchema: () => supplySchema,
|
|
45
50
|
unitSchema: () => unitSchema,
|
|
46
51
|
useAreaChecklistController: () => useAreaChecklistController,
|
|
@@ -51,6 +56,12 @@ __export(src_exports, {
|
|
|
51
56
|
useAreaService: () => useAreaService,
|
|
52
57
|
useParentChecklistController: () => useParentChecklistController,
|
|
53
58
|
useParentChecklistRepo: () => useParentChecklistRepo,
|
|
59
|
+
useRequestItemController: () => useRequestItemController,
|
|
60
|
+
useRequestItemRepository: () => useRequestItemRepository,
|
|
61
|
+
useRequestItemService: () => useRequestItemService,
|
|
62
|
+
useStockController: () => useStockController,
|
|
63
|
+
useStockRepository: () => useStockRepository,
|
|
64
|
+
useStockService: () => useStockService,
|
|
54
65
|
useSupplyController: () => useSupplyController,
|
|
55
66
|
useSupplyRepository: () => useSupplyRepository,
|
|
56
67
|
useUnitController: () => useUnitController,
|
|
@@ -692,7 +703,7 @@ function useAreaController() {
|
|
|
692
703
|
return;
|
|
693
704
|
}
|
|
694
705
|
const page = parseInt(req.query.page) ?? 1;
|
|
695
|
-
const limit = parseInt(req.query.limit) ??
|
|
706
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
696
707
|
const search = req.query.search ?? "";
|
|
697
708
|
const site = req.params.site ?? "";
|
|
698
709
|
try {
|
|
@@ -1228,7 +1239,7 @@ function useUnitController() {
|
|
|
1228
1239
|
return;
|
|
1229
1240
|
}
|
|
1230
1241
|
const page = parseInt(req.query.page) ?? 1;
|
|
1231
|
-
const limit = parseInt(req.query.limit) ??
|
|
1242
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
1232
1243
|
const search = req.query.search ?? "";
|
|
1233
1244
|
const site = req.params.site ?? "";
|
|
1234
1245
|
try {
|
|
@@ -1634,7 +1645,7 @@ function useParentChecklistController() {
|
|
|
1634
1645
|
return;
|
|
1635
1646
|
}
|
|
1636
1647
|
const page = parseInt(req.query.page) ?? 1;
|
|
1637
|
-
const limit = parseInt(req.query.limit) ??
|
|
1648
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
1638
1649
|
const search = req.query.search ?? "";
|
|
1639
1650
|
const site = req.params.site ?? "";
|
|
1640
1651
|
const startDate = req.query.startDate ?? "";
|
|
@@ -2645,7 +2656,7 @@ function useAreaChecklistController() {
|
|
|
2645
2656
|
return;
|
|
2646
2657
|
}
|
|
2647
2658
|
const page = parseInt(req.query.page) ?? 1;
|
|
2648
|
-
const limit = parseInt(req.query.limit) ??
|
|
2659
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
2649
2660
|
const search = req.query.search ?? "";
|
|
2650
2661
|
const type = req.query.type ?? "";
|
|
2651
2662
|
const schedule = req.params.schedule ?? "";
|
|
@@ -2683,7 +2694,7 @@ function useAreaChecklistController() {
|
|
|
2683
2694
|
return;
|
|
2684
2695
|
}
|
|
2685
2696
|
const page = parseInt(req.query.page) ?? 1;
|
|
2686
|
-
const limit = parseInt(req.query.limit) ??
|
|
2697
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
2687
2698
|
const search = req.query.search ?? "";
|
|
2688
2699
|
const type = req.query.type ?? "";
|
|
2689
2700
|
const schedule = req.params.schedule ?? "";
|
|
@@ -2741,7 +2752,7 @@ function useAreaChecklistController() {
|
|
|
2741
2752
|
return;
|
|
2742
2753
|
}
|
|
2743
2754
|
const page = parseInt(req.query.page) ?? 1;
|
|
2744
|
-
const limit = parseInt(req.query.limit) ??
|
|
2755
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
2745
2756
|
const search = req.query.search ?? "";
|
|
2746
2757
|
const _id = req.params.id ?? "";
|
|
2747
2758
|
try {
|
|
@@ -2816,8 +2827,7 @@ var import_mongodb9 = require("mongodb");
|
|
|
2816
2827
|
var supplySchema = import_joi9.default.object({
|
|
2817
2828
|
site: import_joi9.default.string().hex().required(),
|
|
2818
2829
|
name: import_joi9.default.string().required(),
|
|
2819
|
-
unitOfMeasurement: import_joi9.default.string().required()
|
|
2820
|
-
qty: import_joi9.default.number().min(0).required()
|
|
2830
|
+
unitOfMeasurement: import_joi9.default.string().required()
|
|
2821
2831
|
});
|
|
2822
2832
|
function MSupply(value) {
|
|
2823
2833
|
const { error } = supplySchema.validate(value);
|
|
@@ -2836,9 +2846,9 @@ function MSupply(value) {
|
|
|
2836
2846
|
site: value.site,
|
|
2837
2847
|
name: value.name,
|
|
2838
2848
|
unitOfMeasurement: value.unitOfMeasurement,
|
|
2839
|
-
qty:
|
|
2840
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
2849
|
+
qty: 0,
|
|
2841
2850
|
status: "active",
|
|
2851
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2842
2852
|
updatedAt: "",
|
|
2843
2853
|
deletedAt: ""
|
|
2844
2854
|
};
|
|
@@ -2962,7 +2972,7 @@ function useSupplyRepository() {
|
|
|
2962
2972
|
throw error;
|
|
2963
2973
|
}
|
|
2964
2974
|
}
|
|
2965
|
-
async function getSupplyById(_id) {
|
|
2975
|
+
async function getSupplyById(_id, session) {
|
|
2966
2976
|
try {
|
|
2967
2977
|
_id = new import_mongodb10.ObjectId(_id);
|
|
2968
2978
|
} catch (error) {
|
|
@@ -2975,10 +2985,14 @@ function useSupplyRepository() {
|
|
|
2975
2985
|
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, {
|
|
2976
2986
|
_id: _id.toString()
|
|
2977
2987
|
});
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2988
|
+
if (!session) {
|
|
2989
|
+
const cachedData = await getCache(cacheKey);
|
|
2990
|
+
if (cachedData) {
|
|
2991
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2992
|
+
return cachedData;
|
|
2993
|
+
}
|
|
2994
|
+
} else {
|
|
2995
|
+
import_node_server_utils17.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
2982
2996
|
}
|
|
2983
2997
|
try {
|
|
2984
2998
|
const data = await collection.aggregate([
|
|
@@ -3126,7 +3140,7 @@ function useSupplyController() {
|
|
|
3126
3140
|
return;
|
|
3127
3141
|
}
|
|
3128
3142
|
const page = parseInt(req.query.page) ?? 1;
|
|
3129
|
-
const limit = parseInt(req.query.limit) ??
|
|
3143
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
3130
3144
|
const search = req.query.search ?? "";
|
|
3131
3145
|
const site = req.params.site ?? "";
|
|
3132
3146
|
try {
|
|
@@ -3217,19 +3231,648 @@ function useSupplyController() {
|
|
|
3217
3231
|
deleteSupply
|
|
3218
3232
|
};
|
|
3219
3233
|
}
|
|
3234
|
+
|
|
3235
|
+
// src/models/hygiene-stock.model.ts
|
|
3236
|
+
var import_node_server_utils19 = require("@iservice365/node-server-utils");
|
|
3237
|
+
var import_joi11 = __toESM(require("joi"));
|
|
3238
|
+
var import_mongodb11 = require("mongodb");
|
|
3239
|
+
var stockSchema = import_joi11.default.object({
|
|
3240
|
+
site: import_joi11.default.string().hex().required(),
|
|
3241
|
+
supply: import_joi11.default.string().hex().required(),
|
|
3242
|
+
in: import_joi11.default.number().min(0).optional(),
|
|
3243
|
+
out: import_joi11.default.number().min(0).optional(),
|
|
3244
|
+
balance: import_joi11.default.number().min(0).required(),
|
|
3245
|
+
remarks: import_joi11.default.string().optional().allow("", null)
|
|
3246
|
+
});
|
|
3247
|
+
function MStock(value) {
|
|
3248
|
+
const { error } = stockSchema.validate(value);
|
|
3249
|
+
if (error) {
|
|
3250
|
+
import_node_server_utils19.logger.info(`Hygiene Stock Model: ${error.message}`);
|
|
3251
|
+
throw new import_node_server_utils19.BadRequestError(error.message);
|
|
3252
|
+
}
|
|
3253
|
+
if (value.site) {
|
|
3254
|
+
try {
|
|
3255
|
+
value.site = new import_mongodb11.ObjectId(value.site);
|
|
3256
|
+
} catch (error2) {
|
|
3257
|
+
throw new import_node_server_utils19.BadRequestError("Invalid site ID format.");
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
if (value.supply) {
|
|
3261
|
+
try {
|
|
3262
|
+
value.supply = new import_mongodb11.ObjectId(value.supply);
|
|
3263
|
+
} catch (error2) {
|
|
3264
|
+
throw new import_node_server_utils19.BadRequestError("Invalid supply ID format.");
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
return {
|
|
3268
|
+
site: value.site,
|
|
3269
|
+
supply: value.supply,
|
|
3270
|
+
in: value.in ?? 0,
|
|
3271
|
+
out: value.out ?? 0,
|
|
3272
|
+
balance: value.balance,
|
|
3273
|
+
remarks: value.remarks ?? "",
|
|
3274
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3275
|
+
status: "active",
|
|
3276
|
+
updatedAt: "",
|
|
3277
|
+
deletedAt: ""
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
// src/repositories/hygiene-stock.repository.ts
|
|
3282
|
+
var import_mongodb12 = require("mongodb");
|
|
3283
|
+
var import_node_server_utils20 = require("@iservice365/node-server-utils");
|
|
3284
|
+
function useStockRepository() {
|
|
3285
|
+
const db = import_node_server_utils20.useAtlas.getDb();
|
|
3286
|
+
if (!db) {
|
|
3287
|
+
throw new import_node_server_utils20.InternalServerError("Unable to connect to server.");
|
|
3288
|
+
}
|
|
3289
|
+
const namespace_collection = "site.supply.stocks";
|
|
3290
|
+
const supply_collection = "site.supplies";
|
|
3291
|
+
const collection = db.collection(namespace_collection);
|
|
3292
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils20.useCache)(namespace_collection);
|
|
3293
|
+
const { delNamespace: delSupplyNamespace } = (0, import_node_server_utils20.useCache)(supply_collection);
|
|
3294
|
+
async function createIndex() {
|
|
3295
|
+
try {
|
|
3296
|
+
await collection.createIndexes([
|
|
3297
|
+
{ key: { site: 1 } },
|
|
3298
|
+
{ key: { supply: 1 } },
|
|
3299
|
+
{ key: { balance: 1 } },
|
|
3300
|
+
{ key: { status: 1 } }
|
|
3301
|
+
]);
|
|
3302
|
+
} catch (error) {
|
|
3303
|
+
throw new import_node_server_utils20.InternalServerError("Failed to create index on hygiene stock.");
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
3306
|
+
async function createStock(value, session) {
|
|
3307
|
+
try {
|
|
3308
|
+
value = MStock(value);
|
|
3309
|
+
const res = await collection.insertOne(value, { session });
|
|
3310
|
+
delNamespace().then(() => {
|
|
3311
|
+
import_node_server_utils20.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3312
|
+
}).catch((err) => {
|
|
3313
|
+
import_node_server_utils20.logger.error(
|
|
3314
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3315
|
+
err
|
|
3316
|
+
);
|
|
3317
|
+
});
|
|
3318
|
+
delSupplyNamespace().then(() => {
|
|
3319
|
+
import_node_server_utils20.logger.info(`Cache cleared for namespace: ${supply_collection}`);
|
|
3320
|
+
}).catch((err) => {
|
|
3321
|
+
import_node_server_utils20.logger.error(
|
|
3322
|
+
`Failed to clear cache for namespace: ${supply_collection}`,
|
|
3323
|
+
err
|
|
3324
|
+
);
|
|
3325
|
+
});
|
|
3326
|
+
return res.insertedId;
|
|
3327
|
+
} catch (error) {
|
|
3328
|
+
throw error;
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3331
|
+
async function getStocksBySupplyId({
|
|
3332
|
+
page = 1,
|
|
3333
|
+
limit = 10,
|
|
3334
|
+
search = "",
|
|
3335
|
+
site,
|
|
3336
|
+
supply
|
|
3337
|
+
}) {
|
|
3338
|
+
page = page > 0 ? page - 1 : 0;
|
|
3339
|
+
const query = {
|
|
3340
|
+
status: { $ne: "deleted" }
|
|
3341
|
+
};
|
|
3342
|
+
const cacheOptions = {
|
|
3343
|
+
page,
|
|
3344
|
+
limit
|
|
3345
|
+
};
|
|
3346
|
+
try {
|
|
3347
|
+
site = new import_mongodb12.ObjectId(site);
|
|
3348
|
+
query.site = site;
|
|
3349
|
+
cacheOptions.site = site.toString();
|
|
3350
|
+
} catch (error) {
|
|
3351
|
+
throw new import_node_server_utils20.BadRequestError("Invalid site ID format.");
|
|
3352
|
+
}
|
|
3353
|
+
try {
|
|
3354
|
+
supply = new import_mongodb12.ObjectId(supply);
|
|
3355
|
+
query.supply = supply;
|
|
3356
|
+
cacheOptions.supply = supply.toString();
|
|
3357
|
+
} catch (error) {
|
|
3358
|
+
throw new import_node_server_utils20.BadRequestError("Invalid supply ID format.");
|
|
3359
|
+
}
|
|
3360
|
+
if (search) {
|
|
3361
|
+
query.$text = { $search: search };
|
|
3362
|
+
cacheOptions.search = search;
|
|
3363
|
+
}
|
|
3364
|
+
const cacheKey = (0, import_node_server_utils20.makeCacheKey)(namespace_collection, cacheOptions);
|
|
3365
|
+
const cachedData = await getCache(cacheKey);
|
|
3366
|
+
if (cachedData) {
|
|
3367
|
+
import_node_server_utils20.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3368
|
+
return cachedData;
|
|
3369
|
+
}
|
|
3370
|
+
try {
|
|
3371
|
+
const items = await collection.aggregate([
|
|
3372
|
+
{ $match: query },
|
|
3373
|
+
{
|
|
3374
|
+
$project: {
|
|
3375
|
+
createdAt: 1,
|
|
3376
|
+
in: 1,
|
|
3377
|
+
out: 1,
|
|
3378
|
+
balance: 1
|
|
3379
|
+
}
|
|
3380
|
+
},
|
|
3381
|
+
{ $sort: { _id: 1 } },
|
|
3382
|
+
{ $skip: page * limit },
|
|
3383
|
+
{ $limit: limit }
|
|
3384
|
+
]).toArray();
|
|
3385
|
+
const length = await collection.countDocuments(query);
|
|
3386
|
+
const data = (0, import_node_server_utils20.paginate)(items, page, limit, length);
|
|
3387
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3388
|
+
import_node_server_utils20.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3389
|
+
}).catch((err) => {
|
|
3390
|
+
import_node_server_utils20.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3391
|
+
});
|
|
3392
|
+
return data;
|
|
3393
|
+
} catch (error) {
|
|
3394
|
+
throw error;
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
return {
|
|
3398
|
+
createIndex,
|
|
3399
|
+
createStock,
|
|
3400
|
+
getStocksBySupplyId
|
|
3401
|
+
};
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
// src/services/hygiene-stock.service.ts
|
|
3405
|
+
var import_node_server_utils21 = require("@iservice365/node-server-utils");
|
|
3406
|
+
function useStockService() {
|
|
3407
|
+
const { createStock: _createStock } = useStockRepository();
|
|
3408
|
+
const { getSupplyById, updateSupply } = useSupplyRepository();
|
|
3409
|
+
async function createStock(value, out = false) {
|
|
3410
|
+
const session = import_node_server_utils21.useAtlas.getClient()?.startSession();
|
|
3411
|
+
try {
|
|
3412
|
+
session?.startTransaction();
|
|
3413
|
+
const { qty, ...stockData } = value;
|
|
3414
|
+
const supply = await getSupplyById(value.supply, session);
|
|
3415
|
+
if (!supply || supply.qty === void 0) {
|
|
3416
|
+
throw new import_node_server_utils21.NotFoundError("Supply not found.");
|
|
3417
|
+
}
|
|
3418
|
+
const newSupplyQty = out ? supply.qty - qty : supply.qty + qty;
|
|
3419
|
+
if (out && newSupplyQty < 0) {
|
|
3420
|
+
throw new import_node_server_utils21.BadRequestError(
|
|
3421
|
+
`Insufficient stock. Available: ${supply.qty}, Requested: ${qty}`
|
|
3422
|
+
);
|
|
3423
|
+
}
|
|
3424
|
+
await updateSupply(value.supply, { qty: newSupplyQty }, session);
|
|
3425
|
+
const createdStock = await _createStock(
|
|
3426
|
+
{
|
|
3427
|
+
...stockData,
|
|
3428
|
+
in: out ? 0 : qty,
|
|
3429
|
+
out: out ? qty : 0,
|
|
3430
|
+
balance: newSupplyQty
|
|
3431
|
+
},
|
|
3432
|
+
session
|
|
3433
|
+
);
|
|
3434
|
+
await session?.commitTransaction();
|
|
3435
|
+
return createdStock;
|
|
3436
|
+
} catch (error) {
|
|
3437
|
+
await session?.abortTransaction();
|
|
3438
|
+
throw error;
|
|
3439
|
+
} finally {
|
|
3440
|
+
await session?.endSession();
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
return { createStock };
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3446
|
+
// src/controllers/hygiene-stock.controller.ts
|
|
3447
|
+
var import_node_server_utils22 = require("@iservice365/node-server-utils");
|
|
3448
|
+
var import_joi12 = __toESM(require("joi"));
|
|
3449
|
+
function useStockController() {
|
|
3450
|
+
const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
|
|
3451
|
+
const { createStock: _createStock } = useStockService();
|
|
3452
|
+
async function createStock(req, res, next) {
|
|
3453
|
+
const payload = { ...req.body, ...req.params };
|
|
3454
|
+
const validation = import_joi12.default.object({
|
|
3455
|
+
site: import_joi12.default.string().hex().required(),
|
|
3456
|
+
supply: import_joi12.default.string().hex().required(),
|
|
3457
|
+
qty: import_joi12.default.number().min(0).required(),
|
|
3458
|
+
remarks: import_joi12.default.string().optional().allow("", null)
|
|
3459
|
+
});
|
|
3460
|
+
const { error } = validation.validate(payload);
|
|
3461
|
+
if (error) {
|
|
3462
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
3463
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3464
|
+
return;
|
|
3465
|
+
}
|
|
3466
|
+
try {
|
|
3467
|
+
const id = await _createStock(payload);
|
|
3468
|
+
res.status(201).json({ message: "Stock created successfully.", id });
|
|
3469
|
+
return;
|
|
3470
|
+
} catch (error2) {
|
|
3471
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3472
|
+
next(error2);
|
|
3473
|
+
return;
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
async function getStocksBySupplyId(req, res, next) {
|
|
3477
|
+
const query = { ...req.query, ...req.params };
|
|
3478
|
+
const validation = import_joi12.default.object({
|
|
3479
|
+
page: import_joi12.default.number().min(1).optional().allow("", null),
|
|
3480
|
+
limit: import_joi12.default.number().min(1).optional().allow("", null),
|
|
3481
|
+
search: import_joi12.default.string().optional().allow("", null),
|
|
3482
|
+
site: import_joi12.default.string().hex().required(),
|
|
3483
|
+
supply: import_joi12.default.string().hex().required()
|
|
3484
|
+
});
|
|
3485
|
+
const { error } = validation.validate(query);
|
|
3486
|
+
if (error) {
|
|
3487
|
+
import_node_server_utils22.logger.log({ level: "error", message: error.message });
|
|
3488
|
+
next(new import_node_server_utils22.BadRequestError(error.message));
|
|
3489
|
+
return;
|
|
3490
|
+
}
|
|
3491
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
3492
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
3493
|
+
const search = req.query.search ?? "";
|
|
3494
|
+
const site = req.params.site ?? "";
|
|
3495
|
+
const supply = req.params.supply ?? "";
|
|
3496
|
+
try {
|
|
3497
|
+
const data = await _getStocksBySupplyId({
|
|
3498
|
+
page,
|
|
3499
|
+
limit,
|
|
3500
|
+
search,
|
|
3501
|
+
site,
|
|
3502
|
+
supply
|
|
3503
|
+
});
|
|
3504
|
+
res.json(data);
|
|
3505
|
+
return;
|
|
3506
|
+
} catch (error2) {
|
|
3507
|
+
import_node_server_utils22.logger.log({ level: "error", message: error2.message });
|
|
3508
|
+
next(error2);
|
|
3509
|
+
return;
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
return {
|
|
3513
|
+
createStock,
|
|
3514
|
+
getStocksBySupplyId
|
|
3515
|
+
};
|
|
3516
|
+
}
|
|
3517
|
+
|
|
3518
|
+
// src/models/hygiene-request-item.model.ts
|
|
3519
|
+
var import_node_server_utils23 = require("@iservice365/node-server-utils");
|
|
3520
|
+
var import_joi13 = __toESM(require("joi"));
|
|
3521
|
+
var import_mongodb13 = require("mongodb");
|
|
3522
|
+
var allowedRequestItemStatus = [
|
|
3523
|
+
"pending",
|
|
3524
|
+
"approved",
|
|
3525
|
+
"disapproved"
|
|
3526
|
+
];
|
|
3527
|
+
var requestItemSchema = import_joi13.default.object({
|
|
3528
|
+
site: import_joi13.default.string().hex().required(),
|
|
3529
|
+
supply: import_joi13.default.string().hex().required(),
|
|
3530
|
+
supplyName: import_joi13.default.string().required(),
|
|
3531
|
+
qty: import_joi13.default.number().min(0).required(),
|
|
3532
|
+
createdBy: import_joi13.default.string().hex().required(),
|
|
3533
|
+
createdByName: import_joi13.default.string().required()
|
|
3534
|
+
});
|
|
3535
|
+
function MRequestItem(value) {
|
|
3536
|
+
const { error } = requestItemSchema.validate(value);
|
|
3537
|
+
if (error) {
|
|
3538
|
+
import_node_server_utils23.logger.info(`Hygiene Request Item Model: ${error.message}`);
|
|
3539
|
+
throw new import_node_server_utils23.BadRequestError(error.message);
|
|
3540
|
+
}
|
|
3541
|
+
if (value.site) {
|
|
3542
|
+
try {
|
|
3543
|
+
value.site = new import_mongodb13.ObjectId(value.site);
|
|
3544
|
+
} catch (error2) {
|
|
3545
|
+
throw new import_node_server_utils23.BadRequestError("Invalid site ID format.");
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
if (value.supply) {
|
|
3549
|
+
try {
|
|
3550
|
+
value.supply = new import_mongodb13.ObjectId(value.supply);
|
|
3551
|
+
} catch (error2) {
|
|
3552
|
+
throw new import_node_server_utils23.BadRequestError("Invalid supply ID format.");
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3555
|
+
return {
|
|
3556
|
+
site: value.site,
|
|
3557
|
+
supply: value.supply,
|
|
3558
|
+
supplyName: value.supplyName,
|
|
3559
|
+
qty: value.qty,
|
|
3560
|
+
remarks: "",
|
|
3561
|
+
createdBy: value.createdBy,
|
|
3562
|
+
createdByName: value.createdByName,
|
|
3563
|
+
status: "pending",
|
|
3564
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3565
|
+
updatedAt: "",
|
|
3566
|
+
deletedAt: ""
|
|
3567
|
+
};
|
|
3568
|
+
}
|
|
3569
|
+
|
|
3570
|
+
// src/repositories/hygiene-request-item.repository.ts
|
|
3571
|
+
var import_mongodb14 = require("mongodb");
|
|
3572
|
+
var import_node_server_utils24 = require("@iservice365/node-server-utils");
|
|
3573
|
+
function useRequestItemRepository() {
|
|
3574
|
+
const db = import_node_server_utils24.useAtlas.getDb();
|
|
3575
|
+
if (!db) {
|
|
3576
|
+
throw new import_node_server_utils24.InternalServerError("Unable to connect to server.");
|
|
3577
|
+
}
|
|
3578
|
+
const namespace_collection = "site.supply.requests";
|
|
3579
|
+
const collection = db.collection(namespace_collection);
|
|
3580
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils24.useCache)(namespace_collection);
|
|
3581
|
+
async function createIndex() {
|
|
3582
|
+
try {
|
|
3583
|
+
await collection.createIndexes([
|
|
3584
|
+
{ key: { site: 1 } },
|
|
3585
|
+
{ key: { supply: 1 } },
|
|
3586
|
+
{ key: { status: 1 } }
|
|
3587
|
+
]);
|
|
3588
|
+
} catch (error) {
|
|
3589
|
+
throw new import_node_server_utils24.InternalServerError(
|
|
3590
|
+
"Failed to create index on hygiene request item."
|
|
3591
|
+
);
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
async function createTextIndex() {
|
|
3595
|
+
try {
|
|
3596
|
+
await collection.createIndex({ supplyName: "text" });
|
|
3597
|
+
} catch (error) {
|
|
3598
|
+
throw new import_node_server_utils24.InternalServerError(
|
|
3599
|
+
"Failed to create text index on hygiene supply."
|
|
3600
|
+
);
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3603
|
+
async function createRequestItem(value, session) {
|
|
3604
|
+
try {
|
|
3605
|
+
value = MRequestItem(value);
|
|
3606
|
+
const res = await collection.insertOne(value, { session });
|
|
3607
|
+
delNamespace().then(() => {
|
|
3608
|
+
import_node_server_utils24.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3609
|
+
}).catch((err) => {
|
|
3610
|
+
import_node_server_utils24.logger.error(
|
|
3611
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3612
|
+
err
|
|
3613
|
+
);
|
|
3614
|
+
});
|
|
3615
|
+
return res.insertedId;
|
|
3616
|
+
} catch (error) {
|
|
3617
|
+
throw error;
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
async function getRequestItems({
|
|
3621
|
+
page = 1,
|
|
3622
|
+
limit = 10,
|
|
3623
|
+
search = "",
|
|
3624
|
+
site
|
|
3625
|
+
}) {
|
|
3626
|
+
page = page > 0 ? page - 1 : 0;
|
|
3627
|
+
const query = {
|
|
3628
|
+
status: { $ne: "deleted" }
|
|
3629
|
+
};
|
|
3630
|
+
const cacheOptions = {
|
|
3631
|
+
page,
|
|
3632
|
+
limit
|
|
3633
|
+
};
|
|
3634
|
+
try {
|
|
3635
|
+
site = new import_mongodb14.ObjectId(site);
|
|
3636
|
+
query.site = site;
|
|
3637
|
+
cacheOptions.site = site.toString();
|
|
3638
|
+
} catch (error) {
|
|
3639
|
+
throw new import_node_server_utils24.BadRequestError("Invalid site ID format.");
|
|
3640
|
+
}
|
|
3641
|
+
if (search) {
|
|
3642
|
+
query.$text = { $search: search };
|
|
3643
|
+
cacheOptions.search = search;
|
|
3644
|
+
}
|
|
3645
|
+
const cacheKey = (0, import_node_server_utils24.makeCacheKey)(namespace_collection, cacheOptions);
|
|
3646
|
+
const cachedData = await getCache(cacheKey);
|
|
3647
|
+
if (cachedData) {
|
|
3648
|
+
import_node_server_utils24.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3649
|
+
return cachedData;
|
|
3650
|
+
}
|
|
3651
|
+
try {
|
|
3652
|
+
const items = await collection.aggregate([
|
|
3653
|
+
{ $match: query },
|
|
3654
|
+
{
|
|
3655
|
+
$project: {
|
|
3656
|
+
createdAt: 1,
|
|
3657
|
+
status: 1
|
|
3658
|
+
}
|
|
3659
|
+
},
|
|
3660
|
+
{ $sort: { _id: 1 } },
|
|
3661
|
+
{ $skip: page * limit },
|
|
3662
|
+
{ $limit: limit }
|
|
3663
|
+
]).toArray();
|
|
3664
|
+
const length = await collection.countDocuments(query);
|
|
3665
|
+
const data = (0, import_node_server_utils24.paginate)(items, page, limit, length);
|
|
3666
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3667
|
+
import_node_server_utils24.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3668
|
+
}).catch((err) => {
|
|
3669
|
+
import_node_server_utils24.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3670
|
+
});
|
|
3671
|
+
return data;
|
|
3672
|
+
} catch (error) {
|
|
3673
|
+
throw error;
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
return {
|
|
3677
|
+
createIndex,
|
|
3678
|
+
createTextIndex,
|
|
3679
|
+
createRequestItem,
|
|
3680
|
+
getRequestItems
|
|
3681
|
+
};
|
|
3682
|
+
}
|
|
3683
|
+
|
|
3684
|
+
// src/services/hygiene-request-item.service.ts
|
|
3685
|
+
var import_node_server_utils25 = require("@iservice365/node-server-utils");
|
|
3686
|
+
var import_core = require("@iservice365/core");
|
|
3687
|
+
function useRequestItemService() {
|
|
3688
|
+
const { createRequestItem: _createRequestItem } = useRequestItemRepository();
|
|
3689
|
+
const { getSupplyById } = useSupplyRepository();
|
|
3690
|
+
const { getUserById } = (0, import_core.useUserRepo)();
|
|
3691
|
+
async function createRequestItem(value) {
|
|
3692
|
+
try {
|
|
3693
|
+
const { supply, createdBy } = value;
|
|
3694
|
+
const supplyData = await getSupplyById(supply);
|
|
3695
|
+
const createdByData = await getUserById(createdBy);
|
|
3696
|
+
const createdRequestItem = await _createRequestItem({
|
|
3697
|
+
...value,
|
|
3698
|
+
supplyName: supplyData?.name || "",
|
|
3699
|
+
createdByName: createdByData?.name || ""
|
|
3700
|
+
});
|
|
3701
|
+
return createdRequestItem;
|
|
3702
|
+
} catch (error) {
|
|
3703
|
+
throw error;
|
|
3704
|
+
}
|
|
3705
|
+
}
|
|
3706
|
+
async function createRequestItemByBatch(value) {
|
|
3707
|
+
const session = import_node_server_utils25.useAtlas.getClient()?.startSession();
|
|
3708
|
+
try {
|
|
3709
|
+
session?.startTransaction();
|
|
3710
|
+
const { site, createdBy, items } = value;
|
|
3711
|
+
const createdByData = await getUserById(createdBy);
|
|
3712
|
+
const createdRequestItemIds = [];
|
|
3713
|
+
for (const item of items) {
|
|
3714
|
+
const supplyData = await getSupplyById(item.supply, session);
|
|
3715
|
+
const createdId = await _createRequestItem(
|
|
3716
|
+
{
|
|
3717
|
+
site,
|
|
3718
|
+
supply: item.supply,
|
|
3719
|
+
qty: item.qty,
|
|
3720
|
+
supplyName: supplyData?.name || "",
|
|
3721
|
+
createdBy,
|
|
3722
|
+
createdByName: createdByData?.name || ""
|
|
3723
|
+
},
|
|
3724
|
+
session
|
|
3725
|
+
);
|
|
3726
|
+
createdRequestItemIds.push(createdId);
|
|
3727
|
+
}
|
|
3728
|
+
await session?.commitTransaction();
|
|
3729
|
+
return createdRequestItemIds;
|
|
3730
|
+
} catch (error) {
|
|
3731
|
+
await session?.abortTransaction();
|
|
3732
|
+
throw error;
|
|
3733
|
+
} finally {
|
|
3734
|
+
await session?.endSession();
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
return { createRequestItem, createRequestItemByBatch };
|
|
3738
|
+
}
|
|
3739
|
+
|
|
3740
|
+
// src/controllers/hygiene-request-item.controller.ts
|
|
3741
|
+
var import_node_server_utils26 = require("@iservice365/node-server-utils");
|
|
3742
|
+
var import_joi14 = __toESM(require("joi"));
|
|
3743
|
+
function useRequestItemController() {
|
|
3744
|
+
const { getRequestItems: _getRequestItems } = useRequestItemRepository();
|
|
3745
|
+
const {
|
|
3746
|
+
createRequestItem: _createRequestItem,
|
|
3747
|
+
createRequestItemByBatch: _createRequestItemByBatch
|
|
3748
|
+
} = useRequestItemService();
|
|
3749
|
+
async function createRequestItem(req, res, next) {
|
|
3750
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
3751
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
3752
|
+
{}
|
|
3753
|
+
) : {};
|
|
3754
|
+
const createdBy = cookies["user"] || "";
|
|
3755
|
+
const payload = {
|
|
3756
|
+
...req.body,
|
|
3757
|
+
...req.params,
|
|
3758
|
+
createdBy
|
|
3759
|
+
};
|
|
3760
|
+
const validation = import_joi14.default.object({
|
|
3761
|
+
site: import_joi14.default.string().hex().required(),
|
|
3762
|
+
supply: import_joi14.default.string().hex().required(),
|
|
3763
|
+
qty: import_joi14.default.number().min(0).required(),
|
|
3764
|
+
createdBy: import_joi14.default.string().hex().required()
|
|
3765
|
+
});
|
|
3766
|
+
const { error } = validation.validate(payload);
|
|
3767
|
+
if (error) {
|
|
3768
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
3769
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
3770
|
+
return;
|
|
3771
|
+
}
|
|
3772
|
+
try {
|
|
3773
|
+
const id = await _createRequestItem(payload);
|
|
3774
|
+
res.status(201).json({ message: "Request item created successfully.", id });
|
|
3775
|
+
return;
|
|
3776
|
+
} catch (error2) {
|
|
3777
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
3778
|
+
next(error2);
|
|
3779
|
+
return;
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
async function createRequestItemByBatch(req, res, next) {
|
|
3783
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
3784
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
3785
|
+
{}
|
|
3786
|
+
) : {};
|
|
3787
|
+
const createdBy = cookies["user"] || "";
|
|
3788
|
+
const payload = {
|
|
3789
|
+
...req.body,
|
|
3790
|
+
...req.params,
|
|
3791
|
+
createdBy
|
|
3792
|
+
};
|
|
3793
|
+
const validation = import_joi14.default.object({
|
|
3794
|
+
site: import_joi14.default.string().hex().required(),
|
|
3795
|
+
createdBy: import_joi14.default.string().hex().required(),
|
|
3796
|
+
items: import_joi14.default.array().items(
|
|
3797
|
+
import_joi14.default.object({
|
|
3798
|
+
supply: import_joi14.default.string().hex().required(),
|
|
3799
|
+
qty: import_joi14.default.number().min(0).required()
|
|
3800
|
+
})
|
|
3801
|
+
).min(1).required()
|
|
3802
|
+
});
|
|
3803
|
+
const { error } = validation.validate(payload);
|
|
3804
|
+
if (error) {
|
|
3805
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
3806
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
3807
|
+
return;
|
|
3808
|
+
}
|
|
3809
|
+
try {
|
|
3810
|
+
await _createRequestItemByBatch(payload);
|
|
3811
|
+
res.status(201).json({ message: "Request items created successfully." });
|
|
3812
|
+
return;
|
|
3813
|
+
} catch (error2) {
|
|
3814
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
3815
|
+
next(error2);
|
|
3816
|
+
return;
|
|
3817
|
+
}
|
|
3818
|
+
}
|
|
3819
|
+
async function getRequestItems(req, res, next) {
|
|
3820
|
+
const query = { ...req.query, ...req.params };
|
|
3821
|
+
const validation = import_joi14.default.object({
|
|
3822
|
+
page: import_joi14.default.number().min(1).optional().allow("", null),
|
|
3823
|
+
limit: import_joi14.default.number().min(1).optional().allow("", null),
|
|
3824
|
+
search: import_joi14.default.string().optional().allow("", null),
|
|
3825
|
+
site: import_joi14.default.string().hex().required()
|
|
3826
|
+
});
|
|
3827
|
+
const { error } = validation.validate(query);
|
|
3828
|
+
if (error) {
|
|
3829
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
3830
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
3831
|
+
return;
|
|
3832
|
+
}
|
|
3833
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
3834
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
3835
|
+
const search = req.query.search ?? "";
|
|
3836
|
+
const site = req.params.site ?? "";
|
|
3837
|
+
try {
|
|
3838
|
+
const data = await _getRequestItems({
|
|
3839
|
+
page,
|
|
3840
|
+
limit,
|
|
3841
|
+
search,
|
|
3842
|
+
site
|
|
3843
|
+
});
|
|
3844
|
+
res.json(data);
|
|
3845
|
+
return;
|
|
3846
|
+
} catch (error2) {
|
|
3847
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
3848
|
+
next(error2);
|
|
3849
|
+
return;
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3852
|
+
return {
|
|
3853
|
+
createRequestItem,
|
|
3854
|
+
createRequestItemByBatch,
|
|
3855
|
+
getRequestItems
|
|
3856
|
+
};
|
|
3857
|
+
}
|
|
3220
3858
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3221
3859
|
0 && (module.exports = {
|
|
3222
3860
|
MArea,
|
|
3223
3861
|
MAreaChecklist,
|
|
3224
3862
|
MParentChecklist,
|
|
3863
|
+
MRequestItem,
|
|
3864
|
+
MStock,
|
|
3225
3865
|
MSupply,
|
|
3226
3866
|
MUnit,
|
|
3227
3867
|
allowedChecklistStatus,
|
|
3868
|
+
allowedRequestItemStatus,
|
|
3228
3869
|
allowedStatus,
|
|
3229
3870
|
allowedTypes,
|
|
3230
3871
|
areaChecklistSchema,
|
|
3231
3872
|
areaSchema,
|
|
3232
3873
|
parentChecklistSchema,
|
|
3874
|
+
requestItemSchema,
|
|
3875
|
+
stockSchema,
|
|
3233
3876
|
supplySchema,
|
|
3234
3877
|
unitSchema,
|
|
3235
3878
|
useAreaChecklistController,
|
|
@@ -3240,6 +3883,12 @@ function useSupplyController() {
|
|
|
3240
3883
|
useAreaService,
|
|
3241
3884
|
useParentChecklistController,
|
|
3242
3885
|
useParentChecklistRepo,
|
|
3886
|
+
useRequestItemController,
|
|
3887
|
+
useRequestItemRepository,
|
|
3888
|
+
useRequestItemService,
|
|
3889
|
+
useStockController,
|
|
3890
|
+
useStockRepository,
|
|
3891
|
+
useStockService,
|
|
3243
3892
|
useSupplyController,
|
|
3244
3893
|
useSupplyRepository,
|
|
3245
3894
|
useUnitController,
|