toga-ai 1.0.974 → 1.0.975

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.
@@ -10,6 +10,7 @@ owners: [bala, ajean, rgirish]
10
10
  files:
11
11
  - toga2-commerce/src/pages/Cart/api/CartApi.ts
12
12
  - toga2-commerce/src/pages/Cart/viewModel/useCartViewModel.ts
13
+ - toga2-commerce/src/pages/Cart/view/cartForm/EditCart.tsx
13
14
  - worker1.5/crons/toga2/compass/import_locations.php
14
15
  - _underscore/Model/Compass/SalesOrder.php
15
16
  - api2/Component/Api/V2/V2.php
@@ -22,6 +23,7 @@ related:
22
23
  - ../../../2.0/apps/toga2-commerce/features/cart-page-config-architecture.md
23
24
  - ../../../1.0/apps/tools/features/compass-user-persona-admin.md
24
25
  - ./people-file-user-lifecycle.md
26
+ - ../workflows/granting-api-access.md
25
27
  ---
26
28
  A Compass "cost center" is a Unit-level Location keyed by `c_erpSystemEntityId` (NOT a `CostCenters` row), numeric-only since 2026-07-06; open for cost-center dropdown, import, or the numeric-only policy. US Compass only.
27
29
 
@@ -38,6 +40,11 @@ US Compass only (`Client_Compass`). Compass Canada is explicitly out of scope. S
38
40
  - Entity `1001` = US cost centers. Entity `1019` rows look like old / reused CCs (feed active flag `U`, not `Y`).
39
41
  - The `CostCenters` table is empty for Compass; nothing reads `Users_CostCenters` / `Locations_CostCenters` / `SalesOrders.costCenterId` / `Users.defaultCostCenterId`.
40
42
 
43
+ ### Where a user's cost center lives
44
+ - **`Users.c_erpEntityId` = the user's cost center number.** Cart reads it in `fetchUser` (`CartApi.ts` ~464; `EditCart.tsx` ~446-461), then gets the name from `/locations` by `c_erpSystemEntityId` with `distinct=` (`fetchCostCenter`, ~518) and takes `result[0]`.
45
+ - **`Users.locationId` / `location.*` is NOT the cost center.** Example: `RoachC01` has no location but cost center `121109`. Any API consumer looking up a user's cost center reads `Users.c_erpEntityId` (see [API access](../workflows/granting-api-access.md)).
46
+ - Any `/locations` cost-center call must send `distinct=` — prod has ~550 active duplicate rows per number (e.g. `10021` → 545 rows "Cape Cod Mall"); 174 numbers map to more than one active name (2026-10-08).
47
+
41
48
  ### The commerce dropdown
42
49
  - Built by `fetchCostCenter()` in `toga2-commerce/src/pages/Cart/api/CartApi.ts`, which calls `GET /locations` filtered on `c_erpSystemEntityId LIKE %search% AND isActive = 1`, fields `c_erpSystemEntityId,name`, distinct (exact `=` match on the display path).
43
50
  - `useCartViewModel.ts` (~426-460) labels options `"<CC> - <name>"` and dedupes by `c_erpSystemEntityId` — **first row wins**. So when one CC number exists under several entities, the shown name can belong to the wrong entity.
@@ -92,3 +99,4 @@ Deactivation proven safe against prod data:
92
99
 
93
100
  ## Change history
94
101
  - 2026-10-08 — Documented dropdown first-row-wins dedupe (wrong name = display only), entity 1001 vs 1019, the INNER JOIN import bug that inserts duplicate address-less units every run, uuid churn, and the hardcoded SFTP credential. (rgirish)
102
+ - 2026-10-08 — Added: user cost center = `Users.c_erpEntityId` (not `locationId`); `/locations` calls need `distinct=`. (rgirish)
@@ -6,8 +6,8 @@ project: Database Changes
6
6
  client: compass-usa
7
7
  type: workflow
8
8
  status: active
9
- updated: 2026-09-16
10
- owners: ["bala"]
9
+ updated: 2026-10-08
10
+ owners: ["bala", "rgirish"]
11
11
  files:
12
12
  - dbchanges2/Client_Compass/2026-09-10 - RefreshTeamApiAccess.sql
13
13
  related:
@@ -16,6 +16,7 @@ related:
16
16
  - ../../../2.0/apps/api2/features/api-key-authentication-and-scoping.md
17
17
  - ../../../2.0/apps/_underscore/features/acl-permission-chain.md
18
18
  - ../../../2.0/apps/api2/features/request-logging.md
19
+ - ../features/cost-centers.md
19
20
  ---
20
21
  How to build a Compass API key with one dedicated read-only role (the Refresh-team template); open for any "give team X scoped API access" request.
21
22
 
@@ -30,7 +31,18 @@ The Refresh-team key (worked example, landed on **production** 2026-09-10):
30
31
  - Read-only: **9 records**, **83 field permissions**, **18 custom-field permissions**, **0 writable anywhere**.
