toga-ai 1.0.1102 → 1.0.1104
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/library/features/netsuite-suiteql-rest-shim.md +3 -1
- package/knowledge/clients/elite/INDEX.md +1 -1
- package/knowledge/clients/elite/features/supply-csv-export.md +25 -8
- package/knowledge/clients/elite/features/supply2-tableview-config-drift.md +8 -3
- package/knowledge/standalone/apps/claude/workflows/clickup-ticket-workflow.md +16 -2
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ project: Library
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-21
|
|
10
10
|
owners: [dfranks, jcardinal, kyalamarthi, rgirish, bala]
|
|
11
11
|
files:
|
|
12
12
|
- library/app/api/netsuite/rest.php
|
|
@@ -68,6 +68,7 @@ Field semantics (verified on the live account):
|
|
|
68
68
|
- **SO originating line** lives in `previoustransactionlinelink` (correlated subquery on `previoustype='SalesOrd'`), because `transactionline` has **no `orderline` column**.
|
|
69
69
|
- **TO_DATE rejects impossible dates** (e.g. `2026-06-31`) with an opaque HTTP 400 — validate calendar dates before building SuiteQL.
|
|
70
70
|
- **⚠ SuiteQL returns date/datetime columns in the account DISPLAY format (here `M/D/YYYY`, date-only) unless you wrap them in `TO_CHAR` — losing the time is silent (2026-09-02).** A bare `SELECT lastmodifieddate` came back `9/2/2026` (no time, locale-dependent order), while `TO_CHAR(lastmodifieddate,'YYYY-MM-DD HH24:MI:SS')` gave `2026-09-02 17:39:21`. Any shim that **stores or compares a NetSuite date STRING** must `TO_CHAR(col,'YYYY-MM-DD HH24:MI:SS')` it, or it drops the time and inherits the account's locale format. This defeated the per-client sync's per-record resume cursor: it stored `9/2/2026|<id>`, sat at midnight, and re-scanned the whole day every run — fixed by `TO_CHAR`-ing `lastmodifieddate AS lastmodifieddate` in the 8 cursor-feeding SELECTs (`listSalesOrders`, `fetchSalesOrderByIdFull`, `listSales`, `listPurchaseOrders`, `fetchPurchaseOrderById`, `listItemReceipts`, `listItemFulfillments`, `listInventoryAdjustments`). `WHERE`/`ORDER BY` are unaffected by the alias — bound via `TO_TIMESTAMP` — so they still use the base column. **Still latent:** `listOpportunities` and `listItems` return raw date-only `lastmodifieddate` into their shims; harmless only because neither feeds a resume cursor yet. Engine-side detail on the [per-client-sync doc](../../worker/features/netsuite-togasupply-per-client-sync.md).
|
|
71
|
+
- **⚠ A list-type custom field shimmed with `nameCol => null` stores the list ID ("2"), not the name — `shimInventoryAssignment` did this for serials (fixed 2026-10-21, TRUE-82674).** `custitemnumber_charging_brick` / `_charging_cable` / `_device_status` / `_grade` were defined with `nameCol` null, so the shim emitted the plain internal id and Units `c_chargingBrick` / `c_chargingCable` / `c_deviceStatus` / `c_grade` saved "2" instead of "NO". **Fix:** `BUILTIN.DF(...) AS <field>_df` added to all 3 `inventoryassignment` SuiteQL queries (inventory adjustment, item fulfillment, item receipt) and set as `nameCol`. **Rule: any list/select custom field needs a `BUILTIN.DF` column in the SELECT and a `nameCol`; plain text/date fields keep `nameCol => null`.** Lists: `customlist462` YES=1 NO=2 N/A=4 Unknown=5 (brick + cable), `customlist_device_status`, `customlist_grade` A=1..D=4 F=5. Elite's 113 bad units fixed by `dbchanges2/Client_Elite/2026-10-21b - UnitListIdsToNames.sql` ([Elite export](../../../clients/elite/features/supply-csv-export.md)). **Open:** other NetSuite clients' Units may hold the same ids — not checked. All TOGa Supply clients use **one** NetSuite account (`[netsuite]` config), so every `custitemnumber_*` field exists for every client.
|
|
71
72
|
- **The line SuiteQL must SELECT the line location or it is always NULL — the shim reads it but didn't select it.** `listSalesOrders()`'s line query now selects `tl.location` and `BUILTIN.DF(tl.location) AS location_name`. The line-shim assembly code already *read* those two fields, but the SELECT never included them, so every line's location came back null — which broke NYCHH transfer-order origin resolution (`TransferOrders.originLocationId` is NOT NULL → V2 `EV-10`). Same class of bug as ShipItem cost above. (Added 2026-08-27.)
|
|
72
73
|
- **Custom body fields ride in `customFieldList` on the per-id REST GET.** `fetchSalesOrderById()` now carries `custbody_stocking_order` (NetSuite internal id 7097) via `customFieldList` so the importer can route NYCHH orders (checked = stocking/in → SalesOrders, unchecked = transfer/out → TransferOrders). A custom field absent from the record reads as null downstream. See [NYCHH NetSuite → TransferOrders import](../../../clients/nychh/features/netsuite-transfer-order-import.md).
|
|
73
74
|
- **⚠ `scriptId` in a `customFieldList` def is CASE-SENSITIVE on lookup — a case skew silently returns the default (2026-08-29).** `custbody_stocking_order` was **tagged** in the shim with the uppercase scriptId `CUSTBODY_STOCKING_ORDER` but **read** by the importer as lowercase `custbody_stocking_order`, so the lookup never matched and always fell back to the default (unchecked) — which mis-routed **every** NYCHH order to a Transfer Order. Fixed by lowercasing the scriptId in **both** `buildSalesOrderShims()` and `fetchSalesOrderById()` defs; `END_CUSTOMER` is intentionally left uppercase because it is resolved by internalId `3149`, not by scriptId. Nothing errors on a case skew — the field just reads as its default — so verify the exact scriptId string on both the write and read side. See [NYCHH TransferOrders import](../../../clients/nychh/features/netsuite-transfer-order-import.md).
|
|
@@ -98,6 +99,7 @@ Field semantics (verified on the live account):
|
|
|
98
99
|
- **`App_NetSuite::getCustomFieldValue()` (`library/app/netsuite.php`) must be warning-safe.** 1.0 runs on PHP 7.2 in an unguarded path, so any PHP warning → `exit()` (kills the cron). It was hardened 2026-08-27 with `?? []` / `?? null` guards on the custom-field-list traversal. Keep that discipline when touching it.
|
|
99
100
|
|
|
100
101
|
## Change history
|
|
102
|
+
- 2026-10-21 — `shimInventoryAssignment`: list fields (charging brick/cable, device status, grade) now carry `BUILTIN.DF` names in the 3 `inventoryassignment` queries; they stored list ids before. TRUE-82674 (rgirish)
|
|
101
103
|
- 2026-10-09 — `fetchItemFulfillmentById` now exposes `shipMethod` (internalId + name), because `transaction.shipcarrier` is the useless literal `FedEx/USPS/More` on every row and `shipitem` has no carrier column. It feeds the 1.0 carrier resolver. (bala)
|
|
102
104
|
- 2026-09-21 — `listSales()` gained a `$recordTypes` allowlist param (defaults to all 4 for the forecast import); callers pass `RECORD_TYPE_*` constants, not raw SuiteQL codes; throws on unknown/empty. Lets the togasupply sync request INVOICES only. (jcardinal)
|
|
103
105
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| [Elite — NetSuite → TOGa Supply inbound sync (TRUE-80499 onboarding)](features/netsuite-togasupply-sync.md) | 1.0 | Elite is the 18th client on the shared NetSuite → TOGa Supply importer ([engine](../../../1.0/apps/worker/features/netsuite-togasupply-per-client-sync.md)). |
|
|
7
7
|
| [Elite SalesOrder → NetSuite Push (postPost/postPut interceptors → worker2)](features/salesorder-netsuite-push.md) | 2.0 | Elite's event-driven SalesOrder → NetSuite push (postPost/postPut interceptors → worker2); open for the push trigger, interceptor registration, or the 2026-08-2 |
|
|
8
8
|
| [Elite — Sales Order stage change posts a reply on the TOGa Desk (1.0) ticket](features/salesorder-status-togadesk-reply.md) | 2.0 | How an Elite sales-order stage change posts a reply back onto the originating TOGa Desk (1.0) ticket; open for the cross-DB join path or the dedup key. |
|
|
9
|
-
| [Elite: Service Requests + Inventory CSV export (TOGa 2.5 Supply)](features/supply-csv-export.md) | 2.0 | Elite-only Export buttons on the toga25-supply Service Requests and Inventory pages: what each exports and
|
|
9
|
+
| [Elite: Service Requests + Inventory CSV export (TOGa 2.5 Supply)](features/supply-csv-export.md) | 2.0 | Elite-only Export buttons on the toga25-supply Service Requests and Inventory pages: what each exports, the Units column order, and which CSV columns are not in |
|
|
10
10
|
| [Elite — supply2 frontend scope (Inventory + Service Requests, both built)](features/supply2-scope.md) | 2.0 | Elite's toga2-supply frontend (host `ELITE`): the Inventory + Service Requests pages, how each is host-scoped, and the shared-component fixes made along the way |
|
|
11
11
|
| [Elite — Supply TableView config (stale joins, Inventory row filters, Serial Number search)](features/supply2-tableview-config-drift.md) | 2.0 | Elite's `Client_Elite` TOGa Supply table views: dead-id join drift, which view Inventory reads, its row filters, and column search; open before any Elite TableV |
|
|
12
12
|
| [Elite — raising a Service Request from a TOGa Desk ticket (App_Api_ServiceRequest)](features/togadesk-service-request-intake.md) | 1.0 | How an Elite agent raises a Service Request from a TOGa Desk (1.0) ticket (the SR chain's front door, logic in `App_Api_ServiceRequest`); open for the button ga |
|
|
@@ -6,34 +6,51 @@ project: TOGa 2.5 Supply
|
|
|
6
6
|
client: elite
|
|
7
7
|
type: client-feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-21
|
|
10
10
|
owners: ["rgirish"]
|
|
11
11
|
files:
|
|
12
12
|
- toga25-supply/src/pages/ServiceRequests/ServiceRequests.tsx
|
|
13
13
|
- toga25-supply/src/pages/Inventory/Inventory.tsx
|
|
14
14
|
- toga25-supply/src/pages/Inventory/viewModel/useInventoryPageViewModel.tsx
|
|
15
|
+
- dbchanges2/Client_Elite/2026-10-21a - InventoryUnitsCsvColumns.sql
|
|
16
|
+
- dbchanges2/Client_Elite/2026-10-21b - UnitListIdsToNames.sql
|
|
15
17
|
related:
|
|
16
18
|
- ../profile.md
|
|
19
|
+
- ./supply2-tableview-config-drift.md
|
|
17
20
|
- ../../../2.0/apps/toga25-supply/features/tableview-csv-export.md
|
|
21
|
+
- ../../../1.0/apps/library/features/netsuite-suiteql-rest-shim.md
|
|
18
22
|
- ../../../2.0/apps/toga25-supply/features/record-modals-and-nested-tables.md
|
|
19
23
|
- ../../prudential/features/supply-orders-csv-export.md
|
|
20
24
|
- ../../../2.0/apps/toga25-supply/architecture.md
|
|
21
25
|
---
|
|
22
|
-
Elite-only Export buttons on the toga25-supply Service Requests and Inventory pages: what each exports and
|
|
26
|
+
Elite-only Export buttons on the toga25-supply Service Requests and Inventory pages: what each exports, the Units column order, and which CSV columns are not in the DB; open before changing either button or the Units view.
|
|
23
27
|
|
|
24
28
|
## Summary
|
|
25
|
-
Elite gets an **Export** button on *Service Requests* and *Inventory* (TRUE-82674
|
|
29
|
+
Elite gets an **Export** button on *Service Requests* and *Inventory* (TRUE-82674). Both use the shared [TableView CSV export](../../../2.0/apps/toga25-supply/features/tableview-csv-export.md). Prod sizes 2026-10-21: `Client_Elite` Units 746, ServiceRequests 3.
|
|
26
30
|
|
|
27
31
|
## How it works
|
|
28
|
-
- **Service Requests** exports the `service-requests` TableView exactly as shown, all pages: the page's display meta, URL searchParams, and the active filter-button `additionalData` (
|
|
29
|
-
- **Inventory** exports
|
|
30
|
-
- **
|
|
32
|
+
- **Service Requests** exports the `service-requests` TableView exactly as shown, all pages: the page's display meta, URL searchParams, and the active filter-button `additionalData` (returned by `useSalesOrdersViewModel`).
|
|
33
|
+
- **Inventory** always exports the **`units` grouping** (deepest level), whatever grouping is on screen; falls back to the active grouping's deepest level if no `units` grouping exists. For Elite that is `inventory_units` (`Client_Elite.TableViews` id 21) via SurfaceOverride element 120 — not the Core default `units-for-items-for-purchase-orders` (id 17). Always check the client override, not Core ([config doc](./supply2-tableview-config-drift.md)). Meta is fetched on click.
|
|
34
|
+
- **Columns = the view's visible fields in meta order.** So the CSV layout is set in `TableViewFields`, not in code. `2026-10-21a` orders `inventory_units` to follow Elite's serial CSV: Part # (= CSV Item), Unit Description (`c_itemDescription`), Serial, Asset Tag, Unit Condition, Grade, Charging Brick, Charging Cable, Last Modified Date (`c_lastModified`), Device Status, then the rest.
|
|
35
|
+
- **Gate:** `clientSlug === "ELITE"` in the page, marked `TODO(surface)`. Same interim pattern as the [Prudential export](../../prudential/features/supply-orders-csv-export.md).
|
|
31
36
|
|
|
32
37
|
## Decisions
|
|
33
|
-
- **Inventory export ignores on-screen filters and sort (all units).** Root filters are keyed `inventory_items_*` and never reach the units query. Every expanded nested units table writes sort/filter under the shared `inventory_units` slug, so passing URL params would silently narrow the whole export.
|
|
38
|
+
- **Inventory export ignores on-screen filters and sort (all units).** Root filters are keyed `inventory_items_*` and never reach the units query. Every expanded nested units table writes sort/filter under the shared `inventory_units` slug, so passing URL params would silently narrow the whole export.
|
|
39
|
+
- **Always the `units` grouping** (CodeRabbit, PR #69): the file must have the same columns whatever grouping the user is on.
|
|
40
|
+
- **No new Units columns (2026-10-21, rgirish).** Export only data already in the DB. CSV columns with no DB source are left out until decided one by one (see Gotchas).
|
|
34
41
|
|
|
35
42
|
## Gotchas
|
|
36
|
-
- **
|
|
43
|
+
- **"Wipe Status" was really Device Status.** The 2026-08-07 seed labelled the `c_deviceStatus` column "Wipe Status". Fixed in `2026-10-21a` (slug `deviceStatus`, label "Device Status"). Real wipe status is a different NetSuite field (below).
|
|
44
|
+
- **Grade / Charging Brick / Charging Cable / Device Status held NetSuite list ids ("2"), not names**, from the 1.0 REST sync bug ([shim doc](../../../1.0/apps/library/features/netsuite-suiteql-rest-shim.md)). 113 Elite units fixed by `2026-10-21b` (maps ids to names, re-runnable).
|
|
45
|
+
- **Open — CSV columns Elite wants that are NOT in the DB** (developer reviewing each; all are NetSuite inventory-number fields):
|
|
46
|
+
- Date Received/Inspected — `custitemnumber_last_recieved_date_serial` (date)
|
|
47
|
+
- Notes — `inventorynumber.memo`
|
|
48
|
+
- Wipe Status — `custitemnumber_wiped` (list)
|
|
49
|
+
- Lock Status — `custitemnumber_lock_status` (list)
|
|
50
|
+
- Return Tracking — `custitemnumber_return_tracking_number` (text). The numbers exist in `Client_Elite.TrackingNumbers` but are not linked to units.
|
|
51
|
+
- Condition — `Units.unitConditionId` is empty for all 746 prod units; no NetSuite serial field feeds it.
|
|
52
|
+
- **Open follow-up:** move the gate to Surface. CTO suggestion: an `inventory.export` element on the `inventory-list-actions` surface, Core seeded hidden + an Elite `SurfaceOverride`, like `inventory.createTransferOrder`.
|
|
37
53
|
|
|
38
54
|
## Change history
|
|
55
|
+
- 2026-10-21 — Inventory export always uses the `units` grouping; Units columns reordered to Elite's CSV, "Wipe Status" relabelled Device Status, list ids mapped to names; missing CSV columns listed. TRUE-82674 (rgirish)
|
|
39
56
|
- 2026-10-16 — Created: Service Requests + Inventory export for Elite, TRUE-82674 (rgirish)
|
|
@@ -6,7 +6,7 @@ project: Database Changes
|
|
|
6
6
|
client: elite
|
|
7
7
|
type: client-feature
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
9
|
+
updated: 2026-10-21
|
|
10
10
|
owners: [tcox, bala, rgirish]
|
|
11
11
|
files:
|
|
12
12
|
- dbchanges2/Client_Elite/
|
|
@@ -16,6 +16,7 @@ files:
|
|
|
16
16
|
- dbchanges2/Client_Elite/2026-09-15a - InventoryHideServiceClassItems.sql
|
|
17
17
|
- dbchanges2/Client_Elite/2026-10-05e - InventoryUnitsOnlyInWarehouse.sql
|
|
18
18
|
- dbchanges2/Client_Elite/2026-10-14a - InventoryUnitsSerialNumberFilter.sql
|
|
19
|
+
- dbchanges2/Client_Elite/2026-10-21a - InventoryUnitsCsvColumns.sql
|
|
19
20
|
- dbchanges2/Core/2026-08-07 - ServiceRequests TableView.sql
|
|
20
21
|
- dbchanges2/Client/2026-08-11a - ServiceRequestsInventoryUnitsTableViews.sql
|
|
21
22
|
- dbchanges2/Client_Nychh/2026-06-19a - FixItemFulfillmentTableViewTrackingAndRoot.sql
|
|
@@ -151,8 +152,10 @@ hand-insert, so the next tenant refresh keeps it.
|
|
|
151
152
|
default labels. **Elite side:** 2 `SalesOrderStatuses` (shipped, delivered), 2
|
|
152
153
|
`AclFieldPermissions`, 1 `AclActionPermissions`, 6 label overrides.
|
|
153
154
|
|
|
154
|
-
**Elite's
|
|
155
|
-
`
|
|
155
|
+
**Elite's custom `inventory_units` columns** (`grade`, `chargingBrick`, `chargingCable`,
|
|
156
|
+
`deviceStatus` — seeded 2026-08-07 as slug `wipeStatus` / label "Wipe Status" but reading
|
|
157
|
+
`c_deviceStatus`, renamed by `2026-10-21a`; plus `itemDescription`, `lastModified` from `2026-10-21a`;
|
|
158
|
+
column order: [Elite CSV export](./supply-csv-export.md)) plus their
|
|
156
159
|
`ClientCustomRecordFieldSettings` labels live in the **Elite** file, not the all-clients one -
|
|
157
160
|
a `customRecordFieldId` names a *different field per client*, so it can never go in `Client/`.
|
|
158
161
|
|
|
@@ -435,6 +438,8 @@ the old `SVC-` prefix check back into the clause.
|
|
|
435
438
|
[error-reporting-issue-event](../../../2.0/apps/_underscore/features/error-reporting-issue-event.md).
|
|
436
439
|
|
|
437
440
|
## Change history
|
|
441
|
+
- 2026-10-21 — `inventory_units` columns reordered to Elite's serial CSV, mislabelled "Wipe Status"
|
|
442
|
+
column renamed `deviceStatus` (`2026-10-21a`, TRUE-82674). (rgirish)
|
|
438
443
|
- 2026-10-14 — Serial Number column search on `inventory_units` (`2026-10-14a`, `isFilterable`
|
|
439
444
|
only, no frontend change; Asset Tag left off). Recorded that the view lists only owned-warehouse
|
|
440
445
|
units (`2026-10-05e`), so serial search misses shipped units. Corrected the stale "still in
|
|
@@ -6,8 +6,8 @@ project: Claude Harness
|
|
|
6
6
|
client: shared
|
|
7
7
|
type: workflow
|
|
8
8
|
status: active
|
|
9
|
-
updated: 2026-10-
|
|
10
|
-
owners: ["jcardinal"]
|
|
9
|
+
updated: 2026-10-21
|
|
10
|
+
owners: ["jcardinal", "rgirish"]
|
|
11
11
|
files:
|
|
12
12
|
- claude/skills/start/SKILL.md
|
|
13
13
|
- claude/skills/commit/SKILL.md
|
|
@@ -126,6 +126,19 @@ All tested 2026-10-08:
|
|
|
126
126
|
only from `~/.claude/projects/*/tool-results/`. Debug: env `TOGA_START_GATE_DEBUG=1` writes
|
|
127
127
|
`gate-debug.log` in the sessions dir. Only the `ticket-reader` agent does the full read. Drop_down values come back
|
|
128
128
|
as an orderindex — map them through `type_config.options`.
|
|
129
|
+
- **macOS: `/start` fails with "Write to temp dir blocked by start-gate hook (ticket not
|
|
130
|
+
verified yet)"** (seen 2026-10-21, TRUE-82674). A small ticket comes back inline (not saved
|
|
131
|
+
to `tool-results/`), so the `ticket-reader` must Write it to a temp file (step 4). The gate
|
|
132
|
+
allows that Write only under `~/.claude` or `os.tmpdir()`/`$TEMP`/`$TMP`
|
|
133
|
+
(`safeZonePrefixes()`). On macOS that is `$TMPDIR` (`/var/folders/.../T/`); the reader picked
|
|
134
|
+
`/tmp` (= `/private/tmp`) and was blocked. Windows is fine (`%TEMP%` matches).
|
|
135
|
+
- Workaround: re-run the `ticket-reader` and tell it to save inline results under
|
|
136
|
+
`~/.claude/toga-ticket-tmp/` (not `toga-sessions` or any `tool-results` folder). Auto mode
|
|
137
|
+
may block the retry as a gate bypass — leave auto mode and OK it.
|
|
138
|
+
- Real fix (not done yet): `ticket-reader` step 4 names the folder (`$TMPDIR`, never `/tmp`,
|
|
139
|
+
or `~/.claude/toga-ticket-tmp/`), or `safeZonePrefixes()` also allows `/tmp` and `/private/tmp`.
|
|
140
|
+
- The reader must not trim the raw task JSON before parsing. Verify still passes when it
|
|
141
|
+
does (it checks id/url against the hook's `seen` read), so this goes unnoticed.
|
|
129
142
|
- **Done status is `development finished`** (lowercase; valid on the Dev Sprints lists).
|
|
130
143
|
- **The ClickUp GitHub integration works:** a PR whose title starts with the ticket id auto-links.
|
|
131
144
|
worker2 also reads the first token of the PR title as the ticket id.
|
|
@@ -161,6 +174,7 @@ All tested 2026-10-08:
|
|
|
161
174
|
|
|
162
175
|
## Change history
|
|
163
176
|
|
|
177
|
+
- 2026-10-21 — TRUE-82674: macOS `/start` temp-dir block gotcha + workaround. (rgirish)
|
|
164
178
|
- 2026-10-15 — Ticket writes need no approval: `/finish` writes fields itself, `/pseudocode`
|
|
165
179
|
writes once the plan is agreed; the gate allows any field/status/tag/comment on the session
|
|
166
180
|
ticket, except Has Code Changes. (jcardinal)
|
package/package.json
CHANGED