toga-ai 1.0.798 → 1.0.799
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-09-
|
|
9
|
+
updated: 2026-09-11
|
|
10
10
|
owners: [jcardinal, mhammontree, bala]
|
|
11
11
|
files:
|
|
12
12
|
- library/app/api/toga2.php
|
|
@@ -79,6 +79,17 @@ belong to the NetSuite importer — documented in the per-client-sync doc, not h
|
|
|
79
79
|
- Returns the decoded response object; callers read `->data->{resource}`, `->meta->nextPage`,
|
|
80
80
|
`->isSuccess`, `->status`, `->messages[].code`.
|
|
81
81
|
|
|
82
|
+
> **The "Invalid API Response" exception now LEADS with the api2 message codes (2026-09-11).**
|
|
83
|
+
> `send()`'s failure exception used to `print_r` the whole response envelope, whose header prints
|
|
84
|
+
> first — so on a real rejection the useful api2 code (e.g. `EV-10: ...`) fell **past** the
|
|
85
|
+
> `Logs.Event.errorMessage` `varchar(255)` limit and was **truncated away**, making the failure look
|
|
86
|
+
> "quiet" (this is exactly what hid the NYCHH duplicate-`Units` EV-10 — see the
|
|
87
|
+
> [per-client sync doc](../../worker/features/netsuite-togasupply-per-client-sync.md)). The exception
|
|
88
|
+
> message now puts the `->messages[].code: text` list **first**, via a new private helper
|
|
89
|
+
> `describeApiMessages()` (~L726), then the `print_r` dump. The helper **caps each message's text at
|
|
90
|
+
> 160 chars** so an echoed customer value cannot land in full in the log table (cso point). Net: the
|
|
91
|
+
> real api2 cause self-reveals in `Logs.Event` on the next run instead of being cut off.
|
|
92
|
+
|
|
82
93
|
> **`send()` ALWAYS returns something carrying `isSuccess` — so `empty($response->isSuccess)` is a
|
|
83
94
|
> safe failure check on anything it returns, GETs included** (verified 2026-08-12, ~L432–450). It
|
|
84
95
|
> returns early **only** when `isSuccess` is true; when `isSuccess` is false and
|
|
@@ -413,6 +424,15 @@ enable flags** and an optional `$monitorTogadeskDepartmentIds[]`:
|
|
|
413
424
|
|
|
414
425
|
## Change history
|
|
415
426
|
|
|
427
|
+
- 2026-09-11 — **Observability: `send()`'s "Invalid API Response" exception now leads with the api2
|
|
428
|
+
message codes.** Added a private `describeApiMessages()` helper (~L726) that renders the
|
|
429
|
+
`->messages[].code: text` list (each text capped at 160 chars, cso point) and prepended it to the
|
|
430
|
+
exception message ahead of the `print_r` dump (~L636). Reason: `Logs.Event.errorMessage` is
|
|
431
|
+
`varchar(255)` and the old dump printed the envelope header first, pushing the real api2 code (e.g.
|
|
432
|
+
`EV-10`) past 255 chars where it was truncated — so failures looked "quiet". This made the NYCHH
|
|
433
|
+
duplicate-`Units` EV-10 self-reveal; the underlying case-mismatch fix and the three diagnosis traps
|
|
434
|
+
are on the [per-client sync doc](../../worker/features/netsuite-togasupply-per-client-sync.md). Library
|
|
435
|
+
only, `php -l` clean; **written, not committed/deployed**. (jcardinal)
|
|
416
436
|
- 2026-09-08 - Added `updateTransferOrderStageToClosed(&$nsOrder, array &$clientConfiguration): bool`
|
|
417
437
|
and the constant `TRANSFER_ORDER_STATUS__CLOSED = 'closed'` (also now used by the `case 'Closed'` in
|
|
418
438
|
the transfer-order status switch). It is a **stage-only** writer: it never touches line items, so it
|
|
@@ -6,7 +6,7 @@ project: Worker
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-09-
|
|
9
|
+
updated: 2026-09-11
|
|
10
10
|
owners: ["dfranks", "bala", "jcardinal", "mhammontree", "snaredla", "rgirish"]
|
|
11
11
|
files:
|
|
12
12
|
- worker/crons/toga2/netsuite/common_sync_togasupply.php
|
|
@@ -296,6 +296,49 @@ hit **every section and every client**, not just the by-reference ones.
|
|
|
296
296
|
GET's UTC. `strtotime()` and `App_Date::convertToSQLDate()` both use the script tz (Chicago) and are
|
|
297
297
|
the trap. Any manual cursor rewind value you set by hand must also be **Eastern**.
|
|
298
298
|
|
|
299
|
+
### ⚠ ITEM_RECEIPTS froze at RUNNING on a case-mismatched Units serial → duplicate-unit INSERT (EV-10 / 1062) (found + fixed 2026-09-11, NYCHH prod)
|
|
300
|
+
|
|
301
|
+
`syncItemReceiptFromNetsuite()` (`library/app/api/toga2.php` ~L4022) builds a PHP array of the
|
|
302
|
+
client's existing `Units` keyed by **serial number** to decide PUT (update) vs POST (create). The
|
|
303
|
+
DB `GET /units` (`Units.serialNumber IN (...)`) is **case-insensitive** and returns the **stored**
|
|
304
|
+
casing (e.g. `'na100'`), but the code keyed the PHP lookup by that **raw stored** value while reading
|
|
305
|
+
it with the **uppercased** serial (`strtoupper` at ~L3905). **PHP array keys are case-sensitive** → the
|
|
306
|
+
lookup missed the existing row → took the **create** path → `POST /units` collided on the
|
|
307
|
+
case-insensitive `Units.itemId_serialNumber` unique key → MySQL **1062** / api2 **EV-10** → the
|
|
308
|
+
ITEM_RECEIPTS section **threw before its cursor PUT**, freezing at RUNNING (and ITEM_FULFILLMENTS,
|
|
309
|
+
which runs behind it, froze with it).
|
|
310
|
+
|
|
311
|
+
- **Proven on NYCHH:** `Client_Nychh.Units` 23400-23409 store serial `'na100'..'na109'` (lowercase),
|
|
312
|
+
`c_netsuiteInternalInventoryAssignmentId` NULL; the sync sent `'NA100'`.
|
|
313
|
+
- **Fix (library only, `php -l` clean):** `strtoupper()` on **both** the array key **and** the reads,
|
|
314
|
+
so the PHP lookup is case-insensitive like the DB. A **second, half-fixed copy** of the same lookup
|
|
315
|
+
lower in the file (~L6326) already uppercased the **key** but not its two **reads** — made them
|
|
316
|
+
match too. php-reviewer + cso both cleared it (SAFE TO SHIP). **Written, NOT committed/deployed.**
|
|
317
|
+
- **Lesson:** whenever a PHP lookup mirrors a case-insensitive DB column, normalize case on **every**
|
|
318
|
+
side — the key write and every read. One un-normalized read reintroduces the duplicate-create path.
|
|
319
|
+
|
|
320
|
+
#### Diagnosis: three traps that hid this EV-10 (2026-09-11)
|
|
321
|
+
|
|
322
|
+
The section looked "quiet" (RUNNING, no loud crash-loop under the usual filter) because of three
|
|
323
|
+
things worth knowing for any 1.0-sync freeze:
|
|
324
|
+
|
|
325
|
+
- **areaPath is NOT only `crons/toga2/netsuite`.** 1.0 sync NetSuite/api2 errors also log under
|
|
326
|
+
`context.REFERENCE.areaPath` = `library/app/api` and `library/app/api/netsuite` — filtering on the
|
|
327
|
+
cron path alone **misses** them. (The "Filter on areaPath = `crons/toga2/netsuite`" note near the top
|
|
328
|
+
of this doc is therefore an *incomplete* filter — widen it to these two areas as well.)
|
|
329
|
+
- **EV-10 is api2's GENERIC "save failed" wrapper — the real DB error is NOT in base `Logs`.** The
|
|
330
|
+
underlying `1062 Duplicate entry ... for key ...` lives in `Logs_<Client>.Api`: filter
|
|
331
|
+
`responsePayload LIKE '%EV-10%'` (or join by `transactionId`) for route + `requestPayload` + the full
|
|
332
|
+
`responsePayload` carrying the real MySQL error. (Same `Logs_<Client>.Api` chain as the other rejection
|
|
333
|
+
gotchas in this doc.)
|
|
334
|
+
- **Some crashes never record at all.** The worker's error-log write to the logs DB can time out
|
|
335
|
+
(`mysqli_select_db ... errno=110 Connection timed out`, e.g. `Logs.Issue` 588/589), so a section can
|
|
336
|
+
freeze with **no** `Logs.Event`/`Issue` row — read `Client_<X>.Parameters` for the stuck RUNNING
|
|
337
|
+
section as the primary signal, not the log tables.
|
|
338
|
+
- Cross-link: the `send()` "Invalid API Response" exception was also changed 2026-09-11 to **lead with
|
|
339
|
+
the api2 message codes** so this EV-10 self-reveals in `Logs.Event` next time — see
|
|
340
|
+
[App_Api_Toga2](../../library/features/toga2-api-client-and-bridge.md).
|
|
341
|
+
|
|
299
342
|
### ⚠ Per-record isolation is SECTION-SPECIFIC — and SALES_ORDERS has NONE (corrected 2026-08-17)
|
|
300
343
|
|
|
301
344
|
Whether a bad record is "stepped over" or freezes the section depends entirely on whether **that
|
|
@@ -1439,6 +1482,19 @@ library (or vice versa) crashes GroWrk and Adyen on their next sync run.
|
|
|
1439
1482
|
|
|
1440
1483
|
## Change history
|
|
1441
1484
|
|
|
1485
|
+
- 2026-09-11 — **ITEM_RECEIPTS froze at RUNNING on NYCHH: a case-mismatched `Units` serial lookup
|
|
1486
|
+
(library, fix written not deployed).** `syncItemReceiptFromNetsuite` (`library/app/api/toga2.php`
|
|
1487
|
+
~L4022) keyed a PHP existing-`Units` array on the DB's stored serial casing (`'na100'`) but read it
|
|
1488
|
+
with the uppercased serial (`'NA100'`, `strtoupper` ~L3905); PHP array keys are case-sensitive, so the
|
|
1489
|
+
lookup missed the row, took the create path, and hit the case-insensitive `Units.itemId_serialNumber`
|
|
1490
|
+
unique key → MySQL **1062** / api2 **EV-10** → the section threw before its cursor PUT and froze,
|
|
1491
|
+
dragging ITEM_FULFILLMENTS behind it. Fixed by `strtoupper()`-ing **both** the array key and the reads
|
|
1492
|
+
(and the half-fixed second copy ~L6326, which had the key but not its two reads). Proven on
|
|
1493
|
+
`Client_Nychh.Units` 23400-23409 (serial `'na100'..'na109'`). php-reviewer + cso cleared it. Also
|
|
1494
|
+
recorded the three diagnosis traps that hid it: sync errors also log under areaPath `library/app/api`
|
|
1495
|
+
and `library/app/api/netsuite` (not only `crons/toga2/netsuite`); EV-10 is a generic wrapper whose real
|
|
1496
|
+
1062 lives in `Logs_<Client>.Api` (`responsePayload LIKE '%EV-10%'`); and the worker's logs-DB write can
|
|
1497
|
+
time out (errno 110, `Logs.Issue` 588/589) so some crashes never record. (jcardinal)
|
|
1442
1498
|
- 2026-09-09 — **The resume cursor was READ on the wrong clock — a silent +1h window skip dropped
|
|
1443
1499
|
records across ALL 6 sections and ALL clients (worker, deployed + verified).** `startModeIteration`
|
|
1444
1500
|
(`common_sync_togasupply.php` ~L622) parsed the Eastern-stored cursor with `strtotime()` (script tz
|
|
@@ -18,7 +18,7 @@ project: _Underscore
|
|
|
18
18
|
client: nychh
|
|
19
19
|
type: profile
|
|
20
20
|
status: active
|
|
21
|
-
updated: 2026-09-
|
|
21
|
+
updated: 2026-09-11
|
|
22
22
|
owners: ["jcardinal", "apeterson", "bala", "akhokhani"]
|
|
23
23
|
files:
|
|
24
24
|
- dbchanges2/Client_Nychh/2026-09-02a - TransferOrderNetsuitePushInterceptor.sql
|
|
@@ -115,6 +115,16 @@ table views. Client-specific DB change-sets live in `dbchanges2/Client_Nychh/`.
|
|
|
115
115
|
written. Proven on IF `6138135` (Eastern 2025-09-04 17:26:58). Fixes and the standing "cursor is
|
|
116
116
|
always Eastern" rule live in the
|
|
117
117
|
[per-client sync feature doc](../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md).
|
|
118
|
+
- **ITEM_RECEIPTS froze on a case-mismatched serial → duplicate-`Units` EV-10/1062, root-caused + fixed
|
|
119
|
+
(2026-09-11, fix NOT deployed).** The receipts feed threw before its cursor PUT (freezing it and
|
|
120
|
+
ITEM_FULFILLMENTS behind it) because `syncItemReceiptFromNetsuite` keyed its existing-`Units` PHP
|
|
121
|
+
lookup on the DB's stored serial casing (`'na100'`) but read it with the uppercased serial (`'NA100'`);
|
|
122
|
+
the missed row took the create path and collided on the case-insensitive `Units.itemId_serialNumber`
|
|
123
|
+
unique key → MySQL 1062 / api2 EV-10. Proven on `Client_Nychh.Units` 23400-23409
|
|
124
|
+
(serials `'na100'..'na109'`, `c_netsuiteInternalInventoryAssignmentId` NULL). Library-only fix
|
|
125
|
+
(`strtoupper()` on both the key and the reads). This is a **different** duplicate from the open
|
|
126
|
+
sales-order `Items` duplicate below (658-BFZH). Mechanism + the EV-10 → `Logs_Nychh.Api` diagnosis
|
|
127
|
+
traps: [per-client sync doc](../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md).
|
|
118
128
|
- **NYCHH sync scope + data-gap scale + backfill approach (2026-09-09).**
|
|
119
129
|
- **Scope = 22 NetSuite customers:** parent **28908** "NYC Health + Hospitals" + 21 hospital child
|
|
120
130
|
customers (`24145, 29273, 29276, 31584, 31910-31916, 31918-31925, 32229, 33674`).
|
package/package.json
CHANGED