FunkyJuiceRecipes/MILESTONES.md
Funky Waddle c8655e24e4 feat(db,models,dao,logic): nicotine inventory + flavor snapshots; drop legacy nic_pct; migrations, tests
• Migrations
	◦ Create nicotine table with NOCASE strings, base PG/VG check, strength_mg_per_ml (>0), soft-delete, and optional inventory metadata (bottle_size_ml, cost, purchase_date).
	◦ Alter recipe: add nic_target_mg_per_ml (NOT NULL), nic_strength_mg_per_ml (NOT NULL), nicotine_id (FK ON DELETE SET NULL); keep nic_base. Drop legacy nic_pct via rebuild migration.
	◦ Alter flavor: add bottle_size_ml, cost, purchase_date (nullable).
	◦ Alter recipe_flavor: add flavor snapshot columns (flavor_name_snapshot, flavor_company_snapshot NOCASE, flavor_base_snapshot PG/VG CHECK).
	◦ Ensure migration order runs “_created” before ALTERs.
• Models
	◦ Add Nicotine model.
	◦ Update Recipe with nic_target_mg_per_ml, nic_strength_mg_per_ml, nic_base, optional nicotine FK.
	◦ Update Flavor with optional inventory metadata.
	◦ Update RecipeFlavor with snapshot fields and unique index remains.
• DAOs
	◦ Add NicotineRepository (CRUD, list with soft-delete filters; hard_delete_when_safe blocked when referenced by recipes).
	◦ Update RecipeRepository:
		▪ create/update accept nic_target_mg_per_ml, nic_strength_mg_per_ml, nic_base, optional nicotine_id.
		▪ If nicotine_id provided, snapshot strength/base from inventory unless overridden.
		▪ replace_ingredients uses diff-based updates and populates flavor snapshots on insert.
	◦ Update FlavorRepository to edit inventory metadata; soft/undelete; hard delete only when safe.
• DB init
	◦ Bind Peewee models to runtime DB; tweak migration ordering logic.
• Logic
	◦ Add calculation engine (compute_breakdown, breakdown_for_view) supporting target nicotine mg/mL and stock strength mg/mL; rounding policy for display.
• Tests
	◦ Update/init DB tests to include nicotine table and flexible migration counts.
	◦ Add calculation tests (120 mL example, nic in VG, 50 mg/mL stock, validations).
	◦ Add DAO tests including flavor snapshots stability and replace_ingredients diff behavior.
	◦ All tests passing: 15 passed.
• Docs
	◦ Update SPECS and MILESTONES; strike through Milestones 3 and 4.

BREAKING CHANGE: remove Recipe.nic_pct field and any compatibility code. API changes in RecipeRepository.create/update now require mg/mL fields and use snapshot+FK model for nicotine.
2025-12-18 19:55:22 -06:00

