@iservice365/module-hygiene 1.1.0 → 1.4.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 +24 -0
- package/dist/index.d.ts +83 -2
- package/dist/index.js +737 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +744 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34,17 +34,24 @@ __export(src_exports, {
|
|
|
34
34
|
MAreaChecklist: () => MAreaChecklist,
|
|
35
35
|
MParentChecklist: () => MParentChecklist,
|
|
36
36
|
MRequestItem: () => MRequestItem,
|
|
37
|
+
MScheduleTask: () => MScheduleTask,
|
|
37
38
|
MStock: () => MStock,
|
|
38
39
|
MSupply: () => MSupply,
|
|
39
40
|
MUnit: () => MUnit,
|
|
40
41
|
allowedChecklistStatus: () => allowedChecklistStatus,
|
|
42
|
+
allowedDays: () => allowedDays,
|
|
43
|
+
allowedFrequency: () => allowedFrequency,
|
|
44
|
+
allowedMonths: () => allowedMonths,
|
|
45
|
+
allowedQuarter: () => allowedQuarter,
|
|
41
46
|
allowedRequestItemStatus: () => allowedRequestItemStatus,
|
|
42
47
|
allowedStatus: () => allowedStatus,
|
|
43
48
|
allowedTypes: () => allowedTypes,
|
|
49
|
+
allowedWeekOfMonth: () => allowedWeekOfMonth,
|
|
44
50
|
areaChecklistSchema: () => areaChecklistSchema,
|
|
45
51
|
areaSchema: () => areaSchema,
|
|
46
52
|
parentChecklistSchema: () => parentChecklistSchema,
|
|
47
53
|
requestItemSchema: () => requestItemSchema,
|
|
54
|
+
scheduleTaskSchema: () => scheduleTaskSchema,
|
|
48
55
|
stockSchema: () => stockSchema,
|
|
49
56
|
supplySchema: () => supplySchema,
|
|
50
57
|
unitSchema: () => unitSchema,
|
|
@@ -59,6 +66,8 @@ __export(src_exports, {
|
|
|
59
66
|
useRequestItemController: () => useRequestItemController,
|
|
60
67
|
useRequestItemRepository: () => useRequestItemRepository,
|
|
61
68
|
useRequestItemService: () => useRequestItemService,
|
|
69
|
+
useScheduleTaskController: () => useScheduleTaskController,
|
|
70
|
+
useScheduleTaskRepository: () => useScheduleTaskRepository,
|
|
62
71
|
useStockController: () => useStockController,
|
|
63
72
|
useStockRepository: () => useStockRepository,
|
|
64
73
|
useStockService: () => useStockService,
|
|
@@ -849,8 +858,8 @@ function MUnit(value) {
|
|
|
849
858
|
return {
|
|
850
859
|
site: value.site,
|
|
851
860
|
name: value.name,
|
|
852
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
853
861
|
status: "active",
|
|
862
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
854
863
|
updatedAt: "",
|
|
855
864
|
deletedAt: ""
|
|
856
865
|
};
|
|
@@ -1541,6 +1550,9 @@ function useParentChecklistRepo() {
|
|
|
1541
1550
|
status,
|
|
1542
1551
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1543
1552
|
};
|
|
1553
|
+
if (status === "completed") {
|
|
1554
|
+
updateValue.completedAt = /* @__PURE__ */ new Date();
|
|
1555
|
+
}
|
|
1544
1556
|
const res = await collection.updateOne(
|
|
1545
1557
|
{ _id },
|
|
1546
1558
|
{ $set: updateValue },
|
|
@@ -2953,7 +2965,8 @@ function useSupplyRepository() {
|
|
|
2953
2965
|
{
|
|
2954
2966
|
$project: {
|
|
2955
2967
|
name: 1,
|
|
2956
|
-
qty: 1
|
|
2968
|
+
qty: 1,
|
|
2969
|
+
status: 1
|
|
2957
2970
|
}
|
|
2958
2971
|
},
|
|
2959
2972
|
{ $sort: { _id: -1 } },
|
|
@@ -3046,7 +3059,7 @@ function useSupplyRepository() {
|
|
|
3046
3059
|
} catch (error) {
|
|
3047
3060
|
const isDuplicated = error.message.includes("duplicate");
|
|
3048
3061
|
if (isDuplicated) {
|
|
3049
|
-
throw new import_node_server_utils17.BadRequestError("
|
|
3062
|
+
throw new import_node_server_utils17.BadRequestError("Supply already exists.");
|
|
3050
3063
|
}
|
|
3051
3064
|
throw error;
|
|
3052
3065
|
}
|
|
@@ -3657,7 +3670,7 @@ function useRequestItemRepository() {
|
|
|
3657
3670
|
status: 1
|
|
3658
3671
|
}
|
|
3659
3672
|
},
|
|
3660
|
-
{ $sort: { _id: 1 } },
|
|
3673
|
+
{ $sort: { _id: -1 } },
|
|
3661
3674
|
{ $skip: page * limit },
|
|
3662
3675
|
{ $limit: limit }
|
|
3663
3676
|
]).toArray();
|
|
@@ -3673,11 +3686,140 @@ function useRequestItemRepository() {
|
|
|
3673
3686
|
throw error;
|
|
3674
3687
|
}
|
|
3675
3688
|
}
|
|
3689
|
+
async function getRequestItemById(_id, session) {
|
|
3690
|
+
try {
|
|
3691
|
+
_id = new import_mongodb14.ObjectId(_id);
|
|
3692
|
+
} catch (error) {
|
|
3693
|
+
throw new import_node_server_utils24.BadRequestError("Invalid request item ID format.");
|
|
3694
|
+
}
|
|
3695
|
+
const query = { _id };
|
|
3696
|
+
const cacheKey = (0, import_node_server_utils24.makeCacheKey)(namespace_collection, {
|
|
3697
|
+
_id: _id.toString()
|
|
3698
|
+
});
|
|
3699
|
+
if (!session) {
|
|
3700
|
+
const cachedData = await getCache(cacheKey);
|
|
3701
|
+
if (cachedData) {
|
|
3702
|
+
import_node_server_utils24.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3703
|
+
return cachedData;
|
|
3704
|
+
}
|
|
3705
|
+
} else {
|
|
3706
|
+
import_node_server_utils24.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
3707
|
+
}
|
|
3708
|
+
try {
|
|
3709
|
+
const data = await collection.aggregate([
|
|
3710
|
+
{ $match: query },
|
|
3711
|
+
{
|
|
3712
|
+
$lookup: {
|
|
3713
|
+
from: "site.supply.items",
|
|
3714
|
+
localField: "supply",
|
|
3715
|
+
foreignField: "_id",
|
|
3716
|
+
as: "supplyDetails"
|
|
3717
|
+
}
|
|
3718
|
+
},
|
|
3719
|
+
{
|
|
3720
|
+
$unwind: {
|
|
3721
|
+
path: "$supplyDetails",
|
|
3722
|
+
preserveNullAndEmptyArrays: true
|
|
3723
|
+
}
|
|
3724
|
+
},
|
|
3725
|
+
{
|
|
3726
|
+
$project: {
|
|
3727
|
+
site: 1,
|
|
3728
|
+
supply: 1,
|
|
3729
|
+
supplyName: 1,
|
|
3730
|
+
qty: 1,
|
|
3731
|
+
status: 1,
|
|
3732
|
+
unitOfMeasurement: "$supplyDetails.unitOfMeasurement"
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
]).toArray();
|
|
3736
|
+
if (!data || data.length === 0) {
|
|
3737
|
+
throw new import_node_server_utils24.NotFoundError("Request item not found.");
|
|
3738
|
+
}
|
|
3739
|
+
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
3740
|
+
import_node_server_utils24.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3741
|
+
}).catch((err) => {
|
|
3742
|
+
import_node_server_utils24.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3743
|
+
});
|
|
3744
|
+
return data[0];
|
|
3745
|
+
} catch (error) {
|
|
3746
|
+
throw error;
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
async function approveRequestItem(_id, remarks, session) {
|
|
3750
|
+
try {
|
|
3751
|
+
_id = new import_mongodb14.ObjectId(_id);
|
|
3752
|
+
} catch (error) {
|
|
3753
|
+
throw new import_node_server_utils24.BadRequestError("Invalid request item ID format.");
|
|
3754
|
+
}
|
|
3755
|
+
try {
|
|
3756
|
+
const updateValue = {
|
|
3757
|
+
status: "approved",
|
|
3758
|
+
remarks: remarks || "",
|
|
3759
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3760
|
+
};
|
|
3761
|
+
const res = await collection.updateOne(
|
|
3762
|
+
{ _id },
|
|
3763
|
+
{ $set: updateValue },
|
|
3764
|
+
{ session }
|
|
3765
|
+
);
|
|
3766
|
+
if (res.modifiedCount === 0) {
|
|
3767
|
+
throw new import_node_server_utils24.InternalServerError("Unable to approve request item.");
|
|
3768
|
+
}
|
|
3769
|
+
delNamespace().then(() => {
|
|
3770
|
+
import_node_server_utils24.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3771
|
+
}).catch((err) => {
|
|
3772
|
+
import_node_server_utils24.logger.error(
|
|
3773
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3774
|
+
err
|
|
3775
|
+
);
|
|
3776
|
+
});
|
|
3777
|
+
return res.modifiedCount;
|
|
3778
|
+
} catch (error) {
|
|
3779
|
+
throw error;
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
async function disapproveRequestItem(_id, remarks, session) {
|
|
3783
|
+
try {
|
|
3784
|
+
_id = new import_mongodb14.ObjectId(_id);
|
|
3785
|
+
} catch (error) {
|
|
3786
|
+
throw new import_node_server_utils24.BadRequestError("Invalid request item ID format.");
|
|
3787
|
+
}
|
|
3788
|
+
try {
|
|
3789
|
+
const updateValue = {
|
|
3790
|
+
status: "disapproved",
|
|
3791
|
+
remarks: remarks || "",
|
|
3792
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3793
|
+
};
|
|
3794
|
+
const res = await collection.updateOne(
|
|
3795
|
+
{ _id },
|
|
3796
|
+
{ $set: updateValue },
|
|
3797
|
+
{ session }
|
|
3798
|
+
);
|
|
3799
|
+
if (res.modifiedCount === 0) {
|
|
3800
|
+
throw new import_node_server_utils24.InternalServerError("Unable to disapprove request item.");
|
|
3801
|
+
}
|
|
3802
|
+
delNamespace().then(() => {
|
|
3803
|
+
import_node_server_utils24.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3804
|
+
}).catch((err) => {
|
|
3805
|
+
import_node_server_utils24.logger.error(
|
|
3806
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3807
|
+
err
|
|
3808
|
+
);
|
|
3809
|
+
});
|
|
3810
|
+
return res.modifiedCount;
|
|
3811
|
+
} catch (error) {
|
|
3812
|
+
throw error;
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3676
3815
|
return {
|
|
3677
3816
|
createIndex,
|
|
3678
3817
|
createTextIndex,
|
|
3679
3818
|
createRequestItem,
|
|
3680
|
-
getRequestItems
|
|
3819
|
+
getRequestItems,
|
|
3820
|
+
getRequestItemById,
|
|
3821
|
+
approveRequestItem,
|
|
3822
|
+
disapproveRequestItem
|
|
3681
3823
|
};
|
|
3682
3824
|
}
|
|
3683
3825
|
|
|
@@ -3685,9 +3827,15 @@ function useRequestItemRepository() {
|
|
|
3685
3827
|
var import_node_server_utils25 = require("@iservice365/node-server-utils");
|
|
3686
3828
|
var import_core = require("@iservice365/core");
|
|
3687
3829
|
function useRequestItemService() {
|
|
3688
|
-
const {
|
|
3830
|
+
const {
|
|
3831
|
+
createRequestItem: _createRequestItem,
|
|
3832
|
+
getRequestItemById: _getRequestItemById,
|
|
3833
|
+
approveRequestItem: _approveRequestItem,
|
|
3834
|
+
disapproveRequestItem: _disapproveRequestItem
|
|
3835
|
+
} = useRequestItemRepository();
|
|
3689
3836
|
const { getSupplyById } = useSupplyRepository();
|
|
3690
3837
|
const { getUserById } = (0, import_core.useUserRepo)();
|
|
3838
|
+
const { createStock } = useStockService();
|
|
3691
3839
|
async function createRequestItem(value) {
|
|
3692
3840
|
try {
|
|
3693
3841
|
const { supply, createdBy } = value;
|
|
@@ -3734,17 +3882,76 @@ function useRequestItemService() {
|
|
|
3734
3882
|
await session?.endSession();
|
|
3735
3883
|
}
|
|
3736
3884
|
}
|
|
3737
|
-
|
|
3885
|
+
async function approveRequestItem(id, remarks) {
|
|
3886
|
+
const session = import_node_server_utils25.useAtlas.getClient()?.startSession();
|
|
3887
|
+
try {
|
|
3888
|
+
session?.startTransaction();
|
|
3889
|
+
await _approveRequestItem(id, remarks, session);
|
|
3890
|
+
const requestItem = await _getRequestItemById(id, session);
|
|
3891
|
+
if (requestItem.status !== "pending") {
|
|
3892
|
+
throw new import_node_server_utils25.BadRequestError(
|
|
3893
|
+
"Only 'pending' request items can be approved."
|
|
3894
|
+
);
|
|
3895
|
+
}
|
|
3896
|
+
const createdStocks = await createStock(
|
|
3897
|
+
{
|
|
3898
|
+
site: requestItem.site.toString(),
|
|
3899
|
+
supply: requestItem.supply.toString(),
|
|
3900
|
+
qty: requestItem.qty,
|
|
3901
|
+
remarks
|
|
3902
|
+
},
|
|
3903
|
+
true
|
|
3904
|
+
);
|
|
3905
|
+
await session?.commitTransaction();
|
|
3906
|
+
return createdStocks;
|
|
3907
|
+
} catch (error) {
|
|
3908
|
+
await session?.abortTransaction();
|
|
3909
|
+
throw error;
|
|
3910
|
+
} finally {
|
|
3911
|
+
await session?.endSession();
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
async function disapproveRequestItem(id, remarks) {
|
|
3915
|
+
const session = import_node_server_utils25.useAtlas.getClient()?.startSession();
|
|
3916
|
+
try {
|
|
3917
|
+
session?.startTransaction();
|
|
3918
|
+
const result = await _disapproveRequestItem(id, remarks, session);
|
|
3919
|
+
const requestItem = await _getRequestItemById(id, session);
|
|
3920
|
+
if (requestItem.status !== "pending") {
|
|
3921
|
+
throw new import_node_server_utils25.BadRequestError(
|
|
3922
|
+
"Only 'pending' request items can be disapproved."
|
|
3923
|
+
);
|
|
3924
|
+
}
|
|
3925
|
+
await session?.commitTransaction();
|
|
3926
|
+
return result;
|
|
3927
|
+
} catch (error) {
|
|
3928
|
+
await session?.abortTransaction();
|
|
3929
|
+
throw error;
|
|
3930
|
+
} finally {
|
|
3931
|
+
await session?.endSession();
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
return {
|
|
3935
|
+
createRequestItem,
|
|
3936
|
+
createRequestItemByBatch,
|
|
3937
|
+
approveRequestItem,
|
|
3938
|
+
disapproveRequestItem
|
|
3939
|
+
};
|
|
3738
3940
|
}
|
|
3739
3941
|
|
|
3740
3942
|
// src/controllers/hygiene-request-item.controller.ts
|
|
3741
3943
|
var import_node_server_utils26 = require("@iservice365/node-server-utils");
|
|
3742
3944
|
var import_joi14 = __toESM(require("joi"));
|
|
3743
3945
|
function useRequestItemController() {
|
|
3744
|
-
const {
|
|
3946
|
+
const {
|
|
3947
|
+
getRequestItems: _getRequestItems,
|
|
3948
|
+
getRequestItemById: _getRequestItemById
|
|
3949
|
+
} = useRequestItemRepository();
|
|
3745
3950
|
const {
|
|
3746
3951
|
createRequestItem: _createRequestItem,
|
|
3747
|
-
createRequestItemByBatch: _createRequestItemByBatch
|
|
3952
|
+
createRequestItemByBatch: _createRequestItemByBatch,
|
|
3953
|
+
approveRequestItem: _approveRequestItem,
|
|
3954
|
+
disapproveRequestItem: _disapproveRequestItem
|
|
3748
3955
|
} = useRequestItemService();
|
|
3749
3956
|
async function createRequestItem(req, res, next) {
|
|
3750
3957
|
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
@@ -3849,10 +4056,521 @@ function useRequestItemController() {
|
|
|
3849
4056
|
return;
|
|
3850
4057
|
}
|
|
3851
4058
|
}
|
|
4059
|
+
async function getRequestItemById(req, res, next) {
|
|
4060
|
+
const validation = import_joi14.default.string().hex().required();
|
|
4061
|
+
const _id = req.params.id;
|
|
4062
|
+
const { error } = validation.validate(_id);
|
|
4063
|
+
if (error) {
|
|
4064
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
4065
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
4066
|
+
return;
|
|
4067
|
+
}
|
|
4068
|
+
try {
|
|
4069
|
+
const data = await _getRequestItemById(_id);
|
|
4070
|
+
res.json(data);
|
|
4071
|
+
return;
|
|
4072
|
+
} catch (error2) {
|
|
4073
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
4074
|
+
next(error2);
|
|
4075
|
+
return;
|
|
4076
|
+
}
|
|
4077
|
+
}
|
|
4078
|
+
async function approveRequestItem(req, res, next) {
|
|
4079
|
+
const payload = { ...req.params, ...req.body };
|
|
4080
|
+
const validation = import_joi14.default.object({
|
|
4081
|
+
id: import_joi14.default.string().hex().required(),
|
|
4082
|
+
remarks: import_joi14.default.string().optional().allow("", null)
|
|
4083
|
+
});
|
|
4084
|
+
const { error } = validation.validate(payload);
|
|
4085
|
+
if (error) {
|
|
4086
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
4087
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
4088
|
+
return;
|
|
4089
|
+
}
|
|
4090
|
+
try {
|
|
4091
|
+
await _approveRequestItem(payload.id, payload.remarks);
|
|
4092
|
+
res.json({ message: "Request item approved successfully." });
|
|
4093
|
+
return;
|
|
4094
|
+
} catch (error2) {
|
|
4095
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
4096
|
+
next(error2);
|
|
4097
|
+
return;
|
|
4098
|
+
}
|
|
4099
|
+
}
|
|
4100
|
+
async function disapproveRequestItem(req, res, next) {
|
|
4101
|
+
const payload = { ...req.params, ...req.body };
|
|
4102
|
+
const validation = import_joi14.default.object({
|
|
4103
|
+
id: import_joi14.default.string().hex().required(),
|
|
4104
|
+
remarks: import_joi14.default.string().optional().allow("", null)
|
|
4105
|
+
});
|
|
4106
|
+
const { error } = validation.validate(payload);
|
|
4107
|
+
if (error) {
|
|
4108
|
+
import_node_server_utils26.logger.log({ level: "error", message: error.message });
|
|
4109
|
+
next(new import_node_server_utils26.BadRequestError(error.message));
|
|
4110
|
+
return;
|
|
4111
|
+
}
|
|
4112
|
+
try {
|
|
4113
|
+
await _disapproveRequestItem(payload.id, payload.remarks);
|
|
4114
|
+
res.json({ message: "Request item disapproved successfully." });
|
|
4115
|
+
return;
|
|
4116
|
+
} catch (error2) {
|
|
4117
|
+
import_node_server_utils26.logger.log({ level: "error", message: error2.message });
|
|
4118
|
+
next(error2);
|
|
4119
|
+
return;
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
3852
4122
|
return {
|
|
3853
4123
|
createRequestItem,
|
|
3854
4124
|
createRequestItemByBatch,
|
|
3855
|
-
getRequestItems
|
|
4125
|
+
getRequestItems,
|
|
4126
|
+
getRequestItemById,
|
|
4127
|
+
approveRequestItem,
|
|
4128
|
+
disapproveRequestItem
|
|
4129
|
+
};
|
|
4130
|
+
}
|
|
4131
|
+
|
|
4132
|
+
// src/models/hygiene-schedule-task.model.ts
|
|
4133
|
+
var import_node_server_utils27 = require("@iservice365/node-server-utils");
|
|
4134
|
+
var import_joi15 = __toESM(require("joi"));
|
|
4135
|
+
var import_mongodb15 = require("mongodb");
|
|
4136
|
+
var allowedFrequency = ["week", "month", "quarter", "year"];
|
|
4137
|
+
var allowedDays = [
|
|
4138
|
+
"Mon",
|
|
4139
|
+
"Tue",
|
|
4140
|
+
"Wed",
|
|
4141
|
+
"Thu",
|
|
4142
|
+
"Fri",
|
|
4143
|
+
"Sat",
|
|
4144
|
+
"Sun"
|
|
4145
|
+
];
|
|
4146
|
+
var allowedQuarter = ["1st", "2nd", "3rd", "4th"];
|
|
4147
|
+
var allowedWeekOfMonth = [
|
|
4148
|
+
"1st",
|
|
4149
|
+
"2nd",
|
|
4150
|
+
"3rd",
|
|
4151
|
+
"4th",
|
|
4152
|
+
"last"
|
|
4153
|
+
];
|
|
4154
|
+
var allowedMonths = [
|
|
4155
|
+
"January",
|
|
4156
|
+
"February",
|
|
4157
|
+
"March",
|
|
4158
|
+
"April",
|
|
4159
|
+
"May",
|
|
4160
|
+
"June",
|
|
4161
|
+
"July",
|
|
4162
|
+
"August",
|
|
4163
|
+
"September",
|
|
4164
|
+
"October",
|
|
4165
|
+
"November",
|
|
4166
|
+
"December"
|
|
4167
|
+
];
|
|
4168
|
+
var scheduleTaskSchema = import_joi15.default.object({
|
|
4169
|
+
site: import_joi15.default.string().hex().required(),
|
|
4170
|
+
title: import_joi15.default.string().required(),
|
|
4171
|
+
frequency: import_joi15.default.string().valid(...allowedFrequency).required(),
|
|
4172
|
+
time: import_joi15.default.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).required(),
|
|
4173
|
+
day: import_joi15.default.string().valid(...allowedDays).required(),
|
|
4174
|
+
weekOfMonth: import_joi15.default.string().valid(...allowedWeekOfMonth).when("frequency", {
|
|
4175
|
+
is: import_joi15.default.string().valid("month", "quarter", "year"),
|
|
4176
|
+
then: import_joi15.default.required(),
|
|
4177
|
+
otherwise: import_joi15.default.optional().allow("", null)
|
|
4178
|
+
}),
|
|
4179
|
+
quarter: import_joi15.default.string().valid(...allowedQuarter).when("frequency", {
|
|
4180
|
+
is: "quarter",
|
|
4181
|
+
then: import_joi15.default.required(),
|
|
4182
|
+
otherwise: import_joi15.default.optional().allow("", null)
|
|
4183
|
+
}),
|
|
4184
|
+
month: import_joi15.default.string().valid(...allowedMonths).when("frequency", {
|
|
4185
|
+
is: import_joi15.default.string().valid("quarter", "year"),
|
|
4186
|
+
then: import_joi15.default.required(),
|
|
4187
|
+
otherwise: import_joi15.default.optional().allow("", null)
|
|
4188
|
+
}),
|
|
4189
|
+
description: import_joi15.default.string().optional().allow("", null),
|
|
4190
|
+
areas: import_joi15.default.array().min(1).items(
|
|
4191
|
+
import_joi15.default.object({
|
|
4192
|
+
name: import_joi15.default.string().required(),
|
|
4193
|
+
value: import_joi15.default.any().required()
|
|
4194
|
+
})
|
|
4195
|
+
).required()
|
|
4196
|
+
});
|
|
4197
|
+
function MScheduleTask(value) {
|
|
4198
|
+
const { error } = scheduleTaskSchema.validate(value);
|
|
4199
|
+
if (error) {
|
|
4200
|
+
import_node_server_utils27.logger.info(`Hygiene Schedule Task Model: ${error.message}`);
|
|
4201
|
+
throw new import_node_server_utils27.BadRequestError(error.message);
|
|
4202
|
+
}
|
|
4203
|
+
if (value.site) {
|
|
4204
|
+
try {
|
|
4205
|
+
value.site = new import_mongodb15.ObjectId(value.site);
|
|
4206
|
+
} catch (error2) {
|
|
4207
|
+
throw new import_node_server_utils27.BadRequestError("Invalid site ID format.");
|
|
4208
|
+
}
|
|
4209
|
+
}
|
|
4210
|
+
if (value.areas && Array.isArray(value.areas)) {
|
|
4211
|
+
value.areas = value.areas.map((area) => {
|
|
4212
|
+
try {
|
|
4213
|
+
return {
|
|
4214
|
+
name: area.name,
|
|
4215
|
+
value: new import_mongodb15.ObjectId(area.value.toString())
|
|
4216
|
+
};
|
|
4217
|
+
} catch (error2) {
|
|
4218
|
+
throw new import_node_server_utils27.BadRequestError(`Invalid area value format: ${area.name}`);
|
|
4219
|
+
}
|
|
4220
|
+
});
|
|
4221
|
+
}
|
|
4222
|
+
return {
|
|
4223
|
+
site: value.site,
|
|
4224
|
+
title: value.title,
|
|
4225
|
+
frequency: value.frequency,
|
|
4226
|
+
time: value.time,
|
|
4227
|
+
day: value.day,
|
|
4228
|
+
weekOfMonth: value.weekOfMonth,
|
|
4229
|
+
quarter: value.quarter,
|
|
4230
|
+
month: value.month,
|
|
4231
|
+
description: value.description,
|
|
4232
|
+
areas: value.areas,
|
|
4233
|
+
status: "active",
|
|
4234
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
4235
|
+
updatedAt: "",
|
|
4236
|
+
deletedAt: ""
|
|
4237
|
+
};
|
|
4238
|
+
}
|
|
4239
|
+
|
|
4240
|
+
// src/repositories/hygiene-schedule-task.repository.ts
|
|
4241
|
+
var import_mongodb16 = require("mongodb");
|
|
4242
|
+
var import_node_server_utils28 = require("@iservice365/node-server-utils");
|
|
4243
|
+
function useScheduleTaskRepository() {
|
|
4244
|
+
const db = import_node_server_utils28.useAtlas.getDb();
|
|
4245
|
+
if (!db) {
|
|
4246
|
+
throw new import_node_server_utils28.InternalServerError("Unable to connect to server.");
|
|
4247
|
+
}
|
|
4248
|
+
const namespace_collection = "site.schedule-tasks";
|
|
4249
|
+
const collection = db.collection(namespace_collection);
|
|
4250
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils28.useCache)(namespace_collection);
|
|
4251
|
+
async function createIndex() {
|
|
4252
|
+
try {
|
|
4253
|
+
await collection.createIndexes([
|
|
4254
|
+
{ key: { site: 1 } },
|
|
4255
|
+
{ key: { status: 1 } }
|
|
4256
|
+
]);
|
|
4257
|
+
} catch (error) {
|
|
4258
|
+
throw new import_node_server_utils28.InternalServerError(
|
|
4259
|
+
"Failed to create index on hygiene schedule task."
|
|
4260
|
+
);
|
|
4261
|
+
}
|
|
4262
|
+
}
|
|
4263
|
+
async function createTextIndex() {
|
|
4264
|
+
try {
|
|
4265
|
+
await collection.createIndex({ title: "text", description: "text" });
|
|
4266
|
+
} catch (error) {
|
|
4267
|
+
throw new import_node_server_utils28.InternalServerError(
|
|
4268
|
+
"Failed to create text index on hygiene schedule task."
|
|
4269
|
+
);
|
|
4270
|
+
}
|
|
4271
|
+
}
|
|
4272
|
+
async function createScheduleTask(value, session) {
|
|
4273
|
+
try {
|
|
4274
|
+
value = MScheduleTask(value);
|
|
4275
|
+
const res = await collection.insertOne(value, { session });
|
|
4276
|
+
delNamespace().then(() => {
|
|
4277
|
+
import_node_server_utils28.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4278
|
+
}).catch((err) => {
|
|
4279
|
+
import_node_server_utils28.logger.error(
|
|
4280
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4281
|
+
err
|
|
4282
|
+
);
|
|
4283
|
+
});
|
|
4284
|
+
return res.insertedId;
|
|
4285
|
+
} catch (error) {
|
|
4286
|
+
throw error;
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
async function getScheduleTasks({
|
|
4290
|
+
page = 1,
|
|
4291
|
+
limit = 10,
|
|
4292
|
+
search = "",
|
|
4293
|
+
site
|
|
4294
|
+
}) {
|
|
4295
|
+
page = page > 0 ? page - 1 : 0;
|
|
4296
|
+
const query = {
|
|
4297
|
+
status: { $ne: "deleted" }
|
|
4298
|
+
};
|
|
4299
|
+
const cacheOptions = {
|
|
4300
|
+
page,
|
|
4301
|
+
limit
|
|
4302
|
+
};
|
|
4303
|
+
try {
|
|
4304
|
+
site = new import_mongodb16.ObjectId(site);
|
|
4305
|
+
query.site = site;
|
|
4306
|
+
cacheOptions.site = site.toString();
|
|
4307
|
+
} catch (error) {
|
|
4308
|
+
throw new import_node_server_utils28.BadRequestError("Invalid site ID format.");
|
|
4309
|
+
}
|
|
4310
|
+
if (search) {
|
|
4311
|
+
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
4312
|
+
cacheOptions.search = search;
|
|
4313
|
+
}
|
|
4314
|
+
const cacheKey = (0, import_node_server_utils28.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4315
|
+
const cachedData = await getCache(cacheKey);
|
|
4316
|
+
if (cachedData) {
|
|
4317
|
+
import_node_server_utils28.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4318
|
+
return cachedData;
|
|
4319
|
+
}
|
|
4320
|
+
try {
|
|
4321
|
+
const items = await collection.aggregate([
|
|
4322
|
+
{ $match: query },
|
|
4323
|
+
{
|
|
4324
|
+
$project: {
|
|
4325
|
+
title: 1,
|
|
4326
|
+
areas: 1,
|
|
4327
|
+
status: 1
|
|
4328
|
+
}
|
|
4329
|
+
},
|
|
4330
|
+
{ $sort: { _id: -1 } },
|
|
4331
|
+
{ $skip: page * limit },
|
|
4332
|
+
{ $limit: limit }
|
|
4333
|
+
]).toArray();
|
|
4334
|
+
const length = await collection.countDocuments(query);
|
|
4335
|
+
const data = (0, import_node_server_utils28.paginate)(items, page, limit, length);
|
|
4336
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4337
|
+
import_node_server_utils28.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4338
|
+
}).catch((err) => {
|
|
4339
|
+
import_node_server_utils28.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4340
|
+
});
|
|
4341
|
+
return data;
|
|
4342
|
+
} catch (error) {
|
|
4343
|
+
throw error;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
async function getScheduleTaskById(_id, session) {
|
|
4347
|
+
try {
|
|
4348
|
+
_id = new import_mongodb16.ObjectId(_id);
|
|
4349
|
+
} catch (error) {
|
|
4350
|
+
throw new import_node_server_utils28.BadRequestError("Invalid schedule task ID format.");
|
|
4351
|
+
}
|
|
4352
|
+
const query = {
|
|
4353
|
+
_id,
|
|
4354
|
+
status: { $ne: "deleted" }
|
|
4355
|
+
};
|
|
4356
|
+
const cacheKey = (0, import_node_server_utils28.makeCacheKey)(namespace_collection, {
|
|
4357
|
+
_id: _id.toString()
|
|
4358
|
+
});
|
|
4359
|
+
if (!session) {
|
|
4360
|
+
const cachedData = await getCache(cacheKey);
|
|
4361
|
+
if (cachedData) {
|
|
4362
|
+
import_node_server_utils28.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4363
|
+
return cachedData;
|
|
4364
|
+
}
|
|
4365
|
+
} else {
|
|
4366
|
+
import_node_server_utils28.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
4367
|
+
}
|
|
4368
|
+
try {
|
|
4369
|
+
const data = await collection.aggregate([
|
|
4370
|
+
{ $match: query },
|
|
4371
|
+
{
|
|
4372
|
+
$project: {
|
|
4373
|
+
title: 1,
|
|
4374
|
+
frequency: 1,
|
|
4375
|
+
time: 1,
|
|
4376
|
+
day: 1,
|
|
4377
|
+
weekOfMonth: 1,
|
|
4378
|
+
quarter: 1,
|
|
4379
|
+
month: 1,
|
|
4380
|
+
description: 1,
|
|
4381
|
+
areas: 1,
|
|
4382
|
+
status: 1,
|
|
4383
|
+
createdAt: 1
|
|
4384
|
+
}
|
|
4385
|
+
}
|
|
4386
|
+
]).toArray();
|
|
4387
|
+
if (!data || data.length === 0) {
|
|
4388
|
+
throw new import_node_server_utils28.NotFoundError("Schedule task not found.");
|
|
4389
|
+
}
|
|
4390
|
+
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
4391
|
+
import_node_server_utils28.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4392
|
+
}).catch((err) => {
|
|
4393
|
+
import_node_server_utils28.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4394
|
+
});
|
|
4395
|
+
return data[0];
|
|
4396
|
+
} catch (error) {
|
|
4397
|
+
throw error;
|
|
4398
|
+
}
|
|
4399
|
+
}
|
|
4400
|
+
async function updateScheduleTask(_id, value, session) {
|
|
4401
|
+
try {
|
|
4402
|
+
_id = new import_mongodb16.ObjectId(_id);
|
|
4403
|
+
} catch (error) {
|
|
4404
|
+
throw new import_node_server_utils28.BadRequestError("Invalid schedule task ID format.");
|
|
4405
|
+
}
|
|
4406
|
+
if (value.areas && Array.isArray(value.areas)) {
|
|
4407
|
+
value.areas = value.areas.map((area) => {
|
|
4408
|
+
try {
|
|
4409
|
+
return {
|
|
4410
|
+
name: area.name,
|
|
4411
|
+
value: new import_mongodb16.ObjectId(area.value.toString())
|
|
4412
|
+
};
|
|
4413
|
+
} catch (error) {
|
|
4414
|
+
throw new import_node_server_utils28.BadRequestError(`Invalid area value format: ${area.name}`);
|
|
4415
|
+
}
|
|
4416
|
+
});
|
|
4417
|
+
}
|
|
4418
|
+
try {
|
|
4419
|
+
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
4420
|
+
const res = await collection.updateOne(
|
|
4421
|
+
{ _id },
|
|
4422
|
+
{ $set: updateValue },
|
|
4423
|
+
{ session }
|
|
4424
|
+
);
|
|
4425
|
+
if (res.modifiedCount === 0) {
|
|
4426
|
+
throw new import_node_server_utils28.InternalServerError(
|
|
4427
|
+
"Unable to update hygiene schedule task."
|
|
4428
|
+
);
|
|
4429
|
+
}
|
|
4430
|
+
delNamespace().then(() => {
|
|
4431
|
+
import_node_server_utils28.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4432
|
+
}).catch((err) => {
|
|
4433
|
+
import_node_server_utils28.logger.error(
|
|
4434
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4435
|
+
err
|
|
4436
|
+
);
|
|
4437
|
+
});
|
|
4438
|
+
return res.modifiedCount;
|
|
4439
|
+
} catch (error) {
|
|
4440
|
+
throw error;
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
return {
|
|
4444
|
+
createIndex,
|
|
4445
|
+
createTextIndex,
|
|
4446
|
+
createScheduleTask,
|
|
4447
|
+
getScheduleTasks,
|
|
4448
|
+
getScheduleTaskById,
|
|
4449
|
+
updateScheduleTask
|
|
4450
|
+
};
|
|
4451
|
+
}
|
|
4452
|
+
|
|
4453
|
+
// src/controllers/hygiene-schedule-task.controller.ts
|
|
4454
|
+
var import_node_server_utils29 = require("@iservice365/node-server-utils");
|
|
4455
|
+
var import_joi16 = __toESM(require("joi"));
|
|
4456
|
+
function useScheduleTaskController() {
|
|
4457
|
+
const {
|
|
4458
|
+
createScheduleTask: _createScheduleTask,
|
|
4459
|
+
getScheduleTasks: _getScheduleTasks,
|
|
4460
|
+
getScheduleTaskById: _getScheduleTaskById,
|
|
4461
|
+
updateScheduleTask: _updateScheduleTask
|
|
4462
|
+
} = useScheduleTaskRepository();
|
|
4463
|
+
async function createScheduleTask(req, res, next) {
|
|
4464
|
+
const payload = { ...req.body, ...req.params };
|
|
4465
|
+
const { error } = scheduleTaskSchema.validate(payload);
|
|
4466
|
+
if (error) {
|
|
4467
|
+
import_node_server_utils29.logger.log({ level: "error", message: error.message });
|
|
4468
|
+
next(new import_node_server_utils29.BadRequestError(error.message));
|
|
4469
|
+
return;
|
|
4470
|
+
}
|
|
4471
|
+
try {
|
|
4472
|
+
const id = await _createScheduleTask(payload);
|
|
4473
|
+
res.status(201).json({ message: "Schedule task created successfully.", id });
|
|
4474
|
+
return;
|
|
4475
|
+
} catch (error2) {
|
|
4476
|
+
import_node_server_utils29.logger.log({ level: "error", message: error2.message });
|
|
4477
|
+
next(error2);
|
|
4478
|
+
return;
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
async function getScheduleTasks(req, res, next) {
|
|
4482
|
+
const query = { ...req.query, ...req.params };
|
|
4483
|
+
const validation = import_joi16.default.object({
|
|
4484
|
+
page: import_joi16.default.number().min(1).optional().allow("", null),
|
|
4485
|
+
limit: import_joi16.default.number().min(1).optional().allow("", null),
|
|
4486
|
+
search: import_joi16.default.string().optional().allow("", null),
|
|
4487
|
+
site: import_joi16.default.string().hex().required()
|
|
4488
|
+
});
|
|
4489
|
+
const { error } = validation.validate(query);
|
|
4490
|
+
if (error) {
|
|
4491
|
+
import_node_server_utils29.logger.log({ level: "error", message: error.message });
|
|
4492
|
+
next(new import_node_server_utils29.BadRequestError(error.message));
|
|
4493
|
+
return;
|
|
4494
|
+
}
|
|
4495
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
4496
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
4497
|
+
const search = req.query.search ?? "";
|
|
4498
|
+
const site = req.params.site ?? "";
|
|
4499
|
+
try {
|
|
4500
|
+
const data = await _getScheduleTasks({
|
|
4501
|
+
page,
|
|
4502
|
+
limit,
|
|
4503
|
+
search,
|
|
4504
|
+
site
|
|
4505
|
+
});
|
|
4506
|
+
res.json(data);
|
|
4507
|
+
return;
|
|
4508
|
+
} catch (error2) {
|
|
4509
|
+
import_node_server_utils29.logger.log({ level: "error", message: error2.message });
|
|
4510
|
+
next(error2);
|
|
4511
|
+
return;
|
|
4512
|
+
}
|
|
4513
|
+
}
|
|
4514
|
+
async function getScheduleTaskById(req, res, next) {
|
|
4515
|
+
const validation = import_joi16.default.string().hex().required();
|
|
4516
|
+
const _id = req.params.id;
|
|
4517
|
+
const { error } = validation.validate(_id);
|
|
4518
|
+
if (error) {
|
|
4519
|
+
import_node_server_utils29.logger.log({ level: "error", message: error.message });
|
|
4520
|
+
next(new import_node_server_utils29.BadRequestError(error.message));
|
|
4521
|
+
return;
|
|
4522
|
+
}
|
|
4523
|
+
try {
|
|
4524
|
+
const data = await _getScheduleTaskById(_id);
|
|
4525
|
+
res.json(data);
|
|
4526
|
+
return;
|
|
4527
|
+
} catch (error2) {
|
|
4528
|
+
import_node_server_utils29.logger.log({ level: "error", message: error2.message });
|
|
4529
|
+
next(error2);
|
|
4530
|
+
return;
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4533
|
+
async function updateScheduleTask(req, res, next) {
|
|
4534
|
+
const payload = { id: req.params.id, ...req.body };
|
|
4535
|
+
const validation = import_joi16.default.object({
|
|
4536
|
+
id: import_joi16.default.string().hex().required(),
|
|
4537
|
+
title: import_joi16.default.string().optional().allow("", null),
|
|
4538
|
+
frequency: import_joi16.default.string().valid(...allowedFrequency).optional().allow("", null),
|
|
4539
|
+
time: import_joi16.default.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).optional().allow("", null),
|
|
4540
|
+
day: import_joi16.default.string().valid(...allowedDays).optional().allow("", null),
|
|
4541
|
+
weekOfMonth: import_joi16.default.string().valid(...allowedWeekOfMonth).optional().allow("", null),
|
|
4542
|
+
quarter: import_joi16.default.string().valid(...allowedQuarter).optional().allow("", null),
|
|
4543
|
+
month: import_joi16.default.string().valid(...allowedMonths).optional().allow("", null),
|
|
4544
|
+
description: import_joi16.default.string().optional().allow("", null),
|
|
4545
|
+
areas: import_joi16.default.array().min(1).items(
|
|
4546
|
+
import_joi16.default.object({
|
|
4547
|
+
name: import_joi16.default.string().required(),
|
|
4548
|
+
value: import_joi16.default.any().required()
|
|
4549
|
+
})
|
|
4550
|
+
).optional()
|
|
4551
|
+
});
|
|
4552
|
+
const { error } = validation.validate(payload);
|
|
4553
|
+
if (error) {
|
|
4554
|
+
import_node_server_utils29.logger.log({ level: "error", message: error.message });
|
|
4555
|
+
next(new import_node_server_utils29.BadRequestError(error.message));
|
|
4556
|
+
return;
|
|
4557
|
+
}
|
|
4558
|
+
try {
|
|
4559
|
+
const { id, ...value } = payload;
|
|
4560
|
+
await _updateScheduleTask(id, value);
|
|
4561
|
+
res.json({ message: "Schedule task updated successfully." });
|
|
4562
|
+
return;
|
|
4563
|
+
} catch (error2) {
|
|
4564
|
+
import_node_server_utils29.logger.log({ level: "error", message: error2.message });
|
|
4565
|
+
next(error2);
|
|
4566
|
+
return;
|
|
4567
|
+
}
|
|
4568
|
+
}
|
|
4569
|
+
return {
|
|
4570
|
+
createScheduleTask,
|
|
4571
|
+
getScheduleTasks,
|
|
4572
|
+
getScheduleTaskById,
|
|
4573
|
+
updateScheduleTask
|
|
3856
4574
|
};
|
|
3857
4575
|
}
|
|
3858
4576
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -3861,17 +4579,24 @@ function useRequestItemController() {
|
|
|
3861
4579
|
MAreaChecklist,
|
|
3862
4580
|
MParentChecklist,
|
|
3863
4581
|
MRequestItem,
|
|
4582
|
+
MScheduleTask,
|
|
3864
4583
|
MStock,
|
|
3865
4584
|
MSupply,
|
|
3866
4585
|
MUnit,
|
|
3867
4586
|
allowedChecklistStatus,
|
|
4587
|
+
allowedDays,
|
|
4588
|
+
allowedFrequency,
|
|
4589
|
+
allowedMonths,
|
|
4590
|
+
allowedQuarter,
|
|
3868
4591
|
allowedRequestItemStatus,
|
|
3869
4592
|
allowedStatus,
|
|
3870
4593
|
allowedTypes,
|
|
4594
|
+
allowedWeekOfMonth,
|
|
3871
4595
|
areaChecklistSchema,
|
|
3872
4596
|
areaSchema,
|
|
3873
4597
|
parentChecklistSchema,
|
|
3874
4598
|
requestItemSchema,
|
|
4599
|
+
scheduleTaskSchema,
|
|
3875
4600
|
stockSchema,
|
|
3876
4601
|
supplySchema,
|
|
3877
4602
|
unitSchema,
|
|
@@ -3886,6 +4611,8 @@ function useRequestItemController() {
|
|
|
3886
4611
|
useRequestItemController,
|
|
3887
4612
|
useRequestItemRepository,
|
|
3888
4613
|
useRequestItemService,
|
|
4614
|
+
useScheduleTaskController,
|
|
4615
|
+
useScheduleTaskRepository,
|
|
3889
4616
|
useStockController,
|
|
3890
4617
|
useStockRepository,
|
|
3891
4618
|
useStockService,
|