Skip to content

Technical Design TD-002 — Quick Meals & Consumption

Field Value
ID TD-002
Title Quick Meals & Consumption
Status Draft
Owner @souperk
Audience contributors
Created 2026-02-07
Last Updated 2026-02-07
Reviewers TBD
Approvers TBD
Tracking TBD
Related v0.2 Roadmap, TD-001

1. Summary

  • Logging common meals (e.g., yogurt + granola + honey) currently requires multiple API calls
  • Quick meal templates save ingredient+quantity combos for one-tap consumption
  • One-tap consumption deducts from inventory via FIFO without navigating the recipe→cook flow
  • The "almost cookable" enhancement surfaces recipes where only 1–2 items are missing

2. Context and Problem Statement

  • Users eat the same simple meals repeatedly (breakfast combos, snacks, quick lunches)
  • The full recipe→cook flow is too heavyweight for these everyday meals
  • Users want a "just deduct it" action without creating recipes or tracking prepared food portions
  • The binary cookability check misses recipes that are almost cookable, reducing meal planning utility

2.1 Goals

  • Quick meal templates with saved ingredient+quantity combos
  • One-tap consumption endpoint that deducts via FIFO from active inventory
  • "Almost cookable" threshold on cookability check
  • Recipe suggestions endpoint returning cookable + almost-cookable recipes

2.2 Out of Scope

  • Prepared food creation from quick meals (quick meals are consumption-only)
  • Shopping suggestions for missing ingredients (v0.3)
  • Nutrition tracking for quick meals (v0.5)

2.3 Assumptions and Constraints

  • Quick meals are simpler than recipes — no instructions, no tags, no servings
  • One-tap consumption uses the same FIFO logic as cook-recipe
  • "Almost cookable" threshold is specified as a count of missing ingredients (not percentage)

3. Design Overview

  • New QuickMeal entity with QuickMealItem children
  • One-tap consumption endpoint that accepts a quick meal ID and deducts all items
  • Enhancement to RecipeService.check_cookability with missing_threshold parameter
  • New recipe suggestions endpoint combining fully cookable and almost-cookable recipes

3.1 Key Components

Component Purpose
QuickMeal Entity storing a named set of ingredient+quantity combos
QuickMealItem Child entity with ingredient_id, quantity, unit
QuickMealRepository Data access for quick meals
QuickMealService CRUD + one-tap consumption logic
QuickMealRouter FastAPI router at /quick-meal

3.2 Architecture

graph TB
    QMRouter[QuickMealRouter] --> QMService[QuickMealService]
    QMService --> QMRepo[QuickMealRepository]
    QMService --> InvService[InventoryService]
    RecipeRouter[RecipeRouter] --> RecipeService[RecipeService]
    RecipeService --> InvRepo[InventoryBatchRepository]

3.3 Interface Impact (Before → After)

Area Before After
Inventory consumption Only via cook-recipe or manual consume Also via one-tap quick meal
Cookability check Binary: cookable or not Supports missing_threshold parameter
Recipe discovery No suggestion endpoint GET /recipe/suggestions with cookable + almost-cookable

4. Implementation Details

4.1 Core Contracts and APIs

QuickMeal entity:

class QuickMeal(BaseAggregate):
    name: Mapped[str]
    user_id: Mapped[str]
    items: Mapped[list[QuickMealItem]]

QuickMealItem entity:

class QuickMealItem(BaseEntity, AuditMixin):
    quick_meal_id: Mapped[int]
    ingredient_id: Mapped[int]
    quantity: Mapped[Decimal]
    unit: Mapped[str]

API endpoints:

Method Path Description
POST /quick-meal Create quick meal template
GET /quick-meal List quick meals
GET /quick-meal/{id} Get single quick meal
PATCH /quick-meal/{id} Update quick meal
DELETE /quick-meal/{id} Delete quick meal
POST /inventory/quick-consume One-tap consumption (deduct all items)
GET /recipe/{id}/cookability Enhanced with missing_threshold query param
GET /recipe/suggestions Cookable + almost-cookable recipes

