toga-ai 1.0.152 → 1.0.154
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/1.0/apps/worker/INDEX.md +1 -1
- package/knowledge/1.0/apps/worker/features/forecast2-netsuite-reconciliation.md +30 -1
- package/knowledge/2.0/apps/_underscore/INDEX.md +1 -1
- package/knowledge/2.0/apps/_underscore/features/tracking-number-bridges.md +4 -1
- package/knowledge/2.0/apps/worker2/INDEX.md +1 -1
- package/knowledge/2.0/apps/worker2/features/netsuite-salesorder-open-orders-sync.md +32 -1
- package/knowledge/clients/nychh/profile.md +4 -0
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
| [Worker (1.0 Framework) Architecture](architecture.md) | `worker` is the legacy (**1.0** `App_` framework) **background-job tier**. | worker/index.php, worker/_/app/framework.php, worker/crons/, worker/schedules/, worker/ebs/cron.worker.php, worker/.ebextensions/035_cron.worker.config |
|
|
6
6
|
| [Compass MA Sales Order Exception Report](features/compass-ma-sales-order-exception-report.md) | A worker cron that emails operations the "Compass Refresh Exception Report" — Compass `MA%` sales orders whose corresponding Office Depot (ODP) sales order has | worker/crons/toga2/compass/workflow/7_generate_ma_sales_order_exception_report.php |
|
|
7
7
|
| [Compass Partial In-Transit & Delivered Emails (per package)](features/compass-partial-in-transit-delivered-emails.md) | Compass USA and Compass Canada send a **per-package** in-transit email (and a matching delivered email) instead of one email listing the whole order. | worker/crons/toga2/compass/update_salesorder_status_from_odp.php, worker/crons/toga2/compasscanada/workflow/3_update_salesorder_status_from_grand_and_toy.php |
|
|
8
|
-
| [Forecast2 ↔ NetSuite Reconciliation & Trueup Tooling](features/forecast2-netsuite-reconciliation.md) | CLI tools to **audit** and **repair** drift between the production `Forecast` DB (core2) and NetSuite. | test/@dave/reconcile_netsuite_totals.php, test/@dave/analyze_netsuite_forecast_diff.php, test/@dave/trueup_sales.php, test/@dave/trueup_open_orders.php, test/@dave/trueup_opportunities.php, test/@dave/probe_sales_gap_direct.php, worker/crons/toga2/forecast2/common_import_sales_from_netsuite.php |
|
|
8
|
+
| [Forecast2 ↔ NetSuite Reconciliation & Trueup Tooling](features/forecast2-netsuite-reconciliation.md) | CLI tools to **audit** and **repair** drift between the production `Forecast` DB (core2) and NetSuite. | test/@dave/reconcile_netsuite_totals.php, test/@dave/analyze_netsuite_forecast_diff.php, test/@dave/trueup_sales.php, test/@dave/trueup_open_orders.php, test/@dave/trueup_opportunities.php, test/@dave/probe_sales_gap_direct.php, test/@dave/probe_missing_oo_timing.php, test/@dave/probe_missing_oo_createdby.php, worker/crons/toga2/forecast2/common_import_sales_from_netsuite.php |
|
|
9
9
|
| [NetSuite → TOGa Supply Per-Client Sync (thin wrappers)](features/netsuite-togasupply-per-client-sync.md) | Syncs NetSuite transactions (sales orders, purchase orders, invoices, item receipts, item fulfillments, inventory adjustments) into each TOGa Supply (2.0) clien | worker/crons/toga2/netsuite/common_sync_togasupply.php, worker/crons/toga2/netsuite/sync_togasupply_canon.php, worker/schedules/cron.worker.sync.json, dbchanges2/_modules/netsuite/2026-04-01 - Parameters.sql |
|
|
10
10
|
| [Prudential: Send Shipments for the Day report (daily cron)](features/send-shipments-for-the-day.md) | Daily cron (9:00 PM) that emails Prudential and Dell stakeholders an Excel report of all devices shipped that day, including tracking number, serial number, emp | worker/crons/notifications/reports/send_shipments_for_the_day.php |
|
|
11
11
|
| [Onboarding a Client to the NetSuite TOGa Supply Sync](workflows/onboarding-client-to-netsuite-togasupply-sync.md) | How to add a new TOGa 2 client to the per-client NetSuite → TOGa Supply importer (`worker/crons/toga2/netsuite/`). | worker/crons/toga2/netsuite/sync_togasupply.php, worker/crons/toga2/netsuite/common_sync_togasupply.php, worker/schedules/cron.worker.sync.json, dbchanges2/_modules/netsuite/2026-04-01 - Parameters.sql |
|
|
@@ -6,7 +6,7 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-06-
|
|
9
|
+
updated: 2026-06-22
|
|
10
10
|
owners: [dfranks]
|
|
11
11
|
files:
|
|
12
12
|
- test/@dave/reconcile_netsuite_totals.php
|
|
@@ -15,6 +15,8 @@ files:
|
|
|
15
15
|
- test/@dave/trueup_open_orders.php
|
|
16
16
|
- test/@dave/trueup_opportunities.php
|
|
17
17
|
- test/@dave/probe_sales_gap_direct.php
|
|
18
|
+
- test/@dave/probe_missing_oo_timing.php
|
|
19
|
+
- test/@dave/probe_missing_oo_createdby.php
|
|
18
20
|
- worker/crons/toga2/forecast2/common_import_sales_from_netsuite.php
|
|
19
21
|
related:
|
|
20
22
|
- ../architecture.md
|
|
@@ -116,6 +118,27 @@ None — Forecast2 is a single shared dataset.
|
|
|
116
118
|
- **Pre-2024 legacy open SOs** — ordered before the sync window.
|
|
117
119
|
When a user asks about a date range (e.g. 2026 YTD), **filter the open-orders comparison to that
|
|
118
120
|
trandate window manually** — within the normal window (2024→present) the delta is rounding-only.
|
|
121
|
+
- **`reconcile`'s Open Orders headline is product-only; shipping is NS-only and NOT a delta.**
|
|
122
|
+
Forecast2 never stores the synthetic shipping line (the `OpenOrderItems` writer drops it — see the
|
|
123
|
+
open-orders sync doc), so its shipping column is structurally `$0`. Summing NS product+shipping in
|
|
124
|
+
the headline therefore manufactures a phantom delta (e.g. a clean book reported a fake `$7,547`
|
|
125
|
+
"gap" that was 100% the NS shipping line). Fixed 2026-06-22: the **Open Orders** row compares
|
|
126
|
+
**product-only on both sides** (reconciles to ~$0; the residual is float rounding across orders),
|
|
127
|
+
and shipping prints as a separate `+ shipping` info row marked `(NS-only)` via `reportInfoRow()`.
|
|
128
|
+
Compare the **product** figure for sync health.
|
|
129
|
+
- **The per-order presence diff is the real sync-health signal — and it splits misses into two
|
|
130
|
+
buckets.** `reconcile` calls `openOrderPerOrderDiff()` after the totals: for the window it lists
|
|
131
|
+
open SOs *missing from Forecast2* (open in NS, zero rows synced), *missing from NetSuite* (FC rows
|
|
132
|
+
whose SO is no longer open — benign, `trueup_open_orders` cleanup deletes them), and product-revenue
|
|
133
|
+
mismatches. A non-zero "missing from Forecast2" count is a **real** gap (distinct from the benign
|
|
134
|
+
shipping/rounding deltas above). Root-causing those misses (2026-06-22) showed **two independent
|
|
135
|
+
causes** needing different fixes (detailed in the open-orders sync doc): (A) orders the AMQ enqueuer
|
|
136
|
+
never fired for — **no `Core.WorkerJobs` row at all** for the SO id; and (B) orders that processed
|
|
137
|
+
`isSuccess=1` but wrote zero rows via the read-lag→destructive-delete. Diagnose by bucket:
|
|
138
|
+
`probe_missing_oo_timing.php` (NS status/timestamps confirm the orders are genuinely open) +
|
|
139
|
+
`probe_missing_oo_createdby.php` (creator/context — integration/Web-Services-origin orders cluster
|
|
140
|
+
here) + a `Core.WorkerJobs` lookup by `JSON_EXTRACT(parameters,'$.internalId')` (no row → bucket A;
|
|
141
|
+
rows all `isSuccess=1` yet zero OOI rows → bucket B).
|
|
119
142
|
- **Legacy credit-memo wrong-sign rows.** Some `Forecast.Sales` credit-memo/cash-refund rows were
|
|
120
143
|
stored with **flipped signs** by a prior sync version (positive instead of negative), inflating
|
|
121
144
|
revenue. `trueup_sales.php` repairs them: it compares against NS by trandate, detects the sign
|
|
@@ -126,6 +149,12 @@ None — Forecast2 is a single shared dataset.
|
|
|
126
149
|
|
|
127
150
|
## Change history
|
|
128
151
|
|
|
152
|
+
- 2026-06-22 — **`reconcile` Open Orders made apples-to-apples.** Headline row now compares
|
|
153
|
+
product-only on both sides (shipping is NS-only, prints as a separate `(NS-only)` info row) — kills
|
|
154
|
+
a phantom shipping-only "delta". Documented the per-order presence diff as the real sync-health
|
|
155
|
+
signal and the **two missing-from-Forecast2 buckets** (enqueuer-never-fired vs read-lag
|
|
156
|
+
destructive-delete) with a bucket-based diagnostic recipe; added `probe_missing_oo_timing.php` +
|
|
157
|
+
`probe_missing_oo_createdby.php`. (dfranks)
|
|
129
158
|
- 2026-06-11 — Documented the `App_Database` sandbox-dev read pitfall (bypass with direct core2
|
|
130
159
|
mysqli), `reconcile`'s open-orders live-snapshot semantics (future-dated + pre-2024 legacy SOs
|
|
131
160
|
explain apparent gaps), the legacy credit-memo wrong-sign repair, and added `trueup_opportunities`
|
|
@@ -7,4 +7,4 @@
|
|
|
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
|
| [Per-Client Database Connections & the Local Logs Trap](features/per-client-database-connections.md) | When `_underscore` serves a request for a client it opens **three distinct per-client database connections**, not one. | _underscore/Database.php, _underscore/ApiRequest.php, _underscore/Model/Client/Logs/Api.php |
|
|
9
9
|
| [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 |
|
|
10
|
-
| [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, dbchanges2/Client_Prudential/2026-06-15 - ItemFulfillmentTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql, dbchanges2/Client_Quad/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql |
|
|
10
|
+
| [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, dbchanges2/Client_Prudential/2026-06-15 - ItemFulfillmentTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19b - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql, dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql, dbchanges2/Client_Quad/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql |
|
|
@@ -22,6 +22,7 @@ files:
|
|
|
22
22
|
- dbchanges2/Core/2026-06-10 - TrackingNumberBridges.sql
|
|
23
23
|
- dbchanges2/Client_Prudential/2026-06-15 - ItemFulfillmentTrackingNumberAclLogicGroups.sql
|
|
24
24
|
- dbchanges2/Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql
|
|
25
|
+
- dbchanges2/Client_Nychh/2026-06-19b - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql
|
|
25
26
|
- dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql
|
|
26
27
|
- dbchanges2/Client_Quad/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql
|
|
27
28
|
related:
|
|
@@ -151,12 +152,14 @@ returnTrackingNumber: {...} }]`, and an IFIU's as `itemFulfillmentItemUnitTracki
|
|
|
151
152
|
bridge routes during item-fulfillment + item-receipt import, so any NetSuite-integrated client with those
|
|
152
153
|
integrations enabled 403s (EZ-1) on the bridge records the moment the sync exercises them. Fixed one-off
|
|
153
154
|
per client as each starts failing: **Prudential** (`Client_Prudential/2026-06-15 - ...`, recs 317/319) and
|
|
154
|
-
**Quad** (`Client_Quad/2026-06-18a - ...`, all of 317-322)
|
|
155
|
+
**Quad** (`Client_Quad/2026-06-18a - ...`, all of 317-322) and **NYCHH**
|
|
156
|
+
(`Client_Nychh/2026-06-19b - ...`, all of 317-322) so far. Each new client is whack-a-mole until
|
|
155
157
|
the chain is folded back into the base migration + blank-client template.
|
|
156
158
|
|
|
157
159
|
- **Porting the item-fulfillment TableView fix to another client is two independent decisions, not a copy-paste.** The **re-root** (Units 31 → ItemFulfillmentItems 29 + OUTER unit chain) is universally portable and fixes the "0 records" bug everywhere. The **tracking source is client-specific**: Compass writes one tracking number per item fulfillment at the **item level (318)**, so its views read 318. Other clients populate different bridge levels — verify with `SELECT COUNT(*)` per bridge before choosing. As of 2026-06-19, **record 318 is empty in `Client_Nychh` and `Client_Quad`**; their tracking lives at the **IF/shipment level (317)** (covers IFIs: NYCHH 7955/10049 ≈ 79%, Quad 4878/4967 ≈ 98%) and the **unit level (319)** (≈ 7–9% — serialized only). Copying Compass's 318 join into a client that doesn't write 318 yields a structurally-correct view with permanently blank tracking until 318 is backfilled. (NYCHH's pre-fix view pointed at the now-deleted record 41 = old IF-level/package bridge, i.e. it originally intended IF-level 317.)
|
|
158
160
|
|
|
159
161
|
## Change history
|
|
162
|
+
- 2026-06-19 — **NYCHH** hit the bridge ACL gap in prod: 403 EZ-1 on `item-fulfillment-tracking-numbers` (DEBUG "No ACL Logic Groups defined", aclRecordPermissionId 318 = record 317, roleId 1, appId NULL). Confirmed all 6 bridge perms (ids 318-323, records 317-322) had 0 logic groups; added the chain via `Client_Nychh/2026-06-19b - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql` (all 6 bridges, idempotent anti-joins, RANDOM_BYTES uuids, slug='all'/sqlExpression='1', record ids derived from AclRecordPermissions). Same fix pattern as Quad 2026-06-18a / Prudential 2026-06-15. (jcardinal)
|
|
160
163
|
- 2026-06-19 — Applied the Compass item-fulfillment TableView fix to **NYCHH** and **Quad** (`Client_Nychh`/`Client_Quad` `2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql`): re-rooted views 12 & 13 at ItemFulfillmentItems, item-level tracking via 318, preserving Quad's three Units-level custom columns. Confirmed read-only that record 318 is empty for both clients (tracking blank until backfilled) — their data is at 317 (IF-level, ~79%/~98% coverage) and 319 (unit-level); recorded the portability gotcha. (jcardinal)
|
|
161
164
|
- 2026-06-18 — Quad's NetSuite TOGa Supply sync (`sync_togasupply_quad.php`) hit the bridge ACL gap in prod: 403 EZ-1 on `item-fulfillment-tracking-numbers` (Sentry 7559037554, 46×, since the 2026-06-15 deploy). Confirmed `Client_Quad` perms 380-385 (recs 317-322, role 1) had 0 logic groups; added the chain via `Client_Quad/2026-06-18a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql` (all 6 bridges, idempotent, RANDOM_BYTES uuids). Noted the gap surfaces via the per-client sync, not only UI reads. (dfranks)
|
|
162
165
|
- 2026-06-16 — Caught a migration code-update miss: four queries in `Model/Client/ItemFulfillment.php` (`upsShipmentApi`, `fedexShipmentApi`, `fulfill`, `createNetsuiteItemFulfillment`) still joined the dropped `ItemFulfillmentPackages` table to resolve tracking — repointed to `ItemFulfillments_TrackingNumbers`. See the carrier-shipping-labels doc. (mhammontree)
|
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
| [Elite Freshservice Sync (worker2)](features/elite-freshservice-sync.md) | `_Worker_Elite` processes Freshservice webhook events and syncs them into TOGA 2. | worker2/Worker/Elite.php, worker2/Config/dev-kmaramreddy-laptop.ini |
|
|
9
9
|
| [Monitoring Framework (Orchestrator + Child Monitors)](features/monitoring-framework.md) | A unified, DB-driven monitoring framework for business-critical data flows (Compass POs, Prudential asset imports, AIG closed claims, …). | worker2/Worker/Monitor.php, worker2/Worker/Monitors/, worker2/Worker/Notification/Email.php, dbchanges2/Core/2026-05-21 - Monitors.sql |
|
|
10
10
|
| [NetSuite → TOGA Opportunity Sync (API Message Queue + worker2 webhook)](features/netsuite-opportunity-sync.md) | Outbound sync from NetSuite to TOGA for the record types the Forecast2 importer pulls (opportunities first; sales/items/etc. | worker2/Worker/Netsuite.php, worker2/Worker/Netsuite/Opportunity.php, worker2/Controller/Index.php, _underscore/Worker.php, test/@dave/NetSuite/api-message-queue/lib_amq_queue.js, test/@dave/NetSuite/api-message-queue/ue_api_msg_queue_enqueue.js, test/@dave/NetSuite/api-message-queue/ue_amq_drain.js, test/@dave/NetSuite/api-message-queue/ss_amq_drain.js, test/@dave/NetSuite/api-message-queue/DEPLOY_RUNBOOK.md, test/@dave/clickup/backfill_opportunity_numbers.php, test/@dave/clickup/probe_opportunity_fields.php, test/@dave/probe_clickup_desc_match.php, worker/crons/toga2/forecast2/common_import_sales_from_netsuite.php |
|
|
11
|
-
| [NetSuite → Forecast Open-Orders Sync (salesOrder webhook → OpenOrderItems)](features/netsuite-salesorder-open-orders-sync.md) | Webhook-driven, single-record port of the legacy open-orders importer (TRUE-79142). | worker2/Worker/Netsuite/SalesOrder.php, worker2/Worker/Netsuite.php, test/@dave/probe_salesorder_rest_shape.php, test/@dave/probe_open_order_lines.php, test/@dave/check_so_status.php, test/@dave/check_so_history.php, test/@dave/probe_so_rest_lines.php, worker/crons/toga2/forecast2/import_open_orders.php, worker/crons/toga2/forecast2/common_import_sales_from_netsuite.php |
|
|
11
|
+
| [NetSuite → Forecast Open-Orders Sync (salesOrder webhook → OpenOrderItems)](features/netsuite-salesorder-open-orders-sync.md) | Webhook-driven, single-record port of the legacy open-orders importer (TRUE-79142). | worker2/Worker/Netsuite/SalesOrder.php, worker2/Worker/Netsuite.php, test/@dave/probe_salesorder_rest_shape.php, test/@dave/probe_open_order_lines.php, test/@dave/check_so_status.php, test/@dave/check_so_history.php, test/@dave/probe_so_rest_lines.php, test/@dave/probe_missing_oo_timing.php, test/@dave/probe_missing_oo_createdby.php, worker/crons/toga2/forecast2/import_open_orders.php, worker/crons/toga2/forecast2/common_import_sales_from_netsuite.php |
|
|
12
12
|
| [Teams Meeting Transcript Export](features/teams-transcript-export.md) | `_Worker_Team_Transcripts` (action `Team/Transcripts/Export`) polls Microsoft Graph for Teams meeting transcripts produced by a set of organizers, classifies ea | worker2/Worker/Team/Transcripts.php, worker2/Config/production.ini, worker2/Database/TeamsTranscriptExports.sql, dbchanges2/Core/2026-06-18a - Teams Transcript Export schedule.sql |
|
|
@@ -6,7 +6,7 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-06-
|
|
9
|
+
updated: 2026-06-22
|
|
10
10
|
owners: ["dfranks"]
|
|
11
11
|
files:
|
|
12
12
|
- worker2/Worker/Netsuite/SalesOrder.php
|
|
@@ -16,6 +16,8 @@ files:
|
|
|
16
16
|
- test/@dave/check_so_status.php
|
|
17
17
|
- test/@dave/check_so_history.php
|
|
18
18
|
- test/@dave/probe_so_rest_lines.php
|
|
19
|
+
- test/@dave/probe_missing_oo_timing.php
|
|
20
|
+
- test/@dave/probe_missing_oo_createdby.php
|
|
19
21
|
- worker/crons/toga2/forecast2/import_open_orders.php
|
|
20
22
|
- worker/crons/toga2/forecast2/common_import_sales_from_netsuite.php
|
|
21
23
|
related:
|
|
@@ -120,6 +122,26 @@ None — uniform (platform-wide Forecast2 sync).
|
|
|
120
122
|
`project_amq_realtime_requirement` in dev memory). Diagnose with `probe_open_order_lines.php` (SuiteQL vs
|
|
121
123
|
Forecast) + `probe_so_rest_lines.php` (live REST sublist count) + the `WorkerJobs` `dtStarted`/`instanceId`
|
|
122
124
|
timing (to confirm serial-vs-concurrent before blaming ordering).
|
|
125
|
+
- **A missing open order has TWO distinct causes — diagnose which before "fixing" it.** When
|
|
126
|
+
`reconcile_netsuite_totals.php`'s per-order diff reports an open SO with **zero `OpenOrderItems`
|
|
127
|
+
rows**, it's one of two unrelated failures, told apart by `Core.WorkerJobs` (lookup by
|
|
128
|
+
`JSON_EXTRACT(parameters,'$.internalId')`):
|
|
129
|
+
- **Bucket A — the webhook never fired (no `WorkerJobs` row at all).** Nothing enqueued → the
|
|
130
|
+
handler never ran. The enqueuer (NetSuite-side AMQ User Event) doesn't fire for every context —
|
|
131
|
+
**integration/Web-Services-origin orders and backend/scheduled mass-edits cluster here** (a UE
|
|
132
|
+
only fires in the execution contexts its deployment enables). Confirm the order is genuinely open
|
|
133
|
+
+ see its creator/context with `probe_missing_oo_timing.php` + `probe_missing_oo_createdby.php`.
|
|
134
|
+
This is **NetSuite-side** (enqueuer deployment/context), *not* a worker2 handler bug — the
|
|
135
|
+
read-lag fixes below do nothing for it. Backstop: the scheduled drainer / `trueup_open_orders`.
|
|
136
|
+
- **Bucket B — the handler ran and returned `isSuccess=1` but wrote zero rows** (the read-lag →
|
|
137
|
+
destructive-delete below). All items present in `Forecast.Items` (no throw), order genuinely open.
|
|
138
|
+
**Diagnostic for whether the self-heal path is even active:** `deferReimport` re-enqueues with an
|
|
139
|
+
incremented `attempt` parameter, and `logImportBreadcrumb` writes a per-order row to **`Logs.Api`
|
|
140
|
+
`source = 'OPEN_ORDER_IMPORT'`** whose `responseCode` encodes the outcome (**200** synced / **202**
|
|
141
|
+
deferred-reenqueued / **204** removeAll / **409** wrote-but-short = silent zero-rows / **500** gave
|
|
142
|
+
up after `MAX_IMPORT_ATTEMPTS`). If every `WorkerJobs` row for the id has a **NULL `attempt`** and
|
|
143
|
+
there are **no `OPEN_ORDER_IMPORT` breadcrumbs** for it, the self-heal/defer path isn't executing
|
|
144
|
+
for that order — so a bucket-B miss has no retry and freezes at zero rows.
|
|
123
145
|
- **REST shape ≠ SOAP shape.** The cron reads the SOAP-shim shape; this handler reads the REST record
|
|
124
146
|
(`status->refName`, line `quantityBilled`, `class->refName`, `entity->id`, `salesRep->id`,
|
|
125
147
|
`shippingCost`). Verified against live orders via `test/@dave/probe_salesorder_rest_shape.php`.
|
|
@@ -174,6 +196,15 @@ and are a candidate to extract into a shared `_Component_Forecast_Db` before the
|
|
|
174
196
|
|
|
175
197
|
## Change history
|
|
176
198
|
|
|
199
|
+
- 2026-06-22 — **Separated "missing open order" into two distinct buckets** with a discriminating
|
|
200
|
+
diagnostic (`Core.WorkerJobs` lookup by `parameters.internalId`): **(A) webhook never enqueued** (no
|
|
201
|
+
`WorkerJobs` row — NetSuite-side enqueuer not firing for integration/Web-Services/backend-mass-edit
|
|
202
|
+
contexts; not a handler bug) vs **(B) processed `isSuccess=1`, zero rows** (the read-lag destructive
|
|
203
|
+
delete). Recorded the self-heal signal-reading (NULL `attempt` on every job + no `OPEN_ORDER_IMPORT`
|
|
204
|
+
Logs.Api breadcrumb ⇒ self-heal/defer path not active for that order; breadcrumb `responseCode`
|
|
205
|
+
legend 200/202/204/409/500). Reconfirmed every sampled miss carries a NetSuite **item group**, and
|
|
206
|
+
all group/member items resolved in `Forecast.Items` (so isSuccess=1 = no unknown-item throw). Added
|
|
207
|
+
`probe_missing_oo_timing.php` + `probe_missing_oo_createdby.php`. (dfranks)
|
|
177
208
|
- 2026-06-18 — **Root-caused the open-order delta to REST `item.items` read-after-write lag** (not the
|
|
178
209
|
drainer/enqueue fixes, not ordering). SO 7170669 committed 4 of 15 open lines despite 14 *strictly
|
|
179
210
|
sequential, single-instance, in-order* PUTs — the last authoritative read returned a lagged partial
|
|
@@ -37,4 +37,8 @@ table views. Client-specific DB change-sets live in `dbchanges2/Client_Nychh/`.
|
|
|
37
37
|
- Tracking data: record 318 (item-level) is currently empty for this client; their tracking
|
|
38
38
|
populates the IF/shipment level (record 317). The rebuilt views use 318 (per the Compass
|
|
39
39
|
pattern) and will show tracking once item-level tracking is backfilled.
|
|
40
|
+
- Bridge ACL gap fixed 2026-06-19 (`dbchanges2/Client_Nychh/2026-06-19b`): the IF/IR tracking
|
|
41
|
+
bridge records 317-322 had AclRecordPermissions but no AclLogicGroups, so reads of
|
|
42
|
+
`item-fulfillment-tracking-numbers` 403'd (EZ-1). Added the logic-group chain for all 6
|
|
43
|
+
bridges. See [Tracking-Number Bridge Migration](../../2.0/apps/_underscore/features/tracking-number-bridges.md).
|
|
40
44
|
- This profile is a starting point; expand as more NYCHH-specific behavior is captured.
|
package/package.json
CHANGED