Commit Graph

2 Commits

Author SHA1 Message Date
rob 36d02fcb73 Material-aware pricing: oak ≠ pine
Resolves the v1 simplification where every species cost the same.

- CutItem/StockPiece gain `material`; build_cut_plan and reoptimize group by
  (stock, material) so each bought stick/sheet is a single species; pieces are
  stamped with their material (offcut seeds keep theirs).
- prices.estimate groups by (stock, species) and applies a per-species
  multiplier (DEFAULT_MATERIAL_MULTIPLIERS: SPF 1.0, oak 3.0, walnut 5.5, …),
  persisted to material_multipliers.json. CostLine shows "oak 1x4".
- PriceEditDialog gains a species-multiplier table; BOM Buy list shows species.
- Offcuts carry material so offcut reuse matches species.
- tests: multiplier scales price, default species at base, mixed species on the
  same stock priced separately, multiplier save/load.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:48:26 -03:00
rob 067ec0ea46 Add cost estimate (Cost tab) with editable Kent NB price book
New shop-packet output: a printable cost estimate driven by the active
CutPlan's buy-counts × a curated, editable price book (HST 15%).

- prices.py: DEFAULT_PRICES seeded with real Kent (New Brunswick) shelf
  prices per buy-unit (lumber = 8' stick, plywood = 4x8 sheet); persisted to
  $XDG_CONFIG_HOME/woodshop/prices.json (defaults + saved overrides).
  estimate() -> CostEstimate (lines/subtotal/tax/total/missing); lumber price
  scales with stick length; unknown stock is flagged, never invented.
- BOM window: Cost tab with "Edit prices…" (PriceEditDialog), "Refresh from
  Kent…", and Print.
- fetch_kent_prices() + scripts/fetch_kent_prices.py: best-effort refresh.
  Kent renders prices client-side (not in HTML), so it tries a static parse
  then Playwright if installed — honest that it may need updating.
- tests: estimate math, per-sheet plywood, stick-length scaling, missing-price
  flagging, save/load roundtrip, corrupt-file fallback, JSON-LD parse, cost
  tab render + price edit persistence. 153 passing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 16:23:59 -03:00