toga-ai 1.0.349 → 1.0.351
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/api2/INDEX.md +1 -0
- package/knowledge/2.0/apps/api2/features/tableview-apiwhereclause-row-filtering.md +115 -0
- package/knowledge/2.0/apps/toga2-supply/INDEX.md +1 -1
- package/knowledge/2.0/apps/toga2-supply/features/fulfill-and-ship.md +55 -1
- package/knowledge/INDEX.md +1 -1
- package/knowledge/clients/compass-usa/INDEX.md +1 -1
- package/knowledge/clients/compass-usa/features/item-fulfillment-tracking-tableview.md +20 -2
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
| [Nested-relationship writes & child matching (link vs. create)](features/nested-relationship-writes.md) | When a 2.0 API write payload (`POST`/`PUT`) contains a **nested related object** (e.g. | api2/Component/Api/V2/V2.php |
|
|
10
10
|
| [POST + JSON-body args for scripted APIs](features/scripted-api-post-body-args.md) | The V2 engine can run a Record Script (scripted API) for a **POST** request, and a scripted API can receive its arguments from the **JSON request body** instead | api2/Component/Api/V2/V2.php |
|
|
11
11
|
| [Surface action-state via the surface=<slug> request option (M2M-safe)](features/surface-meta-option.md) | An opt-in V2 engine request option, `surface=<slug>`, that attaches per-record UI action state (`isVisible`/`isEnabled`) to a GET response **under `meta.surface | api2/Component/Api/V2/V2.php, _underscore/Model/Core/Surface.php |
|
|
12
|
+
| [TableView row-filtering via apiWhereClause (options.where grammar, end to end)](features/tableview-apiwhereclause-row-filtering.md) | `TableViews.apiWhereClause` (TEXT, nullable) is the sanctioned, code-free way to restrict or exclude rows from a 2.0 table view. | api2/Component/Api/V2/V2.php, _underscore/Model/Client/TableView.php, toga2-supply/src/api/toga.ts |
|
|
12
13
|
| [Tickets API (/v2/tickets)](features/tickets-api.md) | The generic ticket endpoint of the 2.0 REST API. | Component/Api/V2/V2.php |
|
|
13
14
|
| [AWS CodePipeline Deployment via CodeConnections (GitHub → Elastic Beanstalk)](workflows/codepipeline-codeconnections-deploy.md) | 2.0 apps (`api2`, `_underscore`) are deployed through **AWS CodePipeline**. | |
|
|
14
15
|
| [New Environment Configuration & Provisioning (api2)](workflows/environment-configuration-and-provisioning.md) | What it takes for a 2.0 API environment (e.g. | api2/Config/<environment>.ini, api2/Controller/Index.php, dbchanges2/Core/2026-06-16a - DatabaseHosts for new QA QC stage demo environments.sql, _underscore/Route.php |
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TableView row-filtering via apiWhereClause (options.where grammar, end to end)
|
|
3
|
+
framework: "2.0"
|
|
4
|
+
repo: api2
|
|
5
|
+
project: API
|
|
6
|
+
client: shared
|
|
7
|
+
type: feature
|
|
8
|
+
status: active
|
|
9
|
+
updated: 2026-07-15
|
|
10
|
+
owners: ["bala"]
|
|
11
|
+
files:
|
|
12
|
+
- api2/Component/Api/V2/V2.php
|
|
13
|
+
- _underscore/Model/Client/TableView.php
|
|
14
|
+
- toga2-supply/src/api/toga.ts
|
|
15
|
+
related:
|
|
16
|
+
- ../../../clients/compass-usa/features/item-fulfillment-tracking-tableview.md
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Summary
|
|
20
|
+
|
|
21
|
+
`TableViews.apiWhereClause` (TEXT, nullable) is the sanctioned, code-free way to restrict or
|
|
22
|
+
exclude rows from a 2.0 table view. The clause is stored on the view, emitted verbatim in the
|
|
23
|
+
view meta by `_underscore`, pushed into the data request's `options.where.and` by the frontend,
|
|
24
|
+
and finally parsed into SQL by api2's `parseOptionsWhere`. Because api2 parses it for *every*
|
|
25
|
+
data request, the same `field:operator:value` grammar governs any `options.where` filter — table
|
|
26
|
+
views are just one producer of it. Use this to add a "restrict/exclude these rows" rule to a
|
|
27
|
+
view with a migration and no application code.
|
|
28
|
+
|
|
29
|
+
## Key files / entry points
|
|
30
|
+
|
|
31
|
+
- **Emission** — `_underscore/Model/Client/TableView.php`, the `meta()` scripted API (~line 51):
|
|
32
|
+
emits `TableViews.apiWhereClause` verbatim in the view meta, and builds `join`/`ojoin` entries
|
|
33
|
+
from `TableViewJoins` (~line 631-641 of the consumer) so every table joined in the view is
|
|
34
|
+
present on the data request.
|
|
35
|
+
- **Consumption** — `toga2-supply/src/api/toga.ts` (~line 943-951): pushes the `apiWhereClause`
|
|
36
|
+
literal string into `options.where.and`, and (~line 631-641) builds `options.join` / `ojoin`
|
|
37
|
+
from the view's `TableViewJoins`.
|
|
38
|
+
- **Parsing** — `api2/Component/Api/V2/V2.php::parseOptionsWhere` (~line 7574-7773): turns the
|
|
39
|
+
clause string into SQL.
|
|
40
|
+
|
|
41
|
+
## How it works
|
|
42
|
+
|
|
43
|
+
Clause syntax: `field:operator:value`. Conditions are comma-separated, grouped with parens, and
|
|
44
|
+
joined with `,AND,` / `,OR,` between conditions. The parser tracks parenthesis depth and only
|
|
45
|
+
splits conditions on commas at the **top** depth.
|
|
46
|
+
|
|
47
|
+
Operator tokens map to SQL as:
|
|
48
|
+
|
|
49
|
+
| token | SQL |
|
|
50
|
+
|-------|-----|
|
|
51
|
+
| `eq` | `=` |
|
|
52
|
+
| `ne` | `<>` |
|
|
53
|
+
| `gt` | `>` |
|
|
54
|
+
| `ge` | `>=` |
|
|
55
|
+
| `lt` | `<` |
|
|
56
|
+
| `le` | `<=` |
|
|
57
|
+
| `like` | `LIKE` |
|
|
58
|
+
| `contains` / `starts` / `ends` | wildcarded `LIKE` |
|
|
59
|
+
| `excludes` | `NOT LIKE` |
|
|
60
|
+
| `in` | `IN` |
|
|
61
|
+
| `notin` | `NOT IN` |
|
|
62
|
+
| `between` | `BETWEEN` |
|
|
63
|
+
| `not` | `NOT` |
|
|
64
|
+
|
|
65
|
+
The field slot accepts a **raw SQL expression**, not just a plain column — e.g.
|
|
66
|
+
`YEAR(SalesOrders.dateOrder)` or `IFNULL(Items.assetTypeId,0)`. Real-world example (the FEE
|
|
67
|
+
exclusion on the Compass fulfillment view): `(IFNULL(Items.assetTypeId,0):ne:<FEE id>)` — the
|
|
68
|
+
`IFNULL(...,0)` keeps rows with a NULL FK from being silently dropped.
|
|
69
|
+
|
|
70
|
+
### Join alias rule (which table-qualified name to use)
|
|
71
|
+
|
|
72
|
+
In `_underscore/Model/Client/TableView.php` (~line 89-96), the **first** occurrence of a joined
|
|
73
|
+
table in a view gets the bare table name as its SQL alias (e.g. `Items`); each subsequent join to
|
|
74
|
+
the same table gets a `_B`, `_C`, … suffix (counter starts at ASCII 65). So an `apiWhereClause`
|
|
75
|
+
referencing `Items.<field>` only binds correctly when the view joins `Items` **exactly once**.
|
|
76
|
+
Before writing a clause, confirm the target table is joined once, or qualify against the correct
|
|
77
|
+
suffixed alias.
|
|
78
|
+
|
|
79
|
+
## Data model
|
|
80
|
+
|
|
81
|
+
- `TableViews.apiWhereClause` (TEXT, nullable) — the view-level row filter.
|
|
82
|
+
- `TableViewJoins` — the view's joins; drive `options.join` / `ojoin` so any table referenced in
|
|
83
|
+
the clause is present on the data request.
|
|
84
|
+
|
|
85
|
+
## Client variations
|
|
86
|
+
|
|
87
|
+
None — engine behavior. A specific client's view may carry its own `apiWhereClause` value.
|
|
88
|
+
|
|
89
|
+
## Gotchas / known issues
|
|
90
|
+
|
|
91
|
+
- **Comma inside a function is safe.** The parser only splits conditions on top-depth commas, so
|
|
92
|
+
a comma inside `IFNULL(x,0)` or `IN(...)` does not break the clause.
|
|
93
|
+
- **An expression field must NOT start with `(`.** A condition that starts with `(` is treated by
|
|
94
|
+
the parser as a nested group and recursed into — so wrap an expression field in a function that
|
|
95
|
+
starts with a letter (e.g. `IFNULL(...)`), never a bare parenthesized expression.
|
|
96
|
+
- **NULL FKs drop silently.** A plain `field:ne:x` excludes rows where `field IS NULL` too. Wrap
|
|
97
|
+
nullable columns in `IFNULL(col,<sentinel>)` when the intent is "exclude only these values."
|
|
98
|
+
- **Operator allowlist.** `parseOptionsWhere` whitelists the operators above and rejects unknown
|
|
99
|
+
ones (e.g. `regexp` returns a 500) — see the Compass cost-centers doc. Numeric/regex filtering
|
|
100
|
+
that the grammar can't express must be done client-side or by adding an operator to api2.
|
|
101
|
+
|
|
102
|
+
## Change history
|
|
103
|
+
|
|
104
|
+
- 2026-07-15 — Documented the end-to-end `apiWhereClause` row-filter mechanism (emission →
|
|
105
|
+
consumption → `parseOptionsWhere` grammar), the operator→SQL table, the raw-expression field
|
|
106
|
+
slot, the leading-paren / top-depth-comma parser behavior, and the `_underscore` join-alias
|
|
107
|
+
(`_B`/`_C`) rule. No code change — mechanism discovered while building the Compass FEE-exclusion
|
|
108
|
+
migration. (bala)
|
|
109
|
+
|
|
110
|
+
## Related docs
|
|
111
|
+
|
|
112
|
+
- `clients/compass-usa/features/item-fulfillment-tracking-tableview.md` — the Compass fulfillment
|
|
113
|
+
view (id 12) that first used this to exclude FEE-asset-type items.
|
|
114
|
+
- `clients/compass-usa/features/cost-centers.md` — notes `parseOptionsWhere` rejecting `regexp`
|
|
115
|
+
with a 500 (operator allowlist).
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
| Doc | Summary | Files |
|
|
4
4
|
|-----|---------|-------|
|
|
5
5
|
| [TOGa Supply (toga2-supply) Architecture](architecture.md) | `toga2-supply` is the **React + Vite frontend** for TOGa Supply — warehouse fulfillment tooling (shipment selection, fulfill & ship against carrier APIs, NetSui | toga2-supply/src/api/toga.ts, toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx |
|
|
6
|
-
| [Fulfill & Ship](features/fulfill-and-ship.md) | Fulfill & Ship lets a warehouse user select sales-order line items, enter serials, pick a carrier/method, and in one action: create the Item Fulfillment records | toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/view/components/forms/EditShipmentForm.tsx, toga2-supply/src/pages/EditShipment/view/components/SelectedShipmentItemsTable.tsx, toga2-supply/src/pages/EditShipment/view/helpers/ShipmentDetailsForm/renderEditShipmentFormInput.tsx, toga2-supply/src/pages/EditShipment/viewModel/FIELDS/DUMMYUPDATESHIPMENTFIELDS.json, toga2-supply/src/pages/EditShipment/helpers/ShipmentDetailsForm/renderEditShipmentFormInput.tsx, toga2-supply/tailwind.config.cjs, toga2-supply/src/pages/EditShipment/view/modals/ReturnShippingModal.tsx, toga2-supply/src/components/ui/BaseInput/BaseInput.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/EditShipment/helpers/ShipmentDetailsForm/formatShipmentData.ts, toga2-supply/src/pages/EditShipment/types.ts, toga2-supply/src/pages/Shipments/view/ShipmentsPage.tsx, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx, toga2-supply/src/pages/Shipments/api/ShipmentsApi.ts, toga2-supply/src/pages/Shipments/types.ts, toga2-supply/src/pages/FulfilledShipments/view/FulfilledShipmentsPage.tsx, toga2-supply/src/components/ui/CardTable/CardTable.tsx, toga2-supply/src/components/ui/CardTable/types.ts, toga2-supply/src/assets/pen-line.svg, _underscore/Model/Client/ItemFulfillment.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Component/Library/Carriers/Ups/Ups.php |
|
|
6
|
+
| [Fulfill & Ship](features/fulfill-and-ship.md) | Fulfill & Ship lets a warehouse user select sales-order line items, enter serials, pick a carrier/method, and in one action: create the Item Fulfillment records | toga2-supply/src/pages/ShipmentItems/view/ShipmentItemsPage.tsx, toga2-supply/src/pages/EditShipment/view/EditShipmentPage.tsx, toga2-supply/src/pages/EditShipment/view/components/forms/EditShipmentForm.tsx, toga2-supply/src/pages/EditShipment/view/components/SelectedShipmentItemsTable.tsx, toga2-supply/src/pages/EditShipment/view/helpers/ShipmentDetailsForm/renderEditShipmentFormInput.tsx, toga2-supply/src/pages/EditShipment/viewModel/FIELDS/DUMMYUPDATESHIPMENTFIELDS.json, toga2-supply/src/pages/EditShipment/helpers/ShipmentDetailsForm/renderEditShipmentFormInput.tsx, toga2-supply/tailwind.config.cjs, toga2-supply/src/pages/EditShipment/view/modals/ReturnShippingModal.tsx, toga2-supply/src/styles/index.scss, toga2-supply/src/components/ui/BaseInput/BaseInput.tsx, toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts, toga2-supply/src/pages/EditShipment/helpers/ShipmentDetailsForm/formatShipmentData.ts, toga2-supply/src/pages/EditShipment/types.ts, toga2-supply/src/pages/Shipments/view/ShipmentsPage.tsx, toga2-supply/src/pages/Shipments/view/components/ShipmentsCardTableForm/ShipmentsCardTableForm.tsx, toga2-supply/src/pages/Shipments/api/ShipmentsApi.ts, toga2-supply/src/pages/Shipments/types.ts, toga2-supply/src/pages/FulfilledShipments/view/FulfilledShipmentsPage.tsx, toga2-supply/src/components/ui/CardTable/CardTable.tsx, toga2-supply/src/components/ui/CardTable/types.ts, toga2-supply/src/assets/pen-line.svg, _underscore/Model/Client/ItemFulfillment.php, _underscore/Trait/Netsuite/ItemFulfillment.php, _underscore/Component/Library/Carriers/Ups/Ups.php |
|
|
7
7
|
| [AWS Amplify Build & Deploy (non-prod environments)](workflows/amplify-build-and-deploy.md) | How `toga2-supply` (React + Vite) builds and deploys on **AWS Amplify**. | toga2-supply/amplify.yml, toga2-supply/.gitattributes, toga2-supply/.github/workflows/sync-stage-environments.yml, toga2-supply/.env.qc-security |
|
|
@@ -18,6 +18,7 @@ files:
|
|
|
18
18
|
- toga2-supply/src/pages/EditShipment/helpers/ShipmentDetailsForm/renderEditShipmentFormInput.tsx
|
|
19
19
|
- toga2-supply/tailwind.config.cjs
|
|
20
20
|
- toga2-supply/src/pages/EditShipment/view/modals/ReturnShippingModal.tsx
|
|
21
|
+
- toga2-supply/src/styles/index.scss
|
|
21
22
|
- toga2-supply/src/components/ui/BaseInput/BaseInput.tsx
|
|
22
23
|
- toga2-supply/src/pages/EditShipment/api/UpdateShipmentApi.ts
|
|
23
24
|
- toga2-supply/src/pages/EditShipment/helpers/ShipmentDetailsForm/formatShipmentData.ts
|
|
@@ -187,6 +188,27 @@ bare string** — see the gotcha below before wiring a new select field.
|
|
|
187
188
|
(`onBlur` when `field.isCurrency`). Return modal (`ReturnShippingModal.tsx`): compact selects
|
|
188
189
|
vertically centered; Carrier Account # widened to `w-[172px]` to match Carrier.
|
|
189
190
|
|
|
191
|
+
### Edit Return Label modal — searchable Addressee combobox + discard guard (2026-07-15)
|
|
192
|
+
|
|
193
|
+
`ReturnShippingModal.tsx`:
|
|
194
|
+
- **Addressee is a searchable combobox built on a native `<input list>` + `<datalist>`** of
|
|
195
|
+
warehouse/location options — typing filters the list (Chromium does a substring "contains" match;
|
|
196
|
+
Firefox only prefix-matches) and **custom free text is still allowed**; selecting a known option
|
|
197
|
+
prefills the address via `applyWarehouse`. Prefer this native pattern over react-select when free
|
|
198
|
+
text plus suggestions are both wanted — but mind the two gotchas below.
|
|
199
|
+
- **Backdrop-click discard guard.** `BaseModal` calls its `onClose` prop on backdrop click, which
|
|
200
|
+
would silently discard unsaved edits. Pass a **guarded** handler to `BaseModal`'s `onClose`
|
|
201
|
+
(`if (formMethods.formState.isDirty) return; onClose();`) so an accidental outside click can't
|
|
202
|
+
drop a dirty form, while **Cancel and the header X still call the real `onClose`** to close/discard
|
|
203
|
+
explicitly. Reuse this pattern for any BaseModal wrapping an editable form.
|
|
204
|
+
|
|
205
|
+
### Shared checkbox restyled to the Figma design-system spec (2026-07-15)
|
|
206
|
+
|
|
207
|
+
`BaseInput.tsx`'s checkbox now matches the Figma checkbox component: **16px** (was 20px),
|
|
208
|
+
`rounded-sm`, unchecked border `navy-300`, checked fill `supply-blue-400` (`#3F5DCA`, the primary),
|
|
209
|
+
12px check glyph. This is the **shared** checkbox, so the change applies **app-wide**, not just to
|
|
210
|
+
the shipment forms — audit other consumers when touching it.
|
|
211
|
+
|
|
190
212
|
## Planned direction — "Fulfill & Ship" from an existing Item Fulfillment (future, Eric)
|
|
191
213
|
|
|
192
214
|
A **third entry mode** is planned (distinct from Select-Items-create and the pencil-edit): a
|
|
@@ -221,7 +243,27 @@ the call 403s and returns no label.
|
|
|
221
243
|
|
|
222
244
|
## Gotchas / known issues
|
|
223
245
|
|
|
224
|
-
- **⚠
|
|
246
|
+
- **⚠ Native `<datalist>` renders its OWN dropdown arrow, un-hideable by Tailwind.** An
|
|
247
|
+
`<input list>` combobox (the Edit Return Label Addressee) shows a **second dark arrow** (the
|
|
248
|
+
webkit calendar-picker indicator) that a Tailwind arbitrary variant can't reliably hide. Kill it
|
|
249
|
+
with a **real global CSS rule** in the source stylesheet
|
|
250
|
+
`src/styles/index.scss` (imported by `main.tsx`):
|
|
251
|
+
`input[list]::-webkit-calendar-picker-indicator { display: none !important; }`.
|
|
252
|
+
**Edit `index.scss`, NOT `index.css`** — `index.css` is compiled output and will be overwritten.
|
|
253
|
+
Also set **`autoComplete="off"`** on the input or the browser's address-autofill popup
|
|
254
|
+
("Saved data / Manage personal info") overlaps and fights the datalist.
|
|
255
|
+
- **⚠ A `className` template literal must keep the trailing space before `${...}`.** `border ${cond
|
|
256
|
+
? a : b}` is correct; `border${cond ? a : b}` concatenates into an invalid single class
|
|
257
|
+
(e.g. `borderborder-navy-300`) and the utility silently no-ops. Concrete failure: the `BaseInput`
|
|
258
|
+
checkbox's unchecked border disappeared because the space was dropped. Watch this whenever
|
|
259
|
+
conditional classes are appended to a static base class.
|
|
260
|
+
- **⚠ `justify-between` + `clamp()` gaps are frozen when the container is a FIXED width.** The Update
|
|
261
|
+
Info field row uses `gap-x-[clamp(2px,1vw,50px)]` with `justify-between`, but the card was a fixed
|
|
262
|
+
`w-[1820px]`, so `justify-between` distributed columns across a constant width and the gaps never
|
|
263
|
+
changed on resize. Fix: make the card `w-full max-w-[1820px]` and the form section `w-full` so the
|
|
264
|
+
width tracks the viewport and the clamp'd gaps grow/shrink with it. Note `justify-between` does
|
|
265
|
+
**not** cap the max gap at 50px on very wide screens — the `clamp` only *floors* at 2px; the max
|
|
266
|
+
applies until columns are pushed to the edges. (`EditShipmentPage.tsx`.) — a class used ONLY in `viewModel/FIELDS/*.json`
|
|
225
267
|
is silently inert.** The config-driven forms author Tailwind utility classes inside the field JSON
|
|
226
268
|
(e.g. `DUMMYUPDATESHIPMENTFIELDS.json`), but `tailwind.config.cjs` `content` globs only scan
|
|
227
269
|
`./src/**/*.{js,ts,jsx,tsx}` (+ `index.html` + toga-blox dist) — **not `.json`**. So a class used
|
|
@@ -417,6 +459,18 @@ not the base `_Model_Client_ItemFulfillment`. Tested with GroWrk; UPS support wa
|
|
|
417
459
|
for Compass and is not yet in prod.
|
|
418
460
|
|
|
419
461
|
## Change history
|
|
462
|
+
- 2026-07-15 — TRUE-79191: made the Edit Return Label **Addressee a searchable combobox** (native
|
|
463
|
+
`<input list>` + `<datalist>`, filters + allows custom text, prefills via `applyWarehouse`); added a
|
|
464
|
+
**backdrop-click discard guard** (guarded `BaseModal onClose` on `formState.isDirty`); restyled the
|
|
465
|
+
**shared `BaseInput` checkbox** to the Figma spec (16px, navy-300 border, `supply-blue-400` fill,
|
|
466
|
+
app-wide). Documented four durable gotchas: native `<datalist>`'s un-hideable arrow (hide via a
|
|
467
|
+
real global rule in `src/styles/index.scss`, not the compiled `index.css`) + `autoComplete="off"`
|
|
468
|
+
to stop autofill overlap; the `className` **trailing-space-before-`${...}`** footgun (dropped space
|
|
469
|
+
→ invalid concatenated class → silent no-op, killed the checkbox border); and `justify-between` +
|
|
470
|
+
`clamp()` **gaps frozen by a fixed-width card** (fix: `w-full max-w-[1820px]` so width tracks the
|
|
471
|
+
viewport). Remaining Figma polish (5-col address grid, Signature default object, declared-cost
|
|
472
|
+
2-decimal rehydrate, Clear All wiring, residential alignment, footer/divider spacing) was cosmetic
|
|
473
|
+
— no doc change. (mhammontree)
|
|
420
474
|
- 2026-07-15 — TRUE-79191: unified the **dropdown chevron glyph** across the compact selects — added a
|
|
421
475
|
`CompactDropdownIndicator` (FA `chevronDown`) to `BaseInput` and wired it into both react-select
|
|
422
476
|
`components` blocks **only when `compact` is true**, so the react-select caret matches the native
|
package/knowledge/INDEX.md
CHANGED
|
@@ -19,7 +19,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
|
|
|
19
19
|
|
|
20
20
|
- **_underscore** (_Underscore) _(framework core)_ — 32 doc(s) → [2.0/apps/_underscore/INDEX.md](2.0/apps/_underscore/INDEX.md)
|
|
21
21
|
- **worker2** (Worker) — 30 doc(s) → [2.0/apps/worker2/INDEX.md](2.0/apps/worker2/INDEX.md)
|
|
22
|
-
- **api2** (API) —
|
|
22
|
+
- **api2** (API) — 11 doc(s) → [2.0/apps/api2/INDEX.md](2.0/apps/api2/INDEX.md)
|
|
23
23
|
- **dbchanges2** (Database Changes) _(framework core)_ — 3 doc(s) → [2.0/apps/dbchanges2/INDEX.md](2.0/apps/dbchanges2/INDEX.md)
|
|
24
24
|
- **toga2-supply** (TOGa Supply) — 3 doc(s) → [2.0/apps/toga2-supply/INDEX.md](2.0/apps/toga2-supply/INDEX.md)
|
|
25
25
|
- **saml** (SAML SSO Gateway) — 3 doc(s) → [2.0/apps/saml/INDEX.md](2.0/apps/saml/INDEX.md)
|
|
@@ -4,7 +4,7 @@
|
|
|
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
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 |
|
|
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
|
+
| [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, dbchanges2/Client/2026-07-15a - ExcludeFeeItemsFromItemFulfillmentsForSalesOrdersView.sql |
|
|
8
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 |
|
|
9
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, worker/crons/toga2/compasscanada/workflow/2_transmit_mits_purchase_orders_to_vendors.php, library/app/client/compass.php |
|
|
10
10
|
| [Compass MR/MA Order Auto-Approval & Status Gate](features/mr-ma-order-approval-and-status.md) | 2.0 | Compass **MR** and **MA** sales orders are system-generated from the MITS / Office Depot EDI pipeline (they do not originate as user-entered SA orders) and must | _underscore/Model/Compass/SalesOrder.php, _underscore/Model/Compass/PurchaseOrder.php, worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php |
|
|
@@ -5,14 +5,16 @@ project: _Underscore
|
|
|
5
5
|
client: compass-usa
|
|
6
6
|
type: client-feature
|
|
7
7
|
status: active
|
|
8
|
-
updated: 2026-
|
|
9
|
-
owners: ["jcardinal"]
|
|
8
|
+
updated: 2026-07-15
|
|
9
|
+
owners: ["jcardinal", "bala"]
|
|
10
10
|
files:
|
|
11
11
|
- dbchanges2/Client_Compass/2026-06-10 - ItemFulfillmentsForSalesOrderItemsTableView.sql
|
|
12
12
|
- dbchanges2/Client_Compass/2026-06-11 - ItemFulfillmentsForSalesOrdersTableView.sql
|
|
13
13
|
- dbchanges2/Client_Compass/2026-06-15a - FixItemFulfillmentTrackingNumberJoins.sql
|
|
14
|
+
- dbchanges2/Client/2026-07-15a - ExcludeFeeItemsFromItemFulfillmentsForSalesOrdersView.sql
|
|
14
15
|
related:
|
|
15
16
|
- ../../../2.0/apps/_underscore/features/tracking-number-bridges.md
|
|
17
|
+
- ../../../2.0/apps/api2/features/tableview-apiwhereclause-row-filtering.md
|
|
16
18
|
---
|
|
17
19
|
|
|
18
20
|
## Summary
|
|
@@ -93,14 +95,30 @@ returnTrackingNumberId. Superseded unit-level keys: 2183 IFIU-bridge.itemFulfill
|
|
|
93
95
|
- With null `joinOnTableViewJoinId`, the engine resolves a join's parent table by the `recordId` of
|
|
94
96
|
`parentRecordFieldId` — this only works because each record appears once in the graph. Reusing a
|
|
95
97
|
record twice in one view would require an explicit `joinOnTableViewJoinId`.
|
|
98
|
+
- **FEE-item exclusion (view 12) is filtered via `apiWhereClause`, and "asset type" is a nullable
|
|
99
|
+
FK — not a string.** `Items.assetTypeId` is a nullable FK to `AssetTypes(id, uuid, name)`; the
|
|
100
|
+
id for a given name (e.g. `FEE`) **differs per client** (Compass: `FEE` = id 3, 62 items). About
|
|
101
|
+
30% of `Items` rows have a **NULL** `assetTypeId` (Compass: 227,685 of ~269,980 fulfilled-item
|
|
102
|
+
rows in this view), so any exclusion **must be NULL-safe** — a plain `assetTypeId:ne:<id>` would
|
|
103
|
+
silently drop every NULL row. The migration uses `(IFNULL(Items.assetTypeId,0):ne:<FEE id>)` with
|
|
104
|
+
the FEE id resolved per client DB via `(SELECT id FROM AssetTypes WHERE name='FEE' ...)`. See the
|
|
105
|
+
shared `apiWhereClause` mechanism doc. The `apiWhereClause` binds `Items.assetTypeId` correctly
|
|
106
|
+
only because view 12 joins `Items` exactly once (the join-alias rule).
|
|
107
|
+
- **The FEE-exclusion migration is team-wide, not Compass-only.** It lives in the `dbchanges2/Client/`
|
|
108
|
+
fan-out folder, so it runs against **every** client DB, guarded to fire only where the view exists,
|
|
109
|
+
a `FEE` asset type exists, and `Items` is joined exactly once. It composes idempotently onto any
|
|
110
|
+
existing `apiWhereClause` (a CASE skips if `%assetTypeId%` is already present). Verified read-only
|
|
111
|
+
on prod + dev-sandbox that it excludes only FEE rows and keeps all NULL-assetType rows.
|
|
96
112
|
|
|
97
113
|
## Client variations
|
|
98
114
|
Compass-only. The underlying bridge model is shared (see the _underscore feature doc).
|
|
99
115
|
|
|
100
116
|
## Change history
|
|
117
|
+
- 2026-07-15 — Excluded FEE-asset-type items from view 12 (`item-fulfillments-for-sales-orders`) via a NULL-safe `apiWhereClause` `(IFNULL(Items.assetTypeId,0):ne:<FEE id>)`, FEE id resolved per client DB. Migration `2026-07-15a` in `dbchanges2/Client/` (fans out to all clients, idempotent, guarded). Verified read-only on prod + dev-sandbox. (bala)
|
|
101
118
|
- 2026-06-15 — Re-pointed tracking from the unit-level bridge (319) to the item-level bridge `ItemFulfillmentItems_TrackingNumbers` (318) in views 12 & 13; fixes blank item-level tracking on non-serialized lines (e.g. SO MR243437). Migration `2026-06-15a`. (jcardinal)
|
|
102
119
|
- 2026-06-11 — Re-rooted `item-fulfillments-for-sales-orders` (id 12) from Units to ItemFulfillmentItems with OUTER unit/tracking chain; fixes 0-records on orders lacking unit breakdown (e.g. SA132740). (jcardinal)
|
|
103
120
|
- 2026-06-10 — Re-rooted `item-fulfillments-for-sales-order-items` (id 13) and moved tracking to the bridge join. (jcardinal)
|
|
104
121
|
|
|
105
122
|
## Related docs
|
|
106
123
|
- 2.0 _underscore: Tracking-Number Bridge Migration.
|
|
124
|
+
- 2.0 api2: TableView row-filtering via apiWhereClause (the mechanism used for the FEE exclusion).
|
package/package.json
CHANGED