@7365admin1/module-hygiene 4.31.0 → 4.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +82 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +82 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/test/schedule-followups.test.mjs +30 -0
- package/test/schedule-task-rules.test.mjs +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @7365admin1/module-hygiene
|
|
2
2
|
|
|
3
|
+
## 4.32.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 98ff56f: Extra visits: editing a repeating visit no longer fails; one extra visit adds one round; an area or day already Done is reopened when an extra round is added; Next visit is right for a task saved after today's time.
|
|
8
|
+
|
|
9
|
+
## 4.32.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 8b89acd: Extra-visit sets now store `scheduleTaskId`, `scheduleTaskTitle` and `scheduleTaskTime`, returned by the area-checklist unit/set responses (null on older sets). The history PDF marks not-done items "Missed".
|
|
14
|
+
|
|
3
15
|
## 4.31.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -242,6 +242,7 @@ declare function useParentChecklistRepo(): {
|
|
|
242
242
|
_id: ObjectId;
|
|
243
243
|
}>;
|
|
244
244
|
updateParentChecklistStatuses: (_id: string | ObjectId, status: (typeof allowedStatus)[number], session?: ClientSession) => Promise<number>;
|
|
245
|
+
reopenParentChecklist: (_id: string | ObjectId) => Promise<number>;
|
|
245
246
|
getHygieneSiteIds: () => Promise<any[]>;
|
|
246
247
|
closeExpiredParentChecklists: () => Promise<number>;
|
|
247
248
|
getTodayParentChecklists: () => Promise<{
|
|
@@ -281,6 +282,8 @@ type TAreaChecklist = {
|
|
|
281
282
|
attachment?: string[];
|
|
282
283
|
isScheduleTask?: boolean;
|
|
283
284
|
scheduleTaskId?: string | ObjectId;
|
|
285
|
+
scheduleTaskTitle?: string;
|
|
286
|
+
scheduleTaskTime?: string;
|
|
284
287
|
};
|
|
285
288
|
type TAreaChecklistUnits = {
|
|
286
289
|
unit: string | ObjectId;
|
package/dist/index.js
CHANGED
|
@@ -3015,6 +3015,18 @@ function useParentChecklistRepo() {
|
|
|
3015
3015
|
throw error;
|
|
3016
3016
|
}
|
|
3017
3017
|
}
|
|
3018
|
+
async function reopenParentChecklist(_id) {
|
|
3019
|
+
const res = await collection.updateOne(
|
|
3020
|
+
{ _id: new import_mongodb7.ObjectId(_id), status: "completed" },
|
|
3021
|
+
{ $set: { status: "ongoing", updatedAt: /* @__PURE__ */ new Date() }, $unset: { completedAt: "" } }
|
|
3022
|
+
);
|
|
3023
|
+
if (res.modifiedCount > 0) {
|
|
3024
|
+
delNamespace().catch((err) => {
|
|
3025
|
+
import_node_server_utils14.logger.error(`Failed to clear cache for namespace: ${namespace_collection}`, err);
|
|
3026
|
+
});
|
|
3027
|
+
}
|
|
3028
|
+
return res.modifiedCount;
|
|
3029
|
+
}
|
|
3018
3030
|
async function getHygieneSiteIds() {
|
|
3019
3031
|
const query = {
|
|
3020
3032
|
status: { $ne: "deleted" }
|
|
@@ -3121,6 +3133,7 @@ function useParentChecklistRepo() {
|
|
|
3121
3133
|
getAllParentChecklist,
|
|
3122
3134
|
getParentChecklistById,
|
|
3123
3135
|
updateParentChecklistStatuses,
|
|
3136
|
+
reopenParentChecklist,
|
|
3124
3137
|
getHygieneSiteIds,
|
|
3125
3138
|
closeExpiredParentChecklists,
|
|
3126
3139
|
getTodayParentChecklists,
|
|
@@ -3233,7 +3246,9 @@ var areaChecklistSchema = import_joi9.default.object({
|
|
|
3233
3246
|
}).required()
|
|
3234
3247
|
).min(1).required(),
|
|
3235
3248
|
isScheduleTask: import_joi9.default.boolean().optional().default(false),
|
|
3236
|
-
scheduleTaskId: import_joi9.default.string().hex().optional().allow(null)
|
|
3249
|
+
scheduleTaskId: import_joi9.default.string().hex().optional().allow(null),
|
|
3250
|
+
scheduleTaskTitle: import_joi9.default.string().optional().allow("", null),
|
|
3251
|
+
scheduleTaskTime: import_joi9.default.string().optional().allow("", null)
|
|
3237
3252
|
}).required()
|
|
3238
3253
|
).optional().default([])
|
|
3239
3254
|
});
|
|
@@ -3263,6 +3278,8 @@ function MAreaChecklist(value) {
|
|
|
3263
3278
|
set: checklistItem.set,
|
|
3264
3279
|
isScheduleTask: checklistItem.isScheduleTask ?? false,
|
|
3265
3280
|
scheduleTaskId: checklistItem.scheduleTaskId ?? void 0,
|
|
3281
|
+
scheduleTaskTitle: checklistItem.scheduleTaskTitle ?? void 0,
|
|
3282
|
+
scheduleTaskTime: checklistItem.scheduleTaskTime ?? void 0,
|
|
3266
3283
|
units: checklistItem.units.map((unit) => ({
|
|
3267
3284
|
unit: new import_mongodb8.ObjectId(unit.unit),
|
|
3268
3285
|
name: unit.name,
|
|
@@ -3745,6 +3762,9 @@ function useAreaChecklistRepo() {
|
|
|
3745
3762
|
isScheduleTask: {
|
|
3746
3763
|
$ifNull: ["$checklist.isScheduleTask", false]
|
|
3747
3764
|
},
|
|
3765
|
+
scheduleTaskId: { $ifNull: ["$checklist.scheduleTaskId", null] },
|
|
3766
|
+
scheduleTaskTitle: { $ifNull: ["$checklist.scheduleTaskTitle", null] },
|
|
3767
|
+
scheduleTaskTime: { $ifNull: ["$checklist.scheduleTaskTime", null] },
|
|
3748
3768
|
unit: "$checklist.units.unit",
|
|
3749
3769
|
name: "$checklist.units.name",
|
|
3750
3770
|
approve: "$checklist.units.approve",
|
|
@@ -3781,6 +3801,9 @@ function useAreaChecklistRepo() {
|
|
|
3781
3801
|
$group: {
|
|
3782
3802
|
_id: "$set",
|
|
3783
3803
|
isScheduleTask: { $first: "$isScheduleTask" },
|
|
3804
|
+
scheduleTaskId: { $first: "$scheduleTaskId" },
|
|
3805
|
+
scheduleTaskTitle: { $first: "$scheduleTaskTitle" },
|
|
3806
|
+
scheduleTaskTime: { $first: "$scheduleTaskTime" },
|
|
3784
3807
|
units: {
|
|
3785
3808
|
$push: {
|
|
3786
3809
|
unit: "$unit",
|
|
@@ -3801,6 +3824,9 @@ function useAreaChecklistRepo() {
|
|
|
3801
3824
|
_id: 0,
|
|
3802
3825
|
set: "$_id",
|
|
3803
3826
|
isScheduleTask: 1,
|
|
3827
|
+
scheduleTaskId: 1,
|
|
3828
|
+
scheduleTaskTitle: 1,
|
|
3829
|
+
scheduleTaskTime: 1,
|
|
3804
3830
|
units: 1
|
|
3805
3831
|
}
|
|
3806
3832
|
},
|
|
@@ -3932,6 +3958,8 @@ function useAreaChecklistRepo() {
|
|
|
3932
3958
|
isScheduleTask: {
|
|
3933
3959
|
$ifNull: ["$checklist.isScheduleTask", false]
|
|
3934
3960
|
},
|
|
3961
|
+
scheduleTaskTitle: { $ifNull: ["$checklist.scheduleTaskTitle", null] },
|
|
3962
|
+
scheduleTaskTime: { $ifNull: ["$checklist.scheduleTaskTime", null] },
|
|
3935
3963
|
scheduleTaskId: {
|
|
3936
3964
|
$ifNull: ["$checklist.scheduleTaskId", null]
|
|
3937
3965
|
},
|
|
@@ -3972,6 +4000,8 @@ function useAreaChecklistRepo() {
|
|
|
3972
4000
|
$group: {
|
|
3973
4001
|
_id: "$set",
|
|
3974
4002
|
isScheduleTask: { $first: "$isScheduleTask" },
|
|
4003
|
+
scheduleTaskTitle: { $first: "$scheduleTaskTitle" },
|
|
4004
|
+
scheduleTaskTime: { $first: "$scheduleTaskTime" },
|
|
3975
4005
|
scheduleTaskId: { $first: "$scheduleTaskId" },
|
|
3976
4006
|
remarks: { $first: "$remarks" },
|
|
3977
4007
|
attachment: { $first: "$attachment" },
|
|
@@ -3996,6 +4026,8 @@ function useAreaChecklistRepo() {
|
|
|
3996
4026
|
_id: 0,
|
|
3997
4027
|
set: "$_id",
|
|
3998
4028
|
isScheduleTask: 1,
|
|
4029
|
+
scheduleTaskTitle: 1,
|
|
4030
|
+
scheduleTaskTime: 1,
|
|
3999
4031
|
scheduleTaskId: 1,
|
|
4000
4032
|
remarks: "$remarks",
|
|
4001
4033
|
attachment: "$attachment",
|
|
@@ -4318,6 +4350,10 @@ function useAreaChecklistRepo() {
|
|
|
4318
4350
|
}
|
|
4319
4351
|
);
|
|
4320
4352
|
if (result.modifiedCount > 0) {
|
|
4353
|
+
await collection.updateOne(
|
|
4354
|
+
{ schedule, serviceType, area, status: "completed" },
|
|
4355
|
+
{ $set: { status: "ongoing", updatedAt: /* @__PURE__ */ new Date() }, $unset: { completedAt: "" } }
|
|
4356
|
+
);
|
|
4321
4357
|
delNamespace().catch((err) => {
|
|
4322
4358
|
import_node_server_utils17.logger.error(
|
|
4323
4359
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
@@ -4614,6 +4650,9 @@ function validateScheduleRules(task, now = /* @__PURE__ */ new Date()) {
|
|
|
4614
4650
|
}
|
|
4615
4651
|
if (task.endDate && task.endDate < today)
|
|
4616
4652
|
return "The end date has already passed.";
|
|
4653
|
+
if (!repeating && !(task.dates ?? []).length) {
|
|
4654
|
+
return "Pick at least one date, or choose a repeat.";
|
|
4655
|
+
}
|
|
4617
4656
|
if (!repeating) {
|
|
4618
4657
|
const dates = (task.dates ?? []).filter((d) => !task.endDate || d <= task.endDate);
|
|
4619
4658
|
if (dates.length && dates.every((d) => d < today)) {
|
|
@@ -4976,6 +5015,8 @@ var import_core11 = require("@7365admin1/core");
|
|
|
4976
5015
|
var import_puppeteer = require("puppeteer");
|
|
4977
5016
|
var import_node_server_utils19 = require("@7365admin1/node-server-utils");
|
|
4978
5017
|
var import_mongodb11 = require("mongodb");
|
|
5018
|
+
|
|
5019
|
+
// src/utils/checklist-pdf-html.util.ts
|
|
4979
5020
|
function escapeHtml(text) {
|
|
4980
5021
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4981
5022
|
}
|
|
@@ -4988,7 +5029,7 @@ function buildChecklistHtml(areaChecklists) {
|
|
|
4988
5029
|
const unitRows = (setItem.units || []).map(
|
|
4989
5030
|
(unit) => `
|
|
4990
5031
|
<tr>
|
|
4991
|
-
<td class="unit-name">${escapeHtml(unit.name || "")}</td>
|
|
5032
|
+
<td class="unit-name">${escapeHtml(unit.name || "")}${unit.approve || unit.reject ? "" : ' <span class="missed-label">Missed</span>'}</td>
|
|
4992
5033
|
<td class="icon-cell">${unit.reject ? '<span class="reject-icon">✗</span>' : ""}</td>
|
|
4993
5034
|
<td class="icon-cell">${unit.approve ? '<span class="approve-icon">✓</span>' : ""}</td>
|
|
4994
5035
|
</tr>`
|
|
@@ -5125,6 +5166,12 @@ function buildChecklistHtml(areaChecklists) {
|
|
|
5125
5166
|
font-size: 16px;
|
|
5126
5167
|
font-weight: bold;
|
|
5127
5168
|
}
|
|
5169
|
+
.missed-label {
|
|
5170
|
+
color: #b3261e;
|
|
5171
|
+
font-size: 11px;
|
|
5172
|
+
font-weight: bold;
|
|
5173
|
+
margin-left: 6px;
|
|
5174
|
+
}
|
|
5128
5175
|
.reject-icon {
|
|
5129
5176
|
color: #e74c3c;
|
|
5130
5177
|
font-size: 16px;
|
|
@@ -5140,6 +5187,8 @@ function buildChecklistHtml(areaChecklists) {
|
|
|
5140
5187
|
</body>
|
|
5141
5188
|
</html>`;
|
|
5142
5189
|
}
|
|
5190
|
+
|
|
5191
|
+
// src/services/hygiene-checklist-pdf.service.ts
|
|
5143
5192
|
function useChecklistPdfService() {
|
|
5144
5193
|
async function generateChecklistPdf(scheduleId) {
|
|
5145
5194
|
const db = import_node_server_utils19.useAtlas.getDb();
|
|
@@ -7021,7 +7070,11 @@ var SCHEDULE_FIELDS = {
|
|
|
7021
7070
|
startDate: 1,
|
|
7022
7071
|
endDate: 1,
|
|
7023
7072
|
paused: 1,
|
|
7024
|
-
lastRunDate: 1
|
|
7073
|
+
lastRunDate: 1,
|
|
7074
|
+
// when it was saved: a task saved after its time today waits for its next
|
|
7075
|
+
// day, so Next visit must know it (else it says "today" for a visit that never comes)
|
|
7076
|
+
createdAt: 1,
|
|
7077
|
+
updatedAt: 1
|
|
7025
7078
|
};
|
|
7026
7079
|
function useScheduleTaskRepository() {
|
|
7027
7080
|
const db = import_node_server_utils33.useAtlas.getDb();
|
|
@@ -7266,7 +7319,6 @@ function useScheduleTaskRepository() {
|
|
|
7266
7319
|
description: 1,
|
|
7267
7320
|
areas: 1,
|
|
7268
7321
|
status: 1,
|
|
7269
|
-
createdAt: 1,
|
|
7270
7322
|
site: 1,
|
|
7271
7323
|
serviceType: 1,
|
|
7272
7324
|
...SCHEDULE_FIELDS
|
|
@@ -7391,11 +7443,23 @@ function useScheduleTaskRepository() {
|
|
|
7391
7443
|
};
|
|
7392
7444
|
}
|
|
7393
7445
|
|
|
7446
|
+
// src/utils/schedule-task-set.util.ts
|
|
7447
|
+
function buildScheduleTaskSets(task, units, startSet, count = 1) {
|
|
7448
|
+
return Array.from({ length: count }, (_, i) => ({
|
|
7449
|
+
set: startSet + i,
|
|
7450
|
+
units,
|
|
7451
|
+
isScheduleTask: true,
|
|
7452
|
+
scheduleTaskId: task._id,
|
|
7453
|
+
scheduleTaskTitle: task.title,
|
|
7454
|
+
scheduleTaskTime: task.time
|
|
7455
|
+
}));
|
|
7456
|
+
}
|
|
7457
|
+
|
|
7394
7458
|
// src/services/hygiene-schedule-task.service.ts
|
|
7395
7459
|
var import_mongodb20 = require("mongodb");
|
|
7396
7460
|
var import_node_server_utils34 = require("@7365admin1/node-server-utils");
|
|
7397
7461
|
function useScheduleTaskService() {
|
|
7398
|
-
const { createParentChecklist } = useParentChecklistRepo();
|
|
7462
|
+
const { createParentChecklist, reopenParentChecklist } = useParentChecklistRepo();
|
|
7399
7463
|
const { getAllScheduleTask, markScheduleTaskRan } = useScheduleTaskRepository();
|
|
7400
7464
|
const {
|
|
7401
7465
|
createAreaChecklist,
|
|
@@ -7466,7 +7530,7 @@ function useScheduleTaskService() {
|
|
|
7466
7530
|
const parentChecklistIds = await createParentChecklist({
|
|
7467
7531
|
site: scheduleTask.site.toString(),
|
|
7468
7532
|
serviceType,
|
|
7469
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
7533
|
+
createdAt: currentDate ?? /* @__PURE__ */ new Date()
|
|
7470
7534
|
});
|
|
7471
7535
|
const parentChecklistId = Array.isArray(parentChecklistIds) ? parentChecklistIds[0] : parentChecklistIds;
|
|
7472
7536
|
import_node_server_utils34.logger.info(
|
|
@@ -7529,22 +7593,13 @@ function useScheduleTaskService() {
|
|
|
7529
7593
|
);
|
|
7530
7594
|
}
|
|
7531
7595
|
if (existingAreaChecklist) {
|
|
7532
|
-
const areaSetConfig = Number(areaDetails.set) || 1;
|
|
7533
7596
|
const maxSetInChecklist = existingAreaChecklist.checklist?.length ? Math.max(
|
|
7534
7597
|
...existingAreaChecklist.checklist.map(
|
|
7535
7598
|
(c) => c.set
|
|
7536
7599
|
)
|
|
7537
7600
|
) : 0;
|
|
7538
7601
|
const startSetNumber = maxSetInChecklist + 1;
|
|
7539
|
-
const newSets =
|
|
7540
|
-
{ length: areaSetConfig },
|
|
7541
|
-
(_, index) => ({
|
|
7542
|
-
set: startSetNumber + index,
|
|
7543
|
-
units,
|
|
7544
|
-
isScheduleTask: true,
|
|
7545
|
-
scheduleTaskId: scheduleTask._id
|
|
7546
|
-
})
|
|
7547
|
-
);
|
|
7602
|
+
const newSets = buildScheduleTaskSets(scheduleTask, units, startSetNumber);
|
|
7548
7603
|
const modified = await pushScheduleTaskSets(
|
|
7549
7604
|
parentChecklistId.toString(),
|
|
7550
7605
|
serviceType,
|
|
@@ -7555,7 +7610,7 @@ function useScheduleTaskService() {
|
|
|
7555
7610
|
if (modified > 0) {
|
|
7556
7611
|
addedAreas.push(area.name);
|
|
7557
7612
|
import_node_server_utils34.logger.info(
|
|
7558
|
-
`Appended
|
|
7613
|
+
`Appended extra-visit set ${startSetNumber} to area checklist for area ${area.name}`
|
|
7559
7614
|
);
|
|
7560
7615
|
} else {
|
|
7561
7616
|
import_node_server_utils34.logger.info(
|
|
@@ -7563,17 +7618,7 @@ function useScheduleTaskService() {
|
|
|
7563
7618
|
);
|
|
7564
7619
|
}
|
|
7565
7620
|
} else {
|
|
7566
|
-
const
|
|
7567
|
-
const schedTaskId = scheduleTask._id;
|
|
7568
|
-
const schedTaskSets = Array.from(
|
|
7569
|
-
{ length: areaSetConfig },
|
|
7570
|
-
(_, index) => ({
|
|
7571
|
-
set: index + 1,
|
|
7572
|
-
units,
|
|
7573
|
-
isScheduleTask: true,
|
|
7574
|
-
scheduleTaskId: schedTaskId
|
|
7575
|
-
})
|
|
7576
|
-
);
|
|
7621
|
+
const schedTaskSets = buildScheduleTaskSets(scheduleTask, units, 1);
|
|
7577
7622
|
const checklistData = {
|
|
7578
7623
|
schedule: parentChecklistId.toString(),
|
|
7579
7624
|
serviceType,
|
|
@@ -7595,6 +7640,13 @@ function useScheduleTaskService() {
|
|
|
7595
7640
|
continue;
|
|
7596
7641
|
}
|
|
7597
7642
|
}
|
|
7643
|
+
if (addedAreas.length > 0) {
|
|
7644
|
+
try {
|
|
7645
|
+
await reopenParentChecklist(parentChecklistId);
|
|
7646
|
+
} catch (error) {
|
|
7647
|
+
import_node_server_utils34.logger.error(`Could not reopen day list ${parentChecklistId}`, error);
|
|
7648
|
+
}
|
|
7649
|
+
}
|
|
7598
7650
|
const attemptKey = `${scheduleTask._id}:${today}`;
|
|
7599
7651
|
const tried = (attempts.get(attemptKey) ?? 0) + 1;
|
|
7600
7652
|
attempts.set(attemptKey, tried);
|
|
@@ -7744,8 +7796,8 @@ function useScheduleTaskController() {
|
|
|
7744
7796
|
const optional = Object.fromEntries(
|
|
7745
7797
|
Object.entries(scheduleTaskFields).map(([key, rule]) => [
|
|
7746
7798
|
key,
|
|
7747
|
-
key === "dates" ? import_joi19.default.array().
|
|
7748
|
-
"array.
|
|
7799
|
+
key === "dates" ? import_joi19.default.array().items(scheduleDate).optional().messages({
|
|
7800
|
+
"array.base": "Dates must be a list of dates."
|
|
7749
7801
|
}) : rule.optional()
|
|
7750
7802
|
])
|
|
7751
7803
|
);
|