toga-ai 1.0.156 → 1.0.157

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.
@@ -8,3 +8,4 @@
8
8
  | [Per-Client Database Connections & the Local Logs Trap](features/per-client-database-connections.md) | When `_underscore` serves a request for a client it opens **three distinct per-client database connections**, not one. | _underscore/Database.php, _underscore/ApiRequest.php, _underscore/Model/Client/Logs/Api.php |
9
9
  | [Recursive Item Fulfillments (upstream mirroring)](features/recursive-item-fulfillments.md) | In a multi-tier supply chain a sales order (SO) spawns a purchase order (PO) that becomes another SO downstream, and so on. | _underscore/Model/Client/ItemFulfillment.php, _underscore/Model/Client/ItemFulfillmentItem.php, _underscore/Model/Client/ItemFulfillmentItemUnit.php, _underscore/Model/Client/ItemFulfillmentPackage.php, _underscore/Model/Compass/AdvanceShippingNotice.php, dbchanges2/Core/2026-02-13 - 75601 - RecursiveItemFulfillmentCreation.sql, dbchanges2/Core/2026-06-04 - RecursiveItemFulfillmentPut.sql |
10
10
  | [Tracking-Number Bridge Migration (ASN / Item Fulfillment / Item Receipt)](features/tracking-number-bridges.md) | Shipment tracking numbers used to live as **scalar FK columns** (`trackingNumberId`, `returnTrackingNumberId`) directly on the lowest-level "unit"/"item" tables | api2/Component/Api/V2/V2.php, _underscore/Model/Client/AdvanceShippingNoticeItemUnit.php, _underscore/Model/Client/AdvanceShippingNoticeItemUnits/TrackingNumber.php, _underscore/Model/Client/ItemFulfillmentItemUnits/TrackingNumber.php, _underscore/Model/Client/ItemFulfillment.php, _underscore/Model/Prudential/AdvanceShippingNotice.php, _underscore/Model/Compass/AdvanceShippingNotice.php, _underscore/Trait/Netsuite/ItemFulfillment.php, api2/Component/Api/Cxml/Cxml.php, dbchanges2/Client/2026-06-10 - TrackingNumberBridges.sql, dbchanges2/Core/2026-06-10 - TrackingNumberBridges.sql, dbchanges2/Client_Prudential/2026-06-15 - ItemFulfillmentTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19b - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql, dbchanges2/Client_Quad/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql |
