@iservice365/module-hygiene 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -790,8 +790,8 @@ function MUnit(value) {
790
790
  return {
791
791
  site: value.site,
792
792
  name: value.name,
793
- createdAt: /* @__PURE__ */ new Date(),
794
793
  status: "active",
794
+ createdAt: /* @__PURE__ */ new Date(),
795
795
  updatedAt: "",
796
796
  deletedAt: ""
797
797
  };
@@ -1503,6 +1503,9 @@ function useParentChecklistRepo() {
1503
1503
  status,
1504
1504
  updatedAt: /* @__PURE__ */ new Date()
1505
1505
  };
1506
+ if (status === "completed") {
1507
+ updateValue.completedAt = /* @__PURE__ */ new Date();
1508
+ }
1506
1509
  const res = await collection.updateOne(
1507
1510
  { _id },
1508
1511
  { $set: updateValue },
@@ -2932,7 +2935,8 @@ function useSupplyRepository() {
2932
2935
  {
2933
2936
  $project: {
2934
2937
  name: 1,
2935
- qty: 1
2938
+ qty: 1,
2939
+ status: 1
2936
2940
  }
2937
2941
  },
2938
2942
  { $sort: { _id: -1 } },
@@ -3025,7 +3029,7 @@ function useSupplyRepository() {
3025
3029
  } catch (error) {
3026
3030
  const isDuplicated = error.message.includes("duplicate");
3027
3031
  if (isDuplicated) {
3028
- throw new BadRequestError16("Area already exists.");
3032
+ throw new BadRequestError16("Supply already exists.");
3029
3033
  }
3030
3034
  throw error;
3031
3035
  }
@@ -3567,7 +3571,8 @@ import {
3567
3571
  logger as logger23,
3568
3572
  makeCacheKey as makeCacheKey7,
3569
3573
  paginate as paginate7,
3570
- BadRequestError as BadRequestError23
3574
+ BadRequestError as BadRequestError23,
3575
+ NotFoundError as NotFoundError6
3571
3576
  } from "@iservice365/node-server-utils";
3572
3577
  function useRequestItemRepository() {
3573
3578
  const db = useAtlas10.getDb();
@@ -3656,7 +3661,7 @@ function useRequestItemRepository() {
3656
3661
  status: 1
3657
3662
  }
3658
3663
  },
3659
- { $sort: { _id: 1 } },
3664
+ { $sort: { _id: -1 } },
3660
3665
  { $skip: page * limit },
3661
3666
  { $limit: limit }
3662
3667
  ]).toArray();
@@ -3672,21 +3677,156 @@ function useRequestItemRepository() {
3672
3677
  throw error;
3673
3678
  }
3674
3679
  }
