toga-ai 1.0.920 → 1.0.922
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/workflows/reprocessing-one-netsuite-order.md +16 -2
- package/knowledge/2.0/apps/worker2/features/clickup-webhook-health-monitor.md +3 -1
- package/knowledge/clients/nychh/features/netsuite-inventory-adjustment-fulfillment-link.md +20 -7
- package/knowledge/clients/nychh/profile.md +2 -2
- package/package.json +1 -1
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
| [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 |
|
|
23
23
|
| [Deduplicating NetSuite duplicate Items across client DBs (recursive MERGE)](workflows/netsuite-duplicate-items-dedup.md) | Per-client cleanup collapsing duplicate `Items` rows (same `partNumber`) to one canonical via recursive MERGE; open before running it — and read the catalog-bli |
|
|
24
24
|
| [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; open when onboarding a client, and read the vendor-seed / ACL / Parameters-see |
|
|
25
|
-
| [Re-processing NetSuite orders, fulfillments and
|
|
25
|
+
| [Re-processing NetSuite orders, fulfillments, receipts and inventory adjustments (process_netsuite_*.php)](workflows/reprocessing-one-netsuite-order.md) | Run the real sync for given NetSuite ids on ONE client, without touching cursors: one order (+ its vendor POs), or a list of fulfillments/receipts/inventory adj |
|
|
26
26
|
| [Tracing a 1.0 worker cron run in production (no stdout, silent skips)](workflows/tracing-a-worker-cron-run-in-production.md) | How to answer "did this cron run, and what did it do?" on the 1.0 worker tier (no usable stdout, skipped runs leave no trace); open before concluding a cron "ne |
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Re-processing NetSuite orders, fulfillments and
|
|
2
|
+
title: "Re-processing NetSuite orders, fulfillments, receipts and inventory adjustments (process_netsuite_*.php)"
|
|
3
3
|
framework: "1.0"
|
|
4
4
|
repo: worker
|
|
5
5
|
project: Worker
|
|
@@ -11,6 +11,8 @@ owners: ["jcardinal", "rgirish"]
|
|
|
11
11
|
files:
|
|
12
12
|
- worker/crons/toga2/netsuite/process_netsuite_order.php
|
|
13
13
|
- worker/crons/toga2/netsuite/process_netsuite_records.php
|
|
14
|
+
- worker/crons/toga2/netsuite/process_netsuite_item_fulfillment.php
|
|
15
|
+
- worker/crons/toga2/netsuite/process_netsuite_inventory_adjustment.php
|
|
14
16
|
- worker/crons/toga2/netsuite/common_sync_togasupply.php
|
|
15
17
|
- library/app/api/netsuite/rest.php
|
|
16
18
|
related:
|
|
@@ -18,9 +20,10 @@ related:
|
|
|
18
20
|
- ../../library/features/transfer-order-purchase-order-link-reconcile.md
|
|
19
21
|
- ../../../clients/nychh/features/netsuite-transfer-order-import.md
|
|
20
22
|
- ../../library/features/netsuite-closed-order-rule.md
|
|
23
|
+
- ../../../clients/nychh/features/netsuite-inventory-adjustment-fulfillment-link.md
|
|
21
24
|
---
|
|
22
25
|
|
|
23
|
-
Run the real sync for given NetSuite ids on ONE client, without touching cursors: one order (+ its vendor POs), or a list of fulfillments/receipts. Open to heal, debug, or backfill specific records.
|
|
26
|
+
Run the real sync for given NetSuite ids on ONE client, without touching cursors: one order (+ its vendor POs), or a list of fulfillments/receipts/inventory adjustments. Open to heal, debug, or backfill specific records.
|
|
24
27
|
|
|
25
28
|
## Summary
|
|
26
29
|
- Manual CLI, **not scheduled** — never add to `cron.worker.*.json`.
|
|
@@ -55,10 +58,21 @@ php crons/toga2/netsuite/process_netsuite_records.php <client> --fulfillment=<id
|
|
|
55
58
|
- Scope checks: a fulfillment's source SO customer (or end-user customer) must map to this client; with `IS_ENABLED_ITEM_RECEIPT_OWNED_WAREHOUSE_SCOPE` a receipt needs a line at an owned warehouse (`allowReceiving = 1`). Otherwise it throws "refusing to import it".
|
|
56
59
|
- Used 2026-09-29 to backfill 7 Elite closed-order shipments skipped under the old closed rule.
|
|
57
60
|
|
|
61
|
+
### Fulfillments / inventory adjustments by id (2026-09-30)
|
|
62
|
+
```
|
|
63
|
+
php crons/toga2/netsuite/process_netsuite_item_fulfillment.php <client> --id=<id>[,<id>...]
|
|
64
|
+
php crons/toga2/netsuite/process_netsuite_inventory_adjustment.php <client> --id=<id>[,<id>...]
|
|
65
|
+
```
|
|
66
|
+
- Same guards as above. Id list validated all-digits up front, deduped, run in order; stops at first error with "X of N done before it".
|
|
67
|
+
- Fulfillment: real `syncItemFulfillmentFromNetsuite`; scope via source SO customer / end-user customer (the `fetchItemFulfillmentById` shim carries no entity); sales-order fulfillments only — throws on a `TrnfrOrd` source.
|
|
68
|
+
- Inventory adjustment: real `syncInventoryAdjustmentFromNetsuite` (incl. IF link bridges when the wrapper sets `IS_ENABLED_INVENTORY_ADJUSTMENT_FULFILLMENT_LINK` — hh does); scope = any line on this client's warehouse; imports for the named client only (the scheduled sync imports for every client with a line).
|
|
69
|
+
- `process_netsuite_item_fulfillment.php` overlaps `process_netsuite_records.php --fulfillment` (built in parallel).
|
|
70
|
+
|
|
58
71
|
## Gotchas
|
|
59
72
|
- A TO skipped by the sync (out-of-scope customer) prints `NOT imported` — read the error log, not a script bug.
|
|
60
73
|
- Needs `IS_ENABLED_INTEGRATION_TRANSFER_ORDERS` true in the wrapper for TO routing; otherwise the order syncs as a sales order.
|
|
61
74
|
|
|
62
75
|
## Change history
|
|
76
|
+
- 2026-09-30 — Added `process_netsuite_item_fulfillment.php` + `process_netsuite_inventory_adjustment.php`. (jcardinal)
|
|
63
77
|
- 2026-09-30 — Added `process_netsuite_records.php` (fulfillments/receipts by id); Closed routing follows the closed-order rule (v3: line-level). (rgirish)
|
|
64
78
|
- 2026-09-24 — Created; prod-verified on NYCHH TO 11. (jcardinal)
|
|
@@ -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-30
|
|
10
10
|
owners: [jcardinal]
|
|
11
11
|
files:
|
|
12
12
|
- worker2/Worker/Monitor/Clickup.php
|
|
@@ -35,6 +35,7 @@ Distinct from the sibling email watchdog [`_Worker_Clickup_Health`](./clickup-co
|
|
|
35
35
|
- `HIGH` (full failure / Offline) — **blind read**: the ClickUp call threw, OR a monitored `togahub.com` webhook has no readable `health.status`. "We don't know the status."
|
|
36
36
|
- `DEGRADED` — a monitored `togahub.com` webhook has `health.status = "suspended"`, OR no `togahub.com` subscription exists at all. A known outage we can see.
|
|
37
37
|
- `OK` — every monitored webhook is readable and not suspended (so `active`, `failing`, any other readable status → OK).
|
|
38
|
+
- **Coverage check** (`evaluateCoverage()`, added 2026-09-25) also → `DEGRADED`: a watched space/event has no covering webhook, a duplicate covering webhook, or a covering webhook with `health.status = "suspended"` (`self::SUSPENDED_STATUS`). `failing` is OK here too (ClickUp is still retrying). Unreadable status is not flagged by coverage — the main loop already makes it `HIGH`.
|
|
38
39
|
- Precedence: `HIGH` > `DEGRADED` > `OK`. `probe` is `OK` on any successful read (even when `alarm=HIGH` from a blind webhook) and `DEGRADED` only when the ClickUp read itself failed.
|
|
39
40
|
- **OneUptime criteria must match the tokens** (config lives outside the repo): Request Body Contains `"alarm":"HIGH"` → Offline + incident; Contains `"alarm":"DEGRADED"` → Degraded; received in 1 min AND Contains `"alarm":"OK"` → Online (OK-gated recovery).
|
|
40
41
|
- **Push URL is an in-file `$ONEUPTIME_URL` local, not `[oneuptime]` config** — the established team convention for every `Worker/Monitor/*` file (Operations, Staples, Compass, Aig, Prudential, Nycdoe, Fleet). A cso review suggested reading it from config; the developer rejected that on purpose — the heartbeat URL is treated as low-sensitivity and stays inline, matching the siblings. See the credential note in [OneUptime push-metric monitors](./oneuptime-worker2-monitoring.md). The `$push` guard still soft-fails on a blank URL so the job can deploy inert.
|
|
@@ -47,6 +48,7 @@ Distinct from the sibling email watchdog [`_Worker_Clickup_Health`](./clickup-co
|
|
|
47
48
|
- Keep the metric POST non-fatal — a monitoring outage must never break the worker job.
|
|
48
49
|
|
|
49
50
|
## Change history
|
|
51
|
+
- 2026-09-30 — Coverage check flagged any covering webhook with status ≠ `active` as degraded, so `failing` (fail_count 1) made the monitor Degraded. Now flags only `suspended`; const `HEALTHY_STATUS` → `SUSPENDED_STATUS`, `CheckWebhook()` uses `self::SUSPENDED_STATUS` (duplicate local removed). `Worker/Clickup/Project.php` (EnsureWebhooks) only reads `degradedHealth` for a message — unaffected. Not yet committed/deployed at capture. (jcardinal)
|
|
50
52
|
- 2026-09-22 — Reworked the alarm rule from "any status ≠ active → DEGRADED" to three levels: `HIGH` on a blind read (ClickUp call failed, or a webhook has no readable `health.status`), `DEGRADED` on `"suspended"` or no `togahub.com` subscription, `OK` for everything else (`active`/`failing`/other). Original was too sensitive. Also hardened: blind-path OneUptime push wrapped in try/catch (non-fatal), `health` guarded against a non-object, stale "Left BLANK" URL comment removed (URL is live). Payload fields changed: `activeCount` → `okCount`, added `suspendedCount`/`blindCount`. OneUptime monitor criteria must be set to match `"alarm":"HIGH"` and `"alarm":"DEGRADED"`. (jcardinal)
|
|
51
53
|
- 2026-09-21 — Created `_Worker_Monitor_Clickup::CheckWebhook` (OneUptime, `*/10`, stricter than the email watchdog). Recreated the inbound webhook under the service account (`pk_87469444`, new id `bd6168ab-…`, deleting the old OAuth-owned one) so both this monitor and `_Worker_Clickup_Health` can see it — the two were previously blind to it (token-ownership gotcha above). (jcardinal)
|
|
52
54
|
|
|
@@ -6,7 +6,7 @@ project: Library
|
|
|
6
6
|
client: nychh
|
|
7
7
|
type: client-feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-09-
|
|
9
|
+
updated: 2026-09-30
|
|
10
10
|
owners: [jcardinal, rgirish]
|
|
11
11
|
files:
|
|
12
12
|
- library/app/api/toga2.php
|
|
@@ -14,9 +14,11 @@ files:
|
|
|
14
14
|
- _underscore/Model/Client/ItemFulfillments/InventoryAdjustment.php
|
|
15
15
|
- _underscore/Model/Client/ItemFulfillmentItems/InventoryAdjustmentItem.php
|
|
16
16
|
- worker/crons/toga2/netsuite/sync_togasupply_hh.php
|
|
17
|
-
- worker/crons/toga2/netsuite/
|
|
17
|
+
- worker/crons/toga2/netsuite/process_netsuite_inventory_adjustment.php
|
|
18
18
|
- worker/crons/toga2/netsuite/diagnose_hh_import_inventory_adjustment.php
|
|
19
|
+
- test/@jeff/netsuite/test_pair_inventory_adjustment_lines.php
|
|
19
20
|
related:
|
|
21
|
+
- ../../../1.0/apps/worker/workflows/reprocessing-one-netsuite-order.md
|
|
20
22
|
- ./netsuite-transfer-order-import.md
|
|
21
23
|
- ./transfer-order-inventory-quantities.md
|
|
22
24
|
- ../../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md
|
|
@@ -59,8 +61,16 @@ Like [NYCHH transfer-order import](./netsuite-transfer-order-import.md), the bri
|
|
|
59
61
|
|
|
60
62
|
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
63
|
|
|
62
|
-
### Line matching — by
|
|
63
|
-
NetSuite has **no** direct item-fulfillment-item ↔ adjustment-item link.
|
|
64
|
+
### Line matching — per product, 1:1 by exact qty where both sides have many (2026-09-30)
|
|
65
|
+
NetSuite has **no** direct item-fulfillment-item ↔ adjustment-item link. Pairing lives in the pure function `App_Api_Toga2::pairInventoryAdjustmentLinesToFulfillmentLines(array $adjustmentLines, array $fulfillmentLines): array`. Per product:
|
|
66
|
+
1. **1 line on either side → link to all** lines on the other side.
|
|
67
|
+
2. **Both >1 → exact `|qty|` 1:1 pass** (tolerance `INVENTORY_ADJUSTMENT_PAIRING_QUANTITY_TOLERANCE` 0.0001). Order: IA lines by NetSuite `lineNumber`; IF lines by NetSuite IF internal id, then SO/TO item `lineNumber`; uuid last. **Never order by TOGa ids** — dedup/re-import recreates IF lines → link churn.
|
|
68
|
+
3. **Leftovers:** one side has 1 left → link it to all (not flagged). Both >1 left, or leftovers on one side only → link leftovers across, return in `ambiguousProductUuids` + `error_log`. **Never throw on pairing doubt, never drop a link** — old data (IA 676 BCPU 1000/500/500 vs 48/3222) must not freeze the section.
|
|
69
|
+
|
|
70
|
+
Returns pairs + `unlinkableProductUuids` (no IF line, e.g. service items) + `ambiguousProductUuids`. Regression tests: `test/@jeff/netsuite/test_pair_inventory_adjustment_lines.php` (11 cases, 1312/1318/1324/676 shapes; pure, run with local `php`).
|
|
71
|
+
|
|
72
|
+
- **Do NOT add a qty-SUM pass** — rejected by CTO: it can pick the wrong lines and still hit the total = a confident wrong link.
|
|
73
|
+
- **No unique index can enforce this.** Both bridges already have a UNIQUE on the pair (`ItemFulfillmentItems_InventoryAdjustmentItems_UNIQUE_1`, `ItemFulfillments_InventoryAdjustments_UNIQUE_1`). 1-to-many is real (IA 1324: 1×432 vs 9×48; 1788: 40 = 8+5+5+6+16; 1291: 140 = 100+40) and many-to-1 is real (676: 3×200 vs 1×930). Protection is in code only.
|
|
64
74
|
|
|
65
75
|
**⚠ 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
76
|
|
|
@@ -78,7 +88,7 @@ Lives in `library/app/api/toga2.php`, called from `syncInventoryAdjustmentFromNe
|
|
|
78
88
|
2. **loops every fulfillment**, importing each on demand when missing,
|
|
79
89
|
3. resolves each by `ItemFulfillments.c_netsuiteInternalItemFulfillmentId`,
|
|
80
90
|
4. builds + reconciles the **header** bridge (`ItemFulfillments_InventoryAdjustments`), then
|
|
81
|
-
5. builds + reconciles the **line** bridge (`ItemFulfillmentItems_InventoryAdjustmentItems`)
|
|
91
|
+
5. builds + reconciles the **line** bridge (`ItemFulfillmentItems_InventoryAdjustmentItems`) with the pairing above. Lines come from `fetchInventoryAdjustmentLinesForPairing` + `fetchFulfillmentLinesForPairing` (flat, paged 1000; both **throw if rows read != `meta->totalRecordCount`** via `requireTotalRecordCount` — a short IF read would make the reconcile DELETE valid links). `countSyncedInventoryAdjustmentLines` throws if TOGa IA-line count != NetSuite in-scope lines (warehouse in lookup, non-null `adjustQtyBy`). IA lines are no longer read from the nested write response.
|
|
82
92
|
|
|
83
93
|
**Reading the product uuid needs `depth=3` (max-depth omission trap).** Step 4's product match reads `salesOrderItem->item->uuid` from `GET /item-fulfillment-items`. The V2 read engine **omits a non-null FK object that sits at the max requested `depth`** — and a null sibling FK still renders, so the omission is easy to miss. At `depth=2` the grandchild `item` (level 3: `itemFulfillmentItem → salesOrderItem → item`) was dropped → the product-match map was empty → **no `itemFulfillmentItemId` was written**. Fix: request **`depth=3`** *plus* explicit nested fields `salesOrderItem.item.uuid` / `transferOrderItem.item.uuid`. Framework detail: [V2 REST query contract — max-depth FK omission](../../../2.0/apps/api2/features/v2-rest-query-contract.md).
|
|
84
94
|
|
|
@@ -117,8 +127,8 @@ php crons/toga2/netsuite/diagnose_hh_import_inventory_adjustment.php <togaClient
|
|
|
117
127
|
```
|
|
118
128
|
(creds = the `CLIENT_CONFIGURATION` client/api/secret from `sync_togasupply_hh.php`.)
|
|
119
129
|
|
|
120
|
-
###
|
|
121
|
-
|
|
130
|
+
### Re-import one adjustment
|
|
131
|
+
`process_netsuite_inventory_adjustment.php hh --id=<NS id>[,…]` — see [re-processing workflow](../../../1.0/apps/worker/workflows/reprocessing-one-netsuite-order.md).
|
|
122
132
|
|
|
123
133
|
### Go-live toggle
|
|
124
134
|
`IS_ENABLED_INTEGRATION_INVENTORY_ADJUSTMENTS` in `sync_togasupply_hh.php` is the go-live switch for this feature on the scheduled cron.
|
|
@@ -130,6 +140,8 @@ A **manual operator tool** in `worker/crons/toga2/netsuite/` (NEW): imports one
|
|
|
130
140
|
|
|
131
141
|
## Gotchas / known issues
|
|
132
142
|
|
|
143
|
+
- **Old code cross-producted lines (fixed 2026-09-30, NOT deployed).** Every IA line of a product linked to every IF line of it: IA #1312 (NS 5211365, TOGa id 387) had 108 line-bridge rows vs 23 correct (210-BKVQ 9×9 = 81 vs 9). Prod: 615 rows over 8 IAs; only 1312 + 1318 wrong. Self-heals via reconcile on re-import (1312 108→23, 1318 4→2) — no SQL. After worker deploy: `php crons/toga2/netsuite/process_netsuite_inventory_adjustment.php hh --id=5211365,5211772`.
|
|
144
|
+
|
|
133
145
|
- **`custbody_stock_adjustment` is a MULTI-SELECT — one adjustment links MANY fulfillments.** The old code used `custbody_stock_adjustment[0]` and captured only the **first**: on adj **1320** (NS id 5218734) that linked **1 of 17** header + **1 of 16** lines. Always read every id from the scalar and loop.
|
|
134
146
|
- **Older adjustments have no link.** `custbody_stock_adjustment` was added in NetSuite <1 year ago; adjustments predating it will never populate a link — not a bug.
|
|
135
147
|
- **A missing bridge link on a NYCHH adjustment is usually CORRECT, not a bug.** Only records whose NetSuite multi-select body field `custbody_stock_adjustment` is populated get a link — and **0 of 27** NYCHH adjustments carry a value there (only **~1 in 40** recent adjustments account-wide do). So a null header/line FK almost always means NetSuite has **no** stock-adjustment link on that record, not a code fault. The REST shim's read of `custbody_stock_adjustment` as a **scalar SuiteQL column on `transaction`** works when the field IS populated (SuiteQL omits null columns from a row, so an empty field just looks "absent"); the shim only builds the link ref when a value exists. (A clarifying comment was added at the `customFieldList` build in `rest.php` `fetchInventoryAdjustmentById`.)
|
|
@@ -142,6 +154,7 @@ A **manual operator tool** in `worker/crons/toga2/netsuite/` (NEW): imports one
|
|
|
142
154
|
- **⚠ 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
155
|
|
|
144
156
|
## Change history
|
|
157
|
+
- 2026-09-30 — Line pairing: per product, exact-qty 1:1 when both sides have many (was full cross-product); paged reads with totalRecordCount guard; synced-IA-line count guard. Verify harness deleted → `process_netsuite_inventory_adjustment.php`. CTO AGREE, php-reviewer CLEAN; NOT deployed. (jcardinal)
|
|
145
158
|
- 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)
|
|
146
159
|
- 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)
|
|
147
160
|
- 2026-09-03 — Adjustment→fulfillment link moved to its own `IS_ENABLED_INVENTORY_ADJUSTMENT_FULFILLMENT_LINK` flag, independent of transfer-order detection. (jcardinal)
|
|
@@ -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-30
|
|
22
22
|
owners: ["jcardinal", "apeterson", "bala", "akhokhani"]
|
|
23
23
|
files:
|
|
24
24
|
- dbchanges2/Client_Nychh/2026-09-02a - TransferOrderNetsuitePushInterceptor.sql
|
|
@@ -108,7 +108,7 @@ TOGA 2.0 client on `_underscore`, prod schema `Client_Nychh`. Supply-chain / ful
|
|
|
108
108
|
- 🚨 **OPEN BLOCKER — every NYCHH PO line reports availability 0, in sandbox AND production (verified 2026-09-01).** The deployed `_Model_Nychh_PurchaseOrderItem` sources stock-in from inventory adjustments and `INNER JOIN`s `InventoryAdjustmentItems.itemFulfillmentItemId`, which is **NULL on 100% of rows** (292/292 sandbox, 317/317 prod). So `_qtyReceived` / `_qtyOnHand` / `_qtyAvailable` are all `0.00` for every purchase-order line, and the **Create Transfer Order item picker has nothing to show**. Needs an **integration / data-owner decision** — backfill the FK, or change the override's stock-in source (base PO item receipts return real numbers today). Not a frontend or ACL defect, and **not** fixed by `Client/2026-09-01a`. See [transfer-order inventory & quantities](./features/transfer-order-inventory-quantities.md).
|
|
109
109
|
- 🚨 **`_Model_Nychh_PurchaseOrderItem` is NOT on every `_underscore` branch (verified 2026-09-01).** `Model/Nychh/PurchaseOrderItem.php` exists on **`_production`** and **`_sandbox-client`** but is **absent from `_beta`** and **`_sandbox-dev`**. Because `_underscore` is pulled at deploy by branch, NYCHH PO-line `_qty*` values are **different numbers per tier**: prod/sandbox-client run the inventory-adjustment formula (0.00 until the NetSuite link is backfilled), beta/sandbox-dev fall back to the base item-receipt formula and report real quantities. **Never eliminate a tenant override by `ls`-ing your working tree** — use `git ls-tree -r --name-only origin/<branch>`. That mistake cost a full session chasing a non-existent "API returns 0" bug. See [transfer-order inventory & quantities](./features/transfer-order-inventory-quantities.md).
|
|
110
110
|
- **Create Transfer Order modal is scoped by PURCHASE ORDER, not by location (2026-09-01).** Source Location is the one active `allowSending = 1` location, read-only from open; all lines on a transfer must share one PO. `Locations.allowReceiving` is **unmaintained** for this tenant (1 of 31 active locations, and it is the source warehouse), so the target dropdown lists all active locations minus the source. The populated contact join is **`Contacts_Locations`** (record 76), not `Locations_Contacts`; contacts were sparse until 2026-09-09, when 12 test rows were replaced by **19 real delivery contacts** (18 location links). See [Transfer Orders page](../../2.0/apps/toga25-supply/features/transfer-orders-page.md) and [location shipping addresses + delivery contacts](./features/location-shipping-addresses.md).
|
|
111
|
-
- **Inventory-adjustment → item-fulfillment linking** — imports NetSuite `custbody_stock_adjustment` (adjustment→fulfillment) into two all-client bridges for adjustment→fulfillment→SO→PO traceability; gated NYCHH-only, best-effort, with on-demand fulfillment import. Go-live toggle (`IS_ENABLED_INTEGRATION_INVENTORY_ADJUSTMENTS`) still off. See [inventory-adjustment → item-fulfillment linking](./features/netsuite-inventory-adjustment-fulfillment-link.md).
|
|
111
|
+
- **Inventory-adjustment → item-fulfillment linking** — imports NetSuite `custbody_stock_adjustment` (adjustment→fulfillment) into two all-client bridges for adjustment→fulfillment→SO→PO traceability; gated NYCHH-only, best-effort, with on-demand fulfillment import. Go-live toggle (`IS_ENABLED_INTEGRATION_INVENTORY_ADJUSTMENTS`) still off. Line bridge cross-product (IA 1312/1318) fixed 2026-09-30, NOT deployed — re-import both after worker deploy. See [inventory-adjustment → item-fulfillment linking](./features/netsuite-inventory-adjustment-fulfillment-link.md).
|
|
112
112
|
- **PO links are UPSTREAM (`PurchaseOrders_SalesOrders`), not downstream.** The downstream `sales-order-purchase-orders` route returns an empty array for NYCHH by design, and the shared `_purchaseOrders` field (downstream-only) resolves to `null` for this tenant — open gap. See [PO Number direction](./features/po-number-upstream-direction.md).
|
|
113
113
|
|
|
114
114
|
## Notes
|
package/package.json
CHANGED