toga-ai 1.0.103 → 1.0.104

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.
@@ -6,4 +6,4 @@
6
6
  | [Carrier Shipping Labels (UPS/FedEx) & NetSuite Item Fulfillment](features/carrier-shipping-labels.md) | Backend mechanics behind TOGa Supply's Fulfill & Ship: buying a carrier label (UPS/FedEx), persisting it, and creating the NetSuite Item Fulfillment with tracki | _underscore/Model/Client/ItemFulfillment.php, _underscore/Component/Library/Carriers/Ups/Ups.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Trait/Netsuite/SalesOrder.php, _underscore/Component/Library/NetSuite/NetSuite.php, _underscore/Model/Client/TrackingNumber.php, _underscore/Model/Client/ShippingMethod.php, _underscore/Model.php, _underscore/Cloud.php |
7
7
  | [Client Email Template Sending](features/email-template-sending.md) | `_Model_Client_EmailTemplate` sends a stored, client-defined email template by UUID. | _underscore/Model/Client/EmailTemplate.php, _underscore/Model/Client/EmailTemplateOutgoingEmailAddress.php, _underscore/Email.php |
8
8
  | [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 |
9
- | [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 | _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 |
9
+ | [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 |
@@ -6,9 +6,10 @@ project: _Underscore
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-06-10
10
- owners: ["jcardinal"]
9
+ updated: 2026-06-16
10
+ owners: ["jcardinal", "mhammontree"]
11
11
  files:
12
+ - api2/Component/Api/V2/V2.php
12
13
  - _underscore/Model/Client/AdvanceShippingNoticeItemUnit.php
13
14
  - _underscore/Model/Client/AdvanceShippingNoticeItemUnits/TrackingNumber.php
14
15
  - _underscore/Model/Client/ItemFulfillmentItemUnits/TrackingNumber.php
@@ -116,8 +117,25 @@ returnTrackingNumber: {...} }]`, and an IFIU's as `itemFulfillmentItemUnitTracki
116
117
  - **Deploy coupling:** renames are NOT backward compatible — apply the DB migration and deploy
117
118
  `_underscore` + `api2` + `worker` + `library` together. Run the additions/migrations DB file first;
118
119
  run the companion `..._DROPS.sql` (and the Core deletes) only after the bridges + app are confirmed.
120
+ - **⚠ Bridge ACL is incomplete — non-Super-User reads get 403 (prod + every client).** The migration
121
+ registers `AclRecordPermissions` for the new bridge records 317–322 (Core §7 = Super User; Client §6b
122
+ = per-client copies of the parent record's perms) but **never creates the
123
+ `AclLogicGroups` → `AclLogicGroupExpressions` → `AclRecordExpressions` chain beneath them.** A 2.0
124
+ record read requires that full chain (`api2/Component/Api/V2/V2.php`, `!$aclLogicGroupsDefined`), so a
125
+ role hitting a bridge route (e.g. `item-fulfillment-tracking-numbers`) gets **403 EZ-1** with DEBUG
126
+ "No ACL Logic Groups defined for ACL Record Permissions". Confirmed in **prod and every client** —
127
+ working analogs (parent 28, ASN bridges 216/217/218) have 1 logic group + 1 expression each; the IF/IR
128
+ bridges 317–322 have **0**. Downstream symptom: nested bridge fields return `null` (TOGa Supply's
129
+ fulfilled-shipments lists shipments but `itemFulfillmentTrackingNumbers` is null → reprint has no
130
+ label). **Fix:** per bridge `AclRecordPermission`, add one `AclLogicGroup` + `AclLogicGroupExpression` +
131
+ `AclRecordExpression` (`slug='all'`, `sqlExpression='1'`) — mirroring how 28 / 216 work. Run in **both**
132
+ `Core` (Super User) **and** each `Client_*` (per-role; `Client_Growrk` fixed on beta this way).
133
+ **Client-DB caveat:** `Records` is a Core-only table, so the client-side `AclRecordExpressions` insert
134
+ must derive record ids from `AclRecordPermissions` (`SELECT DISTINCT recordId ... WHERE recordId IN (...)`),
135
+ **not** join `Records`. This gap belongs back in the migration (Core §7 + Client §6b + blank-client template).
119
136
 
120
137
  ## Change history
138
+ - 2026-06-16 — Found + documented the bridge ACL gap: the migration creates bridge `AclRecordPermissions` (317–322) but not their `AclLogicGroups`/`AclLogicGroupExpressions`/`AclRecordExpressions` chain → 403 "No ACL Logic Groups defined" for non-Super-User reads (confirmed prod + all clients). Recorded the `slug='all'`/`sqlExpression='1'` fix for Core + per-client, plus the Client-DB `Records`-table caveat. (mhammontree)
121
139
  - 2026-06-10 — Documented the tracking-number bridge migration: scalar FK columns → `*_TrackingNumbers` bridge tables across ASN/IF/IR, ASN unit table rename, packages-table consolidation. (jcardinal)
122
140
 
123
141
  ## Related docs
@@ -6,7 +6,7 @@ project: TOGa Supply
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-06-10
9
+ updated: 2026-06-16
10
10
  owners: [mhammontree]
11
11
  files:
12
12
  - toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx
@@ -40,7 +40,10 @@ GroWrk, June 2026); FedEx + UPS both need verification before prod.
40
40
  **This is the only place the SO syncs from NetSuite into Toga.**
41
41
  2. `/edit-shipment` submit (`onFormSubmit("fulfillAndShip")` in `EditShipmentForm.tsx`):
42
42
  - `saveShipment` → POST `/item-fulfillments`, `/tracking-numbers`,
43
- `/item-fulfillment-packages`.
43
+ `/item-fulfillment-tracking-numbers` (the bridge — payload key
44
+ `itemFulfillmentTrackingNumbers`, **not** the old `itemFulfillmentPackages`; see the
45
+ `_underscore` tracking-number-bridges doc). The frontend migration to the bridge is prod
46
+ commit `b5c16592d`.
44
47
  - `fulfillShipment` → GET `/item-fulfillments/upsShipmentApi` (or `fedexShipmentApi`)
45
48
  for the label, then `saveShipmentToNetsuite` →
46
49
  GET `/item-fulfillments/createNetsuiteItemFulfillment`.
@@ -91,6 +94,29 @@ likely moves to the backend.
91
94
  `hostname LIKE '%ups.com%'`, `responsePayload`).
