@7365admin1/module-hygiene 4.29.1-staging.16 → 4.29.1-staging.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2968,6 +2968,18 @@ function useParentChecklistRepo() {
2968
2968
  throw error;
2969
2969
  }
2970
2970
  }
2971
+ async function reopenParentChecklist(_id) {
2972
+ const res = await collection.updateOne(
2973
+ { _id: new ObjectId7(_id), status: "completed" },
2974
+ { $set: { status: "ongoing", updatedAt: /* @__PURE__ */ new Date() }, $unset: { completedAt: "" } }
2975
+ );
2976
+ if (res.modifiedCount > 0) {
2977
+ delNamespace().catch((err) => {
2978
+ logger14.error(`Failed to clear cache for namespace: ${namespace_collection}`, err);
2979
+ });
2980
+ }
2981
+ return res.modifiedCount;
2982
+ }
2971
2983
  async function getHygieneSiteIds() {
2972
2984
  const query = {
2973
2985
  status: { $ne: "deleted" }
@@ -3074,6 +3086,7 @@ function useParentChecklistRepo() {
3074
3086
  getAllParentChecklist,
3075
3087
  getParentChecklistById,
3076
3088
  updateParentChecklistStatuses,
3089
+ reopenParentChecklist,
3077
3090
  getHygieneSiteIds,
3078
3091
  closeExpiredParentChecklists,
3079
3092
  getTodayParentChecklists,
@@ -3186,7 +3199,9 @@ var areaChecklistSchema = Joi9.object({
3186
3199
  }).required()
3187
3200
  ).min(1).required(),
3188
3201
  isScheduleTask: Joi9.boolean().optional().default(false),
3189
- scheduleTaskId: Joi9.string().hex().optional().allow(null)
3202
+ scheduleTaskId: Joi9.string().hex().optional().allow(null),
3203
+ scheduleTaskTitle: Joi9.string().optional().allow("", null),
3204
+ scheduleTaskTime: Joi9.string().optional().allow("", null)
3190
3205
  }).required()
3191
3206
  ).optional().default([])
3192
3207
  });
