toga-ai 1.0.402 → 1.0.404
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/2.0/apps/_underscore/features/surface-resolver.md +19 -19
- package/knowledge/2.0/apps/toga25-supply/INDEX.md +1 -0
- package/knowledge/2.0/apps/toga25-supply/features/force-logout-on-deployment.md +70 -0
- package/knowledge/INDEX.md +1 -1
- package/knowledge/sessions/2026-07-21-true-79191-fulfill-ship-mhammontree.md +62 -0
- package/package.json +1 -1
|
@@ -322,21 +322,21 @@ Core record grants + their logic-group expressions all evaluate `all`/`"1"`. The
|
|
|
322
322
|
|
|
323
323
|
## Gotchas
|
|
324
324
|
|
|
325
|
-
- **Per-client surface message overrides silently never apply
|
|
326
|
-
`
|
|
327
|
-
|
|
328
|
-
`
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
325
|
+
- **Per-client surface message overrides silently never apply when `languageId` resolves to `0`.**
|
|
326
|
+
`_Model_Core_Surface::_loadMessages` overlays `Core.Messages.defaultValue` with
|
|
327
|
+
`Client_<X>.MessageTranslations` rows **only when `languageId > 0`**. The JWT carries the language as
|
|
328
|
+
the string code `id.language` (`"en"`) but **not** the numeric `id.client.languageId`, so reading
|
|
329
|
+
`id.client.languageId` alone always yielded `0` — the overlay was skipped and every per-client surface
|
|
330
|
+
message override (e.g. a client-specific disabled-tooltip) fell back to the Core default with **no
|
|
331
|
+
error**. **Fix (2026-07-21):** `Surface.php` now resolves `languageId` via a private
|
|
332
|
+
`_resolveLanguageId($api)` helper (used by both `resolve()` and `metaDebug()`) — it prefers
|
|
333
|
+
`id.client.languageId`, and when that is `0` **looks up the client `Languages` row by the
|
|
334
|
+
`id.language` code** (`_Model_Client_Language` load-by-`code`) and uses its id. English resolves to a
|
|
335
|
+
real `languageId` too; a client with no `MessageTranslations` row still falls back to Core defaults.
|
|
336
|
+
This lives entirely in the framework resolver — **no auth/JWT change** (an earlier `V2.php`
|
|
337
|
+
token-embed approach was abandoned in favour of the lookup, so it works across **all** token paths,
|
|
338
|
+
including refresh, without each auth flow having to embed the id). (This is a **separate** concern from
|
|
339
|
+
`id.language` driving the data-translation sidecar — see
|
|
340
340
|
[language-translation-layer](../../api2/features/language-translation-layer.md); do not conflate.)
|
|
341
341
|
- **A `SurfaceOverrides` row with `attribute='CONFIG'` carrying a RULE value is silently DEAD —
|
|
342
342
|
encode rules as `VISIBILITY_RULE`/`ENABLED_RULE`, never as `CONFIG`.** `_castOverride` routes the
|
|
@@ -427,10 +427,10 @@ Core record grants + their logic-group expressions all evaluate `all`/`"1"`. The
|
|
|
427
427
|
`{"type":"poNumberEntered"}` (client-wide, both surfaces) + disabled-tooltip `MessageTranslations`
|
|
428
428
|
override, and the **Compass/CC** approvals-gate marker enable (`2026-07-21b`) needed so
|
|
429
429
|
`stepTwoAssigned` doesn't fail open. New gotcha: per-client surface **message** overrides silently
|
|
430
|
-
never apply
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
430
|
+
never apply when `languageId` resolves to `0` (`_loadMessages` overlays `MessageTranslations` only
|
|
431
|
+
when `languageId>0`; the JWT carries `id.language` code but not `id.client.languageId`) — fixed in
|
|
432
|
+
`Surface.php` via a `_resolveLanguageId()` helper that falls back to looking up the client `Languages`
|
|
433
|
+
row by the `id.language` code. Framework-only; no auth/JWT change, so it holds across all token paths.
|
|
434
434
|
(apeterson)
|
|
435
435
|
- 2026-07-20 — Clarified the **backend Tier-2 gate reality**: `_resolveTier2State` (Surface.php ~280)
|
|
436
436
|
dispatches by **action slug** to `resolveSurfaceActionState()` (`TIER2_CAPABILITY_METHOD`), **not**
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
| [Client API-Fetch Fields (useClientApiFields / apiFields.json)](features/client-api-fetch-fields.md) | The mechanism that resolves a client's **API-fetch projection** — which `fields` / `ojoin` / `join` / `where` to request from the TOGa API for a given page — fr | toga25-supply/src/fieldsConfig/resolveApiConfig.ts, toga25-supply/src/fieldsConfig/useClientApiFields.ts, toga25-supply/src/fieldsConfig/index.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/FIELDS/apiFields.json, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx, toga25-supply/src/layout/ItemRecordModalLayout/viewModel/FIELDS/apiFields.json, toga25-supply/src/layout/ItemRecordModalLayout/viewModel/useItemRecordModalViewModel.tsx |
|
|
8
8
|
| [Client-Configurable Fields (useClientFields / fieldsConfig)](features/client-configurable-fields.md) | The mechanism for config that **varies by client** (or client × role) — field overrides, filter buttons, group-by options, column pickers, layout toggles — with | toga25-supply/src/fieldsConfig/index.ts, toga25-supply/src/fieldsConfig/useClientFields.ts, toga25-supply/src/pages/SalesOrders/viewModel/FIELDS/, toga25-supply/src/pages/Inventory/viewModel/FIELDS/, toga25-supply/src/pages/Inventory/README.md, toga25-supply/src/layout/ItemRecordModalLayout/viewModel/FIELDS/, toga25-supply/src/layout/VendorItemRecordModalLayout/viewModel/FIELDS/, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/sections/SalesOrderTopBar.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/FIELDS/ |
|
|
9
9
|
| [Column Visibility (URL-driven show/hide columns)](features/column-visibility.md) | A "Columns" header button that opens a modal listing every column from the table meta, lets the user show/hide columns, adjusts the table live, and persists the | toga25-supply/src/components/ColumnVisibilityModal/, toga25-supply/src/pages/SalesOrders/SalesOrders.tsx, toga25-supply/src/pages/SalesOrders/viewModel/useSalesOrdersPageViewModel.tsx, toga25-supply/src/pages/SalesOrders/hooks/useSalesOrdersTableData.tsx |
|
|
10
|
+
| [Force Logout on Deployment (useDeploymentGuard)](features/force-logout-on-deployment.md) | On large deployments the backend bumps the Core parameter `META_LAST_REFRESH_DATETIME`. | toga25-supply/src/hooks/useDeploymentGuard.tsx, toga25-supply/src/App.tsx |
|
|
10
11
|
| [Meta-Driven Page & Table Setup](features/meta-driven-table-data.md) | A page in this app is **meta-driven end to end**: the page view model fetches *page meta* (labels, sections, ACL) and *table meta* (the columns/fields + table s | toga25-supply/src/pages/SalesOrders/viewModel/useSalesOrdersPageViewModel.tsx, toga25-supply/src/pages/SalesOrders/hooks/useSalesOrdersTableState.ts, toga25-supply/src/hooks/useTablePageMeta.ts, toga-blox-npm/dist/hooks/useFetchPageMeta.d.ts, toga-blox-npm/dist/hooks/useFetchTablePageMeta.d.ts, toga-blox-npm/dist/hooks/useAssignTableFieldLabels.d.ts, toga-blox-npm/dist/components/Table/hooks/useTableData.d.ts |
|
|
11
12
|
| [Record Modals & Nested Tables](features/record-modals-and-nested-tables.md) | The repo's family of modal + nested-table patterns layered over toga-blox `TableRecordModal` and `PrimaryTable*Layout`. | toga25-supply/src/layout/ItemRecordModalLayout/, toga25-supply/src/layout/SalesOrderRecordModalLayout/, toga25-supply/src/layout/SalesOrderItemsTableLayout/, toga25-supply/src/layout/ItemFulfillmentModal/, toga25-supply/src/layout/GenericNestedTables/GenericNestedTables.tsx, toga25-supply/src/layout/GenericNestedTables/GenericTableLayout.tsx, toga25-supply/src/pages/Inventory/viewModel/useInventoryPageViewModel.tsx, toga25-supply/src/pages/Inventory/viewModel/FIELDS/DEFAULT/inventoryGroupings.json, toga25-supply/src/hooks/useTableCellInteractions.ts, toga25-supply/src/hooks/useServerTableUrlState.ts |
|
|
12
13
|
| [Surface Frontend (DB-driven UI consumption, src/surface/)](features/surface-frontend.md) | The frontend consumer of the platform-wide Surface layer — DB-driven UI config fetched from `GET /v2/surfaces/meta?slug=<slug>` instead of statically-imported J | toga25-supply/src/surface/useFetchSurfaceMeta.ts, toga25-supply/src/pages/SalesOrders/helpers/surfaceBundleToTenantFields.ts, toga25-supply/src/pages/SalesOrders/helpers/buildPatchedTenantFields.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/SalesOrderView.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/layoutComponents/SalesOrderSummaryGrid.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/getDetailSections.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/sections/SalesOrderNotesSection.tsx, toga25-supply/src/pages/SalesOrders/helpers/cleanOrder.ts, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/helpers/index.ts, toga25-supply/src/surface/evaluateSurfaceRule.ts, toga25-supply/src/surface/resolveElementState.ts, toga25-supply/src/pages/SalesOrders/helpers/evaluateEnableRule.ts, toga25-supply/src/pages/SalesOrders/hooks/useSalesOrderRowRecordState.ts, toga25-supply/src/surface/actionRegistry.ts, toga25-supply/src/surface/componentRegistry.tsx, toga25-supply/src/surface/SurfaceActionBar.tsx, toga25-supply/src/surface/SurfaceSection.tsx, toga25-supply/src/surface/resolve.ts, toga25-supply/src/surface/types.ts, toga25-supply/src/surface/index.ts, toga25-supply/src/pages/Login/LoginPage.tsx, toga25-supply/src/pages/SalesOrders/SalesOrders.tsx, toga25-supply/src/pages/SalesOrders/view/SurfaceRowActions.tsx, toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/view/sections/SalesOrderTopBar.tsx, toga25-supply/src/pages/Items/ItemsPage.tsx, toga25-supply/src/pages/Items/viewModel/useItemsPageViewModel.tsx, toga25-supply/src/pages/VendorItems/VendorItemsPage.tsx, toga25-supply/src/pages/VendorItems/viewModel/useVendorItemsPageViewModel.tsx, toga25-supply/src/pages/Inventory/Inventory.tsx, toga25-supply/src/pages/Inventory/viewModel/useInventoryPageViewModel.tsx, toga25-supply/src/pages/Inventory/viewModel/FIELDS/index.ts, toga25-supply/src/fieldsConfig/index.ts, toga25-supply/src/layout/ItemRecordModalLayout/helpers/surfaceBundleToItemFields.ts, toga25-supply/src/layout/ItemRecordModalLayout/helpers/index.ts, toga25-supply/src/layout/ItemRecordModalLayout/viewModel/useItemRecordModalViewModel.tsx, toga25-supply/src/layout/ItemRecordModalLayout/ItemRecordModalLayout.tsx, toga25-supply/src/layout/ItemRecordModalLayout/components/ItemRecordView.tsx, toga25-supply/src/surface/useStatusColors.ts, toga25-supply/src/surface/SurfaceHeader.tsx |
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Force Logout on Deployment (useDeploymentGuard)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: toga25-supply
|
|
5
|
+
project: TOGa 2.5 Supply
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-07-21
|
|
10
|
+
owners: [apeterson]
|
|
11
|
+
files:
|
|
12
|
+
- toga25-supply/src/hooks/useDeploymentGuard.tsx
|
|
13
|
+
- toga25-supply/src/App.tsx
|
|
14
|
+
related: []
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Summary
|
|
18
|
+
|
|
19
|
+
On large deployments the backend bumps the Core parameter
|
|
20
|
+
`META_LAST_REFRESH_DATETIME`. The frontend watches that value and, when it changes
|
|
21
|
+
mid-session, **force-signs-out** every logged-in user so their session, `localStorage`,
|
|
22
|
+
and React Query cache (including the persisted `supply-chain-query-cache`) reset cleanly
|
|
23
|
+
and they pick up the new build and data. Implemented as a headless `<DeploymentGuard />`
|
|
24
|
+
component driven by the `useDeploymentGuard` hook, mounted inside the
|
|
25
|
+
`AuthProvider` / `ToasterProvider` tree in `App.tsx`.
|
|
26
|
+
|
|
27
|
+
## How it works
|
|
28
|
+
|
|
29
|
+
1. **Poll the Core parameter.** A TanStack `useQuery` reads
|
|
30
|
+
`META_LAST_REFRESH_DATETIME` via
|
|
31
|
+
`apiGet("/core-parameters", { fields: ["value"], key: "META_LAST_REFRESH_DATETIME" })`,
|
|
32
|
+
reading `response.data.coreParameters` (tolerant of the value arriving as either an
|
|
33
|
+
array or a single object). The query is:
|
|
34
|
+
- `enabled` only while authenticated,
|
|
35
|
+
- `staleTime: 0`,
|
|
36
|
+
- `refetchOnWindowFocus: true`,
|
|
37
|
+
- `refetchInterval` of 5 minutes.
|
|
38
|
+
|
|
39
|
+
2. **Establish a baseline.** The value observed right after login is stored in the
|
|
40
|
+
`localStorage` key `deployment-version`. The **first** observation only sets the
|
|
41
|
+
baseline — it never logs out. The mismatch check is skipped entirely when no baseline
|
|
42
|
+
exists.
|
|
43
|
+
|
|
44
|
+
3. **Detect a change.** A later fetch whose value differs from the stored baseline
|
|
45
|
+
triggers the reset.
|
|
46
|
+
|
|
47
|
+
4. **Reset UX.** On mismatch it shows a **non-dismissing info toast**
|
|
48
|
+
("A new version is available — signing you out briefly…"), waits **2.5s** for
|
|
49
|
+
readability, then calls the existing `AuthContext` `logout()`.
|
|
50
|
+
|
|
51
|
+
5. **Centralized logout does the wipe.** `logout()` already runs
|
|
52
|
+
`performLogout()` + `clearUser()` + `localStorage.clear()` (which wipes **all**
|
|
53
|
+
`localStorage` — tokens, `zu-user`, `zu-hostname`, the persisted query cache, and the
|
|
54
|
+
`deployment-version` baseline) + `queryClient.clear()`, then `performLogout()`
|
|
55
|
+
hard-redirects to `/`.
|
|
56
|
+
|
|
57
|
+
### Why there is no logout loop
|
|
58
|
+
|
|
59
|
+
Because `logout()` clears the baseline and reloads, the next login's first fetch simply
|
|
60
|
+
re-establishes the baseline (the mismatch check is skipped when no baseline exists). This
|
|
61
|
+
is simpler than the sibling `toga2-commerce` implementation
|
|
62
|
+
(`src/contexts/AuthContext.tsx`), which polls the same Core parameter but had to
|
|
63
|
+
preserve the value across logout. toga25-supply's centralized `logout()`
|
|
64
|
+
(`localStorage.clear` + `queryClient.clear` + `performLogout` redirect) made the port
|
|
65
|
+
cleaner.
|
|
66
|
+
|
|
67
|
+
## Change history
|
|
68
|
+
- 2026-07-21 — Built `useDeploymentGuard` / `<DeploymentGuard />`, force-logout on
|
|
69
|
+
`META_LAST_REFRESH_DATETIME` change; ported from toga2-commerce's AuthContext poll but
|
|
70
|
+
simplified via the centralized `logout()` (apeterson)
|
package/knowledge/INDEX.md
CHANGED
|
@@ -29,7 +29,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
29
29
|
- **voice-to-voice** (TOGa Voice) — 4 doc(s) → [2.0/apps/voice-to-voice/INDEX.md](2.0/apps/voice-to-voice/INDEX.md)
|
|
30
30
|
- **ai-bdr** (AI-BDR) — 8 doc(s) → [2.0/apps/ai-bdr/INDEX.md](2.0/apps/ai-bdr/INDEX.md)
|
|
31
31
|
- **toga2-commerce** (TOGa Commerce) — 9 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
|
|
32
|
-
- **toga25-supply** (TOGa 2.5 Supply) —
|
|
32
|
+
- **toga25-supply** (TOGa 2.5 Supply) — 11 doc(s) → [2.0/apps/toga25-supply/INDEX.md](2.0/apps/toga25-supply/INDEX.md)
|
|
33
33
|
- **toga-blox** (TOGa Blox) — 8 doc(s) → [2.0/apps/toga-blox/INDEX.md](2.0/apps/toga-blox/INDEX.md)
|
|
34
34
|
- **bdr** (BDR) — 0 doc(s) → [2.0/apps/bdr/INDEX.md](2.0/apps/bdr/INDEX.md)
|
|
35
35
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: session
|
|
3
|
+
slug: true-79191-fulfill-ship
|
|
4
|
+
title: TRUE-79191 Fulfill & Ship — review fixes, deployment order, UoM plan
|
|
5
|
+
author: mhammontree
|
|
6
|
+
repos: [toga2-supply, _underscore, api2, dbchanges2]
|
|
7
|
+
framework: "2.0"
|
|
8
|
+
client: shared
|
|
9
|
+
status: active
|
|
10
|
+
created: 2026-07-21
|
|
11
|
+
updated: 2026-07-21
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Session: true-79191-fulfill-ship
|
|
15
|
+
**Date:** 2026-07-21
|
|
16
|
+
**Project/Repo:** toga2-supply (2.0), with _underscore / api2 / dbchanges2 backend
|
|
17
|
+
**Task:** TRUE-79191 Fulfill & Ship — apply David/Jeff review fixes to the Fulfill & Ship UI, produce the deployment order, and design a package units-of-measure change.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## What WORKED
|
|
22
|
+
<!-- All UI fixes below were verified by the developer in the browser this session -->
|
|
23
|
+
- Google Maps links fixed and verified. `GoogleMapsLink.tsx` now maps the physical address (`street||line1`, line2, city, `state.name`, zip) and EXCLUDES the addressee; the Edit Return Label modal's "Google Maps" span was wired with an `onClick`. Both open the correct location. (commit 651e9d9d0)
|
|
24
|
+
- Select Items horizontal scrollbar gone. Description truncation cap lowered per-table: Select Items (13 cols) `max-w-[20vw]`, Update Info (8 cols) keeps `max-w-[30vw]`. CSS `truncate` + `title` tooltip preserved. (651e9d9d0)
|
|
25
|
+
- Select Items row-click selects the row. Added `onRowClick` to `BasicTable` (ignores clicks on `input,button,a,select,textarea,label`); ShipmentItemsTable rows carry `uuid`, disabled rows skipped; the quantity input and checkbox still behave normally. (651e9d9d0)
|
|
26
|
+
- Item images display with placeholder fallback (verified: item with image shows it, items without show the placeholder). Uses computed `_underscore` Item fields `item._imageUrl` (Items.imageId→Images.sourceUrl) and `item._thumbnailImageUrl` (ItemImages default), rendered `_imageUrl || _thumbnailImageUrl || placeholder`. (commit dc900ea4e)
|
|
27
|
+
- Earlier this session, all committed + verified on TRUE-79191: SKU/UPC display fix (skuNumber/upcCode field-selectors), mint-green dirty-field border, red Delete Shipment button, reference-field hint text, responsive description truncation, table header/alignment + sticky-border fixes.
|
|
28
|
+
- Local test data seeded in Client_Growrk (SKU/UPC/Dell manufacturer on items 139/276; test image on item 139). DB-only, not in any repo.
|
|
29
|
+
|
|
30
|
+
## What did NOT work — DO NOT RETRY THESE
|
|
31
|
+
- Saving a shipment returned `EO-1` "There is no field called 'needsReturnLabel' in the '_Model_Client_TrackingNumber' model." Root cause was a **git branch mismatch across repos** (_underscore was on a branch whose generated `Model/Client/TrackingNumber.php` lacked the field). DO NOT chase this as opcache (local php.ini has opcache DISABLED — `;zend_extension=opcache` — so files reload per request, no Apache restart needed) and DO NOT re-apply the migrations (the DB column, Core RecordField, and client AclFieldPermission were all already applied). Fix = put all fulfill/ship repos on the same branch (TRUE-79191).
|
|
32
|
+
- Hard-deleting duplicate item 2742 (merging into primary item 276) failed: `Cannot delete or update a parent row: ItemFulfillmentItemUnits_unitId FK` — item 2742's unit (serial FQ25WL3) is tied to a fulfillment record, and 276 already has its own FQ25WL3 unit. DO NOT DELETE 2742. Resolution used: repoint 2742's 8 SalesOrderItems to 276, NULL 2742's manufacturer to free the (catalog1, Dell, LATITUDE) unique slot, set 276 to Dell; 2742 left as an unreferenced stub (fulfillment history preserved).
|
|
33
|
+
|
|
34
|
+
## Not tried yet (candidates for next session)
|
|
35
|
+
- Implement the package Units of Measure change (see plan) — NOT started; gated on Jeff's opt-in on the design.
|
|
36
|
+
- Promote the Growrk-only bridge-ACL migration (`Client_Growrk/2026-07-13a - ItemFulfillmentItemReceiptTrackingNumberAclLogicGroups.sql`) to a generic `Client/` fan-out migration so ALL clients get the tracking-number bridge AclLogicGroups (records 317-322) — needed for a multi-client rollout (otherwise 403 EZ-1 per client). Documented in the deployment order.
|
|
37
|
+
|
|
38
|
+
## Current file state
|
|
39
|
+
| File | Status | Notes |
|
|
40
|
+
|------|--------|-------|
|
|
41
|
+
| toga2-supply (branch TRUE-79191) | committed & (merged to production earlier) | 5 session commits: 80724c1c2, 853b82e09, f041cfe57, dc900ea4e, 651e9d9d0 |
|
|
42
|
+
| toga2-supply/.env, .env.development, package-lock.json | modified, intentionally UNSTAGED | pre-existing local changes — never commit (.env is secrets/local) |
|
|
43
|
+
| _underscore, api2, dbchanges2 (branch TRUE-79191) | committed/pushed (partly merged to _production) | TRUE-79191 backend + DB migrations; unchanged this session (referenced only) |
|
|
44
|
+
| c:\WWW\TRUE-79191_deployment_order.md | created (external, not a repo) | Deploy order (DB→backend→frontend) + all-clients section; share to ClickUp |
|
|
45
|
+
| c:\WWW\package_units_of_measure_plan.md | created (external) | UoM design for Jeff; updated to enum-for-types (zero new tables recommended) |
|
|
46
|
+
| Client_Growrk DB (local) | test data only | items 139/276 SKU/UPC/Dell + item 139 test image; revert SQL was provided in chat |
|
|
47
|
+
|
|
48
|
+
## Decisions made
|
|
49
|
+
- **Item image source:** render `item._imageUrl || item._thumbnailImageUrl || placeholder` — covers `Items.imageId` (single primary image) OR `ItemImages` (default thumbnail), else placeholder. Rejected: hardcoding placeholder (the pre-existing bug) or a single source.
|
|
50
|
+
- **Responsive truncation:** CSS `truncate` + a per-table viewport-relative `max-w-[NNvw]` cap (tuned by column count) + native `title` tooltip. Rejected: fixed char-count truncation (ExpandableCellContent) — not width-responsive and truncates early.
|
|
51
|
+
- **Google Maps query:** map the address only, never the addressee. Rejected: including the recipient name (caused Google to surface the person).
|
|
52
|
+
- **BasicTable row selection:** an `onRowClick` prop that ignores interactive descendants, rather than per-cell handlers. Reusable across tables.
|
|
53
|
+
- **Units of Measure (design, per Jeff):** measurement *types* are an ENUM (`measureType` LENGTH/VOLUME/WEIGHT/COUNT) — NO separate types table. Recommended to REUSE the existing client `Measures` table (already used by `Items.defaultMeasureId`) + add `conversionFactorToBase`, and add `dimensionMeasureId`/`volumeMeasureId` FKs on `TrackingNumbers` → **zero new tables**. Alternative (two dedicated new UoM tables) documented for opt-in. Carriers accept only IN/CM (dimensions) and LB/KG (weight), so the chosen measure must map/convert to the carrier enum (hence the conversion factor); volume is not sent to carriers.
|
|
54
|
+
|
|
55
|
+
## Blockers
|
|
56
|
+
- none blocking code. The UoM implementation is gated on Jeff opting in to the design (which table strategy; is volume stored or derived; include weight unit too; core vs client seeding).
|
|
57
|
+
|
|
58
|
+
## Exact next step
|
|
59
|
+
> Get Jeff's decision on `c:\WWW\package_units_of_measure_plan.md` (reuse `Measures` + `measureType` enum vs two new tables; volume stored vs derived; include weight UoM; core vs client), and whether the UoM work rides TRUE-79191 or becomes a new ticket. Then implement following the `needsReturnLabel` full-stack pattern (dbchanges2 migrations → `_underscore` Measure/TrackingNumber models → api2 field-selectors → toga2-supply UnitSelect wiring + Pending Shipments display). Separately, the deployment team runs `c:\WWW\TRUE-79191_deployment_order.md` — flag the FedEx production-endpoint config (beta.ini used sandbox) + api2 FPDF `composer install`, and the Client/ fan-out of the bridge-ACL migration for all clients.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
_Saved by /session-save on 2026-07-21_
|
package/package.json
CHANGED