toga-ai 1.0.322 → 1.0.323
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.
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
| [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, dbchanges2/Client_Compass/2026-06-15a - FixItemFulfillmentTrackingNumberJoins.sql |
|
|
8
8
|
| [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, worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php |
|
|
9
9
|
| [Compass MITS PO Transmission to Vendors](features/mits-po-transmission-to-vendors.md) | 2.0 | The 1.0 worker cron `2_transmit_mits_purchase_orders_to_vendors.php` transmits Compass PurchaseOrders to their vendors (Office Depot, Strategic Systems, Compass | worker/crons/toga2/compass/workflow/2_transmit_mits_purchase_orders_to_vendors.php, library/app/client/compass.php |
|
|
10
|
+
| [Compass MR/MA Order Auto-Approval & Status Gate](features/mr-ma-order-approval-and-status.md) | 2.0 | Compass **MR** and **MA** sales orders are system-generated from the MITS / Office Depot EDI pipeline (they do not originate as user-entered SA orders) and must | _underscore/Model/Compass/SalesOrder.php, _underscore/Model/Compass/PurchaseOrder.php, worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php |
|
|
10
11
|
| [Compass USA](profile.md) | 2.0 | Compass USA is a TOGA client running a multi-tier supply-chain commerce operation. | |
|
|
11
12
|
| [Compass Cross-Kit Bundle Corruption — Detection & Repair](workflows/cross-kit-bundle-corruption.md) | 2.0 | A frontend regression in `toga2-commerce`'s edit-order bundle submission mis-attributed bundle (kit) line items and **fees/warranties** to the **wrong kit**, pe | src/api/syncSalesOrderItemsFromLocalStorageCartToApi.ts |
|
|
12
13
|
| [Compass ODP Order Pipeline to NetSuite (numbered worker crons)](workflows/odp-order-pipeline-to-netsuite.md) | 1.0 | The end-to-end **Compass Office Depot (ODP) order → NetSuite** pipeline as it actually runs through the 1.0 `worker` crons under `worker/crons/toga2/compass/`, | worker/crons/toga2/compass/workflow/1_transmit_compass_sales_orders_to_mits.php, worker/crons/toga2/compass/workflow/2_transmit_mits_purchase_orders_to_vendors.php, worker/crons/toga2/compass/edi/1_download_edi_s3_create_po_toga.php, worker/crons/toga2/compass/workflow/5_create_netsuite_sales_orders_from_office_depot_purchase_orders.php, library/app/client/compass.php |
|
|
@@ -6,8 +6,8 @@ project: _Underscore
|
|
|
6
6
|
client: compass-usa
|
|
7
7
|
type: client-feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: ["jcardinal"]
|
|
9
|
+
updated: 2026-07-13
|
|
10
|
+
owners: ["jcardinal", "rgirish"]
|
|
11
11
|
files:
|
|
12
12
|
- _underscore/Model/Compass/PurchaseOrder.php
|
|
13
13
|
- worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php
|
|
@@ -40,6 +40,15 @@ production data-integrity bug.
|
|
|
40
40
|
`createdFromSalesOrderItem`, and deliberately **aligns** SO and PO `lineNumber`s. It does
|
|
41
41
|
NOT build the item bridge — so the `postPost` lineNumber-match pass is the **only** (and
|
|
42
42
|
correct) MR linking mechanism.
|
|
43
|
+
- **MA orders — item population in the ODP PO import cron:** the 3a cron
|
|
44
|
+
(`worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php`) parses ODP
|
|
45
|
+
EDI 850 POs. Its "Non-SA order handling" block creates the Compass **MA** sales order. Line
|
|
46
|
+
items are attached to the Compass SO **only in the new-SO branch**, from `$purchaseOrder['items']`
|
|
47
|
+
(`partNumber` + `UUID_ITEM_CATALOG` Compass catalog + `qtyOrdered` + `unitPrice`), mirroring the
|
|
48
|
+
ODP-facing SO item payload built lower in the same cron. The item-linking block that maps ODP
|
|
49
|
+
items back to the Compass side runs only `if (… == 'SA' || … == 'MR')` — MA is excluded there
|
|
50
|
+
because SA/MR originate in Compass (their Compass SO+items pre-exist) whereas MA is
|
|
51
|
+
ODP-originated, so nothing else would populate it.
|
|
43
52
|
|
|
44
53
|
## Data model
|
|
45
54
|
- `SalesOrderItems_PurchaseOrderItems` (`Client_Compass`): `uuid`, `salesOrderItemId`,
|
|
@@ -115,7 +124,22 @@ USA and Canada share the parent handler unchanged.
|
|
|
115
124
|
off-by-one bridge fingerprint (a `SalesOrderItems_PurchaseOrderItems` PO item linked to two
|
|
116
125
|
adjacent SO items). Only SA132763 was remediated; a broader reviewed backfill is pending.
|
|
117
126
|
|
|
127
|
+
- **Empty MA orders (fixed 2026-07-13 — forward only).** The 3a cron's new-SO branch created MA
|
|
128
|
+
Compass sales orders with **no** `salesOrderItems`, because item population lived only on the
|
|
129
|
+
ODP-facing SO and the back-linking block excludes MA (`if (… == 'SA' || … == 'MR')`). Empty MA
|
|
130
|
+
(and MR) shells then stick at "Pending Initial Approval" because Compass `_status` gates on
|
|
131
|
+
approvals first — see
|
|
132
|
+
[MR/MA Order Auto-Approval & Status Gate](mr-ma-order-approval-and-status.md). **Fix:** build a
|
|
133
|
+
`salesOrderItems` array from `$purchaseOrder['items']` in the new-SO branch (partNumber +
|
|
134
|
+
`UUID_ITEM_CATALOG` + qtyOrdered + unitPrice), mirroring the ODP SO item payload. Only the
|
|
135
|
+
new-SO branch changed; the SO-already-exists branch was intentionally left alone. `php -l`
|
|
136
|
+
passes. This stops NEW empty MA orders; it does **not** repair the 192 historical empties (which
|
|
137
|
+
need item backfill from the sibling ODP SO first).
|
|
138
|
+
|
|
118
139
|
## Change history
|
|
140
|
+
- 2026-07-13 — Fixed empty MA orders: the 3a ODP-PO-import cron's new-SO branch now builds
|
|
141
|
+
`salesOrderItems` from the 850 PO items (the MA back-linking block excludes MA by design).
|
|
142
|
+
Forward-only; 192 historical empties still need item backfill. (rgirish)
|
|
119
143
|
- 2026-06-16 — Found and fixed a SECOND source of cross-part bridge links: the Office Depot
|
|
120
144
|
worker cron `3a_import_office_depot_purchase_orders.php` paired API-returned PO items to SO
|
|
121
145
|
items by array index; now pairs by lineNumber. Remediated SA132763's spurious bridge +
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Compass MR/MA Order Auto-Approval & Status Gate
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: _underscore
|
|
5
|
+
project: _Underscore
|
|
6
|
+
client: compass-usa
|
|
7
|
+
type: client-feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-07-13
|
|
10
|
+
owners: ["rgirish"]
|
|
11
|
+
files:
|
|
12
|
+
- _underscore/Model/Compass/SalesOrder.php
|
|
13
|
+
- _underscore/Model/Compass/PurchaseOrder.php
|
|
14
|
+
- worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php
|
|
15
|
+
related:
|
|
16
|
+
- mits-po-to-so-item-linking.md
|
|
17
|
+
- ../workflows/odp-order-pipeline-to-netsuite.md
|
|
18
|
+
- ../workflows/order-lifecycle-and-data-integrity.md
|
|
19
|
+
- ../../../2.0/apps/_underscore/features/item-fulfillment-stage-lifecycle-and-order-status.md
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Summary
|
|
23
|
+
Compass **MR** and **MA** sales orders are system-generated from the MITS / Office Depot EDI
|
|
24
|
+
pipeline (they do not originate as user-entered SA orders) and must **skip human approval
|
|
25
|
+
entirely**. Compass's `_status` calculated field gates on **approvals FIRST**: if any stage of
|
|
26
|
+
the active `ApprovalTemplate` has no `ApprovalDecision`, `_status` returns the pending-stage slug
|
|
27
|
+
(`pendingInitialApproval`) *before* it ever evaluates fulfillment. So an MR/MA order that has an
|
|
28
|
+
`Approval` row but no decisions is stuck at "Pending Initial Approval" regardless of shipment.
|
|
29
|
+
|
|
30
|
+
Two independent root causes produced the stuck-order population, and both are addressed at the
|
|
31
|
+
source (auto-approval + item population), **not** in the status SQL.
|
|
32
|
+
|
|
33
|
+
## Key files / entry points
|
|
34
|
+
- **`_underscore/Model/Compass/SalesOrder.php`**
|
|
35
|
+
- `_status` calculated field — approval gate runs before the shipped-only fulfillment machine
|
|
36
|
+
(see [IF stage lifecycle & order status](../../../2.0/apps/_underscore/features/item-fulfillment-stage-lifecycle-and-order-status.md)
|
|
37
|
+
for the fulfillment half).
|
|
38
|
+
- `postPost` — the `if ($isMrOrder)` block loops `foreach ([1,2] as $step)` and issues two
|
|
39
|
+
`internalApiRequest('POST', '/approval-decisions', …)` with `isApproved=true`,
|
|
40
|
+
note `'Auto-approved: MR order'`. **Went live 2026-06-03.**
|
|
41
|
+
- **`_underscore/Model/Compass/PurchaseOrder.php`** — MR handling (`handleMrOrder`); MR/MA order
|
|
42
|
+
detection.
|
|
43
|
+
- **`worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php`** — the
|
|
44
|
+
hourly ODP 850 import that creates MA orders (see the item-population fix in
|
|
45
|
+
[MITS PO → SO Item Linking](mits-po-to-so-item-linking.md)).
|
|
46
|
+
|
|
47
|
+
## How it works
|
|
48
|
+
### The approval gate (why empty + un-decided orders stick)
|
|
49
|
+
Prod `Client_Compass` has one active `ApprovalTemplate` (id 1, `salesOrders`) with two stages —
|
|
50
|
+
stage 1 = `step1` = `pendingInitialApproval`, stage 2 = `step2` = `pendingApproval`;
|
|
51
|
+
`APPROVAL_DECISION_TYPE = 1`. The base `_Model_Client_SalesOrder::postPost` creates an `Approval`
|
|
52
|
+
row on **any** order whenever an active template exists. Compass `_status` then requires an
|
|
53
|
+
`ApprovalDecision` for every active-template stage before it will look at fulfillment. No
|
|
54
|
+
decision on a stage ⇒ `_status` short-circuits to that stage's slug.
|
|
55
|
+
|
|
56
|
+
### Auto-approval (the intended MR path)
|
|
57
|
+
`_Model_Compass_SalesOrder::postPost` auto-approves MR orders by POSTing an approval decision for
|
|
58
|
+
each of the two stages (`isApproved=true`). `_status` only checks `isApproved` on the decision —
|
|
59
|
+
never the `assignedToUserId` / `decidedByUserId` columns — so a system decision with NULL user
|
|
60
|
+
columns is fully valid.
|
|
61
|
+
|
|
62
|
+
## Client variations
|
|
63
|
+
- **MR** orders originate in Compass; their Compass SO + items pre-exist. Auto-approval covers them
|
|
64
|
+
from 2026-06-03 onward.
|
|
65
|
+
- **MA** orders are **Office-Depot-originated** (created by the 3a cron) and were **never**
|
|
66
|
+
auto-approved — the `isMrOrder` check only matches numbers starting `MR`, so MA falls through
|
|
67
|
+
the gate. MA orders were additionally created as **empty shells** (see below).
|
|
68
|
+
|
|
69
|
+
## Gotchas / known issues
|
|
70
|
+
- **The stuck orders are EMPTY (zero `SalesOrderItems`).** All stuck MR+MA orders (and their linked
|
|
71
|
+
Compass PO) have no line items — the real line items live on a sibling **Office-Depot-facing SO**
|
|
72
|
+
(`customerId = OfficeDepot`) reachable via `SalesOrders_PurchaseOrders → PurchaseOrders_SalesOrders`.
|
|
73
|
+
A fulfilled-short-circuit in `_status` therefore does **nothing** for them (nothing to fulfill).
|
|
74
|
+
- **Do NOT "fix" this in `_status`.** A speculative fulfilled-short-circuit (plus an extracted
|
|
75
|
+
`_isFullyFulfilledSql` helper) was added and then **reverted** this session: because the stuck
|
|
76
|
+
orders are empty, the short-circuit never fires. The real fix is item population + approval
|
|
77
|
+
decisions at the source.
|
|
78
|
+
- **MA is still creating stuck orders until the item-population cron fix ships** — see
|
|
79
|
+
[MITS PO → SO Item Linking](mits-po-to-so-item-linking.md). Auto-approval for MA is not yet
|
|
80
|
+
implemented (the `isMrOrder` check does not match `MA`).
|
|
81
|
+
|
|
82
|
+
## Prod status buckets (2026-07-13)
|
|
83
|
+
| Type | NO_APPROVAL (correct — pre-template, gate falls through) | APPROVAL_NO_DECISION (STUCK) | FULLY_APPROVED |
|
|
84
|
+
|---|---|---|---|
|
|
85
|
+
| MR | 5922 (Sep 2025–Jan 2026) | 2927 | 583 |
|
|
86
|
+
| MA | 176 | 192 | 0 |
|
|
87
|
+
|
|
88
|
+
- The 5922 MR + 176 MA `NO_APPROVAL` orders pre-date the active template; they have **no**
|
|
89
|
+
`Approval` row, so `_status` skips the gate and reads correctly. They must **NOT** get an
|
|
90
|
+
`Approval` created.
|
|
91
|
+
- Total stuck: **3119** (2927 MR + 192 MA). A CSV of all 3119 (type, orderNumber, orderUuid,
|
|
92
|
+
dateCreated, compassPurchaseOrder, officeDepotSalesOrder_sourceOfItems) was handed to
|
|
93
|
+
ops/integration for remediation.
|
|
94
|
+
|
|
95
|
+
## Historical MR remediation (approval-decision backfill)
|
|
96
|
+
A one-off, idempotent, transaction-wrapped SQL backfill unsticks the 2927 historical MR orders by
|
|
97
|
+
inserting the two auto-approval `ApprovalDecisions` (one per stage, mirroring `postPost`'s
|
|
98
|
+
`foreach([1,2])`). Each row: `approvalTemplateStageId` 1/2, `approvalDecisionTypeId=1`,
|
|
99
|
+
`isApproved=1`, `assignedToUserId`/`decidedByUserId` NULL, note
|
|
100
|
+
`'Auto-approved: MR order (historical backfill)'`, `dtDecision NOW()`.
|
|
101
|
+
|
|
102
|
+
Safe scoping baked in — **decisions only, never Approvals**:
|
|
103
|
+
- **`INNER JOIN Approvals` (`recordId=14`)** so it can only add decisions to orders that *already*
|
|
104
|
+
have an `Approval`. Structurally it cannot touch the `NO_APPROVAL` orders (which are already
|
|
105
|
+
correct and must not get an Approval).
|
|
106
|
+
- **Per-stage `NOT EXISTS`** ⇒ idempotent / re-runnable.
|
|
107
|
+
- Includes a PREVIEW count query (prod: 2927 orders → 2927 step-1 + 2927 step-2 rows). Workflow:
|
|
108
|
+
run on beta, verify, COMMIT; then production.
|
|
109
|
+
- Does **not** create Approvals; does **not** handle MA (MA orders are empty and need item backfill
|
|
110
|
+
from the sibling ODP SO first).
|
|
111
|
+
|
|
112
|
+
## Change history
|
|
113
|
+
- 2026-07-13 — Diagnosed the MR/MA "Pending Initial Approval" stuck-order bug: `_status` gates on
|
|
114
|
+
approvals before fulfillment; MR orders created 2026-02-04..2026-06-02 got an Approval but no
|
|
115
|
+
decisions (auto-approval only live from 2026-06-03), and MA orders were never auto-approved and
|
|
116
|
+
are empty shells. Reverted a speculative `_status` fulfilled-short-circuit (stuck orders are
|
|
117
|
+
empty, so it never fires). Built an idempotent, decisions-only MR approval-decision backfill
|
|
118
|
+
(2927 orders) scoped by `INNER JOIN Approvals` so it can never create an Approval, and a CSV of
|
|
119
|
+
all 3119 stuck orders for ops. MA item population fixed separately at the 3a cron. (rgirish)
|
|
120
|
+
|
|
121
|
+
## Related docs
|
|
122
|
+
- [Compass MITS PO → SO Item Linking](mits-po-to-so-item-linking.md) — the 3a cron item-population fix that stops NEW empty MA orders.
|
|
123
|
+
- [Compass ODP Order Pipeline to NetSuite](../workflows/odp-order-pipeline-to-netsuite.md)
|
|
124
|
+
- [IF Stage Lifecycle & Order Status](../../../2.0/apps/_underscore/features/item-fulfillment-stage-lifecycle-and-order-status.md) — the shipped-only fulfillment half of Compass `_status`.
|
package/package.json
CHANGED