@7365admin1/core 3.52.7 → 3.52.8
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 +80 -0
- package/dist/index.d.ts +122 -2
- package/dist/index.js +226 -78
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +236 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/test/camera-view.util.test.mjs +168 -0
- package/test/site-timezone.test.mjs +69 -0
- package/test/visitor-invite-schema.test.mjs +41 -0
package/dist/index.mjs
CHANGED
|
@@ -11606,6 +11606,36 @@ import {
|
|
|
11606
11606
|
} from "@7365admin1/node-server-utils";
|
|
11607
11607
|
import Joi9 from "joi";
|
|
11608
11608
|
import { ObjectId as ObjectId20 } from "mongodb";
|
|
11609
|
+
|
|
11610
|
+
// src/utils/site-timezone.util.ts
|
|
11611
|
+
import moment from "moment-timezone";
|
|
11612
|
+
var DEFAULT_SITE_TIMEZONE = "Asia/Singapore";
|
|
11613
|
+
function isValidTimezone(tz) {
|
|
11614
|
+
return typeof tz === "string" && tz.length > 0 && !!moment.tz.zone(tz);
|
|
11615
|
+
}
|
|
11616
|
+
function resolveSiteTimezone(site) {
|
|
11617
|
+
const tz = site?.timezone;
|
|
11618
|
+
return isValidTimezone(tz) ? tz : DEFAULT_SITE_TIMEZONE;
|
|
11619
|
+
}
|
|
11620
|
+
function siteDayBounds(value, timezone) {
|
|
11621
|
+
if (!value)
|
|
11622
|
+
return null;
|
|
11623
|
+
const tz = isValidTimezone(timezone) ? timezone : DEFAULT_SITE_TIMEZONE;
|
|
11624
|
+
const isDateOnly = typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value);
|
|
11625
|
+
const m = isDateOnly ? moment.tz(value, "YYYY-MM-DD", tz) : typeof value === "string" ? moment.tz(value, moment.ISO_8601, tz) : moment.tz(value, tz);
|
|
11626
|
+
if (!m.isValid())
|
|
11627
|
+
return null;
|
|
11628
|
+
return {
|
|
11629
|
+
start: m.clone().startOf("day").toDate(),
|
|
11630
|
+
end: m.clone().endOf("day").toDate(),
|
|
11631
|
+
date: m.format("YYYY-MM-DD")
|
|
11632
|
+
};
|
|
11633
|
+
}
|
|
11634
|
+
|
|
11635
|
+
// src/models/site.model.ts
|
|
11636
|
+
function siteTimezoneValidator(value, helpers) {
|
|
11637
|
+
return isValidTimezone(value) ? value : helpers.error("any.invalid");
|
|
11638
|
+
}
|
|
11609
11639
|
var addressSchema = Joi9.object({
|
|
11610
11640
|
line1: Joi9.string().min(3).required(),
|
|
11611
11641
|
line2: Joi9.string().allow("", null),
|
|
@@ -11713,6 +11743,7 @@ var siteSchema = Joi9.object({
|
|
|
11713
11743
|
orgId: Joi9.string().hex().required(),
|
|
11714
11744
|
customerId: Joi9.string().hex().optional().allow("", null),
|
|
11715
11745
|
address: addressSchema.optional(),
|
|
11746
|
+
timezone: Joi9.string().custom(siteTimezoneValidator, "IANA timezone").optional().default(DEFAULT_SITE_TIMEZONE),
|
|
11716
11747
|
category: Joi9.string().valid(...Object.values(SiteCategories)).default("commercial" /* COMMERCIAL */),
|
|
11717
11748
|
deliveryCompanyList: Joi9.array().items(Joi9.string()).optional().allow(null),
|
|
11718
11749
|
isOpenGate: Joi9.boolean().optional().default(false),
|
|
@@ -11723,6 +11754,7 @@ var siteSchema = Joi9.object({
|
|
|
11723
11754
|
var updateSiteSchema = Joi9.object({
|
|
11724
11755
|
_id: Joi9.string().hex().length(24).required(),
|
|
11725
11756
|
address: updateAddressSchema.optional(),
|
|
11757
|
+
timezone: Joi9.string().custom(siteTimezoneValidator, "IANA timezone").optional(),
|
|
11726
11758
|
metadata: metadataSchema3.optional(),
|
|
11727
11759
|
deliveryCompanyList: Joi9.array().items(Joi9.string().trim()).optional().allow(null),
|
|
11728
11760
|
isOpenGate: Joi9.boolean().optional().allow(null),
|
|
@@ -11751,6 +11783,7 @@ function MSite(value) {
|
|
|
11751
11783
|
status: "active",
|
|
11752
11784
|
createdAt: /* @__PURE__ */ new Date(),
|
|
11753
11785
|
address: value.address,
|
|
11786
|
+
timezone: value.timezone ?? DEFAULT_SITE_TIMEZONE,
|
|
11754
11787
|
category: value.category,
|
|
11755
11788
|
deliveryCompanyList: value.deliveryCompanyList ?? [],
|
|
11756
11789
|
isOpenGate: value.isOpenGate,
|
|
@@ -13035,7 +13068,8 @@ function useCustomerSiteRepo() {
|
|
|
13035
13068
|
limit = 10,
|
|
13036
13069
|
sort = {},
|
|
13037
13070
|
org = "",
|
|
13038
|
-
status = "active"
|
|
13071
|
+
status = "active",
|
|
13072
|
+
siteScope = null
|
|
13039
13073
|
}, session) {
|
|
13040
13074
|
page = page > 0 ? page - 1 : 0;
|
|
13041
13075
|
try {
|
|
@@ -13055,6 +13089,11 @@ function useCustomerSiteRepo() {
|
|
|
13055
13089
|
page,
|
|
13056
13090
|
limit
|
|
13057
13091
|
};
|
|
13092
|
+
if (siteScope) {
|
|
13093
|
+
const scoped = siteScope.filter((id) => ObjectId24.isValid(id));
|
|
13094
|
+
query2.site = { $in: scoped.map((id) => new ObjectId24(id)) };
|
|
13095
|
+
cacheOptions.siteScope = scoped.length ? [...scoped].sort().join(",") : "no-site";
|
|
13096
|
+
}
|
|
13058
13097
|
if (search) {
|
|
13059
13098
|
query2.$or = [{ name: { $regex: search, $options: "i" } }];
|
|
13060
13099
|
cacheOptions.search = search;
|
|
@@ -13361,7 +13400,8 @@ var EMPTY = {
|
|
|
13361
13400
|
name: "",
|
|
13362
13401
|
isSuperAdmin: false,
|
|
13363
13402
|
orgIds: [],
|
|
13364
|
-
propertyManagementOrgIds: []
|
|
13403
|
+
propertyManagementOrgIds: [],
|
|
13404
|
+
memberships: []
|
|
13365
13405
|
};
|
|
13366
13406
|
async function resolveInviteActor(userId) {
|
|
13367
13407
|
const id = userId?.toString() ?? "";
|
|
@@ -13388,12 +13428,36 @@ async function resolveInviteActor(userId) {
|
|
|
13388
13428
|
)
|
|
13389
13429
|
);
|
|
13390
13430
|
const user = await db2.collection("users").findOne({ _id: new ObjectId25(id) }, { projection: { name: 1 } });
|
|
13431
|
+
const memberRoleIds = Array.from(
|
|
13432
|
+
new Set(
|
|
13433
|
+
members.map((m) => m.role?.toString?.() ?? "").filter((r) => r && ObjectId25.isValid(r))
|
|
13434
|
+
)
|
|
13435
|
+
);
|
|
13436
|
+
const orgLevelRoleIds = /* @__PURE__ */ new Set();
|
|
13437
|
+
if (memberRoleIds.length) {
|
|
13438
|
+
const memberRoles = await db2.collection("roles").find(
|
|
13439
|
+
{
|
|
13440
|
+
_id: { $in: memberRoleIds.map((r) => new ObjectId25(r)) },
|
|
13441
|
+
...LIVE_ROLE
|
|
13442
|
+
},
|
|
13443
|
+
{ projection: { site: 1 } }
|
|
13444
|
+
).toArray();
|
|
13445
|
+
for (const role of memberRoles) {
|
|
13446
|
+
if (!role.site)
|
|
13447
|
+
orgLevelRoleIds.add(role._id.toString());
|
|
13448
|
+
}
|
|
13449
|
+
}
|
|
13391
13450
|
return {
|
|
13392
13451
|
id,
|
|
13393
13452
|
name: user?.name ?? adminMember?.name ?? "",
|
|
13394
13453
|
isSuperAdmin: isSuperAdmin2,
|
|
13395
13454
|
orgIds,
|
|
13396
|
-
propertyManagementOrgIds
|
|
13455
|
+
propertyManagementOrgIds,
|
|
13456
|
+
memberships: members.map((m) => ({
|
|
13457
|
+
org: m.org?.toString?.() ?? "",
|
|
13458
|
+
siteId: m.siteId?.toString?.() ?? "",
|
|
13459
|
+
orgLevelRole: orgLevelRoleIds.has(m.role?.toString?.() ?? "")
|
|
13460
|
+
}))
|
|
13397
13461
|
};
|
|
13398
13462
|
}
|
|
13399
13463
|
async function hasOrgInvitation(userId, orgId) {
|
|
@@ -19171,6 +19235,11 @@ var schemaVisitorTransaction = Joi21.object({
|
|
|
19171
19235
|
).optional().allow(null),
|
|
19172
19236
|
unitName: Joi21.string().optional().allow(null, ""),
|
|
19173
19237
|
expiredAt: Joi21.date().iso().optional().allow(null, ""),
|
|
19238
|
+
// The calendar day this invitation is valid for, in the site's timezone.
|
|
19239
|
+
// Stored as a bare YYYY-MM-DD so no offset conversion can shift the day.
|
|
19240
|
+
arrivalDate: Joi21.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow(null, "").messages({
|
|
19241
|
+
"string.pattern.base": "arrivalDate must be in YYYY-MM-DD format (e.g. 2026-09-02)"
|
|
19242
|
+
}),
|
|
19174
19243
|
arrivalTime: Joi21.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
|
|
19175
19244
|
"string.pattern.base": "arrivalTime must be in HH:mm format (e.g. 09:30, 18:45)"
|
|
19176
19245
|
}),
|
|
@@ -19232,6 +19301,11 @@ var schemaSelfServiceVisitor = Joi21.object({
|
|
|
19232
19301
|
// value through that schema via MVisitorTransaction(), and Joi.date()
|
|
19233
19302
|
// would have already coerced it to a Date object by then, failing there.
|
|
19234
19303
|
expectedCheckIn: Joi21.string().isoDate().required(),
|
|
19304
|
+
// The calendar day this invitation is valid for, in the site's timezone.
|
|
19305
|
+
// Stored as a bare YYYY-MM-DD so no offset conversion can shift the day.
|
|
19306
|
+
arrivalDate: Joi21.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow(null, "").messages({
|
|
19307
|
+
"string.pattern.base": "arrivalDate must be in YYYY-MM-DD format (e.g. 2026-09-02)"
|
|
19308
|
+
}),
|
|
19235
19309
|
arrivalTime: Joi21.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({ "string.pattern.base": "arrivalTime must be in HH:mm format" }),
|
|
19236
19310
|
duration: Joi21.number().integer().min(0).optional().allow(null, ""),
|
|
19237
19311
|
isOvernightParking: Joi21.boolean().optional().default(false),
|
|
@@ -19265,6 +19339,13 @@ var schemaSelfServiceVisitor = Joi21.object({
|
|
|
19265
19339
|
});
|
|
19266
19340
|
var schemaUpdateVisTrans = Joi21.object({
|
|
19267
19341
|
_id: Joi21.string().hex().length(24).required(),
|
|
19342
|
+
// Accepted here so a caller that moves `expectedCheckIn` can move the day
|
|
19343
|
+
// with it. Without this the two drift apart silently and the QR stays valid
|
|
19344
|
+
// on the ORIGINAL day, which is the failure the day-window work exists to
|
|
19345
|
+
// prevent.
|
|
19346
|
+
arrivalDate: Joi21.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow(null, "").messages({
|
|
19347
|
+
"string.pattern.base": "arrivalDate must be in YYYY-MM-DD format (e.g. 2026-09-02)"
|
|
19348
|
+
}),
|
|
19268
19349
|
name: Joi21.string().optional().allow(null, ""),
|
|
19269
19350
|
type: Joi21.string().valid(...PERSON_TYPES).optional().allow(null, ""),
|
|
19270
19351
|
org: Joi21.string().hex().length(24).optional().allow(null, ""),
|
|
@@ -19495,6 +19576,7 @@ function MVisitorTransaction(value) {
|
|
|
19495
19576
|
remarks: "",
|
|
19496
19577
|
updatedBy: value.inviterId ?? ""
|
|
19497
19578
|
} : null,
|
|
19579
|
+
arrivalDate: value.arrivalDate,
|
|
19498
19580
|
arrivalTime: value.arrivalTime,
|
|
19499
19581
|
duration: value.duration,
|
|
19500
19582
|
members: value.members
|
|
@@ -19503,7 +19585,7 @@ function MVisitorTransaction(value) {
|
|
|
19503
19585
|
|
|
19504
19586
|
// src/repositories/visitor-transaction.repo.ts
|
|
19505
19587
|
import { ObjectId as ObjectId40 } from "mongodb";
|
|
19506
|
-
import
|
|
19588
|
+
import moment2 from "moment-timezone";
|
|
19507
19589
|
|
|
19508
19590
|
// src/utils/compile-handlebars.ts
|
|
19509
19591
|
var import_handlebars = __toESM(require_lib());
|
|
@@ -20334,7 +20416,7 @@ function useVisitorTransactionRepo() {
|
|
|
20334
20416
|
const baseUrl = APP_MAIN;
|
|
20335
20417
|
const qrLink = `${baseUrl}/resident/invite/register/${updatedDocument?._id}`;
|
|
20336
20418
|
const logo = `${baseUrl}/images/resident/dark/seven-365.svg`;
|
|
20337
|
-
const arrivalDate = updatedDocument?.expectedCheckIn ?
|
|
20419
|
+
const arrivalDate = updatedDocument?.expectedCheckIn ? moment2(updatedDocument.expectedCheckIn).tz("Asia/Singapore").format("DD/MM/YYYY") : "No Arrival Date";
|
|
20338
20420
|
const isLead = !updatedDocument?.leadId;
|
|
20339
20421
|
const memberRows = isLead && Array.isArray(updatedDocument?.members) ? updatedDocument.members.map((member, index) => ({
|
|
20340
20422
|
position: index + 1,
|
|
@@ -24161,6 +24243,22 @@ function selectHealthTargets(cameraIds, cap, isValidId) {
|
|
|
24161
24243
|
truncated: unique.length > limit
|
|
24162
24244
|
};
|
|
24163
24245
|
}
|
|
24246
|
+
function orgSiteScope(params) {
|
|
24247
|
+
const org = idOf(params.org);
|
|
24248
|
+
if (!org)
|
|
24249
|
+
return null;
|
|
24250
|
+
const inOrg = params.memberships.filter(
|
|
24251
|
+
(membership) => idOf(membership.org) === org
|
|
24252
|
+
);
|
|
24253
|
+
if (inOrg.some(
|
|
24254
|
+
(membership) => !idOf(membership.siteId) || membership.orgLevelRole === true
|
|
24255
|
+
)) {
|
|
24256
|
+
return null;
|
|
24257
|
+
}
|
|
24258
|
+
return Array.from(
|
|
24259
|
+
new Set(inOrg.map((membership) => idOf(membership.siteId)).filter(Boolean))
|
|
24260
|
+
);
|
|
24261
|
+
}
|
|
24164
24262
|
|
|
24165
24263
|
// src/utils/camera-capability.util.ts
|
|
24166
24264
|
var CAMERA_CAPABILITIES = [
|
|
@@ -39635,7 +39733,7 @@ var deleteVehicleRequestSchema = Joi55.object({
|
|
|
39635
39733
|
});
|
|
39636
39734
|
|
|
39637
39735
|
// src/utils/vehicle-import.util.ts
|
|
39638
|
-
import
|
|
39736
|
+
import moment3 from "moment-timezone";
|
|
39639
39737
|
var SITE_TIME_ZONE = "Asia/Singapore";
|
|
39640
39738
|
var DEFAULT_YEARS = 10;
|
|
39641
39739
|
var CELL_FORMATS = [
|
|
@@ -39647,13 +39745,13 @@ var CELL_FORMATS = [
|
|
|
39647
39745
|
];
|
|
39648
39746
|
function parseExpiryDate(value) {
|
|
39649
39747
|
if (!value) {
|
|
39650
|
-
return
|
|
39748
|
+
return moment3.tz(SITE_TIME_ZONE).add(DEFAULT_YEARS, "years").toISOString();
|
|
39651
39749
|
}
|
|
39652
|
-
const wallClock = value instanceof Date ?
|
|
39750
|
+
const wallClock = value instanceof Date ? moment3.utc(value).format("YYYY-MM-DDTHH:mm:ss") : String(value).trim();
|
|
39653
39751
|
if (!wallClock) {
|
|
39654
|
-
return
|
|
39752
|
+
return moment3.tz(SITE_TIME_ZONE).add(DEFAULT_YEARS, "years").toISOString();
|
|
39655
39753
|
}
|
|
39656
|
-
const parsed =
|
|
39754
|
+
const parsed = moment3.tz(wallClock, CELL_FORMATS, SITE_TIME_ZONE);
|
|
39657
39755
|
return parsed.isValid() ? parsed.toISOString() : void 0;
|
|
39658
39756
|
}
|
|
39659
39757
|
|
|
@@ -41403,13 +41501,16 @@ function useCustomerSiteController() {
|
|
|
41403
41501
|
});
|
|
41404
41502
|
try {
|
|
41405
41503
|
await requireOrgAccess(req, org);
|
|
41504
|
+
const actor = await resolveInviteActor(callerId(req));
|
|
41505
|
+
const siteScope = actor.isSuperAdmin ? null : orgSiteScope({ memberships: actor.memberships, org });
|
|
41406
41506
|
const data = await _getAll({
|
|
41407
41507
|
search,
|
|
41408
41508
|
page,
|
|
41409
41509
|
limit,
|
|
41410
41510
|
sort: sortObj,
|
|
41411
41511
|
org,
|
|
41412
|
-
status
|
|
41512
|
+
status,
|
|
41513
|
+
siteScope
|
|
41413
41514
|
});
|
|
41414
41515
|
res.json(data);
|
|
41415
41516
|
return;
|
|
@@ -41863,7 +41964,7 @@ function MAttendance(value) {
|
|
|
41863
41964
|
|
|
41864
41965
|
// src/repositories/attendance.repository.ts
|
|
41865
41966
|
import { ObjectId as ObjectId77 } from "mongodb";
|
|
41866
|
-
import
|
|
41967
|
+
import moment4 from "moment-timezone";
|
|
41867
41968
|
import {
|
|
41868
41969
|
useAtlas as useAtlas60,
|
|
41869
41970
|
InternalServerError as InternalServerError38,
|
|
@@ -41937,11 +42038,11 @@ function useAttendanceRepository() {
|
|
|
41937
42038
|
cacheOptions.search = search;
|
|
41938
42039
|
}
|
|
41939
42040
|
const singaporeTz = "Asia/Singapore";
|
|
41940
|
-
const normalizedStartDate = typeof startDate === "string" ? startDate :
|
|
41941
|
-
const normalizedEndDate = typeof endDate === "string" ? endDate :
|
|
42041
|
+
const normalizedStartDate = typeof startDate === "string" ? startDate : moment4(startDate).tz(singaporeTz).format("YYYY-MM-DD");
|
|
42042
|
+
const normalizedEndDate = typeof endDate === "string" ? endDate : moment4(endDate).tz(singaporeTz).format("YYYY-MM-DD");
|
|
41942
42043
|
if (startDate && endDate) {
|
|
41943
|
-
const startOfDay =
|
|
41944
|
-
const endOfDay =
|
|
42044
|
+
const startOfDay = moment4.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate();
|
|
42045
|
+
const endOfDay = moment4.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate();
|
|
41945
42046
|
query2.$expr = {
|
|
41946
42047
|
$and: [
|
|
41947
42048
|
{ $gte: [{ $toDate: "$checkIn.timestamp" }, startOfDay] },
|
|
@@ -41954,7 +42055,7 @@ function useAttendanceRepository() {
|
|
|
41954
42055
|
query2.$expr = {
|
|
41955
42056
|
$gte: [
|
|
41956
42057
|
{ $toDate: "$checkIn.timestamp" },
|
|
41957
|
-
|
|
42058
|
+
moment4.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate()
|
|
41958
42059
|
]
|
|
41959
42060
|
};
|
|
41960
42061
|
cacheOptions.startDate = normalizedStartDate;
|
|
@@ -41962,7 +42063,7 @@ function useAttendanceRepository() {
|
|
|
41962
42063
|
query2.$expr = {
|
|
41963
42064
|
$lte: [
|
|
41964
42065
|
{ $toDate: "$checkIn.timestamp" },
|
|
41965
|
-
|
|
42066
|
+
moment4.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate()
|
|
41966
42067
|
]
|
|
41967
42068
|
};
|
|
41968
42069
|
cacheOptions.endDate = normalizedEndDate;
|
|
@@ -42075,11 +42176,11 @@ function useAttendanceRepository() {
|
|
|
42075
42176
|
cacheOptions.search = search;
|
|
42076
42177
|
}
|
|
42077
42178
|
const singaporeTz = "Asia/Singapore";
|
|
42078
|
-
const normalizedStartDate = typeof startDate === "string" ? startDate :
|
|
42079
|
-
const normalizedEndDate = typeof endDate === "string" ? endDate :
|
|
42179
|
+
const normalizedStartDate = typeof startDate === "string" ? startDate : moment4(startDate).tz(singaporeTz).format("YYYY-MM-DD");
|
|
42180
|
+
const normalizedEndDate = typeof endDate === "string" ? endDate : moment4(endDate).tz(singaporeTz).format("YYYY-MM-DD");
|
|
42080
42181
|
if (startDate && endDate) {
|
|
42081
|
-
const startOfDay =
|
|
42082
|
-
const endOfDay =
|
|
42182
|
+
const startOfDay = moment4.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate();
|
|
42183
|
+
const endOfDay = moment4.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate();
|
|
42083
42184
|
query2.$expr = {
|
|
42084
42185
|
$and: [
|
|
42085
42186
|
{ $gte: [{ $toDate: "$checkIn.timestamp" }, startOfDay] },
|
|
@@ -42092,7 +42193,7 @@ function useAttendanceRepository() {
|
|
|
42092
42193
|
query2.$expr = {
|
|
42093
42194
|
$gte: [
|
|
42094
42195
|
{ $toDate: "$checkIn.timestamp" },
|
|
42095
|
-
|
|
42196
|
+
moment4.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate()
|
|
42096
42197
|
]
|
|
42097
42198
|
};
|
|
42098
42199
|
cacheOptions.startDate = normalizedStartDate;
|
|
@@ -42100,7 +42201,7 @@ function useAttendanceRepository() {
|
|
|
42100
42201
|
query2.$expr = {
|
|
42101
42202
|
$lte: [
|
|
42102
42203
|
{ $toDate: "$checkIn.timestamp" },
|
|
42103
|
-
|
|
42204
|
+
moment4.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate()
|
|
42104
42205
|
]
|
|
42105
42206
|
};
|
|
42106
42207
|
cacheOptions.endDate = normalizedEndDate;
|
|
@@ -51857,6 +51958,16 @@ function useVisitorTransactionService() {
|
|
|
51857
51958
|
);
|
|
51858
51959
|
const isAutoApprovedInvitation = settings?.isAutoApprovedInvitation === true;
|
|
51859
51960
|
value.checkIn = null;
|
|
51961
|
+
if (!value.arrivalDate && value.expectedCheckIn) {
|
|
51962
|
+
let timezone;
|
|
51963
|
+
try {
|
|
51964
|
+
const site = await _getSiteById(inviter?.site);
|
|
51965
|
+
timezone = resolveSiteTimezone(site);
|
|
51966
|
+
} catch {
|
|
51967
|
+
timezone = resolveSiteTimezone(null);
|
|
51968
|
+
}
|
|
51969
|
+
value.arrivalDate = siteDayBounds(value.expectedCheckIn, timezone)?.date ?? null;
|
|
51970
|
+
}
|
|
51860
51971
|
const payload = {
|
|
51861
51972
|
...value,
|
|
51862
51973
|
block: inviter?.block?.toString(),
|
|
@@ -51917,18 +52028,31 @@ function useVisitorTransactionService() {
|
|
|
51917
52028
|
}
|
|
51918
52029
|
try {
|
|
51919
52030
|
session.startTransaction();
|
|
52031
|
+
const refId = (value) => {
|
|
52032
|
+
if (!value)
|
|
52033
|
+
return void 0;
|
|
52034
|
+
const id = typeof value === "object" && "_id" in value ? value._id : value;
|
|
52035
|
+
return id ? String(id) : void 0;
|
|
52036
|
+
};
|
|
51920
52037
|
const memberPayload = {
|
|
51921
|
-
block:
|
|
51922
|
-
level:
|
|
51923
|
-
unit:
|
|
51924
|
-
|
|
51925
|
-
|
|
51926
|
-
|
|
52038
|
+
block: refId(lead.block),
|
|
52039
|
+
level: refId(lead.level),
|
|
52040
|
+
unit: refId(lead.unit),
|
|
52041
|
+
// The same $lookup leaves the unit's name on the joined object, which
|
|
52042
|
+
// is the better source when the stored scalar is absent.
|
|
52043
|
+
unitName: lead.unitName ?? lead.unit?.name,
|
|
52044
|
+
org: refId(lead.org),
|
|
52045
|
+
site: refId(lead.site),
|
|
51927
52046
|
type: lead.type,
|
|
51928
52047
|
contractorType: lead.contractorType,
|
|
51929
52048
|
company: lead.company,
|
|
51930
52049
|
purpose: lead.purpose,
|
|
51931
52050
|
expectedCheckIn: lead.expectedCheckIn ? new Date(lead.expectedCheckIn).toISOString() : void 0,
|
|
52051
|
+
// Carried so each member's QR is gated on the same calendar day as the
|
|
52052
|
+
// lead's. Without it a member falls back to deriving the day from
|
|
52053
|
+
// `expectedCheckIn`, which is the same answer today but drifts the
|
|
52054
|
+
// moment the lead's day is edited.
|
|
52055
|
+
arrivalDate: lead.arrivalDate,
|
|
51932
52056
|
arrivalTime: lead.arrivalTime,
|
|
51933
52057
|
duration: lead.duration,
|
|
51934
52058
|
isOvernightParking: lead.isOvernightParking,
|
|
@@ -52020,7 +52144,7 @@ function useVisitorTransactionService() {
|
|
|
52020
52144
|
|
|
52021
52145
|
// src/controllers/visitor-transaction.controller.ts
|
|
52022
52146
|
import Joi67 from "joi";
|
|
52023
|
-
import
|
|
52147
|
+
import moment5 from "moment-timezone";
|
|
52024
52148
|
import { ObjectId as ObjectId88 } from "mongodb";
|
|
52025
52149
|
import { BadRequestError as BadRequestError123, NotFoundError as NotFoundError36, InternalServerError as InternalServerError44, logger as logger94 } from "@7365admin1/node-server-utils";
|
|
52026
52150
|
|
|
@@ -52028,6 +52152,15 @@ import { BadRequestError as BadRequestError123, NotFoundError as NotFoundError36
|
|
|
52028
52152
|
import Joi66 from "joi";
|
|
52029
52153
|
var schemaInviteVisitor = Joi66.object({
|
|
52030
52154
|
expectedCheckIn: Joi66.string().isoDate().required(),
|
|
52155
|
+
// The calendar day the invitation is valid for, as the resident picked it.
|
|
52156
|
+
// A bare YYYY-MM-DD carries no offset, so no conversion between the phone's
|
|
52157
|
+
// zone and the site's can move it onto a neighbouring day - which is exactly
|
|
52158
|
+
// what `expectedCheckIn` alone cannot guarantee. Optional so that already
|
|
52159
|
+
// installed builds, which send only `expectedCheckIn`, keep working; the
|
|
52160
|
+
// server falls back to deriving the day from it in the site's zone.
|
|
52161
|
+
arrivalDate: Joi66.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow(null, "").messages({
|
|
52162
|
+
"string.pattern.base": "arrivalDate must be in YYYY-MM-DD format (e.g. 2026-09-02)"
|
|
52163
|
+
}),
|
|
52031
52164
|
arrivalTime: Joi66.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
|
|
52032
52165
|
"string.pattern.base": "arrivalTime must be in HH:mm format (e.g. 09:30, 18:45)"
|
|
52033
52166
|
}),
|
|
@@ -56100,7 +56233,7 @@ async function sendSelfServicePassEmail(record, occasion, remarks) {
|
|
|
56100
56233
|
if (!to)
|
|
56101
56234
|
return;
|
|
56102
56235
|
const previewLink = `${APP_PROPERTY_MANAGEMENT}/public-view/visitor-onboarding/pass/${String(record._id ?? "")}`;
|
|
56103
|
-
const arrivalDate = record.expectedCheckIn ?
|
|
56236
|
+
const arrivalDate = record.expectedCheckIn ? moment5(record.expectedCheckIn).format("DD/MM/YYYY") : "N/A";
|
|
56104
56237
|
const html = occasion === "rejected" ? compile_handlebars_default({
|
|
56105
56238
|
handlebar: "self-service-visitor-rejected",
|
|
56106
56239
|
context: {
|
|
@@ -56648,6 +56781,7 @@ function useVisitorTransactionController() {
|
|
|
56648
56781
|
}
|
|
56649
56782
|
const {
|
|
56650
56783
|
expectedCheckIn,
|
|
56784
|
+
arrivalDate,
|
|
56651
56785
|
arrivalTime,
|
|
56652
56786
|
duration,
|
|
56653
56787
|
name,
|
|
@@ -56665,6 +56799,10 @@ function useVisitorTransactionController() {
|
|
|
56665
56799
|
} = value;
|
|
56666
56800
|
const rest = {
|
|
56667
56801
|
expectedCheckIn,
|
|
56802
|
+
// Fall back to the day `expectedCheckIn` lands on in the SITE's zone, so
|
|
56803
|
+
// rows written by older builds still carry an explicit day. Resolved in
|
|
56804
|
+
// the invite service, which is where the site id is known.
|
|
56805
|
+
arrivalDate,
|
|
56668
56806
|
arrivalTime,
|
|
56669
56807
|
duration,
|
|
56670
56808
|
name,
|
|
@@ -77390,10 +77528,10 @@ import {
|
|
|
77390
77528
|
useAtlas as useAtlas116
|
|
77391
77529
|
} from "@7365admin1/node-server-utils";
|
|
77392
77530
|
import { ObjectId as ObjectId147 } from "mongodb";
|
|
77393
|
-
import
|
|
77531
|
+
import moment7 from "moment";
|
|
77394
77532
|
|
|
77395
77533
|
// src/utils/dashboard-metrics.util.ts
|
|
77396
|
-
import
|
|
77534
|
+
import moment6 from "moment-timezone";
|
|
77397
77535
|
var DASHBOARD_TIMEZONE = "Asia/Singapore";
|
|
77398
77536
|
var PERIOD_UNITS = {
|
|
77399
77537
|
thisWeek: { boundary: "isoWeek", step: "week" },
|
|
@@ -77404,7 +77542,7 @@ function unitsOf(period) {
|
|
|
77404
77542
|
return PERIOD_UNITS[period] ?? DAY_UNIT;
|
|
77405
77543
|
}
|
|
77406
77544
|
function at(now) {
|
|
77407
|
-
return now === void 0 || now === null ?
|
|
77545
|
+
return now === void 0 || now === null ? moment6.tz(DASHBOARD_TIMEZONE) : moment6.tz(now, DASHBOARD_TIMEZONE);
|
|
77408
77546
|
}
|
|
77409
77547
|
function getPeriodRange(period, now) {
|
|
77410
77548
|
const { boundary } = unitsOf(period);
|
|
@@ -77792,8 +77930,8 @@ function useNewDashboardRepo() {
|
|
|
77792
77930
|
activePatrolLogs.map(async (log) => {
|
|
77793
77931
|
const person = await getPatrolLogPerson(log);
|
|
77794
77932
|
const status = getPatrolLogStatus(log);
|
|
77795
|
-
const logTime =
|
|
77796
|
-
const logDate =
|
|
77933
|
+
const logTime = moment7(log.createdAt).tz("Asia/Singapore").format("HH:mm");
|
|
77934
|
+
const logDate = moment7(log.createdAt).tz("Asia/Singapore").format("DD/MM/YYYY");
|
|
77797
77935
|
return {
|
|
77798
77936
|
id: log._id.toString(),
|
|
77799
77937
|
title: log.name,
|
|
@@ -77852,8 +77990,8 @@ function useNewDashboardRepo() {
|
|
|
77852
77990
|
}
|
|
77853
77991
|
async function getPropertyManagementDashboard(siteId, period = "today" /* TODAY */, type, facility) {
|
|
77854
77992
|
const siteIdObj = toObjectId18(siteId);
|
|
77855
|
-
const startOfToday =
|
|
77856
|
-
const endOfToday =
|
|
77993
|
+
const startOfToday = moment7.tz("Asia/Singapore").startOf("day").toDate();
|
|
77994
|
+
const endOfToday = moment7.tz("Asia/Singapore").endOf("day").toDate();
|
|
77857
77995
|
const facilityPeriodRange = getPeriodRange(period);
|
|
77858
77996
|
const facilityPriorRange = getPreviousPeriodRange(period);
|
|
77859
77997
|
const facilityCurrentStart = facilityPeriodRange.$gte;
|
|
@@ -78479,28 +78617,28 @@ function useNewDashboardRepo() {
|
|
|
78479
78617
|
let labels = [];
|
|
78480
78618
|
let getIntervalIndex;
|
|
78481
78619
|
if (period === "today" /* TODAY */) {
|
|
78482
|
-
rangeStart =
|
|
78483
|
-
rangeEnd =
|
|
78620
|
+
rangeStart = moment7.tz("Asia/Singapore").startOf("day").toDate();
|
|
78621
|
+
rangeEnd = moment7.tz("Asia/Singapore").endOf("day").toDate();
|
|
78484
78622
|
labels = ["12 AM", "4 AM", "8 AM", "12 PM", "4 PM", "8 PM"];
|
|
78485
78623
|
getIntervalIndex = (date) => {
|
|
78486
|
-
const hour =
|
|
78624
|
+
const hour = moment7(date).tz("Asia/Singapore").hour();
|
|
78487
78625
|
return Math.floor(hour / 4);
|
|
78488
78626
|
};
|
|
78489
78627
|
} else if (period === "thisWeek" /* THIS_WEEK */) {
|
|
78490
|
-
rangeStart =
|
|
78491
|
-
rangeEnd =
|
|
78628
|
+
rangeStart = moment7.tz("Asia/Singapore").startOf("isoWeek").toDate();
|
|
78629
|
+
rangeEnd = moment7.tz("Asia/Singapore").endOf("isoWeek").toDate();
|
|
78492
78630
|
labels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
78493
78631
|
getIntervalIndex = (date) => {
|
|
78494
|
-
const day =
|
|
78632
|
+
const day = moment7(date).tz("Asia/Singapore").isoWeekday();
|
|
78495
78633
|
return day - 1;
|
|
78496
78634
|
};
|
|
78497
78635
|
} else if (period === "thisMonth" /* THIS_MONTH */) {
|
|
78498
|
-
rangeStart =
|
|
78499
|
-
rangeEnd =
|
|
78500
|
-
const daysInMonth =
|
|
78636
|
+
rangeStart = moment7.tz("Asia/Singapore").startOf("month").toDate();
|
|
78637
|
+
rangeEnd = moment7.tz("Asia/Singapore").endOf("month").toDate();
|
|
78638
|
+
const daysInMonth = moment7.tz("Asia/Singapore").daysInMonth();
|
|
78501
78639
|
labels = Array.from({ length: daysInMonth }, (_, i) => String(i + 1));
|
|
78502
78640
|
getIntervalIndex = (date) => {
|
|
78503
|
-
return
|
|
78641
|
+
return moment7(date).tz("Asia/Singapore").date() - 1;
|
|
78504
78642
|
};
|
|
78505
78643
|
} else {
|
|
78506
78644
|
throw new BadRequestError208("Invalid period.");
|
|
@@ -79144,7 +79282,7 @@ import {
|
|
|
79144
79282
|
|
|
79145
79283
|
// src/utils/hrmlabs-attendance.util.ts
|
|
79146
79284
|
import axios3 from "axios";
|
|
79147
|
-
import
|
|
79285
|
+
import moment8 from "moment-timezone";
|
|
79148
79286
|
var default_early_checkIn = 4;
|
|
79149
79287
|
async function hrmLabsAuthentication({
|
|
79150
79288
|
authUrl,
|
|
@@ -79216,13 +79354,13 @@ function filterByShiftTime(attendance, shiftData, timezone, format2) {
|
|
|
79216
79354
|
return attendance.filter((item) => {
|
|
79217
79355
|
if (!item.checkIn)
|
|
79218
79356
|
return false;
|
|
79219
|
-
const checkInLocal =
|
|
79357
|
+
const checkInLocal = moment8(item.checkIn, format2);
|
|
79220
79358
|
if (!checkInLocal.isValid())
|
|
79221
79359
|
return false;
|
|
79222
79360
|
const [startHour, startMinute] = shiftData.checkIn.split(":").map(Number);
|
|
79223
79361
|
const [endHour, endMinute] = shiftData.checkOut.split(":").map(Number);
|
|
79224
|
-
const shiftStart =
|
|
79225
|
-
const shiftEnd =
|
|
79362
|
+
const shiftStart = moment8(checkInLocal).set({ hour: startHour, minute: startMinute, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
|
|
79363
|
+
const shiftEnd = moment8(checkInLocal).set({
|
|
79226
79364
|
hour: endHour,
|
|
79227
79365
|
minute: endMinute,
|
|
79228
79366
|
second: 0,
|
|
@@ -79314,18 +79452,18 @@ function totalCountPerShift(attendance, shiftData, timezone, format2) {
|
|
|
79314
79452
|
data = uniqueAttendanceData.filter((item) => {
|
|
79315
79453
|
if (!item.checkIn)
|
|
79316
79454
|
return false;
|
|
79317
|
-
const checkInLocal =
|
|
79455
|
+
const checkInLocal = moment8(item.checkIn, format2);
|
|
79318
79456
|
if (!checkInLocal.isValid())
|
|
79319
79457
|
return false;
|
|
79320
79458
|
const [startHour, startMinute] = shift.checkIn.split(":").map(Number);
|
|
79321
79459
|
const [endHour, endMinute] = shift.checkOut.split(":").map(Number);
|
|
79322
|
-
const shiftStart =
|
|
79460
|
+
const shiftStart = moment8(checkInLocal).set({
|
|
79323
79461
|
hour: startHour,
|
|
79324
79462
|
minute: startMinute,
|
|
79325
79463
|
second: 0,
|
|
79326
79464
|
millisecond: 0
|
|
79327
79465
|
}).subtract(default_early_checkIn, "hour");
|
|
79328
|
-
const shiftEnd =
|
|
79466
|
+
const shiftEnd = moment8(checkInLocal).set({
|
|
79329
79467
|
hour: endHour,
|
|
79330
79468
|
minute: endMinute,
|
|
79331
79469
|
second: 0,
|
|
@@ -79355,11 +79493,11 @@ function filterByStatus(attendance, shiftData, timezone, format2, status) {
|
|
|
79355
79493
|
return attendance.filter((item) => {
|
|
79356
79494
|
if (!item.checkIn)
|
|
79357
79495
|
return false;
|
|
79358
|
-
const checkInLocal =
|
|
79496
|
+
const checkInLocal = moment8(item.checkIn, format2);
|
|
79359
79497
|
if (!checkInLocal.isValid())
|
|
79360
79498
|
return false;
|
|
79361
79499
|
const [lateHour, lateMinute] = shiftData.lateCheckInAlert.split(":").map(Number);
|
|
79362
|
-
const lateLoginTime =
|
|
79500
|
+
const lateLoginTime = moment8(checkInLocal).set({
|
|
79363
79501
|
hour: lateHour,
|
|
79364
79502
|
minute: lateMinute,
|
|
79365
79503
|
second: 0,
|
|
@@ -79431,14 +79569,14 @@ async function totalCountPerStatus(attendance, shiftName, shiftData, timezone, f
|
|
|
79431
79569
|
} = item;
|
|
79432
79570
|
if (!checkInStr || seenGlobal.has(identificationNumber))
|
|
79433
79571
|
continue;
|
|
79434
|
-
const checkIn =
|
|
79435
|
-
const checkOut = checkOutStr ?
|
|
79436
|
-
const checkOutChecker = checkOut ?
|
|
79572
|
+
const checkIn = moment8(checkInStr, format2);
|
|
79573
|
+
const checkOut = checkOutStr ? moment8(checkOutStr, format2) : null;
|
|
79574
|
+
const checkOutChecker = checkOut ? moment8(checkOutStr, format2) : checkIn;
|
|
79437
79575
|
if (!checkIn.isValid())
|
|
79438
79576
|
continue;
|
|
79439
|
-
const shiftStart =
|
|
79440
|
-
const shiftEnd =
|
|
79441
|
-
const lateCheckIn =
|
|
79577
|
+
const shiftStart = moment8(checkIn).set({ ...shiftStartTime, second: 59, millisecond: 59 }).subtract(default_early_checkIn, "hour");
|
|
79578
|
+
const shiftEnd = moment8(checkOutChecker).set({ ...shiftEndTime, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
|
|
79579
|
+
const lateCheckIn = moment8(checkIn).set({
|
|
79442
79580
|
...lateTime,
|
|
79443
79581
|
second: 59,
|
|
79444
79582
|
millisecond: 59
|
|
@@ -79476,8 +79614,8 @@ async function chartCountData(attendance, shiftData, timezone, format2, totalShi
|
|
|
79476
79614
|
const [hour, minute] = timeStr.split(":").map(Number);
|
|
79477
79615
|
return { hour, minute };
|
|
79478
79616
|
};
|
|
79479
|
-
const startDate =
|
|
79480
|
-
const endDate =
|
|
79617
|
+
const startDate = moment8(startDateStr, "DD-MM-YYYY");
|
|
79618
|
+
const endDate = moment8(endDateStr, "DD-MM-YYYY");
|
|
79481
79619
|
const daysInRange = [];
|
|
79482
79620
|
for (let day = startDate.clone(); day.isSameOrBefore(endDate); day.add(1, "day")) {
|
|
79483
79621
|
daysInRange.push(day.format("DD-MM-YYYY"));
|
|
@@ -79548,7 +79686,7 @@ async function chartCountData(attendance, shiftData, timezone, format2, totalShi
|
|
|
79548
79686
|
} = item;
|
|
79549
79687
|
if (!checkInStr)
|
|
79550
79688
|
continue;
|
|
79551
|
-
const checkIn =
|
|
79689
|
+
const checkIn = moment8(checkInStr, format2);
|
|
79552
79690
|
if (!checkIn.isValid())
|
|
79553
79691
|
continue;
|
|
79554
79692
|
const dayKey = `${identificationNumber}-${checkIn.format(
|
|
@@ -79557,10 +79695,10 @@ async function chartCountData(attendance, shiftData, timezone, format2, totalShi
|
|
|
79557
79695
|
if (seenPerDay.has(dayKey))
|
|
79558
79696
|
continue;
|
|
79559
79697
|
seenPerDay.add(dayKey);
|
|
79560
|
-
const checkOut = checkOutStr ?
|
|
79561
|
-
const shiftStart =
|
|
79562
|
-
const shiftEnd =
|
|
79563
|
-
const lateCheckIn =
|
|
79698
|
+
const checkOut = checkOutStr ? moment8(checkOutStr, format2) : checkIn;
|
|
79699
|
+
const shiftStart = moment8(checkIn).set({ ...shiftStartTime, second: 59, millisecond: 59 }).subtract(default_early_checkIn, "hour");
|
|
79700
|
+
const shiftEnd = moment8(checkOut).set({ ...shiftEndTime, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
|
|
79701
|
+
const lateCheckIn = moment8(checkIn).set({
|
|
79564
79702
|
...lateTime,
|
|
79565
79703
|
second: 59,
|
|
79566
79704
|
millisecond: 59
|
|
@@ -79873,7 +80011,7 @@ var MManpowerRemarks = class {
|
|
|
79873
80011
|
|
|
79874
80012
|
// src/repositories/manpower-remarks.repo.ts
|
|
79875
80013
|
import { ObjectId as ObjectId151 } from "mongodb";
|
|
79876
|
-
import
|
|
80014
|
+
import moment9 from "moment-timezone";
|
|
79877
80015
|
function useManpowerRemarksRepo() {
|
|
79878
80016
|
const db2 = useAtlas118.getDb();
|
|
79879
80017
|
if (!db2) {
|
|
@@ -79927,7 +80065,7 @@ function useManpowerRemarksRepo() {
|
|
|
79927
80065
|
page = page ? page - 1 : 0;
|
|
79928
80066
|
limit = limit || 10;
|
|
79929
80067
|
const searchQuery = {};
|
|
79930
|
-
const nowSGT =
|
|
80068
|
+
const nowSGT = moment9().tz("Asia/Singapore");
|
|
79931
80069
|
searchQuery.serviceProviderId = new ObjectId151(serviceProviderId);
|
|
79932
80070
|
if (search != "") {
|
|
79933
80071
|
searchQuery.siteName = { $regex: search, $options: "i" };
|
|
@@ -80039,7 +80177,7 @@ function useManpowerRemarksRepo() {
|
|
|
80039
80177
|
}
|
|
80040
80178
|
|
|
80041
80179
|
// src/services/manpower-monitoring.service.ts
|
|
80042
|
-
import
|
|
80180
|
+
import moment10 from "moment-timezone";
|
|
80043
80181
|
function useManpowerMonitoringSrvc() {
|
|
80044
80182
|
const {
|
|
80045
80183
|
createManpowerMonitoringSettings: _createManpowerMonitoringSettings
|
|
@@ -80057,10 +80195,10 @@ function useManpowerMonitoringSrvc() {
|
|
|
80057
80195
|
const morningAlertFrequencyMins = payload?.shifts?.[payload.shiftType][0]?.alertFrequencyMins;
|
|
80058
80196
|
const afternoonAlertFrequencyMins = payload.shiftType == "3-shifts" ? payload?.shifts?.[payload.shiftType][1]?.alertFrequencyMins : null;
|
|
80059
80197
|
const nightAlertFrequencyMins = payload.shiftType == "3-shifts" ? payload?.shifts?.[payload.shiftType][2]?.alertFrequencyMins : payload?.shifts?.[payload.shiftType][1]?.alertFrequencyMins;
|
|
80060
|
-
const morningAlertTime =
|
|
80061
|
-
const afternoonAlertTime = afternoonCheckInTime ?
|
|
80062
|
-
const nightAlertTime =
|
|
80063
|
-
const nowSGT =
|
|
80198
|
+
const morningAlertTime = moment10.tz(morningCheckInTime, "HH:mm", "Asia/Singapore").add(morningAlertFrequencyMins, "minutes").format("HH:mm");
|
|
80199
|
+
const afternoonAlertTime = afternoonCheckInTime ? moment10.tz(afternoonCheckInTime, "HH:mm", "Asia/Singapore").add(afternoonAlertFrequencyMins, "minutes").format("HH:mm") : "";
|
|
80200
|
+
const nightAlertTime = moment10.tz(nightCheckInTime, "HH:mm", "Asia/Singapore").add(nightAlertFrequencyMins, "minutes").format("HH:mm");
|
|
80201
|
+
const nowSGT = moment10().tz("Asia/Singapore");
|
|
80064
80202
|
try {
|
|
80065
80203
|
const remarksPayload = {
|
|
80066
80204
|
siteId: payload.siteId,
|
|
@@ -82472,7 +82610,7 @@ import {
|
|
|
82472
82610
|
logger as logger192
|
|
82473
82611
|
} from "@7365admin1/node-server-utils";
|
|
82474
82612
|
import { ObjectId as ObjectId156 } from "mongodb";
|
|
82475
|
-
import
|
|
82613
|
+
import moment11 from "moment-timezone";
|
|
82476
82614
|
var createManpowerRemarksDaily = async () => {
|
|
82477
82615
|
const db2 = useAtlas126.getDb();
|
|
82478
82616
|
if (!db2) {
|
|
@@ -82483,9 +82621,9 @@ var createManpowerRemarksDaily = async () => {
|
|
|
82483
82621
|
const remarks = db2.collection("manpower-remarks");
|
|
82484
82622
|
const serviceProviders = db2.collection("site.service-providers");
|
|
82485
82623
|
const items = [];
|
|
82486
|
-
const yesterday =
|
|
82624
|
+
const yesterday = moment11().tz("Asia/Singapore").subtract(1, "days").format("DD-MM-YYYY");
|
|
82487
82625
|
try {
|
|
82488
|
-
const nowSGT =
|
|
82626
|
+
const nowSGT = moment11().tz("Asia/Singapore");
|
|
82489
82627
|
const servideProvider = await serviceProviders.findOne({
|
|
82490
82628
|
name: { $regex: process.env.HRMLABS_DOMAIN, $options: "i" }
|
|
82491
82629
|
});
|
|
@@ -82523,9 +82661,9 @@ var createManpowerRemarksDaily = async () => {
|
|
|
82523
82661
|
const morningAlertFrequencyMins = setting?.shifts?.[shiftType][0]?.alertFrequencyMins;
|
|
82524
82662
|
const afternoonAlertFrequencyMins = shiftType == "3-shifts" ? setting?.shifts?.[shiftType][1]?.alertFrequencyMins : null;
|
|
82525
82663
|
const nightAlertFrequencyMins = shiftType == "3-shifts" ? setting?.shifts?.[shiftType][2]?.alertFrequencyMins : setting?.shifts?.[shiftType][1]?.alertFrequencyMins;
|
|
82526
|
-
const morningAlertTime =
|
|
82527
|
-
const afternoonAlertTime = afternoonCheckInTime ?
|
|
82528
|
-
const nightAlertTime =
|
|
82664
|
+
const morningAlertTime = moment11.tz(morningCheckInTime, "HH:mm", "Asia/Singapore").add(morningAlertFrequencyMins, "minutes").format("HH:mm");
|
|
82665
|
+
const afternoonAlertTime = afternoonCheckInTime ? moment11.tz(afternoonCheckInTime, "HH:mm", "Asia/Singapore").add(afternoonAlertFrequencyMins, "minutes").format("HH:mm") : "";
|
|
82666
|
+
const nightAlertTime = moment11.tz(nightCheckInTime, "HH:mm", "Asia/Singapore").add(nightAlertFrequencyMins, "minutes").format("HH:mm");
|
|
82529
82667
|
const remark2 = {
|
|
82530
82668
|
siteId: site.siteId,
|
|
82531
82669
|
siteName: site.siteName,
|
|
@@ -82582,14 +82720,14 @@ var createManpowerRemarksDaily = async () => {
|
|
|
82582
82720
|
};
|
|
82583
82721
|
var updateRemarksisAcknowledged = async () => {
|
|
82584
82722
|
const { getAttendanceDataCount: _getAttendanceDataCount } = useHrmLabsAttendanceSrvc();
|
|
82585
|
-
const nowSGT =
|
|
82723
|
+
const nowSGT = moment11().tz("Asia/Singapore").format("DD-MM-YYYY");
|
|
82586
82724
|
const db2 = useAtlas126.getDb();
|
|
82587
82725
|
if (!db2) {
|
|
82588
82726
|
throw new Error("Unable to connect to server.");
|
|
82589
82727
|
}
|
|
82590
82728
|
const namespace_collection = "manpower-remarks";
|
|
82591
82729
|
const remarks = db2.collection(namespace_collection);
|
|
82592
|
-
const timeNow =
|
|
82730
|
+
const timeNow = moment11().tz("Asia/Singapore").format("HH:mm");
|
|
82593
82731
|
const settings = db2.collection("manpower-settings");
|
|
82594
82732
|
try {
|
|
82595
82733
|
const matchingDocs = await remarks.find({
|
|
@@ -82717,9 +82855,9 @@ var updateRemarksStatusEod = async () => {
|
|
|
82717
82855
|
}
|
|
82718
82856
|
const remarks = db2.collection("manpower-remarks");
|
|
82719
82857
|
const settings = db2.collection("manpower-settings");
|
|
82720
|
-
const nowSGT =
|
|
82721
|
-
const yesterdaySGT =
|
|
82722
|
-
const timeNow =
|
|
82858
|
+
const nowSGT = moment11().tz("Asia/Singapore").format("DD-MM-YYYY");
|
|
82859
|
+
const yesterdaySGT = moment11().tz("Asia/Singapore").subtract(1, "days").format("DD-MM-YYYY");
|
|
82860
|
+
const timeNow = moment11().tz("Asia/Singapore").format("HH:mm");
|
|
82723
82861
|
const docs = await remarks.find({
|
|
82724
82862
|
$or: [
|
|
82725
82863
|
// Morning & Afternoon from today
|
|
@@ -82855,7 +82993,7 @@ var isWithinHour = (alertTime, timeNow) => {
|
|
|
82855
82993
|
// src/events/manpower.event.ts
|
|
82856
82994
|
import { useAtlas as useAtlas127 } from "@7365admin1/node-server-utils";
|
|
82857
82995
|
import { ObjectId as ObjectId157 } from "mongodb";
|
|
82858
|
-
import
|
|
82996
|
+
import moment12 from "moment-timezone";
|
|
82859
82997
|
async function manpowerEvents(io) {
|
|
82860
82998
|
let intervalId = null;
|
|
82861
82999
|
let activeConnections = 0;
|
|
@@ -82867,9 +83005,9 @@ async function manpowerEvents(io) {
|
|
|
82867
83005
|
}
|
|
82868
83006
|
const remarks = db2.collection("manpower-remarks");
|
|
82869
83007
|
const settings = db2.collection("manpower-settings");
|
|
82870
|
-
const selectedDateMoment =
|
|
83008
|
+
const selectedDateMoment = moment12.tz(date, "DD-MM-YYYY", "Asia/Singapore");
|
|
82871
83009
|
const selectedDateSGT = selectedDateMoment.format("DD-MM-YYYY");
|
|
82872
|
-
const currentSGT =
|
|
83010
|
+
const currentSGT = moment12().tz("Asia/Singapore");
|
|
82873
83011
|
const docs = await remarks.find({
|
|
82874
83012
|
createdAtSGT: selectedDateSGT,
|
|
82875
83013
|
$or: [
|
|
@@ -82891,7 +83029,7 @@ async function manpowerEvents(io) {
|
|
|
82891
83029
|
}
|
|
82892
83030
|
if (currentSGT.isSame(selectedDateMoment, "day")) {
|
|
82893
83031
|
if (currentSGT.isSameOrAfter(
|
|
82894
|
-
|
|
83032
|
+
moment12.tz("19:55", "HH:mm", "Asia/Singapore")
|
|
82895
83033
|
)) {
|
|
82896
83034
|
shiftsToCheck.push({ index: 2, key: "nightShift" });
|
|
82897
83035
|
}
|
|
@@ -91457,6 +91595,7 @@ export {
|
|
|
91457
91595
|
CameraType,
|
|
91458
91596
|
ConsoleAuditAction,
|
|
91459
91597
|
ConsoleAuditTarget,
|
|
91598
|
+
DEFAULT_SITE_TIMEZONE,
|
|
91460
91599
|
DEVICE_STATUS,
|
|
91461
91600
|
DOBStatus,
|
|
91462
91601
|
DUPLICATE_TERMS_VERSION_MESSAGE,
|
|
@@ -91711,6 +91850,7 @@ export {
|
|
|
91711
91850
|
isSafeRelativePath,
|
|
91712
91851
|
isSuperAdmin,
|
|
91713
91852
|
isTermsCurrent,
|
|
91853
|
+
isValidTimezone,
|
|
91714
91854
|
manpowerDesignationsSchema,
|
|
91715
91855
|
manpowerEvents,
|
|
91716
91856
|
manpowerMonitoringSchema,
|
|
@@ -91730,6 +91870,7 @@ export {
|
|
|
91730
91870
|
occurrence_book_namespace_collection,
|
|
91731
91871
|
online_forms_namespace_collection,
|
|
91732
91872
|
orgSchema,
|
|
91873
|
+
orgSiteScope,
|
|
91733
91874
|
overnight_parking_requests_namespace_collection,
|
|
91734
91875
|
parseCameraChannel,
|
|
91735
91876
|
parseCameraHost,
|
|
@@ -91763,6 +91904,7 @@ export {
|
|
|
91763
91904
|
resolveDeviceHttp,
|
|
91764
91905
|
resolveHidPhysicalCardValue,
|
|
91765
91906
|
resolveInviteActor,
|
|
91907
|
+
resolveSiteTimezone,
|
|
91766
91908
|
robotSchema,
|
|
91767
91909
|
rtspUrl,
|
|
91768
91910
|
schema,
|
|
@@ -91919,6 +92061,7 @@ export {
|
|
|
91919
92061
|
sessionSchema,
|
|
91920
92062
|
setIO,
|
|
91921
92063
|
shiftSchema,
|
|
92064
|
+
siteDayBounds,
|
|
91922
92065
|
siteSchema,
|
|
91923
92066
|
site_people_namespace_collection,
|
|
91924
92067
|
snapshotEndpoint,
|