4.2 Component Architecture

  • QuickMeal extends BaseAggregate with standard column helpers
  • QuickMealItem extends BaseEntity + AuditMixin
  • Parent-child via relationship(cascade="all, delete-orphan", lazy="selectin")
  • Repository extends BaseRepository

4.3 Integration Points

  • One-tap consumption: Reuses InventoryService FIFO consumption logic
  • Cookability enhancement: Modifies existing RecipeService.check_cookability to accept threshold
  • Recipe suggestions: New method on RecipeService querying all user recipes and checking cookability

4.4 Error Handling and Edge Cases

Error When Response
QuickMealNotFoundError ID doesn't exist 404
InsufficientInventoryError Not enough stock for one-tap consumption 400 (with details of which items are short)
EmptyQuickMealError Quick meal has no items 400

Edge cases:

  • One-tap consumption is atomic: if any item has insufficient stock, the entire operation fails
  • Quick meal items can reference ingredients that no longer exist; validate on consumption, not on template save
  • Almost-cookable threshold of 0 is equivalent to "fully cookable" (backward compatible)

5. Semantics

  • Quick meals are templates, not recipes — they have no instructions, servings, or tags
  • One-tap consumption creates InventoryActivity records of type CONSUMED for each deducted item
  • The missing_threshold parameter counts distinct missing ingredients, not total missing quantity
  • Recipe suggestions are ordered: fully cookable first, then almost-cookable sorted by missing count ascending

6. Examples

6.1 Create Quick Meal

# POST /quick-meal
{
    "name": "Morning Yogurt Bowl",
    "user_id": "user-123",
    "items": [
        {"ingredient_id": 1, "quantity": "200", "unit": "g"},
        {"ingredient_id": 2, "quantity": "50", "unit": "g"},
        {"ingredient_id": 3, "quantity": "1", "unit": "tbsp"}
    ]
}

6.2 One-Tap Consumption

# POST /inventory/quick-consume
{
    "quick_meal_id": 5,
    "user_id": "user-123"
}
# Response: list of InventoryActivity records created

6.3 Almost-Cookable Check

# GET /recipe/42/cookability?user_id=user-123&missing_threshold=2
{
    "cookable": false,
    "missing_ingredients": [
        {"ingredient_id": 10, "name": "Basil", "required": "10g", "available": "0g"}
    ],
    "missing_count": 1,
    "within_threshold": true  # 1 missing <= 2 threshold
}

7. Test Matrix

  • Unit: QuickMeal entity, threshold logic in cookability check
  • Integration: Quick meal CRUD, one-tap consumption with FIFO, cookability with threshold, recipe suggestions
  • Edge cases: Empty quick meal, insufficient stock (partial), threshold=0, ingredient deleted after template save

8. Acceptance Criteria

  • Quick meal CRUD endpoints functional
  • One-tap consumption deducts from inventory via FIFO
  • One-tap consumption is atomic (all-or-nothing)
  • Cookability check supports missing_threshold parameter
  • Recipe suggestions returns ordered list of cookable + almost-cookable
  • InventoryActivity records created for each deduction
  • All error cases return appropriate HTTP status codes
  • Migration v08 applies cleanly

9. Rollout and Migration

9.1 Phased Plan

Phase 1: QuickMeal aggregate, repository, service, router, migration v08

Phase 2: One-tap consumption endpoint with FIFO integration

Phase 3: Cookability threshold enhancement and recipe suggestions endpoint

9.2 Migration Strategy

  • New tables only (quick_meals, quick_meal_items)
  • No changes to existing tables
  • No new enums required

10. Risks and Mitigations

Risk Mitigation
One-tap consumption atomicity under concurrent access Use database-level row locking on batch consumption
Recipe suggestions query slow with many recipes Limit to user's recipes, add index on user_id, consider pagination
Quick meal templates referencing deleted ingredients Validate on consumption, return clear error with ingredient details

11. Progress

  • Entity design
  • Repository implementation
  • Service implementation
  • Quick meal API endpoints + schemas
  • One-tap consumption endpoint
  • Cookability threshold enhancement
  • Recipe suggestions endpoint
  • Migration v08
  • Tests

12. Changelog

Date Change
2026-02-07 Initial draft