toga-ai 1.0.55 → 1.0.57

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.
@@ -9,7 +9,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
9
9
 
10
10
  ## 2.0 framework
11
11
 
12
- - **_underscore** (_Underscore) _(framework core)_ — 4 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
12
+ - **_underscore** (_Underscore) _(framework core)_ — 5 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
13
13
  - **worker2** (Worker) — 5 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
14
14
  - **api2** (API) — 1 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
15
15
  - **dbchanges2** (Database Changes) _(framework core)_ — 1 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
@@ -3,5 +3,6 @@
3
3
  | Doc | Framework | Summary | Files |
4
4
  |-----|-----------|---------|-------|
5
5
  | [Compass ASN → ItemFulfillment Auto-Creation](features/asn-to-item-fulfillment.md) | 2.0 | For Compass USA, posting an AdvanceShippingNotice (ASN) auto-creates the ItemFulfillment (IF) on the upstream SalesOrder. | _underscore/Model/Compass/AdvanceShippingNotice.php, api2/Component/Api/Cxml/Cxml.php, dbchanges2/Client_Compass/2026-06-11 - AsnItemTrackingNumberAcl.sql |
6
- | [Compass: Item Fulfillments for Sales Order Items TableView (tracking via bridge)](features/item-fulfillment-tracking-tableview.md) | 2.0 | The Compass TableView `item-fulfillments-for-sales-order-items` (`TableViews.id = 13` in Client_Compass) was rebuilt as part of the tracking-number bridge migra | dbchanges2/Client_Compass/2026-06-10 - ItemFulfillmentsForSalesOrderItemsTableView.sql |
6
+ | [Compass: Item-Fulfillment TableViews (for-sales-order-items & for-sales-orders, tracking via bridge)](features/item-fulfillment-tracking-tableview.md) | 2.0 | Two sibling Compass TableViews in `Client_Compass` display fulfilled items in toga2-supply, both driven by `TableViews` / `TableViewJoins` / `TableViewFields` c | dbchanges2/Client_Compass/2026-06-10 - ItemFulfillmentsForSalesOrderItemsTableView.sql, dbchanges2/Client_Compass/2026-06-11 - ItemFulfillmentsForSalesOrdersTableView.sql |
7
+ | [Compass MITS PO → SO Item Linking](features/mits-po-to-so-item-linking.md) | 2.0 | MITS sends Compass inbound Purchase Orders (`POST /v2/purchase-orders`) against a Sales Order (`mitsSalesOrder`). | _underscore/Model/Compass/PurchaseOrder.php |
7
8
  | [Compass USA](profile.md) | 2.0 | Compass USA is a TOGA client running a multi-tier supply-chain commerce operation. | |
@@ -1,46 +1,85 @@
1
1
  ---
2
- title: "Compass: Item Fulfillments for Sales Order Items TableView (tracking via bridge)"
2
+ title: "Compass: Item-Fulfillment TableViews (for-sales-order-items & for-sales-orders, tracking via bridge)"
3
3
  framework: "2.0"
4
4
  project: _Underscore
5
5
  client: compass-usa
6
6
  type: client-feature
7
7
  status: active
8
- updated: 2026-06-10
8
+ updated: 2026-06-11
9
9
  owners: ["jcardinal"]
10
10
  files:
11
11
  - dbchanges2/Client_Compass/2026-06-10 - ItemFulfillmentsForSalesOrderItemsTableView.sql
12
+ - dbchanges2/Client_Compass/2026-06-11 - ItemFulfillmentsForSalesOrdersTableView.sql
12
13
  related:
13
14
  - ../../../2.0/apps/_underscore/features/tracking-number-bridges.md
14
15
  ---
15
16
 
16
17
  ## Summary
17
18
 
18
- The Compass TableView `item-fulfillments-for-sales-order-items` (`TableViews.id = 13` in
19
- Client_Compass) was rebuilt as part of the tracking-number bridge migration. It was rooted at
20
- **Units** with INNER joins (so non-serialized items with no unit never appeared) and sourced the
21
- outbound tracking number from the now-dropped `ItemFulfillmentItemUnits.trackingNumberId`.
19
+ Two sibling Compass TableViews in `Client_Compass` display fulfilled items in toga2-supply,
20
+ both driven by `TableViews` / `TableViewJoins` / `TableViewFields` config (no PHP):
22
21
 
