Repository navigation
feat/household recipients - #4
Merged
Merged
Conversation
Coding-Professional
commented
Oct 30, 2026
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.