@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/dist/index.js CHANGED
@@ -5931,6 +5931,7 @@ __export(src_exports, {
5931
5931
  CameraType: () => CameraType,
5932
5932
  ConsoleAuditAction: () => ConsoleAuditAction,
5933
5933
  ConsoleAuditTarget: () => ConsoleAuditTarget,
5934
+ DEFAULT_SITE_TIMEZONE: () => DEFAULT_SITE_TIMEZONE,
5934
5935
  DEVICE_STATUS: () => DEVICE_STATUS,
5935
5936
  DOBStatus: () => DOBStatus,
5936
5937
  DUPLICATE_TERMS_VERSION_MESSAGE: () => DUPLICATE_TERMS_VERSION_MESSAGE,
@@ -6185,6 +6186,7 @@ __export(src_exports, {
6185
6186
  isSafeRelativePath: () => isSafeRelativePath,
6186
6187
  isSuperAdmin: () => isSuperAdmin,
6187
6188
  isTermsCurrent: () => isTermsCurrent,
6189
+ isValidTimezone: () => isValidTimezone,
6188
6190
  manpowerDesignationsSchema: () => manpowerDesignationsSchema,
6189
6191
  manpowerEvents: () => manpowerEvents,
6190
6192
  manpowerMonitoringSchema: () => manpowerMonitoringSchema,
@@ -6204,6 +6206,7 @@ __export(src_exports, {
6204
6206
  occurrence_book_namespace_collection: () => occurrence_book_namespace_collection,
6205
6207
  online_forms_namespace_collection: () => online_forms_namespace_collection,
6206
6208
  orgSchema: () => orgSchema,
6209
+ orgSiteScope: () => orgSiteScope,
6207
6210
  overnight_parking_requests_namespace_collection: () => overnight_parking_requests_namespace_collection,
6208
6211
  parseCameraChannel: () => parseCameraChannel,
6209
6212
  parseCameraHost: () => parseCameraHost,
@@ -6237,6 +6240,7 @@ __export(src_exports, {
6237
6240
  resolveDeviceHttp: () => resolveDeviceHttp,
6238
6241
  resolveHidPhysicalCardValue: () => resolveHidPhysicalCardValue,
6239
6242
  resolveInviteActor: () => resolveInviteActor,
6243
+ resolveSiteTimezone: () => resolveSiteTimezone,
6240
6244
  robotSchema: () => robotSchema,
6241
6245
  rtspUrl: () => rtspUrl,
6242
6246
  schema: () => schema,
@@ -6393,6 +6397,7 @@ __export(src_exports, {
6393
6397
  sessionSchema: () => sessionSchema,
6394
6398
  setIO: () => setIO,
6395
6399
  shiftSchema: () => shiftSchema,
6400
+ siteDayBounds: () => siteDayBounds,
6396
6401
  siteSchema: () => siteSchema,
6397
6402
  site_people_namespace_collection: () => site_people_namespace_collection,
6398
6403
  snapshotEndpoint: () => snapshotEndpoint,
@@ -12270,6 +12275,36 @@ var import_mongodb21 = require("mongodb");
12270
12275
  var import_node_server_utils22 = require("@7365admin1/node-server-utils");
12271
12276
  var import_joi9 = __toESM(require("joi"));
12272
12277
  var import_mongodb20 = require("mongodb");
12278
+
12279
+ // src/utils/site-timezone.util.ts
12280
+ var import_moment_timezone = __toESM(require("moment-timezone"));
12281
+ var DEFAULT_SITE_TIMEZONE = "Asia/Singapore";
12282
+ function isValidTimezone(tz) {
12283
+ return typeof tz === "string" && tz.length > 0 && !!import_moment_timezone.default.tz.zone(tz);
12284
+ }
12285
+ function resolveSiteTimezone(site) {
12286
+ const tz = site?.timezone;
12287
+ return isValidTimezone(tz) ? tz : DEFAULT_SITE_TIMEZONE;
12288
+ }
12289
+ function siteDayBounds(value, timezone) {
12290
+ if (!value)
12291
+ return null;
12292
+ const tz = isValidTimezone(timezone) ? timezone : DEFAULT_SITE_TIMEZONE;
12293
+ const isDateOnly = typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value);
12294
+ const m = isDateOnly ? import_moment_timezone.default.tz(value, "YYYY-MM-DD", tz) : typeof value === "string" ? import_moment_timezone.default.tz(value, import_moment_timezone.default.ISO_8601, tz) : import_moment_timezone.default.tz(value, tz);
12295
+ if (!m.isValid())
12296
+ return null;
12297
+ return {
12298
+ start: m.clone().startOf("day").toDate(),
12299
+ end: m.clone().endOf("day").toDate(),
12300
+ date: m.format("YYYY-MM-DD")
12301
+ };
12302
+ }
12303
+
12304
+ // src/models/site.model.ts
12305
+ function siteTimezoneValidator(value, helpers) {
12306
+ return isValidTimezone(value) ? value : helpers.error("any.invalid");
12307
+ }
12273
12308
  var addressSchema = import_joi9.default.object({
12274
12309
  line1: import_joi9.default.string().min(3).required(),
12275
12310
  line2: import_joi9.default.string().allow("", null),
@@ -12377,6 +12412,7 @@ var siteSchema = import_joi9.default.object({
12377
12412
  orgId: import_joi9.default.string().hex().required(),
12378
12413
  customerId: import_joi9.default.string().hex().optional().allow("", null),
12379
12414
  address: addressSchema.optional(),
12415
+ timezone: import_joi9.default.string().custom(siteTimezoneValidator, "IANA timezone").optional().default(DEFAULT_SITE_TIMEZONE),
12380
12416
  category: import_joi9.default.string().valid(...Object.values(SiteCategories)).default("commercial" /* COMMERCIAL */),
12381
12417
  deliveryCompanyList: import_joi9.default.array().items(import_joi9.default.string()).optional().allow(null),
12382
12418
  isOpenGate: import_joi9.default.boolean().optional().default(false),
@@ -12387,6 +12423,7 @@ var siteSchema = import_joi9.default.object({
12387
12423
  var updateSiteSchema = import_joi9.default.object({
12388
12424
  _id: import_joi9.default.string().hex().length(24).required(),
12389
12425
  address: updateAddressSchema.optional(),
12426
+ timezone: import_joi9.default.string().custom(siteTimezoneValidator, "IANA timezone").optional(),
12390
12427
  metadata: metadataSchema3.optional(),
12391
12428
  deliveryCompanyList: import_joi9.default.array().items(import_joi9.default.string().trim()).optional().allow(null),
12392
12429
  isOpenGate: import_joi9.default.boolean().optional().allow(null),
@@ -12415,6 +12452,7 @@ function MSite(value) {
12415
12452
  status: "active",
12416
12453
  createdAt: /* @__PURE__ */ new Date(),
12417
12454
  address: value.address,
12455
+ timezone: value.timezone ?? DEFAULT_SITE_TIMEZONE,
12418
12456
  category: value.category,
12419
12457
  deliveryCompanyList: value.deliveryCompanyList ?? [],
12420
12458
  isOpenGate: value.isOpenGate,
@@ -13671,7 +13709,8 @@ function useCustomerSiteRepo() {
13671
13709
  limit = 10,
13672
13710
  sort = {},
13673
13711
  org = "",
13674
- status = "active"
13712
+ status = "active",
13713
+ siteScope = null
13675
13714
  }, session) {
13676
13715
  page = page > 0 ? page - 1 : 0;
13677
13716
  try {
@@ -13691,6 +13730,11 @@ function useCustomerSiteRepo() {
13691
13730
  page,
13692
13731
  limit
13693
13732
  };
13733
+ if (siteScope) {
13734
+ const scoped = siteScope.filter((id) => import_mongodb24.ObjectId.isValid(id));
13735
+ query2.site = { $in: scoped.map((id) => new import_mongodb24.ObjectId(id)) };
13736
+ cacheOptions.siteScope = scoped.length ? [...scoped].sort().join(",") : "no-site";
13737
+ }
13694
13738
  if (search) {
13695
13739
  query2.$or = [{ name: { $regex: search, $options: "i" } }];
13696
13740
  cacheOptions.search = search;
@@ -13997,7 +14041,8 @@ var EMPTY = {
13997
14041
  name: "",
13998
14042
  isSuperAdmin: false,
13999
14043
  orgIds: [],
14000
- propertyManagementOrgIds: []
14044
+ propertyManagementOrgIds: [],
14045
+ memberships: []
14001
14046
  };
14002
14047
  async function resolveInviteActor(userId) {
14003
14048
  const id = userId?.toString() ?? "";
@@ -14024,12 +14069,36 @@ async function resolveInviteActor(userId) {
14024
14069
  )
14025
14070
  );
14026
14071
  const user = await db2.collection("users").findOne({ _id: new import_mongodb25.ObjectId(id) }, { projection: { name: 1 } });
14072
+ const memberRoleIds = Array.from(
14073
+ new Set(
14074
+ members.map((m) => m.role?.toString?.() ?? "").filter((r) => r && import_mongodb25.ObjectId.isValid(r))
14075
+ )
14076
+ );
14077
+ const orgLevelRoleIds = /* @__PURE__ */ new Set();
14078
+ if (memberRoleIds.length) {
14079
+ const memberRoles = await db2.collection("roles").find(
14080
+ {
14081
+ _id: { $in: memberRoleIds.map((r) => new import_mongodb25.ObjectId(r)) },
14082
+ ...LIVE_ROLE
14083
+ },
14084
+ { projection: { site: 1 } }
14085
+ ).toArray();
14086
+ for (const role of memberRoles) {
14087
+ if (!role.site)
14088
+ orgLevelRoleIds.add(role._id.toString());
14089
+ }
14090
+ }
14027
14091
  return {
14028
14092
  id,
14029
14093
  name: user?.name ?? adminMember?.name ?? "",
14030
14094
  isSuperAdmin: isSuperAdmin2,
14031
14095
  orgIds,
14032
- propertyManagementOrgIds
14096
+ propertyManagementOrgIds,
14097
+ memberships: members.map((m) => ({
14098
+ org: m.org?.toString?.() ?? "",
14099
+ siteId: m.siteId?.toString?.() ?? "",
14100
+ orgLevelRole: orgLevelRoleIds.has(m.role?.toString?.() ?? "")
14101
+ }))
14033
14102
  };
14034
14103
  }
14035
14104
  async function hasOrgInvitation(userId, orgId) {
@@ -19714,6 +19783,11 @@ var schemaVisitorTransaction = import_joi21.default.object({
19714
19783
  ).optional().allow(null),
19715
19784
  unitName: import_joi21.default.string().optional().allow(null, ""),
19716
19785
  expiredAt: import_joi21.default.date().iso().optional().allow(null, ""),
19786
+ // The calendar day this invitation is valid for, in the site's timezone.
19787
+ // Stored as a bare YYYY-MM-DD so no offset conversion can shift the day.
19788
+ arrivalDate: import_joi21.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow(null, "").messages({
19789
+ "string.pattern.base": "arrivalDate must be in YYYY-MM-DD format (e.g. 2026-09-02)"
19790
+ }),
19717
19791
  arrivalTime: import_joi21.default.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
19718
19792
  "string.pattern.base": "arrivalTime must be in HH:mm format (e.g. 09:30, 18:45)"
19719
19793
  }),
@@ -19775,6 +19849,11 @@ var schemaSelfServiceVisitor = import_joi21.default.object({
19775
19849
  // value through that schema via MVisitorTransaction(), and Joi.date()
19776
19850
  // would have already coerced it to a Date object by then, failing there.
19777
19851
  expectedCheckIn: import_joi21.default.string().isoDate().required(),
19852
+ // The calendar day this invitation is valid for, in the site's timezone.
19853
+ // Stored as a bare YYYY-MM-DD so no offset conversion can shift the day.
19854
+ arrivalDate: import_joi21.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow(null, "").messages({
19855
+ "string.pattern.base": "arrivalDate must be in YYYY-MM-DD format (e.g. 2026-09-02)"
19856
+ }),
19778
19857
  arrivalTime: import_joi21.default.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({ "string.pattern.base": "arrivalTime must be in HH:mm format" }),
19779
19858
  duration: import_joi21.default.number().integer().min(0).optional().allow(null, ""),
19780
19859
  isOvernightParking: import_joi21.default.boolean().optional().default(false),
@@ -19808,6 +19887,13 @@ var schemaSelfServiceVisitor = import_joi21.default.object({
19808
19887
  });
19809
19888
  var schemaUpdateVisTrans = import_joi21.default.object({
19810
19889
  _id: import_joi21.default.string().hex().length(24).required(),
19890
+ // Accepted here so a caller that moves `expectedCheckIn` can move the day
19891
+ // with it. Without this the two drift apart silently and the QR stays valid
19892
+ // on the ORIGINAL day, which is the failure the day-window work exists to
19893
+ // prevent.
19894
+ arrivalDate: import_joi21.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow(null, "").messages({
19895
+ "string.pattern.base": "arrivalDate must be in YYYY-MM-DD format (e.g. 2026-09-02)"
19896
+ }),
19811
19897
  name: import_joi21.default.string().optional().allow(null, ""),
19812
19898
  type: import_joi21.default.string().valid(...PERSON_TYPES).optional().allow(null, ""),
19813
19899
  org: import_joi21.default.string().hex().length(24).optional().allow(null, ""),
@@ -20038,6 +20124,7 @@ function MVisitorTransaction(value) {
20038
20124
  remarks: "",
20039
20125
  updatedBy: value.inviterId ?? ""
20040
20126
  } : null,
20127
+ arrivalDate: value.arrivalDate,
20041
20128
  arrivalTime: value.arrivalTime,
20042
20129
  duration: value.duration,
20043
20130
  members: value.members
@@ -20046,7 +20133,7 @@ function MVisitorTransaction(value) {
20046
20133
 
20047
20134
  // src/repositories/visitor-transaction.repo.ts
20048
20135
  var import_mongodb40 = require("mongodb");
20049
- var import_moment_timezone = __toESM(require("moment-timezone"));
20136
+ var import_moment_timezone2 = __toESM(require("moment-timezone"));
20050
20137
 
20051
20138
  // src/utils/compile-handlebars.ts
20052
20139
  var import_handlebars = __toESM(require_lib());
@@ -20877,7 +20964,7 @@ function useVisitorTransactionRepo() {
20877
20964
  const baseUrl = APP_MAIN;
20878
20965
  const qrLink = `${baseUrl}/resident/invite/register/${updatedDocument?._id}`;
20879
20966
  const logo = `${baseUrl}/images/resident/dark/seven-365.svg`;
20880
- const arrivalDate = updatedDocument?.expectedCheckIn ? (0, import_moment_timezone.default)(updatedDocument.expectedCheckIn).tz("Asia/Singapore").format("DD/MM/YYYY") : "No Arrival Date";
20967
+ const arrivalDate = updatedDocument?.expectedCheckIn ? (0, import_moment_timezone2.default)(updatedDocument.expectedCheckIn).tz("Asia/Singapore").format("DD/MM/YYYY") : "No Arrival Date";
20881
20968
  const isLead = !updatedDocument?.leadId;
20882
20969
  const memberRows = isLead && Array.isArray(updatedDocument?.members) ? updatedDocument.members.map((member, index) => ({
20883
20970
  position: index + 1,
@@ -24695,6 +24782,22 @@ function selectHealthTargets(cameraIds, cap, isValidId) {
24695
24782
  truncated: unique.length > limit
24696
24783
  };
24697
24784
  }
24785
+ function orgSiteScope(params) {
24786
+ const org = idOf(params.org);
24787
+ if (!org)
24788
+ return null;
24789
+ const inOrg = params.memberships.filter(
24790
+ (membership) => idOf(membership.org) === org
24791
+ );
24792
+ if (inOrg.some(
24793
+ (membership) => !idOf(membership.siteId) || membership.orgLevelRole === true
24794
+ )) {
24795
+ return null;
24796
+ }
24797
+ return Array.from(
24798
+ new Set(inOrg.map((membership) => idOf(membership.siteId)).filter(Boolean))
24799
+ );
24800
+ }
24698
24801
 
24699
24802
  // src/utils/camera-capability.util.ts
24700
24803
  var CAMERA_CAPABILITIES = [
@@ -40004,7 +40107,7 @@ var deleteVehicleRequestSchema = import_joi55.default.object({
40004
40107
  });
40005
40108
 
40006
40109
  // src/utils/vehicle-import.util.ts
40007
- var import_moment_timezone2 = __toESM(require("moment-timezone"));
40110
+ var import_moment_timezone3 = __toESM(require("moment-timezone"));
40008
40111
  var SITE_TIME_ZONE = "Asia/Singapore";
40009
40112
  var DEFAULT_YEARS = 10;
40010
40113
  var CELL_FORMATS = [
@@ -40016,13 +40119,13 @@ var CELL_FORMATS = [
40016
40119
  ];
40017
40120
  function parseExpiryDate(value) {
40018
40121
  if (!value) {
40019
- return import_moment_timezone2.default.tz(SITE_TIME_ZONE).add(DEFAULT_YEARS, "years").toISOString();
40122
+ return import_moment_timezone3.default.tz(SITE_TIME_ZONE).add(DEFAULT_YEARS, "years").toISOString();
40020
40123
  }
40021
- const wallClock = value instanceof Date ? import_moment_timezone2.default.utc(value).format("YYYY-MM-DDTHH:mm:ss") : String(value).trim();
40124
+ const wallClock = value instanceof Date ? import_moment_timezone3.default.utc(value).format("YYYY-MM-DDTHH:mm:ss") : String(value).trim();
40022
40125
  if (!wallClock) {
40023
- return import_moment_timezone2.default.tz(SITE_TIME_ZONE).add(DEFAULT_YEARS, "years").toISOString();
40126
+ return import_moment_timezone3.default.tz(SITE_TIME_ZONE).add(DEFAULT_YEARS, "years").toISOString();
40024
40127
  }
40025
- const parsed = import_moment_timezone2.default.tz(wallClock, CELL_FORMATS, SITE_TIME_ZONE);
40128
+ const parsed = import_moment_timezone3.default.tz(wallClock, CELL_FORMATS, SITE_TIME_ZONE);
40026
40129
  return parsed.isValid() ? parsed.toISOString() : void 0;
40027
40130
  }
40028
40131
 
@@ -41761,13 +41864,16 @@ function useCustomerSiteController() {
41761
41864
  });
41762
41865
  try {
41763
41866
  await requireOrgAccess(req, org);
41867
+ const actor = await resolveInviteActor(callerId(req));
41868
+ const siteScope = actor.isSuperAdmin ? null : orgSiteScope({ memberships: actor.memberships, org });
41764
41869
  const data = await _getAll({
41765
41870
  search,
41766
41871
  page,
41767
41872
  limit,
41768
41873
  sort: sortObj,
41769
41874
  org,
41770
- status
41875
+ status,
41876
+ siteScope
41771
41877
  });
41772
41878
  res.json(data);
41773
41879
  return;
@@ -42213,7 +42319,7 @@ function MAttendance(value) {
42213
42319
 
42214
42320
  // src/repositories/attendance.repository.ts
42215
42321
  var import_mongodb77 = require("mongodb");
42216
- var import_moment_timezone3 = __toESM(require("moment-timezone"));
42322
+ var import_moment_timezone4 = __toESM(require("moment-timezone"));
42217
42323
  var import_node_server_utils124 = require("@7365admin1/node-server-utils");
42218
42324
  function useAttendanceRepository() {
42219
42325
  const db2 = import_node_server_utils124.useAtlas.getDb();
@@ -42278,11 +42384,11 @@ function useAttendanceRepository() {
42278
42384
  cacheOptions.search = search;
42279
42385
  }
42280
42386
  const singaporeTz = "Asia/Singapore";
42281
- const normalizedStartDate = typeof startDate === "string" ? startDate : (0, import_moment_timezone3.default)(startDate).tz(singaporeTz).format("YYYY-MM-DD");
42282
- const normalizedEndDate = typeof endDate === "string" ? endDate : (0, import_moment_timezone3.default)(endDate).tz(singaporeTz).format("YYYY-MM-DD");
42387
+ const normalizedStartDate = typeof startDate === "string" ? startDate : (0, import_moment_timezone4.default)(startDate).tz(singaporeTz).format("YYYY-MM-DD");
42388
+ const normalizedEndDate = typeof endDate === "string" ? endDate : (0, import_moment_timezone4.default)(endDate).tz(singaporeTz).format("YYYY-MM-DD");
42283
42389
  if (startDate && endDate) {
42284
- const startOfDay = import_moment_timezone3.default.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate();
42285
- const endOfDay = import_moment_timezone3.default.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate();
42390
+ const startOfDay = import_moment_timezone4.default.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate();
42391
+ const endOfDay = import_moment_timezone4.default.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate();
42286
42392
  query2.$expr = {
42287
42393
  $and: [
42288
42394
  { $gte: [{ $toDate: "$checkIn.timestamp" }, startOfDay] },
@@ -42295,7 +42401,7 @@ function useAttendanceRepository() {
42295
42401
  query2.$expr = {
42296
42402
  $gte: [
42297
42403
  { $toDate: "$checkIn.timestamp" },
42298
- import_moment_timezone3.default.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate()
42404
+ import_moment_timezone4.default.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate()
42299
42405
  ]
42300
42406
  };
42301
42407
  cacheOptions.startDate = normalizedStartDate;
@@ -42303,7 +42409,7 @@ function useAttendanceRepository() {
42303
42409
  query2.$expr = {
42304
42410
  $lte: [
42305
42411
  { $toDate: "$checkIn.timestamp" },
42306
- import_moment_timezone3.default.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate()
42412
+ import_moment_timezone4.default.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate()
42307
42413
  ]
42308
42414
  };
42309
42415
  cacheOptions.endDate = normalizedEndDate;
@@ -42416,11 +42522,11 @@ function useAttendanceRepository() {
42416
42522
  cacheOptions.search = search;
42417
42523
  }
42418
42524
  const singaporeTz = "Asia/Singapore";
42419
- const normalizedStartDate = typeof startDate === "string" ? startDate : (0, import_moment_timezone3.default)(startDate).tz(singaporeTz).format("YYYY-MM-DD");
42420
- const normalizedEndDate = typeof endDate === "string" ? endDate : (0, import_moment_timezone3.default)(endDate).tz(singaporeTz).format("YYYY-MM-DD");
42525
+ const normalizedStartDate = typeof startDate === "string" ? startDate : (0, import_moment_timezone4.default)(startDate).tz(singaporeTz).format("YYYY-MM-DD");
42526
+ const normalizedEndDate = typeof endDate === "string" ? endDate : (0, import_moment_timezone4.default)(endDate).tz(singaporeTz).format("YYYY-MM-DD");
42421
42527
  if (startDate && endDate) {
42422
- const startOfDay = import_moment_timezone3.default.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate();
42423
- const endOfDay = import_moment_timezone3.default.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate();
42528
+ const startOfDay = import_moment_timezone4.default.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate();
42529
+ const endOfDay = import_moment_timezone4.default.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate();
42424
42530
  query2.$expr = {
42425
42531
  $and: [
42426
42532
  { $gte: [{ $toDate: "$checkIn.timestamp" }, startOfDay] },
@@ -42433,7 +42539,7 @@ function useAttendanceRepository() {
42433
42539
  query2.$expr = {
42434
42540
  $gte: [
42435
42541
  { $toDate: "$checkIn.timestamp" },
42436
- import_moment_timezone3.default.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate()
42542
+ import_moment_timezone4.default.tz(normalizedStartDate, "YYYY-MM-DD", singaporeTz).startOf("day").toDate()
42437
42543
  ]
42438
42544
  };
42439
42545
  cacheOptions.startDate = normalizedStartDate;
@@ -42441,7 +42547,7 @@ function useAttendanceRepository() {
42441
42547
  query2.$expr = {
42442
42548
  $lte: [
42443
42549
  { $toDate: "$checkIn.timestamp" },
42444
- import_moment_timezone3.default.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate()
42550
+ import_moment_timezone4.default.tz(normalizedEndDate, "YYYY-MM-DD", singaporeTz).endOf("day").toDate()
42445
42551
  ]
42446
42552
  };
42447
42553
  cacheOptions.endDate = normalizedEndDate;
@@ -52159,6 +52265,16 @@ function useVisitorTransactionService() {
52159
52265
  );
52160
52266
  const isAutoApprovedInvitation = settings?.isAutoApprovedInvitation === true;
52161
52267
  value.checkIn = null;
52268
+ if (!value.arrivalDate && value.expectedCheckIn) {
52269
+ let timezone;
52270
+ try {
52271
+ const site = await _getSiteById(inviter?.site);
52272
+ timezone = resolveSiteTimezone(site);
52273
+ } catch {
52274
+ timezone = resolveSiteTimezone(null);
52275
+ }
52276
+ value.arrivalDate = siteDayBounds(value.expectedCheckIn, timezone)?.date ?? null;
52277
+ }
52162
52278
  const payload = {
52163
52279
  ...value,
52164
52280
  block: inviter?.block?.toString(),
@@ -52219,18 +52335,31 @@ function useVisitorTransactionService() {
52219
52335
  }
52220
52336
  try {
52221
52337
  session.startTransaction();
52338
+ const refId = (value) => {
52339
+ if (!value)
52340
+ return void 0;
52341
+ const id = typeof value === "object" && "_id" in value ? value._id : value;
52342
+ return id ? String(id) : void 0;
52343
+ };
52222
52344
  const memberPayload = {
52223
- block: lead.block ? String(lead.block) : void 0,
52224
- level: lead.level ? String(lead.level) : void 0,
52225
- unit: lead.unit ? String(lead.unit) : void 0,
52226
- unitName: lead.unitName,
52227
- org: lead.org ? String(lead.org) : void 0,
52228
- site: lead.site ? String(lead.site) : void 0,
52345
+ block: refId(lead.block),
52346
+ level: refId(lead.level),
52347
+ unit: refId(lead.unit),
52348
+ // The same $lookup leaves the unit's name on the joined object, which
52349
+ // is the better source when the stored scalar is absent.
52350
+ unitName: lead.unitName ?? lead.unit?.name,
52351
+ org: refId(lead.org),
52352
+ site: refId(lead.site),
52229
52353
  type: lead.type,
52230
52354
  contractorType: lead.contractorType,
52231
52355
  company: lead.company,
52232
52356
  purpose: lead.purpose,
52233
52357
  expectedCheckIn: lead.expectedCheckIn ? new Date(lead.expectedCheckIn).toISOString() : void 0,
52358
+ // Carried so each member's QR is gated on the same calendar day as the
52359
+ // lead's. Without it a member falls back to deriving the day from
52360
+ // `expectedCheckIn`, which is the same answer today but drifts the
52361
+ // moment the lead's day is edited.
52362
+ arrivalDate: lead.arrivalDate,
52234
52363
  arrivalTime: lead.arrivalTime,
52235
52364
  duration: lead.duration,
52236
52365
  isOvernightParking: lead.isOvernightParking,
@@ -52322,7 +52451,7 @@ function useVisitorTransactionService() {
52322
52451
 
52323
52452
  // src/controllers/visitor-transaction.controller.ts
52324
52453
  var import_joi67 = __toESM(require("joi"));
52325
- var import_moment_timezone4 = __toESM(require("moment-timezone"));
52454
+ var import_moment_timezone5 = __toESM(require("moment-timezone"));
52326
52455
  var import_mongodb88 = require("mongodb");
52327
52456
  var import_node_server_utils137 = require("@7365admin1/node-server-utils");
52328
52457
 
@@ -52330,6 +52459,15 @@ var import_node_server_utils137 = require("@7365admin1/node-server-utils");
52330
52459
  var import_joi66 = __toESM(require("joi"));
52331
52460
  var schemaInviteVisitor = import_joi66.default.object({
52332
52461
  expectedCheckIn: import_joi66.default.string().isoDate().required(),
52462
+ // The calendar day the invitation is valid for, as the resident picked it.
52463
+ // A bare YYYY-MM-DD carries no offset, so no conversion between the phone's
52464
+ // zone and the site's can move it onto a neighbouring day - which is exactly
52465
+ // what `expectedCheckIn` alone cannot guarantee. Optional so that already
52466
+ // installed builds, which send only `expectedCheckIn`, keep working; the
52467
+ // server falls back to deriving the day from it in the site's zone.
52468
+ arrivalDate: import_joi66.default.string().pattern(/^\d{4}-\d{2}-\d{2}$/).optional().allow(null, "").messages({
52469
+ "string.pattern.base": "arrivalDate must be in YYYY-MM-DD format (e.g. 2026-09-02)"
52470
+ }),
52333
52471
  arrivalTime: import_joi66.default.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
52334
52472
  "string.pattern.base": "arrivalTime must be in HH:mm format (e.g. 09:30, 18:45)"
52335
52473
  }),
@@ -56398,7 +56536,7 @@ async function sendSelfServicePassEmail(record, occasion, remarks) {
56398
56536
  if (!to)
56399
56537
  return;
56400
56538
  const previewLink = `${APP_PROPERTY_MANAGEMENT}/public-view/visitor-onboarding/pass/${String(record._id ?? "")}`;
56401
- const arrivalDate = record.expectedCheckIn ? (0, import_moment_timezone4.default)(record.expectedCheckIn).format("DD/MM/YYYY") : "N/A";
56539
+ const arrivalDate = record.expectedCheckIn ? (0, import_moment_timezone5.default)(record.expectedCheckIn).format("DD/MM/YYYY") : "N/A";
56402
56540
  const html = occasion === "rejected" ? compile_handlebars_default({
56403
56541
  handlebar: "self-service-visitor-rejected",
56404
56542
  context: {
@@ -56946,6 +57084,7 @@ function useVisitorTransactionController() {
56946
57084
  }
56947
57085
  const {
56948
57086
  expectedCheckIn,
57087
+ arrivalDate,
56949
57088
  arrivalTime,
56950
57089
  duration,
56951
57090
  name,
@@ -56963,6 +57102,10 @@ function useVisitorTransactionController() {
56963
57102
  } = value;
56964
57103
  const rest = {
56965
57104
  expectedCheckIn,
57105
+ // Fall back to the day `expectedCheckIn` lands on in the SITE's zone, so
57106
+ // rows written by older builds still carry an explicit day. Resolved in
57107
+ // the invite service, which is where the site id is known.
57108
+ arrivalDate,
56966
57109
  arrivalTime,
56967
57110
  duration,
56968
57111
  name,
@@ -77362,7 +77505,7 @@ var import_mongodb147 = require("mongodb");
77362
77505
  var import_moment = __toESM(require("moment"));
77363
77506
 
77364
77507
  // src/utils/dashboard-metrics.util.ts
77365
- var import_moment_timezone5 = __toESM(require("moment-timezone"));
77508
+ var import_moment_timezone6 = __toESM(require("moment-timezone"));
77366
77509
  var DASHBOARD_TIMEZONE = "Asia/Singapore";
77367
77510
  var PERIOD_UNITS = {
77368
77511
  thisWeek: { boundary: "isoWeek", step: "week" },
@@ -77373,7 +77516,7 @@ function unitsOf(period) {
77373
77516
  return PERIOD_UNITS[period] ?? DAY_UNIT;
77374
77517
  }
77375
77518
  function at(now) {
77376
- return now === void 0 || now === null ? import_moment_timezone5.default.tz(DASHBOARD_TIMEZONE) : import_moment_timezone5.default.tz(now, DASHBOARD_TIMEZONE);
77519
+ return now === void 0 || now === null ? import_moment_timezone6.default.tz(DASHBOARD_TIMEZONE) : import_moment_timezone6.default.tz(now, DASHBOARD_TIMEZONE);
77377
77520
  }
77378
77521
  function getPeriodRange(period, now) {
77379
77522
  const { boundary } = unitsOf(period);
@@ -79107,7 +79250,7 @@ var import_node_server_utils238 = require("@7365admin1/node-server-utils");
79107
79250
 
79108
79251
  // src/utils/hrmlabs-attendance.util.ts
79109
79252
  var import_axios3 = __toESM(require("axios"));
79110
- var import_moment_timezone6 = __toESM(require("moment-timezone"));
79253
+ var import_moment_timezone7 = __toESM(require("moment-timezone"));
79111
79254
  var default_early_checkIn = 4;
79112
79255
  async function hrmLabsAuthentication({
79113
79256
  authUrl,
@@ -79179,13 +79322,13 @@ function filterByShiftTime(attendance, shiftData, timezone, format2) {
79179
79322
  return attendance.filter((item) => {
79180
79323
  if (!item.checkIn)
79181
79324
  return false;
79182
- const checkInLocal = (0, import_moment_timezone6.default)(item.checkIn, format2);
79325
+ const checkInLocal = (0, import_moment_timezone7.default)(item.checkIn, format2);
79183
79326
  if (!checkInLocal.isValid())
79184
79327
  return false;
79185
79328
  const [startHour, startMinute] = shiftData.checkIn.split(":").map(Number);
79186
79329
  const [endHour, endMinute] = shiftData.checkOut.split(":").map(Number);
79187
- const shiftStart = (0, import_moment_timezone6.default)(checkInLocal).set({ hour: startHour, minute: startMinute, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
79188
- const shiftEnd = (0, import_moment_timezone6.default)(checkInLocal).set({
79330
+ const shiftStart = (0, import_moment_timezone7.default)(checkInLocal).set({ hour: startHour, minute: startMinute, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
79331
+ const shiftEnd = (0, import_moment_timezone7.default)(checkInLocal).set({
79189
79332
  hour: endHour,
79190
79333
  minute: endMinute,
79191
79334
  second: 0,
@@ -79277,18 +79420,18 @@ function totalCountPerShift(attendance, shiftData, timezone, format2) {
79277
79420
  data = uniqueAttendanceData.filter((item) => {
79278
79421
  if (!item.checkIn)
79279
79422
  return false;
79280
- const checkInLocal = (0, import_moment_timezone6.default)(item.checkIn, format2);
79423
+ const checkInLocal = (0, import_moment_timezone7.default)(item.checkIn, format2);
79281
79424
  if (!checkInLocal.isValid())
79282
79425
  return false;
79283
79426
  const [startHour, startMinute] = shift.checkIn.split(":").map(Number);
79284
79427
  const [endHour, endMinute] = shift.checkOut.split(":").map(Number);
79285
- const shiftStart = (0, import_moment_timezone6.default)(checkInLocal).set({
79428
+ const shiftStart = (0, import_moment_timezone7.default)(checkInLocal).set({
79286
79429
  hour: startHour,
79287
79430
  minute: startMinute,
79288
79431
  second: 0,
79289
79432
  millisecond: 0
79290
79433
  }).subtract(default_early_checkIn, "hour");
79291
- const shiftEnd = (0, import_moment_timezone6.default)(checkInLocal).set({
79434
+ const shiftEnd = (0, import_moment_timezone7.default)(checkInLocal).set({
79292
79435
  hour: endHour,
79293
79436
  minute: endMinute,
79294
79437
  second: 0,
@@ -79318,11 +79461,11 @@ function filterByStatus(attendance, shiftData, timezone, format2, status) {
79318
79461
  return attendance.filter((item) => {
79319
79462
  if (!item.checkIn)
79320
79463
  return false;
79321
- const checkInLocal = (0, import_moment_timezone6.default)(item.checkIn, format2);
79464
+ const checkInLocal = (0, import_moment_timezone7.default)(item.checkIn, format2);
79322
79465
  if (!checkInLocal.isValid())
79323
79466
  return false;
79324
79467
  const [lateHour, lateMinute] = shiftData.lateCheckInAlert.split(":").map(Number);
79325
- const lateLoginTime = (0, import_moment_timezone6.default)(checkInLocal).set({
79468
+ const lateLoginTime = (0, import_moment_timezone7.default)(checkInLocal).set({
79326
79469
  hour: lateHour,
79327
79470
  minute: lateMinute,
79328
79471
  second: 0,
@@ -79394,14 +79537,14 @@ async function totalCountPerStatus(attendance, shiftName, shiftData, timezone, f
79394
79537
  } = item;
79395
79538
  if (!checkInStr || seenGlobal.has(identificationNumber))
79396
79539
  continue;
79397
- const checkIn = (0, import_moment_timezone6.default)(checkInStr, format2);
79398
- const checkOut = checkOutStr ? (0, import_moment_timezone6.default)(checkOutStr, format2) : null;
79399
- const checkOutChecker = checkOut ? (0, import_moment_timezone6.default)(checkOutStr, format2) : checkIn;
79540
+ const checkIn = (0, import_moment_timezone7.default)(checkInStr, format2);
79541
+ const checkOut = checkOutStr ? (0, import_moment_timezone7.default)(checkOutStr, format2) : null;
79542
+ const checkOutChecker = checkOut ? (0, import_moment_timezone7.default)(checkOutStr, format2) : checkIn;
79400
79543
  if (!checkIn.isValid())
79401
79544
  continue;
79402
- const shiftStart = (0, import_moment_timezone6.default)(checkIn).set({ ...shiftStartTime, second: 59, millisecond: 59 }).subtract(default_early_checkIn, "hour");
79403
- const shiftEnd = (0, import_moment_timezone6.default)(checkOutChecker).set({ ...shiftEndTime, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
79404
- const lateCheckIn = (0, import_moment_timezone6.default)(checkIn).set({
79545
+ const shiftStart = (0, import_moment_timezone7.default)(checkIn).set({ ...shiftStartTime, second: 59, millisecond: 59 }).subtract(default_early_checkIn, "hour");
79546
+ const shiftEnd = (0, import_moment_timezone7.default)(checkOutChecker).set({ ...shiftEndTime, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
79547
+ const lateCheckIn = (0, import_moment_timezone7.default)(checkIn).set({
79405
79548
  ...lateTime,
79406
79549
  second: 59,
79407
79550
  millisecond: 59
@@ -79439,8 +79582,8 @@ async function chartCountData(attendance, shiftData, timezone, format2, totalShi
79439
79582
  const [hour, minute] = timeStr.split(":").map(Number);
79440
79583
  return { hour, minute };
79441
79584
  };
79442
- const startDate = (0, import_moment_timezone6.default)(startDateStr, "DD-MM-YYYY");
79443
- const endDate = (0, import_moment_timezone6.default)(endDateStr, "DD-MM-YYYY");
79585
+ const startDate = (0, import_moment_timezone7.default)(startDateStr, "DD-MM-YYYY");
79586
+ const endDate = (0, import_moment_timezone7.default)(endDateStr, "DD-MM-YYYY");
79444
79587
  const daysInRange = [];
79445
79588
  for (let day = startDate.clone(); day.isSameOrBefore(endDate); day.add(1, "day")) {
79446
79589
  daysInRange.push(day.format("DD-MM-YYYY"));
@@ -79511,7 +79654,7 @@ async function chartCountData(attendance, shiftData, timezone, format2, totalShi
79511
79654
  } = item;
79512
79655
  if (!checkInStr)
79513
79656
  continue;
79514
- const checkIn = (0, import_moment_timezone6.default)(checkInStr, format2);
79657
+ const checkIn = (0, import_moment_timezone7.default)(checkInStr, format2);
79515
79658
  if (!checkIn.isValid())
79516
79659
  continue;
79517
79660
  const dayKey = `${identificationNumber}-${checkIn.format(
@@ -79520,10 +79663,10 @@ async function chartCountData(attendance, shiftData, timezone, format2, totalShi
79520
79663
  if (seenPerDay.has(dayKey))
79521
79664
  continue;
79522
79665
  seenPerDay.add(dayKey);
79523
- const checkOut = checkOutStr ? (0, import_moment_timezone6.default)(checkOutStr, format2) : checkIn;
79524
- const shiftStart = (0, import_moment_timezone6.default)(checkIn).set({ ...shiftStartTime, second: 59, millisecond: 59 }).subtract(default_early_checkIn, "hour");
79525
- const shiftEnd = (0, import_moment_timezone6.default)(checkOut).set({ ...shiftEndTime, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
79526
- const lateCheckIn = (0, import_moment_timezone6.default)(checkIn).set({
79666
+ const checkOut = checkOutStr ? (0, import_moment_timezone7.default)(checkOutStr, format2) : checkIn;
79667
+ const shiftStart = (0, import_moment_timezone7.default)(checkIn).set({ ...shiftStartTime, second: 59, millisecond: 59 }).subtract(default_early_checkIn, "hour");
79668
+ const shiftEnd = (0, import_moment_timezone7.default)(checkOut).set({ ...shiftEndTime, second: 0, millisecond: 0 }).subtract(default_early_checkIn, "hour");
79669
+ const lateCheckIn = (0, import_moment_timezone7.default)(checkIn).set({
79527
79670
  ...lateTime,
79528
79671
  second: 59,
79529
79672
  millisecond: 59
@@ -79826,7 +79969,7 @@ var MManpowerRemarks = class {
79826
79969
 
79827
79970
  // src/repositories/manpower-remarks.repo.ts
79828
79971
  var import_mongodb151 = require("mongodb");
79829
- var import_moment_timezone7 = __toESM(require("moment-timezone"));
79972
+ var import_moment_timezone8 = __toESM(require("moment-timezone"));
79830
79973
  function useManpowerRemarksRepo() {
79831
79974
  const db2 = import_node_server_utils239.useAtlas.getDb();
79832
79975
  if (!db2) {
@@ -79880,7 +80023,7 @@ function useManpowerRemarksRepo() {
79880
80023
  page = page ? page - 1 : 0;
79881
80024
  limit = limit || 10;
79882
80025
  const searchQuery = {};
79883
- const nowSGT = (0, import_moment_timezone7.default)().tz("Asia/Singapore");
80026
+ const nowSGT = (0, import_moment_timezone8.default)().tz("Asia/Singapore");
79884
80027
  searchQuery.serviceProviderId = new import_mongodb151.ObjectId(serviceProviderId);
79885
80028
  if (search != "") {
79886
80029
  searchQuery.siteName = { $regex: search, $options: "i" };
@@ -79992,7 +80135,7 @@ function useManpowerRemarksRepo() {
79992
80135
  }
79993
80136
 
79994
80137
  // src/services/manpower-monitoring.service.ts
79995
- var import_moment_timezone8 = __toESM(require("moment-timezone"));
80138
+ var import_moment_timezone9 = __toESM(require("moment-timezone"));
79996
80139
  function useManpowerMonitoringSrvc() {
79997
80140
  const {
79998
80141
  createManpowerMonitoringSettings: _createManpowerMonitoringSettings
@@ -80010,10 +80153,10 @@ function useManpowerMonitoringSrvc() {
80010
80153
  const morningAlertFrequencyMins = payload?.shifts?.[payload.shiftType][0]?.alertFrequencyMins;
80011
80154
  const afternoonAlertFrequencyMins = payload.shiftType == "3-shifts" ? payload?.shifts?.[payload.shiftType][1]?.alertFrequencyMins : null;
80012
80155
  const nightAlertFrequencyMins = payload.shiftType == "3-shifts" ? payload?.shifts?.[payload.shiftType][2]?.alertFrequencyMins : payload?.shifts?.[payload.shiftType][1]?.alertFrequencyMins;
80013
- const morningAlertTime = import_moment_timezone8.default.tz(morningCheckInTime, "HH:mm", "Asia/Singapore").add(morningAlertFrequencyMins, "minutes").format("HH:mm");
80014
- const afternoonAlertTime = afternoonCheckInTime ? import_moment_timezone8.default.tz(afternoonCheckInTime, "HH:mm", "Asia/Singapore").add(afternoonAlertFrequencyMins, "minutes").format("HH:mm") : "";
80015
- const nightAlertTime = import_moment_timezone8.default.tz(nightCheckInTime, "HH:mm", "Asia/Singapore").add(nightAlertFrequencyMins, "minutes").format("HH:mm");
80016
- const nowSGT = (0, import_moment_timezone8.default)().tz("Asia/Singapore");
80156
+ const morningAlertTime = import_moment_timezone9.default.tz(morningCheckInTime, "HH:mm", "Asia/Singapore").add(morningAlertFrequencyMins, "minutes").format("HH:mm");
80157
+ const afternoonAlertTime = afternoonCheckInTime ? import_moment_timezone9.default.tz(afternoonCheckInTime, "HH:mm", "Asia/Singapore").add(afternoonAlertFrequencyMins, "minutes").format("HH:mm") : "";
80158
+ const nightAlertTime = import_moment_timezone9.default.tz(nightCheckInTime, "HH:mm", "Asia/Singapore").add(nightAlertFrequencyMins, "minutes").format("HH:mm");
80159
+ const nowSGT = (0, import_moment_timezone9.default)().tz("Asia/Singapore");
80017
80160
  try {
80018
80161
  const remarksPayload = {
80019
80162
  siteId: payload.siteId,
@@ -82385,7 +82528,7 @@ function useManpowerSitesCtrl() {
82385
82528
  // src/utils/cron.util.ts
82386
82529
  var import_node_server_utils256 = require("@7365admin1/node-server-utils");
82387
82530
  var import_mongodb156 = require("mongodb");
82388
- var import_moment_timezone9 = __toESM(require("moment-timezone"));
82531
+ var import_moment_timezone10 = __toESM(require("moment-timezone"));
82389
82532
  var createManpowerRemarksDaily = async () => {
82390
82533
  const db2 = import_node_server_utils256.useAtlas.getDb();
82391
82534
  if (!db2) {
@@ -82396,9 +82539,9 @@ var createManpowerRemarksDaily = async () => {
82396
82539
  const remarks = db2.collection("manpower-remarks");
82397
82540
  const serviceProviders = db2.collection("site.service-providers");
82398
82541
  const items = [];
82399
- const yesterday = (0, import_moment_timezone9.default)().tz("Asia/Singapore").subtract(1, "days").format("DD-MM-YYYY");
82542
+ const yesterday = (0, import_moment_timezone10.default)().tz("Asia/Singapore").subtract(1, "days").format("DD-MM-YYYY");
82400
82543
  try {
82401
- const nowSGT = (0, import_moment_timezone9.default)().tz("Asia/Singapore");
82544
+ const nowSGT = (0, import_moment_timezone10.default)().tz("Asia/Singapore");
82402
82545
  const servideProvider = await serviceProviders.findOne({
82403
82546
  name: { $regex: process.env.HRMLABS_DOMAIN, $options: "i" }
82404
82547
  });
@@ -82436,9 +82579,9 @@ var createManpowerRemarksDaily = async () => {
82436
82579
  const morningAlertFrequencyMins = setting?.shifts?.[shiftType][0]?.alertFrequencyMins;
82437
82580
  const afternoonAlertFrequencyMins = shiftType == "3-shifts" ? setting?.shifts?.[shiftType][1]?.alertFrequencyMins : null;
82438
82581
  const nightAlertFrequencyMins = shiftType == "3-shifts" ? setting?.shifts?.[shiftType][2]?.alertFrequencyMins : setting?.shifts?.[shiftType][1]?.alertFrequencyMins;
82439
- const morningAlertTime = import_moment_timezone9.default.tz(morningCheckInTime, "HH:mm", "Asia/Singapore").add(morningAlertFrequencyMins, "minutes").format("HH:mm");
82440
- const afternoonAlertTime = afternoonCheckInTime ? import_moment_timezone9.default.tz(afternoonCheckInTime, "HH:mm", "Asia/Singapore").add(afternoonAlertFrequencyMins, "minutes").format("HH:mm") : "";
82441
- const nightAlertTime = import_moment_timezone9.default.tz(nightCheckInTime, "HH:mm", "Asia/Singapore").add(nightAlertFrequencyMins, "minutes").format("HH:mm");
82582
+ const morningAlertTime = import_moment_timezone10.default.tz(morningCheckInTime, "HH:mm", "Asia/Singapore").add(morningAlertFrequencyMins, "minutes").format("HH:mm");
82583
+ const afternoonAlertTime = afternoonCheckInTime ? import_moment_timezone10.default.tz(afternoonCheckInTime, "HH:mm", "Asia/Singapore").add(afternoonAlertFrequencyMins, "minutes").format("HH:mm") : "";
82584
+ const nightAlertTime = import_moment_timezone10.default.tz(nightCheckInTime, "HH:mm", "Asia/Singapore").add(nightAlertFrequencyMins, "minutes").format("HH:mm");
82442
82585
  const remark2 = {
82443
82586
  siteId: site.siteId,
82444
82587
  siteName: site.siteName,
@@ -82495,14 +82638,14 @@ var createManpowerRemarksDaily = async () => {
82495
82638
  };
82496
82639
  var updateRemarksisAcknowledged = async () => {
82497
82640
  const { getAttendanceDataCount: _getAttendanceDataCount } = useHrmLabsAttendanceSrvc();
82498
- const nowSGT = (0, import_moment_timezone9.default)().tz("Asia/Singapore").format("DD-MM-YYYY");
82641
+ const nowSGT = (0, import_moment_timezone10.default)().tz("Asia/Singapore").format("DD-MM-YYYY");
82499
82642
  const db2 = import_node_server_utils256.useAtlas.getDb();
82500
82643
  if (!db2) {
82501
82644
  throw new Error("Unable to connect to server.");
82502
82645
  }
82503
82646
  const namespace_collection = "manpower-remarks";
82504
82647
  const remarks = db2.collection(namespace_collection);
82505
- const timeNow = (0, import_moment_timezone9.default)().tz("Asia/Singapore").format("HH:mm");
82648
+ const timeNow = (0, import_moment_timezone10.default)().tz("Asia/Singapore").format("HH:mm");
82506
82649
  const settings = db2.collection("manpower-settings");
82507
82650
  try {
82508
82651
  const matchingDocs = await remarks.find({
@@ -82630,9 +82773,9 @@ var updateRemarksStatusEod = async () => {
82630
82773
  }
82631
82774
  const remarks = db2.collection("manpower-remarks");
82632
82775
  const settings = db2.collection("manpower-settings");
82633
- const nowSGT = (0, import_moment_timezone9.default)().tz("Asia/Singapore").format("DD-MM-YYYY");
82634
- const yesterdaySGT = (0, import_moment_timezone9.default)().tz("Asia/Singapore").subtract(1, "days").format("DD-MM-YYYY");
82635
- const timeNow = (0, import_moment_timezone9.default)().tz("Asia/Singapore").format("HH:mm");
82776
+ const nowSGT = (0, import_moment_timezone10.default)().tz("Asia/Singapore").format("DD-MM-YYYY");
82777
+ const yesterdaySGT = (0, import_moment_timezone10.default)().tz("Asia/Singapore").subtract(1, "days").format("DD-MM-YYYY");
82778
+ const timeNow = (0, import_moment_timezone10.default)().tz("Asia/Singapore").format("HH:mm");
82636
82779
  const docs = await remarks.find({
82637
82780
  $or: [
82638
82781
  // Morning & Afternoon from today
@@ -82768,7 +82911,7 @@ var isWithinHour = (alertTime, timeNow) => {
82768
82911
  // src/events/manpower.event.ts
82769
82912
  var import_node_server_utils257 = require("@7365admin1/node-server-utils");
82770
82913
  var import_mongodb157 = require("mongodb");
82771
- var import_moment_timezone10 = __toESM(require("moment-timezone"));
82914
+ var import_moment_timezone11 = __toESM(require("moment-timezone"));
82772
82915
  async function manpowerEvents(io) {
82773
82916
  let intervalId = null;
82774
82917
  let activeConnections = 0;
@@ -82780,9 +82923,9 @@ async function manpowerEvents(io) {
82780
82923
  }
82781
82924
  const remarks = db2.collection("manpower-remarks");
82782
82925
  const settings = db2.collection("manpower-settings");
82783
- const selectedDateMoment = import_moment_timezone10.default.tz(date, "DD-MM-YYYY", "Asia/Singapore");
82926
+ const selectedDateMoment = import_moment_timezone11.default.tz(date, "DD-MM-YYYY", "Asia/Singapore");
82784
82927
  const selectedDateSGT = selectedDateMoment.format("DD-MM-YYYY");
82785
- const currentSGT = (0, import_moment_timezone10.default)().tz("Asia/Singapore");
82928
+ const currentSGT = (0, import_moment_timezone11.default)().tz("Asia/Singapore");
82786
82929
  const docs = await remarks.find({
82787
82930
  createdAtSGT: selectedDateSGT,
82788
82931
  $or: [
@@ -82804,7 +82947,7 @@ async function manpowerEvents(io) {
82804
82947
  }
82805
82948
  if (currentSGT.isSame(selectedDateMoment, "day")) {
82806
82949
  if (currentSGT.isSameOrAfter(
82807
- import_moment_timezone10.default.tz("19:55", "HH:mm", "Asia/Singapore")
82950
+ import_moment_timezone11.default.tz("19:55", "HH:mm", "Asia/Singapore")
82808
82951
  )) {
82809
82952
  shiftsToCheck.push({ index: 2, key: "nightShift" });
82810
82953
  }
@@ -91258,6 +91401,7 @@ function useNotificationPreferenceController() {
91258
91401
  CameraType,
91259
91402
  ConsoleAuditAction,
91260
91403
  ConsoleAuditTarget,
91404
+ DEFAULT_SITE_TIMEZONE,
91261
91405
  DEVICE_STATUS,
91262
91406
  DOBStatus,
91263
91407
  DUPLICATE_TERMS_VERSION_MESSAGE,
@@ -91512,6 +91656,7 @@ function useNotificationPreferenceController() {
91512
91656
  isSafeRelativePath,
91513
91657
  isSuperAdmin,
91514
91658
  isTermsCurrent,
91659
+ isValidTimezone,
91515
91660
  manpowerDesignationsSchema,
91516
91661
  manpowerEvents,
91517
91662
  manpowerMonitoringSchema,
@@ -91531,6 +91676,7 @@ function useNotificationPreferenceController() {
91531
91676
  occurrence_book_namespace_collection,
91532
91677
  online_forms_namespace_collection,
91533
91678
  orgSchema,
91679
+ orgSiteScope,
91534
91680
  overnight_parking_requests_namespace_collection,
91535
91681
  parseCameraChannel,
91536
91682
  parseCameraHost,
@@ -91564,6 +91710,7 @@ function useNotificationPreferenceController() {
91564
91710
  resolveDeviceHttp,
91565
91711
  resolveHidPhysicalCardValue,
91566
91712
  resolveInviteActor,
91713
+ resolveSiteTimezone,
91567
91714
  robotSchema,
91568
91715
  rtspUrl,
91569
91716
  schema,
@@ -91720,6 +91867,7 @@ function useNotificationPreferenceController() {
91720
91867
  sessionSchema,
91721
91868
  setIO,
91722
91869
  shiftSchema,
91870
+ siteDayBounds,
91723
91871
  siteSchema,
91724
91872
  site_people_namespace_collection,
91725
91873
  snapshotEndpoint,