toga-ai 1.0.795 → 1.0.796
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/_underscore/features/calculated-sql-fields.md +19 -0
- package/knowledge/2.0/apps/_underscore/features/page-meta-context-field-settings.md +23 -2
- package/knowledge/2.0/apps/_underscore/features/tableview-joins.md +34 -1
- package/knowledge/2.0/apps/_underscore/features/units-for-items-for-purchase-orders.md +56 -3
- package/knowledge/2.0/apps/api2/features/v2-api-error-codes.md +12 -1
- package/knowledge/clients/nychh/profile.md +51 -0
- package/package.json +1 -1
|
@@ -20,6 +20,8 @@ files:
|
|
|
20
20
|
- api2/Component/Api/V2/V2.php
|
|
21
21
|
- _underscore/Model/Quad/Item.php
|
|
22
22
|
- _underscore/Model/Quad/VendorItem.php
|
|
23
|
+
- _underscore/Model/Nychh/Unit.php
|
|
24
|
+
- dbchanges2/Client_Nychh/2026-09-10a - UnitsForPoTableViewRebaseAndTransferLocationField.sql
|
|
23
25
|
- dbchanges2/Client/2026-08-11b - SalesOrderPurchaseOrdersField.sql
|
|
24
26
|
- dbchanges2/Client/2026-08-25 - SalesOrderPurchaseOrdersFieldAllClients.sql
|
|
25
27
|
related:
|
|
@@ -253,6 +255,23 @@ characters — that is the standard of evidence for touching a field that runs o
|
|
|
253
255
|
[save-cascade stored-field deadlocks](./model-save-parent-cascade-stored-field-deadlock.md).
|
|
254
256
|
|
|
255
257
|
## Change history
|
|
258
|
+
- 2026-09-10 — Added two NYCHH-only calc fields on `_Model_Nychh_Unit`
|
|
259
|
+
(`_underscore/Model/Nychh/Unit.php`) for the rebuilt `units-for-items-for-purchase-orders` grid,
|
|
260
|
+
both plain `FIELD_SQL` (text — no `FIELDOPT_SQL_TYPE`): **(a)** an **override** of
|
|
261
|
+
`_unitDisposition()` — NYCHH does **not** use the `UnitDispositions` lookup; disposition is derived
|
|
262
|
+
purely from the transfer chain (`Deployed` if an `ItemFulfillmentItems` with
|
|
263
|
+
`transferOrderItemId IS NOT NULL` exists for the unit, else `Available`). The override **matches the
|
|
264
|
+
parent's untyped signature exactly** (the contravariance fatal above). **(b)** a **new**
|
|
265
|
+
`_transferLocation` field returning the transfer-order destination location name via
|
|
266
|
+
Units → ItemFulfillmentItemUnits → ItemFulfillmentItems → TransferOrderItems → TransferOrders →
|
|
267
|
+
destinationLocationId → Locations (`ORDER BY` fulfillment id `DESC LIMIT 1`), registered as a
|
|
268
|
+
`Client_Nychh.CustomRecordFields` row (record 31) + Base-role `AclCustomFieldPermissions` grant in
|
|
269
|
+
`Client_Nychh/2026-09-10a`. **Why a calc field and not a TableView join:** the location chain
|
|
270
|
+
re-uses `ItemFulfillmentItems`/`ItemFulfillmentItemUnits` a **second** time, and `TableViewJoins`'
|
|
271
|
+
`onB` renders the raw table name — so a chain off a duplicated table binds to the wrong copy (the
|
|
272
|
+
duplicate-join hazard in [tableview-joins](./tableview-joins.md)). A calc field sidesteps the alias
|
|
273
|
+
problem entirely. Column header labeled via a `ClientCustomRecordFieldSettings` `label-singular`
|
|
274
|
+
row ("Location"). (jcardinal)
|
|
256
275
|
- 2026-09-10 — **Fixed `_Model_Client_Location::_addressState()` to return the state CODE, not
|
|
257
276
|
`Addresses.stateId`** (addresses rendered as `Bronx, 33 10451-5504`). Added
|
|
258
277
|
`LEFT JOIN States ON States.id = Addresses.stateId` inside the subquery and selected `States.code`
|
|
@@ -6,8 +6,8 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: [tcox, bala]
|
|
9
|
+
updated: 2026-09-10
|
|
10
|
+
owners: [tcox, bala, jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Core/Page.php
|
|
13
13
|
- _underscore/Model/Client/TableView.php
|
|
@@ -64,6 +64,19 @@ record route resolved through `$lookupRecordIdFromCustomRecordFieldId` →
|
|
|
64
64
|
metadata**, and no amount of adding/correcting those rows will move the header. (Measured
|
|
65
65
|
2026-08-26: two hours lost adding label rows that could never be read.)
|
|
66
66
|
|
|
67
|
+
> **⚠ SCOPE — this "dead metadata" is the legacy `Page.php` / `toga2-supply` path ONLY. On the
|
|
68
|
+
> `toga25-supply` table path it WORKS.** `toga25-supply` reads its grid headers from
|
|
69
|
+
> `/table-views/meta` (`_Model_Client_TableView::meta()`), which fetches
|
|
70
|
+
> `ClientCustomRecordFieldSettings` directly — so a **base** custom-field column (both context
|
|
71
|
+
> columns NULL) IS labeled by a `ClientCustomRecordFieldSettings` row with `settingId = 5`
|
|
72
|
+
> (`Core.Settings.slug = 'label-singular'`), `isOverridable = 1`. Verified live 2026-09-10: this is
|
|
73
|
+
> exactly how `Client_Elite` labels its custom unit columns (`c_grade` → "Grade", `c_chargingBrick`
|
|
74
|
+
> → "Charging Brick", …), and it is how NYCHH's `_transferLocation` column on
|
|
75
|
+
> `units-for-items-for-purchase-orders` gets its "Location" header
|
|
76
|
+
> (`Client_Nychh/2026-09-10c - TransferLocationColumnLabel.sql`). Do **not** move a custom field to
|
|
77
|
+
> a Core `RecordField` just to get a header on a `toga25-supply` grid — the client custom-field
|
|
78
|
+
> settings row is enough. The dead-metadata trap above still holds for the old `Page.php` consumers.
|
|
79
|
+
|
|
67
80
|
Where the label must come from instead, for such a column:
|
|
68
81
|
|
|
69
82
|
- **`Core.DefaultRecordFieldSettings`** on the underlying **Core** `RecordField`, or
|
|
@@ -181,6 +194,14 @@ data change, is what makes it fatal.
|
|
|
181
194
|
customization. The guard belongs in the framework.
|
|
182
195
|
|
|
183
196
|
## Change history
|
|
197
|
+
- 2026-09-10 — Scoped the "custom record field's label row is dead metadata" finding to the **legacy
|
|
198
|
+
`Page.php` / `toga2-supply`** consumer only. On the **`toga25-supply`** grid (headers from
|
|
199
|
+
`/table-views/meta` via `_Model_Client_TableView::meta()`, which fetches
|
|
200
|
+
`ClientCustomRecordFieldSettings` directly) a **base** custom-field column IS labeled by a
|
|
201
|
+
`ClientCustomRecordFieldSettings` row (both context columns NULL, `settingId = 5` =
|
|
202
|
+
`label-singular`, `isOverridable = 1`) — so the field need NOT be promoted to a Core `RecordField`
|
|
203
|
+
for a header. Verified against `Client_Elite`'s custom unit columns and NYCHH's `_transferLocation`
|
|
204
|
+
("Location") on the units-for-items-for-purchase-orders view. (jcardinal)
|
|
184
205
|
- 2026-08-26 - Documented that a grid column's **type** and its **header label** come from two
|
|
185
206
|
different endpoints: type/formatting (the currency icon) from `/table-views/meta`
|
|
186
207
|
`table.fields[].type` via `generateDynamicConfig` → `formatTableData`, header text from
|
|
@@ -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-10
|
|
10
10
|
owners: [bala, apeterson, jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Client/TableView.php
|
|
@@ -19,6 +19,8 @@ files:
|
|
|
19
19
|
- dbchanges2/Client_Nychh/2026-08-28a - TransferOrdersTableView.sql
|
|
20
20
|
- dbchanges2/Client_Nychh/2026-08-31a - PurchaseOrdersTableViewRebase.sql
|
|
21
21
|
- dbchanges2/Client_Nychh/2026-09-02a - PurchaseOrderItemsTableViewRebase.sql
|
|
22
|
+
- dbchanges2/Client_Nychh/2026-09-10a - UnitsForPoTableViewRebaseAndTransferLocationField.sql
|
|
23
|
+
- dbchanges2/Client_Nychh/2026-09-10b - UnitsForPoBridgeBaseAclGrant.sql
|
|
22
24
|
related:
|
|
23
25
|
- ../../api2/features/tableview-field-metadata.md
|
|
24
26
|
- ./page-meta-context-field-settings.md
|
|
@@ -232,6 +234,29 @@ So a role gap only 500s when a **visible column** hangs off the missing join —
|
|
|
232
234
|
client tolerates ACL gaps on records another client cannot. A new joined table (here
|
|
233
235
|
`Manufacturers`, record 20) needs its `AclRecordPermissions` grant in the same migration.
|
|
234
236
|
|
|
237
|
+
#### A dropped BRIDGE join in the middle of a chain 1054s even with NO column on it
|
|
238
|
+
|
|
239
|
+
The "harmless until a column hangs off it" rule has a sharp exception: a **bridge** join that sits
|
|
240
|
+
**in the middle of a chain**. Nothing shows a column from the bridge, but a **later** join's `onB`
|
|
241
|
+
names the bridge's raw table. When ACL drops the bridge, that later join emits an ON clause
|
|
242
|
+
referencing a table that was never added → **MySQL 1054**, not the readable
|
|
243
|
+
`AclRecordPermissions`-message from mode (b).
|
|
244
|
+
|
|
245
|
+
Confirmed NYCHH 2026-09-10 on the rebuilt `units-for-items-for-purchase-orders` view. The bridge
|
|
246
|
+
record **`PurchaseOrderItems_SalesOrderItems`** (Core record **290**) carried only an **API-role**
|
|
247
|
+
read grant in `Client_Nychh`. Records 30/29/15/18 in the chain already had a **Base** grant, so a
|
|
248
|
+
Base user's joins query dropped only the bridge — and the next join's ON referenced it:
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
Unknown column 'PurchaseOrderItems_SalesOrderItems.purchaseOrderItemId' in 'on clause'
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Fix: add the **Base** read grant as the full 4-table ACL chain (`AclRecordPermissions` →
|
|
255
|
+
`AclLogicGroups` → `AclLogicGroupExpressions`), reusing record 290's existing `all`
|
|
256
|
+
`AclRecordExpression` (`Client_Nychh/2026-09-10b - UnitsForPoBridgeBaseAclGrant.sql`). Watch for
|
|
257
|
+
**bridge records that ship with API-only grants** — a view that only ever ran for an API caller
|
|
258
|
+
(or in an environment tested as API) hides this until a Base user opens it.
|
|
259
|
+
|
|
235
260
|
### The debugging signature: 500 + EMPTY body + NO row in `Logs_<client>.Api`
|
|
236
261
|
|
|
237
262
|
Mode (a) throws *before* the response is assembled, so the caller gets a **500 with an empty
|
|
@@ -347,6 +372,14 @@ Core-level reference ids used (identical across all clients and environments): *
|
|
|
347
372
|
|
|
348
373
|
## Change history
|
|
349
374
|
|
|
375
|
+
- 2026-09-10 — Added the **bridge-in-a-chain ACL-drop = 1054** exception to mode (b): a dropped
|
|
376
|
+
bridge join with **no column on it** still breaks, because the next join's `onB` names the bridge's
|
|
377
|
+
raw table. NYCHH's rebuilt `units-for-items-for-purchase-orders` view 1054'd for a **Base** user —
|
|
378
|
+
bridge record 290 (`PurchaseOrderItems_SalesOrderItems`) had only an **API-role** grant while the
|
|
379
|
+
rest of the chain (30/29/15/18) had Base; error *"Unknown column
|
|
380
|
+
'PurchaseOrderItems_SalesOrderItems.purchaseOrderItemId' in 'on clause'"*. Fixed with the full
|
|
381
|
+
4-table Base ACL chain reusing record 290's `all` expression (`Client_Nychh/2026-09-10b`). Watch
|
|
382
|
+
for bridge records that ship with API-only grants. (jcardinal)
|
|
350
383
|
- 2026-09-03 — Added the **filter-only join counterpart** to the PO-items rebase: dropping a
|
|
351
384
|
column-less join that only *filtered* rows (SalesOrders→bridge→PurchaseOrders, ids 123/124/141)
|
|
352
385
|
breaks any row-filter still targeting that table. NYCHH's `items-for-purchase-orders`
|
|
@@ -6,12 +6,18 @@ project: _Underscore
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: ["bala", "tcox"]
|
|
9
|
+
updated: 2026-09-10
|
|
10
|
+
owners: ["bala", "tcox", "jcardinal"]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Client/ServiceRequest.php
|
|
13
|
+
- _underscore/Model/Nychh/Unit.php
|
|
13
14
|
- dbchanges2/Client/2026-08-11a - ServiceRequestsInventoryUnitsTableViews.sql
|
|
15
|
+
- dbchanges2/Client_Nychh/2026-09-10a - UnitsForPoTableViewRebaseAndTransferLocationField.sql
|
|
16
|
+
- dbchanges2/Client_Nychh/2026-09-10b - UnitsForPoBridgeBaseAclGrant.sql
|
|
17
|
+
- dbchanges2/Core/2026-09-10a - InventoryGroupingsUnitsLeafPoItemFilter.sql
|
|
14
18
|
related:
|
|
19
|
+
- ./calculated-sql-fields.md
|
|
20
|
+
- ./tableview-joins.md
|
|
15
21
|
- ./tracking-number-bridges.md
|
|
16
22
|
- ../../../clients/elite/features/supply2-tableview-config-drift.md
|
|
17
23
|
- ../../../clients/prudential/features/supply-orders-csv-export.md
|
|
@@ -74,6 +80,41 @@ a *different field per client*, so client custom columns (and their
|
|
|
74
80
|
Elite's four columns at index 14-17 (`grade`, `chargingBrick`, `chargingCable`, `wipeStatus` via
|
|
75
81
|
`c_deviceStatus`).
|
|
76
82
|
|
|
83
|
+
## NYCHH rebuilt the view onto the FULFILLMENT chain (2026-09-10)
|
|
84
|
+
|
|
85
|
+
This is the "resolver/view change that also walks the fulfillment path" the first gotcha below asks
|
|
86
|
+
for — shipped for one tenant. `Client_Nychh`'s `units-for-items-for-purchase-orders` view (base
|
|
87
|
+
record **Units 31**) was rebuilt to list the serialized units for a clicked **purchase-order item**,
|
|
88
|
+
showing Serial #, Asset Tag, Disposition, Location. The old 25-join / 12-column config (inaccurate)
|
|
89
|
+
was replaced with an **INNER** chain:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Units
|
|
93
|
+
-> ItemFulfillmentItemUnits (30)
|
|
94
|
+
-> ItemFulfillmentItems (29)
|
|
95
|
+
-> PurchaseOrderItems_SalesOrderItems bridge (290)
|
|
96
|
+
-> PurchaseOrderItems (18)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
plus a **filter-only** `SalesOrderItems (15)` join kept so the `itemsByPOs` drill path (which filters
|
|
100
|
+
by `SalesOrderItems.uuid`) still works. The grid is filtered at drill-down time by
|
|
101
|
+
`(PurchaseOrderItems.uuid:eq:...)`. File:
|
|
102
|
+
`dbchanges2/Client_Nychh/2026-09-10a - UnitsForPoTableViewRebaseAndTransferLocationField.sql`.
|
|
103
|
+
|
|
104
|
+
Two column values come from **NYCHH-only calc fields** on `_Model_Nychh_Unit`, not joins —
|
|
105
|
+
Disposition (`_unitDisposition`, overridden to derive from the transfer chain) and Location
|
|
106
|
+
(`_transferLocation`, new). Location is a calc field precisely because its chain re-uses
|
|
107
|
+
`ItemFulfillmentItems`/`ItemFulfillmentItemUnits` a **second** time, which the TableView alias model
|
|
108
|
+
cannot express (see [calculated-sql-fields](./calculated-sql-fields.md) and the duplicate-join hazard
|
|
109
|
+
in [tableview-joins](./tableview-joins.md)).
|
|
110
|
+
|
|
111
|
+
Two failures surfaced during this rebuild, both documented on
|
|
112
|
+
[tableview-joins](./tableview-joins.md): the mid-chain bridge record 290 shipped with an **API-only**
|
|
113
|
+
ACL grant, so a Base user 1054'd on `PurchaseOrderItems_SalesOrderItems.purchaseOrderItemId` in the
|
|
114
|
+
next join's ON clause (fixed by `Client_Nychh/2026-09-10b`); and the Inventory `posByItems` **leaf**
|
|
115
|
+
`additionalDataSlug` had to be the bare table name `PurchaseOrderItems` (the FE appends `.uuid`, so a
|
|
116
|
+
stored `PurchaseOrderItems.uuid` doubled to `.uuid.uuid` and 500'd — `Core/2026-09-10a`).
|
|
117
|
+
|
|
77
118
|
## Serial numbers for a Service Request - the bridge table is empty, use the fulfillment chain
|
|
78
119
|
|
|
79
120
|
`_Model_Client_ServiceRequest::_serialNumbers` (a `FIELD_SQL` field, so every client inherits it)
|
|
@@ -143,7 +184,10 @@ None — uniform. The linkage structure is framework-level and identical across
|
|
|
143
184
|
- **Missing item bridge → no units**, even when units were received. Without a
|
|
144
185
|
`SalesOrderItems_PurchaseOrderItems` row, the receipt path has no starting link.
|
|
145
186
|
- **A present bridge is not sufficient.** If the bridged PO line has no
|
|
146
|
-
`ItemReceiptItemUnits`, the receipt path still resolves to nothing.
|
|
187
|
+
`ItemReceiptItemUnits`, the receipt path still resolves to nothing. The **fulfillment-chain**
|
|
188
|
+
analog (NYCHH rebuild): a PO line with a bridge **and** a fulfillment but **zero
|
|
189
|
+
`ItemFulfillmentItemUnits`** (no serialized units captured) correctly shows an **empty grid** — that
|
|
190
|
+
is not a bug, just a line with no serials recorded.
|
|
147
191
|
- **`inventoryType` determines unit existence**: `SERIALIZED` and `HYBRID` items can produce
|
|
148
192
|
unit records; `NON_SERIALIZED` (bulk/consumable) never do. `HYBRID` items fulfilled as a
|
|
149
193
|
plain quantity (no serial capture) also produce no units — legitimately blank.
|
|
@@ -172,6 +216,15 @@ None — uniform. The linkage structure is framework-level and identical across
|
|
|
172
216
|
rather than reading the SQL.
|
|
173
217
|
|
|
174
218
|
## Change history
|
|
219
|
+
- 2026-09-10 - `Client_Nychh` **rebuilt this view onto the fulfillment chain** (Units → 30 → 29 →
|
|
220
|
+
290 bridge → PurchaseOrderItems 18, filtered by `(PurchaseOrderItems.uuid:eq:...)`), the first
|
|
221
|
+
"resolver that walks the fulfillment path" — lists serialized units for a clicked PO item with
|
|
222
|
+
Serial #, Asset Tag, Disposition, Location. Disposition/Location come from NYCHH-only
|
|
223
|
+
`_Model_Nychh_Unit` calc fields (`_unitDisposition` override, new `_transferLocation`) because the
|
|
224
|
+
location chain re-uses `ItemFulfillmentItems` twice. Added the empty-grid gotcha (bridge +
|
|
225
|
+
fulfillment but zero `ItemFulfillmentItemUnits` = correctly blank). Cross-refs the bridge Base-ACL
|
|
226
|
+
1054 and the surface-leaf slug-doubling fixes on [tableview-joins](./tableview-joins.md). Files:
|
|
227
|
+
`Client_Nychh/2026-09-10a`, `Client_Nychh/2026-09-10b`, `Core/2026-09-10a`. (jcardinal)
|
|
175
228
|
- 2026-08-28 - Corrected the `ServiceRequests_Units` "0 rows" note: that is an **Elite** measurement,
|
|
176
229
|
not a schema fact - `Client_Prudential` has **30,268 rows** and the bridge is the only unit-to-order
|
|
177
230
|
route there for never-shipped units (`SalesOrderItems_CommittedUnits` is the empty one on Prudential,
|
|
@@ -6,7 +6,7 @@ project: API
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-09-10
|
|
10
10
|
owners: [mhammontree, tcox, jcardinal, ajean, bala, apeterson]
|
|
11
11
|
files:
|
|
12
12
|
- api2/Component/Api/V2/V2.php
|
|
@@ -140,6 +140,13 @@ migration instead of re-deriving it. All field/script ACL rows live in the **CLI
|
|
|
140
140
|
`error.id` like `"8K-6"`. The part **before the dash** is `Logs.Issue.reference` —
|
|
141
141
|
`SELECT * FROM Logs.Issue WHERE reference = '8K'` gives the full `errorMessage` and stack
|
|
142
142
|
trace. The envelope itself tells you nothing useful; always go to `Logs.Issue`.
|
|
143
|
+
**A developer will often hand you this id verbally (e.g. "V7-6") to investigate — split on the
|
|
144
|
+
hyphen: the first part (`V7`) is `Logs.Issue.reference`, the second (`6`) is
|
|
145
|
+
`Logs.Event.eventNumber`. The two tables join on `Logs.Event.issueId = Logs.Issue.id`, so the
|
|
146
|
+
exact occurrence (and its `Logs.Event.clientId` tenant) is
|
|
147
|
+
`SELECT * FROM Logs.Event JOIN Logs.Issue ON Logs.Event.issueId = Logs.Issue.id WHERE
|
|
148
|
+
Logs.Issue.reference = 'V7' AND Logs.Event.eventNumber = 6`.** (`Logs.Issue` has no `dtUpdated`
|
|
149
|
+
column.)
|
|
143
150
|
Corollary: if `transactionId`, `authority` and `audience` are **all NULL** in the error
|
|
144
151
|
envelope, the request failed **before client context was established**.
|
|
145
152
|
|
|
@@ -292,6 +299,10 @@ Full mechanics:
|
|
|
292
299
|
- The response-envelope shape and code families: see [api2 architecture](../architecture.md).
|
|
293
300
|
|
|
294
301
|
## Change history
|
|
302
|
+
- 2026-09-10 — Made the developer-shorthand decode of an `error.id` explicit under diagnosis note 9:
|
|
303
|
+
a verbally-provided id like "V7-6" splits into `Logs.Issue.reference` (before the hyphen) +
|
|
304
|
+
`Logs.Event.eventNumber` (after), joined by `Logs.Event.issueId = Logs.Issue.id`; added the ready
|
|
305
|
+
`Logs.Event JOIN Logs.Issue` lookup and noted `Logs.Issue` has no `dtUpdated` column. (jcardinal)
|
|
295
306
|
- 2026-08-27 — Added three codes/notes from the NYCHH transfer-order POST work: **EV-10** (a NOT NULL
|
|
296
307
|
column received NULL — `originLocationId cannot be null`; resolve upstream or default in the ORM), a
|
|
297
308
|
second **EV-12** flavor (`searchableIdentifierFields:[id]` — a nested FK resolved *through* a `c_`
|
|
@@ -33,6 +33,12 @@ files:
|
|
|
33
33
|
- dbchanges2/Client/2026-09-01a - PurchaseOrderItemQtyFieldsApiRoleRead.sql
|
|
34
34
|
- dbchanges2/Client_Nychh/2026-09-02a - TalosAssistantEnable.sql
|
|
35
35
|
- dbchanges2/Client_Nychh/2026-09-09c - UpdateLocationShippingAddresses.sql
|
|
36
|
+
- _underscore/Model/Nychh/Unit.php
|
|
37
|
+
- dbchanges2/Client_Nychh/2026-09-10a - UnitsForPoTableViewRebaseAndTransferLocationField.sql
|
|
38
|
+
- dbchanges2/Client_Nychh/2026-09-10b - UnitsForPoBridgeBaseAclGrant.sql
|
|
39
|
+
- dbchanges2/Client_Nychh/2026-09-10c - TransferLocationColumnLabel.sql
|
|
40
|
+
- dbchanges2/Core/2026-09-10a - InventoryGroupingsUnitsLeafPoItemFilter.sql
|
|
41
|
+
- dbchanges2/Core/2026-09-10b - UnitDispositionColumnLabel.sql
|
|
36
42
|
related:
|
|
37
43
|
- ./features/location-shipping-addresses.md
|
|
38
44
|
- ../../2.0/apps/dbchanges2/workflows/deleting-contacts-from-a-client-database.md
|
|
@@ -206,6 +212,51 @@ table views. Client-specific DB change-sets live in `dbchanges2/Client_Nychh/`.
|
|
|
206
212
|
`PurchaseOrders.id` 81, onB `PurchaseOrderItems.purchaseOrderId` 90, sortOrder 7, no column). No
|
|
207
213
|
new ACL — record 17 already has Base/Developer/API read. Mechanism:
|
|
208
214
|
[tableview-joins](../../2.0/apps/_underscore/features/tableview-joins.md).
|
|
215
|
+
- **`units-for-items-for-purchase-orders` view rebuilt to list serials for a clicked PO item
|
|
216
|
+
(2026-09-10).** Base record Units (31). The old 25-join / 12-column config (inaccurate) was replaced
|
|
217
|
+
with an INNER chain **Units → ItemFulfillmentItemUnits (30) → ItemFulfillmentItems (29) →
|
|
218
|
+
PurchaseOrderItems_SalesOrderItems bridge (290) → PurchaseOrderItems (18)**, plus a **filter-only**
|
|
219
|
+
`SalesOrderItems (15)` join kept so the `itemsByPOs` drill (filters by `SalesOrderItems.uuid`) still
|
|
220
|
+
works. Filtered at drill-down by `(PurchaseOrderItems.uuid:eq:...)`. Columns: Serial #, Asset Tag,
|
|
221
|
+
Disposition, Location. File `Client_Nychh/2026-09-10a -
|
|
222
|
+
UnitsForPoTableViewRebaseAndTransferLocationField.sql`. Four connected pieces:
|
|
223
|
+
1. **Two NYCHH-only calc fields on `_Model_Nychh_Unit`** (`_underscore/Model/Nychh/Unit.php`), both
|
|
224
|
+
plain `FIELD_SQL` text. **`_unitDisposition` is OVERRIDDEN** — NYCHH does **not** use the
|
|
225
|
+
`UnitDispositions` lookup; disposition is `Deployed` if an `ItemFulfillmentItems` with
|
|
226
|
+
`transferOrderItemId IS NOT NULL` exists for the unit, else `Available` (override matches the
|
|
227
|
+
parent's untyped signature exactly). **`_transferLocation` is NEW** — the transfer-order
|
|
228
|
+
destination location name via Units → ItemFulfillmentItemUnits → ItemFulfillmentItems →
|
|
229
|
+
TransferOrderItems → TransferOrders → destinationLocationId → Locations (`ORDER BY` fulfillment
|
|
230
|
+
id `DESC LIMIT 1`); registered as a `Client_Nychh.CustomRecordFields` row (record 31) + Base
|
|
231
|
+
`AclCustomFieldPermissions`. It is a calc field, **not** a join, because the chain re-uses
|
|
232
|
+
`ItemFulfillmentItems`/`ItemFulfillmentItemUnits` a second time and the TableView alias model
|
|
233
|
+
would bind to the wrong copy. See
|
|
234
|
+
[calculated-sql-fields](../../2.0/apps/_underscore/features/calculated-sql-fields.md).
|
|
235
|
+
2. **Bridge Base ACL grant** — record 290 (`PurchaseOrderItems_SalesOrderItems`) shipped with only
|
|
236
|
+
an **API-role** read grant, so a Base user's joins query dropped the bridge and the next join's
|
|
237
|
+
ON errored `Unknown column 'PurchaseOrderItems_SalesOrderItems.purchaseOrderItemId' in 'on
|
|
238
|
+
clause'` (MySQL 1054). Fixed with the full 4-table Base ACL chain reusing record 290's `all`
|
|
239
|
+
expression: `Client_Nychh/2026-09-10b - UnitsForPoBridgeBaseAclGrant.sql`. Records 30/29/15/18
|
|
240
|
+
already had Base. Mechanism: [tableview-joins](../../2.0/apps/_underscore/features/tableview-joins.md).
|
|
241
|
+
3. **Surface drill-down LEAF slug** — the `inventory-list-groupings` `posByItems` **leaf**
|
|
242
|
+
`additionalDataSlug` had to be the bare table name `PurchaseOrderItems` (NOT
|
|
243
|
+
`PurchaseOrderItems.uuid`); the FE appends `.uuid` itself, so a stored `.uuid` doubled to
|
|
244
|
+
`.uuid.uuid` and 500'd (1054). Same doubling rule as the swap level above, one level deeper. This
|
|
245
|
+
is `Core.SurfaceElements` (all-client, no NYCHH override); `Core/2026-09-10a -
|
|
246
|
+
InventoryGroupingsUnitsLeafPoItemFilter.sql` (guard covers both `SalesOrderItems.uuid` and the
|
|
247
|
+
interim `PurchaseOrderItems.uuid`). Confirmed in toga25-supply
|
|
248
|
+
`useInventoryPageViewModel.tsx` (getAdditionalData).
|
|
249
|
+
4. **Column labels (settings layer, `Core.Settings` id 5 = `label-singular`)** — Disposition via a
|
|
250
|
+
`Core.DefaultRecordFieldSettings` row on Core field 619 (`_unitDisposition`), value "Disposition"
|
|
251
|
+
(`Core/2026-09-10b - UnitDispositionColumnLabel.sql`); Location via a
|
|
252
|
+
`Client_Nychh.ClientCustomRecordFieldSettings` row on `_transferLocation` (context columns NULL,
|
|
253
|
+
settingId 5, `isOverridable 1`), value "Location" (`Client_Nychh/2026-09-10c -
|
|
254
|
+
TransferLocationColumnLabel.sql`). Without a label row the grid falls back to the raw
|
|
255
|
+
`TableViewFields.slug`.
|
|
256
|
+
- **Empty grid for a given PO item is correct** when that line has a bridge + fulfillment but zero
|
|
257
|
+
`ItemFulfillmentItemUnits` (no serialized units captured) — not a bug.
|
|
258
|
+
- **Deploy:** the `_underscore` model change must land on **`_production`** and **`_sandbox-client`**
|
|
259
|
+
(api2 pulls `_underscore` per environment by branch); the SQL files run on prod + client-sandbox.
|
|
209
260
|
- **`inventory_units` table view carries item detail as of 2026-08-18** — Part Number, Manufacturer
|
|
210
261
|
and Item Description sit directly after Asset Tag, reached through a **chained** Units → Items →
|
|
211
262
|
Manufacturers join (`dbchanges2/Client_Nychh/2026-08-18 - InventoryUnitsItemColumns.sql`, identical
|
package/package.json
CHANGED