2025-12-18 15:49:31 +00:00
### 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.
---
2025-12-18 20:30:09 +00:00
### ~~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.~~
2025-12-18 15:49:31 +00:00
2025-12-18 20:30:09 +00:00
~~Acceptance:~~
- ~~`briefcase dev` launches an empty Toga window titled “FunkyJuice Recipes”.~~
- ~~`pytest` runs (even with zero or smoke tests).~~
2025-12-18 15:49:31 +00:00
---
2025-12-18 20:30:09 +00:00
### ~~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.~~
2025-12-18 15:49:31 +00:00
2025-12-18 20:30:09 +00:00
~~Acceptance:~~
- ~~On first launch, DB file is created in the per‑ user data directory, tables exist, and migrations table is populated.~~
- ~~Subsequent launches do not re-run applied migrations.~~
2025-12-18 15:49:31 +00:00
---
2025-12-18 20:30:09 +00:00
### ~~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)` .~~
2025-12-18 15:49:31 +00:00
2025-12-18 20:30:09 +00:00
~~Acceptance:~~
- ~~Unit tests can create flavors (no duplicates ignoring case), recipes, and link ingredients; soft-deleted flavors are excluded by default queries.~~
2025-12-18 15:49:31 +00:00
---
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-19 01:55:22 +00:00
### ~~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).~~
2025-12-18 15:49:31 +00:00
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-19 01:55:22 +00:00
~~Acceptance:~~
- ~~Tests cover the README example (120 mL case) and edge cases (nic in PG vs VG, excessive flavor %).~~
2025-12-18 15:49:31 +00:00
---
### 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.