@7365admin1/core 2.64.0 → 2.66.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 +85 -13
- package/dist/index.js +1851 -632
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1849 -632
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -125,7 +125,15 @@ var userSchema = Joi2.object({
|
|
|
125
125
|
email: Joi2.string().email().required(),
|
|
126
126
|
password: Joi2.string().min(8).required(),
|
|
127
127
|
name: Joi2.string().required(),
|
|
128
|
-
defaultOrg: Joi2.string().hex().optional().allow("", null)
|
|
128
|
+
defaultOrg: Joi2.string().hex().optional().allow("", null),
|
|
129
|
+
status: Joi2.string().optional().allow("", null),
|
|
130
|
+
block: Joi2.number().optional().allow(null),
|
|
131
|
+
level: Joi2.string().optional().allow("", null),
|
|
132
|
+
type: Joi2.string().optional().allow("", null),
|
|
133
|
+
unitName: Joi2.string().optional().allow("", null),
|
|
134
|
+
contact: Joi2.string().optional().allow("", null),
|
|
135
|
+
site: Joi2.string().hex().optional().allow("", null),
|
|
136
|
+
unitId: Joi2.string().hex().optional().allow("", null)
|
|
129
137
|
});
|
|
130
138
|
function MUser(value) {
|
|
131
139
|
const { error } = userSchema.validate(value);
|
|
@@ -139,12 +147,33 @@ function MUser(value) {
|
|
|
139
147
|
throw new BadRequestError2("Invalid default org ID format.");
|
|
140
148
|
}
|
|
141
149
|
}
|
|
150
|
+
if (value.site && typeof value.site === "string") {
|
|
151
|
+
try {
|
|
152
|
+
value.site = new ObjectId(value.site);
|
|
153
|
+
} catch {
|
|
154
|
+
throw new BadRequestError2("Invalid site ID format.");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (value.unitId && typeof value.unitId === "string") {
|
|
158
|
+
try {
|
|
159
|
+
value.unitId = new ObjectId(value.unitId);
|
|
160
|
+
} catch {
|
|
161
|
+
throw new BadRequestError2("Invalid unit ID format.");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
142
164
|
return {
|
|
143
165
|
email: value.email,
|
|
144
166
|
password: value.password,
|
|
145
167
|
name: value.name ?? "",
|
|
146
168
|
defaultOrg: value.defaultOrg ?? "",
|
|
147
|
-
status: "active" /* ACTIVE */,
|
|
169
|
+
status: value.status ?? "active" /* ACTIVE */,
|
|
170
|
+
block: value.block ?? null,
|
|
171
|
+
level: value.level ?? "",
|
|
172
|
+
type: value.type ?? "",
|
|
173
|
+
unitName: value.unitName ?? "",
|
|
174
|
+
contact: value.contact ?? "",
|
|
175
|
+
site: value.site ?? "",
|
|
176
|
+
unitId: value.unitId ?? "",
|
|
148
177
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
149
178
|
updatedAt: value.updatedAt ?? "",
|
|
150
179
|
deletedAt: value.deletedAt ?? ""
|
|
@@ -4372,6 +4401,30 @@ function useOrgRepo() {
|
|
|
4372
4401
|
throw error;
|
|
4373
4402
|
}
|
|
4374
4403
|
}
|
|
4404
|
+
async function getOrgsByEmail(email) {
|
|
4405
|
+
const cacheKey = makeCacheKey8(namespace_collection, {
|
|
4406
|
+
type: "many",
|
|
4407
|
+
email
|
|
4408
|
+
});
|
|
4409
|
+
const cachedData = await getCache(cacheKey);
|
|
4410
|
+
if (cachedData) {
|
|
4411
|
+
logger10.info(`Cache hit for key: ${cacheKey}`);
|
|
4412
|
+
return cachedData;
|
|
4413
|
+
}
|
|
4414
|
+
try {
|
|
4415
|
+
const data = await collection.find({
|
|
4416
|
+
email
|
|
4417
|
+
}).toArray();
|
|
4418
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
4419
|
+
logger10.info(`Cache set for key: ${cacheKey}`);
|
|
4420
|
+
}).catch((err) => {
|
|
4421
|
+
logger10.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
4422
|
+
});
|
|
4423
|
+
return data;
|
|
4424
|
+
} catch (error) {
|
|
4425
|
+
throw error;
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4375
4428
|
async function updateFieldById({
|
|
4376
4429
|
_id,
|
|
4377
4430
|
field,
|
|
@@ -4474,7 +4527,8 @@ function useOrgRepo() {
|
|
|
4474
4527
|
getByEmail,
|
|
4475
4528
|
updateFieldById,
|
|
4476
4529
|
updateStatusById,
|
|
4477
|
-
deleteById
|
|
4530
|
+
deleteById,
|
|
4531
|
+
getOrgsByEmail
|
|
4478
4532
|
};
|
|
4479
4533
|
}
|
|
4480
4534
|
|
|
@@ -5497,7 +5551,6 @@ function useVerificationService() {
|
|
|
5497
5551
|
await getSiteById(metadata.siteId);
|
|
5498
5552
|
}
|
|
5499
5553
|
const verificationIds = [];
|
|
5500
|
-
const invitedApps = [];
|
|
5501
5554
|
for (const app of apps) {
|
|
5502
5555
|
await useVerificationRepo().findOne({
|
|
5503
5556
|
type,
|
|
@@ -5520,34 +5573,32 @@ function useVerificationService() {
|
|
|
5520
5573
|
};
|
|
5521
5574
|
const createdId = await add(value);
|
|
5522
5575
|
verificationIds.push(createdId.toString());
|
|
5523
|
-
|
|
5576
|
+
const link = `${APP_MAIN}/verify/invitation/${createdId}`;
|
|
5577
|
+
const emailContent = compileHandlebar({
|
|
5578
|
+
context: {
|
|
5579
|
+
email,
|
|
5580
|
+
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
5581
|
+
link,
|
|
5582
|
+
hasPropertyManagement: app === "property_management_agency",
|
|
5583
|
+
hasSecurity: app === "security_agency",
|
|
5584
|
+
hasCleaning: app === "cleaning_services",
|
|
5585
|
+
hasMechanical: app === "mechanical_electrical_services",
|
|
5586
|
+
hasLandscape: app === "landscaping_services",
|
|
5587
|
+
hasPestControl: app === "pest_control_services",
|
|
5588
|
+
hasPoolMaintenance: app === "pool_maintenance_services"
|
|
5589
|
+
},
|
|
5590
|
+
filePath: getDirectory(
|
|
5591
|
+
__dirname,
|
|
5592
|
+
"./public/handlebars/user-invite"
|
|
5593
|
+
)
|
|
5594
|
+
});
|
|
5595
|
+
await mailer.sendMail({
|
|
5596
|
+
to: email,
|
|
5597
|
+
subject: "User Invite",
|
|
5598
|
+
html: emailContent,
|
|
5599
|
+
sender: "iService365"
|
|
5600
|
+
});
|
|
5524
5601
|
}
|
|
5525
|
-
const link = `${APP_MAIN}/verify/invitation/${verificationIds[0]}`;
|
|
5526
|
-
const appsSet = new Set(invitedApps);
|
|
5527
|
-
const emailContent = compileHandlebar({
|
|
5528
|
-
context: {
|
|
5529
|
-
email,
|
|
5530
|
-
validity: VERIFICATION_USER_INVITE_DURATION,
|
|
5531
|
-
link,
|
|
5532
|
-
hasPropertyManagement: appsSet.has("property_management_agency"),
|
|
5533
|
-
hasSecurity: appsSet.has("security_agency"),
|
|
5534
|
-
hasCleaning: appsSet.has("cleaning_services"),
|
|
5535
|
-
hasMechanical: appsSet.has("mechanical_electrical_services"),
|
|
5536
|
-
hasLandscape: appsSet.has("landscaping_services"),
|
|
5537
|
-
hasPestControl: appsSet.has("pest_control_services"),
|
|
5538
|
-
hasPoolMaintenance: appsSet.has("pool_maintenance_services")
|
|
5539
|
-
},
|
|
5540
|
-
filePath: getDirectory(
|
|
5541
|
-
__dirname,
|
|
5542
|
-
"./public/handlebars/user-invite"
|
|
5543
|
-
)
|
|
5544
|
-
});
|
|
5545
|
-
await mailer.sendMail({
|
|
5546
|
-
to: email,
|
|
5547
|
-
subject: "User Invite",
|
|
5548
|
-
html: emailContent,
|
|
5549
|
-
sender: "iService365"
|
|
5550
|
-
});
|
|
5551
5602
|
return verificationIds;
|
|
5552
5603
|
}
|
|
5553
5604
|
async function createSimpleMemberInvite({
|
|
@@ -8042,7 +8093,7 @@ function useVerificationController() {
|
|
|
8042
8093
|
siteId: Joi16.string().hex().optional().allow("", null),
|
|
8043
8094
|
siteName: Joi16.string().optional().allow("", null)
|
|
8044
8095
|
});
|
|
8045
|
-
const { error } = validation.validate(payload);
|
|
8096
|
+
const { error, value } = validation.validate(payload);
|
|
8046
8097
|
if (error) {
|
|
8047
8098
|
logger22.log({
|
|
8048
8099
|
level: "error",
|
|
@@ -8051,15 +8102,17 @@ function useVerificationController() {
|
|
|
8051
8102
|
next(new BadRequestError31(error.message));
|
|
8052
8103
|
return;
|
|
8053
8104
|
}
|
|
8054
|
-
const email = req.body.email ?? "";
|
|
8055
|
-
const app = req.body.app ?? [];
|
|
8056
|
-
const role = req.body.role ?? "";
|
|
8057
|
-
const name = req.body.name ?? "";
|
|
8058
|
-
const org = req.body.org ?? "";
|
|
8059
|
-
const siteId = req.body.siteId ?? "";
|
|
8060
|
-
const siteName = req.body.siteName ?? "";
|
|
8061
8105
|
try {
|
|
8062
|
-
|
|
8106
|
+
const {
|
|
8107
|
+
email,
|
|
8108
|
+
app,
|
|
8109
|
+
role,
|
|
8110
|
+
name,
|
|
8111
|
+
org,
|
|
8112
|
+
siteId,
|
|
8113
|
+
siteName
|
|
8114
|
+
} = value;
|
|
8115
|
+
const verificationIds = await _createSimpleUserInvite({
|
|
8063
8116
|
email,
|
|
8064
8117
|
metadata: {
|
|
8065
8118
|
app,
|
|
@@ -8071,7 +8124,9 @@ function useVerificationController() {
|
|
|
8071
8124
|
}
|
|
8072
8125
|
});
|
|
8073
8126
|
res.status(201).json({
|
|
8074
|
-
message: "Successfully invited user."
|
|
8127
|
+
message: "Successfully invited user.",
|
|
8128
|
+
totalInvites: verificationIds.length,
|
|
8129
|
+
verificationIds
|
|
8075
8130
|
});
|
|
8076
8131
|
return;
|
|
8077
8132
|
} catch (error2) {
|
|
@@ -8531,7 +8586,8 @@ function useOrgController() {
|
|
|
8531
8586
|
getByEmail: _getByEmail,
|
|
8532
8587
|
getAll: _getAll,
|
|
8533
8588
|
add: _add,
|
|
8534
|
-
update: _update
|
|
8589
|
+
update: _update,
|
|
8590
|
+
getOrgsByEmail: _getOrgsByEmail
|
|
8535
8591
|
} = useOrgRepo();
|
|
8536
8592
|
async function add(req, res, next) {
|
|
8537
8593
|
const validation = Joi18.object({
|
|
@@ -8715,6 +8771,30 @@ function useOrgController() {
|
|
|
8715
8771
|
return;
|
|
8716
8772
|
}
|
|
8717
8773
|
}
|
|
8774
|
+
async function getOrgsByEmail(req, res, next) {
|
|
8775
|
+
const validation = Joi18.object({
|
|
8776
|
+
email: Joi18.string().email().required()
|
|
8777
|
+
});
|
|
8778
|
+
const query = {
|
|
8779
|
+
email: req.params.email
|
|
8780
|
+
};
|
|
8781
|
+
const { error } = validation.validate(query);
|
|
8782
|
+
if (error) {
|
|
8783
|
+
logger25.log({ level: "error", message: error.message });
|
|
8784
|
+
next(new BadRequestError33(error.message));
|
|
8785
|
+
return;
|
|
8786
|
+
}
|
|
8787
|
+
const email = req.params.email;
|
|
8788
|
+
try {
|
|
8789
|
+
const data = await _getOrgsByEmail(email);
|
|
8790
|
+
res.json(data);
|
|
8791
|
+
return;
|
|
8792
|
+
} catch (error2) {
|
|
8793
|
+
logger25.log({ level: "error", message: error2.message });
|
|
8794
|
+
next(error2);
|
|
8795
|
+
return;
|
|
8796
|
+
}
|
|
8797
|
+
}
|
|
8718
8798
|
async function update(req, res, next) {
|
|
8719
8799
|
const validation = Joi18.object({
|
|
8720
8800
|
name: Joi18.string().optional(),
|
|
@@ -8748,7 +8828,8 @@ function useOrgController() {
|
|
|
8748
8828
|
getByName,
|
|
8749
8829
|
getById,
|
|
8750
8830
|
getByEmail,
|
|
8751
|
-
update
|
|
8831
|
+
update,
|
|
8832
|
+
getOrgsByEmail
|
|
8752
8833
|
};
|
|
8753
8834
|
}
|
|
8754
8835
|
|
|
@@ -12314,6 +12395,33 @@ function useServiceProviderRepo() {
|
|
|
12314
12395
|
throw error;
|
|
12315
12396
|
}
|
|
12316
12397
|
}
|
|
12398
|
+
async function updateStatusById(_id, status) {
|
|
12399
|
+
try {
|
|
12400
|
+
_id = new ObjectId34(_id);
|
|
12401
|
+
} catch (error) {
|
|
12402
|
+
throw new BadRequestError54("Invalid service provider ID format.");
|
|
12403
|
+
}
|
|
12404
|
+
try {
|
|
12405
|
+
const result = await collection.updateOne(
|
|
12406
|
+
{ _id },
|
|
12407
|
+
{ $set: { status, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } }
|
|
12408
|
+
);
|
|
12409
|
+
if (!result.matchedCount) {
|
|
12410
|
+
throw new NotFoundError14("Service provider not found.");
|
|
12411
|
+
}
|
|
12412
|
+
delNamespace().then(() => {
|
|
12413
|
+
logger40.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
12414
|
+
}).catch((err) => {
|
|
12415
|
+
logger40.error(
|
|
12416
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
12417
|
+
err
|
|
12418
|
+
);
|
|
12419
|
+
});
|
|
12420
|
+
return result;
|
|
12421
|
+
} catch (error) {
|
|
12422
|
+
throw error;
|
|
12423
|
+
}
|
|
12424
|
+
}
|
|
12317
12425
|
return {
|
|
12318
12426
|
createTextIndex,
|
|
12319
12427
|
createUniqueIndex,
|
|
@@ -12323,7 +12431,8 @@ function useServiceProviderRepo() {
|
|
|
12323
12431
|
getServiceProviderTypes,
|
|
12324
12432
|
getServiceProviderById,
|
|
12325
12433
|
getByServiceProviderOrgIdType,
|
|
12326
|
-
getByEmail
|
|
12434
|
+
getByEmail,
|
|
12435
|
+
updateStatusById
|
|
12327
12436
|
};
|
|
12328
12437
|
}
|
|
12329
12438
|
|
|
@@ -13102,7 +13211,8 @@ function useServiceProviderController() {
|
|
|
13102
13211
|
getServiceProviderTypes: _getServiceProviderTypes,
|
|
13103
13212
|
getServiceProviderById: _getServiceProviderById,
|
|
13104
13213
|
getServiceProviders: _getServiceProviders,
|
|
13105
|
-
getByServiceProviderOrgIdType: _getByServiceProviderOrgIdType
|
|
13214
|
+
getByServiceProviderOrgIdType: _getByServiceProviderOrgIdType,
|
|
13215
|
+
updateStatusById: _updateStatusById
|
|
13106
13216
|
} = useServiceProviderRepo();
|
|
13107
13217
|
const { createServiceProvider: _createServiceProvider } = useServiceProviderService();
|
|
13108
13218
|
const { createServiceProvider: _add } = useServiceProviderRepo();
|
|
@@ -13316,6 +13426,30 @@ function useServiceProviderController() {
|
|
|
13316
13426
|
return;
|
|
13317
13427
|
}
|
|
13318
13428
|
}
|
|
13429
|
+
async function updateStatusById(req, res, next) {
|
|
13430
|
+
const validation = Joi31.object({
|
|
13431
|
+
id: Joi31.string().hex().required(),
|
|
13432
|
+
status: Joi31.string().valid("active", "inactive").required()
|
|
13433
|
+
});
|
|
13434
|
+
const { error, value } = validation.validate({
|
|
13435
|
+
id: req.params.id,
|
|
13436
|
+
status: req.body.status
|
|
13437
|
+
});
|
|
13438
|
+
if (error) {
|
|
13439
|
+
logger43.log({ level: "error", message: error.message });
|
|
13440
|
+
next(new BadRequestError60(error.message));
|
|
13441
|
+
return;
|
|
13442
|
+
}
|
|
13443
|
+
try {
|
|
13444
|
+
await _updateStatusById(value.id, value.status);
|
|
13445
|
+
res.json({ message: "Service provider status updated successfully." });
|
|
13446
|
+
return;
|
|
13447
|
+
} catch (error2) {
|
|
13448
|
+
logger43.log({ level: "error", message: error2.message });
|
|
13449
|
+
next(error2);
|
|
13450
|
+
return;
|
|
13451
|
+
}
|
|
13452
|
+
}
|
|
13319
13453
|
return {
|
|
13320
13454
|
createServiceProvider,
|
|
13321
13455
|
getServiceProviders,
|
|
@@ -13324,7 +13458,8 @@ function useServiceProviderController() {
|
|
|
13324
13458
|
getServiceProviderTypes,
|
|
13325
13459
|
getServiceProviderById,
|
|
13326
13460
|
getByServiceProviderOrgIdType,
|
|
13327
|
-
add
|
|
13461
|
+
add,
|
|
13462
|
+
updateStatusById
|
|
13328
13463
|
};
|
|
13329
13464
|
}
|
|
13330
13465
|
|
|
@@ -26498,7 +26633,14 @@ function usePersonService() {
|
|
|
26498
26633
|
password: hashedPassword,
|
|
26499
26634
|
name: value.name,
|
|
26500
26635
|
status: value.platform == "mobile" ? "pending" : "active",
|
|
26501
|
-
defaultOrg: value.org?.toString() || ""
|
|
26636
|
+
defaultOrg: value.org?.toString() || "",
|
|
26637
|
+
block: value.block,
|
|
26638
|
+
level: value.level,
|
|
26639
|
+
type: value.type,
|
|
26640
|
+
unitName: value.unitName,
|
|
26641
|
+
contact: value.contact,
|
|
26642
|
+
site: value.site?.toString() || "",
|
|
26643
|
+
unitId: value.unit?.toString() || ""
|
|
26502
26644
|
};
|
|
26503
26645
|
const userId = await addUser(user, session);
|
|
26504
26646
|
value.user = userId.toString();
|
|
@@ -36286,10 +36428,42 @@ function UseAccessManagementRepo() {
|
|
|
36286
36428
|
},
|
|
36287
36429
|
{
|
|
36288
36430
|
$facet: {
|
|
36289
|
-
available_physical: [
|
|
36290
|
-
|
|
36291
|
-
|
|
36292
|
-
|
|
36431
|
+
available_physical: [
|
|
36432
|
+
{
|
|
36433
|
+
$match: {
|
|
36434
|
+
assignedUnit: { $eq: null },
|
|
36435
|
+
type: "NFC" /* NFC */
|
|
36436
|
+
}
|
|
36437
|
+
},
|
|
36438
|
+
{ $count: "count" }
|
|
36439
|
+
],
|
|
36440
|
+
available_non_physical: [
|
|
36441
|
+
{
|
|
36442
|
+
$match: {
|
|
36443
|
+
assignedUnit: { $eq: null },
|
|
36444
|
+
type: "QRCODE" /* QR */
|
|
36445
|
+
}
|
|
36446
|
+
},
|
|
36447
|
+
{ $count: "count" }
|
|
36448
|
+
],
|
|
36449
|
+
assigned_physical: [
|
|
36450
|
+
{
|
|
36451
|
+
$match: {
|
|
36452
|
+
assignedUnit: { $ne: null },
|
|
36453
|
+
type: "NFC" /* NFC */
|
|
36454
|
+
}
|
|
36455
|
+
},
|
|
36456
|
+
{ $count: "count" }
|
|
36457
|
+
],
|
|
36458
|
+
assigned_non_physical: [
|
|
36459
|
+
{
|
|
36460
|
+
$match: {
|
|
36461
|
+
assignedUnit: { $ne: null },
|
|
36462
|
+
type: "QRCODE" /* QR */
|
|
36463
|
+
}
|
|
36464
|
+
},
|
|
36465
|
+
{ $count: "count" }
|
|
36466
|
+
]
|
|
36293
36467
|
}
|
|
36294
36468
|
}
|
|
36295
36469
|
]).toArray();
|
|
@@ -36374,16 +36548,35 @@ function UseAccessManagementRepo() {
|
|
|
36374
36548
|
case terms.length >= 3:
|
|
36375
36549
|
return {
|
|
36376
36550
|
$and: [
|
|
36377
|
-
{
|
|
36378
|
-
|
|
36379
|
-
|
|
36551
|
+
{
|
|
36552
|
+
$expr: { $eq: [{ $toLower: "$name" }, terms[0].toLowerCase()] }
|
|
36553
|
+
},
|
|
36554
|
+
{
|
|
36555
|
+
$expr: {
|
|
36556
|
+
$eq: [{ $toLower: "$level.level" }, terms[1].toLowerCase()]
|
|
36557
|
+
}
|
|
36558
|
+
},
|
|
36559
|
+
{
|
|
36560
|
+
$expr: {
|
|
36561
|
+
$eq: [
|
|
36562
|
+
{ $toLower: "$level.units.name" },
|
|
36563
|
+
getAfterSecondSlash(search)
|
|
36564
|
+
]
|
|
36565
|
+
}
|
|
36566
|
+
}
|
|
36380
36567
|
]
|
|
36381
36568
|
};
|
|
36382
36569
|
case terms.length === 2:
|
|
36383
36570
|
return {
|
|
36384
36571
|
$and: [
|
|
36385
|
-
{
|
|
36386
|
-
|
|
36572
|
+
{
|
|
36573
|
+
$expr: { $eq: [{ $toLower: "$name" }, terms[0].toLowerCase()] }
|
|
36574
|
+
},
|
|
36575
|
+
{
|
|
36576
|
+
$expr: {
|
|
36577
|
+
$eq: [{ $toLower: "$level.level" }, terms[1].toLowerCase()]
|
|
36578
|
+
}
|
|
36579
|
+
}
|
|
36387
36580
|
]
|
|
36388
36581
|
};
|
|
36389
36582
|
default:
|
|
@@ -36411,220 +36604,386 @@ function UseAccessManagementRepo() {
|
|
|
36411
36604
|
site
|
|
36412
36605
|
};
|
|
36413
36606
|
const searchQuery = buildSearchQuery(search);
|
|
36414
|
-
const result = await collectionName("buildings").aggregate(
|
|
36415
|
-
|
|
36416
|
-
|
|
36417
|
-
|
|
36418
|
-
|
|
36419
|
-
|
|
36420
|
-
|
|
36421
|
-
|
|
36422
|
-
|
|
36423
|
-
|
|
36424
|
-
|
|
36425
|
-
|
|
36426
|
-
|
|
36427
|
-
|
|
36428
|
-
|
|
36429
|
-
|
|
36430
|
-
|
|
36431
|
-
|
|
36432
|
-
|
|
36433
|
-
|
|
36434
|
-
|
|
36435
|
-
|
|
36436
|
-
|
|
36437
|
-
|
|
36438
|
-
|
|
36439
|
-
|
|
36440
|
-
|
|
36441
|
-
|
|
36442
|
-
|
|
36443
|
-
|
|
36444
|
-
|
|
36445
|
-
|
|
36446
|
-
|
|
36447
|
-
|
|
36448
|
-
|
|
36449
|
-
|
|
36450
|
-
|
|
36451
|
-
|
|
36452
|
-
|
|
36453
|
-
|
|
36454
|
-
|
|
36455
|
-
|
|
36456
|
-
|
|
36457
|
-
|
|
36458
|
-
|
|
36607
|
+
const result = await collectionName("buildings").aggregate(
|
|
36608
|
+
[
|
|
36609
|
+
// ✅ Match early with index-friendly query
|
|
36610
|
+
{
|
|
36611
|
+
$match: {
|
|
36612
|
+
...defaultQuery,
|
|
36613
|
+
status: { $eq: "active" }
|
|
36614
|
+
}
|
|
36615
|
+
},
|
|
36616
|
+
// ✅ Only project needed fields before heavy lookups
|
|
36617
|
+
{
|
|
36618
|
+
$project: {
|
|
36619
|
+
_id: 1,
|
|
36620
|
+
name: 1,
|
|
36621
|
+
site: 1,
|
|
36622
|
+
block: 1
|
|
36623
|
+
}
|
|
36624
|
+
},
|
|
36625
|
+
// ✅ Use localField/foreignField for better index usage
|
|
36626
|
+
{
|
|
36627
|
+
$lookup: {
|
|
36628
|
+
from: "building-levels",
|
|
36629
|
+
localField: "_id",
|
|
36630
|
+
foreignField: "block",
|
|
36631
|
+
pipeline: [
|
|
36632
|
+
{ $match: { status: { $ne: "deleted" } } },
|
|
36633
|
+
{
|
|
36634
|
+
$lookup: {
|
|
36635
|
+
from: "building-units",
|
|
36636
|
+
localField: "_id",
|
|
36637
|
+
foreignField: "level",
|
|
36638
|
+
pipeline: [
|
|
36639
|
+
{ $match: { status: { $ne: "deleted" }, site } },
|
|
36640
|
+
{ $project: { _id: 1, name: 1 } }
|
|
36641
|
+
],
|
|
36642
|
+
as: "units"
|
|
36643
|
+
}
|
|
36644
|
+
},
|
|
36645
|
+
{
|
|
36646
|
+
$match: { "units.0": { $exists: true } }
|
|
36647
|
+
},
|
|
36648
|
+
{
|
|
36649
|
+
$project: {
|
|
36650
|
+
_id: 1,
|
|
36651
|
+
level: 1,
|
|
36652
|
+
units: 1
|
|
36653
|
+
}
|
|
36459
36654
|
}
|
|
36460
|
-
|
|
36461
|
-
|
|
36462
|
-
|
|
36463
|
-
}
|
|
36464
|
-
|
|
36465
|
-
|
|
36466
|
-
|
|
36467
|
-
|
|
36468
|
-
|
|
36469
|
-
|
|
36470
|
-
|
|
36471
|
-
|
|
36472
|
-
|
|
36473
|
-
|
|
36474
|
-
}
|
|
36475
|
-
|
|
36476
|
-
|
|
36477
|
-
|
|
36478
|
-
|
|
36479
|
-
|
|
36480
|
-
}
|
|
36481
|
-
|
|
36482
|
-
|
|
36483
|
-
|
|
36484
|
-
|
|
36485
|
-
|
|
36486
|
-
|
|
36487
|
-
|
|
36488
|
-
|
|
36489
|
-
|
|
36490
|
-
|
|
36491
|
-
|
|
36492
|
-
|
|
36493
|
-
|
|
36494
|
-
|
|
36495
|
-
|
|
36496
|
-
}
|
|
36497
|
-
|
|
36498
|
-
|
|
36499
|
-
|
|
36500
|
-
|
|
36501
|
-
|
|
36502
|
-
|
|
36503
|
-
|
|
36504
|
-
|
|
36505
|
-
|
|
36506
|
-
|
|
36507
|
-
|
|
36508
|
-
|
|
36509
|
-
|
|
36510
|
-
|
|
36511
|
-
|
|
36512
|
-
|
|
36513
|
-
|
|
36514
|
-
|
|
36655
|
+
],
|
|
36656
|
+
as: "level"
|
|
36657
|
+
}
|
|
36658
|
+
},
|
|
36659
|
+
// ✅ Filter out buildings with no levels early
|
|
36660
|
+
{
|
|
36661
|
+
$match: { "level.0": { $exists: true } }
|
|
36662
|
+
},
|
|
36663
|
+
// ✅ Unwind to flatten the hierarchy
|
|
36664
|
+
{
|
|
36665
|
+
$unwind: {
|
|
36666
|
+
path: "$level",
|
|
36667
|
+
preserveNullAndEmptyArrays: false
|
|
36668
|
+
}
|
|
36669
|
+
},
|
|
36670
|
+
{
|
|
36671
|
+
$unwind: {
|
|
36672
|
+
path: "$level.units",
|
|
36673
|
+
preserveNullAndEmptyArrays: false
|
|
36674
|
+
}
|
|
36675
|
+
},
|
|
36676
|
+
// // Groups by unit _id and keeps only the first occurrence
|
|
36677
|
+
// {
|
|
36678
|
+
// $group: {
|
|
36679
|
+
// _id: "$level.units._id",
|
|
36680
|
+
// doc: { $first: "$$ROOT" },
|
|
36681
|
+
// },
|
|
36682
|
+
// },
|
|
36683
|
+
// {
|
|
36684
|
+
// $replaceRoot: { newRoot: "$doc" },
|
|
36685
|
+
// },
|
|
36686
|
+
// ✅ Apply search filter
|
|
36687
|
+
{
|
|
36688
|
+
$match: {
|
|
36689
|
+
...searchQuery
|
|
36690
|
+
}
|
|
36691
|
+
},
|
|
36692
|
+
{
|
|
36693
|
+
$facet: {
|
|
36694
|
+
totalCount: [{ $count: "count" }],
|
|
36695
|
+
items: [
|
|
36696
|
+
// ✅ Sort BEFORE skip/limit for correct pagination
|
|
36697
|
+
{ $skip: page * limit },
|
|
36698
|
+
{ $limit: limit },
|
|
36699
|
+
// ✅ Users lookup - optimized with index hint
|
|
36700
|
+
{
|
|
36701
|
+
$lookup: {
|
|
36702
|
+
from: "users",
|
|
36703
|
+
let: { unit: "$level.units._id" },
|
|
36704
|
+
pipeline: [
|
|
36705
|
+
{
|
|
36706
|
+
$match: {
|
|
36707
|
+
$expr: { $eq: ["$unitNumber", "$$unit"] },
|
|
36708
|
+
residentType: "House/Unit Owner"
|
|
36709
|
+
}
|
|
36710
|
+
},
|
|
36711
|
+
{ $limit: 1 },
|
|
36712
|
+
{ $project: { _id: 1, givenName: 1, surname: 1 } }
|
|
36713
|
+
],
|
|
36714
|
+
as: "unitOwner"
|
|
36715
|
+
}
|
|
36716
|
+
},
|
|
36717
|
+
// ✅ Access card lookup - optimized query
|
|
36718
|
+
{
|
|
36719
|
+
$lookup: {
|
|
36720
|
+
from: "access-cards",
|
|
36721
|
+
let: { unit: "$level.units._id" },
|
|
36722
|
+
pipeline: [
|
|
36723
|
+
{
|
|
36724
|
+
$match: {
|
|
36725
|
+
$expr: {
|
|
36726
|
+
$in: [
|
|
36727
|
+
"$$unit",
|
|
36728
|
+
{
|
|
36729
|
+
$cond: [
|
|
36730
|
+
{ $isArray: "$assignedUnit" },
|
|
36731
|
+
"$assignedUnit",
|
|
36732
|
+
["$assignedUnit"]
|
|
36733
|
+
]
|
|
36734
|
+
}
|
|
36735
|
+
]
|
|
36736
|
+
},
|
|
36737
|
+
userType
|
|
36738
|
+
}
|
|
36739
|
+
},
|
|
36740
|
+
{
|
|
36741
|
+
$project: {
|
|
36742
|
+
_id: 1,
|
|
36743
|
+
userId: 1,
|
|
36744
|
+
type: 1,
|
|
36745
|
+
cardNo: 1,
|
|
36746
|
+
isActivated: 1,
|
|
36747
|
+
replacementStatus: 1
|
|
36748
|
+
}
|
|
36749
|
+
}
|
|
36750
|
+
],
|
|
36751
|
+
as: "accessCards"
|
|
36752
|
+
}
|
|
36753
|
+
},
|
|
36754
|
+
// ✅ Compute all card categorization and counts in ONE stage
|
|
36755
|
+
{
|
|
36756
|
+
$addFields: {
|
|
36757
|
+
f_Available: {
|
|
36758
|
+
$filter: {
|
|
36759
|
+
input: "$accessCards",
|
|
36760
|
+
as: "card",
|
|
36761
|
+
cond: {
|
|
36762
|
+
$and: [
|
|
36763
|
+
{ $eq: ["$$card.userId", null] },
|
|
36764
|
+
{ $eq: ["$$card.isActivated", true] }
|
|
36765
|
+
]
|
|
36766
|
+
}
|
|
36515
36767
|
}
|
|
36516
36768
|
},
|
|
36517
|
-
|
|
36518
|
-
|
|
36519
|
-
|
|
36520
|
-
|
|
36521
|
-
|
|
36522
|
-
|
|
36523
|
-
|
|
36524
|
-
|
|
36525
|
-
$lookup: {
|
|
36526
|
-
from: "access-cards",
|
|
36527
|
-
let: { unit: "$level.units._id" },
|
|
36528
|
-
pipeline: [
|
|
36529
|
-
{
|
|
36530
|
-
$match: {
|
|
36531
|
-
$expr: {
|
|
36532
|
-
$in: [
|
|
36533
|
-
"$$unit",
|
|
36534
|
-
{ $cond: [{ $isArray: "$assignedUnit" }, "$assignedUnit", ["$assignedUnit"]] }
|
|
36769
|
+
f_Assigned: {
|
|
36770
|
+
$filter: {
|
|
36771
|
+
input: "$accessCards",
|
|
36772
|
+
as: "card",
|
|
36773
|
+
cond: {
|
|
36774
|
+
$and: [
|
|
36775
|
+
{ $ne: ["$$card.userId", null] },
|
|
36776
|
+
{ $eq: ["$$card.isActivated", true] }
|
|
36535
36777
|
]
|
|
36536
|
-
}
|
|
36537
|
-
userType
|
|
36778
|
+
}
|
|
36538
36779
|
}
|
|
36539
36780
|
},
|
|
36540
|
-
|
|
36541
|
-
|
|
36542
|
-
|
|
36543
|
-
|
|
36544
|
-
|
|
36545
|
-
|
|
36546
|
-
|
|
36547
|
-
|
|
36548
|
-
|
|
36549
|
-
|
|
36550
|
-
|
|
36551
|
-
|
|
36552
|
-
|
|
36553
|
-
|
|
36554
|
-
|
|
36555
|
-
|
|
36556
|
-
|
|
36557
|
-
|
|
36558
|
-
|
|
36559
|
-
|
|
36560
|
-
|
|
36561
|
-
|
|
36562
|
-
|
|
36563
|
-
$filter: {
|
|
36564
|
-
input: "$accessCards",
|
|
36565
|
-
as: "card",
|
|
36566
|
-
cond: { $and: [{ $eq: ["$$card.isActivated", false] }, { $ne: ["$$card.replacementStatus", null] }] }
|
|
36567
|
-
}
|
|
36568
|
-
},
|
|
36569
|
-
f_deleted: {
|
|
36570
|
-
$filter: {
|
|
36571
|
-
input: "$accessCards",
|
|
36572
|
-
as: "card",
|
|
36573
|
-
cond: { $and: [{ $eq: ["$$card.isActivated", false] }, { $eq: ["$$card.replacementStatus", null] }] }
|
|
36781
|
+
f_replaced: {
|
|
36782
|
+
$filter: {
|
|
36783
|
+
input: "$accessCards",
|
|
36784
|
+
as: "card",
|
|
36785
|
+
cond: {
|
|
36786
|
+
$and: [
|
|
36787
|
+
{ $eq: ["$$card.isActivated", false] },
|
|
36788
|
+
{ $ne: ["$$card.replacementStatus", null] }
|
|
36789
|
+
]
|
|
36790
|
+
}
|
|
36791
|
+
}
|
|
36792
|
+
},
|
|
36793
|
+
f_deleted: {
|
|
36794
|
+
$filter: {
|
|
36795
|
+
input: "$accessCards",
|
|
36796
|
+
as: "card",
|
|
36797
|
+
cond: {
|
|
36798
|
+
$and: [
|
|
36799
|
+
{ $eq: ["$$card.isActivated", false] },
|
|
36800
|
+
{ $eq: ["$$card.replacementStatus", null] }
|
|
36801
|
+
]
|
|
36802
|
+
}
|
|
36803
|
+
}
|
|
36574
36804
|
}
|
|
36575
36805
|
}
|
|
36576
|
-
}
|
|
36577
|
-
|
|
36578
|
-
|
|
36579
|
-
|
|
36580
|
-
|
|
36581
|
-
|
|
36582
|
-
|
|
36583
|
-
|
|
36584
|
-
|
|
36585
|
-
|
|
36586
|
-
unit_owner: { $arrayElemAt: ["$unitOwner", 0] },
|
|
36587
|
-
available: {
|
|
36588
|
-
physical: { $filter: { input: "$f_Available", as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } },
|
|
36589
|
-
non_physical: { $filter: { input: "$f_Available", as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } }
|
|
36590
|
-
},
|
|
36591
|
-
assigned: {
|
|
36592
|
-
physical: { $filter: { input: "$f_Assigned", as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } },
|
|
36593
|
-
non_physical: { $filter: { input: "$f_Assigned", as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } }
|
|
36594
|
-
},
|
|
36595
|
-
cardCounts: {
|
|
36806
|
+
},
|
|
36807
|
+
// ✅ Final projection with all computed fields
|
|
36808
|
+
{
|
|
36809
|
+
$project: {
|
|
36810
|
+
_id: "$level.units._id",
|
|
36811
|
+
name: "$level.units.name",
|
|
36812
|
+
level: { _id: "$level._id", level: "$level.level" },
|
|
36813
|
+
block: { _id: "$_id", name: "$name", block: "$block" },
|
|
36814
|
+
site: "$site",
|
|
36815
|
+
unit_owner: { $arrayElemAt: ["$unitOwner", 0] },
|
|
36596
36816
|
available: {
|
|
36597
|
-
physical: {
|
|
36598
|
-
|
|
36817
|
+
physical: {
|
|
36818
|
+
$filter: {
|
|
36819
|
+
input: "$f_Available",
|
|
36820
|
+
as: "c",
|
|
36821
|
+
cond: { $eq: ["$$c.type", "NFC" /* NFC */] }
|
|
36822
|
+
}
|
|
36823
|
+
},
|
|
36824
|
+
non_physical: {
|
|
36825
|
+
$filter: {
|
|
36826
|
+
input: "$f_Available",
|
|
36827
|
+
as: "c",
|
|
36828
|
+
cond: { $eq: ["$$c.type", "QRCODE" /* QR */] }
|
|
36829
|
+
}
|
|
36830
|
+
}
|
|
36599
36831
|
},
|
|
36600
36832
|
assigned: {
|
|
36601
|
-
physical: {
|
|
36602
|
-
|
|
36833
|
+
physical: {
|
|
36834
|
+
$filter: {
|
|
36835
|
+
input: "$f_Assigned",
|
|
36836
|
+
as: "c",
|
|
36837
|
+
cond: { $eq: ["$$c.type", "NFC" /* NFC */] }
|
|
36838
|
+
}
|
|
36839
|
+
},
|
|
36840
|
+
non_physical: {
|
|
36841
|
+
$filter: {
|
|
36842
|
+
input: "$f_Assigned",
|
|
36843
|
+
as: "c",
|
|
36844
|
+
cond: { $eq: ["$$c.type", "QRCODE" /* QR */] }
|
|
36845
|
+
}
|
|
36846
|
+
}
|
|
36847
|
+
},
|
|
36848
|
+
cardCounts: {
|
|
36849
|
+
available: {
|
|
36850
|
+
physical: {
|
|
36851
|
+
$size: {
|
|
36852
|
+
$filter: {
|
|
36853
|
+
input: { $ifNull: ["$f_Available", []] },
|
|
36854
|
+
as: "c",
|
|
36855
|
+
cond: {
|
|
36856
|
+
$eq: ["$$c.type", "NFC" /* NFC */]
|
|
36857
|
+
}
|
|
36858
|
+
}
|
|
36859
|
+
}
|
|
36860
|
+
},
|
|
36861
|
+
non_physical: {
|
|
36862
|
+
$size: {
|
|
36863
|
+
$filter: {
|
|
36864
|
+
input: { $ifNull: ["$f_Available", []] },
|
|
36865
|
+
as: "c",
|
|
36866
|
+
cond: {
|
|
36867
|
+
$eq: ["$$c.type", "QRCODE" /* QR */]
|
|
36868
|
+
}
|
|
36869
|
+
}
|
|
36870
|
+
}
|
|
36871
|
+
}
|
|
36872
|
+
},
|
|
36873
|
+
assigned: {
|
|
36874
|
+
physical: {
|
|
36875
|
+
$size: {
|
|
36876
|
+
$filter: {
|
|
36877
|
+
input: { $ifNull: ["$f_Assigned", []] },
|
|
36878
|
+
as: "c",
|
|
36879
|
+
cond: {
|
|
36880
|
+
$eq: ["$$c.type", "NFC" /* NFC */]
|
|
36881
|
+
}
|
|
36882
|
+
}
|
|
36883
|
+
}
|
|
36884
|
+
},
|
|
36885
|
+
non_physical: {
|
|
36886
|
+
$size: {
|
|
36887
|
+
$filter: {
|
|
36888
|
+
input: { $ifNull: ["$f_Assigned", []] },
|
|
36889
|
+
as: "c",
|
|
36890
|
+
cond: {
|
|
36891
|
+
$eq: ["$$c.type", "QRCODE" /* QR */]
|
|
36892
|
+
}
|
|
36893
|
+
}
|
|
36894
|
+
}
|
|
36895
|
+
}
|
|
36896
|
+
}
|
|
36897
|
+
},
|
|
36898
|
+
replaced: {
|
|
36899
|
+
physical: {
|
|
36900
|
+
$filter: {
|
|
36901
|
+
input: "$f_replaced",
|
|
36902
|
+
as: "c",
|
|
36903
|
+
cond: { $eq: ["$$c.type", "NFC" /* NFC */] }
|
|
36904
|
+
}
|
|
36905
|
+
},
|
|
36906
|
+
non_physical: {
|
|
36907
|
+
$filter: {
|
|
36908
|
+
input: "$f_replaced",
|
|
36909
|
+
as: "c",
|
|
36910
|
+
cond: { $eq: ["$$c.type", "QRCODE" /* QR */] }
|
|
36911
|
+
}
|
|
36912
|
+
}
|
|
36913
|
+
},
|
|
36914
|
+
deleted: {
|
|
36915
|
+
physical: {
|
|
36916
|
+
$filter: {
|
|
36917
|
+
input: "$f_deleted",
|
|
36918
|
+
as: "c",
|
|
36919
|
+
cond: { $eq: ["$$c.type", "NFC" /* NFC */] }
|
|
36920
|
+
}
|
|
36921
|
+
},
|
|
36922
|
+
non_physical: {
|
|
36923
|
+
$filter: {
|
|
36924
|
+
input: "$f_deleted",
|
|
36925
|
+
as: "c",
|
|
36926
|
+
cond: { $eq: ["$$c.type", "QRCODE" /* QR */] }
|
|
36927
|
+
}
|
|
36928
|
+
}
|
|
36929
|
+
},
|
|
36930
|
+
totalCardCount: {
|
|
36931
|
+
$add: [
|
|
36932
|
+
{
|
|
36933
|
+
$size: {
|
|
36934
|
+
$filter: {
|
|
36935
|
+
input: { $ifNull: ["$f_Available", []] },
|
|
36936
|
+
as: "c",
|
|
36937
|
+
cond: {
|
|
36938
|
+
$eq: ["$$c.type", "NFC" /* NFC */]
|
|
36939
|
+
}
|
|
36940
|
+
}
|
|
36941
|
+
}
|
|
36942
|
+
},
|
|
36943
|
+
{
|
|
36944
|
+
$size: {
|
|
36945
|
+
$filter: {
|
|
36946
|
+
input: { $ifNull: ["$f_Available", []] },
|
|
36947
|
+
as: "c",
|
|
36948
|
+
cond: {
|
|
36949
|
+
$eq: ["$$c.type", "QRCODE" /* QR */]
|
|
36950
|
+
}
|
|
36951
|
+
}
|
|
36952
|
+
}
|
|
36953
|
+
},
|
|
36954
|
+
{
|
|
36955
|
+
$size: {
|
|
36956
|
+
$filter: {
|
|
36957
|
+
input: { $ifNull: ["$f_Assigned", []] },
|
|
36958
|
+
as: "c",
|
|
36959
|
+
cond: {
|
|
36960
|
+
$eq: ["$$c.type", "NFC" /* NFC */]
|
|
36961
|
+
}
|
|
36962
|
+
}
|
|
36963
|
+
}
|
|
36964
|
+
},
|
|
36965
|
+
{
|
|
36966
|
+
$size: {
|
|
36967
|
+
$filter: {
|
|
36968
|
+
input: { $ifNull: ["$f_Assigned", []] },
|
|
36969
|
+
as: "c",
|
|
36970
|
+
cond: {
|
|
36971
|
+
$eq: ["$$c.type", "QRCODE" /* QR */]
|
|
36972
|
+
}
|
|
36973
|
+
}
|
|
36974
|
+
}
|
|
36975
|
+
}
|
|
36976
|
+
]
|
|
36603
36977
|
}
|
|
36604
|
-
},
|
|
36605
|
-
replaced: {
|
|
36606
|
-
physical: { $filter: { input: "$f_replaced", as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } },
|
|
36607
|
-
non_physical: { $filter: { input: "$f_replaced", as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } }
|
|
36608
|
-
},
|
|
36609
|
-
deleted: {
|
|
36610
|
-
physical: { $filter: { input: "$f_deleted", as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } },
|
|
36611
|
-
non_physical: { $filter: { input: "$f_deleted", as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } }
|
|
36612
|
-
},
|
|
36613
|
-
totalCardCount: {
|
|
36614
|
-
$add: [
|
|
36615
|
-
{ $size: { $filter: { input: { $ifNull: ["$f_Available", []] }, as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } } },
|
|
36616
|
-
{ $size: { $filter: { input: { $ifNull: ["$f_Available", []] }, as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } } },
|
|
36617
|
-
{ $size: { $filter: { input: { $ifNull: ["$f_Assigned", []] }, as: "c", cond: { $eq: ["$$c.type", "NFC" /* NFC */] } } } },
|
|
36618
|
-
{ $size: { $filter: { input: { $ifNull: ["$f_Assigned", []] }, as: "c", cond: { $eq: ["$$c.type", "QRCODE" /* QR */] } } } }
|
|
36619
|
-
]
|
|
36620
36978
|
}
|
|
36621
|
-
}
|
|
36622
|
-
|
|
36623
|
-
|
|
36624
|
-
|
|
36979
|
+
},
|
|
36980
|
+
{ $sort: { totalCardCount: -1 } }
|
|
36981
|
+
]
|
|
36982
|
+
}
|
|
36625
36983
|
}
|
|
36626
|
-
|
|
36627
|
-
|
|
36984
|
+
],
|
|
36985
|
+
{ allowDiskUse: true }
|
|
36986
|
+
).toArray();
|
|
36628
36987
|
const totalCount = result[0]?.totalCount?.[0]?.count ?? 0;
|
|
36629
36988
|
const items = result[0]?.items ?? [];
|
|
36630
36989
|
const paginatedResult = paginate39(items, page, limit, totalCount);
|
|
@@ -36643,157 +37002,162 @@ function UseAccessManagementRepo() {
|
|
|
36643
37002
|
site: { $in: [site] }
|
|
36644
37003
|
};
|
|
36645
37004
|
const searchQuery = buildSearchQuery(search);
|
|
36646
|
-
const result = await collectionName("buildings").aggregate(
|
|
36647
|
-
|
|
36648
|
-
|
|
36649
|
-
|
|
36650
|
-
|
|
36651
|
-
|
|
36652
|
-
|
|
36653
|
-
|
|
36654
|
-
|
|
36655
|
-
|
|
36656
|
-
|
|
36657
|
-
|
|
36658
|
-
|
|
36659
|
-
|
|
36660
|
-
|
|
36661
|
-
|
|
36662
|
-
|
|
36663
|
-
|
|
36664
|
-
|
|
36665
|
-
|
|
36666
|
-
|
|
36667
|
-
|
|
36668
|
-
|
|
36669
|
-
|
|
36670
|
-
|
|
36671
|
-
|
|
36672
|
-
|
|
36673
|
-
|
|
36674
|
-
|
|
36675
|
-
|
|
36676
|
-
|
|
36677
|
-
|
|
36678
|
-
|
|
36679
|
-
|
|
36680
|
-
|
|
36681
|
-
|
|
36682
|
-
|
|
36683
|
-
|
|
36684
|
-
|
|
36685
|
-
|
|
36686
|
-
|
|
36687
|
-
|
|
36688
|
-
|
|
36689
|
-
|
|
36690
|
-
|
|
36691
|
-
|
|
36692
|
-
|
|
36693
|
-
|
|
36694
|
-
|
|
36695
|
-
|
|
36696
|
-
|
|
36697
|
-
|
|
36698
|
-
|
|
36699
|
-
$
|
|
36700
|
-
|
|
36701
|
-
|
|
36702
|
-
|
|
36703
|
-
|
|
36704
|
-
|
|
36705
|
-
|
|
37005
|
+
const result = await collectionName("buildings").aggregate(
|
|
37006
|
+
[
|
|
37007
|
+
// ✅ Match early with index-friendly query
|
|
37008
|
+
{
|
|
37009
|
+
$match: {
|
|
37010
|
+
...query,
|
|
37011
|
+
status: { $ne: "deleted" }
|
|
37012
|
+
}
|
|
37013
|
+
},
|
|
37014
|
+
// ✅ Only project needed fields before heavy lookups
|
|
37015
|
+
{
|
|
37016
|
+
$project: {
|
|
37017
|
+
_id: 1,
|
|
37018
|
+
name: 1,
|
|
37019
|
+
site: 1
|
|
37020
|
+
}
|
|
37021
|
+
},
|
|
37022
|
+
// ✅ Use localField/foreignField for better index usage
|
|
37023
|
+
{
|
|
37024
|
+
$lookup: {
|
|
37025
|
+
from: "building-levels",
|
|
37026
|
+
localField: "_id",
|
|
37027
|
+
foreignField: "block",
|
|
37028
|
+
pipeline: [
|
|
37029
|
+
{ $match: { status: { $ne: "deleted" } } },
|
|
37030
|
+
{
|
|
37031
|
+
$lookup: {
|
|
37032
|
+
from: "building-units",
|
|
37033
|
+
localField: "_id",
|
|
37034
|
+
foreignField: "level",
|
|
37035
|
+
pipeline: [
|
|
37036
|
+
{ $match: { status: { $ne: "deleted" } } },
|
|
37037
|
+
{ $project: { _id: 1, name: 1 } },
|
|
37038
|
+
{
|
|
37039
|
+
$lookup: {
|
|
37040
|
+
from: "access-cards",
|
|
37041
|
+
localField: "_id",
|
|
37042
|
+
foreignField: "assignedUnit",
|
|
37043
|
+
pipeline: [
|
|
37044
|
+
{
|
|
37045
|
+
$match: {
|
|
37046
|
+
isActivated: true,
|
|
37047
|
+
userType,
|
|
37048
|
+
type
|
|
37049
|
+
}
|
|
37050
|
+
},
|
|
37051
|
+
{
|
|
37052
|
+
$group: {
|
|
37053
|
+
_id: null,
|
|
37054
|
+
accessLevels: { $addToSet: "$accessLevel" },
|
|
37055
|
+
liftAccessLevels: {
|
|
37056
|
+
$addToSet: "$liftAccessLevel"
|
|
37057
|
+
},
|
|
37058
|
+
doorNames: { $addToSet: "$doorName" },
|
|
37059
|
+
liftNames: { $addToSet: "$liftName" },
|
|
37060
|
+
cards: {
|
|
37061
|
+
$push: {
|
|
37062
|
+
_id: "$_id",
|
|
37063
|
+
cardNo: "$cardNo",
|
|
37064
|
+
accessLevel: "$accessLevel",
|
|
37065
|
+
liftAccessLevel: "$liftAccessLevel",
|
|
37066
|
+
doorName: "$doorName",
|
|
37067
|
+
liftName: "$liftName"
|
|
37068
|
+
}
|
|
36706
37069
|
}
|
|
36707
37070
|
}
|
|
37071
|
+
},
|
|
37072
|
+
{
|
|
37073
|
+
$project: {
|
|
37074
|
+
_id: 0,
|
|
37075
|
+
accessCardCount: {
|
|
37076
|
+
$size: "$cards"
|
|
37077
|
+
},
|
|
37078
|
+
accessLevels: 1,
|
|
37079
|
+
liftAccessLevels: 1,
|
|
37080
|
+
doorNames: 1,
|
|
37081
|
+
liftNames: 1
|
|
37082
|
+
}
|
|
36708
37083
|
}
|
|
36709
|
-
|
|
36710
|
-
|
|
36711
|
-
|
|
36712
|
-
|
|
36713
|
-
|
|
36714
|
-
|
|
36715
|
-
|
|
36716
|
-
|
|
36717
|
-
liftAccessLevels: 1,
|
|
36718
|
-
doorNames: 1,
|
|
36719
|
-
liftNames: 1
|
|
36720
|
-
}
|
|
36721
|
-
}
|
|
36722
|
-
],
|
|
36723
|
-
as: "fAccessCards"
|
|
36724
|
-
}
|
|
36725
|
-
},
|
|
36726
|
-
{
|
|
36727
|
-
$match: {
|
|
36728
|
-
"fAccessCards.0": { $exists: true }
|
|
37084
|
+
],
|
|
37085
|
+
as: "fAccessCards"
|
|
37086
|
+
}
|
|
37087
|
+
},
|
|
37088
|
+
{
|
|
37089
|
+
$match: {
|
|
37090
|
+
"fAccessCards.0": { $exists: true }
|
|
37091
|
+
}
|
|
36729
37092
|
}
|
|
36730
|
-
|
|
36731
|
-
|
|
36732
|
-
|
|
36733
|
-
}
|
|
36734
|
-
|
|
36735
|
-
|
|
36736
|
-
|
|
36737
|
-
|
|
36738
|
-
|
|
36739
|
-
|
|
36740
|
-
|
|
36741
|
-
|
|
36742
|
-
|
|
37093
|
+
],
|
|
37094
|
+
as: "units"
|
|
37095
|
+
}
|
|
37096
|
+
},
|
|
37097
|
+
{
|
|
37098
|
+
$match: { "units.0": { $exists: true } }
|
|
37099
|
+
},
|
|
37100
|
+
{
|
|
37101
|
+
$project: {
|
|
37102
|
+
_id: 1,
|
|
37103
|
+
level: 1,
|
|
37104
|
+
units: 1
|
|
37105
|
+
}
|
|
36743
37106
|
}
|
|
36744
|
-
|
|
36745
|
-
|
|
36746
|
-
|
|
36747
|
-
}
|
|
36748
|
-
|
|
36749
|
-
|
|
36750
|
-
|
|
36751
|
-
|
|
36752
|
-
|
|
36753
|
-
|
|
36754
|
-
|
|
36755
|
-
|
|
36756
|
-
|
|
36757
|
-
|
|
36758
|
-
}
|
|
36759
|
-
|
|
36760
|
-
|
|
36761
|
-
|
|
36762
|
-
|
|
36763
|
-
|
|
36764
|
-
}
|
|
36765
|
-
|
|
36766
|
-
|
|
36767
|
-
|
|
36768
|
-
|
|
36769
|
-
|
|
36770
|
-
}
|
|
36771
|
-
|
|
36772
|
-
|
|
36773
|
-
|
|
36774
|
-
|
|
36775
|
-
|
|
36776
|
-
|
|
36777
|
-
}
|
|
36778
|
-
|
|
36779
|
-
|
|
36780
|
-
|
|
36781
|
-
|
|
36782
|
-
|
|
36783
|
-
|
|
36784
|
-
|
|
36785
|
-
|
|
36786
|
-
}
|
|
36787
|
-
|
|
36788
|
-
|
|
36789
|
-
|
|
36790
|
-
|
|
36791
|
-
|
|
36792
|
-
|
|
36793
|
-
|
|
37107
|
+
],
|
|
37108
|
+
as: "level"
|
|
37109
|
+
}
|
|
37110
|
+
},
|
|
37111
|
+
// ✅ Filter out buildings with no levels early
|
|
37112
|
+
{
|
|
37113
|
+
$match: { "level.0": { $exists: true } }
|
|
37114
|
+
},
|
|
37115
|
+
// ✅ Unwind to flatten the hierarchy
|
|
37116
|
+
{
|
|
37117
|
+
$unwind: {
|
|
37118
|
+
path: "$level",
|
|
37119
|
+
preserveNullAndEmptyArrays: false
|
|
37120
|
+
}
|
|
37121
|
+
},
|
|
37122
|
+
{
|
|
37123
|
+
$unwind: {
|
|
37124
|
+
path: "$level.units",
|
|
37125
|
+
preserveNullAndEmptyArrays: false
|
|
37126
|
+
}
|
|
37127
|
+
},
|
|
37128
|
+
{
|
|
37129
|
+
$unwind: {
|
|
37130
|
+
path: "$level.units.fAccessCards",
|
|
37131
|
+
preserveNullAndEmptyArrays: false
|
|
37132
|
+
}
|
|
37133
|
+
},
|
|
37134
|
+
// // Groups by unit _id and keeps only the first occurrence
|
|
37135
|
+
{
|
|
37136
|
+
$group: {
|
|
37137
|
+
_id: "$level.units._id",
|
|
37138
|
+
doc: { $first: "$$ROOT" }
|
|
37139
|
+
}
|
|
37140
|
+
},
|
|
37141
|
+
{
|
|
37142
|
+
$replaceRoot: { newRoot: "$doc" }
|
|
37143
|
+
},
|
|
37144
|
+
// ✅ Apply search filter
|
|
37145
|
+
{
|
|
37146
|
+
$match: {
|
|
37147
|
+
...searchQuery
|
|
37148
|
+
}
|
|
37149
|
+
},
|
|
37150
|
+
{
|
|
37151
|
+
$project: {
|
|
37152
|
+
name: 1,
|
|
37153
|
+
"level.level": 1,
|
|
37154
|
+
"level.units.name": 1,
|
|
37155
|
+
"level.units.fAccessCards": 1
|
|
37156
|
+
}
|
|
36794
37157
|
}
|
|
36795
|
-
|
|
36796
|
-
|
|
37158
|
+
],
|
|
37159
|
+
{ allowDiskUse: true }
|
|
37160
|
+
).toArray();
|
|
36797
37161
|
return result;
|
|
36798
37162
|
} catch (error) {
|
|
36799
37163
|
throw new Error(error.message);
|
|
@@ -36804,8 +37168,12 @@ function UseAccessManagementRepo() {
|
|
|
36804
37168
|
try {
|
|
36805
37169
|
session?.startTransaction();
|
|
36806
37170
|
const { userId, cardId, site } = params;
|
|
36807
|
-
const allUserId = await Promise.all(
|
|
36808
|
-
|
|
37171
|
+
const allUserId = await Promise.all(
|
|
37172
|
+
userId.map(async (id) => new ObjectId90(id))
|
|
37173
|
+
);
|
|
37174
|
+
const allCardId = await Promise.all(
|
|
37175
|
+
cardId.map(async (id) => new ObjectId90(id))
|
|
37176
|
+
);
|
|
36809
37177
|
const siteId = new ObjectId90(site);
|
|
36810
37178
|
const result = await collection().updateMany(
|
|
36811
37179
|
{
|
|
@@ -36848,16 +37216,19 @@ function UseAccessManagementRepo() {
|
|
|
36848
37216
|
liftAccessLevel,
|
|
36849
37217
|
isActivated: true
|
|
36850
37218
|
};
|
|
36851
|
-
const result = await collection().aggregate(
|
|
36852
|
-
|
|
36853
|
-
|
|
36854
|
-
|
|
36855
|
-
|
|
36856
|
-
|
|
36857
|
-
|
|
37219
|
+
const result = await collection().aggregate(
|
|
37220
|
+
[
|
|
37221
|
+
{
|
|
37222
|
+
$match: query
|
|
37223
|
+
},
|
|
37224
|
+
{
|
|
37225
|
+
$facet: {
|
|
37226
|
+
counts: [{ $count: "count" }]
|
|
37227
|
+
}
|
|
36858
37228
|
}
|
|
36859
|
-
|
|
36860
|
-
|
|
37229
|
+
],
|
|
37230
|
+
{ allowDiskUse: true }
|
|
37231
|
+
).toArray();
|
|
36861
37232
|
return result;
|
|
36862
37233
|
} catch (error) {
|
|
36863
37234
|
throw new Error(error.message);
|
|
@@ -36891,7 +37262,9 @@ function UseAccessManagementRepo() {
|
|
|
36891
37262
|
availableCardNo.push(num);
|
|
36892
37263
|
num++;
|
|
36893
37264
|
}
|
|
36894
|
-
const cardNumbers = availableCardNo.map(
|
|
37265
|
+
const cardNumbers = availableCardNo.map(
|
|
37266
|
+
(no) => no.toString().padStart(10, "0")
|
|
37267
|
+
);
|
|
36895
37268
|
const accessCards = [];
|
|
36896
37269
|
const convertedUnits = unit.map((obj) => new ObjectId90(obj));
|
|
36897
37270
|
for (let j = 0; j < (unit.length > 0 ? unit.length : quantity); j++) {
|
|
@@ -36951,10 +37324,18 @@ function UseAccessManagementRepo() {
|
|
|
36951
37324
|
liftAccessEndDate: formatEntryPassDate(item.liftAccessEndDate) || "19770510",
|
|
36952
37325
|
accessGroup: ag
|
|
36953
37326
|
};
|
|
36954
|
-
return readTemplate(
|
|
37327
|
+
return readTemplate(
|
|
37328
|
+
`${item.accessLevel !== null ? "add-card" : "add-card-lift"}`,
|
|
37329
|
+
{ ...command }
|
|
37330
|
+
);
|
|
36955
37331
|
}).flat();
|
|
36956
|
-
const response = await sendCommand(
|
|
36957
|
-
|
|
37332
|
+
const response = await sendCommand(
|
|
37333
|
+
commands.join("").toString(),
|
|
37334
|
+
params.acm_url
|
|
37335
|
+
);
|
|
37336
|
+
const result = await parseStringPromise2(response, {
|
|
37337
|
+
explicitArray: false
|
|
37338
|
+
});
|
|
36958
37339
|
if (result && result.RESULT.$.STCODE !== "0") {
|
|
36959
37340
|
throw new Error("Command failed, server error.");
|
|
36960
37341
|
}
|
|
@@ -36988,7 +37369,11 @@ function UseAccessManagementRepo() {
|
|
|
36988
37369
|
} else {
|
|
36989
37370
|
updateFields.isActivated = true;
|
|
36990
37371
|
}
|
|
36991
|
-
const res = await collection().updateOne(
|
|
37372
|
+
const res = await collection().updateOne(
|
|
37373
|
+
{ _id: card._id },
|
|
37374
|
+
{ $set: updateFields },
|
|
37375
|
+
{ session }
|
|
37376
|
+
);
|
|
36992
37377
|
results.push({ nfcId: nfc._id, modifiedCount: res.modifiedCount });
|
|
36993
37378
|
}
|
|
36994
37379
|
}
|
|
@@ -37015,8 +37400,20 @@ function UseAccessManagementRepo() {
|
|
|
37015
37400
|
assignedUnit: null,
|
|
37016
37401
|
userId: null,
|
|
37017
37402
|
$or: [
|
|
37018
|
-
{
|
|
37019
|
-
|
|
37403
|
+
{
|
|
37404
|
+
$and: [
|
|
37405
|
+
{ doorName: { $ne: null } },
|
|
37406
|
+
{ doorName: { $ne: "" } },
|
|
37407
|
+
{ accessLevel: { $ne: null } }
|
|
37408
|
+
]
|
|
37409
|
+
},
|
|
37410
|
+
{
|
|
37411
|
+
$and: [
|
|
37412
|
+
{ liftName: { $ne: null } },
|
|
37413
|
+
{ liftName: { $ne: "" } },
|
|
37414
|
+
{ liftAccessLevel: { $ne: null } }
|
|
37415
|
+
]
|
|
37416
|
+
}
|
|
37020
37417
|
]
|
|
37021
37418
|
}
|
|
37022
37419
|
},
|
|
@@ -37030,7 +37427,13 @@ function UseAccessManagementRepo() {
|
|
|
37030
37427
|
accessLevels: {
|
|
37031
37428
|
$addToSet: {
|
|
37032
37429
|
$cond: [
|
|
37033
|
-
{
|
|
37430
|
+
{
|
|
37431
|
+
$and: [
|
|
37432
|
+
{ $ne: ["$doorName", null] },
|
|
37433
|
+
{ $ne: ["$doorName", ""] },
|
|
37434
|
+
{ $ne: ["$accessLevel", null] }
|
|
37435
|
+
]
|
|
37436
|
+
},
|
|
37034
37437
|
{ name: "$doorName", no: "$accessLevel" },
|
|
37035
37438
|
"$$REMOVE"
|
|
37036
37439
|
]
|
|
@@ -37039,7 +37442,13 @@ function UseAccessManagementRepo() {
|
|
|
37039
37442
|
liftAccessLevels: {
|
|
37040
37443
|
$addToSet: {
|
|
37041
37444
|
$cond: [
|
|
37042
|
-
{
|
|
37445
|
+
{
|
|
37446
|
+
$and: [
|
|
37447
|
+
{ $ne: ["$liftName", null] },
|
|
37448
|
+
{ $ne: ["$liftName", ""] },
|
|
37449
|
+
{ $ne: ["$liftAccessLevel", null] }
|
|
37450
|
+
]
|
|
37451
|
+
},
|
|
37043
37452
|
{ name: "$liftName", no: "$liftAccessLevel" },
|
|
37044
37453
|
"$$REMOVE"
|
|
37045
37454
|
]
|
|
@@ -37075,7 +37484,14 @@ function UseAccessManagementRepo() {
|
|
|
37075
37484
|
const sessionResult = await Promise.all([
|
|
37076
37485
|
await collection().findOneAndUpdate(
|
|
37077
37486
|
{ _id: id },
|
|
37078
|
-
{
|
|
37487
|
+
{
|
|
37488
|
+
$set: {
|
|
37489
|
+
remarks,
|
|
37490
|
+
replacementStatus: "Complete",
|
|
37491
|
+
requestDate: /* @__PURE__ */ new Date(),
|
|
37492
|
+
isActivated: false
|
|
37493
|
+
}
|
|
37494
|
+
},
|
|
37079
37495
|
{ returnDocument: "after", session }
|
|
37080
37496
|
),
|
|
37081
37497
|
await collection().findOneAndUpdate(
|
|
@@ -37107,7 +37523,10 @@ function UseAccessManagementRepo() {
|
|
|
37107
37523
|
isActivated: true
|
|
37108
37524
|
};
|
|
37109
37525
|
if (search) {
|
|
37110
|
-
query.$or = [
|
|
37526
|
+
query.$or = [
|
|
37527
|
+
{ accessLevel: { $regex: search, $options: "i" } },
|
|
37528
|
+
{ cardNo: { $regex: search, $options: "i" } }
|
|
37529
|
+
];
|
|
37111
37530
|
}
|
|
37112
37531
|
if (type) {
|
|
37113
37532
|
query.userType = type;
|
|
@@ -37132,14 +37551,22 @@ function UseAccessManagementRepo() {
|
|
|
37132
37551
|
{
|
|
37133
37552
|
$addFields: {
|
|
37134
37553
|
extractedCardNo: {
|
|
37135
|
-
$substr: [
|
|
37554
|
+
$substr: [
|
|
37555
|
+
"$cardNo",
|
|
37556
|
+
{ $subtract: [{ $strLenCP: "$cardNo" }, 5] },
|
|
37557
|
+
5
|
|
37558
|
+
]
|
|
37136
37559
|
}
|
|
37137
37560
|
}
|
|
37138
37561
|
},
|
|
37139
37562
|
{
|
|
37140
37563
|
$facet: {
|
|
37141
37564
|
totalCount: [{ $count: "count" }],
|
|
37142
|
-
items: [
|
|
37565
|
+
items: [
|
|
37566
|
+
{ $sort: { _id: -1 } },
|
|
37567
|
+
{ $skip: page * limit },
|
|
37568
|
+
{ $limit: limit }
|
|
37569
|
+
]
|
|
37143
37570
|
}
|
|
37144
37571
|
}
|
|
37145
37572
|
]).toArray();
|
|
@@ -37170,145 +37597,151 @@ function UseAccessManagementRepo() {
|
|
|
37170
37597
|
query.replacementStatus = statusFilter;
|
|
37171
37598
|
}
|
|
37172
37599
|
if (dateFrom && dateTo) {
|
|
37173
|
-
query.requestDate = {
|
|
37600
|
+
query.requestDate = {
|
|
37601
|
+
$gte: new Date(dateFrom),
|
|
37602
|
+
$lte: new Date(dateTo)
|
|
37603
|
+
};
|
|
37174
37604
|
} else if (dateFrom) {
|
|
37175
37605
|
query.requestDate = { $gte: new Date(dateFrom) };
|
|
37176
37606
|
} else if (dateTo) {
|
|
37177
37607
|
query.requestDate = { $lte: new Date(dateTo) };
|
|
37178
37608
|
}
|
|
37179
|
-
const res = await collection().aggregate(
|
|
37180
|
-
|
|
37181
|
-
|
|
37182
|
-
|
|
37183
|
-
|
|
37184
|
-
|
|
37185
|
-
|
|
37186
|
-
|
|
37187
|
-
|
|
37188
|
-
|
|
37189
|
-
|
|
37190
|
-
$
|
|
37191
|
-
$
|
|
37609
|
+
const res = await collection().aggregate(
|
|
37610
|
+
[
|
|
37611
|
+
{
|
|
37612
|
+
$match: { ...query }
|
|
37613
|
+
},
|
|
37614
|
+
{
|
|
37615
|
+
$lookup: {
|
|
37616
|
+
from: "building-units",
|
|
37617
|
+
let: { unit: "$assignedUnit" },
|
|
37618
|
+
pipeline: [
|
|
37619
|
+
{
|
|
37620
|
+
$match: {
|
|
37621
|
+
$expr: {
|
|
37622
|
+
$eq: ["$_id", "$$unit"]
|
|
37623
|
+
}
|
|
37192
37624
|
}
|
|
37193
|
-
}
|
|
37194
|
-
|
|
37195
|
-
|
|
37196
|
-
|
|
37197
|
-
|
|
37198
|
-
|
|
37199
|
-
level: 1
|
|
37200
|
-
}
|
|
37201
|
-
}
|
|
37202
|
-
],
|
|
37203
|
-
as: "unit"
|
|
37204
|
-
}
|
|
37205
|
-
},
|
|
37206
|
-
{
|
|
37207
|
-
$unwind: { path: "$unit", preserveNullAndEmptyArrays: true }
|
|
37208
|
-
},
|
|
37209
|
-
{
|
|
37210
|
-
$lookup: {
|
|
37211
|
-
from: "building-levels",
|
|
37212
|
-
let: { level: "$unit.level" },
|
|
37213
|
-
pipeline: [
|
|
37214
|
-
{
|
|
37215
|
-
$match: {
|
|
37216
|
-
$expr: {
|
|
37217
|
-
$eq: ["$_id", "$$level"]
|
|
37625
|
+
},
|
|
37626
|
+
{
|
|
37627
|
+
$project: {
|
|
37628
|
+
_id: 1,
|
|
37629
|
+
name: 1,
|
|
37630
|
+
level: 1
|
|
37218
37631
|
}
|
|
37219
37632
|
}
|
|
37220
|
-
|
|
37221
|
-
|
|
37222
|
-
|
|
37223
|
-
|
|
37224
|
-
|
|
37225
|
-
|
|
37226
|
-
|
|
37227
|
-
|
|
37228
|
-
|
|
37229
|
-
|
|
37230
|
-
|
|
37231
|
-
|
|
37232
|
-
|
|
37233
|
-
|
|
37234
|
-
|
|
37235
|
-
|
|
37236
|
-
|
|
37237
|
-
|
|
37238
|
-
|
|
37239
|
-
|
|
37240
|
-
|
|
37241
|
-
|
|
37242
|
-
|
|
37243
|
-
|
|
37633
|
+
],
|
|
37634
|
+
as: "unit"
|
|
37635
|
+
}
|
|
37636
|
+
},
|
|
37637
|
+
{
|
|
37638
|
+
$unwind: { path: "$unit", preserveNullAndEmptyArrays: true }
|
|
37639
|
+
},
|
|
37640
|
+
{
|
|
37641
|
+
$lookup: {
|
|
37642
|
+
from: "building-levels",
|
|
37643
|
+
let: { level: "$unit.level" },
|
|
37644
|
+
pipeline: [
|
|
37645
|
+
{
|
|
37646
|
+
$match: {
|
|
37647
|
+
$expr: {
|
|
37648
|
+
$eq: ["$_id", "$$level"]
|
|
37649
|
+
}
|
|
37650
|
+
}
|
|
37651
|
+
},
|
|
37652
|
+
{
|
|
37653
|
+
$project: {
|
|
37654
|
+
_id: 1,
|
|
37655
|
+
level: 1,
|
|
37656
|
+
block: 1
|
|
37244
37657
|
}
|
|
37245
37658
|
}
|
|
37246
|
-
|
|
37247
|
-
|
|
37248
|
-
|
|
37249
|
-
|
|
37250
|
-
|
|
37251
|
-
|
|
37252
|
-
|
|
37253
|
-
|
|
37254
|
-
|
|
37255
|
-
|
|
37256
|
-
|
|
37257
|
-
|
|
37258
|
-
|
|
37259
|
-
|
|
37260
|
-
|
|
37261
|
-
|
|
37262
|
-
|
|
37263
|
-
|
|
37264
|
-
|
|
37265
|
-
|
|
37266
|
-
|
|
37267
|
-
|
|
37268
|
-
|
|
37659
|
+
],
|
|
37660
|
+
as: "level"
|
|
37661
|
+
}
|
|
37662
|
+
},
|
|
37663
|
+
{
|
|
37664
|
+
$unwind: { path: "$level", preserveNullAndEmptyArrays: true }
|
|
37665
|
+
},
|
|
37666
|
+
{
|
|
37667
|
+
$lookup: {
|
|
37668
|
+
from: "buildings",
|
|
37669
|
+
let: { block: "$level.block" },
|
|
37670
|
+
pipeline: [
|
|
37671
|
+
{
|
|
37672
|
+
$match: {
|
|
37673
|
+
$expr: {
|
|
37674
|
+
$eq: ["$_id", "$$block"]
|
|
37675
|
+
}
|
|
37676
|
+
}
|
|
37677
|
+
},
|
|
37678
|
+
{
|
|
37679
|
+
$project: {
|
|
37680
|
+
_id: 1,
|
|
37681
|
+
name: 1
|
|
37269
37682
|
}
|
|
37270
37683
|
}
|
|
37271
|
-
|
|
37272
|
-
|
|
37273
|
-
|
|
37274
|
-
|
|
37275
|
-
|
|
37684
|
+
],
|
|
37685
|
+
as: "building"
|
|
37686
|
+
}
|
|
37687
|
+
},
|
|
37688
|
+
{
|
|
37689
|
+
$unwind: { path: "$building", preserveNullAndEmptyArrays: true }
|
|
37690
|
+
},
|
|
37691
|
+
{
|
|
37692
|
+
$lookup: {
|
|
37693
|
+
from: "users",
|
|
37694
|
+
let: { id: "$userId" },
|
|
37695
|
+
pipeline: [
|
|
37696
|
+
{
|
|
37697
|
+
$match: {
|
|
37698
|
+
$expr: {
|
|
37699
|
+
$eq: ["$_id", "$$id"]
|
|
37700
|
+
}
|
|
37701
|
+
}
|
|
37702
|
+
},
|
|
37703
|
+
{
|
|
37704
|
+
$project: {
|
|
37705
|
+
givenName: 1,
|
|
37706
|
+
surname: 1
|
|
37707
|
+
}
|
|
37276
37708
|
}
|
|
37277
|
-
|
|
37278
|
-
|
|
37279
|
-
|
|
37280
|
-
}
|
|
37281
|
-
|
|
37282
|
-
|
|
37283
|
-
|
|
37284
|
-
|
|
37285
|
-
|
|
37286
|
-
|
|
37287
|
-
|
|
37288
|
-
|
|
37289
|
-
|
|
37290
|
-
|
|
37291
|
-
|
|
37292
|
-
|
|
37293
|
-
|
|
37294
|
-
|
|
37295
|
-
|
|
37296
|
-
|
|
37297
|
-
|
|
37298
|
-
|
|
37299
|
-
|
|
37300
|
-
|
|
37301
|
-
|
|
37302
|
-
|
|
37303
|
-
|
|
37304
|
-
|
|
37709
|
+
],
|
|
37710
|
+
as: "user"
|
|
37711
|
+
}
|
|
37712
|
+
},
|
|
37713
|
+
{
|
|
37714
|
+
$unwind: { path: "$user", preserveNullAndEmptyArrays: true }
|
|
37715
|
+
},
|
|
37716
|
+
{
|
|
37717
|
+
$match: { ...searchQuery }
|
|
37718
|
+
},
|
|
37719
|
+
{
|
|
37720
|
+
$facet: {
|
|
37721
|
+
data: [
|
|
37722
|
+
{ $skip: page * limit },
|
|
37723
|
+
{ $limit: limit },
|
|
37724
|
+
{
|
|
37725
|
+
$project: {
|
|
37726
|
+
_id: 1,
|
|
37727
|
+
cardNo: 1,
|
|
37728
|
+
accessLevel: 1,
|
|
37729
|
+
liftAccessLevel: 1,
|
|
37730
|
+
replacementStatus: 1,
|
|
37731
|
+
remarks: 1,
|
|
37732
|
+
block: "$building.name",
|
|
37733
|
+
level: "$level.level",
|
|
37734
|
+
unit: "$unit.name",
|
|
37735
|
+
user: "$user"
|
|
37736
|
+
}
|
|
37305
37737
|
}
|
|
37306
|
-
|
|
37307
|
-
|
|
37308
|
-
|
|
37738
|
+
],
|
|
37739
|
+
totalCount: [{ $count: "count" }]
|
|
37740
|
+
}
|
|
37309
37741
|
}
|
|
37310
|
-
|
|
37311
|
-
|
|
37742
|
+
],
|
|
37743
|
+
{ allowDiskUse: true }
|
|
37744
|
+
).toArray();
|
|
37312
37745
|
const count = res[0]?.totalCount[0] ? res[0].totalCount[0].count : 0;
|
|
37313
37746
|
const pagination = paginate39(res[0].data, page, limit, count);
|
|
37314
37747
|
return pagination;
|
|
@@ -37320,7 +37753,10 @@ function UseAccessManagementRepo() {
|
|
|
37320
37753
|
try {
|
|
37321
37754
|
const { site } = params;
|
|
37322
37755
|
const siteId = new ObjectId90(site);
|
|
37323
|
-
const res = await collectionName("entrypass-settings").findOne(
|
|
37756
|
+
const res = await collectionName("entrypass-settings").findOne(
|
|
37757
|
+
{ site: siteId },
|
|
37758
|
+
{ allowDiskUse: true }
|
|
37759
|
+
);
|
|
37324
37760
|
return res;
|
|
37325
37761
|
} catch (error) {
|
|
37326
37762
|
throw new Error(error.message);
|
|
@@ -37330,13 +37766,19 @@ function UseAccessManagementRepo() {
|
|
|
37330
37766
|
const session = useAtlas76.getClient()?.startSession();
|
|
37331
37767
|
try {
|
|
37332
37768
|
const { dataJson, site } = params;
|
|
37333
|
-
const rawItems = JSON.parse(dataJson).filter(
|
|
37769
|
+
const rawItems = JSON.parse(dataJson).filter(
|
|
37770
|
+
(_, index) => index !== -1
|
|
37771
|
+
);
|
|
37334
37772
|
const items = await Promise.all(
|
|
37335
37773
|
rawItems.map(async (item) => {
|
|
37336
37774
|
const date = new Date(item["startDate (format MM/DD/YYYY)"]);
|
|
37337
37775
|
const endDate = new Date(date.setFullYear(date.getFullYear() + 10));
|
|
37338
|
-
const cardNumber = String(
|
|
37339
|
-
|
|
37776
|
+
const cardNumber = String(
|
|
37777
|
+
Number(item["cardNo (number 0-65535 ex. 301)"] || 0)
|
|
37778
|
+
).padStart(6, "0");
|
|
37779
|
+
const facilityCode = String(
|
|
37780
|
+
Number(item["facilityCode (number 0-255 ex. 11)"] || 0)
|
|
37781
|
+
).padStart(4, "0");
|
|
37340
37782
|
const pin = item["pin (number 6 digits only)"] ? item["pin (number 6 digits only)"].toString().padStart(6, "0") : "123456";
|
|
37341
37783
|
const match = item["accessLevel (number ex. 1)"];
|
|
37342
37784
|
const accessLevel = match ? match : null;
|
|
@@ -37367,7 +37809,10 @@ function UseAccessManagementRepo() {
|
|
|
37367
37809
|
});
|
|
37368
37810
|
})
|
|
37369
37811
|
);
|
|
37370
|
-
const result = await collection().insertMany(items, {
|
|
37812
|
+
const result = await collection().insertMany(items, {
|
|
37813
|
+
session,
|
|
37814
|
+
ordered: false
|
|
37815
|
+
});
|
|
37371
37816
|
const mapping = items.map((item, i) => ({
|
|
37372
37817
|
cardNo: item.cardNo,
|
|
37373
37818
|
insertedId: result.insertedIds[i]
|
|
@@ -37382,8 +37827,19 @@ function UseAccessManagementRepo() {
|
|
|
37382
37827
|
let isAborted = false;
|
|
37383
37828
|
try {
|
|
37384
37829
|
await session?.startTransaction();
|
|
37385
|
-
const {
|
|
37386
|
-
|
|
37830
|
+
const {
|
|
37831
|
+
units,
|
|
37832
|
+
quantity,
|
|
37833
|
+
type,
|
|
37834
|
+
site,
|
|
37835
|
+
userType,
|
|
37836
|
+
accessLevel,
|
|
37837
|
+
liftAccessLevel
|
|
37838
|
+
} = params;
|
|
37839
|
+
const [convertedUnits, convertedSite] = await Promise.all([
|
|
37840
|
+
Promise.all(units.map((id) => new ObjectId90(id))),
|
|
37841
|
+
new ObjectId90(site)
|
|
37842
|
+
]);
|
|
37387
37843
|
const totalRequired = quantity * convertedUnits.length;
|
|
37388
37844
|
const availableCards = await collection().find({
|
|
37389
37845
|
assignedUnit: null,
|
|
@@ -37403,16 +37859,18 @@ function UseAccessManagementRepo() {
|
|
|
37403
37859
|
message: `Insufficient ${type} access cards. Need ${totalRequired}, but only ${availableCards.length} available.`
|
|
37404
37860
|
};
|
|
37405
37861
|
}
|
|
37406
|
-
const bulkUpdates = availableCards.map(
|
|
37407
|
-
|
|
37408
|
-
|
|
37409
|
-
|
|
37410
|
-
|
|
37411
|
-
|
|
37862
|
+
const bulkUpdates = availableCards.map(
|
|
37863
|
+
(card, index) => ({
|
|
37864
|
+
updateOne: {
|
|
37865
|
+
filter: { _id: card._id },
|
|
37866
|
+
update: {
|
|
37867
|
+
$set: {
|
|
37868
|
+
assignedUnit: convertedUnits[Math.floor(index / quantity)]
|
|
37869
|
+
}
|
|
37412
37870
|
}
|
|
37413
37871
|
}
|
|
37414
|
-
}
|
|
37415
|
-
|
|
37872
|
+
})
|
|
37873
|
+
);
|
|
37416
37874
|
await collection().bulkWrite(bulkUpdates, { session });
|
|
37417
37875
|
await session?.commitTransaction();
|
|
37418
37876
|
return {
|
|
@@ -37433,7 +37891,18 @@ function UseAccessManagementRepo() {
|
|
|
37433
37891
|
try {
|
|
37434
37892
|
const { cardId, remarks } = params;
|
|
37435
37893
|
const id = new ObjectId90(cardId);
|
|
37436
|
-
const result = await collection().findOneAndUpdate(
|
|
37894
|
+
const result = await collection().findOneAndUpdate(
|
|
37895
|
+
{ _id: id },
|
|
37896
|
+
{
|
|
37897
|
+
$set: {
|
|
37898
|
+
isActivated: false,
|
|
37899
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
37900
|
+
remarks,
|
|
37901
|
+
requestDate: /* @__PURE__ */ new Date()
|
|
37902
|
+
}
|
|
37903
|
+
},
|
|
37904
|
+
{ returnDocument: "after" }
|
|
37905
|
+
);
|
|
37437
37906
|
return result;
|
|
37438
37907
|
} catch (error) {
|
|
37439
37908
|
throw new Error(error.message);
|
|
@@ -37494,7 +37963,13 @@ function UseAccessManagementRepo() {
|
|
|
37494
37963
|
const { site, payload } = params;
|
|
37495
37964
|
const id = new ObjectId90(site);
|
|
37496
37965
|
const highestCardNo = await collection().aggregate([
|
|
37497
|
-
{
|
|
37966
|
+
{
|
|
37967
|
+
$match: {
|
|
37968
|
+
site: id,
|
|
37969
|
+
type: "NFC" /* NFC */,
|
|
37970
|
+
userType: "Visitor/Resident" /* DEFAULT */
|
|
37971
|
+
}
|
|
37972
|
+
},
|
|
37498
37973
|
{
|
|
37499
37974
|
$addFields: {
|
|
37500
37975
|
qrTagCardNoNumeric: { $toInt: "$qrTagCardNo" }
|
|
@@ -37514,14 +37989,19 @@ function UseAccessManagementRepo() {
|
|
|
37514
37989
|
if (highestCardNo.length > 0) {
|
|
37515
37990
|
start = highestCardNo[0].qrTagCardNoNumeric || 0;
|
|
37516
37991
|
}
|
|
37517
|
-
const nextCardNumbers = Array.from(
|
|
37992
|
+
const nextCardNumbers = Array.from(
|
|
37993
|
+
{ length: payload.length },
|
|
37994
|
+
(_, i) => String(start + i + 1).padStart(5, "0")
|
|
37995
|
+
);
|
|
37518
37996
|
const bulkOps = await Promise.all(
|
|
37519
37997
|
payload.map(async (doc, index) => {
|
|
37520
37998
|
const id2 = new ObjectId90(doc._id);
|
|
37521
37999
|
return {
|
|
37522
38000
|
updateOne: {
|
|
37523
38001
|
filter: { _id: id2 },
|
|
37524
|
-
update: {
|
|
38002
|
+
update: {
|
|
38003
|
+
$set: { qrTag: doc.qrTag, qrTagCardNo: nextCardNumbers[index] }
|
|
38004
|
+
}
|
|
37525
38005
|
}
|
|
37526
38006
|
};
|
|
37527
38007
|
})
|
|
@@ -37563,7 +38043,11 @@ function UseAccessManagementRepo() {
|
|
|
37563
38043
|
{
|
|
37564
38044
|
$addFields: {
|
|
37565
38045
|
extractedCardNo: {
|
|
37566
|
-
$substr: [
|
|
38046
|
+
$substr: [
|
|
38047
|
+
"$cardNo",
|
|
38048
|
+
{ $subtract: [{ $strLenCP: "$cardNo" }, 5] },
|
|
38049
|
+
5
|
|
38050
|
+
]
|
|
37567
38051
|
}
|
|
37568
38052
|
}
|
|
37569
38053
|
},
|
|
@@ -37601,7 +38085,11 @@ function UseAccessManagementRepo() {
|
|
|
37601
38085
|
},
|
|
37602
38086
|
{
|
|
37603
38087
|
$facet: {
|
|
37604
|
-
items: [
|
|
38088
|
+
items: [
|
|
38089
|
+
{ $skip: page * limit },
|
|
38090
|
+
{ $limit: limit },
|
|
38091
|
+
{ $project: { cardNo: 1 } }
|
|
38092
|
+
],
|
|
37605
38093
|
totalCounts: [{ $count: "count" }]
|
|
37606
38094
|
}
|
|
37607
38095
|
}
|
|
@@ -37612,7 +38100,9 @@ function UseAccessManagementRepo() {
|
|
|
37612
38100
|
_id: unitId
|
|
37613
38101
|
}
|
|
37614
38102
|
},
|
|
37615
|
-
{
|
|
38103
|
+
{
|
|
38104
|
+
$project: { _id: 1, name: 1, buildingName: 1, block: 1, level: 1 }
|
|
38105
|
+
},
|
|
37616
38106
|
{
|
|
37617
38107
|
$lookup: {
|
|
37618
38108
|
from: "building-levels",
|
|
@@ -37700,7 +38190,18 @@ function UseAccessManagementRepo() {
|
|
|
37700
38190
|
items: [
|
|
37701
38191
|
{ $skip: 0 },
|
|
37702
38192
|
{ $limit: 1 },
|
|
37703
|
-
{
|
|
38193
|
+
{
|
|
38194
|
+
$project: {
|
|
38195
|
+
_id: -1,
|
|
38196
|
+
accessLevel: 1,
|
|
38197
|
+
accessGroup: 1,
|
|
38198
|
+
userType: 1,
|
|
38199
|
+
doorName: 1,
|
|
38200
|
+
liftName: 1,
|
|
38201
|
+
liftAccessLevel: 1,
|
|
38202
|
+
isLiftCard: 1
|
|
38203
|
+
}
|
|
38204
|
+
}
|
|
37704
38205
|
]
|
|
37705
38206
|
}
|
|
37706
38207
|
}
|
|
@@ -37749,13 +38250,25 @@ function UseAccessManagementRepo() {
|
|
|
37749
38250
|
cardsToAttach = [...cardsId];
|
|
37750
38251
|
} else if (type === "NFC" /* NFC */) {
|
|
37751
38252
|
if (nfcCards && nfcCards.length > 0) {
|
|
37752
|
-
const objectIds = nfcCards.map(
|
|
38253
|
+
const objectIds = nfcCards.map(
|
|
38254
|
+
(card) => new ObjectId90(card._id)
|
|
38255
|
+
);
|
|
37753
38256
|
cards = await collection().find({ _id: { $in: objectIds } }).toArray();
|
|
37754
|
-
const nfcList = objectIds.map((card) => ({
|
|
38257
|
+
const nfcList = objectIds.map((card) => ({
|
|
38258
|
+
_id: card,
|
|
38259
|
+
status: "In use",
|
|
38260
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
38261
|
+
}));
|
|
37755
38262
|
cardsToAttach = [...nfcList];
|
|
37756
38263
|
}
|
|
37757
38264
|
}
|
|
37758
|
-
const result = await collectionName(
|
|
38265
|
+
const result = await collectionName(
|
|
38266
|
+
"visitor.transactions"
|
|
38267
|
+
).findOneAndUpdate(
|
|
38268
|
+
{ _id: visitorId },
|
|
38269
|
+
{ $push: { cards: cardsToAttach } },
|
|
38270
|
+
{ session, returnDocument: "after" }
|
|
38271
|
+
);
|
|
37759
38272
|
const updatedVisitor = result?._id;
|
|
37760
38273
|
const assignCards = cards.map((card) => card._id);
|
|
37761
38274
|
if (assignCards.length > 0) {
|
|
@@ -37811,10 +38324,18 @@ function UseAccessManagementRepo() {
|
|
|
37811
38324
|
liftAccessEndDate: formatEntryPassDate(item.liftAccessEndDate) || "19770510",
|
|
37812
38325
|
accessGroup: ag
|
|
37813
38326
|
};
|
|
37814
|
-
return readTemplate(
|
|
38327
|
+
return readTemplate(
|
|
38328
|
+
`${item.accessLevel !== null ? "add-card" : "add-card-lift"}`,
|
|
38329
|
+
{ ...command }
|
|
38330
|
+
);
|
|
37815
38331
|
}).flat();
|
|
37816
|
-
const response = await sendCommand(
|
|
37817
|
-
|
|
38332
|
+
const response = await sendCommand(
|
|
38333
|
+
commands.join("").toString(),
|
|
38334
|
+
acm_url
|
|
38335
|
+
);
|
|
38336
|
+
serverResult = await parseStringPromise2(response, {
|
|
38337
|
+
explicitArray: false
|
|
38338
|
+
});
|
|
37818
38339
|
if (result && serverResult.RESULT.$.STCODE !== "0") {
|
|
37819
38340
|
throw new Error("Command failed, server error.");
|
|
37820
38341
|
}
|
|
@@ -37863,7 +38384,10 @@ function UseAccessManagementRepo() {
|
|
|
37863
38384
|
try {
|
|
37864
38385
|
await session?.startTransaction();
|
|
37865
38386
|
const userId = new ObjectId90(params.userId);
|
|
37866
|
-
const result = await collection().updateMany(
|
|
38387
|
+
const result = await collection().updateMany(
|
|
38388
|
+
{ userId },
|
|
38389
|
+
{ $set: { userId: null, status: "Available", updatedAt: /* @__PURE__ */ new Date() } }
|
|
38390
|
+
);
|
|
37867
38391
|
await session?.commitTransaction();
|
|
37868
38392
|
return result;
|
|
37869
38393
|
} catch (error) {
|
|
@@ -37907,7 +38431,15 @@ function UseAccessManagementRepo() {
|
|
|
37907
38431
|
foreignField: "level",
|
|
37908
38432
|
pipeline: [
|
|
37909
38433
|
{ $match: { status: { $ne: "deleted" } } },
|
|
37910
|
-
{
|
|
38434
|
+
{
|
|
38435
|
+
$project: {
|
|
38436
|
+
_id: 1,
|
|
38437
|
+
name: 1,
|
|
38438
|
+
buildingName: 1,
|
|
38439
|
+
level: 1,
|
|
38440
|
+
block: 1
|
|
38441
|
+
}
|
|
38442
|
+
}
|
|
37911
38443
|
],
|
|
37912
38444
|
as: "units"
|
|
37913
38445
|
}
|
|
@@ -37928,11 +38460,20 @@ function UseAccessManagementRepo() {
|
|
|
37928
38460
|
throw new Error(error.message);
|
|
37929
38461
|
}
|
|
37930
38462
|
}
|
|
37931
|
-
async function getTransactionsRepo({
|
|
38463
|
+
async function getTransactionsRepo({
|
|
38464
|
+
page = 1,
|
|
38465
|
+
limit = 10,
|
|
38466
|
+
site,
|
|
38467
|
+
cardNo,
|
|
38468
|
+
url
|
|
38469
|
+
}) {
|
|
37932
38470
|
page = page ? page - 1 : 0;
|
|
37933
38471
|
site = new ObjectId90(site);
|
|
37934
38472
|
try {
|
|
37935
|
-
let index = await collectionName("access-card-transactions").findOne(
|
|
38473
|
+
let index = await collectionName("access-card-transactions").findOne(
|
|
38474
|
+
{},
|
|
38475
|
+
{ sort: { index: -1 } }
|
|
38476
|
+
);
|
|
37936
38477
|
index = index ? index.index : 0;
|
|
37937
38478
|
const response = await getTransactions(index, url);
|
|
37938
38479
|
if (response && Array.isArray(response.items) && response.items.length > 0) {
|
|
@@ -37941,7 +38482,9 @@ function UseAccessManagementRepo() {
|
|
|
37941
38482
|
data: JSON.parse(item.data),
|
|
37942
38483
|
timestamp: item.timestamp
|
|
37943
38484
|
}));
|
|
37944
|
-
result2 = result2.filter(
|
|
38485
|
+
result2 = result2.filter(
|
|
38486
|
+
(item) => item.data.Event.ETYPE === "0" && item.data.Event.CARDNO !== ""
|
|
38487
|
+
);
|
|
37945
38488
|
if (result2.length > 0) {
|
|
37946
38489
|
const transactions = result2.map(
|
|
37947
38490
|
(item) => new MAccessCardTransaction({
|
|
@@ -37952,11 +38495,16 @@ function UseAccessManagementRepo() {
|
|
|
37952
38495
|
accessType: item.data.Event.DEVNAME,
|
|
37953
38496
|
accessStatus: item.data.Event.TRCODE,
|
|
37954
38497
|
description: item.data.Event.TRDESC,
|
|
37955
|
-
accessTime: entryPassDate(
|
|
38498
|
+
accessTime: entryPassDate(
|
|
38499
|
+
item.data.Event.TRDATE,
|
|
38500
|
+
item.data.Event.TRTIME
|
|
38501
|
+
),
|
|
37956
38502
|
createdAt: /* @__PURE__ */ new Date()
|
|
37957
38503
|
})
|
|
37958
38504
|
);
|
|
37959
|
-
await collectionName("access-card-transactions").insertMany(
|
|
38505
|
+
await collectionName("access-card-transactions").insertMany(
|
|
38506
|
+
transactions
|
|
38507
|
+
);
|
|
37960
38508
|
}
|
|
37961
38509
|
}
|
|
37962
38510
|
const result = await collectionName("access-card-transactions").aggregate([
|
|
@@ -38027,7 +38575,11 @@ function UseAccessManagementRepo() {
|
|
|
38027
38575
|
{
|
|
38028
38576
|
$facet: {
|
|
38029
38577
|
totalCount: [{ $count: "count" }],
|
|
38030
|
-
items: [
|
|
38578
|
+
items: [
|
|
38579
|
+
{ $sort: { _id: -1 } },
|
|
38580
|
+
{ $skip: page * limit },
|
|
38581
|
+
{ $limit: limit }
|
|
38582
|
+
]
|
|
38031
38583
|
}
|
|
38032
38584
|
}
|
|
38033
38585
|
]).toArray();
|
|
@@ -38050,7 +38602,9 @@ function UseAccessManagementRepo() {
|
|
|
38050
38602
|
if (assignees.length < 1) {
|
|
38051
38603
|
throw new Error("No user to Assign.");
|
|
38052
38604
|
}
|
|
38053
|
-
assignees = assignees.map(
|
|
38605
|
+
assignees = assignees.map(
|
|
38606
|
+
(data) => new ObjectId90(data)
|
|
38607
|
+
);
|
|
38054
38608
|
unit = new ObjectId90(unit);
|
|
38055
38609
|
let availableCards = [];
|
|
38056
38610
|
let update = [];
|
|
@@ -38060,7 +38614,18 @@ function UseAccessManagementRepo() {
|
|
|
38060
38614
|
$match: {
|
|
38061
38615
|
$expr: {
|
|
38062
38616
|
$and: [
|
|
38063
|
-
{
|
|
38617
|
+
{
|
|
38618
|
+
$in: [
|
|
38619
|
+
unit,
|
|
38620
|
+
{
|
|
38621
|
+
$cond: [
|
|
38622
|
+
{ $isArray: "$assignedUnit" },
|
|
38623
|
+
"$assignedUnit",
|
|
38624
|
+
["$assignedUnit"]
|
|
38625
|
+
]
|
|
38626
|
+
}
|
|
38627
|
+
]
|
|
38628
|
+
},
|
|
38064
38629
|
{ $eq: ["$userId", null] },
|
|
38065
38630
|
{ $eq: ["$type", type] },
|
|
38066
38631
|
{ $eq: ["$isActivated", true] }
|
|
@@ -38077,7 +38642,10 @@ function UseAccessManagementRepo() {
|
|
|
38077
38642
|
card.staffNo = userId.toString().slice(-10);
|
|
38078
38643
|
return card;
|
|
38079
38644
|
});
|
|
38080
|
-
update = availableCards.slice(0, assignees.length).map((card, index) => ({
|
|
38645
|
+
update = availableCards.slice(0, assignees.length).map((card, index) => ({
|
|
38646
|
+
_id: card._id,
|
|
38647
|
+
userId: new ObjectId90(assignees[index])
|
|
38648
|
+
}));
|
|
38081
38649
|
const commands = cards.map((item, index) => {
|
|
38082
38650
|
let ag = null;
|
|
38083
38651
|
if (item.accessGroup !== void 0) {
|
|
@@ -38107,16 +38675,27 @@ function UseAccessManagementRepo() {
|
|
|
38107
38675
|
liftAccessEndDate: formatEntryPassDate(item.liftAccessEndDate) || "19770510",
|
|
38108
38676
|
accessGroup: ag
|
|
38109
38677
|
};
|
|
38110
|
-
return readTemplate(
|
|
38678
|
+
return readTemplate(
|
|
38679
|
+
`${item.accessLevel !== null ? "add-card" : "add-card-lift"}`,
|
|
38680
|
+
{ ...command }
|
|
38681
|
+
);
|
|
38111
38682
|
}).flat();
|
|
38112
38683
|
const response = await sendCommand(commands.join("").toString(), acm_url);
|
|
38113
|
-
const result = await parseStringPromise2(response, {
|
|
38684
|
+
const result = await parseStringPromise2(response, {
|
|
38685
|
+
explicitArray: false
|
|
38686
|
+
});
|
|
38114
38687
|
console.log("status code", result.RESULT.$.STCODE);
|
|
38115
38688
|
if (result && result.RESULT.$.STCODE !== "0") {
|
|
38116
38689
|
throw new Error("Command failed, server error.");
|
|
38117
38690
|
}
|
|
38118
38691
|
for (const { _id, userId } of update) {
|
|
38119
|
-
await collection().updateOne(
|
|
38692
|
+
await collection().updateOne(
|
|
38693
|
+
{ _id },
|
|
38694
|
+
{
|
|
38695
|
+
$set: { userId, staffNo: `STAFF-${userId.toString().slice(-10)}` }
|
|
38696
|
+
},
|
|
38697
|
+
{ session }
|
|
38698
|
+
);
|
|
38120
38699
|
}
|
|
38121
38700
|
await session?.commitTransaction();
|
|
38122
38701
|
return "Cards assigned successfully.";
|
|
@@ -38132,7 +38711,11 @@ function UseAccessManagementRepo() {
|
|
|
38132
38711
|
try {
|
|
38133
38712
|
session?.startTransaction();
|
|
38134
38713
|
const id = new ObjectId90(userId);
|
|
38135
|
-
await collection().updateMany(
|
|
38714
|
+
await collection().updateMany(
|
|
38715
|
+
{ userId: id },
|
|
38716
|
+
{ $set: { userId: null, status: "Available" } },
|
|
38717
|
+
{ session }
|
|
38718
|
+
);
|
|
38136
38719
|
session?.commitTransaction();
|
|
38137
38720
|
return "Successful Checkout";
|
|
38138
38721
|
} catch (error) {
|
|
@@ -38142,7 +38725,11 @@ function UseAccessManagementRepo() {
|
|
|
38142
38725
|
await session?.endSession();
|
|
38143
38726
|
}
|
|
38144
38727
|
}
|
|
38145
|
-
async function uploadTemplateRepo({
|
|
38728
|
+
async function uploadTemplateRepo({
|
|
38729
|
+
site,
|
|
38730
|
+
id,
|
|
38731
|
+
name
|
|
38732
|
+
}) {
|
|
38146
38733
|
site = new ObjectId90(site);
|
|
38147
38734
|
id = new ObjectId90(id);
|
|
38148
38735
|
try {
|
|
@@ -38155,6 +38742,46 @@ function UseAccessManagementRepo() {
|
|
|
38155
38742
|
throw new Error(error.message);
|
|
38156
38743
|
}
|
|
38157
38744
|
}
|
|
38745
|
+
async function getResidentsRepo({
|
|
38746
|
+
orgId,
|
|
38747
|
+
siteId,
|
|
38748
|
+
unitId
|
|
38749
|
+
}) {
|
|
38750
|
+
try {
|
|
38751
|
+
orgId = new ObjectId90(orgId);
|
|
38752
|
+
siteId = new ObjectId90(siteId);
|
|
38753
|
+
unitId = new ObjectId90(unitId);
|
|
38754
|
+
const result = await collectionName("users").aggregate([
|
|
38755
|
+
{
|
|
38756
|
+
$match: {
|
|
38757
|
+
$expr: {
|
|
38758
|
+
$and: [
|
|
38759
|
+
{ $eq: ["$defaultOrg", orgId] },
|
|
38760
|
+
{ $eq: ["$site", siteId] },
|
|
38761
|
+
{ $eq: ["$unitId", unitId] }
|
|
38762
|
+
]
|
|
38763
|
+
}
|
|
38764
|
+
}
|
|
38765
|
+
},
|
|
38766
|
+
{
|
|
38767
|
+
$project: {
|
|
38768
|
+
_id: 1,
|
|
38769
|
+
email: 1,
|
|
38770
|
+
unitName: 1,
|
|
38771
|
+
type: 1,
|
|
38772
|
+
status: 1,
|
|
38773
|
+
name: 1,
|
|
38774
|
+
defaultOrg: 1,
|
|
38775
|
+
site: 1,
|
|
38776
|
+
unitId: 1
|
|
38777
|
+
}
|
|
38778
|
+
}
|
|
38779
|
+
]).toArray();
|
|
38780
|
+
return result;
|
|
38781
|
+
} catch (error) {
|
|
38782
|
+
throw new Error(error.message);
|
|
38783
|
+
}
|
|
38784
|
+
}
|
|
38158
38785
|
return {
|
|
38159
38786
|
createIndexes,
|
|
38160
38787
|
createIndexForEntrypass,
|
|
@@ -38190,7 +38817,8 @@ function UseAccessManagementRepo() {
|
|
|
38190
38817
|
getTransactionsRepo,
|
|
38191
38818
|
assignMultipleCardsRepo,
|
|
38192
38819
|
visitorCheckoutRepo,
|
|
38193
|
-
uploadTemplateRepo
|
|
38820
|
+
uploadTemplateRepo,
|
|
38821
|
+
getResidentsRepo
|
|
38194
38822
|
};
|
|
38195
38823
|
}
|
|
38196
38824
|
|
|
@@ -38234,7 +38862,8 @@ function useAccessManagementSvc() {
|
|
|
38234
38862
|
getTransactionsRepo,
|
|
38235
38863
|
assignMultipleCardsRepo,
|
|
38236
38864
|
visitorCheckoutRepo,
|
|
38237
|
-
uploadTemplateRepo
|
|
38865
|
+
uploadTemplateRepo,
|
|
38866
|
+
getResidentsRepo
|
|
38238
38867
|
} = UseAccessManagementRepo();
|
|
38239
38868
|
const addPhysicalCardSvc = async (payload) => {
|
|
38240
38869
|
try {
|
|
@@ -38526,17 +39155,39 @@ function useAccessManagementSvc() {
|
|
|
38526
39155
|
throw new Error(err.message);
|
|
38527
39156
|
}
|
|
38528
39157
|
};
|
|
38529
|
-
const getTransactionsSvc = async ({
|
|
39158
|
+
const getTransactionsSvc = async ({
|
|
39159
|
+
page,
|
|
39160
|
+
limit,
|
|
39161
|
+
site,
|
|
39162
|
+
cardNo,
|
|
39163
|
+
url
|
|
39164
|
+
}) => {
|
|
38530
39165
|
try {
|
|
38531
|
-
const response = await getTransactionsRepo({
|
|
39166
|
+
const response = await getTransactionsRepo({
|
|
39167
|
+
page,
|
|
39168
|
+
limit,
|
|
39169
|
+
site,
|
|
39170
|
+
cardNo,
|
|
39171
|
+
url
|
|
39172
|
+
});
|
|
38532
39173
|
return response;
|
|
38533
39174
|
} catch (err) {
|
|
38534
39175
|
throw new Error(err.message);
|
|
38535
39176
|
}
|
|
38536
39177
|
};
|
|
38537
|
-
const assignMultipleCardsSvc = async ({
|
|
39178
|
+
const assignMultipleCardsSvc = async ({
|
|
39179
|
+
assignees,
|
|
39180
|
+
unit,
|
|
39181
|
+
type,
|
|
39182
|
+
acm_url
|
|
39183
|
+
}) => {
|
|
38538
39184
|
try {
|
|
38539
|
-
const response = await assignMultipleCardsRepo({
|
|
39185
|
+
const response = await assignMultipleCardsRepo({
|
|
39186
|
+
assignees,
|
|
39187
|
+
unit,
|
|
39188
|
+
type,
|
|
39189
|
+
acm_url
|
|
39190
|
+
});
|
|
38540
39191
|
return response;
|
|
38541
39192
|
} catch (err) {
|
|
38542
39193
|
throw new Error(err.message);
|
|
@@ -38550,7 +39201,11 @@ function useAccessManagementSvc() {
|
|
|
38550
39201
|
throw new Error(err.message);
|
|
38551
39202
|
}
|
|
38552
39203
|
};
|
|
38553
|
-
const uploadTemplateSvc = async ({
|
|
39204
|
+
const uploadTemplateSvc = async ({
|
|
39205
|
+
site,
|
|
39206
|
+
id,
|
|
39207
|
+
name
|
|
39208
|
+
}) => {
|
|
38554
39209
|
try {
|
|
38555
39210
|
const response = await uploadTemplateRepo({ site, id, name });
|
|
38556
39211
|
return response;
|
|
@@ -38558,6 +39213,18 @@ function useAccessManagementSvc() {
|
|
|
38558
39213
|
throw new Error(err.message);
|
|
38559
39214
|
}
|
|
38560
39215
|
};
|
|
39216
|
+
const getResidentsSvc = async ({
|
|
39217
|
+
orgId,
|
|
39218
|
+
siteId,
|
|
39219
|
+
unitId
|
|
39220
|
+
}) => {
|
|
39221
|
+
try {
|
|
39222
|
+
const response = await getResidentsRepo({ orgId, siteId, unitId });
|
|
39223
|
+
return response;
|
|
39224
|
+
} catch (err) {
|
|
39225
|
+
throw new Error(err.message);
|
|
39226
|
+
}
|
|
39227
|
+
};
|
|
38561
39228
|
return {
|
|
38562
39229
|
addPhysicalCardSvc,
|
|
38563
39230
|
addNonPhysicalCardSvc,
|
|
@@ -38596,7 +39263,8 @@ function useAccessManagementSvc() {
|
|
|
38596
39263
|
getTransactionsSvc,
|
|
38597
39264
|
assignMultipleCardsSvc,
|
|
38598
39265
|
visitorCheckoutSvc,
|
|
38599
|
-
uploadTemplateSvc
|
|
39266
|
+
uploadTemplateSvc,
|
|
39267
|
+
getResidentsSvc
|
|
38600
39268
|
};
|
|
38601
39269
|
}
|
|
38602
39270
|
|
|
@@ -38640,7 +39308,8 @@ function useAccessManagementController() {
|
|
|
38640
39308
|
getTransactionsSvc,
|
|
38641
39309
|
assignMultipleCardsSvc,
|
|
38642
39310
|
visitorCheckoutSvc,
|
|
38643
|
-
uploadTemplateSvc
|
|
39311
|
+
uploadTemplateSvc,
|
|
39312
|
+
getResidentsSvc
|
|
38644
39313
|
} = useAccessManagementSvc();
|
|
38645
39314
|
const addPhysicalCard = async (req, res) => {
|
|
38646
39315
|
try {
|
|
@@ -38889,11 +39558,25 @@ function useAccessManagementController() {
|
|
|
38889
39558
|
search: Joi86.string().optional().allow("", null),
|
|
38890
39559
|
userType: Joi86.string().required()
|
|
38891
39560
|
});
|
|
38892
|
-
const { error } = schema2.validate({
|
|
39561
|
+
const { error } = schema2.validate({
|
|
39562
|
+
page,
|
|
39563
|
+
limit,
|
|
39564
|
+
site,
|
|
39565
|
+
organization,
|
|
39566
|
+
search,
|
|
39567
|
+
userType
|
|
39568
|
+
});
|
|
38893
39569
|
if (error) {
|
|
38894
39570
|
return res.status(400).json({ message: error.message });
|
|
38895
39571
|
}
|
|
38896
|
-
const result = await userTypeAccessCardsSvc({
|
|
39572
|
+
const result = await userTypeAccessCardsSvc({
|
|
39573
|
+
page,
|
|
39574
|
+
limit,
|
|
39575
|
+
search,
|
|
39576
|
+
site,
|
|
39577
|
+
organization,
|
|
39578
|
+
userType
|
|
39579
|
+
});
|
|
38897
39580
|
return res.status(200).json({ message: "Success", data: result });
|
|
38898
39581
|
} catch (error) {
|
|
38899
39582
|
return res.status(500).json({
|
|
@@ -38904,7 +39587,12 @@ function useAccessManagementController() {
|
|
|
38904
39587
|
};
|
|
38905
39588
|
const assignedAccessCards = async (req, res) => {
|
|
38906
39589
|
try {
|
|
38907
|
-
const {
|
|
39590
|
+
const {
|
|
39591
|
+
site,
|
|
39592
|
+
userType,
|
|
39593
|
+
type,
|
|
39594
|
+
search = ""
|
|
39595
|
+
} = req.query;
|
|
38908
39596
|
const schema2 = Joi86.object({
|
|
38909
39597
|
site: Joi86.string().hex().required(),
|
|
38910
39598
|
userType: Joi86.string().required(),
|
|
@@ -38915,7 +39603,12 @@ function useAccessManagementController() {
|
|
|
38915
39603
|
if (error) {
|
|
38916
39604
|
return res.status(400).json({ message: error.message });
|
|
38917
39605
|
}
|
|
38918
|
-
const result = await assignedAccessCardsSvc({
|
|
39606
|
+
const result = await assignedAccessCardsSvc({
|
|
39607
|
+
site,
|
|
39608
|
+
userType,
|
|
39609
|
+
type,
|
|
39610
|
+
search
|
|
39611
|
+
});
|
|
38919
39612
|
return res.status(200).json({ message: "Success", data: result });
|
|
38920
39613
|
} catch (error) {
|
|
38921
39614
|
return res.status(500).json({
|
|
@@ -38961,11 +39654,23 @@ function useAccessManagementController() {
|
|
|
38961
39654
|
userType: Joi86.string().valid(...Object.values(EAccessCardUserTypes)).required(),
|
|
38962
39655
|
type: Joi86.string().valid(...Object.values(EAccessCardTypes)).required()
|
|
38963
39656
|
});
|
|
38964
|
-
const { error } = schema2.validate({
|
|
39657
|
+
const { error } = schema2.validate({
|
|
39658
|
+
accessLevel,
|
|
39659
|
+
liftAccessLevel,
|
|
39660
|
+
site,
|
|
39661
|
+
userType,
|
|
39662
|
+
type
|
|
39663
|
+
});
|
|
38965
39664
|
if (error) {
|
|
38966
39665
|
return res.status(400).json({ message: error.message });
|
|
38967
39666
|
}
|
|
38968
|
-
const result = await accessandLiftCardsSvc({
|
|
39667
|
+
const result = await accessandLiftCardsSvc({
|
|
39668
|
+
accessLevel,
|
|
39669
|
+
liftAccessLevel,
|
|
39670
|
+
site,
|
|
39671
|
+
userType,
|
|
39672
|
+
type
|
|
39673
|
+
});
|
|
38969
39674
|
return res.status(200).json({ message: "Success", data: result });
|
|
38970
39675
|
} catch (error) {
|
|
38971
39676
|
return res.status(500).json({
|
|
@@ -39052,11 +39757,23 @@ function useAccessManagementController() {
|
|
|
39052
39757
|
issuedCardId: Joi86.string().required(),
|
|
39053
39758
|
userId: Joi86.string().hex().required()
|
|
39054
39759
|
});
|
|
39055
|
-
const { error } = schema2.validate({
|
|
39760
|
+
const { error } = schema2.validate({
|
|
39761
|
+
cardId,
|
|
39762
|
+
remarks,
|
|
39763
|
+
unitId,
|
|
39764
|
+
issuedCardId,
|
|
39765
|
+
userId
|
|
39766
|
+
});
|
|
39056
39767
|
if (error) {
|
|
39057
39768
|
return res.status(400).json({ message: error.message });
|
|
39058
39769
|
}
|
|
39059
|
-
const result = await cardReplacementSvc({
|
|
39770
|
+
const result = await cardReplacementSvc({
|
|
39771
|
+
cardId,
|
|
39772
|
+
remarks,
|
|
39773
|
+
unitId,
|
|
39774
|
+
issuedCardId,
|
|
39775
|
+
userId
|
|
39776
|
+
});
|
|
39060
39777
|
return res.status(200).json({ message: "Success", data: result });
|
|
39061
39778
|
} catch (error) {
|
|
39062
39779
|
return res.status(500).json({
|
|
@@ -39085,7 +39802,13 @@ function useAccessManagementController() {
|
|
|
39085
39802
|
if (error) {
|
|
39086
39803
|
return res.status(400).json({ message: error.message });
|
|
39087
39804
|
}
|
|
39088
|
-
const result = await visitorAccessCardsSvc({
|
|
39805
|
+
const result = await visitorAccessCardsSvc({
|
|
39806
|
+
site,
|
|
39807
|
+
page,
|
|
39808
|
+
limit,
|
|
39809
|
+
type,
|
|
39810
|
+
search
|
|
39811
|
+
});
|
|
39089
39812
|
return res.status(200).json({ message: "Success", data: result });
|
|
39090
39813
|
} catch (error) {
|
|
39091
39814
|
return res.status(500).json({
|
|
@@ -39114,11 +39837,27 @@ function useAccessManagementController() {
|
|
|
39114
39837
|
limit: Joi86.number().optional().default(10),
|
|
39115
39838
|
site: Joi86.string().hex().required()
|
|
39116
39839
|
});
|
|
39117
|
-
const { error } = schema2.validate({
|
|
39840
|
+
const { error } = schema2.validate({
|
|
39841
|
+
search,
|
|
39842
|
+
statusFilter,
|
|
39843
|
+
dateFrom,
|
|
39844
|
+
dateTo,
|
|
39845
|
+
page,
|
|
39846
|
+
limit,
|
|
39847
|
+
site
|
|
39848
|
+
});
|
|
39118
39849
|
if (error) {
|
|
39119
39850
|
return res.status(400).json({ message: error.message });
|
|
39120
39851
|
}
|
|
39121
|
-
const result = await getCardReplacementSvc({
|
|
39852
|
+
const result = await getCardReplacementSvc({
|
|
39853
|
+
site,
|
|
39854
|
+
page,
|
|
39855
|
+
limit,
|
|
39856
|
+
search,
|
|
39857
|
+
statusFilter,
|
|
39858
|
+
dateFrom,
|
|
39859
|
+
dateTo
|
|
39860
|
+
});
|
|
39122
39861
|
return res.status(200).json({ message: "Success", data: result });
|
|
39123
39862
|
} catch (error) {
|
|
39124
39863
|
return res.status(500).json({
|
|
@@ -39164,7 +39903,15 @@ function useAccessManagementController() {
|
|
|
39164
39903
|
};
|
|
39165
39904
|
const assignAccessCardToUnit = async (req, res) => {
|
|
39166
39905
|
try {
|
|
39167
|
-
const {
|
|
39906
|
+
const {
|
|
39907
|
+
units,
|
|
39908
|
+
type,
|
|
39909
|
+
quantity,
|
|
39910
|
+
site,
|
|
39911
|
+
userType,
|
|
39912
|
+
accessLevel,
|
|
39913
|
+
liftAccessLevel
|
|
39914
|
+
} = req.body;
|
|
39168
39915
|
const schema2 = Joi86.object({
|
|
39169
39916
|
units: Joi86.array().items(Joi86.string().hex()).required(),
|
|
39170
39917
|
quantity: Joi86.number().required(),
|
|
@@ -39174,11 +39921,27 @@ function useAccessManagementController() {
|
|
|
39174
39921
|
accessLevel: Joi86.string().optional().allow("", null),
|
|
39175
39922
|
liftAccessLevel: Joi86.string().optional().allow("", null)
|
|
39176
39923
|
});
|
|
39177
|
-
const { error } = schema2.validate({
|
|
39924
|
+
const { error } = schema2.validate({
|
|
39925
|
+
units,
|
|
39926
|
+
quantity,
|
|
39927
|
+
type,
|
|
39928
|
+
site,
|
|
39929
|
+
userType,
|
|
39930
|
+
accessLevel,
|
|
39931
|
+
liftAccessLevel
|
|
39932
|
+
});
|
|
39178
39933
|
if (error) {
|
|
39179
39934
|
return res.status(400).json({ message: error.message });
|
|
39180
39935
|
}
|
|
39181
|
-
const result = await assignAccessCardToUnitSvc({
|
|
39936
|
+
const result = await assignAccessCardToUnitSvc({
|
|
39937
|
+
units,
|
|
39938
|
+
quantity,
|
|
39939
|
+
type,
|
|
39940
|
+
site,
|
|
39941
|
+
userType,
|
|
39942
|
+
accessLevel,
|
|
39943
|
+
liftAccessLevel
|
|
39944
|
+
});
|
|
39182
39945
|
return res.status(200).json({ message: "Success", data: result });
|
|
39183
39946
|
} catch (error) {
|
|
39184
39947
|
return res.status(500).json({
|
|
@@ -39276,7 +40039,12 @@ function useAccessManagementController() {
|
|
|
39276
40039
|
};
|
|
39277
40040
|
const availableCardContractors = async (req, res) => {
|
|
39278
40041
|
try {
|
|
39279
|
-
const {
|
|
40042
|
+
const {
|
|
40043
|
+
siteId,
|
|
40044
|
+
unitId,
|
|
40045
|
+
page = 1,
|
|
40046
|
+
limit = 20
|
|
40047
|
+
} = req.query;
|
|
39280
40048
|
const type = req.params.type;
|
|
39281
40049
|
const schema2 = Joi86.object({
|
|
39282
40050
|
siteId: Joi86.string().hex().required(),
|
|
@@ -39289,7 +40057,13 @@ function useAccessManagementController() {
|
|
|
39289
40057
|
if (error) {
|
|
39290
40058
|
return res.status(400).json({ message: error.message });
|
|
39291
40059
|
}
|
|
39292
|
-
const result = await availableCardContractorsSvc({
|
|
40060
|
+
const result = await availableCardContractorsSvc({
|
|
40061
|
+
siteId,
|
|
40062
|
+
unitId,
|
|
40063
|
+
page,
|
|
40064
|
+
limit,
|
|
40065
|
+
type
|
|
40066
|
+
});
|
|
39293
40067
|
return res.status(200).json({ message: "Success", data: result });
|
|
39294
40068
|
} catch (error) {
|
|
39295
40069
|
return res.status(500).json({
|
|
@@ -39300,7 +40074,11 @@ function useAccessManagementController() {
|
|
|
39300
40074
|
};
|
|
39301
40075
|
const vmsgenerateQrCodes = async (req, res) => {
|
|
39302
40076
|
try {
|
|
39303
|
-
const {
|
|
40077
|
+
const {
|
|
40078
|
+
site,
|
|
40079
|
+
unitId,
|
|
40080
|
+
quantity = 100
|
|
40081
|
+
} = req.body;
|
|
39304
40082
|
const schema2 = Joi86.object({
|
|
39305
40083
|
site: Joi86.string().hex().length(24).required(),
|
|
39306
40084
|
unitId: Joi86.string().hex().length(24).required(),
|
|
@@ -39311,7 +40089,12 @@ function useAccessManagementController() {
|
|
|
39311
40089
|
return res.status(400).json({ message: error.message });
|
|
39312
40090
|
}
|
|
39313
40091
|
const normalizedUnitId = [unitId];
|
|
39314
|
-
const result = await vmsgenerateQrCodesSvc({
|
|
40092
|
+
const result = await vmsgenerateQrCodesSvc({
|
|
40093
|
+
site,
|
|
40094
|
+
unitId,
|
|
40095
|
+
normalizedUnitId,
|
|
40096
|
+
quantity
|
|
40097
|
+
});
|
|
39315
40098
|
return res.status(200).json({ message: "Success", data: result });
|
|
39316
40099
|
} catch (error) {
|
|
39317
40100
|
return res.status(500).json({
|
|
@@ -39322,21 +40105,50 @@ function useAccessManagementController() {
|
|
|
39322
40105
|
};
|
|
39323
40106
|
const addVisitorAccessCard = async (req, res) => {
|
|
39324
40107
|
try {
|
|
39325
|
-
const {
|
|
40108
|
+
const {
|
|
40109
|
+
site,
|
|
40110
|
+
unitId,
|
|
40111
|
+
quantity = 1,
|
|
40112
|
+
type,
|
|
40113
|
+
nfcCards,
|
|
40114
|
+
visitorId,
|
|
40115
|
+
acm_url
|
|
40116
|
+
} = req.body;
|
|
39326
40117
|
const schema2 = Joi86.object({
|
|
39327
40118
|
site: Joi86.string().hex().length(24).required(),
|
|
39328
40119
|
unitId: Joi86.string().hex().length(24).required(),
|
|
39329
40120
|
quantity: Joi86.number().allow(null, "").optional(),
|
|
39330
40121
|
type: Joi86.string().required(),
|
|
39331
|
-
nfcCards: Joi86.array().items(
|
|
40122
|
+
nfcCards: Joi86.array().items(
|
|
40123
|
+
Joi86.object({
|
|
40124
|
+
_id: Joi86.string().hex().required(),
|
|
40125
|
+
cardNo: Joi86.string().required()
|
|
40126
|
+
})
|
|
40127
|
+
).required(),
|
|
39332
40128
|
acm_url: Joi86.string().required(),
|
|
39333
40129
|
visitorId: Joi86.string().hex().length(24).required()
|
|
39334
40130
|
});
|
|
39335
|
-
const { error } = schema2.validate({
|
|
40131
|
+
const { error } = schema2.validate({
|
|
40132
|
+
site,
|
|
40133
|
+
unitId,
|
|
40134
|
+
quantity,
|
|
40135
|
+
type,
|
|
40136
|
+
nfcCards,
|
|
40137
|
+
visitorId,
|
|
40138
|
+
acm_url
|
|
40139
|
+
});
|
|
39336
40140
|
if (error) {
|
|
39337
40141
|
return res.status(400).json({ message: error.message });
|
|
39338
40142
|
}
|
|
39339
|
-
const result = await addVisitorAccessCardSvc({
|
|
40143
|
+
const result = await addVisitorAccessCardSvc({
|
|
40144
|
+
site,
|
|
40145
|
+
unitId,
|
|
40146
|
+
quantity,
|
|
40147
|
+
type,
|
|
40148
|
+
nfcCards,
|
|
40149
|
+
visitorId,
|
|
40150
|
+
acm_url
|
|
40151
|
+
});
|
|
39340
40152
|
return res.status(200).json({ message: "Success", data: result });
|
|
39341
40153
|
} catch (error) {
|
|
39342
40154
|
return res.status(500).json({
|
|
@@ -39384,7 +40196,11 @@ function useAccessManagementController() {
|
|
|
39384
40196
|
});
|
|
39385
40197
|
}
|
|
39386
40198
|
};
|
|
39387
|
-
const removeAccessCard = async ({
|
|
40199
|
+
const removeAccessCard = async ({
|
|
40200
|
+
cardNo,
|
|
40201
|
+
staffNo,
|
|
40202
|
+
url
|
|
40203
|
+
}) => {
|
|
39388
40204
|
return removeAccessGroup({ cardNo, staffNo, url });
|
|
39389
40205
|
};
|
|
39390
40206
|
const getBlockLevelAndUnitList = async (req, res) => {
|
|
@@ -39403,7 +40219,13 @@ function useAccessManagementController() {
|
|
|
39403
40219
|
}
|
|
39404
40220
|
};
|
|
39405
40221
|
const getTransactions2 = async (req, res) => {
|
|
39406
|
-
const {
|
|
40222
|
+
const {
|
|
40223
|
+
page = 1,
|
|
40224
|
+
limit = 10,
|
|
40225
|
+
site,
|
|
40226
|
+
cardNo,
|
|
40227
|
+
url
|
|
40228
|
+
} = req.query;
|
|
39407
40229
|
const schema2 = Joi86.object({
|
|
39408
40230
|
page: Joi86.number().required(),
|
|
39409
40231
|
limit: Joi86.number().optional().default(10),
|
|
@@ -39442,7 +40264,12 @@ function useAccessManagementController() {
|
|
|
39442
40264
|
if (error) {
|
|
39443
40265
|
throw new Error(`${error.message}`);
|
|
39444
40266
|
}
|
|
39445
|
-
const result = await assignMultipleCardsSvc({
|
|
40267
|
+
const result = await assignMultipleCardsSvc({
|
|
40268
|
+
assignees,
|
|
40269
|
+
unit,
|
|
40270
|
+
type,
|
|
40271
|
+
acm_url
|
|
40272
|
+
});
|
|
39446
40273
|
return res.status(200).json({ message: "Success", data: result });
|
|
39447
40274
|
} catch (error) {
|
|
39448
40275
|
return res.status(400).json({
|
|
@@ -39485,6 +40312,27 @@ function useAccessManagementController() {
|
|
|
39485
40312
|
});
|
|
39486
40313
|
}
|
|
39487
40314
|
};
|
|
40315
|
+
const getResidents = async (req, res) => {
|
|
40316
|
+
try {
|
|
40317
|
+
const { orgId, siteId, unitId } = req.query;
|
|
40318
|
+
const schema2 = Joi86.object({
|
|
40319
|
+
orgId: Joi86.string().hex().required(),
|
|
40320
|
+
siteId: Joi86.string().hex().required(),
|
|
40321
|
+
unitId: Joi86.string().hex().required()
|
|
40322
|
+
});
|
|
40323
|
+
const { error } = schema2.validate({ orgId, siteId, unitId });
|
|
40324
|
+
if (error) {
|
|
40325
|
+
return res.status(400).json({ message: error.message });
|
|
40326
|
+
}
|
|
40327
|
+
const result = await getResidentsSvc({ orgId, siteId, unitId });
|
|
40328
|
+
return res.status(200).json({ data: result });
|
|
40329
|
+
} catch (error) {
|
|
40330
|
+
return res.status(400).json({
|
|
40331
|
+
data: null,
|
|
40332
|
+
message: error.message
|
|
40333
|
+
});
|
|
40334
|
+
}
|
|
40335
|
+
};
|
|
39488
40336
|
return {
|
|
39489
40337
|
addPhysicalCard,
|
|
39490
40338
|
addNonPhysicalCard,
|
|
@@ -39521,7 +40369,8 @@ function useAccessManagementController() {
|
|
|
39521
40369
|
getTransactions: getTransactions2,
|
|
39522
40370
|
assignMultipleCards,
|
|
39523
40371
|
visitorCheckout,
|
|
39524
|
-
uploadTemplate
|
|
40372
|
+
uploadTemplate,
|
|
40373
|
+
getResidents
|
|
39525
40374
|
};
|
|
39526
40375
|
}
|
|
39527
40376
|
|
|
@@ -53714,6 +54563,7 @@ import Joi132 from "joi";
|
|
|
53714
54563
|
import { ObjectId as ObjectId129 } from "mongodb";
|
|
53715
54564
|
var PostStatus = /* @__PURE__ */ ((PostStatus2) => {
|
|
53716
54565
|
PostStatus2["PUBLISHED"] = "published";
|
|
54566
|
+
PostStatus2["RESERVED"] = "reserved";
|
|
53717
54567
|
PostStatus2["SOLD"] = "sold";
|
|
53718
54568
|
PostStatus2["DELETED"] = "deleted";
|
|
53719
54569
|
return PostStatus2;
|
|
@@ -53746,6 +54596,17 @@ var schemaPost = Joi132.object({
|
|
|
53746
54596
|
updatedAt: Joi132.date().optional().allow(null),
|
|
53747
54597
|
deletedAt: Joi132.date().optional().allow(null)
|
|
53748
54598
|
});
|
|
54599
|
+
var schemaUpdatePost = Joi132.object({
|
|
54600
|
+
_id: Joi132.string().hex().required(),
|
|
54601
|
+
title: Joi132.string().optional().allow("", null),
|
|
54602
|
+
description: Joi132.string().optional().allow("", null),
|
|
54603
|
+
attachments: Joi132.array().items(Joi132.string().hex().optional()).optional().allow(null),
|
|
54604
|
+
category: Joi132.array().items(Joi132.string().hex().optional()).optional().allow(null),
|
|
54605
|
+
currency: Joi132.string().optional().allow("", null),
|
|
54606
|
+
price: Joi132.number().optional(),
|
|
54607
|
+
status: Joi132.string().valid(...Object.values(PostStatus)).optional().allow(null),
|
|
54608
|
+
reserverId: Joi132.string().hex().optional().allow("", null)
|
|
54609
|
+
});
|
|
53749
54610
|
function MPost(value) {
|
|
53750
54611
|
const { error } = schemaPost.validate(value);
|
|
53751
54612
|
if (error) {
|
|
@@ -53969,10 +54830,79 @@ function usePostPrelovedRepo() {
|
|
|
53969
54830
|
throw error;
|
|
53970
54831
|
}
|
|
53971
54832
|
}
|
|
54833
|
+
async function updateById(_id, value, session) {
|
|
54834
|
+
try {
|
|
54835
|
+
_id = new ObjectId130(_id);
|
|
54836
|
+
} catch {
|
|
54837
|
+
throw new BadRequestError210("Invalid post ID format.");
|
|
54838
|
+
}
|
|
54839
|
+
value.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
54840
|
+
try {
|
|
54841
|
+
const res = await collection.updateOne(
|
|
54842
|
+
{ _id },
|
|
54843
|
+
{ $set: value },
|
|
54844
|
+
{ session }
|
|
54845
|
+
);
|
|
54846
|
+
if (res.modifiedCount === 0) {
|
|
54847
|
+
throw new InternalServerError74("Unable to update post.");
|
|
54848
|
+
}
|
|
54849
|
+
return res;
|
|
54850
|
+
} catch (error) {
|
|
54851
|
+
throw error;
|
|
54852
|
+
}
|
|
54853
|
+
}
|
|
54854
|
+
async function deleteById(_id, session) {
|
|
54855
|
+
try {
|
|
54856
|
+
_id = new ObjectId130(_id);
|
|
54857
|
+
} catch {
|
|
54858
|
+
throw new BadRequestError210("Invalid post ID format.");
|
|
54859
|
+
}
|
|
54860
|
+
try {
|
|
54861
|
+
const res = await collection.updateOne(
|
|
54862
|
+
{ _id },
|
|
54863
|
+
{
|
|
54864
|
+
$set: {
|
|
54865
|
+
status: "deleted" /* DELETED */,
|
|
54866
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
54867
|
+
deletedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
54868
|
+
}
|
|
54869
|
+
},
|
|
54870
|
+
{ session }
|
|
54871
|
+
);
|
|
54872
|
+
if (res.modifiedCount === 0) {
|
|
54873
|
+
throw new InternalServerError74("Unable to delete post.");
|
|
54874
|
+
}
|
|
54875
|
+
return res.modifiedCount;
|
|
54876
|
+
} catch (error) {
|
|
54877
|
+
throw error;
|
|
54878
|
+
}
|
|
54879
|
+
}
|
|
54880
|
+
async function updateStatus(_id, status, session) {
|
|
54881
|
+
try {
|
|
54882
|
+
_id = new ObjectId130(_id);
|
|
54883
|
+
} catch {
|
|
54884
|
+
throw new BadRequestError210("Invalid post ID format.");
|
|
54885
|
+
}
|
|
54886
|
+
try {
|
|
54887
|
+
const res = await collection.updateOne(
|
|
54888
|
+
{ _id },
|
|
54889
|
+
{ $set: { status, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
|
|
54890
|
+
{ session }
|
|
54891
|
+
);
|
|
54892
|
+
if (res.modifiedCount === 0)
|
|
54893
|
+
throw new InternalServerError74("Unable to update post status.");
|
|
54894
|
+
return res;
|
|
54895
|
+
} catch (error) {
|
|
54896
|
+
throw error;
|
|
54897
|
+
}
|
|
54898
|
+
}
|
|
53972
54899
|
return {
|
|
53973
54900
|
add,
|
|
53974
54901
|
getById,
|
|
53975
|
-
getAll
|
|
54902
|
+
getAll,
|
|
54903
|
+
updateById,
|
|
54904
|
+
deleteById,
|
|
54905
|
+
updateStatus
|
|
53976
54906
|
};
|
|
53977
54907
|
}
|
|
53978
54908
|
|
|
@@ -53983,7 +54913,10 @@ function usePostPrelovedController() {
|
|
|
53983
54913
|
const {
|
|
53984
54914
|
add: _add,
|
|
53985
54915
|
getById: _getById,
|
|
53986
|
-
getAll: _getAll
|
|
54916
|
+
getAll: _getAll,
|
|
54917
|
+
updateById: _updateById,
|
|
54918
|
+
deleteById: _deleteById,
|
|
54919
|
+
updateStatus: _updateStatus
|
|
53987
54920
|
} = usePostPrelovedRepo();
|
|
53988
54921
|
async function add(req, res, next) {
|
|
53989
54922
|
const { error, value } = schemaPost.validate(req.body, {
|
|
@@ -54066,10 +54999,286 @@ function usePostPrelovedController() {
|
|
|
54066
54999
|
return;
|
|
54067
55000
|
}
|
|
54068
55001
|
}
|
|
55002
|
+
async function updateById(req, res, next) {
|
|
55003
|
+
const _id = req.params.id;
|
|
55004
|
+
const payload = { _id, ...req.body };
|
|
55005
|
+
const { error } = schemaUpdatePost.validate(payload, {
|
|
55006
|
+
abortEarly: false
|
|
55007
|
+
});
|
|
55008
|
+
if (error) {
|
|
55009
|
+
const messages = error.details.map((d) => d.message).join(", ");
|
|
55010
|
+
logger186.log({ level: "error", message: messages });
|
|
55011
|
+
next(new BadRequestError211(messages));
|
|
55012
|
+
return;
|
|
55013
|
+
}
|
|
55014
|
+
try {
|
|
55015
|
+
const data = await _updateById(_id, req.body);
|
|
55016
|
+
res.status(200).json(data);
|
|
55017
|
+
return;
|
|
55018
|
+
} catch (error2) {
|
|
55019
|
+
logger186.log({ level: "error", message: error2.message });
|
|
55020
|
+
next(error2);
|
|
55021
|
+
return;
|
|
55022
|
+
}
|
|
55023
|
+
}
|
|
55024
|
+
async function deleteById(req, res, next) {
|
|
55025
|
+
const schema2 = Joi133.object({
|
|
55026
|
+
_id: Joi133.string().hex().length(24).required()
|
|
55027
|
+
});
|
|
55028
|
+
const { error, value } = schema2.validate({ _id: req.params.id });
|
|
55029
|
+
if (error) {
|
|
55030
|
+
logger186.log({ level: "error", message: error.message });
|
|
55031
|
+
next(new BadRequestError211(error.message));
|
|
55032
|
+
return;
|
|
55033
|
+
}
|
|
55034
|
+
try {
|
|
55035
|
+
const data = await _deleteById(value._id);
|
|
55036
|
+
res.status(200).json({ message: "Successfully deleted post." });
|
|
55037
|
+
return;
|
|
55038
|
+
} catch (error2) {
|
|
55039
|
+
logger186.log({ level: "error", message: error2.message });
|
|
55040
|
+
next(error2);
|
|
55041
|
+
return;
|
|
55042
|
+
}
|
|
55043
|
+
}
|
|
55044
|
+
async function updateStatus(req, res, next) {
|
|
55045
|
+
const schema2 = Joi133.object({
|
|
55046
|
+
_id: Joi133.string().hex().length(24).required(),
|
|
55047
|
+
status: Joi133.string().valid(...Object.values(PostStatus)).required()
|
|
55048
|
+
});
|
|
55049
|
+
const { error, value } = schema2.validate({
|
|
55050
|
+
_id: req.params.id,
|
|
55051
|
+
status: req.body.status
|
|
55052
|
+
});
|
|
55053
|
+
if (error) {
|
|
55054
|
+
logger186.log({ level: "error", message: error.message });
|
|
55055
|
+
next(new BadRequestError211(error.message));
|
|
55056
|
+
return;
|
|
55057
|
+
}
|
|
55058
|
+
try {
|
|
55059
|
+
const data = await _updateStatus(value._id, value.status);
|
|
55060
|
+
res.status(200).json(data);
|
|
55061
|
+
return;
|
|
55062
|
+
} catch (error2) {
|
|
55063
|
+
logger186.log({ level: "error", message: error2.message });
|
|
55064
|
+
next(error2);
|
|
55065
|
+
return;
|
|
55066
|
+
}
|
|
55067
|
+
}
|
|
54069
55068
|
return {
|
|
54070
55069
|
add,
|
|
54071
55070
|
getById,
|
|
54072
|
-
getAll
|
|
55071
|
+
getAll,
|
|
55072
|
+
updateById,
|
|
55073
|
+
deleteById,
|
|
55074
|
+
updateStatus
|
|
55075
|
+
};
|
|
55076
|
+
}
|
|
55077
|
+
|
|
55078
|
+
// src/models/online-forms-v2.model.ts
|
|
55079
|
+
import Joi134 from "joi";
|
|
55080
|
+
import { ObjectId as ObjectId131 } from "mongodb";
|
|
55081
|
+
var FormEntryStatus = /* @__PURE__ */ ((FormEntryStatus2) => {
|
|
55082
|
+
FormEntryStatus2["ACTIVE"] = "active";
|
|
55083
|
+
FormEntryStatus2["INACTIVE"] = "inactive";
|
|
55084
|
+
FormEntryStatus2["DELETED"] = "deleted";
|
|
55085
|
+
return FormEntryStatus2;
|
|
55086
|
+
})(FormEntryStatus || {});
|
|
55087
|
+
var schemaFormEntry = Joi134.object({
|
|
55088
|
+
_id: Joi134.string().hex().optional().allow("", null),
|
|
55089
|
+
formType: Joi134.string().required(),
|
|
55090
|
+
fields: Joi134.object().pattern(
|
|
55091
|
+
Joi134.string(),
|
|
55092
|
+
Joi134.alternatives().try(
|
|
55093
|
+
Joi134.string(),
|
|
55094
|
+
Joi134.number(),
|
|
55095
|
+
Joi134.boolean(),
|
|
55096
|
+
Joi134.valid(null)
|
|
55097
|
+
)
|
|
55098
|
+
).required(),
|
|
55099
|
+
status: Joi134.string().optional().allow("", null),
|
|
55100
|
+
org: Joi134.string().hex().optional().allow("", null),
|
|
55101
|
+
site: Joi134.string().hex().optional().allow("", null),
|
|
55102
|
+
createdAt: Joi134.date().optional().allow("", null),
|
|
55103
|
+
updatedAt: Joi134.date().optional().allow("", null),
|
|
55104
|
+
deletedAt: Joi134.date().optional().allow("", null)
|
|
55105
|
+
});
|
|
55106
|
+
var schemaUpdateFormEntry = Joi134.object({
|
|
55107
|
+
_id: Joi134.string().hex().required(),
|
|
55108
|
+
formType: Joi134.string().optional().allow("", null),
|
|
55109
|
+
fields: Joi134.object().pattern(
|
|
55110
|
+
Joi134.string(),
|
|
55111
|
+
Joi134.alternatives().try(
|
|
55112
|
+
Joi134.string(),
|
|
55113
|
+
Joi134.number(),
|
|
55114
|
+
Joi134.boolean(),
|
|
55115
|
+
Joi134.valid(null)
|
|
55116
|
+
)
|
|
55117
|
+
).optional(),
|
|
55118
|
+
status: Joi134.string().optional().allow("", null),
|
|
55119
|
+
createdAt: Joi134.date().optional().allow("", null),
|
|
55120
|
+
updatedAt: Joi134.date().optional().allow("", null),
|
|
55121
|
+
deletedAt: Joi134.date().optional().allow("", null)
|
|
55122
|
+
});
|
|
55123
|
+
function MFormEntry(value) {
|
|
55124
|
+
const { error } = schemaFormEntry.validate(value);
|
|
55125
|
+
if (error) {
|
|
55126
|
+
throw new Error(error.details[0].message);
|
|
55127
|
+
}
|
|
55128
|
+
if (value._id && typeof value._id === "string") {
|
|
55129
|
+
try {
|
|
55130
|
+
value._id = new ObjectId131(value._id);
|
|
55131
|
+
} catch {
|
|
55132
|
+
throw new Error("Invalid ID.");
|
|
55133
|
+
}
|
|
55134
|
+
}
|
|
55135
|
+
if (value.org && typeof value.org === "string") {
|
|
55136
|
+
try {
|
|
55137
|
+
value.org = new ObjectId131(value.org);
|
|
55138
|
+
} catch {
|
|
55139
|
+
throw new Error("Invalid org ID.");
|
|
55140
|
+
}
|
|
55141
|
+
}
|
|
55142
|
+
if (value.site && typeof value.site === "string") {
|
|
55143
|
+
try {
|
|
55144
|
+
value.site = new ObjectId131(value.site);
|
|
55145
|
+
} catch {
|
|
55146
|
+
throw new Error("Invalid site ID.");
|
|
55147
|
+
}
|
|
55148
|
+
}
|
|
55149
|
+
return {
|
|
55150
|
+
_id: value._id,
|
|
55151
|
+
formType: value.formType,
|
|
55152
|
+
fields: value.fields,
|
|
55153
|
+
status: value.status,
|
|
55154
|
+
org: value.org,
|
|
55155
|
+
site: value.site,
|
|
55156
|
+
createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
|
|
55157
|
+
updatedAt: value.updatedAt ?? null,
|
|
55158
|
+
deletedAt: value.deletedAt ?? null
|
|
55159
|
+
};
|
|
55160
|
+
}
|
|
55161
|
+
|
|
55162
|
+
// src/repositories/online-forms-v2.repository.ts
|
|
55163
|
+
import {
|
|
55164
|
+
BadRequestError as BadRequestError212,
|
|
55165
|
+
InternalServerError as InternalServerError75,
|
|
55166
|
+
logger as logger187,
|
|
55167
|
+
useAtlas as useAtlas118,
|
|
55168
|
+
useCache as useCache69
|
|
55169
|
+
} from "@7365admin1/node-server-utils";
|
|
55170
|
+
var online_forms_namespace_collection = "online-forms";
|
|
55171
|
+
function useFormEntryRepo() {
|
|
55172
|
+
const db = useAtlas118.getDb();
|
|
55173
|
+
if (!db) {
|
|
55174
|
+
throw new InternalServerError75("Unable to connect to server.");
|
|
55175
|
+
}
|
|
55176
|
+
const collection = db.collection(online_forms_namespace_collection);
|
|
55177
|
+
const { delNamespace, getCache, setCache } = useCache69(
|
|
55178
|
+
online_forms_namespace_collection
|
|
55179
|
+
);
|
|
55180
|
+
async function createTextIndex() {
|
|
55181
|
+
try {
|
|
55182
|
+
await collection.createIndex({
|
|
55183
|
+
name: "text"
|
|
55184
|
+
});
|
|
55185
|
+
} catch (error) {
|
|
55186
|
+
throw new InternalServerError75(
|
|
55187
|
+
"Failed to create text index on online form."
|
|
55188
|
+
);
|
|
55189
|
+
}
|
|
55190
|
+
}
|
|
55191
|
+
async function add(value, session) {
|
|
55192
|
+
try {
|
|
55193
|
+
value = MFormEntry(value);
|
|
55194
|
+
const res = await collection.insertOne(value, { session });
|
|
55195
|
+
delNamespace().then(() => {
|
|
55196
|
+
logger187.info(
|
|
55197
|
+
`Cache cleared for namespace: ${online_forms_namespace_collection}`
|
|
55198
|
+
);
|
|
55199
|
+
}).catch((err) => {
|
|
55200
|
+
logger187.error(
|
|
55201
|
+
`Failed to clear cache for namespace: ${online_forms_namespace_collection}`,
|
|
55202
|
+
err
|
|
55203
|
+
);
|
|
55204
|
+
});
|
|
55205
|
+
return res.insertedId;
|
|
55206
|
+
} catch (error) {
|
|
55207
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
55208
|
+
if (isDuplicated) {
|
|
55209
|
+
throw new BadRequestError212("Online Form already exists.");
|
|
55210
|
+
}
|
|
55211
|
+
throw error;
|
|
55212
|
+
}
|
|
55213
|
+
}
|
|
55214
|
+
return {
|
|
55215
|
+
add,
|
|
55216
|
+
createTextIndex
|
|
55217
|
+
};
|
|
55218
|
+
}
|
|
55219
|
+
|
|
55220
|
+
// src/controllers/online-forms-v2.controller.ts
|
|
55221
|
+
import { BadRequestError as BadRequestError213, logger as logger188 } from "@7365admin1/node-server-utils";
|
|
55222
|
+
import ExcelJS3 from "exceljs";
|
|
55223
|
+
import fs5 from "fs";
|
|
55224
|
+
function useFormEntryController() {
|
|
55225
|
+
const { add: _add } = useFormEntryRepo();
|
|
55226
|
+
function toCamelCase(str) {
|
|
55227
|
+
return str.replace(/\s(.)/g, (_, char) => char.toUpperCase()).replace(/\s+/g, "").replace(/^(.)/, (_, char) => char.toLowerCase());
|
|
55228
|
+
}
|
|
55229
|
+
function normalizeKeys(obj) {
|
|
55230
|
+
const normalized = {};
|
|
55231
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
55232
|
+
normalized[toCamelCase(key)] = value;
|
|
55233
|
+
}
|
|
55234
|
+
return normalized;
|
|
55235
|
+
}
|
|
55236
|
+
async function uploadFormEntrys(req, res, next) {
|
|
55237
|
+
try {
|
|
55238
|
+
if (!req.file) {
|
|
55239
|
+
next(new BadRequestError213("Excel file is required."));
|
|
55240
|
+
return;
|
|
55241
|
+
}
|
|
55242
|
+
const workbook = new ExcelJS3.Workbook();
|
|
55243
|
+
await workbook.xlsx.readFile(req.file.path);
|
|
55244
|
+
const worksheet = workbook.worksheets[0];
|
|
55245
|
+
if (!worksheet) {
|
|
55246
|
+
next(new BadRequestError213("No worksheet found in uploaded Excel file."));
|
|
55247
|
+
return;
|
|
55248
|
+
}
|
|
55249
|
+
const headerRow = worksheet.getRow(1);
|
|
55250
|
+
const headers = headerRow.values.slice(1).map((h) => String(h ?? "").trim());
|
|
55251
|
+
const fields = {};
|
|
55252
|
+
headers.forEach((header) => {
|
|
55253
|
+
fields[header] = null;
|
|
55254
|
+
});
|
|
55255
|
+
const formType = req.file.originalname.replace(/\.[^/.]+$/, "");
|
|
55256
|
+
const normalizedFields = normalizeKeys(fields);
|
|
55257
|
+
const payload = {
|
|
55258
|
+
formType,
|
|
55259
|
+
fields: normalizedFields,
|
|
55260
|
+
status: "active" /* ACTIVE */
|
|
55261
|
+
};
|
|
55262
|
+
const { error, value } = schemaFormEntry.validate(payload, {
|
|
55263
|
+
abortEarly: false
|
|
55264
|
+
});
|
|
55265
|
+
if (error) {
|
|
55266
|
+
const messages = error.details.map((d) => d.message).join(", ");
|
|
55267
|
+
logger188.log({ level: "error", message: messages });
|
|
55268
|
+
next(new BadRequestError213(messages));
|
|
55269
|
+
return;
|
|
55270
|
+
}
|
|
55271
|
+
const result = await _add(value);
|
|
55272
|
+
res.status(201).json(result);
|
|
55273
|
+
fs5.unlink(req.file.path, () => {
|
|
55274
|
+
});
|
|
55275
|
+
} catch (error) {
|
|
55276
|
+
logger188.log({ level: "error", message: error.message });
|
|
55277
|
+
next(error);
|
|
55278
|
+
}
|
|
55279
|
+
}
|
|
55280
|
+
return {
|
|
55281
|
+
uploadFormEntrys
|
|
54073
55282
|
};
|
|
54074
55283
|
}
|
|
54075
55284
|
export {
|
|
@@ -54098,6 +55307,7 @@ export {
|
|
|
54098
55307
|
EventType,
|
|
54099
55308
|
FacilitySort,
|
|
54100
55309
|
FacilityStatus,
|
|
55310
|
+
FormEntryStatus,
|
|
54101
55311
|
GuestSort,
|
|
54102
55312
|
GuestStatus,
|
|
54103
55313
|
MAccessCard,
|
|
@@ -54119,6 +55329,7 @@ export {
|
|
|
54119
55329
|
MEventManagement,
|
|
54120
55330
|
MFeedback,
|
|
54121
55331
|
MFile,
|
|
55332
|
+
MFormEntry,
|
|
54122
55333
|
MGuestManagement,
|
|
54123
55334
|
MIncidentReport,
|
|
54124
55335
|
MManpowerDesignations,
|
|
@@ -54230,6 +55441,7 @@ export {
|
|
|
54230
55441
|
nfcPatrolSettingsSchema,
|
|
54231
55442
|
nfcPatrolSettingsSchemaUpdate,
|
|
54232
55443
|
occurrence_book_namespace_collection,
|
|
55444
|
+
online_forms_namespace_collection,
|
|
54233
55445
|
orgSchema,
|
|
54234
55446
|
overnight_parking_requests_namespace_collection,
|
|
54235
55447
|
parseDahuaFind,
|
|
@@ -54254,6 +55466,7 @@ export {
|
|
|
54254
55466
|
schemaEntryPassSettings,
|
|
54255
55467
|
schemaEventManagement,
|
|
54256
55468
|
schemaFiles,
|
|
55469
|
+
schemaFormEntry,
|
|
54257
55470
|
schemaGuestManagement,
|
|
54258
55471
|
schemaIncidentReport,
|
|
54259
55472
|
schemaNfcPatrolLog,
|
|
@@ -54284,6 +55497,7 @@ export {
|
|
|
54284
55497
|
schemaUpdateDocumentManagement,
|
|
54285
55498
|
schemaUpdateEntryPassSettings,
|
|
54286
55499
|
schemaUpdateEventManagement,
|
|
55500
|
+
schemaUpdateFormEntry,
|
|
54287
55501
|
schemaUpdateGuestManagement,
|
|
54288
55502
|
schemaUpdateIncidentReport,
|
|
54289
55503
|
schemaUpdateOccurrenceBook,
|
|
@@ -54296,6 +55510,7 @@ export {
|
|
|
54296
55510
|
schemaUpdatePatrolQuestion,
|
|
54297
55511
|
schemaUpdatePatrolRoute,
|
|
54298
55512
|
schemaUpdatePerson,
|
|
55513
|
+
schemaUpdatePost,
|
|
54299
55514
|
schemaUpdateServiceProviderBilling,
|
|
54300
55515
|
schemaUpdateSiteBillingConfiguration,
|
|
54301
55516
|
schemaUpdateSiteBillingItem,
|
|
@@ -54366,6 +55581,8 @@ export {
|
|
|
54366
55581
|
useFileController,
|
|
54367
55582
|
useFileRepo,
|
|
54368
55583
|
useFileService,
|
|
55584
|
+
useFormEntryController,
|
|
55585
|
+
useFormEntryRepo,
|
|
54369
55586
|
useGuestManagementController,
|
|
54370
55587
|
useGuestManagementRepo,
|
|
54371
55588
|
useGuestManagementService,
|