3680
+ async function getRequestItemById(_id, session) {
3681
+ try {
3682
+ _id = new ObjectId14(_id);
3683
+ } catch (error) {
3684
+ throw new BadRequestError23("Invalid request item ID format.");
3685
+ }
3686
+ const query = { _id };
3687
+ const cacheKey = makeCacheKey7(namespace_collection, {
3688
+ _id: _id.toString()
3689
+ });
3690
+ if (!session) {
3691
+ const cachedData = await getCache(cacheKey);
3692
+ if (cachedData) {
3693
+ logger23.info(`Cache hit for key: ${cacheKey}`);
3694
+ return cachedData;
3695
+ }
3696
+ } else {
3697
+ logger23.info(`Skipping cache during transaction for key: ${cacheKey}`);
3698
+ }
3699
+ try {
3700
+ const data = await collection.aggregate([
3701
+ { $match: query },
3702
+ {
3703
+ $lookup: {
3704
+ from: "site.supply.items",
3705
+ localField: "supply",
3706
+ foreignField: "_id",
3707
+ as: "supplyDetails"
3708
+ }
3709
+ },
3710
+ {
3711
+ $unwind: {
3712
+ path: "$supplyDetails",
3713
+ preserveNullAndEmptyArrays: true
3714
+ }
3715
+ },
3716
+ {
3717
+ $project: {
3718
+ site: 1,
3719
+ supply: 1,
3720
+ supplyName: 1,
3721
+ qty: 1,
3722
+ status: 1,
3723
+ unitOfMeasurement: "$supplyDetails.unitOfMeasurement"
3724
+ }
3725
+ }
3726
+ ]).toArray();
3727
+ if (!data || data.length === 0) {
3728
+ throw new NotFoundError6("Request item not found.");
3729
+ }
3730
+ setCache(cacheKey, data[0], 15 * 60).then(() => {
3731
+ logger23.info(`Cache set for key: ${cacheKey}`);
3732
+ }).catch((err) => {
3733
+ logger23.error(`Failed to set cache for key: ${cacheKey}`, err);
3734
+ });
3735
+ return data[0];
3736
+ } catch (error) {
3737
+ throw error;
3738
+ }
3739
+ }
3740
+ async function approveRequestItem(_id, remarks, session) {
3741
+ try {
3742
+ _id = new ObjectId14(_id);
3743
+ } catch (error) {
3744
+ throw new BadRequestError23("Invalid request item ID format.");
3745
+ }
3746
+ try {
3747
+ const updateValue = {
3748
+ status: "approved",
3749
+ remarks: remarks || "",
3750
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3751
+ };
3752
+ const res = await collection.updateOne(
3753
+ { _id },
3754
+ { $set: updateValue },
3755
+ { session }
3756
+ );
3757
+ if (res.modifiedCount === 0) {
3758
+ throw new InternalServerError7("Unable to approve request item.");
3759
+ }
3760
+ delNamespace().then(() => {
3761
+ logger23.info(`Cache cleared for namespace: ${namespace_collection}`);
3762
+ }).catch((err) => {
3763
+ logger23.error(
3764
+ `Failed to clear cache for namespace: ${namespace_collection}`,
3765
+ err
3766
+ );
3767
+ });
3768
+ return res.modifiedCount;
3769
+ } catch (error) {
3770
+ throw error;
3771
+ }
3772
+ }
3773
+ async function disapproveRequestItem(_id, remarks, session) {
3774
+ try {
3775
+ _id = new ObjectId14(_id);
3776
+ } catch (error) {
3777
+ throw new BadRequestError23("Invalid request item ID format.");
3778
+ }
3779
+ try {
3780
+ const updateValue = {
3781
+ status: "disapproved",
3782
+ remarks: remarks || "",
3783
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3784
+ };
3785
+ const res = await collection.updateOne(
3786
+ { _id },
3787
+ { $set: updateValue },
3788
+ { session }
3789
+ );
3790
+ if (res.modifiedCount === 0) {
3791
+ throw new InternalServerError7("Unable to disapprove request item.");
3792
+ }
3793
+ delNamespace().then(() => {
3794
+ logger23.info(`Cache cleared for namespace: ${namespace_collection}`);
3795
+ }).catch((err) => {
3796
+ logger23.error(
3797
+ `Failed to clear cache for namespace: ${namespace_collection}`,
3798
+ err
3799
+ );
3800
+ });
3801
+ return res.modifiedCount;
3802
+ } catch (error) {
3803
+ throw error;
3804
+ }
3805
+ }
3675
3806
  return {
3676
3807
  createIndex,
3677
3808
  createTextIndex,
3678
3809
  createRequestItem,
3679
- getRequestItems
3810
+ getRequestItems,
3811
+ getRequestItemById,
3812
+ approveRequestItem,
3813
+ disapproveRequestItem
3680
3814
  };
3681
3815
  }
3682
3816
 
3683
3817
  // src/services/hygiene-request-item.service.ts
3684
- import { useAtlas as useAtlas11 } from "@iservice365/node-server-utils";
3818
+ import { BadRequestError as BadRequestError24, useAtlas as useAtlas11 } from "@iservice365/node-server-utils";
3685
3819
  import { useUserRepo } from "@iservice365/core";
