Skip to content

Specification: Inventory v00

Driving specification for Inventory v00. It sequences the work for the implementing engineer and references the requirements, analysis, verification, and the precise implementation changes. Read the goal first for scope and the settled decisions.

Add two nullable fields to ItemtotalInventoryCount (a Quantity) and lastCountDate (a DateTime) — and surface them for viewing and editing in the Items List View (inline) and the Item Detail panel (View + Edit), grouped under an “Inventory Count” group. The change is additive and backward compatible; both fields reuse existing precedents (minQuantity, Order.deliverBy).

  • Backend follows kotlin-coding conventions (monadic error channel, single exit, no getOrNull collapsing errors); frontend follows react-best-practices and the repo’s mapper/type discipline (never use arda-api types in UI — map through ardaClient).
  • Match surrounding style; surgical edits only — every changed line traces to a requirement.
  • Each field’s four-place backend footprint (entity + serializer descriptor, DTO
    • toItem, persistence columns/record, migration) must stay in sync — a missed serializer element(...) or fillPayload line is the most likely defect.
  • Do not edit CHANGELOG.md in documentation (PR-body changelog); operations and arda-frontend-app follow their repos’ changelog models (see Phase D).

Single agent, three repositories, one worktree each — already created under projects/inventory-v00-worktrees/ on branch jmpicnic/inventory-v00: operations/, arda-frontend-app/, documentation/. Different repositories and a single writer, so no integration branch and no per-task worktrees are needed. Each repository produces one PR from its jmpicnic/inventory-v00 branch to its main.

Phase A — operations (backend data contract)

Section titled “Phase A — operations (backend data contract)”

Implements REQ-INV-001…008. Precise edits in implementation-changes.md.

  1. Add totalInventoryCount: Quantity.Value? and lastCountDate: DateTime? to the Item interface and Entity, and the matching element(...) lines to ItemSerializer.
  2. Add both to ItemInput and toItem().
  3. Add persistence: quantityComponent("total_inventory_count") and dateTimeComponent("last_count_date"), plus var delegates, insert lambda, fromEntity, and fillPayload.
  4. Add Flyway migration V022__inventory_count.sql (four nullable columns).
  5. Encode the REQ-INV-006 normalization defaults (amount ⇒ unit "each"; unit ⇒ amount 0; both empty ⇒ null) at the input/mapping boundary.
  6. Extend unit tests: ItemDDLTest, ItemInputModelTest, ItemUniverseTestData
    • universe/service/endpoint tests.
  7. Gate: make build green (Gradle + coverage).

STOP — review Phase A (data contract, migration, normalization semantics) before starting the frontend, since the DateTime wire shape (Decision D3) is a dependency for the mappers.

Phase B — arda-frontend-app (views + editing)

Section titled “Phase B — arda-frontend-app (views + editing)”

Implements REQ-INV-010…023. Precise edits in implementation-changes.md.

  1. Types: add both fields to the domain Item (items.ts), the ARDA DTO types (arda-api.ts), ItemFormState, and ItemCard (constants/types.ts).
  2. Mappers (ardaMappers.ts): read in mapArdaItemToItem; write in mapItemToArdaCreateRequest and mapItemToArdaUpdateRequest, omitting empties for clear-to-null.
  3. Grid: add count amount + unit columns and a date column (hide: true); register in itemTableConfig.ts and ColumnVisibilityMenu.tsx.
  4. Inline edit (gridColumnEnhancers.tsx): add getEditableCellValue / applyEditableCellValue cases; attach UnitCellEditor to the count-unit path and a date cell editor to the date path (Decision D2).
  5. Detail View (ItemDetailsPanel.tsx + convertItemToItemCard): add the titled “Inventory Count” group at the end.
  6. Detail Edit (ItemFormPanel.tsx): add the “Inventory Count” section after the last section; register it in tocSections; prefill; emit in the submit builder with empty ⇒ undefined; date pre-seeds to now when empty (REQ-INV-023).
  7. Tests/mocks/e2e: extend mockItems.ts, component tests, and Playwright specs.
  8. Gate: make ci-replicate green (lint, typecheck, unit, e2e).

STOP — review Phase B (UX of the group, inline-edit behavior, clear-to-null) before documentation.

Implements REQ-INV-030.

  1. Update the Item current-system functional reference (current-system/functional/operations/inventory/… / the Item reference page) to document both fields, their nullability, and the normalization/default behavior.
  2. Move this project’s docs from draft toward completion per the project lifecycle when the code lands.
  3. Gate: make pr-checks green (link check + smoke).
  1. Each repository raises its own changelog entry and PR as soon as its work is complete — the three PRs are independent; there is no cross-repo merge ordering to enforce here.
    • operations and arda-frontend-app: changelog per their repo models.
    • documentation: changelog via the PR body ## CHANGELOG section.
  2. Merging to main and deployment to servers are coordinated by the user outside this project. Do not merge; use pr-steward only to monitor checks and resolve review threads on each PR after it is opened.
#QuestionOptionsRecommendationDecision
D1Grid representation of the count(a) two columns amount+unit; (b) single composite column; (c) amount only(a) — mirrors Min Qty/Min Unit and reuses inline-edit machineryDecided (a)
D2Inline date editor granularity(a) DS DateCellEditor (date only); (b) custom datetime-local editor(a)Decided (a) — inline captures the date and stores it as noon (12:00) in the hinted timezone (noon avoids off-by-one date shifts under tz/DST conversion); full date+time is editable in the Detail panel
D3DateTime wire representation on the frontend(a) carry ISO string in domain, convert in the mapper; (b) carry raw shape in the domain(a)Decided (a) — DateTime JSON is { "timestamp": <epoch millis>, "tz": "<IANA name>" } (tz serializes via @SerialName, e.g. "America/New_York"); the frontend carries an ISO string and the mapper converts both ways
D4Amount default when unit set first(a) 0 per REQ-INV-006; (b) 1 per the minQuantity precedent(a)Decided (a) — deliberate divergence from minQuantity
D5Timezone for lastCountDate(a) browser default; (b) explicit UTC(a)Decided (a) — browser tz is the hint for noon-of-date; operational clock is UTC, so normalize on display
D6Grid column labels & placementLabels “Total Inventory Count”, “Count Unit”, “Last Count Date”; in the meta/detail column groupAs proposedDecided

All decisions are resolved; none remain open.

All requirements verified per verification.md:

  • REQ-INV-001…002 — both fields exist on Item with correct types/nullability
  • REQ-INV-003…005 — create/read/update round-trip; omission clears to null and persists
  • REQ-INV-006 — normalization defaults (each / 0 / null) hold
  • REQ-INV-007…008 — no new validation; existing payloads unaffected
  • REQ-INV-010…013 — three hidden-by-default, inline-editable, correctly formatted columns
  • REQ-INV-014 — single inline edit cannot null the whole count
  • REQ-INV-020…021 — “Inventory Count” group in View and Edit (in ToC), correct inputs
  • REQ-INV-022…023 — clear-to-null persists; null date pre-seeds to now
  • REQ-INV-030 — Item functional reference updated
  • operations make build, arda-frontend-app make ci-replicate, documentation make pr-checks all green
  • One PR per repo with a changelog entry, each raised independently as its work completes (no enforced cross-repo merge ordering — see Phase D)

Copyright: (c) Arda Systems 2025-2026, All rights reserved