@7365admin1/module-hygiene 4.11.0 → 4.13.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 +12 -0
- package/dist/index.d.ts +52 -14
- package/dist/index.js +520 -205
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +519 -205
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
// src/models/hygiene-base.model.ts
|
|
2
|
+
var ServiceType = /* @__PURE__ */ ((ServiceType2) => {
|
|
3
|
+
ServiceType2["REAL_ESTATE_DEVELOPER"] = "real_estate_developer";
|
|
4
|
+
ServiceType2["PROPERTY_MANAGEMENT_AGENCY"] = "property_management_agency";
|
|
5
|
+
ServiceType2["SECURITY_AGENCY"] = "security_agency";
|
|
6
|
+
ServiceType2["CLEANING_SERVICES"] = "cleaning_services";
|
|
7
|
+
ServiceType2["MECHANICAL_ELECTRICAL_SERVICES"] = "mechanical_electrical_services";
|
|
8
|
+
ServiceType2["LANDSCAPING_SERVICES"] = "landscaping_services";
|
|
9
|
+
ServiceType2["PEST_CONTROL_SERVICES"] = "pest_control_services";
|
|
10
|
+
ServiceType2["POOL_MAINTENANCE_SERVICES"] = "pool_maintenance_services";
|
|
11
|
+
return ServiceType2;
|
|
12
|
+
})(ServiceType || {});
|
|
2
13
|
var allowedTypes = ["common", "toilet"];
|
|
3
14
|
var allowedStatus = [
|
|
4
15
|
"open",
|
|
@@ -547,6 +558,7 @@ import { ObjectId as ObjectId2 } from "mongodb";
|
|
|
547
558
|
import { BadRequestError as BadRequestError3, logger as logger3 } from "@7365admin1/node-server-utils";
|
|
548
559
|
var areaSchema = Joi2.object({
|
|
549
560
|
site: Joi2.string().hex().required(),
|
|
561
|
+
serviceType: Joi2.string().valid(...Object.values(ServiceType)).required(),
|
|
550
562
|
name: Joi2.string().required(),
|
|
551
563
|
type: Joi2.string().valid(...allowedTypes).required(),
|
|
552
564
|
set: Joi2.number().min(0).optional(),
|
|
@@ -586,6 +598,7 @@ function MArea(value) {
|
|
|
586
598
|
}
|
|
587
599
|
return {
|
|
588
600
|
site: value.site,
|
|
601
|
+
serviceType: value.serviceType,
|
|
589
602
|
name: value.name,
|
|
590
603
|
type: value.type,
|
|
591
604
|
set: value.set ?? 0,
|
|
@@ -630,6 +643,7 @@ function useAreaRepo() {
|
|
|
630
643
|
try {
|
|
631
644
|
await collection.createIndexes([
|
|
632
645
|
{ key: { site: 1 } },
|
|
646
|
+
{ key: { serviceType: 1 } },
|
|
633
647
|
{ key: { type: 1 } },
|
|
634
648
|
{ key: { status: 1 } },
|
|
635
649
|
{ key: { "units.unit": 1 } }
|
|
@@ -650,7 +664,7 @@ function useAreaRepo() {
|
|
|
650
664
|
async function createUniqueIndex() {
|
|
651
665
|
try {
|
|
652
666
|
await collection.createIndex(
|
|
653
|
-
{ site: 1, name: 1, type: 1, deletedAt: 1 },
|
|
667
|
+
{ site: 1, serviceType: 1, name: 1, type: 1, deletedAt: 1 },
|
|
654
668
|
{ unique: true }
|
|
655
669
|
);
|
|
656
670
|
} catch (error) {
|
|
@@ -687,15 +701,18 @@ function useAreaRepo() {
|
|
|
687
701
|
limit = 10,
|
|
688
702
|
search = "",
|
|
689
703
|
type = "all",
|
|
690
|
-
site
|
|
704
|
+
site,
|
|
705
|
+
serviceType
|
|
691
706
|
}) {
|
|
692
707
|
page = page > 0 ? page - 1 : 0;
|
|
693
708
|
const query = {
|
|
694
|
-
status: { $ne: "deleted" }
|
|
709
|
+
status: { $ne: "deleted" },
|
|
710
|
+
serviceType
|
|
695
711
|
};
|
|
696
712
|
const cacheOptions = {
|
|
697
713
|
page,
|
|
698
|
-
limit
|
|
714
|
+
limit,
|
|
715
|
+
serviceType
|
|
699
716
|
};
|
|
700
717
|
try {
|
|
701
718
|
site = new ObjectId3(site);
|
|
@@ -744,9 +761,15 @@ function useAreaRepo() {
|
|
|
744
761
|
throw error;
|
|
745
762
|
}
|
|
746
763
|
}
|
|
747
|
-
async function getAreasForChecklist(site) {
|
|
748
|
-
const query = {
|
|
764
|
+
async function getAreasForChecklist(site, serviceType) {
|
|
765
|
+
const query = {
|
|
766
|
+
status: { $ne: "deleted" }
|
|
767
|
+
};
|
|
749
768
|
const cacheOptions = {};
|
|
769
|
+
if (serviceType) {
|
|
770
|
+
query.serviceType = serviceType;
|
|
771
|
+
cacheOptions.serviceType = serviceType;
|
|
772
|
+
}
|
|
750
773
|
try {
|
|
751
774
|
site = new ObjectId3(site);
|
|
752
775
|
query.site = site;
|
|
@@ -826,28 +849,6 @@ function useAreaRepo() {
|
|
|
826
849
|
throw error;
|
|
827
850
|
}
|
|
828
851
|
}
|
|
829
|
-
async function getAreaByMultipleId(_id) {
|
|
830
|
-
for (let i = 0; i < _id.length; i++) {
|
|
831
|
-
try {
|
|
832
|
-
_id[i] = new ObjectId3(_id[i]);
|
|
833
|
-
} catch (error) {
|
|
834
|
-
throw new BadRequestError4("Invalid area ID format.");
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
const query = {
|
|
838
|
-
_id: { $in: _id },
|
|
839
|
-
status: { $ne: "deleted" }
|
|
840
|
-
};
|
|
841
|
-
try {
|
|
842
|
-
const data = await collection.aggregate([{ $match: query }]).toArray();
|
|
843
|
-
if (!data || data.length === 0) {
|
|
844
|
-
throw new NotFoundError("Area not found.");
|
|
845
|
-
}
|
|
846
|
-
return data;
|
|
847
|
-
} catch (error) {
|
|
848
|
-
throw error;
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
852
|
async function verifyAreaByUnitId(unitId) {
|
|
852
853
|
try {
|
|
853
854
|
unitId = new ObjectId3(unitId);
|
|
@@ -1009,7 +1010,6 @@ function useAreaRepo() {
|
|
|
1009
1010
|
getAreas,
|
|
1010
1011
|
getAreasForChecklist,
|
|
1011
1012
|
getAreaById,
|
|
1012
|
-
getAreaByMultipleId,
|
|
1013
1013
|
verifyAreaByUnitId,
|
|
1014
1014
|
updateArea,
|
|
1015
1015
|
updateAreaChecklist,
|
|
@@ -1088,6 +1088,7 @@ import { ObjectId as ObjectId4 } from "mongodb";
|
|
|
1088
1088
|
import { BadRequestError as BadRequestError5, logger as logger6 } from "@7365admin1/node-server-utils";
|
|
1089
1089
|
var unitSchema = Joi3.object({
|
|
1090
1090
|
site: Joi3.string().hex().required(),
|
|
1091
|
+
serviceType: Joi3.string().valid(...Object.values(ServiceType)).required(),
|
|
1091
1092
|
name: Joi3.string().required()
|
|
1092
1093
|
});
|
|
1093
1094
|
function MUnit(value) {
|
|
@@ -1105,6 +1106,7 @@ function MUnit(value) {
|
|
|
1105
1106
|
}
|
|
1106
1107
|
return {
|
|
1107
1108
|
site: value.site,
|
|
1109
|
+
serviceType: value.serviceType,
|
|
1108
1110
|
name: value.name,
|
|
1109
1111
|
status: "active",
|
|
1110
1112
|
createdAt: /* @__PURE__ */ new Date(),
|
|
@@ -1126,6 +1128,7 @@ function useUnitRepository() {
|
|
|
1126
1128
|
try {
|
|
1127
1129
|
await collection.createIndexes([
|
|
1128
1130
|
{ key: { site: 1 } },
|
|
1131
|
+
{ key: { serviceType: 1 } },
|
|
1129
1132
|
{ key: { status: 1 } }
|
|
1130
1133
|
]);
|
|
1131
1134
|
} catch (error) {
|
|
@@ -1144,7 +1147,7 @@ function useUnitRepository() {
|
|
|
1144
1147
|
async function createUniqueIndex() {
|
|
1145
1148
|
try {
|
|
1146
1149
|
await collection.createIndex(
|
|
1147
|
-
{ site: 1, name: 1, deletedAt: 1 },
|
|
1150
|
+
{ site: 1, serviceType: 1, name: 1, deletedAt: 1 },
|
|
1148
1151
|
{ unique: true }
|
|
1149
1152
|
);
|
|
1150
1153
|
} catch (error) {
|
|
@@ -1178,7 +1181,8 @@ function useUnitRepository() {
|
|
|
1178
1181
|
page = 1,
|
|
1179
1182
|
limit = 10,
|
|
1180
1183
|
search = "",
|
|
1181
|
-
site
|
|
1184
|
+
site,
|
|
1185
|
+
serviceType
|
|
1182
1186
|
}) {
|
|
1183
1187
|
page = page > 0 ? page - 1 : 0;
|
|
1184
1188
|
const query = {
|
|
@@ -1195,6 +1199,10 @@ function useUnitRepository() {
|
|
|
1195
1199
|
} catch (error) {
|
|
1196
1200
|
throw new BadRequestError6("Invalid site ID format.");
|
|
1197
1201
|
}
|
|
1202
|
+
if (serviceType) {
|
|
1203
|
+
query.serviceType = serviceType;
|
|
1204
|
+
cacheOptions.serviceType = serviceType;
|
|
1205
|
+
}
|
|
1198
1206
|
if (search) {
|
|
1199
1207
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
1200
1208
|
cacheOptions.search = search;
|
|
@@ -1253,7 +1261,7 @@ function useUnitRepository() {
|
|
|
1253
1261
|
} catch (error) {
|
|
1254
1262
|
const isDuplicated = error.message.includes("duplicate");
|
|
1255
1263
|
if (isDuplicated) {
|
|
1256
|
-
throw new BadRequestError6("
|
|
1264
|
+
throw new BadRequestError6("Unit already exists.");
|
|
1257
1265
|
}
|
|
1258
1266
|
throw error;
|
|
1259
1267
|
}
|
|
@@ -1309,7 +1317,8 @@ function useAreaService() {
|
|
|
1309
1317
|
const { getUnits: _getUnits } = useUnitRepository();
|
|
1310
1318
|
async function importArea({
|
|
1311
1319
|
dataJson,
|
|
1312
|
-
site
|
|
1320
|
+
site,
|
|
1321
|
+
serviceType
|
|
1313
1322
|
}) {
|
|
1314
1323
|
let dataArray;
|
|
1315
1324
|
try {
|
|
@@ -1330,7 +1339,8 @@ function useAreaService() {
|
|
|
1330
1339
|
page: 1,
|
|
1331
1340
|
limit: 999999,
|
|
1332
1341
|
search: "",
|
|
1333
|
-
site
|
|
1342
|
+
site,
|
|
1343
|
+
serviceType
|
|
1334
1344
|
});
|
|
1335
1345
|
if (unitsData && unitsData.items) {
|
|
1336
1346
|
availableUnits = unitsData.items;
|
|
@@ -1377,7 +1387,8 @@ function useAreaService() {
|
|
|
1377
1387
|
const areaData = {
|
|
1378
1388
|
type: areaType,
|
|
1379
1389
|
name: areaName,
|
|
1380
|
-
site
|
|
1390
|
+
site,
|
|
1391
|
+
serviceType
|
|
1381
1392
|
};
|
|
1382
1393
|
if (row.SET !== void 0 && row.SET !== null && row.SET !== "") {
|
|
1383
1394
|
const setNumber = parseInt(String(row.SET).trim());
|
|
@@ -1471,9 +1482,12 @@ function useAreaService() {
|
|
|
1471
1482
|
}
|
|
1472
1483
|
}
|
|
1473
1484
|
}
|
|
1474
|
-
async function exportAreas(
|
|
1485
|
+
async function exportAreas({
|
|
1486
|
+
site,
|
|
1487
|
+
serviceType
|
|
1488
|
+
}) {
|
|
1475
1489
|
try {
|
|
1476
|
-
const areas = await getAreasForChecklist(site);
|
|
1490
|
+
const areas = await getAreasForChecklist(site, serviceType);
|
|
1477
1491
|
if (!areas || !Array.isArray(areas) || areas.length === 0) {
|
|
1478
1492
|
throw new BadRequestError7(
|
|
1479
1493
|
"There are no areas to export yet. Please add some areas first, then try again."
|
|
@@ -1560,7 +1574,8 @@ function useAreaController() {
|
|
|
1560
1574
|
limit: Joi4.number().min(1).optional().allow("", null),
|
|
1561
1575
|
search: Joi4.string().optional().allow("", null),
|
|
1562
1576
|
type: Joi4.string().valid("all", ...allowedTypes).optional().allow("", null),
|
|
1563
|
-
site: Joi4.string().hex().required()
|
|
1577
|
+
site: Joi4.string().hex().required(),
|
|
1578
|
+
serviceType: Joi4.string().valid(...Object.values(ServiceType)).required()
|
|
1564
1579
|
});
|
|
1565
1580
|
const { error } = validation.validate(query);
|
|
1566
1581
|
if (error) {
|
|
@@ -1573,13 +1588,15 @@ function useAreaController() {
|
|
|
1573
1588
|
const search = req.query.search ?? "";
|
|
1574
1589
|
const type = req.query.type ?? "all";
|
|
1575
1590
|
const site = req.params.site ?? "";
|
|
1591
|
+
const serviceType = req.query.serviceType ?? "";
|
|
1576
1592
|
try {
|
|
1577
1593
|
const data = await _getAreas({
|
|
1578
1594
|
page,
|
|
1579
1595
|
limit,
|
|
1580
1596
|
search,
|
|
1581
1597
|
type,
|
|
1582
|
-
site
|
|
1598
|
+
site,
|
|
1599
|
+
serviceType
|
|
1583
1600
|
});
|
|
1584
1601
|
res.json(data);
|
|
1585
1602
|
return;
|
|
@@ -1664,9 +1681,12 @@ function useAreaController() {
|
|
|
1664
1681
|
next(new BadRequestError8("File is required!"));
|
|
1665
1682
|
return;
|
|
1666
1683
|
}
|
|
1667
|
-
const
|
|
1668
|
-
const
|
|
1669
|
-
|
|
1684
|
+
const query = { ...req.query, ...req.params };
|
|
1685
|
+
const validation = Joi4.object({
|
|
1686
|
+
site: Joi4.string().hex().required(),
|
|
1687
|
+
serviceType: Joi4.string().valid(...Object.values(ServiceType)).required()
|
|
1688
|
+
});
|
|
1689
|
+
const { error, value } = validation.validate(query);
|
|
1670
1690
|
if (error) {
|
|
1671
1691
|
logger9.log({ level: "error", message: error.message });
|
|
1672
1692
|
next(new BadRequestError8(error.message));
|
|
@@ -1675,7 +1695,7 @@ function useAreaController() {
|
|
|
1675
1695
|
try {
|
|
1676
1696
|
const xlsData = await convertBufferFile(req.file.buffer);
|
|
1677
1697
|
const dataJson = JSON.stringify(xlsData);
|
|
1678
|
-
const result = await _importArea({ dataJson,
|
|
1698
|
+
const result = await _importArea({ dataJson, ...value });
|
|
1679
1699
|
return res.status(201).json(result);
|
|
1680
1700
|
} catch (error2) {
|
|
1681
1701
|
logger9.log({ level: "error", message: error2.message });
|
|
@@ -1684,9 +1704,12 @@ function useAreaController() {
|
|
|
1684
1704
|
}
|
|
1685
1705
|
}
|
|
1686
1706
|
async function exportAreas(req, res, next) {
|
|
1687
|
-
const
|
|
1688
|
-
const validation = Joi4.
|
|
1689
|
-
|
|
1707
|
+
const query = { ...req.query, ...req.params };
|
|
1708
|
+
const validation = Joi4.object({
|
|
1709
|
+
site: Joi4.string().hex().required(),
|
|
1710
|
+
serviceType: Joi4.string().valid(...Object.values(ServiceType)).required()
|
|
1711
|
+
});
|
|
1712
|
+
const { error, value } = validation.validate(query);
|
|
1690
1713
|
if (error) {
|
|
1691
1714
|
logger9.log({ level: "error", message: error.message });
|
|
1692
1715
|
next(new BadRequestError8(error.message));
|
|
@@ -1782,7 +1805,8 @@ function useUnitService() {
|
|
|
1782
1805
|
} = useUnitRepository();
|
|
1783
1806
|
async function importUnit({
|
|
1784
1807
|
dataJson,
|
|
1785
|
-
site
|
|
1808
|
+
site,
|
|
1809
|
+
serviceType
|
|
1786
1810
|
}) {
|
|
1787
1811
|
let dataArray;
|
|
1788
1812
|
try {
|
|
@@ -1823,7 +1847,8 @@ function useUnitService() {
|
|
|
1823
1847
|
try {
|
|
1824
1848
|
const insertedId = await _createUnit({
|
|
1825
1849
|
name: unitName,
|
|
1826
|
-
site
|
|
1850
|
+
site,
|
|
1851
|
+
serviceType
|
|
1827
1852
|
});
|
|
1828
1853
|
insertedUnitIds.push(insertedId);
|
|
1829
1854
|
logger11.info(`Successfully created unit: ${unitName}`);
|
|
@@ -1928,7 +1953,10 @@ function useUnitService() {
|
|
|
1928
1953
|
session?.endSession();
|
|
1929
1954
|
}
|
|
1930
1955
|
}
|
|
1931
|
-
async function exportUnits(
|
|
1956
|
+
async function exportUnits({
|
|
1957
|
+
site,
|
|
1958
|
+
serviceType
|
|
1959
|
+
}) {
|
|
1932
1960
|
const { generateUnitExcel: _generateUnitExcel } = useUnitExportService();
|
|
1933
1961
|
const { getUnits: _getUnits } = useUnitRepository();
|
|
1934
1962
|
try {
|
|
@@ -1936,7 +1964,8 @@ function useUnitService() {
|
|
|
1936
1964
|
page: 1,
|
|
1937
1965
|
limit: 999999,
|
|
1938
1966
|
search: "",
|
|
1939
|
-
site
|
|
1967
|
+
site,
|
|
1968
|
+
serviceType
|
|
1940
1969
|
});
|
|
1941
1970
|
if (!data || !data.items || data.items.length === 0) {
|
|
1942
1971
|
throw new BadRequestError9(
|
|
@@ -1993,7 +2022,8 @@ function useUnitController() {
|
|
|
1993
2022
|
page: Joi5.number().min(1).optional().allow("", null),
|
|
1994
2023
|
limit: Joi5.number().min(1).optional().allow("", null),
|
|
1995
2024
|
search: Joi5.string().optional().allow("", null),
|
|
1996
|
-
site: Joi5.string().hex().required()
|
|
2025
|
+
site: Joi5.string().hex().required(),
|
|
2026
|
+
serviceType: Joi5.string().valid(...Object.values(ServiceType)).required()
|
|
1997
2027
|
});
|
|
1998
2028
|
const { error } = validation.validate(query);
|
|
1999
2029
|
if (error) {
|
|
@@ -2005,12 +2035,14 @@ function useUnitController() {
|
|
|
2005
2035
|
const limit = parseInt(req.query.limit) ?? 10;
|
|
2006
2036
|
const search = req.query.search ?? "";
|
|
2007
2037
|
const site = req.params.site ?? "";
|
|
2038
|
+
const serviceType = req.query.serviceType ?? "";
|
|
2008
2039
|
try {
|
|
2009
2040
|
const data = await _getUnits({
|
|
2010
2041
|
page,
|
|
2011
2042
|
limit,
|
|
2012
2043
|
search,
|
|
2013
|
-
site
|
|
2044
|
+
site,
|
|
2045
|
+
serviceType
|
|
2014
2046
|
});
|
|
2015
2047
|
res.json(data);
|
|
2016
2048
|
return;
|
|
@@ -2069,9 +2101,12 @@ function useUnitController() {
|
|
|
2069
2101
|
next(new BadRequestError10("File is required!"));
|
|
2070
2102
|
return;
|
|
2071
2103
|
}
|
|
2072
|
-
const
|
|
2073
|
-
const validation = Joi5.
|
|
2074
|
-
|
|
2104
|
+
const query = { ...req.query, ...req.params };
|
|
2105
|
+
const validation = Joi5.object({
|
|
2106
|
+
site: Joi5.string().hex().required(),
|
|
2107
|
+
serviceType: Joi5.string().valid(...Object.values(ServiceType)).required()
|
|
2108
|
+
});
|
|
2109
|
+
const { error, value } = validation.validate(query);
|
|
2075
2110
|
if (error) {
|
|
2076
2111
|
logger12.log({ level: "error", message: error.message });
|
|
2077
2112
|
next(new BadRequestError10(error.message));
|
|
@@ -2080,7 +2115,7 @@ function useUnitController() {
|
|
|
2080
2115
|
try {
|
|
2081
2116
|
const xlsData = await convertBufferFile(req.file.buffer);
|
|
2082
2117
|
const dataJson = JSON.stringify(xlsData);
|
|
2083
|
-
const result = await _importUnit({ dataJson,
|
|
2118
|
+
const result = await _importUnit({ dataJson, ...value });
|
|
2084
2119
|
return res.status(201).json(result);
|
|
2085
2120
|
} catch (error2) {
|
|
2086
2121
|
logger12.log({ level: "error", message: error2.message });
|
|
@@ -2089,9 +2124,12 @@ function useUnitController() {
|
|
|
2089
2124
|
}
|
|
2090
2125
|
}
|
|
2091
2126
|
async function exportUnits(req, res, next) {
|
|
2092
|
-
const
|
|
2093
|
-
const validation = Joi5.
|
|
2094
|
-
|
|
2127
|
+
const query = { ...req.query, ...req.params };
|
|
2128
|
+
const validation = Joi5.object({
|
|
2129
|
+
site: Joi5.string().hex().required(),
|
|
2130
|
+
serviceType: Joi5.string().valid(...Object.values(ServiceType)).required()
|
|
2131
|
+
});
|
|
2132
|
+
const { error, value } = validation.validate(query);
|
|
2095
2133
|
if (error) {
|
|
2096
2134
|
logger12.log({ level: "error", message: error.message });
|
|
2097
2135
|
next(new BadRequestError10(error.message));
|
|
@@ -2137,7 +2175,8 @@ import { ObjectId as ObjectId6 } from "mongodb";
|
|
|
2137
2175
|
import { BadRequestError as BadRequestError11, logger as logger13 } from "@7365admin1/node-server-utils";
|
|
2138
2176
|
var parentChecklistSchema = Joi6.object({
|
|
2139
2177
|
createdAt: Joi6.alternatives().try(Joi6.date(), Joi6.string()).optional().allow("", null),
|
|
2140
|
-
site: Joi6.string().hex().required()
|
|
2178
|
+
site: Joi6.string().hex().required(),
|
|
2179
|
+
serviceType: Joi6.string().valid(...Object.values(ServiceType)).required()
|
|
2141
2180
|
});
|
|
2142
2181
|
function MParentChecklist(value) {
|
|
2143
2182
|
const { error } = parentChecklistSchema.validate(value);
|
|
@@ -2154,6 +2193,7 @@ function MParentChecklist(value) {
|
|
|
2154
2193
|
}
|
|
2155
2194
|
return {
|
|
2156
2195
|
site: value.site,
|
|
2196
|
+
serviceType: value.serviceType,
|
|
2157
2197
|
status: "open",
|
|
2158
2198
|
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
2159
2199
|
updatedAt: value.updatedAt ?? ""
|
|
@@ -2236,12 +2276,16 @@ function useParentChecklistRepo() {
|
|
|
2236
2276
|
);
|
|
2237
2277
|
return existingChecklist._id;
|
|
2238
2278
|
}
|
|
2279
|
+
const allServiceTypes = Object.values(ServiceType);
|
|
2239
2280
|
if (value.site) {
|
|
2240
|
-
const
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2281
|
+
const checklistDocs2 = allServiceTypes.map(
|
|
2282
|
+
(serviceType) => MParentChecklist({
|
|
2283
|
+
site: value.site,
|
|
2284
|
+
createdAt: currentDate,
|
|
2285
|
+
serviceType
|
|
2286
|
+
})
|
|
2287
|
+
);
|
|
2288
|
+
const result2 = await collection.insertMany(checklistDocs2, { session });
|
|
2245
2289
|
delNamespace().then(() => {
|
|
2246
2290
|
logger14.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2247
2291
|
}).catch((err) => {
|
|
@@ -2252,9 +2296,9 @@ function useParentChecklistRepo() {
|
|
|
2252
2296
|
});
|
|
2253
2297
|
const dateStr2 = currentDate.toISOString().split("T")[0];
|
|
2254
2298
|
logger14.info(
|
|
2255
|
-
`Created parent
|
|
2299
|
+
`Created ${checklistDocs2.length} parent checklists for site ${value.site} for today: ${dateStr2}`
|
|
2256
2300
|
);
|
|
2257
|
-
return result2.
|
|
2301
|
+
return Object.values(result2.insertedIds);
|
|
2258
2302
|
}
|
|
2259
2303
|
const siteIds = await getHygieneSiteIds();
|
|
2260
2304
|
if (!Array.isArray(siteIds)) {
|
|
@@ -2267,12 +2311,15 @@ function useParentChecklistRepo() {
|
|
|
2267
2311
|
}
|
|
2268
2312
|
const checklistDocs = [];
|
|
2269
2313
|
for (const site of siteIds) {
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2314
|
+
for (const serviceType of allServiceTypes) {
|
|
2315
|
+
checklistDocs.push(
|
|
2316
|
+
MParentChecklist({
|
|
2317
|
+
site,
|
|
2318
|
+
createdAt: currentDate,
|
|
2319
|
+
serviceType
|
|
2320
|
+
})
|
|
2321
|
+
);
|
|
2322
|
+
}
|
|
2276
2323
|
}
|
|
2277
2324
|
const result = await collection.insertMany(checklistDocs, { session });
|
|
2278
2325
|
delNamespace().then(() => {
|
|
@@ -2300,13 +2347,15 @@ function useParentChecklistRepo() {
|
|
|
2300
2347
|
site,
|
|
2301
2348
|
startDate = "",
|
|
2302
2349
|
endDate = "",
|
|
2303
|
-
status = "all"
|
|
2350
|
+
status = "all",
|
|
2351
|
+
serviceType
|
|
2304
2352
|
}) {
|
|
2305
2353
|
page = page > 0 ? page - 1 : 0;
|
|
2306
|
-
const query = {};
|
|
2354
|
+
const query = { serviceType };
|
|
2307
2355
|
const cacheOptions = {
|
|
2308
2356
|
page,
|
|
2309
|
-
limit
|
|
2357
|
+
limit,
|
|
2358
|
+
serviceType
|
|
2310
2359
|
};
|
|
2311
2360
|
try {
|
|
2312
2361
|
site = new ObjectId7(site);
|
|
@@ -2486,12 +2535,30 @@ function useParentChecklistRepo() {
|
|
|
2486
2535
|
throw error;
|
|
2487
2536
|
}
|
|
2488
2537
|
}
|
|
2538
|
+
async function getTodayParentChecklists() {
|
|
2539
|
+
const now = /* @__PURE__ */ new Date();
|
|
2540
|
+
const start = new Date(now);
|
|
2541
|
+
start.setUTCHours(0, 0, 0, 0);
|
|
2542
|
+
const end = new Date(now);
|
|
2543
|
+
end.setUTCHours(23, 59, 59, 999);
|
|
2544
|
+
try {
|
|
2545
|
+
const items = await collection.find(
|
|
2546
|
+
{ createdAt: { $gte: start, $lte: end } },
|
|
2547
|
+
{ projection: { _id: 1, site: 1 } }
|
|
2548
|
+
).toArray();
|
|
2549
|
+
return items;
|
|
2550
|
+
} catch (error) {
|
|
2551
|
+
logger14.error("Failed to get today's parent checklists", error);
|
|
2552
|
+
throw error;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2489
2555
|
return {
|
|
2490
2556
|
createIndex,
|
|
2491
2557
|
createParentChecklist,
|
|
2492
2558
|
getAllParentChecklist,
|
|
2493
2559
|
updateParentChecklistStatuses,
|
|
2494
|
-
closeExpiredParentChecklists
|
|
2560
|
+
closeExpiredParentChecklists,
|
|
2561
|
+
getTodayParentChecklists
|
|
2495
2562
|
};
|
|
2496
2563
|
}
|
|
2497
2564
|
|
|
@@ -2528,6 +2595,7 @@ function useParentChecklistController() {
|
|
|
2528
2595
|
limit: Joi7.number().min(1).optional().allow("", null),
|
|
2529
2596
|
search: Joi7.string().optional().allow("", null),
|
|
2530
2597
|
site: Joi7.string().hex().required(),
|
|
2598
|
+
serviceType: Joi7.string().valid(...Object.values(ServiceType)).required(),
|
|
2531
2599
|
startDate: Joi7.alternatives().try(Joi7.date(), Joi7.string()).optional().allow("", null),
|
|
2532
2600
|
endDate: Joi7.alternatives().try(Joi7.date(), Joi7.string()).optional().allow("", null),
|
|
2533
2601
|
status: Joi7.string().valid(...allowedStatus, "all").optional().allow("", null)
|
|
@@ -2542,6 +2610,7 @@ function useParentChecklistController() {
|
|
|
2542
2610
|
const limit = parseInt(req.query.limit) ?? 10;
|
|
2543
2611
|
const search = req.query.search ?? "";
|
|
2544
2612
|
const site = req.params.site ?? "";
|
|
2613
|
+
const serviceType = req.query.serviceType ?? "";
|
|
2545
2614
|
const startDate = req.query.startDate ?? "";
|
|
2546
2615
|
const endDate = req.query.endDate ?? "";
|
|
2547
2616
|
const status = req.query.status ?? "all";
|
|
@@ -2551,6 +2620,7 @@ function useParentChecklistController() {
|
|
|
2551
2620
|
limit,
|
|
2552
2621
|
search,
|
|
2553
2622
|
site,
|
|
2623
|
+
serviceType,
|
|
2554
2624
|
startDate,
|
|
2555
2625
|
endDate,
|
|
2556
2626
|
status
|
|
@@ -2587,7 +2657,9 @@ var areaChecklistSchema = Joi8.object({
|
|
|
2587
2657
|
unit: Joi8.string().hex().required(),
|
|
2588
2658
|
name: Joi8.string().required()
|
|
2589
2659
|
}).required()
|
|
2590
|
-
).min(1).required()
|
|
2660
|
+
).min(1).required(),
|
|
2661
|
+
isScheduleTask: Joi8.boolean().optional().default(false),
|
|
2662
|
+
scheduleTaskId: Joi8.string().hex().optional().allow(null)
|
|
2591
2663
|
}).required()
|
|
2592
2664
|
).optional().default([]),
|
|
2593
2665
|
createdBy: Joi8.string().hex().required()
|
|
@@ -2616,6 +2688,8 @@ function MAreaChecklist(value) {
|
|
|
2616
2688
|
value.checklist = value.checklist.map((checklistItem) => {
|
|
2617
2689
|
return {
|
|
2618
2690
|
set: checklistItem.set,
|
|
2691
|
+
isScheduleTask: checklistItem.isScheduleTask ?? false,
|
|
2692
|
+
scheduleTaskId: checklistItem.scheduleTaskId ?? void 0,
|
|
2619
2693
|
units: checklistItem.units.map((unit) => ({
|
|
2620
2694
|
unit: new ObjectId8(unit.unit),
|
|
2621
2695
|
name: unit.name,
|
|
@@ -2651,6 +2725,7 @@ function MAreaChecklist(value) {
|
|
|
2651
2725
|
}
|
|
2652
2726
|
|
|
2653
2727
|
// src/services/hygiene-area-checklist.service.ts
|
|
2728
|
+
import { ObjectId as ObjectId10 } from "mongodb";
|
|
2654
2729
|
import {
|
|
2655
2730
|
logger as logger18,
|
|
2656
2731
|
UnauthorizedError,
|
|
@@ -2706,26 +2781,26 @@ function useAreaChecklistRepo() {
|
|
|
2706
2781
|
);
|
|
2707
2782
|
}
|
|
2708
2783
|
}
|
|
2784
|
+
async function createUniqueIndex() {
|
|
2785
|
+
try {
|
|
2786
|
+
await collection.createIndex({ schedule: 1, area: 1 }, { unique: true });
|
|
2787
|
+
} catch (error) {
|
|
2788
|
+
throw new InternalServerError5(
|
|
2789
|
+
"Failed to create unique index on hygiene checklist area."
|
|
2790
|
+
);
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2709
2793
|
async function createAreaChecklist(value, session) {
|
|
2710
2794
|
try {
|
|
2711
2795
|
const parentChecklistId = new ObjectId9(value.schedule);
|
|
2712
|
-
const
|
|
2713
|
-
const
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
const existingChecklist = await collection.findOne({
|
|
2718
|
-
type: value.type,
|
|
2719
|
-
schedule: parentChecklistId,
|
|
2720
|
-
name: value.name,
|
|
2721
|
-
createdAt: {
|
|
2722
|
-
$gte: startOfDay,
|
|
2723
|
-
$lte: endOfDay
|
|
2724
|
-
}
|
|
2725
|
-
});
|
|
2796
|
+
const areaId = new ObjectId9(value.area);
|
|
2797
|
+
const existingChecklist = await collection.findOne(
|
|
2798
|
+
{ schedule: parentChecklistId, area: areaId },
|
|
2799
|
+
{ session }
|
|
2800
|
+
);
|
|
2726
2801
|
if (existingChecklist) {
|
|
2727
2802
|
logger17.info(
|
|
2728
|
-
`Area checklist already exists for area ${value.name}
|
|
2803
|
+
`Area checklist already exists for area ${value.name} (schedule: ${parentChecklistId}, area: ${areaId})`
|
|
2729
2804
|
);
|
|
2730
2805
|
return existingChecklist._id;
|
|
2731
2806
|
}
|
|
@@ -2741,6 +2816,14 @@ function useAreaChecklistRepo() {
|
|
|
2741
2816
|
});
|
|
2742
2817
|
return result.insertedId;
|
|
2743
2818
|
} catch (error) {
|
|
2819
|
+
if (error?.code === 11e3) {
|
|
2820
|
+
logger17.info(`Duplicate area checklist skipped for area ${value.name}`);
|
|
2821
|
+
const existing = await collection.findOne({
|
|
2822
|
+
schedule: new ObjectId9(value.schedule),
|
|
2823
|
+
area: new ObjectId9(value.area)
|
|
2824
|
+
});
|
|
2825
|
+
return existing._id;
|
|
2826
|
+
}
|
|
2744
2827
|
throw error;
|
|
2745
2828
|
}
|
|
2746
2829
|
}
|
|
@@ -3078,6 +3161,9 @@ function useAreaChecklistRepo() {
|
|
|
3078
3161
|
$project: {
|
|
3079
3162
|
_id: 0,
|
|
3080
3163
|
set: "$checklist.set",
|
|
3164
|
+
isScheduleTask: {
|
|
3165
|
+
$ifNull: ["$checklist.isScheduleTask", false]
|
|
3166
|
+
},
|
|
3081
3167
|
unit: "$checklist.units.unit",
|
|
3082
3168
|
name: "$checklist.units.name",
|
|
3083
3169
|
remarks: "$checklist.units.remarks",
|
|
@@ -3108,6 +3194,7 @@ function useAreaChecklistRepo() {
|
|
|
3108
3194
|
{
|
|
3109
3195
|
$group: {
|
|
3110
3196
|
_id: "$set",
|
|
3197
|
+
isScheduleTask: { $first: "$isScheduleTask" },
|
|
3111
3198
|
units: {
|
|
3112
3199
|
$push: {
|
|
3113
3200
|
unit: "$unit",
|
|
@@ -3124,6 +3211,7 @@ function useAreaChecklistRepo() {
|
|
|
3124
3211
|
$project: {
|
|
3125
3212
|
_id: 0,
|
|
3126
3213
|
set: "$_id",
|
|
3214
|
+
isScheduleTask: 1,
|
|
3127
3215
|
units: 1
|
|
3128
3216
|
}
|
|
3129
3217
|
},
|
|
@@ -3240,7 +3328,7 @@ function useAreaChecklistRepo() {
|
|
|
3240
3328
|
},
|
|
3241
3329
|
{
|
|
3242
3330
|
$sort: {
|
|
3243
|
-
set: 1,
|
|
3331
|
+
"checklist.set": 1,
|
|
3244
3332
|
isActioned: 1,
|
|
3245
3333
|
"checklist.units.timestamp": 1,
|
|
3246
3334
|
isCompleted: -1
|
|
@@ -3250,6 +3338,12 @@ function useAreaChecklistRepo() {
|
|
|
3250
3338
|
$project: {
|
|
3251
3339
|
_id: 0,
|
|
3252
3340
|
set: "$checklist.set",
|
|
3341
|
+
isScheduleTask: {
|
|
3342
|
+
$ifNull: ["$checklist.isScheduleTask", false]
|
|
3343
|
+
},
|
|
3344
|
+
scheduleTaskId: {
|
|
3345
|
+
$ifNull: ["$checklist.scheduleTaskId", null]
|
|
3346
|
+
},
|
|
3253
3347
|
remarks: "$checklist.remarks",
|
|
3254
3348
|
attachment: "$checklist.attachment",
|
|
3255
3349
|
unit: "$checklist.units.unit",
|
|
@@ -3282,6 +3376,8 @@ function useAreaChecklistRepo() {
|
|
|
3282
3376
|
{
|
|
3283
3377
|
$group: {
|
|
3284
3378
|
_id: "$set",
|
|
3379
|
+
isScheduleTask: { $first: "$isScheduleTask" },
|
|
3380
|
+
scheduleTaskId: { $first: "$scheduleTaskId" },
|
|
3285
3381
|
remarks: { $first: "$remarks" },
|
|
3286
3382
|
attachment: { $first: "$attachment" },
|
|
3287
3383
|
completedByName: { $first: "$completedByName" },
|
|
@@ -3303,6 +3399,8 @@ function useAreaChecklistRepo() {
|
|
|
3303
3399
|
$project: {
|
|
3304
3400
|
_id: 0,
|
|
3305
3401
|
set: "$_id",
|
|
3402
|
+
isScheduleTask: 1,
|
|
3403
|
+
scheduleTaskId: 1,
|
|
3306
3404
|
remarks: "$remarks",
|
|
3307
3405
|
attachment: "$attachment",
|
|
3308
3406
|
completedByName: 1,
|
|
@@ -3327,7 +3425,7 @@ function useAreaChecklistRepo() {
|
|
|
3327
3425
|
}
|
|
3328
3426
|
}
|
|
3329
3427
|
},
|
|
3330
|
-
{ $sort: { isFullyActioned: 1 } },
|
|
3428
|
+
{ $sort: { isFullyActioned: 1, set: 1 } },
|
|
3331
3429
|
{ $skip: page * limit },
|
|
3332
3430
|
{ $limit: limit }
|
|
3333
3431
|
];
|
|
@@ -3550,7 +3648,7 @@ function useAreaChecklistRepo() {
|
|
|
3550
3648
|
const _id = new ObjectId9(areaId);
|
|
3551
3649
|
const result = await collection.aggregate(
|
|
3552
3650
|
[
|
|
3553
|
-
{ $match: { area: _id
|
|
3651
|
+
{ $match: { area: _id } },
|
|
3554
3652
|
{ $unwind: "$checklist" },
|
|
3555
3653
|
{ $group: { _id: null, maxSet: { $max: "$checklist.set" } } }
|
|
3556
3654
|
],
|
|
@@ -3598,9 +3696,155 @@ function useAreaChecklistRepo() {
|
|
|
3598
3696
|
throw error;
|
|
3599
3697
|
}
|
|
3600
3698
|
}
|
|
3699
|
+
async function pushScheduleTaskSets(scheduleId, areaId, scheduleTaskId, newSets) {
|
|
3700
|
+
try {
|
|
3701
|
+
const schedule = new ObjectId9(scheduleId);
|
|
3702
|
+
const area = new ObjectId9(areaId);
|
|
3703
|
+
const taskId = new ObjectId9(scheduleTaskId);
|
|
3704
|
+
const result = await collection.updateOne(
|
|
3705
|
+
{
|
|
3706
|
+
schedule,
|
|
3707
|
+
area,
|
|
3708
|
+
checklist: { $not: { $elemMatch: { scheduleTaskId: taskId } } }
|
|
3709
|
+
},
|
|
3710
|
+
{
|
|
3711
|
+
$push: { checklist: { $each: newSets } },
|
|
3712
|
+
$set: { updatedAt: /* @__PURE__ */ new Date() }
|
|
3713
|
+
}
|
|
3714
|
+
);
|
|
3715
|
+
if (result.modifiedCount > 0) {
|
|
3716
|
+
delNamespace().catch((err) => {
|
|
3717
|
+
logger17.error(
|
|
3718
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3719
|
+
err
|
|
3720
|
+
);
|
|
3721
|
+
});
|
|
3722
|
+
}
|
|
3723
|
+
return result.modifiedCount;
|
|
3724
|
+
} catch (error) {
|
|
3725
|
+
logger17.error("Error in pushScheduleTaskSets:", error);
|
|
3726
|
+
throw error;
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
async function insertAutoGenSets(scheduleId, areaId, newSets) {
|
|
3730
|
+
try {
|
|
3731
|
+
const schedule = new ObjectId9(scheduleId);
|
|
3732
|
+
const area = new ObjectId9(areaId);
|
|
3733
|
+
const result = await collection.updateOne(
|
|
3734
|
+
{
|
|
3735
|
+
schedule,
|
|
3736
|
+
area,
|
|
3737
|
+
checklist: {
|
|
3738
|
+
$not: { $elemMatch: { isScheduleTask: { $ne: true } } }
|
|
3739
|
+
}
|
|
3740
|
+
},
|
|
3741
|
+
{
|
|
3742
|
+
$push: { checklist: { $each: newSets } },
|
|
3743
|
+
$set: { updatedAt: /* @__PURE__ */ new Date() }
|
|
3744
|
+
}
|
|
3745
|
+
);
|
|
3746
|
+
if (result.modifiedCount > 0) {
|
|
3747
|
+
delNamespace().catch((err) => {
|
|
3748
|
+
logger17.error(
|
|
3749
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3750
|
+
err
|
|
3751
|
+
);
|
|
3752
|
+
});
|
|
3753
|
+
}
|
|
3754
|
+
return result.modifiedCount;
|
|
3755
|
+
} catch (error) {
|
|
3756
|
+
logger17.error("Error in insertAutoGenSets:", error);
|
|
3757
|
+
throw error;
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
async function trimOverflowSets() {
|
|
3761
|
+
try {
|
|
3762
|
+
const db2 = useAtlas6.getDb();
|
|
3763
|
+
if (!db2)
|
|
3764
|
+
return 0;
|
|
3765
|
+
const bloated = await collection.aggregate([
|
|
3766
|
+
{
|
|
3767
|
+
$lookup: {
|
|
3768
|
+
from: "site.cleaning.areas",
|
|
3769
|
+
localField: "area",
|
|
3770
|
+
foreignField: "_id",
|
|
3771
|
+
as: "areaDoc"
|
|
3772
|
+
}
|
|
3773
|
+
},
|
|
3774
|
+
{
|
|
3775
|
+
$unwind: { path: "$areaDoc", preserveNullAndEmptyArrays: false }
|
|
3776
|
+
},
|
|
3777
|
+
{
|
|
3778
|
+
$addFields: {
|
|
3779
|
+
configuredSet: { $max: [1, { $ifNull: ["$areaDoc.set", 1] }] },
|
|
3780
|
+
autoGenSets: {
|
|
3781
|
+
$filter: {
|
|
3782
|
+
input: { $ifNull: ["$checklist", []] },
|
|
3783
|
+
as: "item",
|
|
3784
|
+
cond: { $ne: ["$$item.isScheduleTask", true] }
|
|
3785
|
+
}
|
|
3786
|
+
},
|
|
3787
|
+
scheduledSets: {
|
|
3788
|
+
$filter: {
|
|
3789
|
+
input: { $ifNull: ["$checklist", []] },
|
|
3790
|
+
as: "item",
|
|
3791
|
+
cond: { $eq: ["$$item.isScheduleTask", true] }
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
}
|
|
3795
|
+
},
|
|
3796
|
+
{
|
|
3797
|
+
$match: {
|
|
3798
|
+
$expr: {
|
|
3799
|
+
$gt: [{ $size: "$autoGenSets" }, "$configuredSet"]
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
},
|
|
3803
|
+
{
|
|
3804
|
+
$project: {
|
|
3805
|
+
_id: 1,
|
|
3806
|
+
checklist: 1,
|
|
3807
|
+
configuredSet: 1,
|
|
3808
|
+
autoGenSets: 1,
|
|
3809
|
+
scheduledSets: 1
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
]).toArray();
|
|
3813
|
+
if (bloated.length === 0) {
|
|
3814
|
+
logger17.info(
|
|
3815
|
+
"trimOverflowSets: no bloated area-checklist documents found"
|
|
3816
|
+
);
|
|
3817
|
+
return 0;
|
|
3818
|
+
}
|
|
3819
|
+
let trimmed = 0;
|
|
3820
|
+
for (const doc of bloated) {
|
|
3821
|
+
const limit = Number(doc.configuredSet) || 1;
|
|
3822
|
+
const trimmedAutoGen = [...doc.autoGenSets ?? []].sort((a, b) => (a.set ?? 0) - (b.set ?? 0)).slice(0, limit);
|
|
3823
|
+
const keep = [...trimmedAutoGen, ...doc.scheduledSets ?? []];
|
|
3824
|
+
const res = await collection.updateOne(
|
|
3825
|
+
{ _id: doc._id },
|
|
3826
|
+
{ $set: { checklist: keep, updatedAt: /* @__PURE__ */ new Date() } }
|
|
3827
|
+
);
|
|
3828
|
+
if (res.modifiedCount > 0) {
|
|
3829
|
+
trimmed++;
|
|
3830
|
+
logger17.info(
|
|
3831
|
+
`trimOverflowSets: trimmed doc ${doc._id} \u2014 kept ${keep.length} sets (${trimmedAutoGen.length} auto-gen, ${(doc.scheduledSets ?? []).length} scheduled), removed ${doc.checklist.length - keep.length} excess auto-gen`
|
|
3832
|
+
);
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
delNamespace().catch(() => {
|
|
3836
|
+
});
|
|
3837
|
+
logger17.info(`trimOverflowSets: trimmed ${trimmed} document(s)`);
|
|
3838
|
+
return trimmed;
|
|
3839
|
+
} catch (error) {
|
|
3840
|
+
logger17.error("Error in trimOverflowSets:", error);
|
|
3841
|
+
return 0;
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3601
3844
|
return {
|
|
3602
3845
|
createIndex,
|
|
3603
3846
|
createTextIndex,
|
|
3847
|
+
createUniqueIndex,
|
|
3604
3848
|
createAreaChecklist,
|
|
3605
3849
|
getAllAreaChecklist,
|
|
3606
3850
|
getAreaChecklistHistory,
|
|
@@ -3613,7 +3857,10 @@ function useAreaChecklistRepo() {
|
|
|
3613
3857
|
updateAreaChecklistStatus,
|
|
3614
3858
|
updateAreaChecklistUnits,
|
|
3615
3859
|
getMaxSetNumberForArea,
|
|
3616
|
-
closeExpiredAreaChecklists
|
|
3860
|
+
closeExpiredAreaChecklists,
|
|
3861
|
+
pushScheduleTaskSets,
|
|
3862
|
+
insertAutoGenSets,
|
|
3863
|
+
trimOverflowSets
|
|
3617
3864
|
};
|
|
3618
3865
|
}
|
|
3619
3866
|
|
|
@@ -3625,19 +3872,18 @@ function useAreaChecklistService() {
|
|
|
3625
3872
|
getAllAreaChecklist,
|
|
3626
3873
|
getAreaChecklistUnits,
|
|
3627
3874
|
getAreaChecklistById,
|
|
3875
|
+
getAreaChecklistByAreaAndSchedule,
|
|
3628
3876
|
getAreaChecklistSetOwner,
|
|
3629
3877
|
updateAreaChecklistUnits: _updateAreaChecklistUnits,
|
|
3630
3878
|
updateAreaChecklistStatus,
|
|
3631
|
-
|
|
3879
|
+
insertAutoGenSets
|
|
3632
3880
|
} = useAreaChecklistRepo();
|
|
3633
3881
|
const { updateParentChecklistStatuses } = useParentChecklistRepo();
|
|
3634
3882
|
const { getUserById } = useUserRepo();
|
|
3635
3883
|
async function createAreaChecklist(value) {
|
|
3636
|
-
const
|
|
3884
|
+
const results = [];
|
|
3885
|
+
let totalChecklistsCreated = 0;
|
|
3637
3886
|
try {
|
|
3638
|
-
session?.startTransaction();
|
|
3639
|
-
const results = [];
|
|
3640
|
-
let totalChecklistsCreated = 0;
|
|
3641
3887
|
const BATCH_SIZE = 10;
|
|
3642
3888
|
const areasResult = await getAreasForChecklist(value.site);
|
|
3643
3889
|
const areas = areasResult || [];
|
|
@@ -3651,15 +3897,72 @@ function useAreaChecklistService() {
|
|
|
3651
3897
|
);
|
|
3652
3898
|
return null;
|
|
3653
3899
|
}
|
|
3654
|
-
|
|
3655
|
-
|
|
3900
|
+
let existing = null;
|
|
3901
|
+
try {
|
|
3902
|
+
existing = await getAreaChecklistByAreaAndSchedule(
|
|
3903
|
+
value.schedule.toString(),
|
|
3904
|
+
area._id.toString()
|
|
3905
|
+
);
|
|
3906
|
+
} catch (_) {
|
|
3907
|
+
}
|
|
3908
|
+
if (existing) {
|
|
3909
|
+
const hasAutoGenSets = existing.checklist?.some(
|
|
3910
|
+
(c) => c.isScheduleTask !== true
|
|
3911
|
+
);
|
|
3912
|
+
if (hasAutoGenSets) {
|
|
3913
|
+
logger18.info(
|
|
3914
|
+
`Area checklist already exists with auto-gen sets for area ${area.name}, skipping`
|
|
3915
|
+
);
|
|
3916
|
+
return existing._id;
|
|
3917
|
+
}
|
|
3918
|
+
logger18.info(
|
|
3919
|
+
`Area checklist for area ${area.name} exists but has no auto-gen sets. Inserting auto-gen sets.`
|
|
3920
|
+
);
|
|
3921
|
+
const setCount2 = Number(area.set) || 1;
|
|
3922
|
+
const totalExistingSets = existing.checklist?.length ?? 0;
|
|
3923
|
+
if (totalExistingSets >= setCount2) {
|
|
3924
|
+
logger18.info(
|
|
3925
|
+
`Area checklist for area ${area.name} already has ${totalExistingSets} set(s) (configured: ${setCount2}). Skipping auto-gen sets.`
|
|
3926
|
+
);
|
|
3927
|
+
return existing._id;
|
|
3928
|
+
}
|
|
3929
|
+
const maxExistingSet = existing.checklist?.reduce(
|
|
3930
|
+
(max, c) => Math.max(max, c.set ?? 0),
|
|
3931
|
+
0
|
|
3932
|
+
) ?? 0;
|
|
3933
|
+
const setsToAdd = setCount2 - totalExistingSets;
|
|
3934
|
+
const autoGenSets = Array.from(
|
|
3935
|
+
{ length: setsToAdd },
|
|
3936
|
+
(_, index) => ({
|
|
3937
|
+
set: maxExistingSet + index + 1,
|
|
3938
|
+
isScheduleTask: false,
|
|
3939
|
+
units: area.units.map((unit) => ({
|
|
3940
|
+
unit: new ObjectId10(unit.unit),
|
|
3941
|
+
name: unit.name,
|
|
3942
|
+
approve: false,
|
|
3943
|
+
reject: false,
|
|
3944
|
+
status: "open",
|
|
3945
|
+
remarks: "",
|
|
3946
|
+
completedBy: "",
|
|
3947
|
+
timestamp: ""
|
|
3948
|
+
}))
|
|
3949
|
+
})
|
|
3950
|
+
);
|
|
3951
|
+
await insertAutoGenSets(
|
|
3952
|
+
value.schedule.toString(),
|
|
3953
|
+
area._id.toString(),
|
|
3954
|
+
autoGenSets
|
|
3955
|
+
);
|
|
3956
|
+
return existing._id;
|
|
3957
|
+
}
|
|
3958
|
+
const setCount = Number(area.set) || 1;
|
|
3656
3959
|
const checklistData = {
|
|
3657
3960
|
schedule: value.schedule,
|
|
3658
3961
|
area: area._id.toString(),
|
|
3659
3962
|
name: area.name,
|
|
3660
3963
|
type: area.type,
|
|
3661
3964
|
checklist: Array.from({ length: setCount }, (_, index) => ({
|
|
3662
|
-
set:
|
|
3965
|
+
set: index + 1,
|
|
3663
3966
|
units: area.units.map((unit) => ({
|
|
3664
3967
|
unit: unit.unit.toString(),
|
|
3665
3968
|
name: unit.name
|
|
@@ -3667,10 +3970,7 @@ function useAreaChecklistService() {
|
|
|
3667
3970
|
})),
|
|
3668
3971
|
createdBy: value.createdBy
|
|
3669
3972
|
};
|
|
3670
|
-
const insertedId = await _createAreaChecklist(
|
|
3671
|
-
checklistData,
|
|
3672
|
-
session
|
|
3673
|
-
);
|
|
3973
|
+
const insertedId = await _createAreaChecklist(checklistData);
|
|
3674
3974
|
totalChecklistsCreated++;
|
|
3675
3975
|
return insertedId;
|
|
3676
3976
|
});
|
|
@@ -3683,19 +3983,13 @@ function useAreaChecklistService() {
|
|
|
3683
3983
|
} else {
|
|
3684
3984
|
logger18.warn(`No common areas found for site: ${value.site}`);
|
|
3685
3985
|
}
|
|
3686
|
-
await session?.commitTransaction();
|
|
3687
3986
|
logger18.info(
|
|
3688
3987
|
`Successfully created ${totalChecklistsCreated} area checklists for site: ${value.site}`
|
|
3689
3988
|
);
|
|
3690
3989
|
return results;
|
|
3691
3990
|
} catch (error) {
|
|
3692
3991
|
logger18.error(`Error generating area checklists:`, error);
|
|
3693
|
-
if (session?.inTransaction()) {
|
|
3694
|
-
await session?.abortTransaction();
|
|
3695
|
-
}
|
|
3696
3992
|
throw error;
|
|
3697
|
-
} finally {
|
|
3698
|
-
session?.endSession();
|
|
3699
3993
|
}
|
|
3700
3994
|
}
|
|
3701
3995
|
async function updateAreaChecklistUnits(_id, set, unitId, value) {
|
|
@@ -3799,7 +4093,7 @@ import { BadRequestError as BadRequestError16, InternalServerError as InternalSe
|
|
|
3799
4093
|
// src/services/hygiene-checklist-pdf.service.ts
|
|
3800
4094
|
import { launch } from "puppeteer";
|
|
3801
4095
|
import { InternalServerError as InternalServerError6, useAtlas as useAtlas8 } from "@7365admin1/node-server-utils";
|
|
3802
|
-
import { ObjectId as
|
|
4096
|
+
import { ObjectId as ObjectId11 } from "mongodb";
|
|
3803
4097
|
function escapeHtml(text) {
|
|
3804
4098
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3805
4099
|
}
|
|
@@ -3973,7 +4267,7 @@ function useChecklistPdfService() {
|
|
|
3973
4267
|
const collection = db.collection("site.cleaning.schedule.areas");
|
|
3974
4268
|
let scheduleObjectId;
|
|
3975
4269
|
try {
|
|
3976
|
-
scheduleObjectId = new
|
|
4270
|
+
scheduleObjectId = new ObjectId11(scheduleId);
|
|
3977
4271
|
} catch {
|
|
3978
4272
|
throw new InternalServerError6("Invalid schedule ID format.");
|
|
3979
4273
|
}
|
|
@@ -4282,7 +4576,7 @@ function useAreaChecklistController() {
|
|
|
4282
4576
|
|
|
4283
4577
|
// src/models/hygiene-supply.model.ts
|
|
4284
4578
|
import Joi10 from "joi";
|
|
4285
|
-
import { ObjectId as
|
|
4579
|
+
import { ObjectId as ObjectId12 } from "mongodb";
|
|
4286
4580
|
import { BadRequestError as BadRequestError17, logger as logger21 } from "@7365admin1/node-server-utils";
|
|
4287
4581
|
var supplySchema = Joi10.object({
|
|
4288
4582
|
site: Joi10.string().hex().required(),
|
|
@@ -4297,7 +4591,7 @@ function MSupply(value) {
|
|
|
4297
4591
|
}
|
|
4298
4592
|
if (value.site) {
|
|
4299
4593
|
try {
|
|
4300
|
-
value.site = new
|
|
4594
|
+
value.site = new ObjectId12(value.site);
|
|
4301
4595
|
} catch (error2) {
|
|
4302
4596
|
throw new BadRequestError17("Invalid site ID format.");
|
|
4303
4597
|
}
|
|
@@ -4315,7 +4609,7 @@ function MSupply(value) {
|
|
|
4315
4609
|
}
|
|
4316
4610
|
|
|
4317
4611
|
// src/repositories/hygiene-supply.repository.ts
|
|
4318
|
-
import { ObjectId as
|
|
4612
|
+
import { ObjectId as ObjectId13 } from "mongodb";
|
|
4319
4613
|
import {
|
|
4320
4614
|
useAtlas as useAtlas9,
|
|
4321
4615
|
InternalServerError as InternalServerError8,
|
|
@@ -4400,7 +4694,7 @@ function useSupplyRepository() {
|
|
|
4400
4694
|
limit
|
|
4401
4695
|
};
|
|
4402
4696
|
try {
|
|
4403
|
-
site = new
|
|
4697
|
+
site = new ObjectId13(site);
|
|
4404
4698
|
query.site = site;
|
|
4405
4699
|
cacheOptions.site = site.toString();
|
|
4406
4700
|
} catch (error) {
|
|
@@ -4444,7 +4738,7 @@ function useSupplyRepository() {
|
|
|
4444
4738
|
}
|
|
4445
4739
|
async function getSupplyById(_id, session) {
|
|
4446
4740
|
try {
|
|
4447
|
-
_id = new
|
|
4741
|
+
_id = new ObjectId13(_id);
|
|
4448
4742
|
} catch (error) {
|
|
4449
4743
|
throw new BadRequestError18("Invalid supply ID format.");
|
|
4450
4744
|
}
|
|
@@ -4490,7 +4784,7 @@ function useSupplyRepository() {
|
|
|
4490
4784
|
}
|
|
4491
4785
|
async function updateSupply(_id, value, session) {
|
|
4492
4786
|
try {
|
|
4493
|
-
_id = new
|
|
4787
|
+
_id = new ObjectId13(_id);
|
|
4494
4788
|
} catch (error) {
|
|
4495
4789
|
throw new BadRequestError18("Invalid supply ID format.");
|
|
4496
4790
|
}
|
|
@@ -4523,7 +4817,7 @@ function useSupplyRepository() {
|
|
|
4523
4817
|
}
|
|
4524
4818
|
async function deleteSupply(_id, session) {
|
|
4525
4819
|
try {
|
|
4526
|
-
_id = new
|
|
4820
|
+
_id = new ObjectId13(_id);
|
|
4527
4821
|
} catch (error) {
|
|
4528
4822
|
throw new BadRequestError18("Invalid supply ID format.");
|
|
4529
4823
|
}
|
|
@@ -4704,7 +4998,7 @@ function useSupplyController() {
|
|
|
4704
4998
|
|
|
4705
4999
|
// src/models/hygiene-stock.model.ts
|
|
4706
5000
|
import Joi12 from "joi";
|
|
4707
|
-
import { ObjectId as
|
|
5001
|
+
import { ObjectId as ObjectId14 } from "mongodb";
|
|
4708
5002
|
import { BadRequestError as BadRequestError20, logger as logger24 } from "@7365admin1/node-server-utils";
|
|
4709
5003
|
var stockSchema = Joi12.object({
|
|
4710
5004
|
site: Joi12.string().hex().required(),
|
|
@@ -4722,14 +5016,14 @@ function MStock(value) {
|
|
|
4722
5016
|
}
|
|
4723
5017
|
if (value.site) {
|
|
4724
5018
|
try {
|
|
4725
|
-
value.site = new
|
|
5019
|
+
value.site = new ObjectId14(value.site);
|
|
4726
5020
|
} catch (error2) {
|
|
4727
5021
|
throw new BadRequestError20("Invalid site ID format.");
|
|
4728
5022
|
}
|
|
4729
5023
|
}
|
|
4730
5024
|
if (value.supply) {
|
|
4731
5025
|
try {
|
|
4732
|
-
value.supply = new
|
|
5026
|
+
value.supply = new ObjectId14(value.supply);
|
|
4733
5027
|
} catch (error2) {
|
|
4734
5028
|
throw new BadRequestError20("Invalid supply ID format.");
|
|
4735
5029
|
}
|
|
@@ -4749,7 +5043,7 @@ function MStock(value) {
|
|
|
4749
5043
|
}
|
|
4750
5044
|
|
|
4751
5045
|
// src/repositories/hygiene-stock.repository.ts
|
|
4752
|
-
import { ObjectId as
|
|
5046
|
+
import { ObjectId as ObjectId15 } from "mongodb";
|
|
4753
5047
|
import {
|
|
4754
5048
|
useAtlas as useAtlas10,
|
|
4755
5049
|
InternalServerError as InternalServerError9,
|
|
@@ -4822,14 +5116,14 @@ function useStockRepository() {
|
|
|
4822
5116
|
limit
|
|
4823
5117
|
};
|
|
4824
5118
|
try {
|
|
4825
|
-
site = new
|
|
5119
|
+
site = new ObjectId15(site);
|
|
4826
5120
|
query.site = site;
|
|
4827
5121
|
cacheOptions.site = site.toString();
|
|
4828
5122
|
} catch (error) {
|
|
4829
5123
|
throw new BadRequestError21("Invalid site ID format.");
|
|
4830
5124
|
}
|
|
4831
5125
|
try {
|
|
4832
|
-
supply = new
|
|
5126
|
+
supply = new ObjectId15(supply);
|
|
4833
5127
|
query.supply = supply;
|
|
4834
5128
|
cacheOptions.supply = supply.toString();
|
|
4835
5129
|
} catch (error) {
|
|
@@ -5007,7 +5301,7 @@ function useStockController() {
|
|
|
5007
5301
|
|
|
5008
5302
|
// src/models/hygiene-checkout-item.model.ts
|
|
5009
5303
|
import Joi14 from "joi";
|
|
5010
|
-
import { ObjectId as
|
|
5304
|
+
import { ObjectId as ObjectId16 } from "mongodb";
|
|
5011
5305
|
import { BadRequestError as BadRequestError24, logger as logger27 } from "@7365admin1/node-server-utils";
|
|
5012
5306
|
var allowedCheckOutItemStatus = ["pending", "completed"];
|
|
5013
5307
|
var checkOutItemSchema = Joi14.object({
|
|
@@ -5027,14 +5321,14 @@ function MCheckOutItem(value) {
|
|
|
5027
5321
|
}
|
|
5028
5322
|
if (value.site) {
|
|
5029
5323
|
try {
|
|
5030
|
-
value.site = new
|
|
5324
|
+
value.site = new ObjectId16(value.site);
|
|
5031
5325
|
} catch (error2) {
|
|
5032
5326
|
throw new BadRequestError24("Invalid site ID format.");
|
|
5033
5327
|
}
|
|
5034
5328
|
}
|
|
5035
5329
|
if (value.supply) {
|
|
5036
5330
|
try {
|
|
5037
|
-
value.supply = new
|
|
5331
|
+
value.supply = new ObjectId16(value.supply);
|
|
5038
5332
|
} catch (error2) {
|
|
5039
5333
|
throw new BadRequestError24("Invalid supply ID format.");
|
|
5040
5334
|
}
|
|
@@ -5055,7 +5349,7 @@ function MCheckOutItem(value) {
|
|
|
5055
5349
|
}
|
|
5056
5350
|
|
|
5057
5351
|
// src/repositories/hygiene-checkout-item.repository.ts
|
|
5058
|
-
import { ObjectId as
|
|
5352
|
+
import { ObjectId as ObjectId17 } from "mongodb";
|
|
5059
5353
|
import {
|
|
5060
5354
|
useAtlas as useAtlas12,
|
|
5061
5355
|
InternalServerError as InternalServerError10,
|
|
@@ -5128,7 +5422,7 @@ function useCheckOutItemRepository() {
|
|
|
5128
5422
|
limit
|
|
5129
5423
|
};
|
|
5130
5424
|
try {
|
|
5131
|
-
site = new
|
|
5425
|
+
site = new ObjectId17(site);
|
|
5132
5426
|
query.site = site;
|
|
5133
5427
|
cacheOptions.site = site.toString();
|
|
5134
5428
|
} catch (error) {
|
|
@@ -5201,7 +5495,7 @@ function useCheckOutItemRepository() {
|
|
|
5201
5495
|
}
|
|
5202
5496
|
async function getCheckOutItemById(_id, session) {
|
|
5203
5497
|
try {
|
|
5204
|
-
_id = new
|
|
5498
|
+
_id = new ObjectId17(_id);
|
|
5205
5499
|
} catch (error) {
|
|
5206
5500
|
throw new BadRequestError25("Invalid check out item ID format.");
|
|
5207
5501
|
}
|
|
@@ -5265,7 +5559,7 @@ function useCheckOutItemRepository() {
|
|
|
5265
5559
|
}
|
|
5266
5560
|
async function completeCheckOutItem(_id, session) {
|
|
5267
5561
|
try {
|
|
5268
|
-
_id = new
|
|
5562
|
+
_id = new ObjectId17(_id);
|
|
5269
5563
|
} catch (error) {
|
|
5270
5564
|
throw new BadRequestError25("Invalid check out item ID format.");
|
|
5271
5565
|
}
|
|
@@ -5551,7 +5845,7 @@ function useCheckOutItemController() {
|
|
|
5551
5845
|
// src/models/hygiene-schedule-task.model.ts
|
|
5552
5846
|
import { BadRequestError as BadRequestError28, logger as logger30 } from "@7365admin1/node-server-utils";
|
|
5553
5847
|
import Joi16 from "joi";
|
|
5554
|
-
import { ObjectId as
|
|
5848
|
+
import { ObjectId as ObjectId18 } from "mongodb";
|
|
5555
5849
|
var scheduleTaskSchema = Joi16.object({
|
|
5556
5850
|
site: Joi16.string().hex().required(),
|
|
5557
5851
|
title: Joi16.string().required(),
|
|
@@ -5576,7 +5870,7 @@ function MScheduleTask(value) {
|
|
|
5576
5870
|
}
|
|
5577
5871
|
if (value.site) {
|
|
5578
5872
|
try {
|
|
5579
|
-
value.site = new
|
|
5873
|
+
value.site = new ObjectId18(value.site);
|
|
5580
5874
|
} catch (error2) {
|
|
5581
5875
|
throw new BadRequestError28("Invalid site ID format.");
|
|
5582
5876
|
}
|
|
@@ -5586,7 +5880,7 @@ function MScheduleTask(value) {
|
|
|
5586
5880
|
try {
|
|
5587
5881
|
return {
|
|
5588
5882
|
name: area.name,
|
|
5589
|
-
value: new
|
|
5883
|
+
value: new ObjectId18(area.value.toString())
|
|
5590
5884
|
};
|
|
5591
5885
|
} catch (error2) {
|
|
5592
5886
|
throw new BadRequestError28(`Invalid area value format: ${area.name}`);
|
|
@@ -5595,7 +5889,7 @@ function MScheduleTask(value) {
|
|
|
5595
5889
|
}
|
|
5596
5890
|
if (value.createdBy) {
|
|
5597
5891
|
try {
|
|
5598
|
-
value.createdBy = new
|
|
5892
|
+
value.createdBy = new ObjectId18(value.createdBy);
|
|
5599
5893
|
} catch (error2) {
|
|
5600
5894
|
throw new BadRequestError28("Invalid createdBy ID format.");
|
|
5601
5895
|
}
|
|
@@ -5616,7 +5910,7 @@ function MScheduleTask(value) {
|
|
|
5616
5910
|
}
|
|
5617
5911
|
|
|
5618
5912
|
// src/repositories/hygiene-schedule-task.repository.ts
|
|
5619
|
-
import { ObjectId as
|
|
5913
|
+
import { ObjectId as ObjectId19 } from "mongodb";
|
|
5620
5914
|
import {
|
|
5621
5915
|
useAtlas as useAtlas14,
|
|
5622
5916
|
InternalServerError as InternalServerError11,
|
|
@@ -5688,7 +5982,7 @@ function useScheduleTaskRepository() {
|
|
|
5688
5982
|
limit
|
|
5689
5983
|
};
|
|
5690
5984
|
try {
|
|
5691
|
-
site = new
|
|
5985
|
+
site = new ObjectId19(site);
|
|
5692
5986
|
query.site = site;
|
|
5693
5987
|
cacheOptions.site = site.toString();
|
|
5694
5988
|
} catch (error) {
|
|
@@ -5756,7 +6050,7 @@ function useScheduleTaskRepository() {
|
|
|
5756
6050
|
limit
|
|
5757
6051
|
};
|
|
5758
6052
|
try {
|
|
5759
|
-
site = new
|
|
6053
|
+
site = new ObjectId19(site);
|
|
5760
6054
|
query.site = site;
|
|
5761
6055
|
cacheOptions.site = site.toString();
|
|
5762
6056
|
} catch (error) {
|
|
@@ -5799,7 +6093,7 @@ function useScheduleTaskRepository() {
|
|
|
5799
6093
|
}
|
|
5800
6094
|
async function getScheduleTaskById(_id, session) {
|
|
5801
6095
|
try {
|
|
5802
|
-
_id = new
|
|
6096
|
+
_id = new ObjectId19(_id);
|
|
5803
6097
|
} catch (error) {
|
|
5804
6098
|
throw new BadRequestError29("Invalid schedule task ID format.");
|
|
5805
6099
|
}
|
|
@@ -5849,7 +6143,7 @@ function useScheduleTaskRepository() {
|
|
|
5849
6143
|
}
|
|
5850
6144
|
async function updateScheduleTask(_id, value, session) {
|
|
5851
6145
|
try {
|
|
5852
|
-
_id = new
|
|
6146
|
+
_id = new ObjectId19(_id);
|
|
5853
6147
|
} catch (error) {
|
|
5854
6148
|
throw new BadRequestError29("Invalid schedule task ID format.");
|
|
5855
6149
|
}
|
|
@@ -5858,7 +6152,7 @@ function useScheduleTaskRepository() {
|
|
|
5858
6152
|
try {
|
|
5859
6153
|
return {
|
|
5860
6154
|
name: area.name,
|
|
5861
|
-
value: new
|
|
6155
|
+
value: new ObjectId19(area.value.toString())
|
|
5862
6156
|
};
|
|
5863
6157
|
} catch (error) {
|
|
5864
6158
|
throw new BadRequestError29(`Invalid area value format: ${area.name}`);
|
|
@@ -5903,6 +6197,7 @@ function useScheduleTaskRepository() {
|
|
|
5903
6197
|
}
|
|
5904
6198
|
|
|
5905
6199
|
// src/services/hygiene-schedule-task.service.ts
|
|
6200
|
+
import { ObjectId as ObjectId20 } from "mongodb";
|
|
5906
6201
|
import { logger as logger32 } from "@7365admin1/node-server-utils";
|
|
5907
6202
|
function useScheduleTaskService() {
|
|
5908
6203
|
const { createParentChecklist } = useParentChecklistRepo();
|
|
@@ -5910,7 +6205,7 @@ function useScheduleTaskService() {
|
|
|
5910
6205
|
const {
|
|
5911
6206
|
createAreaChecklist,
|
|
5912
6207
|
getAreaChecklistByAreaAndSchedule,
|
|
5913
|
-
|
|
6208
|
+
pushScheduleTaskSets
|
|
5914
6209
|
} = useAreaChecklistRepo();
|
|
5915
6210
|
const { getAreaById } = useAreaRepo();
|
|
5916
6211
|
function checkScheduleConditions(schedule, currentDate = /* @__PURE__ */ new Date()) {
|
|
@@ -5949,6 +6244,35 @@ function useScheduleTaskService() {
|
|
|
5949
6244
|
);
|
|
5950
6245
|
return false;
|
|
5951
6246
|
}
|
|
6247
|
+
const relevantTimestamp = schedule.updatedAt || schedule.createdAt;
|
|
6248
|
+
if (relevantTimestamp) {
|
|
6249
|
+
const savedAt = new Date(relevantTimestamp);
|
|
6250
|
+
const savedHour = parseInt(
|
|
6251
|
+
savedAt.toLocaleTimeString("en-US", {
|
|
6252
|
+
hour: "2-digit",
|
|
6253
|
+
hour12: false,
|
|
6254
|
+
timeZone: "Asia/Singapore"
|
|
6255
|
+
}),
|
|
6256
|
+
10
|
|
6257
|
+
);
|
|
6258
|
+
const savedMinute = savedAt.toLocaleString("en-US", {
|
|
6259
|
+
minute: "2-digit",
|
|
6260
|
+
timeZone: "Asia/Singapore"
|
|
6261
|
+
});
|
|
6262
|
+
const savedDateFormatted = savedAt.toLocaleDateString("en-CA", {
|
|
6263
|
+
timeZone: "Asia/Singapore"
|
|
6264
|
+
});
|
|
6265
|
+
const savedMinNum = parseInt(savedMinute, 10);
|
|
6266
|
+
const wasSavedThisMinute = savedDateFormatted === currentDateFormatted && savedHour === currentHour && savedMinNum === currentMinute;
|
|
6267
|
+
if (wasSavedThisMinute) {
|
|
6268
|
+
logger32.info(
|
|
6269
|
+
`Schedule ${schedule._id}: Skipping \u2014 task was saved this minute (${savedHour}:${String(
|
|
6270
|
+
savedMinNum
|
|
6271
|
+
).padStart(2, "0")}). Will fire on next occurrence.`
|
|
6272
|
+
);
|
|
6273
|
+
return false;
|
|
6274
|
+
}
|
|
6275
|
+
}
|
|
5952
6276
|
logger32.info(
|
|
5953
6277
|
`Schedule ${schedule._id}: All conditions matched - Date is within range and time matches`
|
|
5954
6278
|
);
|
|
@@ -6016,8 +6340,14 @@ function useScheduleTaskService() {
|
|
|
6016
6340
|
let units = [];
|
|
6017
6341
|
if (areaDetails.units && areaDetails.units.length > 0) {
|
|
6018
6342
|
units = areaDetails.units.map((unit) => ({
|
|
6019
|
-
unit: unit.unit
|
|
6020
|
-
name: unit.name
|
|
6343
|
+
unit: new ObjectId20(unit.unit),
|
|
6344
|
+
name: unit.name,
|
|
6345
|
+
approve: false,
|
|
6346
|
+
reject: false,
|
|
6347
|
+
status: "open",
|
|
6348
|
+
remarks: "",
|
|
6349
|
+
completedBy: "",
|
|
6350
|
+
timestamp: ""
|
|
6021
6351
|
}));
|
|
6022
6352
|
logger32.info(
|
|
6023
6353
|
`Area ${area.name} (${areaId}): Using units from area details: ${JSON.stringify(
|
|
@@ -6054,79 +6384,62 @@ function useScheduleTaskService() {
|
|
|
6054
6384
|
);
|
|
6055
6385
|
}
|
|
6056
6386
|
if (existingAreaChecklist) {
|
|
6057
|
-
const
|
|
6058
|
-
const
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6387
|
+
const areaSetConfig = Number(areaDetails.set) || 1;
|
|
6388
|
+
const maxSetInChecklist = existingAreaChecklist.checklist?.length ? Math.max(
|
|
6389
|
+
...existingAreaChecklist.checklist.map(
|
|
6390
|
+
(c) => c.set
|
|
6391
|
+
)
|
|
6392
|
+
) : 0;
|
|
6393
|
+
const startSetNumber = maxSetInChecklist + 1;
|
|
6394
|
+
const newSets = Array.from(
|
|
6395
|
+
{ length: areaSetConfig },
|
|
6396
|
+
(_, index) => ({
|
|
6397
|
+
set: startSetNumber + index,
|
|
6398
|
+
units,
|
|
6399
|
+
isScheduleTask: true,
|
|
6400
|
+
scheduleTaskId: scheduleTask._id
|
|
6401
|
+
})
|
|
6070
6402
|
);
|
|
6071
|
-
await
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6403
|
+
const modified = await pushScheduleTaskSets(
|
|
6404
|
+
parentChecklistId.toString(),
|
|
6405
|
+
areaId,
|
|
6406
|
+
scheduleTask._id.toString(),
|
|
6407
|
+
newSets
|
|
6076
6408
|
);
|
|
6077
|
-
|
|
6078
|
-
const verifyChecklist = await getAreaChecklistByAreaAndSchedule(
|
|
6079
|
-
parentChecklistId.toString(),
|
|
6080
|
-
areaId
|
|
6081
|
-
);
|
|
6409
|
+
if (modified > 0) {
|
|
6082
6410
|
logger32.info(
|
|
6083
|
-
`
|
|
6084
|
-
verifyChecklist.checklist
|
|
6085
|
-
)}`
|
|
6411
|
+
`Appended ${areaSetConfig} set(s) starting from ${startSetNumber} to area checklist for area ${area.name}`
|
|
6086
6412
|
);
|
|
6087
|
-
}
|
|
6088
|
-
logger32.
|
|
6089
|
-
`Area ${area.name} (${areaId}):
|
|
6090
|
-
verifyError
|
|
6413
|
+
} else {
|
|
6414
|
+
logger32.info(
|
|
6415
|
+
`Area ${area.name} (${areaId}): Schedule task ${scheduleTask._id} already processed (atomic check), skipping.`
|
|
6091
6416
|
);
|
|
6092
6417
|
}
|
|
6093
6418
|
} else {
|
|
6419
|
+
const areaSetConfig = Number(areaDetails.set) || 1;
|
|
6420
|
+
const schedTaskId = scheduleTask._id;
|
|
6421
|
+
const schedTaskSets = Array.from(
|
|
6422
|
+
{ length: areaSetConfig },
|
|
6423
|
+
(_, index) => ({
|
|
6424
|
+
set: index + 1,
|
|
6425
|
+
units,
|
|
6426
|
+
isScheduleTask: true,
|
|
6427
|
+
scheduleTaskId: schedTaskId
|
|
6428
|
+
})
|
|
6429
|
+
);
|
|
6094
6430
|
const checklistData = {
|
|
6095
6431
|
schedule: parentChecklistId.toString(),
|
|
6096
6432
|
area: areaId,
|
|
6097
6433
|
name: area.name,
|
|
6098
6434
|
type: areaDetails.type || "common",
|
|
6099
|
-
checklist:
|
|
6100
|
-
{
|
|
6101
|
-
set: 1,
|
|
6102
|
-
units
|
|
6103
|
-
}
|
|
6104
|
-
],
|
|
6435
|
+
checklist: schedTaskSets,
|
|
6105
6436
|
createdBy: scheduleTask.createdBy
|
|
6106
6437
|
};
|
|
6107
6438
|
logger32.info(
|
|
6108
|
-
`Area ${area.name} (${areaId}): Creating new area checklist with
|
|
6109
|
-
checklistData
|
|
6110
|
-
)}`
|
|
6439
|
+
`Area ${area.name} (${areaId}): Creating new area checklist with schedule-task sets only`
|
|
6111
6440
|
);
|
|
6112
6441
|
await createAreaChecklist(checklistData);
|
|
6113
6442
|
logger32.info(`Created new area checklist for area ${area.name}`);
|
|
6114
|
-
try {
|
|
6115
|
-
const verifyChecklist = await getAreaChecklistByAreaAndSchedule(
|
|
6116
|
-
parentChecklistId.toString(),
|
|
6117
|
-
areaId
|
|
6118
|
-
);
|
|
6119
|
-
logger32.info(
|
|
6120
|
-
`Area ${area.name} (${areaId}): Checklist after creation: ${JSON.stringify(
|
|
6121
|
-
verifyChecklist.checklist
|
|
6122
|
-
)}`
|
|
6123
|
-
);
|
|
6124
|
-
} catch (verifyError) {
|
|
6125
|
-
logger32.warn(
|
|
6126
|
-
`Area ${area.name} (${areaId}): Error verifying checklist after creation:`,
|
|
6127
|
-
verifyError
|
|
6128
|
-
);
|
|
6129
|
-
}
|
|
6130
6443
|
}
|
|
6131
6444
|
} catch (error) {
|
|
6132
6445
|
logger32.error(`Error processing area ${area.name}:`, error);
|
|
@@ -6611,6 +6924,7 @@ export {
|
|
|
6611
6924
|
MStock,
|
|
6612
6925
|
MSupply,
|
|
6613
6926
|
MUnit,
|
|
6927
|
+
ServiceType,
|
|
6614
6928
|
allowedCheckOutItemStatus,
|
|
6615
6929
|
allowedChecklistStatus,
|
|
6616
6930
|
allowedPeriods,
|