@7365admin1/core 2.47.0 → 2.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +55 -17
- package/dist/index.js +541 -92
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +540 -92
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -940,12 +940,16 @@ import {
|
|
|
940
940
|
makeCacheKey as makeCacheKey3
|
|
941
941
|
} from "@7365admin1/node-server-utils";
|
|
942
942
|
var work_orders_namespace_collection = "work-orders";
|
|
943
|
+
var work_orders2_namespace_collection = "work-orders2";
|
|
943
944
|
function useWorkOrderRepo() {
|
|
944
945
|
const db = useAtlas3.getDb();
|
|
945
946
|
if (!db) {
|
|
946
947
|
throw new InternalServerError3("Unable to connect to server.");
|
|
947
948
|
}
|
|
948
949
|
const collection = db.collection(work_orders_namespace_collection);
|
|
950
|
+
const workOrders2Collection = db.collection(
|
|
951
|
+
work_orders2_namespace_collection
|
|
952
|
+
);
|
|
949
953
|
async function createIndex() {
|
|
950
954
|
try {
|
|
951
955
|
await collection.createIndexes([
|
|
@@ -977,6 +981,12 @@ function useWorkOrderRepo() {
|
|
|
977
981
|
const { delNamespace, setCache, getCache, delCache } = useCache3(
|
|
978
982
|
work_orders_namespace_collection
|
|
979
983
|
);
|
|
984
|
+
const {
|
|
985
|
+
delNamespace: delNamespaceWorkOrders2,
|
|
986
|
+
setCache: setCacheWorkOrders2,
|
|
987
|
+
getCache: getCacheWorkOrders2,
|
|
988
|
+
delCache: delCacheWorkOrders2
|
|
989
|
+
} = useCache3(work_orders2_namespace_collection);
|
|
980
990
|
const { delNamespace: _delDashboardNameSpace } = useCache3("dashboard");
|
|
981
991
|
async function createWorkOrder(value, session) {
|
|
982
992
|
try {
|
|
@@ -1378,7 +1388,7 @@ function useWorkOrderRepo() {
|
|
|
1378
1388
|
updatedAt: /* @__PURE__ */ new Date(),
|
|
1379
1389
|
deletedAt: /* @__PURE__ */ new Date()
|
|
1380
1390
|
};
|
|
1381
|
-
const res = await
|
|
1391
|
+
const res = await workOrders2Collection.updateOne(
|
|
1382
1392
|
{ _id },
|
|
1383
1393
|
{ $set: updateValue },
|
|
1384
1394
|
{ session }
|
|
@@ -1386,13 +1396,13 @@ function useWorkOrderRepo() {
|
|
|
1386
1396
|
if (res.modifiedCount === 0) {
|
|
1387
1397
|
throw new InternalServerError3("Unable to delete work order.");
|
|
1388
1398
|
}
|
|
1389
|
-
|
|
1399
|
+
delNamespaceWorkOrders2().then(() => {
|
|
1390
1400
|
logger5.info(
|
|
1391
|
-
`Cache cleared for namespace: ${
|
|
1401
|
+
`Cache cleared for namespace: ${work_orders2_namespace_collection}`
|
|
1392
1402
|
);
|
|
1393
1403
|
}).catch((err) => {
|
|
1394
1404
|
logger5.error(
|
|
1395
|
-
`Failed to clear cache for namespace: ${
|
|
1405
|
+
`Failed to clear cache for namespace: ${work_orders2_namespace_collection}`,
|
|
1396
1406
|
err
|
|
1397
1407
|
);
|
|
1398
1408
|
});
|
|
@@ -2031,7 +2041,7 @@ function useOccurrenceEntryRepo() {
|
|
|
2031
2041
|
logger6.info(`Cache hit for key: ${cacheKey}`);
|
|
2032
2042
|
return cached;
|
|
2033
2043
|
}
|
|
2034
|
-
const bookId = new ObjectId7(dailyOccurrenceBookId);
|
|
2044
|
+
const bookId = typeof dailyOccurrenceBookId === "string" ? new ObjectId7(dailyOccurrenceBookId) : dailyOccurrenceBookId;
|
|
2035
2045
|
const data = await collection.findOne(
|
|
2036
2046
|
{ dailyOccurrenceBookId: bookId },
|
|
2037
2047
|
{
|
|
@@ -2046,6 +2056,16 @@ function useOccurrenceEntryRepo() {
|
|
|
2046
2056
|
});
|
|
2047
2057
|
return serialNumber;
|
|
2048
2058
|
}
|
|
2059
|
+
async function getLatestSerialNumberInGroup(bookId, group) {
|
|
2060
|
+
const latestEntry = await collection.findOne(
|
|
2061
|
+
{
|
|
2062
|
+
dailyOccurrenceBookId: bookId,
|
|
2063
|
+
serialNumber: { $regex: `^${group}(\\.|$)` }
|
|
2064
|
+
},
|
|
2065
|
+
{ sort: { serialNumber: -1 } }
|
|
2066
|
+
);
|
|
2067
|
+
return latestEntry ? Number(latestEntry.serialNumber) : group;
|
|
2068
|
+
}
|
|
2049
2069
|
async function updateUserNameBySignatureId(_id, value, session) {
|
|
2050
2070
|
try {
|
|
2051
2071
|
const updateValue = {
|
|
@@ -2081,7 +2101,8 @@ function useOccurrenceEntryRepo() {
|
|
|
2081
2101
|
createIndexes,
|
|
2082
2102
|
createTextIndex,
|
|
2083
2103
|
getLatestSerialNumber,
|
|
2084
|
-
updateOccurrenceEntryByBookId
|
|
2104
|
+
updateOccurrenceEntryByBookId,
|
|
2105
|
+
getLatestSerialNumberInGroup
|
|
2085
2106
|
};
|
|
2086
2107
|
}
|
|
2087
2108
|
|
|
@@ -2748,6 +2769,7 @@ var APP_POOL_MAINTENANCE = process.env.APP_POOL_MAINTENANCE ?? "http://localhost
|
|
|
2748
2769
|
var ENCRYPTION_KEY = process.env.ENCRYPTION_KEY ?? "";
|
|
2749
2770
|
var DOMAIN = process.env.DOMAIN ?? "localhost";
|
|
2750
2771
|
var OPEN_AI_API_KEY = process.env.OPEN_AI_API_KEY;
|
|
2772
|
+
var STORAGE_API = process.env.STORAGE_API;
|
|
2751
2773
|
|
|
2752
2774
|
// src/services/auth.service.ts
|
|
2753
2775
|
import jwt from "jsonwebtoken";
|
|
@@ -5155,6 +5177,39 @@ function useVerificationRepoV2() {
|
|
|
5155
5177
|
throw new InternalServerError11("Error updating verification status.");
|
|
5156
5178
|
}
|
|
5157
5179
|
}
|
|
5180
|
+
async function countPendingOrgInvites(orgId) {
|
|
5181
|
+
try {
|
|
5182
|
+
orgId = new ObjectId18(orgId);
|
|
5183
|
+
} catch (error) {
|
|
5184
|
+
throw new BadRequestError19("Invalid organization ID format.");
|
|
5185
|
+
}
|
|
5186
|
+
const query = {
|
|
5187
|
+
status: "pending" /* PENDING */,
|
|
5188
|
+
type: { $in: ["user-invite", "member-invite"] },
|
|
5189
|
+
"metadata.org": orgId
|
|
5190
|
+
};
|
|
5191
|
+
const cacheKey = makeCacheKey10(namespace_collection, {
|
|
5192
|
+
status: "pending" /* PENDING */,
|
|
5193
|
+
type: JSON.stringify(["user-invite", "member-invite"]),
|
|
5194
|
+
org: orgId.toString()
|
|
5195
|
+
});
|
|
5196
|
+
const cachedData = await getCache(cacheKey);
|
|
5197
|
+
if (typeof cachedData === "number") {
|
|
5198
|
+
logger13.info(`Cache hit for key: ${cacheKey}`);
|
|
5199
|
+
return cachedData;
|
|
5200
|
+
}
|
|
5201
|
+
try {
|
|
5202
|
+
const count = await collection.countDocuments(query);
|
|
5203
|
+
setCache(cacheKey, count, 15 * 60).then(() => {
|
|
5204
|
+
logger13.info(`Cache set for key: ${cacheKey}`);
|
|
5205
|
+
}).catch((err) => {
|
|
5206
|
+
logger13.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
5207
|
+
});
|
|
5208
|
+
return count;
|
|
5209
|
+
} catch (error) {
|
|
5210
|
+
throw new InternalServerError11("Failed to count pending invitations.");
|
|
5211
|
+
}
|
|
5212
|
+
}
|
|
5158
5213
|
return {
|
|
5159
5214
|
createIndex,
|
|
5160
5215
|
createTextIndex,
|
|
@@ -5163,7 +5218,8 @@ function useVerificationRepoV2() {
|
|
|
5163
5218
|
getByVerificationCode,
|
|
5164
5219
|
getVerificationById,
|
|
5165
5220
|
getVerifications,
|
|
5166
|
-
updateStatusById
|
|
5221
|
+
updateStatusById,
|
|
5222
|
+
countPendingOrgInvites
|
|
5167
5223
|
};
|
|
5168
5224
|
}
|
|
5169
5225
|
|
|
@@ -5241,6 +5297,46 @@ function useVerificationService() {
|
|
|
5241
5297
|
throw error;
|
|
5242
5298
|
}
|
|
5243
5299
|
}
|
|
5300
|
+
async function createSimpleUserInvite({
|
|
5301
|
+
email,
|
|
5302
|
+
metadata
|
|
5303
|
+
}) {
|
|
5304
|
+
const type = "user-invite";
|
|
5305
|
+
const value = {
|
|
5306
|
+
type,
|
|
5307
|
+
email,
|
|
5308
|
+
metadata,
|
|
5309
|
+
expireAt: new Date(
|
|
5310
|
+
(/* @__PURE__ */ new Date()).getTime() + 72 * 60 * 60 * 1e3
|
|
5311
|
+
).toISOString(),
|
|
5312
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5313
|
+
};
|
|
5314
|
+
if (value.metadata?.org) {
|
|
5315
|
+
await getOrgById(value.metadata?.org);
|
|
5316
|
+
}
|
|
5317
|
+
if (value.metadata?.siteId) {
|
|
5318
|
+
await getSiteById(value.metadata?.siteId);
|
|
5319
|
+
}
|
|
5320
|
+
const res = await add(value);
|
|
5321
|
+
const dir = __dirname;
|
|
5322
|
+
const filePath = getDirectory(dir, "./public/handlebars/user-invite");
|
|
5323
|
+
const link = `${APP_MAIN}/verify/invitation/${res}`;
|
|
5324
|
+
const emailContent = compileHandlebar({
|
|
5325
|
+
context: {
|
|
5326
|
+
email,
|
|
5327
|
+
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
5328
|
+
link
|
|
5329
|
+
},
|
|
5330
|
+
filePath
|
|
5331
|
+
});
|
|
5332
|
+
mailer.sendMail({
|
|
5333
|
+
to: email,
|
|
5334
|
+
subject: "User Invite",
|
|
5335
|
+
html: emailContent,
|
|
5336
|
+
sender: "iService365"
|
|
5337
|
+
});
|
|
5338
|
+
return res;
|
|
5339
|
+
}
|
|
5244
5340
|
const {
|
|
5245
5341
|
add: _add,
|
|
5246
5342
|
updateVerificationStatusById: _updateVerificationStatusById,
|
|
@@ -5534,7 +5630,8 @@ function useVerificationService() {
|
|
|
5534
5630
|
cancelUserInvitation,
|
|
5535
5631
|
updateStatusById,
|
|
5536
5632
|
signUp,
|
|
5537
|
-
checkExpiredInvitation
|
|
5633
|
+
checkExpiredInvitation,
|
|
5634
|
+
createSimpleUserInvite
|
|
5538
5635
|
};
|
|
5539
5636
|
}
|
|
5540
5637
|
|
|
@@ -6780,7 +6877,16 @@ function useUserController() {
|
|
|
6780
6877
|
async function updateUserFieldById(req, res, next) {
|
|
6781
6878
|
const validation = Joi13.object({
|
|
6782
6879
|
_id: Joi13.string().hex().required(),
|
|
6783
|
-
field: Joi13.string().valid(
|
|
6880
|
+
field: Joi13.string().valid(
|
|
6881
|
+
"name",
|
|
6882
|
+
"email",
|
|
6883
|
+
"contact",
|
|
6884
|
+
"nric",
|
|
6885
|
+
"dateOfBirth",
|
|
6886
|
+
"profile",
|
|
6887
|
+
"gender",
|
|
6888
|
+
"defaultOrg"
|
|
6889
|
+
).required(),
|
|
6784
6890
|
value: Joi13.when("field", {
|
|
6785
6891
|
switch: [
|
|
6786
6892
|
{ is: "email", then: Joi13.string().email().required() },
|
|
@@ -7384,6 +7490,7 @@ import Joi16 from "joi";
|
|
|
7384
7490
|
function useVerificationController() {
|
|
7385
7491
|
const {
|
|
7386
7492
|
createUserInvite: _createUserInvite,
|
|
7493
|
+
createSimpleUserInvite: _createSimpleUserInvite,
|
|
7387
7494
|
createServiceProviderInvite: _createServiceProviderInvite,
|
|
7388
7495
|
createForgetPassword: _createForgetPassword,
|
|
7389
7496
|
verify: _verify,
|
|
@@ -7434,6 +7541,58 @@ function useVerificationController() {
|
|
|
7434
7541
|
return;
|
|
7435
7542
|
}
|
|
7436
7543
|
}
|
|
7544
|
+
async function createSimpleUserInvite(req, res, next) {
|
|
7545
|
+
const payload = { ...req.body };
|
|
7546
|
+
const validation = Joi16.object({
|
|
7547
|
+
email: Joi16.string().email().required(),
|
|
7548
|
+
app: Joi16.string().optional().allow("", null),
|
|
7549
|
+
role: Joi16.string().hex().optional().allow("", null),
|
|
7550
|
+
name: Joi16.string().optional().allow("", null),
|
|
7551
|
+
org: Joi16.string().hex().optional().allow("", null),
|
|
7552
|
+
siteId: Joi16.string().hex().optional().allow("", null),
|
|
7553
|
+
siteName: Joi16.string().optional().allow("", null)
|
|
7554
|
+
});
|
|
7555
|
+
const { error } = validation.validate(payload);
|
|
7556
|
+
if (error) {
|
|
7557
|
+
logger22.log({
|
|
7558
|
+
level: "error",
|
|
7559
|
+
message: `${error.message}`
|
|
7560
|
+
});
|
|
7561
|
+
next(new BadRequestError31(error.message));
|
|
7562
|
+
return;
|
|
7563
|
+
}
|
|
7564
|
+
const email = req.body.email ?? "";
|
|
7565
|
+
const app = req.body.app ?? "";
|
|
7566
|
+
const role = req.body.role ?? "";
|
|
7567
|
+
const name = req.body.name ?? "";
|
|
7568
|
+
const org = req.body.org ?? "";
|
|
7569
|
+
const siteId = req.body.siteId ?? "";
|
|
7570
|
+
const siteName = req.body.siteName ?? "";
|
|
7571
|
+
try {
|
|
7572
|
+
await _createSimpleUserInvite({
|
|
7573
|
+
email,
|
|
7574
|
+
metadata: {
|
|
7575
|
+
app,
|
|
7576
|
+
role,
|
|
7577
|
+
name,
|
|
7578
|
+
org,
|
|
7579
|
+
siteId,
|
|
7580
|
+
siteName
|
|
7581
|
+
}
|
|
7582
|
+
});
|
|
7583
|
+
res.status(201).json({
|
|
7584
|
+
message: "Successfully invited user."
|
|
7585
|
+
});
|
|
7586
|
+
return;
|
|
7587
|
+
} catch (error2) {
|
|
7588
|
+
logger22.log({
|
|
7589
|
+
level: "error",
|
|
7590
|
+
message: `${error2.message}`
|
|
7591
|
+
});
|
|
7592
|
+
next(error2);
|
|
7593
|
+
return;
|
|
7594
|
+
}
|
|
7595
|
+
}
|
|
7437
7596
|
async function createServiceProviderInvite(req, res, next) {
|
|
7438
7597
|
const payload = req.body;
|
|
7439
7598
|
const validation = Joi16.object({
|
|
@@ -7575,7 +7734,8 @@ function useVerificationController() {
|
|
|
7575
7734
|
createServiceProviderInvite,
|
|
7576
7735
|
createForgetPassword,
|
|
7577
7736
|
verify,
|
|
7578
|
-
cancelUserInvitation
|
|
7737
|
+
cancelUserInvitation,
|
|
7738
|
+
createSimpleUserInvite
|
|
7579
7739
|
};
|
|
7580
7740
|
}
|
|
7581
7741
|
|
|
@@ -13369,11 +13529,18 @@ function useVisitorTransactionRepo() {
|
|
|
13369
13529
|
);
|
|
13370
13530
|
}
|
|
13371
13531
|
}
|
|
13372
|
-
async function add(value, session) {
|
|
13532
|
+
async function add(value, session, returnValue = false) {
|
|
13373
13533
|
try {
|
|
13374
13534
|
value = MVisitorTransaction(value);
|
|
13375
13535
|
const res = await collection.insertOne(value, { session });
|
|
13376
|
-
|
|
13536
|
+
if (returnValue) {
|
|
13537
|
+
return {
|
|
13538
|
+
...value,
|
|
13539
|
+
_id: res.insertedId
|
|
13540
|
+
};
|
|
13541
|
+
} else {
|
|
13542
|
+
return res.insertedId;
|
|
13543
|
+
}
|
|
13377
13544
|
} catch (error) {
|
|
13378
13545
|
console.log("Error in add visitor transaction:", error);
|
|
13379
13546
|
const isDuplicated = error.message.includes("duplicate");
|
|
@@ -14727,7 +14894,11 @@ function usePersonRepo() {
|
|
|
14727
14894
|
try {
|
|
14728
14895
|
await collection.createIndexes([
|
|
14729
14896
|
{ key: { contact: 1 } },
|
|
14730
|
-
{ key: { nric: 1 } }
|
|
14897
|
+
{ key: { nric: 1 } },
|
|
14898
|
+
{ key: { user: 1 } },
|
|
14899
|
+
{ key: { site: 1, status: 1 } },
|
|
14900
|
+
{ key: { "plates.plateNumber": 1, status: 1 } },
|
|
14901
|
+
{ key: { unit: 1, status: 1 } }
|
|
14731
14902
|
]);
|
|
14732
14903
|
} catch (error) {
|
|
14733
14904
|
throw new InternalServerError26("Failed to create index on site people.");
|
|
@@ -16705,6 +16876,9 @@ function useVehicleService() {
|
|
|
16705
16876
|
const _end = vehicle.end;
|
|
16706
16877
|
const _recNo = plate.recNo;
|
|
16707
16878
|
const _type = value.type ? value.type : plate.type;
|
|
16879
|
+
if (value.peopleId) {
|
|
16880
|
+
value.peopleId = new ObjectId46(value.peopleId);
|
|
16881
|
+
}
|
|
16708
16882
|
const { name, plateNumber, start, end, recNo, type, unit, site, ...rest } = value;
|
|
16709
16883
|
const startDahua = value.start ? formatDahuaDate(new Date(value.start)) : formatDahuaDate(new Date(_start));
|
|
16710
16884
|
const endDahua = value.end ? formatDahuaDate(new Date(value.end)) : formatDahuaDate(new Date(_end));
|
|
@@ -16768,6 +16942,17 @@ function useVehicleService() {
|
|
|
16768
16942
|
}
|
|
16769
16943
|
const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
|
|
16770
16944
|
value.recNo = responseData.split("=")[1]?.trim();
|
|
16945
|
+
const normalizedPlateNumber = Array.isArray(plateNumber) ? plateNumber[0] : plateNumber;
|
|
16946
|
+
if (value.peopleId && value.recNo) {
|
|
16947
|
+
await _pushVehicleById(
|
|
16948
|
+
value.peopleId,
|
|
16949
|
+
{
|
|
16950
|
+
plateNumber: normalizedPlateNumber,
|
|
16951
|
+
recNo: value.recNo
|
|
16952
|
+
},
|
|
16953
|
+
session
|
|
16954
|
+
);
|
|
16955
|
+
}
|
|
16771
16956
|
} else {
|
|
16772
16957
|
const dahuaPayload = {
|
|
16773
16958
|
host,
|
|
@@ -16781,6 +16966,17 @@ function useVehicleService() {
|
|
|
16781
16966
|
owner: name ? name : _name
|
|
16782
16967
|
};
|
|
16783
16968
|
const dahuaResponse = await _updatePlateNumber(dahuaPayload);
|
|
16969
|
+
const normalizedPlateNumber = Array.isArray(plateNumber) ? plateNumber[0] : plateNumber;
|
|
16970
|
+
if (value.peopleId && value.recNo) {
|
|
16971
|
+
await _pushVehicleById(
|
|
16972
|
+
value.peopleId,
|
|
16973
|
+
{
|
|
16974
|
+
plateNumber: normalizedPlateNumber,
|
|
16975
|
+
recNo: _recNo
|
|
16976
|
+
},
|
|
16977
|
+
session
|
|
16978
|
+
);
|
|
16979
|
+
}
|
|
16784
16980
|
if (dahuaResponse?.statusCode !== 200) {
|
|
16785
16981
|
throw new BadRequestError72(
|
|
16786
16982
|
"Failed to update plate number to ANPR"
|
|
@@ -16975,7 +17171,7 @@ function useDahuaService() {
|
|
|
16975
17171
|
const { createFile: _createFile } = useFileService();
|
|
16976
17172
|
let currentTransactionId = null;
|
|
16977
17173
|
let currentSnapshotField = null;
|
|
16978
|
-
function useBufferQueue(boundary, site, gate, designation, host, username, password) {
|
|
17174
|
+
function useBufferQueue(boundary, site, gate, designation, host, username, password, onDetected) {
|
|
16979
17175
|
const queue = [];
|
|
16980
17176
|
let processing = false;
|
|
16981
17177
|
let plateNumber = null;
|
|
@@ -17008,7 +17204,7 @@ function useDahuaService() {
|
|
|
17008
17204
|
);
|
|
17009
17205
|
streamRef.pause();
|
|
17010
17206
|
}
|
|
17011
|
-
processNext();
|
|
17207
|
+
processNext(onDetected);
|
|
17012
17208
|
}
|
|
17013
17209
|
function destroy() {
|
|
17014
17210
|
queue.length = 0;
|
|
@@ -17024,30 +17220,30 @@ function useDahuaService() {
|
|
|
17024
17220
|
`[${site}][${gate}] BufferQueue destroyed. Processed=${processedChunks}, Dropped=${droppedChunks}`
|
|
17025
17221
|
);
|
|
17026
17222
|
}
|
|
17027
|
-
async function processNext() {
|
|
17223
|
+
async function processNext(onDetected2) {
|
|
17028
17224
|
if (processing || queue.length === 0)
|
|
17029
17225
|
return;
|
|
17030
17226
|
processing = true;
|
|
17031
17227
|
const buffer = queue.shift();
|
|
17032
17228
|
try {
|
|
17033
|
-
await handleBuffer(buffer);
|
|
17229
|
+
await handleBuffer(buffer, onDetected2);
|
|
17034
17230
|
processedChunks++;
|
|
17035
17231
|
if (queue.length <= RESUME_THRESHOLD && streamRef && streamRef.isPaused()) {
|
|
17036
17232
|
loggerDahua.info(
|
|
17037
|
-
`[${
|
|
17233
|
+
`[${host}]Queue at ${queue.length}/${MAX_QUEUE_SIZE}, resuming stream`
|
|
17038
17234
|
);
|
|
17039
17235
|
streamRef.resume();
|
|
17040
17236
|
}
|
|
17041
17237
|
} catch (err) {
|
|
17042
|
-
loggerDahua.error(`[${
|
|
17238
|
+
loggerDahua.error(`[${host}] Error processing buffer:`, err);
|
|
17043
17239
|
} finally {
|
|
17044
17240
|
processing = false;
|
|
17045
|
-
processNext();
|
|
17241
|
+
processNext(onDetected2);
|
|
17046
17242
|
}
|
|
17047
17243
|
}
|
|
17048
|
-
async function processVehicleTransaction() {
|
|
17244
|
+
async function processVehicleTransaction(onDetected2) {
|
|
17049
17245
|
loggerDahua.info(
|
|
17050
|
-
`[${
|
|
17246
|
+
`[${host}] Vehicle transaction: Plate=${plateNumber}, UTC=${UTCData}, UTCMs=${UTCMs}`
|
|
17051
17247
|
);
|
|
17052
17248
|
let org = "";
|
|
17053
17249
|
try {
|
|
@@ -17055,7 +17251,7 @@ function useDahuaService() {
|
|
|
17055
17251
|
org = theSite?.orgId.toString() || "unknown";
|
|
17056
17252
|
} catch (error) {
|
|
17057
17253
|
loggerDahua.error(
|
|
17058
|
-
`[${
|
|
17254
|
+
`[${host}] Error fetching site for orgId:`,
|
|
17059
17255
|
error
|
|
17060
17256
|
);
|
|
17061
17257
|
}
|
|
@@ -17075,7 +17271,7 @@ function useDahuaService() {
|
|
|
17075
17271
|
}
|
|
17076
17272
|
} catch (error) {
|
|
17077
17273
|
loggerDahua.error(
|
|
17078
|
-
`[${
|
|
17274
|
+
`[${host}] Error closing existing open transaction:`,
|
|
17079
17275
|
error
|
|
17080
17276
|
);
|
|
17081
17277
|
}
|
|
@@ -17125,9 +17321,13 @@ function useDahuaService() {
|
|
|
17125
17321
|
}
|
|
17126
17322
|
try {
|
|
17127
17323
|
await addPlateNumber(dahuaPayload);
|
|
17128
|
-
const
|
|
17129
|
-
|
|
17324
|
+
const result = await add(visitorTransaction, void 0, true);
|
|
17325
|
+
const transactionId = result?._id;
|
|
17326
|
+
currentTransactionId = transactionId?.toString();
|
|
17130
17327
|
currentSnapshotField = "snapshotEntryImage";
|
|
17328
|
+
if (onDetected2) {
|
|
17329
|
+
onDetected2({ _id: transactionId, site: result?.site?.toString(), plateNumber: result.plateNumber });
|
|
17330
|
+
}
|
|
17131
17331
|
} catch (error) {
|
|
17132
17332
|
console.log("failed to create visitor transaction", error);
|
|
17133
17333
|
loggerDahua.error(
|
|
@@ -17161,7 +17361,7 @@ function useDahuaService() {
|
|
|
17161
17361
|
}
|
|
17162
17362
|
}
|
|
17163
17363
|
}
|
|
17164
|
-
async function handleBuffer(chunk) {
|
|
17364
|
+
async function handleBuffer(chunk, onDetected2) {
|
|
17165
17365
|
partialBuffer = Buffer.concat([partialBuffer, chunk]);
|
|
17166
17366
|
while (true) {
|
|
17167
17367
|
const boundaryIndex = partialBuffer.indexOf(Buffer.from(boundary));
|
|
@@ -17187,7 +17387,7 @@ function useDahuaService() {
|
|
|
17187
17387
|
direction = line.split("=")[1].trim();
|
|
17188
17388
|
});
|
|
17189
17389
|
if (plateNumber && UTCData) {
|
|
17190
|
-
await processVehicleTransaction();
|
|
17390
|
+
await processVehicleTransaction(onDetected2);
|
|
17191
17391
|
}
|
|
17192
17392
|
} else if (part.includes("Content-Type: image/jpeg")) {
|
|
17193
17393
|
const [headers, ...imageParts] = part.split("\r\n\r\n");
|
|
@@ -17214,7 +17414,7 @@ function useDahuaService() {
|
|
|
17214
17414
|
try {
|
|
17215
17415
|
await fsAsync.mkdir(dir, { recursive: true });
|
|
17216
17416
|
await fsAsync.writeFile(snapFolder, accumulatedImageBuffer);
|
|
17217
|
-
loggerDahua.debug(`[${
|
|
17417
|
+
loggerDahua.debug(`[${host}] Saved image locally: ${filename}`);
|
|
17218
17418
|
const fileId = await _createFile(
|
|
17219
17419
|
{
|
|
17220
17420
|
originalname: filename,
|
|
@@ -17224,7 +17424,7 @@ function useDahuaService() {
|
|
|
17224
17424
|
`anpr/${site}`
|
|
17225
17425
|
);
|
|
17226
17426
|
loggerDahua.info(
|
|
17227
|
-
`[${
|
|
17427
|
+
`[${host}] Created file record for image: ${fileId.toString()}`
|
|
17228
17428
|
);
|
|
17229
17429
|
if (currentTransactionId && currentSnapshotField) {
|
|
17230
17430
|
await updateById(currentTransactionId, {
|
|
@@ -17232,23 +17432,23 @@ function useDahuaService() {
|
|
|
17232
17432
|
});
|
|
17233
17433
|
}
|
|
17234
17434
|
loggerDahua.info(
|
|
17235
|
-
`[${
|
|
17435
|
+
`[${host}] Image stored with fileId: ${fileId.toString()}`
|
|
17236
17436
|
);
|
|
17237
17437
|
await fsAsync.unlink(snapFolder);
|
|
17238
|
-
loggerDahua.
|
|
17438
|
+
loggerDahua.info(`[${host}] Deleted local file: ${filename}`);
|
|
17239
17439
|
} catch (err) {
|
|
17240
17440
|
loggerDahua.error(
|
|
17241
|
-
`[${
|
|
17441
|
+
`[${host}] Failed to process image ${filename}:`,
|
|
17242
17442
|
err
|
|
17243
17443
|
);
|
|
17244
17444
|
try {
|
|
17245
17445
|
await fsAsync.unlink(snapFolder);
|
|
17246
|
-
loggerDahua.
|
|
17247
|
-
`[${
|
|
17446
|
+
loggerDahua.error(
|
|
17447
|
+
`[${host}] Cleaned up local file after error: ${filename}`
|
|
17248
17448
|
);
|
|
17249
17449
|
} catch (unlinkErr) {
|
|
17250
17450
|
loggerDahua.error(
|
|
17251
|
-
`[${
|
|
17451
|
+
`[${host}] Failed to clean up local file: ${filename}`,
|
|
17252
17452
|
unlinkErr
|
|
17253
17453
|
);
|
|
17254
17454
|
}
|
|
@@ -17288,7 +17488,7 @@ function useDahuaService() {
|
|
|
17288
17488
|
throw error;
|
|
17289
17489
|
}
|
|
17290
17490
|
}
|
|
17291
|
-
async function listenToCamera(camera) {
|
|
17491
|
+
async function listenToCamera(camera, onDetected) {
|
|
17292
17492
|
if (!camera?._id) {
|
|
17293
17493
|
loggerDahua.error(`Camera _id is required to listen to camera.`);
|
|
17294
17494
|
throw new BadRequestError73("Camera _id is required to listen to camera.");
|
|
@@ -17309,10 +17509,11 @@ function useDahuaService() {
|
|
|
17309
17509
|
`guard-post-${camera.guardPost}`,
|
|
17310
17510
|
camera.direction,
|
|
17311
17511
|
cameraId,
|
|
17312
|
-
controller.signal
|
|
17512
|
+
controller.signal,
|
|
17513
|
+
onDetected
|
|
17313
17514
|
);
|
|
17314
17515
|
}
|
|
17315
|
-
async function
|
|
17516
|
+
async function getTrafficJunctionOld(host = "", username = "", password = "", site = "", gate = "", designation = "", cameraId, signal, onDetected) {
|
|
17316
17517
|
if (signal.aborted)
|
|
17317
17518
|
return;
|
|
17318
17519
|
try {
|
|
@@ -17335,7 +17536,8 @@ function useDahuaService() {
|
|
|
17335
17536
|
designation,
|
|
17336
17537
|
host,
|
|
17337
17538
|
username,
|
|
17338
|
-
password
|
|
17539
|
+
password,
|
|
17540
|
+
onDetected
|
|
17339
17541
|
);
|
|
17340
17542
|
bufferQueue.setStream(response.res);
|
|
17341
17543
|
const onAbort = () => {
|
|
@@ -17389,7 +17591,7 @@ function useDahuaService() {
|
|
|
17389
17591
|
await new Promise((res) => setTimeout(res, 5e3));
|
|
17390
17592
|
if (signal.aborted)
|
|
17391
17593
|
return;
|
|
17392
|
-
getTrafficJunction(host, username, password, site, gate, designation, cameraId, signal);
|
|
17594
|
+
getTrafficJunction(host, username, password, site, gate, designation, cameraId, signal, onDetected);
|
|
17393
17595
|
};
|
|
17394
17596
|
response.res.on(
|
|
17395
17597
|
"end",
|
|
@@ -17413,8 +17615,87 @@ function useDahuaService() {
|
|
|
17413
17615
|
await new Promise((res) => setTimeout(res, 5e3));
|
|
17414
17616
|
if (signal.aborted)
|
|
17415
17617
|
return;
|
|
17416
|
-
getTrafficJunction(host, username, password, site, gate, designation, cameraId, signal);
|
|
17618
|
+
getTrafficJunction(host, username, password, site, gate, designation, cameraId, signal, onDetected);
|
|
17619
|
+
}
|
|
17620
|
+
}
|
|
17621
|
+
async function getTrafficJunction(host = "", username = "", password = "", site = "", gate = "", designation = "", cameraId, signal, onDetected) {
|
|
17622
|
+
while (!signal.aborted) {
|
|
17623
|
+
let bufferQueue = null;
|
|
17624
|
+
let response = null;
|
|
17625
|
+
try {
|
|
17626
|
+
response = await useDahuaDigest({
|
|
17627
|
+
host,
|
|
17628
|
+
username,
|
|
17629
|
+
password,
|
|
17630
|
+
endpoint: "/cgi-bin/snapManager.cgi?action=attachFileProc&channel=1&heartbeat=5&Flags[0]=Event&Events=[TrafficJunction]",
|
|
17631
|
+
timeout: 2e4,
|
|
17632
|
+
streaming: true
|
|
17633
|
+
});
|
|
17634
|
+
if ([400, 401, 403, 500].includes(response.statusCode)) {
|
|
17635
|
+
loggerDahua.error(`[${host}] Connection error: ${response.statusCode}`);
|
|
17636
|
+
throw new Error(`Failed to connect to ANPR: ${response.statusCode}`);
|
|
17637
|
+
}
|
|
17638
|
+
loggerDahua.info(`[${host}] Successfully connected to ANPR.`);
|
|
17639
|
+
const contentType = response.res.headers["content-type"];
|
|
17640
|
+
const boundaryMatch = contentType?.match(/boundary=(.*)$/i);
|
|
17641
|
+
const boundary = boundaryMatch ? `--${boundaryMatch[1]}` : "--myboundary";
|
|
17642
|
+
bufferQueue = useBufferQueue(
|
|
17643
|
+
boundary,
|
|
17644
|
+
site,
|
|
17645
|
+
gate,
|
|
17646
|
+
designation,
|
|
17647
|
+
host,
|
|
17648
|
+
username,
|
|
17649
|
+
password,
|
|
17650
|
+
onDetected
|
|
17651
|
+
);
|
|
17652
|
+
bufferQueue.setStream(response.res);
|
|
17653
|
+
await new Promise((resolve, reject) => {
|
|
17654
|
+
const onAbort = () => {
|
|
17655
|
+
loggerDahua.info(`[${site}]-[${host}] Abort triggered. Cleaning up...`);
|
|
17656
|
+
if (response.res && !response.res.destroyed) {
|
|
17657
|
+
response.res.destroy();
|
|
17658
|
+
}
|
|
17659
|
+
resolve("aborted");
|
|
17660
|
+
};
|
|
17661
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
17662
|
+
response.res.on("data", (chunk) => {
|
|
17663
|
+
if (signal.aborted) {
|
|
17664
|
+
response.res.destroy();
|
|
17665
|
+
return;
|
|
17666
|
+
}
|
|
17667
|
+
bufferQueue.enqueue(chunk);
|
|
17668
|
+
});
|
|
17669
|
+
response.res.on("end", () => {
|
|
17670
|
+
signal.removeEventListener("abort", onAbort);
|
|
17671
|
+
resolve("ended");
|
|
17672
|
+
});
|
|
17673
|
+
response.res.on("close", () => {
|
|
17674
|
+
signal.removeEventListener("abort", onAbort);
|
|
17675
|
+
resolve("closed");
|
|
17676
|
+
});
|
|
17677
|
+
response.res.on("error", (err) => {
|
|
17678
|
+
signal.removeEventListener("abort", onAbort);
|
|
17679
|
+
reject(err);
|
|
17680
|
+
});
|
|
17681
|
+
});
|
|
17682
|
+
} catch (error) {
|
|
17683
|
+
if (signal.aborted)
|
|
17684
|
+
break;
|
|
17685
|
+
loggerDahua.error(
|
|
17686
|
+
`[${host}] Connection lost or error: ${error.message || error}. Retrying in 5s...`
|
|
17687
|
+
);
|
|
17688
|
+
} finally {
|
|
17689
|
+
if (bufferQueue?.destroy)
|
|
17690
|
+
bufferQueue.destroy();
|
|
17691
|
+
if (response?.res && !response.res.destroyed)
|
|
17692
|
+
response.res.destroy();
|
|
17693
|
+
}
|
|
17694
|
+
if (!signal.aborted) {
|
|
17695
|
+
await new Promise((res) => setTimeout(res, 5e3));
|
|
17696
|
+
}
|
|
17417
17697
|
}
|
|
17698
|
+
loggerDahua.info(`[${host}] ANPR Listener stopped.`);
|
|
17418
17699
|
}
|
|
17419
17700
|
async function addPlateNumber(value) {
|
|
17420
17701
|
const validation = Joi40.object({
|
|
@@ -19545,7 +19826,7 @@ function useVehicleController() {
|
|
|
19545
19826
|
next(new BadRequestError84("Spreadsheet file is required."));
|
|
19546
19827
|
return;
|
|
19547
19828
|
}
|
|
19548
|
-
const { originalname, path:
|
|
19829
|
+
const { originalname, path: path4 } = req.file;
|
|
19549
19830
|
const lowerName = originalname.toLowerCase();
|
|
19550
19831
|
const rowSchema = Joi46.object({
|
|
19551
19832
|
fullName: Joi46.string().trim().required(),
|
|
@@ -19584,7 +19865,7 @@ function useVehicleController() {
|
|
|
19584
19865
|
let rows = [];
|
|
19585
19866
|
if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
|
|
19586
19867
|
const workbook = new ExcelJS.Workbook();
|
|
19587
|
-
await workbook.xlsx.readFile(
|
|
19868
|
+
await workbook.xlsx.readFile(path4);
|
|
19588
19869
|
const worksheet = workbook.worksheets[0];
|
|
19589
19870
|
if (!worksheet) {
|
|
19590
19871
|
next(
|
|
@@ -19610,7 +19891,7 @@ function useVehicleController() {
|
|
|
19610
19891
|
} else if (lowerName.endsWith(".csv")) {
|
|
19611
19892
|
rows = await new Promise((resolve, reject) => {
|
|
19612
19893
|
const parsed = [];
|
|
19613
|
-
fs.createReadStream(
|
|
19894
|
+
fs.createReadStream(path4).pipe(csv()).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
|
|
19614
19895
|
});
|
|
19615
19896
|
} else {
|
|
19616
19897
|
next(
|
|
@@ -19649,7 +19930,7 @@ function useVehicleController() {
|
|
|
19649
19930
|
validationErrors: invalidRows,
|
|
19650
19931
|
data
|
|
19651
19932
|
});
|
|
19652
|
-
fs.unlink(
|
|
19933
|
+
fs.unlink(path4, () => {
|
|
19653
19934
|
});
|
|
19654
19935
|
} catch (error) {
|
|
19655
19936
|
logger65.log({ level: "error", message: error.message });
|
|
@@ -19790,7 +20071,9 @@ function useVehicleController() {
|
|
|
19790
20071
|
start: Joi46.string().isoDate().optional().allow(null, ""),
|
|
19791
20072
|
end: Joi46.string().isoDate().optional().allow(null, ""),
|
|
19792
20073
|
recNo: Joi46.string().optional().allow(null, ""),
|
|
19793
|
-
type: Joi46.string().optional().valid(...Object.values(VehicleType)).allow(null, "")
|
|
20074
|
+
type: Joi46.string().optional().valid(...Object.values(VehicleType)).allow(null, ""),
|
|
20075
|
+
peopleId: Joi46.string().hex().length(24).optional().allow(null, ""),
|
|
20076
|
+
seasonPassType: Joi46.string().optional().allow("", null)
|
|
19794
20077
|
});
|
|
19795
20078
|
const { error, value } = schema2.validate(
|
|
19796
20079
|
{
|
|
@@ -20027,7 +20310,7 @@ function useSiteCameraService() {
|
|
|
20027
20310
|
session.endSession();
|
|
20028
20311
|
}
|
|
20029
20312
|
}
|
|
20030
|
-
async function listenToCapturedPlateNumber() {
|
|
20313
|
+
async function listenToCapturedPlateNumber(onDetected) {
|
|
20031
20314
|
const siteCameras = [];
|
|
20032
20315
|
let page = 1;
|
|
20033
20316
|
let pages = 1;
|
|
@@ -20048,7 +20331,7 @@ function useSiteCameraService() {
|
|
|
20048
20331
|
for (let index = 0; index < siteCameras.length; index++) {
|
|
20049
20332
|
const siteCamera = siteCameras[index];
|
|
20050
20333
|
if (siteCamera && siteCamera.status === "active" && siteCamera.host && siteCamera.username && siteCamera.password && siteCamera.site && siteCamera.guardPost) {
|
|
20051
|
-
dahuaService.listenToCamera(siteCamera);
|
|
20334
|
+
dahuaService.listenToCamera(siteCamera, onDetected);
|
|
20052
20335
|
}
|
|
20053
20336
|
}
|
|
20054
20337
|
}
|
|
@@ -24102,7 +24385,6 @@ import {
|
|
|
24102
24385
|
compileHandlebar as compileHandlebar3,
|
|
24103
24386
|
getDirectory as getDirectory3
|
|
24104
24387
|
} from "@7365admin1/node-server-utils";
|
|
24105
|
-
import path2 from "path";
|
|
24106
24388
|
function usePersonService() {
|
|
24107
24389
|
const MailerConfig = {
|
|
24108
24390
|
host: MAILER_TRANSPORT_HOST,
|
|
@@ -24317,13 +24599,8 @@ function usePersonService() {
|
|
|
24317
24599
|
value.status = "active";
|
|
24318
24600
|
}
|
|
24319
24601
|
await _reviewResidentPerson(id, value, session);
|
|
24320
|
-
const logoPath =
|
|
24321
|
-
|
|
24322
|
-
"public",
|
|
24323
|
-
"images",
|
|
24324
|
-
"seven-365.svg"
|
|
24325
|
-
);
|
|
24326
|
-
const statusIconPath = path2.join(__dirname, "public", "icons");
|
|
24602
|
+
const logoPath = `${STORAGE_API}/seven-365.svg`;
|
|
24603
|
+
const statusIconPath = STORAGE_API;
|
|
24327
24604
|
let title = "";
|
|
24328
24605
|
let message2 = "";
|
|
24329
24606
|
let hideLogin = true;
|
|
@@ -25223,11 +25500,7 @@ function usePatrolQuestionRepo() {
|
|
|
25223
25500
|
const { delNamespace, getCache, setCache } = useCache34(namespace_collection);
|
|
25224
25501
|
async function createIndexes() {
|
|
25225
25502
|
try {
|
|
25226
|
-
await collection.createIndexes([
|
|
25227
|
-
{
|
|
25228
|
-
key: { site: 1 }
|
|
25229
|
-
}
|
|
25230
|
-
]);
|
|
25503
|
+
await collection.createIndexes([{ key: { site: 1, status: 1 } }]);
|
|
25231
25504
|
return `Successfully created indexes for ${namespace_collection}.`;
|
|
25232
25505
|
} catch (error) {
|
|
25233
25506
|
logger87.log({
|
|
@@ -25672,6 +25945,24 @@ function usePatrolRouteRepo() {
|
|
|
25672
25945
|
const namespace_collection = "patrol.route";
|
|
25673
25946
|
const collection = db.collection(namespace_collection);
|
|
25674
25947
|
const { delNamespace, getCache, setCache } = useCache35(namespace_collection);
|
|
25948
|
+
async function createIndexes() {
|
|
25949
|
+
try {
|
|
25950
|
+
await collection.createIndexes([
|
|
25951
|
+
{ key: { site: 1, status: 1 } },
|
|
25952
|
+
{ key: { site: 1, repeat: 1 } },
|
|
25953
|
+
{ key: { assignee: 1 } }
|
|
25954
|
+
]);
|
|
25955
|
+
return `Successfully created indexes for ${namespace_collection}.`;
|
|
25956
|
+
} catch (error) {
|
|
25957
|
+
logger90.log({
|
|
25958
|
+
level: "error",
|
|
25959
|
+
message: error.message
|
|
25960
|
+
});
|
|
25961
|
+
throw new InternalServerError36(
|
|
25962
|
+
"Failed to create general indexes on patrol routes."
|
|
25963
|
+
);
|
|
25964
|
+
}
|
|
25965
|
+
}
|
|
25675
25966
|
async function createTextIndex() {
|
|
25676
25967
|
try {
|
|
25677
25968
|
await collection.createIndex({
|
|
@@ -26045,7 +26336,8 @@ function usePatrolRouteRepo() {
|
|
|
26045
26336
|
updateById,
|
|
26046
26337
|
deleteById,
|
|
26047
26338
|
getScheduledRoute,
|
|
26048
|
-
getById
|
|
26339
|
+
getById,
|
|
26340
|
+
createIndexes
|
|
26049
26341
|
};
|
|
26050
26342
|
}
|
|
26051
26343
|
|
|
@@ -26392,9 +26684,8 @@ function usePatrolLogRepo() {
|
|
|
26392
26684
|
async function createIndexes() {
|
|
26393
26685
|
try {
|
|
26394
26686
|
await collection.createIndexes([
|
|
26395
|
-
{
|
|
26396
|
-
|
|
26397
|
-
}
|
|
26687
|
+
{ key: { site: 1, createdAt: -1 } },
|
|
26688
|
+
{ key: { assignee: 1 } }
|
|
26398
26689
|
]);
|
|
26399
26690
|
return `Successfully created indexes for ${namespace_collection}.`;
|
|
26400
26691
|
} catch (error) {
|
|
@@ -30285,6 +30576,20 @@ function useSiteBillingItemRepo() {
|
|
|
30285
30576
|
const namespace_collection = "site.billing.items";
|
|
30286
30577
|
const collection = db.collection(namespace_collection);
|
|
30287
30578
|
const { delNamespace, setCache, getCache } = useCache42(namespace_collection);
|
|
30579
|
+
async function createIndexes() {
|
|
30580
|
+
try {
|
|
30581
|
+
await collection.createIndexes([{ key: { site: 1, status: 1 } }]);
|
|
30582
|
+
return `Successfully created indexes for ${namespace_collection}.`;
|
|
30583
|
+
} catch (error) {
|
|
30584
|
+
logger107.log({
|
|
30585
|
+
level: "error",
|
|
30586
|
+
message: error.message
|
|
30587
|
+
});
|
|
30588
|
+
throw new InternalServerError43(
|
|
30589
|
+
"Failed to create general indexes on billing item."
|
|
30590
|
+
);
|
|
30591
|
+
}
|
|
30592
|
+
}
|
|
30288
30593
|
async function createTextIndex() {
|
|
30289
30594
|
try {
|
|
30290
30595
|
await collection.createIndex({
|
|
@@ -30504,7 +30809,8 @@ function useSiteBillingItemRepo() {
|
|
|
30504
30809
|
getAll,
|
|
30505
30810
|
getById,
|
|
30506
30811
|
updateById,
|
|
30507
|
-
deleteById
|
|
30812
|
+
deleteById,
|
|
30813
|
+
createIndexes
|
|
30508
30814
|
};
|
|
30509
30815
|
}
|
|
30510
30816
|
|
|
@@ -30658,6 +30964,20 @@ function useSiteBillingConfigurationRepo() {
|
|
|
30658
30964
|
const namespace_collection = "site.billing.configuration";
|
|
30659
30965
|
const collection = db.collection(namespace_collection);
|
|
30660
30966
|
const { delNamespace, setCache, getCache } = useCache43(namespace_collection);
|
|
30967
|
+
async function createIndexes() {
|
|
30968
|
+
try {
|
|
30969
|
+
await collection.createIndexes([{ key: { site: 1, status: 1 } }]);
|
|
30970
|
+
return `Successfully created indexes for ${namespace_collection}.`;
|
|
30971
|
+
} catch (error) {
|
|
30972
|
+
logger109.log({
|
|
30973
|
+
level: "error",
|
|
30974
|
+
message: error.message
|
|
30975
|
+
});
|
|
30976
|
+
throw new InternalServerError44(
|
|
30977
|
+
"Failed to create general indexes on billing configuration."
|
|
30978
|
+
);
|
|
30979
|
+
}
|
|
30980
|
+
}
|
|
30661
30981
|
async function createTextIndex() {
|
|
30662
30982
|
try {
|
|
30663
30983
|
await collection.createIndex({
|
|
@@ -30867,7 +31187,8 @@ function useSiteBillingConfigurationRepo() {
|
|
|
30867
31187
|
getAll,
|
|
30868
31188
|
getById,
|
|
30869
31189
|
updateById,
|
|
30870
|
-
deleteById
|
|
31190
|
+
deleteById,
|
|
31191
|
+
createIndexes
|
|
30871
31192
|
};
|
|
30872
31193
|
}
|
|
30873
31194
|
|
|
@@ -31929,9 +32250,8 @@ function useEventManagementController() {
|
|
|
31929
32250
|
}
|
|
31930
32251
|
}
|
|
31931
32252
|
async function updateEventManagementById(req, res, next) {
|
|
31932
|
-
const
|
|
31933
|
-
const
|
|
31934
|
-
const { error } = schemaUpdateEventManagement.validate(payload, {
|
|
32253
|
+
const payload = { _id: req.params.id, ...req.body };
|
|
32254
|
+
const { error, value } = schemaUpdateEventManagement.validate(payload, {
|
|
31935
32255
|
abortEarly: false
|
|
31936
32256
|
});
|
|
31937
32257
|
if (error) {
|
|
@@ -31940,8 +32260,9 @@ function useEventManagementController() {
|
|
|
31940
32260
|
next(new BadRequestError137(messages));
|
|
31941
32261
|
return;
|
|
31942
32262
|
}
|
|
32263
|
+
const { _id, ...rest } = value;
|
|
31943
32264
|
try {
|
|
31944
|
-
const result = await _updateEventManagementById(_id,
|
|
32265
|
+
const result = await _updateEventManagementById(_id, rest);
|
|
31945
32266
|
res.status(200).json({ message: result });
|
|
31946
32267
|
return;
|
|
31947
32268
|
} catch (error2) {
|
|
@@ -32170,6 +32491,25 @@ function useSiteUnitBillingRepo() {
|
|
|
32170
32491
|
const namespace_collection = "site.unit.billing";
|
|
32171
32492
|
const collection = db.collection(namespace_collection);
|
|
32172
32493
|
const { delNamespace, setCache, getCache } = useCache45(namespace_collection);
|
|
32494
|
+
async function createIndexes() {
|
|
32495
|
+
try {
|
|
32496
|
+
await collection.createIndexes([
|
|
32497
|
+
{ key: { site: 1, status: 1, paymentStatus: 1 } },
|
|
32498
|
+
{ key: { site: 1, unitId: 1, status: 1, paymentStatus: 1 } },
|
|
32499
|
+
{ key: { site: 1, unitId: 1, issueDate: 1 } },
|
|
32500
|
+
{ key: { createdAt: -1 } }
|
|
32501
|
+
]);
|
|
32502
|
+
return `Successfully created indexes for ${namespace_collection}.`;
|
|
32503
|
+
} catch (error) {
|
|
32504
|
+
logger117.log({
|
|
32505
|
+
level: "error",
|
|
32506
|
+
message: error.message
|
|
32507
|
+
});
|
|
32508
|
+
throw new InternalServerError46(
|
|
32509
|
+
"Failed to create general indexes on unit billing."
|
|
32510
|
+
);
|
|
32511
|
+
}
|
|
32512
|
+
}
|
|
32173
32513
|
async function createTextIndex() {
|
|
32174
32514
|
try {
|
|
32175
32515
|
await collection.createIndex({
|
|
@@ -32723,7 +33063,8 @@ function useSiteUnitBillingRepo() {
|
|
|
32723
33063
|
deleteById,
|
|
32724
33064
|
getUnitBillingBySite,
|
|
32725
33065
|
getResidentUserBilling,
|
|
32726
|
-
getResidentUserUnsettledBilling
|
|
33066
|
+
getResidentUserUnsettledBilling,
|
|
33067
|
+
createIndexes
|
|
32727
33068
|
};
|
|
32728
33069
|
}
|
|
32729
33070
|
|
|
@@ -33286,7 +33627,7 @@ import { ObjectId as ObjectId90 } from "mongodb";
|
|
|
33286
33627
|
|
|
33287
33628
|
// src/utils/access-management.ts
|
|
33288
33629
|
import fs2 from "fs";
|
|
33289
|
-
import
|
|
33630
|
+
import path2 from "path";
|
|
33290
33631
|
import axios from "axios";
|
|
33291
33632
|
import { parseStringPromise } from "xml2js";
|
|
33292
33633
|
import crypto from "crypto";
|
|
@@ -33316,7 +33657,7 @@ var minifyXml = (xml) => {
|
|
|
33316
33657
|
};
|
|
33317
33658
|
var readTemplate = (name, params) => {
|
|
33318
33659
|
const template = fs2.readFileSync(
|
|
33319
|
-
|
|
33660
|
+
path2.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
|
|
33320
33661
|
"utf-8"
|
|
33321
33662
|
);
|
|
33322
33663
|
if (!params)
|
|
@@ -33447,9 +33788,9 @@ import { parseStringPromise as parseStringPromise2 } from "xml2js";
|
|
|
33447
33788
|
// src/utils/rsa-encryption.ts
|
|
33448
33789
|
import * as crypto2 from "crypto";
|
|
33449
33790
|
import fs3 from "fs";
|
|
33450
|
-
import
|
|
33451
|
-
var pub =
|
|
33452
|
-
var priv =
|
|
33791
|
+
import path3 from "path";
|
|
33792
|
+
var pub = path3.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
|
|
33793
|
+
var priv = path3.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
|
|
33453
33794
|
var EncryptionCredentials = class {
|
|
33454
33795
|
};
|
|
33455
33796
|
EncryptionCredentials.RAW_PUBLIC_KEY = fs3.readFileSync(pub, "utf8");
|
|
@@ -38581,6 +38922,22 @@ function useStatementOfAccountRepo() {
|
|
|
38581
38922
|
const namespace_collection = "site.statement-of-accounts";
|
|
38582
38923
|
const collection = db.collection(namespace_collection);
|
|
38583
38924
|
const { delNamespace, getCache, setCache } = useCache50(namespace_collection);
|
|
38925
|
+
async function createIndexes() {
|
|
38926
|
+
try {
|
|
38927
|
+
await collection.createIndexes([
|
|
38928
|
+
{ key: { site: 1, status: 1 } },
|
|
38929
|
+
{ key: { site: 1, unitId: 1, status: 1 } },
|
|
38930
|
+
{ key: { createdAt: -1 } }
|
|
38931
|
+
]);
|
|
38932
|
+
return `Successfully created indexes for ${namespace_collection}.`;
|
|
38933
|
+
} catch (error) {
|
|
38934
|
+
logger128.log({
|
|
38935
|
+
level: "error",
|
|
38936
|
+
message: error.message
|
|
38937
|
+
});
|
|
38938
|
+
throw new InternalServerError51("Failed to create general indexes on SOA.");
|
|
38939
|
+
}
|
|
38940
|
+
}
|
|
38584
38941
|
async function createTextIndex() {
|
|
38585
38942
|
try {
|
|
38586
38943
|
await collection.createIndex({
|
|
@@ -38931,7 +39288,8 @@ function useStatementOfAccountRepo() {
|
|
|
38931
39288
|
deleteById,
|
|
38932
39289
|
updateStatusById,
|
|
38933
39290
|
getResidentUserSoa,
|
|
38934
|
-
reviewSOA
|
|
39291
|
+
reviewSOA,
|
|
39292
|
+
createIndexes
|
|
38935
39293
|
};
|
|
38936
39294
|
}
|
|
38937
39295
|
|
|
@@ -42556,7 +42914,10 @@ function useOccurrenceEntryService() {
|
|
|
42556
42914
|
updateOccurrenceEntryById: _updateOccurrenceEntryById,
|
|
42557
42915
|
getOccurrenceEntryById: _getOccurrenceEntryById,
|
|
42558
42916
|
getOccurrenceEntryByBookId: _getOccurrenceEntryByBookId,
|
|
42559
|
-
updateOccurrenceEntryByBookId: _updateOccurrenceEntryByBookId
|
|
42917
|
+
updateOccurrenceEntryByBookId: _updateOccurrenceEntryByBookId,
|
|
42918
|
+
deleteOccurrenceEntryById: _deleteOccurrenceEntryById,
|
|
42919
|
+
getLatestSerialNumber: _getLatestSerialNumber,
|
|
42920
|
+
getLatestSerialNumberInGroup: _getLatestSerialNumberInGroup
|
|
42560
42921
|
} = useOccurrenceEntryRepo();
|
|
42561
42922
|
const {
|
|
42562
42923
|
getOccurrenceBookById: _getOccurrenceBookById,
|
|
@@ -42608,8 +42969,20 @@ function useOccurrenceEntryService() {
|
|
|
42608
42969
|
if (!occurrenceEntry) {
|
|
42609
42970
|
throw new Error("Occurrence entry not found.");
|
|
42610
42971
|
}
|
|
42611
|
-
const
|
|
42612
|
-
|
|
42972
|
+
const entryCount = await _getLatestSerialNumberInGroup(
|
|
42973
|
+
occurrenceEntry.dailyOccurrenceBookId,
|
|
42974
|
+
Number(occurrenceEntry.serialNumber)
|
|
42975
|
+
);
|
|
42976
|
+
const currentSerial = Number(occurrenceEntry.serialNumber);
|
|
42977
|
+
const latestSerial = Number(entryCount);
|
|
42978
|
+
const currentGroup = Math.floor(currentSerial);
|
|
42979
|
+
const latestGroup = Math.floor(latestSerial);
|
|
42980
|
+
let updatedSerialNumber;
|
|
42981
|
+
if (currentGroup === latestGroup) {
|
|
42982
|
+
updatedSerialNumber = (latestSerial + 0.1).toFixed(1);
|
|
42983
|
+
} else {
|
|
42984
|
+
updatedSerialNumber = (currentSerial + 0.1).toFixed(1);
|
|
42985
|
+
}
|
|
42613
42986
|
const dobId = occurrenceEntry.dailyOccurrenceBookId;
|
|
42614
42987
|
const book = await _getOccurrenceBookById(dobId);
|
|
42615
42988
|
const subject = await _getOccurrenceSubjectById(
|
|
@@ -44659,14 +45032,15 @@ async function hrmLabsAuthentication({
|
|
|
44659
45032
|
showPassword: false
|
|
44660
45033
|
},
|
|
44661
45034
|
{
|
|
44662
|
-
headers: { "Content-Type": "application/json" }
|
|
45035
|
+
headers: { "Content-Type": "application/json" },
|
|
45036
|
+
validateStatus: () => true
|
|
44663
45037
|
}
|
|
44664
45038
|
);
|
|
44665
45039
|
if (res.data?.success && res.data.data?.token) {
|
|
44666
45040
|
return res.data.data.token;
|
|
44667
45041
|
}
|
|
44668
45042
|
throw new Error(
|
|
44669
|
-
"HRMLabs Authentication failed. Please check your credentials."
|
|
45043
|
+
res.status === 401 || res.status === 403 ? "HRMLabs Authentication failed. Please check your credentials." : `HRMLabs Authentication failed with status ${res.status}.`
|
|
44670
45044
|
);
|
|
44671
45045
|
}
|
|
44672
45046
|
async function fetchAttendanceData({
|
|
@@ -45103,7 +45477,9 @@ function useManpowerMonitoringRepo() {
|
|
|
45103
45477
|
{
|
|
45104
45478
|
key: { siteId: 1 }
|
|
45105
45479
|
},
|
|
45106
|
-
{ key: { createdAt: 1 } }
|
|
45480
|
+
{ key: { createdAt: 1 } },
|
|
45481
|
+
{ key: { siteId: 1, serviceProviderId: 1 } },
|
|
45482
|
+
{ key: { siteName: 1 } }
|
|
45107
45483
|
]);
|
|
45108
45484
|
return `Successfully created indexes for ${namespace_collection}.`;
|
|
45109
45485
|
} catch (error) {
|
|
@@ -45372,7 +45748,9 @@ function useManpowerRemarksRepo() {
|
|
|
45372
45748
|
{
|
|
45373
45749
|
key: { siteId: 1 }
|
|
45374
45750
|
},
|
|
45375
|
-
{ key: { createdAt: 1 } }
|
|
45751
|
+
{ key: { createdAt: 1 } },
|
|
45752
|
+
{ key: { siteId: 1, serviceProviderId: 1, createdAtSGT: 1 } },
|
|
45753
|
+
{ key: { serviceProviderId: 1, status: 1, createdAtSGT: 1 } }
|
|
45376
45754
|
]);
|
|
45377
45755
|
return `Successfully created indexes for ${namespace_collection}.`;
|
|
45378
45756
|
} catch (error) {
|
|
@@ -45805,7 +46183,8 @@ function useManpowerDesignationRepo() {
|
|
|
45805
46183
|
{
|
|
45806
46184
|
key: { siteId: 1 }
|
|
45807
46185
|
},
|
|
45808
|
-
{ key: { createdAt: 1 } }
|
|
46186
|
+
{ key: { createdAt: 1 } },
|
|
46187
|
+
{ key: { siteId: 1, serviceProviderId: 1 } }
|
|
45809
46188
|
]);
|
|
45810
46189
|
return `Successfully created indexes for ${namespace_collection}.`;
|
|
45811
46190
|
} catch (error) {
|
|
@@ -46890,7 +47269,7 @@ function useHrmLabsAttendanceSrvc() {
|
|
|
46890
47269
|
} catch (error) {
|
|
46891
47270
|
logger168.error(error.message || error);
|
|
46892
47271
|
console.log("Error fetching attendance data:", error);
|
|
46893
|
-
|
|
47272
|
+
return { success: false, message: error?.message || "Internal Server Error!", items: [], pages: 0, pageRange: "0-0 of 0", count: {} };
|
|
46894
47273
|
}
|
|
46895
47274
|
}
|
|
46896
47275
|
async function getAttendanceDataCount(payload) {
|
|
@@ -47004,7 +47383,7 @@ function useHrmLabsAttendanceSrvc() {
|
|
|
47004
47383
|
} catch (error) {
|
|
47005
47384
|
logger168.error(error.message || error);
|
|
47006
47385
|
console.log("Error fetching attendance data count:", error);
|
|
47007
|
-
|
|
47386
|
+
return { success: false, message: error?.message || "Internal Server Error!", totalCount: null };
|
|
47008
47387
|
}
|
|
47009
47388
|
}
|
|
47010
47389
|
async function getAllAttendance(payload) {
|
|
@@ -47176,7 +47555,7 @@ function useHrmLabsAttendanceSrvc() {
|
|
|
47176
47555
|
} catch (error) {
|
|
47177
47556
|
logger168.error(error.message || error);
|
|
47178
47557
|
console.log("Error fetching attendance data:", error);
|
|
47179
|
-
|
|
47558
|
+
return { success: false, message: error?.message || "Internal Server Error!", items: [], count: {}, countPerJobTitle: {}, totalCount: null, countPerStatus: {} };
|
|
47180
47559
|
}
|
|
47181
47560
|
}
|
|
47182
47561
|
async function getChartAttendanceData(payload) {
|
|
@@ -47283,7 +47662,7 @@ function useHrmLabsAttendanceSrvc() {
|
|
|
47283
47662
|
} catch (error) {
|
|
47284
47663
|
logger168.error(error.message || error);
|
|
47285
47664
|
console.log("Error fetching attendance data:", error);
|
|
47286
|
-
|
|
47665
|
+
return { success: false, message: error?.message || "Internal Server Error!", chartCount: null };
|
|
47287
47666
|
}
|
|
47288
47667
|
}
|
|
47289
47668
|
return {
|
|
@@ -48941,7 +49320,8 @@ function useVerificationServiceV2() {
|
|
|
48941
49320
|
add: _add,
|
|
48942
49321
|
updateVerificationStatusById: _updateVerificationStatusById,
|
|
48943
49322
|
getByVerificationCode: _getByVerificationCode,
|
|
48944
|
-
updateStatusById: _updateStatusById
|
|
49323
|
+
updateStatusById: _updateStatusById,
|
|
49324
|
+
countPendingOrgInvites: _countPendingOrgInvites
|
|
48945
49325
|
} = useVerificationRepoV2();
|
|
48946
49326
|
const {
|
|
48947
49327
|
getUserByEmailStatus: _getUserByEmailStatus,
|
|
@@ -48949,6 +49329,8 @@ function useVerificationServiceV2() {
|
|
|
48949
49329
|
} = useUserRepo();
|
|
48950
49330
|
const { getById: getOrgById, getByEmail: _getByEmail } = useOrgRepo();
|
|
48951
49331
|
const { getSiteById } = useSiteRepo();
|
|
49332
|
+
const { getByOrgId: _getSubscriptionByOrgId } = useSubscriptionRepo();
|
|
49333
|
+
const { countByOrg: _countMemberByOrg } = useMemberRepo();
|
|
48952
49334
|
function errorByType(type, status) {
|
|
48953
49335
|
if ((type === "user-invite" /* USER_INVITE */ || type === "member-invite" /* MEMBER_INVITE */ || type === "service-provider-invite" /* SERVICE_PROVIDER_INVITE */ || type === "service-provider-create-org" /* SERVICE_PROVIDER_CREATE_ORG */) && status === "expired" /* EXPIRED */) {
|
|
48954
49336
|
throw new BadRequestError199(
|
|
@@ -49212,6 +49594,30 @@ function useVerificationServiceV2() {
|
|
|
49212
49594
|
throw error2;
|
|
49213
49595
|
}
|
|
49214
49596
|
}
|
|
49597
|
+
async function createOrganizationInvite({
|
|
49598
|
+
email,
|
|
49599
|
+
metadata
|
|
49600
|
+
}) {
|
|
49601
|
+
const orgId = metadata.org?.toString() ?? "";
|
|
49602
|
+
if (!orgId) {
|
|
49603
|
+
throw new BadRequestError199("Organization is required.");
|
|
49604
|
+
}
|
|
49605
|
+
await getOrgById(orgId);
|
|
49606
|
+
const [subscription, memberCount, pendingInviteCount] = await Promise.all([
|
|
49607
|
+
_getSubscriptionByOrgId(orgId),
|
|
49608
|
+
_countMemberByOrg(orgId),
|
|
49609
|
+
_countPendingOrgInvites(orgId)
|
|
49610
|
+
]);
|
|
49611
|
+
const maxSeats = subscription?.maxSeats ?? 0;
|
|
49612
|
+
if (!maxSeats) {
|
|
49613
|
+
throw new BadRequestError199("No seats configured for organization.");
|
|
49614
|
+
}
|
|
49615
|
+
const usedSeats = memberCount + pendingInviteCount;
|
|
49616
|
+
if (usedSeats >= maxSeats) {
|
|
49617
|
+
throw new BadRequestError199("No available seats for new invitation.");
|
|
49618
|
+
}
|
|
49619
|
+
return createUserInvite({ email, metadata });
|
|
49620
|
+
}
|
|
49215
49621
|
async function createForgetPassword(email) {
|
|
49216
49622
|
const value = {
|
|
49217
49623
|
type: "forget-password" /* FORGET_PASSWORD */,
|
|
@@ -49262,6 +49668,7 @@ function useVerificationServiceV2() {
|
|
|
49262
49668
|
signUp,
|
|
49263
49669
|
verify,
|
|
49264
49670
|
createUserInvite,
|
|
49671
|
+
createOrganizationInvite,
|
|
49265
49672
|
createServiceProviderInvite,
|
|
49266
49673
|
createForgetPassword,
|
|
49267
49674
|
cancelUserInvitation
|
|
@@ -49275,6 +49682,7 @@ function useVerificationControllerV2() {
|
|
|
49275
49682
|
const {
|
|
49276
49683
|
verify: _verify,
|
|
49277
49684
|
createUserInvite: _createUserInvite,
|
|
49685
|
+
createOrganizationInvite: _createOrganizationInvite,
|
|
49278
49686
|
createServiceProviderInvite: _createServiceProviderInvite,
|
|
49279
49687
|
createForgetPassword: _createForgetPassword,
|
|
49280
49688
|
cancelUserInvitation: _cancelUserInvitation
|
|
@@ -49371,6 +49779,44 @@ function useVerificationControllerV2() {
|
|
|
49371
49779
|
return;
|
|
49372
49780
|
}
|
|
49373
49781
|
}
|
|
49782
|
+
async function createOrganizationInvite(req, res, next) {
|
|
49783
|
+
const schema2 = Joi127.object({
|
|
49784
|
+
email: Joi127.string().email().lowercase().required(),
|
|
49785
|
+
role: Joi127.string().hex().length(24).required(),
|
|
49786
|
+
org: Joi127.string().hex().length(24).required(),
|
|
49787
|
+
app: Joi127.string().optional().allow("", null).default("organization"),
|
|
49788
|
+
name: Joi127.string().optional().allow("", null),
|
|
49789
|
+
siteId: Joi127.string().hex().length(24).optional().allow("", null),
|
|
49790
|
+
siteName: Joi127.string().optional().allow("", null)
|
|
49791
|
+
});
|
|
49792
|
+
const { error, value } = schema2.validate(req.body, { abortEarly: false });
|
|
49793
|
+
if (error) {
|
|
49794
|
+
const messages = error.details.map((d) => d.message).join(", ");
|
|
49795
|
+
logger178.log({ level: "error", message: messages });
|
|
49796
|
+
next(new BadRequestError200(messages));
|
|
49797
|
+
return;
|
|
49798
|
+
}
|
|
49799
|
+
try {
|
|
49800
|
+
const { email, app, role, name, org, siteId, siteName } = value;
|
|
49801
|
+
await _createOrganizationInvite({
|
|
49802
|
+
email,
|
|
49803
|
+
metadata: {
|
|
49804
|
+
app,
|
|
49805
|
+
role,
|
|
49806
|
+
name,
|
|
49807
|
+
org,
|
|
49808
|
+
siteId,
|
|
49809
|
+
siteName
|
|
49810
|
+
}
|
|
49811
|
+
});
|
|
49812
|
+
res.status(201).json({ message: "Successfully invited user." });
|
|
49813
|
+
return;
|
|
49814
|
+
} catch (error2) {
|
|
49815
|
+
logger178.log({ level: "error", message: `${error2.message}` });
|
|
49816
|
+
next(error2);
|
|
49817
|
+
return;
|
|
49818
|
+
}
|
|
49819
|
+
}
|
|
49374
49820
|
async function createForgetPassword(req, res, next) {
|
|
49375
49821
|
const schema2 = Joi127.object({
|
|
49376
49822
|
email: Joi127.string().email().lowercase().required()
|
|
@@ -49456,6 +49902,7 @@ function useVerificationControllerV2() {
|
|
|
49456
49902
|
return {
|
|
49457
49903
|
verify,
|
|
49458
49904
|
createUserInvite,
|
|
49905
|
+
createOrganizationInvite,
|
|
49459
49906
|
createServiceProviderInvite,
|
|
49460
49907
|
createForgetPassword,
|
|
49461
49908
|
getVerifications,
|
|
@@ -51256,6 +51703,7 @@ export {
|
|
|
51256
51703
|
vehicles_namespace_collection,
|
|
51257
51704
|
visitors_namespace_collection,
|
|
51258
51705
|
workOrderSchema,
|
|
51706
|
+
work_orders2_namespace_collection,
|
|
51259
51707
|
work_orders_namespace_collection
|
|
51260
51708
|
};
|
|
51261
51709
|
//# sourceMappingURL=index.mjs.map
|