@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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @iservice365/core
|
|
2
2
|
|
|
3
|
+
## 2.53.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 77eff04: release new/latest core package version (hot fix issue)
|
|
8
|
+
|
|
9
|
+
## 2.52.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 8b9b973: get latest changes for today
|
|
14
|
+
|
|
3
15
|
## 2.51.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -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) {
|
|
@@ -19544,6 +19690,9 @@ function useBuildingService() {
|
|
|
19544
19690
|
// src/controllers/building.controller.ts
|
|
19545
19691
|
var import_node_server_utils84 = require("@7365admin1/node-server-utils");
|
|
19546
19692
|
var import_joi44 = __toESM(require("joi"));
|
|
19693
|
+
var import_exceljs = __toESM(require("exceljs"));
|
|
19694
|
+
var import_csv_parser = __toESM(require("csv-parser"));
|
|
19695
|
+
var import_fs2 = __toESM(require("fs"));
|
|
19547
19696
|
function useBuildingController() {
|
|
19548
19697
|
const {
|
|
19549
19698
|
getAll: _getAll,
|
|
@@ -19565,7 +19714,10 @@ function useBuildingController() {
|
|
|
19565
19714
|
serial: import_joi44.default.string().optional().allow("", null),
|
|
19566
19715
|
status: import_joi44.default.string().optional().allow("", null),
|
|
19567
19716
|
// buildingFloorPlan: Joi.array().items(Joi.string()).optional(),
|
|
19568
|
-
buildingFiles: import_joi44.default.array().items({
|
|
19717
|
+
buildingFiles: import_joi44.default.array().items({
|
|
19718
|
+
id: import_joi44.default.string().hex().optional().allow("", null),
|
|
19719
|
+
name: import_joi44.default.string().optional().allow("", null)
|
|
19720
|
+
}).optional().allow("", null)
|
|
19569
19721
|
});
|
|
19570
19722
|
const { error } = validation.validate(value);
|
|
19571
19723
|
if (error) {
|
|
@@ -19703,13 +19855,125 @@ function useBuildingController() {
|
|
|
19703
19855
|
next(error2);
|
|
19704
19856
|
}
|
|
19705
19857
|
}
|
|
19858
|
+
async function uploadSpreadsheetBuilding(req, res, next) {
|
|
19859
|
+
try {
|
|
19860
|
+
if (!req.file) {
|
|
19861
|
+
next(new import_node_server_utils84.BadRequestError("Spreadsheet file is required."));
|
|
19862
|
+
return;
|
|
19863
|
+
}
|
|
19864
|
+
const { originalname, path: path4 } = req.file;
|
|
19865
|
+
const lowerName = originalname.toLowerCase();
|
|
19866
|
+
const rowSchema = import_joi44.default.object({
|
|
19867
|
+
block: import_joi44.default.number().integer().min(0).required(),
|
|
19868
|
+
level: import_joi44.default.string().optional().allow(null, ""),
|
|
19869
|
+
unit: import_joi44.default.string().optional().allow(null, ""),
|
|
19870
|
+
category: import_joi44.default.string().trim().required(),
|
|
19871
|
+
name: import_joi44.default.string().trim().optional().allow(null, ""),
|
|
19872
|
+
email: import_joi44.default.string().email().lowercase().optional().allow(null, ""),
|
|
19873
|
+
phoneNumber: import_joi44.default.string().trim().optional().allow(null, "")
|
|
19874
|
+
});
|
|
19875
|
+
const querySchema = import_joi44.default.object({
|
|
19876
|
+
site: import_joi44.default.string().hex().length(24).required(),
|
|
19877
|
+
org: import_joi44.default.string().hex().length(24).optional().allow(null, "")
|
|
19878
|
+
});
|
|
19879
|
+
const { error: queryError, value: queryValue } = querySchema.validate(
|
|
19880
|
+
req.query,
|
|
19881
|
+
{ abortEarly: false, convert: true }
|
|
19882
|
+
);
|
|
19883
|
+
if (queryError) {
|
|
19884
|
+
next(
|
|
19885
|
+
new import_node_server_utils84.BadRequestError(
|
|
19886
|
+
queryError.details.map((d) => d.message).join(", ")
|
|
19887
|
+
)
|
|
19888
|
+
);
|
|
19889
|
+
return;
|
|
19890
|
+
}
|
|
19891
|
+
const { site, org } = queryValue;
|
|
19892
|
+
let rows = [];
|
|
19893
|
+
if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
|
|
19894
|
+
const workbook = new import_exceljs.default.Workbook();
|
|
19895
|
+
await workbook.xlsx.readFile(path4);
|
|
19896
|
+
const worksheet = workbook.worksheets[0];
|
|
19897
|
+
if (!worksheet) {
|
|
19898
|
+
next(
|
|
19899
|
+
new import_node_server_utils84.BadRequestError("No worksheet found in uploaded Excel file.")
|
|
19900
|
+
);
|
|
19901
|
+
return;
|
|
19902
|
+
}
|
|
19903
|
+
const headerRow = worksheet.getRow(1);
|
|
19904
|
+
const headers = (headerRow.values || []).slice(1).map(
|
|
19905
|
+
(header) => String(header ?? "").trim().replace(/\(.*\)/, "").trim()
|
|
19906
|
+
);
|
|
19907
|
+
worksheet.eachRow((row, rowNumber) => {
|
|
19908
|
+
if (rowNumber === 1)
|
|
19909
|
+
return;
|
|
19910
|
+
const rowData = {};
|
|
19911
|
+
headers.forEach((header, index) => {
|
|
19912
|
+
rowData[header] = row.getCell(index + 1).value ?? "";
|
|
19913
|
+
});
|
|
19914
|
+
if (Object.values(rowData).some(
|
|
19915
|
+
(v) => v !== "" && v !== null && v !== void 0
|
|
19916
|
+
)) {
|
|
19917
|
+
rows.push(rowData);
|
|
19918
|
+
}
|
|
19919
|
+
});
|
|
19920
|
+
} else if (lowerName.endsWith(".csv")) {
|
|
19921
|
+
rows = await new Promise((resolve, reject) => {
|
|
19922
|
+
const parsed = [];
|
|
19923
|
+
import_fs2.default.createReadStream(path4).pipe((0, import_csv_parser.default)()).on("headers", (headers) => {
|
|
19924
|
+
headers = headers.map(
|
|
19925
|
+
(h) => h.trim().replace(/\(.*\)/, "").trim()
|
|
19926
|
+
);
|
|
19927
|
+
}).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
|
|
19928
|
+
});
|
|
19929
|
+
} else {
|
|
19930
|
+
next(
|
|
19931
|
+
new import_node_server_utils84.BadRequestError("Only .xlsx, .xls, or .csv files are allowed.")
|
|
19932
|
+
);
|
|
19933
|
+
return;
|
|
19934
|
+
}
|
|
19935
|
+
const validRows = [];
|
|
19936
|
+
const invalidRows = [];
|
|
19937
|
+
rows.forEach((row, index) => {
|
|
19938
|
+
const { error, value } = rowSchema.validate(row, {
|
|
19939
|
+
abortEarly: false,
|
|
19940
|
+
stripUnknown: true
|
|
19941
|
+
});
|
|
19942
|
+
if (error) {
|
|
19943
|
+
invalidRows.push({
|
|
19944
|
+
row: index + 2,
|
|
19945
|
+
data: row,
|
|
19946
|
+
errors: error.details.map((d) => d.message)
|
|
19947
|
+
});
|
|
19948
|
+
} else {
|
|
19949
|
+
validRows.push(value);
|
|
19950
|
+
}
|
|
19951
|
+
});
|
|
19952
|
+
res.status(200).json({
|
|
19953
|
+
message: "Spreadsheet import completed (buildings).",
|
|
19954
|
+
fileName: originalname,
|
|
19955
|
+
totalRows: rows.length,
|
|
19956
|
+
validRows: validRows.length,
|
|
19957
|
+
invalidRows: invalidRows.length,
|
|
19958
|
+
validationErrors: invalidRows,
|
|
19959
|
+
data: validRows
|
|
19960
|
+
// testing: return the validated building rows directly
|
|
19961
|
+
});
|
|
19962
|
+
import_fs2.default.unlink(path4, () => {
|
|
19963
|
+
});
|
|
19964
|
+
} catch (error) {
|
|
19965
|
+
import_node_server_utils84.logger.log({ level: "error", message: error.message });
|
|
19966
|
+
next(error);
|
|
19967
|
+
}
|
|
19968
|
+
}
|
|
19706
19969
|
return {
|
|
19707
19970
|
createBuilding,
|
|
19708
19971
|
getAll,
|
|
19709
19972
|
getById,
|
|
19710
19973
|
updateById,
|
|
19711
19974
|
deleteById,
|
|
19712
|
-
getBuildingLevel
|
|
19975
|
+
getBuildingLevel,
|
|
19976
|
+
uploadSpreadsheetBuilding
|
|
19713
19977
|
};
|
|
19714
19978
|
}
|
|
19715
19979
|
|
|
@@ -20025,9 +20289,9 @@ function useBuildingUnitController() {
|
|
|
20025
20289
|
// src/controllers/vehicle.controller.ts
|
|
20026
20290
|
var import_node_server_utils87 = require("@7365admin1/node-server-utils");
|
|
20027
20291
|
var import_joi46 = __toESM(require("joi"));
|
|
20028
|
-
var
|
|
20029
|
-
var
|
|
20030
|
-
var
|
|
20292
|
+
var import_exceljs2 = __toESM(require("exceljs"));
|
|
20293
|
+
var import_csv_parser2 = __toESM(require("csv-parser"));
|
|
20294
|
+
var import_fs3 = __toESM(require("fs"));
|
|
20031
20295
|
function useVehicleController() {
|
|
20032
20296
|
const {
|
|
20033
20297
|
add: _add,
|
|
@@ -20147,7 +20411,7 @@ function useVehicleController() {
|
|
|
20147
20411
|
const { site, org } = queryValue;
|
|
20148
20412
|
let rows = [];
|
|
20149
20413
|
if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) {
|
|
20150
|
-
const workbook = new
|
|
20414
|
+
const workbook = new import_exceljs2.default.Workbook();
|
|
20151
20415
|
await workbook.xlsx.readFile(path4);
|
|
20152
20416
|
const worksheet = workbook.worksheets[0];
|
|
20153
20417
|
if (!worksheet) {
|
|
@@ -20176,7 +20440,7 @@ function useVehicleController() {
|
|
|
20176
20440
|
} else if (lowerName.endsWith(".csv")) {
|
|
20177
20441
|
rows = await new Promise((resolve, reject) => {
|
|
20178
20442
|
const parsed = [];
|
|
20179
|
-
|
|
20443
|
+
import_fs3.default.createReadStream(path4).pipe((0, import_csv_parser2.default)()).on("headers", (headers) => {
|
|
20180
20444
|
headers = headers.map(
|
|
20181
20445
|
(h) => h.trim().replace(/\(.*\)/, "").trim()
|
|
20182
20446
|
);
|
|
@@ -20219,7 +20483,7 @@ function useVehicleController() {
|
|
|
20219
20483
|
validationErrors: invalidRows,
|
|
20220
20484
|
data
|
|
20221
20485
|
});
|
|
20222
|
-
|
|
20486
|
+
import_fs3.default.unlink(path4, () => {
|
|
20223
20487
|
});
|
|
20224
20488
|
} catch (error) {
|
|
20225
20489
|
import_node_server_utils87.logger.log({ level: "error", message: error.message });
|
|
@@ -20387,7 +20651,8 @@ function useVehicleController() {
|
|
|
20387
20651
|
recNo: import_joi46.default.string().optional().allow(null, ""),
|
|
20388
20652
|
type: import_joi46.default.string().optional().valid(...Object.values(VehicleType)).allow(null, ""),
|
|
20389
20653
|
peopleId: import_joi46.default.string().hex().length(24).optional().allow(null, ""),
|
|
20390
|
-
seasonPassType: import_joi46.default.string().optional().allow("", null)
|
|
20654
|
+
seasonPassType: import_joi46.default.string().optional().allow("", null),
|
|
20655
|
+
remarks: import_joi46.default.string().optional().allow("", null)
|
|
20391
20656
|
});
|
|
20392
20657
|
const { error, value } = schema2.validate(
|
|
20393
20658
|
{
|
|
@@ -20613,8 +20878,9 @@ function useSiteCameraService() {
|
|
|
20613
20878
|
try {
|
|
20614
20879
|
session.startTransaction();
|
|
20615
20880
|
await _add(value, session);
|
|
20881
|
+
const message = value.type === "ip" ? "CCTV(s) added successfully." : "ANPR(s) added successfully.";
|
|
20616
20882
|
await session.commitTransaction();
|
|
20617
|
-
return
|
|
20883
|
+
return message;
|
|
20618
20884
|
} catch (error2) {
|
|
20619
20885
|
await session.abortTransaction();
|
|
20620
20886
|
throw error2;
|
|
@@ -33748,7 +34014,7 @@ var import_node_server_utils153 = require("@7365admin1/node-server-utils");
|
|
|
33748
34014
|
var import_mongodb90 = require("mongodb");
|
|
33749
34015
|
|
|
33750
34016
|
// src/utils/access-management.ts
|
|
33751
|
-
var
|
|
34017
|
+
var import_fs4 = __toESM(require("fs"));
|
|
33752
34018
|
var import_path = __toESM(require("path"));
|
|
33753
34019
|
var import_axios = __toESM(require("axios"));
|
|
33754
34020
|
var import_xml2js = require("xml2js");
|
|
@@ -33778,7 +34044,7 @@ var minifyXml = (xml) => {
|
|
|
33778
34044
|
return xml.replace(/>\s+</g, "><").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "").trim();
|
|
33779
34045
|
};
|
|
33780
34046
|
var readTemplate = (name, params) => {
|
|
33781
|
-
const template =
|
|
34047
|
+
const template = import_fs4.default.readFileSync(
|
|
33782
34048
|
import_path.default.join(__dirname, `../dist/public/xml-templates/${name}.xml`),
|
|
33783
34049
|
"utf-8"
|
|
33784
34050
|
);
|
|
@@ -33909,14 +34175,14 @@ var import_xml2js2 = require("xml2js");
|
|
|
33909
34175
|
|
|
33910
34176
|
// src/utils/rsa-encryption.ts
|
|
33911
34177
|
var crypto2 = __toESM(require("crypto"));
|
|
33912
|
-
var
|
|
34178
|
+
var import_fs5 = __toESM(require("fs"));
|
|
33913
34179
|
var import_path2 = __toESM(require("path"));
|
|
33914
34180
|
var pub = import_path2.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_pub.pem");
|
|
33915
34181
|
var priv = import_path2.default.resolve(process.cwd(), "./src/public/rsa-keys/new_rsa_512_priv.pem");
|
|
33916
34182
|
var EncryptionCredentials = class {
|
|
33917
34183
|
};
|
|
33918
|
-
EncryptionCredentials.RAW_PUBLIC_KEY =
|
|
33919
|
-
EncryptionCredentials.RAW_PRIVATE_KEY =
|
|
34184
|
+
EncryptionCredentials.RAW_PUBLIC_KEY = import_fs5.default.readFileSync(pub, "utf8");
|
|
34185
|
+
EncryptionCredentials.RAW_PRIVATE_KEY = import_fs5.default.readFileSync(priv, "utf8");
|
|
33920
34186
|
var EntrypassRSAEncryption = class extends EncryptionCredentials {
|
|
33921
34187
|
static hexToCardNumber(hex) {
|
|
33922
34188
|
if (!/^[0-9A-Fa-f]{8}$/.test(hex)) {
|