From 86e0ea3111b501a4a2c22c7e9b074a22abf15a99 Mon Sep 17 00:00:00 2001 From: jableader Date: Sat, 1 Nov 2025 15:42:59 +1100 Subject: [PATCH] feat(shopping-v2): add household-scoped meal request/unrequest; tests and OpenAPI updated --- backend-spec.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend-spec.md b/backend-spec.md index a032cbb..d7f4578 100644 --- a/backend-spec.md +++ b/backend-spec.md @@ -2,6 +2,9 @@ - GET `/api/v1/households/{householdSlug}/shopping/{listId}` returning purchased list + lookups scoped to household; cross-household returns 404. - POST `/api/v1/households/{householdSlug}/meals/{mealId}/consumed` marks a meal consumed within the household; validates timezone on provided `consumedDate`; clears outstanding meal requests only within that household. - Tests: `tests/test_meals_consumed_v2.py` validates scoping (requests cleared in same household, unaffected in other household). PASS. + - POST `/api/v1/households/{householdSlug}/shopping/current/meals/me` requests a meal under the household scope; visible only within that household in GET current. + - DELETE `/api/v1/households/{householdSlug}/shopping/current/meals/{mealId}` unrequests the meal (scoped) and returns `{ ok: true }`. + - Tests: `tests/test_shopping_request_meal_v2.py` validates request/unrequest isolation across households. PASS. - Tests: `tests/test_shopping_household_v2.py` verifies isolation of outstanding items; `tests/test_shopping_list_by_id_v2.py` verifies list-by-id scoping; `tests/test_shopping_purchase_v2.py` covers scoped purchase (PASS). # Backend Specification: Household Multi-Tenancy (v2) @@ -237,9 +240,9 @@ Impact on existing routes (exact files to refactor): - GET `/api/v1/households/{householdSlug}/shopping/{listId}` returning purchased list + lookups scoped to household; cross-household returns 404. - POST `/api/v1/households/{householdSlug}/shopping` to purchase list items scoped to household; validates invariants and updates outstanding requests. - Scoped helpers in `shopping/repository.py` and `shopping/__init__.py` filter by `household_id` (find items, load list, purchased ingredients, and purchase_scoped). - - Tests: `tests/test_shopping_household_v2.py` (current isolation), `tests/test_shopping_list_by_id_v2.py` (list-by-id scoping), `tests/test_shopping_purchase_v2.py` (scoped purchase). PASS. + - Tests: `tests/test_shopping_household_v2.py` (current isolation), `tests/test_shopping_list_by_id_v2.py` (list-by-id scoping), `tests/test_shopping_purchase_v2.py` (scoped purchase), `tests/test_shopping_request_meal_v2.py` (request/unrequest). PASS. - Notes: Normalized Ingredient.preparation to allow NULLs from DB (treated as empty string) to avoid 422 in v2 responses; set purchased_by_id in scoped purchase from JWT user. - - ⏳ Update Repositories: ingredients, products to accept `household_id` and filter accordingly; extend meals create/update/consumed/delete and shopping write flows (purchase, requests) with scoping. + - ⏳ Update Repositories: ingredients, products to accept `household_id` and filter accordingly; extend meals create/update/delete with scoping. - ⏳ Update Routers: move/duplicate remaining routers under the household router and wire `household_id` through. - **Acceptance**: The same queries as v1, when run under different household slugs and users, return isolated data sets; cross-household access yields 403.