toga-ai 1.0.707 → 1.0.708

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.
@@ -5,5 +5,5 @@
5
5
  | [NYCHH inventory-adjustment → item-fulfillment linking (direct FK columns, REST)](features/netsuite-inventory-adjustment-fulfillment-link.md) | 1.0 | For NYCHH stock adjustments, the NetSuite **inventory adjustment** carries a link to the **Item Fulfillment** it corrects, on the multi-select body custom field | library/app/api/toga2.php, library/app/api/netsuite/rest.php, worker/crons/toga2/netsuite/common_sync_togasupply.php, worker/crons/toga2/netsuite/sync_togasupply_hh.php, worker/crons/toga2/netsuite/diagnose_hh_import_inventory_adjustment.php |
6
6
  | [NYCHH NetSuite → TransferOrders import (stocking-flag routing, PO bridges, origin location)](features/netsuite-transfer-order-import.md) | 1.0 | NYCHH's NetSuite **transfer orders are represented as NetSuite sales orders** (same as the GroWrk pattern), so the shared NetSuite → TOGa Supply importer (`App_ | library/app/api/toga2.php, library/app/api/netsuite/rest.php, library/app/netsuite.php, worker/crons/toga2/netsuite/sync_togasupply_hh.php, worker/crons/toga2/netsuite/common_sync_togasupply.php, worker/crons/toga2/netsuite/diagnose_hh_stuck_transfer_order.php, dbchanges2/Core/2026-08-27a - TransferOrderUuidSearchableIdentifier.sql, dbchanges2/Client/2026-08-28a - TransferOrderItemsTimestampColumns.sql, dbchanges2/Client/2026-08-28b - TransferOrderItemsTimestampColumnsReposition.sql, dbchanges2/Client/2026-08-29 - ItemReceiptTransferOrderIdFieldPermission.sql, dbchanges2/Client/2026-08-29b - ItemReceiptItemTransferOrderItemIdFieldPermission.sql |
