@iservice365/module-hygiene 0.1.2 → 0.2.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 +6 -0
- package/dist/index.d.ts +98 -271
- package/dist/index.js +1042 -2384
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1135 -2496
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,32 +33,21 @@ __export(src_exports, {
|
|
|
33
33
|
MArea: () => MArea,
|
|
34
34
|
MAreaChecklist: () => MAreaChecklist,
|
|
35
35
|
MParentChecklist: () => MParentChecklist,
|
|
36
|
-
MScheduleTaskArea: () => MScheduleTaskArea,
|
|
37
|
-
MToiletLocation: () => MToiletLocation,
|
|
38
36
|
MUnit: () => MUnit,
|
|
39
37
|
MUnitChecklist: () => MUnitChecklist,
|
|
40
|
-
|
|
41
|
-
allowedTypes: () => allowedTypes,
|
|
38
|
+
allowedChecklistStatus: () => allowedChecklistStatus,
|
|
42
39
|
areaChecklistSchema: () => areaChecklistSchema,
|
|
43
40
|
areaSchema: () => areaSchema,
|
|
44
41
|
parentChecklistSchema: () => parentChecklistSchema,
|
|
45
|
-
scheduleTaskAreaSchema: () => scheduleTaskAreaSchema,
|
|
46
|
-
toiletLocationSchema: () => toiletLocationSchema,
|
|
47
42
|
unitChecklistSchema: () => unitChecklistSchema,
|
|
48
43
|
unitSchema: () => unitSchema,
|
|
49
44
|
useAreaChecklistController: () => useAreaChecklistController,
|
|
50
45
|
useAreaChecklistRepo: () => useAreaChecklistRepo,
|
|
51
46
|
useAreaController: () => useAreaController,
|
|
52
|
-
|
|
47
|
+
useAreaRepo: () => useAreaRepo,
|
|
53
48
|
useAreaService: () => useAreaService,
|
|
54
49
|
useParentChecklistController: () => useParentChecklistController,
|
|
55
50
|
useParentChecklistRepo: () => useParentChecklistRepo,
|
|
56
|
-
useScheduleTaskAreaController: () => useScheduleTaskAreaController,
|
|
57
|
-
useScheduleTaskAreaRepository: () => useScheduleTaskAreaRepository,
|
|
58
|
-
useScheduleTaskAreaService: () => useScheduleTaskAreaService,
|
|
59
|
-
useToiletLocationController: () => useToiletLocationController,
|
|
60
|
-
useToiletLocationRepository: () => useToiletLocationRepository,
|
|
61
|
-
useToiletLocationService: () => useToiletLocationService,
|
|
62
51
|
useUnitChecklistController: () => useUnitChecklistController,
|
|
63
52
|
useUnitChecklistRepo: () => useUnitChecklistRepo,
|
|
64
53
|
useUnitController: () => useUnitController,
|
|
@@ -71,16 +60,25 @@ module.exports = __toCommonJS(src_exports);
|
|
|
71
60
|
var import_node_server_utils = require("@iservice365/node-server-utils");
|
|
72
61
|
var import_joi = __toESM(require("joi"));
|
|
73
62
|
var import_mongodb = require("mongodb");
|
|
63
|
+
|
|
64
|
+
// src/models/hygiene-base.model.ts
|
|
65
|
+
var allowedTypes = ["common", "toilet"];
|
|
66
|
+
var allowedStatus = ["ready", "ongoing", "completed"];
|
|
67
|
+
|
|
68
|
+
// src/models/hygiene-area.model.ts
|
|
74
69
|
var areaSchema = import_joi.default.object({
|
|
75
|
-
name: import_joi.default.string().required(),
|
|
76
70
|
site: import_joi.default.string().hex().required(),
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
name: import_joi.default.string().required(),
|
|
72
|
+
type: import_joi.default.string().valid(...allowedTypes).required(),
|
|
73
|
+
set: import_joi.default.number().min(0).optional(),
|
|
74
|
+
units: import_joi.default.array().items(
|
|
79
75
|
import_joi.default.object({
|
|
80
|
-
|
|
76
|
+
unit: import_joi.default.string().hex().required(),
|
|
81
77
|
name: import_joi.default.string().required()
|
|
82
|
-
})
|
|
83
|
-
).
|
|
78
|
+
}).optional()
|
|
79
|
+
).min(1).unique("unit", { ignoreUndefined: true }).messages({
|
|
80
|
+
"array.unique": "Duplicate area units are not allowed"
|
|
81
|
+
})
|
|
84
82
|
});
|
|
85
83
|
function MArea(value) {
|
|
86
84
|
const { error } = areaSchema.validate(value);
|
|
@@ -95,56 +93,58 @@ function MArea(value) {
|
|
|
95
93
|
throw new import_node_server_utils.BadRequestError("Invalid site ID format.");
|
|
96
94
|
}
|
|
97
95
|
}
|
|
98
|
-
if (value.
|
|
99
|
-
|
|
100
|
-
value.createdBy = new import_mongodb.ObjectId(value.createdBy);
|
|
101
|
-
} catch (error2) {
|
|
102
|
-
throw new import_node_server_utils.BadRequestError("Invalid createdBy ID format.");
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
if (value.checklist && Array.isArray(value.checklist)) {
|
|
106
|
-
value.checklist = value.checklist.map((item) => {
|
|
96
|
+
if (value.units && Array.isArray(value.units)) {
|
|
97
|
+
value.units = value.units.map((item) => {
|
|
107
98
|
try {
|
|
108
99
|
return {
|
|
109
100
|
...item,
|
|
110
|
-
|
|
101
|
+
unit: new import_mongodb.ObjectId(item.unit)
|
|
111
102
|
};
|
|
112
103
|
} catch (error2) {
|
|
113
|
-
throw new import_node_server_utils.BadRequestError(
|
|
114
|
-
`Invalid checklist item ID format: ${item._id}`
|
|
115
|
-
);
|
|
104
|
+
throw new import_node_server_utils.BadRequestError(`Invalid unit ID format: ${item.unit}`);
|
|
116
105
|
}
|
|
117
106
|
});
|
|
118
107
|
}
|
|
119
108
|
return {
|
|
120
|
-
name: value.name,
|
|
121
109
|
site: value.site,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
110
|
+
name: value.name,
|
|
111
|
+
type: value.type,
|
|
112
|
+
set: value.set ?? 0,
|
|
113
|
+
units: value.units ?? [],
|
|
114
|
+
status: "active",
|
|
125
115
|
createdAt: /* @__PURE__ */ new Date(),
|
|
126
|
-
updatedAt:
|
|
127
|
-
deletedAt:
|
|
116
|
+
updatedAt: "",
|
|
117
|
+
deletedAt: ""
|
|
128
118
|
};
|
|
129
119
|
}
|
|
130
120
|
|
|
131
121
|
// src/repositories/hygiene-area.repository.ts
|
|
132
122
|
var import_mongodb2 = require("mongodb");
|
|
133
123
|
var import_node_server_utils2 = require("@iservice365/node-server-utils");
|
|
134
|
-
|
|
124
|
+
|
|
125
|
+
// src/utils/capitalize-text.ts
|
|
126
|
+
function capitalizeText(text) {
|
|
127
|
+
if (!text)
|
|
128
|
+
return "";
|
|
129
|
+
return text.toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/repositories/hygiene-area.repository.ts
|
|
133
|
+
function useAreaRepo() {
|
|
135
134
|
const db = import_node_server_utils2.useAtlas.getDb();
|
|
136
135
|
if (!db) {
|
|
137
136
|
throw new import_node_server_utils2.InternalServerError("Unable to connect to server.");
|
|
138
137
|
}
|
|
139
|
-
const namespace_collection = "
|
|
138
|
+
const namespace_collection = "site.cleaning.areas";
|
|
140
139
|
const collection = db.collection(namespace_collection);
|
|
141
140
|
const { delNamespace, setCache, getCache } = (0, import_node_server_utils2.useCache)(namespace_collection);
|
|
142
141
|
async function createIndex() {
|
|
143
142
|
try {
|
|
144
143
|
await collection.createIndexes([
|
|
145
144
|
{ key: { site: 1 } },
|
|
146
|
-
{ key: {
|
|
147
|
-
{ key: { status: 1 } }
|
|
145
|
+
{ key: { type: 1 } },
|
|
146
|
+
{ key: { status: 1 } },
|
|
147
|
+
{ key: { "units.unit": 1 } }
|
|
148
148
|
]);
|
|
149
149
|
} catch (error) {
|
|
150
150
|
throw new import_node_server_utils2.InternalServerError("Failed to create index on hygiene area.");
|
|
@@ -162,7 +162,7 @@ function useAreaRepository() {
|
|
|
162
162
|
async function createUniqueIndex() {
|
|
163
163
|
try {
|
|
164
164
|
await collection.createIndex(
|
|
165
|
-
{ name: 1,
|
|
165
|
+
{ site: 1, name: 1, type: 1, deletedAt: 1 },
|
|
166
166
|
{ unique: true }
|
|
167
167
|
);
|
|
168
168
|
} catch (error) {
|
|
@@ -187,7 +187,9 @@ function useAreaRepository() {
|
|
|
187
187
|
} catch (error) {
|
|
188
188
|
const isDuplicated = error.message.includes("duplicate");
|
|
189
189
|
if (isDuplicated) {
|
|
190
|
-
throw new import_node_server_utils2.BadRequestError(
|
|
190
|
+
throw new import_node_server_utils2.BadRequestError(
|
|
191
|
+
`${capitalizeText(value.type)} area already exists.`
|
|
192
|
+
);
|
|
191
193
|
}
|
|
192
194
|
throw error;
|
|
193
195
|
}
|
|
@@ -196,9 +198,7 @@ function useAreaRepository() {
|
|
|
196
198
|
page = 1,
|
|
197
199
|
limit = 10,
|
|
198
200
|
search = "",
|
|
199
|
-
|
|
200
|
-
endDate = "",
|
|
201
|
-
site = ""
|
|
201
|
+
site
|
|
202
202
|
}) {
|
|
203
203
|
page = page > 0 ? page - 1 : 0;
|
|
204
204
|
const query = {
|
|
@@ -208,32 +208,17 @@ function useAreaRepository() {
|
|
|
208
208
|
page,
|
|
209
209
|
limit
|
|
210
210
|
};
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
211
|
+
try {
|
|
212
|
+
site = new import_mongodb2.ObjectId(site);
|
|
213
|
+
query.site = site;
|
|
214
|
+
cacheOptions.site = site.toString();
|
|
215
|
+
} catch (error) {
|
|
216
|
+
throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
|
|
218
217
|
}
|
|
219
218
|
if (search) {
|
|
220
219
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
221
220
|
cacheOptions.search = search;
|
|
222
221
|
}
|
|
223
|
-
if (startDate && endDate) {
|
|
224
|
-
query.createdAt = {
|
|
225
|
-
$gte: new Date(startDate),
|
|
226
|
-
$lte: new Date(endDate)
|
|
227
|
-
};
|
|
228
|
-
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
229
|
-
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
230
|
-
} else if (startDate) {
|
|
231
|
-
query.createdAt = { $gte: new Date(startDate) };
|
|
232
|
-
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
233
|
-
} else if (endDate) {
|
|
234
|
-
query.createdAt = { $lte: new Date(endDate) };
|
|
235
|
-
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
236
|
-
}
|
|
237
222
|
const cacheKey = (0, import_node_server_utils2.makeCacheKey)(namespace_collection, cacheOptions);
|
|
238
223
|
const cachedData = await getCache(cacheKey);
|
|
239
224
|
if (cachedData) {
|
|
@@ -243,45 +228,11 @@ function useAreaRepository() {
|
|
|
243
228
|
try {
|
|
244
229
|
const items = await collection.aggregate([
|
|
245
230
|
{ $match: query },
|
|
246
|
-
{
|
|
247
|
-
$lookup: {
|
|
248
|
-
from: "sites",
|
|
249
|
-
localField: "site",
|
|
250
|
-
foreignField: "_id",
|
|
251
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
252
|
-
as: "site"
|
|
253
|
-
}
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
$unwind: {
|
|
257
|
-
path: "$site",
|
|
258
|
-
preserveNullAndEmptyArrays: true
|
|
259
|
-
}
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
$lookup: {
|
|
263
|
-
from: "users",
|
|
264
|
-
localField: "createdBy",
|
|
265
|
-
foreignField: "_id",
|
|
266
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
267
|
-
as: "createdBy"
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
$unwind: {
|
|
272
|
-
path: "$createdBy",
|
|
273
|
-
preserveNullAndEmptyArrays: true
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
231
|
{
|
|
277
232
|
$project: {
|
|
278
233
|
name: 1,
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
createdByName: "$createdBy.name",
|
|
282
|
-
checklist: 1,
|
|
283
|
-
status: 1,
|
|
284
|
-
createdAt: 1
|
|
234
|
+
type: 1,
|
|
235
|
+
set: 1
|
|
285
236
|
}
|
|
286
237
|
},
|
|
287
238
|
{ $sort: { _id: -1 } },
|
|
@@ -300,6 +251,47 @@ function useAreaRepository() {
|
|
|
300
251
|
throw error;
|
|
301
252
|
}
|
|
302
253
|
}
|
|
254
|
+
async function getAreasForChecklist({
|
|
255
|
+
site,
|
|
256
|
+
type
|
|
257
|
+
}) {
|
|
258
|
+
const query = { type, status: { $ne: "deleted" } };
|
|
259
|
+
const cacheOptions = { type };
|
|
260
|
+
try {
|
|
261
|
+
site = new import_mongodb2.ObjectId(site);
|
|
262
|
+
query.site = site;
|
|
263
|
+
cacheOptions.site = site.toString();
|
|
264
|
+
} catch (error) {
|
|
265
|
+
throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
|
|
266
|
+
}
|
|
267
|
+
const cacheKey = (0, import_node_server_utils2.makeCacheKey)(namespace_collection, cacheOptions);
|
|
268
|
+
const cachedData = await getCache(cacheKey);
|
|
269
|
+
if (cachedData) {
|
|
270
|
+
import_node_server_utils2.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
271
|
+
return cachedData;
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
const items = await collection.aggregate([
|
|
275
|
+
{ $match: query },
|
|
276
|
+
{
|
|
277
|
+
$project: {
|
|
278
|
+
name: 1,
|
|
279
|
+
set: 1,
|
|
280
|
+
units: 1
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
{ $sort: { _id: -1 } }
|
|
284
|
+
]).toArray();
|
|
285
|
+
setCache(cacheKey, items, 15 * 60).then(() => {
|
|
286
|
+
import_node_server_utils2.logger.info(`Cache set for key: ${cacheKey}`);
|
|
287
|
+
}).catch((err) => {
|
|
288
|
+
import_node_server_utils2.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
289
|
+
});
|
|
290
|
+
return items;
|
|
291
|
+
} catch (error) {
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
303
295
|
async function getAreaById(_id) {
|
|
304
296
|
try {
|
|
305
297
|
_id = new import_mongodb2.ObjectId(_id);
|
|
@@ -324,11 +316,12 @@ function useAreaRepository() {
|
|
|
324
316
|
{
|
|
325
317
|
$project: {
|
|
326
318
|
name: 1,
|
|
327
|
-
|
|
319
|
+
set: 1,
|
|
320
|
+
units: 1
|
|
328
321
|
}
|
|
329
322
|
}
|
|
330
323
|
]).toArray();
|
|
331
|
-
if (!data ||
|
|
324
|
+
if (!data || data.length === 0) {
|
|
332
325
|
throw new import_node_server_utils2.NotFoundError("Area not found.");
|
|
333
326
|
}
|
|
334
327
|
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
@@ -341,22 +334,6 @@ function useAreaRepository() {
|
|
|
341
334
|
throw error;
|
|
342
335
|
}
|
|
343
336
|
}
|
|
344
|
-
async function getAreaByName(name, site) {
|
|
345
|
-
try {
|
|
346
|
-
if (site)
|
|
347
|
-
site = new import_mongodb2.ObjectId(site);
|
|
348
|
-
} catch (error) {
|
|
349
|
-
throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
|
|
350
|
-
}
|
|
351
|
-
try {
|
|
352
|
-
return await collection.findOne({
|
|
353
|
-
name: { $regex: new RegExp(`^${name}$`, "i") },
|
|
354
|
-
...site && { site }
|
|
355
|
-
});
|
|
356
|
-
} catch (error) {
|
|
357
|
-
throw new import_node_server_utils2.BadRequestError("Unable to fetch area by name.");
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
337
|
async function updateArea(_id, value) {
|
|
361
338
|
try {
|
|
362
339
|
_id = new import_mongodb2.ObjectId(_id);
|
|
@@ -364,7 +341,30 @@ function useAreaRepository() {
|
|
|
364
341
|
throw new import_node_server_utils2.BadRequestError("Invalid area ID format.");
|
|
365
342
|
}
|
|
366
343
|
try {
|
|
367
|
-
const updateValue = {
|
|
344
|
+
const updateValue = {
|
|
345
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
346
|
+
};
|
|
347
|
+
if (value.name !== void 0) {
|
|
348
|
+
updateValue.name = value.name;
|
|
349
|
+
}
|
|
350
|
+
if (value.type !== void 0) {
|
|
351
|
+
updateValue.type = value.type;
|
|
352
|
+
}
|
|
353
|
+
if (value.set !== void 0) {
|
|
354
|
+
updateValue.set = value.set;
|
|
355
|
+
}
|
|
356
|
+
if (value.units && Array.isArray(value.units)) {
|
|
357
|
+
updateValue.units = value.units.map((item) => {
|
|
358
|
+
try {
|
|
359
|
+
return {
|
|
360
|
+
...item,
|
|
361
|
+
unit: new import_mongodb2.ObjectId(item.unit)
|
|
362
|
+
};
|
|
363
|
+
} catch (error) {
|
|
364
|
+
throw new import_node_server_utils2.BadRequestError(`Invalid unit ID format: ${item.unit}`);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
368
|
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
369
369
|
if (res.modifiedCount === 0) {
|
|
370
370
|
throw new import_node_server_utils2.InternalServerError("Unable to update cleaning area.");
|
|
@@ -392,17 +392,15 @@ function useAreaRepository() {
|
|
|
392
392
|
} catch (error) {
|
|
393
393
|
throw new import_node_server_utils2.BadRequestError("Invalid area ID format.");
|
|
394
394
|
}
|
|
395
|
-
if (value.
|
|
396
|
-
value.
|
|
395
|
+
if (value.units && Array.isArray(value.units)) {
|
|
396
|
+
value.units = value.units.map((item) => {
|
|
397
397
|
try {
|
|
398
398
|
return {
|
|
399
399
|
...item,
|
|
400
|
-
|
|
400
|
+
unit: new import_mongodb2.ObjectId(item.unit)
|
|
401
401
|
};
|
|
402
402
|
} catch (error) {
|
|
403
|
-
throw new import_node_server_utils2.BadRequestError(
|
|
404
|
-
`Invalid checklist item ID format: ${item._id}`
|
|
405
|
-
);
|
|
403
|
+
throw new import_node_server_utils2.BadRequestError(`Invalid unit ID format: ${item.unit}`);
|
|
406
404
|
}
|
|
407
405
|
});
|
|
408
406
|
}
|
|
@@ -464,8 +462,8 @@ function useAreaRepository() {
|
|
|
464
462
|
createUniqueIndex,
|
|
465
463
|
createArea,
|
|
466
464
|
getAreas,
|
|
465
|
+
getAreasForChecklist,
|
|
467
466
|
getAreaById,
|
|
468
|
-
getAreaByName,
|
|
469
467
|
updateArea,
|
|
470
468
|
updateAreaChecklist,
|
|
471
469
|
deleteArea
|
|
@@ -475,10 +473,9 @@ function useAreaRepository() {
|
|
|
475
473
|
// src/services/hygiene-area.service.ts
|
|
476
474
|
var import_node_server_utils3 = require("@iservice365/node-server-utils");
|
|
477
475
|
function useAreaService() {
|
|
478
|
-
const { createArea: _createArea } =
|
|
479
|
-
async function
|
|
476
|
+
const { createArea: _createArea } = useAreaRepo();
|
|
477
|
+
async function importArea({
|
|
480
478
|
dataJson,
|
|
481
|
-
createdBy,
|
|
482
479
|
site
|
|
483
480
|
}) {
|
|
484
481
|
let dataArray;
|
|
@@ -490,49 +487,101 @@ function useAreaService() {
|
|
|
490
487
|
if (!dataArray || dataArray.length === 0) {
|
|
491
488
|
throw new import_node_server_utils3.NotFoundError("No data found in the uploaded file");
|
|
492
489
|
}
|
|
493
|
-
const session = import_node_server_utils3.useAtlas.getClient()?.startSession();
|
|
494
490
|
const insertedAreaIds = [];
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
491
|
+
const duplicateAreas = [];
|
|
492
|
+
const failedAreas = [];
|
|
493
|
+
const skippedRows = [];
|
|
494
|
+
try {
|
|
495
|
+
for (let i = 0; i < dataArray.length; i++) {
|
|
496
|
+
const row = dataArray[i];
|
|
497
|
+
if (!row?.TYPE) {
|
|
498
|
+
import_node_server_utils3.logger.warn(`Skipping row ${i + 1} with missing TYPE:`, row);
|
|
499
|
+
skippedRows.push(i + 1);
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
const areaType = String(row.TYPE).trim();
|
|
503
|
+
if (!areaType) {
|
|
504
|
+
import_node_server_utils3.logger.warn(`Skipping row ${i + 1} with empty area type`);
|
|
505
|
+
skippedRows.push(i + 1);
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
if (!row?.NAME) {
|
|
509
|
+
import_node_server_utils3.logger.warn(`Skipping row ${i + 1} with missing NAME:`, row);
|
|
510
|
+
skippedRows.push(i + 1);
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
const areaName = String(row.NAME).trim();
|
|
514
|
+
if (!areaName) {
|
|
515
|
+
import_node_server_utils3.logger.warn(`Skipping row ${i + 1} with empty ${areaType} area name`);
|
|
516
|
+
skippedRows.push(i + 1);
|
|
500
517
|
continue;
|
|
501
518
|
}
|
|
502
519
|
try {
|
|
503
|
-
const insertedId = await _createArea(
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
},
|
|
509
|
-
session
|
|
510
|
-
);
|
|
520
|
+
const insertedId = await _createArea({
|
|
521
|
+
type: areaType,
|
|
522
|
+
name: areaName,
|
|
523
|
+
site
|
|
524
|
+
});
|
|
511
525
|
insertedAreaIds.push(insertedId);
|
|
526
|
+
import_node_server_utils3.logger.info(`Successfully created ${areaType} area: ${areaName}`);
|
|
512
527
|
} catch (error) {
|
|
513
528
|
import_node_server_utils3.logger.error(
|
|
514
|
-
`Error creating area "${
|
|
515
|
-
error.message
|
|
529
|
+
`Error creating ${areaType} area "${areaName}": ${error.message}`
|
|
516
530
|
);
|
|
517
|
-
|
|
531
|
+
if (error.message.includes("duplicate")) {
|
|
532
|
+
duplicateAreas.push(areaName);
|
|
533
|
+
} else {
|
|
534
|
+
failedAreas.push(areaName);
|
|
535
|
+
}
|
|
518
536
|
}
|
|
519
537
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
538
|
+
let message = `Upload completed: ${insertedAreaIds.length} areas successfully created`;
|
|
539
|
+
if (duplicateAreas.length > 0) {
|
|
540
|
+
message += `, ${duplicateAreas.length} areas skipped (already exist)`;
|
|
541
|
+
}
|
|
542
|
+
if (failedAreas.length > 0) {
|
|
543
|
+
message += `, ${failedAreas.length} areas failed`;
|
|
544
|
+
}
|
|
545
|
+
if (skippedRows.length > 0) {
|
|
546
|
+
message += `, ${skippedRows.length} rows skipped (invalid data)`;
|
|
547
|
+
}
|
|
548
|
+
import_node_server_utils3.logger.info(message);
|
|
549
|
+
if (insertedAreaIds.length === 0) {
|
|
550
|
+
if (duplicateAreas.length > 0 && failedAreas.length === 0) {
|
|
551
|
+
throw new import_node_server_utils3.BadRequestError(
|
|
552
|
+
`No new areas were created. All ${duplicateAreas.length} areas already exist in the system: ${duplicateAreas.join(", ")}`
|
|
553
|
+
);
|
|
554
|
+
} else if (failedAreas.length > 0) {
|
|
555
|
+
throw new import_node_server_utils3.BadRequestError(
|
|
556
|
+
`No areas were created. Please check your data format and ensure area names are valid.`
|
|
557
|
+
);
|
|
558
|
+
} else if (skippedRows.length > 0) {
|
|
559
|
+
throw new import_node_server_utils3.BadRequestError(
|
|
560
|
+
`No areas were created. All rows contained invalid or missing area names.`
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return { message };
|
|
525
565
|
} catch (error) {
|
|
526
|
-
await session?.abortTransaction();
|
|
527
566
|
import_node_server_utils3.logger.error("Error while uploading area information", error);
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
567
|
+
if (error instanceof import_node_server_utils3.BadRequestError) {
|
|
568
|
+
throw error;
|
|
569
|
+
} else if (error.message.includes("duplicate")) {
|
|
570
|
+
throw new import_node_server_utils3.BadRequestError(
|
|
571
|
+
`Upload failed due to duplicate area names. Please ensure all area names are unique.`
|
|
572
|
+
);
|
|
573
|
+
} else if (error.message.includes("validation")) {
|
|
574
|
+
throw new import_node_server_utils3.BadRequestError(
|
|
575
|
+
"Upload failed due to invalid data format. Please check that all required fields are properly filled."
|
|
576
|
+
);
|
|
577
|
+
} else {
|
|
578
|
+
throw new import_node_server_utils3.BadRequestError(
|
|
579
|
+
`Upload failed: ${error.message || "Please check your data format and try again."}`
|
|
580
|
+
);
|
|
581
|
+
}
|
|
531
582
|
}
|
|
532
583
|
}
|
|
533
|
-
return {
|
|
534
|
-
uploadByFile
|
|
535
|
-
};
|
|
584
|
+
return { importArea };
|
|
536
585
|
}
|
|
537
586
|
|
|
538
587
|
// src/controllers/hygiene-area.controller.ts
|
|
@@ -570,20 +619,15 @@ function convertBufferFile(bufferFile) {
|
|
|
570
619
|
function useAreaController() {
|
|
571
620
|
const {
|
|
572
621
|
createArea: _createArea,
|
|
573
|
-
getAreas:
|
|
622
|
+
getAreas: _getAreas,
|
|
574
623
|
getAreaById: _getAreaById,
|
|
575
624
|
updateArea: _updateArea,
|
|
576
625
|
updateAreaChecklist: _updateAreaChecklist,
|
|
577
626
|
deleteArea: _deleteById
|
|
578
|
-
} =
|
|
579
|
-
const {
|
|
627
|
+
} = useAreaRepo();
|
|
628
|
+
const { importArea: _importArea } = useAreaService();
|
|
580
629
|
async function createArea(req, res, next) {
|
|
581
|
-
const
|
|
582
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
583
|
-
{}
|
|
584
|
-
) : {};
|
|
585
|
-
const createdBy = cookies["user"] || "";
|
|
586
|
-
const payload = { ...req.body, createdBy };
|
|
630
|
+
const payload = { ...req.body, ...req.params };
|
|
587
631
|
const { error } = areaSchema.validate(payload);
|
|
588
632
|
if (error) {
|
|
589
633
|
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
@@ -600,35 +644,30 @@ function useAreaController() {
|
|
|
600
644
|
return;
|
|
601
645
|
}
|
|
602
646
|
}
|
|
603
|
-
async function
|
|
604
|
-
const query = req.query;
|
|
647
|
+
async function getAreas(req, res, next) {
|
|
648
|
+
const query = { ...req.query, ...req.params };
|
|
605
649
|
const validation = import_joi2.default.object({
|
|
606
650
|
page: import_joi2.default.number().min(1).optional().allow("", null),
|
|
607
651
|
limit: import_joi2.default.number().min(1).optional().allow("", null),
|
|
608
652
|
search: import_joi2.default.string().optional().allow("", null),
|
|
609
|
-
|
|
610
|
-
endDate: import_joi2.default.alternatives().try(import_joi2.default.date(), import_joi2.default.string()).optional().allow("", null),
|
|
611
|
-
site: import_joi2.default.string().hex().optional().allow("", null)
|
|
653
|
+
site: import_joi2.default.string().hex().required()
|
|
612
654
|
});
|
|
613
655
|
const { error } = validation.validate(query);
|
|
614
656
|
if (error) {
|
|
657
|
+
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
615
658
|
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
616
659
|
return;
|
|
617
660
|
}
|
|
618
661
|
const page = parseInt(req.query.page) ?? 1;
|
|
619
662
|
const limit = parseInt(req.query.limit) ?? 20;
|
|
620
663
|
const search = req.query.search ?? "";
|
|
621
|
-
const site = req.
|
|
622
|
-
const startDate = req.query.startDate ?? "";
|
|
623
|
-
const endDate = req.query.endDate ?? "";
|
|
664
|
+
const site = req.params.site ?? "";
|
|
624
665
|
try {
|
|
625
|
-
const data = await
|
|
666
|
+
const data = await _getAreas({
|
|
626
667
|
page,
|
|
627
668
|
limit,
|
|
628
669
|
search,
|
|
629
|
-
site
|
|
630
|
-
startDate,
|
|
631
|
-
endDate
|
|
670
|
+
site
|
|
632
671
|
});
|
|
633
672
|
res.json(data);
|
|
634
673
|
return;
|
|
@@ -660,7 +699,17 @@ function useAreaController() {
|
|
|
660
699
|
const payload = { id: req.params.id, ...req.body };
|
|
661
700
|
const schema = import_joi2.default.object({
|
|
662
701
|
id: import_joi2.default.string().hex().required(),
|
|
663
|
-
name: import_joi2.default.string().
|
|
702
|
+
name: import_joi2.default.string().optional().allow("", null),
|
|
703
|
+
type: import_joi2.default.string().optional().allow("", null, ...allowedTypes),
|
|
704
|
+
set: import_joi2.default.number().min(0).optional(),
|
|
705
|
+
units: import_joi2.default.array().items(
|
|
706
|
+
import_joi2.default.object({
|
|
707
|
+
unit: import_joi2.default.string().hex().required(),
|
|
708
|
+
name: import_joi2.default.string().required()
|
|
709
|
+
}).required()
|
|
710
|
+
).min(1).unique("unit", { ignoreUndefined: true }).optional().messages({
|
|
711
|
+
"array.unique": "Duplicate area units are not allowed"
|
|
712
|
+
})
|
|
664
713
|
});
|
|
665
714
|
const { error } = schema.validate(payload);
|
|
666
715
|
if (error) {
|
|
@@ -683,13 +732,13 @@ function useAreaController() {
|
|
|
683
732
|
const payload = { id: req.params.id, ...req.body };
|
|
684
733
|
const schema = import_joi2.default.object({
|
|
685
734
|
id: import_joi2.default.string().hex().required(),
|
|
686
|
-
|
|
735
|
+
units: import_joi2.default.array().items(
|
|
687
736
|
import_joi2.default.object({
|
|
688
|
-
|
|
737
|
+
unit: import_joi2.default.string().hex().required(),
|
|
689
738
|
name: import_joi2.default.string().required()
|
|
690
739
|
}).required()
|
|
691
|
-
).min(1).unique("
|
|
692
|
-
"array.unique": "Duplicate
|
|
740
|
+
).min(1).unique("unit", { ignoreUndefined: true }).messages({
|
|
741
|
+
"array.unique": "Duplicate area units are not allowed"
|
|
693
742
|
})
|
|
694
743
|
});
|
|
695
744
|
const { error } = schema.validate(payload);
|
|
@@ -711,10 +760,8 @@ function useAreaController() {
|
|
|
711
760
|
}
|
|
712
761
|
async function deleteArea(req, res, next) {
|
|
713
762
|
const id = req.params.id;
|
|
714
|
-
const validation = import_joi2.default.
|
|
715
|
-
|
|
716
|
-
});
|
|
717
|
-
const { error } = validation.validate({ id });
|
|
763
|
+
const validation = import_joi2.default.string().hex().required();
|
|
764
|
+
const { error } = validation.validate(id);
|
|
718
765
|
if (error) {
|
|
719
766
|
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
720
767
|
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
@@ -730,22 +777,14 @@ function useAreaController() {
|
|
|
730
777
|
return;
|
|
731
778
|
}
|
|
732
779
|
}
|
|
733
|
-
async function
|
|
780
|
+
async function importArea(req, res, next) {
|
|
734
781
|
if (!req.file) {
|
|
735
782
|
next(new import_node_server_utils4.BadRequestError("File is required!"));
|
|
736
783
|
return;
|
|
737
784
|
}
|
|
738
|
-
const
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
) : {};
|
|
742
|
-
const createdBy = cookies["user"] || "";
|
|
743
|
-
const { site } = req.body;
|
|
744
|
-
const schema = import_joi2.default.object({
|
|
745
|
-
site: import_joi2.default.string().hex().optional().allow("", null),
|
|
746
|
-
createdBy: import_joi2.default.string().hex().required()
|
|
747
|
-
});
|
|
748
|
-
const { error } = schema.validate({ site, createdBy });
|
|
785
|
+
const { site } = req.params;
|
|
786
|
+
const schema = import_joi2.default.string().hex().required();
|
|
787
|
+
const { error } = schema.validate(site);
|
|
749
788
|
if (error) {
|
|
750
789
|
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
751
790
|
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
@@ -754,7 +793,7 @@ function useAreaController() {
|
|
|
754
793
|
try {
|
|
755
794
|
const xlsData = await convertBufferFile(req.file.buffer);
|
|
756
795
|
const dataJson = JSON.stringify(xlsData);
|
|
757
|
-
const result = await
|
|
796
|
+
const result = await _importArea({ dataJson, site });
|
|
758
797
|
return res.status(201).json(result);
|
|
759
798
|
} catch (error2) {
|
|
760
799
|
import_node_server_utils4.logger.log({ level: "error", message: error2.message });
|
|
@@ -764,35 +803,27 @@ function useAreaController() {
|
|
|
764
803
|
}
|
|
765
804
|
return {
|
|
766
805
|
createArea,
|
|
767
|
-
|
|
806
|
+
getAreas,
|
|
768
807
|
getAreaById,
|
|
769
808
|
updateArea,
|
|
770
809
|
updateAreaChecklist,
|
|
771
810
|
deleteArea,
|
|
772
|
-
|
|
811
|
+
importArea
|
|
773
812
|
};
|
|
774
813
|
}
|
|
775
814
|
|
|
776
|
-
// src/models/hygiene-
|
|
815
|
+
// src/models/hygiene-unit.model.ts
|
|
777
816
|
var import_node_server_utils5 = require("@iservice365/node-server-utils");
|
|
778
817
|
var import_joi3 = __toESM(require("joi"));
|
|
779
818
|
var import_mongodb3 = require("mongodb");
|
|
780
|
-
var
|
|
781
|
-
name: import_joi3.default.string().required(),
|
|
819
|
+
var unitSchema = import_joi3.default.object({
|
|
782
820
|
site: import_joi3.default.string().hex().required(),
|
|
783
|
-
|
|
784
|
-
checklist: import_joi3.default.array().items(
|
|
785
|
-
import_joi3.default.object({
|
|
786
|
-
_id: import_joi3.default.string().hex().required(),
|
|
787
|
-
name: import_joi3.default.string().required()
|
|
788
|
-
})
|
|
789
|
-
).optional(),
|
|
790
|
-
updatedAt: import_joi3.default.date().optional().allow("", null),
|
|
791
|
-
status: import_joi3.default.string().allow("", null).optional()
|
|
821
|
+
name: import_joi3.default.string().required()
|
|
792
822
|
});
|
|
793
|
-
function
|
|
794
|
-
const { error } =
|
|
823
|
+
function MUnit(value) {
|
|
824
|
+
const { error } = unitSchema.validate(value);
|
|
795
825
|
if (error) {
|
|
826
|
+
import_node_server_utils5.logger.info(`Hygiene Unit Model: ${error.message}`);
|
|
796
827
|
throw new import_node_server_utils5.BadRequestError(error.message);
|
|
797
828
|
}
|
|
798
829
|
if (value.site) {
|
|
@@ -802,75 +833,64 @@ function MToiletLocation(value) {
|
|
|
802
833
|
throw new import_node_server_utils5.BadRequestError("Invalid site ID format.");
|
|
803
834
|
}
|
|
804
835
|
}
|
|
805
|
-
if (value.createdBy) {
|
|
806
|
-
try {
|
|
807
|
-
value.createdBy = new import_mongodb3.ObjectId(value.createdBy);
|
|
808
|
-
} catch (error2) {
|
|
809
|
-
throw new import_node_server_utils5.BadRequestError("Invalid createdBy ID format.");
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
if (value.checklist && Array.isArray(value.checklist)) {
|
|
813
|
-
value.checklist = value.checklist.map((item) => {
|
|
814
|
-
try {
|
|
815
|
-
return {
|
|
816
|
-
...item,
|
|
817
|
-
_id: new import_mongodb3.ObjectId(item._id)
|
|
818
|
-
};
|
|
819
|
-
} catch (error2) {
|
|
820
|
-
throw new import_node_server_utils5.BadRequestError(
|
|
821
|
-
`Invalid checklist item ID format: ${item._id}`
|
|
822
|
-
);
|
|
823
|
-
}
|
|
824
|
-
});
|
|
825
|
-
}
|
|
826
836
|
return {
|
|
827
|
-
name: value.name,
|
|
828
837
|
site: value.site,
|
|
829
|
-
|
|
830
|
-
checklist: value.checklist,
|
|
831
|
-
status: value.status ?? "",
|
|
838
|
+
name: value.name,
|
|
832
839
|
createdAt: /* @__PURE__ */ new Date(),
|
|
833
|
-
|
|
834
|
-
|
|
840
|
+
status: "active",
|
|
841
|
+
updatedAt: "",
|
|
842
|
+
deletedAt: ""
|
|
835
843
|
};
|
|
836
844
|
}
|
|
837
845
|
|
|
838
|
-
// src/
|
|
846
|
+
// src/services/hygiene-unit.service.ts
|
|
847
|
+
var import_node_server_utils7 = require("@iservice365/node-server-utils");
|
|
848
|
+
|
|
849
|
+
// src/repositories/hygiene-unit.repository.ts
|
|
839
850
|
var import_mongodb4 = require("mongodb");
|
|
840
851
|
var import_node_server_utils6 = require("@iservice365/node-server-utils");
|
|
841
|
-
function
|
|
852
|
+
function useUnitRepository() {
|
|
842
853
|
const db = import_node_server_utils6.useAtlas.getDb();
|
|
843
854
|
if (!db) {
|
|
844
855
|
throw new import_node_server_utils6.InternalServerError("Unable to connect to server.");
|
|
845
856
|
}
|
|
846
|
-
const namespace_collection = "
|
|
857
|
+
const namespace_collection = "site.cleaning.area.unit";
|
|
847
858
|
const collection = db.collection(namespace_collection);
|
|
848
|
-
const { delNamespace, setCache, getCache
|
|
849
|
-
async function
|
|
859
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils6.useCache)(namespace_collection);
|
|
860
|
+
async function createIndex() {
|
|
850
861
|
try {
|
|
851
862
|
await collection.createIndexes([
|
|
852
863
|
{ key: { site: 1 } },
|
|
853
|
-
{ key: {
|
|
864
|
+
{ key: { status: 1 } }
|
|
854
865
|
]);
|
|
855
866
|
} catch (error) {
|
|
856
|
-
throw new import_node_server_utils6.InternalServerError("Failed to create index on
|
|
867
|
+
throw new import_node_server_utils6.InternalServerError("Failed to create index on hygiene unit.");
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
async function createTextIndex() {
|
|
871
|
+
try {
|
|
872
|
+
await collection.createIndex({ name: "text" });
|
|
873
|
+
} catch (error) {
|
|
874
|
+
throw new import_node_server_utils6.InternalServerError(
|
|
875
|
+
"Failed to create text index on hygiene unit."
|
|
876
|
+
);
|
|
857
877
|
}
|
|
858
878
|
}
|
|
859
879
|
async function createUniqueIndex() {
|
|
860
880
|
try {
|
|
861
881
|
await collection.createIndex(
|
|
862
|
-
{
|
|
882
|
+
{ site: 1, name: 1, deletedAt: 1 },
|
|
863
883
|
{ unique: true }
|
|
864
884
|
);
|
|
865
885
|
} catch (error) {
|
|
866
886
|
throw new import_node_server_utils6.InternalServerError(
|
|
867
|
-
"Failed to create unique index on hygiene
|
|
887
|
+
"Failed to create unique index on hygiene unit."
|
|
868
888
|
);
|
|
869
889
|
}
|
|
870
890
|
}
|
|
871
|
-
async function
|
|
891
|
+
async function createUnit(value, session) {
|
|
872
892
|
try {
|
|
873
|
-
value =
|
|
893
|
+
value = MUnit(value);
|
|
874
894
|
const res = await collection.insertOne(value, { session });
|
|
875
895
|
delNamespace().then(() => {
|
|
876
896
|
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
@@ -884,190 +904,46 @@ function useToiletLocationRepository() {
|
|
|
884
904
|
} catch (error) {
|
|
885
905
|
const isDuplicated = error.message.includes("duplicate");
|
|
886
906
|
if (isDuplicated) {
|
|
887
|
-
throw new import_node_server_utils6.BadRequestError("
|
|
907
|
+
throw new import_node_server_utils6.BadRequestError("Unit already exists.");
|
|
888
908
|
}
|
|
889
909
|
throw error;
|
|
890
910
|
}
|
|
891
911
|
}
|
|
892
|
-
async function
|
|
912
|
+
async function getUnits({
|
|
913
|
+
page = 1,
|
|
914
|
+
limit = 10,
|
|
915
|
+
search = "",
|
|
916
|
+
site
|
|
917
|
+
}) {
|
|
918
|
+
page = page > 0 ? page - 1 : 0;
|
|
919
|
+
const query = {
|
|
920
|
+
status: { $ne: "deleted" }
|
|
921
|
+
};
|
|
922
|
+
const cacheOptions = {
|
|
923
|
+
page,
|
|
924
|
+
limit
|
|
925
|
+
};
|
|
893
926
|
try {
|
|
894
|
-
|
|
927
|
+
site = new import_mongodb4.ObjectId(site);
|
|
928
|
+
query.site = site;
|
|
929
|
+
cacheOptions.site = site.toString();
|
|
895
930
|
} catch (error) {
|
|
896
|
-
throw new import_node_server_utils6.BadRequestError("Invalid
|
|
897
|
-
}
|
|
898
|
-
if (value.checklist && Array.isArray(value.checklist)) {
|
|
899
|
-
value.checklist = value.checklist.map((item) => {
|
|
900
|
-
try {
|
|
901
|
-
return {
|
|
902
|
-
...item,
|
|
903
|
-
_id: new import_mongodb4.ObjectId(item._id)
|
|
904
|
-
};
|
|
905
|
-
} catch (error) {
|
|
906
|
-
throw new import_node_server_utils6.BadRequestError(
|
|
907
|
-
`Invalid checklist item ID format: ${item._id}`
|
|
908
|
-
);
|
|
909
|
-
}
|
|
910
|
-
});
|
|
931
|
+
throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
|
|
911
932
|
}
|
|
912
|
-
try {
|
|
913
|
-
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
914
|
-
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
915
|
-
if (res.modifiedCount === 0) {
|
|
916
|
-
throw new import_node_server_utils6.InternalServerError("Unable to update toilet location.");
|
|
917
|
-
}
|
|
918
|
-
delNamespace().then(() => {
|
|
919
|
-
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
920
|
-
}).catch((err) => {
|
|
921
|
-
import_node_server_utils6.logger.error(
|
|
922
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
923
|
-
err
|
|
924
|
-
);
|
|
925
|
-
});
|
|
926
|
-
return res.modifiedCount;
|
|
927
|
-
} catch (error) {
|
|
928
|
-
const isDuplicated = error.message.includes("duplicate");
|
|
929
|
-
if (isDuplicated) {
|
|
930
|
-
throw new import_node_server_utils6.BadRequestError("Toilet location already exists.");
|
|
931
|
-
}
|
|
932
|
-
throw error;
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
async function deleteToiletLocation(_id, session) {
|
|
936
|
-
try {
|
|
937
|
-
_id = new import_mongodb4.ObjectId(_id);
|
|
938
|
-
} catch (error) {
|
|
939
|
-
throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
|
|
940
|
-
}
|
|
941
|
-
try {
|
|
942
|
-
const updateValue = {
|
|
943
|
-
status: "deleted",
|
|
944
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
945
|
-
deletedAt: /* @__PURE__ */ new Date()
|
|
946
|
-
};
|
|
947
|
-
const res = await collection.updateOne(
|
|
948
|
-
{ _id },
|
|
949
|
-
{ $set: updateValue },
|
|
950
|
-
{ session }
|
|
951
|
-
);
|
|
952
|
-
if (res.modifiedCount === 0) {
|
|
953
|
-
throw new import_node_server_utils6.InternalServerError("Unable to delete toilet location.");
|
|
954
|
-
}
|
|
955
|
-
delNamespace().then(() => {
|
|
956
|
-
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
957
|
-
}).catch((err) => {
|
|
958
|
-
import_node_server_utils6.logger.error(
|
|
959
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
960
|
-
err
|
|
961
|
-
);
|
|
962
|
-
});
|
|
963
|
-
return res.modifiedCount;
|
|
964
|
-
} catch (error) {
|
|
965
|
-
throw error;
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
async function getToiletLocations({
|
|
969
|
-
page = 1,
|
|
970
|
-
limit = 10,
|
|
971
|
-
search = "",
|
|
972
|
-
sort = {},
|
|
973
|
-
startDate = "",
|
|
974
|
-
endDate = "",
|
|
975
|
-
site = ""
|
|
976
|
-
}) {
|
|
977
|
-
page = page > 0 ? page - 1 : 0;
|
|
978
|
-
let dateFilter = {};
|
|
979
|
-
try {
|
|
980
|
-
site = new import_mongodb4.ObjectId(site);
|
|
981
|
-
} catch (error) {
|
|
982
|
-
throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
|
|
983
|
-
}
|
|
984
|
-
const query = {
|
|
985
|
-
status: { $ne: "deleted" }
|
|
986
|
-
};
|
|
987
|
-
const cacheOptions = {
|
|
988
|
-
site: site.toString()
|
|
989
|
-
};
|
|
990
|
-
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
991
|
-
cacheOptions.sort = JSON.stringify(sort);
|
|
992
933
|
if (search) {
|
|
993
934
|
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
994
935
|
cacheOptions.search = search;
|
|
995
936
|
}
|
|
996
|
-
delNamespace().then(() => {
|
|
997
|
-
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
998
|
-
}).catch((err) => {
|
|
999
|
-
import_node_server_utils6.logger.error(
|
|
1000
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1001
|
-
err
|
|
1002
|
-
);
|
|
1003
|
-
});
|
|
1004
937
|
const cacheKey = (0, import_node_server_utils6.makeCacheKey)(namespace_collection, cacheOptions);
|
|
1005
938
|
const cachedData = await getCache(cacheKey);
|
|
1006
939
|
if (cachedData) {
|
|
1007
940
|
import_node_server_utils6.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
1008
941
|
return cachedData;
|
|
1009
942
|
}
|
|
1010
|
-
if (startDate && endDate) {
|
|
1011
|
-
dateFilter = {
|
|
1012
|
-
createdAt: {
|
|
1013
|
-
$gte: new Date(startDate),
|
|
1014
|
-
$lte: new Date(endDate)
|
|
1015
|
-
}
|
|
1016
|
-
};
|
|
1017
|
-
} else if (startDate) {
|
|
1018
|
-
dateFilter = { createdAt: { $gte: new Date(startDate) } };
|
|
1019
|
-
} else if (endDate) {
|
|
1020
|
-
dateFilter = { createdAt: { $lte: new Date(endDate) } };
|
|
1021
|
-
}
|
|
1022
943
|
try {
|
|
1023
944
|
const items = await collection.aggregate([
|
|
1024
|
-
{
|
|
1025
|
-
|
|
1026
|
-
...dateFilter,
|
|
1027
|
-
...query
|
|
1028
|
-
}
|
|
1029
|
-
},
|
|
1030
|
-
{
|
|
1031
|
-
$lookup: {
|
|
1032
|
-
from: "sites",
|
|
1033
|
-
localField: "site",
|
|
1034
|
-
foreignField: "_id",
|
|
1035
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
1036
|
-
as: "site"
|
|
1037
|
-
}
|
|
1038
|
-
},
|
|
1039
|
-
{
|
|
1040
|
-
$unwind: {
|
|
1041
|
-
path: "$site",
|
|
1042
|
-
preserveNullAndEmptyArrays: true
|
|
1043
|
-
}
|
|
1044
|
-
},
|
|
1045
|
-
{
|
|
1046
|
-
$lookup: {
|
|
1047
|
-
from: "users",
|
|
1048
|
-
localField: "createdBy",
|
|
1049
|
-
foreignField: "_id",
|
|
1050
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
1051
|
-
as: "createdBy"
|
|
1052
|
-
}
|
|
1053
|
-
},
|
|
1054
|
-
{
|
|
1055
|
-
$unwind: {
|
|
1056
|
-
path: "$createdBy",
|
|
1057
|
-
preserveNullAndEmptyArrays: true
|
|
1058
|
-
}
|
|
1059
|
-
},
|
|
1060
|
-
{
|
|
1061
|
-
$project: {
|
|
1062
|
-
name: 1,
|
|
1063
|
-
site: "$site._id",
|
|
1064
|
-
siteName: "$site.name",
|
|
1065
|
-
createdByName: "$createdBy.name",
|
|
1066
|
-
checklist: 1,
|
|
1067
|
-
status: 1,
|
|
1068
|
-
createdAt: 1
|
|
1069
|
-
}
|
|
1070
|
-
},
|
|
945
|
+
{ $match: query },
|
|
946
|
+
{ $project: { name: 1 } },
|
|
1071
947
|
{ $sort: { _id: -1 } },
|
|
1072
948
|
{ $skip: page * limit },
|
|
1073
949
|
{ $limit: limit }
|
|
@@ -1084,47 +960,17 @@ function useToiletLocationRepository() {
|
|
|
1084
960
|
throw error;
|
|
1085
961
|
}
|
|
1086
962
|
}
|
|
1087
|
-
async function
|
|
1088
|
-
try {
|
|
1089
|
-
if (site)
|
|
1090
|
-
site = new import_mongodb4.ObjectId(site);
|
|
1091
|
-
} catch (error) {
|
|
1092
|
-
throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
|
|
1093
|
-
}
|
|
1094
|
-
try {
|
|
1095
|
-
return await collection.findOne({
|
|
1096
|
-
name: { $regex: new RegExp(`^${name}$`, "i") },
|
|
1097
|
-
...site && { site }
|
|
1098
|
-
});
|
|
1099
|
-
} catch (error) {
|
|
1100
|
-
throw new import_node_server_utils6.BadRequestError("Unable to fetch toilet location by name.");
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
async function updateToiletLocationChecklist(_id, value) {
|
|
963
|
+
async function updateUnit(_id, value) {
|
|
1104
964
|
try {
|
|
1105
965
|
_id = new import_mongodb4.ObjectId(_id);
|
|
1106
966
|
} catch (error) {
|
|
1107
|
-
throw new import_node_server_utils6.BadRequestError("Invalid
|
|
1108
|
-
}
|
|
1109
|
-
if (value.checklist && Array.isArray(value.checklist)) {
|
|
1110
|
-
value.checklist = value.checklist.map((item) => {
|
|
1111
|
-
try {
|
|
1112
|
-
return {
|
|
1113
|
-
...item,
|
|
1114
|
-
_id: new import_mongodb4.ObjectId(item._id)
|
|
1115
|
-
};
|
|
1116
|
-
} catch (error) {
|
|
1117
|
-
throw new import_node_server_utils6.BadRequestError(
|
|
1118
|
-
`Invalid checklist item ID format: ${item._id}`
|
|
1119
|
-
);
|
|
1120
|
-
}
|
|
1121
|
-
});
|
|
967
|
+
throw new import_node_server_utils6.BadRequestError("Invalid unit ID format.");
|
|
1122
968
|
}
|
|
1123
969
|
try {
|
|
1124
970
|
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
1125
971
|
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
1126
972
|
if (res.modifiedCount === 0) {
|
|
1127
|
-
throw new import_node_server_utils6.InternalServerError("Unable to update
|
|
973
|
+
throw new import_node_server_utils6.InternalServerError("Unable to update cleaning unit.");
|
|
1128
974
|
}
|
|
1129
975
|
delNamespace().then(() => {
|
|
1130
976
|
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
@@ -1136,70 +982,62 @@ function useToiletLocationRepository() {
|
|
|
1136
982
|
});
|
|
1137
983
|
return res.modifiedCount;
|
|
1138
984
|
} catch (error) {
|
|
985
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
986
|
+
if (isDuplicated) {
|
|
987
|
+
throw new import_node_server_utils6.BadRequestError("Area already exists.");
|
|
988
|
+
}
|
|
1139
989
|
throw error;
|
|
1140
990
|
}
|
|
1141
991
|
}
|
|
1142
|
-
async function
|
|
992
|
+
async function deleteUnit(_id, session) {
|
|
1143
993
|
try {
|
|
1144
994
|
_id = new import_mongodb4.ObjectId(_id);
|
|
1145
995
|
} catch (error) {
|
|
1146
|
-
throw new import_node_server_utils6.BadRequestError("Invalid
|
|
1147
|
-
}
|
|
1148
|
-
const query = {
|
|
1149
|
-
_id,
|
|
1150
|
-
status: { $ne: "deleted" }
|
|
1151
|
-
};
|
|
1152
|
-
const cacheKey = (0, import_node_server_utils6.makeCacheKey)(namespace_collection, {
|
|
1153
|
-
_id: _id.toString()
|
|
1154
|
-
});
|
|
1155
|
-
const cachedData = await getCache(cacheKey);
|
|
1156
|
-
if (cachedData) {
|
|
1157
|
-
import_node_server_utils6.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
1158
|
-
return cachedData;
|
|
996
|
+
throw new import_node_server_utils6.BadRequestError("Invalid unit ID format.");
|
|
1159
997
|
}
|
|
1160
998
|
try {
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
999
|
+
const updateValue = {
|
|
1000
|
+
status: "deleted",
|
|
1001
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
1002
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
1003
|
+
};
|
|
1004
|
+
const res = await collection.updateOne(
|
|
1005
|
+
{ _id },
|
|
1006
|
+
{ $set: updateValue },
|
|
1007
|
+
{ session }
|
|
1008
|
+
);
|
|
1009
|
+
if (res.modifiedCount === 0) {
|
|
1010
|
+
throw new import_node_server_utils6.InternalServerError("Unable to delete unit.");
|
|
1172
1011
|
}
|
|
1173
|
-
|
|
1174
|
-
import_node_server_utils6.logger.info(`Cache
|
|
1012
|
+
delNamespace().then(() => {
|
|
1013
|
+
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1175
1014
|
}).catch((err) => {
|
|
1176
|
-
import_node_server_utils6.logger.error(
|
|
1015
|
+
import_node_server_utils6.logger.error(
|
|
1016
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1017
|
+
err
|
|
1018
|
+
);
|
|
1177
1019
|
});
|
|
1178
|
-
return
|
|
1020
|
+
return res.modifiedCount;
|
|
1179
1021
|
} catch (error) {
|
|
1180
1022
|
throw error;
|
|
1181
1023
|
}
|
|
1182
1024
|
}
|
|
1183
1025
|
return {
|
|
1184
|
-
|
|
1026
|
+
createIndex,
|
|
1027
|
+
createTextIndex,
|
|
1185
1028
|
createUniqueIndex,
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
getToiletLocationByName,
|
|
1191
|
-
getToiletLocationById,
|
|
1192
|
-
updateToiletLocationChecklist
|
|
1029
|
+
createUnit,
|
|
1030
|
+
getUnits,
|
|
1031
|
+
updateUnit,
|
|
1032
|
+
deleteUnit
|
|
1193
1033
|
};
|
|
1194
1034
|
}
|
|
1195
1035
|
|
|
1196
|
-
// src/services/hygiene-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
async function uploadByFile({
|
|
1036
|
+
// src/services/hygiene-unit.service.ts
|
|
1037
|
+
function useUnitService() {
|
|
1038
|
+
const { createUnit: _createUnit } = useUnitRepository();
|
|
1039
|
+
async function importUnit({
|
|
1201
1040
|
dataJson,
|
|
1202
|
-
createdBy,
|
|
1203
1041
|
site
|
|
1204
1042
|
}) {
|
|
1205
1043
|
let dataArray;
|
|
@@ -1211,146 +1049,158 @@ function useToiletLocationService() {
|
|
|
1211
1049
|
if (!dataArray || dataArray.length === 0) {
|
|
1212
1050
|
throw new import_node_server_utils7.NotFoundError("No data found in the uploaded file");
|
|
1213
1051
|
}
|
|
1214
|
-
const
|
|
1215
|
-
const
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1052
|
+
const insertedUnitIds = [];
|
|
1053
|
+
const duplicateUnits = [];
|
|
1054
|
+
const failedUnits = [];
|
|
1055
|
+
const skippedRows = [];
|
|
1056
|
+
try {
|
|
1057
|
+
for (let i = 0; i < dataArray.length; i++) {
|
|
1058
|
+
const row = dataArray[i];
|
|
1059
|
+
if (!row?.NAME) {
|
|
1060
|
+
import_node_server_utils7.logger.warn(`Skipping row ${i + 1} with missing NAME:`, row);
|
|
1061
|
+
skippedRows.push(i + 1);
|
|
1062
|
+
continue;
|
|
1063
|
+
}
|
|
1064
|
+
const unitName = String(row.NAME).trim();
|
|
1065
|
+
if (!unitName) {
|
|
1066
|
+
import_node_server_utils7.logger.warn(`Skipping row ${i + 1} with empty unit name`);
|
|
1067
|
+
skippedRows.push(i + 1);
|
|
1221
1068
|
continue;
|
|
1222
1069
|
}
|
|
1223
1070
|
try {
|
|
1224
|
-
const insertedId = await
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
session
|
|
1231
|
-
);
|
|
1232
|
-
insertedAreaIds.push(insertedId);
|
|
1071
|
+
const insertedId = await _createUnit({
|
|
1072
|
+
name: unitName,
|
|
1073
|
+
site
|
|
1074
|
+
});
|
|
1075
|
+
insertedUnitIds.push(insertedId);
|
|
1076
|
+
import_node_server_utils7.logger.info(`Successfully created unit: ${unitName}`);
|
|
1233
1077
|
} catch (error) {
|
|
1234
|
-
import_node_server_utils7.logger.error(
|
|
1235
|
-
|
|
1236
|
-
|
|
1078
|
+
import_node_server_utils7.logger.error(`Error creating unit "${unitName}": ${error.message}`);
|
|
1079
|
+
if (error.message.includes("Unit already exists")) {
|
|
1080
|
+
duplicateUnits.push(unitName);
|
|
1081
|
+
} else {
|
|
1082
|
+
failedUnits.push(unitName);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
let message = `Upload completed: ${insertedUnitIds.length} units successfully created`;
|
|
1087
|
+
if (duplicateUnits.length > 0) {
|
|
1088
|
+
message += `, ${duplicateUnits.length} units skipped (already exist)`;
|
|
1089
|
+
}
|
|
1090
|
+
if (failedUnits.length > 0) {
|
|
1091
|
+
message += `, ${failedUnits.length} units failed`;
|
|
1092
|
+
}
|
|
1093
|
+
if (skippedRows.length > 0) {
|
|
1094
|
+
message += `, ${skippedRows.length} rows skipped (invalid data)`;
|
|
1095
|
+
}
|
|
1096
|
+
import_node_server_utils7.logger.info(message);
|
|
1097
|
+
if (insertedUnitIds.length === 0) {
|
|
1098
|
+
if (duplicateUnits.length > 0 && failedUnits.length === 0) {
|
|
1099
|
+
throw new import_node_server_utils7.BadRequestError(
|
|
1100
|
+
`No new units were created. All ${duplicateUnits.length} units already exist in the system: ${duplicateUnits.join(", ")}`
|
|
1101
|
+
);
|
|
1102
|
+
} else if (failedUnits.length > 0) {
|
|
1103
|
+
throw new import_node_server_utils7.BadRequestError(
|
|
1104
|
+
`No units were created. Please check your data format and ensure unit names are valid.`
|
|
1105
|
+
);
|
|
1106
|
+
} else if (skippedRows.length > 0) {
|
|
1107
|
+
throw new import_node_server_utils7.BadRequestError(
|
|
1108
|
+
`No units were created. All rows contained invalid or missing unit names.`
|
|
1237
1109
|
);
|
|
1238
|
-
continue;
|
|
1239
1110
|
}
|
|
1240
1111
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1112
|
+
return { message };
|
|
1113
|
+
} catch (error) {
|
|
1114
|
+
import_node_server_utils7.logger.error("Error while uploading unit information", error);
|
|
1115
|
+
if (error instanceof import_node_server_utils7.BadRequestError) {
|
|
1116
|
+
throw error;
|
|
1117
|
+
} else if (error.message.includes("duplicate")) {
|
|
1118
|
+
throw new import_node_server_utils7.BadRequestError(
|
|
1119
|
+
"Upload failed due to duplicate unit names. Please ensure all unit names are unique."
|
|
1120
|
+
);
|
|
1121
|
+
} else if (error.message.includes("validation")) {
|
|
1122
|
+
throw new import_node_server_utils7.BadRequestError(
|
|
1123
|
+
"Upload failed due to invalid data format. Please check that all required fields are properly filled."
|
|
1124
|
+
);
|
|
1125
|
+
} else {
|
|
1126
|
+
throw new import_node_server_utils7.BadRequestError(
|
|
1127
|
+
`Upload failed: ${error.message || "Please check your data format and try again."}`
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1252
1130
|
}
|
|
1253
1131
|
}
|
|
1254
|
-
return {
|
|
1255
|
-
uploadByFile
|
|
1256
|
-
};
|
|
1132
|
+
return { importUnit };
|
|
1257
1133
|
}
|
|
1258
1134
|
|
|
1259
|
-
// src/controllers/hygiene-
|
|
1260
|
-
var import_joi4 = __toESM(require("joi"));
|
|
1135
|
+
// src/controllers/hygiene-unit.controller.ts
|
|
1261
1136
|
var import_node_server_utils8 = require("@iservice365/node-server-utils");
|
|
1262
|
-
|
|
1263
|
-
|
|
1137
|
+
var import_joi4 = __toESM(require("joi"));
|
|
1138
|
+
function useUnitController() {
|
|
1264
1139
|
const {
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
const
|
|
1140
|
+
createUnit: _createUnit,
|
|
1141
|
+
getUnits: _getUnits,
|
|
1142
|
+
updateUnit: _updateUnit,
|
|
1143
|
+
deleteUnit: _deleteUnit
|
|
1144
|
+
} = useUnitRepository();
|
|
1145
|
+
const { importUnit: _importUnit } = useUnitService();
|
|
1146
|
+
async function createUnit(req, res, next) {
|
|
1147
|
+
const payload = { ...req.body, ...req.params };
|
|
1148
|
+
const { error } = unitSchema.validate(payload);
|
|
1149
|
+
if (error) {
|
|
1150
|
+
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1151
|
+
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
try {
|
|
1155
|
+
const id = await _createUnit(payload);
|
|
1156
|
+
res.status(201).json({ message: "Unit created successfully.", id });
|
|
1157
|
+
return;
|
|
1158
|
+
} catch (error2) {
|
|
1159
|
+
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
1160
|
+
next(error2);
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
async function getUnits(req, res, next) {
|
|
1165
|
+
const query = { ...req.query, ...req.params };
|
|
1274
1166
|
const validation = import_joi4.default.object({
|
|
1275
1167
|
page: import_joi4.default.number().min(1).optional().allow("", null),
|
|
1276
1168
|
limit: import_joi4.default.number().min(1).optional().allow("", null),
|
|
1277
1169
|
search: import_joi4.default.string().optional().allow("", null),
|
|
1278
|
-
site: import_joi4.default.string().hex().
|
|
1170
|
+
site: import_joi4.default.string().hex().required()
|
|
1279
1171
|
});
|
|
1280
1172
|
const { error } = validation.validate(query);
|
|
1281
1173
|
if (error) {
|
|
1174
|
+
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1282
1175
|
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1283
1176
|
return;
|
|
1284
1177
|
}
|
|
1285
1178
|
const page = parseInt(req.query.page) ?? 1;
|
|
1286
|
-
|
|
1287
|
-
limit = isNaN(limit) ? 20 : limit;
|
|
1288
|
-
const sort = req.query.sort ? String(req.query.sort).split(",") : "";
|
|
1289
|
-
const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
|
|
1290
|
-
const sortObj = {};
|
|
1291
|
-
if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
|
|
1292
|
-
sort.forEach((field, index) => {
|
|
1293
|
-
sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
|
|
1294
|
-
});
|
|
1295
|
-
}
|
|
1296
|
-
const site = req.query.site ?? "";
|
|
1179
|
+
const limit = parseInt(req.query.limit) ?? 20;
|
|
1297
1180
|
const search = req.query.search ?? "";
|
|
1181
|
+
const site = req.params.site ?? "";
|
|
1298
1182
|
try {
|
|
1299
|
-
const
|
|
1183
|
+
const data = await _getUnits({
|
|
1300
1184
|
page,
|
|
1301
1185
|
limit,
|
|
1302
|
-
|
|
1303
|
-
site
|
|
1304
|
-
search
|
|
1186
|
+
search,
|
|
1187
|
+
site
|
|
1305
1188
|
});
|
|
1306
|
-
res.json(
|
|
1189
|
+
res.json(data);
|
|
1307
1190
|
return;
|
|
1308
1191
|
} catch (error2) {
|
|
1192
|
+
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
1309
1193
|
next(error2);
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
async function createToiletLocation(req, res, next) {
|
|
1313
|
-
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
1314
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
1315
|
-
{}
|
|
1316
|
-
) : {};
|
|
1317
|
-
const createdBy = cookies["user"] || "";
|
|
1318
|
-
const payload = { ...req.body, createdBy };
|
|
1319
|
-
const schema = import_joi4.default.object({
|
|
1320
|
-
name: import_joi4.default.string().required(),
|
|
1321
|
-
site: import_joi4.default.string().hex().optional().allow("", null),
|
|
1322
|
-
status: import_joi4.default.string().optional().allow("", null),
|
|
1323
|
-
createdBy: import_joi4.default.string().hex().optional().allow("", null)
|
|
1324
|
-
});
|
|
1325
|
-
const { error } = schema.validate(payload);
|
|
1326
|
-
if (error) {
|
|
1327
|
-
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1328
|
-
import_node_server_utils8.logger.info(`Controller: ${error.message}`);
|
|
1329
|
-
return;
|
|
1330
|
-
}
|
|
1331
|
-
try {
|
|
1332
|
-
const result = await _createToiletLocation(payload);
|
|
1333
|
-
res.status(201).json(result);
|
|
1334
1194
|
return;
|
|
1335
|
-
} catch (error2) {
|
|
1336
|
-
next(error2);
|
|
1337
1195
|
}
|
|
1338
1196
|
}
|
|
1339
|
-
async function
|
|
1197
|
+
async function updateUnit(req, res, next) {
|
|
1340
1198
|
const payload = { id: req.params.id, ...req.body };
|
|
1341
|
-
const
|
|
1199
|
+
const validation = import_joi4.default.object({
|
|
1342
1200
|
id: import_joi4.default.string().hex().required(),
|
|
1343
|
-
name: import_joi4.default.string().required()
|
|
1344
|
-
checklist: import_joi4.default.array().items(
|
|
1345
|
-
import_joi4.default.object({
|
|
1346
|
-
_id: import_joi4.default.string().hex().required(),
|
|
1347
|
-
name: import_joi4.default.string().required()
|
|
1348
|
-
}).optional()
|
|
1349
|
-
),
|
|
1350
|
-
site: import_joi4.default.string().hex().optional().allow("", null),
|
|
1351
|
-
status: import_joi4.default.string().optional().allow("", null)
|
|
1201
|
+
name: import_joi4.default.string().required()
|
|
1352
1202
|
});
|
|
1353
|
-
const { error } =
|
|
1203
|
+
const { error } = validation.validate(payload);
|
|
1354
1204
|
if (error) {
|
|
1355
1205
|
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1356
1206
|
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
@@ -1358,74 +1208,29 @@ function useToiletLocationController() {
|
|
|
1358
1208
|
}
|
|
1359
1209
|
try {
|
|
1360
1210
|
const { id, ...value } = payload;
|
|
1361
|
-
await
|
|
1362
|
-
res.
|
|
1211
|
+
await _updateUnit(id, value);
|
|
1212
|
+
res.json({ message: "Unit updated successfully." });
|
|
1363
1213
|
return;
|
|
1364
1214
|
} catch (error2) {
|
|
1365
1215
|
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
1366
1216
|
next(error2);
|
|
1217
|
+
return;
|
|
1367
1218
|
}
|
|
1368
1219
|
}
|
|
1369
|
-
async function
|
|
1220
|
+
async function deleteUnit(req, res, next) {
|
|
1370
1221
|
const id = req.params.id;
|
|
1371
1222
|
const validation = import_joi4.default.object({
|
|
1372
1223
|
id: import_joi4.default.string().hex().required()
|
|
1373
1224
|
});
|
|
1374
1225
|
const { error } = validation.validate({ id });
|
|
1375
|
-
if (error) {
|
|
1376
|
-
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1377
|
-
return;
|
|
1378
|
-
}
|
|
1379
|
-
try {
|
|
1380
|
-
const message = await _deleteById(id);
|
|
1381
|
-
res.json(message);
|
|
1382
|
-
return;
|
|
1383
|
-
} catch (error2) {
|
|
1384
|
-
next(error2);
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
async function updateToiletLocationChecklist(req, res, next) {
|
|
1388
|
-
const payload = { id: req.params.id, ...req.body };
|
|
1389
|
-
const schema = import_joi4.default.object({
|
|
1390
|
-
id: import_joi4.default.string().hex().required(),
|
|
1391
|
-
checklist: import_joi4.default.array().items(
|
|
1392
|
-
import_joi4.default.object({
|
|
1393
|
-
_id: import_joi4.default.string().hex().required(),
|
|
1394
|
-
name: import_joi4.default.string().required()
|
|
1395
|
-
}).required()
|
|
1396
|
-
).min(1).unique("_id", { ignoreUndefined: true }).messages({
|
|
1397
|
-
"array.unique": "Duplicate checklist items are not allowed"
|
|
1398
|
-
})
|
|
1399
|
-
});
|
|
1400
|
-
const { error } = schema.validate(payload);
|
|
1401
|
-
if (error) {
|
|
1402
|
-
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1403
|
-
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1404
|
-
return;
|
|
1405
|
-
}
|
|
1406
|
-
try {
|
|
1407
|
-
const { id, ...value } = payload;
|
|
1408
|
-
await _updateToiletLocationChecklist(id, value);
|
|
1409
|
-
res.json({ message: "Toilet location updated successfully." });
|
|
1410
|
-
return;
|
|
1411
|
-
} catch (error2) {
|
|
1412
|
-
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
1413
|
-
next(error2);
|
|
1414
|
-
return;
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
async function getToiletLocationById(req, res, next) {
|
|
1418
|
-
const validation = import_joi4.default.string().hex().required();
|
|
1419
|
-
const _id = req.params.id;
|
|
1420
|
-
const { error } = validation.validate(_id);
|
|
1421
1226
|
if (error) {
|
|
1422
1227
|
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1423
1228
|
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1424
1229
|
return;
|
|
1425
1230
|
}
|
|
1426
1231
|
try {
|
|
1427
|
-
|
|
1428
|
-
res.json(
|
|
1232
|
+
await _deleteUnit(id);
|
|
1233
|
+
res.json({ message: "Unit deleted successfully." });
|
|
1429
1234
|
return;
|
|
1430
1235
|
} catch (error2) {
|
|
1431
1236
|
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
@@ -1433,22 +1238,14 @@ function useToiletLocationController() {
|
|
|
1433
1238
|
return;
|
|
1434
1239
|
}
|
|
1435
1240
|
}
|
|
1436
|
-
async function
|
|
1241
|
+
async function importUnit(req, res, next) {
|
|
1437
1242
|
if (!req.file) {
|
|
1438
1243
|
next(new import_node_server_utils8.BadRequestError("File is required!"));
|
|
1439
1244
|
return;
|
|
1440
1245
|
}
|
|
1441
|
-
const
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
) : {};
|
|
1445
|
-
const createdBy = cookies["user"] || "";
|
|
1446
|
-
const { site } = req.body;
|
|
1447
|
-
const schema = import_joi4.default.object({
|
|
1448
|
-
site: import_joi4.default.string().hex().optional().allow("", null),
|
|
1449
|
-
createdBy: import_joi4.default.string().hex().required()
|
|
1450
|
-
});
|
|
1451
|
-
const { error } = schema.validate({ site, createdBy });
|
|
1246
|
+
const { site } = req.params;
|
|
1247
|
+
const validation = import_joi4.default.string().hex().required();
|
|
1248
|
+
const { error } = validation.validate(site);
|
|
1452
1249
|
if (error) {
|
|
1453
1250
|
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1454
1251
|
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
@@ -1457,7 +1254,7 @@ function useToiletLocationController() {
|
|
|
1457
1254
|
try {
|
|
1458
1255
|
const xlsData = await convertBufferFile(req.file.buffer);
|
|
1459
1256
|
const dataJson = JSON.stringify(xlsData);
|
|
1460
|
-
const result = await
|
|
1257
|
+
const result = await _importUnit({ dataJson, site });
|
|
1461
1258
|
return res.status(201).json(result);
|
|
1462
1259
|
} catch (error2) {
|
|
1463
1260
|
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
@@ -1466,13 +1263,11 @@ function useToiletLocationController() {
|
|
|
1466
1263
|
}
|
|
1467
1264
|
}
|
|
1468
1265
|
return {
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
getToiletLocationById,
|
|
1475
|
-
uploadByFile
|
|
1266
|
+
createUnit,
|
|
1267
|
+
getUnits,
|
|
1268
|
+
updateUnit,
|
|
1269
|
+
deleteUnit,
|
|
1270
|
+
importUnit
|
|
1476
1271
|
};
|
|
1477
1272
|
}
|
|
1478
1273
|
|
|
@@ -1480,22 +1275,9 @@ function useToiletLocationController() {
|
|
|
1480
1275
|
var import_node_server_utils9 = require("@iservice365/node-server-utils");
|
|
1481
1276
|
var import_joi5 = __toESM(require("joi"));
|
|
1482
1277
|
var import_mongodb5 = require("mongodb");
|
|
1483
|
-
var allowedTypes = ["cleaner", "toilet"];
|
|
1484
|
-
var allowedStatus = [
|
|
1485
|
-
"To Do",
|
|
1486
|
-
"Pending",
|
|
1487
|
-
"In Progress",
|
|
1488
|
-
"Completed",
|
|
1489
|
-
"Expired"
|
|
1490
|
-
];
|
|
1491
1278
|
var parentChecklistSchema = import_joi5.default.object({
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
import_joi5.default.object({
|
|
1495
|
-
type: import_joi5.default.string().required().valid(...allowedTypes),
|
|
1496
|
-
site: import_joi5.default.string().hex().required()
|
|
1497
|
-
})
|
|
1498
|
-
).optional()
|
|
1279
|
+
createdAt: import_joi5.default.alternatives().try(import_joi5.default.date(), import_joi5.default.string()).optional().allow("", null),
|
|
1280
|
+
site: import_joi5.default.string().hex().required()
|
|
1499
1281
|
});
|
|
1500
1282
|
function MParentChecklist(value) {
|
|
1501
1283
|
const { error } = parentChecklistSchema.validate(value);
|
|
@@ -1503,26 +1285,17 @@ function MParentChecklist(value) {
|
|
|
1503
1285
|
import_node_server_utils9.logger.info(`Hygiene Parent Checklist Model: ${error.message}`);
|
|
1504
1286
|
throw new import_node_server_utils9.BadRequestError(error.message);
|
|
1505
1287
|
}
|
|
1506
|
-
if (value.
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
status: item.status || "To Do",
|
|
1513
|
-
completedAt: item.completedAt || ""
|
|
1514
|
-
};
|
|
1515
|
-
} catch (error2) {
|
|
1516
|
-
throw new import_node_server_utils9.BadRequestError(
|
|
1517
|
-
`Invalid status site ID format: ${item.site}`
|
|
1518
|
-
);
|
|
1519
|
-
}
|
|
1520
|
-
});
|
|
1288
|
+
if (value.site) {
|
|
1289
|
+
try {
|
|
1290
|
+
value.site = new import_mongodb5.ObjectId(value.site);
|
|
1291
|
+
} catch (error2) {
|
|
1292
|
+
throw new import_node_server_utils9.BadRequestError(`Invalid site ID format: ${value.site}`);
|
|
1293
|
+
}
|
|
1521
1294
|
}
|
|
1522
1295
|
return {
|
|
1523
|
-
|
|
1524
|
-
status:
|
|
1525
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
1296
|
+
site: value.site,
|
|
1297
|
+
status: "ready",
|
|
1298
|
+
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
1526
1299
|
updatedAt: value.updatedAt ?? ""
|
|
1527
1300
|
};
|
|
1528
1301
|
}
|
|
@@ -1535,14 +1308,17 @@ function useParentChecklistRepo() {
|
|
|
1535
1308
|
if (!db) {
|
|
1536
1309
|
throw new import_node_server_utils10.InternalServerError("Unable to connect to server.");
|
|
1537
1310
|
}
|
|
1538
|
-
const namespace_collection = "
|
|
1311
|
+
const namespace_collection = "site.cleaning.schedules";
|
|
1312
|
+
const site_collection = "sites";
|
|
1539
1313
|
const collection = db.collection(namespace_collection);
|
|
1314
|
+
const siteCollection = db.collection(site_collection);
|
|
1540
1315
|
const { delNamespace, setCache, getCache } = (0, import_node_server_utils10.useCache)(namespace_collection);
|
|
1541
1316
|
async function createIndex() {
|
|
1542
1317
|
try {
|
|
1543
1318
|
await collection.createIndexes([
|
|
1544
|
-
{ key: {
|
|
1545
|
-
{ key: {
|
|
1319
|
+
{ key: { createdAt: 1 } },
|
|
1320
|
+
{ key: { site: 1 } },
|
|
1321
|
+
{ key: { status: 1 } }
|
|
1546
1322
|
]);
|
|
1547
1323
|
} catch (error) {
|
|
1548
1324
|
throw new import_node_server_utils10.InternalServerError(
|
|
@@ -1552,13 +1328,13 @@ function useParentChecklistRepo() {
|
|
|
1552
1328
|
}
|
|
1553
1329
|
async function createParentChecklist(value, session) {
|
|
1554
1330
|
try {
|
|
1555
|
-
const currentDate = value.
|
|
1331
|
+
const currentDate = value.createdAt ? new Date(value.createdAt) : /* @__PURE__ */ new Date();
|
|
1556
1332
|
const startOfDay = new Date(currentDate);
|
|
1557
1333
|
startOfDay.setUTCHours(0, 0, 0, 0);
|
|
1558
1334
|
const endOfDay = new Date(currentDate);
|
|
1559
1335
|
endOfDay.setUTCHours(23, 59, 59, 999);
|
|
1560
1336
|
const existingChecklist = await collection.findOne({
|
|
1561
|
-
|
|
1337
|
+
createdAt: {
|
|
1562
1338
|
$gte: startOfDay,
|
|
1563
1339
|
$lte: endOfDay
|
|
1564
1340
|
}
|
|
@@ -1568,8 +1344,25 @@ function useParentChecklistRepo() {
|
|
|
1568
1344
|
import_node_server_utils10.logger.info(`Parent checklist already exists for today: ${dateStr2}`);
|
|
1569
1345
|
return existingChecklist._id;
|
|
1570
1346
|
}
|
|
1571
|
-
const
|
|
1572
|
-
|
|
1347
|
+
const siteIds = await getHygieneSiteIds();
|
|
1348
|
+
if (!Array.isArray(siteIds)) {
|
|
1349
|
+
import_node_server_utils10.logger.error("getHygieneSiteIds returned non-array value:", siteIds);
|
|
1350
|
+
throw new import_node_server_utils10.InternalServerError("Failed to retrieve site IDs");
|
|
1351
|
+
}
|
|
1352
|
+
if (siteIds.length === 0) {
|
|
1353
|
+
import_node_server_utils10.logger.warn("No sites found for creating parent checklist");
|
|
1354
|
+
throw new import_node_server_utils10.BadRequestError("No sites available for checklist creation");
|
|
1355
|
+
}
|
|
1356
|
+
const checklistDocs = [];
|
|
1357
|
+
for (const site of siteIds) {
|
|
1358
|
+
checklistDocs.push(
|
|
1359
|
+
MParentChecklist({
|
|
1360
|
+
site,
|
|
1361
|
+
createdAt: currentDate
|
|
1362
|
+
})
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
const result = await collection.insertMany(checklistDocs, { session });
|
|
1573
1366
|
delNamespace().then(() => {
|
|
1574
1367
|
import_node_server_utils10.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1575
1368
|
}).catch((err) => {
|
|
@@ -1580,9 +1373,9 @@ function useParentChecklistRepo() {
|
|
|
1580
1373
|
});
|
|
1581
1374
|
const dateStr = currentDate.toISOString().split("T")[0];
|
|
1582
1375
|
import_node_server_utils10.logger.info(
|
|
1583
|
-
`Created
|
|
1376
|
+
`Created ${Object.keys(result.insertedIds).length} parent checklists for today: ${dateStr}`
|
|
1584
1377
|
);
|
|
1585
|
-
return result.
|
|
1378
|
+
return Object.values(result.insertedIds);
|
|
1586
1379
|
} catch (error) {
|
|
1587
1380
|
import_node_server_utils10.logger.error("Failed to create daily parent checklist", error);
|
|
1588
1381
|
throw error;
|
|
@@ -1593,7 +1386,6 @@ function useParentChecklistRepo() {
|
|
|
1593
1386
|
limit = 10,
|
|
1594
1387
|
search = "",
|
|
1595
1388
|
site,
|
|
1596
|
-
type,
|
|
1597
1389
|
startDate = "",
|
|
1598
1390
|
endDate = ""
|
|
1599
1391
|
}) {
|
|
@@ -1605,19 +1397,13 @@ function useParentChecklistRepo() {
|
|
|
1605
1397
|
};
|
|
1606
1398
|
try {
|
|
1607
1399
|
site = new import_mongodb6.ObjectId(site);
|
|
1400
|
+
query.site = site;
|
|
1608
1401
|
cacheOptions.site = site.toString();
|
|
1609
1402
|
} catch (error) {
|
|
1610
1403
|
throw new import_node_server_utils10.BadRequestError("Invalid site ID format.");
|
|
1611
1404
|
}
|
|
1612
|
-
cacheOptions.type = type;
|
|
1613
|
-
query.status = {
|
|
1614
|
-
$elemMatch: {
|
|
1615
|
-
site: new import_mongodb6.ObjectId(site),
|
|
1616
|
-
type
|
|
1617
|
-
}
|
|
1618
|
-
};
|
|
1619
1405
|
if (search) {
|
|
1620
|
-
query.$
|
|
1406
|
+
query.$text = { $search: search };
|
|
1621
1407
|
cacheOptions.search = search;
|
|
1622
1408
|
}
|
|
1623
1409
|
if (startDate && endDate) {
|
|
@@ -1642,35 +1428,24 @@ function useParentChecklistRepo() {
|
|
|
1642
1428
|
}
|
|
1643
1429
|
try {
|
|
1644
1430
|
const pipeline = [{ $match: query }];
|
|
1645
|
-
const filterConditions = [];
|
|
1646
|
-
filterConditions.push({ $eq: ["$$this.site", new import_mongodb6.ObjectId(site)] });
|
|
1647
|
-
filterConditions.push({ $eq: ["$$this.type", type] });
|
|
1648
|
-
pipeline.push({
|
|
1649
|
-
$addFields: {
|
|
1650
|
-
filteredStatus: {
|
|
1651
|
-
$filter: {
|
|
1652
|
-
input: "$status",
|
|
1653
|
-
cond: { $and: filterConditions }
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
});
|
|
1658
|
-
pipeline.push({
|
|
1659
|
-
$match: {
|
|
1660
|
-
filteredStatus: { $ne: [] }
|
|
1661
|
-
}
|
|
1662
|
-
});
|
|
1663
|
-
pipeline.push({
|
|
1664
|
-
$addFields: {
|
|
1665
|
-
statusObj: { $arrayElemAt: ["$filteredStatus", 0] }
|
|
1666
|
-
}
|
|
1667
|
-
});
|
|
1668
1431
|
pipeline.push({
|
|
1669
1432
|
$project: {
|
|
1670
1433
|
_id: 1,
|
|
1671
|
-
|
|
1672
|
-
status:
|
|
1673
|
-
|
|
1434
|
+
site: 1,
|
|
1435
|
+
status: {
|
|
1436
|
+
$switch: {
|
|
1437
|
+
branches: [
|
|
1438
|
+
{ case: { $eq: ["$status", "ready"] }, then: "Ready" },
|
|
1439
|
+
{
|
|
1440
|
+
case: { $eq: ["$status", "ongoing"] },
|
|
1441
|
+
then: "Ongoing"
|
|
1442
|
+
},
|
|
1443
|
+
{ case: { $eq: ["$status", "completed"] }, then: "Completed" }
|
|
1444
|
+
],
|
|
1445
|
+
default: "$status"
|
|
1446
|
+
}
|
|
1447
|
+
},
|
|
1448
|
+
completedAt: 1,
|
|
1674
1449
|
createdAt: 1
|
|
1675
1450
|
}
|
|
1676
1451
|
});
|
|
@@ -1692,10 +1467,10 @@ function useParentChecklistRepo() {
|
|
|
1692
1467
|
throw error;
|
|
1693
1468
|
}
|
|
1694
1469
|
}
|
|
1695
|
-
async function updateParentChecklistStatuses(
|
|
1470
|
+
async function updateParentChecklistStatuses(createdAt) {
|
|
1696
1471
|
try {
|
|
1697
1472
|
const currentDate = /* @__PURE__ */ new Date();
|
|
1698
|
-
const dateToUpdate =
|
|
1473
|
+
const dateToUpdate = createdAt || new Date(currentDate.getTime() - 24 * 60 * 60 * 1e3);
|
|
1699
1474
|
const startOfDay = new Date(dateToUpdate);
|
|
1700
1475
|
startOfDay.setUTCHours(0, 0, 0, 0);
|
|
1701
1476
|
const endOfDay = new Date(dateToUpdate);
|
|
@@ -1714,38 +1489,32 @@ function useParentChecklistRepo() {
|
|
|
1714
1489
|
},
|
|
1715
1490
|
{
|
|
1716
1491
|
$lookup: {
|
|
1717
|
-
from: "
|
|
1718
|
-
|
|
1719
|
-
foreignField: "parentChecklist",
|
|
1492
|
+
from: "site.cleaning.schedule.areas",
|
|
1493
|
+
let: { parentId: "$_id" },
|
|
1720
1494
|
pipeline: [
|
|
1495
|
+
{
|
|
1496
|
+
$match: {
|
|
1497
|
+
$expr: { $eq: ["$parentChecklist", "$$parentId"] }
|
|
1498
|
+
}
|
|
1499
|
+
},
|
|
1721
1500
|
{
|
|
1722
1501
|
$group: {
|
|
1723
1502
|
_id: {
|
|
1724
|
-
|
|
1725
|
-
type: "$type"
|
|
1503
|
+
parentChecklist: "$parentChecklist"
|
|
1726
1504
|
},
|
|
1727
1505
|
completedCount: {
|
|
1728
1506
|
$sum: {
|
|
1729
|
-
$cond: [{ $eq: ["$status", "
|
|
1507
|
+
$cond: [{ $eq: ["$status", "completed"] }, 1, 0]
|
|
1730
1508
|
}
|
|
1731
1509
|
},
|
|
1732
|
-
|
|
1510
|
+
ongoingCount: {
|
|
1733
1511
|
$sum: {
|
|
1734
|
-
$cond: [{ $eq: ["$status", "
|
|
1512
|
+
$cond: [{ $eq: ["$status", "ongoing"] }, 1, 0]
|
|
1735
1513
|
}
|
|
1736
1514
|
},
|
|
1737
|
-
|
|
1515
|
+
readyCount: {
|
|
1738
1516
|
$sum: {
|
|
1739
|
-
$cond: [
|
|
1740
|
-
{
|
|
1741
|
-
$or: [
|
|
1742
|
-
{ $eq: ["$status", "To Do"] },
|
|
1743
|
-
{ $eq: ["$status", "Pending"] }
|
|
1744
|
-
]
|
|
1745
|
-
},
|
|
1746
|
-
1,
|
|
1747
|
-
0
|
|
1748
|
-
]
|
|
1517
|
+
$cond: [{ $eq: ["$status", "ready"] }, 1, 0]
|
|
1749
1518
|
}
|
|
1750
1519
|
},
|
|
1751
1520
|
totalCount: { $sum: 1 }
|
|
@@ -1758,21 +1527,21 @@ function useParentChecklistRepo() {
|
|
|
1758
1527
|
if: {
|
|
1759
1528
|
$and: [
|
|
1760
1529
|
{ $gt: ["$completedCount", 0] },
|
|
1761
|
-
{ $eq: ["$
|
|
1762
|
-
{ $eq: ["$
|
|
1530
|
+
{ $eq: ["$ongoingCount", 0] },
|
|
1531
|
+
{ $eq: ["$readyCount", 0] }
|
|
1763
1532
|
]
|
|
1764
1533
|
},
|
|
1765
|
-
then: "
|
|
1534
|
+
then: "completed",
|
|
1766
1535
|
else: {
|
|
1767
1536
|
$cond: {
|
|
1768
1537
|
if: {
|
|
1769
1538
|
$and: [
|
|
1770
1539
|
{ $eq: ["$completedCount", 0] },
|
|
1771
|
-
{ $eq: ["$
|
|
1540
|
+
{ $eq: ["$ongoingCount", 0] }
|
|
1772
1541
|
]
|
|
1773
1542
|
},
|
|
1774
|
-
then: "
|
|
1775
|
-
else: "
|
|
1543
|
+
then: "expired",
|
|
1544
|
+
else: "ongoing"
|
|
1776
1545
|
}
|
|
1777
1546
|
}
|
|
1778
1547
|
}
|
|
@@ -1782,8 +1551,8 @@ function useParentChecklistRepo() {
|
|
|
1782
1551
|
if: {
|
|
1783
1552
|
$and: [
|
|
1784
1553
|
{ $gt: ["$completedCount", 0] },
|
|
1785
|
-
{ $eq: ["$
|
|
1786
|
-
{ $eq: ["$
|
|
1554
|
+
{ $eq: ["$ongoingCount", 0] },
|
|
1555
|
+
{ $eq: ["$readyCount", 0] }
|
|
1787
1556
|
]
|
|
1788
1557
|
},
|
|
1789
1558
|
then: /* @__PURE__ */ new Date(),
|
|
@@ -1796,27 +1565,21 @@ function useParentChecklistRepo() {
|
|
|
1796
1565
|
as: "areaStats"
|
|
1797
1566
|
}
|
|
1798
1567
|
},
|
|
1568
|
+
{
|
|
1569
|
+
$match: {
|
|
1570
|
+
"areaStats.0": { $exists: true }
|
|
1571
|
+
}
|
|
1572
|
+
},
|
|
1799
1573
|
{
|
|
1800
1574
|
$addFields: {
|
|
1801
|
-
|
|
1802
|
-
$map: {
|
|
1803
|
-
input: "$areaStats",
|
|
1804
|
-
as: "stat",
|
|
1805
|
-
in: {
|
|
1806
|
-
site: "$$stat._id.site",
|
|
1807
|
-
type: "$$stat._id.type",
|
|
1808
|
-
status: "$$stat.finalStatus",
|
|
1809
|
-
completedAt: "$$stat.completedAt"
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
}
|
|
1575
|
+
areaData: { $arrayElemAt: ["$areaStats", 0] }
|
|
1813
1576
|
}
|
|
1814
1577
|
},
|
|
1815
|
-
{ $match: { newStatus: { $ne: [] } } },
|
|
1816
1578
|
{
|
|
1817
1579
|
$project: {
|
|
1818
1580
|
_id: 1,
|
|
1819
|
-
newStatus:
|
|
1581
|
+
newStatus: "$areaData.finalStatus",
|
|
1582
|
+
completedAt: "$areaData.completedAt"
|
|
1820
1583
|
}
|
|
1821
1584
|
}
|
|
1822
1585
|
]).toArray();
|
|
@@ -1830,9 +1593,8 @@ function useParentChecklistRepo() {
|
|
|
1830
1593
|
return null;
|
|
1831
1594
|
}
|
|
1832
1595
|
const bulkOps = statusUpdates.map((update) => {
|
|
1833
|
-
const statusTypes = update.newStatus.map((s) => `${s.type}(${s.status})`).join(", ");
|
|
1834
1596
|
import_node_server_utils10.logger.info(
|
|
1835
|
-
`Updating parent checklist ${update._id} with ${update.newStatus
|
|
1597
|
+
`Updating parent checklist ${update._id} with status: ${update.newStatus}`
|
|
1836
1598
|
);
|
|
1837
1599
|
return {
|
|
1838
1600
|
updateOne: {
|
|
@@ -1840,6 +1602,7 @@ function useParentChecklistRepo() {
|
|
|
1840
1602
|
update: {
|
|
1841
1603
|
$set: {
|
|
1842
1604
|
status: update.newStatus,
|
|
1605
|
+
completedAt: update.completedAt,
|
|
1843
1606
|
updatedAt: /* @__PURE__ */ new Date()
|
|
1844
1607
|
}
|
|
1845
1608
|
}
|
|
@@ -1865,6 +1628,36 @@ function useParentChecklistRepo() {
|
|
|
1865
1628
|
throw error;
|
|
1866
1629
|
}
|
|
1867
1630
|
}
|
|
1631
|
+
async function getHygieneSiteIds() {
|
|
1632
|
+
const query = {
|
|
1633
|
+
status: { $ne: "deleted" }
|
|
1634
|
+
};
|
|
1635
|
+
const cacheKey = (0, import_node_server_utils10.makeCacheKey)(site_collection, { tag: "site-ids" });
|
|
1636
|
+
const cachedData = await getCache(cacheKey);
|
|
1637
|
+
if (cachedData && Array.isArray(cachedData)) {
|
|
1638
|
+
import_node_server_utils10.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
1639
|
+
return cachedData;
|
|
1640
|
+
}
|
|
1641
|
+
try {
|
|
1642
|
+
const items = await siteCollection.aggregate([
|
|
1643
|
+
{ $match: query },
|
|
1644
|
+
{ $project: { _id: 1 } },
|
|
1645
|
+
{ $sort: { _id: -1 } }
|
|
1646
|
+
]).toArray();
|
|
1647
|
+
const siteIds = items.map((item) => item._id.toString());
|
|
1648
|
+
if (siteIds.length > 0) {
|
|
1649
|
+
setCache(cacheKey, siteIds, 15 * 60).then(() => {
|
|
1650
|
+
import_node_server_utils10.logger.info(`Cache set for key: ${cacheKey}`);
|
|
1651
|
+
}).catch((err) => {
|
|
1652
|
+
import_node_server_utils10.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
return siteIds;
|
|
1656
|
+
} catch (error) {
|
|
1657
|
+
import_node_server_utils10.logger.error("Failed to get hygiene site IDs", error);
|
|
1658
|
+
throw error;
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1868
1661
|
return {
|
|
1869
1662
|
createIndex,
|
|
1870
1663
|
createParentChecklist,
|
|
@@ -1906,7 +1699,6 @@ function useParentChecklistController() {
|
|
|
1906
1699
|
limit: import_joi6.default.number().min(1).optional().allow("", null),
|
|
1907
1700
|
search: import_joi6.default.string().optional().allow("", null),
|
|
1908
1701
|
site: import_joi6.default.string().hex().required(),
|
|
1909
|
-
type: import_joi6.default.string().required().valid(...allowedTypes),
|
|
1910
1702
|
startDate: import_joi6.default.alternatives().try(import_joi6.default.date(), import_joi6.default.string()).optional().allow("", null),
|
|
1911
1703
|
endDate: import_joi6.default.alternatives().try(import_joi6.default.date(), import_joi6.default.string()).optional().allow("", null)
|
|
1912
1704
|
});
|
|
@@ -1916,1299 +1708,119 @@ function useParentChecklistController() {
|
|
|
1916
1708
|
next(new import_node_server_utils11.BadRequestError(error.message));
|
|
1917
1709
|
return;
|
|
1918
1710
|
}
|
|
1919
|
-
const page = parseInt(req.query.page) ?? 1;
|
|
1920
|
-
const limit = parseInt(req.query.limit) ?? 20;
|
|
1921
|
-
const search = req.query.search ?? "";
|
|
1922
|
-
const site = req.params.site ?? "";
|
|
1923
|
-
const
|
|
1924
|
-
const
|
|
1925
|
-
const endDate = req.query.endDate ?? "";
|
|
1926
|
-
try {
|
|
1927
|
-
const data = await _getAllParentChecklist({
|
|
1928
|
-
page,
|
|
1929
|
-
limit,
|
|
1930
|
-
search,
|
|
1931
|
-
site,
|
|
1932
|
-
type,
|
|
1933
|
-
startDate,
|
|
1934
|
-
endDate
|
|
1935
|
-
});
|
|
1936
|
-
res.json(data);
|
|
1937
|
-
return;
|
|
1938
|
-
} catch (error2) {
|
|
1939
|
-
import_node_server_utils11.logger.log({ level: "error", message: error2.message });
|
|
1940
|
-
next(error2);
|
|
1941
|
-
return;
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
|
-
return {
|
|
1945
|
-
createParentChecklist,
|
|
1946
|
-
getAllParentChecklist
|
|
1947
|
-
};
|
|
1948
|
-
}
|
|
1949
|
-
|
|
1950
|
-
// src/models/hygiene-unit.model.ts
|
|
1951
|
-
var import_node_server_utils12 = require("@iservice365/node-server-utils");
|
|
1952
|
-
var import_joi7 = __toESM(require("joi"));
|
|
1953
|
-
var import_mongodb7 = require("mongodb");
|
|
1954
|
-
var unitSchema = import_joi7.default.object({
|
|
1955
|
-
name: import_joi7.default.string().required(),
|
|
1956
|
-
site: import_joi7.default.string().hex().required(),
|
|
1957
|
-
createdBy: import_joi7.default.string().hex().required()
|
|
1958
|
-
});
|
|
1959
|
-
function MUnit(value) {
|
|
1960
|
-
const { error } = unitSchema.validate(value);
|
|
1961
|
-
if (error) {
|
|
1962
|
-
import_node_server_utils12.logger.info(`Hygiene Unit Model: ${error.message}`);
|
|
1963
|
-
throw new import_node_server_utils12.BadRequestError(error.message);
|
|
1964
|
-
}
|
|
1965
|
-
if (value.site) {
|
|
1966
|
-
try {
|
|
1967
|
-
value.site = new import_mongodb7.ObjectId(value.site);
|
|
1968
|
-
} catch (error2) {
|
|
1969
|
-
throw new import_node_server_utils12.BadRequestError("Invalid site ID format.");
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
if (value.createdBy) {
|
|
1973
|
-
try {
|
|
1974
|
-
value.createdBy = new import_mongodb7.ObjectId(value.createdBy);
|
|
1975
|
-
} catch (error2) {
|
|
1976
|
-
throw new import_node_server_utils12.BadRequestError("Invalid createdBy ID format.");
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
return {
|
|
1980
|
-
name: value.name,
|
|
1981
|
-
createdBy: value.createdBy,
|
|
1982
|
-
site: value.site,
|
|
1983
|
-
status: "active",
|
|
1984
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
1985
|
-
updatedAt: value.updatedAt ?? "",
|
|
1986
|
-
deletedAt: value.deletedAt ?? ""
|
|
1987
|
-
};
|
|
1988
|
-
}
|
|
1989
|
-
|
|
1990
|
-
// src/services/hygiene-unit.service.ts
|
|
1991
|
-
var import_node_server_utils14 = require("@iservice365/node-server-utils");
|
|
1992
|
-
|
|
1993
|
-
// src/repositories/hygiene-unit.repository.ts
|
|
1994
|
-
var import_mongodb8 = require("mongodb");
|
|
1995
|
-
var import_node_server_utils13 = require("@iservice365/node-server-utils");
|
|
1996
|
-
function useUnitRepository() {
|
|
1997
|
-
const db = import_node_server_utils13.useAtlas.getDb();
|
|
1998
|
-
if (!db) {
|
|
1999
|
-
throw new import_node_server_utils13.InternalServerError("Unable to connect to server.");
|
|
2000
|
-
}
|
|
2001
|
-
const namespace_collection = "hygiene-units";
|
|
2002
|
-
const collection = db.collection(namespace_collection);
|
|
2003
|
-
const { delNamespace, setCache, getCache } = (0, import_node_server_utils13.useCache)(namespace_collection);
|
|
2004
|
-
async function createIndex() {
|
|
2005
|
-
try {
|
|
2006
|
-
await collection.createIndexes([
|
|
2007
|
-
{ key: { site: 1 } },
|
|
2008
|
-
{ key: { createdBy: 1 } },
|
|
2009
|
-
{ key: { status: 1 } }
|
|
2010
|
-
]);
|
|
2011
|
-
} catch (error) {
|
|
2012
|
-
throw new import_node_server_utils13.InternalServerError("Failed to create index on hygiene unit.");
|
|
2013
|
-
}
|
|
2014
|
-
}
|
|
2015
|
-
async function createTextIndex() {
|
|
2016
|
-
try {
|
|
2017
|
-
await collection.createIndex({ name: "text" });
|
|
2018
|
-
} catch (error) {
|
|
2019
|
-
throw new import_node_server_utils13.InternalServerError(
|
|
2020
|
-
"Failed to create text index on hygiene unit."
|
|
2021
|
-
);
|
|
2022
|
-
}
|
|
2023
|
-
}
|
|
2024
|
-
async function createUniqueIndex() {
|
|
2025
|
-
try {
|
|
2026
|
-
await collection.createIndex(
|
|
2027
|
-
{ name: 1, site: 1, deletedAt: 1 },
|
|
2028
|
-
{ unique: true }
|
|
2029
|
-
);
|
|
2030
|
-
} catch (error) {
|
|
2031
|
-
throw new import_node_server_utils13.InternalServerError(
|
|
2032
|
-
"Failed to create unique index on hygiene unit."
|
|
2033
|
-
);
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
async function createUnit(value, session) {
|
|
2037
|
-
try {
|
|
2038
|
-
value = MUnit(value);
|
|
2039
|
-
const res = await collection.insertOne(value, { session });
|
|
2040
|
-
delNamespace().then(() => {
|
|
2041
|
-
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2042
|
-
}).catch((err) => {
|
|
2043
|
-
import_node_server_utils13.logger.error(
|
|
2044
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2045
|
-
err
|
|
2046
|
-
);
|
|
2047
|
-
});
|
|
2048
|
-
return res.insertedId;
|
|
2049
|
-
} catch (error) {
|
|
2050
|
-
const isDuplicated = error.message.includes("duplicate");
|
|
2051
|
-
if (isDuplicated) {
|
|
2052
|
-
throw new import_node_server_utils13.BadRequestError("Unit already exists.");
|
|
2053
|
-
}
|
|
2054
|
-
throw error;
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
async function getUnits({
|
|
2058
|
-
page = 1,
|
|
2059
|
-
limit = 10,
|
|
2060
|
-
search = "",
|
|
2061
|
-
startDate = "",
|
|
2062
|
-
endDate = "",
|
|
2063
|
-
site = ""
|
|
2064
|
-
}) {
|
|
2065
|
-
page = page > 0 ? page - 1 : 0;
|
|
2066
|
-
try {
|
|
2067
|
-
site = new import_mongodb8.ObjectId(site);
|
|
2068
|
-
} catch (error) {
|
|
2069
|
-
throw new import_node_server_utils13.BadRequestError("Invalid site ID format.");
|
|
2070
|
-
}
|
|
2071
|
-
const query = {
|
|
2072
|
-
status: { $ne: "deleted" },
|
|
2073
|
-
site
|
|
2074
|
-
};
|
|
2075
|
-
const cacheOptions = {
|
|
2076
|
-
page,
|
|
2077
|
-
limit,
|
|
2078
|
-
site: site.toString()
|
|
2079
|
-
};
|
|
2080
|
-
if (search) {
|
|
2081
|
-
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
2082
|
-
cacheOptions.search = search;
|
|
2083
|
-
}
|
|
2084
|
-
if (startDate && endDate) {
|
|
2085
|
-
query.createdAt = {
|
|
2086
|
-
$gte: new Date(startDate),
|
|
2087
|
-
$lte: new Date(endDate)
|
|
2088
|
-
};
|
|
2089
|
-
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
2090
|
-
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
2091
|
-
} else if (startDate) {
|
|
2092
|
-
query.createdAt = { $gte: new Date(startDate) };
|
|
2093
|
-
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
2094
|
-
} else if (endDate) {
|
|
2095
|
-
query.createdAt = { $lte: new Date(endDate) };
|
|
2096
|
-
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
2097
|
-
}
|
|
2098
|
-
const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2099
|
-
const cachedData = await getCache(cacheKey);
|
|
2100
|
-
if (cachedData) {
|
|
2101
|
-
import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2102
|
-
return cachedData;
|
|
2103
|
-
}
|
|
2104
|
-
try {
|
|
2105
|
-
const items = await collection.aggregate([
|
|
2106
|
-
{ $match: query },
|
|
2107
|
-
{
|
|
2108
|
-
$lookup: {
|
|
2109
|
-
from: "sites",
|
|
2110
|
-
localField: "site",
|
|
2111
|
-
foreignField: "_id",
|
|
2112
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
2113
|
-
as: "site"
|
|
2114
|
-
}
|
|
2115
|
-
},
|
|
2116
|
-
{
|
|
2117
|
-
$unwind: {
|
|
2118
|
-
path: "$site",
|
|
2119
|
-
preserveNullAndEmptyArrays: true
|
|
2120
|
-
}
|
|
2121
|
-
},
|
|
2122
|
-
{
|
|
2123
|
-
$lookup: {
|
|
2124
|
-
from: "users",
|
|
2125
|
-
localField: "createdBy",
|
|
2126
|
-
foreignField: "_id",
|
|
2127
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
2128
|
-
as: "createdBy"
|
|
2129
|
-
}
|
|
2130
|
-
},
|
|
2131
|
-
{
|
|
2132
|
-
$unwind: {
|
|
2133
|
-
path: "$createdBy",
|
|
2134
|
-
preserveNullAndEmptyArrays: true
|
|
2135
|
-
}
|
|
2136
|
-
},
|
|
2137
|
-
{
|
|
2138
|
-
$project: {
|
|
2139
|
-
name: 1,
|
|
2140
|
-
site: "$site._id",
|
|
2141
|
-
siteName: "$site.name",
|
|
2142
|
-
createdByName: "$createdBy.name",
|
|
2143
|
-
checklist: 1,
|
|
2144
|
-
status: 1,
|
|
2145
|
-
createdAt: 1
|
|
2146
|
-
}
|
|
2147
|
-
},
|
|
2148
|
-
{ $sort: { _id: -1 } },
|
|
2149
|
-
{ $skip: page * limit },
|
|
2150
|
-
{ $limit: limit }
|
|
2151
|
-
]).toArray();
|
|
2152
|
-
const length = await collection.countDocuments(query);
|
|
2153
|
-
const data = (0, import_node_server_utils13.paginate)(items, page, limit, length);
|
|
2154
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2155
|
-
import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2156
|
-
}).catch((err) => {
|
|
2157
|
-
import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2158
|
-
});
|
|
2159
|
-
return data;
|
|
2160
|
-
} catch (error) {
|
|
2161
|
-
throw error;
|
|
2162
|
-
}
|
|
2163
|
-
}
|
|
2164
|
-
async function getUnitByName(name, site) {
|
|
2165
|
-
try {
|
|
2166
|
-
if (site)
|
|
2167
|
-
site = new import_mongodb8.ObjectId(site);
|
|
2168
|
-
} catch (error) {
|
|
2169
|
-
throw new import_node_server_utils13.BadRequestError("Invalid site ID format.");
|
|
2170
|
-
}
|
|
2171
|
-
try {
|
|
2172
|
-
return await collection.findOne({
|
|
2173
|
-
name: { $regex: new RegExp(`^${name}$`, "i") },
|
|
2174
|
-
...site && { site }
|
|
2175
|
-
});
|
|
2176
|
-
} catch (error) {
|
|
2177
|
-
throw new import_node_server_utils13.BadRequestError("Unable to fetch unit by name.");
|
|
2178
|
-
}
|
|
2179
|
-
}
|
|
2180
|
-
async function getUnitById(id, site) {
|
|
2181
|
-
try {
|
|
2182
|
-
id = typeof id === "string" ? new import_mongodb8.ObjectId(id) : id;
|
|
2183
|
-
} catch (error) {
|
|
2184
|
-
throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
|
|
2185
|
-
}
|
|
2186
|
-
try {
|
|
2187
|
-
if (site)
|
|
2188
|
-
site = new import_mongodb8.ObjectId(site);
|
|
2189
|
-
} catch (error) {
|
|
2190
|
-
throw new import_node_server_utils13.BadRequestError(
|
|
2191
|
-
"Unable to fetch unit by ID, Invalid site ID format."
|
|
2192
|
-
);
|
|
2193
|
-
}
|
|
2194
|
-
try {
|
|
2195
|
-
return await collection.findOne({ _id: id, ...site && { site } });
|
|
2196
|
-
} catch (error) {
|
|
2197
|
-
throw new import_node_server_utils13.BadRequestError("Unable to fetch unit by id.");
|
|
2198
|
-
}
|
|
2199
|
-
}
|
|
2200
|
-
async function updateUnit(_id, value) {
|
|
2201
|
-
try {
|
|
2202
|
-
_id = new import_mongodb8.ObjectId(_id);
|
|
2203
|
-
} catch (error) {
|
|
2204
|
-
throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
|
|
2205
|
-
}
|
|
2206
|
-
try {
|
|
2207
|
-
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
2208
|
-
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
2209
|
-
if (res.modifiedCount === 0) {
|
|
2210
|
-
throw new import_node_server_utils13.InternalServerError("Unable to update cleaning unit.");
|
|
2211
|
-
}
|
|
2212
|
-
delNamespace().then(() => {
|
|
2213
|
-
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2214
|
-
}).catch((err) => {
|
|
2215
|
-
import_node_server_utils13.logger.error(
|
|
2216
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2217
|
-
err
|
|
2218
|
-
);
|
|
2219
|
-
});
|
|
2220
|
-
return res.modifiedCount;
|
|
2221
|
-
} catch (error) {
|
|
2222
|
-
const isDuplicated = error.message.includes("duplicate");
|
|
2223
|
-
if (isDuplicated) {
|
|
2224
|
-
throw new import_node_server_utils13.BadRequestError("Area already exists.");
|
|
2225
|
-
}
|
|
2226
|
-
throw error;
|
|
2227
|
-
}
|
|
2228
|
-
}
|
|
2229
|
-
async function deleteUnit(_id, session) {
|
|
2230
|
-
try {
|
|
2231
|
-
_id = new import_mongodb8.ObjectId(_id);
|
|
2232
|
-
} catch (error) {
|
|
2233
|
-
throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
|
|
2234
|
-
}
|
|
2235
|
-
try {
|
|
2236
|
-
const updateValue = {
|
|
2237
|
-
status: "deleted",
|
|
2238
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
2239
|
-
deletedAt: /* @__PURE__ */ new Date()
|
|
2240
|
-
};
|
|
2241
|
-
const res = await collection.updateOne(
|
|
2242
|
-
{ _id },
|
|
2243
|
-
{ $set: updateValue },
|
|
2244
|
-
{ session }
|
|
2245
|
-
);
|
|
2246
|
-
if (res.modifiedCount === 0) {
|
|
2247
|
-
throw new import_node_server_utils13.InternalServerError("Unable to delete unit.");
|
|
2248
|
-
}
|
|
2249
|
-
delNamespace().then(() => {
|
|
2250
|
-
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2251
|
-
}).catch((err) => {
|
|
2252
|
-
import_node_server_utils13.logger.error(
|
|
2253
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2254
|
-
err
|
|
2255
|
-
);
|
|
2256
|
-
});
|
|
2257
|
-
return res.modifiedCount;
|
|
2258
|
-
} catch (error) {
|
|
2259
|
-
throw error;
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
return {
|
|
2263
|
-
createIndex,
|
|
2264
|
-
createTextIndex,
|
|
2265
|
-
createUniqueIndex,
|
|
2266
|
-
createUnit,
|
|
2267
|
-
getUnits,
|
|
2268
|
-
getUnitByName,
|
|
2269
|
-
getUnitById,
|
|
2270
|
-
updateUnit,
|
|
2271
|
-
deleteUnit
|
|
2272
|
-
};
|
|
2273
|
-
}
|
|
2274
|
-
|
|
2275
|
-
// src/services/hygiene-unit.service.ts
|
|
2276
|
-
function useUnitService() {
|
|
2277
|
-
const { createUnit: _createUnit } = useUnitRepository();
|
|
2278
|
-
async function uploadByFile({
|
|
2279
|
-
dataJson,
|
|
2280
|
-
createdBy,
|
|
2281
|
-
site
|
|
2282
|
-
}) {
|
|
2283
|
-
let dataArray;
|
|
2284
|
-
try {
|
|
2285
|
-
dataArray = JSON.parse(dataJson);
|
|
2286
|
-
} catch (error) {
|
|
2287
|
-
throw new import_node_server_utils14.BadRequestError("Invalid JSON format for data in excel");
|
|
2288
|
-
}
|
|
2289
|
-
if (!dataArray || dataArray.length === 0) {
|
|
2290
|
-
throw new import_node_server_utils14.NotFoundError("No data found in the uploaded file");
|
|
2291
|
-
}
|
|
2292
|
-
const session = import_node_server_utils14.useAtlas.getClient()?.startSession();
|
|
2293
|
-
const insertedUnitIds = [];
|
|
2294
|
-
try {
|
|
2295
|
-
session?.startTransaction();
|
|
2296
|
-
for (const row of dataArray) {
|
|
2297
|
-
if (!row?.UNIT_NAME) {
|
|
2298
|
-
import_node_server_utils14.logger.warn("Skipping row with missing UNIT_NAME:", row);
|
|
2299
|
-
continue;
|
|
2300
|
-
}
|
|
2301
|
-
try {
|
|
2302
|
-
const insertedId = await _createUnit(
|
|
2303
|
-
{
|
|
2304
|
-
name: String(row.UNIT_NAME).trim(),
|
|
2305
|
-
site,
|
|
2306
|
-
createdBy
|
|
2307
|
-
},
|
|
2308
|
-
session
|
|
2309
|
-
);
|
|
2310
|
-
insertedUnitIds.push(insertedId);
|
|
2311
|
-
} catch (error) {
|
|
2312
|
-
import_node_server_utils14.logger.error(
|
|
2313
|
-
`Error creating unit "${row.UNIT_NAME}":`,
|
|
2314
|
-
error.message
|
|
2315
|
-
);
|
|
2316
|
-
continue;
|
|
2317
|
-
}
|
|
2318
|
-
}
|
|
2319
|
-
await session?.commitTransaction();
|
|
2320
|
-
import_node_server_utils14.logger.info(`Successfully uploaded ${insertedUnitIds.length} units`);
|
|
2321
|
-
return {
|
|
2322
|
-
message: `Successfully uploaded ${insertedUnitIds.length} units`
|
|
2323
|
-
};
|
|
2324
|
-
} catch (error) {
|
|
2325
|
-
await session?.abortTransaction();
|
|
2326
|
-
import_node_server_utils14.logger.error("Error while uploading unit information", error);
|
|
2327
|
-
throw error;
|
|
2328
|
-
} finally {
|
|
2329
|
-
session?.endSession();
|
|
2330
|
-
}
|
|
2331
|
-
}
|
|
2332
|
-
return {
|
|
2333
|
-
uploadByFile
|
|
2334
|
-
};
|
|
2335
|
-
}
|
|
2336
|
-
|
|
2337
|
-
// src/controllers/hygiene-unit.controller.ts
|
|
2338
|
-
var import_node_server_utils15 = require("@iservice365/node-server-utils");
|
|
2339
|
-
var import_joi8 = __toESM(require("joi"));
|
|
2340
|
-
function useUnitController() {
|
|
2341
|
-
const {
|
|
2342
|
-
createUnit: _createUnit,
|
|
2343
|
-
getUnits: _getUnits,
|
|
2344
|
-
updateUnit: _updateUnit,
|
|
2345
|
-
deleteUnit: _deleteUnit
|
|
2346
|
-
} = useUnitRepository();
|
|
2347
|
-
const { uploadByFile: _uploadByFile } = useUnitService();
|
|
2348
|
-
async function createUnit(req, res, next) {
|
|
2349
|
-
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
2350
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
2351
|
-
{}
|
|
2352
|
-
) : {};
|
|
2353
|
-
const createdBy = cookies["user"] || "";
|
|
2354
|
-
const payload = { ...req.body, createdBy };
|
|
2355
|
-
const { error } = unitSchema.validate(payload);
|
|
2356
|
-
if (error) {
|
|
2357
|
-
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2358
|
-
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2359
|
-
return;
|
|
2360
|
-
}
|
|
2361
|
-
try {
|
|
2362
|
-
const id = await _createUnit(payload);
|
|
2363
|
-
res.status(201).json({ message: "Unit created successfully.", id });
|
|
2364
|
-
return;
|
|
2365
|
-
} catch (error2) {
|
|
2366
|
-
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2367
|
-
next(error2);
|
|
2368
|
-
return;
|
|
2369
|
-
}
|
|
2370
|
-
}
|
|
2371
|
-
async function getAll(req, res, next) {
|
|
2372
|
-
const query = req.query;
|
|
2373
|
-
const validation = import_joi8.default.object({
|
|
2374
|
-
page: import_joi8.default.number().min(1).optional().allow("", null),
|
|
2375
|
-
limit: import_joi8.default.number().min(1).optional().allow("", null),
|
|
2376
|
-
search: import_joi8.default.string().optional().allow("", null),
|
|
2377
|
-
startDate: import_joi8.default.alternatives().try(import_joi8.default.date(), import_joi8.default.string()).optional().allow("", null),
|
|
2378
|
-
endDate: import_joi8.default.alternatives().try(import_joi8.default.date(), import_joi8.default.string()).optional().allow("", null),
|
|
2379
|
-
site: import_joi8.default.string().hex().optional().allow("", null)
|
|
2380
|
-
});
|
|
2381
|
-
const { error } = validation.validate(query);
|
|
2382
|
-
if (error) {
|
|
2383
|
-
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2384
|
-
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2385
|
-
return;
|
|
2386
|
-
}
|
|
2387
|
-
const page = parseInt(req.query.page) ?? 1;
|
|
2388
|
-
const limit = parseInt(req.query.limit) ?? 20;
|
|
2389
|
-
const search = req.query.search ?? "";
|
|
2390
|
-
const site = req.query.site ?? "";
|
|
2391
|
-
const startDate = req.query.startDate ?? "";
|
|
2392
|
-
const endDate = req.query.endDate ?? "";
|
|
2393
|
-
try {
|
|
2394
|
-
const data = await _getUnits({
|
|
2395
|
-
page,
|
|
2396
|
-
limit,
|
|
2397
|
-
search,
|
|
2398
|
-
site,
|
|
2399
|
-
startDate,
|
|
2400
|
-
endDate
|
|
2401
|
-
});
|
|
2402
|
-
res.json(data);
|
|
2403
|
-
return;
|
|
2404
|
-
} catch (error2) {
|
|
2405
|
-
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2406
|
-
next(error2);
|
|
2407
|
-
return;
|
|
2408
|
-
}
|
|
2409
|
-
}
|
|
2410
|
-
async function updateUnit(req, res, next) {
|
|
2411
|
-
const payload = { id: req.params.id, ...req.body };
|
|
2412
|
-
const schema = import_joi8.default.object({
|
|
2413
|
-
id: import_joi8.default.string().hex().required(),
|
|
2414
|
-
name: import_joi8.default.string().required()
|
|
2415
|
-
});
|
|
2416
|
-
const { error } = schema.validate(payload);
|
|
2417
|
-
if (error) {
|
|
2418
|
-
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2419
|
-
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2420
|
-
return;
|
|
2421
|
-
}
|
|
2422
|
-
try {
|
|
2423
|
-
const { id, ...value } = payload;
|
|
2424
|
-
await _updateUnit(id, value);
|
|
2425
|
-
res.json({ message: "Unit updated successfully." });
|
|
2426
|
-
return;
|
|
2427
|
-
} catch (error2) {
|
|
2428
|
-
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2429
|
-
next(error2);
|
|
2430
|
-
return;
|
|
2431
|
-
}
|
|
2432
|
-
}
|
|
2433
|
-
async function deleteUnit(req, res, next) {
|
|
2434
|
-
const id = req.params.id;
|
|
2435
|
-
const validation = import_joi8.default.object({
|
|
2436
|
-
id: import_joi8.default.string().hex().required()
|
|
2437
|
-
});
|
|
2438
|
-
const { error } = validation.validate({ id });
|
|
2439
|
-
if (error) {
|
|
2440
|
-
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2441
|
-
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2442
|
-
return;
|
|
2443
|
-
}
|
|
2444
|
-
try {
|
|
2445
|
-
await _deleteUnit(id);
|
|
2446
|
-
res.json({ message: "Unit deleted successfully." });
|
|
2447
|
-
return;
|
|
2448
|
-
} catch (error2) {
|
|
2449
|
-
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2450
|
-
next(error2);
|
|
2451
|
-
return;
|
|
2452
|
-
}
|
|
2453
|
-
}
|
|
2454
|
-
async function uploadByFile(req, res, next) {
|
|
2455
|
-
if (!req.file) {
|
|
2456
|
-
next(new import_node_server_utils15.BadRequestError("File is required!"));
|
|
2457
|
-
return;
|
|
2458
|
-
}
|
|
2459
|
-
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
2460
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
2461
|
-
{}
|
|
2462
|
-
) : {};
|
|
2463
|
-
const createdBy = cookies["user"] || "";
|
|
2464
|
-
const { site } = req.body;
|
|
2465
|
-
const schema = import_joi8.default.object({
|
|
2466
|
-
site: import_joi8.default.string().hex().optional().allow("", null),
|
|
2467
|
-
createdBy: import_joi8.default.string().hex().required()
|
|
2468
|
-
});
|
|
2469
|
-
const { error } = schema.validate({ site, createdBy });
|
|
2470
|
-
if (error) {
|
|
2471
|
-
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2472
|
-
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2473
|
-
return;
|
|
2474
|
-
}
|
|
2475
|
-
try {
|
|
2476
|
-
const xlsData = await convertBufferFile(req.file.buffer);
|
|
2477
|
-
const dataJson = JSON.stringify(xlsData);
|
|
2478
|
-
const result = await _uploadByFile({ dataJson, createdBy, site });
|
|
2479
|
-
return res.status(201).json(result);
|
|
2480
|
-
} catch (error2) {
|
|
2481
|
-
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2482
|
-
next(error2);
|
|
2483
|
-
return;
|
|
2484
|
-
}
|
|
2485
|
-
}
|
|
2486
|
-
return {
|
|
2487
|
-
createUnit,
|
|
2488
|
-
getAll,
|
|
2489
|
-
updateUnit,
|
|
2490
|
-
deleteUnit,
|
|
2491
|
-
uploadByFile
|
|
2492
|
-
};
|
|
2493
|
-
}
|
|
2494
|
-
|
|
2495
|
-
// src/models/hygiene-schedule-task-area.model.ts
|
|
2496
|
-
var import_node_server_utils16 = require("@iservice365/node-server-utils");
|
|
2497
|
-
var import_joi9 = __toESM(require("joi"));
|
|
2498
|
-
var import_mongodb9 = require("mongodb");
|
|
2499
|
-
var scheduleTaskAreaSchema = import_joi9.default.object({
|
|
2500
|
-
name: import_joi9.default.string().required(),
|
|
2501
|
-
site: import_joi9.default.string().hex().required(),
|
|
2502
|
-
createdBy: import_joi9.default.string().hex().required(),
|
|
2503
|
-
checklist: import_joi9.default.array().items(
|
|
2504
|
-
import_joi9.default.object({
|
|
2505
|
-
_id: import_joi9.default.string().hex().required(),
|
|
2506
|
-
name: import_joi9.default.string().required()
|
|
2507
|
-
})
|
|
2508
|
-
).optional(),
|
|
2509
|
-
updatedAt: import_joi9.default.date().optional().allow("", null),
|
|
2510
|
-
status: import_joi9.default.string().allow("", null).optional()
|
|
2511
|
-
});
|
|
2512
|
-
function MScheduleTaskArea(value) {
|
|
2513
|
-
const { error } = scheduleTaskAreaSchema.validate(value);
|
|
2514
|
-
if (error) {
|
|
2515
|
-
throw new import_node_server_utils16.BadRequestError(error.message);
|
|
2516
|
-
}
|
|
2517
|
-
if (value.site) {
|
|
2518
|
-
try {
|
|
2519
|
-
value.site = new import_mongodb9.ObjectId(value.site);
|
|
2520
|
-
} catch (error2) {
|
|
2521
|
-
throw new import_node_server_utils16.BadRequestError("Invalid site ID format.");
|
|
2522
|
-
}
|
|
2523
|
-
}
|
|
2524
|
-
if (value.createdBy) {
|
|
2525
|
-
try {
|
|
2526
|
-
value.createdBy = new import_mongodb9.ObjectId(value.createdBy);
|
|
2527
|
-
} catch (error2) {
|
|
2528
|
-
throw new import_node_server_utils16.BadRequestError("Invalid createdBy ID format.");
|
|
2529
|
-
}
|
|
2530
|
-
}
|
|
2531
|
-
if (value.checklist && Array.isArray(value.checklist)) {
|
|
2532
|
-
value.checklist = value.checklist.map((item) => {
|
|
2533
|
-
try {
|
|
2534
|
-
return {
|
|
2535
|
-
...item,
|
|
2536
|
-
_id: new import_mongodb9.ObjectId(item._id)
|
|
2537
|
-
};
|
|
2538
|
-
} catch (error2) {
|
|
2539
|
-
throw new import_node_server_utils16.BadRequestError(
|
|
2540
|
-
`Invalid checklist item ID format: ${item._id}`
|
|
2541
|
-
);
|
|
2542
|
-
}
|
|
2543
|
-
});
|
|
2544
|
-
}
|
|
2545
|
-
return {
|
|
2546
|
-
name: value.name,
|
|
2547
|
-
site: value.site,
|
|
2548
|
-
createdBy: value.createdBy,
|
|
2549
|
-
checklist: value.checklist,
|
|
2550
|
-
status: value.status ?? "",
|
|
2551
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
2552
|
-
updatedAt: value.updatedAt ?? "",
|
|
2553
|
-
deletedAt: value.deletedAt ?? ""
|
|
2554
|
-
};
|
|
2555
|
-
}
|
|
2556
|
-
|
|
2557
|
-
// src/repositories/hygiene-schedule-task-area.repository.ts
|
|
2558
|
-
var import_mongodb10 = require("mongodb");
|
|
2559
|
-
var import_node_server_utils17 = require("@iservice365/node-server-utils");
|
|
2560
|
-
function useScheduleTaskAreaRepository() {
|
|
2561
|
-
const db = import_node_server_utils17.useAtlas.getDb();
|
|
2562
|
-
if (!db) {
|
|
2563
|
-
throw new import_node_server_utils17.InternalServerError("Unable to connect to server.");
|
|
2564
|
-
}
|
|
2565
|
-
const namespace_collection = "hygiene-schedule-task-areas";
|
|
2566
|
-
const collection = db.collection(namespace_collection);
|
|
2567
|
-
const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils17.useCache)(namespace_collection);
|
|
2568
|
-
async function createIndexes() {
|
|
2569
|
-
try {
|
|
2570
|
-
await collection.createIndexes([
|
|
2571
|
-
{ key: { site: 1 } },
|
|
2572
|
-
{ key: { name: "text" } }
|
|
2573
|
-
]);
|
|
2574
|
-
} catch (error) {
|
|
2575
|
-
throw new import_node_server_utils17.InternalServerError("Failed to create index on site.");
|
|
2576
|
-
}
|
|
2577
|
-
}
|
|
2578
|
-
async function createUniqueIndex() {
|
|
2579
|
-
try {
|
|
2580
|
-
await collection.createIndex(
|
|
2581
|
-
{ name: 1, site: 1, deletedAt: 1 },
|
|
2582
|
-
{ unique: true }
|
|
2583
|
-
);
|
|
2584
|
-
} catch (error) {
|
|
2585
|
-
throw new import_node_server_utils17.InternalServerError(
|
|
2586
|
-
"Failed to create unique index on hygiene area."
|
|
2587
|
-
);
|
|
2588
|
-
}
|
|
2589
|
-
}
|
|
2590
|
-
async function createScheduleTaskArea(value, session) {
|
|
2591
|
-
try {
|
|
2592
|
-
value = MScheduleTaskArea(value);
|
|
2593
|
-
const res = await collection.insertOne(value, { session });
|
|
2594
|
-
delNamespace().then(() => {
|
|
2595
|
-
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2596
|
-
}).catch((err) => {
|
|
2597
|
-
import_node_server_utils17.logger.error(
|
|
2598
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2599
|
-
err
|
|
2600
|
-
);
|
|
2601
|
-
});
|
|
2602
|
-
return res.insertedId;
|
|
2603
|
-
} catch (error) {
|
|
2604
|
-
const isDuplicated = error.message.includes("duplicate");
|
|
2605
|
-
if (isDuplicated) {
|
|
2606
|
-
throw new import_node_server_utils17.BadRequestError("Area already exists.");
|
|
2607
|
-
}
|
|
2608
|
-
throw error;
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
async function updateScheduleTaskArea(_id, params) {
|
|
2612
|
-
try {
|
|
2613
|
-
_id = new import_mongodb10.ObjectId(_id);
|
|
2614
|
-
} catch (error) {
|
|
2615
|
-
throw new import_node_server_utils17.BadRequestError("Invalid area ID format.");
|
|
2616
|
-
}
|
|
2617
|
-
try {
|
|
2618
|
-
const updateValue = { ...params, updatedAt: /* @__PURE__ */ new Date() };
|
|
2619
|
-
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
2620
|
-
if (res.modifiedCount === 0) {
|
|
2621
|
-
throw new import_node_server_utils17.InternalServerError("Unable to update cleaning area.");
|
|
2622
|
-
}
|
|
2623
|
-
delNamespace().then(() => {
|
|
2624
|
-
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2625
|
-
}).catch((err) => {
|
|
2626
|
-
import_node_server_utils17.logger.error(
|
|
2627
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2628
|
-
err
|
|
2629
|
-
);
|
|
2630
|
-
});
|
|
2631
|
-
return res.modifiedCount;
|
|
2632
|
-
} catch (error) {
|
|
2633
|
-
const isDuplicated = error.message.includes("duplicate");
|
|
2634
|
-
if (isDuplicated) {
|
|
2635
|
-
throw new import_node_server_utils17.BadRequestError("Area already exists.");
|
|
2636
|
-
}
|
|
2637
|
-
throw error;
|
|
2638
|
-
}
|
|
2639
|
-
}
|
|
2640
|
-
async function deleteScheduleTaskArea(_id, session) {
|
|
2641
|
-
try {
|
|
2642
|
-
_id = new import_mongodb10.ObjectId(_id);
|
|
2643
|
-
} catch (error) {
|
|
2644
|
-
throw new import_node_server_utils17.BadRequestError("Invalid area ID format.");
|
|
2645
|
-
}
|
|
2646
|
-
try {
|
|
2647
|
-
const updateValue = {
|
|
2648
|
-
status: "deleted",
|
|
2649
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
2650
|
-
deletedAt: /* @__PURE__ */ new Date()
|
|
2651
|
-
};
|
|
2652
|
-
const res = await collection.updateOne(
|
|
2653
|
-
{ _id },
|
|
2654
|
-
{ $set: updateValue },
|
|
2655
|
-
{ session }
|
|
2656
|
-
);
|
|
2657
|
-
if (res.modifiedCount === 0) {
|
|
2658
|
-
throw new import_node_server_utils17.InternalServerError("Unable to delete area.");
|
|
2659
|
-
}
|
|
2660
|
-
delNamespace().then(() => {
|
|
2661
|
-
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2662
|
-
}).catch((err) => {
|
|
2663
|
-
import_node_server_utils17.logger.error(
|
|
2664
|
-
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2665
|
-
err
|
|
2666
|
-
);
|
|
2667
|
-
});
|
|
2668
|
-
return res.modifiedCount;
|
|
2669
|
-
} catch (error) {
|
|
2670
|
-
throw error;
|
|
2671
|
-
}
|
|
2672
|
-
}
|
|
2673
|
-
async function getScheduleTaskAreas({
|
|
2674
|
-
page = 1,
|
|
2675
|
-
limit = 10,
|
|
2676
|
-
search = "",
|
|
2677
|
-
startDate = "",
|
|
2678
|
-
endDate = "",
|
|
2679
|
-
site = ""
|
|
2680
|
-
}) {
|
|
2681
|
-
page = page > 0 ? page - 1 : 0;
|
|
2682
|
-
const query = {
|
|
2683
|
-
status: { $ne: "deleted" }
|
|
2684
|
-
};
|
|
2685
|
-
const cacheOptions = {
|
|
2686
|
-
page,
|
|
2687
|
-
limit
|
|
2688
|
-
};
|
|
2689
|
-
if (site) {
|
|
2690
|
-
try {
|
|
2691
|
-
site = new import_mongodb10.ObjectId(site);
|
|
2692
|
-
cacheOptions.site = site.toString();
|
|
2693
|
-
} catch (error) {
|
|
2694
|
-
throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
if (search) {
|
|
2698
|
-
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
2699
|
-
cacheOptions.search = search;
|
|
2700
|
-
}
|
|
2701
|
-
if (startDate && endDate) {
|
|
2702
|
-
query.createdAt = {
|
|
2703
|
-
$gte: new Date(startDate),
|
|
2704
|
-
$lte: new Date(endDate)
|
|
2705
|
-
};
|
|
2706
|
-
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
2707
|
-
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
2708
|
-
} else if (startDate) {
|
|
2709
|
-
query.createdAt = { $gte: new Date(startDate) };
|
|
2710
|
-
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
2711
|
-
} else if (endDate) {
|
|
2712
|
-
query.createdAt = { $lte: new Date(endDate) };
|
|
2713
|
-
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
2714
|
-
}
|
|
2715
|
-
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2716
|
-
const cachedData = await getCache(cacheKey);
|
|
2717
|
-
if (cachedData) {
|
|
2718
|
-
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2719
|
-
return cachedData;
|
|
2720
|
-
}
|
|
2721
|
-
try {
|
|
2722
|
-
const items = await collection.aggregate([
|
|
2723
|
-
{
|
|
2724
|
-
$match: query
|
|
2725
|
-
},
|
|
2726
|
-
{
|
|
2727
|
-
$lookup: {
|
|
2728
|
-
from: "sites",
|
|
2729
|
-
localField: "site",
|
|
2730
|
-
foreignField: "_id",
|
|
2731
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
2732
|
-
as: "site"
|
|
2733
|
-
}
|
|
2734
|
-
},
|
|
2735
|
-
{
|
|
2736
|
-
$unwind: {
|
|
2737
|
-
path: "$site",
|
|
2738
|
-
preserveNullAndEmptyArrays: true
|
|
2739
|
-
}
|
|
2740
|
-
},
|
|
2741
|
-
{
|
|
2742
|
-
$lookup: {
|
|
2743
|
-
from: "users",
|
|
2744
|
-
localField: "createdBy",
|
|
2745
|
-
foreignField: "_id",
|
|
2746
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
2747
|
-
as: "createdBy"
|
|
2748
|
-
}
|
|
2749
|
-
},
|
|
2750
|
-
{
|
|
2751
|
-
$unwind: {
|
|
2752
|
-
path: "$createdBy",
|
|
2753
|
-
preserveNullAndEmptyArrays: true
|
|
2754
|
-
}
|
|
2755
|
-
},
|
|
2756
|
-
{
|
|
2757
|
-
$project: {
|
|
2758
|
-
name: 1,
|
|
2759
|
-
site: "$site._id",
|
|
2760
|
-
siteName: "$site.name",
|
|
2761
|
-
createdByName: "$createdBy.name",
|
|
2762
|
-
checklist: 1,
|
|
2763
|
-
status: 1,
|
|
2764
|
-
createdAt: 1
|
|
2765
|
-
}
|
|
2766
|
-
},
|
|
2767
|
-
{ $sort: { _id: -1 } },
|
|
2768
|
-
{ $skip: page * limit },
|
|
2769
|
-
{ $limit: limit }
|
|
2770
|
-
]).toArray();
|
|
2771
|
-
const length = await collection.countDocuments(query);
|
|
2772
|
-
const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
2773
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2774
|
-
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2775
|
-
}).catch((err) => {
|
|
2776
|
-
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2777
|
-
});
|
|
2778
|
-
return data;
|
|
2779
|
-
} catch (error) {
|
|
2780
|
-
throw error;
|
|
2781
|
-
}
|
|
2782
|
-
}
|
|
2783
|
-
async function getScheduleTaskAreaByName(name, site) {
|
|
2784
|
-
try {
|
|
2785
|
-
if (site)
|
|
2786
|
-
site = new import_mongodb10.ObjectId(site);
|
|
2787
|
-
} catch (error) {
|
|
2788
|
-
throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
|
|
2789
|
-
}
|
|
2790
|
-
try {
|
|
2791
|
-
return await collection.findOne({
|
|
2792
|
-
name: { $regex: new RegExp(`^${name}$`, "i") },
|
|
2793
|
-
...site && { site }
|
|
2794
|
-
});
|
|
2795
|
-
} catch (error) {
|
|
2796
|
-
throw new import_node_server_utils17.BadRequestError("Unable to fetch schedule task area by name.");
|
|
2797
|
-
}
|
|
2798
|
-
}
|
|
2799
|
-
async function getScheduleTaskAreaById(id, site) {
|
|
2800
|
-
try {
|
|
2801
|
-
id = typeof id === "string" ? new import_mongodb10.ObjectId(id) : id;
|
|
2802
|
-
} catch (error) {
|
|
2803
|
-
throw new import_node_server_utils17.BadRequestError("Invalid unit ID format.");
|
|
2804
|
-
}
|
|
2805
|
-
try {
|
|
2806
|
-
if (site)
|
|
2807
|
-
site = new import_mongodb10.ObjectId(site);
|
|
2808
|
-
} catch (error) {
|
|
2809
|
-
throw new import_node_server_utils17.BadRequestError(
|
|
2810
|
-
"Unable to fetch schedule task area by ID, Invalid site ID format."
|
|
2811
|
-
);
|
|
2812
|
-
}
|
|
2813
|
-
try {
|
|
2814
|
-
return await collection.findOne({ _id: id, ...site && { site } });
|
|
2815
|
-
} catch (error) {
|
|
2816
|
-
throw new import_node_server_utils17.BadRequestError("Unable to fetch schedule task area by id.");
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2819
|
-
async function getAreaById(_id) {
|
|
2820
|
-
try {
|
|
2821
|
-
_id = new import_mongodb10.ObjectId(_id);
|
|
2822
|
-
} catch (error) {
|
|
2823
|
-
throw new import_node_server_utils17.BadRequestError("Invalid area ID format.");
|
|
2824
|
-
}
|
|
2825
|
-
const query = {
|
|
2826
|
-
_id,
|
|
2827
|
-
status: { $ne: "deleted" }
|
|
2828
|
-
};
|
|
2829
|
-
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, {
|
|
2830
|
-
_id: _id.toString()
|
|
2831
|
-
});
|
|
2832
|
-
const cachedData = await getCache(cacheKey);
|
|
2833
|
-
if (cachedData) {
|
|
2834
|
-
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2835
|
-
return cachedData;
|
|
2836
|
-
}
|
|
2837
|
-
try {
|
|
2838
|
-
const data = await collection.aggregate([
|
|
2839
|
-
{ $match: query },
|
|
2840
|
-
{
|
|
2841
|
-
$project: {
|
|
2842
|
-
name: 1,
|
|
2843
|
-
checklist: 1
|
|
2844
|
-
}
|
|
2845
|
-
}
|
|
2846
|
-
]).toArray();
|
|
2847
|
-
if (!data || !data.length) {
|
|
2848
|
-
throw new import_node_server_utils17.NotFoundError("Area not found.");
|
|
2849
|
-
}
|
|
2850
|
-
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
2851
|
-
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2852
|
-
}).catch((err) => {
|
|
2853
|
-
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2854
|
-
});
|
|
2855
|
-
return data[0];
|
|
2856
|
-
} catch (error) {
|
|
2857
|
-
throw error;
|
|
2858
|
-
}
|
|
2859
|
-
}
|
|
2860
|
-
return {
|
|
2861
|
-
createUniqueIndex,
|
|
2862
|
-
createScheduleTaskArea,
|
|
2863
|
-
updateScheduleTaskArea,
|
|
2864
|
-
deleteScheduleTaskArea,
|
|
2865
|
-
getScheduleTaskAreas,
|
|
2866
|
-
createIndexes,
|
|
2867
|
-
getScheduleTaskAreaByName,
|
|
2868
|
-
getScheduleTaskAreaById,
|
|
2869
|
-
getAreaById
|
|
2870
|
-
};
|
|
2871
|
-
}
|
|
2872
|
-
|
|
2873
|
-
// src/services/hygiene-schedule-task-area.service.ts
|
|
2874
|
-
var import_node_server_utils18 = require("@iservice365/node-server-utils");
|
|
2875
|
-
function useScheduleTaskAreaService() {
|
|
2876
|
-
const { createScheduleTaskArea: _create } = useScheduleTaskAreaRepository();
|
|
2877
|
-
async function uploadByFile({
|
|
2878
|
-
dataJson,
|
|
2879
|
-
createdBy,
|
|
2880
|
-
site
|
|
2881
|
-
}) {
|
|
2882
|
-
let dataArray;
|
|
2883
|
-
try {
|
|
2884
|
-
dataArray = JSON.parse(dataJson);
|
|
2885
|
-
} catch (error) {
|
|
2886
|
-
throw new import_node_server_utils18.BadRequestError("Invalid JSON format for data in excel");
|
|
2887
|
-
}
|
|
2888
|
-
if (!dataArray || dataArray.length === 0) {
|
|
2889
|
-
throw new import_node_server_utils18.NotFoundError("No data found in the uploaded file");
|
|
2890
|
-
}
|
|
2891
|
-
const session = import_node_server_utils18.useAtlas.getClient()?.startSession();
|
|
2892
|
-
const insertedAreaIds = [];
|
|
2893
|
-
try {
|
|
2894
|
-
session?.startTransaction();
|
|
2895
|
-
for (const row of dataArray) {
|
|
2896
|
-
if (!row?.AREA_NAME) {
|
|
2897
|
-
import_node_server_utils18.logger.warn("Skipping row with missing AREA_NAME:", row);
|
|
2898
|
-
continue;
|
|
2899
|
-
}
|
|
2900
|
-
try {
|
|
2901
|
-
const insertedId = await _create(
|
|
2902
|
-
{
|
|
2903
|
-
name: String(row.AREA_NAME).trim(),
|
|
2904
|
-
site,
|
|
2905
|
-
createdBy
|
|
2906
|
-
},
|
|
2907
|
-
session
|
|
2908
|
-
);
|
|
2909
|
-
insertedAreaIds.push(insertedId);
|
|
2910
|
-
} catch (error) {
|
|
2911
|
-
import_node_server_utils18.logger.error(
|
|
2912
|
-
`Error creating area "${row.AREA_NAME}":`,
|
|
2913
|
-
error.message
|
|
2914
|
-
);
|
|
2915
|
-
continue;
|
|
2916
|
-
}
|
|
2917
|
-
}
|
|
2918
|
-
await session?.commitTransaction();
|
|
2919
|
-
import_node_server_utils18.logger.info(`Successfully uploaded ${insertedAreaIds.length} areas`);
|
|
2920
|
-
return {
|
|
2921
|
-
message: `Successfully uploaded ${insertedAreaIds.length} areas`
|
|
2922
|
-
};
|
|
2923
|
-
} catch (error) {
|
|
2924
|
-
await session?.abortTransaction();
|
|
2925
|
-
import_node_server_utils18.logger.error("Error while uploading area information", error);
|
|
2926
|
-
throw error;
|
|
2927
|
-
} finally {
|
|
2928
|
-
session?.endSession();
|
|
2929
|
-
}
|
|
2930
|
-
}
|
|
2931
|
-
return {
|
|
2932
|
-
uploadByFile
|
|
2933
|
-
};
|
|
2934
|
-
}
|
|
2935
|
-
|
|
2936
|
-
// src/controllers/hygiene-schedule-task-area.controller.ts
|
|
2937
|
-
var import_node_server_utils19 = require("@iservice365/node-server-utils");
|
|
2938
|
-
var import_joi10 = __toESM(require("joi"));
|
|
2939
|
-
function useScheduleTaskAreaController() {
|
|
2940
|
-
const { uploadByFile: _uploadByFile } = useScheduleTaskAreaService();
|
|
2941
|
-
const {
|
|
2942
|
-
getScheduleTaskAreas: _getAll,
|
|
2943
|
-
createScheduleTaskArea: _createScheduleTaskArea,
|
|
2944
|
-
updateScheduleTaskArea: _updateScheduleTaskArea,
|
|
2945
|
-
deleteScheduleTaskArea: _deleteById,
|
|
2946
|
-
getAreaById: _getAreaById
|
|
2947
|
-
} = useScheduleTaskAreaRepository();
|
|
2948
|
-
async function getAll(req, res, next) {
|
|
2949
|
-
const query = req.query;
|
|
2950
|
-
const validation = import_joi10.default.object({
|
|
2951
|
-
page: import_joi10.default.number().min(1).optional().allow("", null),
|
|
2952
|
-
limit: import_joi10.default.number().min(1).optional().allow("", null),
|
|
2953
|
-
search: import_joi10.default.string().optional().allow("", null),
|
|
2954
|
-
startDate: import_joi10.default.alternatives().try(import_joi10.default.date(), import_joi10.default.string()).optional().allow("", null),
|
|
2955
|
-
endDate: import_joi10.default.alternatives().try(import_joi10.default.date(), import_joi10.default.string()).optional().allow("", null),
|
|
2956
|
-
site: import_joi10.default.string().hex().optional().allow("", null)
|
|
2957
|
-
});
|
|
2958
|
-
const { error } = validation.validate(query);
|
|
2959
|
-
if (error) {
|
|
2960
|
-
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
2961
|
-
return;
|
|
2962
|
-
}
|
|
2963
|
-
const page = parseInt(req.query.page) ?? 1;
|
|
2964
|
-
const limit = parseInt(req.query.limit) ?? 20;
|
|
2965
|
-
const search = req.query.search ?? "";
|
|
2966
|
-
const site = req.query.site ?? "";
|
|
2967
|
-
const startDate = req.query.startDate ?? "";
|
|
2968
|
-
const endDate = req.query.endDate ?? "";
|
|
2969
|
-
try {
|
|
2970
|
-
const data = await _getAll({
|
|
2971
|
-
page,
|
|
2972
|
-
limit,
|
|
2973
|
-
search,
|
|
2974
|
-
site,
|
|
2975
|
-
startDate,
|
|
2976
|
-
endDate
|
|
2977
|
-
});
|
|
2978
|
-
res.json(data);
|
|
2979
|
-
return;
|
|
2980
|
-
} catch (error2) {
|
|
2981
|
-
next(error2);
|
|
2982
|
-
return;
|
|
2983
|
-
}
|
|
2984
|
-
}
|
|
2985
|
-
async function createScheduleTaskArea(req, res, next) {
|
|
2986
|
-
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
2987
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
2988
|
-
{}
|
|
2989
|
-
) : {};
|
|
2990
|
-
const createdBy = cookies["user"] || "";
|
|
2991
|
-
const payload = { ...req.body, createdBy };
|
|
2992
|
-
const { error } = scheduleTaskAreaSchema.validate(payload);
|
|
2993
|
-
if (error) {
|
|
2994
|
-
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
2995
|
-
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
2996
|
-
return;
|
|
2997
|
-
}
|
|
2998
|
-
try {
|
|
2999
|
-
const id = await _createScheduleTaskArea(payload);
|
|
3000
|
-
res.status(201).json({ message: "Area created successfully.", id });
|
|
3001
|
-
return;
|
|
3002
|
-
} catch (error2) {
|
|
3003
|
-
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3004
|
-
next(error2);
|
|
3005
|
-
return;
|
|
3006
|
-
}
|
|
3007
|
-
}
|
|
3008
|
-
async function updateScheduleTaskArea(req, res, next) {
|
|
3009
|
-
const payload = { id: req.params.id, ...req.body };
|
|
3010
|
-
const schema = import_joi10.default.object({
|
|
3011
|
-
id: import_joi10.default.string().hex().required(),
|
|
3012
|
-
name: import_joi10.default.string().required()
|
|
3013
|
-
});
|
|
3014
|
-
const { error } = schema.validate(payload);
|
|
3015
|
-
if (error) {
|
|
3016
|
-
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3017
|
-
import_node_server_utils19.logger.info(`Controller: ${error.message}`);
|
|
3018
|
-
return;
|
|
3019
|
-
}
|
|
3020
|
-
try {
|
|
3021
|
-
const { id, ...value } = payload;
|
|
3022
|
-
await _updateScheduleTaskArea(id, value);
|
|
3023
|
-
res.json({ message: "Area updated successfully." });
|
|
3024
|
-
return;
|
|
3025
|
-
} catch (error2) {
|
|
3026
|
-
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3027
|
-
next(error2);
|
|
3028
|
-
return;
|
|
3029
|
-
}
|
|
3030
|
-
}
|
|
3031
|
-
async function deleteScheduleTaskArea(req, res, next) {
|
|
3032
|
-
const id = req.params.id;
|
|
3033
|
-
const validation = import_joi10.default.object({
|
|
3034
|
-
id: import_joi10.default.string().hex().required()
|
|
3035
|
-
});
|
|
3036
|
-
const { error } = validation.validate({ id });
|
|
3037
|
-
if (error) {
|
|
3038
|
-
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3039
|
-
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3040
|
-
return;
|
|
3041
|
-
}
|
|
3042
|
-
try {
|
|
3043
|
-
await _deleteById(id);
|
|
3044
|
-
res.json({ message: "Area deleted successfully." });
|
|
3045
|
-
return;
|
|
3046
|
-
} catch (error2) {
|
|
3047
|
-
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3048
|
-
next(error2);
|
|
3049
|
-
return;
|
|
3050
|
-
}
|
|
3051
|
-
}
|
|
3052
|
-
async function uploadByFile(req, res, next) {
|
|
3053
|
-
if (!req.file) {
|
|
3054
|
-
next(new import_node_server_utils19.BadRequestError("File is required!"));
|
|
3055
|
-
return;
|
|
3056
|
-
}
|
|
3057
|
-
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
3058
|
-
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
3059
|
-
{}
|
|
3060
|
-
) : {};
|
|
3061
|
-
const createdBy = cookies["user"] || "";
|
|
3062
|
-
const { site } = req.body;
|
|
3063
|
-
const schema = import_joi10.default.object({
|
|
3064
|
-
site: import_joi10.default.string().hex().optional().allow("", null),
|
|
3065
|
-
createdBy: import_joi10.default.string().hex().required()
|
|
3066
|
-
});
|
|
3067
|
-
const { error } = schema.validate({ site, createdBy });
|
|
3068
|
-
if (error) {
|
|
3069
|
-
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3070
|
-
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3071
|
-
return;
|
|
3072
|
-
}
|
|
3073
|
-
try {
|
|
3074
|
-
const xlsData = await convertBufferFile(req.file.buffer);
|
|
3075
|
-
const dataJson = JSON.stringify(xlsData);
|
|
3076
|
-
const result = await _uploadByFile({ dataJson, createdBy, site });
|
|
3077
|
-
return res.status(201).json(result);
|
|
3078
|
-
} catch (error2) {
|
|
3079
|
-
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
3080
|
-
next(error2);
|
|
3081
|
-
return;
|
|
3082
|
-
}
|
|
3083
|
-
}
|
|
3084
|
-
async function getAreaById(req, res, next) {
|
|
3085
|
-
const validation = import_joi10.default.string().hex().required();
|
|
3086
|
-
const _id = req.params.id;
|
|
3087
|
-
const { error } = validation.validate(_id);
|
|
3088
|
-
if (error) {
|
|
3089
|
-
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3090
|
-
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
3091
|
-
return;
|
|
3092
|
-
}
|
|
1711
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
1712
|
+
const limit = parseInt(req.query.limit) ?? 20;
|
|
1713
|
+
const search = req.query.search ?? "";
|
|
1714
|
+
const site = req.params.site ?? "";
|
|
1715
|
+
const startDate = req.query.startDate ?? "";
|
|
1716
|
+
const endDate = req.query.endDate ?? "";
|
|
3093
1717
|
try {
|
|
3094
|
-
const data = await
|
|
1718
|
+
const data = await _getAllParentChecklist({
|
|
1719
|
+
page,
|
|
1720
|
+
limit,
|
|
1721
|
+
search,
|
|
1722
|
+
site,
|
|
1723
|
+
startDate,
|
|
1724
|
+
endDate
|
|
1725
|
+
});
|
|
3095
1726
|
res.json(data);
|
|
3096
1727
|
return;
|
|
3097
1728
|
} catch (error2) {
|
|
3098
|
-
|
|
1729
|
+
import_node_server_utils11.logger.log({ level: "error", message: error2.message });
|
|
3099
1730
|
next(error2);
|
|
3100
1731
|
return;
|
|
3101
1732
|
}
|
|
3102
1733
|
}
|
|
3103
1734
|
return {
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
createScheduleTaskArea,
|
|
3107
|
-
updateScheduleTaskArea,
|
|
3108
|
-
deleteScheduleTaskArea,
|
|
3109
|
-
uploadByFile
|
|
1735
|
+
createParentChecklist,
|
|
1736
|
+
getAllParentChecklist
|
|
3110
1737
|
};
|
|
3111
1738
|
}
|
|
3112
1739
|
|
|
3113
1740
|
// src/models/hygiene-area-checklist.model.ts
|
|
3114
|
-
var
|
|
3115
|
-
var
|
|
3116
|
-
var
|
|
3117
|
-
var
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
1741
|
+
var import_node_server_utils12 = require("@iservice365/node-server-utils");
|
|
1742
|
+
var import_joi7 = __toESM(require("joi"));
|
|
1743
|
+
var import_mongodb7 = require("mongodb");
|
|
1744
|
+
var allowedChecklistStatus = ["ready", "completed"];
|
|
1745
|
+
var areaChecklistSchema = import_joi7.default.object({
|
|
1746
|
+
schedule: import_joi7.default.string().hex().required(),
|
|
1747
|
+
name: import_joi7.default.string().required(),
|
|
1748
|
+
type: import_joi7.default.string().valid(...allowedTypes).required(),
|
|
1749
|
+
checklist: import_joi7.default.array().items(
|
|
1750
|
+
import_joi7.default.object({
|
|
1751
|
+
set: import_joi7.default.number().min(0).required(),
|
|
1752
|
+
units: import_joi7.default.array().items(
|
|
1753
|
+
import_joi7.default.object({
|
|
1754
|
+
name: import_joi7.default.string().required()
|
|
1755
|
+
}).required()
|
|
1756
|
+
).min(1).required()
|
|
1757
|
+
}).required()
|
|
1758
|
+
).optional().default([])
|
|
3124
1759
|
});
|
|
3125
1760
|
function MAreaChecklist(value) {
|
|
3126
1761
|
const { error } = areaChecklistSchema.validate(value);
|
|
3127
1762
|
if (error) {
|
|
3128
|
-
|
|
3129
|
-
throw new
|
|
3130
|
-
}
|
|
3131
|
-
if (value.site) {
|
|
3132
|
-
try {
|
|
3133
|
-
value.site = new import_mongodb11.ObjectId(value.site);
|
|
3134
|
-
} catch (error2) {
|
|
3135
|
-
throw new import_node_server_utils20.BadRequestError("Invalid site ID format.");
|
|
3136
|
-
}
|
|
3137
|
-
}
|
|
3138
|
-
if (value.parentChecklist) {
|
|
3139
|
-
try {
|
|
3140
|
-
value.parentChecklist = new import_mongodb11.ObjectId(value.parentChecklist);
|
|
3141
|
-
} catch (error2) {
|
|
3142
|
-
throw new import_node_server_utils20.BadRequestError("Invalid checklist ID format.");
|
|
3143
|
-
}
|
|
3144
|
-
}
|
|
3145
|
-
if (value.area) {
|
|
3146
|
-
try {
|
|
3147
|
-
value.area = new import_mongodb11.ObjectId(value.area);
|
|
3148
|
-
} catch (error2) {
|
|
3149
|
-
throw new import_node_server_utils20.BadRequestError("Invalid area ID format.");
|
|
3150
|
-
}
|
|
1763
|
+
import_node_server_utils12.logger.info(`Hygiene Checklist Area Model: ${error.message}`);
|
|
1764
|
+
throw new import_node_server_utils12.BadRequestError(error.message);
|
|
3151
1765
|
}
|
|
3152
|
-
if (value.
|
|
1766
|
+
if (value.schedule) {
|
|
3153
1767
|
try {
|
|
3154
|
-
value.
|
|
1768
|
+
value.schedule = new import_mongodb7.ObjectId(value.schedule);
|
|
3155
1769
|
} catch (error2) {
|
|
3156
|
-
throw new
|
|
1770
|
+
throw new import_node_server_utils12.BadRequestError("Invalid schedule ID format.");
|
|
3157
1771
|
}
|
|
3158
1772
|
}
|
|
3159
|
-
if (value.
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
1773
|
+
if (value.checklist && Array.isArray(value.checklist)) {
|
|
1774
|
+
value.checklist = value.checklist.map((checklistItem) => {
|
|
1775
|
+
return {
|
|
1776
|
+
set: checklistItem.set,
|
|
1777
|
+
units: checklistItem.units.map((unit) => ({
|
|
1778
|
+
name: unit.name,
|
|
1779
|
+
status: "ready",
|
|
1780
|
+
remarks: "",
|
|
1781
|
+
timestamp: ""
|
|
1782
|
+
}))
|
|
1783
|
+
};
|
|
1784
|
+
});
|
|
3165
1785
|
}
|
|
3166
1786
|
return {
|
|
1787
|
+
schedule: value.schedule,
|
|
1788
|
+
name: value.name,
|
|
3167
1789
|
type: value.type,
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
area: value.area,
|
|
3171
|
-
name: value.name ?? "",
|
|
3172
|
-
status: value.status ?? "To Do",
|
|
3173
|
-
createdBy: value.createdBy ?? "",
|
|
1790
|
+
checklist: value.checklist || [],
|
|
1791
|
+
status: "ready",
|
|
3174
1792
|
createdAt: /* @__PURE__ */ new Date(),
|
|
3175
|
-
|
|
3176
|
-
acceptedAt: value.acceptedAt ?? "",
|
|
3177
|
-
startedAt: value.startedAt ?? "",
|
|
3178
|
-
endedAt: value.endedAt ?? "",
|
|
3179
|
-
signature: value.signature ?? "",
|
|
3180
|
-
updatedAt: value.updatedAt ?? ""
|
|
1793
|
+
updatedAt: ""
|
|
3181
1794
|
};
|
|
3182
1795
|
}
|
|
3183
1796
|
|
|
3184
1797
|
// src/repositories/hygiene-area-checklist.repository.ts
|
|
3185
|
-
var
|
|
3186
|
-
var
|
|
1798
|
+
var import_node_server_utils13 = require("@iservice365/node-server-utils");
|
|
1799
|
+
var import_mongodb8 = require("mongodb");
|
|
3187
1800
|
function useAreaChecklistRepo() {
|
|
3188
|
-
const db =
|
|
1801
|
+
const db = import_node_server_utils13.useAtlas.getDb();
|
|
3189
1802
|
if (!db) {
|
|
3190
|
-
throw new
|
|
1803
|
+
throw new import_node_server_utils13.InternalServerError("Unable to connect to server.");
|
|
3191
1804
|
}
|
|
3192
|
-
const namespace_collection = "
|
|
3193
|
-
const unit_checklist_collection = "
|
|
1805
|
+
const namespace_collection = "site.cleaning.schedule.areas";
|
|
1806
|
+
const unit_checklist_collection = "site.cleaning.schedule.units";
|
|
3194
1807
|
const collection = db.collection(namespace_collection);
|
|
3195
1808
|
const unitChecklistCollection = db.collection(unit_checklist_collection);
|
|
3196
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
3197
|
-
const { delNamespace: delUnitNamespace } = (0,
|
|
1809
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils13.useCache)(namespace_collection);
|
|
1810
|
+
const { delNamespace: delUnitNamespace } = (0, import_node_server_utils13.useCache)(
|
|
3198
1811
|
unit_checklist_collection
|
|
3199
1812
|
);
|
|
3200
1813
|
async function createIndex() {
|
|
3201
1814
|
try {
|
|
3202
1815
|
await collection.createIndexes([
|
|
1816
|
+
{ key: { schedule: 1 } },
|
|
3203
1817
|
{ key: { type: 1 } },
|
|
3204
|
-
{ key: {
|
|
3205
|
-
{ key: { parentChecklist: 1 } },
|
|
3206
|
-
{ key: { area: 1 } },
|
|
1818
|
+
{ key: { status: 1 } },
|
|
3207
1819
|
{ key: { createdAt: 1 } },
|
|
3208
1820
|
{ key: { acceptedBy: 1 } }
|
|
3209
1821
|
]);
|
|
3210
1822
|
} catch (error) {
|
|
3211
|
-
throw new
|
|
1823
|
+
throw new import_node_server_utils13.InternalServerError(
|
|
3212
1824
|
"Failed to create index on hygiene checklist area."
|
|
3213
1825
|
);
|
|
3214
1826
|
}
|
|
@@ -3217,16 +1829,14 @@ function useAreaChecklistRepo() {
|
|
|
3217
1829
|
try {
|
|
3218
1830
|
await collection.createIndex({ name: "text" });
|
|
3219
1831
|
} catch (error) {
|
|
3220
|
-
throw new
|
|
1832
|
+
throw new import_node_server_utils13.InternalServerError(
|
|
3221
1833
|
"Failed to create text index on hygiene checklist area."
|
|
3222
1834
|
);
|
|
3223
1835
|
}
|
|
3224
1836
|
}
|
|
3225
1837
|
async function createAreaChecklist(value, session) {
|
|
3226
1838
|
try {
|
|
3227
|
-
const
|
|
3228
|
-
const parentChecklistId = new import_mongodb12.ObjectId(value.parentChecklist);
|
|
3229
|
-
const areaId = new import_mongodb12.ObjectId(value.area);
|
|
1839
|
+
const parentChecklistId = new import_mongodb8.ObjectId(value.schedule);
|
|
3230
1840
|
const currentDate = /* @__PURE__ */ new Date();
|
|
3231
1841
|
const startOfDay = new Date(currentDate);
|
|
3232
1842
|
startOfDay.setUTCHours(0, 0, 0, 0);
|
|
@@ -3234,26 +1844,25 @@ function useAreaChecklistRepo() {
|
|
|
3234
1844
|
endOfDay.setUTCHours(23, 59, 59, 999);
|
|
3235
1845
|
const existingChecklist = await collection.findOne({
|
|
3236
1846
|
type: value.type,
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
area: areaId,
|
|
1847
|
+
schedule: parentChecklistId,
|
|
1848
|
+
name: value.name,
|
|
3240
1849
|
createdAt: {
|
|
3241
1850
|
$gte: startOfDay,
|
|
3242
1851
|
$lte: endOfDay
|
|
3243
1852
|
}
|
|
3244
1853
|
});
|
|
3245
1854
|
if (existingChecklist) {
|
|
3246
|
-
|
|
3247
|
-
`Area checklist already exists for area ${
|
|
1855
|
+
import_node_server_utils13.logger.info(
|
|
1856
|
+
`Area checklist already exists for area ${value.name} on ${currentDate.toISOString().split("T")[0]}`
|
|
3248
1857
|
);
|
|
3249
1858
|
return existingChecklist._id;
|
|
3250
1859
|
}
|
|
3251
1860
|
const processedValue = MAreaChecklist(value);
|
|
3252
1861
|
const result = await collection.insertOne(processedValue, { session });
|
|
3253
1862
|
delNamespace().then(() => {
|
|
3254
|
-
|
|
1863
|
+
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3255
1864
|
}).catch((err) => {
|
|
3256
|
-
|
|
1865
|
+
import_node_server_utils13.logger.error(
|
|
3257
1866
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3258
1867
|
err
|
|
3259
1868
|
);
|
|
@@ -3267,62 +1876,62 @@ function useAreaChecklistRepo() {
|
|
|
3267
1876
|
page = 1,
|
|
3268
1877
|
limit = 10,
|
|
3269
1878
|
search = "",
|
|
3270
|
-
site,
|
|
3271
1879
|
type,
|
|
3272
|
-
|
|
1880
|
+
schedule
|
|
3273
1881
|
}) {
|
|
3274
1882
|
page = page > 0 ? page - 1 : 0;
|
|
3275
|
-
const query = {
|
|
1883
|
+
const query = {};
|
|
3276
1884
|
const cacheOptions = {
|
|
3277
1885
|
page,
|
|
3278
1886
|
limit
|
|
3279
1887
|
};
|
|
3280
1888
|
try {
|
|
3281
|
-
query.
|
|
3282
|
-
cacheOptions.
|
|
1889
|
+
query.schedule = new import_mongodb8.ObjectId(schedule);
|
|
1890
|
+
cacheOptions.schedule = schedule.toString();
|
|
3283
1891
|
} catch (error) {
|
|
3284
|
-
throw new
|
|
1892
|
+
throw new import_node_server_utils13.BadRequestError("Invalid parent checklist ID format.");
|
|
3285
1893
|
}
|
|
3286
|
-
|
|
3287
|
-
query.
|
|
3288
|
-
cacheOptions.
|
|
3289
|
-
} catch (error) {
|
|
3290
|
-
throw new import_node_server_utils21.BadRequestError("Invalid parent checklist ID format.");
|
|
1894
|
+
if (type) {
|
|
1895
|
+
query.type = type;
|
|
1896
|
+
cacheOptions.type = type;
|
|
3291
1897
|
}
|
|
3292
1898
|
if (search) {
|
|
3293
1899
|
query.$text = { $search: search };
|
|
3294
1900
|
cacheOptions.search = search;
|
|
3295
1901
|
}
|
|
3296
|
-
const cacheKey = (0,
|
|
1902
|
+
const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, cacheOptions);
|
|
3297
1903
|
const cachedData = await getCache(cacheKey);
|
|
3298
1904
|
if (cachedData) {
|
|
3299
|
-
|
|
1905
|
+
import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3300
1906
|
return cachedData;
|
|
3301
1907
|
}
|
|
3302
1908
|
try {
|
|
3303
1909
|
const pipeline = [
|
|
3304
1910
|
{ $match: query },
|
|
3305
|
-
{
|
|
3306
|
-
$lookup: {
|
|
3307
|
-
from: "users",
|
|
3308
|
-
localField: "acceptedBy",
|
|
3309
|
-
foreignField: "_id",
|
|
3310
|
-
pipeline: [{ $project: { name: 1 } }],
|
|
3311
|
-
as: "acceptedBy"
|
|
3312
|
-
}
|
|
3313
|
-
},
|
|
3314
|
-
{
|
|
3315
|
-
$unwind: {
|
|
3316
|
-
path: "$acceptedBy",
|
|
3317
|
-
preserveNullAndEmptyArrays: true
|
|
3318
|
-
}
|
|
3319
|
-
},
|
|
3320
1911
|
{
|
|
3321
1912
|
$project: {
|
|
3322
1913
|
name: 1,
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
1914
|
+
status: {
|
|
1915
|
+
$switch: {
|
|
1916
|
+
branches: [
|
|
1917
|
+
{ case: { $eq: ["$status", "ready"] }, then: "Ready" },
|
|
1918
|
+
{ case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
|
|
1919
|
+
{
|
|
1920
|
+
case: { $eq: ["$status", "completed"] },
|
|
1921
|
+
then: "Completed"
|
|
1922
|
+
}
|
|
1923
|
+
],
|
|
1924
|
+
default: "$status"
|
|
1925
|
+
}
|
|
1926
|
+
},
|
|
1927
|
+
type: 1,
|
|
1928
|
+
set: {
|
|
1929
|
+
$cond: {
|
|
1930
|
+
if: { $gt: [{ $size: { $ifNull: ["$checklist", []] } }, 0] },
|
|
1931
|
+
then: { $max: "$checklist.set" },
|
|
1932
|
+
else: 0
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
3326
1935
|
}
|
|
3327
1936
|
},
|
|
3328
1937
|
{ $sort: { _id: -1 } },
|
|
@@ -3331,11 +1940,11 @@ function useAreaChecklistRepo() {
|
|
|
3331
1940
|
];
|
|
3332
1941
|
const items = await collection.aggregate(pipeline).toArray();
|
|
3333
1942
|
const length = await collection.countDocuments(query);
|
|
3334
|
-
const data = (0,
|
|
1943
|
+
const data = (0, import_node_server_utils13.paginate)(items, page, limit, length);
|
|
3335
1944
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3336
|
-
|
|
1945
|
+
import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3337
1946
|
}).catch((err) => {
|
|
3338
|
-
|
|
1947
|
+
import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3339
1948
|
});
|
|
3340
1949
|
return data;
|
|
3341
1950
|
} catch (error) {
|
|
@@ -3348,7 +1957,7 @@ function useAreaChecklistRepo() {
|
|
|
3348
1957
|
search = "",
|
|
3349
1958
|
site,
|
|
3350
1959
|
type,
|
|
3351
|
-
|
|
1960
|
+
schedule,
|
|
3352
1961
|
status,
|
|
3353
1962
|
createdAt,
|
|
3354
1963
|
user
|
|
@@ -3360,16 +1969,16 @@ function useAreaChecklistRepo() {
|
|
|
3360
1969
|
limit
|
|
3361
1970
|
};
|
|
3362
1971
|
try {
|
|
3363
|
-
query.site = new
|
|
1972
|
+
query.site = new import_mongodb8.ObjectId(site);
|
|
3364
1973
|
cacheOptions.site = site.toString();
|
|
3365
1974
|
} catch (error) {
|
|
3366
|
-
throw new
|
|
1975
|
+
throw new import_node_server_utils13.BadRequestError("Invalid site ID format.");
|
|
3367
1976
|
}
|
|
3368
1977
|
try {
|
|
3369
|
-
query.
|
|
3370
|
-
cacheOptions.
|
|
1978
|
+
query.schedule = new import_mongodb8.ObjectId(schedule);
|
|
1979
|
+
cacheOptions.schedule = schedule.toString();
|
|
3371
1980
|
} catch (error) {
|
|
3372
|
-
throw new
|
|
1981
|
+
throw new import_node_server_utils13.BadRequestError("Invalid parent checklist ID format.");
|
|
3373
1982
|
}
|
|
3374
1983
|
if (search) {
|
|
3375
1984
|
query.$text = { $search: search };
|
|
@@ -3386,20 +1995,20 @@ function useAreaChecklistRepo() {
|
|
|
3386
1995
|
query.status = status;
|
|
3387
1996
|
cacheOptions.status = status;
|
|
3388
1997
|
} else {
|
|
3389
|
-
query.status = { $in: ["
|
|
1998
|
+
query.status = { $in: ["ongoing", "completed"] };
|
|
3390
1999
|
}
|
|
3391
2000
|
if (user) {
|
|
3392
2001
|
try {
|
|
3393
|
-
query.acceptedBy = new
|
|
2002
|
+
query.acceptedBy = new import_mongodb8.ObjectId(user);
|
|
3394
2003
|
cacheOptions.user = user.toString();
|
|
3395
2004
|
} catch (error) {
|
|
3396
|
-
throw new
|
|
2005
|
+
throw new import_node_server_utils13.BadRequestError("Invalid user ID format.");
|
|
3397
2006
|
}
|
|
3398
2007
|
}
|
|
3399
|
-
const cacheKey = (0,
|
|
2008
|
+
const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, cacheOptions);
|
|
3400
2009
|
const cachedData = await getCache(cacheKey);
|
|
3401
2010
|
if (cachedData) {
|
|
3402
|
-
|
|
2011
|
+
import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3403
2012
|
return cachedData;
|
|
3404
2013
|
}
|
|
3405
2014
|
try {
|
|
@@ -3428,9 +2037,21 @@ function useAreaChecklistRepo() {
|
|
|
3428
2037
|
name: 1,
|
|
3429
2038
|
createdAt: 1,
|
|
3430
2039
|
acceptedByName: "$acceptedBy.name",
|
|
3431
|
-
status:
|
|
3432
|
-
|
|
3433
|
-
|
|
2040
|
+
status: {
|
|
2041
|
+
$switch: {
|
|
2042
|
+
branches: [
|
|
2043
|
+
{ case: { $eq: ["$status", "ready"] }, then: "Ready" },
|
|
2044
|
+
{ case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
|
|
2045
|
+
{
|
|
2046
|
+
case: { $eq: ["$status", "completed"] },
|
|
2047
|
+
then: "Completed"
|
|
2048
|
+
}
|
|
2049
|
+
],
|
|
2050
|
+
default: "$status"
|
|
2051
|
+
}
|
|
2052
|
+
},
|
|
2053
|
+
startedAt: "$acceptedAt",
|
|
2054
|
+
endedAt: "$completedAt"
|
|
3434
2055
|
}
|
|
3435
2056
|
},
|
|
3436
2057
|
{ $sort: { status: 1 } },
|
|
@@ -3439,11 +2060,11 @@ function useAreaChecklistRepo() {
|
|
|
3439
2060
|
];
|
|
3440
2061
|
const items = await collection.aggregate(pipeline).toArray();
|
|
3441
2062
|
const length = await collection.countDocuments(query);
|
|
3442
|
-
const data = (0,
|
|
2063
|
+
const data = (0, import_node_server_utils13.paginate)(items, page, limit, length);
|
|
3443
2064
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3444
|
-
|
|
2065
|
+
import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3445
2066
|
}).catch((err) => {
|
|
3446
|
-
|
|
2067
|
+
import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3447
2068
|
});
|
|
3448
2069
|
return data;
|
|
3449
2070
|
} catch (error) {
|
|
@@ -3452,16 +2073,16 @@ function useAreaChecklistRepo() {
|
|
|
3452
2073
|
}
|
|
3453
2074
|
async function getAreaChecklistHistoryDetails(_id) {
|
|
3454
2075
|
try {
|
|
3455
|
-
_id = new
|
|
2076
|
+
_id = new import_mongodb8.ObjectId(_id);
|
|
3456
2077
|
} catch (error) {
|
|
3457
|
-
throw new
|
|
2078
|
+
throw new import_node_server_utils13.BadRequestError("Invalid area checklist ID format.");
|
|
3458
2079
|
}
|
|
3459
|
-
const cacheKey = (0,
|
|
2080
|
+
const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, {
|
|
3460
2081
|
_id: _id.toString()
|
|
3461
2082
|
});
|
|
3462
2083
|
const cachedData = await getCache(cacheKey);
|
|
3463
2084
|
if (cachedData) {
|
|
3464
|
-
|
|
2085
|
+
import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
3465
2086
|
return cachedData;
|
|
3466
2087
|
}
|
|
3467
2088
|
try {
|
|
@@ -3502,9 +2123,21 @@ function useAreaChecklistRepo() {
|
|
|
3502
2123
|
name: 1,
|
|
3503
2124
|
createdAt: 1,
|
|
3504
2125
|
createdByName: "$createdBy.name",
|
|
3505
|
-
startedAt:
|
|
3506
|
-
endedAt:
|
|
3507
|
-
status:
|
|
2126
|
+
startedAt: "$acceptedAt",
|
|
2127
|
+
endedAt: "$completedAt",
|
|
2128
|
+
status: {
|
|
2129
|
+
$switch: {
|
|
2130
|
+
branches: [
|
|
2131
|
+
{ case: { $eq: ["$status", "ready"] }, then: "Ready" },
|
|
2132
|
+
{ case: { $eq: ["$status", "ongoing"] }, then: "Ongoing" },
|
|
2133
|
+
{
|
|
2134
|
+
case: { $eq: ["$status", "completed"] },
|
|
2135
|
+
then: "Completed"
|
|
2136
|
+
}
|
|
2137
|
+
],
|
|
2138
|
+
default: "$status"
|
|
2139
|
+
}
|
|
2140
|
+
},
|
|
3508
2141
|
signature: 1,
|
|
3509
2142
|
acceptedByName: "$acceptedBy.name"
|
|
3510
2143
|
}
|
|
@@ -3527,16 +2160,16 @@ function useAreaChecklistRepo() {
|
|
|
3527
2160
|
unitChecklistCollection.aggregate(unitPipeline).toArray()
|
|
3528
2161
|
]);
|
|
3529
2162
|
if (!area.length) {
|
|
3530
|
-
throw new
|
|
2163
|
+
throw new import_node_server_utils13.BadRequestError("Area checklist not found.");
|
|
3531
2164
|
}
|
|
3532
2165
|
const items = {
|
|
3533
2166
|
area: area[0],
|
|
3534
2167
|
units
|
|
3535
2168
|
};
|
|
3536
2169
|
setCache(cacheKey, items, 15 * 60).then(() => {
|
|
3537
|
-
|
|
2170
|
+
import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
|
|
3538
2171
|
}).catch((err) => {
|
|
3539
|
-
|
|
2172
|
+
import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3540
2173
|
});
|
|
3541
2174
|
return items;
|
|
3542
2175
|
} catch (error) {
|
|
@@ -3545,31 +2178,32 @@ function useAreaChecklistRepo() {
|
|
|
3545
2178
|
}
|
|
3546
2179
|
async function acceptAreaChecklist(_id, acceptedBy) {
|
|
3547
2180
|
try {
|
|
3548
|
-
_id = new
|
|
2181
|
+
_id = new import_mongodb8.ObjectId(_id);
|
|
3549
2182
|
} catch (error) {
|
|
3550
|
-
throw new
|
|
2183
|
+
throw new import_node_server_utils13.BadRequestError("Invalid area ID format.");
|
|
3551
2184
|
}
|
|
3552
2185
|
try {
|
|
3553
|
-
acceptedBy = new
|
|
2186
|
+
acceptedBy = new import_mongodb8.ObjectId(acceptedBy);
|
|
3554
2187
|
} catch (error) {
|
|
3555
|
-
throw new
|
|
2188
|
+
throw new import_node_server_utils13.BadRequestError("Invalid acceptedBy ID format.");
|
|
3556
2189
|
}
|
|
3557
2190
|
try {
|
|
3558
2191
|
const now = /* @__PURE__ */ new Date();
|
|
3559
2192
|
const updateValue = {
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
2193
|
+
metadata: {
|
|
2194
|
+
acceptedBy,
|
|
2195
|
+
acceptedAt: now
|
|
2196
|
+
},
|
|
3563
2197
|
updatedAt: now
|
|
3564
2198
|
};
|
|
3565
2199
|
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
3566
2200
|
if (res.modifiedCount === 0) {
|
|
3567
|
-
throw new
|
|
2201
|
+
throw new import_node_server_utils13.InternalServerError("Unable to update cleaning area.");
|
|
3568
2202
|
}
|
|
3569
2203
|
delNamespace().then(() => {
|
|
3570
|
-
|
|
2204
|
+
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3571
2205
|
}).catch((err) => {
|
|
3572
|
-
|
|
2206
|
+
import_node_server_utils13.logger.error(
|
|
3573
2207
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3574
2208
|
err
|
|
3575
2209
|
);
|
|
@@ -3581,9 +2215,9 @@ function useAreaChecklistRepo() {
|
|
|
3581
2215
|
}
|
|
3582
2216
|
async function attachImageAreaChecklist(_id, attachments, session) {
|
|
3583
2217
|
try {
|
|
3584
|
-
_id = new
|
|
2218
|
+
_id = new import_mongodb8.ObjectId(_id);
|
|
3585
2219
|
} catch (error) {
|
|
3586
|
-
throw new
|
|
2220
|
+
throw new import_node_server_utils13.BadRequestError("Invalid area checklist ID format.");
|
|
3587
2221
|
}
|
|
3588
2222
|
try {
|
|
3589
2223
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -3597,24 +2231,24 @@ function useAreaChecklistRepo() {
|
|
|
3597
2231
|
{ session }
|
|
3598
2232
|
);
|
|
3599
2233
|
if (res.modifiedCount === 0) {
|
|
3600
|
-
throw new
|
|
2234
|
+
throw new import_node_server_utils13.InternalServerError(
|
|
3601
2235
|
"Unable to update cleaning area checklist."
|
|
3602
2236
|
);
|
|
3603
2237
|
}
|
|
3604
2238
|
delNamespace().then(() => {
|
|
3605
|
-
|
|
2239
|
+
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3606
2240
|
}).catch((err) => {
|
|
3607
|
-
|
|
2241
|
+
import_node_server_utils13.logger.error(
|
|
3608
2242
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3609
2243
|
err
|
|
3610
2244
|
);
|
|
3611
2245
|
});
|
|
3612
2246
|
delUnitNamespace().then(() => {
|
|
3613
|
-
|
|
2247
|
+
import_node_server_utils13.logger.info(
|
|
3614
2248
|
`Cache cleared for namespace: ${unit_checklist_collection}`
|
|
3615
2249
|
);
|
|
3616
2250
|
}).catch((err) => {
|
|
3617
|
-
|
|
2251
|
+
import_node_server_utils13.logger.error(
|
|
3618
2252
|
`Failed to clear cache for namespace: ${unit_checklist_collection}`,
|
|
3619
2253
|
err
|
|
3620
2254
|
);
|
|
@@ -3626,26 +2260,28 @@ function useAreaChecklistRepo() {
|
|
|
3626
2260
|
}
|
|
3627
2261
|
async function submitAreaChecklist(_id, signature) {
|
|
3628
2262
|
try {
|
|
3629
|
-
_id = new
|
|
2263
|
+
_id = new import_mongodb8.ObjectId(_id);
|
|
3630
2264
|
} catch (error) {
|
|
3631
|
-
throw new
|
|
2265
|
+
throw new import_node_server_utils13.BadRequestError("Invalid area ID format.");
|
|
3632
2266
|
}
|
|
3633
2267
|
try {
|
|
3634
2268
|
const now = /* @__PURE__ */ new Date();
|
|
3635
2269
|
const updateValue = {
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
2270
|
+
metadata: {
|
|
2271
|
+
signature,
|
|
2272
|
+
completedAt: now
|
|
2273
|
+
},
|
|
2274
|
+
status: "ongoing",
|
|
3639
2275
|
updatedAt: now
|
|
3640
2276
|
};
|
|
3641
2277
|
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
3642
2278
|
if (res.modifiedCount === 0) {
|
|
3643
|
-
throw new
|
|
2279
|
+
throw new import_node_server_utils13.InternalServerError("Unable to update cleaning area.");
|
|
3644
2280
|
}
|
|
3645
2281
|
delNamespace().then(() => {
|
|
3646
|
-
|
|
2282
|
+
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3647
2283
|
}).catch((err) => {
|
|
3648
|
-
|
|
2284
|
+
import_node_server_utils13.logger.error(
|
|
3649
2285
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3650
2286
|
err
|
|
3651
2287
|
);
|
|
@@ -3657,26 +2293,28 @@ function useAreaChecklistRepo() {
|
|
|
3657
2293
|
}
|
|
3658
2294
|
async function completeAreaChecklist(_id, signature) {
|
|
3659
2295
|
try {
|
|
3660
|
-
_id = new
|
|
2296
|
+
_id = new import_mongodb8.ObjectId(_id);
|
|
3661
2297
|
} catch (error) {
|
|
3662
|
-
throw new
|
|
2298
|
+
throw new import_node_server_utils13.BadRequestError("Invalid area ID format.");
|
|
3663
2299
|
}
|
|
3664
2300
|
try {
|
|
3665
2301
|
const now = /* @__PURE__ */ new Date();
|
|
3666
2302
|
const updateValue = {
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
2303
|
+
metadata: {
|
|
2304
|
+
signature,
|
|
2305
|
+
completedAt: now
|
|
2306
|
+
},
|
|
2307
|
+
status: "completed",
|
|
3670
2308
|
updatedAt: now
|
|
3671
2309
|
};
|
|
3672
2310
|
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
3673
2311
|
if (res.modifiedCount === 0) {
|
|
3674
|
-
throw new
|
|
2312
|
+
throw new import_node_server_utils13.InternalServerError("Unable to update cleaning area.");
|
|
3675
2313
|
}
|
|
3676
2314
|
delNamespace().then(() => {
|
|
3677
|
-
|
|
2315
|
+
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3678
2316
|
}).catch((err) => {
|
|
3679
|
-
|
|
2317
|
+
import_node_server_utils13.logger.error(
|
|
3680
2318
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3681
2319
|
err
|
|
3682
2320
|
);
|
|
@@ -3701,72 +2339,110 @@ function useAreaChecklistRepo() {
|
|
|
3701
2339
|
}
|
|
3702
2340
|
|
|
3703
2341
|
// src/controllers/hygiene-area-checklist.controller.ts
|
|
3704
|
-
var
|
|
3705
|
-
var
|
|
2342
|
+
var import_node_server_utils15 = require("@iservice365/node-server-utils");
|
|
2343
|
+
var import_joi8 = __toESM(require("joi"));
|
|
3706
2344
|
|
|
3707
2345
|
// src/services/hygiene-area-checklist.service.ts
|
|
3708
|
-
var
|
|
2346
|
+
var import_node_server_utils14 = require("@iservice365/node-server-utils");
|
|
3709
2347
|
function useAreaChecklistService() {
|
|
3710
2348
|
const { createAreaChecklist: _createAreaChecklist } = useAreaChecklistRepo();
|
|
3711
|
-
const {
|
|
3712
|
-
const { getToiletLocations } = useToiletLocationRepository();
|
|
2349
|
+
const { getAreasForChecklist } = useAreaRepo();
|
|
3713
2350
|
async function createAreaChecklist(value) {
|
|
2351
|
+
const session = import_node_server_utils14.useAtlas.getClient()?.startSession();
|
|
3714
2352
|
try {
|
|
2353
|
+
session?.startTransaction();
|
|
3715
2354
|
const results = [];
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
const
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
2355
|
+
let totalChecklistsCreated = 0;
|
|
2356
|
+
const BATCH_SIZE = 10;
|
|
2357
|
+
const commonAreasResult = await getAreasForChecklist({
|
|
2358
|
+
site: value.site,
|
|
2359
|
+
type: "common"
|
|
2360
|
+
});
|
|
2361
|
+
const commonAreas = commonAreasResult || [];
|
|
2362
|
+
if (commonAreas.length > 0) {
|
|
2363
|
+
for (let i = 0; i < commonAreas.length; i += BATCH_SIZE) {
|
|
2364
|
+
const batch = commonAreas.slice(i, i + BATCH_SIZE);
|
|
2365
|
+
const batchPromises = batch.map(async (area) => {
|
|
2366
|
+
const checklistData = {
|
|
2367
|
+
schedule: value.schedule,
|
|
2368
|
+
name: area.name,
|
|
2369
|
+
type: "common",
|
|
2370
|
+
checklist: area.units && area.units.length > 0 ? [
|
|
2371
|
+
{
|
|
2372
|
+
set: area.set || 0,
|
|
2373
|
+
units: area.units.map((unit) => ({
|
|
2374
|
+
name: unit.name
|
|
2375
|
+
}))
|
|
2376
|
+
}
|
|
2377
|
+
] : []
|
|
2378
|
+
};
|
|
2379
|
+
const insertedId = await _createAreaChecklist(
|
|
2380
|
+
checklistData,
|
|
2381
|
+
session
|
|
2382
|
+
);
|
|
2383
|
+
totalChecklistsCreated++;
|
|
2384
|
+
return insertedId;
|
|
2385
|
+
});
|
|
2386
|
+
const batchResults = await Promise.all(batchPromises);
|
|
2387
|
+
results.push(...batchResults);
|
|
3736
2388
|
}
|
|
3737
|
-
|
|
3738
|
-
`Created ${
|
|
2389
|
+
import_node_server_utils14.logger.info(
|
|
2390
|
+
`Created ${commonAreas.length} common area checklists for site: ${value.site}`
|
|
3739
2391
|
);
|
|
2392
|
+
} else {
|
|
2393
|
+
import_node_server_utils14.logger.warn(`No common areas found for site: ${value.site}`);
|
|
3740
2394
|
}
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
2395
|
+
const toiletAreasResult = await getAreasForChecklist({
|
|
2396
|
+
site: value.site,
|
|
2397
|
+
type: "toilet"
|
|
2398
|
+
});
|
|
2399
|
+
const toiletAreas = toiletAreasResult || [];
|
|
2400
|
+
if (toiletAreas.length > 0) {
|
|
2401
|
+
for (let i = 0; i < toiletAreas.length; i += BATCH_SIZE) {
|
|
2402
|
+
const batch = toiletAreas.slice(i, i + BATCH_SIZE);
|
|
2403
|
+
const batchPromises = batch.map(async (toiletLocation) => {
|
|
2404
|
+
const checklistData = {
|
|
2405
|
+
schedule: value.schedule,
|
|
2406
|
+
name: toiletLocation.name,
|
|
2407
|
+
type: "toilet",
|
|
2408
|
+
checklist: toiletLocation.units && toiletLocation.units.length > 0 ? [
|
|
2409
|
+
{
|
|
2410
|
+
set: toiletLocation.set || 0,
|
|
2411
|
+
units: toiletLocation.units.map((unit) => ({
|
|
2412
|
+
name: unit.name
|
|
2413
|
+
}))
|
|
2414
|
+
}
|
|
2415
|
+
] : []
|
|
2416
|
+
};
|
|
2417
|
+
const insertedId = await _createAreaChecklist(
|
|
2418
|
+
checklistData,
|
|
2419
|
+
session
|
|
2420
|
+
);
|
|
2421
|
+
totalChecklistsCreated++;
|
|
2422
|
+
return insertedId;
|
|
2423
|
+
});
|
|
2424
|
+
const batchResults = await Promise.all(batchPromises);
|
|
2425
|
+
results.push(...batchResults);
|
|
3761
2426
|
}
|
|
3762
|
-
|
|
3763
|
-
`Created ${
|
|
2427
|
+
import_node_server_utils14.logger.info(
|
|
2428
|
+
`Created ${toiletAreas.length} toilet area checklists for site: ${value.site}`
|
|
3764
2429
|
);
|
|
2430
|
+
} else {
|
|
2431
|
+
import_node_server_utils14.logger.warn(`No toilet locations found for site: ${value.site}`);
|
|
3765
2432
|
}
|
|
2433
|
+
await session?.commitTransaction();
|
|
2434
|
+
import_node_server_utils14.logger.info(
|
|
2435
|
+
`Successfully created ${totalChecklistsCreated} area checklists for site: ${value.site}`
|
|
2436
|
+
);
|
|
3766
2437
|
return results;
|
|
3767
2438
|
} catch (error) {
|
|
3768
|
-
|
|
2439
|
+
import_node_server_utils14.logger.error(`Error generating area checklists:`, error);
|
|
2440
|
+
if (session?.inTransaction()) {
|
|
2441
|
+
await session?.abortTransaction();
|
|
2442
|
+
}
|
|
3769
2443
|
throw error;
|
|
2444
|
+
} finally {
|
|
2445
|
+
session?.endSession();
|
|
3770
2446
|
}
|
|
3771
2447
|
}
|
|
3772
2448
|
return { createAreaChecklist };
|
|
@@ -3785,69 +2461,62 @@ function useAreaChecklistController() {
|
|
|
3785
2461
|
} = useAreaChecklistRepo();
|
|
3786
2462
|
const { createAreaChecklist: _createAreaChecklist } = useAreaChecklistService();
|
|
3787
2463
|
async function createAreaChecklist(req, res, next) {
|
|
3788
|
-
const
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
const
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
type: import_joi12.default.string().required().valid(...allowedTypes),
|
|
3796
|
-
site: import_joi12.default.string().hex().required(),
|
|
3797
|
-
parentChecklist: import_joi12.default.string().hex().required(),
|
|
3798
|
-
createdBy: import_joi12.default.string().hex().optional().allow("", null)
|
|
2464
|
+
const payload = {
|
|
2465
|
+
site: req.params.site,
|
|
2466
|
+
schedule: req.params.schedule
|
|
2467
|
+
};
|
|
2468
|
+
const validation = import_joi8.default.object({
|
|
2469
|
+
site: import_joi8.default.string().hex().required(),
|
|
2470
|
+
schedule: import_joi8.default.string().hex().required()
|
|
3799
2471
|
});
|
|
3800
2472
|
const { error } = validation.validate(payload);
|
|
3801
2473
|
if (error) {
|
|
3802
|
-
|
|
3803
|
-
next(new
|
|
2474
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2475
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
3804
2476
|
return;
|
|
3805
2477
|
}
|
|
3806
2478
|
try {
|
|
3807
2479
|
await _createAreaChecklist(payload);
|
|
3808
|
-
res.status(201).json({ message: "Area
|
|
2480
|
+
res.status(201).json({ message: "Area checklist generated successfully." });
|
|
3809
2481
|
return;
|
|
3810
2482
|
} catch (error2) {
|
|
3811
|
-
|
|
2483
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
3812
2484
|
next(error2);
|
|
3813
2485
|
return;
|
|
3814
2486
|
}
|
|
3815
2487
|
}
|
|
3816
2488
|
async function getAllAreaChecklist(req, res, next) {
|
|
3817
2489
|
const query = { ...req.query, ...req.params };
|
|
3818
|
-
const validation =
|
|
3819
|
-
page:
|
|
3820
|
-
limit:
|
|
3821
|
-
search:
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
parentChecklist: import_joi12.default.string().hex().required()
|
|
2490
|
+
const validation = import_joi8.default.object({
|
|
2491
|
+
page: import_joi8.default.number().min(1).optional().allow("", null),
|
|
2492
|
+
limit: import_joi8.default.number().min(1).optional().allow("", null),
|
|
2493
|
+
search: import_joi8.default.string().optional().allow("", null),
|
|
2494
|
+
type: import_joi8.default.string().optional().allow("", ...allowedTypes),
|
|
2495
|
+
schedule: import_joi8.default.string().hex().required()
|
|
3825
2496
|
});
|
|
3826
2497
|
const { error } = validation.validate(query);
|
|
3827
2498
|
if (error) {
|
|
3828
|
-
|
|
3829
|
-
next(new
|
|
2499
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2500
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
3830
2501
|
return;
|
|
3831
2502
|
}
|
|
3832
2503
|
const page = parseInt(req.query.page) ?? 1;
|
|
3833
2504
|
const limit = parseInt(req.query.limit) ?? 20;
|
|
3834
2505
|
const search = req.query.search ?? "";
|
|
3835
|
-
const
|
|
3836
|
-
const
|
|
3837
|
-
const parentChecklist = req.params.parentChecklist ?? "";
|
|
2506
|
+
const type = req.query.type ?? "";
|
|
2507
|
+
const schedule = req.params.schedule ?? "";
|
|
3838
2508
|
try {
|
|
3839
2509
|
const data = await _getAllAreaChecklist({
|
|
3840
2510
|
page,
|
|
3841
2511
|
limit,
|
|
3842
2512
|
search,
|
|
3843
|
-
site,
|
|
3844
2513
|
type,
|
|
3845
|
-
|
|
2514
|
+
schedule
|
|
3846
2515
|
});
|
|
3847
2516
|
res.json(data);
|
|
3848
2517
|
return;
|
|
3849
2518
|
} catch (error2) {
|
|
3850
|
-
|
|
2519
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
3851
2520
|
next(error2);
|
|
3852
2521
|
return;
|
|
3853
2522
|
}
|
|
@@ -3859,29 +2528,29 @@ function useAreaChecklistController() {
|
|
|
3859
2528
|
) : {};
|
|
3860
2529
|
const user = cookies["user"] || "";
|
|
3861
2530
|
const query = { ...req.query, ...req.params, user };
|
|
3862
|
-
const validation =
|
|
3863
|
-
page:
|
|
3864
|
-
limit:
|
|
3865
|
-
search:
|
|
3866
|
-
site:
|
|
3867
|
-
type:
|
|
3868
|
-
|
|
3869
|
-
status:
|
|
3870
|
-
createdAt:
|
|
3871
|
-
user:
|
|
2531
|
+
const validation = import_joi8.default.object({
|
|
2532
|
+
page: import_joi8.default.number().min(1).optional().allow("", null),
|
|
2533
|
+
limit: import_joi8.default.number().min(1).optional().allow("", null),
|
|
2534
|
+
search: import_joi8.default.string().optional().allow("", null),
|
|
2535
|
+
site: import_joi8.default.string().hex().required(),
|
|
2536
|
+
type: import_joi8.default.string().valid(...allowedTypes).required(),
|
|
2537
|
+
schedule: import_joi8.default.string().hex().required(),
|
|
2538
|
+
status: import_joi8.default.string().allow("", null, ...allowedStatus),
|
|
2539
|
+
createdAt: import_joi8.default.alternatives().try(import_joi8.default.date(), import_joi8.default.string()).optional().allow("", null),
|
|
2540
|
+
user: import_joi8.default.string().hex().optional().allow("", null)
|
|
3872
2541
|
});
|
|
3873
2542
|
const { error } = validation.validate(query);
|
|
3874
2543
|
if (error) {
|
|
3875
|
-
|
|
3876
|
-
next(new
|
|
2544
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2545
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
3877
2546
|
return;
|
|
3878
2547
|
}
|
|
3879
2548
|
const page = parseInt(req.query.page) ?? 1;
|
|
3880
2549
|
const limit = parseInt(req.query.limit) ?? 20;
|
|
3881
2550
|
const search = req.query.search ?? "";
|
|
3882
2551
|
const site = req.params.site ?? "";
|
|
3883
|
-
const type = req.
|
|
3884
|
-
const
|
|
2552
|
+
const type = req.query.type ?? "";
|
|
2553
|
+
const schedule = req.params.schedule ?? "";
|
|
3885
2554
|
const status = req.query.status ?? "";
|
|
3886
2555
|
const createdAt = req.query.createdAt ?? "";
|
|
3887
2556
|
try {
|
|
@@ -3891,7 +2560,7 @@ function useAreaChecklistController() {
|
|
|
3891
2560
|
search,
|
|
3892
2561
|
site,
|
|
3893
2562
|
type,
|
|
3894
|
-
|
|
2563
|
+
schedule,
|
|
3895
2564
|
status,
|
|
3896
2565
|
createdAt,
|
|
3897
2566
|
user
|
|
@@ -3899,18 +2568,18 @@ function useAreaChecklistController() {
|
|
|
3899
2568
|
res.json(data);
|
|
3900
2569
|
return;
|
|
3901
2570
|
} catch (error2) {
|
|
3902
|
-
|
|
2571
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
3903
2572
|
next(error2);
|
|
3904
2573
|
return;
|
|
3905
2574
|
}
|
|
3906
2575
|
}
|
|
3907
2576
|
async function getAreaChecklistHistoryDetails(req, res, next) {
|
|
3908
|
-
const validation =
|
|
2577
|
+
const validation = import_joi8.default.string().hex().required();
|
|
3909
2578
|
const _id = req.params.id;
|
|
3910
2579
|
const { error } = validation.validate(_id);
|
|
3911
2580
|
if (error) {
|
|
3912
|
-
|
|
3913
|
-
next(new
|
|
2581
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2582
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
3914
2583
|
return;
|
|
3915
2584
|
}
|
|
3916
2585
|
try {
|
|
@@ -3918,7 +2587,7 @@ function useAreaChecklistController() {
|
|
|
3918
2587
|
res.json(data);
|
|
3919
2588
|
return;
|
|
3920
2589
|
} catch (error2) {
|
|
3921
|
-
|
|
2590
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
3922
2591
|
next(error2);
|
|
3923
2592
|
return;
|
|
3924
2593
|
}
|
|
@@ -3930,14 +2599,14 @@ function useAreaChecklistController() {
|
|
|
3930
2599
|
) : {};
|
|
3931
2600
|
const acceptedBy = cookies["user"] || "";
|
|
3932
2601
|
const payload = { id: req.params.id, acceptedBy };
|
|
3933
|
-
const validation =
|
|
3934
|
-
id:
|
|
3935
|
-
acceptedBy:
|
|
2602
|
+
const validation = import_joi8.default.object({
|
|
2603
|
+
id: import_joi8.default.string().hex().required(),
|
|
2604
|
+
acceptedBy: import_joi8.default.string().hex().required()
|
|
3936
2605
|
});
|
|
3937
2606
|
const { error } = validation.validate(payload);
|
|
3938
2607
|
if (error) {
|
|
3939
|
-
|
|
3940
|
-
next(new
|
|
2608
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2609
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
3941
2610
|
return;
|
|
3942
2611
|
}
|
|
3943
2612
|
try {
|
|
@@ -3945,21 +2614,21 @@ function useAreaChecklistController() {
|
|
|
3945
2614
|
res.json({ message: "Area checklist updated successfully." });
|
|
3946
2615
|
return;
|
|
3947
2616
|
} catch (error2) {
|
|
3948
|
-
|
|
2617
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
3949
2618
|
next(error2);
|
|
3950
2619
|
return;
|
|
3951
2620
|
}
|
|
3952
2621
|
}
|
|
3953
2622
|
async function attachImageAreaChecklist(req, res, next) {
|
|
3954
2623
|
const payload = { id: req.params.id, attachments: req.body.attachments };
|
|
3955
|
-
const validation =
|
|
3956
|
-
id:
|
|
3957
|
-
attachments:
|
|
2624
|
+
const validation = import_joi8.default.object({
|
|
2625
|
+
id: import_joi8.default.string().hex().required(),
|
|
2626
|
+
attachments: import_joi8.default.array().items(import_joi8.default.string()).optional()
|
|
3958
2627
|
});
|
|
3959
2628
|
const { error } = validation.validate(payload);
|
|
3960
2629
|
if (error) {
|
|
3961
|
-
|
|
3962
|
-
next(new
|
|
2630
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2631
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
3963
2632
|
return;
|
|
3964
2633
|
}
|
|
3965
2634
|
try {
|
|
@@ -3967,21 +2636,21 @@ function useAreaChecklistController() {
|
|
|
3967
2636
|
res.json({ message: "Area checklist attachments updated successfully." });
|
|
3968
2637
|
return;
|
|
3969
2638
|
} catch (error2) {
|
|
3970
|
-
|
|
2639
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
3971
2640
|
next(error2);
|
|
3972
2641
|
return;
|
|
3973
2642
|
}
|
|
3974
2643
|
}
|
|
3975
2644
|
async function submitAreaChecklist(req, res, next) {
|
|
3976
2645
|
const payload = { id: req.params.id, signature: req.body.signature };
|
|
3977
|
-
const validation =
|
|
3978
|
-
id:
|
|
3979
|
-
signature:
|
|
2646
|
+
const validation = import_joi8.default.object({
|
|
2647
|
+
id: import_joi8.default.string().hex().required(),
|
|
2648
|
+
signature: import_joi8.default.string().required()
|
|
3980
2649
|
});
|
|
3981
2650
|
const { error } = validation.validate(payload);
|
|
3982
2651
|
if (error) {
|
|
3983
|
-
|
|
3984
|
-
next(new
|
|
2652
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2653
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
3985
2654
|
return;
|
|
3986
2655
|
}
|
|
3987
2656
|
try {
|
|
@@ -3989,21 +2658,21 @@ function useAreaChecklistController() {
|
|
|
3989
2658
|
res.json({ message: "Area checklist submitted successfully." });
|
|
3990
2659
|
return;
|
|
3991
2660
|
} catch (error2) {
|
|
3992
|
-
|
|
2661
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
3993
2662
|
next(error2);
|
|
3994
2663
|
return;
|
|
3995
2664
|
}
|
|
3996
2665
|
}
|
|
3997
2666
|
async function completeAreaChecklist(req, res, next) {
|
|
3998
2667
|
const payload = { id: req.params.id, signature: req.body.signature };
|
|
3999
|
-
const validation =
|
|
4000
|
-
id:
|
|
4001
|
-
signature:
|
|
2668
|
+
const validation = import_joi8.default.object({
|
|
2669
|
+
id: import_joi8.default.string().hex().required(),
|
|
2670
|
+
signature: import_joi8.default.string().required()
|
|
4002
2671
|
});
|
|
4003
2672
|
const { error } = validation.validate(payload);
|
|
4004
2673
|
if (error) {
|
|
4005
|
-
|
|
4006
|
-
next(new
|
|
2674
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2675
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
4007
2676
|
return;
|
|
4008
2677
|
}
|
|
4009
2678
|
try {
|
|
@@ -4011,7 +2680,7 @@ function useAreaChecklistController() {
|
|
|
4011
2680
|
res.json({ message: "Area checklist completed successfully." });
|
|
4012
2681
|
return;
|
|
4013
2682
|
} catch (error2) {
|
|
4014
|
-
|
|
2683
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
4015
2684
|
next(error2);
|
|
4016
2685
|
return;
|
|
4017
2686
|
}
|
|
@@ -4029,57 +2698,57 @@ function useAreaChecklistController() {
|
|
|
4029
2698
|
}
|
|
4030
2699
|
|
|
4031
2700
|
// src/models/hygiene-unit-checklist.model.ts
|
|
4032
|
-
var
|
|
4033
|
-
var
|
|
4034
|
-
var
|
|
4035
|
-
var unitChecklistSchema =
|
|
4036
|
-
site:
|
|
4037
|
-
type:
|
|
4038
|
-
parentChecklist:
|
|
4039
|
-
areaChecklist:
|
|
4040
|
-
unit:
|
|
4041
|
-
name:
|
|
4042
|
-
createdBy:
|
|
2701
|
+
var import_node_server_utils16 = require("@iservice365/node-server-utils");
|
|
2702
|
+
var import_joi9 = __toESM(require("joi"));
|
|
2703
|
+
var import_mongodb9 = require("mongodb");
|
|
2704
|
+
var unitChecklistSchema = import_joi9.default.object({
|
|
2705
|
+
site: import_joi9.default.string().hex().required(),
|
|
2706
|
+
type: import_joi9.default.string().valid(...allowedTypes).required(),
|
|
2707
|
+
parentChecklist: import_joi9.default.string().hex().required(),
|
|
2708
|
+
areaChecklist: import_joi9.default.string().hex().required(),
|
|
2709
|
+
unit: import_joi9.default.string().hex().required(),
|
|
2710
|
+
name: import_joi9.default.string().optional().allow("", null),
|
|
2711
|
+
createdBy: import_joi9.default.string().hex().optional().allow("", null)
|
|
4043
2712
|
});
|
|
4044
2713
|
function MUnitChecklist(value) {
|
|
4045
2714
|
const { error } = unitChecklistSchema.validate(value);
|
|
4046
2715
|
if (error) {
|
|
4047
|
-
|
|
4048
|
-
throw new
|
|
2716
|
+
import_node_server_utils16.logger.info(`Hygiene Checklist Unit Model: ${error.message}`);
|
|
2717
|
+
throw new import_node_server_utils16.BadRequestError(error.message);
|
|
4049
2718
|
}
|
|
4050
2719
|
if (value.site) {
|
|
4051
2720
|
try {
|
|
4052
|
-
value.site = new
|
|
2721
|
+
value.site = new import_mongodb9.ObjectId(value.site);
|
|
4053
2722
|
} catch (error2) {
|
|
4054
|
-
throw new
|
|
2723
|
+
throw new import_node_server_utils16.BadRequestError("Invalid site ID format.");
|
|
4055
2724
|
}
|
|
4056
2725
|
}
|
|
4057
2726
|
if (value.parentChecklist) {
|
|
4058
2727
|
try {
|
|
4059
|
-
value.parentChecklist = new
|
|
2728
|
+
value.parentChecklist = new import_mongodb9.ObjectId(value.parentChecklist);
|
|
4060
2729
|
} catch (error2) {
|
|
4061
|
-
throw new
|
|
2730
|
+
throw new import_node_server_utils16.BadRequestError("Invalid parent checklist ID format.");
|
|
4062
2731
|
}
|
|
4063
2732
|
}
|
|
4064
2733
|
if (value.areaChecklist) {
|
|
4065
2734
|
try {
|
|
4066
|
-
value.areaChecklist = new
|
|
2735
|
+
value.areaChecklist = new import_mongodb9.ObjectId(value.areaChecklist);
|
|
4067
2736
|
} catch (error2) {
|
|
4068
|
-
throw new
|
|
2737
|
+
throw new import_node_server_utils16.BadRequestError("Invalid area checklist ID format.");
|
|
4069
2738
|
}
|
|
4070
2739
|
}
|
|
4071
2740
|
if (value.unit) {
|
|
4072
2741
|
try {
|
|
4073
|
-
value.unit = new
|
|
2742
|
+
value.unit = new import_mongodb9.ObjectId(value.unit);
|
|
4074
2743
|
} catch (error2) {
|
|
4075
|
-
throw new
|
|
2744
|
+
throw new import_node_server_utils16.BadRequestError("Invalid unit ID format.");
|
|
4076
2745
|
}
|
|
4077
2746
|
}
|
|
4078
2747
|
if (value.createdBy) {
|
|
4079
2748
|
try {
|
|
4080
|
-
value.createdBy = new
|
|
2749
|
+
value.createdBy = new import_mongodb9.ObjectId(value.createdBy);
|
|
4081
2750
|
} catch (error2) {
|
|
4082
|
-
throw new
|
|
2751
|
+
throw new import_node_server_utils16.BadRequestError("Invalid createdBy ID format.");
|
|
4083
2752
|
}
|
|
4084
2753
|
}
|
|
4085
2754
|
return {
|
|
@@ -4098,16 +2767,16 @@ function MUnitChecklist(value) {
|
|
|
4098
2767
|
}
|
|
4099
2768
|
|
|
4100
2769
|
// src/repositories/hygiene-unit-checklist.repository.ts
|
|
4101
|
-
var
|
|
4102
|
-
var
|
|
2770
|
+
var import_node_server_utils17 = require("@iservice365/node-server-utils");
|
|
2771
|
+
var import_mongodb10 = require("mongodb");
|
|
4103
2772
|
function useUnitChecklistRepo() {
|
|
4104
|
-
const db =
|
|
2773
|
+
const db = import_node_server_utils17.useAtlas.getDb();
|
|
4105
2774
|
if (!db) {
|
|
4106
|
-
throw new
|
|
2775
|
+
throw new import_node_server_utils17.InternalServerError("Unable to connect to server.");
|
|
4107
2776
|
}
|
|
4108
2777
|
const namespace_collection = "hygiene-checklist.units";
|
|
4109
2778
|
const collection = db.collection(namespace_collection);
|
|
4110
|
-
const { delNamespace, setCache, getCache } = (0,
|
|
2779
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils17.useCache)(namespace_collection);
|
|
4111
2780
|
async function createIndex() {
|
|
4112
2781
|
try {
|
|
4113
2782
|
await collection.createIndexes([
|
|
@@ -4122,7 +2791,7 @@ function useUnitChecklistRepo() {
|
|
|
4122
2791
|
{ key: { "metadata.workOrder.site": 1 } }
|
|
4123
2792
|
]);
|
|
4124
2793
|
} catch (error) {
|
|
4125
|
-
throw new
|
|
2794
|
+
throw new import_node_server_utils17.InternalServerError(
|
|
4126
2795
|
"Failed to create index on hygiene unit checklist."
|
|
4127
2796
|
);
|
|
4128
2797
|
}
|
|
@@ -4131,7 +2800,7 @@ function useUnitChecklistRepo() {
|
|
|
4131
2800
|
try {
|
|
4132
2801
|
await collection.createIndex({ name: "text" });
|
|
4133
2802
|
} catch (error) {
|
|
4134
|
-
throw new
|
|
2803
|
+
throw new import_node_server_utils17.InternalServerError(
|
|
4135
2804
|
"Failed to create text index on hygiene unit checklist."
|
|
4136
2805
|
);
|
|
4137
2806
|
}
|
|
@@ -4141,9 +2810,9 @@ function useUnitChecklistRepo() {
|
|
|
4141
2810
|
value = MUnitChecklist(value);
|
|
4142
2811
|
const res = await collection.insertOne(value, { session });
|
|
4143
2812
|
delNamespace().then(() => {
|
|
4144
|
-
|
|
2813
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4145
2814
|
}).catch((err) => {
|
|
4146
|
-
|
|
2815
|
+
import_node_server_utils17.logger.error(
|
|
4147
2816
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4148
2817
|
err
|
|
4149
2818
|
);
|
|
@@ -4169,31 +2838,31 @@ function useUnitChecklistRepo() {
|
|
|
4169
2838
|
limit
|
|
4170
2839
|
};
|
|
4171
2840
|
try {
|
|
4172
|
-
query.site = new
|
|
2841
|
+
query.site = new import_mongodb10.ObjectId(site);
|
|
4173
2842
|
cacheOptions.site = site.toString();
|
|
4174
2843
|
} catch (error) {
|
|
4175
|
-
throw new
|
|
2844
|
+
throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
|
|
4176
2845
|
}
|
|
4177
2846
|
try {
|
|
4178
|
-
query.parentChecklist = new
|
|
2847
|
+
query.parentChecklist = new import_mongodb10.ObjectId(parentChecklist);
|
|
4179
2848
|
cacheOptions.parentChecklist = parentChecklist.toString();
|
|
4180
2849
|
} catch (error) {
|
|
4181
|
-
throw new
|
|
2850
|
+
throw new import_node_server_utils17.BadRequestError("Invalid parent checklist ID format.");
|
|
4182
2851
|
}
|
|
4183
2852
|
try {
|
|
4184
|
-
query.areaChecklist = new
|
|
2853
|
+
query.areaChecklist = new import_mongodb10.ObjectId(areaChecklist);
|
|
4185
2854
|
cacheOptions.areaChecklist = areaChecklist.toString();
|
|
4186
2855
|
} catch (error) {
|
|
4187
|
-
throw new
|
|
2856
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area checklist ID format.");
|
|
4188
2857
|
}
|
|
4189
2858
|
if (search) {
|
|
4190
2859
|
query.$text = { $search: search };
|
|
4191
2860
|
cacheOptions.search = search;
|
|
4192
2861
|
}
|
|
4193
|
-
const cacheKey = (0,
|
|
2862
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
4194
2863
|
const cachedData = await getCache(cacheKey);
|
|
4195
2864
|
if (cachedData) {
|
|
4196
|
-
|
|
2865
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
4197
2866
|
return cachedData;
|
|
4198
2867
|
}
|
|
4199
2868
|
try {
|
|
@@ -4306,15 +2975,15 @@ function useUnitChecklistRepo() {
|
|
|
4306
2975
|
];
|
|
4307
2976
|
const items = await collection.aggregate(pipeline).toArray();
|
|
4308
2977
|
const length = await collection.countDocuments(query);
|
|
4309
|
-
const paginatedData = (0,
|
|
2978
|
+
const paginatedData = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
4310
2979
|
const data = {
|
|
4311
2980
|
attachments: areaAttachments,
|
|
4312
2981
|
...paginatedData
|
|
4313
2982
|
};
|
|
4314
2983
|
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4315
|
-
|
|
2984
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
4316
2985
|
}).catch((err) => {
|
|
4317
|
-
|
|
2986
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4318
2987
|
});
|
|
4319
2988
|
return data;
|
|
4320
2989
|
} catch (error) {
|
|
@@ -4323,9 +2992,9 @@ function useUnitChecklistRepo() {
|
|
|
4323
2992
|
}
|
|
4324
2993
|
async function getUnitChecklistById(_id) {
|
|
4325
2994
|
try {
|
|
4326
|
-
_id = new
|
|
2995
|
+
_id = new import_mongodb10.ObjectId(_id);
|
|
4327
2996
|
} catch (error) {
|
|
4328
|
-
throw new
|
|
2997
|
+
throw new import_node_server_utils17.BadRequestError("Invalid unit checklist ID format.");
|
|
4329
2998
|
}
|
|
4330
2999
|
try {
|
|
4331
3000
|
return await collection.findOne({ _id });
|
|
@@ -4335,52 +3004,52 @@ function useUnitChecklistRepo() {
|
|
|
4335
3004
|
}
|
|
4336
3005
|
async function updateUnitChecklist(_id, value, session) {
|
|
4337
3006
|
try {
|
|
4338
|
-
_id = new
|
|
3007
|
+
_id = new import_mongodb10.ObjectId(_id);
|
|
4339
3008
|
} catch (error) {
|
|
4340
|
-
throw new
|
|
3009
|
+
throw new import_node_server_utils17.BadRequestError("Invalid unit checklist ID format.");
|
|
4341
3010
|
}
|
|
4342
3011
|
if (value.checkedBy && typeof value.checkedBy === "string") {
|
|
4343
3012
|
try {
|
|
4344
|
-
value.checkedBy = new
|
|
3013
|
+
value.checkedBy = new import_mongodb10.ObjectId(value.checkedBy);
|
|
4345
3014
|
} catch (error) {
|
|
4346
|
-
throw new
|
|
3015
|
+
throw new import_node_server_utils17.BadRequestError("Invalid checkedBy ID format.");
|
|
4347
3016
|
}
|
|
4348
3017
|
}
|
|
4349
3018
|
if ("metadata" in value && value.metadata?.workOrder) {
|
|
4350
3019
|
const workOrder = value.metadata.workOrder;
|
|
4351
3020
|
if (workOrder.category && typeof workOrder.category === "string") {
|
|
4352
3021
|
try {
|
|
4353
|
-
workOrder.category = new
|
|
3022
|
+
workOrder.category = new import_mongodb10.ObjectId(workOrder.category);
|
|
4354
3023
|
} catch (error) {
|
|
4355
|
-
throw new
|
|
3024
|
+
throw new import_node_server_utils17.BadRequestError("Invalid category ID format.");
|
|
4356
3025
|
}
|
|
4357
3026
|
}
|
|
4358
3027
|
if (workOrder.createdBy && typeof workOrder.createdBy === "string") {
|
|
4359
3028
|
try {
|
|
4360
|
-
workOrder.createdBy = new
|
|
3029
|
+
workOrder.createdBy = new import_mongodb10.ObjectId(workOrder.createdBy);
|
|
4361
3030
|
} catch (error) {
|
|
4362
|
-
throw new
|
|
3031
|
+
throw new import_node_server_utils17.BadRequestError("Invalid createdBy ID format.");
|
|
4363
3032
|
}
|
|
4364
3033
|
}
|
|
4365
3034
|
if (workOrder.serviceProvider && typeof workOrder.serviceProvider === "string") {
|
|
4366
3035
|
try {
|
|
4367
|
-
workOrder.serviceProvider = new
|
|
3036
|
+
workOrder.serviceProvider = new import_mongodb10.ObjectId(workOrder.serviceProvider);
|
|
4368
3037
|
} catch (error) {
|
|
4369
|
-
throw new
|
|
3038
|
+
throw new import_node_server_utils17.BadRequestError("Invalid serviceProvider ID format.");
|
|
4370
3039
|
}
|
|
4371
3040
|
}
|
|
4372
3041
|
if (workOrder.organization && typeof workOrder.organization === "string") {
|
|
4373
3042
|
try {
|
|
4374
|
-
workOrder.organization = new
|
|
3043
|
+
workOrder.organization = new import_mongodb10.ObjectId(workOrder.organization);
|
|
4375
3044
|
} catch (error) {
|
|
4376
|
-
throw new
|
|
3045
|
+
throw new import_node_server_utils17.BadRequestError("Invalid organization ID format.");
|
|
4377
3046
|
}
|
|
4378
3047
|
}
|
|
4379
3048
|
if (workOrder.site && typeof workOrder.site === "string") {
|
|
4380
3049
|
try {
|
|
4381
|
-
workOrder.site = new
|
|
3050
|
+
workOrder.site = new import_mongodb10.ObjectId(workOrder.site);
|
|
4382
3051
|
} catch (error) {
|
|
4383
|
-
throw new
|
|
3052
|
+
throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
|
|
4384
3053
|
}
|
|
4385
3054
|
}
|
|
4386
3055
|
}
|
|
@@ -4392,12 +3061,12 @@ function useUnitChecklistRepo() {
|
|
|
4392
3061
|
{ session }
|
|
4393
3062
|
);
|
|
4394
3063
|
if (res.modifiedCount === 0) {
|
|
4395
|
-
throw new
|
|
3064
|
+
throw new import_node_server_utils17.InternalServerError("Unable to update unit checklist.");
|
|
4396
3065
|
}
|
|
4397
3066
|
delNamespace().then(() => {
|
|
4398
|
-
|
|
3067
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
4399
3068
|
}).catch((err) => {
|
|
4400
|
-
|
|
3069
|
+
import_node_server_utils17.logger.error(
|
|
4401
3070
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
4402
3071
|
err
|
|
4403
3072
|
);
|
|
@@ -4418,11 +3087,11 @@ function useUnitChecklistRepo() {
|
|
|
4418
3087
|
}
|
|
4419
3088
|
|
|
4420
3089
|
// src/controllers/hygiene-unit-checklist.controller.ts
|
|
4421
|
-
var
|
|
4422
|
-
var
|
|
3090
|
+
var import_node_server_utils19 = require("@iservice365/node-server-utils");
|
|
3091
|
+
var import_joi10 = __toESM(require("joi"));
|
|
4423
3092
|
|
|
4424
3093
|
// src/services/hygiene-unit-checklist.service.ts
|
|
4425
|
-
var
|
|
3094
|
+
var import_node_server_utils18 = require("@iservice365/node-server-utils");
|
|
4426
3095
|
var import_core = require("@iservice365/core");
|
|
4427
3096
|
function useUnitChecklistService() {
|
|
4428
3097
|
const {
|
|
@@ -4438,7 +3107,7 @@ function useUnitChecklistService() {
|
|
|
4438
3107
|
const result = await _updateUnitChecklist(id, value);
|
|
4439
3108
|
return result;
|
|
4440
3109
|
} catch (error) {
|
|
4441
|
-
|
|
3110
|
+
import_node_server_utils18.logger.error(`Error updating unit checklist with id ${id}:`, error);
|
|
4442
3111
|
throw error;
|
|
4443
3112
|
}
|
|
4444
3113
|
}
|
|
@@ -4449,12 +3118,12 @@ function useUnitChecklistService() {
|
|
|
4449
3118
|
if (value.metadata?.workOrder) {
|
|
4450
3119
|
const existingChecklist = await _getUnitChecklistById(id);
|
|
4451
3120
|
if (!existingChecklist)
|
|
4452
|
-
throw new
|
|
3121
|
+
throw new import_node_server_utils18.NotFoundError("Unit checklist not found.");
|
|
4453
3122
|
const site = await getSiteById(
|
|
4454
3123
|
existingChecklist.site
|
|
4455
3124
|
);
|
|
4456
3125
|
if (!site)
|
|
4457
|
-
throw new
|
|
3126
|
+
throw new import_node_server_utils18.NotFoundError("Site not found.");
|
|
4458
3127
|
const workOrderData = {
|
|
4459
3128
|
...value.metadata.workOrder,
|
|
4460
3129
|
attachments: value.metadata.attachments,
|
|
@@ -4467,12 +3136,12 @@ function useUnitChecklistService() {
|
|
|
4467
3136
|
fullHost
|
|
4468
3137
|
);
|
|
4469
3138
|
if (!workOrder)
|
|
4470
|
-
throw new
|
|
3139
|
+
throw new import_node_server_utils18.NotFoundError("Failed to create work order.");
|
|
4471
3140
|
}
|
|
4472
3141
|
const result = await _updateUnitChecklist(id, value);
|
|
4473
3142
|
return result;
|
|
4474
3143
|
} catch (error) {
|
|
4475
|
-
|
|
3144
|
+
import_node_server_utils18.logger.error(`Error updating unit checklist with id ${id}:`, error);
|
|
4476
3145
|
throw error;
|
|
4477
3146
|
}
|
|
4478
3147
|
}
|
|
@@ -4502,8 +3171,8 @@ function useUnitChecklistController() {
|
|
|
4502
3171
|
const payload = { ...req.body, ...req.params, createdBy };
|
|
4503
3172
|
const { error } = unitChecklistSchema.validate(payload);
|
|
4504
3173
|
if (error) {
|
|
4505
|
-
|
|
4506
|
-
next(new
|
|
3174
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3175
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
4507
3176
|
return;
|
|
4508
3177
|
}
|
|
4509
3178
|
try {
|
|
@@ -4511,26 +3180,26 @@ function useUnitChecklistController() {
|
|
|
4511
3180
|
res.status(201).json({ message: "Unit checklist created successfully.", id });
|
|
4512
3181
|
return;
|
|
4513
3182
|
} catch (error2) {
|
|
4514
|
-
|
|
3183
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
4515
3184
|
next(error2);
|
|
4516
3185
|
return;
|
|
4517
3186
|
}
|
|
4518
3187
|
}
|
|
4519
3188
|
async function getAllUnitChecklist(req, res, next) {
|
|
4520
3189
|
const query = { ...req.query, ...req.params };
|
|
4521
|
-
const validation =
|
|
4522
|
-
page:
|
|
4523
|
-
limit:
|
|
4524
|
-
search:
|
|
4525
|
-
site:
|
|
4526
|
-
type:
|
|
4527
|
-
parentChecklist:
|
|
4528
|
-
areaChecklist:
|
|
3190
|
+
const validation = import_joi10.default.object({
|
|
3191
|
+
page: import_joi10.default.number().min(1).optional().allow("", null),
|
|
3192
|
+
limit: import_joi10.default.number().min(1).optional().allow("", null),
|
|
3193
|
+
search: import_joi10.default.string().optional().allow("", null),
|
|
3194
|
+
site: import_joi10.default.string().hex().required(),
|
|
3195
|
+
type: import_joi10.default.string().valid(...allowedTypes).required(),
|
|
3196
|
+
parentChecklist: import_joi10.default.string().hex().required(),
|
|
3197
|
+
areaChecklist: import_joi10.default.string().hex().required()
|
|
4529
3198
|
});
|
|
4530
3199
|
const { error } = validation.validate(query);
|
|
4531
3200
|
if (error) {
|
|
4532
|
-
|
|
4533
|
-
next(new
|
|
3201
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3202
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
4534
3203
|
return;
|
|
4535
3204
|
}
|
|
4536
3205
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -4553,7 +3222,7 @@ function useUnitChecklistController() {
|
|
|
4553
3222
|
res.json(data);
|
|
4554
3223
|
return;
|
|
4555
3224
|
} catch (error2) {
|
|
4556
|
-
|
|
3225
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
4557
3226
|
next(error2);
|
|
4558
3227
|
return;
|
|
4559
3228
|
}
|
|
@@ -4565,14 +3234,14 @@ function useUnitChecklistController() {
|
|
|
4565
3234
|
) : {};
|
|
4566
3235
|
const checkedBy = cookies["user"] || "";
|
|
4567
3236
|
const payload = { id: req.params.id, checkedBy };
|
|
4568
|
-
const validation =
|
|
4569
|
-
id:
|
|
4570
|
-
checkedBy:
|
|
3237
|
+
const validation = import_joi10.default.object({
|
|
3238
|
+
id: import_joi10.default.string().hex().required(),
|
|
3239
|
+
checkedBy: import_joi10.default.string().hex().required()
|
|
4571
3240
|
});
|
|
4572
3241
|
const { error } = validation.validate(payload);
|
|
4573
3242
|
if (error) {
|
|
4574
|
-
|
|
4575
|
-
next(new
|
|
3243
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3244
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
4576
3245
|
return;
|
|
4577
3246
|
}
|
|
4578
3247
|
try {
|
|
@@ -4581,7 +3250,7 @@ function useUnitChecklistController() {
|
|
|
4581
3250
|
res.json({ message: "Unit checklist approved successfully." });
|
|
4582
3251
|
return;
|
|
4583
3252
|
} catch (error2) {
|
|
4584
|
-
|
|
3253
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
4585
3254
|
next(error2);
|
|
4586
3255
|
return;
|
|
4587
3256
|
}
|
|
@@ -4596,17 +3265,17 @@ function useUnitChecklistController() {
|
|
|
4596
3265
|
req.body.workOrder.createdBy = checkedBy;
|
|
4597
3266
|
}
|
|
4598
3267
|
const payload = { id: req.params.id, checkedBy, ...req.body };
|
|
4599
|
-
const validation =
|
|
4600
|
-
id:
|
|
4601
|
-
attachments:
|
|
4602
|
-
remarks:
|
|
3268
|
+
const validation = import_joi10.default.object({
|
|
3269
|
+
id: import_joi10.default.string().hex().required(),
|
|
3270
|
+
attachments: import_joi10.default.array().items(import_joi10.default.string()).optional(),
|
|
3271
|
+
remarks: import_joi10.default.string().required(),
|
|
4603
3272
|
workOrder: import_core2.workOrderSchema.optional(),
|
|
4604
|
-
checkedBy:
|
|
3273
|
+
checkedBy: import_joi10.default.string().hex().required()
|
|
4605
3274
|
});
|
|
4606
3275
|
const { error } = validation.validate(payload);
|
|
4607
3276
|
if (error) {
|
|
4608
|
-
|
|
4609
|
-
next(new
|
|
3277
|
+
import_node_server_utils19.logger.log({ level: "error", message: error.message });
|
|
3278
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
4610
3279
|
return;
|
|
4611
3280
|
}
|
|
4612
3281
|
try {
|
|
@@ -4630,7 +3299,7 @@ function useUnitChecklistController() {
|
|
|
4630
3299
|
res.json({ message: "Unit checklist rejected successfully." });
|
|
4631
3300
|
return;
|
|
4632
3301
|
} catch (error2) {
|
|
4633
|
-
|
|
3302
|
+
import_node_server_utils19.logger.log({ level: "error", message: error2.message });
|
|
4634
3303
|
next(error2);
|
|
4635
3304
|
return;
|
|
4636
3305
|
}
|
|
@@ -4647,32 +3316,21 @@ function useUnitChecklistController() {
|
|
|
4647
3316
|
MArea,
|
|
4648
3317
|
MAreaChecklist,
|
|
4649
3318
|
MParentChecklist,
|
|
4650
|
-
MScheduleTaskArea,
|
|
4651
|
-
MToiletLocation,
|
|
4652
3319
|
MUnit,
|
|
4653
3320
|
MUnitChecklist,
|
|
4654
|
-
|
|
4655
|
-
allowedTypes,
|
|
3321
|
+
allowedChecklistStatus,
|
|
4656
3322
|
areaChecklistSchema,
|
|
4657
3323
|
areaSchema,
|
|
4658
3324
|
parentChecklistSchema,
|
|
4659
|
-
scheduleTaskAreaSchema,
|
|
4660
|
-
toiletLocationSchema,
|
|
4661
3325
|
unitChecklistSchema,
|
|
4662
3326
|
unitSchema,
|
|
4663
3327
|
useAreaChecklistController,
|
|
4664
3328
|
useAreaChecklistRepo,
|
|
4665
3329
|
useAreaController,
|
|
4666
|
-
|
|
3330
|
+
useAreaRepo,
|
|
4667
3331
|
useAreaService,
|
|
4668
3332
|
useParentChecklistController,
|
|
4669
3333
|
useParentChecklistRepo,
|
|
4670
|
-
useScheduleTaskAreaController,
|
|
4671
|
-
useScheduleTaskAreaRepository,
|
|
4672
|
-
useScheduleTaskAreaService,
|
|
4673
|
-
useToiletLocationController,
|
|
4674
|
-
useToiletLocationRepository,
|
|
4675
|
-
useToiletLocationService,
|
|
4676
3334
|
useUnitChecklistController,
|
|
4677
3335
|
useUnitChecklistRepo,
|
|
4678
3336
|
useUnitController,
|