toga-ai 1.0.277 → 1.0.278

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,6 +6,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
6
6
 
7
7
  - **library** (Library) _(framework core)_ — 11 doc(s) → [1.0/apps/library/INDEX.md](1.0/apps/library/INDEX.md)
8
8
  - **worker** (Worker) — 13 doc(s) → [1.0/apps/worker/INDEX.md](1.0/apps/worker/INDEX.md)
9
+ - **worker1.5** (Worker 1.5) — 0 doc(s) → [1.0/apps/worker1.5/INDEX.md](1.0/apps/worker1.5/INDEX.md)
9
10
  - **togadesk** (TOGa Desk) — 8 doc(s) → [1.0/apps/togadesk/INDEX.md](1.0/apps/togadesk/INDEX.md)
10
11
  - **togaview** (TOGa View) — 6 doc(s) → [1.0/apps/togaview/INDEX.md](1.0/apps/togaview/INDEX.md)
11
12
  - **webhook** (Webhook) — 1 doc(s) → [1.0/apps/webhook/INDEX.md](1.0/apps/webhook/INDEX.md)
@@ -3,6 +3,7 @@
3
3
  | Doc | Framework | Summary | Files |
4
4
  |-----|-----------|---------|-------|
5
5
  | [Compass ASN → ItemFulfillment Auto-Creation](features/asn-to-item-fulfillment.md) | 2.0 | For Compass USA, posting an AdvanceShippingNotice (ASN) auto-creates the ItemFulfillment (IF) on the upstream SalesOrder. | _underscore/Model/Compass/AdvanceShippingNotice.php, _underscore/Model/Compass/PurchaseOrder.php, api2/Component/Api/Cxml/Cxml.php, dbchanges2/Client_Compass/2026-06-11 - AsnItemTrackingNumberAcl.sql, dbchanges2/Client_Compass/2026-06-15b - BackfillSA132781ItemFulfillmentTracking.sql, dbchanges2/Client_Compass/2026-06-16 - CleanupSA132763CrossLineTracking.sql, dbchanges2/Client_Compass/2026-06-16b - CleanupSA132743CrossLineTracking.sql, dbchanges2/Client_Compass/2026-06-16c - BackfillSA132763C40QYUCTracking.sql, dbchanges2/Client_Compass/2026-06-18a - CleanupSA132898DuplicateTracking.sql, dbchanges2/Client_Compass/2026-06-18b - CleanupSA132881DuplicateTracking.sql, dbchanges2/Client_Compass/2026-07-02a - FixSA133377TrackingSerialAndDuplicateIF.sql |
6
+ | [Cost Centers — Unit Locations, numeric-only policy](features/cost-centers.md) | 2.0 | A Compass "cost center" — the value a user picks in commerce and that lands on an order — is **not** a `CostCenters` row. | toga2-commerce/src/pages/Cart/api/CartApi.ts, worker1.5/crons/toga2/compass/import_locations.php, _underscore/Model/Compass/SalesOrder.php, api2/Component/Api/V2/V2.php, dbchanges2/Client_Compass/2026-07-06 - RemoveNonNumericCostCenters.sql |
6
7
  | [Compass: Item-Fulfillment TableViews (for-sales-order-items & for-sales-orders, tracking via bridge)](features/item-fulfillment-tracking-tableview.md) | 2.0 | Two sibling Compass TableViews in `Client_Compass` display fulfilled items in toga2-supply, both driven by `TableViews` / `TableViewJoins` / `TableViewFields` c | dbchanges2/Client_Compass/2026-06-10 - ItemFulfillmentsForSalesOrderItemsTableView.sql, dbchanges2/Client_Compass/2026-06-11 - ItemFulfillmentsForSalesOrdersTableView.sql, dbchanges2/Client_Compass/2026-06-15a - FixItemFulfillmentTrackingNumberJoins.sql |