124 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### FunkyJuice Recipes — Project Milestones
This document outlines the sequence of milestones to deliver the FunkyJuice Recipes desktop app using Toga, Peewee (SQLite), and Briefcase. Each milestone is scoped to be achievable in a short iteration and includes clear acceptance criteria.
---
### ~~Milestone 1 — Project skeleton and tooling~~
- ~~Set up `src/funkyjuicerecipes/` package layout per SPECS.~~
- ~~Add minimal `app.py` with `FunkyJuiceRecipesApp` and `main()` returning the app.~~
- ~~Configure `pyproject.toml` (already added) and ensure `briefcase dev` can start a blank window.~~
- ~~Add `tests/` folder and test runner config.~~
~~Acceptance:~~
- ~~`briefcase dev` launches an empty Toga window titled “FunkyJuice Recipes”.~~
- ~~`pytest` runs (even with zero or smoke tests).~~
---
### ~~Milestone 2 — Database initialization and migrations framework~~
- ~~Implement `data/db.py` using `app.paths.data` and Peewee pragmas (`foreign_keys=1`, WAL).~~
- ~~Create migrations table and a simple migration runner that detects unapplied migration files by filename.~~
- ~~Implement initial migrations for `flavor`, `recipe`, and `recipe_flavor` tables matching SPECS DDL.~~
~~Acceptance:~~
- ~~On first launch, DB file is created in the peruser data directory, tables exist, and migrations table is populated.~~
- ~~Subsequent launches do not re-run applied migrations.~~
---
### ~~Milestone 3 — Peewee models and DAOs~~
- ~~Implement `Flavor`, `Recipe`, `RecipeFlavor` models reflecting constraints (UNIQUEs, FKs, CHECKs where applicable in logic).~~
- ~~Provide DAO/helper functions for common ops (create/list/get/update/delete) with soft-delete semantics for flavors).~~
- ~~Enable case-insensitive uniqueness for `Flavor(name, company)`.~~
~~Acceptance:~~
- ~~Unit tests can create flavors (no duplicates ignoring case), recipes, and link ingredients; soft-deleted flavors are excluded by default queries.~~
---
### ~~Milestone 4 — Calculation engine~~
- ~~Implement pure functions in `logic/calculations.py` to compute PG/VG/Nic and per-flavor mL from inputs (percents + size).~~
- ~~Include validation (non-negative PG/VG; base_pg + base_vg = 100; percent totals ≈ 100 within tolerance).~~
- ~~Define rounding/display policy (e.g., 1 decimal for View screen).~~
~~Acceptance:~~
- ~~Tests cover the README example (120 mL case) and edge cases (nic in PG vs VG, excessive flavor %).~~
---
### Milestone 5 — Main window and navigation shell
- Build `MainWindow`: menu bar (File/New Recipe/Exit; Help/About), buttons for Inventory, recipe list placeholder.
- Wire basic screens/routes (View Recipe, Add/Edit Recipe, Inventory) with placeholders.
Acceptance:
- App displays main list and can navigate to empty placeholder screens and back.
---
### Milestone 6 — Inventory screen (CRUD + soft delete)
- Implement `FlavorsTable` with add/edit/delete.
- Enforce no duplicates; on delete, soft-delete if referenced by recipes; otherwise hard-delete.
- Provide toggle to view soft-deleted flavors and actions to undelete or hard-delete when safe.
Acceptance:
- Users can manage flavors per README, with correct soft/hard delete behavior.
---
### Milestone 7 — Add/Edit Recipe screens
- Implement `RecipeForm` with PG/VG base, Nic % and base, size, and flavor lines (select existing flavors + percentage).
- Auto-maintain PG + VG = 100; prevent negatives.
- On save: validate, combine duplicate flavors (prompt as specified), persist recipe + ingredients.
Acceptance:
- Users can create and edit recipes meeting validation rules and duplicate-combine flow.
---
### Milestone 8 — View Recipe screen
- Render computed components (PG, VG, Nic, flavors) using calculation engine, rounded to 1 decimal.
- Support view mode toggle: Individual Flavors vs Flavor Prep total.
- Provide action to open Edit, Delete confirmation, and Inventory.
Acceptance:
- A saved recipe displays correct amounts; toggle updates view accordingly.
---
### Milestone 9 — Flavor Prep mixer utility
- Implement “Mix Flavor Prep” dialog/workflow computing batch amounts from recipe flavor ratios for selectable sizes (10/30/120 mL, etc.).
- No persistence for Flavor Prep (ephemeral), but support printing/exporting batch breakdown (optional CSV).
Acceptance:
- Users can choose a batch size and see per-flavor mL for the prep; closing returns to View Recipe.
---
### Milestone 10 — Polishing, About, and edge behaviors
- Implement About dialog (app name, version, author).
- Confirm unsaved-changes prompts on screen change and app exit while editing.
- Empty states, error dialogs, and friendly validation messages.
Acceptance:
- UX polish complete; no obvious dead-ends; dialogs work across platforms.
---
### Milestone 11 — Packaging and distribution
- Verify `briefcase dev` on target OS; add icons under `resources/`.
- Build installers with Briefcase for target platforms.
- Document install/run instructions and DB location.
Acceptance:
- Installers build successfully; smoke test of installed app passes.
---
### Milestone 12 — Testing and CI (optional but recommended)
- Add unit tests for models/DAOs and calculations; UI smoke tests using Toga Dummy backend where feasible.
- Set up a simple CI (e.g., GitHub Actions) to run tests on push.
Acceptance:
- CI passes on main branch; coverage of calculation and DAO logic acceptable.