toga-ai 1.0.238 → 1.0.239

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,5 +6,6 @@
6
6
  | [Cart Notification Emails — duplicate prevention](features/cart-notification-emails.md) | On the cart "Notifications" section a user can add CC email addresses to an order. | src/pages/Cart/CartPage.tsx, src/pages/Cart/view/cartForm/CartForm.tsx, src/stores/useEmailOptionsStore.ts, src/stores/useCartSalesQuoteZu.ts, src/pages/Cart/viewModel/FIELDS/*/*/*/CARTPAGE.ts |
7
7
  | [Cart Page — config-driven form architecture (current state + planned refactor)](features/cart-page-config-architecture.md) | The Cart page (`src/pages/Cart/`) is the most config-heavy page in `toga2-commerce`. | src/pages/Cart/CartPage.tsx, src/pages/Cart/view/cartForm/CartForm.tsx, src/pages/Cart/view/cartForm/CartFormSection.tsx, src/pages/Cart/view/cartForm/CartFormRenderer.tsx, src/pages/Cart/view/EditCart.tsx, src/pages/Cart/view/EditOrder.tsx, src/pages/Cart/viewModel/useEditOrderOrEditCartViewModel.ts, src/pages/Cart/viewModel/FIELDS/*/*/*/CARTPAGE.ts, src/hooks/useAssignClientFields.ts |
8
8
  | [Client Fields — per-tenant / language / role content & config](features/client-fields.md) | Almost no user-facing text, field layout, or page config is hard-coded in `toga2-commerce`. | src/fieldsConfig/index.ts, src/fieldsConfig/getClientLoginFields.ts, src/fieldsConfig/clientFields/COMPASS.json, src/fieldsConfig/clientFields/COMPASSCANADA.json, src/fieldsConfig/clientFields/QUAD.json, src/hooks/useAssignClientFields.ts, src/hooks/useDynamicConditionalFieldOptions.ts, src/stores/useFieldsStore.ts, src/components/BaseDetailField/BaseDetailField.tsx |
9
+ | [Config-Driven Expedited Shipping Gating (Cart)](features/expedited-shipping-gating.md) | On the toga2-commerce **Cart** page, expedited shipping options (**"2nd Day EOB"** and **"Next Day Air"**) are only offered in the *Shipping Method* dropdown wh | toga2-commerce/src/pages/Cart/helpers/shippingOptionGates.ts, toga2-commerce/src/pages/Cart/viewModel/FIELDS/shared/shippingOptionGates.ts, toga2-commerce/src/pages/Cart/view/cartForm/CartForm.tsx, toga2-commerce/src/pages/Cart/CartPage.tsx |
9
10
  | [Multi-Tenant Resolution & Theming](features/multi-tenant-theming.md) | `toga2-commerce` serves multiple clients from one codebase. | src/themeConfig/themes.json, src/themeConfig/ThemeContext.tsx, src/themeConfig/types.ts, src/components/ThemeSwitcher/ThemeSwitcher.tsx, src/components/AuthLayout/AuthLayout.tsx, src/api/axiosInstance.ts, src/contexts/AuthContext.tsx, tailwind.config.js |
10
11
  | [AWS Amplify Build & Deploy (non-prod environments)](workflows/amplify-build-and-deploy.md) | How `toga2-commerce` (React + Vite, "commerce2-react") builds and deploys on **AWS Amplify**. | toga2-commerce/amplify.yml, toga2-commerce/.gitattributes, toga2-commerce/package.json, toga2-commerce/.github/workflows/sync-stage-environments.yml |
