@7365admin1/core 2.14.0 → 2.15.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 +79 -16
- package/dist/index.js +952 -181
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +945 -179
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/tsconfig.json +1 -3
package/dist/index.js
CHANGED
|
@@ -30,7 +30,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
|
+
ANPRMode: () => ANPRMode,
|
|
33
34
|
AccessTypeProps: () => AccessTypeProps,
|
|
35
|
+
BULLETIN_RECIPIENTS: () => BULLETIN_RECIPIENTS,
|
|
34
36
|
DEVICE_STATUS: () => DEVICE_STATUS,
|
|
35
37
|
EAccessCardTypes: () => EAccessCardTypes,
|
|
36
38
|
EAccessCardUserTypes: () => EAccessCardUserTypes,
|
|
@@ -89,12 +91,15 @@ __export(src_exports, {
|
|
|
89
91
|
MVerification: () => MVerification,
|
|
90
92
|
MVisitorTransaction: () => MVisitorTransaction,
|
|
91
93
|
MWorkOrder: () => MWorkOrder,
|
|
94
|
+
OrgNature: () => OrgNature,
|
|
92
95
|
PERSON_TYPES: () => PERSON_TYPES,
|
|
96
|
+
STATUS_VALUES: () => STATUS_VALUES,
|
|
93
97
|
UseAccessManagementRepo: () => UseAccessManagementRepo,
|
|
94
|
-
|
|
98
|
+
VehicleCategory: () => VehicleCategory,
|
|
99
|
+
VehicleStatus: () => VehicleStatus,
|
|
100
|
+
VehicleType: () => VehicleType,
|
|
95
101
|
allowedFieldsSite: () => allowedFieldsSite,
|
|
96
102
|
allowedNatures: () => allowedNatures,
|
|
97
|
-
allowedTypes: () => allowedTypes,
|
|
98
103
|
attendanceSchema: () => attendanceSchema,
|
|
99
104
|
attendanceSettingsSchema: () => attendanceSettingsSchema,
|
|
100
105
|
chatSchema: () => chatSchema,
|
|
@@ -1669,7 +1674,9 @@ var schemaOccurrenceEntry = import_joi5.default.object({
|
|
|
1669
1674
|
subject: import_joi5.default.string().hex().optional().allow(null, ""),
|
|
1670
1675
|
occurrence: import_joi5.default.string().optional().allow(null, ""),
|
|
1671
1676
|
signature: import_joi5.default.string().hex().optional().allow(null, ""),
|
|
1672
|
-
incidentReportId: import_joi5.default.string().hex().optional().allow(null, "")
|
|
1677
|
+
incidentReportId: import_joi5.default.string().hex().optional().allow(null, ""),
|
|
1678
|
+
eSignature: import_joi5.default.string().required(),
|
|
1679
|
+
createdByName: import_joi5.default.string().optional().allow(null, "")
|
|
1673
1680
|
});
|
|
1674
1681
|
var schemaUpdateOccurrenceEntry = import_joi5.default.object({
|
|
1675
1682
|
_id: import_joi5.default.string().hex().required(),
|
|
@@ -1678,7 +1685,9 @@ var schemaUpdateOccurrenceEntry = import_joi5.default.object({
|
|
|
1678
1685
|
subject: import_joi5.default.string().hex().optional().allow(null, ""),
|
|
1679
1686
|
occurrence: import_joi5.default.string().optional().allow(null, ""),
|
|
1680
1687
|
signature: import_joi5.default.string().hex().optional().allow(null, ""),
|
|
1681
|
-
incidentReportId: import_joi5.default.string().hex().optional().allow(null, "")
|
|
1688
|
+
incidentReportId: import_joi5.default.string().hex().optional().allow(null, ""),
|
|
1689
|
+
eSignature: import_joi5.default.string().required(),
|
|
1690
|
+
createdByName: import_joi5.default.string().optional().allow(null, "")
|
|
1682
1691
|
});
|
|
1683
1692
|
function MOccurrenceEntry(value) {
|
|
1684
1693
|
if (value._id && typeof value._id === "string") {
|
|
@@ -1735,6 +1744,8 @@ function MOccurrenceEntry(value) {
|
|
|
1735
1744
|
incidentReportId: value.incidentReportId,
|
|
1736
1745
|
signature: value.signature,
|
|
1737
1746
|
userName: value.userName,
|
|
1747
|
+
eSignature: value.eSignature,
|
|
1748
|
+
createdByName: value.createdByName,
|
|
1738
1749
|
date: value.date,
|
|
1739
1750
|
createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1740
1751
|
updatedAt: value.updatedAt,
|
|
@@ -6617,12 +6628,12 @@ function useUserController() {
|
|
|
6617
6628
|
}
|
|
6618
6629
|
}
|
|
6619
6630
|
async function createUserByVerification(req, res, next) {
|
|
6620
|
-
const
|
|
6631
|
+
const allowedTypes = ["user-sign-up", "user-invite"];
|
|
6621
6632
|
const validation = import_joi14.default.object({
|
|
6622
6633
|
id: import_joi14.default.string().hex().required(),
|
|
6623
6634
|
name: import_joi14.default.string().required(),
|
|
6624
6635
|
password: import_joi14.default.string().required(),
|
|
6625
|
-
type: import_joi14.default.string().required().valid(...
|
|
6636
|
+
type: import_joi14.default.string().required().valid(...allowedTypes)
|
|
6626
6637
|
});
|
|
6627
6638
|
const id = req.params.id;
|
|
6628
6639
|
const payload = { ...req.body };
|
|
@@ -15533,12 +15544,37 @@ var import_node_server_utils81 = require("@7365admin1/node-server-utils");
|
|
|
15533
15544
|
var import_node_server_utils80 = require("@7365admin1/node-server-utils");
|
|
15534
15545
|
var import_joi43 = __toESM(require("joi"));
|
|
15535
15546
|
var import_mongodb45 = require("mongodb");
|
|
15536
|
-
var
|
|
15537
|
-
|
|
15547
|
+
var VehicleType = /* @__PURE__ */ ((VehicleType2) => {
|
|
15548
|
+
VehicleType2["WHITELIST"] = "whitelist";
|
|
15549
|
+
VehicleType2["BLOCKLIST"] = "blocklist";
|
|
15550
|
+
return VehicleType2;
|
|
15551
|
+
})(VehicleType || {});
|
|
15552
|
+
var VehicleCategory = /* @__PURE__ */ ((VehicleCategory2) => {
|
|
15553
|
+
VehicleCategory2["RESIDENT"] = "resident";
|
|
15554
|
+
VehicleCategory2["VISITOR"] = "visitor";
|
|
15555
|
+
return VehicleCategory2;
|
|
15556
|
+
})(VehicleCategory || {});
|
|
15557
|
+
var VehicleStatus = /* @__PURE__ */ ((VehicleStatus2) => {
|
|
15558
|
+
VehicleStatus2["PENDING"] = "pending";
|
|
15559
|
+
VehicleStatus2["ACTIVE"] = "active";
|
|
15560
|
+
VehicleStatus2["INACTIVE"] = "inactive";
|
|
15561
|
+
VehicleStatus2["DELETED"] = "deleted";
|
|
15562
|
+
return VehicleStatus2;
|
|
15563
|
+
})(VehicleStatus || {});
|
|
15564
|
+
var OrgNature = /* @__PURE__ */ ((OrgNature2) => {
|
|
15565
|
+
OrgNature2["PROPERTY_MANAGEMENT_AGENCY"] = "property_management_agency";
|
|
15566
|
+
OrgNature2["SECURITY_AGENCY"] = "security_agency";
|
|
15567
|
+
return OrgNature2;
|
|
15568
|
+
})(OrgNature || {});
|
|
15569
|
+
var ANPRMode = /* @__PURE__ */ ((ANPRMode2) => {
|
|
15570
|
+
ANPRMode2["TRAFFIC_REDLIST"] = "TrafficRedList";
|
|
15571
|
+
ANPRMode2["TRAFFIC_BLACKLIST"] = "TrafficBlackList";
|
|
15572
|
+
return ANPRMode2;
|
|
15573
|
+
})(ANPRMode || {});
|
|
15538
15574
|
var vehicleSchema = import_joi43.default.object({
|
|
15539
15575
|
plateNumber: import_joi43.default.string().required(),
|
|
15540
|
-
type: import_joi43.default.string().required().
|
|
15541
|
-
category: import_joi43.default.string().required().
|
|
15576
|
+
type: import_joi43.default.string().required().valid(...Object.values(VehicleType)),
|
|
15577
|
+
category: import_joi43.default.string().required().valid(...Object.values(VehicleCategory)),
|
|
15542
15578
|
name: import_joi43.default.string().required(),
|
|
15543
15579
|
phoneNumber: import_joi43.default.string().optional().allow("", null),
|
|
15544
15580
|
recNo: import_joi43.default.string().optional().allow("", null),
|
|
@@ -15552,7 +15588,8 @@ var vehicleSchema = import_joi43.default.object({
|
|
|
15552
15588
|
seasonPassType: import_joi43.default.string().optional().allow("", null),
|
|
15553
15589
|
start: import_joi43.default.date().optional().allow("", null),
|
|
15554
15590
|
end: import_joi43.default.date().optional().allow("", null),
|
|
15555
|
-
unitName: import_joi43.default.string().optional().allow("", null)
|
|
15591
|
+
unitName: import_joi43.default.string().optional().allow("", null),
|
|
15592
|
+
status: import_joi43.default.string().optional().valid(...Object.values(VehicleStatus)).allow("")
|
|
15556
15593
|
});
|
|
15557
15594
|
function MVehicle(value) {
|
|
15558
15595
|
const { error } = vehicleSchema.validate(value);
|
|
@@ -15581,6 +15618,11 @@ function MVehicle(value) {
|
|
|
15581
15618
|
throw new import_node_server_utils80.BadRequestError("Invalid building unit ID format.");
|
|
15582
15619
|
}
|
|
15583
15620
|
}
|
|
15621
|
+
const createdAtDate = value.createdAt ? new Date(value.createdAt) : /* @__PURE__ */ new Date();
|
|
15622
|
+
const expiredDate = new Date(createdAtDate);
|
|
15623
|
+
expiredDate.setFullYear(expiredDate.getFullYear() + 10);
|
|
15624
|
+
const createdAt = createdAtDate.toISOString();
|
|
15625
|
+
const expiredAt = value.end ?? expiredDate.toISOString();
|
|
15584
15626
|
return {
|
|
15585
15627
|
plateNumber: value.plateNumber ?? "",
|
|
15586
15628
|
type: value.type ?? "",
|
|
@@ -15596,11 +15638,11 @@ function MVehicle(value) {
|
|
|
15596
15638
|
nric: value.nric ?? "",
|
|
15597
15639
|
remarks: value.remarks ?? "",
|
|
15598
15640
|
seasonPassType: value.seasonPassType ?? "",
|
|
15599
|
-
start: value.start ??
|
|
15600
|
-
end: value.end ??
|
|
15601
|
-
status: value.status ?? "active"
|
|
15641
|
+
start: value.start ?? createdAt,
|
|
15642
|
+
end: value.end ?? expiredAt,
|
|
15643
|
+
status: value.status ?? "active" /* ACTIVE */,
|
|
15602
15644
|
unitName: value.unitName ?? "",
|
|
15603
|
-
createdAt
|
|
15645
|
+
createdAt,
|
|
15604
15646
|
updatedAt: value.updatedAt ?? "",
|
|
15605
15647
|
deletedAt: value.deletedAt ?? ""
|
|
15606
15648
|
};
|
|
@@ -15658,18 +15700,44 @@ function useVehicleRepo() {
|
|
|
15658
15700
|
}
|
|
15659
15701
|
const namespace_collection = "vehicles";
|
|
15660
15702
|
const collection = db.collection(namespace_collection);
|
|
15661
|
-
const { delNamespace, setCache, getCache
|
|
15703
|
+
const { delNamespace, setCache, getCache } = (0, import_node_server_utils81.useCache)(namespace_collection);
|
|
15662
15704
|
async function createIndex() {
|
|
15663
15705
|
try {
|
|
15664
15706
|
await collection.createIndexes([
|
|
15665
15707
|
{ key: { status: 1 } },
|
|
15666
15708
|
{ key: { type: 1 } },
|
|
15667
|
-
{ key: { category: 1 } }
|
|
15709
|
+
{ key: { category: 1 } },
|
|
15710
|
+
{
|
|
15711
|
+
key: { nric: 1 },
|
|
15712
|
+
name: "uniq_nric_not_deleted_nonempty",
|
|
15713
|
+
unique: true,
|
|
15714
|
+
partialFilterExpression: {
|
|
15715
|
+
nric: { $type: "string", $gt: "" },
|
|
15716
|
+
deletedAt: ""
|
|
15717
|
+
}
|
|
15718
|
+
}
|
|
15668
15719
|
]);
|
|
15669
15720
|
} catch (error) {
|
|
15721
|
+
console.error("createIndexes error:", error);
|
|
15670
15722
|
throw new import_node_server_utils81.InternalServerError("Failed to create index on vehicle.");
|
|
15671
15723
|
}
|
|
15672
15724
|
}
|
|
15725
|
+
async function createTextIndex() {
|
|
15726
|
+
try {
|
|
15727
|
+
await collection.createIndex({
|
|
15728
|
+
name: "text",
|
|
15729
|
+
plateNumber: "text",
|
|
15730
|
+
level: "text",
|
|
15731
|
+
unitName: "text",
|
|
15732
|
+
phoneNumber: "text",
|
|
15733
|
+
nric: "text"
|
|
15734
|
+
});
|
|
15735
|
+
} catch (error) {
|
|
15736
|
+
throw new import_node_server_utils81.InternalServerError(
|
|
15737
|
+
"Failed to create text index on visitor transaction."
|
|
15738
|
+
);
|
|
15739
|
+
}
|
|
15740
|
+
}
|
|
15673
15741
|
async function add(value, session) {
|
|
15674
15742
|
try {
|
|
15675
15743
|
value = MVehicle(value);
|
|
@@ -15701,37 +15769,40 @@ function useVehicleRepo() {
|
|
|
15701
15769
|
search = "",
|
|
15702
15770
|
sort = {},
|
|
15703
15771
|
type = "",
|
|
15704
|
-
category = ""
|
|
15772
|
+
category = "",
|
|
15773
|
+
status = ""
|
|
15705
15774
|
}) {
|
|
15706
15775
|
page = page > 0 ? page - 1 : 0;
|
|
15707
|
-
const
|
|
15776
|
+
const baseQuery = {
|
|
15777
|
+
...status && { status },
|
|
15778
|
+
...type && { type },
|
|
15779
|
+
...type && { type }
|
|
15780
|
+
};
|
|
15781
|
+
let query = { ...baseQuery };
|
|
15782
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
15708
15783
|
const cacheOptions = {
|
|
15709
|
-
status
|
|
15784
|
+
...status && { status },
|
|
15785
|
+
...type && { type },
|
|
15786
|
+
...type && { type },
|
|
15710
15787
|
page: String(page),
|
|
15711
|
-
limit: String(limit)
|
|
15788
|
+
limit: String(limit),
|
|
15789
|
+
sort: JSON.stringify(sort)
|
|
15712
15790
|
};
|
|
15713
|
-
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
15714
|
-
cacheOptions.sort = JSON.stringify(sort);
|
|
15715
15791
|
if (search) {
|
|
15716
|
-
query.$
|
|
15792
|
+
query.$text = { $search: search };
|
|
15717
15793
|
cacheOptions.search = search;
|
|
15718
15794
|
}
|
|
15719
|
-
if (type) {
|
|
15720
|
-
query.type = type;
|
|
15721
|
-
cacheOptions.type = type;
|
|
15722
|
-
}
|
|
15723
|
-
if (category) {
|
|
15724
|
-
query.category = category;
|
|
15725
|
-
cacheOptions.category = category;
|
|
15726
|
-
}
|
|
15727
15795
|
const cacheKey = (0, import_node_server_utils81.makeCacheKey)(namespace_collection, cacheOptions);
|
|
15728
15796
|
const cachedData = await getCache(cacheKey);
|
|
15729
15797
|
if (cachedData) {
|
|
15730
15798
|
import_node_server_utils81.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
15731
15799
|
return cachedData;
|
|
15732
15800
|
}
|
|
15801
|
+
const escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
15733
15802
|
try {
|
|
15734
|
-
|
|
15803
|
+
let items = [];
|
|
15804
|
+
let length = 0;
|
|
15805
|
+
items = await collection.aggregate([
|
|
15735
15806
|
{ $match: query },
|
|
15736
15807
|
{ $sort: sort },
|
|
15737
15808
|
{ $skip: page * limit },
|
|
@@ -15757,17 +15828,65 @@ function useVehicleRepo() {
|
|
|
15757
15828
|
level: 1,
|
|
15758
15829
|
unit: "$units.name",
|
|
15759
15830
|
plateNumber: 1,
|
|
15760
|
-
recNo: 1
|
|
15831
|
+
recNo: 1,
|
|
15832
|
+
nric: 1
|
|
15761
15833
|
}
|
|
15762
15834
|
}
|
|
15763
15835
|
]).toArray();
|
|
15764
|
-
|
|
15836
|
+
length = await collection.countDocuments(query);
|
|
15837
|
+
if ((!items || items.length === 0) && search) {
|
|
15838
|
+
const escaped = escapeRegex(search);
|
|
15839
|
+
const regexQuery = {
|
|
15840
|
+
...baseQuery,
|
|
15841
|
+
...type && { type },
|
|
15842
|
+
...category && { category },
|
|
15843
|
+
$or: [
|
|
15844
|
+
{ name: { $regex: escaped, $options: "i" } },
|
|
15845
|
+
{ plateNumber: { $regex: escaped, $options: "i" } },
|
|
15846
|
+
{ company: { $regex: escaped, $options: "i" } },
|
|
15847
|
+
{ level: { $regex: escaped, $options: "i" } },
|
|
15848
|
+
{ unitName: { $regex: escaped, $options: "i" } },
|
|
15849
|
+
{ contact: { $regex: escaped, $options: "i" } },
|
|
15850
|
+
{ nric: { $regex: escaped, $options: "i" } }
|
|
15851
|
+
]
|
|
15852
|
+
};
|
|
15853
|
+
items = await collection.aggregate([
|
|
15854
|
+
{ $match: regexQuery },
|
|
15855
|
+
{ $sort: sort },
|
|
15856
|
+
{ $skip: page * limit },
|
|
15857
|
+
{ $limit: limit },
|
|
15858
|
+
{
|
|
15859
|
+
$lookup: {
|
|
15860
|
+
from: "building-units",
|
|
15861
|
+
localField: "unit",
|
|
15862
|
+
foreignField: "_id",
|
|
15863
|
+
as: "units",
|
|
15864
|
+
pipeline: [{ $project: { name: 1 } }]
|
|
15865
|
+
}
|
|
15866
|
+
},
|
|
15867
|
+
{ $unwind: { path: "$units", preserveNullAndEmptyArrays: true } },
|
|
15868
|
+
{
|
|
15869
|
+
$project: {
|
|
15870
|
+
name: 1,
|
|
15871
|
+
type: 1,
|
|
15872
|
+
category: 1,
|
|
15873
|
+
status: 1,
|
|
15874
|
+
phoneNumber: 1,
|
|
15875
|
+
block: 1,
|
|
15876
|
+
level: 1,
|
|
15877
|
+
unit: "$units.name",
|
|
15878
|
+
plateNumber: 1,
|
|
15879
|
+
recNo: 1,
|
|
15880
|
+
nric: 1
|
|
15881
|
+
}
|
|
15882
|
+
}
|
|
15883
|
+
]).toArray();
|
|
15884
|
+
length = await collection.countDocuments(regexQuery);
|
|
15885
|
+
}
|
|
15765
15886
|
const data = (0, import_node_server_utils81.paginate)(items, page, limit, length);
|
|
15766
|
-
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
15767
|
-
import_node_server_utils81.logger.
|
|
15768
|
-
|
|
15769
|
-
import_node_server_utils81.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
15770
|
-
});
|
|
15887
|
+
setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils81.logger.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
15888
|
+
(err) => import_node_server_utils81.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
15889
|
+
);
|
|
15771
15890
|
return data;
|
|
15772
15891
|
} catch (error) {
|
|
15773
15892
|
throw error;
|
|
@@ -15861,7 +15980,10 @@ function useVehicleRepo() {
|
|
|
15861
15980
|
type: 1,
|
|
15862
15981
|
category: 1,
|
|
15863
15982
|
status: 1,
|
|
15864
|
-
recNo: 1
|
|
15983
|
+
recNo: 1,
|
|
15984
|
+
start: 1,
|
|
15985
|
+
end: 1,
|
|
15986
|
+
seasonPassType: 1
|
|
15865
15987
|
}
|
|
15866
15988
|
}
|
|
15867
15989
|
]).toArray();
|
|
@@ -15910,7 +16032,7 @@ function useVehicleRepo() {
|
|
|
15910
16032
|
throw error2;
|
|
15911
16033
|
}
|
|
15912
16034
|
}
|
|
15913
|
-
async function updateVehicle(_id, value) {
|
|
16035
|
+
async function updateVehicle(_id, value, session) {
|
|
15914
16036
|
try {
|
|
15915
16037
|
_id = new import_mongodb46.ObjectId(_id);
|
|
15916
16038
|
} catch (error) {
|
|
@@ -15921,7 +16043,11 @@ function useVehicleRepo() {
|
|
|
15921
16043
|
...value,
|
|
15922
16044
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
15923
16045
|
};
|
|
15924
|
-
const res = await collection.updateOne(
|
|
16046
|
+
const res = await collection.updateOne(
|
|
16047
|
+
{ _id },
|
|
16048
|
+
{ $set: updateValue },
|
|
16049
|
+
{ session }
|
|
16050
|
+
);
|
|
15925
16051
|
if (res.modifiedCount === 0) {
|
|
15926
16052
|
throw new import_node_server_utils81.InternalServerError("Unable to update vehicle.");
|
|
15927
16053
|
}
|
|
@@ -16000,8 +16126,126 @@ function useVehicleRepo() {
|
|
|
16000
16126
|
);
|
|
16001
16127
|
}
|
|
16002
16128
|
}
|
|
16129
|
+
async function getVehiclesByNRIC({
|
|
16130
|
+
page = 1,
|
|
16131
|
+
limit = 10,
|
|
16132
|
+
search = "",
|
|
16133
|
+
sort = {}
|
|
16134
|
+
}) {
|
|
16135
|
+
page = page > 0 ? page - 1 : 0;
|
|
16136
|
+
const baseQuery = {
|
|
16137
|
+
deletedAt: ""
|
|
16138
|
+
};
|
|
16139
|
+
let query = { ...baseQuery };
|
|
16140
|
+
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
16141
|
+
const cacheOptions = {
|
|
16142
|
+
deletedAt: "",
|
|
16143
|
+
page: String(page),
|
|
16144
|
+
limit: String(limit),
|
|
16145
|
+
sort: JSON.stringify(sort)
|
|
16146
|
+
};
|
|
16147
|
+
if (search) {
|
|
16148
|
+
query.$text = { $search: search };
|
|
16149
|
+
cacheOptions.search = search;
|
|
16150
|
+
}
|
|
16151
|
+
const cacheKey = (0, import_node_server_utils81.makeCacheKey)(namespace_collection, cacheOptions);
|
|
16152
|
+
const cachedData = await getCache(cacheKey);
|
|
16153
|
+
if (cachedData) {
|
|
16154
|
+
import_node_server_utils81.logger.info(`Cache hit for key: ${cacheKey}`);
|
|
16155
|
+
return cachedData;
|
|
16156
|
+
}
|
|
16157
|
+
const escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
16158
|
+
try {
|
|
16159
|
+
let items = [];
|
|
16160
|
+
let length = 0;
|
|
16161
|
+
items = await collection.aggregate([
|
|
16162
|
+
{ $match: query },
|
|
16163
|
+
{ $sort: sort },
|
|
16164
|
+
{ $skip: page * limit },
|
|
16165
|
+
{ $limit: limit },
|
|
16166
|
+
{
|
|
16167
|
+
$project: {
|
|
16168
|
+
name: 1,
|
|
16169
|
+
phoneNumber: 1,
|
|
16170
|
+
plateNumber: 1,
|
|
16171
|
+
recNo: 1,
|
|
16172
|
+
nric: 1,
|
|
16173
|
+
status: 1,
|
|
16174
|
+
type: 1
|
|
16175
|
+
}
|
|
16176
|
+
}
|
|
16177
|
+
]).toArray();
|
|
16178
|
+
length = await collection.countDocuments(query);
|
|
16179
|
+
if ((!items || items.length === 0) && search) {
|
|
16180
|
+
const escaped = escapeRegex(search);
|
|
16181
|
+
const regexQuery = {
|
|
16182
|
+
...baseQuery,
|
|
16183
|
+
$or: [
|
|
16184
|
+
{ name: { $regex: escaped, $options: "i" } },
|
|
16185
|
+
{ plateNumber: { $regex: escaped, $options: "i" } },
|
|
16186
|
+
{ level: { $regex: escaped, $options: "i" } },
|
|
16187
|
+
{ nric: { $regex: escaped, $options: "i" } }
|
|
16188
|
+
]
|
|
16189
|
+
};
|
|
16190
|
+
items = await collection.aggregate([
|
|
16191
|
+
{ $match: regexQuery },
|
|
16192
|
+
{ $sort: sort },
|
|
16193
|
+
{ $skip: page * limit },
|
|
16194
|
+
{ $limit: limit },
|
|
16195
|
+
{
|
|
16196
|
+
$project: {
|
|
16197
|
+
name: 1,
|
|
16198
|
+
phoneNumber: 1,
|
|
16199
|
+
plateNumber: 1,
|
|
16200
|
+
recNo: 1,
|
|
16201
|
+
nric: 1,
|
|
16202
|
+
status: 1,
|
|
16203
|
+
type: 1
|
|
16204
|
+
}
|
|
16205
|
+
}
|
|
16206
|
+
]).toArray();
|
|
16207
|
+
length = await collection.countDocuments(regexQuery);
|
|
16208
|
+
}
|
|
16209
|
+
const data = (0, import_node_server_utils81.paginate)(items, page, limit, length);
|
|
16210
|
+
setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils81.logger.info(`Cache set for key: ${cacheKey}`)).catch(
|
|
16211
|
+
(err) => import_node_server_utils81.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
|
|
16212
|
+
);
|
|
16213
|
+
return data;
|
|
16214
|
+
} catch (error) {
|
|
16215
|
+
throw error;
|
|
16216
|
+
}
|
|
16217
|
+
}
|
|
16218
|
+
async function deleteExpiredVehicles(session) {
|
|
16219
|
+
try {
|
|
16220
|
+
const tenYearsAgo = /* @__PURE__ */ new Date();
|
|
16221
|
+
tenYearsAgo.setFullYear(tenYearsAgo.getFullYear() - 10);
|
|
16222
|
+
const res = await collection.updateMany(
|
|
16223
|
+
{
|
|
16224
|
+
status: { $ne: "deleted" },
|
|
16225
|
+
end: { $exists: true, $lte: tenYearsAgo }
|
|
16226
|
+
// check only end
|
|
16227
|
+
},
|
|
16228
|
+
{ $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } },
|
|
16229
|
+
{ session }
|
|
16230
|
+
);
|
|
16231
|
+
if (res.modifiedCount === 0)
|
|
16232
|
+
throw new import_node_server_utils81.InternalServerError("Unable to delete vehicle.");
|
|
16233
|
+
delNamespace().then(() => {
|
|
16234
|
+
import_node_server_utils81.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
16235
|
+
}).catch((err) => {
|
|
16236
|
+
import_node_server_utils81.logger.error(
|
|
16237
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
16238
|
+
err
|
|
16239
|
+
);
|
|
16240
|
+
});
|
|
16241
|
+
return res.modifiedCount;
|
|
16242
|
+
} catch (error) {
|
|
16243
|
+
throw error;
|
|
16244
|
+
}
|
|
16245
|
+
}
|
|
16003
16246
|
return {
|
|
16004
16247
|
createIndex,
|
|
16248
|
+
createTextIndex,
|
|
16005
16249
|
add,
|
|
16006
16250
|
getVehicles,
|
|
16007
16251
|
getSeasonPassTypes,
|
|
@@ -16009,7 +16253,9 @@ function useVehicleRepo() {
|
|
|
16009
16253
|
updateVehicle,
|
|
16010
16254
|
deleteVehicle,
|
|
16011
16255
|
getByPlaceNumber,
|
|
16012
|
-
getVehicleByPlateNumber
|
|
16256
|
+
getVehicleByPlateNumber,
|
|
16257
|
+
getVehiclesByNRIC,
|
|
16258
|
+
deleteExpiredVehicles
|
|
16013
16259
|
};
|
|
16014
16260
|
}
|
|
16015
16261
|
|
|
@@ -16395,7 +16641,7 @@ function useDahuaService() {
|
|
|
16395
16641
|
username: import_joi45.default.string().required(),
|
|
16396
16642
|
password: import_joi45.default.string().required(),
|
|
16397
16643
|
plateNumber: import_joi45.default.string().required(),
|
|
16398
|
-
mode: import_joi45.default.string().valid(
|
|
16644
|
+
mode: import_joi45.default.string().valid(...Object.values(ANPRMode)).required(),
|
|
16399
16645
|
start: import_joi45.default.string().isoDate().optional().allow("", null),
|
|
16400
16646
|
end: import_joi45.default.string().isoDate().optional().allow("", null),
|
|
16401
16647
|
owner: import_joi45.default.string().optional().allow("", null)
|
|
@@ -16419,7 +16665,7 @@ function useDahuaService() {
|
|
|
16419
16665
|
host: value.host,
|
|
16420
16666
|
username: value.username,
|
|
16421
16667
|
password: value.password,
|
|
16422
|
-
endpoint: `/cgi-bin/recordUpdater.cgi?action=insert&name=${value.mode}&PlateNumber=${value.plateNumber}&BeginTime=${value.start}&CancelTime=${value.end}
|
|
16668
|
+
endpoint: `/cgi-bin/recordUpdater.cgi?action=insert&name=${value.mode}&PlateNumber=${value.plateNumber}&BeginTime=${value.start}&CancelTime=${value.end}&OpenGate=true&MasterOfCar=${value.owner}`
|
|
16423
16669
|
});
|
|
16424
16670
|
return response;
|
|
16425
16671
|
} catch (error2) {
|
|
@@ -16461,18 +16707,148 @@ function useDahuaService() {
|
|
|
16461
16707
|
|
|
16462
16708
|
// src/services/vehicle.service.ts
|
|
16463
16709
|
var import_node_server_utils83 = require("@7365admin1/node-server-utils");
|
|
16710
|
+
function formatDahuaDate(date) {
|
|
16711
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
16712
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(
|
|
16713
|
+
date.getDate()
|
|
16714
|
+
)} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(
|
|
16715
|
+
date.getSeconds()
|
|
16716
|
+
)}`;
|
|
16717
|
+
}
|
|
16464
16718
|
function useVehicleService() {
|
|
16465
|
-
const {
|
|
16719
|
+
const {
|
|
16720
|
+
add: _add,
|
|
16721
|
+
deleteVehicle: _deleteVehicle,
|
|
16722
|
+
updateVehicle: _updateVehicle,
|
|
16723
|
+
getVehicleById: _getVehicleById,
|
|
16724
|
+
deleteExpiredVehicles: _deleteExpiredVehicles
|
|
16725
|
+
} = useVehicleRepo();
|
|
16466
16726
|
const {
|
|
16467
16727
|
addPlateNumber: _addPlateNumber,
|
|
16468
16728
|
removePlateNumber: _removePlateNumber
|
|
16469
16729
|
} = useDahuaService();
|
|
16470
16730
|
const { getAllCameraWithPassword: _getAllSiteCameras } = useSiteCameraRepo();
|
|
16731
|
+
const { getById: _getById } = useOrgRepo();
|
|
16471
16732
|
async function add(value) {
|
|
16733
|
+
const session = import_node_server_utils83.useAtlas.getClient()?.startSession();
|
|
16734
|
+
if (!session)
|
|
16735
|
+
throw new Error("Unable to start session for vehicle service.");
|
|
16736
|
+
const org = await _getById(value.org);
|
|
16737
|
+
if (!org)
|
|
16738
|
+
throw new import_node_server_utils83.BadRequestError("Org not found");
|
|
16739
|
+
if (!Object.values(OrgNature).includes(org.nature)) {
|
|
16740
|
+
throw new import_node_server_utils83.BadRequestError(
|
|
16741
|
+
"This organization is not allowed to add vehicles."
|
|
16742
|
+
);
|
|
16743
|
+
}
|
|
16744
|
+
value.status = "active" /* ACTIVE */;
|
|
16745
|
+
const addedBySecurity = org.nature === "security_agency" /* SECURITY_AGENCY */;
|
|
16746
|
+
const addedByPM = org.nature === "property_management_agency" /* PROPERTY_MANAGEMENT_AGENCY */;
|
|
16747
|
+
if (addedBySecurity)
|
|
16748
|
+
value.status = "pending" /* PENDING */;
|
|
16749
|
+
const isBlocklist = value.type === "blocklist" /* BLOCKLIST */;
|
|
16750
|
+
if (isBlocklist)
|
|
16751
|
+
value.status = "inactive" /* INACTIVE */;
|
|
16752
|
+
const _type = value.type;
|
|
16753
|
+
const _mode = isBlocklist ? "TrafficBlackList" /* TRAFFIC_BLACKLIST */ : "TrafficRedList" /* TRAFFIC_REDLIST */;
|
|
16754
|
+
const hasStart = typeof value.start === "string" ? value.start.trim() !== "" : !!value.start;
|
|
16755
|
+
const hasEnd = typeof value.end === "string" ? value.end.trim() !== "" : !!value.end;
|
|
16756
|
+
let startDate = null;
|
|
16757
|
+
let endDate = null;
|
|
16758
|
+
let start = "";
|
|
16759
|
+
let end = "";
|
|
16760
|
+
let startDateDahua;
|
|
16761
|
+
let endDateDahua;
|
|
16762
|
+
if (addedByPM && !hasStart && !hasEnd) {
|
|
16763
|
+
startDate = /* @__PURE__ */ new Date();
|
|
16764
|
+
endDate = new Date(startDate);
|
|
16765
|
+
endDate.setFullYear(endDate.getFullYear() + 10);
|
|
16766
|
+
start = startDate.toISOString();
|
|
16767
|
+
end = endDate.toISOString();
|
|
16768
|
+
startDateDahua = formatDahuaDate(startDate);
|
|
16769
|
+
endDateDahua = formatDahuaDate(endDate);
|
|
16770
|
+
} else {
|
|
16771
|
+
if (hasStart) {
|
|
16772
|
+
startDate = new Date(value.start);
|
|
16773
|
+
start = startDate.toISOString();
|
|
16774
|
+
startDateDahua = formatDahuaDate(startDate);
|
|
16775
|
+
}
|
|
16776
|
+
if (hasEnd) {
|
|
16777
|
+
endDate = new Date(value.end);
|
|
16778
|
+
end = endDate.toISOString();
|
|
16779
|
+
endDateDahua = formatDahuaDate(endDate);
|
|
16780
|
+
}
|
|
16781
|
+
}
|
|
16782
|
+
const owner = String(value.name ?? "").substring(0, 15);
|
|
16783
|
+
try {
|
|
16784
|
+
session.startTransaction();
|
|
16785
|
+
let message = "Vehicle plate number needs approval from property management.";
|
|
16786
|
+
if (value.status && value.status !== "pending" /* PENDING */) {
|
|
16787
|
+
const siteCameras = [];
|
|
16788
|
+
let page = 1;
|
|
16789
|
+
let pages = 1;
|
|
16790
|
+
const limit = 20;
|
|
16791
|
+
do {
|
|
16792
|
+
const siteCameraReq = await _getAllSiteCameras({
|
|
16793
|
+
site: value.site,
|
|
16794
|
+
type: "anpr",
|
|
16795
|
+
direction: ["both", "entry"],
|
|
16796
|
+
page,
|
|
16797
|
+
limit
|
|
16798
|
+
});
|
|
16799
|
+
pages = siteCameraReq.pages || 1;
|
|
16800
|
+
siteCameras.push(...siteCameraReq.items);
|
|
16801
|
+
page++;
|
|
16802
|
+
} while (page < pages);
|
|
16803
|
+
if (!siteCameras.length)
|
|
16804
|
+
throw new import_node_server_utils83.BadRequestError("No site cameras found.");
|
|
16805
|
+
for (const camera of siteCameras) {
|
|
16806
|
+
const { host, username, password } = camera;
|
|
16807
|
+
const dahuaPayload = {
|
|
16808
|
+
host,
|
|
16809
|
+
username,
|
|
16810
|
+
password,
|
|
16811
|
+
plateNumber: value.plateNumber,
|
|
16812
|
+
mode: _mode,
|
|
16813
|
+
owner,
|
|
16814
|
+
...startDateDahua ? { start: startDateDahua } : "",
|
|
16815
|
+
...endDateDahua ? { end: endDateDahua } : ""
|
|
16816
|
+
};
|
|
16817
|
+
const dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
16818
|
+
if (dahuaResponse?.statusCode !== 200) {
|
|
16819
|
+
throw new import_node_server_utils83.BadRequestError(
|
|
16820
|
+
`Failed to add plate number to ANPR ${_type}`
|
|
16821
|
+
);
|
|
16822
|
+
}
|
|
16823
|
+
const responseData = dahuaResponse?.data.toString("utf-8");
|
|
16824
|
+
value.recNo = responseData.split("=")[1]?.trim();
|
|
16825
|
+
message = `Vehicle plate number added to ${_type} successfully.`;
|
|
16826
|
+
}
|
|
16827
|
+
}
|
|
16828
|
+
const formattedValue = {
|
|
16829
|
+
...value,
|
|
16830
|
+
start,
|
|
16831
|
+
// ISO string or ""
|
|
16832
|
+
end
|
|
16833
|
+
// ISO string or ""
|
|
16834
|
+
};
|
|
16835
|
+
await _add(formattedValue, session);
|
|
16836
|
+
await session.commitTransaction();
|
|
16837
|
+
return message;
|
|
16838
|
+
} catch (error) {
|
|
16839
|
+
import_node_server_utils83.logger.error("Error in vehicle service add:", error);
|
|
16840
|
+
await session.abortTransaction();
|
|
16841
|
+
throw error;
|
|
16842
|
+
} finally {
|
|
16843
|
+
session.endSession();
|
|
16844
|
+
}
|
|
16845
|
+
}
|
|
16846
|
+
async function deleteVehicle(_id, recno, site, type, bypass = false) {
|
|
16472
16847
|
const session = import_node_server_utils83.useAtlas.getClient()?.startSession();
|
|
16473
16848
|
if (!session) {
|
|
16474
16849
|
throw new Error("Unable to start session for vehicle service.");
|
|
16475
16850
|
}
|
|
16851
|
+
const _mode = type !== "whitelist" /* WHITELIST */ ? "TrafficBlackList" /* TRAFFIC_BLACKLIST */ : "TrafficRedList" /* TRAFFIC_REDLIST */;
|
|
16476
16852
|
try {
|
|
16477
16853
|
session.startTransaction();
|
|
16478
16854
|
const siteCameras = [];
|
|
@@ -16481,9 +16857,8 @@ function useVehicleService() {
|
|
|
16481
16857
|
const limit = 20;
|
|
16482
16858
|
do {
|
|
16483
16859
|
const siteCameraReq = await _getAllSiteCameras({
|
|
16484
|
-
site
|
|
16860
|
+
site,
|
|
16485
16861
|
type: "anpr",
|
|
16486
|
-
direction: ["both", "entry"],
|
|
16487
16862
|
page,
|
|
16488
16863
|
limit
|
|
16489
16864
|
});
|
|
@@ -16495,55 +16870,82 @@ function useVehicleService() {
|
|
|
16495
16870
|
throw new import_node_server_utils83.BadRequestError("No site cameras found.");
|
|
16496
16871
|
}
|
|
16497
16872
|
for (const camera of siteCameras) {
|
|
16498
|
-
const
|
|
16873
|
+
const host = camera.host;
|
|
16874
|
+
const username = camera.username;
|
|
16875
|
+
const password = camera.password;
|
|
16499
16876
|
const dahuaPayload = {
|
|
16500
16877
|
host,
|
|
16501
16878
|
username,
|
|
16502
16879
|
password,
|
|
16503
|
-
|
|
16504
|
-
mode:
|
|
16505
|
-
start: value.start ? new Date(value.start).toISOString() : "",
|
|
16506
|
-
end: value.end ? new Date(value.end).toISOString() : "",
|
|
16507
|
-
owner: value.name
|
|
16880
|
+
recno,
|
|
16881
|
+
mode: _mode
|
|
16508
16882
|
};
|
|
16509
|
-
const dahuaResponse = await
|
|
16510
|
-
if (dahuaResponse?.statusCode !== 200) {
|
|
16511
|
-
throw new import_node_server_utils83.BadRequestError(
|
|
16883
|
+
const dahuaResponse = await _removePlateNumber(dahuaPayload);
|
|
16884
|
+
if (!bypass && dahuaResponse?.statusCode !== 200) {
|
|
16885
|
+
throw new import_node_server_utils83.BadRequestError(
|
|
16886
|
+
`Failed to remove plate number to ANPR from ${type}`
|
|
16887
|
+
);
|
|
16512
16888
|
}
|
|
16513
|
-
const responseData = dahuaResponse?.data.toString("utf-8");
|
|
16514
|
-
value.recNo = responseData.split("=")[1]?.trim();
|
|
16515
|
-
const formattedValue = {
|
|
16516
|
-
...value,
|
|
16517
|
-
start: value.start ? new Date(value.start).toISOString() : "",
|
|
16518
|
-
end: value.end ? new Date(value.end).toISOString() : ""
|
|
16519
|
-
};
|
|
16520
|
-
await _add(formattedValue, session);
|
|
16521
16889
|
}
|
|
16890
|
+
await _deleteVehicle(_id, session);
|
|
16522
16891
|
await session.commitTransaction();
|
|
16523
|
-
return
|
|
16892
|
+
return `Vehicle plate number deleted from ${type} record successfully.`;
|
|
16524
16893
|
} catch (error) {
|
|
16525
|
-
import_node_server_utils83.logger.error("Error in vehicle service add:", error);
|
|
16526
16894
|
await session.abortTransaction();
|
|
16527
|
-
|
|
16895
|
+
if (error instanceof import_node_server_utils83.AppError)
|
|
16896
|
+
throw error;
|
|
16897
|
+
throw new import_node_server_utils83.InternalServerError("Failed to delete vehicle");
|
|
16528
16898
|
} finally {
|
|
16529
16899
|
session.endSession();
|
|
16530
16900
|
}
|
|
16531
16901
|
}
|
|
16532
|
-
async function
|
|
16902
|
+
async function approveVehicleById(id, orgId, siteId) {
|
|
16533
16903
|
const session = import_node_server_utils83.useAtlas.getClient()?.startSession();
|
|
16534
16904
|
if (!session) {
|
|
16535
16905
|
throw new Error("Unable to start session for vehicle service.");
|
|
16536
16906
|
}
|
|
16907
|
+
const org = await _getById(orgId);
|
|
16908
|
+
if (!org)
|
|
16909
|
+
throw new import_node_server_utils83.BadRequestError("Org not found");
|
|
16910
|
+
const allowedNatures2 = ["property_management_agency"];
|
|
16911
|
+
if (!allowedNatures2.includes(org.nature)) {
|
|
16912
|
+
throw new import_node_server_utils83.BadRequestError(
|
|
16913
|
+
"Only property management can approve vehicles."
|
|
16914
|
+
);
|
|
16915
|
+
}
|
|
16916
|
+
const vehicle = await _getVehicleById(id);
|
|
16917
|
+
if (!vehicle) {
|
|
16918
|
+
throw new import_node_server_utils83.BadRequestError("Vehicle not found");
|
|
16919
|
+
}
|
|
16920
|
+
const owner = vehicle.name.substring(0, 15);
|
|
16921
|
+
const hasStart = typeof vehicle.start === "string" ? vehicle.start.trim() !== "" : !!vehicle.start;
|
|
16922
|
+
const hasEnd = typeof vehicle.end === "string" ? vehicle.end.trim() !== "" : !!vehicle.end;
|
|
16923
|
+
let startDate = null;
|
|
16924
|
+
let endDate = null;
|
|
16925
|
+
if (!hasStart && !hasEnd) {
|
|
16926
|
+
startDate = /* @__PURE__ */ new Date();
|
|
16927
|
+
endDate = new Date(startDate);
|
|
16928
|
+
endDate.setFullYear(endDate.getFullYear() + 10);
|
|
16929
|
+
} else {
|
|
16930
|
+
startDate = hasStart ? new Date(vehicle.start) : null;
|
|
16931
|
+
endDate = hasEnd ? new Date(vehicle.end) : null;
|
|
16932
|
+
}
|
|
16933
|
+
const startIso = startDate ? startDate.toISOString() : "";
|
|
16934
|
+
const endIso = endDate ? endDate.toISOString() : "";
|
|
16935
|
+
const startDahua = startDate ? formatDahuaDate(startDate) : "";
|
|
16936
|
+
const endDahua = endDate ? formatDahuaDate(endDate) : "";
|
|
16537
16937
|
try {
|
|
16538
16938
|
session.startTransaction();
|
|
16539
16939
|
const siteCameras = [];
|
|
16540
16940
|
let page = 1;
|
|
16541
16941
|
let pages = 1;
|
|
16542
16942
|
const limit = 20;
|
|
16943
|
+
let value = {};
|
|
16543
16944
|
do {
|
|
16544
16945
|
const siteCameraReq = await _getAllSiteCameras({
|
|
16545
|
-
site,
|
|
16946
|
+
site: siteId,
|
|
16546
16947
|
type: "anpr",
|
|
16948
|
+
direction: ["both", "entry"],
|
|
16547
16949
|
page,
|
|
16548
16950
|
limit
|
|
16549
16951
|
});
|
|
@@ -16555,24 +16957,51 @@ function useVehicleService() {
|
|
|
16555
16957
|
throw new import_node_server_utils83.BadRequestError("No site cameras found.");
|
|
16556
16958
|
}
|
|
16557
16959
|
for (const camera of siteCameras) {
|
|
16558
|
-
const host = camera
|
|
16559
|
-
const username = camera.username;
|
|
16560
|
-
const password = camera.password;
|
|
16960
|
+
const { host, username, password } = camera;
|
|
16561
16961
|
const dahuaPayload = {
|
|
16562
16962
|
host,
|
|
16563
16963
|
username,
|
|
16564
16964
|
password,
|
|
16565
|
-
|
|
16566
|
-
mode: "TrafficRedList"
|
|
16965
|
+
plateNumber: vehicle.plateNumber,
|
|
16966
|
+
mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
|
|
16967
|
+
start: startDahua,
|
|
16968
|
+
end: endDahua,
|
|
16969
|
+
owner
|
|
16567
16970
|
};
|
|
16568
|
-
const dahuaResponse = await
|
|
16569
|
-
if (
|
|
16570
|
-
throw new import_node_server_utils83.BadRequestError("Failed to
|
|
16971
|
+
const dahuaResponse = await _addPlateNumber(dahuaPayload);
|
|
16972
|
+
if (dahuaResponse?.statusCode !== 200) {
|
|
16973
|
+
throw new import_node_server_utils83.BadRequestError("Failed to add plate number to ANPR");
|
|
16571
16974
|
}
|
|
16975
|
+
const responseData = dahuaResponse?.data.toString("utf-8");
|
|
16976
|
+
value.recNo = responseData.split("=")[1]?.trim();
|
|
16572
16977
|
}
|
|
16573
|
-
|
|
16978
|
+
value.status = "active";
|
|
16979
|
+
const formattedValue = {
|
|
16980
|
+
...value,
|
|
16981
|
+
start: startIso,
|
|
16982
|
+
end: endIso
|
|
16983
|
+
};
|
|
16984
|
+
await _updateVehicle(id, formattedValue, session);
|
|
16985
|
+
await session.commitTransaction();
|
|
16986
|
+
return "Vehicle plate number approved and added successfully.";
|
|
16987
|
+
} catch (error) {
|
|
16988
|
+
import_node_server_utils83.logger.error("Error in vehicle service add:", error);
|
|
16989
|
+
await session.abortTransaction();
|
|
16990
|
+
throw error;
|
|
16991
|
+
} finally {
|
|
16992
|
+
session.endSession();
|
|
16993
|
+
}
|
|
16994
|
+
}
|
|
16995
|
+
async function processDeletingExpiredVehicles() {
|
|
16996
|
+
const session = import_node_server_utils83.useAtlas.getClient()?.startSession();
|
|
16997
|
+
if (!session) {
|
|
16998
|
+
throw new Error("Unable to start session for vehicle service.");
|
|
16999
|
+
}
|
|
17000
|
+
try {
|
|
17001
|
+
session.startTransaction();
|
|
17002
|
+
await _deleteExpiredVehicles();
|
|
16574
17003
|
await session.commitTransaction();
|
|
16575
|
-
return
|
|
17004
|
+
return `Expired Vehicle plate numbers deleted successfully.`;
|
|
16576
17005
|
} catch (error) {
|
|
16577
17006
|
await session.abortTransaction();
|
|
16578
17007
|
if (error instanceof import_node_server_utils83.AppError)
|
|
@@ -16584,7 +17013,9 @@ function useVehicleService() {
|
|
|
16584
17013
|
}
|
|
16585
17014
|
return {
|
|
16586
17015
|
add,
|
|
16587
|
-
deleteVehicle
|
|
17016
|
+
deleteVehicle,
|
|
17017
|
+
approveVehicleById,
|
|
17018
|
+
processDeletingExpiredVehicles
|
|
16588
17019
|
};
|
|
16589
17020
|
}
|
|
16590
17021
|
|
|
@@ -16592,12 +17023,17 @@ function useVehicleService() {
|
|
|
16592
17023
|
var import_node_server_utils84 = require("@7365admin1/node-server-utils");
|
|
16593
17024
|
var import_joi46 = __toESM(require("joi"));
|
|
16594
17025
|
function useVehicleController() {
|
|
16595
|
-
const {
|
|
17026
|
+
const {
|
|
17027
|
+
add: _add,
|
|
17028
|
+
deleteVehicle: _deleteVehicle,
|
|
17029
|
+
approveVehicleById: _approveVehicleById
|
|
17030
|
+
} = useVehicleService();
|
|
16596
17031
|
const {
|
|
16597
17032
|
getSeasonPassTypes: _getSeasonPassTypes,
|
|
16598
17033
|
getVehicles: _getVehicles,
|
|
16599
17034
|
getVehicleById: _getVehicleById,
|
|
16600
|
-
updateVehicle: _updateVehicle
|
|
17035
|
+
updateVehicle: _updateVehicle,
|
|
17036
|
+
getVehiclesByNRIC: _getVehiclesByNRIC
|
|
16601
17037
|
} = useVehicleRepo();
|
|
16602
17038
|
async function add(req, res, next) {
|
|
16603
17039
|
const payload = req.body;
|
|
@@ -16628,8 +17064,9 @@ function useVehicleController() {
|
|
|
16628
17064
|
limit: import_joi46.default.number().integer().min(1).max(100).allow("", null).default(10),
|
|
16629
17065
|
sort: import_joi46.default.string().pattern(/^([a-zA-Z0-9_]+)(,[a-zA-Z0-9_]+)*$/).optional().allow("", ...allowedFields),
|
|
16630
17066
|
order: import_joi46.default.string().pattern(/^(asc|desc)(,(asc|desc))*$/).optional().allow("", ...allowedOrder),
|
|
16631
|
-
type: import_joi46.default.string().optional().
|
|
16632
|
-
category: import_joi46.default.string().optional().
|
|
17067
|
+
type: import_joi46.default.string().optional().valid(...Object.values(VehicleType)),
|
|
17068
|
+
category: import_joi46.default.string().optional().valid(...Object.values(VehicleCategory)),
|
|
17069
|
+
status: import_joi46.default.string().optional().valid(...Object.values(VehicleStatus)).allow("")
|
|
16633
17070
|
});
|
|
16634
17071
|
const query = { ...req.query };
|
|
16635
17072
|
const { error } = validation.validate(query);
|
|
@@ -16643,6 +17080,7 @@ function useVehicleController() {
|
|
|
16643
17080
|
const limit = parseInt(req.query.limit ?? "10");
|
|
16644
17081
|
const type = req.query.type ?? "";
|
|
16645
17082
|
const category = req.query.category ?? "";
|
|
17083
|
+
const status = req.query.status ?? "";
|
|
16646
17084
|
const sortObj = {};
|
|
16647
17085
|
const sortFields = String(req.query.sort).split(",");
|
|
16648
17086
|
const sortOrders = String(req.query.order).split(",");
|
|
@@ -16659,7 +17097,8 @@ function useVehicleController() {
|
|
|
16659
17097
|
limit,
|
|
16660
17098
|
sort: sortObj,
|
|
16661
17099
|
type,
|
|
16662
|
-
category
|
|
17100
|
+
category,
|
|
17101
|
+
status
|
|
16663
17102
|
});
|
|
16664
17103
|
res.json(data);
|
|
16665
17104
|
return;
|
|
@@ -16715,7 +17154,8 @@ function useVehicleController() {
|
|
|
16715
17154
|
block: import_joi46.default.number().integer().optional().allow(0, null),
|
|
16716
17155
|
level: import_joi46.default.string().optional().allow("", null),
|
|
16717
17156
|
unit: import_joi46.default.string().optional().allow("", null),
|
|
16718
|
-
plateNumber: import_joi46.default.string().optional().allow("", null)
|
|
17157
|
+
plateNumber: import_joi46.default.string().optional().allow("", null),
|
|
17158
|
+
nric: import_joi46.default.string().optional().allow("", null)
|
|
16719
17159
|
});
|
|
16720
17160
|
const _id = req.params.id;
|
|
16721
17161
|
const payload = { ...req.body };
|
|
@@ -16736,23 +17176,23 @@ function useVehicleController() {
|
|
|
16736
17176
|
}
|
|
16737
17177
|
}
|
|
16738
17178
|
async function deleteVehicle(req, res, next) {
|
|
16739
|
-
const
|
|
16740
|
-
const _id = req.params.id ?? "";
|
|
16741
|
-
const recno = req.params.recno ?? "";
|
|
16742
|
-
const bypass = req.query.bypass === "true";
|
|
17179
|
+
const _id = req.params.id;
|
|
16743
17180
|
const deleteVehicleSchema = import_joi46.default.object({
|
|
16744
|
-
_id: import_joi46.default.string().hex().required(),
|
|
17181
|
+
_id: import_joi46.default.string().hex().length(24).required(),
|
|
16745
17182
|
recno: import_joi46.default.string().required(),
|
|
16746
|
-
|
|
17183
|
+
site: import_joi46.default.string().hex().length(24).required(),
|
|
17184
|
+
type: import_joi46.default.string().valid("whitelist", "blocklist").required(),
|
|
17185
|
+
bypass: import_joi46.default.boolean().optional().default(true)
|
|
16747
17186
|
});
|
|
16748
|
-
const { error } = deleteVehicleSchema.validate({ _id,
|
|
17187
|
+
const { error, value } = deleteVehicleSchema.validate({ _id, ...req.body });
|
|
16749
17188
|
if (error) {
|
|
16750
17189
|
import_node_server_utils84.logger.log({ level: "error", message: error.message });
|
|
16751
17190
|
next(new import_node_server_utils84.BadRequestError(error.message));
|
|
16752
17191
|
return;
|
|
16753
17192
|
}
|
|
17193
|
+
const { recno, site, type, bypass } = value;
|
|
16754
17194
|
try {
|
|
16755
|
-
const data = await _deleteVehicle(_id, recno, site, bypass);
|
|
17195
|
+
const data = await _deleteVehicle(_id, recno, site, type, bypass);
|
|
16756
17196
|
res.json({
|
|
16757
17197
|
message: "Vehicle deleted successfully.",
|
|
16758
17198
|
data
|
|
@@ -16763,13 +17203,83 @@ function useVehicleController() {
|
|
|
16763
17203
|
return;
|
|
16764
17204
|
}
|
|
16765
17205
|
}
|
|
17206
|
+
async function approveVehicleById(req, res, next) {
|
|
17207
|
+
const validation = import_joi46.default.object({
|
|
17208
|
+
_id: import_joi46.default.string().hex().length(24).required(),
|
|
17209
|
+
org: import_joi46.default.string().hex().length(24).required(),
|
|
17210
|
+
site: import_joi46.default.string().hex().length(24).required()
|
|
17211
|
+
});
|
|
17212
|
+
const _id = req.params.id;
|
|
17213
|
+
const payload = { ...req.body };
|
|
17214
|
+
const { error, value } = validation.validate({ _id, ...payload });
|
|
17215
|
+
if (error) {
|
|
17216
|
+
import_node_server_utils84.logger.log({ level: "error", message: error.message });
|
|
17217
|
+
next(new import_node_server_utils84.BadRequestError(error.message));
|
|
17218
|
+
return;
|
|
17219
|
+
}
|
|
17220
|
+
try {
|
|
17221
|
+
await _approveVehicleById(value._id, value.org, value.site);
|
|
17222
|
+
res.json({ message: "Successfully approved and updated vehicle." });
|
|
17223
|
+
return;
|
|
17224
|
+
} catch (error2) {
|
|
17225
|
+
import_node_server_utils84.logger.log({ level: "error", message: error2.message });
|
|
17226
|
+
next(error2);
|
|
17227
|
+
return;
|
|
17228
|
+
}
|
|
17229
|
+
}
|
|
17230
|
+
async function getVehiclesByNRIC(req, res, next) {
|
|
17231
|
+
const allowedFields = ["start", "end"];
|
|
17232
|
+
const allowedOrder = ["asc", "desc"];
|
|
17233
|
+
const validation = import_joi46.default.object({
|
|
17234
|
+
search: import_joi46.default.string().optional().allow("", null),
|
|
17235
|
+
page: import_joi46.default.number().integer().min(1).allow("", null).default(1),
|
|
17236
|
+
limit: import_joi46.default.number().integer().min(1).max(100).allow("", null).default(10),
|
|
17237
|
+
sort: import_joi46.default.string().pattern(/^([a-zA-Z0-9_]+)(,[a-zA-Z0-9_]+)*$/).optional().allow("", ...allowedFields),
|
|
17238
|
+
order: import_joi46.default.string().pattern(/^(asc|desc)(,(asc|desc))*$/).optional().allow("", ...allowedOrder)
|
|
17239
|
+
});
|
|
17240
|
+
const query = { ...req.query };
|
|
17241
|
+
const { error } = validation.validate(query);
|
|
17242
|
+
if (error) {
|
|
17243
|
+
import_node_server_utils84.logger.log({ level: "error", message: error.message });
|
|
17244
|
+
next(new import_node_server_utils84.BadRequestError(error.message));
|
|
17245
|
+
return;
|
|
17246
|
+
}
|
|
17247
|
+
const search = req.query.search ?? "";
|
|
17248
|
+
const page = parseInt(req.query.page ?? "1");
|
|
17249
|
+
const limit = parseInt(req.query.limit ?? "10");
|
|
17250
|
+
const sortObj = {};
|
|
17251
|
+
const sortFields = String(req.query.sort).split(",");
|
|
17252
|
+
const sortOrders = String(req.query.order).split(",");
|
|
17253
|
+
sortFields.forEach((field, index) => {
|
|
17254
|
+
if (allowedFields.includes(field)) {
|
|
17255
|
+
const order = sortOrders[index] === "asc" ? 1 : -1;
|
|
17256
|
+
sortObj[field] = order;
|
|
17257
|
+
}
|
|
17258
|
+
});
|
|
17259
|
+
try {
|
|
17260
|
+
const data = await _getVehiclesByNRIC({
|
|
17261
|
+
search,
|
|
17262
|
+
page,
|
|
17263
|
+
limit,
|
|
17264
|
+
sort: sortObj
|
|
17265
|
+
});
|
|
17266
|
+
res.json(data);
|
|
17267
|
+
return;
|
|
17268
|
+
} catch (error2) {
|
|
17269
|
+
import_node_server_utils84.logger.log({ level: "error", message: error2.message });
|
|
17270
|
+
next(error2);
|
|
17271
|
+
return;
|
|
17272
|
+
}
|
|
17273
|
+
}
|
|
16766
17274
|
return {
|
|
16767
17275
|
add,
|
|
16768
17276
|
getVehicles,
|
|
16769
17277
|
getSeasonPassTypes,
|
|
16770
17278
|
getVehicleById,
|
|
16771
17279
|
updateVehicle,
|
|
16772
|
-
deleteVehicle
|
|
17280
|
+
deleteVehicle,
|
|
17281
|
+
approveVehicleById,
|
|
17282
|
+
getVehiclesByNRIC
|
|
16773
17283
|
};
|
|
16774
17284
|
}
|
|
16775
17285
|
|
|
@@ -16868,7 +17378,7 @@ function useSiteCameraController() {
|
|
|
16868
17378
|
}
|
|
16869
17379
|
async function getAll(req, res, next) {
|
|
16870
17380
|
const query = req.query;
|
|
16871
|
-
const
|
|
17381
|
+
const allowedTypes = ["ip", "exit", "entry", "both"];
|
|
16872
17382
|
const validation = import_joi47.default.object({
|
|
16873
17383
|
type: import_joi47.default.string().optional(),
|
|
16874
17384
|
site: import_joi47.default.string().optional(),
|
|
@@ -24228,20 +24738,19 @@ function useDocumentManagementController() {
|
|
|
24228
24738
|
// src/models/bulletin-board.model.ts
|
|
24229
24739
|
var import_joi75 = __toESM(require("joi"));
|
|
24230
24740
|
var import_mongodb71 = require("mongodb");
|
|
24741
|
+
var BULLETIN_RECIPIENTS = [
|
|
24742
|
+
"resident",
|
|
24743
|
+
"security_agency",
|
|
24744
|
+
"cleaning_services",
|
|
24745
|
+
"mechanical_electrical",
|
|
24746
|
+
"property_management_agency"
|
|
24747
|
+
];
|
|
24748
|
+
var STATUS_VALUES = ["active", "expired", "deleted"];
|
|
24231
24749
|
var schemaBulletinBoard = import_joi75.default.object({
|
|
24232
24750
|
_id: import_joi75.default.string().hex().optional().allow("", null),
|
|
24233
24751
|
site: import_joi75.default.string().hex().optional().allow("", null),
|
|
24234
24752
|
orgId: import_joi75.default.string().hex().optional().allow("", null),
|
|
24235
|
-
recipients: import_joi75.default.array().items(
|
|
24236
|
-
import_joi75.default.string().valid(
|
|
24237
|
-
"admin",
|
|
24238
|
-
"organization",
|
|
24239
|
-
"site",
|
|
24240
|
-
"service-provider",
|
|
24241
|
-
"service-provider-member",
|
|
24242
|
-
"resident"
|
|
24243
|
-
)
|
|
24244
|
-
).optional(),
|
|
24753
|
+
recipients: import_joi75.default.array().items(import_joi75.default.string().valid(...BULLETIN_RECIPIENTS)).unique().optional(),
|
|
24245
24754
|
title: import_joi75.default.string().optional().allow("", null),
|
|
24246
24755
|
content: import_joi75.default.string().optional().allow("", null),
|
|
24247
24756
|
file: import_joi75.default.array().items(
|
|
@@ -24254,23 +24763,14 @@ var schemaBulletinBoard = import_joi75.default.object({
|
|
|
24254
24763
|
noExpiration: import_joi75.default.boolean().optional(),
|
|
24255
24764
|
startDate: import_joi75.default.date().optional().allow("", null),
|
|
24256
24765
|
endDate: import_joi75.default.date().optional().allow("", null),
|
|
24257
|
-
status: import_joi75.default.string().
|
|
24766
|
+
status: import_joi75.default.string().valid(...STATUS_VALUES).optional(),
|
|
24258
24767
|
createdAt: import_joi75.default.date().optional().allow(null),
|
|
24259
24768
|
updatedAt: import_joi75.default.date().optional().allow(null),
|
|
24260
24769
|
deletedAt: import_joi75.default.date().optional().allow(null)
|
|
24261
24770
|
});
|
|
24262
24771
|
var schemaUpdateBulletinBoard = import_joi75.default.object({
|
|
24263
24772
|
_id: import_joi75.default.string().hex().required(),
|
|
24264
|
-
recipients: import_joi75.default.array().items(
|
|
24265
|
-
import_joi75.default.string().valid(
|
|
24266
|
-
"admin",
|
|
24267
|
-
"organization",
|
|
24268
|
-
"site",
|
|
24269
|
-
"service-provider",
|
|
24270
|
-
"service-provider-member",
|
|
24271
|
-
"resident"
|
|
24272
|
-
)
|
|
24273
|
-
).optional(),
|
|
24773
|
+
recipients: import_joi75.default.array().items(import_joi75.default.string().valid(...BULLETIN_RECIPIENTS)).unique().optional(),
|
|
24274
24774
|
title: import_joi75.default.string().optional().allow("", null),
|
|
24275
24775
|
content: import_joi75.default.string().optional().allow("", null),
|
|
24276
24776
|
file: import_joi75.default.array().items(
|
|
@@ -24283,7 +24783,7 @@ var schemaUpdateBulletinBoard = import_joi75.default.object({
|
|
|
24283
24783
|
noExpiration: import_joi75.default.boolean().optional(),
|
|
24284
24784
|
startDate: import_joi75.default.date().optional().allow("", null),
|
|
24285
24785
|
endDate: import_joi75.default.date().optional().allow("", null),
|
|
24286
|
-
status: import_joi75.default.string().
|
|
24786
|
+
status: import_joi75.default.string().valid(...STATUS_VALUES).optional()
|
|
24287
24787
|
});
|
|
24288
24788
|
function MBulletinBoard(value) {
|
|
24289
24789
|
const { error } = schemaBulletinBoard.validate(value);
|
|
@@ -24374,7 +24874,8 @@ function useBulletinBoardRepo() {
|
|
|
24374
24874
|
limit = 10,
|
|
24375
24875
|
sort = {},
|
|
24376
24876
|
site = "",
|
|
24377
|
-
status = "active"
|
|
24877
|
+
status = "active",
|
|
24878
|
+
recipients = []
|
|
24378
24879
|
}, session) {
|
|
24379
24880
|
page = page > 0 ? page - 1 : 0;
|
|
24380
24881
|
try {
|
|
@@ -24384,7 +24885,9 @@ function useBulletinBoardRepo() {
|
|
|
24384
24885
|
}
|
|
24385
24886
|
const query = {
|
|
24386
24887
|
site,
|
|
24387
|
-
status
|
|
24888
|
+
status,
|
|
24889
|
+
...search && { $text: { $search: search } },
|
|
24890
|
+
...recipients?.length && { recipients: { $in: recipients } }
|
|
24388
24891
|
};
|
|
24389
24892
|
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
24390
24893
|
const cacheOptions = {
|
|
@@ -24392,12 +24895,10 @@ function useBulletinBoardRepo() {
|
|
|
24392
24895
|
status,
|
|
24393
24896
|
sort: JSON.stringify(sort),
|
|
24394
24897
|
page,
|
|
24395
|
-
limit
|
|
24898
|
+
limit,
|
|
24899
|
+
...search && { search },
|
|
24900
|
+
...recipients?.length && { recipients: recipients.sort().join(",") }
|
|
24396
24901
|
};
|
|
24397
|
-
if (search) {
|
|
24398
|
-
query.$text = { $search: search };
|
|
24399
|
-
cacheOptions.search = search;
|
|
24400
|
-
}
|
|
24401
24902
|
const cacheKey = (0, import_node_server_utils131.makeCacheKey)(namespace_collection, cacheOptions);
|
|
24402
24903
|
const cachedData = await getCache(cacheKey);
|
|
24403
24904
|
if (cachedData) {
|
|
@@ -24489,7 +24990,7 @@ function useBulletinBoardRepo() {
|
|
|
24489
24990
|
throw error;
|
|
24490
24991
|
}
|
|
24491
24992
|
}
|
|
24492
|
-
async function deleteBulletinBoardById(_id) {
|
|
24993
|
+
async function deleteBulletinBoardById(_id, session) {
|
|
24493
24994
|
try {
|
|
24494
24995
|
_id = new import_mongodb72.ObjectId(_id);
|
|
24495
24996
|
} catch (error) {
|
|
@@ -24501,7 +25002,11 @@ function useBulletinBoardRepo() {
|
|
|
24501
25002
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24502
25003
|
deletedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
24503
25004
|
};
|
|
24504
|
-
const res = await collection.updateOne(
|
|
25005
|
+
const res = await collection.updateOne(
|
|
25006
|
+
{ _id },
|
|
25007
|
+
{ $set: updateValue },
|
|
25008
|
+
{ session }
|
|
25009
|
+
);
|
|
24505
25010
|
if (res.modifiedCount === 0) {
|
|
24506
25011
|
throw new import_node_server_utils131.InternalServerError("Unable to delete bulletin board.");
|
|
24507
25012
|
}
|
|
@@ -24567,8 +25072,11 @@ function useBulletinBoardService() {
|
|
|
24567
25072
|
const {
|
|
24568
25073
|
add: _add,
|
|
24569
25074
|
updateBulletinBoardById: _updateBulletinBoardById,
|
|
24570
|
-
processExpiredBulletinBoards: _processExpiredBulletinBoards
|
|
25075
|
+
processExpiredBulletinBoards: _processExpiredBulletinBoards,
|
|
25076
|
+
deleteBulletinBoardById: _deleteBulletinBoardById,
|
|
25077
|
+
getBulletinBoardById: _getBulletinBoardById
|
|
24571
25078
|
} = useBulletinBoardRepo();
|
|
25079
|
+
const { deleteFileById: _deleteFileById } = useFileRepo();
|
|
24572
25080
|
async function add(value) {
|
|
24573
25081
|
const session = import_node_server_utils132.useAtlas.getClient()?.startSession();
|
|
24574
25082
|
session?.startTransaction();
|
|
@@ -24611,10 +25119,31 @@ function useBulletinBoardService() {
|
|
|
24611
25119
|
session?.endSession();
|
|
24612
25120
|
}
|
|
24613
25121
|
}
|
|
25122
|
+
async function deleteBulletinBoardById(id) {
|
|
25123
|
+
const session = import_node_server_utils132.useAtlas.getClient()?.startSession();
|
|
25124
|
+
session?.startTransaction();
|
|
25125
|
+
try {
|
|
25126
|
+
const existingBulletinBoard = await _getBulletinBoardById(id);
|
|
25127
|
+
if (Array.isArray(existingBulletinBoard.file)) {
|
|
25128
|
+
for (const file of existingBulletinBoard.file) {
|
|
25129
|
+
await _deleteFileById(file, session);
|
|
25130
|
+
}
|
|
25131
|
+
}
|
|
25132
|
+
await _deleteBulletinBoardById(id, session);
|
|
25133
|
+
await session?.commitTransaction();
|
|
25134
|
+
return "Successfully deleted bulletin board.";
|
|
25135
|
+
} catch (error) {
|
|
25136
|
+
await session?.abortTransaction();
|
|
25137
|
+
throw error;
|
|
25138
|
+
} finally {
|
|
25139
|
+
session?.endSession();
|
|
25140
|
+
}
|
|
25141
|
+
}
|
|
24614
25142
|
return {
|
|
24615
25143
|
add,
|
|
24616
25144
|
updateBulletinBoardById,
|
|
24617
|
-
processExpiredBulletinBoards
|
|
25145
|
+
processExpiredBulletinBoards,
|
|
25146
|
+
deleteBulletinBoardById
|
|
24618
25147
|
};
|
|
24619
25148
|
}
|
|
24620
25149
|
|
|
@@ -24622,12 +25151,12 @@ function useBulletinBoardService() {
|
|
|
24622
25151
|
var import_node_server_utils133 = require("@7365admin1/node-server-utils");
|
|
24623
25152
|
var import_joi76 = __toESM(require("joi"));
|
|
24624
25153
|
function useBulletinBoardController() {
|
|
24625
|
-
const { add: _add, updateBulletinBoardById: _updateBulletinBoardById } = useBulletinBoardService();
|
|
24626
25154
|
const {
|
|
24627
|
-
|
|
24628
|
-
|
|
25155
|
+
add: _add,
|
|
25156
|
+
updateBulletinBoardById: _updateBulletinBoardById,
|
|
24629
25157
|
deleteBulletinBoardById: _deleteBulletinBoardById
|
|
24630
|
-
} =
|
|
25158
|
+
} = useBulletinBoardService();
|
|
25159
|
+
const { getAll: _getAll, getBulletinBoardById: _getBulletinBoardById } = useBulletinBoardRepo();
|
|
24631
25160
|
async function add(req, res, next) {
|
|
24632
25161
|
const payload = { ...req.body };
|
|
24633
25162
|
const { error } = schemaBulletinBoard.validate(payload, {
|
|
@@ -24659,12 +25188,23 @@ function useBulletinBoardController() {
|
|
|
24659
25188
|
sort: import_joi76.default.string().pattern(/^([a-zA-Z0-9_]+)(,[a-zA-Z0-9_]+)*$/).optional().allow("", ...allowedFields),
|
|
24660
25189
|
order: import_joi76.default.string().pattern(/^(asc|desc)(,(asc|desc))*$/).optional().allow("", ...allowedOrder),
|
|
24661
25190
|
site: import_joi76.default.string().hex().required(),
|
|
24662
|
-
status: import_joi76.default.string().optional().allow(null, "")
|
|
25191
|
+
status: import_joi76.default.string().optional().allow(null, ""),
|
|
25192
|
+
recipients: import_joi76.default.string().optional().allow("", null).custom((value, helpers) => {
|
|
25193
|
+
const parsed = value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
25194
|
+
for (const r of parsed) {
|
|
25195
|
+
if (!BULLETIN_RECIPIENTS.includes(r)) {
|
|
25196
|
+
return helpers.error("any.only");
|
|
25197
|
+
}
|
|
25198
|
+
}
|
|
25199
|
+
return value;
|
|
25200
|
+
}).messages({
|
|
25201
|
+
"any.only": `Recipients must be one of: ${BULLETIN_RECIPIENTS.join(
|
|
25202
|
+
", "
|
|
25203
|
+
)}`
|
|
25204
|
+
})
|
|
24663
25205
|
});
|
|
24664
25206
|
const query = { ...req.query };
|
|
24665
|
-
const { error } = validation.validate(query, {
|
|
24666
|
-
abortEarly: false
|
|
24667
|
-
});
|
|
25207
|
+
const { error } = validation.validate(query, { abortEarly: false });
|
|
24668
25208
|
if (error) {
|
|
24669
25209
|
const messages = error.details.map((d) => d.message).join(", ");
|
|
24670
25210
|
import_node_server_utils133.logger.log({ level: "error", message: messages });
|
|
@@ -24676,9 +25216,15 @@ function useBulletinBoardController() {
|
|
|
24676
25216
|
const limit = parseInt(req.query.limit ?? "10");
|
|
24677
25217
|
const site = req.query.site ?? "";
|
|
24678
25218
|
const status = req.query.status ?? "active";
|
|
25219
|
+
const recipientsRaw = req.query.recipients ?? "";
|
|
25220
|
+
const recipients = recipientsRaw && typeof recipientsRaw === "string" ? Array.from(
|
|
25221
|
+
new Set(
|
|
25222
|
+
recipientsRaw.split(",").map((r) => r.trim()).filter(Boolean)
|
|
25223
|
+
)
|
|
25224
|
+
) : [];
|
|
24679
25225
|
const sortObj = {};
|
|
24680
|
-
const sortFields = String(req.query.sort).split(",");
|
|
24681
|
-
const sortOrders = String(req.query.order).split(",");
|
|
25226
|
+
const sortFields = String(req.query.sort ?? "").split(",").filter(Boolean);
|
|
25227
|
+
const sortOrders = String(req.query.order ?? "").split(",").filter(Boolean);
|
|
24682
25228
|
sortFields.forEach((field, index) => {
|
|
24683
25229
|
if (allowedFields.includes(field)) {
|
|
24684
25230
|
const order = sortOrders[index] === "asc" ? 1 : -1;
|
|
@@ -24692,7 +25238,8 @@ function useBulletinBoardController() {
|
|
|
24692
25238
|
limit,
|
|
24693
25239
|
sort: sortObj,
|
|
24694
25240
|
site,
|
|
24695
|
-
status
|
|
25241
|
+
status,
|
|
25242
|
+
recipients
|
|
24696
25243
|
});
|
|
24697
25244
|
res.status(200).json(data);
|
|
24698
25245
|
return;
|
|
@@ -24775,6 +25322,16 @@ function useBulletinBoardController() {
|
|
|
24775
25322
|
var import_node_server_utils134 = require("@7365admin1/node-server-utils");
|
|
24776
25323
|
var import_mongodb73 = require("mongodb");
|
|
24777
25324
|
var import_joi77 = __toESM(require("joi"));
|
|
25325
|
+
|
|
25326
|
+
// src/types/enums/billing-frequency.enum.ts
|
|
25327
|
+
var EBillingFrequency = /* @__PURE__ */ ((EBillingFrequency2) => {
|
|
25328
|
+
EBillingFrequency2["MONTHLY"] = "monthly";
|
|
25329
|
+
EBillingFrequency2["QAURTERLY"] = "quarterly";
|
|
25330
|
+
EBillingFrequency2["ANNUALLY"] = "annually";
|
|
25331
|
+
return EBillingFrequency2;
|
|
25332
|
+
})(EBillingFrequency || {});
|
|
25333
|
+
|
|
25334
|
+
// src/models/site-billing-item.model.ts
|
|
24778
25335
|
var schemaUnits = import_joi77.default.object({
|
|
24779
25336
|
_id: import_joi77.default.string().hex().optional(),
|
|
24780
25337
|
name: import_joi77.default.string().optional()
|
|
@@ -24785,7 +25342,7 @@ var schemaBillingItem = import_joi77.default.object({
|
|
|
24785
25342
|
org: import_joi77.default.string().hex().required(),
|
|
24786
25343
|
name: import_joi77.default.string().required(),
|
|
24787
25344
|
amount: import_joi77.default.number().required(),
|
|
24788
|
-
frequency: import_joi77.default.string().valid(
|
|
25345
|
+
frequency: import_joi77.default.string().valid(...Object.values(EBillingFrequency)).required(),
|
|
24789
25346
|
billingType: import_joi77.default.string().valid("recurring", "non-recurring").required(),
|
|
24790
25347
|
dueInDays: import_joi77.default.number().optional().allow(null, ""),
|
|
24791
25348
|
date: import_joi77.default.string().required(),
|
|
@@ -24810,7 +25367,7 @@ var schemaUpdateSiteBillingItem = import_joi77.default.object({
|
|
|
24810
25367
|
org: import_joi77.default.string().hex().optional().allow(null, ""),
|
|
24811
25368
|
name: import_joi77.default.string().optional().allow(null, ""),
|
|
24812
25369
|
amount: import_joi77.default.number().optional().allow(null, ""),
|
|
24813
|
-
frequency: import_joi77.default.string().valid(
|
|
25370
|
+
frequency: import_joi77.default.string().valid(...Object.values(EBillingFrequency)).optional().allow(null, ""),
|
|
24814
25371
|
billingType: import_joi77.default.string().valid("recurring", "non-recurring").optional().allow(null, ""),
|
|
24815
25372
|
dueInDays: import_joi77.default.number().optional().allow(null, ""),
|
|
24816
25373
|
date: import_joi77.default.string().optional().allow(null, ""),
|
|
@@ -24955,7 +25512,16 @@ function useSiteBillingItemRepo() {
|
|
|
24955
25512
|
...search && {
|
|
24956
25513
|
$or: [
|
|
24957
25514
|
{ name: { $regex: search, $options: "i" } },
|
|
24958
|
-
{ frequency: { $regex: search, $options: "i" } }
|
|
25515
|
+
{ frequency: { $regex: search, $options: "i" } },
|
|
25516
|
+
{
|
|
25517
|
+
$expr: {
|
|
25518
|
+
$regexMatch: {
|
|
25519
|
+
input: { $toString: "$totalAmount" },
|
|
25520
|
+
regex: search,
|
|
25521
|
+
options: "i"
|
|
25522
|
+
}
|
|
25523
|
+
}
|
|
25524
|
+
}
|
|
24959
25525
|
]
|
|
24960
25526
|
},
|
|
24961
25527
|
...import_mongodb74.ObjectId.isValid(site) && { site: new import_mongodb74.ObjectId(site) }
|
|
@@ -26105,7 +26671,8 @@ function useEventManagementRepo() {
|
|
|
26105
26671
|
sort = {},
|
|
26106
26672
|
site = "",
|
|
26107
26673
|
status = "",
|
|
26108
|
-
type = ""
|
|
26674
|
+
type = "",
|
|
26675
|
+
date = ""
|
|
26109
26676
|
}, session) {
|
|
26110
26677
|
page = page > 0 ? page - 1 : 0;
|
|
26111
26678
|
try {
|
|
@@ -26116,7 +26683,13 @@ function useEventManagementRepo() {
|
|
|
26116
26683
|
const baseQuery = {
|
|
26117
26684
|
site,
|
|
26118
26685
|
status: status ? status : { $ne: "deleted" },
|
|
26119
|
-
...type && { type }
|
|
26686
|
+
...type && { type },
|
|
26687
|
+
...date && {
|
|
26688
|
+
dateTime: {
|
|
26689
|
+
$gte: `${date}T00:00:00.000Z`,
|
|
26690
|
+
$lt: `${date}T23:59:59.999Z`
|
|
26691
|
+
}
|
|
26692
|
+
}
|
|
26120
26693
|
};
|
|
26121
26694
|
let query = { ...baseQuery };
|
|
26122
26695
|
sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
|
|
@@ -26414,7 +26987,8 @@ function useEventManagementController() {
|
|
|
26414
26987
|
order: import_joi82.default.string().pattern(/^(asc|desc)(,(asc|desc))*$/).optional().allow("", ...allowedOrder),
|
|
26415
26988
|
site: import_joi82.default.string().hex().required(),
|
|
26416
26989
|
status: import_joi82.default.string().optional(),
|
|
26417
|
-
type: import_joi82.default.string().optional().valid("TASK", "EVENT").allow(null, "")
|
|
26990
|
+
type: import_joi82.default.string().optional().valid("TASK", "EVENT").allow(null, ""),
|
|
26991
|
+
date: import_joi82.default.string().optional().allow(null, "")
|
|
26418
26992
|
});
|
|
26419
26993
|
const query = { ...req.query };
|
|
26420
26994
|
const { error } = validation.validate(query, {
|
|
@@ -26432,6 +27006,7 @@ function useEventManagementController() {
|
|
|
26432
27006
|
const site = req.query.site ?? "";
|
|
26433
27007
|
const status = req.query.status ?? "";
|
|
26434
27008
|
const type = req.query.type ?? "";
|
|
27009
|
+
const date = req.query.date ?? "";
|
|
26435
27010
|
const sortObj = {};
|
|
26436
27011
|
const sortFields = String(req.query.sort).split(",");
|
|
26437
27012
|
const sortOrders = String(req.query.order).split(",");
|
|
@@ -26449,7 +27024,8 @@ function useEventManagementController() {
|
|
|
26449
27024
|
sort: sortObj,
|
|
26450
27025
|
site,
|
|
26451
27026
|
status,
|
|
26452
|
-
type
|
|
27027
|
+
type,
|
|
27028
|
+
date
|
|
26453
27029
|
});
|
|
26454
27030
|
res.status(200).json(data);
|
|
26455
27031
|
return;
|
|
@@ -26766,6 +27342,7 @@ function useSiteUnitBillingRepo() {
|
|
|
26766
27342
|
}
|
|
26767
27343
|
};
|
|
26768
27344
|
}
|
|
27345
|
+
const unitSearchRegex = search ? search.trim().replace(/\s+/g, "").replace(/\//g, "\\s*/\\s*") : null;
|
|
26769
27346
|
const query = {
|
|
26770
27347
|
paymentStatus,
|
|
26771
27348
|
status,
|
|
@@ -26773,7 +27350,16 @@ function useSiteUnitBillingRepo() {
|
|
|
26773
27350
|
$or: [
|
|
26774
27351
|
{ unitOwner: { $regex: search, $options: "i" } },
|
|
26775
27352
|
{ billName: { $regex: search, $options: "i" } },
|
|
26776
|
-
{ unit: { $regex:
|
|
27353
|
+
{ unit: { $regex: unitSearchRegex, $options: "i" } },
|
|
27354
|
+
{
|
|
27355
|
+
$expr: {
|
|
27356
|
+
$regexMatch: {
|
|
27357
|
+
input: { $toString: "$amountPaid" },
|
|
27358
|
+
regex: search,
|
|
27359
|
+
options: "i"
|
|
27360
|
+
}
|
|
27361
|
+
}
|
|
27362
|
+
}
|
|
26777
27363
|
]
|
|
26778
27364
|
},
|
|
26779
27365
|
...import_mongodb80.ObjectId.isValid(site) && { site: new import_mongodb80.ObjectId(site) },
|
|
@@ -27196,14 +27782,14 @@ function useSiteUnitBillingService() {
|
|
|
27196
27782
|
function isBillingChecker(billing_item, todayMonth, todayDate) {
|
|
27197
27783
|
const billingMonth = Number(billing_item.month);
|
|
27198
27784
|
const billingDay = Number(billing_item.date);
|
|
27199
|
-
if (billing_item.frequency === "
|
|
27785
|
+
if (billing_item.frequency === "monthly" /* MONTHLY */) {
|
|
27200
27786
|
return todayDate === billingDay;
|
|
27201
27787
|
}
|
|
27202
|
-
if (billing_item.frequency === "
|
|
27788
|
+
if (billing_item.frequency === "quarterly" /* QAURTERLY */) {
|
|
27203
27789
|
const monthDiff = todayMonth - billingMonth;
|
|
27204
27790
|
return monthDiff % 3 === 0 && todayDate === billingDay;
|
|
27205
27791
|
}
|
|
27206
|
-
if (billing_item.frequency === "
|
|
27792
|
+
if (billing_item.frequency === "annually" /* ANNUALLY */) {
|
|
27207
27793
|
return todayMonth === billingMonth && todayDate === billingDay;
|
|
27208
27794
|
}
|
|
27209
27795
|
return false;
|
|
@@ -27995,7 +28581,7 @@ function UseAccessManagementRepo() {
|
|
|
27995
28581
|
{
|
|
27996
28582
|
$match: {
|
|
27997
28583
|
...defaultQuery,
|
|
27998
|
-
status: { $
|
|
28584
|
+
status: { $eq: "active" }
|
|
27999
28585
|
}
|
|
28000
28586
|
},
|
|
28001
28587
|
// ✅ Only project needed fields before heavy lookups
|
|
@@ -28115,7 +28701,7 @@ function UseAccessManagementRepo() {
|
|
|
28115
28701
|
userType
|
|
28116
28702
|
}
|
|
28117
28703
|
},
|
|
28118
|
-
{ $project: { _id: 1, userId: 1, type: 1, cardNo: 1, isActivated: 1 } }
|
|
28704
|
+
{ $project: { _id: 1, userId: 1, type: 1, cardNo: 1, isActivated: 1, replacementStatus: 1 } }
|
|
28119
28705
|
],
|
|
28120
28706
|
as: "accessCards"
|
|
28121
28707
|
}
|
|
@@ -28134,7 +28720,21 @@ function UseAccessManagementRepo() {
|
|
|
28134
28720
|
$filter: {
|
|
28135
28721
|
input: "$accessCards",
|
|
28136
28722
|
as: "card",
|
|
28137
|
-
cond: { $ne: ["$$card.userId", null] }
|
|
28723
|
+
cond: { $and: [{ $ne: ["$$card.userId", null] }, { $eq: ["$$card.isActivated", true] }] }
|
|
28724
|
+
}
|
|
28725
|
+
},
|
|
28726
|
+
f_replaced: {
|
|
28727
|
+
$filter: {
|
|
28728
|
+
input: "$accessCards",
|
|
28729
|
+
as: "card",
|
|
28730
|
+
cond: { $and: [{ $eq: ["$$card.isActivated", false] }, { $ne: ["$$card.replacementStatus", null] }] }
|
|
28731
|
+
}
|
|
28732
|
+
},
|
|
28733
|
+
f_deleted: {
|
|
28734
|
+
$filter: {
|
|
28735
|
+
input: "$accessCards",
|
|
28736
|
+
as: "card",
|
|
28737
|
+
cond: { $and: [{ $eq: ["$$card.isActivated", false] }, { $eq: ["$$card.replacementStatus", null] }] }
|
|
28138
28738
|
}
|
|
28139
28739
|
}
|
|
28140
28740
|
}
|
|
@@ -28166,6 +28766,14 @@ function UseAccessManagementRepo() {
|
|
|
28166
28766
|
non_physical: { $size: { $filter: { input: { $ifNull: ["$f_Assigned", []] }, as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } } }
|
|
28167
28767
|
}
|
|
28168
28768
|
},
|
|
28769
|
+
replaced: {
|
|
28770
|
+
physical: { $filter: { input: "$f_replaced", as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } },
|
|
28771
|
+
non_physical: { $filter: { input: "$f_replaced", as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } }
|
|
28772
|
+
},
|
|
28773
|
+
deleted: {
|
|
28774
|
+
physical: { $filter: { input: "$f_deleted", as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } },
|
|
28775
|
+
non_physical: { $filter: { input: "$f_deleted", as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } }
|
|
28776
|
+
},
|
|
28169
28777
|
totalCardCount: {
|
|
28170
28778
|
$add: [
|
|
28171
28779
|
{ $size: { $filter: { input: { $ifNull: ["$f_Available", []] }, as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } } },
|
|
@@ -28622,16 +29230,26 @@ function UseAccessManagementRepo() {
|
|
|
28622
29230
|
async function cardReplacementRepo(params) {
|
|
28623
29231
|
const session = import_node_server_utils149.useAtlas.getClient()?.startSession();
|
|
28624
29232
|
try {
|
|
28625
|
-
const { cardId, remarks } = params;
|
|
29233
|
+
const { cardId, remarks, issuedCardId, unitId, userId } = params;
|
|
28626
29234
|
const id = new import_mongodb83.ObjectId(cardId);
|
|
29235
|
+
const newCardId = new import_mongodb83.ObjectId(issuedCardId);
|
|
29236
|
+
const unit = new import_mongodb83.ObjectId(unitId);
|
|
29237
|
+
const user = new import_mongodb83.ObjectId(userId);
|
|
28627
29238
|
session?.startTransaction();
|
|
28628
|
-
const
|
|
28629
|
-
|
|
28630
|
-
|
|
28631
|
-
|
|
28632
|
-
|
|
29239
|
+
const sessionResult = await Promise.all([
|
|
29240
|
+
await collection().findOneAndUpdate(
|
|
29241
|
+
{ _id: id },
|
|
29242
|
+
{ $set: { remarks, replacementStatus: "Complete", requestDate: /* @__PURE__ */ new Date(), isActivated: false } },
|
|
29243
|
+
{ returnDocument: "after", session }
|
|
29244
|
+
),
|
|
29245
|
+
await collection().findOneAndUpdate(
|
|
29246
|
+
{ _id: newCardId },
|
|
29247
|
+
{ $set: { updatedAt: /* @__PURE__ */ new Date(), assignedUnit: unit, userId: user } },
|
|
29248
|
+
{ returnDocument: "after", session }
|
|
29249
|
+
)
|
|
29250
|
+
]);
|
|
28633
29251
|
await session?.commitTransaction();
|
|
28634
|
-
return
|
|
29252
|
+
return sessionResult;
|
|
28635
29253
|
} catch (error) {
|
|
28636
29254
|
await session?.abortTransaction();
|
|
28637
29255
|
throw new Error(error.message);
|
|
@@ -28880,7 +29498,8 @@ function UseAccessManagementRepo() {
|
|
|
28880
29498
|
rawItems.map(async (item) => {
|
|
28881
29499
|
const date = new Date(item["startDate (format MM/DD/YYYY)"]);
|
|
28882
29500
|
const endDate = new Date(date.setFullYear(date.getFullYear() + 10));
|
|
28883
|
-
const cardNumber = item["cardNo (number 0-65535 ex. 301)"]
|
|
29501
|
+
const cardNumber = String(Number(item["cardNo (number 0-65535 ex. 301)"] || 0)).padStart(6, "0");
|
|
29502
|
+
const facilityCode = String(Number(item["facilityCode (number 0-255 ex. 11)"] || 0)).padStart(4, "0");
|
|
28884
29503
|
const pin = item["pin (number 6 digits only)"] ? item["pin (number 6 digits only)"].toString().padStart(6, "0") : "123456";
|
|
28885
29504
|
const match = item["accessLevel (number ex. 1)"];
|
|
28886
29505
|
const accessLevel = match ? match : null;
|
|
@@ -28894,9 +29513,9 @@ function UseAccessManagementRepo() {
|
|
|
28894
29513
|
accessLevel,
|
|
28895
29514
|
accessGroup,
|
|
28896
29515
|
accessType: "Normal" /* NORMAL */,
|
|
28897
|
-
cardNo: cardNumber
|
|
29516
|
+
cardNo: `${facilityCode}${cardNumber}`,
|
|
28898
29517
|
pin,
|
|
28899
|
-
qrData: await createQrData({ cardNumber }),
|
|
29518
|
+
qrData: await createQrData({ cardNumber: `${facilityCode}${cardNumber}` }),
|
|
28900
29519
|
startDate: new Date(item["startDate (format MM/DD/YYYY)"]),
|
|
28901
29520
|
endDate: new Date(item["endDate (format MM/DD/YYYY)"] || endDate),
|
|
28902
29521
|
isActivated: true,
|
|
@@ -28970,6 +29589,66 @@ function UseAccessManagementRepo() {
|
|
|
28970
29589
|
session?.endSession();
|
|
28971
29590
|
}
|
|
28972
29591
|
}
|
|
29592
|
+
async function deleteCardRepo(params) {
|
|
29593
|
+
try {
|
|
29594
|
+
const { cardId, remarks } = params;
|
|
29595
|
+
const id = new import_mongodb83.ObjectId(cardId);
|
|
29596
|
+
const result = await collection().findOneAndUpdate({ _id: id }, { $set: { isActivated: false, updatedAt: /* @__PURE__ */ new Date(), remarks, requestDate: /* @__PURE__ */ new Date() } }, { returnDocument: "after" });
|
|
29597
|
+
return result;
|
|
29598
|
+
} catch (error) {
|
|
29599
|
+
throw new Error(error.message);
|
|
29600
|
+
}
|
|
29601
|
+
}
|
|
29602
|
+
async function getCardDetailsRepo(params) {
|
|
29603
|
+
try {
|
|
29604
|
+
const { siteId, cardId } = params;
|
|
29605
|
+
const convertedSiteId = new import_mongodb83.ObjectId(siteId);
|
|
29606
|
+
const convertedCardId = new import_mongodb83.ObjectId(cardId);
|
|
29607
|
+
const card = await collection().findOne(
|
|
29608
|
+
{
|
|
29609
|
+
_id: convertedCardId,
|
|
29610
|
+
site: convertedSiteId,
|
|
29611
|
+
type: "NFC" /* NFC */,
|
|
29612
|
+
userType: "Visitor/Resident" /* DEFAULT */
|
|
29613
|
+
},
|
|
29614
|
+
{
|
|
29615
|
+
projection: {
|
|
29616
|
+
userId: 1,
|
|
29617
|
+
site: 1,
|
|
29618
|
+
type: 1,
|
|
29619
|
+
userType: 1,
|
|
29620
|
+
cardNo: 1,
|
|
29621
|
+
isActivated: 1,
|
|
29622
|
+
replacementStatus: 1,
|
|
29623
|
+
vmsRemarks: 1,
|
|
29624
|
+
remarks: 1,
|
|
29625
|
+
requestDate: 1,
|
|
29626
|
+
createdAt: 1,
|
|
29627
|
+
updatedAt: 1
|
|
29628
|
+
}
|
|
29629
|
+
}
|
|
29630
|
+
);
|
|
29631
|
+
if (!card)
|
|
29632
|
+
return null;
|
|
29633
|
+
const site = await collectionName("sites").findOne(
|
|
29634
|
+
{ _id: card.site },
|
|
29635
|
+
{ projection: { name: 1, status: 1 } }
|
|
29636
|
+
);
|
|
29637
|
+
const user = card.userId ? await collectionName("users").findOne(
|
|
29638
|
+
{ _id: card.userId },
|
|
29639
|
+
{ projection: { name: 1, email: 1 } }
|
|
29640
|
+
) : null;
|
|
29641
|
+
const status = card.userId === null && card.isActivated === true ? "available" : card.userId !== null && card.isActivated === true ? "assigned" : card.isActivated === false && card.replacementStatus !== null ? "replaced" : "deleted";
|
|
29642
|
+
return {
|
|
29643
|
+
...card,
|
|
29644
|
+
status,
|
|
29645
|
+
site,
|
|
29646
|
+
user
|
|
29647
|
+
};
|
|
29648
|
+
} catch (error) {
|
|
29649
|
+
throw new Error(error.message);
|
|
29650
|
+
}
|
|
29651
|
+
}
|
|
28973
29652
|
return {
|
|
28974
29653
|
createIndexes,
|
|
28975
29654
|
createIndexForEntrypass,
|
|
@@ -28990,7 +29669,9 @@ function UseAccessManagementRepo() {
|
|
|
28990
29669
|
getCardReplacementRepo,
|
|
28991
29670
|
getAccessManagementSettingsRepo,
|
|
28992
29671
|
bulkPhysicalAccessCardRepo,
|
|
28993
|
-
assignAccessCardToUnitRepo
|
|
29672
|
+
assignAccessCardToUnitRepo,
|
|
29673
|
+
deleteCardRepo,
|
|
29674
|
+
getCardDetailsRepo
|
|
28994
29675
|
};
|
|
28995
29676
|
}
|
|
28996
29677
|
|
|
@@ -29022,7 +29703,9 @@ function useAccessManagementSvc() {
|
|
|
29022
29703
|
getCardReplacementRepo,
|
|
29023
29704
|
getAccessManagementSettingsRepo,
|
|
29024
29705
|
bulkPhysicalAccessCardRepo,
|
|
29025
|
-
assignAccessCardToUnitRepo
|
|
29706
|
+
assignAccessCardToUnitRepo,
|
|
29707
|
+
deleteCardRepo,
|
|
29708
|
+
getCardDetailsRepo
|
|
29026
29709
|
} = UseAccessManagementRepo();
|
|
29027
29710
|
const addPhysicalCardSvc = async (payload) => {
|
|
29028
29711
|
try {
|
|
@@ -29270,6 +29953,22 @@ function useAccessManagementSvc() {
|
|
|
29270
29953
|
throw new Error(err.message);
|
|
29271
29954
|
}
|
|
29272
29955
|
};
|
|
29956
|
+
const deleteCardSvc = async (params) => {
|
|
29957
|
+
try {
|
|
29958
|
+
const response = await deleteCardRepo({ ...params });
|
|
29959
|
+
return response;
|
|
29960
|
+
} catch (err) {
|
|
29961
|
+
throw new Error(err.message);
|
|
29962
|
+
}
|
|
29963
|
+
};
|
|
29964
|
+
const getCardDetailsSvc = async (params) => {
|
|
29965
|
+
try {
|
|
29966
|
+
const response = await getCardDetailsRepo({ ...params });
|
|
29967
|
+
return response;
|
|
29968
|
+
} catch (err) {
|
|
29969
|
+
throw new Error(err.message);
|
|
29970
|
+
}
|
|
29971
|
+
};
|
|
29273
29972
|
return {
|
|
29274
29973
|
addPhysicalCardSvc,
|
|
29275
29974
|
addNonPhysicalCardSvc,
|
|
@@ -29294,7 +29993,9 @@ function useAccessManagementSvc() {
|
|
|
29294
29993
|
getAccessManagementSettingsSvc,
|
|
29295
29994
|
convertBufferFile,
|
|
29296
29995
|
bulkPhysicalAccessCardSvc,
|
|
29297
|
-
assignAccessCardToUnitSvc
|
|
29996
|
+
assignAccessCardToUnitSvc,
|
|
29997
|
+
deleteCardSvc,
|
|
29998
|
+
getCardDetailsSvc
|
|
29298
29999
|
};
|
|
29299
30000
|
}
|
|
29300
30001
|
|
|
@@ -29326,7 +30027,9 @@ function useAccessManagementController() {
|
|
|
29326
30027
|
getAccessManagementSettingsSvc,
|
|
29327
30028
|
convertBufferFile,
|
|
29328
30029
|
bulkPhysicalAccessCardSvc,
|
|
29329
|
-
assignAccessCardToUnitSvc
|
|
30030
|
+
assignAccessCardToUnitSvc,
|
|
30031
|
+
deleteCardSvc,
|
|
30032
|
+
getCardDetailsSvc
|
|
29330
30033
|
} = useAccessManagementSvc();
|
|
29331
30034
|
const addPhysicalCard = async (req, res) => {
|
|
29332
30035
|
try {
|
|
@@ -29555,11 +30258,24 @@ function useAccessManagementController() {
|
|
|
29555
30258
|
userType: import_joi85.default.string().optional().allow("", null),
|
|
29556
30259
|
type: import_joi85.default.string().optional().allow("", null)
|
|
29557
30260
|
});
|
|
30261
|
+
const user = req.cookies?.sid;
|
|
29558
30262
|
const { error } = schema2.validate({ site, userType, type });
|
|
29559
30263
|
if (error) {
|
|
29560
30264
|
return res.status(400).json({ message: error.message });
|
|
29561
30265
|
}
|
|
30266
|
+
const key = `${namespace2}:${user}:available-access-cards`;
|
|
30267
|
+
const listKey = `${namespace2}:${user}:list`;
|
|
30268
|
+
const { redis } = (0, import_node_server_utils151.useCache)(key);
|
|
30269
|
+
const cachedData = await getCache({ key, redis });
|
|
30270
|
+
if (cachedData) {
|
|
30271
|
+
console.log("\u26A1 Cache hit:", key);
|
|
30272
|
+
redis.expire(key, 60).catch(console.error);
|
|
30273
|
+
redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
|
|
30274
|
+
return res.status(200).json({ message: "Success", data: cachedData });
|
|
30275
|
+
}
|
|
29562
30276
|
const result = await availableAccessCardsSvc({ site, userType, type });
|
|
30277
|
+
await setCache({ key, data: result, ttlSeconds: 60, redis });
|
|
30278
|
+
redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
|
|
29563
30279
|
return res.status(200).json({ message: "Success", data: result });
|
|
29564
30280
|
} catch (error) {
|
|
29565
30281
|
return res.status(400).json({
|
|
@@ -29741,16 +30457,19 @@ function useAccessManagementController() {
|
|
|
29741
30457
|
};
|
|
29742
30458
|
const cardReplacement = async (req, res) => {
|
|
29743
30459
|
try {
|
|
29744
|
-
const { cardId, remarks } = req.body;
|
|
30460
|
+
const { cardId, remarks, unitId, issuedCardId, userId } = req.body;
|
|
29745
30461
|
const schema2 = import_joi85.default.object({
|
|
29746
30462
|
cardId: import_joi85.default.string().required(),
|
|
29747
|
-
remarks: import_joi85.default.string().optional().allow("", null)
|
|
30463
|
+
remarks: import_joi85.default.string().optional().allow("", null),
|
|
30464
|
+
unitId: import_joi85.default.string().hex().required(),
|
|
30465
|
+
issuedCardId: import_joi85.default.string().required(),
|
|
30466
|
+
userId: import_joi85.default.string().hex().required()
|
|
29748
30467
|
});
|
|
29749
|
-
const { error } = schema2.validate({ cardId, remarks });
|
|
30468
|
+
const { error } = schema2.validate({ cardId, remarks, unitId, issuedCardId, userId });
|
|
29750
30469
|
if (error) {
|
|
29751
30470
|
return res.status(400).json({ message: error.message });
|
|
29752
30471
|
}
|
|
29753
|
-
const result = await cardReplacementSvc({ cardId, remarks });
|
|
30472
|
+
const result = await cardReplacementSvc({ cardId, remarks, unitId, issuedCardId, userId });
|
|
29754
30473
|
return res.status(200).json({ message: "Success", data: result });
|
|
29755
30474
|
} catch (error) {
|
|
29756
30475
|
return res.status(500).json({
|
|
@@ -29881,6 +30600,46 @@ function useAccessManagementController() {
|
|
|
29881
30600
|
});
|
|
29882
30601
|
}
|
|
29883
30602
|
};
|
|
30603
|
+
const deleteCard = async (req, res) => {
|
|
30604
|
+
try {
|
|
30605
|
+
const { cardId, remarks } = req.body;
|
|
30606
|
+
const schema2 = import_joi85.default.object({
|
|
30607
|
+
cardId: import_joi85.default.string().hex().required(),
|
|
30608
|
+
remarks: import_joi85.default.string().optional().allow("", null)
|
|
30609
|
+
});
|
|
30610
|
+
const { error } = schema2.validate({ cardId, remarks });
|
|
30611
|
+
if (error) {
|
|
30612
|
+
return res.status(400).json({ message: error.message });
|
|
30613
|
+
}
|
|
30614
|
+
const result = await deleteCardSvc({ cardId, remarks });
|
|
30615
|
+
return res.status(200).json({ message: "Success", data: result });
|
|
30616
|
+
} catch (error) {
|
|
30617
|
+
return res.status(500).json({
|
|
30618
|
+
data: null,
|
|
30619
|
+
message: error.message
|
|
30620
|
+
});
|
|
30621
|
+
}
|
|
30622
|
+
};
|
|
30623
|
+
const getCardDetails = async (req, res) => {
|
|
30624
|
+
try {
|
|
30625
|
+
const { siteId, cardId } = req.query;
|
|
30626
|
+
const schema2 = import_joi85.default.object({
|
|
30627
|
+
siteId: import_joi85.default.string().hex().required(),
|
|
30628
|
+
cardId: import_joi85.default.string().hex().required()
|
|
30629
|
+
});
|
|
30630
|
+
const { error } = schema2.validate({ siteId, cardId });
|
|
30631
|
+
if (error) {
|
|
30632
|
+
return res.status(400).json({ message: error.message });
|
|
30633
|
+
}
|
|
30634
|
+
const result = await getCardDetailsSvc({ siteId, cardId });
|
|
30635
|
+
return res.status(200).json({ message: "Success", data: result });
|
|
30636
|
+
} catch (error) {
|
|
30637
|
+
return res.status(500).json({
|
|
30638
|
+
data: null,
|
|
30639
|
+
message: error.message
|
|
30640
|
+
});
|
|
30641
|
+
}
|
|
30642
|
+
};
|
|
29884
30643
|
return {
|
|
29885
30644
|
addPhysicalCard,
|
|
29886
30645
|
addNonPhysicalCard,
|
|
@@ -29902,7 +30661,9 @@ function useAccessManagementController() {
|
|
|
29902
30661
|
getCardReplacement,
|
|
29903
30662
|
getAccessManagementSettings,
|
|
29904
30663
|
bulkPhysicalAccessCard,
|
|
29905
|
-
assignAccessCardToUnit
|
|
30664
|
+
assignAccessCardToUnit,
|
|
30665
|
+
deleteCard,
|
|
30666
|
+
getCardDetails
|
|
29906
30667
|
};
|
|
29907
30668
|
}
|
|
29908
30669
|
|
|
@@ -31619,9 +32380,9 @@ function useStatementOfAccountRepo() {
|
|
|
31619
32380
|
page = page > 0 ? page - 1 : 0;
|
|
31620
32381
|
let dateExpr = {};
|
|
31621
32382
|
if (dateFrom && dateTo) {
|
|
31622
|
-
|
|
32383
|
+
let startDate = new Date(dateFrom);
|
|
31623
32384
|
startDate.setHours(0, 0, 0, 0);
|
|
31624
|
-
|
|
32385
|
+
let endDate = new Date(dateTo);
|
|
31625
32386
|
endDate.setHours(23, 59, 59, 999);
|
|
31626
32387
|
dateExpr = {
|
|
31627
32388
|
$expr: {
|
|
@@ -31632,13 +32393,15 @@ function useStatementOfAccountRepo() {
|
|
|
31632
32393
|
}
|
|
31633
32394
|
};
|
|
31634
32395
|
}
|
|
32396
|
+
const unitSearchRegex = search ? search.trim().replace(/\s+/g, "").replace(/\//g, "\\s*/\\s*") : null;
|
|
31635
32397
|
const query = {
|
|
31636
32398
|
...status && status !== "all" && { status },
|
|
31637
32399
|
...search && {
|
|
31638
32400
|
$or: [
|
|
31639
32401
|
{ unitOwner: { $regex: search, $options: "i" } },
|
|
31640
|
-
{ unit: { $regex:
|
|
31641
|
-
{ email: { $regex: search, $options: "i" } }
|
|
32402
|
+
{ unit: { $regex: unitSearchRegex, $options: "i" } },
|
|
32403
|
+
{ email: { $regex: search, $options: "i" } },
|
|
32404
|
+
{ category: { $regex: search, $options: "i" } }
|
|
31642
32405
|
]
|
|
31643
32406
|
},
|
|
31644
32407
|
...import_mongodb91.ObjectId.isValid(site) && { site: new import_mongodb91.ObjectId(site) },
|
|
@@ -33883,6 +34646,9 @@ function useIncidentReportRepo() {
|
|
|
33883
34646
|
$regex: search,
|
|
33884
34647
|
$options: "i"
|
|
33885
34648
|
}
|
|
34649
|
+
},
|
|
34650
|
+
{
|
|
34651
|
+
approvedByName: { $regex: search, $options: "i" }
|
|
33886
34652
|
}
|
|
33887
34653
|
]
|
|
33888
34654
|
},
|
|
@@ -36396,7 +37162,9 @@ function useNfcPatrolLogController() {
|
|
|
36396
37162
|
}
|
|
36397
37163
|
// Annotate the CommonJS export names for ESM import in node:
|
|
36398
37164
|
0 && (module.exports = {
|
|
37165
|
+
ANPRMode,
|
|
36399
37166
|
AccessTypeProps,
|
|
37167
|
+
BULLETIN_RECIPIENTS,
|
|
36400
37168
|
DEVICE_STATUS,
|
|
36401
37169
|
EAccessCardTypes,
|
|
36402
37170
|
EAccessCardUserTypes,
|
|
@@ -36455,12 +37223,15 @@ function useNfcPatrolLogController() {
|
|
|
36455
37223
|
MVerification,
|
|
36456
37224
|
MVisitorTransaction,
|
|
36457
37225
|
MWorkOrder,
|
|
37226
|
+
OrgNature,
|
|
36458
37227
|
PERSON_TYPES,
|
|
37228
|
+
STATUS_VALUES,
|
|
36459
37229
|
UseAccessManagementRepo,
|
|
36460
|
-
|
|
37230
|
+
VehicleCategory,
|
|
37231
|
+
VehicleStatus,
|
|
37232
|
+
VehicleType,
|
|
36461
37233
|
allowedFieldsSite,
|
|
36462
37234
|
allowedNatures,
|
|
36463
|
-
allowedTypes,
|
|
36464
37235
|
attendanceSchema,
|
|
36465
37236
|
attendanceSettingsSchema,
|
|
36466
37237
|
chatSchema,
|