toga-ai 1.0.942 → 1.0.944

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.
@@ -17,7 +17,7 @@
17
17
  | [Prudential: Send Shipments for the Day report (daily cron)](features/send-shipments-for-the-day.md) | Daily 9:00 PM Prudential/Dell cron emailing an Excel of every device shipped today (tracking, serial, XID, FedEx status, vendor); open for the ASN join chain an |
18
18
  | [Staples 856 ASN Outbound (NetSuite fulfillments → SFTP, tracked in StaplesAdvanceShipNotices)](features/staples-asn-856-outbound.md) | Hourly cron sending Staples 856 ASNs for shipped NetSuite item fulfillments, one row per fulfillment in `Common.StaplesAdvanceShipNotices`; open for the queue/r |
19
19
  | [Staples cXML Order Import (SFTP → NetSuite)](features/staples-cxml-order-import.md) | Hourly cron importing Staples cXML POs from SFTP into NetSuite Sales Orders (writes 855 ack back); open for the per-file flow, saved-search-8412 Location resolu |
20
- | [UMA Student Roster Sync (SFTP → TOGaDeskSupport customers) + Ivanti Ticket Sync](features/uma-student-sync.md) | Daily SFTP full-roster file loads UMA students into TOGaDeskSupport.customers (clientId 10); open for the file format, insert/deactivate rules, how the Ivanti t |
20
+ | [UMA Student Roster Sync (SFTP → TOGaDeskSupport customers) + Ivanti Ticket Sync](features/uma-student-sync.md) | Daily SFTP full-roster file loads UMA students into TOGaDeskSupport.customers (clientId 10); plus the once-a-day Ivanti ticket sync (escalations reach UMA only |
21
21
  | [Walmart Daily Sales Report (send_toga_walmart_report.php)](features/walmart-daily-sales-report.md) | The two Walmart sales workbooks (summary + details) built from `TOGA_Walmart` (in-store) and `TOGA_WalmartEComm` (.COM); open for the pseudo-store 1472 channel |
22
22
  | [Diagnosing frozen 1.0 worker cron check-ins (Sentry "missed" flood)](workflows/diagnosing-frozen-cron-checkins.md) | Ordered path to diagnose frozen 1.0 worker cron timestamps + a Sentry `worker1` "missed" flood; open when check-ins stall and you suspect a wedged lock. |
23
23
  | [isFulfillable Multi-Client Backfill (all togasupply clients)](workflows/isfulfillable-multi-client-backfill.md) | One-time backfill catching up `Items.isFulfillable` on existing items across all 17 togasupply clients; open when running/re-running it or deciding whether rema |
@@ -6,7 +6,7 @@ project: Worker
6
6
  client: uma
7
7
  type: client-feature
8
8
  status: active
9
- updated: 2026-09-28
9
+ updated: 2026-10-05
10
10
  owners: ["mhammontree"]
11
11
  files:
12
12
  - worker/crons/togadesk/sync_uma_customers.php
@@ -17,7 +17,7 @@ related:
17
17
  - 1.0/apps/worker/architecture.md
18
18
  ---
19
19
 
20
- Daily SFTP full-roster file loads UMA students into TOGaDeskSupport.customers (clientId 10); open for the file format, insert/deactivate rules, how the Ivanti ticket sync depends on it, health-check queries, and the PII/hardcoded-credential traps.
20
+ Daily SFTP full-roster file loads UMA students into TOGaDeskSupport.customers (clientId 10); plus the once-a-day Ivanti ticket sync (escalations reach UMA only when it runs); open for the file format, insert/deactivate rules, escalation timing, health-check queries, and the PII/hardcoded-credential traps.
21
21
 
22
22
  ## Summary
23
23
 
@@ -35,7 +35,15 @@ UMA students reach our system through a **daily SFTP file**, not an API. `togade
35
35
  - existing → **untouched** (name/email/phone are never updated);
36
36
  - existing but absent from the file → `isActive = 0`. The file is the **full roster**.
37
37
 
38
- **Ticket sync (`sync_uma_tickets.php`):** uses `App_Api_UMA` (`library/app/api/uma.php`, extends `App_Api_Ivanti`, endpoint `umaservicecenter.saasit.com`) to pull new student incidents and push TOGaDesk tickets. A ticket is created only when the incident email matches a student's `emailPersonal`/`emailWork`.
38
+ **Ticket sync (`sync_uma_tickets.php`):** uses `App_Api_UMA` (`library/app/api/uma.php`, extends `App_Api_Ivanti`, endpoint `umaservicecenter.saasit.com`). Each run, in order:
39
+ 1. Pull new Ivanti incidents → TOGaDesk tickets. Created only when the incident email matches a student's `emailPersonal`/`emailWork`.
40
+ 2. Close TOGaDesk tickets whose incident is resolved in Ivanti.
41
+ 3. **Escalate ("send new tickets back to uma"):** clientId 10 tickets with `referenceId IS NULL AND dtSynced IS NULL` → `App_Api_UMA::postNewIncident()`; Ivanti RecId stored in `tickets.referenceId`.
42
+ 4. Push Closed TOGaDesk tickets back to Ivanti as Resolved.
43
+
44
+ Nothing is sent at escalation time — an escalated ticket waits for the next run.
45
+
46
+ **Ticket sync schedule** (`schedules/cron.worker.togadesk.json`, server time = Central): **once per day** — Mon–Thu `0 15 * * 1-4`, Fri `30 11 * * 5`, Sat `0 17 * * 6`, Mon `0 1 * * 1`. No Sunday run (~32 h gap Sat 17:00 → Mon 01:00). Runs take ~2 min. Fix if asked: restore an hourly (or tighter) range.
39
47
 
40
48
  ## Health check (read-only prod, env `legacy`)
41
49
 
@@ -43,6 +51,7 @@ UMA students reach our system through a **daily SFTP file**, not an API. `togade
43
51
  - **Runs:** `Common.CronJobExecutions` (~120M rows, **no index** on `job`/`dtCheckIn`). Bound by id range (~750k rows/day, e.g. `id > MAX(id) - N`) and match `job = '/var/www/html/crons/togadesk/sync_uma_customers.php'`.
44
52
  - `dtCheckOut` set = finished cleanly; a thrown error leaves it NULL.
45
53
  - ~12-13 s = file processed; ~2 s = SFTP root was empty.
54
+ - **Ticket sync runs:** same table, `job = '/var/www/html/crons/togadesk/sync_uma_tickets.php'`. Escalation send time = run time; check Ivanti created timestamps, not `dtSynced`.
46
55
  - **Normal pattern:** one file/day. Occasional misses or a late file arriving with the next day's — harmless, since only the newest (full roster) is parsed.
47
56
 
48
57
  ## Gotchas
@@ -54,6 +63,9 @@ UMA students reach our system through a **daily SFTP file**, not an API. `togade
54
63
  - **PII.** Files hold DOB and SSN last 4. When investigating, pull only dates/file names from FileLog, never `fileData`.
55
64
  - **Hardcoded credentials — treat as leaked, rotate.** SFTP login is hardcoded in `sync_uma_customers.php`; the Ivanti API key is hardcoded in `library/app/api/uma.php`. Do not copy them anywhere.
56
65
  - Does not call `App_Database::closeConnections()`.
66
+ - **Escalations batch once a day.** Cron entry names still say windows like "9:00–21:00" — misleading; the cron expressions are single hours. Cause: `d53e1ab35` (TRUE-61196, 2025-03-10, UTC→CST) replaced hourly ranges (`0 3-15 * * 2-5`, `0 0-15 * * 6`, `0 0-17 * * 0`, `0 1-15 * * 1`) with single hours; later TZ shifts `9732b7b50` (TRUE-74692) and `9f16ad1de` (TRUE-77365) kept single hours.
67
+ - **`tickets.dtSynced` is not the send time.** On push the code sets it to the ticket's created timestamp; some rows show the run time instead.
57
68
 
58
69
  ## Change history
59
70
  - 2026-09-28 — Documented (TRUE-82352 investigation). Open incident: no UMA file since 2026-09-20; runs 9-21..9-27 clean with empty SFTP; togadesk worker instance changed that day but SFTP login still works from the new box — likely UMA stopped uploading, awaiting UMA confirmation. No wrong deactivations; new students and their tickets missing since 9-20. (mhammontree)
71
+ - 2026-10-05 — TRUE-82504 escalation-batch investigation: escalations reach UMA's Ivanti once a day (prod: tickets created 9/29 20:17 → 9/30 08:21 all sent 9/30 15:01–15:02 CT; repeated 10/1). Findings delivered, no fix requested. (mhammontree)
@@ -6,11 +6,12 @@ project: Worker
6
6
  client: shared
7
7
  type: feature
8
8
  status: active
9
- updated: 2026-10-01
9
+ updated: 2026-10-05
10
10
  owners: ["jcardinal", "mhammontree", "bala", "rgirish"]
11
11
  files:
12
12
  - worker2/Worker/Monitor/Compass.php
13
13
  - worker2/Worker/Client/Compass.php
14
+ - worker2/Worker/Client/CompassCanada.php
14
15
  - worker2/composer.json
15
16
  - _underscore/Cloud.php
16
17
  - worker2/Worker/Monitor/Operations.php
@@ -34,6 +35,7 @@ related:
34
35
  - ../../../clients/compass-usa/features/oneuptime-ma-refresh-order-monitor.md
35
36
  - ../../../clients/compass-usa/features/oneuptime-netsuite-duplicate-sales-orders-monitor.md
36
37
  - ../../../../clients/wje/features/oneuptime-monitors.md
38
+ - ../../../clients/compass-canada/features/oneuptime-po-transmissions-to-vendors-monitor.md
37
39
  ---
38
40
 
39
41
  OneUptime push-metric monitor pattern for worker2 (2.0): a self-contained cron action decides pass/fail and POSTs a string token to a OneUptime Incoming Request monitor; open when building/tuning a worker2 monitor, its thresholds, or the OneUptime import JSON.
@@ -44,7 +46,7 @@ A second, **OneUptime-reporting** monitoring pattern for the 2.0 worker2 tier, p
44
46
  `App_SystemMonitor_Compass` monitors. A worker2 cron action runs a self-contained check, decides
45
47
  pass/fail itself, and POSTs a JSON metric body to a OneUptime "Incoming Request" monitor — replacing
46
48
  the 1.0 tier's email alerts. The class is `abstract class _Worker_Monitor_Compass` and now carries a
47
- **suite of 12 monitors** covering the Compass USA / Office Depot integration (S3, DB, mailbox, and
49
+ **suite of 13 monitors** covering the Compass USA / Office Depot integration (plus one Compass Canada monitor) (S3, DB, mailbox, and
48
50
  NetSuite SuiteQL checks). Designed to be **client-agnostic** — a reusable template for future monitors and clients.
49
51
 
50
52
  Distinct from the DB-driven email-orchestrator [Monitoring Framework](./monitoring-framework.md)
@@ -72,9 +74,9 @@ disallows `const` at function scope), plus a `$push` closure using `_ApiRequest`
72
74
  method, so the class scales cleanly as monitors accumulate. The metric POST runs with **logging
73
75
  disabled** and **`throwExceptionsOnFailure` disabled**, so a failed ping never fails the worker job.
74
76
 
75
- ### The 12 monitors
77
+ ### The 13 monitors
76
78
 
77
- Each measures one Compass/Office Depot integration metric and pushes a decided alarm token.
79
+ Each measures one Compass/Office Depot (or Compass Canada) integration metric and pushes a decided alarm token.
78
80
 
79
81
  - **OfficeDepotEdiImportQueue** (S3) — counts files >10 min old in `s3://agilant-as2/OfficeDepot/`,
80
82
  excluding `OUTBOX/`, `SENT/` and directory placeholders.
@@ -134,6 +136,11 @@ Each measures one Compass/Office Depot integration metric and pushes a decided a
134
136
  NetSuite instead of a Toga DB** (via `_Component_Api_Netsuite::send()`, `QUERY_SUITEQL`), because the
135
137
  duplicates exist only in NetSuite. Details:
136
138
  [Compass: NetSuite duplicate SO monitor](../../../clients/compass-usa/features/oneuptime-netsuite-duplicate-sales-orders-monitor.md).
139
+ - **CompassCanadaPurchaseOrderTransmissionsToVendors** (DB, added 2026-10-05) — due, unsubmitted
140
+ `Client_CompassCanada` POs (customer 5) the 1.0 Canada transmit cron has not sent to Grand & Toy.
141
+ `Core.CronJobs` id 87, `*/5`. First monitor in this class on a **second client DB** (registers
142
+ `Client_CompassCanada` in-method). DEGRADED >10 waiting / >15 min oldest, HIGH >20 / >30 min. Details:
143
+ [Compass Canada: PO-to-vendor monitor](../../../clients/compass-canada/features/oneuptime-po-transmissions-to-vendors-monitor.md).
137
144
 
138
145
  ### Payload contract & OneUptime criteria (critical — OneUptime cannot compare numbers)
139
146
 
@@ -573,6 +580,7 @@ production deploy.**
573
580
  - [OneUptime 1.0 worker uptime monitoring](../../../1.0/apps/worker/features/oneuptime-worker-uptime-monitoring.md) — the 1.0 push-heartbeat predecessor
574
581
 
575
582
  ## Change history
583
+ - 2026-10-05 — Added `CompassCanadaPurchaseOrderTransmissionsToVendors` (cron 87), the first monitor reading `Client_CompassCanada`. (bala)
576
584
  - 2026-10-01 — Added the `resetQueryCache()` re-read trap to the in-run retry pattern; WJE link now points at the 3-monitor suite. (mhammontree)
577
585
  - 2026-10-01 — Clarified worker2 reads `TOGaDeskSupport` (`DB_TOGADESK1`) — only `Common` is unreachable; added `Monitor/Wje`. (mhammontree)
578
586
  - 2026-09-25 — Added `NetsuiteDuplicateSalesOrders`, the first monitor that queries NetSuite (SuiteQL) instead of a Toga DB. (rgirish)
@@ -20,7 +20,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
20
20
  ## 2.0 framework
21
21
 
22
22
  - **_underscore** (_Underscore) _(framework core)_ — 94 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
23
- - **worker2** (Worker) — 82 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
23
+ - **worker2** (Worker) — 83 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
24
24
  - **api2** (API) — 26 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
25
25
  - **dbchanges2** (Database Changes) _(framework core)_ — 22 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
26
26
  - **toga2-supply** (TOGa Supply) — 9 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
@@ -6,6 +6,7 @@
6
6
  | [French (fr-CA) Order Email Localization (Compass Canada)](features/french-order-email-localization.md) | 2.0 | How Compass Canada order emails render per-recipient EN/FR (item block, labels, denial-reason machine translation) under an iso-8859-1 send; open for any locali |
7
7
  | [Grand & Toy ASN Import (Compass Canada)](features/grand-and-toy-asn-import.md) | 2.0 | Imports Grand & Toy ASNs for Compass Canada (CSV cron + cXML gateway) and auto-builds the ItemFulfillment chain + bilingual in-transit email; open for G&T ASN f |
8
8
  | [Compass Canada — Item-Fulfillment TableViews (dead-Core-id 500, rebuilt onto the USA shape)](features/item-fulfillment-tableviews.md) | 2.0 | Why Compass Canada's item-fulfillment TableViews 500'd on dead Core ids and how they were rebuilt onto the USA shape; open when a Canada TableView 500s on /meta |
9
+ | [Compass Canada: PO-to-vendor transmission monitor (Monitor/Compass/CompassCanadaPurchaseOrderTransmissionsToVendors)](features/oneuptime-po-transmissions-to-vendors-monitor.md) | 2.0 | worker2 OneUptime push monitor for Compass Canada POs the 1.0 cron has not yet sent to the vendor (Grand & Toy), plus how the Canada PO transmit cron differs fr |
9
10
  | [Compass Canada — Fulfilled vs Partially Fulfilled (per-line, ASN bridge only)](features/order-fulfillment-status-per-line.md) | 2.0 | Compass Canada's pure per-line fulfilled/partiallyFulfilled rule (ASN bridge only) and why it diverges from USA; open before touching Canada `_fulfillmentStatus |
10
11
  | [Compass Canada](profile.md) | 2.0 | Compass Canada is the Canadian arm of the Compass account — a separate TOGA tenant, related to but distinct from Compass USA. |
11
12
  | [Copying a Compass USA user into the Canada tenant (cross-tenant hand-add)](workflows/copying-a-us-user-into-the-canada-tenant.md) | 2.0 | Giving a Compass **USA** person a login on the Canada TechHub portal: the guarded insert chain, the uuid role/persona mapping, and the worker2 guard that stops |
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: "Compass Canada: PO-to-vendor transmission monitor (Monitor/Compass/CompassCanadaPurchaseOrderTransmissionsToVendors)"
3
+ framework: "2.0"
4
+ repo: worker2
5
+ project: Worker
6
+ client: compass-canada
7
+ type: client-feature
8
+ status: active
9
+ updated: 2026-10-05
10
+ owners: ["bala"]
11
+ files:
12
+ - worker2/Worker/Monitor/Compass.php
13
+ - worker2/Worker/Client/CompassCanada.php
14
+ - worker/crons/toga2/compasscanada/workflow/2_transmit_mits_purchase_orders_to_vendors.php
15
+ - worker/schedules/cron.worker.sync.json
16
+ - library/app/client/compasscanada.php
17
+ related:
18
+ - ../../../2.0/apps/worker2/features/oneuptime-worker2-monitoring.md
19
+ - ../../compass-usa/features/mits-po-transmission-to-vendors.md
20
+ - ./grand-and-toy-asn-import.md
21
+ - ../profile.md
22
+ ---
23
+ worker2 OneUptime push monitor for Compass Canada POs the 1.0 cron has not yet sent to the vendor (Grand & Toy), plus how the Canada PO transmit cron differs from USA; open when Canada POs are not reaching G&T or when tuning this monitor.
24
+
25
+ ## Summary
26
+ `_Worker_Monitor_Compass::CompassCanadaPurchaseOrderTransmissionsToVendors()` counts due, unsubmitted Canada POs and how long the oldest has waited, and pushes an alarm token to OneUptime. Follows the shared [OneUptime push-metric pattern](../../../2.0/apps/worker2/features/oneuptime-worker2-monitoring.md) (payload contract, provisioning, criteria).
27
+
28
+ - Prod `Core.CronJobs` **id 87**, `*/5 * * * *`, action `Monitor/Compass/CompassCanadaPurchaseOrderTransmissionsToVendors`. Live 2026-10-05 (first runs: 0 waiting, alarm=OK, push ok).
29
+ - Push URL = in-method `$ONEUPTIME_URL` local (credential; never record the value). Import JSON is a local artifact, not in the repo.
30
+ - Canada had no PO-to-vendor monitor before this. The US sibling `CompassPurchaseOrderTransmissionsToVendors` only checks count > 10.
31
+
32
+ ## How it works
33
+
34
+ ### Producer being watched (1.0)
35
+ `worker/crons/toga2/compasscanada/workflow/2_transmit_mits_purchase_orders_to_vendors.php`, `*/2` in `worker/schedules/cron.worker.sync.json`. Picks `Client_CompassCanada.PurchaseOrders` with `customerId = 5`, `dtSubmitted IS NULL`, `dateRefresh` NULL or `<= CURDATE()`, vendor id IN (1, 2, 3), and an INNER JOIN `Vendors.defaultPoSubmissionIntegrationId -> Integrations`. Uses LEFT joins elsewhere (no SalesOrders INNER JOIN, unlike USA).
36
+
37
+ ### Query (mirrors the cron)
38
+ - Same WHERE as the cron. `Integrations` is LEFT joined so non-routable POs can be counted.
39
+ - **Routable** = `Integrations.id IS NOT NULL AND Vendors.id IN (1,2,3)`. Only routable POs drive the alarm.
40
+ - **Age** = minutes since `GREATEST(dtCreated, dateRefresh)`, so a future-dated PO is not "late" the moment it becomes due.
41
+ - `unroutableCount` = due POs the cron will never pick up. Reported, never alarmed.
42
+ - Registers `Client_CompassCanada` in-method via `_Worker_Client_CompassCanada::DB_CLIENT_COMPASSCANADA` (the class `initialize()` only registers Compass USA).
43
+
44
+ ### Thresholds (calibrated on prod, last 60 days: every PO sent within 7 min, avg < 1 min, busiest day 17 POs)
45
+ | Signal | DEGRADED | HIGH |
46
+ |---|---|---|
47
+ | `pendingCount` | > 10 | > 20 |
48
+ | `oldestPendingMinutes` | > 15 | > 30 |
49
+ | heartbeat not received | 10 min | 15 min |
50
+
51
+ DB read failure pushes `status:"error"`. Body also carries `lateCount` and all four thresholds.
52
+
53
+ ## Gotchas
54
+ - **Only one real vendor.** All 1,041 Canada POs (2026-04-09 to 2026-10-01) went to Grand & Toy (`Vendors.id 1`, integration 1 = CXML). Prod `Vendors`: 1 GRAND & TOY, 4 COMPASS CANADA, 5 AGILANT SOLUTIONS INC (4 and 5 have no integration).
55
+ - **⚠ 1.0 constants do not match prod.** `App_Client_CompassCanada::VENDOR_ID__COMPASS_CANADA = '2'` and `VENDOR_ID__AGILANT_SOLUTIONS = '3'`, but prod ids are 4 and 5. Cron and monitor both use (1,2,3). Harmless while only G&T gets POs; fix both together if Canada ever routes to a second vendor.
56
+ - **The cXML endpoint row has `isProduction = 0` but IS the live G&T URL** (grandandtoy.com `B2BIntegration/SubmitPO_CXML.aspx`). Not a test endpoint; do not "fix" the flag or skip it.
57
+ - **A non-200 cXML response throws and stops the whole cron run.** Every PO behind it waits. The age threshold catches this.
58
+ - **Non-Ground shipping forces the EMAIL integration (id 2)**, and `dtSubmitted` is stamped after the email is queued with no delivery check. Delivery of an emailed PO cannot be monitored.
59
+ - worker2 has no Canada vendor/customer constants (`_Worker_Client_CompassCanada` only has `DB_CLIENT_COMPASSCANADA`); customer id 5 and vendor list are method locals.
60
+
61
+ ## Change history
62
+ - 2026-10-05 — Created and deployed to prod (cron 87, `*/5`); first runs 0 waiting, alarm=OK. (bala)
@@ -18,7 +18,7 @@ project: _Underscore
18
18
  client: compass-canada
19
19
  type: profile
20
20
  status: active
21
- updated: 2026-09-28
21
+ updated: 2026-10-05
22
22
  owners: [jcardinal, bala, tcox, apeterson, ajean, mhammontree, rgirish]
23
23
  files: []
24
24
  related:
@@ -37,6 +37,7 @@ related:
37
37
  - features/french-order-email-localization.md
38
38
  - features/order-fulfillment-status-per-line.md
39
39
  - features/item-fulfillment-tableviews.md
40
+ - features/oneuptime-po-transmissions-to-vendors-monitor.md
40
41
  - ../../2.0/apps/toga2-commerce/features/expedited-shipping-gating.md
41
42
  - ../../2.0/apps/toga2-commerce/features/sso-redirect-and-session-gating.md
42
43
  - ../compass-usa/features/saml-sso.md
@@ -75,6 +76,11 @@ to but distinct from Compass USA. Like Compass USA it spans the **2.0** commerce
75
76
  (6 rows here); the fix seeds the catalog as a Surface create-default per tenant.
76
77
 
77
78
  ## Vendors & integrations
79
+ - **One real vendor, customer id 5 (verified 2026-10-05).** Canada `PurchaseOrders.customerId = 5`.
80
+ Every Canada PO (1,041, 2026-04-09 to 2026-10-01) went to Grand & Toy `Vendors.id 1` (integration 1 =
81
+ CXML). Prod `Vendors` 4 COMPASS CANADA and 5 AGILANT SOLUTIONS INC have no integration, and the 1.0
82
+ constants for them (`'2'`, `'3'`) do not match prod. PO transmit cron quirks and the OneUptime monitor
83
+ (cron 87): [PO-to-vendor monitor](features/oneuptime-po-transmissions-to-vendors-monitor.md).
78
84
  - **Grand & Toy (G&T)** — primary hardware vendor. SOs flow toga → MITS → PO to G&T; G&T sends
79
85
  back ASNs. ASN ingestion (email CSV + the auto-created ItemFulfillment chain + bilingual
80
86
  in-transit email) is documented in [Grand & Toy ASN Import](features/grand-and-toy-asn-import.md).
@@ -5,7 +5,7 @@ project: _Underscore
5
5
  client: compass-usa
6
6
  type: client-feature
7
7
  status: active
8
- updated: 2026-09-16
8
+ updated: 2026-10-05
9
9
  owners: ["rgirish", "bala", "jcardinal"]
10
10
  files:
11
11
  - worker/crons/toga2/compass/workflow/2_transmit_mits_purchase_orders_to_vendors.php
@@ -49,7 +49,7 @@ Renders the PO with **ezpdf** (`Cezpdf`). The "MAIN ITEM LISTING" draws one row
49
49
  - `Logs_Compass.Record` — `recordId` 17 (PurchaseOrder) / 14 (SalesOrder), `primaryKeyId` = the PO/SO `id`. The "transmitted to Vendor" note is the success marker.
50
50
 
51
51
  ### Client variations
52
- Compass Canada has a parallel `compasscanada/workflow/2_transmit_...` keyed on `CUSTOMER_ID__COMPASS_CANADA`.
52
+ Compass Canada has a parallel `compasscanada/workflow/2_transmit_...` keyed on `CUSTOMER_ID__COMPASS_CANADA` (5), sending only to Grand & Toy; it uses LEFT joins (no SalesOrders INNER JOIN). Canada cron differences + its monitor: [Compass Canada PO-to-vendor monitor](../../compass-canada/features/oneuptime-po-transmissions-to-vendors-monitor.md).
53
53
 
54
54
  ## Gotchas
55
55
  - **⚠ Everything transmitted is sourced from the `VendorItem` the PO line points at — a wrong-catalog `vendorItemId` sends the wrong SKU, wrong cost, AND the wrong channel.** The vendor SKU and the cXML-vs-EMAIL routing come entirely from the `VendorItem` that `PurchaseOrderItems.vendorItemId` references (with `PurchaseOrderItems.cost` for price). So a PO line pointing at an **Agilant** VendorItem instead of the Office-Depot one transmits Agilant's **internal SKU** and **wrong cost**, and — because that VendorItem carries **no `overridePoSubmissionIntegrationId`** — falls back to the vendor's default **EMAIL** integration instead of **cXML**. Verified in the legacy `Logs.API`: good order **SA136666** went **cXML** to `b2b.odpbusiness.com` with `SupplierPartID 5775600` / `UnitPrice 945.17`; bad order **SA136846** went **email** with `C40QYUC#ABA` / `$61`. Downstream symptom of the 2026-08-31 catalog fold (a folded PO line resolved to the Agilant twin) — root cause and reversal: [catalog-fold reversal](../workflows/catalog-fold-reversal.md); [two-catalog item model](item-catalogs-and-duplicate-items.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.942",
3
+ "version": "1.0.944",
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",