7
8
  | [Compass MITS PO → SO Item Linking](features/mits-po-to-so-item-linking.md) | 2.0 | MITS sends Compass inbound Purchase Orders (`POST /v2/purchase-orders`) against a Sales Order (`mitsSalesOrder`). | _underscore/Model/Compass/PurchaseOrder.php, worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php |
8
9
  | [Compass MITS PO Transmission to Vendors](features/mits-po-transmission-to-vendors.md) | 2.0 | The 1.0 worker cron `2_transmit_mits_purchase_orders_to_vendors.php` transmits Compass PurchaseOrders to their vendors (Office Depot, Strategic Systems, Compass | worker/crons/toga2/compass/workflow/2_transmit_mits_purchase_orders_to_vendors.php, library/app/client/compass.php |
@@ -0,0 +1,115 @@
1
+ ---
2
+ title: Cost Centers — Unit Locations, numeric-only policy
3
+ framework: "2.0"
4
+ project: _Underscore
5
+ client: compass-usa
6
+ type: client-feature
7
+ status: active
8
+ updated: 2026-07-06
9
+ owners: [bala]
10
+ files:
11
+ - toga2-commerce/src/pages/Cart/api/CartApi.ts
12
+ - worker1.5/crons/toga2/compass/import_locations.php
13
+ - _underscore/Model/Compass/SalesOrder.php
14
+ - api2/Component/Api/V2/V2.php
15
+ - dbchanges2/Client_Compass/2026-07-06 - RemoveNonNumericCostCenters.sql
16
+ related:
17
+ - ../profile.md
18
+ - ../../../2.0/apps/toga2-commerce/features/cart-page-config-architecture.md
19
+ ---
20
+
21
+ ## Summary
22
+ A Compass "cost center" — the value a user picks in commerce and that lands on an order — is
23
+ **not** a `CostCenters` row. In `Client_Compass` it is a **Unit-level Location**
24
+ (`locationTypeId = 1`) identified by its **`c_erpSystemEntityId`** custom field. The
25
+ `CostCenters` table (and the `Users_CostCenters` / `Locations_CostCenters` bridges,
26
+ `SalesOrders.costCenterId`, `Users.defaultCostCenterId`) are **empty / vestigial** for Compass
27
+ and unused. As of **2026-07-06**, Compass policy is **numeric-only cost centers**: users may only
28
+ select cost centers whose `c_erpSystemEntityId` is all digits, all existing non-numeric ones are
29
+ soft-deactivated, and the import will never re-create or re-activate a non-numeric one.
30
+
31
+ This is US Compass only (`Client_Compass`). Compass Canada is explicitly out of scope.
32
+
33
+ ## How it works
34
+
35
+ ### What a cost center actually is
36
+ - A cost center = a **Unit Location** in `Client_Compass.Locations` (`locationTypeId = 1`),
37
+ keyed by the custom field **`c_erpSystemEntityId`**.
38
+ - `c_erpEntityId` is a **different** field on the Unit row (the unit id) — do not confuse the
39
+ two. At checkout the chosen cost-center value is written to **`SalesOrders.c_erpEntityId`** as a
40
+ **plain string, not a foreign key**. `_underscore/Model/Compass/SalesOrder.php` exposes a
41
+ `_costCenter` computed field.
42
+ - The `CostCenters` table is empty for Compass; nothing reads
43
+ `Users_CostCenters` / `Locations_CostCenters` / `SalesOrders.costCenterId` /
44
+ `Users.defaultCostCenterId`.
45
+
46
+ ### The commerce dropdown
47
+ - Built by **`fetchCostCenter()`** in
48
+ `toga2-commerce/src/pages/Cart/api/CartApi.ts`, which calls
49
+ `GET /locations` filtered on `c_erpSystemEntityId LIKE %search% AND isActive = 1`, and displays
50
+ each as `"{c_erpSystemEntityId} - {name}"`.
51
+ - It funnels **both** the cart checkout and the New-User form, so a single filter in
52
+ `fetchCostCenter` covers both entry points.
53
+ - **api2 does no cost-center validation** — the FE is the only selection gate.
54
+
55
+ ### Where the values come from (import)
56
+ - `worker1.5/crons/toga2/compass/import_locations.php` reads an SFTP file and sets
57
+ `c_erpSystemEntityId` on Unit rows from **column 16**.
58
+ - Repeated imports have massively **duplicated** cost-center rows (~730× per value).
59
+
60
+ ### Numeric-only enforcement (2026-07-06) — three layers
61
+ 1. **Front-end selection block** — in `fetchCostCenter`, on the **search path**
62
+ (`useSearchOptions === true`), returned locations are filtered to numeric-only cost centers
63
+ with `/^[0-9]+$/` on `c_erpSystemEntityId.trim()`. The non-search / display path is left
64
+ untouched (so an already-saved value still renders). Done client-side because api2 rejects a
65
+ server-side numeric filter (see gotcha) and api2 was out of scope.
66
+ 2. **Data cleanup (one-time, reversible)** —
67
+ `dbchanges2/Client_Compass/2026-07-06 - RemoveNonNumericCostCenters.sql` runs
68
+ `UPDATE Locations SET isActive = 0` for every active row whose `c_erpSystemEntityId` is
69
+ non-empty and does **not** match `^[0-9]+$`. **Soft delete (isActive=0), not a hard delete.**
70
+ ~401,719 active rows across 1,185 distinct non-numeric codes. They then drop out of the
71
+ commerce lookup automatically via its existing `isActive = 1` filter.
72
+ 3. **Import durability guard** — in `import_locations.php`, in **both** Unit branches
73
+ (new-create and existing-update), after `$isActiveValue` is computed it is forced to `0` when
74
+ the cost center is non-empty and not `ctype_digit`, so future imports never re-activate or
75
+ create active non-numeric cost centers.
76
+
77
+ ## Gotchas
78
+ - **api2 cannot do a server-side numeric filter.** The V2 query-string where-parser
79
+ (`api2/Component/Api/V2/V2.php` → `parseOptionsWhere`) **whitelists operators and rejects
80
+ `regexp` with a 500**. Any numeric/regex filtering must happen client-side (or via a new
81
+ operator in api2, which was out of scope here).
82
+ - **Two fields, easy to swap.** `c_erpSystemEntityId` is the cost center (what users pick);
83
+ `c_erpEntityId` is the unit id and the value that orders record on
84
+ `SalesOrders.c_erpEntityId`.
85
+ - **Second, possibly-live copy of the import cron not yet guarded.** A second copy exists at
86
+ `worker/crons/toga2/compass/DOA_Scripts/import_locations.php` (appears disabled / "DOA"). It
87
+ did **not** receive the numeric guard — **confirm whether it is live** before trusting the
88
+ guard to be complete.
89
+ - Non-numeric cost centers include both number+alphabet combos (e.g. `10007A`, `224GT`) and
90
+ letters-only codes (e.g. `EAGLE`, `TAMU`). All are retired in favor of numeric-only.
91
+
92
+ ## Safety verification (before deactivation, prod Client_Compass)
93
+ Deactivation was proven safe against prod data:
94
+ - **0** users (active or inactive, via `Users.locationId`), **0** sales orders / SO items /
95
+ purchase orders / item fulfillments / item receipts / transfer orders / inventory adjustments /
96
+ tickets / contacts / child locations reference these non-numeric Unit locations.
97
+ - Only **1,180** `Locations_Addresses` links point at them (harmless, left intact).
98
+ - Only **2** sales orders ever used a non-numeric cost-center value (stored as string on
99
+ `SalesOrders.c_erpEntityId`, unaffected by deactivating the Location).
100
+ - **0** active users have a non-numeric `c_erpEntityId`, so no cost-center display goes blank.
101
+ - Proven end-to-end in dev-sandbox: after the migration, active non-numeric rows = **0** (all
102
+ 1,185 codes incl. the 725 number+alphabet combos) while pure-numeric stayed untouched at
103
+ **440,005** active rows.
104
+
105
+ ## Scope constraints (from the developer)
106
+ - Do **not** change anything in `api2`.
107
+ - Do **not** hard-delete — use `isActive = 0` (reversible).
108
+ - **US Compass only** (`Client_Compass`); Compass Canada is out of scope.
109
+
110
+ ## Change history
111
+ - 2026-07-06 — Established numeric-only cost-center policy across three layers: FE `fetchCostCenter`
112
+ search-path filter (`/^[0-9]+$/`), one-time `RemoveNonNumericCostCenters.sql` soft-deactivation
113
+ (~401,719 rows / 1,185 codes), and an `import_locations.php` guard forcing `isActive=0` on
114
+ non-`ctype_digit` cost centers in both Unit branches. Documented that a Compass cost center is a
115
+ Unit Location keyed by `c_erpSystemEntityId` (not the vestigial `CostCenters` table). (bala)
@@ -8,16 +8,18 @@ apps:
8
8
  - toga25-supply
9
9
  - toga2-commerce
10
10
  - worker
11
+ - worker1.5
11
12
  - dbchanges2
12
13
  project: _Underscore
13
14
  client: compass-usa
14
15
  type: profile
15
16
  status: active
16
- updated: 2026-06-30
17
+ updated: 2026-07-06
17
18
  owners: [jcardinal, bala, tcox]
18
19
  files: []
19
20
  related:
20
21
  - features/asn-to-item-fulfillment.md
22
+ - features/cost-centers.md
21
23
  - ../../2.0/apps/toga2-commerce/features/expedited-shipping-gating.md
22
24
  - ../../2.0/apps/_underscore/features/item-fulfillment-stage-lifecycle-and-order-status.md
23
25
  ---
@@ -34,7 +36,9 @@ separate, related client (see its own profile).
34
36
  - **2.0:** `_underscore` backend, prod schema `Client_Compass` (worker link `db_compass`).
35
37
  Client-specific model overrides live under `_underscore/Model/Compass/`.
36
38
  - **1.0:** worker crons under `worker/crons/toga2/compass/` handle email-based imports and
37
- notifications.
39
+ notifications. A separate **`worker1.5`** repo (also App_/1.0-style) runs the SFTP location
40
+ import (`worker1.5/crons/toga2/compass/import_locations.php`) that seeds Unit Locations /
41
+ cost centers.
38
42
  - Storefront: compass.togacommerce.com / compass.togahub.com. The storefront app repo is
39
43
  **`toga2-commerce`** (2.0, consumes api2).
40
44
 
@@ -56,6 +60,9 @@ separate, related client (see its own profile).
56
60
  ## Key features (this client)
57
61
  - [Compass ASN → ItemFulfillment Auto-Creation](features/asn-to-item-fulfillment.md) — the
58
62
  `_Model_Compass_AdvanceShippingNotice::postPost` handler.
63
+ - [Cost Centers (Unit Locations, numeric-only)](features/cost-centers.md) — what a Compass
64
+ "cost center" actually is (a Unit Location keyed by `c_erpSystemEntityId`), and the
65
+ numeric-only selection/import/data policy (2026-07-06).
59
66
 
60
67
  ## Notes
61
68
  - **Order status is shipped-only (2026-06-30).** Compass imports all IF stages
@@ -41,6 +41,15 @@
41
41
  "role": "app",
42
42
  "dependsOn": []
43
43
  },
44
+ {
45
+ "repo": "worker1.5",
46
+ "project": "Worker 1.5",
47
+ "framework": "1.0",
48
+ "role": "app",
49
+ "dependsOn": [
50
+ "library"
51
+ ]
52
+ },
44
53
  {
45
54
  "repo": "toga2-supply",
46
55
  "project": "TOGa Supply",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.277",
3
+ "version": "1.0.278",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",