WIP: feat(contract) #004 Fill a shopping list from a meal plan, and move a dish keeping its id #51

Draft
araemer wants to merge 4 commits from 004-fill-list-from-meal-plan-contract into main
Owner

Contract for spec 004 (epic E01 spec B), approved at GATE A. Docs PR: #50

  • shopping-lists.ts:
    • new routes POST /shopping-list/:id/fill-preview, /fill and /remove-meal-plan-items;
    • the MEAL_PLAN reason source with ShoppingListItemMealPlanReasonDto;
    • the review DTOs;
    • an item's version now also changes when a fill changes the item.
  • meal-plans.ts: POST /meal-plan-dish/:dishId/move, which keeps the dish's id.
  • errors.ts: SOURCE_MEAL_PLAN_NOT_FOUND and SOURCE_MEAL_PLAN_ACCESS_DENIED; the CONFLICT doc now also covers a stale preview token.

Design: docs/adr/2026-10-24-fill-list-from-meal-plan.md.

This PR stays a draft until the review gate. It is merged there, just before the sibling feature PRs. The sibling feature branches pin this branch's commit in contract.ref. Never rebase or force-push this branch.

🤖 Generated with Claude Code

Contract for spec 004 (epic E01 spec B), approved at GATE A. Docs PR: https://git.raemer.net/araemer/recipe-platform/pulls/50 - `shopping-lists.ts`: - new routes `POST /shopping-list/:id/fill-preview`, `/fill` and `/remove-meal-plan-items`; - the `MEAL_PLAN` reason source with `ShoppingListItemMealPlanReasonDto`; - the review DTOs; - an item's `version` now also changes when a fill changes the item. - `meal-plans.ts`: `POST /meal-plan-dish/:dishId/move`, which keeps the dish's id. - `errors.ts`: `SOURCE_MEAL_PLAN_NOT_FOUND` and `SOURCE_MEAL_PLAN_ACCESS_DENIED`; the `CONFLICT` doc now also covers a stale preview token. Design: `docs/adr/2026-10-24-fill-list-from-meal-plan.md`. This PR stays a draft until the review gate. It is merged there, just before the sibling feature PRs. The sibling feature branches pin this branch's commit in `contract.ref`. Never rebase or force-push this branch. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
docs(features) #004 Add spec, epic updates and ADR for filling a list from a meal plan
All checks were successful
/ typecheck-contract (pull_request) Successful in 20s
7317dee1f9
Spec 004 (epic E01, spec B) with the Affected Repos section and status
Phase B for both repos, the epic updates, the cross-cutting ADR
2026-10-24-fill-list-from-meal-plan, and the partial supersede mark on
the shopping list contract ADR. Approved at GATE A.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
feat(contract) #004 Fill a shopping list from a meal plan, and move a dish keeping its id
All checks were successful
/ typecheck-contract (pull_request) Successful in 22s
fe52ccc289
Adds POST /shopping-list/:id/fill-preview, /fill and
/remove-meal-plan-items, the MEAL_PLAN reason source with its mealPlan
block, POST /meal-plan-dish/:dishId/move, and the error codes
SOURCE_MEAL_PLAN_NOT_FOUND and SOURCE_MEAL_PLAN_ACCESS_DENIED.
See docs/adr/2026-10-24-fill-list-from-meal-plan.md. Approved at GATE A.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(contract) #004 Apply clearTicked only while the ticked-items question is shown
All checks were successful
/ typecheck-contract (pull_request) Successful in 21s
712a4f9c7e
clearTicked is ignored when no ticked item of the target list covers a
dish in the range, so a fill never removes ticked items the user was not
asked about, e.g. after switching the target list with decisions kept.
Found at GATE B (recipe-app keeps decisions on a list change).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(contract) #004 Show a meal plan reason's day as null once its dish is no longer planned
All checks were successful
/ typecheck-contract (pull_request) Successful in 20s
8ab6bbee52
ShoppingListItemMealPlanReasonDto.date becomes string | null: the dish's
current day while it is planned, null once it is removed, its day or plan
deleted, or its recipe swapped. Replaces "the last day the dish was on",
which needed a stored copy synced by the meal plan code. Decided at GATE B.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(contract) #004 Reject dish ids from another day on a day save, document its errors
All checks were successful
/ typecheck-contract (pull_request) Successful in 21s
cf101fc4b2
A day save may carry only ids of dishes already on that day; a dish move
goes only through POST /meal-plan-dish/:dishId/move. Closes a hole where a
day save could pull a dish out of another, possibly inaccessible, plan.
Lists the route's errors (400, 403, 404, 409). Decided at GATE B.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ -362,0 +603,4 @@
/** Free-text unit. Absent when the line has no unit. */
unit?: string;
/** True when at least one contributing recipe has no yield, so its amounts were not scaled ("recipe has no yield, amounts not scaled"). Always present. */
notScaled: boolean;
Author
Owner

wouldn't positive be better? Scaled instead of not scaled?

wouldn't positive be better? Scaled instead of not scaled?
@ -362,0 +643,4 @@
/** The item as it is now. Always present. */
item: CompactShoppingListItemDto;
/** The reasons that are removed, one per gone dish, with its share. Always present, at least one. */
goneDishes: ShoppingListItemMealPlanReasonDto[];
Author
Owner

Wouldn't this be goneDishesReasons or something alike?

Wouldn't this be goneDishesReasons or something alike?
All checks were successful
/ typecheck-contract (pull_request) Successful in 21s
This pull request is marked as a work in progress.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin 004-fill-list-from-meal-plan-contract:004-fill-list-from-meal-plan-contract
git switch 004-fill-list-from-meal-plan-contract

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff 004-fill-list-from-meal-plan-contract
git switch 004-fill-list-from-meal-plan-contract
git rebase main
git switch main
git merge --ff-only 004-fill-list-from-meal-plan-contract
git switch 004-fill-list-from-meal-plan-contract
git rebase main
git switch main
git merge --no-ff 004-fill-list-from-meal-plan-contract
git switch main
git merge --squash 004-fill-list-from-meal-plan-contract
git switch main
git merge --ff-only 004-fill-list-from-meal-plan-contract
git switch main
git merge 004-fill-list-from-meal-plan-contract
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
araemer/recipe-platform!51
No description provided.