23
- ## How it works (new definition)
22
+ - **`item-fulfillments-for-sales-order-items`** (`TableViews.id = 13`) — fulfilled items for a
23
+ single sales-order line.
24
+ - **`item-fulfillments-for-sales-orders`** (`TableViews.id = 12`) — fulfilled items across the
25
+ whole sales order.
24
26
 
25
- - **Base record re-rooted** to `ItemFulfillmentItems` (record 29).
26
- - Joins: INNER `SalesOrderItems`; **OUTER** `ItemFulfillmentItemUnits` (so items without a
27
- serialized unit still return); OUTER `Units`; OUTER the new `ItemFulfillmentItemUnits_TrackingNumbers`
28
- bridge (record 319) OUTER `TrackingNumbers` OUTER `ShippingCarriers`.
29
- - Columns, in order: **Sales Order Line Number, Quantity Fulfilled (new — `ItemFulfillmentItems.quantity`),
27
+ Both were originally **rooted at `Units` (record 31) with INNER joins upward**, so any fulfilled
28
+ item with no serialized unit (no `ItemFulfillmentItemUnits` / `Units`) never appeared — and for
29
+ view 12, an entire order with zero unit-level rows returned **0 records** even though its items
30
+ were fulfilled. View 13 was re-rooted on 2026-06-10; view 12 on 2026-06-11.
31
+
32
+ ## How it works (new definitions)
33
+
34
+ Both views are re-rooted at **`ItemFulfillmentItems` (record 29)** so every fulfilled item appears,
35
+ with the unit/tracking chain made **OUTER** so missing units no longer drop rows.
36
+
37
+ **View 13 — `item-fulfillments-for-sales-order-items`:**
38
+ - INNER `SalesOrderItems`; OUTER `ItemFulfillmentItemUnits` → OUTER `Units` → OUTER
39
+ `ItemFulfillmentItemUnits_TrackingNumbers` (record 319) → OUTER `TrackingNumbers` → OUTER `ShippingCarriers`.
40
+ - Columns: **Sales Order Line Number, Quantity Fulfilled (`ItemFulfillmentItems.quantity`),
30
41
  Outbound Tracking #, Carrier, Serial #, Asset Tag.**
31
- - Default sort (`TableViews.sortPrimaryTableViewFieldId`) re-pointed to the line-number field.
42
+
43
+ **View 12 — `item-fulfillments-for-sales-orders`:**
44
+ - Same base + OUTER unit/tracking chain, plus the order-scoping INNER joins:
45
+ INNER `SalesOrderItems`, INNER `ItemFulfillments`, INNER `SalesOrders`, INNER `Items`.
46
+ - Columns: **Sales Order Line Number, Part Number (`Items.partNumber`), Quantity Fulfilled,
47
+ Outbound Tracking # (hyperlink via `TrackingNumbers._hyperlink` rf 1272), Carrier, Serial #, Asset Tag.**
48
+ - Default sort re-pointed to the line-number field.
49
+
50
+ Stable Core ids used: records 29 IFI, 30 IFIU, 31 Units, 15 SalesOrderItems, 14 SalesOrders,
51
+ 28 ItemFulfillments, 21 Items, 319 IFIU-tracking bridge, 62 TrackingNumbers, 9 ShippingCarriers.
52
+
53
+ ## Data model
54
+
55
+ Join keys (RecordField ids): 60 SOI.id / 368 IFI.salesOrderItemId; 360 IF.id / 367 IFI.itemFulfillmentId;
56
+ 59 SO.id / 254 SOI.salesOrderId; 105 Item.id / 66 SOI.itemId; 374 IFIU.itemFulfillmentItemId / 365 IFI.id;
57
+ 236 Unit.id / 375 IFIU.unitId; 2183 bridge.itemFulfillmentItemUnitId / 372 IFIU.id;
58
+ 336 TN.id / 2184 bridge.trackingNumberId; 21 SC.id / 613 TN.shippingCarrierId.
32
59
 
33
60
  ## Gotchas / known issues
34
61
 
