toga-ai 1.0.758 → 1.0.760
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/1.0/apps/library/features/netsuite-suiteql-rest-shim.md +26 -1
- package/knowledge/2.0/apps/_underscore/features/tableview-joins.md +39 -1
- package/knowledge/2.0/apps/toga25-supply/features/record-modals-and-nested-tables.md +20 -2
- package/knowledge/clients/nychh/profile.md +22 -5
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ project: Library
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-09-
|
|
9
|
+
updated: 2026-09-03
|
|
10
10
|
owners: [dfranks, jcardinal, kyalamarthi]
|
|
11
11
|
files:
|
|
12
12
|
- library/app/api/netsuite/rest.php
|
|
@@ -197,6 +197,23 @@ Forecast2 tables already store.
|
|
|
197
197
|
same underlying trap of reusing a sales-order-shaped assumption on a purchase order. Full
|
|
198
198
|
engine-side impact + the tier-wide per-client backfill live on the
|
|
199
199
|
[per-client-sync doc](../../worker/features/netsuite-togasupply-per-client-sync.md).
|
|
200
|
+
- **⚠ The three detail-fetch shims were inconsistent about `->lastModifiedDate` — two omitted it and
|
|
201
|
+
froze their sections once a per-record cursor started reading it (fixed 2026-09-03).**
|
|
202
|
+
`fetchItemReceiptById` set `$shim->lastModifiedDate` from its REST header, but **`fetchItemFulfillmentById`
|
|
203
|
+
and `fetchInventoryAdjustmentById` did not** (and InventoryAdjustment's SuiteQL header didn't even SELECT
|
|
204
|
+
`lastmodifieddate`). This was harmless until the 2026-09-02 per-record resume cursor: because
|
|
205
|
+
`syncItemFulfillmentFromNetsuite(&$rec)` / `syncInventoryAdjustmentFromNetsuite(&$rec)` **reassign** their
|
|
206
|
+
by-reference record to the fetch-by-id shim, the engine's cursor PUT then read `$rec->lastModifiedDate` on
|
|
207
|
+
the **replaced** object → *Undefined property: stdClass::$lastModifiedDate* → `App_Error` `exit()` → the
|
|
208
|
+
ITEM_FULFILLMENTS / INVENTORY_ADJUSTMENTS section froze at `1-RUNNING`, window ÷3 (GroWrk's fulfillments
|
|
209
|
+
re-threw every 5 min; InvAdj was latent only because no client had processed one since the rename). **Fix
|
|
210
|
+
(`library` only, `php -l` clean):** `$shim->lastModifiedDate = (string)(...)` in **both** shims —
|
|
211
|
+
fulfillment from the REST header, inventory-adjustment after adding
|
|
212
|
+
`TO_CHAR(lastmodifieddate,'YYYY-MM-DD HH24:MI:SS') AS lastmodifieddate` to its header SELECT. **Lesson:
|
|
213
|
+
a fetch-by-id shim consumed as the replacement for a `&$byReference` record must carry every field the
|
|
214
|
+
caller reads after the call — `lastModifiedDate` first.** Sales orders / POs / invoices don't reassign, so
|
|
215
|
+
they were unaffected. Engine-side detail on the
|
|
216
|
+
[per-client-sync doc](../../worker/features/netsuite-togasupply-per-client-sync.md).
|
|
200
217
|
- **A shim must produce the SOAP object's SHAPE, not just its scalar fields — an absent nested list
|
|
201
218
|
crashes 1.0 (2026-08-29).** `fetchCustomerById()`'s `addressbookList` was where the AIG lookup phase
|
|
202
219
|
crashed: a REST customer with no/odd address made the shim omit the nested `addressbook` structure the
|
|
@@ -290,6 +307,14 @@ None — uniform across clients (NetSuite is a single shared account).
|
|
|
290
307
|
|
|
291
308
|
## Change history
|
|
292
309
|
|
|
310
|
+
- 2026-09-03 — Recorded that **`fetchItemFulfillmentById` and `fetchInventoryAdjustmentById` omitted
|
|
311
|
+
`->lastModifiedDate`** (unlike `fetchItemReceiptById`), which froze ITEM_FULFILLMENTS + INVENTORY_ADJUSTMENTS
|
|
312
|
+
once the 2026-09-02 per-record cursor read that field off the by-reference record these shims replace. GroWrk
|
|
313
|
+
was the reported alert; shared code so all four active togasupply clients (GroWrk, NYCHH, Prudential-EDI,
|
|
314
|
+
S&P Global) were affected. Fixed by setting `$shim->lastModifiedDate` in both shims (adding `lastmodifieddate`
|
|
315
|
+
to InventoryAdjustment's SuiteQL SELECT). `library`-only, `php -l` clean, no data lost, self-heals after
|
|
316
|
+
deploy. Lesson: a fetch-by-id shim used to replace a `&$byReference` record must carry every field the
|
|
317
|
+
caller reads afterward. (jcardinal)
|
|
293
318
|
- 2026-09-02 — Recorded that **SuiteQL returns date columns in the account DISPLAY format (date-only
|
|
294
319
|
`M/D/YYYY` here) unless wrapped in `TO_CHAR`** — a bare `lastmodifieddate` silently drops the time and
|
|
295
320
|
is locale-dependent. This defeated the per-client sync's per-record resume cursor (stored `9/2/2026|id`,
|
|
@@ -6,7 +6,7 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-09-
|
|
9
|
+
updated: 2026-09-03
|
|
10
10
|
owners: [bala, apeterson, jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Client/TableView.php
|
|
@@ -28,6 +28,7 @@ related:
|
|
|
28
28
|
- ../../../../clients/compass-canada/features/item-fulfillment-tableviews.md
|
|
29
29
|
- ./acl-permission-chain.md
|
|
30
30
|
- ../../toga25-supply/features/transfer-orders-page.md
|
|
31
|
+
- ../../toga25-supply/features/record-modals-and-nested-tables.md
|
|
31
32
|
---
|
|
32
33
|
|
|
33
34
|
## Summary
|
|
@@ -134,6 +135,36 @@ For NYCHH both hops are **100% populated** (PO items 1129/1129, VendorItems 2414
|
|
|
134
135
|
**INNER** — no empty-grid risk (third failure mode above). Verify FK population per tenant first: a
|
|
135
136
|
tenant with sparse `vendorItemId` would need LEFT OUTER or would empty the grid.
|
|
136
137
|
|
|
138
|
+
### A dropped FILTER-ONLY join must be re-added when a row-filter still targets that table
|
|
139
|
+
|
|
140
|
+
The rebase above **dropped** the old SalesOrders→bridge→PurchaseOrders chain (join ids 123/124/141)
|
|
141
|
+
because those joins showed **no column** — they only filtered rows. But a filter-only join is still
|
|
142
|
+
needed if something still filters on that table. NYCHH's Inventory "Items by Customer POs" grouping
|
|
143
|
+
drills into `items-for-purchase-orders` with an `additionalDataSlug` that binds a
|
|
144
|
+
`(PurchaseOrders.uuid:eq:...)` where clause (see
|
|
145
|
+
[record-modals-and-nested-tables](../../toga25-supply/features/record-modals-and-nested-tables.md),
|
|
146
|
+
Pattern 5, and
|
|
147
|
+
[tableview-apiwhereclause-row-filtering](../../api2/features/tableview-apiwhereclause-row-filtering.md)).
|
|
148
|
+
After the rebase the view no longer joined PurchaseOrders, so that filter failed with **error
|
|
149
|
+
3L-2492**.
|
|
150
|
+
|
|
151
|
+
Fix (confirmed working NYCHH 2026-09-03): **INSERT one filter-only `TableViewJoins` row** on the
|
|
152
|
+
`items-for-purchase-orders` view re-adding a real PurchaseOrders join — no column hangs off it:
|
|
153
|
+
|
|
154
|
+
- `joinRecordId = 17` (PurchaseOrders), `joinOnRecordFieldId = 81` (`PurchaseOrders.id`) as onA,
|
|
155
|
+
`parentRecordFieldId = 90` (`PurchaseOrderItems.purchaseOrderId`) as onB.
|
|
156
|
+
- `type INNER` — `purchaseOrderId` is always populated on PO items, so no empty-grid risk (third mode
|
|
157
|
+
above). `sortOrder 7` (after the existing 1–6).
|
|
158
|
+
- **No ACL row needed** if PurchaseOrders already has read grants for the caller's roles: NYCHH's
|
|
159
|
+
record 17 already had Base(1)/Developer(2)/API(3), so the ACL-INNER-JOIN joins query keeps it.
|
|
160
|
+
- Idempotent: key to the view by `TableViews.slug` (id-agnostic) with a fixed uuid and a `NOT EXISTS`
|
|
161
|
+
guard on `(tableViewId, joinRecordId=17)`. Core ids 17/81/90 verified stable/identical across prod
|
|
162
|
+
and client-sandbox.
|
|
163
|
+
|
|
164
|
+
**Both env states were verified rebased** (prod AND client-sandbox: view 16 at base recordId 18 with
|
|
165
|
+
no PurchaseOrders join) — the earlier "rebase is prod-only, not on client-sandbox" note is now stale.
|
|
166
|
+
Applied to client-sandbox then prod (Client_Nychh).
|
|
167
|
+
|
|
137
168
|
Core ids for this conversion (verified prod 2026-09-02, identical across clients/envs): **Records** —
|
|
138
169
|
sales-order-items 15, purchase-order-items 18, vendor-items 19, items 21; item-level SO/PO bridges
|
|
139
170
|
289 (downstream) / 290 (upstream). **RecordFields** — `PurchaseOrderItems.quantity` 94,
|
|
@@ -316,6 +347,13 @@ Core-level reference ids used (identical across all clients and environments): *
|
|
|
316
347
|
|
|
317
348
|
## Change history
|
|
318
349
|
|
|
350
|
+
- 2026-09-03 — Added the **filter-only join counterpart** to the PO-items rebase: dropping a
|
|
351
|
+
column-less join that only *filtered* rows (SalesOrders→bridge→PurchaseOrders, ids 123/124/141)
|
|
352
|
+
breaks any row-filter still targeting that table. NYCHH's `items-for-purchase-orders`
|
|
353
|
+
`(PurchaseOrders.uuid:eq:...)` filter errored **3L-2492** post-rebase; fix is one INNER filter-only
|
|
354
|
+
PurchaseOrders join (joinRecordId 17, onA `PurchaseOrders.id` 81, onB `PurchaseOrderItems.purchaseOrderId`
|
|
355
|
+
90, sortOrder 7, no column, no new ACL). Confirmed working; both prod and client-sandbox verified
|
|
356
|
+
rebased (the prior "prod-only" note is stale). (jcardinal)
|
|
319
357
|
- 2026-09-02 — Documented the **sales-order-item → purchase-order-item view conversion**: it needs an
|
|
320
358
|
extra **VendorItems** hop because `PurchaseOrderItems` has no `itemId` (catalog reached via
|
|
321
359
|
`vendorItemId → VendorItems (record 19) → itemId → Items`), unlike `SalesOrderItems` which joins
|
|
@@ -6,8 +6,8 @@ project: TOGa 2.5 Supply
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-09-
|
|
10
|
-
owners: [apeterson, tcox]
|
|
9
|
+
updated: 2026-09-03
|
|
10
|
+
owners: [apeterson, tcox, jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/hooks/usePurchaseOrderDetails.ts
|
|
13
13
|
- toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx
|
|
@@ -127,6 +127,18 @@ level. Each level fetches its own meta + data and renders a `GenericTableLayout`
|
|
|
127
127
|
|
|
128
128
|
`additionalData` is produced per-level by callbacks (the WHERE-filter shape from Pattern 4). Each
|
|
129
129
|
level runs its own `useServerTableUrlState` and strips its own slug key, isolating URL state.
|
|
130
|
+
|
|
131
|
+
> **The FE APPENDS `.uuid` to a swap level's `additionalDataSlug` itself — so the stored surface
|
|
132
|
+
> value must be the BARE table name (`PurchaseOrders`), never `<Table>.uuid`.** The grouping config
|
|
133
|
+
> lives on `Core.SurfaceElements.config` (`inventory-list-groupings`, e.g. element key `posByItems`,
|
|
134
|
+
> in `$.levels[N].additionalDataSlug`). If you store `PurchaseOrders.uuid` there, the FE produces a
|
|
135
|
+
> **doubled** where clause `(PurchaseOrders.uuid.uuid:like:...)` and the filter never binds. Fix the
|
|
136
|
+
> stored value to just `PurchaseOrders` (JSON_SET keyed by `Surfaces.slug` + `config.key`, guarded to
|
|
137
|
+
> the stale value so it is re-runnable — id/uuid-agnostic because ids differ per env). Confirmed on
|
|
138
|
+
> NYCHH 2026-09-03: this Core row is all-client (no NYCHH SurfaceOverride), and its old
|
|
139
|
+
> `SalesOrders.uuid` was already wrong for a child view named `items-for-purchase-orders`. Sibling
|
|
140
|
+
> element `itemsByPOs` (view `purchase-orders_items`) still carries the stale `SalesOrders.uuid` —
|
|
141
|
+
> likely the same bug, not yet fixed.
|
|
130
142
|
A page-level `pageMeta` (from `useFetchPageMeta`) flows down for field-label overrides. The page
|
|
131
143
|
view model builds `TableLevel[]` arrays, picks the active one via a URL param, and passes `levels`
|
|
132
144
|
to `GenericNestedTables` with `key={activeGrouping.key}` to force remount and avoid stale state.
|
|
@@ -274,6 +286,12 @@ Scaffold per the `ItemRecordModalLayout` pattern (`src/layout/ItemRecordModalLay
|
|
|
274
286
|
[Transfer Orders page](transfer-orders-page.md).
|
|
275
287
|
|
|
276
288
|
## Change history
|
|
289
|
+
- 2026-09-03 — Documented that the FE **appends `.uuid`** to a `GenericNestedTables` swap level's
|
|
290
|
+
`additionalDataSlug`, so the stored `Core.SurfaceElements.config` value must be the **bare table
|
|
291
|
+
name** (`PurchaseOrders`), not `<Table>.uuid` — a `.uuid` in the stored value produces a doubled
|
|
292
|
+
`(PurchaseOrders.uuid.uuid:like:...)` where clause and the filter never binds. Found fixing the
|
|
293
|
+
NYCHH Inventory "Group: Items by Customer POs" grouping (`inventory-list-groupings`, element
|
|
294
|
+
`posByItems`); sibling `itemsByPOs` still stale. (jcardinal)
|
|
277
295
|
- 2026-09-02 — Fixed the approve/deny modal's Submit/Cancel row being cut off by a long "Reason for
|
|
278
296
|
Request" (found in testing by Skyler; approach agreed with David — grow the height a little, scroll
|
|
279
297
|
when it is very long). The single-action dialog is now taller but viewport-capped, and its action row
|
|
@@ -18,7 +18,7 @@ project: _Underscore
|
|
|
18
18
|
client: nychh
|
|
19
19
|
type: profile
|
|
20
20
|
status: active
|
|
21
|
-
updated: 2026-09-
|
|
21
|
+
updated: 2026-09-03
|
|
22
22
|
owners: ["jcardinal", "apeterson", "bala", "akhokhani"]
|
|
23
23
|
files:
|
|
24
24
|
- dbchanges2/Client_Nychh/2026-09-02a - TransferOrderNetsuitePushInterceptor.sql
|
|
@@ -97,15 +97,32 @@ table views. Client-specific DB change-sets live in `dbchanges2/Client_Nychh/`.
|
|
|
97
97
|
items 1129/1129, VendorItems 2414/2414) so both stay INNER. Seeds Developer-role record grants for
|
|
98
98
|
records 18 and 19 (both had only Base+API) plus Developer read on `PurchaseOrderItems.quantity`
|
|
99
99
|
(field 94); roles resolved by name, uuid-keyed, idempotent. Mechanism:
|
|
100
|
-
[tableview-joins](../../2.0/apps/_underscore/features/tableview-joins.md).
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
[tableview-joins](../../2.0/apps/_underscore/features/tableview-joins.md). **Applied to prod AND
|
|
101
|
+
client-sandbox** — both verified rebased 2026-09-03 (view 16 at base recordId 18, no PurchaseOrders
|
|
102
|
+
join). An earlier note here said this rebase was prod-only / not on client-sandbox; that is **stale**
|
|
103
|
+
— client-sandbox is also rebased. **OPEN:** the parent `purchase-orders` view filters to vendor 172
|
|
104
|
+
(`apiWhereClause
|
|
104
105
|
(vendorId:eq:172)`); this item view has no `apiWhereClause`, so it lists items for all POs — left
|
|
105
106
|
unfiltered (mirrors prior state), flagged as a decision for the dev. A "3L-2250" error reported
|
|
106
107
|
right after this deploy was **unrelated** — prod `Logs.Issue` reference **3L** is a Prudential ASN
|
|
107
108
|
error (`Client_Prudential.AdvanceShippingNoticeUnits` doesn't exist); the suffix is the occurrence
|
|
108
109
|
count (3L, occurrence 2250).
|
|
110
|
+
- **"Group: Items by Customer POs" grouping fixed to drill into PO items (2026-09-03).** After the
|
|
111
|
+
`items-for-purchase-orders` view was rebased to PO-items, the Inventory groupings surface
|
|
112
|
+
(`inventory-list-groupings`, element `posByItems`) was broken. Two fixes, both applied to
|
|
113
|
+
client-sandbox then prod (confirmed working):
|
|
114
|
+
1. **Stale filter slug** — the swap level's `additionalDataSlug` was `SalesOrders.uuid`; changed to
|
|
115
|
+
`PurchaseOrders`. The FE **appends `.uuid` itself**, so the stored value must be the bare table
|
|
116
|
+
name — `PurchaseOrders.uuid` produced a doubled `(PurchaseOrders.uuid.uuid:like:...)` clause.
|
|
117
|
+
This config is on `Core.SurfaceElements.config` (all-client, no NYCHH override); JSON_SET keyed by
|
|
118
|
+
`Surfaces.slug` + `config.key`, guarded/re-runnable. Sibling `itemsByPOs` still carries the stale
|
|
119
|
+
`SalesOrders.uuid` — likely the same bug, **not yet fixed**.
|
|
120
|
+
2. **Missing join** — the `(PurchaseOrders.uuid:eq:...)` filter errored **3L-2492** because the
|
|
121
|
+
rebase dropped the old SalesOrders→PurchaseOrders filter chain and the view no longer joined
|
|
122
|
+
PurchaseOrders. Added one filter-only INNER `TableViewJoins` row (joinRecordId 17, onA
|
|
123
|
+
`PurchaseOrders.id` 81, onB `PurchaseOrderItems.purchaseOrderId` 90, sortOrder 7, no column). No
|
|
124
|
+
new ACL — record 17 already has Base/Developer/API read. Mechanism:
|
|
125
|
+
[tableview-joins](../../2.0/apps/_underscore/features/tableview-joins.md).
|
|
109
126
|
- **`inventory_units` table view carries item detail as of 2026-08-18** — Part Number, Manufacturer
|
|
110
127
|
and Item Description sit directly after Asset Tag, reached through a **chained** Units → Items →
|
|
111
128
|
Manufacturers join (`dbchanges2/Client_Nychh/2026-08-18 - InventoryUnitsItemColumns.sql`, identical
|
package/package.json
CHANGED