7
7
  | [NYCHH PO links are UPSTREAM — the downstream SO→PO route returns empty](features/po-number-upstream-direction.md) | 2.0 | NYCHH's sales orders are created **from the customer's purchase order**, so their SO↔PO links live in the **upstream** table `PurchaseOrders_SalesOrders` (route | _underscore/Model/Client/SalesOrder.php, _underscore/Trait/Netsuite/SalesOrder.php, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/hooks/usePurchaseOrderDetails.ts, dbchanges2/Client/2026-08-11b - SalesOrderPurchaseOrdersField.sql, dbchanges2/Client/2026-08-25 - SalesOrderPurchaseOrdersFieldAllClients.sql |
8
- | [NYCHH transfer-order 2.0 model — inventory quantities + V2 field enablement](features/transfer-order-inventory-quantities.md) | 2.0 | The 2.0 (`_underscore`) side of NYCHH transfer-order support: a **two-branch inventory quantity model** on the NYCHH `Item` override, plus the **client-override | _underscore/Model/Nychh/Item.php, _underscore/Model/Nychh/TransferOrder.php, _underscore/Model/Nychh/TransferOrderStage.php, _underscore/Model/Client/TransferOrder.php, _underscore/Model/Client/TransferOrderItem.php, dbchanges2/Client_Nychh/2026-08-27a - TransferOrderCustomFieldWritePermission.sql, dbchanges2/Client_Nychh/2026-08-27b - TransferOrderStageStatusIdentifier.sql, dbchanges2/Client_Nychh/2026-08-28c - TransferOrderRecordAcl.sql, dbchanges2/Client/2026-08-28b - TransferOrderItemsTimestamps.sql |
8
+ | [NYCHH transfer-order 2.0 model — inventory quantities + V2 field enablement](features/transfer-order-inventory-quantities.md) | 2.0 | The 2.0 (`_underscore`) side of NYCHH transfer-order support: a **two-branch inventory quantity model** on the NYCHH `Item` override, plus the **client-override | _underscore/Model/Nychh/Item.php, _underscore/Model/Nychh/PurchaseOrderItem.php, _underscore/Model/Nychh/TransferOrder.php, _underscore/Model/Nychh/TransferOrderStage.php, _underscore/Model/Client/TransferOrder.php, _underscore/Model/Client/TransferOrderItem.php, dbchanges2/Client_Nychh/2026-08-27a - TransferOrderCustomFieldWritePermission.sql, dbchanges2/Client_Nychh/2026-08-27b - TransferOrderStageStatusIdentifier.sql, dbchanges2/Client_Nychh/2026-08-28c - TransferOrderRecordAcl.sql, dbchanges2/Client/2026-08-28b - TransferOrderItemsTimestamps.sql |
9
9
  | [NYC Health & Hospitals](profile.md) | 2.0 | NYC Health & Hospitals (NYCHH) is a TOGA 2.0 client on the `_underscore` platform, prod schema `Client_Nychh`. | dbchanges2/Client_Nychh/2026-08-18 - InventoryUnitsItemColumns.sql, dbchanges2/Client_Nychh/2026-08-24 - FixInventoryGroupingsUnitsTopologyOverrideIds.sql, dbchanges2/Client_Nychh/2026-08-27a - TransferOrderCustomFieldWritePermission.sql, dbchanges2/Client_Nychh/2026-08-27b - TransferOrderStageStatusIdentifier.sql, dbchanges2/Client_Nychh/2026-08-28a - TransferOrdersTableView.sql, dbchanges2/Client_Nychh/2026-08-28b - TransferOrdersNavigationEnable.sql, dbchanges2/Client_Nychh/2026-08-28c - TransferOrderRecordAcl.sql, dbchanges2/Client/2026-08-28b - TransferOrderItemsTimestamps.sql |
@@ -6,10 +6,11 @@ project: _Underscore
6
6
  client: nychh
7
7
  type: client-feature
8
8
  status: active
9
- updated: 2026-08-28
9
+ updated: 2026-08-31
10
10
  owners: [jcardinal, apeterson]
11
11
  files:
12
12
  - _underscore/Model/Nychh/Item.php
13
+ - _underscore/Model/Nychh/PurchaseOrderItem.php
13
14
  - _underscore/Model/Nychh/TransferOrder.php
14
15
  - _underscore/Model/Nychh/TransferOrderStage.php
15
16
  - _underscore/Model/Client/TransferOrder.php
@@ -25,6 +26,8 @@ related:
25
26
  - ../../../2.0/apps/toga25-supply/features/transfer-orders-page.md
26
27
  - ../../growrk/features/transfer-order-flow.md
27
28
  - ./netsuite-transfer-order-import.md
29
+ - ./netsuite-inventory-adjustment-fulfillment-link.md
30
+ - ../../../2.0/apps/_underscore/features/sales-order-purchase-order-bridge-direction.md
28
31
  - ../profile.md
29
32
  ---
30
33
 
@@ -47,20 +50,84 @@ NYCHH-specific composition.
47
50
 
48
51
  ## NYCHH-only quantity calculations (two-branch inventory model)
49
52
 
50
- Per the 2026-08-17 "TOGa Supply" meeting. **NYCHH ONLY** — the overrides live on the client model
51
- `_Model_Nychh_Item` (`_underscore/Model/Nychh/Item.php`), not the base. Stocking orders bring stock
52
- **in**, transfer orders send it **out**, so the quantities reflect that direction:
53
+ Per the 2026-08-17 and 2026-08-27 "TOGa Supply" meetings. **NYCHH ONLY** — the overrides live on the
54
+ client models `_Model_Nychh_Item` (`_underscore/Model/Nychh/Item.php`) and, as of 2026-08-31, the new
55
+ `_Model_Nychh_PurchaseOrderItem` (`_underscore/Model/Nychh/PurchaseOrderItem.php`), not the base.
56
+ Stocking orders bring stock **in**, transfer orders send it **out**, so the quantities reflect that
57
+ direction:
53
58
 
54
59
  | Quantity | Definition |
55
60
  |---|---|
56
- | **on hand** | `received` (PO item receipts) − `fulfilled` (transfer-order item fulfillments) |
61
+ | **received** (stock-in) | net Σ `InventoryAdjustmentItems.quantityAdjustBy` on the item's **stocking** fulfillments |
62
+ | **on hand** | `received` − `fulfilled` (transfer-order item fulfillments) |
57
63
  | **available** | `on hand` − `committed` |
58
64
  | **fulfilled** | Σ shipped transfer-order fulfillments |
59
- | **backordered** | `ordered` − `received` |
65
+ | **backordered** | `ordered` − `received` (floored at 0) |
60
66
 
61
- `_qtyOnOrder` was added alongside these. The stock-in side reads PO receipts; the stock-out side
62
- reads transfer orders (which is why the 1.0 importer must populate
63
- `ItemFulfillmentItems.transferOrderItemId` — see the import doc).
67
+ `_qtyOnOrder` was added alongside these. The stock-out side reads transfer orders (which is why the
68
+ 1.0 importer must populate `ItemFulfillmentItems.transferOrderItemId` — see the import doc).
69
+
70
+ ### Stock-in now reads inventory adjustments, NOT PO item receipts (changed 2026-08-31)
71
+
72
+ Per the **2026-08-27 TOGa Supply meeting**: NetSuite has no "stocking" concept, so the only way stock
73
+ is added is an **inventory adjustment** linked to the stocking order's item fulfillment (never
74
+ directly to the PO). So `_Model_Nychh_Item::_qtyReceived` was changed to the **net
75
+ `SUM(InventoryAdjustmentItems.quantityAdjustBy)`**, joined
76
+ `InventoryAdjustmentItems.itemFulfillmentItemId → ItemFulfillmentItems.salesOrderItemId →
77
+ SalesOrderItems` where `SalesOrderItems.itemId = Items.id`. This **supersedes** the old PO-item-receipt
78
+ basis. Because on-hand and backordered both derive from `received`, they now use adjustments too.
79
+
80
+ - **The adjustment↔fulfillment link** is the direct FK `InventoryAdjustmentItems.itemFulfillmentItemId`
81
+ (recent; NULL on older adjustments). Details on
82
+ [NYCHH inventory-adjustment → item-fulfillment linking](./netsuite-inventory-adjustment-fulfillment-link.md).
83
+ - **Implicit stocking filter:** joining through `ItemFulfillmentItems.salesOrderItemId` counts only
84
+ **stocking-side** fulfillments — transfer-side fulfillment items have that column NULL — and all
85
+ Client_Nychh SalesOrders are stocking orders by the import routing.
86
+ - **⚠ Reads 0.00 today, by design.** Verified in prod Client_Nychh 2026-08-31: `InventoryAdjustmentItems`
87
+ has 292 rows but **0** carry `itemFulfillmentItemId`, and all 351 `ItemFulfillmentItems` are
88
+ transfer-side (`salesOrderItemId = 0`). INNER JOINs make an unlinked adjustment contribute 0, so every
89
+ item reads 0 **until the NetSuite integration backfills the link** — expected, not a bug.
90
+
91
+ ## Per-PO-line quantities — `_Model_Nychh_PurchaseOrderItem` (new 2026-08-31)
92
+
93
+ `_Model_Nychh_PurchaseOrderItem extends _Model_Client_PurchaseOrderItem` gives the **same quantities
94
+ as Item level, but limited to a single purchase-order line** (previously these existed only at Item
95
+ level), which NYCHH needs for PO-specific fulfillment.
96
+
97
+ - **`_qtyReceived`** — adjustment stock-in (same as Item) but scoped to the PO line via
98
+ `PurchaseOrderItems_SalesOrderItems` (the PO→SO stocking bridge; see the bridge note below).
99
+ - **`_qtyCommitted`** — Transfer-Order based, scoped to the PO line via
100
+ `PurchaseOrderItems_TransferOrderItems`, mirroring the Item-level two-branch model.
101
+ - **`_qtyOnHand` / `_qtyAvailable` / `_qtyBackordered` / `_qtyOnOrder`** are **re-declared verbatim** on
102
+ the child so early-bound `self::` rebinds to the new leaf `_qtyReceived`/`_qtyCommitted` (established
103
+ framework pattern — a composite `FIELD_SQL` method that calls `self::` must be re-declared on the
104
+ child, not inherited). `_qtyBackordered` is floored at 0 with `GREATEST`, matching Item level.
105
+
106
+ > **⚠ Signature must match the parent EXACTLY** when overriding a `FIELD_SQL` static method — an added
107
+ > param type is a **fatal at class load** that `php -l` does NOT catch. Verified this session by
108
+ > php-reviewer + sql-reviewer.
109
+
110
+ ### Which SO↔PO bridge scopes the PO line (they are two directional tables, not duplicates)
111
+
112
+ The item-level bridges mirror the header-level SO↔PO direction split documented on
113
+ [SO↔PO bridge direction](../../../2.0/apps/_underscore/features/sales-order-purchase-order-bridge-direction.md):
114
+
115
+ - `PurchaseOrderItems_SalesOrderItems` — **SO items created FROM a PO item** (PO→SO stocking direction);
116
+ the **populated/canonical** one for stocking (682 rows in prod). PO-line stock-in scopes on this.
117
+ - `SalesOrderItems_PurchaseOrderItems` — PO items created FROM a SO item (3 rows).
118
+
119
+ Verified 0 SO lines map to >1 PO line, so PO-line `received` **cannot double-count**. Optional deferred
120
+ hardening (not done): a `UNIQUE(purchaseOrderItemId, salesOrderItemId)` on the bridge as defense-in-depth.
121
+
122
+ - **⚠ PO-level outbound reads 0 until a separate backfill.** `_qtyCommitted` depends on
123
+ `PurchaseOrderItems_TransferOrderItems`, which is currently **empty (0 rows)** in prod — so PO-level
124
+ outbound reads 0 until the transfer-order import populates that bridge. Separate import gap, not this change.
125
+
126
+ ### Index coverage / schema
127
+
128
+ No `dbchanges2` file — pure calculated `FIELD_SQL` in PHP. All correlation columns
129
+ (`InventoryAdjustmentItems.itemFulfillmentItemId`, `ItemFulfillmentItems.salesOrderItemId`,
130
+ `SalesOrderItems.itemId`, both bridge FKs) are already indexed.
64
131
 