62
+ - **A Unit-rooted view returns 0 rows whenever the order has no unit-level breakdown.** Symptom
63
+ seen on SA132740 (salesOrderId 105826): 13 SalesOrderItems, 7 ItemFulfillmentItems, but **0
64
+ ItemFulfillmentItemUnits / 0 Units** → view 12 showed "0 records" while the re-rooted sibling
65
+ view 13 showed the items fine. Fix is structural (re-root + OUTER chain), independent of the
66
+ missing-unit data issue.
35
67
  - Tracking is sourced through the bridge join (`ItemFulfillmentItemUnits_TrackingNumbers.trackingNumberId`),
36
- NOT the dropped column. The bridge record/fields (319 / 2183 itemFulfillmentItemUnitId / 2184
37
- trackingNumberId) come from the Core migration and must exist before this file runs.
38
- - `TableViews.sortPrimaryTableViewFieldId` is a FK to `TableViewFields`; it must be set NULL before the
39
- old fields are deleted, then re-pointed (via a multi-table UPDATE, not a self-subquery, to avoid 1093).
68
+ NOT the dropped `ItemFulfillmentItemUnits.trackingNumberId` column. The bridge record/fields
69
+ (319 / 2183 / 2184) come from the Core migration and must exist before these files run.
70
+ - `TableViews.sortPrimaryTableViewFieldId` is a FK to `TableViewFields`; set it NULL before deleting
71
+ the old fields, then re-point via a multi-table UPDATE (not a self-subquery) to avoid MySQL 1093.
40
72
  - `TableViewFields` must be deleted before `TableViewJoins` (`tableViewJoinId` FK).
73
+ - With null `joinOnTableViewJoinId`, the engine resolves a join's parent table by the `recordId` of
74
+ `parentRecordFieldId` — this only works because each record appears once in the graph. Reusing a
75
+ record twice in one view would require an explicit `joinOnTableViewJoinId`.
41
76
 
42
77
  ## Client variations
43
- This is Compass-only. The underlying bridge model is shared (see the _underscore feature doc).
78
+ Compass-only. The underlying bridge model is shared (see the _underscore feature doc).
79
+
80
+ ## Change history
81
+ - 2026-06-11 — Re-rooted `item-fulfillments-for-sales-orders` (id 12) from Units to ItemFulfillmentItems with OUTER unit/tracking chain; fixes 0-records on orders lacking unit breakdown (e.g. SA132740). (jcardinal)
82
+ - 2026-06-10 — Re-rooted `item-fulfillments-for-sales-order-items` (id 13) and moved tracking to the bridge join. (jcardinal)
44
83
 
45
84
  ## Related docs
46
85
  - 2.0 _underscore: Tracking-Number Bridge Migration.
