@7365admin1/core 2.51.0 → 2.53.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 +5 -2
- package/dist/index.js +294 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +294 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -13093,23 +13093,42 @@ var CameraType = /* @__PURE__ */ ((CameraType2) => {
|
|
|
13093
13093
|
})(CameraType || {});
|
|
13094
13094
|
var schemaUpdateSiteCamera = Joi34.object({
|
|
13095
13095
|
host: Joi34.string().required(),
|
|
13096
|
-
username: Joi34.string().
|
|
13097
|
-
|
|
13096
|
+
username: Joi34.string().when("type", {
|
|
13097
|
+
is: "anpr",
|
|
13098
|
+
then: Joi34.required(),
|
|
13099
|
+
otherwise: Joi34.optional().allow(null, "")
|
|
13100
|
+
}),
|
|
13101
|
+
password: Joi34.string().when("type", {
|
|
13102
|
+
is: "anpr",
|
|
13103
|
+
then: Joi34.required(),
|
|
13104
|
+
otherwise: Joi34.optional().allow(null, "")
|
|
13105
|
+
}),
|
|
13098
13106
|
category: Joi34.string().allow("standard", "resident", "visitor").required(),
|
|
13099
13107
|
guardPost: Joi34.number().integer().optional(),
|
|
13100
|
-
direction: Joi34.string().optional().allow("entry", "exit", "both", "none")
|
|
13108
|
+
direction: Joi34.string().optional().allow("entry", "exit", "both", "none"),
|
|
13109
|
+
status: Joi34.string().optional().allow("active", "inactive", "deleted"),
|
|
13110
|
+
name: Joi34.string().optional().allow(null, "")
|
|
13101
13111
|
});
|
|
13102
13112
|
var schemaSiteCamera = Joi34.object({
|
|
13103
13113
|
_id: Joi34.string().hex().optional(),
|
|
13104
13114
|
site: Joi34.string().hex().required(),
|
|
13105
13115
|
host: Joi34.string().required(),
|
|
13106
|
-
username: Joi34.string().
|
|
13107
|
-
|
|
13116
|
+
username: Joi34.string().when("type", {
|
|
13117
|
+
is: "anpr",
|
|
13118
|
+
then: Joi34.required(),
|
|
13119
|
+
otherwise: Joi34.optional().allow(null, "")
|
|
13120
|
+
}),
|
|
13121
|
+
password: Joi34.string().when("type", {
|
|
13122
|
+
is: "anpr",
|
|
13123
|
+
then: Joi34.required(),
|
|
13124
|
+
otherwise: Joi34.optional().allow(null, "")
|
|
13125
|
+
}),
|
|
13108
13126
|
type: Joi34.string().allow("ip", "anpr").required(),
|
|
13109
13127
|
category: Joi34.string().allow("standard", "resident", "visitor").required(),
|
|
13110
13128
|
direction: Joi34.string().required().allow("entry", "exit", "both", "none"),
|
|
13111
13129
|
guardPost: Joi34.number().integer().optional(),
|
|
13112
13130
|
status: Joi34.string().optional().allow("active", "inactive", "deleted"),
|
|
13131
|
+
name: Joi34.string().optional().allow(null, ""),
|
|
13113
13132
|
createdAt: Joi34.date().optional(),
|
|
13114
13133
|
updatedAt: Joi34.date().optional(),
|
|
13115
13134
|
deletedAt: Joi34.date().optional()
|
|
@@ -13138,6 +13157,7 @@ function MSiteCamera(value) {
|
|
|
13138
13157
|
guardPost: value.guardPost ?? 0,
|
|
13139
13158
|
status: value.status ?? "active",
|
|
13140
13159
|
direction: value.direction ?? "",
|
|
13160
|
+
name: value.name ?? "",
|
|
13141
13161
|
createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
13142
13162
|
updatedAt: value.updatedAt ?? "",
|
|
13143
13163
|
deletedAt: value.deletedAt ?? ""
|
|
@@ -13458,7 +13478,24 @@ var schemaUpdateVisTrans = Joi36.object({
|
|
|
13458
13478
|
checkInRemarks: Joi36.string().optional().allow("", null),
|
|
13459
13479
|
checkOutRemarks: Joi36.string().optional().allow("", null),
|
|
13460
13480
|
expectedCheckIn: Joi36.string().isoDate().optional(),
|
|
13461
|
-
purpose: Joi36.string().optional().allow(null, "")
|
|
13481
|
+
purpose: Joi36.string().optional().allow(null, ""),
|
|
13482
|
+
members: Joi36.array().items(
|
|
13483
|
+
Joi36.object({
|
|
13484
|
+
name: Joi36.string().optional().allow(null, ""),
|
|
13485
|
+
nric: Joi36.string().optional().allow(null, ""),
|
|
13486
|
+
visitorPass: Joi36.array().items(
|
|
13487
|
+
Joi36.object({
|
|
13488
|
+
keyId: Joi36.string().hex().length(24).required()
|
|
13489
|
+
})
|
|
13490
|
+
).optional().allow(null),
|
|
13491
|
+
passKeys: Joi36.array().items(
|
|
13492
|
+
Joi36.object({
|
|
13493
|
+
keyId: Joi36.string().hex().length(24).required()
|
|
13494
|
+
})
|
|
13495
|
+
).optional().allow(null),
|
|
13496
|
+
contact: Joi36.string().optional().allow(null, "")
|
|
13497
|
+
})
|
|
13498
|
+
).optional().allow(null)
|
|
13462
13499
|
});
|
|
13463
13500
|
function MVisitorTransaction(value) {
|
|
13464
13501
|
const { error } = schemaVisitorTransaction.validate(value, {
|
|
@@ -13908,14 +13945,14 @@ function useVisitorTransactionRepo() {
|
|
|
13908
13945
|
);
|
|
13909
13946
|
}
|
|
13910
13947
|
}
|
|
13911
|
-
async function updateById(_id, value, session,
|
|
13948
|
+
async function updateById(_id, value, session, isManualCheckOut = true) {
|
|
13912
13949
|
try {
|
|
13913
13950
|
_id = new ObjectId40(_id);
|
|
13914
13951
|
} catch (error) {
|
|
13915
13952
|
throw new BadRequestError66("Invalid visitor transaction ID format.");
|
|
13916
13953
|
}
|
|
13917
13954
|
value.updatedAt = /* @__PURE__ */ new Date();
|
|
13918
|
-
if (value.checkOut &&
|
|
13955
|
+
if (value.checkOut && isManualCheckOut) {
|
|
13919
13956
|
value.manualCheckout = true;
|
|
13920
13957
|
}
|
|
13921
13958
|
try {
|
|
@@ -17371,7 +17408,7 @@ function useDahuaService() {
|
|
|
17371
17408
|
);
|
|
17372
17409
|
}
|
|
17373
17410
|
}
|
|
17374
|
-
if (["entry"
|
|
17411
|
+
if (["entry"].includes(designation) && plateNumber) {
|
|
17375
17412
|
await closeOpenTransaction(plateNumber);
|
|
17376
17413
|
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17377
17414
|
const visitorTransaction = {
|
|
@@ -17426,11 +17463,11 @@ function useDahuaService() {
|
|
|
17426
17463
|
} catch (error) {
|
|
17427
17464
|
console.log("failed to create visitor transaction", error);
|
|
17428
17465
|
loggerDahua.error(
|
|
17429
|
-
`[${site}][${
|
|
17466
|
+
`[${site}][${host}] Error creating visitor transaction:`,
|
|
17430
17467
|
error
|
|
17431
17468
|
);
|
|
17432
17469
|
}
|
|
17433
|
-
} else if (["exit"
|
|
17470
|
+
} else if (["exit"].includes(designation) && plateNumber) {
|
|
17434
17471
|
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17435
17472
|
const existingOpenTransaction = await getOpenByPlateNumber(
|
|
17436
17473
|
plateNumber,
|
|
@@ -17455,6 +17492,92 @@ function useDahuaService() {
|
|
|
17455
17492
|
if (onDetected2) {
|
|
17456
17493
|
onDetected2({ reload: true, site: existingOpenTransaction?.site?.toString(), host, direction });
|
|
17457
17494
|
}
|
|
17495
|
+
} else if (["both"].includes(designation) && plateNumber) {
|
|
17496
|
+
if (direction.toLowerCase() === "leave") {
|
|
17497
|
+
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17498
|
+
const existingOpenTransaction = await getOpenByPlateNumber(
|
|
17499
|
+
plateNumber,
|
|
17500
|
+
site
|
|
17501
|
+
);
|
|
17502
|
+
if (existingOpenTransaction?._id) {
|
|
17503
|
+
currentTransactionId = existingOpenTransaction._id.toString();
|
|
17504
|
+
currentSnapshotField = "snapshotExitImage";
|
|
17505
|
+
}
|
|
17506
|
+
if (vehicle?.recNo) {
|
|
17507
|
+
const dahuaPayload = {
|
|
17508
|
+
host,
|
|
17509
|
+
username,
|
|
17510
|
+
password,
|
|
17511
|
+
plateNumber,
|
|
17512
|
+
mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
|
|
17513
|
+
recno: vehicle?.recNo
|
|
17514
|
+
};
|
|
17515
|
+
await removePlateNumber(dahuaPayload);
|
|
17516
|
+
}
|
|
17517
|
+
await closeOpenTransaction(plateNumber);
|
|
17518
|
+
if (onDetected2 && existingOpenTransaction?.site) {
|
|
17519
|
+
onDetected2({ reload: true, site: existingOpenTransaction?.site?.toString(), host, direction });
|
|
17520
|
+
}
|
|
17521
|
+
} else if (direction.toLowerCase() === "approach") {
|
|
17522
|
+
await closeOpenTransaction(plateNumber);
|
|
17523
|
+
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17524
|
+
const visitorTransaction = {
|
|
17525
|
+
site,
|
|
17526
|
+
plateNumber,
|
|
17527
|
+
org,
|
|
17528
|
+
status: "unregistered" /* UNREGISTERED */
|
|
17529
|
+
};
|
|
17530
|
+
const typesForAutoRegister = Object.values(PersonTypes);
|
|
17531
|
+
let startDate = vehicle?.start ? new Date(vehicle?.start) : /* @__PURE__ */ new Date();
|
|
17532
|
+
let endDate = vehicle?.end ? new Date(vehicle?.end) : new Date(startDate.getTime() + 60 * 60 * 1e3);
|
|
17533
|
+
if (vehicle && typeof vehicle.category === "string" && typesForAutoRegister.includes(vehicle.category)) {
|
|
17534
|
+
visitorTransaction.name = vehicle.name;
|
|
17535
|
+
visitorTransaction.nric = vehicle.nric;
|
|
17536
|
+
visitorTransaction.contact = vehicle.phoneNumber;
|
|
17537
|
+
visitorTransaction.block = Number(vehicle.block);
|
|
17538
|
+
visitorTransaction.level = vehicle.level;
|
|
17539
|
+
visitorTransaction.unit = vehicle.unit?.toString();
|
|
17540
|
+
visitorTransaction.unitName = vehicle.unitName;
|
|
17541
|
+
visitorTransaction.type = vehicle.category;
|
|
17542
|
+
visitorTransaction.status = "registered" /* REGISTERED */;
|
|
17543
|
+
visitorTransaction.recNo = vehicle.recNo;
|
|
17544
|
+
visitorTransaction.expiredAt = vehicle.end;
|
|
17545
|
+
}
|
|
17546
|
+
const dahuaPayload = {
|
|
17547
|
+
host,
|
|
17548
|
+
username,
|
|
17549
|
+
password,
|
|
17550
|
+
plateNumber,
|
|
17551
|
+
mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
|
|
17552
|
+
owner: vehicle?.name ?? ""
|
|
17553
|
+
};
|
|
17554
|
+
dahuaPayload.start = formatDahuaDate(startDate);
|
|
17555
|
+
dahuaPayload.end = formatDahuaDate(endDate);
|
|
17556
|
+
const shouldHaveTimeLimit = visitorTransaction.type === "guest" /* GUEST */ || visitorTransaction.status === "unregistered" /* UNREGISTERED */;
|
|
17557
|
+
if (shouldHaveTimeLimit) {
|
|
17558
|
+
const startDate2 = /* @__PURE__ */ new Date();
|
|
17559
|
+
const endDate2 = new Date(startDate2.getTime() + 60 * 60 * 1e3);
|
|
17560
|
+
dahuaPayload.start = formatDahuaDate(startDate2);
|
|
17561
|
+
dahuaPayload.end = formatDahuaDate(endDate2);
|
|
17562
|
+
visitorTransaction.expiredAt = endDate2.toISOString();
|
|
17563
|
+
}
|
|
17564
|
+
try {
|
|
17565
|
+
await addPlateNumber(dahuaPayload);
|
|
17566
|
+
const result = await add(visitorTransaction, void 0, true);
|
|
17567
|
+
const transactionId = result?._id;
|
|
17568
|
+
currentTransactionId = transactionId?.toString();
|
|
17569
|
+
currentSnapshotField = "snapshotEntryImage";
|
|
17570
|
+
if (onDetected2) {
|
|
17571
|
+
onDetected2({ _id: transactionId, site: result?.site?.toString(), plateNumber: result.plateNumber, host, direction });
|
|
17572
|
+
}
|
|
17573
|
+
} catch (error) {
|
|
17574
|
+
console.log("failed to create visitor transaction", error);
|
|
17575
|
+
loggerDahua.error(
|
|
17576
|
+
`[${site}][${host}] Error creating visitor transaction:`,
|
|
17577
|
+
error
|
|
17578
|
+
);
|
|
17579
|
+
}
|
|
17580
|
+
}
|
|
17458
17581
|
}
|
|
17459
17582
|
}
|
|
17460
17583
|
}
|
|
@@ -17586,6 +17709,9 @@ function useDahuaService() {
|
|
|
17586
17709
|
}
|
|
17587
17710
|
}
|
|
17588
17711
|
async function listenToCamera(camera, onDetected) {
|
|
17712
|
+
if (camera?.type != "anpr" && camera?.status != "deleted") {
|
|
17713
|
+
return;
|
|
17714
|
+
}
|
|
17589
17715
|
if (onDetected) {
|
|
17590
17716
|
_savedOnDetected = onDetected;
|
|
17591
17717
|
}
|
|
@@ -17594,6 +17720,14 @@ function useDahuaService() {
|
|
|
17594
17720
|
return;
|
|
17595
17721
|
}
|
|
17596
17722
|
const cameraId = camera._id.toString();
|
|
17723
|
+
if (camera.status !== "active") {
|
|
17724
|
+
if (cameraRegistry.has(cameraId)) {
|
|
17725
|
+
loggerDahua.info(`[${camera?.host ?? camera?._id}] Camera is ${camera.status}. Stopping connection.`);
|
|
17726
|
+
cameraRegistry.get(cameraId)?.abort();
|
|
17727
|
+
cameraRegistry.delete(cameraId);
|
|
17728
|
+
}
|
|
17729
|
+
return;
|
|
17730
|
+
}
|
|
17597
17731
|
if (cameraRegistry.has(cameraId)) {
|
|
17598
17732
|
loggerDahua.info(`[${camera.host}] Stopping existing connection for update.`);
|
|
17599
17733
|
cameraRegistry.get(cameraId)?.abort();
|
|
@@ -17741,6 +17875,9 @@ function useDahuaService() {
|
|
|
17741
17875
|
continue;
|
|
17742
17876
|
} else if ([400, 401, 403, 500].includes(response.statusCode)) {
|
|
17743
17877
|
loggerDahua.error(`[${host}] Connection error: ${response.statusCode}`);
|
|
17878
|
+
if (onDetected) {
|
|
17879
|
+
onDetected({ site, messagePermanent: `Camera with last 3 characters ${host?.slice(-3)} Connection Error. Check username and password.` });
|
|
17880
|
+
}
|
|
17744
17881
|
return;
|
|
17745
17882
|
}
|
|
17746
17883
|
loggerDahua.info(`[${host}] Successfully connected to ANPR.`);
|
|
@@ -17793,8 +17930,15 @@ function useDahuaService() {
|
|
|
17793
17930
|
break;
|
|
17794
17931
|
}
|
|
17795
17932
|
loggerDahua.error(
|
|
17796
|
-
`[${host}] Connection lost or error: ${error.message || error}. Retrying in
|
|
17933
|
+
`[${host}] Connection lost or error: ${error.message || error}. Retrying in 10 seconds...`
|
|
17797
17934
|
);
|
|
17935
|
+
if (onDetected) {
|
|
17936
|
+
onDetected({
|
|
17937
|
+
site,
|
|
17938
|
+
host,
|
|
17939
|
+
message: `Camera in ${gate} Connection Lost. Retrying in 10 seconds. Check the camera if this issue persists, Or set the camera to Inactive to stop this notification.`
|
|
17940
|
+
});
|
|
17941
|
+
}
|
|
17798
17942
|
} finally {
|
|
17799
17943
|
if (bufferQueue?.destroy) {
|
|
17800
17944
|
try {
|
|
@@ -17815,7 +17959,7 @@ function useDahuaService() {
|
|
|
17815
17959
|
}
|
|
17816
17960
|
}
|
|
17817
17961
|
if (!signal.aborted) {
|
|
17818
|
-
await new Promise((res) => setTimeout(res,
|
|
17962
|
+
await new Promise((res) => setTimeout(res, 1e4));
|
|
17819
17963
|
}
|
|
17820
17964
|
}
|
|
17821
17965
|
loggerDahua.info(`[${host}] ANPR Listener stopped.`);
|
|
@@ -18317,6 +18461,8 @@ function useSiteCameraRepo() {
|
|
|
18317
18461
|
}
|
|
18318
18462
|
try {
|
|
18319
18463
|
await collection.deleteOne({ _id }, { session });
|
|
18464
|
+
const { listenToCamera } = useDahuaService();
|
|
18465
|
+
await listenToCamera({ _id, status: "deleted" });
|
|
18320
18466
|
delCachedData();
|
|
18321
18467
|
return "Successfully deleted site camera.";
|
|
18322
18468
|
} catch (error) {
|
|
@@ -19382,6 +19528,9 @@ function useBuildingService() {
|
|
|
19382
19528
|
// src/controllers/building.controller.ts
|
|
19383
19529
|
import { BadRequestError as BadRequestError81, logger as logger62 } from "@7365admin1/node-server-utils";
|
|
19384
19530
|
import Joi44 from "joi";
|
|
19531
|
+
import ExcelJS from "exceljs";
|
|
19532
|
+
import csv from "csv-parser";
|
|
19533
|
+
import fs from "fs";
|
|
19385
19534
|
function useBuildingController() {
|
|
19386
19535
|
const {
|
|
19387
19536
|
getAll: _getAll,
|
|
@@ -19403,7 +19552,10 @@ function useBuildingController() {
|
|
|
19403
19552
|
serial: Joi44.string().optional().allow("", null),
|
|
19404
19553
|
status: Joi44.string().optional().allow("", null),
|
|
19405
19554
|
// buildingFloorPlan: Joi.array().items(Joi.string()).optional(),
|
|
19406
|
-
buildingFiles: Joi44.array().items({
|
|
19555
|
+
buildingFiles: Joi44.array().items({
|
|
19556
|
+
id: Joi44.string().hex().optional().allow("", null),
|
|
19557
|
+
name: Joi44.string().optional().allow("", null)
|
|
19558
|
+
}).optional().allow("", null)
|
|
19407
19559
|
});
|
|
19408
19560
|
const { error } = validation.validate(value);
|
|
19409
19561
|
if (error) {
|
|
@@ -19541,13 +19693,125 @@ function useBuildingController() {
|
|
|
19541
19693
|
next(error2);
|
|
19542
19694
|
}
|
|
19543
19695
|
}
|
|
19696
|
+
async function uploadSpreadsheetBuilding(req, res, next) {
|
|
19697
|
+
try {
|
|
19698
|
+
if (!req.file) {
|
|
19699
|
+
next(new BadRequestError81("Spreadsheet file is required."));
|
|
19700
|
+
return;
|
|
19701
|
+
}
|
|
19702
|
+
const { originalname, path: path4 } = req.file;
|
|
19703
|
+
const lowerName = originalname.toLowerCase();
|
|
19704
|
+
const rowSchema = Joi44.object({
|
|
19705
|
+
block: Joi44.number().integer().min(0).required(),
|
|
19706
|
+
level: Joi44.string().optional().allow(null, ""),
|
|
19707
|
+
unit: Joi44.string().optional().allow(null, ""),
|
|
19708
|
+
category: Joi44.string().trim().required(),
|
|
19709
|
+
name: Joi44.string().trim().optional().allow(null, ""),
|
|
19710
|
+
email: Joi44.string().email().lowercase().optional().allow(null, ""),
|
|
19711
|
+
phoneNumber: Joi44.string().trim().optional().allow(null, "")
|
|
19712
|
+
});
|
|
19713
|
+
const querySchema = Joi44.object({
|
|
19714
|
+
site: Joi44.string().hex().length(24).required(),
|
|
19715
|
+
org: Joi44.string().hex().length(24).optional().allow(null, "")
|
|
19716
|
+
});
|
|
19717
|
+
const { error: queryError, value: queryValue } = querySchema.validate(
|
|
19718
|
+
req.query,
|
|
19719
|
+
{ abortEarly: false, convert: true }
|
|
19720
|
+
);
|
|
19721
|
+
if (queryError) {
|
|
19722
|
+
next(
|
|
19723
|
+
new BadRequestError81(
|
|
19724
|
+
queryError.details.map((d) => d.message).join(", ")
|
|
19725
|
+
)
|
|
19726
|
+
);
|
|
19727
|
+
return;
|
|
19728
|
+
}
|
|
19729
|
+
const { site, org } = queryValue;
|
|
19730
|
+
let rows = [];
|
|
19731
|
+
if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
|
|
19732
|
+
const workbook = new ExcelJS.Workbook();
|
|
19733
|
+
await workbook.xlsx.readFile(path4);
|
|
19734
|
+
const worksheet = workbook.worksheets[0];
|
|
19735
|
+
if (!worksheet) {
|
|
19736
|
+
next(
|
|
19737
|
+
new BadRequestError81("No worksheet found in uploaded Excel file.")
|
|
19738
|
+
);
|
|
19739
|
+
return;
|
|
19740
|
+
}
|
|
19741
|
+
const headerRow = worksheet.getRow(1);
|
|
19742
|
+
const headers = (headerRow.values || []).slice(1).map(
|
|
19743
|
+
(header) => String(header ?? "").trim().replace(/\(.*\)/, "").trim()
|
|
19744
|
+
);
|
|
19745
|
+
worksheet.eachRow((row, rowNumber) => {
|
|
19746
|
+
if (rowNumber === 1)
|
|
19747
|
+
return;
|
|
19748
|
+
const rowData = {};
|
|
19749
|
+
headers.forEach((header, index) => {
|
|
19750
|
+
rowData[header] = row.getCell(index + 1).value ?? "";
|
|
19751
|
+
});
|
|
19752
|
+
if (Object.values(rowData).some(
|
|
19753
|
+
(v) => v !== "" && v !== null && v !== void 0
|
|
19754
|
+
)) {
|
|
19755
|
+
rows.push(rowData);
|
|
19756
|
+
}
|
|
19757
|
+
});
|
|
19758
|
+
} else if (lowerName.endsWith(".csv")) {
|
|
19759
|
+
rows = await new Promise((resolve, reject) => {
|
|
19760
|
+
const parsed = [];
|
|
19761
|
+
fs.createReadStream(path4).pipe(csv()).on("headers", (headers) => {
|
|
19762
|
+
headers = headers.map(
|
|
19763
|
+
(h) => h.trim().replace(/\(.*\)/, "").trim()
|
|
19764
|
+
);
|
|
19765
|
+
}).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
|
|
19766
|
+
});
|
|
19767
|
+
} else {
|
|
19768
|
+
next(
|
|
19769
|
+
new BadRequestError81("Only .xlsx, .xls, or .csv files are allowed.")
|
|
19770
|
+
);
|
|
19771
|
+
return;
|
|
19772
|
+
}
|
|
19773
|
+
const validRows = [];
|
|
19774
|
+
const invalidRows = [];
|
|
19775
|
+
rows.forEach((row, index) => {
|
|
19776
|
+
const { error, value } = rowSchema.validate(row, {
|
|
19777
|
+
abortEarly: false,
|
|
19778
|
+
stripUnknown: true
|
|
19779
|
+
});
|
|
19780
|
+
if (error) {
|
|
19781
|
+
invalidRows.push({
|
|
19782
|
+
row: index + 2,
|
|
19783
|
+
data: row,
|
|
19784
|
+
errors: error.details.map((d) => d.message)
|
|
19785
|
+
});
|
|
19786
|
+
} else {
|
|
19787
|
+
validRows.push(value);
|
|
19788
|
+
}
|
|
19789
|
+
});
|
|
19790
|
+
res.status(200).json({
|
|
19791
|
+
message: "Spreadsheet import completed (buildings).",
|
|
19792
|
+
fileName: originalname,
|
|
19793
|
+
totalRows: rows.length,
|
|
19794
|
+
validRows: validRows.length,
|
|
19795
|
+
invalidRows: invalidRows.length,
|
|
19796
|
+
validationErrors: invalidRows,
|
|
19797
|
+
data: validRows
|
|
19798
|
+
// testing: return the validated building rows directly
|
|
19799
|
+
});
|
|
19800
|
+
fs.unlink(path4, () => {
|
|
19801
|
+
});
|
|
19802
|
+
} catch (error) {
|
|
19803
|
+
logger62.log({ level: "error", message: error.message });
|
|
19804
|
+
next(error);
|
|
19805
|
+
}
|
|
19806
|
+
}
|
|
19544
19807
|
return {
|
|
19545
19808
|
createBuilding,
|
|
19546
19809
|
getAll,
|
|
19547
19810
|
getById,
|
|
19548
19811
|
updateById,
|
|
19549
19812
|
deleteById,
|
|
19550
|
-
getBuildingLevel
|
|
19813
|
+
getBuildingLevel,
|
|
19814
|
+
uploadSpreadsheetBuilding
|
|
19551
19815
|
};
|
|
19552
19816
|
}
|
|
19553
19817
|
|
|
@@ -19868,9 +20132,9 @@ function useBuildingUnitController() {
|
|
|
19868
20132
|
// src/controllers/vehicle.controller.ts
|
|
19869
20133
|
import { BadRequestError as BadRequestError84, logger as logger65 } from "@7365admin1/node-server-utils";
|
|
19870
20134
|
import Joi46 from "joi";
|
|
19871
|
-
import
|
|
19872
|
-
import
|
|
19873
|
-
import
|
|
20135
|
+
import ExcelJS2 from "exceljs";
|
|
20136
|
+
import csv2 from "csv-parser";
|
|
20137
|
+
import fs2 from "fs";
|
|
19874
20138
|
function useVehicleController() {
|
|
19875
20139
|
const {
|
|
19876
20140
|
add: _add,
|
|
@@ -19990,7 +20254,7 @@ function useVehicleController() {
|
|
|
19990
20254
|
const { site, org } = queryValue;
|
|
19991
20255
|
let rows = [];
|
|
19992
20256
|
if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
|
|
19993
|
-
const workbook = new
|
|
20257
|
+
const workbook = new ExcelJS2.Workbook();
|
|
19994
20258
|
await workbook.xlsx.readFile(path4);
|
|
19995
20259
|
const worksheet = workbook.worksheets[0];
|
|
19996
20260
|
if (!worksheet) {
|
|
@@ -20019,7 +20283,7 @@ function useVehicleController() {
|
|
|
20019
20283
|
} else if (lowerName.endsWith(".csv")) {
|
|
20020
20284
|
rows = await new Promise((resolve, reject) => {
|
|
20021
20285
|
const parsed = [];
|
|
20022
|
-
|
|
20286
|
+
fs2.createReadStream(path4).pipe(csv2()).on("headers", (headers) => {
|
|
20023
20287
|
headers = headers.map(
|
|
20024
20288
|
(h) => h.trim().replace(/\(.*\)/, "").trim()
|
|
20025
20289
|
);
|
|
@@ -20062,7 +20326,7 @@ function useVehicleController() {
|
|
|
20062
20326
|
validationErrors: invalidRows,
|
|
20063
20327
|
data
|
|
20064
20328
|
});
|
|
20065
|
-
|
|
20329
|
+
fs2.unlink(path4, () => {
|
|
20066
20330
|
});
|
|
20067
20331
|
} catch (error) {
|
|
20068
20332
|
logger65.log({ level: "error", message: error.message });
|
|
@@ -20230,7 +20494,8 @@ function useVehicleController() {
|
|
|
20230
20494
|
recNo: Joi46.string().optional().allow(null, ""),
|
|
20231
20495
|
type: Joi46.string().optional().valid(...Object.values(VehicleType)).allow(null, ""),
|
|
20232
20496
|
peopleId: Joi46.string().hex().length(24).optional().allow(null, ""),
|
|
20233
|
-
seasonPassType: Joi46.string().optional().allow("", null)
|
|
20497
|
+
seasonPassType: Joi46.string().optional().allow("", null),
|
|
20498
|
+
remarks: Joi46.string().optional().allow("", null)
|
|
20234
20499
|
});
|
|
20235
20500
|
const { error, value } = schema2.validate(
|
|
20236
20501
|
{
|
|
@@ -20459,8 +20724,9 @@ function useSiteCameraService() {
|
|
|
20459
20724
|
try {
|
|
20460
20725
|
session.startTransaction();
|
|
20461
20726
|
await _add(value, session);
|
|
20727
|
+
const message = value.type === "ip" ? "CCTV(s) added successfully." : "ANPR(s) added successfully.";
|
|
20462
20728
|
await session.commitTransaction();
|
|
20463
|
-
return
|
|
20729
|
+
return message;
|
|
20464
20730
|
} catch (error2) {
|
|
20465
20731
|
await session.abortTransaction();
|
|
20466
20732
|
throw error2;
|
|
@@ -33793,7 +34059,7 @@ import {
|
|
|
33793
34059
|
import { ObjectId as ObjectId90 } from "mongodb";
|
|
33794
34060
|
|
|
33795
34061
|
// src/utils/access-management.ts
|
|
33796
|
-
import
|
|
34062
|
+
import fs3 from "fs";
|
|
33797
34063
|
import path2 from "path";
|
|
33798
34064
|
import axios from "axios";
|
|
33799
34065
|
import { parseStringPromise } from "xml2js";
|
|
@@ -33823,7 +34089,7 @@ var minifyXml = (xml) => {
|
|
|
33823
34089
|
return xml.replace(/>\s+</g, "><").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "").trim();
|
|
33824
34090
|
};
|
|
33825
34091
|
var readTemplate = (name, params) => {
|
|
33826
|
-
const template =
|
|
34092
|
+
const template = fs3.readFileSync(
|
|
33827
34093
|
path2.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
|
|
33828
34094
|
"utf-8"
|
|
33829
34095
|
);
|
|
@@ -33954,14 +34220,14 @@ import { parseStringPromise as parseStringPromise2 } from "xml2js";
|
|
|
33954
34220
|
|
|
33955
34221
|
// src/utils/rsa-encryption.ts
|
|
33956
34222
|
import * as crypto2 from "crypto";
|
|
33957
|
-
import
|
|
34223
|
+
import fs4 from "fs";
|
|
33958
34224
|
import path3 from "path";
|
|
33959
34225
|
var pub = path3.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
|
|
33960
34226
|
var priv = path3.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
|
|
33961
34227
|
var EncryptionCredentials = class {
|
|
33962
34228
|
};
|
|
33963
|
-
EncryptionCredentials.RAW_PUBLIC_KEY =
|
|
33964
|
-
EncryptionCredentials.RAW_PRIVATE_KEY =
|
|
34229
|
+
EncryptionCredentials.RAW_PUBLIC_KEY = fs4.readFileSync(pub, "utf8");
|
|
34230
|
+
EncryptionCredentials.RAW_PRIVATE_KEY = fs4.readFileSync(priv, "utf8");
|
|
33965
34231
|
var EntrypassRSAEncryption = class extends EncryptionCredentials {
|
|
33966
34232
|
static hexToCardNumber(hex) {
|
|
33967
34233
|
if (!/^[0-9A-Fa-f]{8}$/.test(hex)) {
|