toga-ai 1.0.335 → 1.0.337
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.
- package/knowledge/2.0/apps/toga2-supply/INDEX.md +1 -1
- package/knowledge/2.0/apps/toga2-supply/features/fulfill-and-ship.md +110 -1
- package/knowledge/clients/compass-usa/INDEX.md +1 -1
- package/knowledge/clients/compass-usa/features/mits-po-transmission-to-vendors.md +37 -2
- package/package.json +1 -1
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
| Doc | Summary | Files |
|
|
4
4
|
|-----|---------|-------|
|
|
5
5
|
| [TOGa Supply (toga2-supply) Architecture](architecture.md) | `toga2-supply` is the **React + Vite frontend** for TOGa Supply — warehouse fulfillment tooling (shipment selection, fulfill & ship against carrier APIs, NetSui | toga2-supply/src/api/toga.ts, toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx |
|
|
6
|
-
| [Fulfill & Ship](features/fulfill-and-ship.md) | Fulfill & Ship lets a warehouse user select sales-order line items, enter serials, pick a carrier/method, and in one action: create the Item Fulfillment records | toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/view/components/forms/EditShipmentForm.tsx, toga2-supply/src/pages/EditShipment/view/components/SelectedShipmentItemsTable.tsx, toga2-supply/src/pages/EditShipment/view/modals/ReturnShippingModal.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/EditShipment/types.ts, toga2-supply/src/pages/Shipments/view/ShipmentsPage.tsx, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx, toga2-supply/src/pages/Shipments/api/ShipmentsApi.ts, toga2-supply/src/pages/Shipments/types.ts, toga2-supply/src/pages/FulfilledShipments/view/FulfilledShipmentsPage.tsx, toga2-supply/src/components/ui/CardTable/CardTable.tsx, toga2-supply/src/components/ui/CardTable/types.ts, toga2-supply/src/assets/pen-line.svg, _underscore/Model/Client/ItemFulfillment.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Component/Library/Carriers/Ups/Ups.php |
|
|
6
|
+
| [Fulfill & Ship](features/fulfill-and-ship.md) | Fulfill & Ship lets a warehouse user select sales-order line items, enter serials, pick a carrier/method, and in one action: create the Item Fulfillment records | toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/view/components/forms/EditShipmentForm.tsx, toga2-supply/src/pages/EditShipment/view/components/SelectedShipmentItemsTable.tsx, toga2-supply/src/pages/EditShipment/view/helpers/ShipmentDetailsForm/renderEditShipmentFormInput.tsx, toga2-supply/src/pages/EditShipment/viewModel/FIELDS/DUMMYUPDATESHIPMENTFIELDS.json, toga2-supply/src/pages/EditShipment/view/modals/ReturnShippingModal.tsx, toga2-supply/src/components/ui/BaseInput/BaseInput.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/EditShipment/types.ts, toga2-supply/src/pages/Shipments/view/ShipmentsPage.tsx, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx, toga2-supply/src/pages/Shipments/api/ShipmentsApi.ts, toga2-supply/src/pages/Shipments/types.ts, toga2-supply/src/pages/FulfilledShipments/view/FulfilledShipmentsPage.tsx, toga2-supply/src/components/ui/CardTable/CardTable.tsx, toga2-supply/src/components/ui/CardTable/types.ts, toga2-supply/src/assets/pen-line.svg, _underscore/Model/Client/ItemFulfillment.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Component/Library/Carriers/Ups/Ups.php |
|
|
7
7
|
| [AWS Amplify Build & Deploy (non-prod environments)](workflows/amplify-build-and-deploy.md) | How `toga2-supply` (React + Vite) builds and deploys on **AWS Amplify**. | toga2-supply/amplify.yml, toga2-supply/.gitattributes, toga2-supply/.github/workflows/sync-stage-environments.yml, toga2-supply/.env.qc-security |
|
|
@@ -13,7 +13,10 @@ files:
|
|
|
13
13
|
- toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx
|
|
14
14
|
- toga2-supply/src/pages/EditShipment/view/components/forms/EditShipmentForm.tsx
|
|
15
15
|
- toga2-supply/src/pages/EditShipment/view/components/SelectedShipmentItemsTable.tsx
|
|
16
|
+
- toga2-supply/src/pages/EditShipment/view/helpers/ShipmentDetailsForm/renderEditShipmentFormInput.tsx
|
|
17
|
+
- toga2-supply/src/pages/EditShipment/viewModel/FIELDS/DUMMYUPDATESHIPMENTFIELDS.json
|
|
16
18
|
- toga2-supply/src/pages/EditShipment/view/modals/ReturnShippingModal.tsx
|
|
19
|
+
- toga2-supply/src/components/ui/BaseInput/BaseInput.tsx
|
|
17
20
|
- toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts
|
|
18
21
|
- toga2-supply/src/pages/EditShipment/types.ts
|
|
19
22
|
- toga2-supply/src/pages/Shipments/view/ShipmentsPage.tsx
|
|
@@ -87,6 +90,75 @@ from the saved fulfillment; **Save UPDATES the existing records** instead of POS
|
|
|
87
90
|
- `CardTable` was made reusable for this: optional `editIcon` + `isEditButtonDisabled` props
|
|
88
91
|
(defaults preserve prior behavior; the shipments card is the only consumer today).
|
|
89
92
|
|
|
93
|
+
## Update Info / Edit Shipment form (config-driven; Figma-alignment pass 2026-07)
|
|
94
|
+
|
|
95
|
+
The New Shipment / Edit Shipment form is **config-driven**: fields come from
|
|
96
|
+
`viewModel/FIELDS/DUMMYUPDATESHIPMENTFIELDS.json`, are rendered by
|
|
97
|
+
`view/helpers/ShipmentDetailsForm/renderEditShipmentFormInput.tsx` through the shared
|
|
98
|
+
`EditShipmentForm.tsx`, and the individual inputs are `components/ui/BaseInput/BaseInput.tsx`
|
|
99
|
+
(text/currency) plus react-select (State/Country). To change field layout, labels,
|
|
100
|
+
required-ness, or ordering, edit the **config JSON**, not the component.
|
|
101
|
+
|
|
102
|
+
- **Create vs Edit are distinct entry points (decision — kept, not merged).** Select Items →
|
|
103
|
+
Next = create a **New Shipment**; the pending-shipments pencil = **edit** an existing draft.
|
|
104
|
+
They are deliberately NOT merged and there is no auto-load from Select Items, because a Sales
|
|
105
|
+
Order can have **multiple** shipments (partial fulfillment — Select Items shows
|
|
106
|
+
Ordered/Fulfilled/Committed per line), so "the saved shipment" is not singular and auto-loading
|
|
107
|
+
would be ambiguous. Page title now signals the mode: create = **"New Shipment"**, edit =
|
|
108
|
+
**"Edit Shipment"** (create previously mis-titled "Update Info").
|
|
109
|
+
- **Fulfillment Location is READ-ONLY (decision — Eric, Exec Dir Services Ops, authoritative).**
|
|
110
|
+
Sourced from the Sales Order's location and shown display-only; the value must **not** change
|
|
111
|
+
in the tool — any change happens back at the SO. Implemented as `getAddress` fetching
|
|
112
|
+
`location.name`, `EditShipmentPage` adding `fulfillmentLocation` to the transformed address, and
|
|
113
|
+
`renderEditShipmentFormInput` rendering it via `BaseDisabledInput` on an `isReadOnly` flag. **Not
|
|
114
|
+
persisted to `IF.locationId`** for now — persisting would be a separate backend "set from SO"
|
|
115
|
+
change plus a NetSuite-mapping check.
|
|
116
|
+
- **Reference 1 / Reference 2 fields are placeholders (rendered, values NOT wired yet).**
|
|
117
|
+
Definitions are settled: **Reference 1 = NetSuite Sales Order #, Reference 2 = NetSuite Purchase
|
|
118
|
+
Order #** (Eric, authoritative — supersedes Skyler's earlier "Ref 1 = vendor account #, Ref 2 =
|
|
119
|
+
company name"). Value sourcing/persistence/carrier-wiring is intentionally deferred; when wiring,
|
|
120
|
+
verify: SO# = the document **ORDER #** (e.g. `281144`) vs the internal id (`7221433`, stored as
|
|
121
|
+
`c_netsuiteInternalSalesOrderId`); the PO# lives in NetSuite and may not be in the 2.0 DB (the
|
|
122
|
+
SO's `customerPurchaseOrder` field — already reused as the carrier `referenceString` — vs a
|
|
123
|
+
separate linked NetSuite PO document).
|
|
124
|
+
- **Phone # is REQUIRED by design (verified, kept per Eric):** config `isRequired:true` +
|
|
125
|
+
`showRequiredIndicator`, enforced by `validateFormOnSubmit`.
|
|
126
|
+
- **Address block layout (Figma):** inline **left** labels (Addressee / Attention / Address 1 /
|
|
127
|
+
Address 2 / City / State / ZIP / Country) — previously `sr-only`. Residential checkbox moved
|
|
128
|
+
**below** Country with the checkbox to the **right** of the label.
|
|
129
|
+
- **Carrier section = two vertical stacks (Figma, was 3 horizontal columns):** col6 = Carrier /
|
|
130
|
+
Shipment Method / Carrier Account # / Declared Cost; col7 = Reference 1 / Reference 2 / Phone # /
|
|
131
|
+
Fulfillment Location. Row container is `justify-between` so the columns fill to the right edge.
|
|
132
|
+
- **Verbiage (David):** "This shipment contains a battery" → "Contains a battery"; "This shipment
|
|
133
|
+
needs a return label" → "Needs a return label".
|
|
134
|
+
- **Return-label affordance:** the "Edit" link is inline to the right of the "Needs a return label"
|
|
135
|
+
label, and the return-location text ("TOGA Technology") below it is also clickable — both open the
|
|
136
|
+
Edit Return Label modal.
|
|
137
|
+
- **Input UX helpers (`BaseInput`):** per-field clear "X" on address text inputs (opt-in
|
|
138
|
+
`hasClearButton` flag, via `useFormContext` `setValue`/`watch`; State/Country already have
|
|
139
|
+
react-select's clear); a **"Clear All"** link in the address header (`ClearAllAddressButton`
|
|
140
|
+
resets every address field via `useFormContext`); Declared Cost formats to 2 decimals on blur
|
|
141
|
+
(`onBlur` when `field.isCurrency`). Return modal (`ReturnShippingModal.tsx`): compact selects
|
|
142
|
+
vertically centered; Carrier Account # widened to `w-[172px]` to match Carrier.
|
|
143
|
+
|
|
144
|
+
## Planned direction — "Fulfill & Ship" from an existing Item Fulfillment (future, Eric)
|
|
145
|
+
|
|
146
|
+
A **third entry mode** is planned (distinct from Select-Items-create and the pencil-edit): a
|
|
147
|
+
"Fulfill & Ship" button on an **existing NetSuite Item Fulfillment** punches out to the tool,
|
|
148
|
+
sources item/serial info from that existing fulfillment, uses the tool for the **shipping-label
|
|
149
|
+
portion only**, then pushes label/tracking data back into the Item Fulfillment. Most plumbing
|
|
150
|
+
already exists from TRUE-79191: `getShipmentForEdit`/rehydrate + read-only items (source from the
|
|
151
|
+
existing IF), `fulfillShipment` + `generateReturnLabel` (label), `saveShipmentToNetsuite`
|
|
152
|
+
(push-back). New pieces needed: the punch-out entry carrying an IF id, and a **label-only mode**
|
|
153
|
+
(skip the create step). This is a separate feature/ticket — recorded as planned direction, not done.
|
|
154
|
+
|
|
155
|
+
## Sources — meeting notes / decision origins
|
|
156
|
+
|
|
157
|
+
Fulfill & Ship meeting transcripts and notes live in the **Internal Knowledgebase MCP connector**
|
|
158
|
+
(AWS Bedrock KBs, slug `development-team`, client `general`/`toga-technology`), searchable via
|
|
159
|
+
`kb_search` — e.g. "2026-05-20 - Fulfill and Ship Dev Sync", "2026-02-27 - Fulfill & Ship Process
|
|
160
|
+
Review". Use it when a decision's origin needs tracing.
|
|
161
|
+
|
|
90
162
|
## Reprint (backend-combined, 2026-07)
|
|
91
163
|
|
|
92
164
|
Fulfilled-shipments view (`FulfilledShipmentsPage` → `ShipmentsCardTableForm` with
|
|
@@ -180,6 +252,19 @@ the call 403s and returns no label.
|
|
|
180
252
|
everywhere (and `overflow-y-auto` on the `max-h-[530px]` card list in `ShipmentsCardTableForm`),
|
|
181
253
|
and the fulfilled-page outer → `h-full overflow-auto`.
|
|
182
254
|
|
|
255
|
+
- **"Attention" wrote to the wrong field (fixed 2026-07).** The Attention input was bound to
|
|
256
|
+
`valueKey "addressee"` — the same key as the Address name — so both wrote to `addressee` and the
|
|
257
|
+
form showed the same value twice (e.g. "Eric" in both). Rebound Attention to `"attention"`. When a
|
|
258
|
+
config-driven field mirrors another field's value, suspect a duplicated `valueKey`.
|
|
259
|
+
- **The `/shipments` list is PER-SALES-ORDER (open product decision, Eric to decide).**
|
|
260
|
+
`getShipments` filters by `SalesOrders.c_netsuiteInternalSalesOrderId = <internalId>`, so
|
|
261
|
+
`/shipments` with no `internalId` shows the empty state — the tool is a per-SO **punch-out**
|
|
262
|
+
(entered from a NetSuite SO). The hamburger "Shipments" nav link (no SO context) is therefore
|
|
263
|
+
misleading. Options pending Eric's model decision (nothing changed yet): (A) keep per-SO and
|
|
264
|
+
remove/relabel the nav link; (B) add a global "All Pending Shipments" view — drop the SO filter
|
|
265
|
+
(client scoping is automatic from the JWT), but each row must then carry its own SO `internalId`
|
|
266
|
+
for the edit/fulfill links.
|
|
267
|
+
|
|
183
268
|
## Remaining work
|
|
184
269
|
|
|
185
270
|
- ~~Reprint rewire~~ — done (backend `reprintLabelsApi` combine; see Reprint section).
|
|
@@ -194,7 +279,19 @@ the call 403s and returns no label.
|
|
|
194
279
|
unit add/remove diffing against the API (the edit route already carries the fulfillment uuid);
|
|
195
280
|
(b) the return modal's weight/dims/carrier fields are an **edit-trap** — see the gotcha below.
|
|
196
281
|
- UPS 35-char hardening, location-scoped inventory lookup, carrier/method on the NS IF,
|
|
197
|
-
|
|
282
|
+
FedEx + UPS end-to-end verification before prod.
|
|
283
|
+
- **Responsiveness (phase 2/3 — explicitly NOT in original scope per the 2026-02-27 Process Review
|
|
284
|
+
and 2026-05-20 Dev Sync).** David Mancol's Figma annotation **is** the spec: reduce the in-box
|
|
285
|
+
column count by 1 on narrower screens; flexible gaps that scale with screen size (min 2px, max
|
|
286
|
+
50px); may explore stacking. Owners: David Mancol (design) + Alexandra Peterson (phase 2/3). Not
|
|
287
|
+
yet implemented.
|
|
288
|
+
- **Reference 1/2 value wiring** — fields render but values aren't sourced/persisted; see the form
|
|
289
|
+
section (SO# vs internal id, PO# in NetSuite) before wiring.
|
|
290
|
+
- **Global-vs-per-SO Shipments list** — pending Eric's model decision; see the gotcha above.
|
|
291
|
+
- **"Fulfill & Ship from an existing Item Fulfillment"** third entry mode — see Planned direction.
|
|
292
|
+
|
|
293
|
+
This is the **first testable iteration** of the Figma-aligned form; a change-request list is
|
|
294
|
+
expected once QA/users start.
|
|
198
295
|
|
|
199
296
|
## Deploy / provisioning requirements (per environment)
|
|
200
297
|
|
|
@@ -228,6 +325,18 @@ not the base `_Model_Client_ItemFulfillment`. Tested with GroWrk; UPS support wa
|
|
|
228
325
|
for Compass and is not yet in prod.
|
|
229
326
|
|
|
230
327
|
## Change history
|
|
328
|
+
- 2026-07-14 — TRUE-79191 (Figma-alignment pass on the config-driven New/Edit Shipment form):
|
|
329
|
+
fixed the **Attention** field writing to `addressee` (rebound to `attention`); Figma layout
|
|
330
|
+
(inline left address labels, residential checkbox below Country, carrier section as two vertical
|
|
331
|
+
stacks with `justify-between`, David's verbiage trims); create-vs-edit titles clarified
|
|
332
|
+
("New Shipment" vs "Edit Shipment"); added **Fulfillment Location** (read-only, sourced from the
|
|
333
|
+
SO — Eric); added **Reference 1/2** placeholder inputs (Ref1 = NetSuite SO#, Ref2 = NetSuite PO#,
|
|
334
|
+
values not wired yet — Eric); `BaseInput` per-field clear + "Clear All", Declared Cost 2-decimal
|
|
335
|
+
blur formatting; return-label "Edit" link inline + return-location text clickable. Recorded
|
|
336
|
+
decisions: create/edit entry points kept distinct (SO can have multiple shipments), Phone #
|
|
337
|
+
required, the `/shipments` list is per-SO (nav-link/global-view open item — Eric), the planned
|
|
338
|
+
**third entry mode** (Fulfill & Ship from an existing IF, label-only), David's responsiveness spec
|
|
339
|
+
(phase 2/3), and where the meeting transcripts live (`kb_search`). (mhammontree)
|
|
231
340
|
- 2026-07-14 — TRUE-79191: added **edit-a-saved-pending-shipment-in-place** (pencil on `dtSubmitted==null` rows → `/edit-shipment`, `getShipmentForEdit`/`updateShipment` PUT existing records; item lines/serials read-only in v1; `CardTable` made reusable with `editIcon`/`isEditButtonDisabled`). Completed the Increment-3 **return-label** frontend (combined outbound+return PDF, return page captioned "Return Label" via a position-aligned `captions` CSV to `reprintLabelsApi`). Fixed the Declared Cost "$ -" column (field was never requested/mapped). Documented the return-modal edit-trap (only the return ADDRESS persists — weight/carrier/dims reuse outbound) and the per-env deploy/provisioning checklist + the "testing in prod = full prod release (real labels/NS IF)" decision. (mhammontree)
|
|
232
341
|
- 2026-07-02 — Reprint rewired to the backend: `ShipmentsApi.ts` now calls `GET /v2/tracking-numbers/reprint` (`reprintLabelsApi`) for a combined base64 PDF built from the stored PNGs; removed the stale client-side `pdf-lib` merge. Return-label backend generation landed (`generateReturnLabel`, `returnTrackingNumberId` on the bridge). Ship-to address source resolved to `COALESCE(IF, SO)`. (mhammontree)
|
|
233
342
|
- 2026-06-18 — PNG label-storage rework reflected on the frontend: labels now store as PNG and the PDF is built on the backend (`LabelPdf`), so the client-side `pdf-lib` reprint is stale and must be rewired to a backend generate endpoint. Fixed the Fulfilled Shipments responsiveness/clip bug (Reprint button unreachable at 100% zoom) — `overflow-scroll` → `overflow-auto` and gave `FulfilledShipmentsPage`'s outer its own scroll; documented the `/shipments` vs `/fulfilled-shipments` two-component trap and the `AuthLayout overflow-hidden` clip. (mhammontree)
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| [Cost Centers — Unit Locations, numeric-only policy](features/cost-centers.md) | 2.0 | A Compass "cost center" — the value a user picks in commerce and that lands on an order — is **not** a `CostCenters` row. | toga2-commerce/src/pages/Cart/api/CartApi.ts, worker1.5/crons/toga2/compass/import_locations.php, _underscore/Model/Compass/SalesOrder.php, api2/Component/Api/V2/V2.php, dbchanges2/Client_Compass/2026-07-06 - RemoveNonNumericCostCenters.sql |
|
|
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
|
-
| [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 |
|
|
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, worker/crons/toga2/compasscanada/workflow/2_transmit_mits_purchase_orders_to_vendors.php, library/app/client/compass.php |
|
|
10
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 |
|
|
11
11
|
| [Compass USA](profile.md) | 2.0 | Compass USA is a TOGA client running a multi-tier supply-chain commerce operation. | |
|
|
12
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 |
|
|
@@ -5,10 +5,11 @@ project: _Underscore
|
|
|
5
5
|
client: compass-usa
|
|
6
6
|
type: client-feature
|
|
7
7
|
status: active
|
|
8
|
-
updated: 2026-
|
|
9
|
-
owners: ["rgirish"]
|
|
8
|
+
updated: 2026-07-14
|
|
9
|
+
owners: ["rgirish", "bala"]
|
|
10
10
|
files:
|
|
11
11
|
- worker/crons/toga2/compass/workflow/2_transmit_mits_purchase_orders_to_vendors.php
|
|
12
|
+
- worker/crons/toga2/compasscanada/workflow/2_transmit_mits_purchase_orders_to_vendors.php
|
|
12
13
|
- library/app/client/compass.php
|
|
13
14
|
related:
|
|
14
15
|
- mits-po-to-so-item-linking.md
|
|
@@ -47,6 +48,34 @@ Routing note: Office Depot (vendor 1) `defaultPoSubmissionIntegrationId = 2`, wh
|
|
|
47
48
|
cXML, unless a `VendorItem` overrides it. There is also a CXML integration (id 1,
|
|
48
49
|
"Office Depot / No") that is NOT the default.
|
|
49
50
|
|
|
51
|
+
**A single PO can split across channels.** Because grouping is per item
|
|
52
|
+
(`VendorItems.overridePoSubmissionIntegrationId`), the same PO can have some items on the
|
|
53
|
+
EMAIL integration (id 2) and others on the CXML integration (id 1). The emailed PDF therefore
|
|
54
|
+
contains only the **subset** of line items on the EMAIL integration — the CXML items go to
|
|
55
|
+
Office Depot separately with no PDF. Note the PDF's "Order Total" cell prints the whole-PO
|
|
56
|
+
`_total`, **not** a per-integration subtotal, so it can exceed the sum of the items shown.
|
|
57
|
+
|
|
58
|
+
## PDF rendering (EMAIL branch)
|
|
59
|
+
The EMAIL branch renders the PO with **ezpdf** (`Cezpdf`). The "MAIN ITEM LISTING" draws one
|
|
60
|
+
row per line item; the DESCRIPTION cell is 150pt wide and wraps to multiple lines for long
|
|
61
|
+
descriptions.
|
|
62
|
+
- **Row height must be measured, not assumed.** Each row's true height is taken from the
|
|
63
|
+
lowest y any cell reached (`ezText` returns the y it finished wrapping at). A row advances
|
|
64
|
+
by `max($spacingY, ($rowStartY - $rowLowestY) + ($spacingY - $pdf->getFontHeight(11)))` with
|
|
65
|
+
`$spacingY = 40`: single-line rows stay at 40pt (no regression), multi-line rows grow to fit,
|
|
66
|
+
and the `($spacingY - getFontHeight)` term gives every row the same trailing gap a
|
|
67
|
+
single-line row has so tall rows are not cramped.
|
|
68
|
+
- **Pagination is height-aware, not count-based.** Before drawing each row, its wrapped line
|
|
69
|
+
count is pre-measured and a new page is started before the row would spill past the item box
|
|
70
|
+
(first page ≈420pt, extra pages ≈625pt). Count-based chunking (8 then 10 per page) overflowed
|
|
71
|
+
once rows took their true taller height, which made ezpdf's internal `ezText` auto-page-break
|
|
72
|
+
fire per cell and scatter each cell of the overflowing item onto its own blank page.
|
|
73
|
+
- **Measuring wrapped height without drawing (ezpdf):** call
|
|
74
|
+
`$pdf->addTextWrap($x, $y, $columnWidth, $size, $text, 'left', 0, 1)` with the last arg
|
|
75
|
+
(`$test`) = `1`. In test mode `addTextWrap` does not draw (guarded by `if (!$test)`) but wraps
|
|
76
|
+
identically to `ezText` and returns the remainder, so looping it mirrors `ezText`'s own
|
|
77
|
+
wrapping exactly — the reliable way to pre-measure a row for pagination decisions.
|
|
78
|
+
|
|
50
79
|
## Data model
|
|
51
80
|
- `Client_Compass.PurchaseOrders.dtSubmitted` — set by step 4; the outer query's `IS NULL`
|
|
52
81
|
guard means a PO is only ever picked up once.
|
|
@@ -80,6 +109,12 @@ Compass Canada has a parallel `compasscanada/workflow/2_transmit_...` keyed on
|
|
|
80
109
|
`dtSubmitted` stamped without a log (separate, previously-observed failure mode).
|
|
81
110
|
|
|
82
111
|
## Change history
|
|
112
|
+
- 2026-07-14 — Fixed the emailed-PO PDF for both US Compass and Compass Canada: line-item
|
|
113
|
+
rows now advance by their measured wrapped height (long descriptions no longer overwritten),
|
|
114
|
+
and pagination is height-aware (a real 21-item PO went from a broken 17-page PDF to a clean
|
|
115
|
+
3-page one). Recorded the ezpdf `addTextWrap($test=1)` line-height measurement technique and
|
|
116
|
+
the single-PO EMAIL/CXML channel split (emailed PDF shows only the EMAIL-integration subset;
|
|
117
|
+
Order Total prints the whole-PO `_total`). (bala)
|
|
83
118
|
- 2026-06-22 — Documented the cron and the unconditional-`dtSubmitted` gotcha: item-less POs
|
|
84
119
|
get marked submitted without transmitting or logging; diagnosed via MR241298 inbound MITS
|
|
85
120
|
payload showing empty item arrays. No code change made (diagnosis only). (rgirish)
|
package/package.json
CHANGED