92
95
  - React warning: `setState`-in-render in `ShipmentItemsTable.tsx` (~line 149,
93
96
  `clearErrors` inside a `setRowsClicked` updater) — move out of the updater.
97
+ - **Local frontend runs against the *deployed* beta backend.** The dev frontend
98
+ (`growrk.togasupply:5173`) calls `api.beta.togahub.com`, so **any `_underscore` change
99
+ only takes effect after a deploy to beta** — a fix you made locally looks "unfixed" until
100
+ deployed (and a local frontend ahead of the deployed backend produces skew errors, e.g.
101
+ `Unknown named parameter $labelFileInternalId` when the FE passes a param the deployed
102
+ method lacks). When chasing a beta error, confirm what commit is deployed before assuming
103
+ the local code is what ran.
104
+ - **Fulfilled vs pending is driven by `ItemFulfillments.dtSubmitted`** (`ShipmentsApi.ts`
105
+ `getShipments`: fulfilled = `dtSubmitted ne null`, pending = `eq null`). `dtSubmitted` is
106
+ set **only** by `createNetsuiteItemFulfillment` on a successful NetSuite IF creation
107
+ (`Trait/Netsuite/ItemFulfillment.php`). So if the NetSuite step fails, the shipment stays
108
+ on the **pending** page, never the fulfilled one — "no fulfilled shipments" usually means
109
+ the NS step didn't complete, not a UI bug.
110
+ - **`createNetsuiteItemFulfillment` line mapping is fragile on partial/already-fulfilled
111
+ orders.** It `get`s the NetSuite SO and sets the fulfillment `orderLine` = the SO's `line`.
112
+ If a line is already fulfilled (or NetSuite re-sequences the fulfillable sublist because a
113
+ line isn't committed), NetSuite returns **"Unable to find a matching line for sublist item
114
+ with key: [orderLine] and value: [N]"**. Test against an SO line that's genuinely open;
115
+ robust fix = NetSuite `initialize`/`transform` (only exposes fulfillable lines).
116
+ - **Bridge ACL blocks the tracking/label read (reprint).** Reading tracking via the
117
+ `item-fulfillment-tracking-numbers` bridge requires the bridge record's ACL logic-group
118
+ chain to exist for the user's role, or it 403s and `itemFulfillmentTrackingNumbers` returns
119
+ `null` (so reprint has no label). See the tracking-number-bridges doc's ACL gotcha + fix.
94
120
 
95
121
  ## Remaining work
96
122
 
@@ -112,4 +138,5 @@ not the base `_Model_Client_ItemFulfillment`. Tested with GroWrk; UPS support wa
112
138
  for Compass and is not yet in prod.
113
139
 
114
140
  ## Change history
141
+ - 2026-06-16 — Drove the full beta flow green for UPS/GroWrk. Updated the save step to the `/item-fulfillment-tracking-numbers` bridge (FE commit `b5c16592d`, key `itemFulfillmentTrackingNumbers`). Added gotchas: local-FE↔deployed-beta-BE skew, `dtSubmitted` fulfilled/pending gating, `createNetsuiteItemFulfillment` orderLine fragility on partial/already-fulfilled orders, and the bridge-ACL 403 that nulls tracking/labels (reprint). (mhammontree)
115
142
  - 2026-06-10 — Documented the Fulfill & Ship flow (SO sync, label purchase, NetSuite IF creation, success gating, reprint). Driven green on beta for UPS/GroWrk; FedEx + prod verification pending. (mhammontree)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.103",
3
+ "version": "1.0.104",
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",