toga-ai 1.0.861 → 1.0.863
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/features/netsuite-togasupply-per-client-sync.md +24 -0
- package/knowledge/INDEX.md +1 -1
- package/knowledge/clients/managelife/INDEX.md +2 -2
- package/knowledge/clients/managelife/profile.md +2 -2
- package/knowledge/clients/nychh/features/netsuite-inventory-adjustment-fulfillment-link.md +15 -2
- package/package.json +1 -1
|
@@ -800,6 +800,11 @@ nested count:
|
|
|
800
800
|
fetch returned `salesOrderItems` truncated (observed cap **25**); an order with >25 lines dropped a
|
|
801
801
|
line the fulfillment referenced, the match failed, and the section fail-loud-froze. The flat list
|
|
802
802
|
replaces the truncated nested one before match/reconstruct.
|
|
803
|
+
- **Existing `ItemFulfillmentItems` for the dedup lookup (added 2026-09-21)** — the create-vs-update
|
|
804
|
+
dedup read the truncated **nested** `itemFulfillmentItems` off a `depth=4` header GET, so it missed
|
|
805
|
+
every line past **25** and **re-created duplicate `ItemFulfillmentItems` every run**. Now paged flat
|
|
806
|
+
(`recordsPerPage=1000`, `$maxPages=500` cap, on `meta->nextPage`). api2's unpaged cap is
|
|
807
|
+
`DEFAULT_RECORDS_PER_PAGE = 25` (`api2/Component/Api/V2/V2.php:27`).
|
|
803
808
|
|
|
804
809
|
### Retiring the stale SalesOrder a reclassified TransferOrder leaves behind (DEPLOYED + RUNNING 2026-09-18)
|
|
805
810
|
|
|
@@ -1197,6 +1202,16 @@ library (or vice versa) crashes GroWrk and Adyen on their next sync run.
|
|
|
1197
1202
|
|
|
1198
1203
|
## Gotchas / known issues
|
|
1199
1204
|
|
|
1205
|
+
- **PLATFORM FACT: NO TOGA client fulfills NetSuite item groups (bundles).** Every client fulfills the
|
|
1206
|
+
**member items individually**. This is the load-bearing safety assumption behind the IA dedup's
|
|
1207
|
+
empty-serials delete branch (see [NYCHH IA→fulfillment link](../../../clients/nychh/features/netsuite-inventory-adjustment-fulfillment-link.md))
|
|
1208
|
+
and any item-group discussion. If a client ever starts fulfilling item groups, revisit every dedup
|
|
1209
|
+
that keys on product/order-line alone.
|
|
1210
|
+
- **⚠ OPEN — the downstream fulfillment→SO match in `syncItemFulfillmentFromNetsuite` still keys by
|
|
1211
|
+
parent order-line uuid ALONE.** The reconcile map build (`toga2.php` ~L6088-6092) and the two match
|
|
1212
|
+
sites (~L6352 / ~L6387) key on parent order-line uuid only. Harmless today (no client fulfills item
|
|
1213
|
+
groups — see the platform fact above), but for any client that ever fulfills item-group bundles this
|
|
1214
|
+
risks item-group churn / a possible wrong-qty overwrite. Not fixed.
|
|
1200
1215
|
- **OPEN, not root-caused (2026-09-08): a duplicate item INSERT aborts the whole NYCHH sales-order
|
|
1201
1216
|
run.** A run created `Client_Nychh.Items` id **5429** (`partNumber` 658-BFZH, `manufacturerId` 26,
|
|
1202
1217
|
`catalogId` 1, `c_netsuiteInternalItemId` 1617692) at 16:22:09 and then tried to insert **the same
|
|
@@ -2047,6 +2062,15 @@ library (or vice versa) crashes GroWrk and Adyen on their next sync run.
|
|
|
2047
2062
|
[NetSuite Sync Alert Monitor](../../library/features/netsuite-sync-alert-monitor.md).
|
|
2048
2063
|
|
|
2049
2064
|
## Change history
|
|
2065
|
+
- 2026-09-21 — **NYCHH INVENTORY_ADJUSTMENTS unfrozen (library, deployed + prod-verified).** Paged the
|
|
2066
|
+
existing-`ItemFulfillmentItems` dedup lookup in `syncItemFulfillmentFromNetsuite` (it read a truncated
|
|
2067
|
+
nested collection off a `depth=4` header GET past the 25-row cap and re-created duplicate
|
|
2068
|
+
`ItemFulfillmentItems` every run). Recorded the platform fact that **no TOGA client fulfills NetSuite
|
|
2069
|
+
item groups**, and the open follow-up that the fulfillment→SO reconcile map still keys on parent
|
|
2070
|
+
order-line uuid alone. The IA→fulfillment attach fixes (equality rule removed, product-only link,
|
|
2071
|
+
no-line skip, `deleteItemFulfillmentDuplicateLines`) live on the
|
|
2072
|
+
[NYCHH IA→fulfillment link doc](../../../clients/nychh/features/netsuite-inventory-adjustment-fulfillment-link.md).
|
|
2073
|
+
INVENTORY_ADJUSTMENTS reached IDLE, cursor draining, `Logs.Issue` 827 cleared. (jcardinal)
|
|
2050
2074
|
- 2026-09-21 — **Two NYCHH sync freezes fixed, deployed (library + worker together) and prod-verified.**
|
|
2051
2075
|
(1) SALES_ORDERS froze (`Logs.Issue` 813) on a stale transfer-order invoice the retirement couldn't
|
|
2052
2076
|
move (`Invoices` has no `transferOrderId`). New `deleteStaleTransferOrderInvoicesForSalesOrder()`
|
package/knowledge/INDEX.md
CHANGED
|
@@ -55,7 +55,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
55
55
|
- **Endeavor Health** (`endeavor-health`) → [clients/endeavor-health/INDEX.md](clients/endeavor-health/INDEX.md)
|
|
56
56
|
- **Fordham University** (`fordham`) → [clients/fordham/INDEX.md](clients/fordham/INDEX.md)
|
|
57
57
|
- **GroWrk** (`growrk`) → [clients/growrk/INDEX.md](clients/growrk/INDEX.md)
|
|
58
|
-
- **
|
|
58
|
+
- **ManageLife** (`managelife`) → [clients/managelife/INDEX.md](clients/managelife/INDEX.md)
|
|
59
59
|
- **Northwell Health** (`northwell`) → [clients/northwell/INDEX.md](clients/northwell/INDEX.md)
|
|
60
60
|
- **New York City Department of Education** (`nycdoe`) → [clients/nycdoe/INDEX.md](clients/nycdoe/INDEX.md)
|
|
61
61
|
- **NYC Health & Hospitals** (`nychh`) → [clients/nychh/INDEX.md](clients/nychh/INDEX.md)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# Client:
|
|
1
|
+
# Client: ManageLife `managelife`
|
|
2
2
|
|
|
3
3
|
| Doc | Framework | Summary |
|
|
4
4
|
|-----|-----------|---------|
|
|
5
|
-
| [
|
|
5
|
+
| [ManageLife](profile.md) | 2.0 | ManageLife 2.0 platform tenant (`Client_Managelife`). |
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
2
|
+
title: "ManageLife"
|
|
3
3
|
framework: "2.0"
|
|
4
4
|
apps:
|
|
5
5
|
- dbchanges2
|
|
@@ -14,7 +14,7 @@ related:
|
|
|
14
14
|
- ../../2.0/apps/_underscore/features/client-user-contactid-required.md
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
ManageLife 2.0 platform tenant (`Client_Managelife`). Stub profile — expand as work touches it.
|
|
18
18
|
|
|
19
19
|
## Summary
|
|
20
20
|
|
|
@@ -59,8 +59,12 @@ Like [NYCHH transfer-order import](./netsuite-transfer-order-import.md), the bri
|
|
|
59
59
|
|
|
60
60
|
Registered in `dbchanges2` this session: records **363/364** + `RecordFields` **2608-2615** + Super User ACL (`Core/2026-09-21a`); old fields **2517/2521** retired (`Core/2026-09-21b`); both bridge tables created all-client + existing 1-to-1 backfilled (`Client/2026-09-21a`); the Base+API four-table ACL chain on 363/364 (`Client/2026-09-21b`); old FK columns dropped, guarded/re-runnable (`Client/2026-09-21c`). The FK declarations were removed from `Model/Client/InventoryAdjustment.php` + `InventoryAdjustmentItem.php`.
|
|
61
61
|
|
|
62
|
-
### Line matching — by PRODUCT
|
|
63
|
-
NetSuite has **no** direct item-fulfillment-item ↔ adjustment-item link. Match by **product**:
|
|
62
|
+
### Line matching — by PRODUCT ONLY (no quantity-equality)
|
|
63
|
+
NetSuite has **no** direct item-fulfillment-item ↔ adjustment-item link. Match by **product**: link every fulfillment line whose product matches an adjustment line's product. Link **product-to-product**, which handles a product that appears on more than one adjustment line.
|
|
64
|
+
|
|
65
|
+
**⚠ The old "quantities must be EQUAL" rule was WRONG and froze the feed on valid data (removed 2026-09-21).** An inventory adjustment corrects stock (recount / damage / shrinkage) **independently** of what shipped, so the adjustment `quantityAdjustBy` need NOT equal the fulfillment quantity. Proven in NetSuite: adj **6868145** adjusts **400** of `GM-394-SE_` while its referenced fulfillment (SO #259330) shipped **350**. The equality check is removed — do NOT reinstate it. The link is by product; quantity is not part of the match.
|
|
66
|
+
|
|
67
|
+
**A product on the adjustment with NO line on the linked fulfillment LOGS and skips that product (2026-09-21) — it does not throw.** Proven legitimate: adj **6966700** lists `SVC-FS-ENROLLWIN-GW_`, a **service** item on the adjustment that is never on the fulfillment (services aren't shipped). There is no fulfillment line to link a service to, so skipping is correct, not dropped data.
|
|
64
68
|
|
|
65
69
|
### Reconcile every run (self-healing, gated delete)
|
|
66
70
|
Each run **reconciles** both bridges: add missing links, and delete only links NetSuite no longer lists — so a cursor reset re-produces correct data. The delete is **gated**: if a bridge row's key reads back **null** (a read/ACL gap), **throw** instead of deleting — never wipe good links on a partial read.
|
|
@@ -82,6 +86,12 @@ Lives in `library/app/api/toga2.php`, called from `syncInventoryAdjustmentFromNe
|
|
|
82
86
|
|
|
83
87
|
**Loud failure (best-effort try/catch removed).** The attach and the surrounding NetSuite→DB sync path **no longer swallow errors**: the error-log-and-swallow `try/catch` blocks were removed so a data-corruption failure surfaces loudly (StarTech/Sentry catches left alone). Same loud-failure policy as the 2026-08-27 removal of the per-order `try/catch` skips across all six sync sections — see [per-client sync](../../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md). **Do not "soften" this back into a swallow** — a bridge/link miss must be visible, not silently dropped.
|
|
84
88
|
|
|
89
|
+
### Unpaged reads truncate at 25 → the attach's reads are all paged (2026-09-21)
|
|
90
|
+
api2 caps an unpaged read at `DEFAULT_RECORDS_PER_PAGE = 25` (`api2/Component/Api/V2/V2.php:27`). All **three** reads in `attachInventoryAdjustmentToItemFulfillment` — the header bridge, the fulfillment-items read, and the line bridge — now **page** on `meta->nextPage` (`recordsPerPage=1000`, `$maxPages=500` cap), so a fulfillment with >25 of anything links completely. Same fix on the existing-items dedup lookup in `syncItemFulfillmentFromNetsuite` — see [per-client sync](../../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md); an unpaged dedup lookup missed rows past 25 and **re-created duplicate `ItemFulfillmentItems` every run**.
|
|
91
|
+
|
|
92
|
+
### `deleteItemFulfillmentDuplicateLines()` — the IA attach cleans a linked fulfillment's duplicate lines BEFORE matching (2026-09-21)
|
|
93
|
+
The IA path does **not** re-run the fulfillment reconcile for an already-imported fulfillment, so that reconcile's self-heal never reaches truncation duplicates left on it. So the attach cleans them itself first. Dedup key = **`(parentOrderLineUuid|productUuid)`** PLUS a serial-assignment-id subset test: a later same-key row is deleted **only** when its `c_netsuiteInternalInventoryAssignmentId` set is **empty or a subset** of the kept row's — this spares NetSuite item-group members and removes only true truncation copies. A **circuit breaker** throws if >50% of lines are flagged; partial reads fail loud. The empty-serials delete branch is safe because [no TOGA client fulfills NetSuite item groups](../../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md) — every client fulfills the member items individually.
|
|
94
|
+
|
|
85
95
|
### On-demand dependency import (fulfillment not yet in TOGA) — now REST
|
|
86
96
|
When the linked fulfillment has **not** been imported into TOGA yet, the attach **imports the fulfillment on demand** via `syncItemFulfillmentFromNetsuite` (which itself cascades to the originating sales order when missing), then **re-resolves and links**. This on-demand import was **converted from SOAP to REST** this session.
|
|
87
97
|
|
|
@@ -129,7 +139,10 @@ A **manual operator tool** in `worker/crons/toga2/netsuite/` (NEW): imports one
|
|
|
129
139
|
- **Empty lookups drop or duplicate items.** The item loop filters to known warehouses and creates items on lookup-miss, so any manual/diagnostic invocation must seed the warehouse/item/manufacturer lookups (the harness does).
|
|
130
140
|
- **A frozen NYCHH `INVENTORY_ADJUSTMENTS` section is NOT necessarily an item-matching / two-catalog problem (verified 2026-09-01).** When the section stuck at `1-RUNNING`, item matching was suspected (wrong of two intentional catalogs). Verified in prod it was fine: item **560** (uuid `4c7b93d2-…`, partNumber **B11B242201**, HYBRID) is the Agilant-catalog item and the **only** item with that part number — no duplicate second-catalog item, `$uuidItem` resolved correctly, and the inventory-adjustment item-create already stamps catalog `Agilant`. The freeze was purely the serial-CASE bug (fix (c) above). **Diagnosis chain (no NetSuite access):** `Client_Nychh.Parameters` (localize the stuck section) → `Logs.Event` `clientId=3` (crash `toga2.php:6080` via `common_sync_togasupply.php:1180` `syncInventoryAdjustmentFromNetsuite`, + `transactionId`) → `Logs_Nychh.Api` on that `transactionId` (untruncated `EV-10`/1062 rejection + payload).
|
|
131
141
|
|
|
142
|
+
- **⚠ OPEN — the IA dedup / self-heal deletes are NOT idempotent against already-gone children.** A half-finished prior run leaves a child already deleted; the retry's `send()` **throws on the 404** and wedges the run. Fix (not yet done): treat not-found as done in the delete path.
|
|
143
|
+
|
|
132
144
|
## Change history
|
|
145
|
+
- 2026-09-21 — Removed the wrong "adjustment qty must EQUAL fulfillment qty" match rule (an adjustment corrects stock independently of what shipped — proven adj 6868145: 400 adjusted vs 350 shipped); the IA→fulfillment line link is now by **PRODUCT only**, and a product with no fulfillment line **logs + skips** (service items, proven adj 6966700). Paged all 3 attach reads + the fulfillment dedup lookup (api2's 25-row unpaged cap was re-creating duplicate `ItemFulfillmentItems`). New `deleteItemFulfillmentDuplicateLines()` cleans a linked fulfillment's truncation duplicates before matching (serial-subset guard spares item-group members). Prod-verified: INVENTORY_ADJUSTMENTS reached IDLE, cursor draining, `Logs.Issue` 827 cleared. (jcardinal)
|
|
133
146
|
- 2026-09-21 — Redesigned to **many-to-many**: `custbody_stock_adjustment` is multi-select (one adjustment → many fulfillments), so two bridge tables (`ItemFulfillments_InventoryAdjustments` rec 363, `ItemFulfillmentItems_InventoryAdjustmentItems` rec 364) replace the single FK columns; attach loops all fulfillments, line-matches by product quantity (fail-loud), reconciles each run with a gated delete. Prod-verified on adj 1320 (17 header + 16/16 line). (jcardinal)
|
|
134
147
|
- 2026-09-03 — Adjustment→fulfillment link moved to its own `IS_ENABLED_INVENTORY_ADJUSTMENT_FULFILLMENT_LINK` flag, independent of transfer-order detection. (jcardinal)
|
|
135
148
|
- 2026-08-29 — Migrated the sync + on-demand import from SOAP to REST. (jcardinal)
|
package/package.json
CHANGED