@@ -0,0 +1,79 @@
1
+ ---
2
+ title: Compass MITS PO → SO Item Linking
3
+ framework: "2.0"
4
+ repo: _underscore
5
+ project: _Underscore
6
+ client: compass-usa
7
+ type: client-feature
8
+ status: active
9
+ updated: 2026-06-11
10
+ owners: ["jcardinal"]
11
+ files:
12
+ - _underscore/Model/Compass/PurchaseOrder.php
13
+ related:
14
+ - asn-to-item-fulfillment.md
15
+ ---
16
+
17
+ ## Summary
18
+ MITS sends Compass inbound Purchase Orders (`POST /v2/purchase-orders`) against a Sales Order
19
+ (`mitsSalesOrder`). `_Model_Compass_PurchaseOrder` links each `PurchaseOrderItem` to the
20
+ `SalesOrderItem` it fulfills via the `SalesOrderItems_PurchaseOrderItems` bridge. There are
21
+ **two distinct linking paths** depending on order type, and conflating them caused a
22
+ production data-integrity bug.
23
+
24
+ ## Key files / entry points
25
+ - `_underscore/Model/Compass/PurchaseOrder.php` — `prePost` (SA path + MR via `handleMrOrder`)
26
+ and `postPost` (link creation).
27
+ - USA/Canada subclasses (`Model/Compass/Usa|Canada/PurchaseOrder.php`) are empty and inherit
28
+ this behavior — edit the parent.
29
+
30
+ ## How it works
31
+ - **SA orders (normal):** each inbound PO item carries `createdFromSalesOrderItem.lineNumber`
32
+ (the MITS line, which includes configuration-line offsets). `prePost` remaps it to the real
33
+ SO `lineNumber` via `$mapIncomingLineNumbersToOriginalLineNumbers` and builds
34
+ `salesOrderItemPurchaseOrderItems` on the payload, so the **correct** bridge rows are created
35
+ by the normal nested API write. This is the authoritative SA linkage.
36
+ - **MR orders (`mitsSalesOrder` starts with `MR`):** `prePost` calls `handleMrOrder` and
37
+ returns early. `handleMrOrder` creates/appends the SO from the PO items, **strips**
38
+ `createdFromSalesOrderItem`, and deliberately **aligns** SO and PO `lineNumber`s. It does
39
+ NOT build the item bridge — so the `postPost` lineNumber-match pass is the **only** (and
40
+ correct) MR linking mechanism.
41
+
42
+ ## Data model
43
+ - `SalesOrderItems_PurchaseOrderItems` (`Client_Compass`): `uuid`, `salesOrderItemId`,
44
+ `purchaseOrderItemId`. One row per (SO item, PO item) the PO fulfills.
45
+ - A PO item's `lineNumber` is **PO-local (1..N per PO)** — NOT the SO line number.
46
+
47
+ ## Client variations
48
+ USA and Canada share the parent handler unchanged.
49
+
50
+ ## Gotchas / known issues
51
+ - **Spurious cross-part links from the `postPost` lineNumber join (fixed 2026-06-11).** The
52
+ `postPost` link pass matched `SalesOrderItems.lineNumber = PurchaseOrderItems.lineNumber`
53
+ for *all* orders. For SA orders that is wrong: PO line numbers are PO-local, so whenever an
54
+ SO is split across multiple POs, or carries non-PO lines (freight/tax/warranty) that shift
55
+ the SO line numbers, the join created extra links pointing PO items at the **wrong** SO line
56
+ (different part). The correct SA links already existed from `prePost`; the `postPost` pass
57
+ only added bogus duplicates. Detection: ~40% of recent SA orders had ≥1 link where the PO
58
+ item's part ≠ the SO item's part. **Fix:** guard the `postPost` link block with
59
+ `if (static::isMrOrder($api->httpPayload))` so it runs for MR only. A link whose PO-item
60
+ part ≠ SO-item part is always invalid (a PO line can only fulfill the same part) — that is
61
+ the safe cleanup predicate for remediating historical rows.
62
+ - **Downstream tracking-number misattribution (NOT yet fixed as of 2026-06-11).** Because
63
+ tracking propagation followed the (scrambled) SO↔PO linkage, tracking numbers landed on the
64
+ wrong IF granularity for affected SA orders. Tracking for Compass lives at
65
+ `ItemFulfillmentItemUnits_TrackingNumbers` and `ItemFulfillments_TrackingNumbers` (header),
66
+ NOT `ItemFulfillmentItems_TrackingNumbers`. Source of truth for "which tracking shipped which
67
+ part" is the ASN side: `AdvanceShippingNoticeItemUnits_TrackingNumbers` →
68
+ `AdvanceShippingNoticeItems.purchaseOrderItemId` → PO item → part. A correct remediation
69
+ re-derives every tracking→IF-unit attachment from that ASN truth rather than doing per-line
70
+ swaps (the scramble spans multiple lines, so a single swap just moves a different wrong
71
+ number onto the line). Example seen on SA132739: UPS `1Z8696XA0193326215` actually shipped
72
+ `C40QYUC-1` (SO line 4) but was attached to SO line 1 (`1000555`).
73
+
74
+ ## Change history
75
+ - 2026-06-11 — Guarded `postPost` SO↔PO item linking to MR orders only; SA links come solely
76
+ from `prePost`'s `createdFromSalesOrderItem` remap. Fixes spurious cross-part links. (jcardinal)
77
+
78
+ ## Related docs
79
+ - [Compass ASN → ItemFulfillment Auto-Creation](asn-to-item-fulfillment.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.55",
3
+ "version": "1.0.57",
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",