@@ -0,0 +1,108 @@
1
+ ---
2
+ title: Config-Driven Expedited Shipping Gating (Cart)
3
+ framework: "2.0"
4
+ repo: toga2-commerce
5
+ project: TOGa Commerce
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-06-30
10
+ owners: [tcox]
11
+ files:
12
+ - toga2-commerce/src/pages/Cart/helpers/shippingOptionGates.ts
13
+ - toga2-commerce/src/pages/Cart/viewModel/FIELDS/shared/shippingOptionGates.ts
14
+ - toga2-commerce/src/pages/Cart/view/cartForm/CartForm.tsx
15
+ - toga2-commerce/src/pages/Cart/CartPage.tsx
16
+ related:
17
+ - ../../../../clients/compass-usa/profile.md
18
+ - ../../../../clients/compass-canada/profile.md
19
+ ---
20
+
21
+ ## Summary
22
+ On the toga2-commerce **Cart** page, expedited shipping options (**"2nd Day EOB"** and
23
+ **"Next Day Air"**) are only offered in the *Shipping Method* dropdown when the cart contains
24
+ a **computer kit**. Otherwise they are filtered out of the options, and any previously
25
+ selected expedited method auto-resets to **"Standard Ground"**. The behavior is **config
26
+ driven** — a tenant opts in per shipping-method field via an `optionGates` entry; there is no
27
+ `if (clientSlug === ...)` branching. Omitting `optionGates` means expedited is always shown.
28
+
29
+ Applies today to all three tenants: **COMPASS**, **COMPASSCANADA** (English + French), and
30
+ **QUAD**.
31
+
32
+ ## Key files / entry points
33
+ - `src/pages/Cart/helpers/shippingOptionGates.ts` (NEW) — pure helpers + types:
34
+ `ShippingOptionGate` / `ShippingOptionRule`, `filterShippingOptionsByGates`,
35
+ `getHiddenShippingOptionNames`, `evaluateShippingOptionRule`, `findShippingMethodField`
36
+ (resolves the shipping field by `valueKey`, **not** by index), `getBaseShippingOptionName` +
37
+ `SHIPPING_OPTION_LABEL_SEPARATOR`, and `STANDARD_GROUND_SHIPPING_NAME`.
38
+ - `src/pages/Cart/viewModel/FIELDS/shared/shippingOptionGates.ts` (NEW) — the
39
+ `EXPEDITED_SHIPPING_GATE` config constant: `optionNames` `["2nd Day EOB","Next Day Air"]`,
40
+ `visibleWhen { item: "primaryItem", path: "item.itemCategory.name", operator: "equals",
41
+ value: "COMPUTERS" }`.
42
+ - 15 `CARTPAGE.ts` files (COMPASS x4 roles, COMPASSCANADA ENGLISH x4 + FRENCH x4, QUAD x3) —
43
+ each shipping-method field opts in via `optionGates: [EXPEDITED_SHIPPING_GATE]`.
44
+ - `src/pages/Cart/view/cartForm/CartForm.tsx` — filters `shippingMethodOptions` through the
45
+ gates (reactive on `cartData.cartBundles`) before the select renders; resolves the shipping
46
+ field via `findShippingMethodField`; uses `SHIPPING_OPTION_LABEL_SEPARATOR` for the
47
+ cost-suffix label.
48
+ - `src/pages/Cart/CartPage.tsx` — the warning-modal effect derives expedited names from the
49
+ config gates; a NEW auto-reset effect (guarded on `dirtyFields.shippingMethod` + loaded
50
+ options) resets a now-hidden expedited selection back to Standard Ground.
51
+
52
+ ## How it works
53
+ 1. The config layer (`EXPEDITED_SHIPPING_GATE`) declares which option names are gated and the
54
+ condition under which they are *visible* (`visibleWhen`). A shipping-method field opts in by
55
+ listing the gate in `optionGates`.
56
+ 2. A **"computer kit"** is identified by the bundle's **PRIMARY item** —
57
+ `bundleItemGroup.slug === "primary"` — having `item.itemCategory.name === "COMPUTERS"`. This
58
+ reuses the same `{ item, path, operator, value }` rule vocabulary as the existing bundle-page
59
+ one-per-order limit (`evaluateCartQuantityRestriction.ts` + `restrictedQuantity` in
60
+ `BUNDLEDETAILSPAGE.json` / `CartOverlay/Bundle.tsx`). `value` may be a string **or** a
61
+ `string[]`, so qualifying categories stay editable in config without code changes.
62
+ 3. Cart contents are sourced from `useCartStoreZu` (`cartData.cartBundles`), so detection
63
+ reacts to add/remove. A computer kit plus a non-computer item (printer/accessory) still
64
+ shows expedited; removing the kit hides it.
65
+ 4. `CartForm` runs `filterShippingOptionsByGates` over the fetched options before rendering the
66
+ select; `CartPage` runs the auto-reset effect so an already-chosen expedited method does not
67
+ silently survive once it is no longer offered.
68
+
69
+ This mirrors the toga2.5 / toga25-supply "named rule" / config-driven cart pattern: tenant
70
+ behavior is expressed in config, not in code branches.
71
+
72
+ ## Gotchas
73
+ - **Compass MacBook catalog categorization is INCONSISTENT, and it breaks the computer-kit
74
+ assumption.** Verified in prod `Client_Compass.Items`: MacBooks are spread across at least
75
+ **four** categories — `"APPLE LAPTOP"` (e.g. 14" MacBook Pro M5, partNumber `MDE54LL/A-S`),
76
+ `"COMPUTERS"` (14"/16" MacBook Pro M4, `MW2W3LLA-S` / `MX2X3LLA-S`), `"MAC & ACCESSORIES"`
77
+ (~18 older M1/M2 MacBook Air/Pro models), and `"PDC NEW HIRE - APPLE"`. The gate matches
78
+ `itemCategory.name === "COMPUTERS"` **only**, so MacBooks tagged `APPLE LAPTOP` /
79
+ `MAC & ACCESSORIES` do **not** qualify for expedited shipping (and would not trigger the
80
+ one-per-order limit either). Confirmed live on beta and prod: the "Compass 14\" Macbook"
81
+ kit's primary item resolves to `APPLE LAPTOP`. The backend assumption (Alex) was that all
82
+ MacBooks were already `COMPUTERS`; the data shows otherwise. **Team decision this session:**
83
+ keep the rule keyed to `COMPUTERS` only (intended). The fix is **catalog data
84
+ normalization** (or extending the config `value` list to
85
+ `["COMPUTERS","APPLE LAPTOP"]`) — it is *not* a code gap. Hand the categorization to the
86
+ catalog/data team.
87
+ - **The gate is UI-only, not server-enforced.** Shipping methods come from `/shipping-methods`
88
+ (UPS carrier, fetched in `useCartViewModel`) and are filtered client-side. The gate is a
89
+ selection restriction, not order validation. Follow-up recommended: enforce
90
+ expedited-requires-kit at order submission in **api2**.
91
+ - **Only the top-level primary item is scanned.** Nested child-bundle items are not inspected
92
+ for the computer category (consistent with the existing `checkCartContainsComputerKit`
93
+ detector). Fine today, but a miss if a `COMPUTERS` item ever lives only in a nested child
94
+ bundle.
95
+ - **No automated test was added.** The repo has no unit-test runner (Cypress only). Verified
96
+ via `tsc -b` (clean, twice) and an independent maker≠checker code review. ESLint could not
97
+ run locally (missing `eslint-plugin-react-compiler` — environment issue).
98
+
99
+ ## Change history
100
+ - 2026-06-30 — Built config-driven expedited-shipping gating: expedited methods shown only
101
+ when the cart holds a COMPUTERS-category computer kit, with auto-reset to Standard Ground
102
+ otherwise; tenant opt-in via `optionGates` (no client-slug branching). Code review fixed 3
103
+ findings: fail-open index read → resolve field by `valueKey`; substring `.includes` match →
104
+ base-name compare via `getBaseShippingOptionName`; edit-order silent-downgrade/load race →
105
+ reset guarded on dirty + loaded options. Documented the Compass MacBook category
106
+ inconsistency as a known gotcha (data-normalization item, not a code gap). (tcox)
107
+ </content>
108
+ </invoke>
@@ -27,7 +27,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
27
27
  - **talos** (TOGa IQ) — 7 doc(s) → [2.0/apps/talos/INDEX.md](2.0/apps/talos/INDEX.md)
28
28
  - **voice-to-voice** (TOGa Voice) — 4 doc(s) → [2.0/apps/voice-to-voice/INDEX.md](2.0/apps/voice-to-voice/INDEX.md)
29
29
  - **ai-bdr** (AI-BDR) — 4 doc(s) → [2.0/apps/ai-bdr/INDEX.md](2.0/apps/ai-bdr/INDEX.md)
30
- - **toga2-commerce** (TOGa Commerce) — 6 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
30
+ - **toga2-commerce** (TOGa Commerce) — 7 doc(s) → [2.0/apps/toga2-commerce/INDEX.md](2.0/apps/toga2-commerce/INDEX.md)
31
31
  - **toga25-supply** (TOGa 2.5 Supply) — 7 doc(s) → [2.0/apps/toga25-supply/INDEX.md](2.0/apps/toga25-supply/INDEX.md)
32
32
  - **toga-blox** (TOGa Blox) — 7 doc(s) → [2.0/apps/toga-blox/INDEX.md](2.0/apps/toga-blox/INDEX.md)
33
33
 
@@ -13,11 +13,12 @@ project: _Underscore
13
13
  client: compass-canada
14
14
  type: profile
15
15
  status: active
16
- updated: 2026-06-26
17
- owners: [jcardinal, bala]
16
+ updated: 2026-06-30
17
+ owners: [jcardinal, bala, tcox]
18
18
  files: []
19
19
  related:
20
20
  - ../compass-usa/profile.md
21
+ - ../../2.0/apps/toga2-commerce/features/expedited-shipping-gating.md
21
22
  ---
22
23
 
23
24
  ## Summary
@@ -41,6 +42,11 @@ to but distinct from Compass USA. Like Compass USA it spans the **2.0** commerce
41
42
  (`1_…` transmit SOs to MITS, `2_…` transmit POs to vendors, `3_…` status from G&T cXML,
42
43
  `4_…` import G&T ASNs).
43
44
 
45
+ ## Storefront notes (toga2-commerce)
46
+ - Runs the same `toga2-commerce` storefront (2.0, consumes api2), with English + French cart
47
+ configs (COMPASSCANADA ENGLISH / FRENCH). Cart expedited-shipping gating applies here too —
48
+ see [Config-Driven Expedited Shipping Gating](../../2.0/apps/toga2-commerce/features/expedited-shipping-gating.md).
49
+
44
50
  ## Notes
45
51
  - Customer language preference: `UserGlobalSettings.settingId = 2` (`en` / `fr-CA`); customer-
46
52
  facing emails are sent in EN or FR accordingly.
@@ -12,11 +12,12 @@ project: _Underscore
12
12
  client: compass-usa
13
13
  type: profile
14
14
  status: active
15
- updated: 2026-06-18
16
- owners: [jcardinal, bala]
15
+ updated: 2026-06-30
16
+ owners: [jcardinal, bala, tcox]
17
17
  files: []
18
18
  related:
19
19
  - features/asn-to-item-fulfillment.md
20
+ - ../../2.0/apps/toga2-commerce/features/expedited-shipping-gating.md
20
21
  ---
21
22
 
22
23
  ## Summary
@@ -32,7 +33,16 @@ separate, related client (see its own profile).
32
33
  Client-specific model overrides live under `_underscore/Model/Compass/`.
33
34
  - **1.0:** worker crons under `worker/crons/toga2/compass/` handle email-based imports and
34
35
  notifications.
35
- - Storefront: compass.togacommerce.com / compass.togahub.com.
36
+ - Storefront: compass.togacommerce.com / compass.togahub.com. The storefront app repo is
37
+ **`toga2-commerce`** (2.0, consumes api2).
38
+
39
+ ## Storefront notes (toga2-commerce)
40
+ - Cart expedited-shipping gating: expedited methods ("2nd Day EOB", "Next Day Air") are shown
41
+ only when the cart contains a COMPUTERS-category computer kit — see
42
+ [Config-Driven Expedited Shipping Gating](../../2.0/apps/toga2-commerce/features/expedited-shipping-gating.md).
43
+ **Known data issue:** many Compass MacBooks are categorized `APPLE LAPTOP` /
44
+ `MAC & ACCESSORIES`, not `COMPUTERS`, so those kits do **not** qualify for expedited — a
45
+ catalog-data normalization matter, not a code gap.
36
46
 
37
47
  ## Vendors & integrations
38
48
  - **Office Depot (ODP)** — vendor id 1. ASNs arrive via **cXML** (direct V2 API) and via the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.238",
3
+ "version": "1.0.239",
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",