toga-ai 1.0.412 → 1.0.414
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/knowledge/2.0/apps/dbchanges2/INDEX.md +1 -1
- package/knowledge/2.0/apps/dbchanges2/features/surface-layer-schema.md +39 -2
- package/knowledge/2.0/apps/toga25-supply/features/surface-frontend.md +19 -0
- package/knowledge/sessions/2026-07-21-nycdoe-hold-sync-sking.md +64 -0
- package/package.json +1 -1
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
| Doc | Summary | Files |
|
|
4
4
|
|-----|---------|-------|
|
|
5
5
|
| [Database Changes (dbchanges2) Repository Architecture](architecture.md) | `dbchanges2` is the **schema-migration / SQL change-set repository** for the entire 2.0 platform. | Core/, Client/, Client_<Tenant>/, Logs/, Logs_Client/, _modules/ |
|
|
6
|
-
| [Surface Layer Schema (UI presentation/config tables)](features/surface-layer-schema.md) | The persistent schema for the platform-wide **Surface** UI presentation/configuration layer (see the `_underscore` [surface-resolver](../../_underscore/features | dbchanges2/Client/2026-06-25a - SurfaceClientTables.sql, dbchanges2/Client_Compass/2026-06-25d - SalesOrderSurfaceClientSeed.sql, _underscore/Model/Client/ThemeToken.php, toga25-supply/src/themeConfig.json, dbchanges2/Core/2026-06-25a - SurfaceCoreTables.sql, dbchanges2/Core/2026-06-25b - SurfaceRecordsAndFields.sql, dbchanges2/Core/2026-06-25c - SalesOrderLoginSurfaceSeed.sql, dbchanges2/Core/2026-06-29a - ItemsSurfaceSeed.sql, dbchanges2/Core/2026-06-29b - SurfaceMetaPublicReadAcl.sql, dbchanges2/Client/2026-06-29c - SurfaceRecordScriptAcl.sql, dbchanges2/Core/2026-06-29c - SurfaceDebugPhpMethodFix.sql, dbchanges2/Core/2026-06-29d - VendorItemsSurfaceSeed.sql, dbchanges2/Core/2026-06-29e - InventorySurfaceSeed.sql, dbchanges2/Core/2026-06-30a - SurfaceMetaGroupAndSalesOrderSections.sql, dbchanges2/Client/2026-06-30a - SurfaceMetaGroupAcl.sql, dbchanges2/Client_Compass/2026-06-30a - SalesOrderDisplaySectionManagerOverrides.sql, dbchanges2/Client_CompassCanada/2026-06-30a - SalesOrderSurfaceManagerOverrides.sql, dbchanges2/Client_Quad/2026-06-30a - SalesOrderSurfaceClientOverrides.sql, dbchanges2/Client/2026-06-25a - SurfaceClientTables.sql, dbchanges2/Client/2026-06-25b - SurfaceClientSeed.sql, dbchanges2/Client/2026-06-25c - SurfaceClientAcl.sql, dbchanges2/Client/2026-06-03- BLANK_CLIENT_DATABASE.sql, dbchanges2/Core/2026-07-17h - Update - ClearApprovalsFilterButtonConfig.sql, dbchanges2/Client_Compass/2026-07-17a - SalesOrderApprovalActionsOverride.sql, dbchanges2/Client_Compass/2026-07-17b - SalesOrderApprovalsFilterButtonOverride.sql, dbchanges2/Client_CompassCanada/2026-07-17a - SalesOrderApprovalActionsOverride.sql, dbchanges2/Client_CompassCanada/2026-07-17b - SalesOrderApprovalsFilterButtonOverride.sql, dbchanges2/Client_Quad/2026-07-17a - SalesOrderApprovalActionsOverride.sql, dbchanges2/Client_Quad/2026-07-17b - SalesOrderApprovalsFilterButtonOverride.sql, dbchanges2/Core/2026-07-20a - Update - HideAdminNotesSectionByDefault.sql, dbchanges2/Core/2026-07-20b - Update - NotesSectionFieldElements.sql, dbchanges2/Client_Compass/2026-07-20a - AdminNotesSectionVisibilityOverride.sql, dbchanges2/Client_Compass/2026-07-20b - NotesSectionFieldsOverride.sql, dbchanges2/Client_CompassCanada/2026-07-20a - AdminNotesSectionVisibilityOverride.sql, dbchanges2/Client_CompassCanada/2026-07-20b - NotesSectionFieldsOverride.sql, dbchanges2/Client_Quad/2026-07-20a - NotesSectionFieldsOverride.sql, dbchanges2/Core/2026-07-20c - Update - VendorItemsToggleSurfaceSeed.sql, dbchanges2/Client_Compass/2026-07-20c - ItemRecordEditButtonEnable.sql, dbchanges2/Client_Compass/2026-07-20d - ItemRecordVendorItemsEnable.sql, dbchanges2/Client_CompassCanada/2026-07-20c - ItemRecordEditButtonEnable.sql, dbchanges2/Client_CompassCanada/2026-07-20d - ItemRecordVendorItemsEnable.sql, dbchanges2/Core/2026-07-20e - RestoreApproveDenyRowActions.sql, dbchanges2/Client_Compass/2026-07-20e - RowActionsApprovalWorkflowAdminEnable.sql, dbchanges2/Client_CompassCanada/2026-07-20e - RowActionsApprovalWorkflowAdminEnable.sql, dbchanges2/Core/2026-07-17 - README - RUN ORDER.md, dbchanges2/Client_Compass/2026-07-21a - SalesOrderApproveEnabledRuleOverride.sql, dbchanges2/Client_Compass/2026-07-21b - SalesOrderApprovalsGateEnable.sql, dbchanges2/Client_CompassCanada/2026-07-21a - SalesOrderApproveEnabledRuleOverride.sql, dbchanges2/Client_CompassCanada/2026-07-21b - SalesOrderApprovalsGateEnable.sql, dbchanges2/Client_Quad/2026-07-21a - SalesOrderApproveEnabledRuleOverride.sql, dbchanges2/Client_Quad/2026-07-21b - SalesOrderApproveDisabledTooltipTranslation.sql, dbchanges2/Core/2026-07-21a - SalesOrderDecisionSummarySurfaceSeed.sql, dbchanges2/Core/2026-07-21b - SalesOrderDecisionActionSurfaceSeed.sql |
|
|
6
|
+
| [Surface Layer Schema (UI presentation/config tables)](features/surface-layer-schema.md) | The persistent schema for the platform-wide **Surface** UI presentation/configuration layer (see the `_underscore` [surface-resolver](../../_underscore/features | dbchanges2/Client/2026-06-25a - SurfaceClientTables.sql, dbchanges2/Client_Compass/2026-06-25d - SalesOrderSurfaceClientSeed.sql, _underscore/Model/Client/ThemeToken.php, toga25-supply/src/themeConfig.json, dbchanges2/Core/2026-06-25a - SurfaceCoreTables.sql, dbchanges2/Core/2026-06-25b - SurfaceRecordsAndFields.sql, dbchanges2/Core/2026-06-25c - SalesOrderLoginSurfaceSeed.sql, dbchanges2/Core/2026-06-29a - ItemsSurfaceSeed.sql, dbchanges2/Core/2026-06-29b - SurfaceMetaPublicReadAcl.sql, dbchanges2/Client/2026-06-29c - SurfaceRecordScriptAcl.sql, dbchanges2/Core/2026-06-29c - SurfaceDebugPhpMethodFix.sql, dbchanges2/Core/2026-06-29d - VendorItemsSurfaceSeed.sql, dbchanges2/Core/2026-06-29e - InventorySurfaceSeed.sql, dbchanges2/Core/2026-06-30a - SurfaceMetaGroupAndSalesOrderSections.sql, dbchanges2/Client/2026-06-30a - SurfaceMetaGroupAcl.sql, dbchanges2/Client_Compass/2026-06-30a - SalesOrderDisplaySectionManagerOverrides.sql, dbchanges2/Client_CompassCanada/2026-06-30a - SalesOrderSurfaceManagerOverrides.sql, dbchanges2/Client_Quad/2026-06-30a - SalesOrderSurfaceClientOverrides.sql, dbchanges2/Client/2026-06-25a - SurfaceClientTables.sql, dbchanges2/Client/2026-06-25b - SurfaceClientSeed.sql, dbchanges2/Client/2026-06-25c - SurfaceClientAcl.sql, dbchanges2/Client/2026-06-03- BLANK_CLIENT_DATABASE.sql, dbchanges2/Core/2026-07-17h - Update - ClearApprovalsFilterButtonConfig.sql, dbchanges2/Client_Compass/2026-07-17a - SalesOrderApprovalActionsOverride.sql, dbchanges2/Client_Compass/2026-07-17b - SalesOrderApprovalsFilterButtonOverride.sql, dbchanges2/Client_CompassCanada/2026-07-17a - SalesOrderApprovalActionsOverride.sql, dbchanges2/Client_CompassCanada/2026-07-17b - SalesOrderApprovalsFilterButtonOverride.sql, dbchanges2/Client_Quad/2026-07-17a - SalesOrderApprovalActionsOverride.sql, dbchanges2/Client_Quad/2026-07-17b - SalesOrderApprovalsFilterButtonOverride.sql, dbchanges2/Core/2026-07-20a - Update - HideAdminNotesSectionByDefault.sql, dbchanges2/Core/2026-07-20b - Update - NotesSectionFieldElements.sql, dbchanges2/Client_Compass/2026-07-20a - AdminNotesSectionVisibilityOverride.sql, dbchanges2/Client_Compass/2026-07-20b - NotesSectionFieldsOverride.sql, dbchanges2/Client_CompassCanada/2026-07-20a - AdminNotesSectionVisibilityOverride.sql, dbchanges2/Client_CompassCanada/2026-07-20b - NotesSectionFieldsOverride.sql, dbchanges2/Client_Quad/2026-07-20a - NotesSectionFieldsOverride.sql, dbchanges2/Core/2026-07-20c - Update - VendorItemsToggleSurfaceSeed.sql, dbchanges2/Client_Compass/2026-07-20c - ItemRecordEditButtonEnable.sql, dbchanges2/Client_Compass/2026-07-20d - ItemRecordVendorItemsEnable.sql, dbchanges2/Client_CompassCanada/2026-07-20c - ItemRecordEditButtonEnable.sql, dbchanges2/Client_CompassCanada/2026-07-20d - ItemRecordVendorItemsEnable.sql, dbchanges2/Core/2026-07-20e - RestoreApproveDenyRowActions.sql, dbchanges2/Client_Compass/2026-07-20e - RowActionsApprovalWorkflowAdminEnable.sql, dbchanges2/Client_CompassCanada/2026-07-20e - RowActionsApprovalWorkflowAdminEnable.sql, dbchanges2/Core/2026-07-17 - README - RUN ORDER.md, dbchanges2/Client_Compass/2026-07-21a - SalesOrderApproveEnabledRuleOverride.sql, dbchanges2/Client_Compass/2026-07-21b - SalesOrderApprovalsGateEnable.sql, dbchanges2/Client_CompassCanada/2026-07-21a - SalesOrderApproveEnabledRuleOverride.sql, dbchanges2/Client_CompassCanada/2026-07-21b - SalesOrderApprovalsGateEnable.sql, dbchanges2/Client_Quad/2026-07-21a - SalesOrderApproveEnabledRuleOverride.sql, dbchanges2/Client_Quad/2026-07-21b - SalesOrderApproveDisabledTooltipTranslation.sql, dbchanges2/Core/2026-07-21a - SalesOrderDecisionSummarySurfaceSeed.sql, dbchanges2/Core/2026-07-21b - SalesOrderDecisionActionSurfaceSeed.sql, dbchanges2/Client_Quad/2026-07-21c - SalesOrderDecisionSummaryOverride.sql, dbchanges2/Client_Compass/2026-07-21c - SalesOrderDecisionSummaryTotalConcat.sql, dbchanges2/Client_CompassCanada/2026-07-21c - SalesOrderDecisionSummaryTotalConcat.sql |
|
|
7
7
|
| [2.0 New-Client Onboarding (manual process)](workflows/client-onboarding.md) | > **A local browser wizard now automates this.** Steps 2–9 below (create DBs, generate Core/API > inserts, append to `Clients_Db.txt`) — plus the dbchanges2 bla | Client/, Client_<Tenant>/, Core/, Logs_Client/ |
|
|
@@ -62,6 +62,9 @@ files:
|
|
|
62
62
|
- dbchanges2/Client_Quad/2026-07-21b - SalesOrderApproveDisabledTooltipTranslation.sql
|
|
63
63
|
- dbchanges2/Core/2026-07-21a - SalesOrderDecisionSummarySurfaceSeed.sql
|
|
64
64
|
- dbchanges2/Core/2026-07-21b - SalesOrderDecisionActionSurfaceSeed.sql
|
|
65
|
+
- dbchanges2/Client_Quad/2026-07-21c - SalesOrderDecisionSummaryOverride.sql
|
|
66
|
+
- dbchanges2/Client_Compass/2026-07-21c - SalesOrderDecisionSummaryTotalConcat.sql
|
|
67
|
+
- dbchanges2/Client_CompassCanada/2026-07-21c - SalesOrderDecisionSummaryTotalConcat.sql
|
|
65
68
|
related:
|
|
66
69
|
- ../../_underscore/features/surface-resolver.md
|
|
67
70
|
---
|
|
@@ -306,8 +309,31 @@ Both seeds are **ADDITIVE, id-agnostic, and re-runnable**: `NOT EXISTS`-guarded
|
|
|
306
309
|
`config.role`/`valueKey`; Messages guarded by `messageKey`; the surfaces inherit `appId`/`recordId`
|
|
307
310
|
from the existing `order-details` sibling surface **by slug** (never a hardcoded id). Same authoring
|
|
308
311
|
pattern as the `2026-07-17g` seed. These are **Core→Core only** (prod-safe — no cross-DB Client
|
|
309
|
-
subselect).
|
|
310
|
-
|
|
312
|
+
subselect).
|
|
313
|
+
|
|
314
|
+
### Per-client decision-summary overrides (Quad hides + Compass/CC concat Total, 2026-07-21c)
|
|
315
|
+
The per-client divergence off the shared `sales-order-decision-summary` surface was seeded (all three
|
|
316
|
+
files use suffix `c`; `b` was already taken in each client folder, and each `run after Core/2026-07-21a`
|
|
317
|
+
per the RUN ORDER README). All are **client-level** (`roleId`/`personaId`/`languageId` NULL — see the
|
|
318
|
+
decision below), id-agnostic (resolved by `Surfaces.slug` + `config.valueKey`, never a hardcoded id),
|
|
319
|
+
and `NOT EXISTS`-guarded.
|
|
320
|
+
|
|
321
|
+
- **Quad field hides** (`Client_Quad/2026-07-21c`) — three `IS_VISIBLE='0'` overrides hiding **Assigned
|
|
322
|
+
Manager** (`assignedTo._name`), **Cost Center** (`c_erpEntityId`), and **Reason for Request**
|
|
323
|
+
(`reasonForRequest`, the read-only summary row — **NOT** the editable reason input). `IS_VISIBLE` is
|
|
324
|
+
in the base attribute ENUM (no widener needed). Renders end-to-end with **no FE change** (the resolver
|
|
325
|
+
applies visibility; the summary adapter already honors `el.isVisible`). Applied to local Client_Quad
|
|
326
|
+
and verified.
|
|
327
|
+
- **Compass + Compass Canada concatenated Total** (`Client_Compass/2026-07-21c`,
|
|
328
|
+
`Client_CompassCanada/2026-07-21c`) — a `CONFIG` override on the Total element setting the **full**
|
|
329
|
+
config `{"valueKey":"_totalPurchase","isConcatenated":{"valueKey":"_totalLease","suffix":"/mo",
|
|
330
|
+
"layout":"stacked","valueType":"currency"}}` — stacks the monthly lease figure under the purchase
|
|
331
|
+
Total for the lease clients. Because a `CONFIG` override **replaces the whole object** (see the resolver
|
|
332
|
+
doc), the override **must** carry the base `valueKey` (`_totalPurchase`), not just the added
|
|
333
|
+
`isConcatenated` key — omitting it silently drops the base binding. Resolved by slug +
|
|
334
|
+
`config.valueKey='_totalPurchase'`. Requires the small FE adapter extension to emit `isConcatenated`
|
|
335
|
+
(see [surface-frontend](../../toga25-supply/features/surface-frontend.md)). Authored this session;
|
|
336
|
+
only Quad confirmed applied locally.
|
|
311
337
|
|
|
312
338
|
## ThemeTokens — per-tenant, physically isolated in each client DB
|
|
313
339
|
|
|
@@ -473,6 +499,17 @@ rule resumes.
|
|
|
473
499
|
override is added). **Open follow-up.**
|
|
474
500
|
|
|
475
501
|
## Change history
|
|
502
|
+
- 2026-07-21 — Seeded the **per-client decision-summary overrides** off the shared
|
|
503
|
+
`sales-order-decision-summary` surface (all `2026-07-21c`, client-level — `roleId`/`personaId`/
|
|
504
|
+
`languageId` NULL): **Quad** hides three summary rows (`assignedTo._name`, `c_erpEntityId`,
|
|
505
|
+
`reasonForRequest` — the read-only row, not the reason input) via `IS_VISIBLE='0'` (base ENUM, no FE
|
|
506
|
+
change); **Compass + Compass Canada** stack the monthly lease figure under Total via a `CONFIG`
|
|
507
|
+
override carrying the **full** config (`_totalPurchase` + `isConcatenated{_totalLease, suffix "/mo",
|
|
508
|
+
layout stacked, currency}`). All id-agnostic (slug + `config.valueKey`), NOT EXISTS-guarded, registered
|
|
509
|
+
in the RUN ORDER README (`run after Core/2026-07-21a`). Reinforces the CONFIG-replaces-wholesale rule:
|
|
510
|
+
a partial CONFIG override silently drops the base `valueKey`. Scoped client-level not role-scoped (a
|
|
511
|
+
display flourish for every tenant user; open follow-up to re-scope Compass concat to a role if wanted).
|
|
512
|
+
Only Quad confirmed applied locally. (apeterson)
|
|
476
513
|
- 2026-07-21 — Seeded the **SalesOrder decision-modal (approve + deny) surfaces**, migrating the
|
|
477
514
|
per-client `approvalActionFields.json` display config to metadata. `Core/2026-07-21a` = one SHARED
|
|
478
515
|
`sales-order-decision-summary` SECTION surface (cardType `decisionSummary`, 8 read-only FIELD summary
|
|
@@ -292,6 +292,17 @@ values, so JSON-only functional fields survive: **Surface owns all display attri
|
|
|
292
292
|
visibility, icons, `isRequired`, placeholder, `textAreaHeight`); JSON fills gaps and functional
|
|
293
293
|
wiring. The per-client `approvalActionFields.json` files are kept on disk as reference (not deleted).
|
|
294
294
|
|
|
295
|
+
**Concatenated summary values (`isConcatenated`).** `surfaceBundlesToDecisionFields.ts` now passes an
|
|
296
|
+
element's `config.isConcatenated` through **verbatim** onto the decision-summary row: it exports a
|
|
297
|
+
`DecisionSummaryConcat` type (string shorthand | descriptor `{valueKey, prefix?, suffix?, valueType?,
|
|
298
|
+
layout?: 'inline'|'stacked', label?}`, mirroring blox `BaseDetailField`'s `isConcatenated`) and added an
|
|
299
|
+
optional `isConcatenated?` to `DecisionSummaryField`; `buildSummaryFields` copies `config.isConcatenated`
|
|
300
|
+
straight through. This is purely additive — before it, the adapter dropped the concat config, so the
|
|
301
|
+
Compass / Compass Canada Total `CONFIG` override (stacking `_totalLease` under `_totalPurchase`, seed
|
|
302
|
+
side in [surface-layer-schema](../../dbchanges2/features/surface-layer-schema.md)) would have seeded data
|
|
303
|
+
the FE ignored. blox `BaseDetailField` (`renderBaseDetailFieldValue.tsx`) already supports
|
|
304
|
+
`valueKey`+`suffix`+`layout:'stacked'`+`valueType:'currency'`. tsc + eslint clean.
|
|
305
|
+
|
|
295
306
|
**Shared summary, separate per-action chrome (decision).** The 8 order-summary rows are identical for
|
|
296
307
|
approve and deny, so they come from **one** shared surface (`sales-order-decision-summary`); the action
|
|
297
308
|
chrome (title, reason-input required-ness, confirm button, icons, toasts) diverges, so it is **two**
|
|
@@ -460,6 +471,14 @@ now carry it (2026-07-21):
|
|
|
460
471
|
treat type-checking as pending. Runtime `GET /v2/surfaces/{slug}/meta` also not yet exercised.
|
|
461
472
|
|
|
462
473
|
## Change history
|
|
474
|
+
- 2026-07-21 — Extended `surfaceBundlesToDecisionFields.ts` to emit **`isConcatenated`** on
|
|
475
|
+
decision-summary rows: new exported `DecisionSummaryConcat` type (string shorthand | descriptor
|
|
476
|
+
`{valueKey, prefix?, suffix?, valueType?, layout?, label?}`, mirroring blox `BaseDetailField`); optional
|
|
477
|
+
`isConcatenated?` added to `DecisionSummaryField`; `buildSummaryFields` passes `config.isConcatenated`
|
|
478
|
+
through verbatim. Purely additive (tsc + eslint clean). The adapter previously dropped concat config, so
|
|
479
|
+
the Compass / Compass Canada Total `CONFIG` override (stacks `_totalLease` under `_totalPurchase`)
|
|
480
|
+
would have been ignored FE-side; blox `renderBaseDetailFieldValue.tsx` already renders
|
|
481
|
+
valueKey+suffix+stacked+currency. (apeterson)
|
|
463
482
|
- 2026-07-21 — Migrated the **SalesOrders approve/deny decision modal** display config onto Surface via
|
|
464
483
|
an **overlay** adapter seam. New `surfaceBundlesToDecisionFields.ts` adapts the 3 resolved bundles
|
|
465
484
|
(`DECISION_SURFACE_SLUGS`) into `{orderContentDetails, approve, deny}`, finding elements by
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: session
|
|
3
|
+
slug: nycdoe-hold-sync
|
|
4
|
+
title: NYC DOE onsite-repair hold status sync to ServiceNow
|
|
5
|
+
author: sking
|
|
6
|
+
repos: [worker, library]
|
|
7
|
+
framework: "1.0"
|
|
8
|
+
client: nycdoe
|
|
9
|
+
status: active
|
|
10
|
+
created: 2026-07-21
|
|
11
|
+
updated: 2026-07-21
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Session: nycdoe-hold-sync
|
|
15
|
+
**Date:** 2026-07-21
|
|
16
|
+
**Project/Repo:** worker + library (1.0)
|
|
17
|
+
**Task:** Make the "on hold" statuses set on NYC DOE onsite-repair Incident (INC) tickets in TogaDesk sync to — and stay on — the ServiceNow (nycd3) client side, and stop the TogaDesk ticket from reverting on inbound sync. DEPLOYED AND CONFIRMED WORKING.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What WORKED
|
|
22
|
+
<!-- Include specific file paths and evidence -->
|
|
23
|
+
- **Root-cause discovery via `Logs.API` (legacy prod):** Outbound nycd3 PATCHes are logged in `Logs.API` (direction=OUT, endpoint LIKE '%nycd3/data/tasks/%'). This is the primary diagnostic surface for this integration. Repair orders live in `TOGaDeskSupport`, tickets in `Common.NYCDOETickets`.
|
|
24
|
+
- **Controlled test PATCH proved the authoritative field.** A one-off script PATCHing `{u_status_task:'On Hold'}` to INC2192842 returned `{"status":"success"}`, and a re-fetch showed `u_status_task='On Hold'` while native `state` stayed `In Progress`. The value **persisted 3+ days** (still On Hold on 2026-07-20). → `u_status_task` (custom field) is the client-facing/authoritative status, writable independently of native `state`.
|
|
25
|
+
- **worker fix (PRs #1676 merged, #1677 merged):** In `worker/crons/sync/nycdoe/send_ticket_updates.php` — set `u_status_task='On Hold'` on the hold push (writable from any active state); set native `state=3` only when incident is In Progress (SLA pause, avoids empty-body rejection); on release set `u_status_task` back to `In Progress`; reconcile incidents already Resolved/Closed/Canceled by advancing `dtSynced` (stops the retry storm). Added named constants SN_STATE_IN_PROGRESS/ON_HOLD, SN_HOLD_REASON_DEFAULT, SN_TASK_STATUS_ON_HOLD/IN_PROGRESS.
|
|
26
|
+
- **library fix (PR #845 merged):** `library/app/model/togadesk/repairorder.php` — `qqStatus()` now recognizes all six hold constants (was only HOLD_AWAITING_APPROVAL, HOLD_OTHER) in both hold IN-clauses, so a bare `'HOLD'` note written by inbound no longer collapses the derived status to ORDER_ASSIGNED_AWAITING_SCHEDULING.
|
|
27
|
+
- **End result:** Deployed; hold now syncs to ServiceNow client side and no longer reverts. User confirmed successful.
|
|
28
|
+
- **Knowledge captured:** `knowledge/clients/nycdoe/features/hold-status-sync.md` updated + pushed (commit a05e184) — corrected the prior doc's backwards claim that native `state` was authoritative.
|
|
29
|
+
|
|
30
|
+
## What did NOT work — DO NOT RETRY THESE
|
|
31
|
+
<!-- Exact failure reasons — do not vague-ify -->
|
|
32
|
+
- **Setting native `state=3` alone (the original production behavior).** ServiceNow accepted it (`state` became "On Hold") but the client-facing `u_status_task` stayed "Open", so the client saw no change. Native `state` is NOT what the client/workflow reads. INC2173220 and INC2192842 both showed `state:"On Hold"` + `u_status_task:"Open"` simultaneously.
|
|
33
|
+
- **First fix attempt (In-Progress gate + closed-ticket reconcile only, worker PR #1676).** Necessary but insufficient — it fixed the empty-body retry storm but did NOT make the hold visible (never touched `u_status_task`). INC2195124 still "reverted as always."
|
|
34
|
+
- **Pushing native `state=3` from a non–In-Progress incident.** The nycd3 `data/tasks` PATCH returns **HTTP 200 with an EMPTY body** (no `result` object) — ServiceNow only allows native On Hold FROM In Progress. The old code then threw on the empty body and never advanced `dtSynced`, re-sending forever (INC2190846, a Canceled incident, accumulated **2,392** failed PATCHes).
|
|
35
|
+
- **`hold_reason=10`.** Dropped/stored empty by ServiceNow (not a valid choice value). Native On Hold sticks without it, so it's harmless but meaningless. Not the cause of anything.
|
|
36
|
+
- **Assuming the outbound was the only problem.** The hold also reverted LOCALLY: `qqStatus()` derived status from the latest `repair_order_notes.newstatus`, and inbound `process_tickets.php:1127` writes ServiceNow "On Hold" as the bare `STATUS_HOLD` ('HOLD') — which `qqStatus()` didn't list as a hold, so status fell through to ORDER_ASSIGNED_AWAITING_SCHEDULING. Fixing outbound alone would not have held.
|
|
37
|
+
|
|
38
|
+
## Not tried yet (candidates for next session)
|
|
39
|
+
- Confirm whether NYC DOE's SLA/timers actually key off native `state` vs `u_status_task` — if only `u_status_task` matters, the native `state=3` push (and the In-Progress gate around it) could be dropped entirely to simplify.
|
|
40
|
+
- Convert remaining pre-existing magic numbers in `send_ticket_updates.php` (`state = 8` Canceled, `state = 6` Resolved) to named constants (flagged by review, left out of scope).
|
|
41
|
+
- Broaden the same `u_status_task`-authoritative handling to the RITM path (`send_request_item_updates.php`) if RITM holds show the same client-visibility gap (it already reads `u_status_task=='On Hold'` but sets native `state=8`).
|
|
42
|
+
|
|
43
|
+
## Current file state
|
|
44
|
+
| File | Status | Notes |
|
|
45
|
+
|------|--------|-------|
|
|
46
|
+
| worker/crons/sync/nycdoe/send_ticket_updates.php | Modified, merged (#1676 + #1677), deployed | u_status_task hold push + native-state gate + closed reconcile + constants |
|
|
47
|
+
| library/app/model/togadesk/repairorder.php | Modified, merged (#845), deployed | qqStatus() recognizes all 6 hold constants in both IN-clauses |
|
|
48
|
+
| worker/crons/sync/nycdoe/test_hold_ustatus.php | Deleted from worker repo | One-off Phase-A test; user kept a copy under test/@skyler/ |
|
|
49
|
+
| knowledge/clients/nycdoe/features/hold-status-sync.md (toga-tech) | Updated, pushed (a05e184) | Corrected authoritative-field model + gotchas |
|
|
50
|
+
|
|
51
|
+
## Decisions made
|
|
52
|
+
- **Write `u_status_task` as the hold signal (not just native `state`).** Rationale: proven via test PATCH to be the client-facing/authoritative field; inbound already keys off it. Rejected: native `state=3` only (invisible to client).
|
|
53
|
+
- **Keep native `state=3` but gate on In Progress.** Rationale: likely pauses the incident SLA; only legal from In Progress so gating avoids the empty-body rejection. Rejected: dropping native state entirely (deferred pending SLA confirmation); pushing state=3 unconditionally (causes retry storm).
|
|
54
|
+
- **Fix hold recognition in shared `qqStatus()` (library) rather than in process_tickets.** Rationale: bare `STATUS_HOLD` is a valid constant that qqStatus should recognize; additive change (classifies more notes as hold, never fewer), lowest-surprise root fix. Rejected: making process_tickets write HOLD_OTHER instead of bare HOLD (narrower, leaves qqStatus wrong for other callers).
|
|
55
|
+
- **Reconcile closed-on-SN incidents by advancing dtSynced.** Rationale: stop the infinite empty-body retry; let inbound move the order to Complete/Exception.
|
|
56
|
+
|
|
57
|
+
## Blockers
|
|
58
|
+
none — deployed and confirmed working.
|
|
59
|
+
|
|
60
|
+
## Exact next step
|
|
61
|
+
> None required — fix is complete, merged (worker #1676/#1677, library #845), deployed, and confirmed successful by the user. If revisiting: confirm with NYC DOE whether SLA keys off native `state` or `u_status_task`; if only `u_status_task`, simplify by removing the native `state=3` push and its In-Progress gate in `send_ticket_updates.php`.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
_Saved by /session-save on 2026-07-21_
|
package/package.json
CHANGED