11
+ | [Units for Items for Purchase Orders — Data Structure](features/units-for-items-for-purchase-orders.md) | Describes how unit (serialized inventory) data is linked to sales-order and purchase-order line items behind the `units-for-items-for-purchase-orders` TableView | |
@@ -0,0 +1,92 @@
1
+ ---
2
+ title: Units for Items for Purchase Orders — Data Structure
3
+ framework: "2.0"
4
+ repo: _underscore
5
+ project: _Underscore
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-06-22
10
+ owners: ["bala"]
11
+ files: []
12
+ related: []
13
+ ---
14
+
15
+ ## Summary
16
+ Describes how unit (serialized inventory) data is linked to sales-order and purchase-order
17
+ line items behind the `units-for-items-for-purchase-orders` TableView. A unit only becomes
18
+ visible in this view if it can be walked from the sales-order item out to a unit record. There
19
+ are **two independent linkage paths** in the schema, and the view traverses only one of them —
20
+ which is the root cause of "units not showing" cases.
21
+
22
+ ## How it works
23
+ A `Unit` can be tied to an order line through either of two chains:
24
+
25
+ **1. Receipt path (what this view follows):**
26
+ ```
27
+ SalesOrderItems
28
+ -> SalesOrderItems_PurchaseOrderItems (item-level bridge: salesOrderItemId, purchaseOrderItemId)
29
+ -> PurchaseOrderItems (PurchaseOrderItems.id = bridge.purchaseOrderItemId)
30
+ -> ItemReceiptItems (ItemReceiptItems.purchaseOrderItemId = PurchaseOrderItems.id)
31
+ -> ItemReceiptItemUnits (ItemReceiptItemUnits.itemReceiptItemId = ItemReceiptItems.id)
32
+ -> Units (ItemReceiptItemUnits.unitId)
33
+ ```
34
+
35
+ **2. Fulfillment path (direct; NOT followed by this view):**
36
+ ```
37
+ SalesOrderItems
38
+ -> ItemFulfillmentItems (ItemFulfillmentItems.salesOrderItemId = SalesOrderItems.id)
39
+ -> ItemFulfillmentItemUnits (ItemFulfillmentItemUnits.itemFulfillmentItemId = ItemFulfillmentItems.id)
40
+ -> Units (ItemFulfillmentItemUnits.unitId)
41
+ ```
42
+
43
+ The receipt path requires both the item-level bridge **and** an item receipt against the
44
+ bridged purchase-order line. The fulfillment path reaches `SalesOrderItems` directly by
45
+ `salesOrderItemId` with no purchase order or bridge involved.
46
+
47
+ ## Data model
48
+ Header-level vs item-level bridges, and the level each transaction is anchored at:
49
+
50
+ - **`PurchaseOrders_SalesOrders`** — *header* bridge: links a customer PO to a sales order
51
+ (`purchaseOrderId`, `salesOrderId`).
52
+ - **`SalesOrderItems_PurchaseOrderItems`** — *item* bridge: links a sales-order line to a
53
+ vendor purchase-order line (`salesOrderItemId`, `purchaseOrderItemId`). This is the bridge
54
+ the receipt path depends on.
55
+ - **Item receipts are PO-anchored only**: `ItemReceipts.purchaseOrderId`,
56
+ `ItemReceiptItems.purchaseOrderItemId` — there is **no sales-order FK on a receipt**. The
57
+ only way a received unit reaches a sales order is through the item bridge.
58
+ - **Item fulfillments are SO-anchored**: `ItemFulfillments.salesOrderId`,
59
+ `ItemFulfillmentItems.salesOrderItemId`.
60
+ - Both customer POs and vendor POs live in the same `PurchaseOrders` table, distinguished by
61
+ which bridge references them (header bridge = customer PO; item bridge via
62
+ `PurchaseOrderItems` = vendor PO).
63
+ - `Items.inventoryType` governs whether units exist at all (see Gotchas).
64
+
65
+ ## Client variations
66
+ None — uniform. The linkage structure is framework-level and identical across clients.
67
+
68
+ ## Gotchas / known issues
69
+ - **The view only walks the receipt path.** A line whose units exist solely via the
70
+ fulfillment path (shipped from stock, never received against the bridged PO line) shows
71
+ **0 units** even though units physically exist. No data backfill can surface these — only a
72
+ resolver/view change that also walks the fulfillment path will.
73
+ - **Missing item bridge → no units**, even when units were received. Without a
74
+ `SalesOrderItems_PurchaseOrderItems` row, the receipt path has no starting link.
75
+ - **A present bridge is not sufficient.** If the bridged PO line has no
76
+ `ItemReceiptItemUnits`, the receipt path still resolves to nothing.
77
+ - **`inventoryType` determines unit existence**: `SERIALIZED` and `HYBRID` items can produce
78
+ unit records; `NON_SERIALIZED` (bulk/consumable) never do. `HYBRID` items fulfilled as a
79
+ plain quantity (no serial capture) also produce no units — legitimately blank.
80
+ - **Receipt-path counts are PO-line-wide.** Units surfaced reflect everything received against
81
+ the bridged PO line, which may exceed or differ from what was actually fulfilled to a given
82
+ sales order (over/under-attribution), because attribution is by PO line, not by the
83
+ fulfillment that shipped the unit.
84
+
85
+ ## Change history
86
+ - 2026-06-22 — Documented the two-path units linkage model behind the
87
+ units-for-items-for-purchase-orders view and why the receipt-only traversal hides
88
+ fulfillment-only units. (bala)
89
+
90
+ ## Related docs
91
+ - [[recursive-item-fulfillments]]
92
+ - [[tracking-number-bridges]]
@@ -14,7 +14,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
14
14
 
15
15
  ## 2.0 framework
16
16
 
17
- - **_underscore** (_Underscore) _(framework core)_ — 9 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
17
+ - **_underscore** (_Underscore) _(framework core)_ — 10 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
18
18
  - **worker2** (Worker) — 8 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
19
19
  - **api2** (API) — 4 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
20
20
  - **dbchanges2** (Database Changes) _(framework core)_ — 1 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.156",
3
+ "version": "1.0.157",
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",