@iservice365/module-hygiene 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -3,9 +3,9 @@ var allowedTypes = ["common", "toilet"];
3
3
  var allowedStatus = ["ready", "ongoing", "completed"];
4
4
 
5
5
  // src/models/hygiene-area.model.ts
6
- import { BadRequestError, logger } from "@iservice365/node-server-utils";
7
6
  import Joi from "joi";
8
7
  import { ObjectId } from "mongodb";
8
+ import { BadRequestError, logger } from "@iservice365/node-server-utils";
9
9
  var areaSchema = Joi.object({
10
10
  site: Joi.string().hex().required(),
11
11
  name: Joi.string().required(),
@@ -200,12 +200,9 @@ function useAreaRepo() {
200
200
  throw error;
201
201
  }
202
202
  }
203
- async function getAreasForChecklist({
204
- site,
205
- type
206
- }) {
207
- const query = { type, status: { $ne: "deleted" } };
208
- const cacheOptions = { type };
203
+ async function getAreasForChecklist(site) {
204
+ const query = { status: { $ne: "deleted" } };
205
+ const cacheOptions = {};
209
206
  try {
210
207
  site = new ObjectId2(site);
211
208
  query.site = site;
@@ -225,6 +222,7 @@ function useAreaRepo() {
225
222
  {
226
223
  $project: {
227
224
  name: 1,
225
+ type: 1,
228
226
  set: 1,
229
227
  units: 1
230
228
  }
@@ -284,6 +282,28 @@ function useAreaRepo() {
284
282
  throw error;
285
283
  }
286
284
  }
285
+ async function getAreaByMultipleId(_id) {
286
+ for (let i = 0; i < _id.length; i++) {
287
+ try {
288
+ _id[i] = new ObjectId2(_id[i]);
289
+ } catch (error) {
290
+ throw new BadRequestError2("Invalid area ID format.");
291
+ }
292
+ }
293
+ const query = {
294
+ _id: { $in: _id },
295
+ status: { $ne: "deleted" }
296
+ };
297
+ try {
298
+ const data = await collection.aggregate([{ $match: query }]).toArray();
299
+ if (!data || data.length === 0) {
300
+ throw new NotFoundError("Area not found.");
301
+ }
302
+ return data;
303
+ } catch (error) {
304
+ throw error;
305
+ }
306
+ }
287
307
  async function verifyAreaByUnitId(unitId) {
288
308
  try {
289
309
  unitId = new ObjectId2(unitId);
@@ -445,6 +465,7 @@ function useAreaRepo() {
445
465
  getAreas,
446
466
  getAreasForChecklist,
447
467
  getAreaById,
468
+ getAreaByMultipleId,
448
469
  verifyAreaByUnitId,
449
470
  updateArea,
450
471
  updateAreaChecklist,
@@ -571,8 +592,8 @@ function useAreaService() {
571
592
  }
572
593
 
573
594
  // src/controllers/hygiene-area.controller.ts
574
- import { BadRequestError as BadRequestError4, logger as logger4 } from "@iservice365/node-server-utils";
575
595
  import Joi2 from "joi";
596
+ import { BadRequestError as BadRequestError4, logger as logger4 } from "@iservice365/node-server-utils";
576
597
 
577
598
  // src/utils/convert-excel.util.ts
578
599
  import { Readable } from "stream";
@@ -767,9 +788,9 @@ function useAreaController() {
767
788
  }
768
789
 
769
790
  // src/models/hygiene-unit.model.ts
770
- import { BadRequestError as BadRequestError5, logger as logger5 } from "@iservice365/node-server-utils";
771
791
  import Joi3 from "joi";
772
792
  import { ObjectId as ObjectId3 } from "mongodb";
793
+ import { BadRequestError as BadRequestError5, logger as logger5 } from "@iservice365/node-server-utils";
773
794
  var unitSchema = Joi3.object({
774
795
  site: Joi3.string().hex().required(),
775
796
  name: Joi3.string().required()
@@ -1006,12 +1027,12 @@ function useUnitRepository() {
1006
1027
 
1007
1028
  // src/services/hygiene-unit.service.ts
1008
1029
  function useUnitService() {
1030
+ const { verifyAreaByUnitId, updateAreaChecklist } = useAreaRepo();
1009
1031
  const {
1010
1032
  createUnit: _createUnit,
1011
1033
  updateUnit: _updateUnit,
1012
1034
  deleteUnit: _deleteUnit
1013
1035
  } = useUnitRepository();
1014
- const { verifyAreaByUnitId, updateAreaChecklist } = useAreaRepo();
1015
1036
  async function importUnit({
1016
1037
  dataJson,
1017
1038
  site
@@ -1151,8 +1172,8 @@ function useUnitService() {
1151
1172
  }
1152
1173
 
1153
1174
  // src/controllers/hygiene-unit.controller.ts
1154
- import { BadRequestError as BadRequestError8, logger as logger8 } from "@iservice365/node-server-utils";
1155
1175
  import Joi4 from "joi";
1176
+ import { BadRequestError as BadRequestError8, logger as logger8 } from "@iservice365/node-server-utils";
1156
1177
  function useUnitController() {
1157
1178
  const { createUnit: _createUnit, getUnits: _getUnits } = useUnitRepository();
1158
1179
  const {
@@ -1289,9 +1310,9 @@ function useUnitController() {
1289
1310
  }
1290
1311
 
1291
1312
  // src/models/hygiene-parent-checklist.model.ts
1292
- import { BadRequestError as BadRequestError9, logger as logger9 } from "@iservice365/node-server-utils";
1293
1313
  import Joi5 from "joi";
1294
1314
  import { ObjectId as ObjectId5 } from "mongodb";
1315
+ import { BadRequestError as BadRequestError9, logger as logger9 } from "@iservice365/node-server-utils";
1295
1316
  var parentChecklistSchema = Joi5.object({
1296
1317
  createdAt: Joi5.alternatives().try(Joi5.date(), Joi5.string()).optional().allow("", null),
1297
1318
  site: Joi5.string().hex().required()
@@ -1568,8 +1589,8 @@ function useParentChecklistRepo() {
1568
1589
  }
1569
1590
 
1570
1591
  // src/controllers/hygiene-parent-checklist.controller.ts
1571
- import { BadRequestError as BadRequestError11, logger as logger11 } from "@iservice365/node-server-utils";
1572
1592
  import Joi6 from "joi";
1593
+ import { BadRequestError as BadRequestError11, logger as logger11 } from "@iservice365/node-server-utils";
1573
1594
  function useParentChecklistController() {
1574
1595
  const {
1575
1596
  createParentChecklist: _createParentChecklist,
@@ -1639,12 +1660,13 @@ function useParentChecklistController() {
1639
1660
  }
1640
1661
 
1641
1662
  // src/models/hygiene-area-checklist.model.ts
1642
- import { BadRequestError as BadRequestError12, logger as logger12 } from "@iservice365/node-server-utils";
1643
1663
  import Joi7 from "joi";
1644
1664
  import { ObjectId as ObjectId7 } from "mongodb";
1665
+ import { BadRequestError as BadRequestError12, logger as logger12 } from "@iservice365/node-server-utils";
1645
1666
  var allowedChecklistStatus = ["ready", "completed"];
1646
1667
  var areaChecklistSchema = Joi7.object({
1647
1668
  schedule: Joi7.string().hex().required(),
1669
+ area: Joi7.string().hex().required(),
1648
1670
  name: Joi7.string().required(),
1649
1671
  type: Joi7.string().valid(...allowedTypes).required(),
1650
1672
  checklist: Joi7.array().items(
@@ -1672,6 +1694,13 @@ function MAreaChecklist(value) {
1672
1694
  throw new BadRequestError12("Invalid schedule ID format.");
1673
1695
  }
1674
1696
  }
1697
+ if (value.area) {
1698
+ try {
1699
+ value.area = new ObjectId7(value.area);
1700
+ } catch (error2) {
1701
+ throw new BadRequestError12("Invalid area ID format.");
1702
+ }
1703
+ }
1675
1704
  if (value.checklist && Array.isArray(value.checklist)) {
1676
1705
  value.checklist = value.checklist.map((checklistItem) => {
1677
1706
  return {
@@ -1689,6 +1718,7 @@ function MAreaChecklist(value) {
1689
1718
  }
1690
1719
  return {
1691
1720
  schedule: value.schedule,
1721
+ area: value.area,
1692
1722
  name: value.name,
1693
1723
  type: value.type,
1694
1724
  checklist: value.checklist || [],
@@ -1703,6 +1733,7 @@ function MAreaChecklist(value) {
1703
1733
  import { logger as logger14, useAtlas as useAtlas6 } from "@iservice365/node-server-utils";
1704
1734
 
1705
1735
  // src/repositories/hygiene-area-checklist.repository.ts
1736
+ import { ObjectId as ObjectId8 } from "mongodb";
1706
1737
  import {
1707
1738
  BadRequestError as BadRequestError13,
1708
1739
  InternalServerError as InternalServerError4,
@@ -1712,7 +1743,6 @@ import {
1712
1743
  useAtlas as useAtlas5,
1713
1744
  useCache as useCache4
1714
1745
  } from "@iservice365/node-server-utils";
1715
- import { ObjectId as ObjectId8 } from "mongodb";
1716
1746
  function useAreaChecklistRepo() {
1717
1747
  const db = useAtlas5.getDb();
1718
1748
  if (!db) {
@@ -2378,6 +2408,7 @@ function useAreaChecklistRepo() {
2378
2408
 
2379
2409
  // src/services/hygiene-area-checklist.service.ts
2380
2410
  function useAreaChecklistService() {
2411
+ const { getAreasForChecklist } = useAreaRepo();
2381
2412
  const {
2382
2413
  createAreaChecklist: _createAreaChecklist,
2383
2414
  getAllAreaChecklist,
@@ -2386,7 +2417,6 @@ function useAreaChecklistService() {
2386
2417
  completeAreaChecklistUnits: _completeAreaChecklistUnits,
2387
2418
  updateAreaChecklistStatus
2388
2419
  } = useAreaChecklistRepo();
2389
- const { getAreasForChecklist } = useAreaRepo();
2390
2420
  const { updateParentChecklistStatuses } = useParentChecklistRepo();
2391
2421
  async function createAreaChecklist(value) {
2392
2422
  const session = useAtlas6.getClient()?.startSession();
@@ -2395,19 +2425,17 @@ function useAreaChecklistService() {
2395
2425
  const results = [];
2396
2426
  let totalChecklistsCreated = 0;
2397
2427
  const BATCH_SIZE = 10;
2398
- const commonAreasResult = await getAreasForChecklist({
2399
- site: value.site,
2400
- type: "common"
2401
- });
2402
- const commonAreas = commonAreasResult || [];
2403
- if (commonAreas.length > 0) {
2404
- for (let i = 0; i < commonAreas.length; i += BATCH_SIZE) {
2405
- const batch = commonAreas.slice(i, i + BATCH_SIZE);
2428
+ const areasResult = await getAreasForChecklist(value.site);
2429
+ const areas = areasResult || [];
2430
+ if (areas.length > 0) {
2431
+ for (let i = 0; i < areas.length; i += BATCH_SIZE) {
2432
+ const batch = areas.slice(i, i + BATCH_SIZE);
2406
2433
  const batchPromises = batch.map(async (area) => {
2407
2434
  const checklistData = {
2408
2435
  schedule: value.schedule,
2436
+ area: area._id.toString(),
2409
2437
  name: area.name,
2410
- type: "common",
2438
+ type: area.type,
2411
2439
  checklist: area.units && area.units.length > 0 ? Array.from({ length: area.set || 1 }, (_, index) => ({
2412
2440
  set: index + 1,
2413
2441
  units: area.units.map((unit) => ({
@@ -2427,51 +2455,11 @@ function useAreaChecklistService() {
2427
2455
  results.push(...batchResults);
2428
2456
  }
2429
2457
  logger14.info(
2430
- `Created ${commonAreas.length} common area checklists for site: ${value.site}`
2458
+ `Created ${areas.length} common area checklists for site: ${value.site}`
2431
2459
  );
2432
2460
  } else {
2433
2461
  logger14.warn(`No common areas found for site: ${value.site}`);
2434
2462
  }
2435
- const toiletAreasResult = await getAreasForChecklist({
2436
- site: value.site,
2437
- type: "toilet"
2438
- });
2439
- const toiletAreas = toiletAreasResult || [];
2440
- if (toiletAreas.length > 0) {
2441
- for (let i = 0; i < toiletAreas.length; i += BATCH_SIZE) {
2442
- const batch = toiletAreas.slice(i, i + BATCH_SIZE);
2443
- const batchPromises = batch.map(async (toiletLocation) => {
2444
- const checklistData = {
2445
- schedule: value.schedule,
2446
- name: toiletLocation.name,
2447
- type: "toilet",
2448
- checklist: toiletLocation.units && toiletLocation.units.length > 0 ? Array.from(
2449
- { length: toiletLocation.set || 1 },
2450
- (_, index) => ({
2451
- set: index + 1,
2452
- units: toiletLocation.units.map((unit) => ({
2453
- unit: unit.unit.toString(),
2454
- name: unit.name
2455
- }))
2456
- })
2457
- ) : []
2458
- };
2459
- const insertedId = await _createAreaChecklist(
2460
- checklistData,
2461
- session
2462
- );
2463
- totalChecklistsCreated++;
2464
- return insertedId;
2465
- });
2466
- const batchResults = await Promise.all(batchPromises);
2467
- results.push(...batchResults);
2468
- }
2469
- logger14.info(
2470
- `Created ${toiletAreas.length} toilet area checklists for site: ${value.site}`
2471
- );
2472
- } else {
2473
- logger14.warn(`No toilet locations found for site: ${value.site}`);
2474
- }
2475
2463
  await session?.commitTransaction();
2476
2464
  logger14.info(
2477
2465
  `Successfully created ${totalChecklistsCreated} area checklists for site: ${value.site}`
@@ -2575,8 +2563,8 @@ function useAreaChecklistService() {
2575
2563
  }
2576
2564
 
2577
2565
  // src/controllers/hygiene-area-checklist.controller.ts
2578
- import { BadRequestError as BadRequestError14, logger as logger15 } from "@iservice365/node-server-utils";
2579
2566
  import Joi8 from "joi";
2567
+ import { BadRequestError as BadRequestError14, logger as logger15 } from "@iservice365/node-server-utils";
2580
2568
  function useAreaChecklistController() {
2581
2569
  const {
2582
2570
  getAllAreaChecklist: _getAllAreaChecklist,
@@ -2794,9 +2782,9 @@ function useAreaChecklistController() {
2794
2782
  }
2795
2783
 
2796
2784
  // src/models/hygiene-supply.model.ts
2797
- import { BadRequestError as BadRequestError15, logger as logger16 } from "@iservice365/node-server-utils";
2798
2785
  import Joi9 from "joi";
2799
2786
  import { ObjectId as ObjectId9 } from "mongodb";
2787
+ import { BadRequestError as BadRequestError15, logger as logger16 } from "@iservice365/node-server-utils";
2800
2788
  var supplySchema = Joi9.object({
2801
2789
  site: Joi9.string().hex().required(),
2802
2790
  name: Joi9.string().required(),
@@ -3080,8 +3068,8 @@ function useSupplyRepository() {
3080
3068
  }
3081
3069
 
3082
3070
  // src/controllers/hygiene-supply.controller.ts
3083
- import { BadRequestError as BadRequestError17, logger as logger18 } from "@iservice365/node-server-utils";
3084
3071
  import Joi10 from "joi";
3072
+ import { BadRequestError as BadRequestError17, logger as logger18 } from "@iservice365/node-server-utils";
3085
3073
  function useSupplyController() {
3086
3074
  const {
3087
3075
  createSupply: _createSupply,
@@ -3216,9 +3204,9 @@ function useSupplyController() {
3216
3204
  }
3217
3205
 
3218
3206
  // src/models/hygiene-stock.model.ts
3219
- import { BadRequestError as BadRequestError18, logger as logger19 } from "@iservice365/node-server-utils";
3220
3207
  import Joi11 from "joi";
3221
3208
  import { ObjectId as ObjectId11 } from "mongodb";
3209
+ import { BadRequestError as BadRequestError18, logger as logger19 } from "@iservice365/node-server-utils";
3222
3210
  var stockSchema = Joi11.object({
3223
3211
  site: Joi11.string().hex().required(),
3224
3212
  supply: Joi11.string().hex().required(),
@@ -3439,8 +3427,8 @@ function useStockService() {
3439
3427
  }
3440
3428
 
3441
3429
  // src/controllers/hygiene-stock.controller.ts
3442
- import { BadRequestError as BadRequestError21, logger as logger21 } from "@iservice365/node-server-utils";
3443
3430
  import Joi12 from "joi";
3431
+ import { BadRequestError as BadRequestError21, logger as logger21 } from "@iservice365/node-server-utils";
3444
3432
  function useStockController() {
3445
3433
  const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
3446
3434
  const { createStock: _createStock } = useStockService();
@@ -3511,9 +3499,9 @@ function useStockController() {
3511
3499
  }
3512
3500
 
3513
3501
  // src/models/hygiene-request-item.model.ts
3514
- import { BadRequestError as BadRequestError22, logger as logger22 } from "@iservice365/node-server-utils";
3515
3502
  import Joi13 from "joi";
3516
3503
  import { ObjectId as ObjectId13 } from "mongodb";
3504
+ import { BadRequestError as BadRequestError22, logger as logger22 } from "@iservice365/node-server-utils";
3517
3505
  var allowedRequestItemStatus = [
3518
3506
  "pending",
3519
3507
  "approved",
@@ -3657,6 +3645,7 @@ function useRequestItemRepository() {
3657
3645
  { $match: query },
3658
3646
  {
3659
3647
  $project: {
3648
+ supplyName: 1,
3660
3649
  createdAt: 1,
3661
3650
  status: 1
3662
3651
  }
@@ -3815,8 +3804,8 @@ function useRequestItemRepository() {
3815
3804
  }
3816
3805
 
3817
3806
  // src/services/hygiene-request-item.service.ts
3818
- import { BadRequestError as BadRequestError24, useAtlas as useAtlas11 } from "@iservice365/node-server-utils";
3819
3807
  import { useUserRepo } from "@iservice365/core";
3808
+ import { BadRequestError as BadRequestError24, useAtlas as useAtlas11 } from "@iservice365/node-server-utils";
3820
3809
  function useRequestItemService() {
3821
3810
  const {
3822
3811
  createRequestItem: _createRequestItem,
@@ -3931,8 +3920,8 @@ function useRequestItemService() {
3931
3920
  }
3932
3921
 
3933
3922
  // src/controllers/hygiene-request-item.controller.ts
3934
- import { BadRequestError as BadRequestError25, logger as logger24 } from "@iservice365/node-server-utils";
3935
3923
  import Joi14 from "joi";
3924
+ import { BadRequestError as BadRequestError25, logger as logger24 } from "@iservice365/node-server-utils";
3936
3925
  function useRequestItemController() {
3937
3926
  const {
3938
3927
  getRequestItems: _getRequestItems,
@@ -4124,24 +4113,22 @@ function useRequestItemController() {
4124
4113
  import { BadRequestError as BadRequestError26, logger as logger25 } from "@iservice365/node-server-utils";
4125
4114
  import Joi15 from "joi";
4126
4115
  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"
4116
+ var allowedFrequency = [
4117
+ "daily",
4118
+ "weekly",
4119
+ "monthly",
4120
+ "annually"
4136
4121
  ];
4137
- var allowedQuarter = ["1st", "2nd", "3rd", "4th"];
4138
- var allowedWeekOfMonth = [
4139
- "1st",
4140
- "2nd",
4141
- "3rd",
4142
- "4th",
4143
- "last"
4122
+ var allowedDays = [
4123
+ "Monday",
4124
+ "Tuesday",
4125
+ "Wednesday",
4126
+ "Thursday",
4127
+ "Friday",
4128
+ "Saturday",
4129
+ "Sunday"
4144
4130
  ];
4131
+ var allowedWeekOfMonth = ["start", "end"];
4145
4132
  var allowedMonths = [
4146
4133
  "January",
4147
4134
  "February",
@@ -4161,22 +4148,10 @@ var scheduleTaskSchema = Joi15.object({
4161
4148
  title: Joi15.string().required(),
4162
4149
  frequency: Joi15.string().valid(...allowedFrequency).required(),
4163
4150
  time: Joi15.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).required(),
4164
- day: Joi15.string().valid(...allowedDays).required(),
4165
- weekOfMonth: Joi15.string().valid(...allowedWeekOfMonth).when("frequency", {
4166
- is: Joi15.string().valid("month", "quarter", "year"),
4167
- then: Joi15.required(),
4168
- otherwise: Joi15.optional().allow("", null)
4169
- }),
4170
- quarter: Joi15.string().valid(...allowedQuarter).when("frequency", {
4171
- is: "quarter",
4172
- then: Joi15.required(),
4173
- otherwise: Joi15.optional().allow("", null)
4174
- }),
4175
- month: Joi15.string().valid(...allowedMonths).when("frequency", {
4176
- is: Joi15.string().valid("quarter", "year"),
4177
- then: Joi15.required(),
4178
- otherwise: Joi15.optional().allow("", null)
4179
- }),
4151
+ day: Joi15.array().items(Joi15.string().valid(...allowedDays)).optional().allow(null),
4152
+ weekOfMonth: Joi15.string().valid(...allowedWeekOfMonth).optional().allow("", null),
4153
+ month: Joi15.string().valid(...allowedMonths).optional().allow("", null),
4154
+ date: Joi15.number().min(1).max(31).optional().allow(null),
4180
4155
  description: Joi15.string().optional().allow("", null),
4181
4156
  areas: Joi15.array().min(1).items(
4182
4157
  Joi15.object({
@@ -4217,8 +4192,8 @@ function MScheduleTask(value) {
4217
4192
  time: value.time,
4218
4193
  day: value.day,
4219
4194
  weekOfMonth: value.weekOfMonth,
4220
- quarter: value.quarter,
4221
4195
  month: value.month,
4196
+ date: value.date,
4222
4197
  description: value.description,
4223
4198
  areas: value.areas,
4224
4199
  status: "active",
@@ -4343,6 +4318,73 @@ function useScheduleTaskRepository() {
4343
4318
  throw error;
4344
4319
  }
4345
4320
  }
4321
+ async function getAllScheduleTask() {
4322
+ const query = {
4323
+ status: { $ne: "deleted" }
4324
+ };
4325
+ try {
4326
+ const items = await collection.aggregate([{ $match: query }, { $sort: { _id: -1 } }]).toArray();
4327
+ return items;
4328
+ } catch (error) {
4329
+ throw error;
4330
+ }
4331
+ }
4332
+ async function getTasksForScheduleTask({
4333
+ page = 1,
4334
+ limit = 10,
4335
+ search = "",
4336
+ site
4337
+ }) {
4338
+ page = page > 0 ? page - 1 : 0;
4339
+ const query = {
4340
+ status: { $ne: "deleted" }
4341
+ };
4342
+ const cacheOptions = {
4343
+ page,
4344
+ limit
4345
+ };
4346
+ try {
4347
+ site = new ObjectId16(site);
4348
+ query.site = site;
4349
+ cacheOptions.site = site.toString();
4350
+ } catch (error) {
4351
+ throw new BadRequestError27("Invalid site ID format.");
4352
+ }
4353
+ if (search) {
4354
+ query.$or = [{ name: { $regex: search, $options: "i" } }];
4355
+ cacheOptions.search = search;
4356
+ }
4357
+ const cacheKey = makeCacheKey8(namespace_collection, cacheOptions);
4358
+ const cachedData = await getCache(cacheKey);
4359
+ if (cachedData) {
4360
+ logger26.info(`Cache hit for key: ${cacheKey}`);
4361
+ return cachedData;
4362
+ }
4363
+ try {
4364
+ const items = await collection.aggregate([
4365
+ { $match: query },
4366
+ {
4367
+ $project: {
4368
+ createdAt: 1,
4369
+ title: 1
4370
+ }
4371
+ },
4372
+ { $sort: { _id: -1 } },
4373
+ { $skip: page * limit },
4374
+ { $limit: limit }
4375
+ ]).toArray();
4376
+ const length = await collection.countDocuments(query);
4377
+ const data = paginate8(items, page, limit, length);
4378
+ setCache(cacheKey, data, 15 * 60).then(() => {
4379
+ logger26.info(`Cache set for key: ${cacheKey}`);
4380
+ }).catch((err) => {
4381
+ logger26.error(`Failed to set cache for key: ${cacheKey}`, err);
4382
+ });
4383
+ return data;
4384
+ } catch (error) {
4385
+ throw error;
4386
+ }
4387
+ }
4346
4388
  async function getScheduleTaskById(_id, session) {
4347
4389
  try {
4348
4390
  _id = new ObjectId16(_id);
@@ -4375,8 +4417,8 @@ function useScheduleTaskRepository() {
4375
4417
  time: 1,
4376
4418
  day: 1,
4377
4419
  weekOfMonth: 1,
4378
- quarter: 1,
4379
4420
  month: 1,
4421
+ date: 1,
4380
4422
  description: 1,
4381
4423
  areas: 1,
4382
4424
  status: 1,
@@ -4445,18 +4487,213 @@ function useScheduleTaskRepository() {
4445
4487
  createTextIndex,
4446
4488
  createScheduleTask,
4447
4489
  getScheduleTasks,
4490
+ getAllScheduleTask,
4491
+ getTasksForScheduleTask,
4448
4492
  getScheduleTaskById,
4449
4493
  updateScheduleTask
4450
4494
  };
4451
4495
  }
4452
4496
 
4497
+ // src/services/hygiene-schedule-task.service.ts
4498
+ import { logger as logger27 } from "@iservice365/node-server-utils";
4499
+ function useScheduleTaskService() {
4500
+ const { createParentChecklist } = useParentChecklistRepo();
4501
+ const { getAllScheduleTask } = useScheduleTaskRepository();
4502
+ const { createAreaChecklist } = useAreaChecklistService();
4503
+ function checkScheduleConditions(schedule, currentDate = /* @__PURE__ */ new Date()) {
4504
+ try {
4505
+ const now = currentDate;
4506
+ const currentDay = now.toLocaleDateString("en-US", {
4507
+ weekday: "long",
4508
+ timeZone: "Asia/Singapore"
4509
+ });
4510
+ const currentMonth = now.toLocaleDateString("en-US", {
4511
+ month: "long",
4512
+ timeZone: "Asia/Singapore"
4513
+ });
4514
+ const currentDate_num = Number(
4515
+ now.toLocaleDateString("en-US", {
4516
+ day: "numeric",
4517
+ timeZone: "Asia/Singapore"
4518
+ })
4519
+ );
4520
+ const timeString = now.toLocaleTimeString("en-US", {
4521
+ hour: "2-digit",
4522
+ minute: "2-digit",
4523
+ hour12: false,
4524
+ timeZone: "Asia/Singapore"
4525
+ });
4526
+ const [currentHour, currentMinute] = timeString.split(":").map(Number);
4527
+ logger27.info(
4528
+ `Checking schedule ${schedule._id}: Current time ${currentHour}:${currentMinute}, Schedule time ${schedule.time}, Frequency ${schedule.frequency}`
4529
+ );
4530
+ const [scheduleHour, scheduleMinute] = schedule.time.split(":").map(Number);
4531
+ const timeMatches = currentHour === scheduleHour && currentMinute === scheduleMinute;
4532
+ if (!timeMatches) {
4533
+ logger27.info(
4534
+ `Schedule ${schedule._id}: Time does not match. Current: ${currentHour}:${currentMinute}, Expected: ${scheduleHour}:${scheduleMinute}`
4535
+ );
4536
+ return false;
4537
+ }
4538
+ logger27.info(
4539
+ `Schedule ${schedule._id}: Time matches, checking frequency...`
4540
+ );
4541
+ switch (schedule.frequency) {
4542
+ case "daily":
4543
+ logger27.info(`Schedule ${schedule._id}: Daily frequency matched`);
4544
+ return true;
4545
+ case "weekly":
4546
+ if (!schedule.day || schedule.day.length === 0) {
4547
+ logger27.warn(
4548
+ `Schedule ${schedule._id} is weekly but has no days specified`
4549
+ );
4550
+ return false;
4551
+ }
4552
+ const dayMatches = schedule.day.includes(currentDay);
4553
+ logger27.info(
4554
+ `Schedule ${schedule._id}: Weekly - Current day: ${currentDay}, Schedule days: ${schedule.day.join(
4555
+ ", "
4556
+ )}, Match: ${dayMatches}`
4557
+ );
4558
+ return dayMatches;
4559
+ case "monthly":
4560
+ if (!schedule.weekOfMonth) {
4561
+ logger27.warn(
4562
+ `Schedule ${schedule._id} is monthly but has no weekOfMonth specified`
4563
+ );
4564
+ return false;
4565
+ }
4566
+ if (schedule.weekOfMonth === "start") {
4567
+ const matches2 = currentDate_num >= 1 && currentDate_num <= 7;
4568
+ logger27.info(
4569
+ `Schedule ${schedule._id}: Monthly start - Current date: ${currentDate_num}, Match: ${matches2}`
4570
+ );
4571
+ return matches2;
4572
+ } else if (schedule.weekOfMonth === "end") {
4573
+ const lastDayOfMonth = new Date(
4574
+ now.getFullYear(),
4575
+ now.getMonth() + 1,
4576
+ 0
4577
+ ).getDate();
4578
+ const matches2 = currentDate_num > lastDayOfMonth - 7;
4579
+ logger27.info(
4580
+ `Schedule ${schedule._id}: Monthly end - Current date: ${currentDate_num}, Last day: ${lastDayOfMonth}, Match: ${matches2}`
4581
+ );
4582
+ return matches2;
4583
+ }
4584
+ return false;
4585
+ case "annually":
4586
+ if (!schedule.month || !schedule.date) {
4587
+ logger27.warn(
4588
+ `Schedule ${schedule._id} is annually but has no month or date specified`
4589
+ );
4590
+ return false;
4591
+ }
4592
+ const matches = currentMonth === schedule.month && currentDate_num === schedule.date;
4593
+ logger27.info(
4594
+ `Schedule ${schedule._id}: Annually - Current: ${currentMonth} ${currentDate_num}, Expected: ${schedule.month} ${schedule.date}, Match: ${matches}`
4595
+ );
4596
+ return matches;
4597
+ default:
4598
+ logger27.warn(`Unknown frequency type: ${schedule.frequency}`);
4599
+ return false;
4600
+ }
4601
+ } catch (error) {
4602
+ logger27.error(
4603
+ `Error checking schedule conditions for ${schedule._id}:`,
4604
+ error
4605
+ );
4606
+ return false;
4607
+ }
4608
+ }
4609
+ async function processScheduledTasks(currentDate) {
4610
+ try {
4611
+ logger27.info("Starting scheduled task processing...");
4612
+ const scheduleTasks = await getAllScheduleTask();
4613
+ if (!scheduleTasks || scheduleTasks.length === 0) {
4614
+ logger27.info("No schedule tasks found to process");
4615
+ return { processed: 0, validated: 0 };
4616
+ }
4617
+ logger27.info(`Found ${scheduleTasks.length} schedule tasks to check`);
4618
+ let processedCount = 0;
4619
+ let validatedCount = 0;
4620
+ const validatedTasks = [];
4621
+ for (const scheduleTask of scheduleTasks) {
4622
+ try {
4623
+ logger27.info(
4624
+ `Checking schedule ${scheduleTask._id} - ${scheduleTask.title}: time=${scheduleTask.time}, frequency=${scheduleTask.frequency}`
4625
+ );
4626
+ const shouldRun = checkScheduleConditions(scheduleTask, currentDate);
4627
+ if (!shouldRun) {
4628
+ logger27.info(
4629
+ `Schedule ${scheduleTask._id} conditions not met, skipping`
4630
+ );
4631
+ continue;
4632
+ }
4633
+ logger27.info(
4634
+ `Schedule ${scheduleTask._id} conditions validated, creating area checklists`
4635
+ );
4636
+ if (!scheduleTask._id) {
4637
+ logger27.warn(`Schedule ${scheduleTask.title} has no _id, skipping`);
4638
+ continue;
4639
+ }
4640
+ if (!scheduleTask.site) {
4641
+ logger27.warn(`Schedule ${scheduleTask._id} has no site, skipping`);
4642
+ continue;
4643
+ }
4644
+ logger27.info(
4645
+ `Getting or creating parent checklist for schedule ${scheduleTask._id} in site ${scheduleTask.site}`
4646
+ );
4647
+ const parentChecklistIds = await createParentChecklist({
4648
+ site: scheduleTask.site.toString(),
4649
+ createdAt: /* @__PURE__ */ new Date()
4650
+ });
4651
+ const parentChecklistId = Array.isArray(parentChecklistIds) ? parentChecklistIds[0] : parentChecklistIds;
4652
+ logger27.info(
4653
+ `Using parent checklist ${parentChecklistId}, now creating area checklists`
4654
+ );
4655
+ const createdChecklistIds = await createAreaChecklist({
4656
+ schedule: parentChecklistId.toString(),
4657
+ site: scheduleTask.site.toString()
4658
+ });
4659
+ processedCount++;
4660
+ validatedCount++;
4661
+ validatedTasks.push(scheduleTask);
4662
+ logger27.info(
4663
+ `Successfully processed schedule ${scheduleTask._id}, created parent checklist ${parentChecklistId} and ${createdChecklistIds.length} area checklists`
4664
+ );
4665
+ } catch (error) {
4666
+ logger27.error(
4667
+ `Error processing schedule task ${scheduleTask._id}:`,
4668
+ error
4669
+ );
4670
+ continue;
4671
+ }
4672
+ }
4673
+ logger27.info(
4674
+ `Scheduled task processing completed. Processed: ${processedCount}, Validated: ${validatedCount} tasks`
4675
+ );
4676
+ return {
4677
+ processed: processedCount,
4678
+ validated: validatedCount,
4679
+ tasks: validatedTasks
4680
+ };
4681
+ } catch (error) {
4682
+ logger27.error("Error processing scheduled tasks:", error);
4683
+ throw error;
4684
+ }
4685
+ }
4686
+ return { checkScheduleConditions, processScheduledTasks };
4687
+ }
4688
+
4453
4689
  // src/controllers/hygiene-schedule-task.controller.ts
4454
- import { BadRequestError as BadRequestError28, logger as logger27 } from "@iservice365/node-server-utils";
4455
4690
  import Joi16 from "joi";
4691
+ import { BadRequestError as BadRequestError28, logger as logger28 } from "@iservice365/node-server-utils";
4456
4692
  function useScheduleTaskController() {
4457
4693
  const {
4458
4694
  createScheduleTask: _createScheduleTask,
4459
4695
  getScheduleTasks: _getScheduleTasks,
4696
+ getTasksForScheduleTask: _getTasksForScheduleTask,
4460
4697
  getScheduleTaskById: _getScheduleTaskById,
4461
4698
  updateScheduleTask: _updateScheduleTask
4462
4699
  } = useScheduleTaskRepository();
@@ -4464,7 +4701,7 @@ function useScheduleTaskController() {
4464
4701
  const payload = { ...req.body, ...req.params };
4465
4702
  const { error } = scheduleTaskSchema.validate(payload);
4466
4703
  if (error) {
4467
- logger27.log({ level: "error", message: error.message });
4704
+ logger28.log({ level: "error", message: error.message });
4468
4705
  next(new BadRequestError28(error.message));
4469
4706
  return;
4470
4707
  }
@@ -4473,7 +4710,7 @@ function useScheduleTaskController() {
4473
4710
  res.status(201).json({ message: "Schedule task created successfully.", id });
4474
4711
  return;
4475
4712
  } catch (error2) {
4476
- logger27.log({ level: "error", message: error2.message });
4713
+ logger28.log({ level: "error", message: error2.message });
4477
4714
  next(error2);
4478
4715
  return;
4479
4716
  }
@@ -4488,7 +4725,7 @@ function useScheduleTaskController() {
4488
4725
  });
4489
4726
  const { error } = validation.validate(query);
4490
4727
  if (error) {
4491
- logger27.log({ level: "error", message: error.message });
4728
+ logger28.log({ level: "error", message: error.message });
4492
4729
  next(new BadRequestError28(error.message));
4493
4730
  return;
4494
4731
  }
@@ -4506,7 +4743,40 @@ function useScheduleTaskController() {
4506
4743
  res.json(data);
4507
4744
  return;
4508
4745
  } catch (error2) {
4509
- logger27.log({ level: "error", message: error2.message });
4746
+ logger28.log({ level: "error", message: error2.message });
4747
+ next(error2);
4748
+ return;
4749
+ }
4750
+ }
4751
+ async function getTasksForScheduleTask(req, res, next) {
4752
+ const query = { ...req.query, ...req.params };
4753
+ const validation = Joi16.object({
4754
+ page: Joi16.number().min(1).optional().allow("", null),
4755
+ limit: Joi16.number().min(1).optional().allow("", null),
4756
+ search: Joi16.string().optional().allow("", null),
4757
+ site: Joi16.string().hex().required()
4758
+ });
4759
+ const { error } = validation.validate(query);
4760
+ if (error) {
4761
+ logger28.log({ level: "error", message: error.message });
4762
+ next(new BadRequestError28(error.message));
4763
+ return;
4764
+ }
4765
+ const page = parseInt(req.query.page) ?? 1;
4766
+ const limit = parseInt(req.query.limit) ?? 10;
4767
+ const search = req.query.search ?? "";
4768
+ const site = req.params.site ?? "";
4769
+ try {
4770
+ const data = await _getTasksForScheduleTask({
4771
+ page,
4772
+ limit,
4773
+ search,
4774
+ site
4775
+ });
4776
+ res.json(data);
4777
+ return;
4778
+ } catch (error2) {
4779
+ logger28.log({ level: "error", message: error2.message });
4510
4780
  next(error2);
4511
4781
  return;
4512
4782
  }
@@ -4516,7 +4786,7 @@ function useScheduleTaskController() {
4516
4786
  const _id = req.params.id;
4517
4787
  const { error } = validation.validate(_id);
4518
4788
  if (error) {
4519
- logger27.log({ level: "error", message: error.message });
4789
+ logger28.log({ level: "error", message: error.message });
4520
4790
  next(new BadRequestError28(error.message));
4521
4791
  return;
4522
4792
  }
@@ -4525,7 +4795,7 @@ function useScheduleTaskController() {
4525
4795
  res.json(data);
4526
4796
  return;
4527
4797
  } catch (error2) {
4528
- logger27.log({ level: "error", message: error2.message });
4798
+ logger28.log({ level: "error", message: error2.message });
4529
4799
  next(error2);
4530
4800
  return;
4531
4801
  }
@@ -4537,10 +4807,10 @@ function useScheduleTaskController() {
4537
4807
  title: Joi16.string().optional().allow("", null),
4538
4808
  frequency: Joi16.string().valid(...allowedFrequency).optional().allow("", null),
4539
4809
  time: Joi16.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).optional().allow("", null),
4540
- day: Joi16.string().valid(...allowedDays).optional().allow("", null),
4810
+ day: Joi16.array().items(Joi16.string().valid(...allowedDays)).optional().allow(null),
4541
4811
  weekOfMonth: Joi16.string().valid(...allowedWeekOfMonth).optional().allow("", null),
4542
- quarter: Joi16.string().valid(...allowedQuarter).optional().allow("", null),
4543
4812
  month: Joi16.string().valid(...allowedMonths).optional().allow("", null),
4813
+ date: Joi16.number().min(1).max(31).optional().allow(null),
4544
4814
  description: Joi16.string().optional().allow("", null),
4545
4815
  areas: Joi16.array().min(1).items(
4546
4816
  Joi16.object({
@@ -4551,7 +4821,7 @@ function useScheduleTaskController() {
4551
4821
  });
4552
4822
  const { error } = validation.validate(payload);
4553
4823
  if (error) {
4554
- logger27.log({ level: "error", message: error.message });
4824
+ logger28.log({ level: "error", message: error.message });
4555
4825
  next(new BadRequestError28(error.message));
4556
4826
  return;
4557
4827
  }
@@ -4561,7 +4831,7 @@ function useScheduleTaskController() {
4561
4831
  res.json({ message: "Schedule task updated successfully." });
4562
4832
  return;
4563
4833
  } catch (error2) {
4564
- logger27.log({ level: "error", message: error2.message });
4834
+ logger28.log({ level: "error", message: error2.message });
4565
4835
  next(error2);
4566
4836
  return;
4567
4837
  }
@@ -4569,6 +4839,7 @@ function useScheduleTaskController() {
4569
4839
  return {
4570
4840
  createScheduleTask,
4571
4841
  getScheduleTasks,
4842
+ getTasksForScheduleTask,
4572
4843
  getScheduleTaskById,
4573
4844
  updateScheduleTask
4574
4845
  };
@@ -4586,7 +4857,6 @@ export {
4586
4857
  allowedDays,
4587
4858
  allowedFrequency,
4588
4859
  allowedMonths,
4589
- allowedQuarter,
4590
4860
  allowedRequestItemStatus,
4591
4861
  allowedStatus,
4592
4862
  allowedTypes,
@@ -4612,6 +4882,7 @@ export {
4612
4882
  useRequestItemService,
4613
4883
  useScheduleTaskController,
4614
4884
  useScheduleTaskRepository,
4885
+ useScheduleTaskService,
4615
4886
  useStockController,
4616
4887
  useStockRepository,
4617
4888
  useStockService,