@7365admin1/module-hygiene 4.7.0 → 4.9.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 +11 -10
- package/dist/index.js +786 -375
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +720 -309
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -84,7 +84,12 @@ module.exports = __toCommonJS(src_exports);
|
|
|
84
84
|
|
|
85
85
|
// src/models/hygiene-base.model.ts
|
|
86
86
|
var allowedTypes = ["common", "toilet"];
|
|
87
|
-
var allowedStatus = [
|
|
87
|
+
var allowedStatus = [
|
|
88
|
+
"open",
|
|
89
|
+
"ongoing",
|
|
90
|
+
"completed",
|
|
91
|
+
"closed"
|
|
92
|
+
];
|
|
88
93
|
var allowedPeriods = ["today", "thisWeek", "thisMonth"];
|
|
89
94
|
|
|
90
95
|
// src/repositories/hygiene-dashboard.repository.ts
|
|
@@ -1366,10 +1371,14 @@ function useAreaService() {
|
|
|
1366
1371
|
try {
|
|
1367
1372
|
dataArray = JSON.parse(dataJson);
|
|
1368
1373
|
} catch (error) {
|
|
1369
|
-
throw new import_node_server_utils8.BadRequestError(
|
|
1374
|
+
throw new import_node_server_utils8.BadRequestError(
|
|
1375
|
+
"We couldn't read the uploaded file. Please make sure you're uploading the correct file and try again."
|
|
1376
|
+
);
|
|
1370
1377
|
}
|
|
1371
1378
|
if (!dataArray || dataArray.length === 0) {
|
|
1372
|
-
throw new import_node_server_utils8.NotFoundError(
|
|
1379
|
+
throw new import_node_server_utils8.NotFoundError(
|
|
1380
|
+
"The uploaded file is empty. Please make sure your file contains data and try again."
|
|
1381
|
+
);
|
|
1373
1382
|
}
|
|
1374
1383
|
let availableUnits = [];
|
|
1375
1384
|
try {
|
|
@@ -1470,33 +1479,35 @@ function useAreaService() {
|
|
|
1470
1479
|
}
|
|
1471
1480
|
}
|
|
1472
1481
|
}
|
|
1473
|
-
let message = `Upload
|
|
1482
|
+
let message = `Upload complete! ${insertedAreaIds.length} ${insertedAreaIds.length === 1 ? "area was" : "areas were"} successfully added`;
|
|
1474
1483
|
if (duplicateAreas.length > 0) {
|
|
1475
|
-
message += `, ${duplicateAreas.length} areas skipped
|
|
1484
|
+
message += `, ${duplicateAreas.length} ${duplicateAreas.length === 1 ? "area was" : "areas were"} skipped because they already exist`;
|
|
1476
1485
|
}
|
|
1477
1486
|
if (failedAreas.length > 0) {
|
|
1478
|
-
message += `, ${failedAreas.length} areas
|
|
1487
|
+
message += `, ${failedAreas.length} ${failedAreas.length === 1 ? "area" : "areas"} could not be saved`;
|
|
1479
1488
|
}
|
|
1480
1489
|
if (skippedRows.length > 0) {
|
|
1481
|
-
message += `, ${skippedRows.length} rows skipped
|
|
1490
|
+
message += `, ${skippedRows.length} ${skippedRows.length === 1 ? "row was" : "rows were"} skipped due to missing information`;
|
|
1482
1491
|
}
|
|
1483
1492
|
import_node_server_utils8.logger.info(message);
|
|
1484
1493
|
if (insertedAreaIds.length === 0) {
|
|
1485
1494
|
if (duplicateAreas.length > 0 && failedAreas.length === 0 && skippedRows.length === 0) {
|
|
1486
1495
|
return {
|
|
1487
|
-
message: `No new areas were
|
|
1496
|
+
message: `No new areas were added. All ${duplicateAreas.length} ${duplicateAreas.length === 1 ? "area" : "areas"} in your file already exist in the system: ${duplicateAreas.join(
|
|
1497
|
+
", "
|
|
1498
|
+
)}.`
|
|
1488
1499
|
};
|
|
1489
1500
|
} else if (failedAreas.length > 0) {
|
|
1490
1501
|
throw new import_node_server_utils8.BadRequestError(
|
|
1491
|
-
`No areas were
|
|
1502
|
+
`No areas were added. ${failedAreas.length} ${failedAreas.length === 1 ? "area" : "areas"} could not be saved. Please review the area names and information in your file, then try again.`
|
|
1492
1503
|
);
|
|
1493
1504
|
} else if (skippedRows.length > 0 && duplicateAreas.length === 0) {
|
|
1494
1505
|
throw new import_node_server_utils8.BadRequestError(
|
|
1495
|
-
`No areas were
|
|
1506
|
+
`No areas were added. ${skippedRows.length} ${skippedRows.length === 1 ? "row" : "rows"} in your file had missing or incomplete information. Please fill in all required fields and try again.`
|
|
1496
1507
|
);
|
|
1497
1508
|
} else {
|
|
1498
1509
|
return {
|
|
1499
|
-
message: `No new areas were
|
|
1510
|
+
message: `No new areas were added. ${duplicateAreas.length} ${duplicateAreas.length === 1 ? "area" : "areas"} already exist${skippedRows.length > 0 ? `, and ${skippedRows.length} ${skippedRows.length === 1 ? "row" : "rows"} had missing or incomplete information` : ""}.`
|
|
1500
1511
|
};
|
|
1501
1512
|
}
|
|
1502
1513
|
}
|
|
@@ -1507,11 +1518,11 @@ function useAreaService() {
|
|
|
1507
1518
|
throw error;
|
|
1508
1519
|
} else if (error.message.includes("validation")) {
|
|
1509
1520
|
throw new import_node_server_utils8.BadRequestError(
|
|
1510
|
-
"Upload failed
|
|
1521
|
+
"Upload failed because some required information is missing or incorrect. Please review your file and make sure all fields are filled in properly."
|
|
1511
1522
|
);
|
|
1512
1523
|
} else {
|
|
1513
1524
|
throw new import_node_server_utils8.BadRequestError(
|
|
1514
|
-
|
|
1525
|
+
"Something went wrong while uploading. Please check your file and try again."
|
|
1515
1526
|
);
|
|
1516
1527
|
}
|
|
1517
1528
|
}
|
|
@@ -1520,11 +1531,15 @@ function useAreaService() {
|
|
|
1520
1531
|
try {
|
|
1521
1532
|
const areas = await getAreasForChecklist(site);
|
|
1522
1533
|
if (!areas || !Array.isArray(areas) || areas.length === 0) {
|
|
1523
|
-
throw new import_node_server_utils8.BadRequestError(
|
|
1534
|
+
throw new import_node_server_utils8.BadRequestError(
|
|
1535
|
+
"There are no areas to export yet. Please add some areas first, then try again."
|
|
1536
|
+
);
|
|
1524
1537
|
}
|
|
1525
1538
|
const excelBuffer = await generateAreaExcel(areas);
|
|
1526
1539
|
if (!excelBuffer || excelBuffer.length === 0) {
|
|
1527
|
-
throw new Error(
|
|
1540
|
+
throw new Error(
|
|
1541
|
+
"Something went wrong while preparing your export file. Please try again."
|
|
1542
|
+
);
|
|
1528
1543
|
}
|
|
1529
1544
|
return excelBuffer;
|
|
1530
1545
|
} catch (error) {
|
|
@@ -1824,10 +1839,14 @@ function useUnitService() {
|
|
|
1824
1839
|
try {
|
|
1825
1840
|
dataArray = JSON.parse(dataJson);
|
|
1826
1841
|
} catch (error) {
|
|
1827
|
-
throw new import_node_server_utils11.BadRequestError(
|
|
1842
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1843
|
+
"We couldn't read the uploaded file. Please make sure you're uploading the correct file and try again."
|
|
1844
|
+
);
|
|
1828
1845
|
}
|
|
1829
1846
|
if (!dataArray || dataArray.length === 0) {
|
|
1830
|
-
throw new import_node_server_utils11.NotFoundError(
|
|
1847
|
+
throw new import_node_server_utils11.NotFoundError(
|
|
1848
|
+
"The uploaded file is empty. Please make sure your file contains data and try again."
|
|
1849
|
+
);
|
|
1831
1850
|
}
|
|
1832
1851
|
const insertedUnitIds = [];
|
|
1833
1852
|
const duplicateUnits = [];
|
|
@@ -1868,29 +1887,31 @@ function useUnitService() {
|
|
|
1868
1887
|
}
|
|
1869
1888
|
}
|
|
1870
1889
|
}
|
|
1871
|
-
let message = `Upload
|
|
1890
|
+
let message = `Upload complete! ${insertedUnitIds.length} ${insertedUnitIds.length === 1 ? "unit was" : "units were"} successfully added`;
|
|
1872
1891
|
if (duplicateUnits.length > 0) {
|
|
1873
|
-
message += `, ${duplicateUnits.length} units skipped
|
|
1892
|
+
message += `, ${duplicateUnits.length} ${duplicateUnits.length === 1 ? "unit was" : "units were"} skipped because they already exist`;
|
|
1874
1893
|
}
|
|
1875
1894
|
if (failedUnits.length > 0) {
|
|
1876
|
-
message += `, ${failedUnits.length} units
|
|
1895
|
+
message += `, ${failedUnits.length} ${failedUnits.length === 1 ? "unit" : "units"} could not be saved`;
|
|
1877
1896
|
}
|
|
1878
1897
|
if (skippedRows.length > 0) {
|
|
1879
|
-
message += `, ${skippedRows.length} rows skipped
|
|
1898
|
+
message += `, ${skippedRows.length} ${skippedRows.length === 1 ? "row was" : "rows were"} skipped due to missing information`;
|
|
1880
1899
|
}
|
|
1881
1900
|
import_node_server_utils11.logger.info(message);
|
|
1882
1901
|
if (insertedUnitIds.length === 0) {
|
|
1883
1902
|
if (duplicateUnits.length > 0 && failedUnits.length === 0) {
|
|
1884
1903
|
throw new import_node_server_utils11.BadRequestError(
|
|
1885
|
-
`No new units were
|
|
1904
|
+
`No new units were added. All ${duplicateUnits.length} ${duplicateUnits.length === 1 ? "unit" : "units"} in your file already exist in the system: ${duplicateUnits.join(
|
|
1905
|
+
", "
|
|
1906
|
+
)}.`
|
|
1886
1907
|
);
|
|
1887
1908
|
} else if (failedUnits.length > 0) {
|
|
1888
1909
|
throw new import_node_server_utils11.BadRequestError(
|
|
1889
|
-
`No units were
|
|
1910
|
+
`No units were added. ${failedUnits.length} ${failedUnits.length === 1 ? "unit" : "units"} could not be saved. Please review the unit names in your file and try again.`
|
|
1890
1911
|
);
|
|
1891
1912
|
} else if (skippedRows.length > 0) {
|
|
1892
1913
|
throw new import_node_server_utils11.BadRequestError(
|
|
1893
|
-
`No units were
|
|
1914
|
+
`No units were added. ${skippedRows.length} ${skippedRows.length === 1 ? "row" : "rows"} in your file had missing or incomplete information. Please fill in all required fields and try again.`
|
|
1894
1915
|
);
|
|
1895
1916
|
}
|
|
1896
1917
|
}
|
|
@@ -1901,15 +1922,15 @@ function useUnitService() {
|
|
|
1901
1922
|
throw error;
|
|
1902
1923
|
} else if (error.message.includes("duplicate")) {
|
|
1903
1924
|
throw new import_node_server_utils11.BadRequestError(
|
|
1904
|
-
"Upload failed
|
|
1925
|
+
"Upload failed because some unit names are already taken. Please make sure each unit has a unique name and try again."
|
|
1905
1926
|
);
|
|
1906
1927
|
} else if (error.message.includes("validation")) {
|
|
1907
1928
|
throw new import_node_server_utils11.BadRequestError(
|
|
1908
|
-
"Upload failed
|
|
1929
|
+
"Upload failed because some required information is missing or incorrect. Please review your file and make sure all fields are filled in properly."
|
|
1909
1930
|
);
|
|
1910
1931
|
} else {
|
|
1911
1932
|
throw new import_node_server_utils11.BadRequestError(
|
|
1912
|
-
|
|
1933
|
+
"Something went wrong while uploading. Please check your file and try again."
|
|
1913
1934
|
);
|
|
1914
1935
|
}
|
|
1915
1936
|
}
|
|
@@ -1941,7 +1962,9 @@ function useUnitService() {
|
|
|
1941
1962
|
session?.startTransaction();
|
|
1942
1963
|
const isExistingArea = await verifyAreaByUnitId(_id);
|
|
1943
1964
|
if (isExistingArea) {
|
|
1944
|
-
throw new import_node_server_utils11.BadRequestError(
|
|
1965
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1966
|
+
"This unit can't be deleted because it's currently being used in one or more areas. Please remove it from those areas first, then try again."
|
|
1967
|
+
);
|
|
1945
1968
|
}
|
|
1946
1969
|
const result = await _deleteUnit(_id, session);
|
|
1947
1970
|
await session?.commitTransaction();
|
|
@@ -1967,11 +1990,15 @@ function useUnitService() {
|
|
|
1967
1990
|
site
|
|
1968
1991
|
});
|
|
1969
1992
|
if (!data || !data.items || data.items.length === 0) {
|
|
1970
|
-
throw new import_node_server_utils11.BadRequestError(
|
|
1993
|
+
throw new import_node_server_utils11.BadRequestError(
|
|
1994
|
+
"There are no units to export yet. Please add some units first, then try again."
|
|
1995
|
+
);
|
|
1971
1996
|
}
|
|
1972
1997
|
const excelBuffer = await _generateUnitExcel(data.items);
|
|
1973
1998
|
if (!excelBuffer || excelBuffer.length === 0) {
|
|
1974
|
-
throw new Error(
|
|
1999
|
+
throw new Error(
|
|
2000
|
+
"Something went wrong while preparing your export file. Please try again."
|
|
2001
|
+
);
|
|
1975
2002
|
}
|
|
1976
2003
|
return excelBuffer;
|
|
1977
2004
|
} catch (error) {
|
|
@@ -2178,7 +2205,7 @@ function MParentChecklist(value) {
|
|
|
2178
2205
|
}
|
|
2179
2206
|
return {
|
|
2180
2207
|
site: value.site,
|
|
2181
|
-
status: "
|
|
2208
|
+
status: "open",
|
|
2182
2209
|
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
2183
2210
|
updatedAt: value.updatedAt ?? ""
|
|
2184
2211
|
};
|
|
@@ -2368,18 +2395,23 @@ function useParentChecklistRepo() {
|
|
|
2368
2395
|
status: {
|
|
2369
2396
|
$switch: {
|
|
2370
2397
|
branches: [
|
|
2371
|
-
{ case: { $eq: ["$status", "
|
|
2398
|
+
{ case: { $eq: ["$status", "open"] }, then: "Open" },
|
|
2372
2399
|
{
|
|
2373
2400
|
case: { $eq: ["$status", "ongoing"] },
|
|
2374
2401
|
then: "Ongoing"
|
|
2375
2402
|
},
|
|
2376
|
-
{ case: { $eq: ["$status", "completed"] }, then: "Completed" }
|
|
2403
|
+
{ case: { $eq: ["$status", "completed"] }, then: "Completed" },
|
|
2404
|
+
{
|
|
2405
|
+
case: { $eq: ["$status", "closed"] },
|
|
2406
|
+
then: "Closed"
|
|
2407
|
+
}
|
|
2377
2408
|
],
|
|
2378
2409
|
default: "$status"
|
|
2379
2410
|
}
|
|
2380
2411
|
},
|
|
2381
2412
|
completedAt: 1,
|
|
2382
|
-
createdAt: 1
|
|
2413
|
+
createdAt: 1,
|
|
2414
|
+
closeIn: { $add: ["$createdAt", 24 * 60 * 60 * 1e3] }
|
|
2383
2415
|
}
|
|
2384
2416
|
});
|
|
2385
2417
|
pipeline.push(
|
|
@@ -2467,11 +2499,42 @@ function useParentChecklistRepo() {
|
|
|
2467
2499
|
throw error;
|
|
2468
2500
|
}
|
|
2469
2501
|
}
|
|
2502
|
+
async function closeExpiredParentChecklists() {
|
|
2503
|
+
try {
|
|
2504
|
+
const expiryDate = new Date(Date.now() - 24 * 60 * 60 * 1e3);
|
|
2505
|
+
const result = await collection.updateMany(
|
|
2506
|
+
{
|
|
2507
|
+
status: { $in: ["open", "ongoing", "completed"] },
|
|
2508
|
+
createdAt: { $lte: expiryDate }
|
|
2509
|
+
},
|
|
2510
|
+
{
|
|
2511
|
+
$set: {
|
|
2512
|
+
status: "closed",
|
|
2513
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
);
|
|
2517
|
+
if (result.modifiedCount > 0) {
|
|
2518
|
+
delNamespace().catch((err) => {
|
|
2519
|
+
import_node_server_utils14.logger.error(
|
|
2520
|
+
"Failed to invalidate cache after closing expired parent checklists",
|
|
2521
|
+
err
|
|
2522
|
+
);
|
|
2523
|
+
});
|
|
2524
|
+
import_node_server_utils14.logger.info(`Closed ${result.modifiedCount} expired parent checklists`);
|
|
2525
|
+
}
|
|
2526
|
+
return result.modifiedCount;
|
|
2527
|
+
} catch (error) {
|
|
2528
|
+
import_node_server_utils14.logger.error("Failed to close expired parent checklists", error);
|
|
2529
|
+
throw error;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2470
2532
|
return {
|
|
2471
2533
|
createIndex,
|
|
2472
2534
|
createParentChecklist,
|
|
2473
2535
|
getAllParentChecklist,
|
|
2474
|
-
updateParentChecklistStatuses
|
|
2536
|
+
updateParentChecklistStatuses,
|
|
2537
|
+
closeExpiredParentChecklists
|
|
2475
2538
|
};
|
|
2476
2539
|
}
|
|
2477
2540
|
|
|
@@ -2553,7 +2616,7 @@ function useParentChecklistController() {
|
|
|
2553
2616
|
var import_joi8 = __toESM(require("joi"));
|
|
2554
2617
|
var import_mongodb8 = require("mongodb");
|
|
2555
2618
|
var import_node_server_utils16 = require("@7365admin1/node-server-utils");
|
|
2556
|
-
var allowedChecklistStatus = ["
|
|
2619
|
+
var allowedChecklistStatus = ["open", "completed", "closed"];
|
|
2557
2620
|
var areaChecklistSchema = import_joi8.default.object({
|
|
2558
2621
|
schedule: import_joi8.default.string().hex().required(),
|
|
2559
2622
|
area: import_joi8.default.string().hex().required(),
|
|
@@ -2601,7 +2664,7 @@ function MAreaChecklist(value) {
|
|
|
2601
2664
|
name: unit.name,
|
|
2602
2665
|
approve: false,
|
|
2603
2666
|
reject: false,
|
|
2604
|
-
status: "
|
|
2667
|
+
status: "open",
|
|
2605
2668
|
remarks: "",
|
|
2606
2669
|
completedBy: "",
|
|
2607
2670
|
timestamp: ""
|
|
@@ -2622,7 +2685,7 @@ function MAreaChecklist(value) {
|
|
|
2622
2685
|
name: value.name,
|
|
2623
2686
|
type: value.type,
|
|
2624
2687
|
checklist: value.checklist || [],
|
|
2625
|
-
status: "
|
|
2688
|
+
status: "open",
|
|
2626
2689
|
createdBy: value.createdBy,
|
|
2627
2690
|
createdAt: /* @__PURE__ */ new Date(),
|
|
2628
2691
|
completedAt: "",
|
|
@@ -2786,11 +2849,15 @@ function useAreaChecklistRepo() {
|
|
|
2786
2849
|
status: {
|
|
2787
2850
|
$switch: {
|
|
2788
2851
|
branches: [
|
|
2789
|
-
{ case: { $eq: ["$status", "
|
|
2852
|
+
{ case: { $eq: ["$status", "open"] }, then: "Open" },
|
|
2790
2853
|
{ case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
|
|
2791
2854
|
{
|
|
2792
2855
|
case: { $eq: ["$status", "completed"] },
|
|
2793
2856
|
then: "Completed"
|
|
2857
|
+
},
|
|
2858
|
+
{
|
|
2859
|
+
case: { $eq: ["$status", "closed"] },
|
|
2860
|
+
then: "Closed"
|
|
2794
2861
|
}
|
|
2795
2862
|
],
|
|
2796
2863
|
default: "$status"
|
|
@@ -2892,11 +2959,15 @@ function useAreaChecklistRepo() {
|
|
|
2892
2959
|
status: {
|
|
2893
2960
|
$switch: {
|
|
2894
2961
|
branches: [
|
|
2895
|
-
{ case: { $eq: ["$status", "
|
|
2962
|
+
{ case: { $eq: ["$status", "open"] }, then: "Open" },
|
|
2896
2963
|
{ case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
|
|
2897
2964
|
{
|
|
2898
2965
|
case: { $eq: ["$status", "completed"] },
|
|
2899
2966
|
then: "Completed"
|
|
2967
|
+
},
|
|
2968
|
+
{
|
|
2969
|
+
case: { $eq: ["$status", "closed"] },
|
|
2970
|
+
then: "Closed"
|
|
2900
2971
|
}
|
|
2901
2972
|
],
|
|
2902
2973
|
default: "$status"
|
|
@@ -2961,11 +3032,15 @@ function useAreaChecklistRepo() {
|
|
|
2961
3032
|
status: {
|
|
2962
3033
|
$switch: {
|
|
2963
3034
|
branches: [
|
|
2964
|
-
{ case: { $eq: ["$status", "
|
|
3035
|
+
{ case: { $eq: ["$status", "open"] }, then: "Open" },
|
|
2965
3036
|
{ case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
|
|
2966
3037
|
{
|
|
2967
3038
|
case: { $eq: ["$status", "completed"] },
|
|
2968
3039
|
then: "Completed"
|
|
3040
|
+
},
|
|
3041
|
+
{
|
|
3042
|
+
case: { $eq: ["$status", "closed"] },
|
|
3043
|
+
then: "Closed"
|
|
2969
3044
|
}
|
|
2970
3045
|
],
|
|
2971
3046
|
default: "$status"
|
|
@@ -3025,12 +3100,16 @@ function useAreaChecklistRepo() {
|
|
|
3025
3100
|
$switch: {
|
|
3026
3101
|
branches: [
|
|
3027
3102
|
{
|
|
3028
|
-
case: { $eq: ["$checklist.units.status", "
|
|
3029
|
-
then: "
|
|
3103
|
+
case: { $eq: ["$checklist.units.status", "open"] },
|
|
3104
|
+
then: "Open"
|
|
3030
3105
|
},
|
|
3031
3106
|
{
|
|
3032
3107
|
case: { $eq: ["$checklist.units.status", "completed"] },
|
|
3033
3108
|
then: "Completed"
|
|
3109
|
+
},
|
|
3110
|
+
{
|
|
3111
|
+
case: { $eq: ["$checklist.units.status", "closed"] },
|
|
3112
|
+
then: "Closed"
|
|
3034
3113
|
}
|
|
3035
3114
|
],
|
|
3036
3115
|
default: "$checklist.units.status"
|
|
@@ -3131,6 +3210,38 @@ function useAreaChecklistRepo() {
|
|
|
3131
3210
|
preserveNullAndEmptyArrays: false
|
|
3132
3211
|
}
|
|
3133
3212
|
},
|
|
3213
|
+
{
|
|
3214
|
+
$addFields: {
|
|
3215
|
+
isCompleted: { $ne: ["$checklist.units.completedBy", ""] }
|
|
3216
|
+
}
|
|
3217
|
+
},
|
|
3218
|
+
{
|
|
3219
|
+
$lookup: {
|
|
3220
|
+
from: "users",
|
|
3221
|
+
let: { completedById: "$checklist.units.completedBy" },
|
|
3222
|
+
pipeline: [
|
|
3223
|
+
{
|
|
3224
|
+
$match: {
|
|
3225
|
+
$expr: {
|
|
3226
|
+
$and: [
|
|
3227
|
+
{ $ne: ["$$completedById", ""] },
|
|
3228
|
+
{ $eq: ["$_id", "$$completedById"] }
|
|
3229
|
+
]
|
|
3230
|
+
}
|
|
3231
|
+
}
|
|
3232
|
+
},
|
|
3233
|
+
{ $project: { name: 1 } }
|
|
3234
|
+
],
|
|
3235
|
+
as: "completedBy"
|
|
3236
|
+
}
|
|
3237
|
+
},
|
|
3238
|
+
{
|
|
3239
|
+
$unwind: {
|
|
3240
|
+
path: "$completedBy",
|
|
3241
|
+
preserveNullAndEmptyArrays: true
|
|
3242
|
+
}
|
|
3243
|
+
},
|
|
3244
|
+
{ $sort: { set: 1, isCompleted: -1, "checklist.units.timestamp": 1 } },
|
|
3134
3245
|
{
|
|
3135
3246
|
$project: {
|
|
3136
3247
|
_id: 0,
|
|
@@ -3145,25 +3256,30 @@ function useAreaChecklistRepo() {
|
|
|
3145
3256
|
$switch: {
|
|
3146
3257
|
branches: [
|
|
3147
3258
|
{
|
|
3148
|
-
case: { $eq: ["$checklist.units.status", "
|
|
3149
|
-
then: "
|
|
3259
|
+
case: { $eq: ["$checklist.units.status", "open"] },
|
|
3260
|
+
then: "Open"
|
|
3150
3261
|
},
|
|
3151
3262
|
{
|
|
3152
3263
|
case: { $eq: ["$checklist.units.status", "completed"] },
|
|
3153
3264
|
then: "Completed"
|
|
3265
|
+
},
|
|
3266
|
+
{
|
|
3267
|
+
case: { $eq: ["$checklist.units.status", "closed"] },
|
|
3268
|
+
then: "Closed"
|
|
3154
3269
|
}
|
|
3155
3270
|
],
|
|
3156
3271
|
default: "$checklist.units.status"
|
|
3157
3272
|
}
|
|
3158
|
-
}
|
|
3273
|
+
},
|
|
3274
|
+
completedByName: "$completedBy.name"
|
|
3159
3275
|
}
|
|
3160
3276
|
},
|
|
3161
|
-
{ $sort: { set: 1, name: 1 } },
|
|
3162
3277
|
{
|
|
3163
3278
|
$group: {
|
|
3164
3279
|
_id: "$set",
|
|
3165
3280
|
remarks: { $first: "$remarks" },
|
|
3166
3281
|
attachment: { $first: "$attachment" },
|
|
3282
|
+
completedByName: { $first: "$completedByName" },
|
|
3167
3283
|
units: {
|
|
3168
3284
|
$push: {
|
|
3169
3285
|
unit: "$unit",
|
|
@@ -3171,7 +3287,8 @@ function useAreaChecklistRepo() {
|
|
|
3171
3287
|
approve: "$approve",
|
|
3172
3288
|
reject: "$reject",
|
|
3173
3289
|
status: "$status",
|
|
3174
|
-
remarks: "$remarks"
|
|
3290
|
+
remarks: "$remarks",
|
|
3291
|
+
completedByName: "$completedByName"
|
|
3175
3292
|
}
|
|
3176
3293
|
}
|
|
3177
3294
|
}
|
|
@@ -3182,6 +3299,7 @@ function useAreaChecklistRepo() {
|
|
|
3182
3299
|
set: "$_id",
|
|
3183
3300
|
remarks: "$remarks",
|
|
3184
3301
|
attachment: "$attachment",
|
|
3302
|
+
completedByName: 1,
|
|
3185
3303
|
units: 1
|
|
3186
3304
|
}
|
|
3187
3305
|
},
|
|
@@ -3280,7 +3398,7 @@ function useAreaChecklistRepo() {
|
|
|
3280
3398
|
} else if (value.reject === true) {
|
|
3281
3399
|
updateValue["checklist.$[checklist].units.$[unit].approve"] = false;
|
|
3282
3400
|
updateValue["checklist.$[checklist].units.$[unit].reject"] = true;
|
|
3283
|
-
updateValue["checklist.$[checklist].units.$[unit].status"] = "
|
|
3401
|
+
updateValue["checklist.$[checklist].units.$[unit].status"] = "open";
|
|
3284
3402
|
}
|
|
3285
3403
|
if (value.remarks) {
|
|
3286
3404
|
updateValue["checklist.$[checklist].units.$[unit].remarks"] = value.remarks;
|
|
@@ -3406,6 +3524,42 @@ function useAreaChecklistRepo() {
|
|
|
3406
3524
|
return 0;
|
|
3407
3525
|
}
|
|
3408
3526
|
}
|
|
3527
|
+
async function closeExpiredAreaChecklists() {
|
|
3528
|
+
try {
|
|
3529
|
+
const expiryDate = new Date(Date.now() - 24 * 60 * 60 * 1e3);
|
|
3530
|
+
const result = await collection.updateMany(
|
|
3531
|
+
{
|
|
3532
|
+
status: { $in: ["open", "ongoing", "completed"] },
|
|
3533
|
+
createdAt: { $lte: expiryDate }
|
|
3534
|
+
},
|
|
3535
|
+
{
|
|
3536
|
+
$set: {
|
|
3537
|
+
status: "closed",
|
|
3538
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
3539
|
+
"checklist.$[].units.$[unit].status": "closed"
|
|
3540
|
+
}
|
|
3541
|
+
},
|
|
3542
|
+
{
|
|
3543
|
+
arrayFilters: [{ "unit.status": { $in: ["open", "completed"] } }]
|
|
3544
|
+
}
|
|
3545
|
+
);
|
|
3546
|
+
if (result.modifiedCount > 0) {
|
|
3547
|
+
delNamespace().catch((err) => {
|
|
3548
|
+
import_node_server_utils17.logger.error(
|
|
3549
|
+
"Failed to invalidate cache after closing expired area checklists",
|
|
3550
|
+
err
|
|
3551
|
+
);
|
|
3552
|
+
});
|
|
3553
|
+
import_node_server_utils17.logger.info(
|
|
3554
|
+
`Closed ${result.modifiedCount} expired area checklists and their units`
|
|
3555
|
+
);
|
|
3556
|
+
}
|
|
3557
|
+
return result.modifiedCount;
|
|
3558
|
+
} catch (error) {
|
|
3559
|
+
import_node_server_utils17.logger.error("Failed to close expired area checklists", error);
|
|
3560
|
+
throw error;
|
|
3561
|
+
}
|
|
3562
|
+
}
|
|
3409
3563
|
return {
|
|
3410
3564
|
createIndex,
|
|
3411
3565
|
createTextIndex,
|
|
@@ -3419,7 +3573,8 @@ function useAreaChecklistRepo() {
|
|
|
3419
3573
|
updateAreaChecklist,
|
|
3420
3574
|
updateAreaChecklistStatus,
|
|
3421
3575
|
updateAreaChecklistUnits,
|
|
3422
|
-
getMaxSetNumberForArea
|
|
3576
|
+
getMaxSetNumberForArea,
|
|
3577
|
+
closeExpiredAreaChecklists
|
|
3423
3578
|
};
|
|
3424
3579
|
}
|
|
3425
3580
|
|
|
@@ -3515,12 +3670,12 @@ function useAreaChecklistService() {
|
|
|
3515
3670
|
},
|
|
3516
3671
|
session
|
|
3517
3672
|
);
|
|
3518
|
-
let areaStatus = "
|
|
3673
|
+
let areaStatus = "open";
|
|
3519
3674
|
if (allUnitsResult && allUnitsResult.items && allUnitsResult.items.length > 0) {
|
|
3520
3675
|
const sets = allUnitsResult.items;
|
|
3521
3676
|
const allUnits = sets.flatMap((set2) => set2.units || []);
|
|
3522
|
-
const
|
|
3523
|
-
(unit) => unit.status === "
|
|
3677
|
+
const openCount = allUnits.filter(
|
|
3678
|
+
(unit) => unit.status === "Open"
|
|
3524
3679
|
).length;
|
|
3525
3680
|
const completedCount = allUnits.filter(
|
|
3526
3681
|
(unit) => unit.status === "Completed"
|
|
@@ -3528,8 +3683,8 @@ function useAreaChecklistService() {
|
|
|
3528
3683
|
const totalCount = allUnits.length;
|
|
3529
3684
|
if (completedCount === totalCount) {
|
|
3530
3685
|
areaStatus = "completed";
|
|
3531
|
-
} else if (
|
|
3532
|
-
areaStatus = "
|
|
3686
|
+
} else if (openCount === totalCount) {
|
|
3687
|
+
areaStatus = "open";
|
|
3533
3688
|
} else {
|
|
3534
3689
|
areaStatus = "ongoing";
|
|
3535
3690
|
}
|
|
@@ -3548,18 +3703,18 @@ function useAreaChecklistService() {
|
|
|
3548
3703
|
);
|
|
3549
3704
|
if (allAreasResult && allAreasResult.items && allAreasResult.items.length > 0) {
|
|
3550
3705
|
const areas = allAreasResult.items;
|
|
3551
|
-
const
|
|
3552
|
-
(area) => area.status === "
|
|
3706
|
+
const openAreasCount = areas.filter(
|
|
3707
|
+
(area) => area.status === "Open"
|
|
3553
3708
|
).length;
|
|
3554
3709
|
const completedAreasCount = areas.filter(
|
|
3555
3710
|
(area) => area.status === "Completed"
|
|
3556
3711
|
).length;
|
|
3557
3712
|
const totalAreasCount = areas.length;
|
|
3558
|
-
let parentStatus = "
|
|
3713
|
+
let parentStatus = "open";
|
|
3559
3714
|
if (completedAreasCount === totalAreasCount) {
|
|
3560
3715
|
parentStatus = "completed";
|
|
3561
|
-
} else if (
|
|
3562
|
-
parentStatus = "
|
|
3716
|
+
} else if (openAreasCount === totalAreasCount) {
|
|
3717
|
+
parentStatus = "open";
|
|
3563
3718
|
} else {
|
|
3564
3719
|
parentStatus = "ongoing";
|
|
3565
3720
|
}
|
|
@@ -3570,7 +3725,7 @@ function useAreaChecklistService() {
|
|
|
3570
3725
|
);
|
|
3571
3726
|
} else {
|
|
3572
3727
|
import_node_server_utils18.logger.info(
|
|
3573
|
-
"No area checklists found, keeping parent status as
|
|
3728
|
+
"No area checklists found, keeping parent status as open"
|
|
3574
3729
|
);
|
|
3575
3730
|
}
|
|
3576
3731
|
}
|
|
@@ -3591,7 +3746,223 @@ function useAreaChecklistService() {
|
|
|
3591
3746
|
|
|
3592
3747
|
// src/controllers/hygiene-area-checklist.controller.ts
|
|
3593
3748
|
var import_joi9 = __toESM(require("joi"));
|
|
3749
|
+
var import_node_server_utils20 = require("@7365admin1/node-server-utils");
|
|
3750
|
+
|
|
3751
|
+
// src/services/hygiene-checklist-pdf.service.ts
|
|
3752
|
+
var import_puppeteer = require("puppeteer");
|
|
3594
3753
|
var import_node_server_utils19 = require("@7365admin1/node-server-utils");
|
|
3754
|
+
var import_mongodb10 = require("mongodb");
|
|
3755
|
+
function escapeHtml(text) {
|
|
3756
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3757
|
+
}
|
|
3758
|
+
function buildChecklistHtml(areaChecklists) {
|
|
3759
|
+
const areaSections = areaChecklists.map((area) => {
|
|
3760
|
+
const sortedChecklist = [...area.checklist || []].sort(
|
|
3761
|
+
(a, b) => a.set - b.set
|
|
3762
|
+
);
|
|
3763
|
+
const setRows = sortedChecklist.map((setItem) => {
|
|
3764
|
+
const unitRows = (setItem.units || []).map(
|
|
3765
|
+
(unit) => `
|
|
3766
|
+
<tr>
|
|
3767
|
+
<td class="unit-name">${escapeHtml(unit.name || "")}</td>
|
|
3768
|
+
<td class="icon-cell">${unit.reject ? '<span class="reject-icon">✗</span>' : ""}</td>
|
|
3769
|
+
<td class="icon-cell">${unit.approve ? '<span class="approve-icon">✓</span>' : ""}</td>
|
|
3770
|
+
</tr>`
|
|
3771
|
+
).join("");
|
|
3772
|
+
return `
|
|
3773
|
+
<tr class="set-header-row">
|
|
3774
|
+
<td colspan="3">Set ${setItem.set}</td>
|
|
3775
|
+
</tr>
|
|
3776
|
+
${unitRows}`;
|
|
3777
|
+
}).join("");
|
|
3778
|
+
return `
|
|
3779
|
+
<div class="area-section">
|
|
3780
|
+
<div class="area-header">
|
|
3781
|
+
<span class="area-name">${escapeHtml(area.name || "")}</span>
|
|
3782
|
+
<span class="area-type">${escapeHtml(area.type || "")}</span>
|
|
3783
|
+
</div>
|
|
3784
|
+
<table class="checklist-table">
|
|
3785
|
+
<thead>
|
|
3786
|
+
<tr>
|
|
3787
|
+
<th class="col-unit">Unit</th>
|
|
3788
|
+
<th class="col-icon">✗</th>
|
|
3789
|
+
<th class="col-icon">✓</th>
|
|
3790
|
+
</tr>
|
|
3791
|
+
</thead>
|
|
3792
|
+
<tbody>
|
|
3793
|
+
${setRows}
|
|
3794
|
+
</tbody>
|
|
3795
|
+
</table>
|
|
3796
|
+
</div>`;
|
|
3797
|
+
}).join("");
|
|
3798
|
+
return `<!DOCTYPE html>
|
|
3799
|
+
<html lang="en">
|
|
3800
|
+
<head>
|
|
3801
|
+
<meta charset="UTF-8">
|
|
3802
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
3803
|
+
<title>Checklist</title>
|
|
3804
|
+
<style>
|
|
3805
|
+
* {
|
|
3806
|
+
margin: 0;
|
|
3807
|
+
padding: 0;
|
|
3808
|
+
box-sizing: border-box;
|
|
3809
|
+
}
|
|
3810
|
+
body {
|
|
3811
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
3812
|
+
background: #ffffff;
|
|
3813
|
+
padding: 30px 35px;
|
|
3814
|
+
color: #1a1a1a;
|
|
3815
|
+
font-size: 13px;
|
|
3816
|
+
}
|
|
3817
|
+
.page-header {
|
|
3818
|
+
display: flex;
|
|
3819
|
+
align-items: center;
|
|
3820
|
+
justify-content: flex-start;
|
|
3821
|
+
background: #1a3a6b;
|
|
3822
|
+
margin-bottom: 24px;
|
|
3823
|
+
padding: 12px 16px;
|
|
3824
|
+
border-radius: 4px;
|
|
3825
|
+
}
|
|
3826
|
+
.page-logo {
|
|
3827
|
+
height: 40px;
|
|
3828
|
+
width: auto;
|
|
3829
|
+
object-fit: contain;
|
|
3830
|
+
}
|
|
3831
|
+
.area-section {
|
|
3832
|
+
margin-bottom: 22px;
|
|
3833
|
+
border: 1px solid #dce1e7;
|
|
3834
|
+
border-radius: 4px;
|
|
3835
|
+
overflow: hidden;
|
|
3836
|
+
page-break-inside: avoid;
|
|
3837
|
+
}
|
|
3838
|
+
.area-header {
|
|
3839
|
+
display: flex;
|
|
3840
|
+
align-items: center;
|
|
3841
|
+
justify-content: space-between;
|
|
3842
|
+
background: #2c3e50;
|
|
3843
|
+
color: #ffffff;
|
|
3844
|
+
padding: 9px 12px;
|
|
3845
|
+
}
|
|
3846
|
+
.area-name {
|
|
3847
|
+
font-size: 14px;
|
|
3848
|
+
font-weight: 600;
|
|
3849
|
+
}
|
|
3850
|
+
.area-type {
|
|
3851
|
+
font-size: 11px;
|
|
3852
|
+
text-transform: capitalize;
|
|
3853
|
+
background: rgba(255,255,255,0.2);
|
|
3854
|
+
padding: 2px 8px;
|
|
3855
|
+
border-radius: 10px;
|
|
3856
|
+
}
|
|
3857
|
+
.checklist-table {
|
|
3858
|
+
width: 100%;
|
|
3859
|
+
border-collapse: collapse;
|
|
3860
|
+
}
|
|
3861
|
+
.checklist-table thead tr th {
|
|
3862
|
+
background: #34495e;
|
|
3863
|
+
color: #ffffff;
|
|
3864
|
+
padding: 7px 10px;
|
|
3865
|
+
text-align: left;
|
|
3866
|
+
font-size: 12px;
|
|
3867
|
+
font-weight: 600;
|
|
3868
|
+
letter-spacing: 0.3px;
|
|
3869
|
+
}
|
|
3870
|
+
.checklist-table thead tr th.col-icon {
|
|
3871
|
+
text-align: center;
|
|
3872
|
+
width: 52px;
|
|
3873
|
+
}
|
|
3874
|
+
.checklist-table thead tr th.col-unit {
|
|
3875
|
+
width: auto;
|
|
3876
|
+
}
|
|
3877
|
+
.set-header-row td {
|
|
3878
|
+
background: #ecf0f1;
|
|
3879
|
+
color: #555;
|
|
3880
|
+
font-weight: 700;
|
|
3881
|
+
font-size: 12px;
|
|
3882
|
+
padding: 5px 10px;
|
|
3883
|
+
border-bottom: 1px solid #dce1e7;
|
|
3884
|
+
text-transform: uppercase;
|
|
3885
|
+
letter-spacing: 0.4px;
|
|
3886
|
+
}
|
|
3887
|
+
.checklist-table tbody tr td {
|
|
3888
|
+
padding: 7px 10px;
|
|
3889
|
+
border-bottom: 1px solid #f0f2f4;
|
|
3890
|
+
font-size: 13px;
|
|
3891
|
+
}
|
|
3892
|
+
.checklist-table tbody tr:last-child td {
|
|
3893
|
+
border-bottom: none;
|
|
3894
|
+
}
|
|
3895
|
+
.icon-cell {
|
|
3896
|
+
text-align: center;
|
|
3897
|
+
width: 52px;
|
|
3898
|
+
}
|
|
3899
|
+
.approve-icon {
|
|
3900
|
+
color: #27ae60;
|
|
3901
|
+
font-size: 16px;
|
|
3902
|
+
font-weight: bold;
|
|
3903
|
+
}
|
|
3904
|
+
.reject-icon {
|
|
3905
|
+
color: #e74c3c;
|
|
3906
|
+
font-size: 16px;
|
|
3907
|
+
font-weight: bold;
|
|
3908
|
+
}
|
|
3909
|
+
</style>
|
|
3910
|
+
</head>
|
|
3911
|
+
<body>
|
|
3912
|
+
<div class="page-header">
|
|
3913
|
+
<img class="page-logo" src="https://seven365-storage.sgp1.cdn.digitaloceanspaces.com/seven365-public/images/seven365-logo.png" alt="Seven365 Logo" />
|
|
3914
|
+
</div>
|
|
3915
|
+
${areaSections}
|
|
3916
|
+
</body>
|
|
3917
|
+
</html>`;
|
|
3918
|
+
}
|
|
3919
|
+
function useChecklistPdfService() {
|
|
3920
|
+
async function generateChecklistPdf(scheduleId) {
|
|
3921
|
+
const db = import_node_server_utils19.useAtlas.getDb();
|
|
3922
|
+
if (!db) {
|
|
3923
|
+
throw new import_node_server_utils19.InternalServerError("Unable to connect to server.");
|
|
3924
|
+
}
|
|
3925
|
+
const collection = db.collection("site.cleaning.schedule.areas");
|
|
3926
|
+
let scheduleObjectId;
|
|
3927
|
+
try {
|
|
3928
|
+
scheduleObjectId = new import_mongodb10.ObjectId(scheduleId);
|
|
3929
|
+
} catch {
|
|
3930
|
+
throw new import_node_server_utils19.InternalServerError("Invalid schedule ID format.");
|
|
3931
|
+
}
|
|
3932
|
+
const areaChecklists = await collection.find({ schedule: scheduleObjectId }).sort({ createdAt: 1, name: 1 }).toArray();
|
|
3933
|
+
const html = buildChecklistHtml(areaChecklists);
|
|
3934
|
+
const browser = await (0, import_puppeteer.launch)({
|
|
3935
|
+
headless: true,
|
|
3936
|
+
executablePath: process.env.CHROME_BINARY,
|
|
3937
|
+
args: ["--no-sandbox", "--disable-gpu", "--disable-dev-shm-usage"]
|
|
3938
|
+
});
|
|
3939
|
+
try {
|
|
3940
|
+
const page = await browser.newPage();
|
|
3941
|
+
await page.setViewport({ width: 794, height: 1123 });
|
|
3942
|
+
await page.setContent(html, {
|
|
3943
|
+
waitUntil: ["load", "networkidle0"]
|
|
3944
|
+
});
|
|
3945
|
+
const pdfBuffer = await page.pdf({
|
|
3946
|
+
format: "A4",
|
|
3947
|
+
printBackground: true,
|
|
3948
|
+
margin: {
|
|
3949
|
+
top: "15mm",
|
|
3950
|
+
right: "15mm",
|
|
3951
|
+
bottom: "15mm",
|
|
3952
|
+
left: "15mm"
|
|
3953
|
+
}
|
|
3954
|
+
});
|
|
3955
|
+
return pdfBuffer;
|
|
3956
|
+
} finally {
|
|
3957
|
+
await browser.close();
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
return {
|
|
3961
|
+
generateChecklistPdf
|
|
3962
|
+
};
|
|
3963
|
+
}
|
|
3964
|
+
|
|
3965
|
+
// src/controllers/hygiene-area-checklist.controller.ts
|
|
3595
3966
|
function useAreaChecklistController() {
|
|
3596
3967
|
const {
|
|
3597
3968
|
getAllAreaChecklist: _getAllAreaChecklist,
|
|
@@ -3603,6 +3974,7 @@ function useAreaChecklistController() {
|
|
|
3603
3974
|
createAreaChecklist: _createAreaChecklist,
|
|
3604
3975
|
updateAreaChecklistUnits: _updateAreaChecklistUnits
|
|
3605
3976
|
} = useAreaChecklistService();
|
|
3977
|
+
const { generateChecklistPdf: _generateChecklistPdf } = useChecklistPdfService();
|
|
3606
3978
|
async function createAreaChecklist(req, res, next) {
|
|
3607
3979
|
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
3608
3980
|
(acc, [key, value2]) => ({ ...acc, [key]: value2 }),
|
|
@@ -3621,8 +3993,8 @@ function useAreaChecklistController() {
|
|
|
3621
3993
|
});
|
|
3622
3994
|
const { error, value } = validation.validate(payload);
|
|
3623
3995
|
if (error) {
|
|
3624
|
-
|
|
3625
|
-
next(new
|
|
3996
|
+
import_node_server_utils20.logger.log({ level: "error", message: error.message });
|
|
3997
|
+
next(new import_node_server_utils20.BadRequestError(error.message));
|
|
3626
3998
|
return;
|
|
3627
3999
|
}
|
|
3628
4000
|
try {
|
|
@@ -3630,7 +4002,7 @@ function useAreaChecklistController() {
|
|
|
3630
4002
|
res.status(201).json({ message: "Area checklist generated successfully." });
|
|
3631
4003
|
return;
|
|
3632
4004
|
} catch (error2) {
|
|
3633
|
-
|
|
4005
|
+
import_node_server_utils20.logger.log({ level: "error", message: error2.message });
|
|
3634
4006
|
next(error2);
|
|
3635
4007
|
return;
|
|
3636
4008
|
}
|
|
@@ -3647,8 +4019,8 @@ function useAreaChecklistController() {
|
|
|
3647
4019
|
});
|
|
3648
4020
|
const { error } = validation.validate(query);
|
|
3649
4021
|
if (error) {
|
|
3650
|
-
|
|
3651
|
-
next(new
|
|
4022
|
+
import_node_server_utils20.logger.log({ level: "error", message: error.message });
|
|
4023
|
+
next(new import_node_server_utils20.BadRequestError(error.message));
|
|
3652
4024
|
return;
|
|
3653
4025
|
}
|
|
3654
4026
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3669,7 +4041,7 @@ function useAreaChecklistController() {
|
|
|
3669
4041
|
res.json(data);
|
|
3670
4042
|
return;
|
|
3671
4043
|
} catch (error2) {
|
|
3672
|
-
|
|
4044
|
+
import_node_server_utils20.logger.log({ level: "error", message: error2.message });
|
|
3673
4045
|
next(error2);
|
|
3674
4046
|
return;
|
|
3675
4047
|
}
|
|
@@ -3687,8 +4059,8 @@ function useAreaChecklistController() {
|
|
|
3687
4059
|
});
|
|
3688
4060
|
const { error } = validation.validate(query);
|
|
3689
4061
|
if (error) {
|
|
3690
|
-
|
|
3691
|
-
next(new
|
|
4062
|
+
import_node_server_utils20.logger.log({ level: "error", message: error.message });
|
|
4063
|
+
next(new import_node_server_utils20.BadRequestError(error.message));
|
|
3692
4064
|
return;
|
|
3693
4065
|
}
|
|
3694
4066
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3711,7 +4083,7 @@ function useAreaChecklistController() {
|
|
|
3711
4083
|
res.json(data);
|
|
3712
4084
|
return;
|
|
3713
4085
|
} catch (error2) {
|
|
3714
|
-
|
|
4086
|
+
import_node_server_utils20.logger.log({ level: "error", message: error2.message });
|
|
3715
4087
|
next(error2);
|
|
3716
4088
|
return;
|
|
3717
4089
|
}
|
|
@@ -3721,8 +4093,8 @@ function useAreaChecklistController() {
|
|
|
3721
4093
|
const _id = req.params.id;
|
|
3722
4094
|
const { error, value } = validation.validate(_id);
|
|
3723
4095
|
if (error) {
|
|
3724
|
-
|
|
3725
|
-
next(new
|
|
4096
|
+
import_node_server_utils20.logger.log({ level: "error", message: error.message });
|
|
4097
|
+
next(new import_node_server_utils20.BadRequestError(error.message));
|
|
3726
4098
|
return;
|
|
3727
4099
|
}
|
|
3728
4100
|
try {
|
|
@@ -3730,7 +4102,7 @@ function useAreaChecklistController() {
|
|
|
3730
4102
|
res.json(data);
|
|
3731
4103
|
return;
|
|
3732
4104
|
} catch (error2) {
|
|
3733
|
-
|
|
4105
|
+
import_node_server_utils20.logger.log({ level: "error", message: error2.message });
|
|
3734
4106
|
next(error2);
|
|
3735
4107
|
return;
|
|
3736
4108
|
}
|
|
@@ -3745,8 +4117,8 @@ function useAreaChecklistController() {
|
|
|
3745
4117
|
});
|
|
3746
4118
|
const { error } = validation.validate(query);
|
|
3747
4119
|
if (error) {
|
|
3748
|
-
|
|
3749
|
-
next(new
|
|
4120
|
+
import_node_server_utils20.logger.log({ level: "error", message: error.message });
|
|
4121
|
+
next(new import_node_server_utils20.BadRequestError(error.message));
|
|
3750
4122
|
return;
|
|
3751
4123
|
}
|
|
3752
4124
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3763,7 +4135,7 @@ function useAreaChecklistController() {
|
|
|
3763
4135
|
res.json(data);
|
|
3764
4136
|
return;
|
|
3765
4137
|
} catch (error2) {
|
|
3766
|
-
|
|
4138
|
+
import_node_server_utils20.logger.log({ level: "error", message: error2.message });
|
|
3767
4139
|
next(error2);
|
|
3768
4140
|
return;
|
|
3769
4141
|
}
|
|
@@ -3802,8 +4174,8 @@ function useAreaChecklistController() {
|
|
|
3802
4174
|
});
|
|
3803
4175
|
const { error } = validation.validate(payload);
|
|
3804
4176
|
if (error) {
|
|
3805
|
-
|
|
3806
|
-
next(new
|
|
4177
|
+
import_node_server_utils20.logger.log({ level: "error", message: error.message });
|
|
4178
|
+
next(new import_node_server_utils20.BadRequestError(error.message));
|
|
3807
4179
|
return;
|
|
3808
4180
|
}
|
|
3809
4181
|
try {
|
|
@@ -3812,7 +4184,39 @@ function useAreaChecklistController() {
|
|
|
3812
4184
|
res.json({ message: "Area checklist updated successfully." });
|
|
3813
4185
|
return;
|
|
3814
4186
|
} catch (error2) {
|
|
3815
|
-
|
|
4187
|
+
import_node_server_utils20.logger.log({ level: "error", message: error2.message });
|
|
4188
|
+
next(error2);
|
|
4189
|
+
return;
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
async function downloadChecklistPdf(req, res, next) {
|
|
4193
|
+
const validation = import_joi9.default.string().hex().required();
|
|
4194
|
+
const schedule = req.params.schedule;
|
|
4195
|
+
const { error, value } = validation.validate(schedule);
|
|
4196
|
+
if (error) {
|
|
4197
|
+
import_node_server_utils20.logger.log({ level: "error", message: error.message });
|
|
4198
|
+
next(new import_node_server_utils20.BadRequestError(error.message));
|
|
4199
|
+
return;
|
|
4200
|
+
}
|
|
4201
|
+
try {
|
|
4202
|
+
const pdfBuffer = await _generateChecklistPdf(value);
|
|
4203
|
+
if (!pdfBuffer || pdfBuffer.length === 0) {
|
|
4204
|
+
throw new import_node_server_utils20.InternalServerError("Generated checklist PDF is empty or invalid.");
|
|
4205
|
+
}
|
|
4206
|
+
const date = /* @__PURE__ */ new Date();
|
|
4207
|
+
const formattedDate = `${String(date.getDate()).padStart(2, "0")}_${String(
|
|
4208
|
+
date.getMonth() + 1
|
|
4209
|
+
).padStart(2, "0")}_${date.getFullYear()}`;
|
|
4210
|
+
res.setHeader("Content-Type", "application/pdf");
|
|
4211
|
+
res.setHeader(
|
|
4212
|
+
"Content-Disposition",
|
|
4213
|
+
`attachment; filename="CHECKLIST_${formattedDate}.pdf"`
|
|
4214
|
+
);
|
|
4215
|
+
res.setHeader("Content-Length", pdfBuffer.length);
|
|
4216
|
+
res.end(pdfBuffer);
|
|
4217
|
+
return;
|
|
4218
|
+
} catch (error2) {
|
|
4219
|
+
import_node_server_utils20.logger.log({ level: "error", message: error2.message });
|
|
3816
4220
|
next(error2);
|
|
3817
4221
|
return;
|
|
3818
4222
|
}
|
|
@@ -3823,14 +4227,15 @@ function useAreaChecklistController() {
|
|
|
3823
4227
|
getAreaChecklistHistory,
|
|
3824
4228
|
getAreaChecklistHistoryDetails,
|
|
3825
4229
|
getAreaChecklistUnits,
|
|
3826
|
-
updateAreaChecklistUnits
|
|
4230
|
+
updateAreaChecklistUnits,
|
|
4231
|
+
downloadChecklistPdf
|
|
3827
4232
|
};
|
|
3828
4233
|
}
|
|
3829
4234
|
|
|
3830
4235
|
// src/models/hygiene-supply.model.ts
|
|
3831
4236
|
var import_joi10 = __toESM(require("joi"));
|
|
3832
|
-
var
|
|
3833
|
-
var
|
|
4237
|
+
var import_mongodb11 = require("mongodb");
|
|
4238
|
+
var import_node_server_utils21 = require("@7365admin1/node-server-utils");
|
|
3834
4239
|
var supplySchema = import_joi10.default.object({
|
|
3835
4240
|
site: import_joi10.default.string().hex().required(),
|
|
3836
4241
|
name: import_joi10.default.string().required(),
|
|
@@ -3839,14 +4244,14 @@ var supplySchema = import_joi10.default.object({
|
|
|
3839
4244
|
function MSupply(value) {
|
|
3840
4245
|
const { error } = supplySchema.validate(value);
|
|
3841
4246
|
if (error) {
|
|
3842
|
-
|
|
3843
|
-
throw new
|
|
4247
|
+
import_node_server_utils21.logger.info(`Hygiene Supply Model: ${error.message}`);
|
|
4248
|
+
throw new import_node_server_utils21.BadRequestError(error.message);
|
|
3844
4249
|
}
|
|
3845
4250
|
if (value.site) {
|
|
3846
4251
|
try {
|
|
3847
|
-
value.site = new
|
|
4252
|
+
value.site = new import_mongodb11.ObjectId(value.site);
|
|
3848
4253
|
} catch (error2) {
|
|
3849
|
-
throw new
|
|
4254
|
+
throw new import_node_server_utils21.BadRequestError("Invalid site ID format.");
|
|
3850
4255
|
}
|
|
3851
4256
|
}
|
|
3852
4257
|
return {
|
|
@@ -3862,21 +4267,21 @@ function MSupply(value) {
|
|
|
3862
4267
|
}
|
|
3863
4268
|
|
|
3864
4269
|
// src/repositories/hygiene-supply.repository.ts
|
|
3865
|
-
var
|
|
3866
|
-
var
|
|
4270
|
+
var import_mongodb12 = require("mongodb");
|
|
4271
|
+
var import_node_server_utils22 = require("@7365admin1/node-server-utils");
|
|
3867
4272
|
function useSupplyRepository() {
|
|
3868
|
-
const db =
|
|
4273
|
+
const db = import_node_server_utils22.useAtlas.getDb();
|
|
3869
4274
|
if (!db) {
|
|
3870
|
-
throw new
|
|
4275
|
+
throw new import_node_server_utils22.InternalServerError("Unable to connect to server.");
|
|
3871
4276
|
}
|
|
3872
4277
|
const namespace_collection = "site.supplies";
|
|
3873
4278
|
const collection = db.collection(namespace_collection);
|
|
3874
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
4279
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils22.useCache)(namespace_collection);
|
|
3875
4280
|
async function createIndex() {
|
|
3876
4281
|
try {
|
|
3877
4282
|
await collection.createIndexes([{ key: { site: 1 } }]);
|
|
3878
4283
|
} catch (error) {
|
|
3879
|
-
throw new
|
|
4284
|
+
throw new import_node_server_utils22.InternalServerError(
|
|
3880
4285
|
"Failed to create index on hygiene supply."
|
|
3881
4286
|
);
|
|
3882
4287
|
}
|
|
@@ -3885,7 +4290,7 @@ function useSupplyRepository() {
|
|
|
3885
4290
|
try {
|
|
3886
4291
|
await collection.createIndex({ name: "text" });
|
|
3887
4292
|
} catch (error) {
|
|
3888
|
-
throw new
|
|
4293
|
+
throw new import_node_server_utils22.InternalServerError(
|
|
3889
4294
|
"Failed to create text index on hygiene supply."
|
|
3890
4295
|
);
|
|
3891
4296
|
}
|
|
@@ -3897,7 +4302,7 @@ function useSupplyRepository() {
|
|
|
3897
4302
|
{ unique: true }
|
|
3898
4303
|
);
|
|
3899
4304
|
} catch (error) {
|
|
3900
|
-
throw new
|
|
4305
|
+
throw new import_node_server_utils22.InternalServerError(
|
|
3901
4306
|
"Failed to create unique index on hygiene supply."
|
|
3902
4307
|
);
|
|
3903
4308
|
}
|
|
@@ -3907,9 +4312,9 @@ function useSupplyRepository() {
|
|
|
3907
4312
|
value = MSupply(value);
|
|
3908
4313
|
const res = await collection.insertOne(value, { session });
|
|
3909
4314
|
delNamespace().then(() => {
|
|
3910
|
-
|
|
4315
|
+
import_node_server_utils22.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3911
4316
|
}).catch((err) => {
|
|
3912
|
-
|
|
4317
|
+
import_node_server_utils22.logger.error(
|
|
3913
4318
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3914
4319
|
err
|
|
3915
4320
|
);
|
|
@@ -3918,7 +4323,7 @@ function useSupplyRepository() {
|
|
|
3918
4323
|
} catch (error) {
|
|
3919
4324
|
const isDuplicated = error.message.includes("duplicate");
|
|
3920
4325
|
if (isDuplicated) {
|
|
3921
|
-
throw new
|
|
4326
|
+
throw new import_node_server_utils22.BadRequestError("Supply already exists.");
|
|
3922
4327
|
}
|
|
3923
4328
|
throw error;
|
|
3924
4329
|
}
|
|
@@ -3938,20 +4343,20 @@ function useSupplyRepository() {
|
|
|
3938
4343
|
limit
|
|
3939
4344
|
};
|
|
3940
4345
|
try {
|
|
3941
|
-
site = new
|
|
4346
|
+
site = new import_mongodb12.ObjectId(site);
|
|
3942
4347
|
query.site = site;
|
|
3943
4348
|
cacheOptions.site = site.toString();
|
|
3944
4349
|
} catch (error) {
|
|
3945
|
-
throw new
|
|
4350
|
+
throw new import_node_server_utils22.BadRequestError("Invalid site ID format.");
|
|
3946
4351
|
}
|
|
3947
4352
|
if (search) {
|
|
3948
4353
|
query.$text = { $search: search };
|
|
3949
4354
|
cacheOptions.search = search;
|
|
3950
4355
|
}
|
|
3951
|
-
const cacheKey = (0,
|
|
4356
|
+
const cacheKey = (0, import_node_server_utils22.makeCacheKey)(namespace_collection, cacheOptions);
|
|
3952
4357
|
const cachedData = await getCache(cacheKey);
|
|
3953
4358
|
if (cachedData) {
|
|
3954
|
-
|
|
4359
|
+
import_node_server_utils22.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3955
4360
|
return cachedData;
|
|
3956
4361
|
}
|
|
3957
4362
|
try {
|
|
@@ -3969,11 +4374,11 @@ function useSupplyRepository() {
|
|
|
3969
4374
|
{ $limit: limit }
|
|
3970
4375
|
]).toArray();
|
|
3971
4376
|
const length = await collection.countDocuments(query);
|
|
3972
|
-
const data = (0,
|
|
4377
|
+
const data = (0, import_node_server_utils22.paginate)(items, page, limit, length);
|
|
3973
4378
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3974
|
-
|
|
4379
|
+
import_node_server_utils22.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3975
4380
|
}).catch((err) => {
|
|
3976
|
-
|
|
4381
|
+
import_node_server_utils22.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3977
4382
|
});
|
|
3978
4383
|
return data;
|
|
3979
4384
|
} catch (error) {
|
|
@@ -3982,25 +4387,25 @@ function useSupplyRepository() {
|
|
|
3982
4387
|
}
|
|
3983
4388
|
async function getSupplyById(_id, session) {
|
|
3984
4389
|
try {
|
|
3985
|
-
_id = new
|
|
4390
|
+
_id = new import_mongodb12.ObjectId(_id);
|
|
3986
4391
|
} catch (error) {
|
|
3987
|
-
throw new
|
|
4392
|
+
throw new import_node_server_utils22.BadRequestError("Invalid supply ID format.");
|
|
3988
4393
|
}
|
|
3989
4394
|
const query = {
|
|
3990
4395
|
_id,
|
|
3991
4396
|
status: { $ne: "deleted" }
|
|
3992
4397
|
};
|
|
3993
|
-
const cacheKey = (0,
|
|
4398
|
+
const cacheKey = (0, import_node_server_utils22.makeCacheKey)(namespace_collection, {
|
|
3994
4399
|
_id: _id.toString()
|
|
3995
4400
|
});
|
|
3996
4401
|
if (!session) {
|
|
3997
4402
|
const cachedData = await getCache(cacheKey);
|
|
3998
4403
|
if (cachedData) {
|
|
3999
|
-
|
|
4404
|
+
import_node_server_utils22.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4000
4405
|
return cachedData;
|
|
4001
4406
|
}
|
|
4002
4407
|
} else {
|
|
4003
|
-
|
|
4408
|
+
import_node_server_utils22.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
4004
4409
|
}
|
|
4005
4410
|
try {
|
|
4006
4411
|
const data = await collection.aggregate([
|
|
@@ -4014,12 +4419,12 @@ function useSupplyRepository() {
|
|
|
4014
4419
|
}
|
|
4015
4420
|
]).toArray();
|
|
4016
4421
|
if (!data || data.length === 0) {
|
|
4017
|
-
throw new
|
|
4422
|
+
throw new import_node_server_utils22.NotFoundError("Supply not found.");
|
|
4018
4423
|
}
|
|
4019
4424
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
4020
|
-
|
|
4425
|
+
import_node_server_utils22.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4021
4426
|
}).catch((err) => {
|
|
4022
|
-
|
|
4427
|
+
import_node_server_utils22.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4023
4428
|
});
|
|
4024
4429
|
return data[0];
|
|
4025
4430
|
} catch (error) {
|
|
@@ -4028,9 +4433,9 @@ function useSupplyRepository() {
|
|
|
4028
4433
|
}
|
|
4029
4434
|
async function updateSupply(_id, value, session) {
|
|
4030
4435
|
try {
|
|
4031
|
-
_id = new
|
|
4436
|
+
_id = new import_mongodb12.ObjectId(_id);
|
|
4032
4437
|
} catch (error) {
|
|
4033
|
-
throw new
|
|
4438
|
+
throw new import_node_server_utils22.BadRequestError("Invalid supply ID format.");
|
|
4034
4439
|
}
|
|
4035
4440
|
try {
|
|
4036
4441
|
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
@@ -4040,12 +4445,12 @@ function useSupplyRepository() {
|
|
|
4040
4445
|
{ session }
|
|
4041
4446
|
);
|
|
4042
4447
|
if (res.modifiedCount === 0) {
|
|
4043
|
-
throw new
|
|
4448
|
+
throw new import_node_server_utils22.InternalServerError("Unable to update cleaning supply.");
|
|
4044
4449
|
}
|
|
4045
4450
|
delNamespace().then(() => {
|
|
4046
|
-
|
|
4451
|
+
import_node_server_utils22.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4047
4452
|
}).catch((err) => {
|
|
4048
|
-
|
|
4453
|
+
import_node_server_utils22.logger.error(
|
|
4049
4454
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4050
4455
|
err
|
|
4051
4456
|
);
|
|
@@ -4054,16 +4459,16 @@ function useSupplyRepository() {
|
|
|
4054
4459
|
} catch (error) {
|
|
4055
4460
|
const isDuplicated = error.message.includes("duplicate");
|
|
4056
4461
|
if (isDuplicated) {
|
|
4057
|
-
throw new
|
|
4462
|
+
throw new import_node_server_utils22.BadRequestError("Supply already exists.");
|
|
4058
4463
|
}
|
|
4059
4464
|
throw error;
|
|
4060
4465
|
}
|
|
4061
4466
|
}
|
|
4062
4467
|
async function deleteSupply(_id, session) {
|
|
4063
4468
|
try {
|
|
4064
|
-
_id = new
|
|
4469
|
+
_id = new import_mongodb12.ObjectId(_id);
|
|
4065
4470
|
} catch (error) {
|
|
4066
|
-
throw new
|
|
4471
|
+
throw new import_node_server_utils22.BadRequestError("Invalid supply ID format.");
|
|
4067
4472
|
}
|
|
4068
4473
|
try {
|
|
4069
4474
|
const updateValue = {
|
|
@@ -4077,12 +4482,12 @@ function useSupplyRepository() {
|
|
|
4077
4482
|
{ session }
|
|
4078
4483
|
);
|
|
4079
4484
|
if (res.modifiedCount === 0) {
|
|
4080
|
-
throw new
|
|
4485
|
+
throw new import_node_server_utils22.InternalServerError("Unable to delete supply.");
|
|
4081
4486
|
}
|
|
4082
4487
|
delNamespace().then(() => {
|
|
4083
|
-
|
|
4488
|
+
import_node_server_utils22.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4084
4489
|
}).catch((err) => {
|
|
4085
|
-
|
|
4490
|
+
import_node_server_utils22.logger.error(
|
|
4086
4491
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4087
4492
|
err
|
|
4088
4493
|
);
|
|
@@ -4106,7 +4511,7 @@ function useSupplyRepository() {
|
|
|
4106
4511
|
|
|
4107
4512
|
// src/controllers/hygiene-supply.controller.ts
|
|
4108
4513
|
var import_joi11 = __toESM(require("joi"));
|
|
4109
|
-
var
|
|
4514
|
+
var import_node_server_utils23 = require("@7365admin1/node-server-utils");
|
|
4110
4515
|
function useSupplyController() {
|
|
4111
4516
|
const {
|
|
4112
4517
|
createSupply: _createSupply,
|
|
@@ -4119,8 +4524,8 @@ function useSupplyController() {
|
|
|
4119
4524
|
const payload = { ...req.body, ...req.params };
|
|
4120
4525
|
const { error } = supplySchema.validate(payload);
|
|
4121
4526
|
if (error) {
|
|
4122
|
-
|
|
4123
|
-
next(new
|
|
4527
|
+
import_node_server_utils23.logger.log({ level: "error", message: error.message });
|
|
4528
|
+
next(new import_node_server_utils23.BadRequestError(error.message));
|
|
4124
4529
|
return;
|
|
4125
4530
|
}
|
|
4126
4531
|
try {
|
|
@@ -4128,7 +4533,7 @@ function useSupplyController() {
|
|
|
4128
4533
|
res.status(201).json({ message: "Supply created successfully.", id });
|
|
4129
4534
|
return;
|
|
4130
4535
|
} catch (error2) {
|
|
4131
|
-
|
|
4536
|
+
import_node_server_utils23.logger.log({ level: "error", message: error2.message });
|
|
4132
4537
|
next(error2);
|
|
4133
4538
|
return;
|
|
4134
4539
|
}
|
|
@@ -4143,8 +4548,8 @@ function useSupplyController() {
|
|
|
4143
4548
|
});
|
|
4144
4549
|
const { error } = validation.validate(query);
|
|
4145
4550
|
if (error) {
|
|
4146
|
-
|
|
4147
|
-
next(new
|
|
4551
|
+
import_node_server_utils23.logger.log({ level: "error", message: error.message });
|
|
4552
|
+
next(new import_node_server_utils23.BadRequestError(error.message));
|
|
4148
4553
|
return;
|
|
4149
4554
|
}
|
|
4150
4555
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -4161,7 +4566,7 @@ function useSupplyController() {
|
|
|
4161
4566
|
res.json(data);
|
|
4162
4567
|
return;
|
|
4163
4568
|
} catch (error2) {
|
|
4164
|
-
|
|
4569
|
+
import_node_server_utils23.logger.log({ level: "error", message: error2.message });
|
|
4165
4570
|
next(error2);
|
|
4166
4571
|
return;
|
|
4167
4572
|
}
|
|
@@ -4171,8 +4576,8 @@ function useSupplyController() {
|
|
|
4171
4576
|
const _id = req.params.id;
|
|
4172
4577
|
const { error, value } = validation.validate(_id);
|
|
4173
4578
|
if (error) {
|
|
4174
|
-
|
|
4175
|
-
next(new
|
|
4579
|
+
import_node_server_utils23.logger.log({ level: "error", message: error.message });
|
|
4580
|
+
next(new import_node_server_utils23.BadRequestError(error.message));
|
|
4176
4581
|
return;
|
|
4177
4582
|
}
|
|
4178
4583
|
try {
|
|
@@ -4180,7 +4585,7 @@ function useSupplyController() {
|
|
|
4180
4585
|
res.json(data);
|
|
4181
4586
|
return;
|
|
4182
4587
|
} catch (error2) {
|
|
4183
|
-
|
|
4588
|
+
import_node_server_utils23.logger.log({ level: "error", message: error2.message });
|
|
4184
4589
|
next(error2);
|
|
4185
4590
|
return;
|
|
4186
4591
|
}
|
|
@@ -4195,8 +4600,8 @@ function useSupplyController() {
|
|
|
4195
4600
|
});
|
|
4196
4601
|
const { error } = validation.validate(payload);
|
|
4197
4602
|
if (error) {
|
|
4198
|
-
|
|
4199
|
-
next(new
|
|
4603
|
+
import_node_server_utils23.logger.log({ level: "error", message: error.message });
|
|
4604
|
+
next(new import_node_server_utils23.BadRequestError(error.message));
|
|
4200
4605
|
return;
|
|
4201
4606
|
}
|
|
4202
4607
|
try {
|
|
@@ -4205,7 +4610,7 @@ function useSupplyController() {
|
|
|
4205
4610
|
res.json({ message: "Supply updated successfully." });
|
|
4206
4611
|
return;
|
|
4207
4612
|
} catch (error2) {
|
|
4208
|
-
|
|
4613
|
+
import_node_server_utils23.logger.log({ level: "error", message: error2.message });
|
|
4209
4614
|
next(error2);
|
|
4210
4615
|
return;
|
|
4211
4616
|
}
|
|
@@ -4217,8 +4622,8 @@ function useSupplyController() {
|
|
|
4217
4622
|
});
|
|
4218
4623
|
const { error, value } = validation.validate({ id });
|
|
4219
4624
|
if (error) {
|
|
4220
|
-
|
|
4221
|
-
next(new
|
|
4625
|
+
import_node_server_utils23.logger.log({ level: "error", message: error.message });
|
|
4626
|
+
next(new import_node_server_utils23.BadRequestError(error.message));
|
|
4222
4627
|
return;
|
|
4223
4628
|
}
|
|
4224
4629
|
try {
|
|
@@ -4226,7 +4631,7 @@ function useSupplyController() {
|
|
|
4226
4631
|
res.json({ message: "Supply deleted successfully." });
|
|
4227
4632
|
return;
|
|
4228
4633
|
} catch (error2) {
|
|
4229
|
-
|
|
4634
|
+
import_node_server_utils23.logger.log({ level: "error", message: error2.message });
|
|
4230
4635
|
next(error2);
|
|
4231
4636
|
return;
|
|
4232
4637
|
}
|
|
@@ -4242,8 +4647,8 @@ function useSupplyController() {
|
|
|
4242
4647
|
|
|
4243
4648
|
// src/models/hygiene-stock.model.ts
|
|
4244
4649
|
var import_joi12 = __toESM(require("joi"));
|
|
4245
|
-
var
|
|
4246
|
-
var
|
|
4650
|
+
var import_mongodb13 = require("mongodb");
|
|
4651
|
+
var import_node_server_utils24 = require("@7365admin1/node-server-utils");
|
|
4247
4652
|
var stockSchema = import_joi12.default.object({
|
|
4248
4653
|
site: import_joi12.default.string().hex().required(),
|
|
4249
4654
|
supply: import_joi12.default.string().hex().required(),
|
|
@@ -4255,21 +4660,21 @@ var stockSchema = import_joi12.default.object({
|
|
|
4255
4660
|
function MStock(value) {
|
|
4256
4661
|
const { error } = stockSchema.validate(value);
|
|
4257
4662
|
if (error) {
|
|
4258
|
-
|
|
4259
|
-
throw new
|
|
4663
|
+
import_node_server_utils24.logger.info(`Hygiene Stock Model: ${error.message}`);
|
|
4664
|
+
throw new import_node_server_utils24.BadRequestError(error.message);
|
|
4260
4665
|
}
|
|
4261
4666
|
if (value.site) {
|
|
4262
4667
|
try {
|
|
4263
|
-
value.site = new
|
|
4668
|
+
value.site = new import_mongodb13.ObjectId(value.site);
|
|
4264
4669
|
} catch (error2) {
|
|
4265
|
-
throw new
|
|
4670
|
+
throw new import_node_server_utils24.BadRequestError("Invalid site ID format.");
|
|
4266
4671
|
}
|
|
4267
4672
|
}
|
|
4268
4673
|
if (value.supply) {
|
|
4269
4674
|
try {
|
|
4270
|
-
value.supply = new
|
|
4675
|
+
value.supply = new import_mongodb13.ObjectId(value.supply);
|
|
4271
4676
|
} catch (error2) {
|
|
4272
|
-
throw new
|
|
4677
|
+
throw new import_node_server_utils24.BadRequestError("Invalid supply ID format.");
|
|
4273
4678
|
}
|
|
4274
4679
|
}
|
|
4275
4680
|
return {
|
|
@@ -4287,18 +4692,18 @@ function MStock(value) {
|
|
|
4287
4692
|
}
|
|
4288
4693
|
|
|
4289
4694
|
// src/repositories/hygiene-stock.repository.ts
|
|
4290
|
-
var
|
|
4291
|
-
var
|
|
4695
|
+
var import_mongodb14 = require("mongodb");
|
|
4696
|
+
var import_node_server_utils25 = require("@7365admin1/node-server-utils");
|
|
4292
4697
|
function useStockRepository() {
|
|
4293
|
-
const db =
|
|
4698
|
+
const db = import_node_server_utils25.useAtlas.getDb();
|
|
4294
4699
|
if (!db) {
|
|
4295
|
-
throw new
|
|
4700
|
+
throw new import_node_server_utils25.InternalServerError("Unable to connect to server.");
|
|
4296
4701
|
}
|
|
4297
4702
|
const namespace_collection = "site.supply.stocks";
|
|
4298
4703
|
const supply_collection = "site.supplies";
|
|
4299
4704
|
const collection = db.collection(namespace_collection);
|
|
4300
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
4301
|
-
const { delNamespace: delSupplyNamespace } = (0,
|
|
4705
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils25.useCache)(namespace_collection);
|
|
4706
|
+
const { delNamespace: delSupplyNamespace } = (0, import_node_server_utils25.useCache)(supply_collection);
|
|
4302
4707
|
async function createIndex() {
|
|
4303
4708
|
try {
|
|
4304
4709
|
await collection.createIndexes([
|
|
@@ -4308,7 +4713,7 @@ function useStockRepository() {
|
|
|
4308
4713
|
{ key: { status: 1 } }
|
|
4309
4714
|
]);
|
|
4310
4715
|
} catch (error) {
|
|
4311
|
-
throw new
|
|
4716
|
+
throw new import_node_server_utils25.InternalServerError("Failed to create index on hygiene stock.");
|
|
4312
4717
|
}
|
|
4313
4718
|
}
|
|
4314
4719
|
async function createStock(value, session) {
|
|
@@ -4316,17 +4721,17 @@ function useStockRepository() {
|
|
|
4316
4721
|
value = MStock(value);
|
|
4317
4722
|
const res = await collection.insertOne(value, { session });
|
|
4318
4723
|
delNamespace().then(() => {
|
|
4319
|
-
|
|
4724
|
+
import_node_server_utils25.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4320
4725
|
}).catch((err) => {
|
|
4321
|
-
|
|
4726
|
+
import_node_server_utils25.logger.error(
|
|
4322
4727
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4323
4728
|
err
|
|
4324
4729
|
);
|
|
4325
4730
|
});
|
|
4326
4731
|
delSupplyNamespace().then(() => {
|
|
4327
|
-
|
|
4732
|
+
import_node_server_utils25.logger.info(`Cache cleared for namespace: ${supply_collection}`);
|
|
4328
4733
|
}).catch((err) => {
|
|
4329
|
-
|
|
4734
|
+
import_node_server_utils25.logger.error(
|
|
4330
4735
|
`Failed to clear cache for namespace: ${supply_collection}`,
|
|
4331
4736
|
err
|
|
4332
4737
|
);
|
|
@@ -4352,27 +4757,27 @@ function useStockRepository() {
|
|
|
4352
4757
|
limit
|
|
4353
4758
|
};
|
|
4354
4759
|
try {
|
|
4355
|
-
site = new
|
|
4760
|
+
site = new import_mongodb14.ObjectId(site);
|
|
4356
4761
|
query.site = site;
|
|
4357
4762
|
cacheOptions.site = site.toString();
|
|
4358
4763
|
} catch (error) {
|
|
4359
|
-
throw new
|
|
4764
|
+
throw new import_node_server_utils25.BadRequestError("Invalid site ID format.");
|
|
4360
4765
|
}
|
|
4361
4766
|
try {
|
|
4362
|
-
supply = new
|
|
4767
|
+
supply = new import_mongodb14.ObjectId(supply);
|
|
4363
4768
|
query.supply = supply;
|
|
4364
4769
|
cacheOptions.supply = supply.toString();
|
|
4365
4770
|
} catch (error) {
|
|
4366
|
-
throw new
|
|
4771
|
+
throw new import_node_server_utils25.BadRequestError("Invalid supply ID format.");
|
|
4367
4772
|
}
|
|
4368
4773
|
if (search) {
|
|
4369
4774
|
query.$text = { $search: search };
|
|
4370
4775
|
cacheOptions.search = search;
|
|
4371
4776
|
}
|
|
4372
|
-
const cacheKey = (0,
|
|
4777
|
+
const cacheKey = (0, import_node_server_utils25.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4373
4778
|
const cachedData = await getCache(cacheKey);
|
|
4374
4779
|
if (cachedData) {
|
|
4375
|
-
|
|
4780
|
+
import_node_server_utils25.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4376
4781
|
return cachedData;
|
|
4377
4782
|
}
|
|
4378
4783
|
try {
|
|
@@ -4391,11 +4796,11 @@ function useStockRepository() {
|
|
|
4391
4796
|
{ $limit: limit }
|
|
4392
4797
|
]).toArray();
|
|
4393
4798
|
const length = await collection.countDocuments(query);
|
|
4394
|
-
const data = (0,
|
|
4799
|
+
const data = (0, import_node_server_utils25.paginate)(items, page, limit, length);
|
|
4395
4800
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4396
|
-
|
|
4801
|
+
import_node_server_utils25.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4397
4802
|
}).catch((err) => {
|
|
4398
|
-
|
|
4803
|
+
import_node_server_utils25.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4399
4804
|
});
|
|
4400
4805
|
return data;
|
|
4401
4806
|
} catch (error) {
|
|
@@ -4410,14 +4815,14 @@ function useStockRepository() {
|
|
|
4410
4815
|
}
|
|
4411
4816
|
|
|
4412
4817
|
// src/services/hygiene-stock.service.ts
|
|
4413
|
-
var
|
|
4818
|
+
var import_node_server_utils26 = require("@7365admin1/node-server-utils");
|
|
4414
4819
|
function useStockService() {
|
|
4415
4820
|
const { createStock: _createStock } = useStockRepository();
|
|
4416
4821
|
const { getSupplyById, updateSupply } = useSupplyRepository();
|
|
4417
4822
|
async function createStock(value, out = false, session) {
|
|
4418
4823
|
let ownSession = false;
|
|
4419
4824
|
if (!session) {
|
|
4420
|
-
session =
|
|
4825
|
+
session = import_node_server_utils26.useAtlas.getClient()?.startSession();
|
|
4421
4826
|
ownSession = true;
|
|
4422
4827
|
}
|
|
4423
4828
|
try {
|
|
@@ -4426,11 +4831,11 @@ function useStockService() {
|
|
|
4426
4831
|
const { qty, ...stockData } = value;
|
|
4427
4832
|
const supply = await getSupplyById(value.supply, session);
|
|
4428
4833
|
if (!supply || supply.qty === void 0) {
|
|
4429
|
-
throw new
|
|
4834
|
+
throw new import_node_server_utils26.NotFoundError("Supply not found.");
|
|
4430
4835
|
}
|
|
4431
4836
|
const newSupplyQty = out ? supply.qty - qty : supply.qty + qty;
|
|
4432
4837
|
if (out && newSupplyQty < 0) {
|
|
4433
|
-
throw new
|
|
4838
|
+
throw new import_node_server_utils26.BadRequestError(
|
|
4434
4839
|
`Insufficient stock. Available: ${supply.qty}, Requested: ${qty}`
|
|
4435
4840
|
);
|
|
4436
4841
|
}
|
|
@@ -4461,7 +4866,7 @@ function useStockService() {
|
|
|
4461
4866
|
|
|
4462
4867
|
// src/controllers/hygiene-stock.controller.ts
|
|
4463
4868
|
var import_joi13 = __toESM(require("joi"));
|
|
4464
|
-
var
|
|
4869
|
+
var import_node_server_utils27 = require("@7365admin1/node-server-utils");
|
|
4465
4870
|
function useStockController() {
|
|
4466
4871
|
const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
|
|
4467
4872
|
const { createStock: _createStock } = useStockService();
|
|
@@ -4475,8 +4880,8 @@ function useStockController() {
|
|
|
4475
4880
|
});
|
|
4476
4881
|
const { error } = validation.validate(payload);
|
|
4477
4882
|
if (error) {
|
|
4478
|
-
|
|
4479
|
-
next(new
|
|
4883
|
+
import_node_server_utils27.logger.log({ level: "error", message: error.message });
|
|
4884
|
+
next(new import_node_server_utils27.BadRequestError(error.message));
|
|
4480
4885
|
return;
|
|
4481
4886
|
}
|
|
4482
4887
|
try {
|
|
@@ -4484,7 +4889,7 @@ function useStockController() {
|
|
|
4484
4889
|
res.status(201).json({ message: "Stock created successfully.", id });
|
|
4485
4890
|
return;
|
|
4486
4891
|
} catch (error2) {
|
|
4487
|
-
|
|
4892
|
+
import_node_server_utils27.logger.log({ level: "error", message: error2.message });
|
|
4488
4893
|
next(error2);
|
|
4489
4894
|
return;
|
|
4490
4895
|
}
|
|
@@ -4500,8 +4905,8 @@ function useStockController() {
|
|
|
4500
4905
|
});
|
|
4501
4906
|
const { error } = validation.validate(query);
|
|
4502
4907
|
if (error) {
|
|
4503
|
-
|
|
4504
|
-
next(new
|
|
4908
|
+
import_node_server_utils27.logger.log({ level: "error", message: error.message });
|
|
4909
|
+
next(new import_node_server_utils27.BadRequestError(error.message));
|
|
4505
4910
|
return;
|
|
4506
4911
|
}
|
|
4507
4912
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -4520,7 +4925,7 @@ function useStockController() {
|
|
|
4520
4925
|
res.json(data);
|
|
4521
4926
|
return;
|
|
4522
4927
|
} catch (error2) {
|
|
4523
|
-
|
|
4928
|
+
import_node_server_utils27.logger.log({ level: "error", message: error2.message });
|
|
4524
4929
|
next(error2);
|
|
4525
4930
|
return;
|
|
4526
4931
|
}
|
|
@@ -4533,8 +4938,8 @@ function useStockController() {
|
|
|
4533
4938
|
|
|
4534
4939
|
// src/models/hygiene-checkout-item.model.ts
|
|
4535
4940
|
var import_joi14 = __toESM(require("joi"));
|
|
4536
|
-
var
|
|
4537
|
-
var
|
|
4941
|
+
var import_mongodb15 = require("mongodb");
|
|
4942
|
+
var import_node_server_utils28 = require("@7365admin1/node-server-utils");
|
|
4538
4943
|
var allowedCheckOutItemStatus = ["pending", "completed"];
|
|
4539
4944
|
var checkOutItemSchema = import_joi14.default.object({
|
|
4540
4945
|
site: import_joi14.default.string().hex().required(),
|
|
@@ -4548,21 +4953,21 @@ var checkOutItemSchema = import_joi14.default.object({
|
|
|
4548
4953
|
function MCheckOutItem(value) {
|
|
4549
4954
|
const { error } = checkOutItemSchema.validate(value);
|
|
4550
4955
|
if (error) {
|
|
4551
|
-
|
|
4552
|
-
throw new
|
|
4956
|
+
import_node_server_utils28.logger.info(`Hygiene Check Out Item Model: ${error.message}`);
|
|
4957
|
+
throw new import_node_server_utils28.BadRequestError(error.message);
|
|
4553
4958
|
}
|
|
4554
4959
|
if (value.site) {
|
|
4555
4960
|
try {
|
|
4556
|
-
value.site = new
|
|
4961
|
+
value.site = new import_mongodb15.ObjectId(value.site);
|
|
4557
4962
|
} catch (error2) {
|
|
4558
|
-
throw new
|
|
4963
|
+
throw new import_node_server_utils28.BadRequestError("Invalid site ID format.");
|
|
4559
4964
|
}
|
|
4560
4965
|
}
|
|
4561
4966
|
if (value.supply) {
|
|
4562
4967
|
try {
|
|
4563
|
-
value.supply = new
|
|
4968
|
+
value.supply = new import_mongodb15.ObjectId(value.supply);
|
|
4564
4969
|
} catch (error2) {
|
|
4565
|
-
throw new
|
|
4970
|
+
throw new import_node_server_utils28.BadRequestError("Invalid supply ID format.");
|
|
4566
4971
|
}
|
|
4567
4972
|
}
|
|
4568
4973
|
return {
|
|
@@ -4581,16 +4986,16 @@ function MCheckOutItem(value) {
|
|
|
4581
4986
|
}
|
|
4582
4987
|
|
|
4583
4988
|
// src/repositories/hygiene-checkout-item.repository.ts
|
|
4584
|
-
var
|
|
4585
|
-
var
|
|
4989
|
+
var import_mongodb16 = require("mongodb");
|
|
4990
|
+
var import_node_server_utils29 = require("@7365admin1/node-server-utils");
|
|
4586
4991
|
function useCheckOutItemRepository() {
|
|
4587
|
-
const db =
|
|
4992
|
+
const db = import_node_server_utils29.useAtlas.getDb();
|
|
4588
4993
|
if (!db) {
|
|
4589
|
-
throw new
|
|
4994
|
+
throw new import_node_server_utils29.InternalServerError("Unable to connect to server.");
|
|
4590
4995
|
}
|
|
4591
4996
|
const namespace_collection = "site.supply.checkouts";
|
|
4592
4997
|
const collection = db.collection(namespace_collection);
|
|
4593
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
4998
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils29.useCache)(namespace_collection);
|
|
4594
4999
|
async function createIndex() {
|
|
4595
5000
|
try {
|
|
4596
5001
|
await collection.createIndexes([
|
|
@@ -4599,7 +5004,7 @@ function useCheckOutItemRepository() {
|
|
|
4599
5004
|
{ key: { status: 1 } }
|
|
4600
5005
|
]);
|
|
4601
5006
|
} catch (error) {
|
|
4602
|
-
throw new
|
|
5007
|
+
throw new import_node_server_utils29.InternalServerError(
|
|
4603
5008
|
"Failed to create index on hygiene check out item."
|
|
4604
5009
|
);
|
|
4605
5010
|
}
|
|
@@ -4608,7 +5013,7 @@ function useCheckOutItemRepository() {
|
|
|
4608
5013
|
try {
|
|
4609
5014
|
await collection.createIndex({ supplyName: "text" });
|
|
4610
5015
|
} catch (error) {
|
|
4611
|
-
throw new
|
|
5016
|
+
throw new import_node_server_utils29.InternalServerError(
|
|
4612
5017
|
"Failed to create text index on hygiene supply."
|
|
4613
5018
|
);
|
|
4614
5019
|
}
|
|
@@ -4618,9 +5023,9 @@ function useCheckOutItemRepository() {
|
|
|
4618
5023
|
value = MCheckOutItem(value);
|
|
4619
5024
|
const res = await collection.insertOne(value, { session });
|
|
4620
5025
|
delNamespace().then(() => {
|
|
4621
|
-
|
|
5026
|
+
import_node_server_utils29.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4622
5027
|
}).catch((err) => {
|
|
4623
|
-
|
|
5028
|
+
import_node_server_utils29.logger.error(
|
|
4624
5029
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4625
5030
|
err
|
|
4626
5031
|
);
|
|
@@ -4645,20 +5050,20 @@ function useCheckOutItemRepository() {
|
|
|
4645
5050
|
limit
|
|
4646
5051
|
};
|
|
4647
5052
|
try {
|
|
4648
|
-
site = new
|
|
5053
|
+
site = new import_mongodb16.ObjectId(site);
|
|
4649
5054
|
query.site = site;
|
|
4650
5055
|
cacheOptions.site = site.toString();
|
|
4651
5056
|
} catch (error) {
|
|
4652
|
-
throw new
|
|
5057
|
+
throw new import_node_server_utils29.BadRequestError("Invalid site ID format.");
|
|
4653
5058
|
}
|
|
4654
5059
|
if (search) {
|
|
4655
5060
|
query.$text = { $search: search };
|
|
4656
5061
|
cacheOptions.search = search;
|
|
4657
5062
|
}
|
|
4658
|
-
const cacheKey = (0,
|
|
5063
|
+
const cacheKey = (0, import_node_server_utils29.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4659
5064
|
const cachedData = await getCache(cacheKey);
|
|
4660
5065
|
if (cachedData) {
|
|
4661
|
-
|
|
5066
|
+
import_node_server_utils29.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4662
5067
|
return cachedData;
|
|
4663
5068
|
}
|
|
4664
5069
|
try {
|
|
@@ -4705,11 +5110,11 @@ function useCheckOutItemRepository() {
|
|
|
4705
5110
|
{ $limit: limit }
|
|
4706
5111
|
]).toArray();
|
|
4707
5112
|
const length = await collection.countDocuments(query);
|
|
4708
|
-
const data = (0,
|
|
5113
|
+
const data = (0, import_node_server_utils29.paginate)(items, page, limit, length);
|
|
4709
5114
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4710
|
-
|
|
5115
|
+
import_node_server_utils29.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4711
5116
|
}).catch((err) => {
|
|
4712
|
-
|
|
5117
|
+
import_node_server_utils29.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4713
5118
|
});
|
|
4714
5119
|
return data;
|
|
4715
5120
|
} catch (error) {
|
|
@@ -4718,22 +5123,22 @@ function useCheckOutItemRepository() {
|
|
|
4718
5123
|
}
|
|
4719
5124
|
async function getCheckOutItemById(_id, session) {
|
|
4720
5125
|
try {
|
|
4721
|
-
_id = new
|
|
5126
|
+
_id = new import_mongodb16.ObjectId(_id);
|
|
4722
5127
|
} catch (error) {
|
|
4723
|
-
throw new
|
|
5128
|
+
throw new import_node_server_utils29.BadRequestError("Invalid check out item ID format.");
|
|
4724
5129
|
}
|
|
4725
5130
|
const query = { _id };
|
|
4726
|
-
const cacheKey = (0,
|
|
5131
|
+
const cacheKey = (0, import_node_server_utils29.makeCacheKey)(namespace_collection, {
|
|
4727
5132
|
_id: _id.toString()
|
|
4728
5133
|
});
|
|
4729
5134
|
if (!session) {
|
|
4730
5135
|
const cachedData = await getCache(cacheKey);
|
|
4731
5136
|
if (cachedData) {
|
|
4732
|
-
|
|
5137
|
+
import_node_server_utils29.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4733
5138
|
return cachedData;
|
|
4734
5139
|
}
|
|
4735
5140
|
} else {
|
|
4736
|
-
|
|
5141
|
+
import_node_server_utils29.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
4737
5142
|
}
|
|
4738
5143
|
try {
|
|
4739
5144
|
const data = await collection.aggregate(
|
|
@@ -4768,12 +5173,12 @@ function useCheckOutItemRepository() {
|
|
|
4768
5173
|
session ? { session } : void 0
|
|
4769
5174
|
).toArray();
|
|
4770
5175
|
if (!data || data.length === 0) {
|
|
4771
|
-
throw new
|
|
5176
|
+
throw new import_node_server_utils29.NotFoundError("Check out item not found.");
|
|
4772
5177
|
}
|
|
4773
5178
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
4774
|
-
|
|
5179
|
+
import_node_server_utils29.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4775
5180
|
}).catch((err) => {
|
|
4776
|
-
|
|
5181
|
+
import_node_server_utils29.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4777
5182
|
});
|
|
4778
5183
|
return data[0];
|
|
4779
5184
|
} catch (error) {
|
|
@@ -4782,9 +5187,9 @@ function useCheckOutItemRepository() {
|
|
|
4782
5187
|
}
|
|
4783
5188
|
async function completeCheckOutItem(_id, session) {
|
|
4784
5189
|
try {
|
|
4785
|
-
_id = new
|
|
5190
|
+
_id = new import_mongodb16.ObjectId(_id);
|
|
4786
5191
|
} catch (error) {
|
|
4787
|
-
throw new
|
|
5192
|
+
throw new import_node_server_utils29.BadRequestError("Invalid check out item ID format.");
|
|
4788
5193
|
}
|
|
4789
5194
|
try {
|
|
4790
5195
|
const updateValue = {
|
|
@@ -4797,12 +5202,12 @@ function useCheckOutItemRepository() {
|
|
|
4797
5202
|
{ session }
|
|
4798
5203
|
);
|
|
4799
5204
|
if (res.modifiedCount === 0) {
|
|
4800
|
-
throw new
|
|
5205
|
+
throw new import_node_server_utils29.InternalServerError("Unable to complete check out item.");
|
|
4801
5206
|
}
|
|
4802
5207
|
delNamespace().then(() => {
|
|
4803
|
-
|
|
5208
|
+
import_node_server_utils29.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4804
5209
|
}).catch((err) => {
|
|
4805
|
-
|
|
5210
|
+
import_node_server_utils29.logger.error(
|
|
4806
5211
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4807
5212
|
err
|
|
4808
5213
|
);
|
|
@@ -4824,7 +5229,7 @@ function useCheckOutItemRepository() {
|
|
|
4824
5229
|
|
|
4825
5230
|
// src/services/hygiene-checkout-item.service.ts
|
|
4826
5231
|
var import_core = require("@7365admin1/core");
|
|
4827
|
-
var
|
|
5232
|
+
var import_node_server_utils30 = require("@7365admin1/node-server-utils");
|
|
4828
5233
|
function useCheckOutItemService() {
|
|
4829
5234
|
const {
|
|
4830
5235
|
createCheckOutItem: _createCheckOutItem,
|
|
@@ -4835,7 +5240,7 @@ function useCheckOutItemService() {
|
|
|
4835
5240
|
const { getUserById } = (0, import_core.useUserRepo)();
|
|
4836
5241
|
const { createStock } = useStockService();
|
|
4837
5242
|
async function createCheckOutItem(value) {
|
|
4838
|
-
const session =
|
|
5243
|
+
const session = import_node_server_utils30.useAtlas.getClient()?.startSession();
|
|
4839
5244
|
try {
|
|
4840
5245
|
session?.startTransaction();
|
|
4841
5246
|
const supplyData = await getSupplyById(value.supply);
|
|
@@ -4853,7 +5258,7 @@ function useCheckOutItemService() {
|
|
|
4853
5258
|
session
|
|
4854
5259
|
);
|
|
4855
5260
|
if (!checkOutItem) {
|
|
4856
|
-
throw new
|
|
5261
|
+
throw new import_node_server_utils30.BadRequestError("Failed to create check out item.");
|
|
4857
5262
|
}
|
|
4858
5263
|
const createdStocks = await createStock(
|
|
4859
5264
|
{
|
|
@@ -4875,10 +5280,10 @@ function useCheckOutItemService() {
|
|
|
4875
5280
|
}
|
|
4876
5281
|
}
|
|
4877
5282
|
async function createCheckOutItemByBatch(value) {
|
|
4878
|
-
const session =
|
|
5283
|
+
const session = import_node_server_utils30.useAtlas.getClient()?.startSession();
|
|
4879
5284
|
try {
|
|
4880
5285
|
session?.startTransaction();
|
|
4881
|
-
const { site,
|
|
5286
|
+
const { site, createdBy, items } = value;
|
|
4882
5287
|
const createdByData = await getUserById(createdBy);
|
|
4883
5288
|
const createdCheckOutItemIds = [];
|
|
4884
5289
|
for (const item of items) {
|
|
@@ -4889,7 +5294,7 @@ function useCheckOutItemService() {
|
|
|
4889
5294
|
supply: item.supply,
|
|
4890
5295
|
supplyName: supplyData?.name || "",
|
|
4891
5296
|
qty: item.qty,
|
|
4892
|
-
attachment,
|
|
5297
|
+
attachment: item.attachment,
|
|
4893
5298
|
createdBy,
|
|
4894
5299
|
createdByName: createdByData?.name || ""
|
|
4895
5300
|
},
|
|
@@ -4923,7 +5328,7 @@ function useCheckOutItemService() {
|
|
|
4923
5328
|
|
|
4924
5329
|
// src/controllers/hygiene-checkout-item.controller.ts
|
|
4925
5330
|
var import_joi15 = __toESM(require("joi"));
|
|
4926
|
-
var
|
|
5331
|
+
var import_node_server_utils31 = require("@7365admin1/node-server-utils");
|
|
4927
5332
|
function useCheckOutItemController() {
|
|
4928
5333
|
const {
|
|
4929
5334
|
getCheckOutItems: _getCheckOutItems,
|
|
@@ -4953,8 +5358,8 @@ function useCheckOutItemController() {
|
|
|
4953
5358
|
});
|
|
4954
5359
|
const { error } = validation.validate(payload);
|
|
4955
5360
|
if (error) {
|
|
4956
|
-
|
|
4957
|
-
next(new
|
|
5361
|
+
import_node_server_utils31.logger.log({ level: "error", message: error.message });
|
|
5362
|
+
next(new import_node_server_utils31.BadRequestError(error.message));
|
|
4958
5363
|
return;
|
|
4959
5364
|
}
|
|
4960
5365
|
try {
|
|
@@ -4962,7 +5367,7 @@ function useCheckOutItemController() {
|
|
|
4962
5367
|
res.status(201).json({ message: "Check out item created successfully.", id });
|
|
4963
5368
|
return;
|
|
4964
5369
|
} catch (error2) {
|
|
4965
|
-
|
|
5370
|
+
import_node_server_utils31.logger.log({ level: "error", message: error2.message });
|
|
4966
5371
|
next(error2);
|
|
4967
5372
|
return;
|
|
4968
5373
|
}
|
|
@@ -4980,19 +5385,19 @@ function useCheckOutItemController() {
|
|
|
4980
5385
|
};
|
|
4981
5386
|
const validation = import_joi15.default.object({
|
|
4982
5387
|
site: import_joi15.default.string().hex().required(),
|
|
4983
|
-
attachment: import_joi15.default.array().items(import_joi15.default.string()).optional().allow(null),
|
|
4984
5388
|
createdBy: import_joi15.default.string().hex().required(),
|
|
4985
5389
|
items: import_joi15.default.array().items(
|
|
4986
5390
|
import_joi15.default.object({
|
|
4987
5391
|
supply: import_joi15.default.string().hex().required(),
|
|
4988
|
-
qty: import_joi15.default.number().min(0).required()
|
|
5392
|
+
qty: import_joi15.default.number().min(0).required(),
|
|
5393
|
+
attachment: import_joi15.default.array().items(import_joi15.default.string()).optional().allow(null)
|
|
4989
5394
|
})
|
|
4990
5395
|
).min(1).required()
|
|
4991
5396
|
});
|
|
4992
5397
|
const { error } = validation.validate(payload);
|
|
4993
5398
|
if (error) {
|
|
4994
|
-
|
|
4995
|
-
next(new
|
|
5399
|
+
import_node_server_utils31.logger.log({ level: "error", message: error.message });
|
|
5400
|
+
next(new import_node_server_utils31.BadRequestError(error.message));
|
|
4996
5401
|
return;
|
|
4997
5402
|
}
|
|
4998
5403
|
try {
|
|
@@ -5000,7 +5405,7 @@ function useCheckOutItemController() {
|
|
|
5000
5405
|
res.status(201).json({ message: "Check out items created successfully." });
|
|
5001
5406
|
return;
|
|
5002
5407
|
} catch (error2) {
|
|
5003
|
-
|
|
5408
|
+
import_node_server_utils31.logger.log({ level: "error", message: error2.message });
|
|
5004
5409
|
next(error2);
|
|
5005
5410
|
return;
|
|
5006
5411
|
}
|
|
@@ -5015,8 +5420,8 @@ function useCheckOutItemController() {
|
|
|
5015
5420
|
});
|
|
5016
5421
|
const { error } = validation.validate(query);
|
|
5017
5422
|
if (error) {
|
|
5018
|
-
|
|
5019
|
-
next(new
|
|
5423
|
+
import_node_server_utils31.logger.log({ level: "error", message: error.message });
|
|
5424
|
+
next(new import_node_server_utils31.BadRequestError(error.message));
|
|
5020
5425
|
return;
|
|
5021
5426
|
}
|
|
5022
5427
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -5033,7 +5438,7 @@ function useCheckOutItemController() {
|
|
|
5033
5438
|
res.json(data);
|
|
5034
5439
|
return;
|
|
5035
5440
|
} catch (error2) {
|
|
5036
|
-
|
|
5441
|
+
import_node_server_utils31.logger.log({ level: "error", message: error2.message });
|
|
5037
5442
|
next(error2);
|
|
5038
5443
|
return;
|
|
5039
5444
|
}
|
|
@@ -5043,8 +5448,8 @@ function useCheckOutItemController() {
|
|
|
5043
5448
|
const _id = req.params.id;
|
|
5044
5449
|
const { error, value } = validation.validate(_id);
|
|
5045
5450
|
if (error) {
|
|
5046
|
-
|
|
5047
|
-
next(new
|
|
5451
|
+
import_node_server_utils31.logger.log({ level: "error", message: error.message });
|
|
5452
|
+
next(new import_node_server_utils31.BadRequestError(error.message));
|
|
5048
5453
|
return;
|
|
5049
5454
|
}
|
|
5050
5455
|
try {
|
|
@@ -5052,7 +5457,7 @@ function useCheckOutItemController() {
|
|
|
5052
5457
|
res.json(data);
|
|
5053
5458
|
return;
|
|
5054
5459
|
} catch (error2) {
|
|
5055
|
-
|
|
5460
|
+
import_node_server_utils31.logger.log({ level: "error", message: error2.message });
|
|
5056
5461
|
next(error2);
|
|
5057
5462
|
return;
|
|
5058
5463
|
}
|
|
@@ -5066,15 +5471,16 @@ function useCheckOutItemController() {
|
|
|
5066
5471
|
}
|
|
5067
5472
|
|
|
5068
5473
|
// src/models/hygiene-schedule-task.model.ts
|
|
5069
|
-
var
|
|
5474
|
+
var import_node_server_utils32 = require("@7365admin1/node-server-utils");
|
|
5070
5475
|
var import_joi16 = __toESM(require("joi"));
|
|
5071
|
-
var
|
|
5476
|
+
var import_mongodb17 = require("mongodb");
|
|
5072
5477
|
var scheduleTaskSchema = import_joi16.default.object({
|
|
5073
5478
|
site: import_joi16.default.string().hex().required(),
|
|
5074
5479
|
title: import_joi16.default.string().required(),
|
|
5075
5480
|
time: import_joi16.default.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).required(),
|
|
5076
|
-
|
|
5077
|
-
|
|
5481
|
+
dates: import_joi16.default.array().min(1).items(
|
|
5482
|
+
import_joi16.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).required()
|
|
5483
|
+
).required(),
|
|
5078
5484
|
description: import_joi16.default.string().optional().allow("", null),
|
|
5079
5485
|
areas: import_joi16.default.array().min(1).items(
|
|
5080
5486
|
import_joi16.default.object({
|
|
@@ -5087,14 +5493,14 @@ var scheduleTaskSchema = import_joi16.default.object({
|
|
|
5087
5493
|
function MScheduleTask(value) {
|
|
5088
5494
|
const { error } = scheduleTaskSchema.validate(value);
|
|
5089
5495
|
if (error) {
|
|
5090
|
-
|
|
5091
|
-
throw new
|
|
5496
|
+
import_node_server_utils32.logger.info(`Hygiene Schedule Task Model: ${error.message}`);
|
|
5497
|
+
throw new import_node_server_utils32.BadRequestError(error.message);
|
|
5092
5498
|
}
|
|
5093
5499
|
if (value.site) {
|
|
5094
5500
|
try {
|
|
5095
|
-
value.site = new
|
|
5501
|
+
value.site = new import_mongodb17.ObjectId(value.site);
|
|
5096
5502
|
} catch (error2) {
|
|
5097
|
-
throw new
|
|
5503
|
+
throw new import_node_server_utils32.BadRequestError("Invalid site ID format.");
|
|
5098
5504
|
}
|
|
5099
5505
|
}
|
|
5100
5506
|
if (value.areas && Array.isArray(value.areas)) {
|
|
@@ -5102,26 +5508,25 @@ function MScheduleTask(value) {
|
|
|
5102
5508
|
try {
|
|
5103
5509
|
return {
|
|
5104
5510
|
name: area.name,
|
|
5105
|
-
value: new
|
|
5511
|
+
value: new import_mongodb17.ObjectId(area.value.toString())
|
|
5106
5512
|
};
|
|
5107
5513
|
} catch (error2) {
|
|
5108
|
-
throw new
|
|
5514
|
+
throw new import_node_server_utils32.BadRequestError(`Invalid area value format: ${area.name}`);
|
|
5109
5515
|
}
|
|
5110
5516
|
});
|
|
5111
5517
|
}
|
|
5112
5518
|
if (value.createdBy) {
|
|
5113
5519
|
try {
|
|
5114
|
-
value.createdBy = new
|
|
5520
|
+
value.createdBy = new import_mongodb17.ObjectId(value.createdBy);
|
|
5115
5521
|
} catch (error2) {
|
|
5116
|
-
throw new
|
|
5522
|
+
throw new import_node_server_utils32.BadRequestError("Invalid createdBy ID format.");
|
|
5117
5523
|
}
|
|
5118
5524
|
}
|
|
5119
5525
|
return {
|
|
5120
5526
|
site: value.site,
|
|
5121
5527
|
title: value.title,
|
|
5122
5528
|
time: value.time,
|
|
5123
|
-
|
|
5124
|
-
endDate: value.endDate,
|
|
5529
|
+
dates: value.dates,
|
|
5125
5530
|
description: value.description,
|
|
5126
5531
|
areas: value.areas,
|
|
5127
5532
|
status: "active",
|
|
@@ -5133,16 +5538,16 @@ function MScheduleTask(value) {
|
|
|
5133
5538
|
}
|
|
5134
5539
|
|
|
5135
5540
|
// src/repositories/hygiene-schedule-task.repository.ts
|
|
5136
|
-
var
|
|
5137
|
-
var
|
|
5541
|
+
var import_mongodb18 = require("mongodb");
|
|
5542
|
+
var import_node_server_utils33 = require("@7365admin1/node-server-utils");
|
|
5138
5543
|
function useScheduleTaskRepository() {
|
|
5139
|
-
const db =
|
|
5544
|
+
const db = import_node_server_utils33.useAtlas.getDb();
|
|
5140
5545
|
if (!db) {
|
|
5141
|
-
throw new
|
|
5546
|
+
throw new import_node_server_utils33.InternalServerError("Unable to connect to server.");
|
|
5142
5547
|
}
|
|
5143
5548
|
const namespace_collection = "site.schedule-tasks";
|
|
5144
5549
|
const collection = db.collection(namespace_collection);
|
|
5145
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
5550
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils33.useCache)(namespace_collection);
|
|
5146
5551
|
async function createIndex() {
|
|
5147
5552
|
try {
|
|
5148
5553
|
await collection.createIndexes([
|
|
@@ -5150,7 +5555,7 @@ function useScheduleTaskRepository() {
|
|
|
5150
5555
|
{ key: { status: 1 } }
|
|
5151
5556
|
]);
|
|
5152
5557
|
} catch (error) {
|
|
5153
|
-
throw new
|
|
5558
|
+
throw new import_node_server_utils33.InternalServerError(
|
|
5154
5559
|
"Failed to create index on hygiene schedule task."
|
|
5155
5560
|
);
|
|
5156
5561
|
}
|
|
@@ -5159,7 +5564,7 @@ function useScheduleTaskRepository() {
|
|
|
5159
5564
|
try {
|
|
5160
5565
|
await collection.createIndex({ title: "text", description: "text" });
|
|
5161
5566
|
} catch (error) {
|
|
5162
|
-
throw new
|
|
5567
|
+
throw new import_node_server_utils33.InternalServerError(
|
|
5163
5568
|
"Failed to create text index on hygiene schedule task."
|
|
5164
5569
|
);
|
|
5165
5570
|
}
|
|
@@ -5169,9 +5574,9 @@ function useScheduleTaskRepository() {
|
|
|
5169
5574
|
value = MScheduleTask(value);
|
|
5170
5575
|
const res = await collection.insertOne(value, { session });
|
|
5171
5576
|
delNamespace().then(() => {
|
|
5172
|
-
|
|
5577
|
+
import_node_server_utils33.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
5173
5578
|
}).catch((err) => {
|
|
5174
|
-
|
|
5579
|
+
import_node_server_utils33.logger.error(
|
|
5175
5580
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
5176
5581
|
err
|
|
5177
5582
|
);
|
|
@@ -5196,20 +5601,20 @@ function useScheduleTaskRepository() {
|
|
|
5196
5601
|
limit
|
|
5197
5602
|
};
|
|
5198
5603
|
try {
|
|
5199
|
-
site = new
|
|
5604
|
+
site = new import_mongodb18.ObjectId(site);
|
|
5200
5605
|
query.site = site;
|
|
5201
5606
|
cacheOptions.site = site.toString();
|
|
5202
5607
|
} catch (error) {
|
|
5203
|
-
throw new
|
|
5608
|
+
throw new import_node_server_utils33.BadRequestError("Invalid site ID format.");
|
|
5204
5609
|
}
|
|
5205
5610
|
if (search) {
|
|
5206
5611
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
5207
5612
|
cacheOptions.search = search;
|
|
5208
5613
|
}
|
|
5209
|
-
const cacheKey = (0,
|
|
5614
|
+
const cacheKey = (0, import_node_server_utils33.makeCacheKey)(namespace_collection, cacheOptions);
|
|
5210
5615
|
const cachedData = await getCache(cacheKey);
|
|
5211
5616
|
if (cachedData) {
|
|
5212
|
-
|
|
5617
|
+
import_node_server_utils33.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
5213
5618
|
return cachedData;
|
|
5214
5619
|
}
|
|
5215
5620
|
try {
|
|
@@ -5227,11 +5632,11 @@ function useScheduleTaskRepository() {
|
|
|
5227
5632
|
{ $limit: limit }
|
|
5228
5633
|
]).toArray();
|
|
5229
5634
|
const length = await collection.countDocuments(query);
|
|
5230
|
-
const data = (0,
|
|
5635
|
+
const data = (0, import_node_server_utils33.paginate)(items, page, limit, length);
|
|
5231
5636
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
5232
|
-
|
|
5637
|
+
import_node_server_utils33.logger.info(`Cache set for key: ${cacheKey}`);
|
|
5233
5638
|
}).catch((err) => {
|
|
5234
|
-
|
|
5639
|
+
import_node_server_utils33.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
5235
5640
|
});
|
|
5236
5641
|
return data;
|
|
5237
5642
|
} catch (error) {
|
|
@@ -5264,20 +5669,20 @@ function useScheduleTaskRepository() {
|
|
|
5264
5669
|
limit
|
|
5265
5670
|
};
|
|
5266
5671
|
try {
|
|
5267
|
-
site = new
|
|
5672
|
+
site = new import_mongodb18.ObjectId(site);
|
|
5268
5673
|
query.site = site;
|
|
5269
5674
|
cacheOptions.site = site.toString();
|
|
5270
5675
|
} catch (error) {
|
|
5271
|
-
throw new
|
|
5676
|
+
throw new import_node_server_utils33.BadRequestError("Invalid site ID format.");
|
|
5272
5677
|
}
|
|
5273
5678
|
if (search) {
|
|
5274
5679
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
5275
5680
|
cacheOptions.search = search;
|
|
5276
5681
|
}
|
|
5277
|
-
const cacheKey = (0,
|
|
5682
|
+
const cacheKey = (0, import_node_server_utils33.makeCacheKey)(namespace_collection, cacheOptions);
|
|
5278
5683
|
const cachedData = await getCache(cacheKey);
|
|
5279
5684
|
if (cachedData) {
|
|
5280
|
-
|
|
5685
|
+
import_node_server_utils33.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
5281
5686
|
return cachedData;
|
|
5282
5687
|
}
|
|
5283
5688
|
try {
|
|
@@ -5294,11 +5699,11 @@ function useScheduleTaskRepository() {
|
|
|
5294
5699
|
{ $limit: limit }
|
|
5295
5700
|
]).toArray();
|
|
5296
5701
|
const length = await collection.countDocuments(query);
|
|
5297
|
-
const data = (0,
|
|
5702
|
+
const data = (0, import_node_server_utils33.paginate)(items, page, limit, length);
|
|
5298
5703
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
5299
|
-
|
|
5704
|
+
import_node_server_utils33.logger.info(`Cache set for key: ${cacheKey}`);
|
|
5300
5705
|
}).catch((err) => {
|
|
5301
|
-
|
|
5706
|
+
import_node_server_utils33.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
5302
5707
|
});
|
|
5303
5708
|
return data;
|
|
5304
5709
|
} catch (error) {
|
|
@@ -5307,25 +5712,25 @@ function useScheduleTaskRepository() {
|
|
|
5307
5712
|
}
|
|
5308
5713
|
async function getScheduleTaskById(_id, session) {
|
|
5309
5714
|
try {
|
|
5310
|
-
_id = new
|
|
5715
|
+
_id = new import_mongodb18.ObjectId(_id);
|
|
5311
5716
|
} catch (error) {
|
|
5312
|
-
throw new
|
|
5717
|
+
throw new import_node_server_utils33.BadRequestError("Invalid schedule task ID format.");
|
|
5313
5718
|
}
|
|
5314
5719
|
const query = {
|
|
5315
5720
|
_id,
|
|
5316
5721
|
status: { $ne: "deleted" }
|
|
5317
5722
|
};
|
|
5318
|
-
const cacheKey = (0,
|
|
5723
|
+
const cacheKey = (0, import_node_server_utils33.makeCacheKey)(namespace_collection, {
|
|
5319
5724
|
_id: _id.toString()
|
|
5320
5725
|
});
|
|
5321
5726
|
if (!session) {
|
|
5322
5727
|
const cachedData = await getCache(cacheKey);
|
|
5323
5728
|
if (cachedData) {
|
|
5324
|
-
|
|
5729
|
+
import_node_server_utils33.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
5325
5730
|
return cachedData;
|
|
5326
5731
|
}
|
|
5327
5732
|
} else {
|
|
5328
|
-
|
|
5733
|
+
import_node_server_utils33.logger.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
5329
5734
|
}
|
|
5330
5735
|
try {
|
|
5331
5736
|
const data = await collection.aggregate([
|
|
@@ -5334,8 +5739,7 @@ function useScheduleTaskRepository() {
|
|
|
5334
5739
|
$project: {
|
|
5335
5740
|
title: 1,
|
|
5336
5741
|
time: 1,
|
|
5337
|
-
|
|
5338
|
-
endDate: 1,
|
|
5742
|
+
dates: 1,
|
|
5339
5743
|
description: 1,
|
|
5340
5744
|
areas: 1,
|
|
5341
5745
|
status: 1,
|
|
@@ -5344,12 +5748,12 @@ function useScheduleTaskRepository() {
|
|
|
5344
5748
|
}
|
|
5345
5749
|
]).toArray();
|
|
5346
5750
|
if (!data || data.length === 0) {
|
|
5347
|
-
throw new
|
|
5751
|
+
throw new import_node_server_utils33.NotFoundError("Schedule task not found.");
|
|
5348
5752
|
}
|
|
5349
5753
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
5350
|
-
|
|
5754
|
+
import_node_server_utils33.logger.info(`Cache set for key: ${cacheKey}`);
|
|
5351
5755
|
}).catch((err) => {
|
|
5352
|
-
|
|
5756
|
+
import_node_server_utils33.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
5353
5757
|
});
|
|
5354
5758
|
return data[0];
|
|
5355
5759
|
} catch (error) {
|
|
@@ -5358,19 +5762,19 @@ function useScheduleTaskRepository() {
|
|
|
5358
5762
|
}
|
|
5359
5763
|
async function updateScheduleTask(_id, value, session) {
|
|
5360
5764
|
try {
|
|
5361
|
-
_id = new
|
|
5765
|
+
_id = new import_mongodb18.ObjectId(_id);
|
|
5362
5766
|
} catch (error) {
|
|
5363
|
-
throw new
|
|
5767
|
+
throw new import_node_server_utils33.BadRequestError("Invalid schedule task ID format.");
|
|
5364
5768
|
}
|
|
5365
5769
|
if (value.areas && Array.isArray(value.areas)) {
|
|
5366
5770
|
value.areas = value.areas.map((area) => {
|
|
5367
5771
|
try {
|
|
5368
5772
|
return {
|
|
5369
5773
|
name: area.name,
|
|
5370
|
-
value: new
|
|
5774
|
+
value: new import_mongodb18.ObjectId(area.value.toString())
|
|
5371
5775
|
};
|
|
5372
5776
|
} catch (error) {
|
|
5373
|
-
throw new
|
|
5777
|
+
throw new import_node_server_utils33.BadRequestError(`Invalid area value format: ${area.name}`);
|
|
5374
5778
|
}
|
|
5375
5779
|
});
|
|
5376
5780
|
}
|
|
@@ -5382,14 +5786,14 @@ function useScheduleTaskRepository() {
|
|
|
5382
5786
|
{ session }
|
|
5383
5787
|
);
|
|
5384
5788
|
if (res.modifiedCount === 0) {
|
|
5385
|
-
throw new
|
|
5789
|
+
throw new import_node_server_utils33.InternalServerError(
|
|
5386
5790
|
"Unable to update hygiene schedule task."
|
|
5387
5791
|
);
|
|
5388
5792
|
}
|
|
5389
5793
|
delNamespace().then(() => {
|
|
5390
|
-
|
|
5794
|
+
import_node_server_utils33.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
5391
5795
|
}).catch((err) => {
|
|
5392
|
-
|
|
5796
|
+
import_node_server_utils33.logger.error(
|
|
5393
5797
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
5394
5798
|
err
|
|
5395
5799
|
);
|
|
@@ -5412,7 +5816,7 @@ function useScheduleTaskRepository() {
|
|
|
5412
5816
|
}
|
|
5413
5817
|
|
|
5414
5818
|
// src/services/hygiene-schedule-task.service.ts
|
|
5415
|
-
var
|
|
5819
|
+
var import_node_server_utils34 = require("@7365admin1/node-server-utils");
|
|
5416
5820
|
function useScheduleTaskService() {
|
|
5417
5821
|
const { createParentChecklist } = useParentChecklistRepo();
|
|
5418
5822
|
const { getAllScheduleTask } = useScheduleTaskRepository();
|
|
@@ -5432,43 +5836,38 @@ function useScheduleTaskService() {
|
|
|
5432
5836
|
timeZone: "Asia/Singapore"
|
|
5433
5837
|
});
|
|
5434
5838
|
const [currentHour, currentMinute] = timeString.split(":").map(Number);
|
|
5435
|
-
|
|
5839
|
+
import_node_server_utils34.logger.info(
|
|
5840
|
+
`Checking schedule ${schedule._id}: Current time ${currentHour}:${currentMinute}, Schedule time ${schedule.time}, Dates ${JSON.stringify(schedule.dates)}`
|
|
5841
|
+
);
|
|
5842
|
+
const currentDateFormatted = now.toLocaleDateString("en-CA", {
|
|
5436
5843
|
timeZone: "Asia/Singapore"
|
|
5437
5844
|
});
|
|
5438
|
-
|
|
5439
|
-
`
|
|
5440
|
-
);
|
|
5441
|
-
const startDate = /* @__PURE__ */ new Date(schedule.startDate + "T00:00:00");
|
|
5442
|
-
const currentDateOnly = /* @__PURE__ */ new Date(currentDateString + "T00:00:00");
|
|
5443
|
-
if (currentDateOnly < startDate) {
|
|
5444
|
-
import_node_server_utils33.logger.info(
|
|
5445
|
-
`Schedule ${schedule._id}: Current date ${currentDateString} is before start date ${schedule.startDate}`
|
|
5446
|
-
);
|
|
5845
|
+
if (!schedule.dates || !Array.isArray(schedule.dates) || schedule.dates.length === 0) {
|
|
5846
|
+
import_node_server_utils34.logger.info(`Schedule ${schedule._id}: No dates configured, skipping`);
|
|
5447
5847
|
return false;
|
|
5448
5848
|
}
|
|
5449
|
-
if (schedule.
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
}
|
|
5849
|
+
if (!schedule.dates.includes(currentDateFormatted)) {
|
|
5850
|
+
import_node_server_utils34.logger.info(
|
|
5851
|
+
`Schedule ${schedule._id}: Current date ${currentDateFormatted} is not in scheduled dates [${schedule.dates.join(
|
|
5852
|
+
", "
|
|
5853
|
+
)}]`
|
|
5854
|
+
);
|
|
5855
|
+
return false;
|
|
5457
5856
|
}
|
|
5458
5857
|
const [scheduleHour, scheduleMinute] = schedule.time.split(":").map(Number);
|
|
5459
5858
|
const timeMatches = currentHour === scheduleHour && currentMinute === scheduleMinute;
|
|
5460
5859
|
if (!timeMatches) {
|
|
5461
|
-
|
|
5860
|
+
import_node_server_utils34.logger.info(
|
|
5462
5861
|
`Schedule ${schedule._id}: Time does not match. Current: ${currentHour}:${currentMinute}, Expected: ${scheduleHour}:${scheduleMinute}`
|
|
5463
5862
|
);
|
|
5464
5863
|
return false;
|
|
5465
5864
|
}
|
|
5466
|
-
|
|
5865
|
+
import_node_server_utils34.logger.info(
|
|
5467
5866
|
`Schedule ${schedule._id}: All conditions matched - Date is within range and time matches`
|
|
5468
5867
|
);
|
|
5469
5868
|
return true;
|
|
5470
5869
|
} catch (error) {
|
|
5471
|
-
|
|
5870
|
+
import_node_server_utils34.logger.error(
|
|
5472
5871
|
`Error checking schedule conditions for ${schedule._id}:`,
|
|
5473
5872
|
error
|
|
5474
5873
|
);
|
|
@@ -5477,40 +5876,42 @@ function useScheduleTaskService() {
|
|
|
5477
5876
|
}
|
|
5478
5877
|
async function processScheduledTasks(currentDate) {
|
|
5479
5878
|
try {
|
|
5480
|
-
|
|
5879
|
+
import_node_server_utils34.logger.info("Starting scheduled task processing...");
|
|
5481
5880
|
const scheduleTasks = await getAllScheduleTask();
|
|
5482
5881
|
if (!scheduleTasks || scheduleTasks.length === 0) {
|
|
5483
|
-
|
|
5882
|
+
import_node_server_utils34.logger.info("No schedule tasks found to process");
|
|
5484
5883
|
return { processed: 0, validated: 0 };
|
|
5485
5884
|
}
|
|
5486
|
-
|
|
5885
|
+
import_node_server_utils34.logger.info(`Found ${scheduleTasks.length} schedule tasks to check`);
|
|
5487
5886
|
let processedCount = 0;
|
|
5488
5887
|
let validatedCount = 0;
|
|
5489
5888
|
const validatedTasks = [];
|
|
5490
5889
|
for (const scheduleTask of scheduleTasks) {
|
|
5491
5890
|
try {
|
|
5492
|
-
|
|
5493
|
-
`Checking schedule ${scheduleTask._id} - ${scheduleTask.title}: time=${scheduleTask.time},
|
|
5891
|
+
import_node_server_utils34.logger.info(
|
|
5892
|
+
`Checking schedule ${scheduleTask._id} - ${scheduleTask.title}: time=${scheduleTask.time}, dates=${JSON.stringify(
|
|
5893
|
+
scheduleTask.dates
|
|
5894
|
+
)}`
|
|
5494
5895
|
);
|
|
5495
5896
|
const shouldRun = checkScheduleConditions(scheduleTask, currentDate);
|
|
5496
5897
|
if (!shouldRun) {
|
|
5497
|
-
|
|
5898
|
+
import_node_server_utils34.logger.info(
|
|
5498
5899
|
`Schedule ${scheduleTask._id} conditions not met, skipping`
|
|
5499
5900
|
);
|
|
5500
5901
|
continue;
|
|
5501
5902
|
}
|
|
5502
|
-
|
|
5903
|
+
import_node_server_utils34.logger.info(
|
|
5503
5904
|
`Schedule ${scheduleTask._id} conditions validated, creating area checklists`
|
|
5504
5905
|
);
|
|
5505
5906
|
if (!scheduleTask._id) {
|
|
5506
|
-
|
|
5907
|
+
import_node_server_utils34.logger.warn(`Schedule ${scheduleTask.title} has no _id, skipping`);
|
|
5507
5908
|
continue;
|
|
5508
5909
|
}
|
|
5509
5910
|
if (!scheduleTask.site) {
|
|
5510
|
-
|
|
5911
|
+
import_node_server_utils34.logger.warn(`Schedule ${scheduleTask._id} has no site, skipping`);
|
|
5511
5912
|
continue;
|
|
5512
5913
|
}
|
|
5513
|
-
|
|
5914
|
+
import_node_server_utils34.logger.info(
|
|
5514
5915
|
`Getting or creating parent checklist for schedule ${scheduleTask._id} in site ${scheduleTask.site}`
|
|
5515
5916
|
);
|
|
5516
5917
|
const parentChecklistIds = await createParentChecklist({
|
|
@@ -5518,7 +5919,7 @@ function useScheduleTaskService() {
|
|
|
5518
5919
|
createdAt: /* @__PURE__ */ new Date()
|
|
5519
5920
|
});
|
|
5520
5921
|
const parentChecklistId = Array.isArray(parentChecklistIds) ? parentChecklistIds[0] : parentChecklistIds;
|
|
5521
|
-
|
|
5922
|
+
import_node_server_utils34.logger.info(
|
|
5522
5923
|
`Using parent checklist ${parentChecklistId}, now creating/updating area checklists`
|
|
5523
5924
|
);
|
|
5524
5925
|
for (const area of scheduleTask.areas) {
|
|
@@ -5531,14 +5932,14 @@ function useScheduleTaskService() {
|
|
|
5531
5932
|
unit: unit.unit.toString(),
|
|
5532
5933
|
name: unit.name
|
|
5533
5934
|
}));
|
|
5534
|
-
|
|
5935
|
+
import_node_server_utils34.logger.info(
|
|
5535
5936
|
`Area ${area.name} (${areaId}): Using units from area details: ${JSON.stringify(
|
|
5536
5937
|
units
|
|
5537
5938
|
)}`
|
|
5538
5939
|
);
|
|
5539
5940
|
}
|
|
5540
5941
|
if (units.length === 0) {
|
|
5541
|
-
|
|
5942
|
+
import_node_server_utils34.logger.warn(
|
|
5542
5943
|
`Area ${area.name} (${areaId}): No units found, skipping area.`
|
|
5543
5944
|
);
|
|
5544
5945
|
continue;
|
|
@@ -5549,11 +5950,11 @@ function useScheduleTaskService() {
|
|
|
5549
5950
|
parentChecklistId.toString(),
|
|
5550
5951
|
areaId
|
|
5551
5952
|
);
|
|
5552
|
-
|
|
5953
|
+
import_node_server_utils34.logger.info(
|
|
5553
5954
|
`Area ${area.name} (${areaId}): Existing area checklist found: ${existingAreaChecklist ? "Yes" : "No"}`
|
|
5554
5955
|
);
|
|
5555
5956
|
if (existingAreaChecklist) {
|
|
5556
|
-
|
|
5957
|
+
import_node_server_utils34.logger.info(
|
|
5557
5958
|
`Area ${area.name} (${areaId}): Existing checklist content: ${JSON.stringify(
|
|
5558
5959
|
existingAreaChecklist.checklist
|
|
5559
5960
|
)}`
|
|
@@ -5561,7 +5962,7 @@ function useScheduleTaskService() {
|
|
|
5561
5962
|
}
|
|
5562
5963
|
} catch (error) {
|
|
5563
5964
|
existingAreaChecklist = null;
|
|
5564
|
-
|
|
5965
|
+
import_node_server_utils34.logger.info(
|
|
5565
5966
|
`Area ${area.name} (${areaId}): No existing area checklist found (exception).`
|
|
5566
5967
|
);
|
|
5567
5968
|
}
|
|
@@ -5575,7 +5976,7 @@ function useScheduleTaskService() {
|
|
|
5575
5976
|
...existingAreaChecklist.checklist || [],
|
|
5576
5977
|
newSet
|
|
5577
5978
|
];
|
|
5578
|
-
|
|
5979
|
+
import_node_server_utils34.logger.info(
|
|
5579
5980
|
`Area ${area.name} (${areaId}): Appending new set ${newSet.set} to checklist. Updated checklist: ${JSON.stringify(
|
|
5580
5981
|
updatedChecklist
|
|
5581
5982
|
)}`
|
|
@@ -5583,7 +5984,7 @@ function useScheduleTaskService() {
|
|
|
5583
5984
|
await updateAreaChecklist(existingAreaChecklist._id, {
|
|
5584
5985
|
checklist: updatedChecklist
|
|
5585
5986
|
});
|
|
5586
|
-
|
|
5987
|
+
import_node_server_utils34.logger.info(
|
|
5587
5988
|
`Appended set ${newSet.set} to area checklist for area ${area.name}`
|
|
5588
5989
|
);
|
|
5589
5990
|
try {
|
|
@@ -5591,13 +5992,13 @@ function useScheduleTaskService() {
|
|
|
5591
5992
|
parentChecklistId.toString(),
|
|
5592
5993
|
areaId
|
|
5593
5994
|
);
|
|
5594
|
-
|
|
5995
|
+
import_node_server_utils34.logger.info(
|
|
5595
5996
|
`Area ${area.name} (${areaId}): Checklist after update: ${JSON.stringify(
|
|
5596
5997
|
verifyChecklist.checklist
|
|
5597
5998
|
)}`
|
|
5598
5999
|
);
|
|
5599
6000
|
} catch (verifyError) {
|
|
5600
|
-
|
|
6001
|
+
import_node_server_utils34.logger.warn(
|
|
5601
6002
|
`Area ${area.name} (${areaId}): Error verifying checklist after update:`,
|
|
5602
6003
|
verifyError
|
|
5603
6004
|
);
|
|
@@ -5616,50 +6017,50 @@ function useScheduleTaskService() {
|
|
|
5616
6017
|
],
|
|
5617
6018
|
createdBy: scheduleTask.createdBy
|
|
5618
6019
|
};
|
|
5619
|
-
|
|
6020
|
+
import_node_server_utils34.logger.info(
|
|
5620
6021
|
`Area ${area.name} (${areaId}): Creating new area checklist with data: ${JSON.stringify(
|
|
5621
6022
|
checklistData
|
|
5622
6023
|
)}`
|
|
5623
6024
|
);
|
|
5624
6025
|
await createAreaChecklist(checklistData);
|
|
5625
|
-
|
|
6026
|
+
import_node_server_utils34.logger.info(`Created new area checklist for area ${area.name}`);
|
|
5626
6027
|
try {
|
|
5627
6028
|
const verifyChecklist = await getAreaChecklistByAreaAndSchedule(
|
|
5628
6029
|
parentChecklistId.toString(),
|
|
5629
6030
|
areaId
|
|
5630
6031
|
);
|
|
5631
|
-
|
|
6032
|
+
import_node_server_utils34.logger.info(
|
|
5632
6033
|
`Area ${area.name} (${areaId}): Checklist after creation: ${JSON.stringify(
|
|
5633
6034
|
verifyChecklist.checklist
|
|
5634
6035
|
)}`
|
|
5635
6036
|
);
|
|
5636
6037
|
} catch (verifyError) {
|
|
5637
|
-
|
|
6038
|
+
import_node_server_utils34.logger.warn(
|
|
5638
6039
|
`Area ${area.name} (${areaId}): Error verifying checklist after creation:`,
|
|
5639
6040
|
verifyError
|
|
5640
6041
|
);
|
|
5641
6042
|
}
|
|
5642
6043
|
}
|
|
5643
6044
|
} catch (error) {
|
|
5644
|
-
|
|
6045
|
+
import_node_server_utils34.logger.error(`Error processing area ${area.name}:`, error);
|
|
5645
6046
|
continue;
|
|
5646
6047
|
}
|
|
5647
6048
|
}
|
|
5648
6049
|
processedCount++;
|
|
5649
6050
|
validatedCount++;
|
|
5650
6051
|
validatedTasks.push(scheduleTask);
|
|
5651
|
-
|
|
6052
|
+
import_node_server_utils34.logger.info(
|
|
5652
6053
|
`Successfully processed schedule ${scheduleTask._id}, created/updated area checklists for all areas.`
|
|
5653
6054
|
);
|
|
5654
6055
|
} catch (error) {
|
|
5655
|
-
|
|
6056
|
+
import_node_server_utils34.logger.error(
|
|
5656
6057
|
`Error processing schedule task ${scheduleTask._id}:`,
|
|
5657
6058
|
error
|
|
5658
6059
|
);
|
|
5659
6060
|
continue;
|
|
5660
6061
|
}
|
|
5661
6062
|
}
|
|
5662
|
-
|
|
6063
|
+
import_node_server_utils34.logger.info(
|
|
5663
6064
|
`Scheduled task processing completed. Processed: ${processedCount}, Validated: ${validatedCount} tasks`
|
|
5664
6065
|
);
|
|
5665
6066
|
return {
|
|
@@ -5668,7 +6069,7 @@ function useScheduleTaskService() {
|
|
|
5668
6069
|
tasks: validatedTasks
|
|
5669
6070
|
};
|
|
5670
6071
|
} catch (error) {
|
|
5671
|
-
|
|
6072
|
+
import_node_server_utils34.logger.error("Error processing scheduled tasks:", error);
|
|
5672
6073
|
throw error;
|
|
5673
6074
|
}
|
|
5674
6075
|
}
|
|
@@ -5677,7 +6078,7 @@ function useScheduleTaskService() {
|
|
|
5677
6078
|
|
|
5678
6079
|
// src/controllers/hygiene-schedule-task.controller.ts
|
|
5679
6080
|
var import_joi17 = __toESM(require("joi"));
|
|
5680
|
-
var
|
|
6081
|
+
var import_node_server_utils35 = require("@7365admin1/node-server-utils");
|
|
5681
6082
|
function useScheduleTaskController() {
|
|
5682
6083
|
const {
|
|
5683
6084
|
createScheduleTask: _createScheduleTask,
|
|
@@ -5695,8 +6096,8 @@ function useScheduleTaskController() {
|
|
|
5695
6096
|
const payload = { ...req.body, ...req.params, createdBy };
|
|
5696
6097
|
const { error } = scheduleTaskSchema.validate(payload);
|
|
5697
6098
|
if (error) {
|
|
5698
|
-
|
|
5699
|
-
next(new
|
|
6099
|
+
import_node_server_utils35.logger.log({ level: "error", message: error.message });
|
|
6100
|
+
next(new import_node_server_utils35.BadRequestError(error.message));
|
|
5700
6101
|
return;
|
|
5701
6102
|
}
|
|
5702
6103
|
try {
|
|
@@ -5704,7 +6105,7 @@ function useScheduleTaskController() {
|
|
|
5704
6105
|
res.status(201).json({ message: "Schedule task created successfully.", id });
|
|
5705
6106
|
return;
|
|
5706
6107
|
} catch (error2) {
|
|
5707
|
-
|
|
6108
|
+
import_node_server_utils35.logger.log({ level: "error", message: error2.message });
|
|
5708
6109
|
next(error2);
|
|
5709
6110
|
return;
|
|
5710
6111
|
}
|
|
@@ -5719,8 +6120,8 @@ function useScheduleTaskController() {
|
|
|
5719
6120
|
});
|
|
5720
6121
|
const { error } = validation.validate(query);
|
|
5721
6122
|
if (error) {
|
|
5722
|
-
|
|
5723
|
-
next(new
|
|
6123
|
+
import_node_server_utils35.logger.log({ level: "error", message: error.message });
|
|
6124
|
+
next(new import_node_server_utils35.BadRequestError(error.message));
|
|
5724
6125
|
return;
|
|
5725
6126
|
}
|
|
5726
6127
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -5737,7 +6138,7 @@ function useScheduleTaskController() {
|
|
|
5737
6138
|
res.json(data);
|
|
5738
6139
|
return;
|
|
5739
6140
|
} catch (error2) {
|
|
5740
|
-
|
|
6141
|
+
import_node_server_utils35.logger.log({ level: "error", message: error2.message });
|
|
5741
6142
|
next(error2);
|
|
5742
6143
|
return;
|
|
5743
6144
|
}
|
|
@@ -5752,8 +6153,8 @@ function useScheduleTaskController() {
|
|
|
5752
6153
|
});
|
|
5753
6154
|
const { error } = validation.validate(query);
|
|
5754
6155
|
if (error) {
|
|
5755
|
-
|
|
5756
|
-
next(new
|
|
6156
|
+
import_node_server_utils35.logger.log({ level: "error", message: error.message });
|
|
6157
|
+
next(new import_node_server_utils35.BadRequestError(error.message));
|
|
5757
6158
|
return;
|
|
5758
6159
|
}
|
|
5759
6160
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -5770,7 +6171,7 @@ function useScheduleTaskController() {
|
|
|
5770
6171
|
res.json(data);
|
|
5771
6172
|
return;
|
|
5772
6173
|
} catch (error2) {
|
|
5773
|
-
|
|
6174
|
+
import_node_server_utils35.logger.log({ level: "error", message: error2.message });
|
|
5774
6175
|
next(error2);
|
|
5775
6176
|
return;
|
|
5776
6177
|
}
|
|
@@ -5780,8 +6181,8 @@ function useScheduleTaskController() {
|
|
|
5780
6181
|
const _id = req.params.id;
|
|
5781
6182
|
const { error, value } = validation.validate(_id);
|
|
5782
6183
|
if (error) {
|
|
5783
|
-
|
|
5784
|
-
next(new
|
|
6184
|
+
import_node_server_utils35.logger.log({ level: "error", message: error.message });
|
|
6185
|
+
next(new import_node_server_utils35.BadRequestError(error.message));
|
|
5785
6186
|
return;
|
|
5786
6187
|
}
|
|
5787
6188
|
try {
|
|
@@ -5789,7 +6190,7 @@ function useScheduleTaskController() {
|
|
|
5789
6190
|
res.json(data);
|
|
5790
6191
|
return;
|
|
5791
6192
|
} catch (error2) {
|
|
5792
|
-
|
|
6193
|
+
import_node_server_utils35.logger.log({ level: "error", message: error2.message });
|
|
5793
6194
|
next(error2);
|
|
5794
6195
|
return;
|
|
5795
6196
|
}
|
|
@@ -5800,8 +6201,9 @@ function useScheduleTaskController() {
|
|
|
5800
6201
|
id: import_joi17.default.string().hex().required(),
|
|
5801
6202
|
title: import_joi17.default.string().optional().allow("", null),
|
|
5802
6203
|
time: import_joi17.default.string().pattern(/^([0-1]\d|2[0-3]):([0-5]\d)$/).optional().allow("", null),
|
|
5803
|
-
|
|
5804
|
-
|
|
6204
|
+
dates: import_joi17.default.array().min(1).items(
|
|
6205
|
+
import_joi17.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).required()
|
|
6206
|
+
).optional(),
|
|
5805
6207
|
description: import_joi17.default.string().optional().allow("", null),
|
|
5806
6208
|
areas: import_joi17.default.array().min(1).items(
|
|
5807
6209
|
import_joi17.default.object({
|
|
@@ -5812,8 +6214,8 @@ function useScheduleTaskController() {
|
|
|
5812
6214
|
});
|
|
5813
6215
|
const { error } = validation.validate(payload);
|
|
5814
6216
|
if (error) {
|
|
5815
|
-
|
|
5816
|
-
next(new
|
|
6217
|
+
import_node_server_utils35.logger.log({ level: "error", message: error.message });
|
|
6218
|
+
next(new import_node_server_utils35.BadRequestError(error.message));
|
|
5817
6219
|
return;
|
|
5818
6220
|
}
|
|
5819
6221
|
try {
|
|
@@ -5822,7 +6224,7 @@ function useScheduleTaskController() {
|
|
|
5822
6224
|
res.json({ message: "Schedule task updated successfully." });
|
|
5823
6225
|
return;
|
|
5824
6226
|
} catch (error2) {
|
|
5825
|
-
|
|
6227
|
+
import_node_server_utils35.logger.log({ level: "error", message: error2.message });
|
|
5826
6228
|
next(error2);
|
|
5827
6229
|
return;
|
|
5828
6230
|
}
|
|
@@ -5837,8 +6239,8 @@ function useScheduleTaskController() {
|
|
|
5837
6239
|
}
|
|
5838
6240
|
|
|
5839
6241
|
// src/services/hygiene-qr.service.ts
|
|
5840
|
-
var
|
|
5841
|
-
var
|
|
6242
|
+
var import_node_server_utils36 = require("@7365admin1/node-server-utils");
|
|
6243
|
+
var import_puppeteer2 = require("puppeteer");
|
|
5842
6244
|
var import_qrcode = __toESM(require("qrcode"));
|
|
5843
6245
|
function useQRService() {
|
|
5844
6246
|
async function generateQRDataUrl(qrUrl) {
|
|
@@ -5855,7 +6257,7 @@ function useQRService() {
|
|
|
5855
6257
|
async function generateQRImage(qrUrl) {
|
|
5856
6258
|
try {
|
|
5857
6259
|
const qrDataUrl = await generateQRDataUrl(qrUrl);
|
|
5858
|
-
const browser = await (0,
|
|
6260
|
+
const browser = await (0, import_puppeteer2.launch)({
|
|
5859
6261
|
headless: true,
|
|
5860
6262
|
executablePath: process.env.CHROME_BINARY,
|
|
5861
6263
|
args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
|
|
@@ -5908,17 +6310,17 @@ function useQRService() {
|
|
|
5908
6310
|
await browser.close();
|
|
5909
6311
|
return imageBuffer;
|
|
5910
6312
|
} catch (error) {
|
|
5911
|
-
|
|
6313
|
+
import_node_server_utils36.logger.log({
|
|
5912
6314
|
level: "error",
|
|
5913
6315
|
message: `Failed to generate QR image: ${error.message}`
|
|
5914
6316
|
});
|
|
5915
6317
|
throw error;
|
|
5916
6318
|
}
|
|
5917
6319
|
}
|
|
5918
|
-
async function generateQRPDF(qrUrl, title) {
|
|
6320
|
+
async function generateQRPDF(qrUrl, title, subtitle) {
|
|
5919
6321
|
try {
|
|
5920
6322
|
const qrDataUrl = await generateQRDataUrl(qrUrl);
|
|
5921
|
-
const browser = await (0,
|
|
6323
|
+
const browser = await (0, import_puppeteer2.launch)({
|
|
5922
6324
|
headless: true,
|
|
5923
6325
|
executablePath: process.env.CHROME_BINARY,
|
|
5924
6326
|
args: [`--no-sandbox`, `--disable-gpu`, `--disable-dev-shm-usage`]
|
|
@@ -5929,6 +6331,7 @@ function useQRService() {
|
|
|
5929
6331
|
height: 1100
|
|
5930
6332
|
});
|
|
5931
6333
|
const escapedTitle = (title || "Cleaning Schedule QR Code").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
6334
|
+
const escapedSubtitle = subtitle ? subtitle.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """) : "";
|
|
5932
6335
|
const html = `
|
|
5933
6336
|
<!DOCTYPE html>
|
|
5934
6337
|
<html>
|
|
@@ -5956,10 +6359,16 @@ function useQRService() {
|
|
|
5956
6359
|
padding: 0;
|
|
5957
6360
|
}
|
|
5958
6361
|
h1 {
|
|
5959
|
-
font-size:
|
|
6362
|
+
font-size: 38px;
|
|
5960
6363
|
color: #333;
|
|
5961
|
-
margin-bottom:
|
|
5962
|
-
font-weight:
|
|
6364
|
+
margin-bottom: 8px;
|
|
6365
|
+
font-weight: 700;
|
|
6366
|
+
}
|
|
6367
|
+
.subtitle {
|
|
6368
|
+
font-size: 26px;
|
|
6369
|
+
color: #555;
|
|
6370
|
+
margin-bottom: 12px;
|
|
6371
|
+
font-weight: 500;
|
|
5963
6372
|
}
|
|
5964
6373
|
.qr-wrapper {
|
|
5965
6374
|
display: inline-block;
|
|
@@ -5994,6 +6403,7 @@ function useQRService() {
|
|
|
5994
6403
|
<body>
|
|
5995
6404
|
<div class="qr-container">
|
|
5996
6405
|
<h1>${escapedTitle}</h1>
|
|
6406
|
+
${escapedSubtitle ? `<p class="subtitle">${escapedSubtitle}</p>` : ""}
|
|
5997
6407
|
<div class="qr-wrapper">
|
|
5998
6408
|
<img id="qr-image" src="${qrDataUrl}" alt="QR Code" />
|
|
5999
6409
|
</div>
|
|
@@ -6031,7 +6441,7 @@ function useQRService() {
|
|
|
6031
6441
|
await browser.close();
|
|
6032
6442
|
return pdfBuffer;
|
|
6033
6443
|
} catch (error) {
|
|
6034
|
-
|
|
6444
|
+
import_node_server_utils36.logger.log({
|
|
6035
6445
|
level: "error",
|
|
6036
6446
|
message: `Failed to generate QR PDF: ${error.message}`
|
|
6037
6447
|
});
|
|
@@ -6046,7 +6456,7 @@ function useQRService() {
|
|
|
6046
6456
|
|
|
6047
6457
|
// src/controllers/hygiene-qr.controller.ts
|
|
6048
6458
|
var import_joi18 = __toESM(require("joi"));
|
|
6049
|
-
var
|
|
6459
|
+
var import_node_server_utils37 = require("@7365admin1/node-server-utils");
|
|
6050
6460
|
function useQRController() {
|
|
6051
6461
|
const { generateQRImage: _generateQRImage, generateQRPDF: _generateQRPDF } = useQRService();
|
|
6052
6462
|
async function generateQR(req, res, next) {
|
|
@@ -6054,19 +6464,20 @@ function useQRController() {
|
|
|
6054
6464
|
url: import_joi18.default.string().uri().required(),
|
|
6055
6465
|
filename: import_joi18.default.string().optional().allow("", null),
|
|
6056
6466
|
title: import_joi18.default.string().optional().allow("", null),
|
|
6467
|
+
subtitle: import_joi18.default.string().optional().allow("", null),
|
|
6057
6468
|
download: import_joi18.default.boolean().optional().default(false)
|
|
6058
6469
|
});
|
|
6059
6470
|
const query = { ...req.query };
|
|
6060
6471
|
const { error, value } = validation.validate(query);
|
|
6061
6472
|
if (error) {
|
|
6062
|
-
|
|
6063
|
-
next(new
|
|
6473
|
+
import_node_server_utils37.logger.log({ level: "error", message: error.message });
|
|
6474
|
+
next(new import_node_server_utils37.BadRequestError(error.message));
|
|
6064
6475
|
return;
|
|
6065
6476
|
}
|
|
6066
6477
|
try {
|
|
6067
|
-
const { url, filename, title, download } = value;
|
|
6478
|
+
const { url, filename, title, subtitle, download } = value;
|
|
6068
6479
|
if (download) {
|
|
6069
|
-
const pdfBuffer = await _generateQRPDF(url, title);
|
|
6480
|
+
const pdfBuffer = await _generateQRPDF(url, title, subtitle);
|
|
6070
6481
|
if (!pdfBuffer || pdfBuffer.length === 0) {
|
|
6071
6482
|
throw new Error("Generated QR PDF is empty or invalid.");
|
|
6072
6483
|
}
|
|
@@ -6095,7 +6506,7 @@ function useQRController() {
|
|
|
6095
6506
|
}
|
|
6096
6507
|
return;
|
|
6097
6508
|
} catch (error2) {
|
|
6098
|
-
|
|
6509
|
+
import_node_server_utils37.logger.log({ level: "error", message: error2.message });
|
|
6099
6510
|
next(error2);
|
|
6100
6511
|
return;
|
|
6101
6512
|
}
|