65
132
  ## V2 field enablement — how the TransferOrder POST was made to work
66
133
 
@@ -153,11 +220,28 @@ pattern (default a NOT NULL non-writable column in the model, never send it) is
153
220
  trait on the client-override model) AND the ACL/metadata rows exist.** Declaring without the ACL
154
221
  row, or granting the ACL without the declaration, each fails with its own error — see the peeled
155
222
  sequence above.
156
- - **These quantity overrides are NYCHH-only.** They live on `_Model_Nychh_Item`; do not lift them to
157
- the base `_Model_Client_Item` — other clients do not have the stocking/transfer two-branch model.
223
+ - **These quantity overrides are NYCHH-only.** They live on `_Model_Nychh_Item` and
224
+ `_Model_Nychh_PurchaseOrderItem`; do not lift them to the base `_Model_Client_*` — other clients do
225
+ not have the stocking/transfer two-branch model.
226
+ - **A 0.00 quantity for NYCHH is expected today, not a bug.** Stock-in reads inventory-adjustment links
227
+ that are not backfilled yet, and PO-level outbound reads a still-empty
228
+ `PurchaseOrderItems_TransferOrderItems` bridge (see above).
158
229
 
159
230
  ## Change history
160
231
 
232
+ - 2026-08-31 — **Stock-in flipped from PO item receipts → inventory adjustments** (per the 2026-08-27
233
+ TOGa Supply meeting: NetSuite has no stocking concept, stock is added only by an inventory adjustment
234
+ linked to the stocking order's item fulfillment). Changed `_Model_Nychh_Item::_qtyReceived` to net
235
+ `SUM(InventoryAdjustmentItems.quantityAdjustBy)` joined
236
+ `itemFulfillmentItemId → ItemFulfillmentItems.salesOrderItemId → SalesOrderItems` (`itemId = Items.id`);
237
+ on-hand and backordered follow. Added the **NYCHH-only `_Model_Nychh_PurchaseOrderItem`** for per-PO-line
238
+ quantities (same logic scoped to the PO line via `PurchaseOrderItems_SalesOrderItems` for received and
239
+ `PurchaseOrderItems_TransferOrderItems` for committed; composite `FIELD_SQL` methods re-declared verbatim
240
+ to rebind early-bound `self::`; backordered floored with `GREATEST`). Both read **0.00 in prod today** by
241
+ design — the adjustment↔fulfillment links are not backfilled (292 adjustment items, 0 linked; all 351
242
+ fulfillment items transfer-side) and `PurchaseOrderItems_TransferOrderItems` is empty. No dbchanges2
243
+ (pure `FIELD_SQL`; correlation columns already indexed); double-count ruled out (0 SO lines map to >1 PO
244
+ line). `php -l` clean; php-reviewer 0 critical, sql-reviewer warnings resolved. (jcardinal)
161
245
  - 2026-08-28 — Discovered that the transfer-order enablement on **prod and sandbox-client is
162
246
  UNTRACKED**: record ACL for 312/313 (roles 1 and 3), their logic-group/expression chain, field ACL
163
247
  for all 17 RecordFields, and the `TransferOrderItems.dtCreated`/`dtUpdated` columns all exist with
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.707",
3
+ "version": "1.0.708",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",