31
32
  - Records granted (`Core.Records.id`): **2** users, **11** locations, **37** contacts, **38** contact-email-addresses, **39** contact-phone-numbers, **40** personas, **201** user-personas, **273** user-roles, **274** roles.
32
33
  - Field grants were **cloned from the shared API role (roleId 3)** for those same records, minus the two fields dropped in the steps below.
33
- - The consumer calls four requests: auth, cost center by number (`/locations`), user by email (`/users`), and user by Compass username (`/users`).
34
+ - Not readable by this key: `Users.c_isVip`, `Users.c_supportedByUserId` (not in the cloned grants).
35
+ - Auth: `POST /v2/auth/api` with `{client: <Compass client uuid>, api: Apis.uuid, secret: Apis.secret}`. `Apis.secret` is stored **plain text** in `Client_Compass.Apis` — fetch it from there; never copy the value into docs or git.
36
+ - Separate from the MITS (`Apis.id 2`) and "Compass Group" (`Apis.id 3`) keys.
37
+
38
+ ### Refresh-team calls (decided 2026-10-08: Users only, no `/locations`)
39
+ Cost center lookups go through `Users.c_erpEntityId`, the same field the cart reads ([Cost Centers](../features/cost-centers.md)). Calls:
40
+ 0. `POST /v2/auth/api` (above).
41
+ 1. Search cost centers: `/users?recordsPerPage=25&fields=c_erpEntityId&where=(c_erpEntityId:like:%25{text}%25,AND,isActive:eq:1)&distinct=`
42
+ 2. User by email: `/users?fields=_name,firstName,lastName,email,c_erpEntityId,_personaIds,userPersonas.persona.name&where=(email:eq:{email})`
43
+ 3. User by HR username: same fields, `where=(c_hrEmpUsername:eq:{username})`
44
+
45
+ Delivered as a Postman collection (`Compass_Refresh_Team_API.postman_collection.json`, kept on the developer's machine, not in git), credentials as placeholders.
34
46
 
35
47
  ## Steps
36
48
  1. Create the `Client_Compass.Roles` row for the consumer (one role, one key). `coreRoleId` may stay NULL — every record here has `Core.Records.aclDatabase = 'CLIENT'`.
@@ -49,7 +61,7 @@ The Refresh-team key (worked example, landed on **production** 2026-09-10):
49
61
  - Call each intended route with the new key, then read `Logs_Compass.Api` filtered on the new `apiId` to confirm the exact routes and response payloads ([V2 Request Logging](../../../2.0/apps/api2/features/request-logging.md)).
50
62
 
51
63
  ### The consumer-facing reference document
52
- Each API consumer gets a Word reference document, mirroring the existing MITS one. Generated with `python-docx` using the MITS `.docx` as the style template, covering the four requests, real sample responses lifted from `Logs_Compass.Api`, Postman links, token lifetimes, and a plain-English "what your key can access" section. **Credentials in the document are placeholders only.** The file lives outside the repos (the developer's local Downloads) — the binary is not stored in git or the knowledge base.
64
+ Each API consumer gets a Word reference document, mirroring the existing MITS one. Generated with `python-docx` using the MITS `.docx` as the style template, covering the requests, real sample responses lifted from `Logs_Compass.Api`, Postman links, token lifetimes, and a plain-English "what your key can access" section. **Credentials in the document are placeholders only.** The file lives outside the repos (the developer's local Downloads) — the binary is not stored in git or the knowledge base.
53
65
 
54
66
  ## Gotchas
55
67
  - **⚠ The four older Compass keys are NOT scoped.** All four pre-existing `Client_Compass.Apis` rows — **Agilant**, **MITS Service Hub**, **Compass Group**, **Office Depot (Cxml)** — are wired in `Apis_Roles` to the **same two roles**:
@@ -65,6 +77,8 @@ Each API consumer gets a Word reference document, mirroring the existing MITS on
65
77
  - The **negative test has not been run** — calling a route outside the grant (e.g. `/items`) with the Refresh key to confirm `UNAUTHORIZED`.
66
78
  - The script was run **directly on production**; the intended client-sandbox dry run was skipped.
67
79
  - Migrating the four older keys off the shared Base + API roles onto per-key roles is **not started**.
80
+ - (2026-10-08) The Postman collection is **not tested live**. `userPersonas.persona.name` is unverified — copied from the `userRoles.role.name` shape.
81
+ - The old `Refresh_Team_API_Reference.docx` used `/locations` / the user's location for cost center — **wrong**; regenerate it from the Users-only calls.
68
82
 
69
83
  ## Related
70
84
  - [Compass USA profile](../profile.md)
@@ -72,3 +86,4 @@ Each API consumer gets a Word reference document, mirroring the existing MITS on
72
86
  - [API-Key Authentication & scoping](../../../2.0/apps/api2/features/api-key-authentication-and-scoping.md)
73
87
  - [ACL Permission Chain](../../../2.0/apps/_underscore/features/acl-permission-chain.md)
74
88
  - [V2 Request Logging](../../../2.0/apps/api2/features/request-logging.md)
89
+ - [Cost Centers](../features/cost-centers.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.974",
3
+ "version": "1.0.975",
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",