@7365admin1/core 3.77.1-staging.330 → 3.77.1-staging.331

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.
@@ -32,3 +32,5 @@ A book now belongs to its SITE's local day. `siteBookDay` reads `sites.timezone`
32
32
  A newly created site gets today's book immediately instead of waiting for its next local midnight or a restart. The three site-creation paths (`site`, `customer` and `customer-site` services) call `startTodaysBookForSite` right after their transaction commits, so a rolled-back site never gets an orphan book. It is fire-and-forget and never throws, not even synchronously, so a book problem can never make an already-committed site look like it failed. It runs through `processCreateDOB({ siteIds })`, so the book gets the site's own timezone, day and No. 1, with the same duplicate protection as the midnight job.
33
33
 
34
34
  `startTodaysBookForSite` is also called after a site's timezone is edited (`PUT /api/sites/:id` with `timezone`), and it tells API-core the set of timezones may have changed through `onBookTimezonesChanged`, a listener API-core registers at start-up. So a zone no site used before gets its midnight job without any polling, and a site moved into a zone whose day has already begun gets that day's book. A server that misses the call re-reads the timezones on its next restart.
35
+
36
+ A site's timezone can now be set from the Add / Edit Site form, which saves through `/api/customer-sites`. `TCustomerSite` and `schemaCustomerSite` accept `timezone` (validated as an IANA zone); it is passed through to `sites.timezone` on create and on update and never stored on the customer-site row. On update an unknown zone is refused with 400, and a CHANGED zone calls `startTodaysBookForSite` after the commit, so a new zone gets its midnight job and the site gets a book for its new day if that day has begun. The customer-sites list now returns each row's live `timezone` from its site, so the form opens on the zone the site actually has.
package/dist/index.d.ts CHANGED
@@ -5617,6 +5617,14 @@ type TCustomerSite = {
5617
5617
  shareCapital?: string;
5618
5618
  temporaryOccupationPermit?: string;
5619
5619
  certificateOfStatutory?: string;
5620
+ /**
5621
+ * The SITE's IANA timezone, as picked on the Add / Edit Site form. Passed
5622
+ * through to `sites.timezone` - it is never stored on the engagement row
5623
+ * itself (`MCustomerSite` does not return it). It decides the site's local
5624
+ * day: when its daily occurrence book starts, and "today" for visitors and
5625
+ * ANPR.
5626
+ */
5627
+ timezone?: string;
5620
5628
  createdAt?: string | Date;
5621
5629
  updatedAt?: string | Date;
5622
5630
  deletedAt?: string | Date;
@@ -5646,6 +5654,7 @@ declare function MCustomerSite(value: TCustomerSite): {
5646
5654
  shareCapital?: string | undefined;
5647
5655
  temporaryOccupationPermit?: string | undefined;
5648
5656
  certificateOfStatutory?: string | undefined;
5657
+ timezone?: string | undefined;
5649
5658
  };
5650
5659
 
5651
5660
  declare function useCustomerSiteRepo(): {
package/dist/index.js CHANGED
@@ -8291,6 +8291,10 @@ var schemaCustomerSite = import_joi12.default.object({
8291
8291
  shareCapital: import_joi12.default.string().optional().allow("", null),
8292
8292
  temporaryOccupationPermit: import_joi12.default.string().optional().allow("", null),
8293
8293
  certificateOfStatutory: import_joi12.default.string().optional().allow("", null),
8294
+ timezone: import_joi12.default.string().custom(
8295
+ (value, helpers) => isValidTimezone(value) ? value : helpers.error("any.invalid"),
8296
+ "IANA timezone"
8297
+ ).optional().allow("", null),
8294
8298
  createdAt: import_joi12.default.string().optional().allow("", null),
8295
8299
  updatedAt: import_joi12.default.string().optional().allow("", null),
8296
8300
  deletedAt: import_joi12.default.string().optional().allow("", null)
@@ -8511,7 +8515,14 @@ function useCustomerSiteRepo() {
8511
8515
  }
8512
8516
  },
8513
8517
  { $unwind: { path: "$_liveSite", preserveNullAndEmptyArrays: true } },
8514
- { $set: { name: { $ifNull: ["$_liveSite.name", "$name"] } } },
8518
+ {
8519
+ $set: {
8520
+ name: { $ifNull: ["$_liveSite.name", "$name"] },
8521
+ // The site's own timezone, so the Edit Site form opens on the zone
8522
+ // the site really has. Lives only on the site, never on this row.
8523
+ timezone: "$_liveSite.timezone"
8524
+ }
8525
+ },
8515
8526
  { $unset: "_liveSite" },
8516
8527
  ...search ? [{ $match: { name: { $regex: search, $options: "i" } } }] : [],
8517
8528
  { $sort: sort }
@@ -41374,7 +41385,10 @@ function useCustomerSiteService() {
41374
41385
  name: value.name,
41375
41386
  orgId: value.siteOrg,
41376
41387
  address: value.address,
41377
- category: value.category
41388
+ category: value.category,
41389
+ // The zone picked on the Add Site form. Left out when absent, so the
41390
+ // site model's own default (Singapore) applies exactly as before.
41391
+ ...isValidTimezone(value.timezone) && { timezone: value.timezone }
41378
41392
  },
41379
41393
  session
41380
41394
  );
@@ -41505,12 +41519,18 @@ function useCustomerSiteService() {
41505
41519
  throw new import_node_server_utils127.NotFoundError("Customer site not found.");
41506
41520
  }
41507
41521
  const siteId = customerSite.site;
41522
+ const timezone = typeof payload.timezone === "string" && payload.timezone.trim() !== "" ? payload.timezone.trim() : void 0;
41523
+ if (timezone !== void 0 && !isValidTimezone(timezone)) {
41524
+ throw new import_node_server_utils127.BadRequestError(`Unknown timezone "${timezone}".`);
41525
+ }
41526
+ const timezoneBefore = timezone !== void 0 ? (await getSiteById(siteId).catch(() => null))?.timezone : void 0;
41508
41527
  await updateSiteById(
41509
41528
  siteId,
41510
41529
  {
41511
41530
  ...payload.name !== void 0 && { name: payload.name },
41512
41531
  ...payload.address !== void 0 && { address: payload.address },
41513
- ...payload.category !== void 0 && { category: payload.category }
41532
+ ...payload.category !== void 0 && { category: payload.category },
41533
+ ...timezone !== void 0 && { timezone }
41514
41534
  },
41515
41535
  session
41516
41536
  );
@@ -41528,6 +41548,9 @@ function useCustomerSiteService() {
41528
41548
  session
41529
41549
  );
41530
41550
  await session?.commitTransaction();
41551
+ if (timezone !== void 0 && timezone !== timezoneBefore) {
41552
+ startTodaysBookForSite(siteId);
41553
+ }
41531
41554
  return result;
41532
41555
  } catch (error) {
41533
41556
  await session?.abortTransaction();