3686
3820
  function useRequestItemService() {
3687
- const { createRequestItem: _createRequestItem } = useRequestItemRepository();
3821
+ const {
3822
+ createRequestItem: _createRequestItem,
3823
+ getRequestItemById: _getRequestItemById,
3824
+ approveRequestItem: _approveRequestItem,
3825
+ disapproveRequestItem: _disapproveRequestItem
3826
+ } = useRequestItemRepository();
3688
3827
  const { getSupplyById } = useSupplyRepository();
3689
3828
  const { getUserById } = useUserRepo();
3829
+ const { createStock } = useStockService();
3690
3830
  async function createRequestItem(value) {
3691
3831
  try {
3692
3832
  const { supply, createdBy } = value;
@@ -3733,17 +3873,76 @@ function useRequestItemService() {
3733
3873
  await session?.endSession();
3734
3874
  }
3735
3875
  }
3736
- return { createRequestItem, createRequestItemByBatch };
3876
+ async function approveRequestItem(id, remarks) {
3877
+ const session = useAtlas11.getClient()?.startSession();
3878
+ try {
3879
+ session?.startTransaction();
3880
+ await _approveRequestItem(id, remarks, session);
3881
+ const requestItem = await _getRequestItemById(id, session);
3882
+ if (requestItem.status !== "pending") {
3883
+ throw new BadRequestError24(
3884
+ "Only 'pending' request items can be approved."
3885
+ );
3886
+ }
3887
+ const createdStocks = await createStock(
3888
+ {
3889
+ site: requestItem.site.toString(),
3890
+ supply: requestItem.supply.toString(),
3891
+ qty: requestItem.qty,
3892
+ remarks
3893
+ },
3894
+ true
3895
+ );
3896
+ await session?.commitTransaction();
3897
+ return createdStocks;
3898
+ } catch (error) {
3899
+ await session?.abortTransaction();
3900
+ throw error;
3901
+ } finally {
3902
+ await session?.endSession();
3903
+ }
3904
+ }
3905
+ async function disapproveRequestItem(id, remarks) {
3906
+ const session = useAtlas11.getClient()?.startSession();
3907
+ try {
3908
+ session?.startTransaction();
3909
+ const result = await _disapproveRequestItem(id, remarks, session);
3910
+ const requestItem = await _getRequestItemById(id, session);
3911
+ if (requestItem.status !== "pending") {
3912
+ throw new BadRequestError24(
3913
+ "Only 'pending' request items can be disapproved."
3914
+ );
3915
+ }
3916
+ await session?.commitTransaction();
3917
+ return result;
3918
+ } catch (error) {
3919
+ await session?.abortTransaction();
3920
+ throw error;
3921
+ } finally {
3922
+ await session?.endSession();
3923
+ }
3924
+ }
3925
+ return {
3926
+ createRequestItem,
3927
+ createRequestItemByBatch,
3928
+ approveRequestItem,
3929
+ disapproveRequestItem
3930
+ };
3737
3931
  }
3738
3932
 
3739
3933
  // src/controllers/hygiene-request-item.controller.ts
3740
- import { BadRequestError as BadRequestError24, logger as logger24 } from "@iservice365/node-server-utils";
3934
+ import { BadRequestError as BadRequestError25, logger as logger24 } from "@iservice365/node-server-utils";
3741
3935
  import Joi14 from "joi";
3742
3936
  function useRequestItemController() {
3743
- const { getRequestItems: _getRequestItems } = useRequestItemRepository();
3937
+ const {
3938
+ getRequestItems: _getRequestItems,
3939
+ getRequestItemById: _getRequestItemById
3940
+ } = useRequestItemRepository();
3744
3941
  const {
3745
3942
  createRequestItem: _createRequestItem,
3746
- createRequestItemByBatch: _createRequestItemByBatch
3943
+ createRequestItemByBatch: _createRequestItemByBatch,
3944
+ approveRequestItem: _approveRequestItem,
3945
+ disapproveRequestItem: _disapproveRequestItem
3747
3946
  } = useRequestItemService();
3748
3947
  async function createRequestItem(req, res, next) {
3749
3948
  const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
@@ -3765,7 +3964,7 @@ function useRequestItemController() {
3765
3964
  const { error } = validation.validate(payload);
3766
3965
  if (error) {
3767
3966
  logger24.log({ level: "error", message: error.message });
3768
- next(new BadRequestError24(error.message));
3967
+ next(new BadRequestError25(error.message));
3769
3968
  return;
3770
3969
  }
3771
3970
  try {
@@ -3802,7 +4001,7 @@ function useRequestItemController() {
3802
4001
  const { error } = validation.validate(payload);
3803
4002
  if (error) {
3804
4003
  logger24.log({ level: "error", message: error.message });
3805
- next(new BadRequestError24(error.message));
4004
+ next(new BadRequestError25(error.message));
3806
4005
  return;
3807
4006
  }
3808
4007
  try {
@@ -3826,7 +4025,7 @@ function useRequestItemController() {
3826
4025
  const { error } = validation.validate(query);
3827
4026
  if (error) {
3828
4027
  logger24.log({ level: "error", message: error.message });
3829
- next(new BadRequestError24(error.message));
4028
+ next(new BadRequestError25(error.message));
3830
4029
  return;
3831
4030
  }
3832
4031
  const page = parseInt(req.query.page) ?? 1;
@@ -3848,10 +4047,526 @@ function useRequestItemController() {
3848
4047
  return;
3849
4048
  }
3850
4049
  }
4050
+ async function getRequestItemById(req, res, next) {
4051
+ const validation = Joi14.string().hex().required();
4052
+ const _id = req.params.id;
4053
+ const { error } = validation.validate(_id);
4054
+ if (error) {
4055
+ logger24.log({ level: "error", message: error.message });
4056
+ next(new BadRequestError25(error.message));
4057
+ return;
4058
+ }
4059
+ try {
4060
+ const data = await _getRequestItemById(_id);
4061
+ res.json(data);
4062
+ return;
4063
+ } catch (error2) {
4064
+ logger24.log({ level: "error", message: error2.message });
4065
+ next(error2);
4066
+ return;
4067
+ }
4068
+ }
4069
+ async function approveRequestItem(req, res, next) {
4070
+ const payload = { ...req.params, ...req.body };
4071
+ const validation = Joi14.object({
4072
+ id: Joi14.string().hex().required(),
4073
+ remarks: Joi14.string().optional().allow("", null)
4074
+ });
4075
+ const { error } = validation.validate(payload);
4076
+ if (error) {
4077
+ logger24.log({ level: "error", message: error.message });
4078
+ next(new BadRequestError25(error.message));
4079
+ return;
4080
+ }
4081
+ try {
4082
+ await _approveRequestItem(payload.id, payload.remarks);
4083
+ res.json({ message: "Request item approved successfully." });
4084
+ return;
4085
+ } catch (error2) {
4086
+ logger24.log({ level: "error", message: error2.message });
4087
+ next(error2);
4088
+ return;
4089
+ }
4090
+ }
4091
+ async function disapproveRequestItem(req, res, next) {
4092
+ const payload = { ...req.params, ...req.body };
4093
+ const validation = Joi14.object({
4094
+ id: Joi14.string().hex().required(),
4095
+ remarks: Joi14.string().optional().allow("", null)
4096
+ });
4097
+ const { error } = validation.validate(payload);
4098
+ if (error) {
4099
+ logger24.log({ level: "error", message: error.message });
4100
+ next(new BadRequestError25(error.message));
4101
+ return;
4102
+ }
4103
+ try {
4104
+ await _disapproveRequestItem(payload.id, payload.remarks);
4105
+ res.json({ message: "Request item disapproved successfully." });
4106
+ return;
4107
+ } catch (error2) {
4108
+ logger24.log({ level: "error", message: error2.message });
4109
+ next(error2);
4110
+ return;
4111
+ }
4112
+ }
3851
4113
  return {
3852
4114
  createRequestItem,
3853
4115
  createRequestItemByBatch,
3854
- getRequestItems
4116
+ getRequestItems,
4117
+ getRequestItemById,
4118
+ approveRequestItem,
4119
+ disapproveRequestItem
4120
+ };
4121
+ }
4122
+
4123
+ // src/models/hygiene-schedule-task.model.ts
4124
+ import { BadRequestError as BadRequestError26, logger as logger25 } from "@iservice365/node-server-utils";
4125
+ import Joi15 from "joi";
4126
+ import { ObjectId as ObjectId15 } from "mongodb";
4127
+ var allowedFrequency = ["week", "month", "quarter", "year"];
4128
+ var allowedDays = [
4129
+ "Mon",
4130
+ "Tue",
4131
+ "Wed",
4132
+ "Thu",
4133
+ "Fri",
4134
+ "Sat",
4135
+ "Sun"
4136
+ ];
4137
+ var allowedQuarter = ["1st", "2nd", "3rd", "4th"];
4138
+ var allowedWeekOfMonth = [
4139
+ "1st",
4140
+ "2nd",
4141
+ "3rd",
4142
+ "4th",
4143
+ "last"
4144
+ ];
4145
+ var allowedMonths = [
4146
+ "January",
4147
+ "February",
4148
+ "March",
4149
+ "April",
4150
+ "May",
4151
+ "June",
4152
+ "July",
4153
+ "August",
4154
+ "September",
4155
+ "October",
4156
+ "November",
4157
+ "December"
4158
+ ];
4159
+ var scheduleTaskSchema = Joi15.object({
4160
+ site: Joi15.string().hex().required(),
4161
+ title: Joi15.string().required(),
4162
+ frequency: Joi15.string().valid(...allowedFrequency).required(),
4163
+ day: Joi15.string().valid(...allowedDays).required(),
4164
+ weekOfMonth: Joi15.string().valid(...allowedWeekOfMonth).when("frequency", {
4165
+ is: Joi15.string().valid("month", "quarter", "year"),
4166
+ then: Joi15.required(),
4167
+ otherwise: Joi15.optional().allow("", null)
4168
+ }),
4169
+ quarter: Joi15.string().valid(...allowedQuarter).when("frequency", {
4170
+ is: "quarter",
4171
+ then: Joi15.required(),
4172
+ otherwise: Joi15.optional().allow("", null)
4173
+ }),
4174
+ month: Joi15.string().valid(...allowedMonths).when("frequency", {
4175
+ is: Joi15.string().valid("quarter", "year"),
4176
+ then: Joi15.required(),
4177
+ otherwise: Joi15.optional().allow("", null)
4178
+ }),
4179
+ description: Joi15.string().optional().allow("", null),
4180
+ areas: Joi15.array().min(1).items(
4181
+ Joi15.object({
4182
+ name: Joi15.string().required(),
4183
+ value: Joi15.any().required()
4184
+ })
4185
+ ).required()
4186
+ });
4187
+ function MScheduleTask(value) {
4188
+ const { error } = scheduleTaskSchema.validate(value);
4189
+ if (error) {
4190
+ logger25.info(`Hygiene Schedule Task Model: ${error.message}`);
4191
+ throw new BadRequestError26(error.message);
4192
+ }
4193
+ if (value.site) {
4194
+ try {
4195
+ value.site = new ObjectId15(value.site);
4196
+ } catch (error2) {
4197
+ throw new BadRequestError26("Invalid site ID format.");
4198
+ }
4199
+ }
4200
+ if (value.areas && Array.isArray(value.areas)) {
4201
+ value.areas = value.areas.map((area) => {
4202
+ try {
4203
+ return {
4204
+ name: area.name,
4205
+ value: new ObjectId15(area.value.toString())
4206
+ };
4207
+ } catch (error2) {
4208
+ throw new BadRequestError26(`Invalid area value format: ${area.name}`);
4209
+ }
4210
+ });
4211
+ }
4212
+ return {
4213
+ site: value.site,
4214
+ title: value.title,
4215
+ frequency: value.frequency,
4216
+ day: value.day,
4217
+ weekOfMonth: value.weekOfMonth,
4218
+ quarter: value.quarter,
4219
+ month: value.month,
4220
+ description: value.description,
4221
+ areas: value.areas,
4222
+ status: "active",
4223
+ createdAt: /* @__PURE__ */ new Date(),
4224
+ updatedAt: "",
4225
+ deletedAt: ""
4226
+ };
4227
+ }
4228
+
4229
+ // src/repositories/hygiene-schedule-task.repository.ts
4230
+ import { ObjectId as ObjectId16 } from "mongodb";
4231
+ import {
4232
+ useAtlas as useAtlas12,
4233
+ InternalServerError as InternalServerError8,
4234
+ paginate as paginate8,
4235
+ BadRequestError as BadRequestError27,
4236
+ useCache as useCache8,
4237
+ logger as logger26,
4238
+ makeCacheKey as makeCacheKey8,
4239
+ NotFoundError as NotFoundError7
4240
+ } from "@iservice365/node-server-utils";
4241
+ function useScheduleTaskRepository() {
4242
+ const db = useAtlas12.getDb();
4243
+ if (!db) {
4244
+ throw new InternalServerError8("Unable to connect to server.");
4245
+ }
4246
+ const namespace_collection = "site.schedule-tasks";
4247
+ const collection = db.collection(namespace_collection);
4248
+ const { delNamespace, setCache, getCache } = useCache8(namespace_collection);
4249
+ async function createIndex() {
4250
+ try {
4251
+ await collection.createIndexes([
4252
+ { key: { site: 1 } },
4253
+ { key: { status: 1 } }
4254
+ ]);
4255
+ } catch (error) {
4256
+ throw new InternalServerError8(
4257
+ "Failed to create index on hygiene schedule task."
4258
+ );
4259
+ }
4260
+ }
4261
+ async function createTextIndex() {
4262
+ try {
4263
+ await collection.createIndex({ title: "text", description: "text" });
4264
+ } catch (error) {
4265
+ throw new InternalServerError8(
4266
+ "Failed to create text index on hygiene schedule task."
4267
+ );
4268
+ }
4269
+ }
4270
+ async function createScheduleTask(value, session) {
4271
+ try {
4272
+ value = MScheduleTask(value);
4273
+ const res = await collection.insertOne(value, { session });
4274
+ delNamespace().then(() => {
4275
+ logger26.info(`Cache cleared for namespace: ${namespace_collection}`);
4276
+ }).catch((err) => {
4277
+ logger26.error(
4278
+ `Failed to clear cache for namespace: ${namespace_collection}`,
4279
+ err
4280
+ );
4281
+ });
4282
+ return res.insertedId;
4283
+ } catch (error) {
4284
+ throw error;
4285
+ }
4286
+ }
4287
+ async function getScheduleTasks({
4288
+ page = 1,
4289
+ limit = 10,
4290
+ search = "",
4291
+ site
4292
+ }) {
4293
+ page = page > 0 ? page - 1 : 0;
4294
+ const query = {
4295
+ status: { $ne: "deleted" }
4296
+ };
4297
+ const cacheOptions = {
4298
+ page,
4299
+ limit
4300
+ };
4301
+ try {
4302
+ site = new ObjectId16(site);
4303
+ query.site = site;
4304
+ cacheOptions.site = site.toString();
4305
+ } catch (error) {
4306
+ throw new BadRequestError27("Invalid site ID format.");
4307
+ }
4308
+ if (search) {
4309
+ query.$or = [{ name: { $regex: search, $options: "i" } }];
4310
+ cacheOptions.search = search;
4311
+ }
4312
+ const cacheKey = makeCacheKey8(namespace_collection, cacheOptions);
4313
+ const cachedData = await getCache(cacheKey);
4314
+ if (cachedData) {
4315
+ logger26.info(`Cache hit for key: ${cacheKey}`);
4316
+ return cachedData;
4317
+ }
4318
+ try {
4319
+ const items = await collection.aggregate([
4320
+ { $match: query },
4321
+ {
4322
+ $project: {
4323
+ title: 1,
4324
+ areas: 1,
4325
+ status: 1
4326
+ }
4327
+ },
4328
+ { $sort: { _id: -1 } },
4329
+ { $skip: page * limit },
4330
+ { $limit: limit }
4331
+ ]).toArray();
4332
+ const length = await collection.countDocuments(query);
4333
+ const data = paginate8(items, page, limit, length);
4334
+ setCache(cacheKey, data, 15 * 60).then(() => {
4335
+ logger26.info(`Cache set for key: ${cacheKey}`);
4336
+ }).catch((err) => {
4337
+ logger26.error(`Failed to set cache for key: ${cacheKey}`, err);
4338
+ });
4339
+ return data;
4340
+ } catch (error) {
4341
+ throw error;
4342
+ }
4343
+ }
4344
+ async function getScheduleTaskById(_id, session) {
4345
+ try {
4346
+ _id = new ObjectId16(_id);
4347
+ } catch (error) {
4348
+ throw new BadRequestError27("Invalid schedule task ID format.");
4349
+ }
4350
+ const query = {
4351
+ _id,
4352
+ status: { $ne: "deleted" }
4353
+ };
4354
+ const cacheKey = makeCacheKey8(namespace_collection, {
4355
+ _id: _id.toString()
4356
+ });
4357
+ if (!session) {
4358
+ const cachedData = await getCache(cacheKey);
4359
+ if (cachedData) {
4360
+ logger26.info(`Cache hit for key: ${cacheKey}`);
4361
+ return cachedData;
4362
+ }
4363
+ } else {
4364
+ logger26.info(`Skipping cache during transaction for key: ${cacheKey}`);
4365
+ }
4366
+ try {
4367
+ const data = await collection.aggregate([
4368
+ { $match: query },
4369
+ {
4370
+ $project: {
4371
+ title: 1,
4372
+ frequency: 1,
4373
+ day: 1,
4374
+ weekOfMonth: 1,
4375
+ quarter: 1,
4376
+ month: 1,
4377
+ description: 1,
4378
+ areas: 1,
4379
+ status: 1,
4380
+ createdAt: 1
4381
+ }
4382
+ }
4383
+ ]).toArray();
4384
+ if (!data || data.length === 0) {
4385
+ throw new NotFoundError7("Schedule task not found.");
4386
+ }
4387
+ setCache(cacheKey, data[0], 15 * 60).then(() => {
4388
+ logger26.info(`Cache set for key: ${cacheKey}`);
4389
+ }).catch((err) => {
4390
+ logger26.error(`Failed to set cache for key: ${cacheKey}`, err);
4391
+ });
4392
+ return data[0];
4393
+ } catch (error) {
4394
+ throw error;
4395
+ }
4396
+ }
4397
+ async function updateScheduleTask(_id, value, session) {
4398
+ try {
4399
+ _id = new ObjectId16(_id);
4400
+ } catch (error) {
4401
+ throw new BadRequestError27("Invalid schedule task ID format.");
4402
+ }
4403
+ if (value.areas && Array.isArray(value.areas)) {
4404
+ value.areas = value.areas.map((area) => {
4405
+ try {
4406
+ return {
4407
+ name: area.name,
4408
+ value: new ObjectId16(area.value.toString())
4409
+ };
4410
+ } catch (error) {
4411
+ throw new BadRequestError27(`Invalid area value format: ${area.name}`);
4412
+ }
4413
+ });
4414
+ }
4415
+ try {
4416
+ const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
4417
+ const res = await collection.updateOne(
4418
+ { _id },
4419
+ { $set: updateValue },
4420
+ { session }
4421
+ );
4422
+ if (res.modifiedCount === 0) {
4423
+ throw new InternalServerError8(
4424
+ "Unable to update hygiene schedule task."
4425
+ );
4426
+ }
4427
+ delNamespace().then(() => {
4428
+ logger26.info(`Cache cleared for namespace: ${namespace_collection}`);
4429
+ }).catch((err) => {
4430
+ logger26.error(
4431
+ `Failed to clear cache for namespace: ${namespace_collection}`,
4432
+ err
4433
+ );
4434
+ });
4435
+ return res.modifiedCount;
4436
+ } catch (error) {
4437
+ throw error;
4438
+ }
4439
+ }
4440
+ return {
4441
+ createIndex,
4442
+ createTextIndex,
4443
+ createScheduleTask,
4444
+ getScheduleTasks,
4445
+ getScheduleTaskById,
4446
+ updateScheduleTask
4447
+ };
4448
+ }
4449
+
4450
+ // src/controllers/hygiene-schedule-task.controller.ts
4451
+ import { BadRequestError as BadRequestError28, logger as logger27 } from "@iservice365/node-server-utils";
4452
+ import Joi16 from "joi";
4453
+ function useScheduleTaskController() {
4454
+ const {
4455
+ createScheduleTask: _createScheduleTask,
4456
+ getScheduleTasks: _getScheduleTasks,
4457
+ getScheduleTaskById: _getScheduleTaskById,
4458
+ updateScheduleTask: _updateScheduleTask
4459
+ } = useScheduleTaskRepository();
4460
+ async function createScheduleTask(req, res, next) {
4461
+ const payload = { ...req.body, ...req.params };
4462
+ const { error } = scheduleTaskSchema.validate(payload);
4463
+ if (error) {
4464
+ logger27.log({ level: "error", message: error.message });
4465
+ next(new BadRequestError28(error.message));
4466
+ return;
4467
+ }
4468
+ try {
4469
+ const id = await _createScheduleTask(payload);
4470
+ res.status(201).json({ message: "Schedule task created successfully.", id });
4471
+ return;
4472
+ } catch (error2) {
4473
+ logger27.log({ level: "error", message: error2.message });
4474
+ next(error2);
4475
+ return;
4476
+ }
4477
+ }
4478
+ async function getScheduleTasks(req, res, next) {
4479
+ const query = { ...req.query, ...req.params };
4480
+ const validation = Joi16.object({
4481
+ page: Joi16.number().min(1).optional().allow("", null),
4482
+ limit: Joi16.number().min(1).optional().allow("", null),
4483
+ search: Joi16.string().optional().allow("", null),
4484
+ site: Joi16.string().hex().required()
4485
+ });
4486
+ const { error } = validation.validate(query);
4487
+ if (error) {
4488
+ logger27.log({ level: "error", message: error.message });
4489
+ next(new BadRequestError28(error.message));
4490
+ return;
4491
+ }
4492
+ const page = parseInt(req.query.page) ?? 1;
4493
+ const limit = parseInt(req.query.limit) ?? 10;
4494
+ const search = req.query.search ?? "";
4495
+ const site = req.params.site ?? "";
4496
+ try {
4497
+ const data = await _getScheduleTasks({
4498
+ page,
4499
+ limit,
4500
+ search,
4501
+ site
4502
+ });
4503
+ res.json(data);
4504
+ return;
4505
+ } catch (error2) {
4506
+ logger27.log({ level: "error", message: error2.message });
4507
+ next(error2);
4508
+ return;
4509
+ }
4510
+ }
4511
+ async function getScheduleTaskById(req, res, next) {
4512
+ const validation = Joi16.string().hex().required();
4513
+ const _id = req.params.id;
4514
+ const { error } = validation.validate(_id);
4515
+ if (error) {
4516
+ logger27.log({ level: "error", message: error.message });
4517
+ next(new BadRequestError28(error.message));
4518
+ return;
4519
+ }
4520
+ try {
4521
+ const data = await _getScheduleTaskById(_id);
4522
+ res.json(data);
4523
+ return;
4524
+ } catch (error2) {
4525
+ logger27.log({ level: "error", message: error2.message });
4526
+ next(error2);
4527
+ return;
4528
+ }
4529
+ }
4530
+ async function updateScheduleTask(req, res, next) {
4531
+ const payload = { id: req.params.id, ...req.body };
4532
+ const validation = Joi16.object({
4533
+ id: Joi16.string().hex().required(),
4534
+ title: Joi16.string().optional().allow("", null),
4535
+ frequency: Joi16.string().valid(...allowedFrequency).optional().allow("", null),
4536
+ day: Joi16.string().valid(...allowedDays).optional().allow("", null),
4537
+ weekOfMonth: Joi16.string().valid(...allowedWeekOfMonth).optional().allow("", null),
4538
+ quarter: Joi16.string().valid(...allowedQuarter).optional().allow("", null),
4539
+ month: Joi16.string().valid(...allowedMonths).optional().allow("", null),
4540
+ description: Joi16.string().optional().allow("", null),
4541
+ areas: Joi16.array().min(1).items(
4542
+ Joi16.object({
4543
+ name: Joi16.string().required(),
4544
+ value: Joi16.any().required()
4545
+ })
4546
+ ).optional()
4547
+ });
4548
+ const { error } = validation.validate(payload);
4549
+ if (error) {
4550
+ logger27.log({ level: "error", message: error.message });
4551
+ next(new BadRequestError28(error.message));
4552
+ return;
4553
+ }
4554
+ try {
4555
+ const { id, ...value } = payload;
4556
+ await _updateScheduleTask(id, value);
4557
+ res.json({ message: "Schedule task updated successfully." });
4558
+ return;
4559
+ } catch (error2) {
4560
+ logger27.log({ level: "error", message: error2.message });
4561
+ next(error2);
4562
+ return;
4563
+ }
4564
+ }
4565
+ return {
4566
+ createScheduleTask,
4567
+ getScheduleTasks,
4568
+ getScheduleTaskById,
4569
+ updateScheduleTask
3855
4570
  };
3856
4571
  }
3857
4572
  export {
@@ -3859,17 +4574,24 @@ export {
3859
4574
  MAreaChecklist,
3860
4575
  MParentChecklist,
3861
4576
  MRequestItem,
4577
+ MScheduleTask,
3862
4578
  MStock,
3863
4579
  MSupply,
3864
4580
  MUnit,
3865
4581
  allowedChecklistStatus,
4582
+ allowedDays,
4583
+ allowedFrequency,
4584
+ allowedMonths,
4585
+ allowedQuarter,
3866
4586
  allowedRequestItemStatus,
3867
4587
  allowedStatus,
3868
4588
  allowedTypes,
4589
+ allowedWeekOfMonth,
3869
4590
  areaChecklistSchema,
3870
4591
  areaSchema,
3871
4592
  parentChecklistSchema,
3872
4593
  requestItemSchema,
4594
+ scheduleTaskSchema,
3873
4595
  stockSchema,
3874
4596
  supplySchema,
3875
4597
  unitSchema,
@@ -3884,6 +4606,8 @@ export {
3884
4606
  useRequestItemController,
3885
4607
  useRequestItemRepository,
3886
4608
  useRequestItemService,
4609
+ useScheduleTaskController,
4610
+ useScheduleTaskRepository,
3887
4611
  useStockController,
3888
4612
  useStockRepository,
3889
4613
  useStockService,