batchCooking/apps/web/cypress/e2e/planning.feature
Nicolas eba0ea70bd
All checks were successful
CI / lint (push) Successful in 2m37s
CI / intent-service-test (push) Successful in 4m26s
CI / test (push) Successful in 15m8s
CI / build (push) Successful in 2m45s
CI / e2e (push) Successful in 8m6s
feat(planning): sépare portions demandées et portions préparées
Première PR du chantier « gestion des restes » (issue #34) — les
fondations, sans encore d'UI de panier.

À l'ajout d'une recette au planning on ne saisit plus qu'un seul nombre,
`portionsRequested` (« combien ce créneau doit nourrir »). Le serveur en
dérive `portions` (ce qui est réellement préparé) via
`computeBatchedPortions` : arrondi au multiple supérieur du rendement de
la recette (on cuisine des lots entiers, jamais une fraction de plat).
L'écart est le futur pool de restes de l'item.

Modèle (`PlanningItem`, purement additif) :
- `portionsRequested` NOT NULL — migration nullable → backfill (`= portions`
  pour les lignes existantes, sans restes à l'époque) → verrou, même
  discipline que `ingredient_unit_catalog`.
- `sourcePlanningItemId` (auto-FK nullable, `onDelete: Cascade`) et
  `discardedPortions` (défaut 0) — posés maintenant, utilisés plus tard.

Partagé (`@batch-cooking/shared/logic/planning-portions.ts`) :
- `computeBatchedPortions(recipePortions, requested)` → `{ portions, leftover }`
- `computeAvailableLeftover(item)` → pool encore disponible (posé pour les
  PRs suivantes : validation d'écriture côté API, affichage du panier
  côté web — une seule formule, deux appelants)

API : `addPlanningItemSchema` prend `portionsRequested` ; `addPlanningItem`
calcule et stocke les deux valeurs + l'évènement analytics ; `PlanningItemView`
et `getPlanningForDate` exposent `portionsRequested`/`discardedPortions`/
`sourceItem`.

Front : `RecipePickerDialog` — champ « portions demandées » + indice en
direct « → N préparées, M en restes » quand l'arrondi crée un reste ;
envoie `portionsRequested`. `RecipeImportForm` — envoie `portionsRequested`
(un import atterrit à son propre rendement, donc reste nul).

Tests : `planning-portions.test.ts` (les deux exemples de #34 + bornes) ;
nouveau bloc `POST /planning/items` dans `planning.test.ts` (arrondi au
lot, plusieurs lots, borne exacte, 400 sur non-positif) ; fixtures
`planningItem.create` des suites existantes mises à jour ; scénario
Cypress planning ajusté (`portionsRequested` dans le corps).

Docs : `batch-cooking-modele.md`, `backend-architecture.md`,
`frontend-architecture.md`.

Réf #34

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 23:29:58 +02:00

59 lines
3.1 KiB
Gherkin

Feature: Adding a recipe to the planning
As a signed-in user
I want to add a recipe to a planning slot even when I haven't imported it yet
So that browsing an external source and planning it is a single trip
Background:
Given I am signed in as "Alice" "Martin"
And my household id is 1
And today is frozen at "2026-08-17T09:00:00.000Z"
And the household request returns no household
And the recipe catalog contains nothing
And the ingredient and diet catalog is available for import
And the sources reference list has options
And the household has enabled TheMealDB
And browsing TheMealDB returns some items
And the planning request returns nothing
Scenario: Selecting a source item only previews it, the footer's Confirmer is what acts on it
Given previewing TheMealDB item "9999" is available
When I visit "/"
And I click the add button for the first empty planning slot
And I click the button "TheMealDB"
And I click the source item "Fish Pie"
Then the recipe detail panel heading should be "Fish Pie"
And the URL should be the home page
Scenario: Confirming a not-yet-imported source item lands on the embedded review form since an ingredient needs resolving
Given previewing TheMealDB item "9999" is available
And importing the previewed item will succeed and return id 99
And adding the imported recipe to the planning will succeed
When I visit "/"
And I click the add button for the first empty planning slot
And I click the button "TheMealDB"
And I click the source item "Fish Pie"
And I click the button "Confirmer"
Then I should see "Cette recette sera automatiquement ajoutée à votre planning une fois importée."
When I choose an ingredient for the unresolved line "some mystery paste"
And I select the ingredient "Sel" from the picker
And I select unit "unité" for the first ingredient
And I fill in the last ingredient's quantity with "1" and unit "unité"
And I click the button "Importer"
Then the planning add request should have included recipe 99, weekDay "lundi", meal "petit-dejeuner", and requested portions 4
And the recipe picker dialog should be closed
And the recipe "Fish Pie" should appear in the first planning slot with 4 portions
Scenario: Confirming a fully-resolved not-yet-imported item adds it to the planning transparently, with no review screen at all
Given previewing TheMealDB item "7777" is fully resolved as "Ratatouille"
And importing item "7777" will succeed and return id 100
And adding recipe 100 to the planning will succeed
When I visit "/"
And I click the add button for the first empty planning slot
And I click the button "TheMealDB"
And I click the source item "Ratatouille"
And I click the button "Confirmer"
Then the import request for "7777" should have included the name "Ratatouille"
And the planning add request should have included recipe 100, weekDay "lundi", meal "petit-dejeuner", and requested portions 4
And the recipe picker dialog should be closed
And the recipe "Ratatouille" should appear in the first planning slot with 4 portions