toga-ai 1.0.730 → 1.0.731
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -6,7 +6,7 @@ project: Library
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
9
|
+
updated: 2026-09-01
|
|
10
10
|
owners: [dfranks, jcardinal, kyalamarthi]
|
|
11
11
|
files:
|
|
12
12
|
- library/app/api/netsuite/rest.php
|
|
@@ -169,6 +169,19 @@ Forecast2 tables already store.
|
|
|
169
169
|
cross-checking item id, then number each line by the NetSuite `line` (fall back to `linesequencenumber`
|
|
170
170
|
if the item ids disagree). Self-heals on the next receipt sync (it re-imports the PO). Same "join a
|
|
171
171
|
NetSuite line on `line`, not `linesequencenumber`" lesson as the `tl.id` semantics above.
|
|
172
|
+
- **⚠ `listPurchaseOrders()` scoped POs by the VENDOR header `entity`, silently dropping every
|
|
173
|
+
drop-ship PO for all clients (fixed 2026-09-01).** It reused the shared `buildEntityInFilter()`
|
|
174
|
+
helper — correct for `listSalesOrders`/`listSales` (SO header `entity` = customer) but **wrong for
|
|
175
|
+
POs**, whose header `entity` is the **vendor**. The `AND entity IN (<customer ids>)` filter matched
|
|
176
|
+
ZERO customer POs, so the header query returned nothing and the section imported nothing — no error.
|
|
177
|
+
Replaced with a new `buildPurchaseOrderCustomerFilter()` that scopes by the customer on the LINES or
|
|
178
|
+
the end-customer body field:
|
|
179
|
+
`AND ( id IN (SELECT tl.transaction FROM transactionline tl WHERE tl.entity IN ($ids) AND tl.mainline = 'F') OR CUSTBODY_END_CUSTOMER IN ($ids) )`.
|
|
180
|
+
`buildEntityInFilter()` is unchanged. This is a **fetch-scope** bug (record never returned by the
|
|
181
|
+
`list*`), a class distinct from the per-id `fetchPurchaseOrderById` shim-shape gaps above — but the
|
|
182
|
+
same underlying trap of reusing a sales-order-shaped assumption on a purchase order. Full
|
|
183
|
+
engine-side impact + the tier-wide per-client backfill live on the
|
|
184
|
+
[per-client-sync doc](../../worker/features/netsuite-togasupply-per-client-sync.md).
|
|
172
185
|
- **A shim must produce the SOAP object's SHAPE, not just its scalar fields — an absent nested list
|
|
173
186
|
crashes 1.0 (2026-08-29).** `fetchCustomerById()`'s `addressbookList` was where the AIG lookup phase
|
|
174
187
|
crashed: a REST customer with no/odd address made the shim omit the nested `addressbook` structure the
|
|
@@ -262,6 +275,14 @@ None — uniform across clients (NetSuite is a single shared account).
|
|
|
262
275
|
|
|
263
276
|
## Change history
|
|
264
277
|
|
|
278
|
+
- 2026-09-01 — Recorded that **`listPurchaseOrders()` scoped POs by the VENDOR header `entity`** (via
|
|
279
|
+
the reused `buildEntityInFilter()`), silently dropping every drop-ship / special-order PO for all
|
|
280
|
+
togasupply clients since the SOAP→REST migration. A PO header `entity` is the vendor, not the
|
|
281
|
+
customer, so `AND entity IN (<customer ids>)` matched zero rows and the section imported nothing with
|
|
282
|
+
no error. Fixed by a new `buildPurchaseOrderCustomerFilter()` that scopes by the line-level customer
|
|
283
|
+
or `CUSTBODY_END_CUSTOMER` body field; `buildEntityInFilter()` untouched. Fetch-scope bug (distinct
|
|
284
|
+
from the per-id shim-shape gaps). Engine impact + per-client backfill on the per-client-sync doc.
|
|
285
|
+
(jcardinal)
|
|
265
286
|
- 2026-08-30 — Recorded that **`fetchPurchaseOrderById` numbered PO lines by `linesequencenumber` instead
|
|
266
287
|
of the NetSuite `line`** — a receipt for a post-gap line (PO with a deleted middle line, real lines
|
|
267
288
|
1,2,4) failed `EV-12` "unable to find a unique match" (GroWrk PO 168223). The PO record line sublist
|
|
@@ -389,6 +389,47 @@ Parameters are stored **per client DB** but accessed **through the TOGa2 API**,
|
|
|
389
389
|
skipped; and because the location filter is shared, receipts belonging to **other** clients at a
|
|
390
390
|
shared warehouse are returned and correctly skipped. Modelling receipts as "location-matched"
|
|
391
391
|
produces wrong diagnostics.
|
|
392
|
+
- **⚠ The PURCHASE_ORDERS section silently dropped EVERY drop-ship / special-order PO on ALL
|
|
393
|
+
togasupply clients — a PO header `entity` is the VENDOR, not the customer (fixed 2026-09-01).**
|
|
394
|
+
`App_Api_Netsuite_Rest::listPurchaseOrders()` (`library/app/api/netsuite/rest.php`) scoped the PO
|
|
395
|
+
HEADER query with `AND entity IN (<client customer ids>)` via the shared `buildEntityInFilter()`
|
|
396
|
+
helper. That helper is correct for **sales** orders (an SO header `entity` IS the customer) but
|
|
397
|
+
**wrong for POs** — a PO header `entity` is the **vendor**. So the customer-id filter matched ZERO
|
|
398
|
+
of a client's POs, the `foreach` never ran, and there was **no interest check, no throw, no log** —
|
|
399
|
+
a pure fetch-scope miss. Proven on Elite PO tranid 128238 (NS internal 5412515, customer 36443,
|
|
400
|
+
vendor TD Synnex 20202): `... AND entity IN (36443)` returned 0 rows; unfiltered returned 1;
|
|
401
|
+
filtering by LINE entity (`transactionline.entity IN (36443)`) returned 1.
|
|
402
|
+
- **Why drop-ship POs vanished ENTIRELY (two-path gap).** Two import paths reach a PO and both
|
|
403
|
+
excluded drop-ship: (a) the dedicated PURCHASE_ORDERS section, via the header-entity filter above;
|
|
404
|
+
(b) the nested `syncItemReceiptFromNetsuite → syncPurchaseOrderFromNetsuite` path (via
|
|
405
|
+
`fetchPurchaseOrderById`, which has **no** entity filter) never fires for a drop-ship PO because a
|
|
406
|
+
drop-ship PO produces item **fulfillments**, not item **receipts**. Stock POs still imported via
|
|
407
|
+
the item-receipt path — which is why Elite had 51 NS POs (all stock, from the 2026-08-12 backfill)
|
|
408
|
+
yet was missing drop-ship ones like 128238. Drop-ship POs carry `customForm.internalId = 148`
|
|
409
|
+
("ASI - Drop Ship Purchase Order"), the end customer on the transaction LINES
|
|
410
|
+
(`transactionline.entity`) and on `shipTo`, so the dedicated PURCHASE_ORDERS section is their
|
|
411
|
+
**only** import path.
|
|
412
|
+
- **Fix (library only, no SQL, no other repos):** added
|
|
413
|
+
`private static function buildPurchaseOrderCustomerFilter(array $entityInternalIds): string` and
|
|
414
|
+
switched `listPurchaseOrders()` to use it. It scopes POs by the customer on the LINES or the
|
|
415
|
+
end-customer body field instead of the vendor header:
|
|
416
|
+
`AND ( id IN (SELECT tl.transaction FROM transactionline tl WHERE tl.entity IN ($ids) AND tl.mainline = 'F') OR CUSTBODY_END_CUSTOMER IN ($ids) )`.
|
|
417
|
+
`buildEntityInFilter()` is left **untouched** (still correct for `listSalesOrders`/`listSales`/
|
|
418
|
+
`listItemFulfillments`, where header entity = customer). Empty-ids behavior preserved (returns
|
|
419
|
+
`''` = no scoping). Deployed; PO 128238 then imported for Elite (dev confirmed). **PO fetch must
|
|
420
|
+
scope by line-level customer / end-customer, never the vendor header entity — the opposite of the
|
|
421
|
+
sales-order shape, and the reason the reused helper silently lost data.** Cross-ref: the sibling
|
|
422
|
+
per-id path's own shim gaps are in the
|
|
423
|
+
[SuiteQL/REST shim doc](../../library/features/netsuite-suiteql-rest-shim.md).
|
|
424
|
+
- **⚠ Tier-wide backfill owed, per-client.** Because `listPurchaseOrders` is shared, EVERY
|
|
425
|
+
togasupply client has been missing its drop-ship POs since the SOAP→REST migration. Backfill each
|
|
426
|
+
client by rewinding `NETSUITE_LAST_SYNC_DATETIME_PURCHASE_ORDERS` (idempotent) — do it
|
|
427
|
+
**deliberately, one client at a time**, not all at once (Elite's first window 2024-04-15..04-18
|
|
428
|
+
alone held 269 POs).
|
|
429
|
+
- **Diagnostic lesson (durable):** a "silent, no-error, not-imported" record in this engine can be a
|
|
430
|
+
**fetch-scope mismatch** (the record is never returned by `list*`), distinct from a per-record
|
|
431
|
+
throw. The `$isInterested == 1` you see when feeding a single PO directly (or via the diagnose
|
|
432
|
+
script) can disagree with the scheduled section, which never fetched it.
|
|
392
433
|
- **`Units.locationId` is never populated by this sync — transaction location lives on the item
|
|
393
434
|
rows.** All 229 `Client_Elite.Units` have `locationId` NULL. `locationId` exists only on `Units`
|
|
394
435
|
and `InventoryAdjustmentItems` (not on the `*ItemUnits` bridge tables), and
|
|
@@ -6,8 +6,8 @@ project: Worker
|
|
|
6
6
|
client: elite
|
|
7
7
|
type: client-feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-
|
|
10
|
-
owners: ["snaredla"]
|
|
9
|
+
updated: 2026-09-01
|
|
10
|
+
owners: ["snaredla", "jcardinal"]
|
|
11
11
|
files:
|
|
12
12
|
- worker/crons/toga2/netsuite/sync_togasupply_elite.php
|
|
13
13
|
- worker/crons/toga2/netsuite/common_sync_togasupply.php
|
|
@@ -125,6 +125,17 @@ the trait declares must exist as a column, a `CustomRecordFields` row **and** an
|
|
|
125
125
|
|
|
126
126
|
## Change history
|
|
127
127
|
|
|
128
|
+
- 2026-09-01 — **Drop-ship / special-order POs were never importing for Elite** (e.g. PO tranid
|
|
129
|
+
128238). Root cause was in shared code, not Elite: `listPurchaseOrders()` filtered the PO header by
|
|
130
|
+
the VENDOR `entity` (TD Synnex 20202) instead of the customer, so Elite's 36443-scoped filter matched
|
|
131
|
+
0 POs, and drop-ship POs — which make item fulfillments, not receipts — had no other import path.
|
|
132
|
+
Fixed engine-side (new `buildPurchaseOrderCustomerFilter()` scoping by line-level customer /
|
|
133
|
+
end-customer); PO 128238 then imported (dev confirmed). Full write-up on the
|
|
134
|
+
[engine doc](../../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md) and
|
|
135
|
+
[SuiteQL/REST shim doc](../../../1.0/apps/library/features/netsuite-suiteql-rest-shim.md). Elite's
|
|
136
|
+
older stock-only PO count (51) will grow once its `NETSUITE_LAST_SYNC_DATETIME_PURCHASE_ORDERS` is
|
|
137
|
+
rewound to backfill drop-ship POs (idempotent; first 2024-04-15..04-18 window alone held 269 POs).
|
|
138
|
+
(jcardinal)
|
|
128
139
|
- 2026-08-12 — TRUE-80499: **onboarded Elite to the NetSuite → TOGa Supply importer.** Built the
|
|
129
140
|
wrapper (customer 36443, `isParentCustomer` false, 30-day window, invoices temporarily disabled),
|
|
130
141
|
the schedule entry, 18 `_Model_Elite_*` netsuite trait models, the `_modules/netsuite` opt-in, and
|
package/package.json
CHANGED