@@ -3216,6 +3231,8 @@ function MAreaChecklist(value) {
3216
3231
  set: checklistItem.set,
3217
3232
  isScheduleTask: checklistItem.isScheduleTask ?? false,
3218
3233
  scheduleTaskId: checklistItem.scheduleTaskId ?? void 0,
3234
+ scheduleTaskTitle: checklistItem.scheduleTaskTitle ?? void 0,
3235
+ scheduleTaskTime: checklistItem.scheduleTaskTime ?? void 0,
3219
3236
  units: checklistItem.units.map((unit) => ({
3220
3237
  unit: new ObjectId8(unit.unit),
3221
3238
  name: unit.name,
@@ -3710,6 +3727,9 @@ function useAreaChecklistRepo() {
3710
3727
  isScheduleTask: {
3711
3728
  $ifNull: ["$checklist.isScheduleTask", false]
3712
3729
  },
3730
+ scheduleTaskId: { $ifNull: ["$checklist.scheduleTaskId", null] },
3731
+ scheduleTaskTitle: { $ifNull: ["$checklist.scheduleTaskTitle", null] },
3732
+ scheduleTaskTime: { $ifNull: ["$checklist.scheduleTaskTime", null] },
3713
3733
  unit: "$checklist.units.unit",
3714
3734
  name: "$checklist.units.name",
3715
3735
  approve: "$checklist.units.approve",
@@ -3746,6 +3766,9 @@ function useAreaChecklistRepo() {
3746
3766
  $group: {
3747
3767
  _id: "$set",
3748
3768
  isScheduleTask: { $first: "$isScheduleTask" },
3769
+ scheduleTaskId: { $first: "$scheduleTaskId" },
3770
+ scheduleTaskTitle: { $first: "$scheduleTaskTitle" },
3771
+ scheduleTaskTime: { $first: "$scheduleTaskTime" },
3749
3772
  units: {
3750
3773
  $push: {
3751
3774
  unit: "$unit",
@@ -3766,6 +3789,9 @@ function useAreaChecklistRepo() {
3766
3789
  _id: 0,
3767
3790
  set: "$_id",
3768
3791
  isScheduleTask: 1,
3792
+ scheduleTaskId: 1,
3793
+ scheduleTaskTitle: 1,
3794
+ scheduleTaskTime: 1,
3769
3795
  units: 1
3770
3796
  }
3771
3797
  },
@@ -3897,6 +3923,8 @@ function useAreaChecklistRepo() {
3897
3923
  isScheduleTask: {
3898
3924
  $ifNull: ["$checklist.isScheduleTask", false]
3899
3925
  },
3926
+ scheduleTaskTitle: { $ifNull: ["$checklist.scheduleTaskTitle", null] },
3927
+ scheduleTaskTime: { $ifNull: ["$checklist.scheduleTaskTime", null] },
3900
3928
  scheduleTaskId: {
3901
3929
  $ifNull: ["$checklist.scheduleTaskId", null]
3902
3930
  },
@@ -3937,6 +3965,8 @@ function useAreaChecklistRepo() {
3937
3965
  $group: {
3938
3966
  _id: "$set",
3939
3967
  isScheduleTask: { $first: "$isScheduleTask" },
3968
+ scheduleTaskTitle: { $first: "$scheduleTaskTitle" },
3969
+ scheduleTaskTime: { $first: "$scheduleTaskTime" },
3940
3970
  scheduleTaskId: { $first: "$scheduleTaskId" },
3941
3971
  remarks: { $first: "$remarks" },
3942
3972
  attachment: { $first: "$attachment" },
@@ -3961,6 +3991,8 @@ function useAreaChecklistRepo() {
3961
3991
  _id: 0,
3962
3992
  set: "$_id",
3963
3993
  isScheduleTask: 1,
3994
+ scheduleTaskTitle: 1,
3995
+ scheduleTaskTime: 1,
3964
3996
  scheduleTaskId: 1,
3965
3997
  remarks: "$remarks",
3966
3998
  attachment: "$attachment",
@@ -4283,6 +4315,10 @@ function useAreaChecklistRepo() {
4283
4315
  }
4284
4316
  );
4285
4317
  if (result.modifiedCount > 0) {
4318
+ await collection.updateOne(
4319
+ { schedule, serviceType, area, status: "completed" },
4320
+ { $set: { status: "ongoing", updatedAt: /* @__PURE__ */ new Date() }, $unset: { completedAt: "" } }
4321
+ );
4286
4322
  delNamespace().catch((err) => {
4287
4323
  logger17.error(
4288
4324
  `Failed to clear cache for namespace: ${namespace_collection}`,
@@ -4579,6 +4615,9 @@ function validateScheduleRules(task, now = /* @__PURE__ */ new Date()) {
4579
4615
  }
4580
4616
  if (task.endDate && task.endDate < today)
4581
4617
  return "The end date has already passed.";
4618
+ if (!repeating && !(task.dates ?? []).length) {
4619
+ return "Pick at least one date, or choose a repeat.";
4620
+ }
4582
4621
  if (!repeating) {
4583
4622
  const dates = (task.dates ?? []).filter((d) => !task.endDate || d <= task.endDate);
4584
4623
  if (dates.length && dates.every((d) => d < today)) {
@@ -4945,6 +4984,8 @@ import { AppServiceType as AppServiceType10 } from "@7365admin1/core";
4945
4984
  import { launch } from "puppeteer";
4946
4985
  import { InternalServerError as InternalServerError6, useAtlas as useAtlas8 } from "@7365admin1/node-server-utils";
4947
4986
  import { ObjectId as ObjectId11 } from "mongodb";
4987
+
4988
+ // src/utils/checklist-pdf-html.util.ts
4948
4989
  function escapeHtml(text) {
4949
4990
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
4950
4991
  }
@@ -4957,7 +4998,7 @@ function buildChecklistHtml(areaChecklists) {
4957
4998
  const unitRows = (setItem.units || []).map(
4958
4999
  (unit) => `
4959
5000
  <tr>
4960
- <td class="unit-name">${escapeHtml(unit.name || "")}</td>
5001
+ <td class="unit-name">${escapeHtml(unit.name || "")}${unit.approve || unit.reject ? "" : ' <span class="missed-label">Missed</span>'}</td>
4961
5002
  <td class="icon-cell">${unit.reject ? '<span class="reject-icon">&#10007;</span>' : ""}</td>
4962
5003
  <td class="icon-cell">${unit.approve ? '<span class="approve-icon">&#10003;</span>' : ""}</td>
4963
5004
  </tr>`
@@ -5094,6 +5135,12 @@ function buildChecklistHtml(areaChecklists) {
5094
5135
  font-size: 16px;
5095
5136
  font-weight: bold;
5096
5137
  }
5138
+ .missed-label {
5139
+ color: #b3261e;
5140
+ font-size: 11px;
5141
+ font-weight: bold;
5142
+ margin-left: 6px;
5143
+ }
5097
5144
  .reject-icon {
5098
5145
  color: #e74c3c;
5099
5146
  font-size: 16px;
@@ -5109,6 +5156,8 @@ function buildChecklistHtml(areaChecklists) {
5109
5156
  </body>
5110
5157
  </html>`;
5111
5158
  }
5159
+
5160
+ // src/services/hygiene-checklist-pdf.service.ts
5112
5161
  function useChecklistPdfService() {
5113
5162
  async function generateChecklistPdf(scheduleId) {
5114
5163
  const db = useAtlas8.getDb();
@@ -7029,7 +7078,11 @@ var SCHEDULE_FIELDS = {
7029
7078
  startDate: 1,
7030
7079
  endDate: 1,
7031
7080
  paused: 1,
7032
- lastRunDate: 1
7081
+ lastRunDate: 1,
7082
+ // when it was saved: a task saved after its time today waits for its next
7083
+ // day, so Next visit must know it (else it says "today" for a visit that never comes)
7084
+ createdAt: 1,
7085
+ updatedAt: 1
7033
7086
  };
7034
7087
  function useScheduleTaskRepository() {
7035
7088
  const db = useAtlas14.getDb();
@@ -7274,7 +7327,6 @@ function useScheduleTaskRepository() {
7274
7327
  description: 1,
7275
7328
  areas: 1,
7276
7329
  status: 1,
7277
- createdAt: 1,
7278
7330
  site: 1,
7279
7331
  serviceType: 1,
7280
7332
  ...SCHEDULE_FIELDS
@@ -7399,11 +7451,23 @@ function useScheduleTaskRepository() {
7399
7451
  };
7400
7452
  }
7401
7453
 
7454
+ // src/utils/schedule-task-set.util.ts
7455
+ function buildScheduleTaskSets(task, units, startSet, count = 1) {
7456
+ return Array.from({ length: count }, (_, i) => ({
7457
+ set: startSet + i,
7458
+ units,
7459
+ isScheduleTask: true,
7460
+ scheduleTaskId: task._id,
7461
+ scheduleTaskTitle: task.title,
7462
+ scheduleTaskTime: task.time
7463
+ }));
7464
+ }
7465
+
7402
7466
  // src/services/hygiene-schedule-task.service.ts
7403
7467
  import { ObjectId as ObjectId20 } from "mongodb";
7404
7468
  import { logger as logger32 } from "@7365admin1/node-server-utils";
7405
7469
  function useScheduleTaskService() {
7406
- const { createParentChecklist } = useParentChecklistRepo();
7470
+ const { createParentChecklist, reopenParentChecklist } = useParentChecklistRepo();
7407
7471
  const { getAllScheduleTask, markScheduleTaskRan } = useScheduleTaskRepository();
7408
7472
  const {
7409
7473
  createAreaChecklist,
@@ -7474,7 +7538,7 @@ function useScheduleTaskService() {
7474
7538
  const parentChecklistIds = await createParentChecklist({
7475
7539
  site: scheduleTask.site.toString(),
7476
7540
  serviceType,
7477
- createdAt: /* @__PURE__ */ new Date()
7541
+ createdAt: currentDate ?? /* @__PURE__ */ new Date()
7478
7542
  });
7479
7543
  const parentChecklistId = Array.isArray(parentChecklistIds) ? parentChecklistIds[0] : parentChecklistIds;
7480
7544
  logger32.info(
@@ -7537,22 +7601,13 @@ function useScheduleTaskService() {
7537
7601
  );
7538
7602
  }
7539
7603
  if (existingAreaChecklist) {
7540
- const areaSetConfig = Number(areaDetails.set) || 1;
7541
7604
  const maxSetInChecklist = existingAreaChecklist.checklist?.length ? Math.max(
7542
7605
  ...existingAreaChecklist.checklist.map(
7543
7606
  (c) => c.set
7544
7607
  )
7545
7608
  ) : 0;
7546
7609
  const startSetNumber = maxSetInChecklist + 1;
7547
- const newSets = Array.from(
7548
- { length: areaSetConfig },
7549
- (_, index) => ({
7550
- set: startSetNumber + index,
7551
- units,
7552
- isScheduleTask: true,
7553
- scheduleTaskId: scheduleTask._id
7554
- })
7555
- );
7610
+ const newSets = buildScheduleTaskSets(scheduleTask, units, startSetNumber);
7556
7611
  const modified = await pushScheduleTaskSets(
7557
7612
  parentChecklistId.toString(),
7558
7613
  serviceType,
@@ -7563,7 +7618,7 @@ function useScheduleTaskService() {
7563
7618
  if (modified > 0) {
7564
7619
  addedAreas.push(area.name);
7565
7620
  logger32.info(
7566
- `Appended ${areaSetConfig} set(s) starting from ${startSetNumber} to area checklist for area ${area.name}`
7621
+ `Appended extra-visit set ${startSetNumber} to area checklist for area ${area.name}`
7567
7622
  );
7568
7623
  } else {
7569
7624
  logger32.info(
@@ -7571,17 +7626,7 @@ function useScheduleTaskService() {
7571
7626
  );
7572
7627
  }
7573
7628
  } else {
7574
- const areaSetConfig = Number(areaDetails.set) || 1;
7575
- const schedTaskId = scheduleTask._id;
7576
- const schedTaskSets = Array.from(
7577
- { length: areaSetConfig },
7578
- (_, index) => ({
7579
- set: index + 1,
7580
- units,
7581
- isScheduleTask: true,
7582
- scheduleTaskId: schedTaskId
7583
- })
7584
- );
7629
+ const schedTaskSets = buildScheduleTaskSets(scheduleTask, units, 1);
7585
7630
  const checklistData = {
7586
7631
  schedule: parentChecklistId.toString(),
7587
7632
  serviceType,
@@ -7603,6 +7648,13 @@ function useScheduleTaskService() {
7603
7648
  continue;
7604
7649
  }
7605
7650
  }
7651
+ if (addedAreas.length > 0) {
7652
+ try {
7653
+ await reopenParentChecklist(parentChecklistId);
7654
+ } catch (error) {
7655
+ logger32.error(`Could not reopen day list ${parentChecklistId}`, error);
7656
+ }
7657
+ }
7606
7658
  const attemptKey = `${scheduleTask._id}:${today}`;
7607
7659
  const tried = (attempts.get(attemptKey) ?? 0) + 1;
7608
7660
  attempts.set(attemptKey, tried);
@@ -7752,8 +7804,8 @@ function useScheduleTaskController() {
7752
7804
  const optional = Object.fromEntries(
7753
7805
  Object.entries(scheduleTaskFields).map(([key, rule]) => [
7754
7806
  key,
7755
- key === "dates" ? Joi19.array().min(1).items(scheduleDate).optional().messages({
7756
- "array.min": "Pick at least one date, or choose a repeat."
7807
+ key === "dates" ? Joi19.array().items(scheduleDate).optional().messages({
7808
+ "array.base": "Dates must be a list of dates."
7757
7809
  }) : rule.optional()
7758
7810
  ])
7759
7811
  );