@7365admin1/core 2.51.0 → 2.52.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 +6 -3
- package/dist/index.js +314 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +314 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1854,7 +1854,7 @@ declare function useBuildingRepo(): {
|
|
|
1854
1854
|
getById: (_id: string | ObjectId) => Promise<TBuilding | null>;
|
|
1855
1855
|
updateById: (_id: ObjectId | string, value: Pick<TBuilding, "name" | "block" | "levels" | "buildingFiles">, session?: ClientSession) => Promise<mongodb.UpdateResult<bson.Document>>;
|
|
1856
1856
|
deleteById: (_id: string | ObjectId, session?: ClientSession) => Promise<mongodb.UpdateResult<bson.Document>>;
|
|
1857
|
-
getBuildingLevel: (site: string | ObjectId, block: number) => Promise<
|
|
1857
|
+
getBuildingLevel: (site: string | ObjectId, block: number, isVMS: boolean) => Promise<bson.Document[] | TBuilding>;
|
|
1858
1858
|
};
|
|
1859
1859
|
|
|
1860
1860
|
declare function useBuildingService(): {
|
|
@@ -1870,6 +1870,7 @@ declare function useBuildingController(): {
|
|
|
1870
1870
|
updateById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
1871
1871
|
deleteById: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
1872
1872
|
getBuildingLevel: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
1873
|
+
uploadSpreadsheetBuilding: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
1873
1874
|
};
|
|
1874
1875
|
|
|
1875
1876
|
declare function useBuildingUnitRepo(): {
|
|
@@ -1927,6 +1928,7 @@ type TCamera = {
|
|
|
1927
1928
|
};
|
|
1928
1929
|
type TSiteCamera = {
|
|
1929
1930
|
_id?: ObjectId;
|
|
1931
|
+
name?: string;
|
|
1930
1932
|
site: string | ObjectId;
|
|
1931
1933
|
host: string;
|
|
1932
1934
|
username: string;
|
|
@@ -1953,6 +1955,7 @@ declare function MSiteCamera(value: TSiteCamera): {
|
|
|
1953
1955
|
guardPost: number;
|
|
1954
1956
|
status: string;
|
|
1955
1957
|
direction: string;
|
|
1958
|
+
name: string;
|
|
1956
1959
|
createdAt: string | Date;
|
|
1957
1960
|
updatedAt: string | Date;
|
|
1958
1961
|
deletedAt: string | Date;
|
|
@@ -2285,7 +2288,7 @@ declare function useSiteCameraRepo(): {
|
|
|
2285
2288
|
};
|
|
2286
2289
|
|
|
2287
2290
|
declare function useSiteCameraService(): {
|
|
2288
|
-
add: (value: TSiteCamera) => Promise<
|
|
2291
|
+
add: (value: TSiteCamera) => Promise<"CCTV(s) added successfully." | "ANPR(s) added successfully.">;
|
|
2289
2292
|
listenToCapturedPlateNumber: (onDetected?: ((data: any) => void) | undefined) => Promise<void>;
|
|
2290
2293
|
};
|
|
2291
2294
|
|
|
@@ -2705,7 +2708,7 @@ declare function useVisitorTransactionRepo(): {
|
|
|
2705
2708
|
pageRange: string;
|
|
2706
2709
|
}>;
|
|
2707
2710
|
getOpenByPlateNumber: (plateNumber: string, site: string | ObjectId) => Promise<TVisitorTransaction | null>;
|
|
2708
|
-
updateById: (_id: string | ObjectId, value: Partial<TVisitorTransaction>, session?: ClientSession,
|
|
2711
|
+
updateById: (_id: string | ObjectId, value: Partial<TVisitorTransaction>, session?: ClientSession, isManualCheckOut?: boolean) => Promise<mongodb.UpdateResult<bson.Document>>;
|
|
2709
2712
|
deleteVisitorTransaction: (_id: string | ObjectId) => Promise<number>;
|
|
2710
2713
|
createTextIndex: () => Promise<void>;
|
|
2711
2714
|
getDeliveryPickupTransactions: () => Promise<mongodb.WithId<bson.Document>[]>;
|
package/dist/index.js
CHANGED
|
@@ -13313,23 +13313,42 @@ var CameraType = /* @__PURE__ */ ((CameraType2) => {
|
|
|
13313
13313
|
})(CameraType || {});
|
|
13314
13314
|
var schemaUpdateSiteCamera = import_joi34.default.object({
|
|
13315
13315
|
host: import_joi34.default.string().required(),
|
|
13316
|
-
username: import_joi34.default.string().
|
|
13317
|
-
|
|
13316
|
+
username: import_joi34.default.string().when("type", {
|
|
13317
|
+
is: "anpr",
|
|
13318
|
+
then: import_joi34.default.required(),
|
|
13319
|
+
otherwise: import_joi34.default.optional().allow(null, "")
|
|
13320
|
+
}),
|
|
13321
|
+
password: import_joi34.default.string().when("type", {
|
|
13322
|
+
is: "anpr",
|
|
13323
|
+
then: import_joi34.default.required(),
|
|
13324
|
+
otherwise: import_joi34.default.optional().allow(null, "")
|
|
13325
|
+
}),
|
|
13318
13326
|
category: import_joi34.default.string().allow("standard", "resident", "visitor").required(),
|
|
13319
13327
|
guardPost: import_joi34.default.number().integer().optional(),
|
|
13320
|
-
direction: import_joi34.default.string().optional().allow("entry", "exit", "both", "none")
|
|
13328
|
+
direction: import_joi34.default.string().optional().allow("entry", "exit", "both", "none"),
|
|
13329
|
+
status: import_joi34.default.string().optional().allow("active", "inactive", "deleted"),
|
|
13330
|
+
name: import_joi34.default.string().optional().allow(null, "")
|
|
13321
13331
|
});
|
|
13322
13332
|
var schemaSiteCamera = import_joi34.default.object({
|
|
13323
13333
|
_id: import_joi34.default.string().hex().optional(),
|
|
13324
13334
|
site: import_joi34.default.string().hex().required(),
|
|
13325
13335
|
host: import_joi34.default.string().required(),
|
|
13326
|
-
username: import_joi34.default.string().
|
|
13327
|
-
|
|
13336
|
+
username: import_joi34.default.string().when("type", {
|
|
13337
|
+
is: "anpr",
|
|
13338
|
+
then: import_joi34.default.required(),
|
|
13339
|
+
otherwise: import_joi34.default.optional().allow(null, "")
|
|
13340
|
+
}),
|
|
13341
|
+
password: import_joi34.default.string().when("type", {
|
|
13342
|
+
is: "anpr",
|
|
13343
|
+
then: import_joi34.default.required(),
|
|
13344
|
+
otherwise: import_joi34.default.optional().allow(null, "")
|
|
13345
|
+
}),
|
|
13328
13346
|
type: import_joi34.default.string().allow("ip", "anpr").required(),
|
|
13329
13347
|
category: import_joi34.default.string().allow("standard", "resident", "visitor").required(),
|
|
13330
13348
|
direction: import_joi34.default.string().required().allow("entry", "exit", "both", "none"),
|
|
13331
13349
|
guardPost: import_joi34.default.number().integer().optional(),
|
|
13332
13350
|
status: import_joi34.default.string().optional().allow("active", "inactive", "deleted"),
|
|
13351
|
+
name: import_joi34.default.string().optional().allow(null, ""),
|
|
13333
13352
|
createdAt: import_joi34.default.date().optional(),
|
|
13334
13353
|
updatedAt: import_joi34.default.date().optional(),
|
|
13335
13354
|
deletedAt: import_joi34.default.date().optional()
|
|
@@ -13358,6 +13377,7 @@ function MSiteCamera(value) {
|
|
|
13358
13377
|
guardPost: value.guardPost ?? 0,
|
|
13359
13378
|
status: value.status ?? "active",
|
|
13360
13379
|
direction: value.direction ?? "",
|
|
13380
|
+
name: value.name ?? "",
|
|
13361
13381
|
createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
13362
13382
|
updatedAt: value.updatedAt ?? "",
|
|
13363
13383
|
deletedAt: value.deletedAt ?? ""
|
|
@@ -13672,7 +13692,24 @@ var schemaUpdateVisTrans = import_joi36.default.object({
|
|
|
13672
13692
|
checkInRemarks: import_joi36.default.string().optional().allow("", null),
|
|
13673
13693
|
checkOutRemarks: import_joi36.default.string().optional().allow("", null),
|
|
13674
13694
|
expectedCheckIn: import_joi36.default.string().isoDate().optional(),
|
|
13675
|
-
purpose: import_joi36.default.string().optional().allow(null, "")
|
|
13695
|
+
purpose: import_joi36.default.string().optional().allow(null, ""),
|
|
13696
|
+
members: import_joi36.default.array().items(
|
|
13697
|
+
import_joi36.default.object({
|
|
13698
|
+
name: import_joi36.default.string().optional().allow(null, ""),
|
|
13699
|
+
nric: import_joi36.default.string().optional().allow(null, ""),
|
|
13700
|
+
visitorPass: import_joi36.default.array().items(
|
|
13701
|
+
import_joi36.default.object({
|
|
13702
|
+
keyId: import_joi36.default.string().hex().length(24).required()
|
|
13703
|
+
})
|
|
13704
|
+
).optional().allow(null),
|
|
13705
|
+
passKeys: import_joi36.default.array().items(
|
|
13706
|
+
import_joi36.default.object({
|
|
13707
|
+
keyId: import_joi36.default.string().hex().length(24).required()
|
|
13708
|
+
})
|
|
13709
|
+
).optional().allow(null),
|
|
13710
|
+
contact: import_joi36.default.string().optional().allow(null, "")
|
|
13711
|
+
})
|
|
13712
|
+
).optional().allow(null)
|
|
13676
13713
|
});
|
|
13677
13714
|
function MVisitorTransaction(value) {
|
|
13678
13715
|
const { error } = schemaVisitorTransaction.validate(value, {
|
|
@@ -14122,14 +14159,14 @@ function useVisitorTransactionRepo() {
|
|
|
14122
14159
|
);
|
|
14123
14160
|
}
|
|
14124
14161
|
}
|
|
14125
|
-
async function updateById(_id, value, session,
|
|
14162
|
+
async function updateById(_id, value, session, isManualCheckOut = true) {
|
|
14126
14163
|
try {
|
|
14127
14164
|
_id = new import_mongodb40.ObjectId(_id);
|
|
14128
14165
|
} catch (error) {
|
|
14129
14166
|
throw new import_node_server_utils68.BadRequestError("Invalid visitor transaction ID format.");
|
|
14130
14167
|
}
|
|
14131
14168
|
value.updatedAt = /* @__PURE__ */ new Date();
|
|
14132
|
-
if (value.checkOut &&
|
|
14169
|
+
if (value.checkOut && isManualCheckOut) {
|
|
14133
14170
|
value.manualCheckout = true;
|
|
14134
14171
|
}
|
|
14135
14172
|
try {
|
|
@@ -17552,7 +17589,7 @@ function useDahuaService() {
|
|
|
17552
17589
|
);
|
|
17553
17590
|
}
|
|
17554
17591
|
}
|
|
17555
|
-
if (["entry"
|
|
17592
|
+
if (["entry"].includes(designation) && plateNumber) {
|
|
17556
17593
|
await closeOpenTransaction(plateNumber);
|
|
17557
17594
|
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17558
17595
|
const visitorTransaction = {
|
|
@@ -17607,11 +17644,11 @@ function useDahuaService() {
|
|
|
17607
17644
|
} catch (error) {
|
|
17608
17645
|
console.log("failed to create visitor transaction", error);
|
|
17609
17646
|
loggerDahua.error(
|
|
17610
|
-
`[${site}][${
|
|
17647
|
+
`[${site}][${host}] Error creating visitor transaction:`,
|
|
17611
17648
|
error
|
|
17612
17649
|
);
|
|
17613
17650
|
}
|
|
17614
|
-
} else if (["exit"
|
|
17651
|
+
} else if (["exit"].includes(designation) && plateNumber) {
|
|
17615
17652
|
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17616
17653
|
const existingOpenTransaction = await getOpenByPlateNumber(
|
|
17617
17654
|
plateNumber,
|
|
@@ -17636,6 +17673,92 @@ function useDahuaService() {
|
|
|
17636
17673
|
if (onDetected2) {
|
|
17637
17674
|
onDetected2({ reload: true, site: existingOpenTransaction?.site?.toString(), host, direction });
|
|
17638
17675
|
}
|
|
17676
|
+
} else if (["both"].includes(designation) && plateNumber) {
|
|
17677
|
+
if (direction.toLowerCase() === "leave") {
|
|
17678
|
+
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17679
|
+
const existingOpenTransaction = await getOpenByPlateNumber(
|
|
17680
|
+
plateNumber,
|
|
17681
|
+
site
|
|
17682
|
+
);
|
|
17683
|
+
if (existingOpenTransaction?._id) {
|
|
17684
|
+
currentTransactionId = existingOpenTransaction._id.toString();
|
|
17685
|
+
currentSnapshotField = "snapshotExitImage";
|
|
17686
|
+
}
|
|
17687
|
+
if (vehicle?.recNo) {
|
|
17688
|
+
const dahuaPayload = {
|
|
17689
|
+
host,
|
|
17690
|
+
username,
|
|
17691
|
+
password,
|
|
17692
|
+
plateNumber,
|
|
17693
|
+
mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
|
|
17694
|
+
recno: vehicle?.recNo
|
|
17695
|
+
};
|
|
17696
|
+
await removePlateNumber(dahuaPayload);
|
|
17697
|
+
}
|
|
17698
|
+
await closeOpenTransaction(plateNumber);
|
|
17699
|
+
if (onDetected2 && existingOpenTransaction?.site) {
|
|
17700
|
+
onDetected2({ reload: true, site: existingOpenTransaction?.site?.toString(), host, direction });
|
|
17701
|
+
}
|
|
17702
|
+
} else if (direction.toLowerCase() === "approach") {
|
|
17703
|
+
await closeOpenTransaction(plateNumber);
|
|
17704
|
+
const vehicle = await getVehicleByPlateNumber(plateNumber);
|
|
17705
|
+
const visitorTransaction = {
|
|
17706
|
+
site,
|
|
17707
|
+
plateNumber,
|
|
17708
|
+
org,
|
|
17709
|
+
status: "unregistered" /* UNREGISTERED */
|
|
17710
|
+
};
|
|
17711
|
+
const typesForAutoRegister = Object.values(PersonTypes);
|
|
17712
|
+
let startDate = vehicle?.start ? new Date(vehicle?.start) : /* @__PURE__ */ new Date();
|
|
17713
|
+
let endDate = vehicle?.end ? new Date(vehicle?.end) : new Date(startDate.getTime() + 60 * 60 * 1e3);
|
|
17714
|
+
if (vehicle && typeof vehicle.category === "string" && typesForAutoRegister.includes(vehicle.category)) {
|
|
17715
|
+
visitorTransaction.name = vehicle.name;
|
|
17716
|
+
visitorTransaction.nric = vehicle.nric;
|
|
17717
|
+
visitorTransaction.contact = vehicle.phoneNumber;
|
|
17718
|
+
visitorTransaction.block = Number(vehicle.block);
|
|
17719
|
+
visitorTransaction.level = vehicle.level;
|
|
17720
|
+
visitorTransaction.unit = vehicle.unit?.toString();
|
|
17721
|
+
visitorTransaction.unitName = vehicle.unitName;
|
|
17722
|
+
visitorTransaction.type = vehicle.category;
|
|
17723
|
+
visitorTransaction.status = "registered" /* REGISTERED */;
|
|
17724
|
+
visitorTransaction.recNo = vehicle.recNo;
|
|
17725
|
+
visitorTransaction.expiredAt = vehicle.end;
|
|
17726
|
+
}
|
|
17727
|
+
const dahuaPayload = {
|
|
17728
|
+
host,
|
|
17729
|
+
username,
|
|
17730
|
+
password,
|
|
17731
|
+
plateNumber,
|
|
17732
|
+
mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
|
|
17733
|
+
owner: vehicle?.name ?? ""
|
|
17734
|
+
};
|
|
17735
|
+
dahuaPayload.start = formatDahuaDate(startDate);
|
|
17736
|
+
dahuaPayload.end = formatDahuaDate(endDate);
|
|
17737
|
+
const shouldHaveTimeLimit = visitorTransaction.type === "guest" /* GUEST */ || visitorTransaction.status === "unregistered" /* UNREGISTERED */;
|
|
17738
|
+
if (shouldHaveTimeLimit) {
|
|
17739
|
+
const startDate2 = /* @__PURE__ */ new Date();
|
|
17740
|
+
const endDate2 = new Date(startDate2.getTime() + 60 * 60 * 1e3);
|
|
17741
|
+
dahuaPayload.start = formatDahuaDate(startDate2);
|
|
17742
|
+
dahuaPayload.end = formatDahuaDate(endDate2);
|
|
17743
|
+
visitorTransaction.expiredAt = endDate2.toISOString();
|
|
17744
|
+
}
|
|
17745
|
+
try {
|
|
17746
|
+
await addPlateNumber(dahuaPayload);
|
|
17747
|
+
const result = await add(visitorTransaction, void 0, true);
|
|
17748
|
+
const transactionId = result?._id;
|
|
17749
|
+
currentTransactionId = transactionId?.toString();
|
|
17750
|
+
currentSnapshotField = "snapshotEntryImage";
|
|
17751
|
+
if (onDetected2) {
|
|
17752
|
+
onDetected2({ _id: transactionId, site: result?.site?.toString(), plateNumber: result.plateNumber, host, direction });
|
|
17753
|
+
}
|
|
17754
|
+
} catch (error) {
|
|
17755
|
+
console.log("failed to create visitor transaction", error);
|
|
17756
|
+
loggerDahua.error(
|
|
17757
|
+
`[${site}][${host}] Error creating visitor transaction:`,
|
|
17758
|
+
error
|
|
17759
|
+
);
|
|
17760
|
+
}
|
|
17761
|
+
}
|
|
17639
17762
|
}
|
|
17640
17763
|
}
|
|
17641
17764
|
}
|
|
@@ -17767,6 +17890,9 @@ function useDahuaService() {
|
|
|
17767
17890
|
}
|
|
17768
17891
|
}
|
|
17769
17892
|
async function listenToCamera(camera, onDetected) {
|
|
17893
|
+
if (camera?.type != "anpr" && camera?.status != "deleted") {
|
|
17894
|
+
return;
|
|
17895
|
+
}
|
|
17770
17896
|
if (onDetected) {
|
|
17771
17897
|
_savedOnDetected = onDetected;
|
|
17772
17898
|
}
|
|
@@ -17775,6 +17901,14 @@ function useDahuaService() {
|
|
|
17775
17901
|
return;
|
|
17776
17902
|
}
|
|
17777
17903
|
const cameraId = camera._id.toString();
|
|
17904
|
+
if (camera.status !== "active") {
|
|
17905
|
+
if (cameraRegistry.has(cameraId)) {
|
|
17906
|
+
loggerDahua.info(`[${camera?.host ?? camera?._id}] Camera is ${camera.status}. Stopping connection.`);
|
|
17907
|
+
cameraRegistry.get(cameraId)?.abort();
|
|
17908
|
+
cameraRegistry.delete(cameraId);
|
|
17909
|
+
}
|
|
17910
|
+
return;
|
|
17911
|
+
}
|
|
17778
17912
|
if (cameraRegistry.has(cameraId)) {
|
|
17779
17913
|
loggerDahua.info(`[${camera.host}] Stopping existing connection for update.`);
|
|
17780
17914
|
cameraRegistry.get(cameraId)?.abort();
|
|
@@ -17922,6 +18056,9 @@ function useDahuaService() {
|
|
|
17922
18056
|
continue;
|
|
17923
18057
|
} else if ([400, 401, 403, 500].includes(response.statusCode)) {
|
|
17924
18058
|
loggerDahua.error(`[${host}] Connection error: ${response.statusCode}`);
|
|
18059
|
+
if (onDetected) {
|
|
18060
|
+
onDetected({ site, messagePermanent: `Camera with last 3 characters ${host?.slice(-3)} Connection Error. Check username and password.` });
|
|
18061
|
+
}
|
|
17925
18062
|
return;
|
|
17926
18063
|
}
|
|
17927
18064
|
loggerDahua.info(`[${host}] Successfully connected to ANPR.`);
|
|
@@ -17974,8 +18111,15 @@ function useDahuaService() {
|
|
|
17974
18111
|
break;
|
|
17975
18112
|
}
|
|
17976
18113
|
loggerDahua.error(
|
|
17977
|
-
`[${host}] Connection lost or error: ${error.message || error}. Retrying in
|
|
18114
|
+
`[${host}] Connection lost or error: ${error.message || error}. Retrying in 10 seconds...`
|
|
17978
18115
|
);
|
|
18116
|
+
if (onDetected) {
|
|
18117
|
+
onDetected({
|
|
18118
|
+
site,
|
|
18119
|
+
host,
|
|
18120
|
+
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.`
|
|
18121
|
+
});
|
|
18122
|
+
}
|
|
17979
18123
|
} finally {
|
|
17980
18124
|
if (bufferQueue?.destroy) {
|
|
17981
18125
|
try {
|
|
@@ -17996,7 +18140,7 @@ function useDahuaService() {
|
|
|
17996
18140
|
}
|
|
17997
18141
|
}
|
|
17998
18142
|
if (!signal.aborted) {
|
|
17999
|
-
await new Promise((res) => setTimeout(res,
|
|
18143
|
+
await new Promise((res) => setTimeout(res, 1e4));
|
|
18000
18144
|
}
|
|
18001
18145
|
}
|
|
18002
18146
|
loggerDahua.info(`[${host}] ANPR Listener stopped.`);
|
|
@@ -18498,6 +18642,8 @@ function useSiteCameraRepo() {
|
|
|
18498
18642
|
}
|
|
18499
18643
|
try {
|
|
18500
18644
|
await collection.deleteOne({ _id }, { session });
|
|
18645
|
+
const { listenToCamera } = useDahuaService();
|
|
18646
|
+
await listenToCamera({ _id, status: "deleted" });
|
|
18501
18647
|
delCachedData();
|
|
18502
18648
|
return "Successfully deleted site camera.";
|
|
18503
18649
|
} catch (error) {
|
|
@@ -19335,7 +19481,7 @@ function useBuildingRepo() {
|
|
|
19335
19481
|
}
|
|
19336
19482
|
}
|
|
19337
19483
|
}
|
|
19338
|
-
async function getBuildingLevel(site, block) {
|
|
19484
|
+
async function getBuildingLevel(site, block, isVMS) {
|
|
19339
19485
|
try {
|
|
19340
19486
|
site = new import_mongodb49.ObjectId(site);
|
|
19341
19487
|
} catch (error) {
|
|
@@ -19345,8 +19491,7 @@ function useBuildingRepo() {
|
|
|
19345
19491
|
site,
|
|
19346
19492
|
block
|
|
19347
19493
|
};
|
|
19348
|
-
const
|
|
19349
|
-
const cacheKey = (0, import_node_server_utils82.makeCacheKey)(buildings_namespace_collection, cacheOptions);
|
|
19494
|
+
const cacheKey = (0, import_node_server_utils82.makeCacheKey)(buildings_namespace_collection, { ...query, isVMS });
|
|
19350
19495
|
try {
|
|
19351
19496
|
const cached = await getCache(cacheKey);
|
|
19352
19497
|
if (cached) {
|
|
@@ -19356,7 +19501,24 @@ function useBuildingRepo() {
|
|
|
19356
19501
|
});
|
|
19357
19502
|
return cached;
|
|
19358
19503
|
}
|
|
19359
|
-
const
|
|
19504
|
+
const pipeline = [{ $match: { ...query } }];
|
|
19505
|
+
if (isVMS) {
|
|
19506
|
+
pipeline.push({
|
|
19507
|
+
$lookup: {
|
|
19508
|
+
from: "building-levels",
|
|
19509
|
+
let: { id: "$_id" },
|
|
19510
|
+
pipeline: [
|
|
19511
|
+
{
|
|
19512
|
+
$match: {
|
|
19513
|
+
$expr: { $eq: ["$block", "$$id"] }
|
|
19514
|
+
}
|
|
19515
|
+
}
|
|
19516
|
+
],
|
|
19517
|
+
as: "building_levels"
|
|
19518
|
+
}
|
|
19519
|
+
});
|
|
19520
|
+
}
|
|
19521
|
+
const result = await collection.aggregate(pipeline).toArray();
|
|
19360
19522
|
setCache(cacheKey, result, 300).then(() => {
|
|
19361
19523
|
import_node_server_utils82.logger.log({
|
|
19362
19524
|
level: "info",
|
|
@@ -19544,6 +19706,9 @@ function useBuildingService() {
|
|
|
19544
19706
|
// src/controllers/building.controller.ts
|
|
19545
19707
|
var import_node_server_utils84 = require("@7365admin1/node-server-utils");
|
|
19546
19708
|
var import_joi44 = __toESM(require("joi"));
|
|
19709
|
+
var import_exceljs = __toESM(require("exceljs"));
|
|
19710
|
+
var import_csv_parser = __toESM(require("csv-parser"));
|
|
19711
|
+
var import_fs2 = __toESM(require("fs"));
|
|
19547
19712
|
function useBuildingController() {
|
|
19548
19713
|
const {
|
|
19549
19714
|
getAll: _getAll,
|
|
@@ -19565,7 +19730,10 @@ function useBuildingController() {
|
|
|
19565
19730
|
serial: import_joi44.default.string().optional().allow("", null),
|
|
19566
19731
|
status: import_joi44.default.string().optional().allow("", null),
|
|
19567
19732
|
// buildingFloorPlan: Joi.array().items(Joi.string()).optional(),
|
|
19568
|
-
buildingFiles: import_joi44.default.array().items({
|
|
19733
|
+
buildingFiles: import_joi44.default.array().items({
|
|
19734
|
+
id: import_joi44.default.string().hex().optional().allow("", null),
|
|
19735
|
+
name: import_joi44.default.string().optional().allow("", null)
|
|
19736
|
+
}).optional().allow("", null)
|
|
19569
19737
|
});
|
|
19570
19738
|
const { error } = validation.validate(value);
|
|
19571
19739
|
if (error) {
|
|
@@ -19685,6 +19853,7 @@ function useBuildingController() {
|
|
|
19685
19853
|
async function getBuildingLevel(req, res, next) {
|
|
19686
19854
|
const site = req.params.site ?? "";
|
|
19687
19855
|
let block = req.query.block;
|
|
19856
|
+
const isVMS = req.query.isVMS;
|
|
19688
19857
|
const validation = import_joi44.default.object({
|
|
19689
19858
|
site: import_joi44.default.string().hex().required(),
|
|
19690
19859
|
block: import_joi44.default.number().required()
|
|
@@ -19696,20 +19865,132 @@ function useBuildingController() {
|
|
|
19696
19865
|
}
|
|
19697
19866
|
block = parseInt(block) ?? 0;
|
|
19698
19867
|
try {
|
|
19699
|
-
const siteBlock = await _getBuildingLevel(site, block);
|
|
19868
|
+
const siteBlock = await _getBuildingLevel(site, block, isVMS);
|
|
19700
19869
|
res.json(siteBlock);
|
|
19701
19870
|
return;
|
|
19702
19871
|
} catch (error2) {
|
|
19703
19872
|
next(error2);
|
|
19704
19873
|
}
|
|
19705
19874
|
}
|
|
19875
|
+
async function uploadSpreadsheetBuilding(req, res, next) {
|
|
19876
|
+
try {
|
|
19877
|
+
if (!req.file) {
|
|
19878
|
+
next(new import_node_server_utils84.BadRequestError("Spreadsheet file is required."));
|
|
19879
|
+
return;
|
|
19880
|
+
}
|
|
19881
|
+
const { originalname, path: path4 } = req.file;
|
|
19882
|
+
const lowerName = originalname.toLowerCase();
|
|
19883
|
+
const rowSchema = import_joi44.default.object({
|
|
19884
|
+
block: import_joi44.default.number().integer().min(0).required(),
|
|
19885
|
+
level: import_joi44.default.string().optional().allow(null, ""),
|
|
19886
|
+
unit: import_joi44.default.string().optional().allow(null, ""),
|
|
19887
|
+
category: import_joi44.default.string().trim().required(),
|
|
19888
|
+
name: import_joi44.default.string().trim().optional().allow(null, ""),
|
|
19889
|
+
email: import_joi44.default.string().email().lowercase().optional().allow(null, ""),
|
|
19890
|
+
phoneNumber: import_joi44.default.string().trim().optional().allow(null, "")
|
|
19891
|
+
});
|
|
19892
|
+
const querySchema = import_joi44.default.object({
|
|
19893
|
+
site: import_joi44.default.string().hex().length(24).required(),
|
|
19894
|
+
org: import_joi44.default.string().hex().length(24).optional().allow(null, "")
|
|
19895
|
+
});
|
|
19896
|
+
const { error: queryError, value: queryValue } = querySchema.validate(
|
|
19897
|
+
req.query,
|
|
19898
|
+
{ abortEarly: false, convert: true }
|
|
19899
|
+
);
|
|
19900
|
+
if (queryError) {
|
|
19901
|
+
next(
|
|
19902
|
+
new import_node_server_utils84.BadRequestError(
|
|
19903
|
+
queryError.details.map((d) => d.message).join(", ")
|
|
19904
|
+
)
|
|
19905
|
+
);
|
|
19906
|
+
return;
|
|
19907
|
+
}
|
|
19908
|
+
const { site, org } = queryValue;
|
|
19909
|
+
let rows = [];
|
|
19910
|
+
if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
|
|
19911
|
+
const workbook = new import_exceljs.default.Workbook();
|
|
19912
|
+
await workbook.xlsx.readFile(path4);
|
|
19913
|
+
const worksheet = workbook.worksheets[0];
|
|
19914
|
+
if (!worksheet) {
|
|
19915
|
+
next(
|
|
19916
|
+
new import_node_server_utils84.BadRequestError("No worksheet found in uploaded Excel file.")
|
|
19917
|
+
);
|
|
19918
|
+
return;
|
|
19919
|
+
}
|
|
19920
|
+
const headerRow = worksheet.getRow(1);
|
|
19921
|
+
const headers = (headerRow.values || []).slice(1).map(
|
|
19922
|
+
(header) => String(header ?? "").trim().replace(/\(.*\)/, "").trim()
|
|
19923
|
+
);
|
|
19924
|
+
worksheet.eachRow((row, rowNumber) => {
|
|
19925
|
+
if (rowNumber === 1)
|
|
19926
|
+
return;
|
|
19927
|
+
const rowData = {};
|
|
19928
|
+
headers.forEach((header, index) => {
|
|
19929
|
+
rowData[header] = row.getCell(index + 1).value ?? "";
|
|
19930
|
+
});
|
|
19931
|
+
if (Object.values(rowData).some(
|
|
19932
|
+
(v) => v !== "" && v !== null && v !== void 0
|
|
19933
|
+
)) {
|
|
19934
|
+
rows.push(rowData);
|
|
19935
|
+
}
|
|
19936
|
+
});
|
|
19937
|
+
} else if (lowerName.endsWith(".csv")) {
|
|
19938
|
+
rows = await new Promise((resolve, reject) => {
|
|
19939
|
+
const parsed = [];
|
|
19940
|
+
import_fs2.default.createReadStream(path4).pipe((0, import_csv_parser.default)()).on("headers", (headers) => {
|
|
19941
|
+
headers = headers.map(
|
|
19942
|
+
(h) => h.trim().replace(/\(.*\)/, "").trim()
|
|
19943
|
+
);
|
|
19944
|
+
}).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
|
|
19945
|
+
});
|
|
19946
|
+
} else {
|
|
19947
|
+
next(
|
|
19948
|
+
new import_node_server_utils84.BadRequestError("Only .xlsx, .xls, or .csv files are allowed.")
|
|
19949
|
+
);
|
|
19950
|
+
return;
|
|
19951
|
+
}
|
|
19952
|
+
const validRows = [];
|
|
19953
|
+
const invalidRows = [];
|
|
19954
|
+
rows.forEach((row, index) => {
|
|
19955
|
+
const { error, value } = rowSchema.validate(row, {
|
|
19956
|
+
abortEarly: false,
|
|
19957
|
+
stripUnknown: true
|
|
19958
|
+
});
|
|
19959
|
+
if (error) {
|
|
19960
|
+
invalidRows.push({
|
|
19961
|
+
row: index + 2,
|
|
19962
|
+
data: row,
|
|
19963
|
+
errors: error.details.map((d) => d.message)
|
|
19964
|
+
});
|
|
19965
|
+
} else {
|
|
19966
|
+
validRows.push(value);
|
|
19967
|
+
}
|
|
19968
|
+
});
|
|
19969
|
+
res.status(200).json({
|
|
19970
|
+
message: "Spreadsheet import completed (buildings).",
|
|
19971
|
+
fileName: originalname,
|
|
19972
|
+
totalRows: rows.length,
|
|
19973
|
+
validRows: validRows.length,
|
|
19974
|
+
invalidRows: invalidRows.length,
|
|
19975
|
+
validationErrors: invalidRows,
|
|
19976
|
+
data: validRows
|
|
19977
|
+
// testing: return the validated building rows directly
|
|
19978
|
+
});
|
|
19979
|
+
import_fs2.default.unlink(path4, () => {
|
|
19980
|
+
});
|
|
19981
|
+
} catch (error) {
|
|
19982
|
+
import_node_server_utils84.logger.log({ level: "error", message: error.message });
|
|
19983
|
+
next(error);
|
|
19984
|
+
}
|
|
19985
|
+
}
|
|
19706
19986
|
return {
|
|
19707
19987
|
createBuilding,
|
|
19708
19988
|
getAll,
|
|
19709
19989
|
getById,
|
|
19710
19990
|
updateById,
|
|
19711
19991
|
deleteById,
|
|
19712
|
-
getBuildingLevel
|
|
19992
|
+
getBuildingLevel,
|
|
19993
|
+
uploadSpreadsheetBuilding
|
|
19713
19994
|
};
|
|
19714
19995
|
}
|
|
19715
19996
|
|
|
@@ -20025,9 +20306,9 @@ function useBuildingUnitController() {
|
|
|
20025
20306
|
// src/controllers/vehicle.controller.ts
|
|
20026
20307
|
var import_node_server_utils87 = require("@7365admin1/node-server-utils");
|
|
20027
20308
|
var import_joi46 = __toESM(require("joi"));
|
|
20028
|
-
var
|
|
20029
|
-
var
|
|
20030
|
-
var
|
|
20309
|
+
var import_exceljs2 = __toESM(require("exceljs"));
|
|
20310
|
+
var import_csv_parser2 = __toESM(require("csv-parser"));
|
|
20311
|
+
var import_fs3 = __toESM(require("fs"));
|
|
20031
20312
|
function useVehicleController() {
|
|
20032
20313
|
const {
|
|
20033
20314
|
add: _add,
|
|
@@ -20147,7 +20428,7 @@ function useVehicleController() {
|
|
|
20147
20428
|
const { site, org } = queryValue;
|
|
20148
20429
|
let rows = [];
|
|
20149
20430
|
if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
|
|
20150
|
-
const workbook = new
|
|
20431
|
+
const workbook = new import_exceljs2.default.Workbook();
|
|
20151
20432
|
await workbook.xlsx.readFile(path4);
|
|
20152
20433
|
const worksheet = workbook.worksheets[0];
|
|
20153
20434
|
if (!worksheet) {
|
|
@@ -20176,7 +20457,7 @@ function useVehicleController() {
|
|
|
20176
20457
|
} else if (lowerName.endsWith(".csv")) {
|
|
20177
20458
|
rows = await new Promise((resolve, reject) => {
|
|
20178
20459
|
const parsed = [];
|
|
20179
|
-
|
|
20460
|
+
import_fs3.default.createReadStream(path4).pipe((0, import_csv_parser2.default)()).on("headers", (headers) => {
|
|
20180
20461
|
headers = headers.map(
|
|
20181
20462
|
(h) => h.trim().replace(/\(.*\)/, "").trim()
|
|
20182
20463
|
);
|
|
@@ -20219,7 +20500,7 @@ function useVehicleController() {
|
|
|
20219
20500
|
validationErrors: invalidRows,
|
|
20220
20501
|
data
|
|
20221
20502
|
});
|
|
20222
|
-
|
|
20503
|
+
import_fs3.default.unlink(path4, () => {
|
|
20223
20504
|
});
|
|
20224
20505
|
} catch (error) {
|
|
20225
20506
|
import_node_server_utils87.logger.log({ level: "error", message: error.message });
|
|
@@ -20613,8 +20894,9 @@ function useSiteCameraService() {
|
|
|
20613
20894
|
try {
|
|
20614
20895
|
session.startTransaction();
|
|
20615
20896
|
await _add(value, session);
|
|
20897
|
+
const message = value.type === "ip" ? "CCTV(s) added successfully." : "ANPR(s) added successfully.";
|
|
20616
20898
|
await session.commitTransaction();
|
|
20617
|
-
return
|
|
20899
|
+
return message;
|
|
20618
20900
|
} catch (error2) {
|
|
20619
20901
|
await session.abortTransaction();
|
|
20620
20902
|
throw error2;
|
|
@@ -33748,7 +34030,7 @@ var import_node_server_utils153 = require("@7365admin1/node-server-utils");
|
|
|
33748
34030
|
var import_mongodb90 = require("mongodb");
|
|
33749
34031
|
|
|
33750
34032
|
// src/utils/access-management.ts
|
|
33751
|
-
var
|
|
34033
|
+
var import_fs4 = __toESM(require("fs"));
|
|
33752
34034
|
var import_path = __toESM(require("path"));
|
|
33753
34035
|
var import_axios = __toESM(require("axios"));
|
|
33754
34036
|
var import_xml2js = require("xml2js");
|
|
@@ -33778,7 +34060,7 @@ var minifyXml = (xml) => {
|
|
|
33778
34060
|
return xml.replace(/>\s+</g, "><").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "").trim();
|
|
33779
34061
|
};
|
|
33780
34062
|
var readTemplate = (name, params) => {
|
|
33781
|
-
const template =
|
|
34063
|
+
const template = import_fs4.default.readFileSync(
|
|
33782
34064
|
import_path.default.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
|
|
33783
34065
|
"utf-8"
|
|
33784
34066
|
);
|
|
@@ -33909,14 +34191,14 @@ var import_xml2js2 = require("xml2js");
|
|
|
33909
34191
|
|
|
33910
34192
|
// src/utils/rsa-encryption.ts
|
|
33911
34193
|
var crypto2 = __toESM(require("crypto"));
|
|
33912
|
-
var
|
|
34194
|
+
var import_fs5 = __toESM(require("fs"));
|
|
33913
34195
|
var import_path2 = __toESM(require("path"));
|
|
33914
34196
|
var pub = import_path2.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
|
|
33915
34197
|
var priv = import_path2.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
|
|
33916
34198
|
var EncryptionCredentials = class {
|
|
33917
34199
|
};
|
|
33918
|
-
EncryptionCredentials.RAW_PUBLIC_KEY =
|
|
33919
|
-
EncryptionCredentials.RAW_PRIVATE_KEY =
|
|
34200
|
+
EncryptionCredentials.RAW_PUBLIC_KEY = import_fs5.default.readFileSync(pub, "utf8");
|
|
34201
|
+
EncryptionCredentials.RAW_PRIVATE_KEY = import_fs5.default.readFileSync(priv, "utf8");
|
|
33920
34202
|
var EntrypassRSAEncryption = class extends EncryptionCredentials {
|
|
33921
34203
|
static hexToCardNumber(hex) {
|
|
33922
34204
|
if (!/^[0-9A-Fa-f]{8}$/.test(hex)) {
|