@7365admin1/core 3.52.0 → 3.52.1-staging.231
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/dist/index.d.ts +8 -1
- package/dist/index.js +139 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +139 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4664,6 +4664,7 @@ type TVisitorTransaction = {
|
|
|
4664
4664
|
status?: VisitorStatus;
|
|
4665
4665
|
nric?: string;
|
|
4666
4666
|
remarks?: string;
|
|
4667
|
+
invitationNote?: string;
|
|
4667
4668
|
org?: string | ObjectId;
|
|
4668
4669
|
site?: string | ObjectId;
|
|
4669
4670
|
plateNumber?: string;
|
|
@@ -4743,6 +4744,7 @@ declare function MVisitorTransaction(value: TVisitorTransaction): {
|
|
|
4743
4744
|
checkOut: string | Date | null | undefined;
|
|
4744
4745
|
status: VisitorStatus | undefined;
|
|
4745
4746
|
remarks: string | undefined;
|
|
4747
|
+
invitationNote: string | undefined;
|
|
4746
4748
|
deliveryType: string | undefined;
|
|
4747
4749
|
attachments: string[] | undefined;
|
|
4748
4750
|
snapshotEntryImage: string | undefined;
|
|
@@ -4822,7 +4824,7 @@ declare function useVisitorTransactionRepo(): {
|
|
|
4822
4824
|
checkOutBySiteAndPlate: (site: string | ObjectId, plateNumber: string, session?: ClientSession) => Promise<mongodb.WithId<bson.Document> | null>;
|
|
4823
4825
|
resendEmailInvitedResident: (visitorId: string, updatedBy: string | ObjectId) => Promise<any>;
|
|
4824
4826
|
getSelfServiceVisitorPreview: (id: string | ObjectId) => Promise<mongodb.WithId<bson.Document> | null>;
|
|
4825
|
-
patchFields: (id: string | ObjectId, fields: Record<string, any
|
|
4827
|
+
patchFields: (id: string | ObjectId, fields: Record<string, any>, session?: ClientSession) => Promise<void>;
|
|
4826
4828
|
updateStatusByLeadId: (leadId: string | ObjectId, status: string) => Promise<void>;
|
|
4827
4829
|
};
|
|
4828
4830
|
|
|
@@ -4831,6 +4833,7 @@ declare function useVisitorTransactionService(): {
|
|
|
4831
4833
|
updateVisitorTransactionById: (id: string | ObjectId, value: TVisitorTransaction) => Promise<string>;
|
|
4832
4834
|
processTransactionDahuaStatus: () => Promise<void>;
|
|
4833
4835
|
inviteVisitor: (value: TVisitorTransaction, userId: string) => Promise<ObjectId[]>;
|
|
4836
|
+
createInvitedMemberDocuments: (leadId: string | ObjectId, status: VisitorStatus) => Promise<ObjectId[]>;
|
|
4834
4837
|
deleteVisitorTransaction: (id: string) => Promise<void>;
|
|
4835
4838
|
};
|
|
4836
4839
|
|
|
@@ -7022,6 +7025,10 @@ interface AdditionalSettings {
|
|
|
7022
7025
|
vendorId: string | null | number;
|
|
7023
7026
|
productId: string | null | number;
|
|
7024
7027
|
};
|
|
7028
|
+
invitationNote?: {
|
|
7029
|
+
isEnabled: boolean;
|
|
7030
|
+
text: string;
|
|
7031
|
+
};
|
|
7025
7032
|
};
|
|
7026
7033
|
}
|
|
7027
7034
|
type TAccessMngmntSettings = {
|
package/dist/index.js
CHANGED
|
@@ -19589,6 +19589,7 @@ var schemaVisitorTransaction = import_joi21.default.object({
|
|
|
19589
19589
|
deliveryType: import_joi21.default.string().optional().allow(null, ""),
|
|
19590
19590
|
status: import_joi21.default.string().optional().valid(...Object.values(VisitorStatus)).default("registered" /* REGISTERED */),
|
|
19591
19591
|
remarks: import_joi21.default.string().optional().allow(null, ""),
|
|
19592
|
+
invitationNote: import_joi21.default.string().optional().allow(null, ""),
|
|
19592
19593
|
members: import_joi21.default.array().items(
|
|
19593
19594
|
import_joi21.default.object({
|
|
19594
19595
|
name: import_joi21.default.string().optional().allow(null, ""),
|
|
@@ -19899,6 +19900,7 @@ function MVisitorTransaction(value) {
|
|
|
19899
19900
|
checkOut: value.checkOut,
|
|
19900
19901
|
status: value.status,
|
|
19901
19902
|
remarks: value.remarks,
|
|
19903
|
+
invitationNote: value.invitationNote,
|
|
19902
19904
|
deliveryType: value.deliveryType,
|
|
19903
19905
|
attachments: value.attachments,
|
|
19904
19906
|
snapshotEntryImage: value.snapshotEntryImage,
|
|
@@ -20842,6 +20844,7 @@ function useVisitorTransactionRepo() {
|
|
|
20842
20844
|
arrivalTime: 1,
|
|
20843
20845
|
duration: 1,
|
|
20844
20846
|
purpose: 1,
|
|
20847
|
+
invitationNote: 1,
|
|
20845
20848
|
checkIn: 1
|
|
20846
20849
|
}
|
|
20847
20850
|
}
|
|
@@ -20850,10 +20853,10 @@ function useVisitorTransactionRepo() {
|
|
|
20850
20853
|
throw new Error(error.message);
|
|
20851
20854
|
}
|
|
20852
20855
|
}
|
|
20853
|
-
async function patchFields(id, fields) {
|
|
20856
|
+
async function patchFields(id, fields, session) {
|
|
20854
20857
|
const _id = (0, import_node_server_utils48.toObjectId)(id);
|
|
20855
20858
|
try {
|
|
20856
|
-
await collection.updateOne({ _id }, { $set: fields });
|
|
20859
|
+
await collection.updateOne({ _id }, { $set: fields }, { session });
|
|
20857
20860
|
} catch (error) {
|
|
20858
20861
|
throw new Error(error.message);
|
|
20859
20862
|
}
|
|
@@ -50480,7 +50483,8 @@ function useVisitorTransactionService() {
|
|
|
50480
50483
|
getExpiredCheckedOutTransactionsBySite: _getExpiredCheckedOutTransactionsBySite,
|
|
50481
50484
|
updateManyDahuaSyncStatus: _updateManyDahuaSyncStatus,
|
|
50482
50485
|
getVisitorTransactionById: _getVisitorTransactionById,
|
|
50483
|
-
deleteVisitorTransaction: _deleteVisitorTransaction
|
|
50486
|
+
deleteVisitorTransaction: _deleteVisitorTransaction,
|
|
50487
|
+
patchFields: _patchFields
|
|
50484
50488
|
} = useVisitorTransactionRepo();
|
|
50485
50489
|
const { getById } = useBuildingUnitRepo();
|
|
50486
50490
|
const {
|
|
@@ -50608,6 +50612,7 @@ function useVisitorTransactionService() {
|
|
|
50608
50612
|
type: type2,
|
|
50609
50613
|
company: company2,
|
|
50610
50614
|
remarks,
|
|
50615
|
+
invitationNote,
|
|
50611
50616
|
contractorType,
|
|
50612
50617
|
unitName
|
|
50613
50618
|
} = value;
|
|
@@ -50654,6 +50659,10 @@ function useVisitorTransactionService() {
|
|
|
50654
50659
|
type: type2,
|
|
50655
50660
|
company: company2,
|
|
50656
50661
|
remarks,
|
|
50662
|
+
// Every member holds their OWN invitation/pass link, so the
|
|
50663
|
+
// site's note has to ride along to each of them - otherwise
|
|
50664
|
+
// only the lead contractor ever sees it.
|
|
50665
|
+
invitationNote,
|
|
50657
50666
|
contractorType,
|
|
50658
50667
|
checkIn: start,
|
|
50659
50668
|
visitorPass: preparedVisitorPass,
|
|
@@ -51321,6 +51330,79 @@ function useVisitorTransactionService() {
|
|
|
51321
51330
|
session?.endSession();
|
|
51322
51331
|
}
|
|
51323
51332
|
}
|
|
51333
|
+
async function createInvitedMemberDocuments(leadId, status) {
|
|
51334
|
+
const lead = await _getVisitorTransactionById(String(leadId));
|
|
51335
|
+
if (!lead)
|
|
51336
|
+
return [];
|
|
51337
|
+
const members = Array.isArray(lead.members) ? lead.members : [];
|
|
51338
|
+
if (members.length === 0)
|
|
51339
|
+
return [];
|
|
51340
|
+
if (!members.every((member) => !member._id))
|
|
51341
|
+
return [];
|
|
51342
|
+
const session = import_node_server_utils134.useAtlas.getClient()?.startSession();
|
|
51343
|
+
if (!session) {
|
|
51344
|
+
throw new Error("Unable to start session for people service.");
|
|
51345
|
+
}
|
|
51346
|
+
try {
|
|
51347
|
+
session.startTransaction();
|
|
51348
|
+
const memberPayload = {
|
|
51349
|
+
block: lead.block ? String(lead.block) : void 0,
|
|
51350
|
+
level: lead.level ? String(lead.level) : void 0,
|
|
51351
|
+
unit: lead.unit ? String(lead.unit) : void 0,
|
|
51352
|
+
unitName: lead.unitName,
|
|
51353
|
+
org: lead.org ? String(lead.org) : void 0,
|
|
51354
|
+
site: lead.site ? String(lead.site) : void 0,
|
|
51355
|
+
type: lead.type,
|
|
51356
|
+
contractorType: lead.contractorType,
|
|
51357
|
+
company: lead.company,
|
|
51358
|
+
purpose: lead.purpose,
|
|
51359
|
+
expectedCheckIn: lead.expectedCheckIn ? new Date(lead.expectedCheckIn).toISOString() : void 0,
|
|
51360
|
+
arrivalTime: lead.arrivalTime,
|
|
51361
|
+
duration: lead.duration,
|
|
51362
|
+
isOvernightParking: lead.isOvernightParking,
|
|
51363
|
+
numberOfPassengers: lead.numberOfPassengers,
|
|
51364
|
+
// Site-configured note from the self-service settings. Each member
|
|
51365
|
+
// holds their own pass link, so the note has to ride along to all of
|
|
51366
|
+
// them - the same thing the creation-time fan-out does. Absent on
|
|
51367
|
+
// resident invitations, which never set it.
|
|
51368
|
+
invitationNote: lead.invitationNote,
|
|
51369
|
+
status,
|
|
51370
|
+
...lead.inviterId ? { inviterId: String(lead.inviterId) } : {},
|
|
51371
|
+
leadId: String(lead._id),
|
|
51372
|
+
// Explicit - MVisitorTransaction defaults an undefined checkIn to now,
|
|
51373
|
+
// and an approved invitation hasn't arrived yet.
|
|
51374
|
+
checkIn: null
|
|
51375
|
+
};
|
|
51376
|
+
const insertedIds = [];
|
|
51377
|
+
for (const member of members) {
|
|
51378
|
+
const memberId = await _add(
|
|
51379
|
+
{
|
|
51380
|
+
...memberPayload,
|
|
51381
|
+
name: member.name ?? "",
|
|
51382
|
+
nric: member.nric ?? "",
|
|
51383
|
+
contact: member.contact ?? "",
|
|
51384
|
+
email: member.email ?? "",
|
|
51385
|
+
plateNumber: member.plateNumber ?? ""
|
|
51386
|
+
},
|
|
51387
|
+
session
|
|
51388
|
+
);
|
|
51389
|
+
member._id = memberId;
|
|
51390
|
+
insertedIds.push(memberId);
|
|
51391
|
+
}
|
|
51392
|
+
await _patchFields(leadId, { members }, session);
|
|
51393
|
+
await session.commitTransaction();
|
|
51394
|
+
return insertedIds;
|
|
51395
|
+
} catch (error) {
|
|
51396
|
+
import_node_server_utils134.logger.error(
|
|
51397
|
+
"Error creating member documents for approved invitation:",
|
|
51398
|
+
error
|
|
51399
|
+
);
|
|
51400
|
+
await session.abortTransaction();
|
|
51401
|
+
throw error;
|
|
51402
|
+
} finally {
|
|
51403
|
+
session?.endSession();
|
|
51404
|
+
}
|
|
51405
|
+
}
|
|
51324
51406
|
async function deleteVisitorTransaction(id) {
|
|
51325
51407
|
const visitor = await _getVisitorTransactionById(id);
|
|
51326
51408
|
if (!visitor) {
|
|
@@ -51353,6 +51435,7 @@ function useVisitorTransactionService() {
|
|
|
51353
51435
|
updateVisitorTransactionById,
|
|
51354
51436
|
processTransactionDahuaStatus,
|
|
51355
51437
|
inviteVisitor,
|
|
51438
|
+
createInvitedMemberDocuments,
|
|
51356
51439
|
deleteVisitorTransaction
|
|
51357
51440
|
// changeVisitorTransactionKeysById,
|
|
51358
51441
|
};
|
|
@@ -55312,6 +55395,7 @@ function useVisitorTransactionController() {
|
|
|
55312
55395
|
add: _add,
|
|
55313
55396
|
updateVisitorTransactionById: _updateVisitorTransactionById,
|
|
55314
55397
|
inviteVisitor: _inviteVisitor,
|
|
55398
|
+
createInvitedMemberDocuments: _createInvitedMemberDocuments,
|
|
55315
55399
|
deleteVisitorTransaction: _deleteVisitorTransaction
|
|
55316
55400
|
// changeVisitorTransactionKeysById: _changeVisitorTransactionKeysById,
|
|
55317
55401
|
} = useVisitorTransactionService();
|
|
@@ -55375,12 +55459,17 @@ function useVisitorTransactionController() {
|
|
|
55375
55459
|
return;
|
|
55376
55460
|
}
|
|
55377
55461
|
const leadId = new import_mongodb88.ObjectId();
|
|
55462
|
+
const invitationNote = value.type === "contractor" /* CONTRACTOR */ && onboardingSettings?.invitationNote?.isEnabled === true ? String(onboardingSettings.invitationNote.text ?? "").trim() : "";
|
|
55463
|
+
const members = Array.isArray(value.members) ? value.members : [];
|
|
55464
|
+
const deferMembers = value.type === "contractor" /* CONTRACTOR */ && members.length > 0 && status !== "approved" /* APPROVED */;
|
|
55465
|
+
const { members: _deferredMembers, ...valueWithoutMembers } = value;
|
|
55378
55466
|
const insertedId = await _add({
|
|
55379
|
-
...value,
|
|
55467
|
+
...deferMembers ? valueWithoutMembers : value,
|
|
55380
55468
|
_id: leadId.toString(),
|
|
55381
55469
|
org: site.orgId.toString(),
|
|
55382
55470
|
site: siteId,
|
|
55383
55471
|
status,
|
|
55472
|
+
...invitationNote ? { invitationNote } : {},
|
|
55384
55473
|
// MVisitorTransaction() defaults checkIn to "now" whenever it's
|
|
55385
55474
|
// undefined - correct for the staff "walk-in" flow, where creating
|
|
55386
55475
|
// the record IS the check-in event, but wrong here: a self-service
|
|
@@ -55389,8 +55478,10 @@ function useVisitorTransactionController() {
|
|
|
55389
55478
|
// checked in later (inline button / Guests-tab action menu).
|
|
55390
55479
|
checkIn: null
|
|
55391
55480
|
});
|
|
55392
|
-
|
|
55393
|
-
|
|
55481
|
+
if (deferMembers) {
|
|
55482
|
+
await _patchFields(insertedId, { members });
|
|
55483
|
+
}
|
|
55484
|
+
if (!deferMembers && value.type === "contractor" /* CONTRACTOR */ && members.length) {
|
|
55394
55485
|
await Promise.all(
|
|
55395
55486
|
members.filter((m) => m._id).map((m) => _patchFields(m._id, { checkIn: null, status }))
|
|
55396
55487
|
);
|
|
@@ -55475,6 +55566,11 @@ function useVisitorTransactionController() {
|
|
|
55475
55566
|
arrivalTime: data.arrivalTime || null,
|
|
55476
55567
|
duration: data.duration ?? null,
|
|
55477
55568
|
purpose: data.purpose || null,
|
|
55569
|
+
// Set by the site, not the registrant - see the Invitation Note
|
|
55570
|
+
// block in `createSelfServiceVisitor`. Safe to hand back here:
|
|
55571
|
+
// this is exactly the invitation link the note was written for,
|
|
55572
|
+
// and it's only reachable by someone already holding the ID.
|
|
55573
|
+
invitationNote: data.invitationNote || null,
|
|
55478
55574
|
// Public response exposes whether check-in happened, not the raw
|
|
55479
55575
|
// timestamp - the preview page needs it to know an already-arrived
|
|
55480
55576
|
// visitor's lapsed arrival window isn't the same thing as an
|
|
@@ -55636,8 +55732,36 @@ function useVisitorTransactionController() {
|
|
|
55636
55732
|
const remarks = approval?.remarks ?? req.body.remarks;
|
|
55637
55733
|
const isApprovalTransition = nextStatus === "approved" /* APPROVED */ || nextStatus === "rejected" /* REJECTED */;
|
|
55638
55734
|
const current = isApprovalTransition ? await _getVisitorTransactionById(_id) : null;
|
|
55639
|
-
const
|
|
55735
|
+
const needsMemberFanOut = nextStatus === "approved" /* APPROVED */ && (!!current?.inviterId || current?.type === "contractor" /* CONTRACTOR */) && Array.isArray(current?.members) && current.members.length > 0 && current.members.every((member) => !member._id);
|
|
55736
|
+
const { members: _unusedMembers, ...bodyWithoutMembers } = req.body;
|
|
55737
|
+
const baseBody = needsMemberFanOut ? bodyWithoutMembers : req.body;
|
|
55738
|
+
const updateBody = approval ? { ...baseBody, status: nextStatus } : baseBody;
|
|
55640
55739
|
await _updateVisitorTransactionById(_id, updateBody);
|
|
55740
|
+
let invitedMemberIds = [];
|
|
55741
|
+
if (needsMemberFanOut) {
|
|
55742
|
+
try {
|
|
55743
|
+
invitedMemberIds = await _createInvitedMemberDocuments(
|
|
55744
|
+
_id,
|
|
55745
|
+
nextStatus
|
|
55746
|
+
);
|
|
55747
|
+
} catch (fanOutError) {
|
|
55748
|
+
import_node_server_utils137.logger.log({
|
|
55749
|
+
level: "error",
|
|
55750
|
+
message: `Failed to create member documents for approved invitation ${_id}: ${fanOutError?.message}`
|
|
55751
|
+
});
|
|
55752
|
+
}
|
|
55753
|
+
}
|
|
55754
|
+
for (const insertedId of current?.inviterId ? invitedMemberIds : []) {
|
|
55755
|
+
resendEmailInvitedResident(
|
|
55756
|
+
String(insertedId),
|
|
55757
|
+
String(current?.inviterId)
|
|
55758
|
+
).catch((error2) => {
|
|
55759
|
+
import_node_server_utils137.logger.log({
|
|
55760
|
+
level: "error",
|
|
55761
|
+
message: `Failed to send invitation email: ${error2?.message}`
|
|
55762
|
+
});
|
|
55763
|
+
});
|
|
55764
|
+
}
|
|
55641
55765
|
if (isApprovalTransition && current && current.type === "contractor" /* CONTRACTOR */) {
|
|
55642
55766
|
try {
|
|
55643
55767
|
await _updateStatusByLeadId(_id, nextStatus);
|
|
@@ -67962,7 +68086,14 @@ function useAccessManagementController() {
|
|
|
67962
68086
|
return res.status(400).json({ message: error.message });
|
|
67963
68087
|
}
|
|
67964
68088
|
const result = await getOnboardingSettingsSvc(site);
|
|
67965
|
-
return res.status(200).json({
|
|
68089
|
+
return res.status(200).json({
|
|
68090
|
+
message: "Success",
|
|
68091
|
+
data: {
|
|
68092
|
+
enabled: result?.enabled ?? false,
|
|
68093
|
+
header: result?.header ?? "",
|
|
68094
|
+
subText: result?.subText ?? ""
|
|
68095
|
+
}
|
|
68096
|
+
});
|
|
67966
68097
|
} catch (error) {
|
|
67967
68098
|
return res.status(500).json({
|
|
67968
68099
|
data: null,
|