Skip to content

feat/household recipients - #4

Merged
Coding-Professional merged 10 commits into
mainfrom
feat/household-recipients
Nov 2, 2026
Merged

Coding-Professional merged 10 commits into
mainfrom
feat/household-recipients

Conversation

@Coding-Professional

Copy link
Copy Markdown
Owner
  • feat(domain): add household, recipient and milk rate model
  • feat(application): add household, recipient and milk rate use cases
  • feat(infrastructure): persist households, recipients and milk rates
  • feat(api): expose household, recipient and milk rate endpoints
  • fix(infrastructure): order the single-household lookup
  • fix(application): archive from the day after a recipient starts by default
  • feat(web): add API services and price and date helpers
  • feat(web): manage recipients and the milk price on real API data
  • ci: run the database tests and a smoke test after applying the migrations
  • docs: describe what slice 1 PR A built

Add the Household, Recipient and MilkRate aggregates with typed UUIDv7 ids,
Money in whole paise, PricePerLitre with half-up rounding once per line, and
RateSchedule for rate lookups by date. DomainException can name the input a
rule is about. Every applicable invariant from the domain model has a test.
Add handlers for setting up the household, listing, adding, updating,
archiving and restoring recipients, and listing, adding, changing, deleting
and looking up milk rates. Repository interfaces, the unit of work and the
current household are declared here without any EF Core types. Conflicts and
missing data are reported with stable error codes. Handler tests run against
an in-memory database that only commits on save.
Map the three aggregates to PostgreSQL with EF Core: typed id, quantity and
price converters, check constraints, restrict-on-delete foreign keys, a unique
(household_id, id) key for future composite foreign keys, a partial unique
index on the lower-cased name of active recipients and a unique index on
(household_id, effective_from). Add the repositories, a unit of work that turns
a unique-index race into a conflict, and the single-household provider. The
readiness check now also fails while migrations are pending.

The initial migration is AddHouseholdsRecipientsAndMilkRates. Tests run against
a real PostgreSQL, one throwaway database per class, and are tagged
Category=Database so the other jobs can exclude them.
Add the /api/v1 endpoints for the household (get, set up), recipients (list,
add, get, update, archive, restore) and milk rates (list, add, rate in effect,
change, delete). Validation failures are Problem Details naming the field;
missing data is 404 and clashes are 409, each with a stable code. There is no
way to delete a recipient.

Until authentication exists the data endpoints are mapped only in Development
and Testing, or when Access__AllowUnauthenticated is set to true. Any other
value, including an empty one, leaves them off.
Taking two households without an ORDER BY made EF Core warn on every request.
Order by id so the lookup is deterministic.
…fault

A recipient is active for at least one day, so archiving "from today" was
refused for anyone who started today, which is exactly who gets archived after a
mistake. With no date given, archive from today or the day after the start date,
whichever is later.
Add household, recipient and milk rate services on top of an API client that now
sends POST, PUT and DELETE and keeps the Problem Details of an error, with its
stable code and per-field messages. Prices are formatted and parsed as whole
paise without floating-point arithmetic, and calendar dates are shown without
turning them into time-zone dependent Date objects.
The Recipients page lists, adds, edits, archives and restores the household's
recipients, and Settings sets up the household and manages the milk price, all
through the services layer. Each screen has loading, empty, error and
validation states and works at 360px. With no API address the Recipients page
keeps its labelled demo data and Settings says it needs the API; with one it
never falls back to demo data silently.

Unit tests cover the page states with mocked service calls. The Playwright
tests, pinned to a build with no API address, cover the demo mode of Recipients
and Settings.
…ions

The api job and scripts/check.* now leave out the tests tagged Category=Database
and tolerate the resulting empty test project. The database job applies the
migrations to its empty PostgreSQL, runs those tests, then starts the API, waits
for /health/ready (which now also needs every migration applied) and runs
scripts/smoke-api.sh against the data endpoints. No job name changes.

scripts/check.* take --db (-Database) to run the database tests locally, and the
development guide covers the migration, the database tests and the
unauthenticated-access setting.
Update the architecture overview (current phase, readiness check, what is and is
not implemented, single-household mode) and add a "PR A as built" section to the
slice plan listing where the implementation differs from it, including the
confirmed test filter. ADR 0004 stays Proposed.
Copilot AI balanced review requested due to automatic review settings October 30, 2026 13:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@Coding-Professional
Coding-Professional merged commit 32c21d4 into main Nov 2, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants