@iservice365/module-hygiene 0.0.1 → 0.1.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 +331 -1
- package/dist/index.js +2781 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2780 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -2
- package/dist/public/user-invite.hbs +0 -142
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2783 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
MArea: () => MArea,
|
|
34
|
+
MParentChecklist: () => MParentChecklist,
|
|
35
|
+
MScheduleTaskArea: () => MScheduleTaskArea,
|
|
36
|
+
MToiletLocation: () => MToiletLocation,
|
|
37
|
+
MUnit: () => MUnit,
|
|
38
|
+
areaSchema: () => areaSchema,
|
|
39
|
+
parentChecklistSchema: () => parentChecklistSchema,
|
|
40
|
+
scheduleTaskAreaSchema: () => scheduleTaskAreaSchema,
|
|
41
|
+
toiletLocationSchema: () => toiletLocationSchema,
|
|
42
|
+
unitSchema: () => unitSchema,
|
|
43
|
+
useAreaController: () => useAreaController,
|
|
44
|
+
useAreaRepository: () => useAreaRepository,
|
|
45
|
+
useAreaService: () => useAreaService,
|
|
46
|
+
useParentCheckilstController: () => useParentCheckilstController,
|
|
47
|
+
useParentChecklistRepo: () => useParentChecklistRepo,
|
|
48
|
+
useScheduleTaskAreaController: () => useScheduleTaskAreaController,
|
|
49
|
+
useScheduleTaskAreaRepository: () => useScheduleTaskAreaRepository,
|
|
50
|
+
useScheduleTaskAreaService: () => useScheduleTaskAreaService,
|
|
51
|
+
useToiletLocationController: () => useToiletLocationController,
|
|
52
|
+
useToiletLocationRepository: () => useToiletLocationRepository,
|
|
53
|
+
useToiletLocationService: () => useToiletLocationService,
|
|
54
|
+
useUnitController: () => useUnitController,
|
|
55
|
+
useUnitRepository: () => useUnitRepository,
|
|
56
|
+
useUnitService: () => useUnitService
|
|
57
|
+
});
|
|
58
|
+
module.exports = __toCommonJS(src_exports);
|
|
59
|
+
|
|
60
|
+
// src/models/hygiene-area.model.ts
|
|
61
|
+
var import_node_server_utils = require("@iservice365/node-server-utils");
|
|
62
|
+
var import_joi = __toESM(require("joi"));
|
|
63
|
+
var import_mongodb = require("mongodb");
|
|
64
|
+
var areaSchema = import_joi.default.object({
|
|
65
|
+
name: import_joi.default.string().required(),
|
|
66
|
+
site: import_joi.default.string().hex().required(),
|
|
67
|
+
createdBy: import_joi.default.string().hex().required(),
|
|
68
|
+
checklist: import_joi.default.array().items(
|
|
69
|
+
import_joi.default.object({
|
|
70
|
+
_id: import_joi.default.string().hex().required(),
|
|
71
|
+
name: import_joi.default.string().required()
|
|
72
|
+
})
|
|
73
|
+
).optional()
|
|
74
|
+
});
|
|
75
|
+
function MArea(value) {
|
|
76
|
+
const { error } = areaSchema.validate(value);
|
|
77
|
+
if (error) {
|
|
78
|
+
import_node_server_utils.logger.info(`Hygiene Area Model: ${error.message}`);
|
|
79
|
+
throw new import_node_server_utils.BadRequestError(error.message);
|
|
80
|
+
}
|
|
81
|
+
if (value.site) {
|
|
82
|
+
try {
|
|
83
|
+
value.site = new import_mongodb.ObjectId(value.site);
|
|
84
|
+
} catch (error2) {
|
|
85
|
+
throw new import_node_server_utils.BadRequestError("Invalid site ID format.");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (value.createdBy) {
|
|
89
|
+
try {
|
|
90
|
+
value.createdBy = new import_mongodb.ObjectId(value.createdBy);
|
|
91
|
+
} catch (error2) {
|
|
92
|
+
throw new import_node_server_utils.BadRequestError("Invalid createdBy ID format.");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (value.checklist && Array.isArray(value.checklist)) {
|
|
96
|
+
value.checklist = value.checklist.map((item) => {
|
|
97
|
+
try {
|
|
98
|
+
return {
|
|
99
|
+
...item,
|
|
100
|
+
_id: new import_mongodb.ObjectId(item._id)
|
|
101
|
+
};
|
|
102
|
+
} catch (error2) {
|
|
103
|
+
throw new import_node_server_utils.BadRequestError(
|
|
104
|
+
`Invalid checklist item ID format: ${item._id}`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
name: value.name,
|
|
111
|
+
site: value.site,
|
|
112
|
+
createdBy: value.createdBy,
|
|
113
|
+
checklist: value.checklist,
|
|
114
|
+
status: value.status ?? "active",
|
|
115
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
116
|
+
updatedAt: value.updatedAt ?? "",
|
|
117
|
+
deletedAt: value.deletedAt ?? ""
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/repositories/hygiene-area.repository.ts
|
|
122
|
+
var import_mongodb2 = require("mongodb");
|
|
123
|
+
var import_node_server_utils2 = require("@iservice365/node-server-utils");
|
|
124
|
+
function useAreaRepository() {
|
|
125
|
+
const db = import_node_server_utils2.useAtlas.getDb();
|
|
126
|
+
if (!db) {
|
|
127
|
+
throw new import_node_server_utils2.InternalServerError("Unable to connect to server.");
|
|
128
|
+
}
|
|
129
|
+
const namespace_collection = "hygiene-areas";
|
|
130
|
+
const collection = db.collection(namespace_collection);
|
|
131
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils2.useCache)(namespace_collection);
|
|
132
|
+
async function createIndex() {
|
|
133
|
+
try {
|
|
134
|
+
await collection.createIndexes([
|
|
135
|
+
{ key: { site: 1 } },
|
|
136
|
+
{ key: { createdBy: 1 } },
|
|
137
|
+
{ key: { status: 1 } }
|
|
138
|
+
]);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
throw new import_node_server_utils2.InternalServerError("Failed to create index on hygiene area.");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function createTextIndex() {
|
|
144
|
+
try {
|
|
145
|
+
await collection.createIndex({ name: "text" });
|
|
146
|
+
} catch (error) {
|
|
147
|
+
throw new import_node_server_utils2.InternalServerError(
|
|
148
|
+
"Failed to create text index on hygiene area."
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function createUniqueIndex() {
|
|
153
|
+
try {
|
|
154
|
+
await collection.createIndex(
|
|
155
|
+
{ name: 1, site: 1, deletedAt: 1 },
|
|
156
|
+
{ unique: true }
|
|
157
|
+
);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
throw new import_node_server_utils2.InternalServerError(
|
|
160
|
+
"Failed to create unique index on hygiene area."
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function createArea(value, session) {
|
|
165
|
+
try {
|
|
166
|
+
value = MArea(value);
|
|
167
|
+
const res = await collection.insertOne(value, { session });
|
|
168
|
+
delNamespace().then(() => {
|
|
169
|
+
import_node_server_utils2.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
170
|
+
}).catch((err) => {
|
|
171
|
+
import_node_server_utils2.logger.error(
|
|
172
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
173
|
+
err
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
return res.insertedId;
|
|
177
|
+
} catch (error) {
|
|
178
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
179
|
+
if (isDuplicated) {
|
|
180
|
+
throw new import_node_server_utils2.BadRequestError("Area already exists.");
|
|
181
|
+
}
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async function getAreas({
|
|
186
|
+
page = 1,
|
|
187
|
+
limit = 10,
|
|
188
|
+
search = "",
|
|
189
|
+
startDate = "",
|
|
190
|
+
endDate = "",
|
|
191
|
+
site = ""
|
|
192
|
+
}) {
|
|
193
|
+
page = page > 0 ? page - 1 : 0;
|
|
194
|
+
const query = {
|
|
195
|
+
status: { $ne: "deleted" }
|
|
196
|
+
};
|
|
197
|
+
const cacheOptions = {
|
|
198
|
+
page,
|
|
199
|
+
limit
|
|
200
|
+
};
|
|
201
|
+
if (site) {
|
|
202
|
+
try {
|
|
203
|
+
site = new import_mongodb2.ObjectId(site);
|
|
204
|
+
cacheOptions.site = site.toString();
|
|
205
|
+
} catch (error) {
|
|
206
|
+
throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (search) {
|
|
210
|
+
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
211
|
+
cacheOptions.search = search;
|
|
212
|
+
}
|
|
213
|
+
if (startDate && endDate) {
|
|
214
|
+
query.createdAt = {
|
|
215
|
+
$gte: new Date(startDate),
|
|
216
|
+
$lte: new Date(endDate)
|
|
217
|
+
};
|
|
218
|
+
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
219
|
+
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
220
|
+
} else if (startDate) {
|
|
221
|
+
query.createdAt = { $gte: new Date(startDate) };
|
|
222
|
+
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
223
|
+
} else if (endDate) {
|
|
224
|
+
query.createdAt = { $lte: new Date(endDate) };
|
|
225
|
+
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
226
|
+
}
|
|
227
|
+
const cacheKey = (0, import_node_server_utils2.makeCacheKey)(namespace_collection, cacheOptions);
|
|
228
|
+
const cachedData = await getCache(cacheKey);
|
|
229
|
+
if (cachedData) {
|
|
230
|
+
import_node_server_utils2.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
231
|
+
return cachedData;
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
const items = await collection.aggregate([
|
|
235
|
+
{ $match: query },
|
|
236
|
+
{
|
|
237
|
+
$lookup: {
|
|
238
|
+
from: "sites",
|
|
239
|
+
localField: "site",
|
|
240
|
+
foreignField: "_id",
|
|
241
|
+
pipeline: [{ $project: { name: 1 } }],
|
|
242
|
+
as: "site"
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
$unwind: {
|
|
247
|
+
path: "$site",
|
|
248
|
+
preserveNullAndEmptyArrays: true
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
$lookup: {
|
|
253
|
+
from: "users",
|
|
254
|
+
localField: "createdBy",
|
|
255
|
+
foreignField: "_id",
|
|
256
|
+
pipeline: [{ $project: { name: 1 } }],
|
|
257
|
+
as: "createdBy"
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
$unwind: {
|
|
262
|
+
path: "$createdBy",
|
|
263
|
+
preserveNullAndEmptyArrays: true
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
$project: {
|
|
268
|
+
name: 1,
|
|
269
|
+
site: "$site._id",
|
|
270
|
+
siteName: "$site.name",
|
|
271
|
+
createdByName: "$createdBy.name",
|
|
272
|
+
checklist: 1,
|
|
273
|
+
status: 1,
|
|
274
|
+
createdAt: 1
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
{ $sort: { _id: -1 } },
|
|
278
|
+
{ $skip: page * limit },
|
|
279
|
+
{ $limit: limit }
|
|
280
|
+
]).toArray();
|
|
281
|
+
const length = await collection.countDocuments(query);
|
|
282
|
+
const data = (0, import_node_server_utils2.paginate)(items, page, limit, length);
|
|
283
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
284
|
+
import_node_server_utils2.logger.info(`Cache set for key: ${cacheKey}`);
|
|
285
|
+
}).catch((err) => {
|
|
286
|
+
import_node_server_utils2.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
287
|
+
});
|
|
288
|
+
return data;
|
|
289
|
+
} catch (error) {
|
|
290
|
+
throw error;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
async function getAreaById(_id) {
|
|
294
|
+
try {
|
|
295
|
+
_id = new import_mongodb2.ObjectId(_id);
|
|
296
|
+
} catch (error) {
|
|
297
|
+
throw new import_node_server_utils2.BadRequestError("Invalid area ID format.");
|
|
298
|
+
}
|
|
299
|
+
const query = {
|
|
300
|
+
_id,
|
|
301
|
+
status: { $ne: "deleted" }
|
|
302
|
+
};
|
|
303
|
+
const cacheKey = (0, import_node_server_utils2.makeCacheKey)(namespace_collection, {
|
|
304
|
+
_id: _id.toString()
|
|
305
|
+
});
|
|
306
|
+
const cachedData = await getCache(cacheKey);
|
|
307
|
+
if (cachedData) {
|
|
308
|
+
import_node_server_utils2.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
309
|
+
return cachedData;
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
const data = await collection.aggregate([
|
|
313
|
+
{ $match: query },
|
|
314
|
+
{
|
|
315
|
+
$project: {
|
|
316
|
+
name: 1,
|
|
317
|
+
checklist: 1
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
]).toArray();
|
|
321
|
+
if (!data || !data.length) {
|
|
322
|
+
throw new import_node_server_utils2.NotFoundError("Area not found.");
|
|
323
|
+
}
|
|
324
|
+
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
325
|
+
import_node_server_utils2.logger.info(`Cache set for key: ${cacheKey}`);
|
|
326
|
+
}).catch((err) => {
|
|
327
|
+
import_node_server_utils2.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
328
|
+
});
|
|
329
|
+
return data[0];
|
|
330
|
+
} catch (error) {
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
async function getAreaByName(name, site) {
|
|
335
|
+
try {
|
|
336
|
+
if (site)
|
|
337
|
+
site = new import_mongodb2.ObjectId(site);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
throw new import_node_server_utils2.BadRequestError("Invalid site ID format.");
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
return await collection.findOne({
|
|
343
|
+
name: { $regex: new RegExp(`^${name}$`, "i") },
|
|
344
|
+
...site && { site }
|
|
345
|
+
});
|
|
346
|
+
} catch (error) {
|
|
347
|
+
throw new import_node_server_utils2.BadRequestError("Unable to fetch area by name.");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async function updateArea(_id, value) {
|
|
351
|
+
try {
|
|
352
|
+
_id = new import_mongodb2.ObjectId(_id);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
throw new import_node_server_utils2.BadRequestError("Invalid area ID format.");
|
|
355
|
+
}
|
|
356
|
+
try {
|
|
357
|
+
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
358
|
+
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
359
|
+
if (res.modifiedCount === 0) {
|
|
360
|
+
throw new import_node_server_utils2.InternalServerError("Unable to update cleaning area.");
|
|
361
|
+
}
|
|
362
|
+
delNamespace().then(() => {
|
|
363
|
+
import_node_server_utils2.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
364
|
+
}).catch((err) => {
|
|
365
|
+
import_node_server_utils2.logger.error(
|
|
366
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
367
|
+
err
|
|
368
|
+
);
|
|
369
|
+
});
|
|
370
|
+
return res.modifiedCount;
|
|
371
|
+
} catch (error) {
|
|
372
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
373
|
+
if (isDuplicated) {
|
|
374
|
+
throw new import_node_server_utils2.BadRequestError("Area already exists.");
|
|
375
|
+
}
|
|
376
|
+
throw error;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
async function updateAreaChecklist(_id, value) {
|
|
380
|
+
try {
|
|
381
|
+
_id = new import_mongodb2.ObjectId(_id);
|
|
382
|
+
} catch (error) {
|
|
383
|
+
throw new import_node_server_utils2.BadRequestError("Invalid area ID format.");
|
|
384
|
+
}
|
|
385
|
+
if (value.checklist && Array.isArray(value.checklist)) {
|
|
386
|
+
value.checklist = value.checklist.map((item) => {
|
|
387
|
+
try {
|
|
388
|
+
return {
|
|
389
|
+
...item,
|
|
390
|
+
_id: new import_mongodb2.ObjectId(item._id)
|
|
391
|
+
};
|
|
392
|
+
} catch (error) {
|
|
393
|
+
throw new import_node_server_utils2.BadRequestError(
|
|
394
|
+
`Invalid checklist item ID format: ${item._id}`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
try {
|
|
400
|
+
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
401
|
+
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
402
|
+
if (res.modifiedCount === 0) {
|
|
403
|
+
throw new import_node_server_utils2.InternalServerError("Unable to update cleaning area.");
|
|
404
|
+
}
|
|
405
|
+
delNamespace().then(() => {
|
|
406
|
+
import_node_server_utils2.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
407
|
+
}).catch((err) => {
|
|
408
|
+
import_node_server_utils2.logger.error(
|
|
409
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
410
|
+
err
|
|
411
|
+
);
|
|
412
|
+
});
|
|
413
|
+
return res.modifiedCount;
|
|
414
|
+
} catch (error) {
|
|
415
|
+
throw error;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
async function deleteArea(_id, session) {
|
|
419
|
+
try {
|
|
420
|
+
_id = new import_mongodb2.ObjectId(_id);
|
|
421
|
+
} catch (error) {
|
|
422
|
+
throw new import_node_server_utils2.BadRequestError("Invalid area ID format.");
|
|
423
|
+
}
|
|
424
|
+
try {
|
|
425
|
+
const updateValue = {
|
|
426
|
+
status: "deleted",
|
|
427
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
428
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
429
|
+
};
|
|
430
|
+
const res = await collection.updateOne(
|
|
431
|
+
{ _id },
|
|
432
|
+
{ $set: updateValue },
|
|
433
|
+
{ session }
|
|
434
|
+
);
|
|
435
|
+
if (res.modifiedCount === 0) {
|
|
436
|
+
throw new import_node_server_utils2.InternalServerError("Unable to delete area.");
|
|
437
|
+
}
|
|
438
|
+
delNamespace().then(() => {
|
|
439
|
+
import_node_server_utils2.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
440
|
+
}).catch((err) => {
|
|
441
|
+
import_node_server_utils2.logger.error(
|
|
442
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
443
|
+
err
|
|
444
|
+
);
|
|
445
|
+
});
|
|
446
|
+
return res.modifiedCount;
|
|
447
|
+
} catch (error) {
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
createIndex,
|
|
453
|
+
createTextIndex,
|
|
454
|
+
createUniqueIndex,
|
|
455
|
+
createArea,
|
|
456
|
+
getAreas,
|
|
457
|
+
getAreaById,
|
|
458
|
+
getAreaByName,
|
|
459
|
+
updateArea,
|
|
460
|
+
updateAreaChecklist,
|
|
461
|
+
deleteArea
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// src/services/hygiene-area.service.ts
|
|
466
|
+
var import_node_server_utils3 = require("@iservice365/node-server-utils");
|
|
467
|
+
function useAreaService() {
|
|
468
|
+
const { createArea: _createArea } = useAreaRepository();
|
|
469
|
+
async function uploadByFile({
|
|
470
|
+
dataJson,
|
|
471
|
+
createdBy,
|
|
472
|
+
site
|
|
473
|
+
}) {
|
|
474
|
+
let dataArray;
|
|
475
|
+
try {
|
|
476
|
+
dataArray = JSON.parse(dataJson);
|
|
477
|
+
} catch (error) {
|
|
478
|
+
throw new import_node_server_utils3.BadRequestError("Invalid JSON format for data in excel");
|
|
479
|
+
}
|
|
480
|
+
if (!dataArray || dataArray.length === 0) {
|
|
481
|
+
throw new import_node_server_utils3.NotFoundError("No data found in the uploaded file");
|
|
482
|
+
}
|
|
483
|
+
const session = import_node_server_utils3.useAtlas.getClient()?.startSession();
|
|
484
|
+
const insertedAreaIds = [];
|
|
485
|
+
try {
|
|
486
|
+
session?.startTransaction();
|
|
487
|
+
for (const row of dataArray) {
|
|
488
|
+
if (!row?.AREA_NAME) {
|
|
489
|
+
import_node_server_utils3.logger.warn("Skipping row with missing AREA_NAME:", row);
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
try {
|
|
493
|
+
const insertedId = await _createArea(
|
|
494
|
+
{
|
|
495
|
+
name: String(row.AREA_NAME).trim(),
|
|
496
|
+
site,
|
|
497
|
+
createdBy
|
|
498
|
+
},
|
|
499
|
+
session
|
|
500
|
+
);
|
|
501
|
+
insertedAreaIds.push(insertedId);
|
|
502
|
+
} catch (error) {
|
|
503
|
+
import_node_server_utils3.logger.error(
|
|
504
|
+
`Error creating area "${row.AREA_NAME}":`,
|
|
505
|
+
error.message
|
|
506
|
+
);
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
await session?.commitTransaction();
|
|
511
|
+
import_node_server_utils3.logger.info(`Successfully uploaded ${insertedAreaIds.length} areas`);
|
|
512
|
+
return {
|
|
513
|
+
message: `Successfully uploaded ${insertedAreaIds.length} areas`
|
|
514
|
+
};
|
|
515
|
+
} catch (error) {
|
|
516
|
+
await session?.abortTransaction();
|
|
517
|
+
import_node_server_utils3.logger.error("Error while uploading area information", error);
|
|
518
|
+
throw error;
|
|
519
|
+
} finally {
|
|
520
|
+
session?.endSession();
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
uploadByFile
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// src/controllers/hygiene-area.controller.ts
|
|
529
|
+
var import_node_server_utils4 = require("@iservice365/node-server-utils");
|
|
530
|
+
var import_joi2 = __toESM(require("joi"));
|
|
531
|
+
|
|
532
|
+
// src/utils/convert-excel.util.ts
|
|
533
|
+
var import_stream = require("stream");
|
|
534
|
+
var xlsx = __toESM(require("xlsx"));
|
|
535
|
+
function convertBufferFile(bufferFile) {
|
|
536
|
+
return new Promise((resolve, reject) => {
|
|
537
|
+
const fileStream = import_stream.Readable.from(bufferFile);
|
|
538
|
+
let fileBuffer = Buffer.alloc(0);
|
|
539
|
+
fileStream.on("data", (chunk) => {
|
|
540
|
+
fileBuffer = Buffer.concat([fileBuffer, chunk]);
|
|
541
|
+
});
|
|
542
|
+
fileStream.on("end", () => {
|
|
543
|
+
try {
|
|
544
|
+
const workbook = xlsx.read(fileBuffer, { type: "buffer" });
|
|
545
|
+
const sheetName = workbook.SheetNames[0];
|
|
546
|
+
const sheet = workbook.Sheets[sheetName];
|
|
547
|
+
const jsonData = xlsx.utils.sheet_to_json(sheet);
|
|
548
|
+
resolve(jsonData);
|
|
549
|
+
} catch (error) {
|
|
550
|
+
reject("Error parsing file");
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
fileStream.on("error", (err) => {
|
|
554
|
+
reject("Error Reading File: " + err.message);
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// src/controllers/hygiene-area.controller.ts
|
|
560
|
+
function useAreaController() {
|
|
561
|
+
const {
|
|
562
|
+
createArea: _createArea,
|
|
563
|
+
getAreas: _getAll,
|
|
564
|
+
getAreaById: _getAreaById,
|
|
565
|
+
updateArea: _updateArea,
|
|
566
|
+
updateAreaChecklist: _updateAreaChecklist,
|
|
567
|
+
deleteArea: _deleteById
|
|
568
|
+
} = useAreaRepository();
|
|
569
|
+
const { uploadByFile: _uploadByFile } = useAreaService();
|
|
570
|
+
async function createArea(req, res, next) {
|
|
571
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
572
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
573
|
+
{}
|
|
574
|
+
) : {};
|
|
575
|
+
const createdBy = cookies["user"] || "";
|
|
576
|
+
const payload = { ...req.body, createdBy };
|
|
577
|
+
const { error } = areaSchema.validate(payload);
|
|
578
|
+
if (error) {
|
|
579
|
+
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
580
|
+
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const id = await _createArea(payload);
|
|
585
|
+
res.status(201).json({ message: "Area created successfully.", id });
|
|
586
|
+
return;
|
|
587
|
+
} catch (error2) {
|
|
588
|
+
import_node_server_utils4.logger.log({ level: "error", message: error2.message });
|
|
589
|
+
next(error2);
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
async function getAll(req, res, next) {
|
|
594
|
+
const query = req.query;
|
|
595
|
+
const validation = import_joi2.default.object({
|
|
596
|
+
page: import_joi2.default.number().min(1).optional().allow("", null),
|
|
597
|
+
limit: import_joi2.default.number().min(1).optional().allow("", null),
|
|
598
|
+
search: import_joi2.default.string().optional().allow("", null),
|
|
599
|
+
startDate: import_joi2.default.alternatives().try(import_joi2.default.date(), import_joi2.default.string()).optional().allow("", null),
|
|
600
|
+
endDate: import_joi2.default.alternatives().try(import_joi2.default.date(), import_joi2.default.string()).optional().allow("", null),
|
|
601
|
+
site: import_joi2.default.string().hex().optional().allow("", null)
|
|
602
|
+
});
|
|
603
|
+
const { error } = validation.validate(query);
|
|
604
|
+
if (error) {
|
|
605
|
+
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
609
|
+
const limit = parseInt(req.query.limit) ?? 20;
|
|
610
|
+
const search = req.query.search ?? "";
|
|
611
|
+
const site = req.query.site ?? "";
|
|
612
|
+
const startDate = req.query.startDate ?? "";
|
|
613
|
+
const endDate = req.query.endDate ?? "";
|
|
614
|
+
try {
|
|
615
|
+
const data = await _getAll({
|
|
616
|
+
page,
|
|
617
|
+
limit,
|
|
618
|
+
search,
|
|
619
|
+
site,
|
|
620
|
+
startDate,
|
|
621
|
+
endDate
|
|
622
|
+
});
|
|
623
|
+
res.json(data);
|
|
624
|
+
return;
|
|
625
|
+
} catch (error2) {
|
|
626
|
+
next(error2);
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
async function getAreaById(req, res, next) {
|
|
631
|
+
const validation = import_joi2.default.string().hex().required();
|
|
632
|
+
const _id = req.params.id;
|
|
633
|
+
const { error } = validation.validate(_id);
|
|
634
|
+
if (error) {
|
|
635
|
+
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
636
|
+
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
try {
|
|
640
|
+
const data = await _getAreaById(_id);
|
|
641
|
+
res.json(data);
|
|
642
|
+
return;
|
|
643
|
+
} catch (error2) {
|
|
644
|
+
import_node_server_utils4.logger.log({ level: "error", message: error2.message });
|
|
645
|
+
next(error2);
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
async function updateArea(req, res, next) {
|
|
650
|
+
const payload = { id: req.params.id, ...req.body };
|
|
651
|
+
const schema = import_joi2.default.object({
|
|
652
|
+
id: import_joi2.default.string().hex().required(),
|
|
653
|
+
name: import_joi2.default.string().required()
|
|
654
|
+
});
|
|
655
|
+
const { error } = schema.validate(payload);
|
|
656
|
+
if (error) {
|
|
657
|
+
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
658
|
+
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
try {
|
|
662
|
+
const { id, ...value } = payload;
|
|
663
|
+
await _updateArea(id, value);
|
|
664
|
+
res.json({ message: "Area updated successfully." });
|
|
665
|
+
return;
|
|
666
|
+
} catch (error2) {
|
|
667
|
+
import_node_server_utils4.logger.log({ level: "error", message: error2.message });
|
|
668
|
+
next(error2);
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
async function updateAreaChecklist(req, res, next) {
|
|
673
|
+
const payload = { id: req.params.id, ...req.body };
|
|
674
|
+
const schema = import_joi2.default.object({
|
|
675
|
+
id: import_joi2.default.string().hex().required(),
|
|
676
|
+
checklist: import_joi2.default.array().items(
|
|
677
|
+
import_joi2.default.object({
|
|
678
|
+
_id: import_joi2.default.string().hex().required(),
|
|
679
|
+
name: import_joi2.default.string().required()
|
|
680
|
+
}).required()
|
|
681
|
+
).min(1).unique("_id", { ignoreUndefined: true }).messages({
|
|
682
|
+
"array.unique": "Duplicate checklist items are not allowed"
|
|
683
|
+
})
|
|
684
|
+
});
|
|
685
|
+
const { error } = schema.validate(payload);
|
|
686
|
+
if (error) {
|
|
687
|
+
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
688
|
+
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
try {
|
|
692
|
+
const { id, ...value } = payload;
|
|
693
|
+
await _updateAreaChecklist(id, value);
|
|
694
|
+
res.json({ message: "Area updated successfully." });
|
|
695
|
+
return;
|
|
696
|
+
} catch (error2) {
|
|
697
|
+
import_node_server_utils4.logger.log({ level: "error", message: error2.message });
|
|
698
|
+
next(error2);
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
async function deleteArea(req, res, next) {
|
|
703
|
+
const id = req.params.id;
|
|
704
|
+
const validation = import_joi2.default.object({
|
|
705
|
+
id: import_joi2.default.string().hex().required()
|
|
706
|
+
});
|
|
707
|
+
const { error } = validation.validate({ id });
|
|
708
|
+
if (error) {
|
|
709
|
+
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
710
|
+
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
try {
|
|
714
|
+
await _deleteById(id);
|
|
715
|
+
res.json({ message: "Area deleted successfully." });
|
|
716
|
+
return;
|
|
717
|
+
} catch (error2) {
|
|
718
|
+
import_node_server_utils4.logger.log({ level: "error", message: error2.message });
|
|
719
|
+
next(error2);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
async function uploadByFile(req, res, next) {
|
|
724
|
+
if (!req.file) {
|
|
725
|
+
next(new import_node_server_utils4.BadRequestError("File is required!"));
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
729
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
730
|
+
{}
|
|
731
|
+
) : {};
|
|
732
|
+
const createdBy = cookies["user"] || "";
|
|
733
|
+
const { site } = req.body;
|
|
734
|
+
const schema = import_joi2.default.object({
|
|
735
|
+
site: import_joi2.default.string().hex().optional().allow("", null),
|
|
736
|
+
createdBy: import_joi2.default.string().hex().required()
|
|
737
|
+
});
|
|
738
|
+
const { error } = schema.validate({ site, createdBy });
|
|
739
|
+
if (error) {
|
|
740
|
+
import_node_server_utils4.logger.log({ level: "error", message: error.message });
|
|
741
|
+
next(new import_node_server_utils4.BadRequestError(error.message));
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
try {
|
|
745
|
+
const xlsData = await convertBufferFile(req.file.buffer);
|
|
746
|
+
const dataJson = JSON.stringify(xlsData);
|
|
747
|
+
const result = await _uploadByFile({ dataJson, createdBy, site });
|
|
748
|
+
return res.status(201).json(result);
|
|
749
|
+
} catch (error2) {
|
|
750
|
+
import_node_server_utils4.logger.log({ level: "error", message: error2.message });
|
|
751
|
+
next(error2);
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
return {
|
|
756
|
+
createArea,
|
|
757
|
+
getAll,
|
|
758
|
+
getAreaById,
|
|
759
|
+
updateArea,
|
|
760
|
+
updateAreaChecklist,
|
|
761
|
+
deleteArea,
|
|
762
|
+
uploadByFile
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// src/models/hygiene-toilet-location.model.ts
|
|
767
|
+
var import_node_server_utils5 = require("@iservice365/node-server-utils");
|
|
768
|
+
var import_joi3 = __toESM(require("joi"));
|
|
769
|
+
var import_mongodb3 = require("mongodb");
|
|
770
|
+
var toiletLocationSchema = import_joi3.default.object({
|
|
771
|
+
name: import_joi3.default.string().required(),
|
|
772
|
+
site: import_joi3.default.string().hex().required(),
|
|
773
|
+
createdBy: import_joi3.default.string().hex().required(),
|
|
774
|
+
checklist: import_joi3.default.array().items(
|
|
775
|
+
import_joi3.default.object({
|
|
776
|
+
_id: import_joi3.default.string().hex().required(),
|
|
777
|
+
name: import_joi3.default.string().required()
|
|
778
|
+
})
|
|
779
|
+
).optional(),
|
|
780
|
+
updatedAt: import_joi3.default.date().optional().allow("", null),
|
|
781
|
+
status: import_joi3.default.string().allow("", null).optional()
|
|
782
|
+
});
|
|
783
|
+
function MToiletLocation(value) {
|
|
784
|
+
const { error } = toiletLocationSchema.validate(value);
|
|
785
|
+
if (error) {
|
|
786
|
+
throw new import_node_server_utils5.BadRequestError(error.message);
|
|
787
|
+
}
|
|
788
|
+
if (value.site) {
|
|
789
|
+
try {
|
|
790
|
+
value.site = new import_mongodb3.ObjectId(value.site);
|
|
791
|
+
} catch (error2) {
|
|
792
|
+
throw new import_node_server_utils5.BadRequestError("Invalid site ID format.");
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
if (value.createdBy) {
|
|
796
|
+
try {
|
|
797
|
+
value.createdBy = new import_mongodb3.ObjectId(value.createdBy);
|
|
798
|
+
} catch (error2) {
|
|
799
|
+
throw new import_node_server_utils5.BadRequestError("Invalid createdBy ID format.");
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
if (value.checklist && Array.isArray(value.checklist)) {
|
|
803
|
+
value.checklist = value.checklist.map((item) => {
|
|
804
|
+
try {
|
|
805
|
+
return {
|
|
806
|
+
...item,
|
|
807
|
+
_id: new import_mongodb3.ObjectId(item._id)
|
|
808
|
+
};
|
|
809
|
+
} catch (error2) {
|
|
810
|
+
throw new import_node_server_utils5.BadRequestError(
|
|
811
|
+
`Invalid checklist item ID format: ${item._id}`
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
return {
|
|
817
|
+
name: value.name,
|
|
818
|
+
site: value.site,
|
|
819
|
+
createdBy: value.createdBy,
|
|
820
|
+
checklist: value.checklist,
|
|
821
|
+
status: value.status ?? "",
|
|
822
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
823
|
+
updatedAt: value.updatedAt ?? "",
|
|
824
|
+
deletedAt: value.deletedAt ?? ""
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// src/repositories/hygiene-toilet-location.repository.ts
|
|
829
|
+
var import_mongodb4 = require("mongodb");
|
|
830
|
+
var import_node_server_utils6 = require("@iservice365/node-server-utils");
|
|
831
|
+
function useToiletLocationRepository() {
|
|
832
|
+
const db = import_node_server_utils6.useAtlas.getDb();
|
|
833
|
+
if (!db) {
|
|
834
|
+
throw new import_node_server_utils6.InternalServerError("Unable to connect to server.");
|
|
835
|
+
}
|
|
836
|
+
const namespace_collection = "hygiene-toilet-locations";
|
|
837
|
+
const collection = db.collection(namespace_collection);
|
|
838
|
+
const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils6.useCache)(namespace_collection);
|
|
839
|
+
async function createIndexes() {
|
|
840
|
+
try {
|
|
841
|
+
await collection.createIndexes([
|
|
842
|
+
{ key: { site: 1 } },
|
|
843
|
+
{ key: { name: "text" } }
|
|
844
|
+
]);
|
|
845
|
+
} catch (error) {
|
|
846
|
+
throw new import_node_server_utils6.InternalServerError("Failed to create index on site.");
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
async function createUniqueIndex() {
|
|
850
|
+
try {
|
|
851
|
+
await collection.createIndex(
|
|
852
|
+
{ name: 1, site: 1, deletedAt: 1 },
|
|
853
|
+
{ unique: true }
|
|
854
|
+
);
|
|
855
|
+
} catch (error) {
|
|
856
|
+
throw new import_node_server_utils6.InternalServerError(
|
|
857
|
+
"Failed to create unique index on hygiene area."
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
async function create(value, session) {
|
|
862
|
+
try {
|
|
863
|
+
value = MToiletLocation(value);
|
|
864
|
+
const res = await collection.insertOne(value, { session });
|
|
865
|
+
delNamespace().then(() => {
|
|
866
|
+
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
867
|
+
}).catch((err) => {
|
|
868
|
+
import_node_server_utils6.logger.error(
|
|
869
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
870
|
+
err
|
|
871
|
+
);
|
|
872
|
+
});
|
|
873
|
+
return res.insertedId;
|
|
874
|
+
} catch (error) {
|
|
875
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
876
|
+
if (isDuplicated) {
|
|
877
|
+
throw new import_node_server_utils6.BadRequestError("Toilet location already exists.");
|
|
878
|
+
}
|
|
879
|
+
throw error;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
async function updateToiletLocation(_id, value) {
|
|
883
|
+
try {
|
|
884
|
+
_id = new import_mongodb4.ObjectId(_id);
|
|
885
|
+
} catch (error) {
|
|
886
|
+
throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
|
|
887
|
+
}
|
|
888
|
+
if (value.checklist && Array.isArray(value.checklist)) {
|
|
889
|
+
value.checklist = value.checklist.map((item) => {
|
|
890
|
+
try {
|
|
891
|
+
return {
|
|
892
|
+
...item,
|
|
893
|
+
_id: new import_mongodb4.ObjectId(item._id)
|
|
894
|
+
};
|
|
895
|
+
} catch (error) {
|
|
896
|
+
throw new import_node_server_utils6.BadRequestError(
|
|
897
|
+
`Invalid checklist item ID format: ${item._id}`
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
try {
|
|
903
|
+
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
904
|
+
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
905
|
+
if (res.modifiedCount === 0) {
|
|
906
|
+
throw new import_node_server_utils6.InternalServerError("Unable to update toilet location.");
|
|
907
|
+
}
|
|
908
|
+
delNamespace().then(() => {
|
|
909
|
+
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
910
|
+
}).catch((err) => {
|
|
911
|
+
import_node_server_utils6.logger.error(
|
|
912
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
913
|
+
err
|
|
914
|
+
);
|
|
915
|
+
});
|
|
916
|
+
return res.modifiedCount;
|
|
917
|
+
} catch (error) {
|
|
918
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
919
|
+
if (isDuplicated) {
|
|
920
|
+
throw new import_node_server_utils6.BadRequestError("Toilet location already exists.");
|
|
921
|
+
}
|
|
922
|
+
throw error;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
async function deleteToiletLocation(_id, session) {
|
|
926
|
+
try {
|
|
927
|
+
_id = new import_mongodb4.ObjectId(_id);
|
|
928
|
+
} catch (error) {
|
|
929
|
+
throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
|
|
930
|
+
}
|
|
931
|
+
try {
|
|
932
|
+
const updateValue = {
|
|
933
|
+
status: "deleted",
|
|
934
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
935
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
936
|
+
};
|
|
937
|
+
const res = await collection.updateOne(
|
|
938
|
+
{ _id },
|
|
939
|
+
{ $set: updateValue },
|
|
940
|
+
{ session }
|
|
941
|
+
);
|
|
942
|
+
if (res.modifiedCount === 0) {
|
|
943
|
+
throw new import_node_server_utils6.InternalServerError("Unable to delete toilet location.");
|
|
944
|
+
}
|
|
945
|
+
delNamespace().then(() => {
|
|
946
|
+
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
947
|
+
}).catch((err) => {
|
|
948
|
+
import_node_server_utils6.logger.error(
|
|
949
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
950
|
+
err
|
|
951
|
+
);
|
|
952
|
+
});
|
|
953
|
+
return res.modifiedCount;
|
|
954
|
+
} catch (error) {
|
|
955
|
+
throw error;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
async function getToiletLocations({
|
|
959
|
+
page = 1,
|
|
960
|
+
limit = 10,
|
|
961
|
+
search = "",
|
|
962
|
+
sort = {},
|
|
963
|
+
startDate = "",
|
|
964
|
+
endDate = "",
|
|
965
|
+
site = ""
|
|
966
|
+
}) {
|
|
967
|
+
page = page > 0 ? page - 1 : 0;
|
|
968
|
+
let dateFilter = {};
|
|
969
|
+
try {
|
|
970
|
+
site = new import_mongodb4.ObjectId(site);
|
|
971
|
+
} catch (error) {
|
|
972
|
+
throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
|
|
973
|
+
}
|
|
974
|
+
const query = {
|
|
975
|
+
status: { $ne: "deleted" }
|
|
976
|
+
};
|
|
977
|
+
const cacheOptions = {
|
|
978
|
+
site: site.toString()
|
|
979
|
+
};
|
|
980
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
981
|
+
cacheOptions.sort = JSON.stringify(sort);
|
|
982
|
+
if (search) {
|
|
983
|
+
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
984
|
+
cacheOptions.search = search;
|
|
985
|
+
}
|
|
986
|
+
delNamespace().then(() => {
|
|
987
|
+
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
988
|
+
}).catch((err) => {
|
|
989
|
+
import_node_server_utils6.logger.error(
|
|
990
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
991
|
+
err
|
|
992
|
+
);
|
|
993
|
+
});
|
|
994
|
+
const cacheKey = (0, import_node_server_utils6.makeCacheKey)(namespace_collection, cacheOptions);
|
|
995
|
+
const cachedData = await getCache(cacheKey);
|
|
996
|
+
if (cachedData) {
|
|
997
|
+
import_node_server_utils6.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
998
|
+
return cachedData;
|
|
999
|
+
}
|
|
1000
|
+
if (startDate && endDate) {
|
|
1001
|
+
dateFilter = {
|
|
1002
|
+
createdAt: {
|
|
1003
|
+
$gte: new Date(startDate),
|
|
1004
|
+
$lte: new Date(endDate)
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
} else if (startDate) {
|
|
1008
|
+
dateFilter = { createdAt: { $gte: new Date(startDate) } };
|
|
1009
|
+
} else if (endDate) {
|
|
1010
|
+
dateFilter = { createdAt: { $lte: new Date(endDate) } };
|
|
1011
|
+
}
|
|
1012
|
+
try {
|
|
1013
|
+
const items = await collection.aggregate([
|
|
1014
|
+
{
|
|
1015
|
+
$match: {
|
|
1016
|
+
...dateFilter,
|
|
1017
|
+
...query
|
|
1018
|
+
}
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
$lookup: {
|
|
1022
|
+
from: "sites",
|
|
1023
|
+
localField: "site",
|
|
1024
|
+
foreignField: "_id",
|
|
1025
|
+
pipeline: [{ $project: { name: 1 } }],
|
|
1026
|
+
as: "site"
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
$unwind: {
|
|
1031
|
+
path: "$site",
|
|
1032
|
+
preserveNullAndEmptyArrays: true
|
|
1033
|
+
}
|
|
1034
|
+
},
|
|
1035
|
+
{
|
|
1036
|
+
$lookup: {
|
|
1037
|
+
from: "users",
|
|
1038
|
+
localField: "createdBy",
|
|
1039
|
+
foreignField: "_id",
|
|
1040
|
+
pipeline: [{ $project: { name: 1 } }],
|
|
1041
|
+
as: "createdBy"
|
|
1042
|
+
}
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
$unwind: {
|
|
1046
|
+
path: "$createdBy",
|
|
1047
|
+
preserveNullAndEmptyArrays: true
|
|
1048
|
+
}
|
|
1049
|
+
},
|
|
1050
|
+
{
|
|
1051
|
+
$project: {
|
|
1052
|
+
name: 1,
|
|
1053
|
+
site: "$site._id",
|
|
1054
|
+
siteName: "$site.name",
|
|
1055
|
+
createdByName: "$createdBy.name",
|
|
1056
|
+
checklist: 1,
|
|
1057
|
+
status: 1,
|
|
1058
|
+
createdAt: 1
|
|
1059
|
+
}
|
|
1060
|
+
},
|
|
1061
|
+
{ $sort: { _id: -1 } },
|
|
1062
|
+
{ $skip: page * limit },
|
|
1063
|
+
{ $limit: limit }
|
|
1064
|
+
]).toArray();
|
|
1065
|
+
const length = await collection.countDocuments(query);
|
|
1066
|
+
const data = (0, import_node_server_utils6.paginate)(items, page, limit, length);
|
|
1067
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
1068
|
+
import_node_server_utils6.logger.info(`Cache set for key: ${cacheKey}`);
|
|
1069
|
+
}).catch((err) => {
|
|
1070
|
+
import_node_server_utils6.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
1071
|
+
});
|
|
1072
|
+
return data;
|
|
1073
|
+
} catch (error) {
|
|
1074
|
+
throw error;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
async function getToiletLocationByName(name, site) {
|
|
1078
|
+
try {
|
|
1079
|
+
if (site)
|
|
1080
|
+
site = new import_mongodb4.ObjectId(site);
|
|
1081
|
+
} catch (error) {
|
|
1082
|
+
throw new import_node_server_utils6.BadRequestError("Invalid site ID format.");
|
|
1083
|
+
}
|
|
1084
|
+
try {
|
|
1085
|
+
return await collection.findOne({
|
|
1086
|
+
name: { $regex: new RegExp(`^${name}$`, "i") },
|
|
1087
|
+
...site && { site }
|
|
1088
|
+
});
|
|
1089
|
+
} catch (error) {
|
|
1090
|
+
throw new import_node_server_utils6.BadRequestError("Unable to fetch toilet location by name.");
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
async function updateToiletLocationChecklist(_id, value) {
|
|
1094
|
+
try {
|
|
1095
|
+
_id = new import_mongodb4.ObjectId(_id);
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
|
|
1098
|
+
}
|
|
1099
|
+
if (value.checklist && Array.isArray(value.checklist)) {
|
|
1100
|
+
value.checklist = value.checklist.map((item) => {
|
|
1101
|
+
try {
|
|
1102
|
+
return {
|
|
1103
|
+
...item,
|
|
1104
|
+
_id: new import_mongodb4.ObjectId(item._id)
|
|
1105
|
+
};
|
|
1106
|
+
} catch (error) {
|
|
1107
|
+
throw new import_node_server_utils6.BadRequestError(
|
|
1108
|
+
`Invalid checklist item ID format: ${item._id}`
|
|
1109
|
+
);
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
try {
|
|
1114
|
+
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
1115
|
+
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
1116
|
+
if (res.modifiedCount === 0) {
|
|
1117
|
+
throw new import_node_server_utils6.InternalServerError("Unable to update toilet location.");
|
|
1118
|
+
}
|
|
1119
|
+
delNamespace().then(() => {
|
|
1120
|
+
import_node_server_utils6.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1121
|
+
}).catch((err) => {
|
|
1122
|
+
import_node_server_utils6.logger.error(
|
|
1123
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1124
|
+
err
|
|
1125
|
+
);
|
|
1126
|
+
});
|
|
1127
|
+
return res.modifiedCount;
|
|
1128
|
+
} catch (error) {
|
|
1129
|
+
throw error;
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
async function getToiletLocationById(_id) {
|
|
1133
|
+
try {
|
|
1134
|
+
_id = new import_mongodb4.ObjectId(_id);
|
|
1135
|
+
} catch (error) {
|
|
1136
|
+
throw new import_node_server_utils6.BadRequestError("Invalid area ID format.");
|
|
1137
|
+
}
|
|
1138
|
+
const query = {
|
|
1139
|
+
_id,
|
|
1140
|
+
status: { $ne: "deleted" }
|
|
1141
|
+
};
|
|
1142
|
+
const cacheKey = (0, import_node_server_utils6.makeCacheKey)(namespace_collection, {
|
|
1143
|
+
_id: _id.toString()
|
|
1144
|
+
});
|
|
1145
|
+
const cachedData = await getCache(cacheKey);
|
|
1146
|
+
if (cachedData) {
|
|
1147
|
+
import_node_server_utils6.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
1148
|
+
return cachedData;
|
|
1149
|
+
}
|
|
1150
|
+
try {
|
|
1151
|
+
const data = await collection.aggregate([
|
|
1152
|
+
{ $match: query },
|
|
1153
|
+
{
|
|
1154
|
+
$project: {
|
|
1155
|
+
name: 1,
|
|
1156
|
+
checklist: 1
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
]).toArray();
|
|
1160
|
+
if (!data || !data.length) {
|
|
1161
|
+
throw new import_node_server_utils6.NotFoundError("Area not found.");
|
|
1162
|
+
}
|
|
1163
|
+
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
1164
|
+
import_node_server_utils6.logger.info(`Cache set for key: ${cacheKey}`);
|
|
1165
|
+
}).catch((err) => {
|
|
1166
|
+
import_node_server_utils6.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
1167
|
+
});
|
|
1168
|
+
return data[0];
|
|
1169
|
+
} catch (error) {
|
|
1170
|
+
throw error;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
return {
|
|
1174
|
+
createIndexes,
|
|
1175
|
+
createUniqueIndex,
|
|
1176
|
+
getToiletLocations,
|
|
1177
|
+
create,
|
|
1178
|
+
updateToiletLocation,
|
|
1179
|
+
deleteToiletLocation,
|
|
1180
|
+
getToiletLocationByName,
|
|
1181
|
+
getToiletLocationById,
|
|
1182
|
+
updateToiletLocationChecklist
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// src/services/hygiene-toilet-location.service.ts
|
|
1187
|
+
var import_node_server_utils7 = require("@iservice365/node-server-utils");
|
|
1188
|
+
function useToiletLocationService() {
|
|
1189
|
+
const { create: _createToilet } = useToiletLocationRepository();
|
|
1190
|
+
async function uploadByFile({
|
|
1191
|
+
dataJson,
|
|
1192
|
+
createdBy,
|
|
1193
|
+
site
|
|
1194
|
+
}) {
|
|
1195
|
+
let dataArray;
|
|
1196
|
+
try {
|
|
1197
|
+
dataArray = JSON.parse(dataJson);
|
|
1198
|
+
} catch (error) {
|
|
1199
|
+
throw new import_node_server_utils7.BadRequestError("Invalid JSON format for data in excel");
|
|
1200
|
+
}
|
|
1201
|
+
if (!dataArray || dataArray.length === 0) {
|
|
1202
|
+
throw new import_node_server_utils7.NotFoundError("No data found in the uploaded file");
|
|
1203
|
+
}
|
|
1204
|
+
const session = import_node_server_utils7.useAtlas.getClient()?.startSession();
|
|
1205
|
+
const insertedAreaIds = [];
|
|
1206
|
+
try {
|
|
1207
|
+
session?.startTransaction();
|
|
1208
|
+
for (const row of dataArray) {
|
|
1209
|
+
if (!row?.AREA_NAME) {
|
|
1210
|
+
import_node_server_utils7.logger.warn("Skipping row with missing TOILET NAME:", row);
|
|
1211
|
+
continue;
|
|
1212
|
+
}
|
|
1213
|
+
try {
|
|
1214
|
+
const insertedId = await _createToilet(
|
|
1215
|
+
{
|
|
1216
|
+
name: String(row.TOILET_NAME).trim(),
|
|
1217
|
+
site,
|
|
1218
|
+
createdBy
|
|
1219
|
+
},
|
|
1220
|
+
session
|
|
1221
|
+
);
|
|
1222
|
+
insertedAreaIds.push(insertedId);
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
import_node_server_utils7.logger.error(
|
|
1225
|
+
`Error creating area "${row.AREA_NAME}":`,
|
|
1226
|
+
error.message
|
|
1227
|
+
);
|
|
1228
|
+
continue;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
await session?.commitTransaction();
|
|
1232
|
+
import_node_server_utils7.logger.info(`Successfully uploaded ${insertedAreaIds.length} areas`);
|
|
1233
|
+
return {
|
|
1234
|
+
message: `Successfully uploaded ${insertedAreaIds.length} areas`
|
|
1235
|
+
};
|
|
1236
|
+
} catch (error) {
|
|
1237
|
+
await session?.abortTransaction();
|
|
1238
|
+
import_node_server_utils7.logger.error("Error while uploading area information", error);
|
|
1239
|
+
throw error;
|
|
1240
|
+
} finally {
|
|
1241
|
+
session?.endSession();
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
return {
|
|
1245
|
+
uploadByFile
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
// src/controllers/hygiene-toilet-location.controller.ts
|
|
1250
|
+
var import_joi4 = __toESM(require("joi"));
|
|
1251
|
+
var import_node_server_utils8 = require("@iservice365/node-server-utils");
|
|
1252
|
+
function useToiletLocationController() {
|
|
1253
|
+
const { uploadByFile: _uploadByFile } = useToiletLocationService();
|
|
1254
|
+
const {
|
|
1255
|
+
create: _createToiletLocation,
|
|
1256
|
+
updateToiletLocation: _updateToiletLocation,
|
|
1257
|
+
updateToiletLocationChecklist: _updateToiletLocationChecklist,
|
|
1258
|
+
getToiletLocationById: _getToiletLocationById,
|
|
1259
|
+
getToiletLocations: _getAll,
|
|
1260
|
+
deleteToiletLocation: _deleteById
|
|
1261
|
+
} = useToiletLocationRepository();
|
|
1262
|
+
async function getAll(req, res, next) {
|
|
1263
|
+
const query = req.query;
|
|
1264
|
+
const validation = import_joi4.default.object({
|
|
1265
|
+
page: import_joi4.default.number().min(1).optional().allow("", null),
|
|
1266
|
+
limit: import_joi4.default.number().min(1).optional().allow("", null),
|
|
1267
|
+
search: import_joi4.default.string().optional().allow("", null),
|
|
1268
|
+
site: import_joi4.default.string().hex().optional().allow("", null)
|
|
1269
|
+
});
|
|
1270
|
+
const { error } = validation.validate(query);
|
|
1271
|
+
if (error) {
|
|
1272
|
+
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
1276
|
+
let limit = parseInt(req.query.limit) ?? 20;
|
|
1277
|
+
limit = isNaN(limit) ? 20 : limit;
|
|
1278
|
+
const sort = req.query.sort ? String(req.query.sort).split(",") : "";
|
|
1279
|
+
const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
|
|
1280
|
+
const sortObj = {};
|
|
1281
|
+
if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
|
|
1282
|
+
sort.forEach((field, index) => {
|
|
1283
|
+
sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
const site = req.query.site ?? "";
|
|
1287
|
+
const search = req.query.search ?? "";
|
|
1288
|
+
try {
|
|
1289
|
+
const buildings = await _getAll({
|
|
1290
|
+
page,
|
|
1291
|
+
limit,
|
|
1292
|
+
sort: sortObj,
|
|
1293
|
+
site,
|
|
1294
|
+
search
|
|
1295
|
+
});
|
|
1296
|
+
res.json(buildings);
|
|
1297
|
+
return;
|
|
1298
|
+
} catch (error2) {
|
|
1299
|
+
next(error2);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
async function createToiletLocation(req, res, next) {
|
|
1303
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
1304
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
1305
|
+
{}
|
|
1306
|
+
) : {};
|
|
1307
|
+
const createdBy = cookies["user"] || "";
|
|
1308
|
+
const payload = { ...req.body, createdBy };
|
|
1309
|
+
const schema = import_joi4.default.object({
|
|
1310
|
+
name: import_joi4.default.string().required(),
|
|
1311
|
+
site: import_joi4.default.string().hex().optional().allow("", null),
|
|
1312
|
+
status: import_joi4.default.string().optional().allow("", null),
|
|
1313
|
+
createdBy: import_joi4.default.string().hex().optional().allow("", null)
|
|
1314
|
+
});
|
|
1315
|
+
const { error } = schema.validate(payload);
|
|
1316
|
+
if (error) {
|
|
1317
|
+
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1318
|
+
import_node_server_utils8.logger.info(`Controller: ${error.message}`);
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
try {
|
|
1322
|
+
const result = await _createToiletLocation(payload);
|
|
1323
|
+
res.status(201).json(result);
|
|
1324
|
+
return;
|
|
1325
|
+
} catch (error2) {
|
|
1326
|
+
next(error2);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
async function updateToiletLocation(req, res, next) {
|
|
1330
|
+
const payload = { id: req.params.id, ...req.body };
|
|
1331
|
+
const schema = import_joi4.default.object({
|
|
1332
|
+
id: import_joi4.default.string().hex().required(),
|
|
1333
|
+
name: import_joi4.default.string().required(),
|
|
1334
|
+
checklist: import_joi4.default.array().items(
|
|
1335
|
+
import_joi4.default.object({
|
|
1336
|
+
_id: import_joi4.default.string().hex().required(),
|
|
1337
|
+
name: import_joi4.default.string().required()
|
|
1338
|
+
}).optional()
|
|
1339
|
+
),
|
|
1340
|
+
site: import_joi4.default.string().hex().optional().allow("", null),
|
|
1341
|
+
status: import_joi4.default.string().optional().allow("", null)
|
|
1342
|
+
});
|
|
1343
|
+
const { error } = schema.validate(payload);
|
|
1344
|
+
if (error) {
|
|
1345
|
+
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1346
|
+
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
try {
|
|
1350
|
+
const { id, ...value } = payload;
|
|
1351
|
+
await _updateToiletLocation(id, value);
|
|
1352
|
+
res.status(201).json({ message: "Toilet location updated successfully." });
|
|
1353
|
+
return;
|
|
1354
|
+
} catch (error2) {
|
|
1355
|
+
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
1356
|
+
next(error2);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
async function deleteToiletLocation(req, res, next) {
|
|
1360
|
+
const id = req.params.id;
|
|
1361
|
+
const validation = import_joi4.default.object({
|
|
1362
|
+
id: import_joi4.default.string().hex().required()
|
|
1363
|
+
});
|
|
1364
|
+
const { error } = validation.validate({ id });
|
|
1365
|
+
if (error) {
|
|
1366
|
+
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1367
|
+
return;
|
|
1368
|
+
}
|
|
1369
|
+
try {
|
|
1370
|
+
const message = await _deleteById(id);
|
|
1371
|
+
res.json(message);
|
|
1372
|
+
return;
|
|
1373
|
+
} catch (error2) {
|
|
1374
|
+
next(error2);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
async function updateToiletLocationChecklist(req, res, next) {
|
|
1378
|
+
const payload = { id: req.params.id, ...req.body };
|
|
1379
|
+
const schema = import_joi4.default.object({
|
|
1380
|
+
id: import_joi4.default.string().hex().required(),
|
|
1381
|
+
checklist: import_joi4.default.array().items(
|
|
1382
|
+
import_joi4.default.object({
|
|
1383
|
+
_id: import_joi4.default.string().hex().required(),
|
|
1384
|
+
name: import_joi4.default.string().required()
|
|
1385
|
+
}).required()
|
|
1386
|
+
).min(1).unique("_id", { ignoreUndefined: true }).messages({
|
|
1387
|
+
"array.unique": "Duplicate checklist items are not allowed"
|
|
1388
|
+
})
|
|
1389
|
+
});
|
|
1390
|
+
const { error } = schema.validate(payload);
|
|
1391
|
+
if (error) {
|
|
1392
|
+
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1393
|
+
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
try {
|
|
1397
|
+
const { id, ...value } = payload;
|
|
1398
|
+
await _updateToiletLocationChecklist(id, value);
|
|
1399
|
+
res.json({ message: "Toilet location updated successfully." });
|
|
1400
|
+
return;
|
|
1401
|
+
} catch (error2) {
|
|
1402
|
+
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
1403
|
+
next(error2);
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
async function getToiletLocationById(req, res, next) {
|
|
1408
|
+
const validation = import_joi4.default.string().hex().required();
|
|
1409
|
+
const _id = req.params.id;
|
|
1410
|
+
const { error } = validation.validate(_id);
|
|
1411
|
+
if (error) {
|
|
1412
|
+
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1413
|
+
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1414
|
+
return;
|
|
1415
|
+
}
|
|
1416
|
+
try {
|
|
1417
|
+
const data = await _getToiletLocationById(_id);
|
|
1418
|
+
res.json(data);
|
|
1419
|
+
return;
|
|
1420
|
+
} catch (error2) {
|
|
1421
|
+
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
1422
|
+
next(error2);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
async function uploadByFile(req, res, next) {
|
|
1427
|
+
if (!req.file) {
|
|
1428
|
+
next(new import_node_server_utils8.BadRequestError("File is required!"));
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
1432
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
1433
|
+
{}
|
|
1434
|
+
) : {};
|
|
1435
|
+
const createdBy = cookies["user"] || "";
|
|
1436
|
+
const { site } = req.body;
|
|
1437
|
+
const schema = import_joi4.default.object({
|
|
1438
|
+
site: import_joi4.default.string().hex().optional().allow("", null),
|
|
1439
|
+
createdBy: import_joi4.default.string().hex().required()
|
|
1440
|
+
});
|
|
1441
|
+
const { error } = schema.validate({ site, createdBy });
|
|
1442
|
+
if (error) {
|
|
1443
|
+
import_node_server_utils8.logger.log({ level: "error", message: error.message });
|
|
1444
|
+
next(new import_node_server_utils8.BadRequestError(error.message));
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
try {
|
|
1448
|
+
const xlsData = await convertBufferFile(req.file.buffer);
|
|
1449
|
+
const dataJson = JSON.stringify(xlsData);
|
|
1450
|
+
const result = await _uploadByFile({ dataJson, createdBy, site });
|
|
1451
|
+
return res.status(201).json(result);
|
|
1452
|
+
} catch (error2) {
|
|
1453
|
+
import_node_server_utils8.logger.log({ level: "error", message: error2.message });
|
|
1454
|
+
next(error2);
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
return {
|
|
1459
|
+
getAll,
|
|
1460
|
+
createToiletLocation,
|
|
1461
|
+
updateToiletLocation,
|
|
1462
|
+
deleteToiletLocation,
|
|
1463
|
+
updateToiletLocationChecklist,
|
|
1464
|
+
getToiletLocationById,
|
|
1465
|
+
uploadByFile
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
// src/models/hygiene-parent-checklist.model.ts
|
|
1470
|
+
var import_node_server_utils9 = require("@iservice365/node-server-utils");
|
|
1471
|
+
var import_joi5 = __toESM(require("joi"));
|
|
1472
|
+
var parentChecklistSchema = import_joi5.default.object({
|
|
1473
|
+
date: import_joi5.default.date().required(),
|
|
1474
|
+
status: import_joi5.default.array().items(
|
|
1475
|
+
import_joi5.default.object({
|
|
1476
|
+
site: import_joi5.default.string().hex().required(),
|
|
1477
|
+
status: import_joi5.default.string().required(),
|
|
1478
|
+
completedAt: import_joi5.default.date().required(),
|
|
1479
|
+
type: import_joi5.default.string().required()
|
|
1480
|
+
})
|
|
1481
|
+
).optional(),
|
|
1482
|
+
updatedAt: import_joi5.default.date().optional().allow("", null)
|
|
1483
|
+
});
|
|
1484
|
+
function MParentChecklist(value) {
|
|
1485
|
+
const { error } = parentChecklistSchema.validate(value);
|
|
1486
|
+
if (error) {
|
|
1487
|
+
throw new import_node_server_utils9.BadRequestError(error.message);
|
|
1488
|
+
}
|
|
1489
|
+
return {
|
|
1490
|
+
date: value.date,
|
|
1491
|
+
status: value.status,
|
|
1492
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1493
|
+
updatedAt: value.updatedAt ?? "",
|
|
1494
|
+
deletedAt: value.deletedAt ?? ""
|
|
1495
|
+
};
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
// src/repositories/hygiene-parent-checklist.repository.ts
|
|
1499
|
+
var import_node_server_utils10 = require("@iservice365/node-server-utils");
|
|
1500
|
+
function useParentChecklistRepo() {
|
|
1501
|
+
const db = import_node_server_utils10.useAtlas.getDb();
|
|
1502
|
+
if (!db) {
|
|
1503
|
+
throw new import_node_server_utils10.InternalServerError("Unable to connect to server.");
|
|
1504
|
+
}
|
|
1505
|
+
const namespace_collection = "hygiene-parent-checklist";
|
|
1506
|
+
const collection = db.collection(namespace_collection);
|
|
1507
|
+
const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils10.useCache)(namespace_collection);
|
|
1508
|
+
async function createIndexes() {
|
|
1509
|
+
try {
|
|
1510
|
+
await collection.createIndexes([
|
|
1511
|
+
{ key: { date: "text" } }
|
|
1512
|
+
]);
|
|
1513
|
+
} catch (error) {
|
|
1514
|
+
throw new import_node_server_utils10.InternalServerError("Failed to create index on site.");
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
async function create(value, session) {
|
|
1518
|
+
try {
|
|
1519
|
+
const currentDate = /* @__PURE__ */ new Date();
|
|
1520
|
+
const startOfDay = new Date(currentDate);
|
|
1521
|
+
startOfDay.setDate(currentDate.getDate());
|
|
1522
|
+
startOfDay.setUTCHours(0, 0, 0, 0);
|
|
1523
|
+
const endOfDay = new Date(currentDate);
|
|
1524
|
+
endOfDay.setDate(currentDate.getDate());
|
|
1525
|
+
endOfDay.setUTCHours(23, 59, 59, 999);
|
|
1526
|
+
const checklistRecord = await collection.findOne({
|
|
1527
|
+
date: {
|
|
1528
|
+
$gte: startOfDay,
|
|
1529
|
+
$lte: endOfDay
|
|
1530
|
+
}
|
|
1531
|
+
});
|
|
1532
|
+
delNamespace().then(() => {
|
|
1533
|
+
import_node_server_utils10.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1534
|
+
}).catch((err) => {
|
|
1535
|
+
import_node_server_utils10.logger.error(
|
|
1536
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1537
|
+
err
|
|
1538
|
+
);
|
|
1539
|
+
});
|
|
1540
|
+
if (!checklistRecord) {
|
|
1541
|
+
value = MParentChecklist(value);
|
|
1542
|
+
const res = await collection.insertOne(value, { session });
|
|
1543
|
+
return res.insertedId;
|
|
1544
|
+
}
|
|
1545
|
+
return checklistRecord;
|
|
1546
|
+
} catch (error) {
|
|
1547
|
+
throw error;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
async function get({
|
|
1551
|
+
page = 1,
|
|
1552
|
+
limit = 10,
|
|
1553
|
+
search = "",
|
|
1554
|
+
sort = {},
|
|
1555
|
+
startDate = "",
|
|
1556
|
+
endDate = ""
|
|
1557
|
+
}) {
|
|
1558
|
+
page = page > 0 ? page - 1 : 0;
|
|
1559
|
+
let dateFilter = {};
|
|
1560
|
+
const query = {
|
|
1561
|
+
createdAt: {
|
|
1562
|
+
createdAt: {
|
|
1563
|
+
$gte: new Date(startDate),
|
|
1564
|
+
$lte: new Date(endDate)
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
};
|
|
1568
|
+
const cacheOptions = {
|
|
1569
|
+
createdAt: {
|
|
1570
|
+
createdAt: {
|
|
1571
|
+
$gte: new Date(startDate),
|
|
1572
|
+
$lte: new Date(endDate)
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
1577
|
+
cacheOptions.sort = JSON.stringify(sort);
|
|
1578
|
+
if (search) {
|
|
1579
|
+
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
1580
|
+
cacheOptions.search = search;
|
|
1581
|
+
}
|
|
1582
|
+
delNamespace().then(() => {
|
|
1583
|
+
import_node_server_utils10.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1584
|
+
}).catch((err) => {
|
|
1585
|
+
import_node_server_utils10.logger.error(
|
|
1586
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1587
|
+
err
|
|
1588
|
+
);
|
|
1589
|
+
});
|
|
1590
|
+
const cacheKey = (0, import_node_server_utils10.makeCacheKey)(namespace_collection, cacheOptions);
|
|
1591
|
+
const cachedData = await getCache(cacheKey);
|
|
1592
|
+
if (cachedData) {
|
|
1593
|
+
import_node_server_utils10.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
1594
|
+
return cachedData;
|
|
1595
|
+
}
|
|
1596
|
+
if (startDate && endDate) {
|
|
1597
|
+
dateFilter = {
|
|
1598
|
+
createdAt: {
|
|
1599
|
+
$gte: new Date(startDate),
|
|
1600
|
+
$lte: new Date(endDate)
|
|
1601
|
+
}
|
|
1602
|
+
};
|
|
1603
|
+
} else if (startDate) {
|
|
1604
|
+
dateFilter = { createdAt: { $gte: new Date(startDate) } };
|
|
1605
|
+
} else if (endDate) {
|
|
1606
|
+
dateFilter = { createdAt: { $lte: new Date(endDate) } };
|
|
1607
|
+
}
|
|
1608
|
+
try {
|
|
1609
|
+
const items = await collection.aggregate([
|
|
1610
|
+
{
|
|
1611
|
+
$match: {
|
|
1612
|
+
...dateFilter
|
|
1613
|
+
}
|
|
1614
|
+
},
|
|
1615
|
+
{
|
|
1616
|
+
$facet: {
|
|
1617
|
+
totalCount: [{ $count: "count" }],
|
|
1618
|
+
items: [
|
|
1619
|
+
{ $sort: { createdAt: -1 } },
|
|
1620
|
+
{ $skip: page * limit },
|
|
1621
|
+
{ $limit: limit }
|
|
1622
|
+
]
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
]).toArray();
|
|
1626
|
+
const length = await collection.countDocuments(dateFilter);
|
|
1627
|
+
const data = (0, import_node_server_utils10.paginate)(items, page, limit, length);
|
|
1628
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
1629
|
+
import_node_server_utils10.logger.info(`Cache set for key: ${cacheKey}`);
|
|
1630
|
+
}).catch((err) => {
|
|
1631
|
+
import_node_server_utils10.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
1632
|
+
});
|
|
1633
|
+
return data;
|
|
1634
|
+
} catch (error) {
|
|
1635
|
+
throw error;
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
return {
|
|
1639
|
+
createIndexes,
|
|
1640
|
+
create,
|
|
1641
|
+
get
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
// src/controllers/hygiene-parent-checklist.controller.ts
|
|
1646
|
+
var import_node_server_utils11 = require("@iservice365/node-server-utils");
|
|
1647
|
+
var import_joi6 = __toESM(require("joi"));
|
|
1648
|
+
function useParentCheckilstController() {
|
|
1649
|
+
const {
|
|
1650
|
+
get: _getAll,
|
|
1651
|
+
create: _create
|
|
1652
|
+
} = useParentChecklistRepo();
|
|
1653
|
+
async function getAll(req, res, next) {
|
|
1654
|
+
const query = req.query;
|
|
1655
|
+
const validation = import_joi6.default.object({
|
|
1656
|
+
page: import_joi6.default.number().min(1).optional().allow("", null),
|
|
1657
|
+
limit: import_joi6.default.number().min(1).optional().allow("", null)
|
|
1658
|
+
});
|
|
1659
|
+
const { error } = validation.validate(query);
|
|
1660
|
+
if (error) {
|
|
1661
|
+
next(new import_node_server_utils11.BadRequestError(error.message));
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
1665
|
+
let limit = parseInt(req.query.limit) ?? 20;
|
|
1666
|
+
limit = isNaN(limit) ? 20 : limit;
|
|
1667
|
+
const sort = req.query.sort ? String(req.query.sort).split(",") : "";
|
|
1668
|
+
const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
|
|
1669
|
+
const sortObj = {};
|
|
1670
|
+
if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
|
|
1671
|
+
sort.forEach((field, index) => {
|
|
1672
|
+
sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
const site = req.query.site ?? "";
|
|
1676
|
+
const search = req.query.search ?? "";
|
|
1677
|
+
try {
|
|
1678
|
+
const buildings = await _getAll({
|
|
1679
|
+
page,
|
|
1680
|
+
limit,
|
|
1681
|
+
sort: sortObj,
|
|
1682
|
+
site,
|
|
1683
|
+
search
|
|
1684
|
+
});
|
|
1685
|
+
res.json(buildings);
|
|
1686
|
+
return;
|
|
1687
|
+
} catch (error2) {
|
|
1688
|
+
next(error2);
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
async function create(req, res, next) {
|
|
1692
|
+
const value = req.body;
|
|
1693
|
+
const schema = import_joi6.default.object({
|
|
1694
|
+
date: import_joi6.default.string().required()
|
|
1695
|
+
});
|
|
1696
|
+
const { error } = schema.validate(value);
|
|
1697
|
+
if (error) {
|
|
1698
|
+
next(new import_node_server_utils11.BadRequestError(error.message));
|
|
1699
|
+
import_node_server_utils11.logger.info(`Controller: ${error.message}`);
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1702
|
+
try {
|
|
1703
|
+
const result = await _create(value);
|
|
1704
|
+
res.status(201).json(result);
|
|
1705
|
+
return;
|
|
1706
|
+
} catch (error2) {
|
|
1707
|
+
next(error2);
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
return {
|
|
1711
|
+
getAll,
|
|
1712
|
+
create
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
// src/models/hygiene-unit.model.ts
|
|
1717
|
+
var import_node_server_utils12 = require("@iservice365/node-server-utils");
|
|
1718
|
+
var import_joi7 = __toESM(require("joi"));
|
|
1719
|
+
var import_mongodb5 = require("mongodb");
|
|
1720
|
+
var unitSchema = import_joi7.default.object({
|
|
1721
|
+
name: import_joi7.default.string().required(),
|
|
1722
|
+
site: import_joi7.default.string().hex().required(),
|
|
1723
|
+
createdBy: import_joi7.default.string().hex().required()
|
|
1724
|
+
});
|
|
1725
|
+
function MUnit(value) {
|
|
1726
|
+
const { error } = unitSchema.validate(value);
|
|
1727
|
+
if (error) {
|
|
1728
|
+
import_node_server_utils12.logger.info(`Hygiene Unit Model: ${error.message}`);
|
|
1729
|
+
throw new import_node_server_utils12.BadRequestError(error.message);
|
|
1730
|
+
}
|
|
1731
|
+
if (value.site) {
|
|
1732
|
+
try {
|
|
1733
|
+
value.site = new import_mongodb5.ObjectId(value.site);
|
|
1734
|
+
} catch (error2) {
|
|
1735
|
+
throw new import_node_server_utils12.BadRequestError("Invalid site ID format.");
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
if (value.createdBy) {
|
|
1739
|
+
try {
|
|
1740
|
+
value.createdBy = new import_mongodb5.ObjectId(value.createdBy);
|
|
1741
|
+
} catch (error2) {
|
|
1742
|
+
throw new import_node_server_utils12.BadRequestError("Invalid createdBy ID format.");
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
return {
|
|
1746
|
+
name: value.name,
|
|
1747
|
+
createdBy: value.createdBy,
|
|
1748
|
+
site: value.site,
|
|
1749
|
+
status: "active",
|
|
1750
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1751
|
+
updatedAt: value.updatedAt ?? "",
|
|
1752
|
+
deletedAt: value.deletedAt ?? ""
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
// src/services/hygiene-unit.service.ts
|
|
1757
|
+
var import_node_server_utils14 = require("@iservice365/node-server-utils");
|
|
1758
|
+
|
|
1759
|
+
// src/repositories/hygiene-unit.repository.ts
|
|
1760
|
+
var import_mongodb6 = require("mongodb");
|
|
1761
|
+
var import_node_server_utils13 = require("@iservice365/node-server-utils");
|
|
1762
|
+
function useUnitRepository() {
|
|
1763
|
+
const db = import_node_server_utils13.useAtlas.getDb();
|
|
1764
|
+
if (!db) {
|
|
1765
|
+
throw new import_node_server_utils13.InternalServerError("Unable to connect to server.");
|
|
1766
|
+
}
|
|
1767
|
+
const namespace_collection = "hygiene-units";
|
|
1768
|
+
const collection = db.collection(namespace_collection);
|
|
1769
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils13.useCache)(namespace_collection);
|
|
1770
|
+
async function createIndex() {
|
|
1771
|
+
try {
|
|
1772
|
+
await collection.createIndexes([
|
|
1773
|
+
{ key: { site: 1 } },
|
|
1774
|
+
{ key: { createdBy: 1 } },
|
|
1775
|
+
{ key: { status: 1 } }
|
|
1776
|
+
]);
|
|
1777
|
+
} catch (error) {
|
|
1778
|
+
throw new import_node_server_utils13.InternalServerError("Failed to create index on hygiene unit.");
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
async function createTextIndex() {
|
|
1782
|
+
try {
|
|
1783
|
+
await collection.createIndex({ name: "text" });
|
|
1784
|
+
} catch (error) {
|
|
1785
|
+
throw new import_node_server_utils13.InternalServerError(
|
|
1786
|
+
"Failed to create text index on hygiene unit."
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
async function createUniqueIndex() {
|
|
1791
|
+
try {
|
|
1792
|
+
await collection.createIndex(
|
|
1793
|
+
{ name: 1, site: 1, deletedAt: 1 },
|
|
1794
|
+
{ unique: true }
|
|
1795
|
+
);
|
|
1796
|
+
} catch (error) {
|
|
1797
|
+
throw new import_node_server_utils13.InternalServerError(
|
|
1798
|
+
"Failed to create unique index on hygiene unit."
|
|
1799
|
+
);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
async function createUnit(value, session) {
|
|
1803
|
+
try {
|
|
1804
|
+
value = MUnit(value);
|
|
1805
|
+
const res = await collection.insertOne(value, { session });
|
|
1806
|
+
delNamespace().then(() => {
|
|
1807
|
+
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1808
|
+
}).catch((err) => {
|
|
1809
|
+
import_node_server_utils13.logger.error(
|
|
1810
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1811
|
+
err
|
|
1812
|
+
);
|
|
1813
|
+
});
|
|
1814
|
+
return res.insertedId;
|
|
1815
|
+
} catch (error) {
|
|
1816
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
1817
|
+
if (isDuplicated) {
|
|
1818
|
+
throw new import_node_server_utils13.BadRequestError("Unit already exists.");
|
|
1819
|
+
}
|
|
1820
|
+
throw error;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
async function getUnits({
|
|
1824
|
+
page = 1,
|
|
1825
|
+
limit = 10,
|
|
1826
|
+
search = "",
|
|
1827
|
+
startDate = "",
|
|
1828
|
+
endDate = "",
|
|
1829
|
+
site = ""
|
|
1830
|
+
}) {
|
|
1831
|
+
page = page > 0 ? page - 1 : 0;
|
|
1832
|
+
try {
|
|
1833
|
+
site = new import_mongodb6.ObjectId(site);
|
|
1834
|
+
} catch (error) {
|
|
1835
|
+
throw new import_node_server_utils13.BadRequestError("Invalid site ID format.");
|
|
1836
|
+
}
|
|
1837
|
+
const query = {
|
|
1838
|
+
status: { $ne: "deleted" },
|
|
1839
|
+
site
|
|
1840
|
+
};
|
|
1841
|
+
const cacheOptions = {
|
|
1842
|
+
page,
|
|
1843
|
+
limit,
|
|
1844
|
+
site: site.toString()
|
|
1845
|
+
};
|
|
1846
|
+
if (search) {
|
|
1847
|
+
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
1848
|
+
cacheOptions.search = search;
|
|
1849
|
+
}
|
|
1850
|
+
if (startDate && endDate) {
|
|
1851
|
+
query.createdAt = {
|
|
1852
|
+
$gte: new Date(startDate),
|
|
1853
|
+
$lte: new Date(endDate)
|
|
1854
|
+
};
|
|
1855
|
+
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
1856
|
+
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
1857
|
+
} else if (startDate) {
|
|
1858
|
+
query.createdAt = { $gte: new Date(startDate) };
|
|
1859
|
+
cacheOptions.startDate = new Date(startDate).toISOString().split("T")[0];
|
|
1860
|
+
} else if (endDate) {
|
|
1861
|
+
query.createdAt = { $lte: new Date(endDate) };
|
|
1862
|
+
cacheOptions.endDate = new Date(endDate).toISOString().split("T")[0];
|
|
1863
|
+
}
|
|
1864
|
+
const cacheKey = (0, import_node_server_utils13.makeCacheKey)(namespace_collection, cacheOptions);
|
|
1865
|
+
const cachedData = await getCache(cacheKey);
|
|
1866
|
+
if (cachedData) {
|
|
1867
|
+
import_node_server_utils13.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
1868
|
+
return cachedData;
|
|
1869
|
+
}
|
|
1870
|
+
try {
|
|
1871
|
+
const items = await collection.aggregate([
|
|
1872
|
+
{ $match: query },
|
|
1873
|
+
{
|
|
1874
|
+
$lookup: {
|
|
1875
|
+
from: "sites",
|
|
1876
|
+
localField: "site",
|
|
1877
|
+
foreignField: "_id",
|
|
1878
|
+
pipeline: [{ $project: { name: 1 } }],
|
|
1879
|
+
as: "site"
|
|
1880
|
+
}
|
|
1881
|
+
},
|
|
1882
|
+
{
|
|
1883
|
+
$unwind: {
|
|
1884
|
+
path: "$site",
|
|
1885
|
+
preserveNullAndEmptyArrays: true
|
|
1886
|
+
}
|
|
1887
|
+
},
|
|
1888
|
+
{
|
|
1889
|
+
$lookup: {
|
|
1890
|
+
from: "users",
|
|
1891
|
+
localField: "createdBy",
|
|
1892
|
+
foreignField: "_id",
|
|
1893
|
+
pipeline: [{ $project: { name: 1 } }],
|
|
1894
|
+
as: "createdBy"
|
|
1895
|
+
}
|
|
1896
|
+
},
|
|
1897
|
+
{
|
|
1898
|
+
$unwind: {
|
|
1899
|
+
path: "$createdBy",
|
|
1900
|
+
preserveNullAndEmptyArrays: true
|
|
1901
|
+
}
|
|
1902
|
+
},
|
|
1903
|
+
{
|
|
1904
|
+
$project: {
|
|
1905
|
+
name: 1,
|
|
1906
|
+
site: "$site._id",
|
|
1907
|
+
siteName: "$site.name",
|
|
1908
|
+
createdByName: "$createdBy.name",
|
|
1909
|
+
checklist: 1,
|
|
1910
|
+
status: 1,
|
|
1911
|
+
createdAt: 1
|
|
1912
|
+
}
|
|
1913
|
+
},
|
|
1914
|
+
{ $sort: { _id: -1 } },
|
|
1915
|
+
{ $skip: page * limit },
|
|
1916
|
+
{ $limit: limit }
|
|
1917
|
+
]).toArray();
|
|
1918
|
+
const length = await collection.countDocuments(query);
|
|
1919
|
+
const data = (0, import_node_server_utils13.paginate)(items, page, limit, length);
|
|
1920
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
1921
|
+
import_node_server_utils13.logger.info(`Cache set for key: ${cacheKey}`);
|
|
1922
|
+
}).catch((err) => {
|
|
1923
|
+
import_node_server_utils13.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
1924
|
+
});
|
|
1925
|
+
return data;
|
|
1926
|
+
} catch (error) {
|
|
1927
|
+
throw error;
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
async function getUnitByName(name, site) {
|
|
1931
|
+
try {
|
|
1932
|
+
if (site)
|
|
1933
|
+
site = new import_mongodb6.ObjectId(site);
|
|
1934
|
+
} catch (error) {
|
|
1935
|
+
throw new import_node_server_utils13.BadRequestError("Invalid site ID format.");
|
|
1936
|
+
}
|
|
1937
|
+
try {
|
|
1938
|
+
return await collection.findOne({
|
|
1939
|
+
name: { $regex: new RegExp(`^${name}$`, "i") },
|
|
1940
|
+
...site && { site }
|
|
1941
|
+
});
|
|
1942
|
+
} catch (error) {
|
|
1943
|
+
throw new import_node_server_utils13.BadRequestError("Unable to fetch unit by name.");
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
async function getUnitById(id, site) {
|
|
1947
|
+
try {
|
|
1948
|
+
id = typeof id === "string" ? new import_mongodb6.ObjectId(id) : id;
|
|
1949
|
+
} catch (error) {
|
|
1950
|
+
throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
|
|
1951
|
+
}
|
|
1952
|
+
try {
|
|
1953
|
+
if (site)
|
|
1954
|
+
site = new import_mongodb6.ObjectId(site);
|
|
1955
|
+
} catch (error) {
|
|
1956
|
+
throw new import_node_server_utils13.BadRequestError(
|
|
1957
|
+
"Unable to fetch unit by ID, Invalid site ID format."
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
try {
|
|
1961
|
+
return await collection.findOne({ _id: id, ...site && { site } });
|
|
1962
|
+
} catch (error) {
|
|
1963
|
+
throw new import_node_server_utils13.BadRequestError("Unable to fetch unit by id.");
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
async function updateUnit(_id, value) {
|
|
1967
|
+
try {
|
|
1968
|
+
_id = new import_mongodb6.ObjectId(_id);
|
|
1969
|
+
} catch (error) {
|
|
1970
|
+
throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
|
|
1971
|
+
}
|
|
1972
|
+
try {
|
|
1973
|
+
const updateValue = { ...value, updatedAt: /* @__PURE__ */ new Date() };
|
|
1974
|
+
const res = await collection.updateOne({ _id }, { $set: updateValue });
|
|
1975
|
+
if (res.modifiedCount === 0) {
|
|
1976
|
+
throw new import_node_server_utils13.InternalServerError("Unable to update cleaning unit.");
|
|
1977
|
+
}
|
|
1978
|
+
delNamespace().then(() => {
|
|
1979
|
+
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
1980
|
+
}).catch((err) => {
|
|
1981
|
+
import_node_server_utils13.logger.error(
|
|
1982
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
1983
|
+
err
|
|
1984
|
+
);
|
|
1985
|
+
});
|
|
1986
|
+
return res.modifiedCount;
|
|
1987
|
+
} catch (error) {
|
|
1988
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
1989
|
+
if (isDuplicated) {
|
|
1990
|
+
throw new import_node_server_utils13.BadRequestError("Area already exists.");
|
|
1991
|
+
}
|
|
1992
|
+
throw error;
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
async function deleteUnit(_id, session) {
|
|
1996
|
+
try {
|
|
1997
|
+
_id = new import_mongodb6.ObjectId(_id);
|
|
1998
|
+
} catch (error) {
|
|
1999
|
+
throw new import_node_server_utils13.BadRequestError("Invalid unit ID format.");
|
|
2000
|
+
}
|
|
2001
|
+
try {
|
|
2002
|
+
const updateValue = {
|
|
2003
|
+
status: "deleted",
|
|
2004
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
2005
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
2006
|
+
};
|
|
2007
|
+
const res = await collection.updateOne(
|
|
2008
|
+
{ _id },
|
|
2009
|
+
{ $set: updateValue },
|
|
2010
|
+
{ session }
|
|
2011
|
+
);
|
|
2012
|
+
if (res.modifiedCount === 0) {
|
|
2013
|
+
throw new import_node_server_utils13.InternalServerError("Unable to delete unit.");
|
|
2014
|
+
}
|
|
2015
|
+
delNamespace().then(() => {
|
|
2016
|
+
import_node_server_utils13.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2017
|
+
}).catch((err) => {
|
|
2018
|
+
import_node_server_utils13.logger.error(
|
|
2019
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2020
|
+
err
|
|
2021
|
+
);
|
|
2022
|
+
});
|
|
2023
|
+
return res.modifiedCount;
|
|
2024
|
+
} catch (error) {
|
|
2025
|
+
throw error;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
return {
|
|
2029
|
+
createIndex,
|
|
2030
|
+
createTextIndex,
|
|
2031
|
+
createUniqueIndex,
|
|
2032
|
+
createUnit,
|
|
2033
|
+
getUnits,
|
|
2034
|
+
getUnitByName,
|
|
2035
|
+
getUnitById,
|
|
2036
|
+
updateUnit,
|
|
2037
|
+
deleteUnit
|
|
2038
|
+
};
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
// src/services/hygiene-unit.service.ts
|
|
2042
|
+
function useUnitService() {
|
|
2043
|
+
const { createUnit: _createUnit } = useUnitRepository();
|
|
2044
|
+
async function uploadByFile({
|
|
2045
|
+
dataJson,
|
|
2046
|
+
createdBy,
|
|
2047
|
+
site
|
|
2048
|
+
}) {
|
|
2049
|
+
let dataArray;
|
|
2050
|
+
try {
|
|
2051
|
+
dataArray = JSON.parse(dataJson);
|
|
2052
|
+
} catch (error) {
|
|
2053
|
+
throw new import_node_server_utils14.BadRequestError("Invalid JSON format for data in excel");
|
|
2054
|
+
}
|
|
2055
|
+
if (!dataArray || dataArray.length === 0) {
|
|
2056
|
+
throw new import_node_server_utils14.NotFoundError("No data found in the uploaded file");
|
|
2057
|
+
}
|
|
2058
|
+
const session = import_node_server_utils14.useAtlas.getClient()?.startSession();
|
|
2059
|
+
const insertedUnitIds = [];
|
|
2060
|
+
try {
|
|
2061
|
+
session?.startTransaction();
|
|
2062
|
+
for (const row of dataArray) {
|
|
2063
|
+
if (!row?.UNIT_NAME) {
|
|
2064
|
+
import_node_server_utils14.logger.warn("Skipping row with missing UNIT_NAME:", row);
|
|
2065
|
+
continue;
|
|
2066
|
+
}
|
|
2067
|
+
try {
|
|
2068
|
+
const insertedId = await _createUnit(
|
|
2069
|
+
{
|
|
2070
|
+
name: String(row.UNIT_NAME).trim(),
|
|
2071
|
+
site,
|
|
2072
|
+
createdBy
|
|
2073
|
+
},
|
|
2074
|
+
session
|
|
2075
|
+
);
|
|
2076
|
+
insertedUnitIds.push(insertedId);
|
|
2077
|
+
} catch (error) {
|
|
2078
|
+
import_node_server_utils14.logger.error(
|
|
2079
|
+
`Error creating unit "${row.UNIT_NAME}":`,
|
|
2080
|
+
error.message
|
|
2081
|
+
);
|
|
2082
|
+
continue;
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
await session?.commitTransaction();
|
|
2086
|
+
import_node_server_utils14.logger.info(`Successfully uploaded ${insertedUnitIds.length} units`);
|
|
2087
|
+
return {
|
|
2088
|
+
message: `Successfully uploaded ${insertedUnitIds.length} units`
|
|
2089
|
+
};
|
|
2090
|
+
} catch (error) {
|
|
2091
|
+
await session?.abortTransaction();
|
|
2092
|
+
import_node_server_utils14.logger.error("Error while uploading unit information", error);
|
|
2093
|
+
throw error;
|
|
2094
|
+
} finally {
|
|
2095
|
+
session?.endSession();
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
return {
|
|
2099
|
+
uploadByFile
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
// src/controllers/hygiene-unit.controller.ts
|
|
2104
|
+
var import_node_server_utils15 = require("@iservice365/node-server-utils");
|
|
2105
|
+
var import_joi8 = __toESM(require("joi"));
|
|
2106
|
+
function useUnitController() {
|
|
2107
|
+
const {
|
|
2108
|
+
createUnit: _createUnit,
|
|
2109
|
+
getUnits: _getUnits,
|
|
2110
|
+
updateUnit: _updateUnit,
|
|
2111
|
+
deleteUnit: _deleteUnit
|
|
2112
|
+
} = useUnitRepository();
|
|
2113
|
+
const { uploadByFile: _uploadByFile } = useUnitService();
|
|
2114
|
+
async function createUnit(req, res, next) {
|
|
2115
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
2116
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
2117
|
+
{}
|
|
2118
|
+
) : {};
|
|
2119
|
+
const createdBy = cookies["user"] || "";
|
|
2120
|
+
const payload = { ...req.body, createdBy };
|
|
2121
|
+
const { error } = unitSchema.validate(payload);
|
|
2122
|
+
if (error) {
|
|
2123
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2124
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
try {
|
|
2128
|
+
const id = await _createUnit(payload);
|
|
2129
|
+
res.status(201).json({ message: "Unit created successfully.", id });
|
|
2130
|
+
return;
|
|
2131
|
+
} catch (error2) {
|
|
2132
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2133
|
+
next(error2);
|
|
2134
|
+
return;
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
async function getAll(req, res, next) {
|
|
2138
|
+
const query = req.query;
|
|
2139
|
+
const validation = import_joi8.default.object({
|
|
2140
|
+
page: import_joi8.default.number().min(1).optional().allow("", null),
|
|
2141
|
+
limit: import_joi8.default.number().min(1).optional().allow("", null),
|
|
2142
|
+
search: import_joi8.default.string().optional().allow("", null),
|
|
2143
|
+
startDate: import_joi8.default.alternatives().try(import_joi8.default.date(), import_joi8.default.string()).optional().allow("", null),
|
|
2144
|
+
endDate: import_joi8.default.alternatives().try(import_joi8.default.date(), import_joi8.default.string()).optional().allow("", null),
|
|
2145
|
+
site: import_joi8.default.string().hex().optional().allow("", null)
|
|
2146
|
+
});
|
|
2147
|
+
const { error } = validation.validate(query);
|
|
2148
|
+
if (error) {
|
|
2149
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2150
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
2154
|
+
const limit = parseInt(req.query.limit) ?? 20;
|
|
2155
|
+
const search = req.query.search ?? "";
|
|
2156
|
+
const site = req.query.site ?? "";
|
|
2157
|
+
const startDate = req.query.startDate ?? "";
|
|
2158
|
+
const endDate = req.query.endDate ?? "";
|
|
2159
|
+
try {
|
|
2160
|
+
const data = await _getUnits({
|
|
2161
|
+
page,
|
|
2162
|
+
limit,
|
|
2163
|
+
search,
|
|
2164
|
+
site,
|
|
2165
|
+
startDate,
|
|
2166
|
+
endDate
|
|
2167
|
+
});
|
|
2168
|
+
res.json(data);
|
|
2169
|
+
return;
|
|
2170
|
+
} catch (error2) {
|
|
2171
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2172
|
+
next(error2);
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
async function updateUnit(req, res, next) {
|
|
2177
|
+
const payload = { id: req.params.id, ...req.body };
|
|
2178
|
+
const schema = import_joi8.default.object({
|
|
2179
|
+
id: import_joi8.default.string().hex().required(),
|
|
2180
|
+
name: import_joi8.default.string().required()
|
|
2181
|
+
});
|
|
2182
|
+
const { error } = schema.validate(payload);
|
|
2183
|
+
if (error) {
|
|
2184
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2185
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2186
|
+
return;
|
|
2187
|
+
}
|
|
2188
|
+
try {
|
|
2189
|
+
const { id, ...value } = payload;
|
|
2190
|
+
await _updateUnit(id, value);
|
|
2191
|
+
res.json({ message: "Unit updated successfully." });
|
|
2192
|
+
return;
|
|
2193
|
+
} catch (error2) {
|
|
2194
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2195
|
+
next(error2);
|
|
2196
|
+
return;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
async function deleteUnit(req, res, next) {
|
|
2200
|
+
const id = req.params.id;
|
|
2201
|
+
const validation = import_joi8.default.object({
|
|
2202
|
+
id: import_joi8.default.string().hex().required()
|
|
2203
|
+
});
|
|
2204
|
+
const { error } = validation.validate({ id });
|
|
2205
|
+
if (error) {
|
|
2206
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2207
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
try {
|
|
2211
|
+
await _deleteUnit(id);
|
|
2212
|
+
res.json({ message: "Unit deleted successfully." });
|
|
2213
|
+
return;
|
|
2214
|
+
} catch (error2) {
|
|
2215
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2216
|
+
next(error2);
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
async function uploadByFile(req, res, next) {
|
|
2221
|
+
if (!req.file) {
|
|
2222
|
+
next(new import_node_server_utils15.BadRequestError("File is required!"));
|
|
2223
|
+
return;
|
|
2224
|
+
}
|
|
2225
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
2226
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
2227
|
+
{}
|
|
2228
|
+
) : {};
|
|
2229
|
+
const createdBy = cookies["user"] || "";
|
|
2230
|
+
const { site } = req.body;
|
|
2231
|
+
const schema = import_joi8.default.object({
|
|
2232
|
+
site: import_joi8.default.string().hex().optional().allow("", null),
|
|
2233
|
+
createdBy: import_joi8.default.string().hex().required()
|
|
2234
|
+
});
|
|
2235
|
+
const { error } = schema.validate({ site, createdBy });
|
|
2236
|
+
if (error) {
|
|
2237
|
+
import_node_server_utils15.logger.log({ level: "error", message: error.message });
|
|
2238
|
+
next(new import_node_server_utils15.BadRequestError(error.message));
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2241
|
+
try {
|
|
2242
|
+
const xlsData = await convertBufferFile(req.file.buffer);
|
|
2243
|
+
const dataJson = JSON.stringify(xlsData);
|
|
2244
|
+
const result = await _uploadByFile({ dataJson, createdBy, site });
|
|
2245
|
+
return res.status(201).json(result);
|
|
2246
|
+
} catch (error2) {
|
|
2247
|
+
import_node_server_utils15.logger.log({ level: "error", message: error2.message });
|
|
2248
|
+
next(error2);
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
return {
|
|
2253
|
+
createUnit,
|
|
2254
|
+
getAll,
|
|
2255
|
+
updateUnit,
|
|
2256
|
+
deleteUnit,
|
|
2257
|
+
uploadByFile
|
|
2258
|
+
};
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
// src/models/hygiene-schedule-task-area.model.ts
|
|
2262
|
+
var import_node_server_utils16 = require("@iservice365/node-server-utils");
|
|
2263
|
+
var import_joi9 = __toESM(require("joi"));
|
|
2264
|
+
var import_mongodb7 = require("mongodb");
|
|
2265
|
+
var scheduleTaskAreaSchema = import_joi9.default.object({
|
|
2266
|
+
name: import_joi9.default.string().required(),
|
|
2267
|
+
site: import_joi9.default.string().hex().required(),
|
|
2268
|
+
createdBy: import_joi9.default.string().hex().required(),
|
|
2269
|
+
checklist: import_joi9.default.array().items(
|
|
2270
|
+
import_joi9.default.object({
|
|
2271
|
+
_id: import_joi9.default.string().hex().required(),
|
|
2272
|
+
name: import_joi9.default.string().required()
|
|
2273
|
+
})
|
|
2274
|
+
).optional(),
|
|
2275
|
+
updatedAt: import_joi9.default.date().optional().allow("", null),
|
|
2276
|
+
status: import_joi9.default.string().allow("", null).optional()
|
|
2277
|
+
});
|
|
2278
|
+
function MScheduleTaskArea(value) {
|
|
2279
|
+
const { error } = scheduleTaskAreaSchema.validate(value);
|
|
2280
|
+
if (error) {
|
|
2281
|
+
throw new import_node_server_utils16.BadRequestError(error.message);
|
|
2282
|
+
}
|
|
2283
|
+
if (value.site) {
|
|
2284
|
+
try {
|
|
2285
|
+
value.site = new import_mongodb7.ObjectId(value.site);
|
|
2286
|
+
} catch (error2) {
|
|
2287
|
+
throw new import_node_server_utils16.BadRequestError("Invalid site ID format.");
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
if (value.createdBy) {
|
|
2291
|
+
try {
|
|
2292
|
+
value.createdBy = new import_mongodb7.ObjectId(value.createdBy);
|
|
2293
|
+
} catch (error2) {
|
|
2294
|
+
throw new import_node_server_utils16.BadRequestError("Invalid createdBy ID format.");
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
if (value.checklist && Array.isArray(value.checklist)) {
|
|
2298
|
+
value.checklist = value.checklist.map((item) => {
|
|
2299
|
+
try {
|
|
2300
|
+
return {
|
|
2301
|
+
...item,
|
|
2302
|
+
_id: new import_mongodb7.ObjectId(item._id)
|
|
2303
|
+
};
|
|
2304
|
+
} catch (error2) {
|
|
2305
|
+
throw new import_node_server_utils16.BadRequestError(
|
|
2306
|
+
`Invalid checklist item ID format: ${item._id}`
|
|
2307
|
+
);
|
|
2308
|
+
}
|
|
2309
|
+
});
|
|
2310
|
+
}
|
|
2311
|
+
return {
|
|
2312
|
+
name: value.name,
|
|
2313
|
+
site: value.site,
|
|
2314
|
+
createdBy: value.createdBy,
|
|
2315
|
+
checklist: value.checklist,
|
|
2316
|
+
status: value.status ?? "",
|
|
2317
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
2318
|
+
updatedAt: value.updatedAt ?? "",
|
|
2319
|
+
deletedAt: value.deletedAt ?? ""
|
|
2320
|
+
};
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
// src/repositories/hygiene-schedule-task-area.repository.ts
|
|
2324
|
+
var import_mongodb8 = require("mongodb");
|
|
2325
|
+
var import_node_server_utils17 = require("@iservice365/node-server-utils");
|
|
2326
|
+
function useScheduleTaskAreaRepository() {
|
|
2327
|
+
const db = import_node_server_utils17.useAtlas.getDb();
|
|
2328
|
+
if (!db) {
|
|
2329
|
+
throw new import_node_server_utils17.InternalServerError("Unable to connect to server.");
|
|
2330
|
+
}
|
|
2331
|
+
const namespace_collection = "hygiene-schedule-task-areas";
|
|
2332
|
+
const collection = db.collection(namespace_collection);
|
|
2333
|
+
const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils17.useCache)(namespace_collection);
|
|
2334
|
+
async function createIndexes() {
|
|
2335
|
+
try {
|
|
2336
|
+
await collection.createIndexes([
|
|
2337
|
+
{ key: { site: 1 } },
|
|
2338
|
+
{ key: { name: "text" } }
|
|
2339
|
+
]);
|
|
2340
|
+
} catch (error) {
|
|
2341
|
+
throw new import_node_server_utils17.InternalServerError("Failed to create index on site.");
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
async function createScheduleTaskArea(value, session) {
|
|
2345
|
+
try {
|
|
2346
|
+
value = MScheduleTaskArea(value);
|
|
2347
|
+
const res = await collection.insertOne(value, { session });
|
|
2348
|
+
delNamespace().then(() => {
|
|
2349
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2350
|
+
}).catch((err) => {
|
|
2351
|
+
import_node_server_utils17.logger.error(
|
|
2352
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2353
|
+
err
|
|
2354
|
+
);
|
|
2355
|
+
});
|
|
2356
|
+
return res.insertedId;
|
|
2357
|
+
} catch (error) {
|
|
2358
|
+
throw error;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
async function updateScheduleTaskArea(_id, params) {
|
|
2362
|
+
try {
|
|
2363
|
+
_id = new import_mongodb8.ObjectId(_id);
|
|
2364
|
+
} catch (error) {
|
|
2365
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area ID format.");
|
|
2366
|
+
}
|
|
2367
|
+
try {
|
|
2368
|
+
const value = MScheduleTaskArea({ ...params, updatedAt: /* @__PURE__ */ new Date() });
|
|
2369
|
+
const res = await collection.updateOne({ _id }, { $set: value });
|
|
2370
|
+
if (res.modifiedCount === 0) {
|
|
2371
|
+
throw new import_node_server_utils17.InternalServerError("Unable to update cleaning area.");
|
|
2372
|
+
}
|
|
2373
|
+
delNamespace().then(() => {
|
|
2374
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2375
|
+
}).catch((err) => {
|
|
2376
|
+
import_node_server_utils17.logger.error(
|
|
2377
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2378
|
+
err
|
|
2379
|
+
);
|
|
2380
|
+
});
|
|
2381
|
+
return res.modifiedCount;
|
|
2382
|
+
} catch (error) {
|
|
2383
|
+
throw error;
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
async function deleteScheduleTaskArea(_id, session) {
|
|
2387
|
+
try {
|
|
2388
|
+
_id = new import_mongodb8.ObjectId(_id);
|
|
2389
|
+
} catch (error) {
|
|
2390
|
+
throw new import_node_server_utils17.BadRequestError("Invalid area ID format.");
|
|
2391
|
+
}
|
|
2392
|
+
try {
|
|
2393
|
+
const updateValue = {
|
|
2394
|
+
status: "deleted",
|
|
2395
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
2396
|
+
deletedAt: /* @__PURE__ */ new Date()
|
|
2397
|
+
};
|
|
2398
|
+
const res = await collection.updateOne(
|
|
2399
|
+
{ _id },
|
|
2400
|
+
{ $set: updateValue },
|
|
2401
|
+
{ session }
|
|
2402
|
+
);
|
|
2403
|
+
if (res.modifiedCount === 0)
|
|
2404
|
+
throw new import_node_server_utils17.InternalServerError("Unable to delete area.");
|
|
2405
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, { _id });
|
|
2406
|
+
delCache(cacheKey).then(() => {
|
|
2407
|
+
import_node_server_utils17.logger.info(`Cache deleted for key: ${cacheKey}`);
|
|
2408
|
+
}).catch((err) => {
|
|
2409
|
+
import_node_server_utils17.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
|
|
2410
|
+
});
|
|
2411
|
+
return res.modifiedCount;
|
|
2412
|
+
} catch (error) {
|
|
2413
|
+
throw error;
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
async function getScheduleTaskAreas({
|
|
2417
|
+
page = 1,
|
|
2418
|
+
limit = 10,
|
|
2419
|
+
search = "",
|
|
2420
|
+
sort = {},
|
|
2421
|
+
startDate = "",
|
|
2422
|
+
endDate = "",
|
|
2423
|
+
site = ""
|
|
2424
|
+
}) {
|
|
2425
|
+
page = page > 0 ? page - 1 : 0;
|
|
2426
|
+
let dateFilter = {};
|
|
2427
|
+
try {
|
|
2428
|
+
site = new import_mongodb8.ObjectId(site);
|
|
2429
|
+
} catch (error) {
|
|
2430
|
+
throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
|
|
2431
|
+
}
|
|
2432
|
+
const query = {
|
|
2433
|
+
status: { $ne: "deleted" }
|
|
2434
|
+
};
|
|
2435
|
+
const cacheOptions = {
|
|
2436
|
+
site: site.toString()
|
|
2437
|
+
};
|
|
2438
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
2439
|
+
cacheOptions.sort = JSON.stringify(sort);
|
|
2440
|
+
if (search) {
|
|
2441
|
+
query.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
2442
|
+
cacheOptions.search = search;
|
|
2443
|
+
}
|
|
2444
|
+
delNamespace().then(() => {
|
|
2445
|
+
import_node_server_utils17.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
2446
|
+
}).catch((err) => {
|
|
2447
|
+
import_node_server_utils17.logger.error(
|
|
2448
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
2449
|
+
err
|
|
2450
|
+
);
|
|
2451
|
+
});
|
|
2452
|
+
const cacheKey = (0, import_node_server_utils17.makeCacheKey)(namespace_collection, cacheOptions);
|
|
2453
|
+
const cachedData = await getCache(cacheKey);
|
|
2454
|
+
if (cachedData) {
|
|
2455
|
+
import_node_server_utils17.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
2456
|
+
return cachedData;
|
|
2457
|
+
}
|
|
2458
|
+
if (startDate && endDate) {
|
|
2459
|
+
dateFilter = {
|
|
2460
|
+
createdAt: {
|
|
2461
|
+
$gte: new Date(startDate),
|
|
2462
|
+
$lte: new Date(endDate)
|
|
2463
|
+
}
|
|
2464
|
+
};
|
|
2465
|
+
} else if (startDate) {
|
|
2466
|
+
dateFilter = { createdAt: { $gte: new Date(startDate) } };
|
|
2467
|
+
} else if (endDate) {
|
|
2468
|
+
dateFilter = { createdAt: { $lte: new Date(endDate) } };
|
|
2469
|
+
}
|
|
2470
|
+
try {
|
|
2471
|
+
const items = await collection.aggregate([
|
|
2472
|
+
{
|
|
2473
|
+
$match: {
|
|
2474
|
+
...dateFilter,
|
|
2475
|
+
...query
|
|
2476
|
+
}
|
|
2477
|
+
},
|
|
2478
|
+
{
|
|
2479
|
+
$lookup: {
|
|
2480
|
+
from: "sites",
|
|
2481
|
+
localField: "site",
|
|
2482
|
+
foreignField: "_id",
|
|
2483
|
+
pipeline: [{ $project: { name: 1 } }],
|
|
2484
|
+
as: "site"
|
|
2485
|
+
}
|
|
2486
|
+
},
|
|
2487
|
+
{
|
|
2488
|
+
$unwind: {
|
|
2489
|
+
path: "$site",
|
|
2490
|
+
preserveNullAndEmptyArrays: true
|
|
2491
|
+
}
|
|
2492
|
+
},
|
|
2493
|
+
{
|
|
2494
|
+
$lookup: {
|
|
2495
|
+
from: "users",
|
|
2496
|
+
localField: "createdBy",
|
|
2497
|
+
foreignField: "_id",
|
|
2498
|
+
pipeline: [{ $project: { name: 1 } }],
|
|
2499
|
+
as: "createdBy"
|
|
2500
|
+
}
|
|
2501
|
+
},
|
|
2502
|
+
{
|
|
2503
|
+
$unwind: {
|
|
2504
|
+
path: "$createdBy",
|
|
2505
|
+
preserveNullAndEmptyArrays: true
|
|
2506
|
+
}
|
|
2507
|
+
},
|
|
2508
|
+
{
|
|
2509
|
+
$facet: {
|
|
2510
|
+
totalCount: [{ $count: "count" }],
|
|
2511
|
+
items: [
|
|
2512
|
+
{ $sort: { createdAt: -1 } },
|
|
2513
|
+
{ $skip: page * limit },
|
|
2514
|
+
{ $limit: limit }
|
|
2515
|
+
]
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
]).toArray();
|
|
2519
|
+
const length = await collection.countDocuments(query);
|
|
2520
|
+
const data = (0, import_node_server_utils17.paginate)(items, page, limit, length);
|
|
2521
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
2522
|
+
import_node_server_utils17.logger.info(`Cache set for key: ${cacheKey}`);
|
|
2523
|
+
}).catch((err) => {
|
|
2524
|
+
import_node_server_utils17.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2525
|
+
});
|
|
2526
|
+
return data;
|
|
2527
|
+
} catch (error) {
|
|
2528
|
+
throw error;
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
async function getScheduleTaskAreaByName(name, site) {
|
|
2532
|
+
try {
|
|
2533
|
+
if (site)
|
|
2534
|
+
site = new import_mongodb8.ObjectId(site);
|
|
2535
|
+
} catch (error) {
|
|
2536
|
+
throw new import_node_server_utils17.BadRequestError("Invalid site ID format.");
|
|
2537
|
+
}
|
|
2538
|
+
try {
|
|
2539
|
+
return await collection.findOne({
|
|
2540
|
+
name: { $regex: new RegExp(`^${name}$`, "i") },
|
|
2541
|
+
...site && { site }
|
|
2542
|
+
});
|
|
2543
|
+
} catch (error) {
|
|
2544
|
+
throw new import_node_server_utils17.BadRequestError("Unable to fetch schedule task area by name.");
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
async function getScheduleTaskAreaById(id, site) {
|
|
2548
|
+
try {
|
|
2549
|
+
id = typeof id === "string" ? new import_mongodb8.ObjectId(id) : id;
|
|
2550
|
+
} catch (error) {
|
|
2551
|
+
throw new import_node_server_utils17.BadRequestError("Invalid unit ID format.");
|
|
2552
|
+
}
|
|
2553
|
+
try {
|
|
2554
|
+
if (site)
|
|
2555
|
+
site = new import_mongodb8.ObjectId(site);
|
|
2556
|
+
} catch (error) {
|
|
2557
|
+
throw new import_node_server_utils17.BadRequestError(
|
|
2558
|
+
"Unable to fetch schedule task area by ID, Invalid site ID format."
|
|
2559
|
+
);
|
|
2560
|
+
}
|
|
2561
|
+
try {
|
|
2562
|
+
return await collection.findOne({ _id: id, ...site && { site } });
|
|
2563
|
+
} catch (error) {
|
|
2564
|
+
throw new import_node_server_utils17.BadRequestError("Unable to fetch schedule task area by id.");
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
return {
|
|
2568
|
+
createScheduleTaskArea,
|
|
2569
|
+
updateScheduleTaskArea,
|
|
2570
|
+
deleteScheduleTaskArea,
|
|
2571
|
+
getScheduleTaskAreas,
|
|
2572
|
+
createIndexes,
|
|
2573
|
+
getScheduleTaskAreaByName,
|
|
2574
|
+
getScheduleTaskAreaById
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
// src/services/hygiene-schedule-task-area.service.ts
|
|
2579
|
+
var import_node_server_utils18 = require("@iservice365/node-server-utils");
|
|
2580
|
+
function useScheduleTaskAreaService() {
|
|
2581
|
+
const {
|
|
2582
|
+
getScheduleTaskAreas: _getAll,
|
|
2583
|
+
createScheduleTaskArea: _create,
|
|
2584
|
+
updateScheduleTaskArea: _updateById,
|
|
2585
|
+
deleteScheduleTaskArea: _deleteById,
|
|
2586
|
+
getScheduleTaskAreaByName: _getScheduleTaskAreaByName,
|
|
2587
|
+
getScheduleTaskAreaById: _getScheduleTaskAreaById
|
|
2588
|
+
} = useScheduleTaskAreaRepository();
|
|
2589
|
+
async function getAll(query) {
|
|
2590
|
+
return await _getAll(query);
|
|
2591
|
+
}
|
|
2592
|
+
async function create(scheduleTaskArea) {
|
|
2593
|
+
const result = await _getScheduleTaskAreaByName(
|
|
2594
|
+
scheduleTaskArea.name,
|
|
2595
|
+
scheduleTaskArea.site
|
|
2596
|
+
);
|
|
2597
|
+
if (result)
|
|
2598
|
+
throw new import_node_server_utils18.InternalServerError(
|
|
2599
|
+
"Schedule Task Area name already exists in this site."
|
|
2600
|
+
);
|
|
2601
|
+
return await _create(scheduleTaskArea);
|
|
2602
|
+
}
|
|
2603
|
+
async function updateById(id, scheduleTaskArea) {
|
|
2604
|
+
const result = await _getScheduleTaskAreaByName(
|
|
2605
|
+
scheduleTaskArea.name,
|
|
2606
|
+
scheduleTaskArea.site
|
|
2607
|
+
);
|
|
2608
|
+
const resultId = result?._id.toString() ?? "";
|
|
2609
|
+
if (result && id != resultId) {
|
|
2610
|
+
throw new import_node_server_utils18.InternalServerError(
|
|
2611
|
+
"Schedule Task Area name already exists in this site."
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
return await _updateById(id, scheduleTaskArea);
|
|
2615
|
+
}
|
|
2616
|
+
async function deleteById(id) {
|
|
2617
|
+
return await _deleteById(id);
|
|
2618
|
+
}
|
|
2619
|
+
return {
|
|
2620
|
+
getAll,
|
|
2621
|
+
create,
|
|
2622
|
+
updateById,
|
|
2623
|
+
deleteById
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
// src/controllers/hygiene-schedule-task-area.controller.ts
|
|
2628
|
+
var import_node_server_utils19 = require("@iservice365/node-server-utils");
|
|
2629
|
+
var import_joi10 = __toESM(require("joi"));
|
|
2630
|
+
function useScheduleTaskAreaController() {
|
|
2631
|
+
const {
|
|
2632
|
+
getAll: _getAll,
|
|
2633
|
+
create: _createScheduleTaskArea,
|
|
2634
|
+
updateById: _updateScheduleTaskArea,
|
|
2635
|
+
deleteById: _deleteById
|
|
2636
|
+
} = useScheduleTaskAreaService();
|
|
2637
|
+
async function getAll(req, res, next) {
|
|
2638
|
+
const query = req.query;
|
|
2639
|
+
const validation = import_joi10.default.object({
|
|
2640
|
+
page: import_joi10.default.number().min(1).optional().allow("", null),
|
|
2641
|
+
limit: import_joi10.default.number().min(1).optional().allow("", null),
|
|
2642
|
+
search: import_joi10.default.string().optional().allow("", null),
|
|
2643
|
+
site: import_joi10.default.string().hex().optional().allow("", null)
|
|
2644
|
+
});
|
|
2645
|
+
const { error } = validation.validate(query);
|
|
2646
|
+
if (error) {
|
|
2647
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
2651
|
+
let limit = parseInt(req.query.limit) ?? 20;
|
|
2652
|
+
limit = isNaN(limit) ? 20 : limit;
|
|
2653
|
+
const sort = req.query.sort ? String(req.query.sort).split(",") : "";
|
|
2654
|
+
const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
|
|
2655
|
+
const sortObj = {};
|
|
2656
|
+
if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
|
|
2657
|
+
sort.forEach((field, index) => {
|
|
2658
|
+
sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
|
|
2659
|
+
});
|
|
2660
|
+
}
|
|
2661
|
+
const site = req.query.site ?? "";
|
|
2662
|
+
const search = req.query.search ?? "";
|
|
2663
|
+
try {
|
|
2664
|
+
const scheduleTaskAreas = await _getAll({
|
|
2665
|
+
page,
|
|
2666
|
+
limit,
|
|
2667
|
+
sort: sortObj,
|
|
2668
|
+
site,
|
|
2669
|
+
search
|
|
2670
|
+
});
|
|
2671
|
+
res.json(scheduleTaskAreas);
|
|
2672
|
+
return;
|
|
2673
|
+
} catch (error2) {
|
|
2674
|
+
next(error2);
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
async function createScheduleTaskArea(req, res, next) {
|
|
2678
|
+
const value = req.body;
|
|
2679
|
+
const schema = import_joi10.default.object({
|
|
2680
|
+
name: import_joi10.default.string().required(),
|
|
2681
|
+
site: import_joi10.default.string().hex().optional().allow("", null),
|
|
2682
|
+
createdBy: import_joi10.default.string().hex().optional().allow("", null)
|
|
2683
|
+
});
|
|
2684
|
+
const { error } = schema.validate(value);
|
|
2685
|
+
if (error) {
|
|
2686
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
2687
|
+
import_node_server_utils19.logger.info(`Controller: ${error.message}`);
|
|
2688
|
+
return;
|
|
2689
|
+
}
|
|
2690
|
+
try {
|
|
2691
|
+
const result = await _createScheduleTaskArea(value);
|
|
2692
|
+
res.status(201).json(result);
|
|
2693
|
+
return;
|
|
2694
|
+
} catch (error2) {
|
|
2695
|
+
next(error2);
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
async function updateScheduleTaskArea(req, res, next) {
|
|
2699
|
+
const { name, site, createdBy } = req.body;
|
|
2700
|
+
const id = req.params.id;
|
|
2701
|
+
const schema = import_joi10.default.object({
|
|
2702
|
+
id: import_joi10.default.string().hex().required(),
|
|
2703
|
+
name: import_joi10.default.string().required(),
|
|
2704
|
+
site: import_joi10.default.string().required(),
|
|
2705
|
+
checklist: import_joi10.default.array().optional().items(
|
|
2706
|
+
import_joi10.default.object({
|
|
2707
|
+
_id: import_joi10.default.string().optional().required(),
|
|
2708
|
+
name: import_joi10.default.string().optional().required()
|
|
2709
|
+
})
|
|
2710
|
+
),
|
|
2711
|
+
createdBy: import_joi10.default.string().hex().optional().allow("", null)
|
|
2712
|
+
});
|
|
2713
|
+
const { error } = schema.validate({ id, name, createdBy, site });
|
|
2714
|
+
if (error) {
|
|
2715
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
2716
|
+
import_node_server_utils19.logger.info(`Controller: ${error.message}`);
|
|
2717
|
+
return;
|
|
2718
|
+
}
|
|
2719
|
+
try {
|
|
2720
|
+
const result = await _updateScheduleTaskArea(id, {
|
|
2721
|
+
name,
|
|
2722
|
+
createdBy,
|
|
2723
|
+
site
|
|
2724
|
+
});
|
|
2725
|
+
res.json(result);
|
|
2726
|
+
return;
|
|
2727
|
+
} catch (error2) {
|
|
2728
|
+
next(error2);
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
async function deleteScheduleTaskArea(req, res, next) {
|
|
2732
|
+
const id = req.params.id;
|
|
2733
|
+
const validation = import_joi10.default.object({
|
|
2734
|
+
id: import_joi10.default.string().hex().required()
|
|
2735
|
+
});
|
|
2736
|
+
const { error } = validation.validate({ id });
|
|
2737
|
+
if (error) {
|
|
2738
|
+
next(new import_node_server_utils19.BadRequestError(error.message));
|
|
2739
|
+
return;
|
|
2740
|
+
}
|
|
2741
|
+
try {
|
|
2742
|
+
const message = await _deleteById(id);
|
|
2743
|
+
res.json(message);
|
|
2744
|
+
return;
|
|
2745
|
+
} catch (error2) {
|
|
2746
|
+
next(error2);
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
return {
|
|
2750
|
+
getAll,
|
|
2751
|
+
createScheduleTaskArea,
|
|
2752
|
+
updateScheduleTaskArea,
|
|
2753
|
+
deleteScheduleTaskArea
|
|
2754
|
+
};
|
|
2755
|
+
}
|
|
2756
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2757
|
+
0 && (module.exports = {
|
|
2758
|
+
MArea,
|
|
2759
|
+
MParentChecklist,
|
|
2760
|
+
MScheduleTaskArea,
|
|
2761
|
+
MToiletLocation,
|
|
2762
|
+
MUnit,
|
|
2763
|
+
areaSchema,
|
|
2764
|
+
parentChecklistSchema,
|
|
2765
|
+
scheduleTaskAreaSchema,
|
|
2766
|
+
toiletLocationSchema,
|
|
2767
|
+
unitSchema,
|
|
2768
|
+
useAreaController,
|
|
2769
|
+
useAreaRepository,
|
|
2770
|
+
useAreaService,
|
|
2771
|
+
useParentCheckilstController,
|
|
2772
|
+
useParentChecklistRepo,
|
|
2773
|
+
useScheduleTaskAreaController,
|
|
2774
|
+
useScheduleTaskAreaRepository,
|
|
2775
|
+
useScheduleTaskAreaService,
|
|
2776
|
+
useToiletLocationController,
|
|
2777
|
+
useToiletLocationRepository,
|
|
2778
|
+
useToiletLocationService,
|
|
2779
|
+
useUnitController,
|
|
2780
|
+
useUnitRepository,
|
|
2781
|
+
useUnitService
|
|
2782
|
+
});
|
|
2
2783
|
//# sourceMappingURL=index.js.map
|