# Changelog

The version lives in `app/version.py` (shown in the main window title and stamped
into both packaged builds). Add an entry here per release — it doubles as the source
for community update posts.

## 0.3.11 — 2026-07-21

Smarter reorder timing + supplier-aware group buys + a tighter sidebar:

- **Model vs. behavior cross-check** — Reorders now shows a "Cadence says"
  column: when each client's own delivery history expects them back (average
  gap between dated deliveries). Disagreements beyond two weeks are flagged —
  "behavior says 18d SOONER" — so stale supply inputs or changed habits
  surface instead of hiding inside a confident-looking runout date.
- **Ramp starts itself** — converting a prospect on a product that has a
  default dose ladder now auto-assigns that ladder (start = today) when the
  client doesn't have their own, so new clients get ramp-aware runout math
  from day one. The convert dialog says so when it will happen; never in the
  dosing-safe edition, never overriding a per-client pick.
- **Group Buy on any supplier channel** — the campaign's channel picker now
  lists every channel on your active supplier offerings (EU warehouse,
  multipacks, whatever your imported price lists carry), not just the built-in
  China/US pair. Campaign pricing prefers the cheapest live offering on the
  chosen channel (volume tiers applied) and falls back to the built-in catalog.
- **One outreach slot** — Group Buy and Promos now live as tabs inside
  Campaigns (like Stock consolidates Inventory/Orders/Reorders). Every
  cross-link still lands on the right tab, including agenda double-clicks.

## 0.3.10 — 2026-07-21

- **Guide covers Campaigns** — a full section on the new Campaigns tab
  (audiences, message tokens, the copy-and-mark-contacted flow, no-double-nudge
  skip), contact channels + the "No contact info" audit filter documented under
  Customers, the Group Buy → "Nudge in Campaigns" hand-off, and a step-by-step
  "Run a reorder nudge campaign" workflow.

## 0.3.9 — 2026-07-21

Campaigns — proactive outreach:

- **New Campaigns tab (Clients group)** — turn "who's due to reorder" into
  actual messages. Build an audience by urgency (due/overdue, +soon, or
  everyone), product, and stage; the same reorder engine behind Group Buy and
  Promos does the targeting. Write one message with tokens ({first_name},
  {product}, {reorder_date}, {days_left}, plus {deadline}/{reward} from the
  active group buy) and work the list: **Copy & Mark Contacted** puts each
  client's personalized message on the clipboard and stamps them, or grab the
  whole audience as a text blob / CSV export.
- **No double-nudging** — marking someone contacted stamps a last-contacted
  date, and audiences skip anyone contacted within the last N days (default 7).
- **Contact channels on clients** — new Venmo handle and preferred-channel
  (text / email / Venmo) fields on customers and prospects, shown alongside
  phone/email. Contact gaps glow red in the campaign audience (double-click to
  fix in place), and a new **"No contact info"** filter in Customers surfaces
  everyone you can't reach at all.
- **Group Buy → "Nudge in Campaigns"** — jump straight from the nudge list to
  the tool that actually contacts them.
- Client CSV import/template now carries a `venmo` column.

## 0.3.8 — 2026-07-20

Idempotent deliveries:

- **One hand-off, one record** — recording a delivery for a client who already
  has one for the same product on the same day now stops and asks before
  drawing stock and booking revenue a second time. This closes the trap where
  converting a prospect with "deliver from stock" and then opening Deliver/Sell
  (for the labels/packing slip) double-drew inventory and double-booked the
  sale. Deliberate second deliveries still work — you just confirm them.

## 0.3.7 — 2026-07-20

Label profile memory + printed-lot tracking:

- **Your label profile sticks** — brand line, purity, and both disclaimers now
  save as defaults whenever you print or export (product fields like
  descriptor/formula already did). Batch and Exp stay per-lot and are never
  remembered.
- **The app knows what's already labeled** — every successful vial-label print
  is logged per lot. Labeled lots show "✓ N labeled" in the From Lot / Order
  picker, the dialog preselects the oldest UNLABELED lot instead, and
  reselecting a labeled one warns before you reprint. Packet tags (D30) are
  logged too but don't mark a lot as labeled.

## 0.3.6 — 2026-07-20

Label QR correctness:

- **Generated dose-page QRs never stick to the product** — printing a label
  used to save the auto-filled QR (which can carry one client's personal scan
  code) back onto the product, so later labels would show a stale link and
  misattribute scans. Only a hand-entered QR link persists now.

## 0.3.5 — 2026-07-20

Titration ladder editor:

- **Edit Ladders** — dose templates are now editable in-app (they were seed
  data until now). Open from the client editor's Ramp schedule row or the
  product editor's Dose page schedule row: create, rename, duplicate, and
  delete ladders, and edit their steps (week a dose starts → weekly mg).
  Steps validate (weeks start at 1, no negative doses), sort themselves, and
  save on Save/switch/close.
- **Safe deletes** — deleting a ladder shows how many clients, stack peptides,
  and products point at it first; they fall back to flat dose /
  auto-by-family. Fresh installs still ship with zero built-in schedules.

## 0.3.4 — 2026-07-20

Per-product dose page schedule + signed builds:

- **Dose page schedule per product** — the product editor now picks which
  titration ladder the customer dose page shows: Auto (match the product
  family's Standard ladder), a specific template, or no schedule (the page
  falls back to its your-dose calculator). Client-level assignments (Customers
  → client → Dose Template) are unchanged and still drive forecasting.
- **Stable code signing** — builds sign with the best identity in the keychain
  (Developer ID → self-signed → Apple Development for operator builds), so
  macOS keeps Bluetooth-printing permission across updates. Developer ID
  builds get hardened runtime + one-command notarization
  (`RATATOUILLE_NOTARIZE=1`), ending the right-click→Open dance for customers.

## 0.3.3 — 2026-07-20

Label maker: print quantities + lot recall:

- **Copies** — print any number of labels in one go on both printers (the M2
  uses its native copies command; the D30 prints one tag per copy in a single
  send).
- **From Lot / Order picker** — every on-hand FIFO lot is offered right in the
  dialog (received date · batch · PO · vials on hand). Picking one recalls the
  batch origin from the book — batch field, matching CoA's QR + purity — no
  retyping. "Manual" prints with no lot seed.
- **Smart default count** — copies default to the picked lot's on-hand vials
  (label what you hold); labels opened from a delivery default to the vials
  just delivered. Your own edit always wins and survives lot switches.

## 0.3.2 — 2026-07-20

Scan evidence applies itself:

- **Auto-apply on launch** — a few seconds after the app opens it quietly pulls
  the dose-page scan log and applies any fresh break-seal evidence, then
  repaints the current view. Offline launches, dosing-safe books, and books
  without an admin token behave exactly as before; manual/deliver dates are
  still never overwritten. Scan Log remains for reviewing the detail.

## 0.3.1 — 2026-07-20

Scan Log — QR scans become inventory evidence:

- **Customers → Scan Log** — dose-page scans mapped back to clients: assumed
  break-seal (mix) date, estimated vial expiry, scan count, and observed
  days-per-vial pace. Re-scans within half a shelf life count as lookups, not a
  new vial, so clients who check their units every injection don't reset their
  own clock.
- **Apply Break-Seal Dates** — one click stamps each client's latest break-seal
  as their last-opened date (depleting the snapshot to that date first), so
  runout countdowns and reorder alerts tick on real scan behavior — especially
  the clients who never had an open date recorded. Newer manual/deliver evidence
  is never overwritten.
- The scan log needs the activation server's admin token pasted once; scans key
  on opaque codes, so no client names ever touch the server.

## 0.3.0 — 2026-07-20

Vial QR → customer dose page (operator edition):

- **Dose page on the site** — vial-label QR codes now default to
  getratatouille.app/dose?p=&lt;product&gt;: a branded page where the customer taps
  their reconstitution volume (2 or 3 mL) and reads their titration schedule as
  U-100 syringe units, plus the mixed-vial use-by window. Bac water entries show
  only how much to use. Data comes from `dose-data.json`, exported from the book
  (`python -m app.dosepage <site_dir>`) and listing only products in stock or in
  use.
- **Scan attribution** — labels printed from the Deliver flow embed the client's
  opaque scan code, and the page beacons scans to the activation server: first
  scan ≈ break-seal date (bounds expiry), scan gaps ≈ usage pace. No names ever
  leave the machine — only the app can map a code to a person.
- **Dosing-safe books are exempt** — a dose link is a dosing surface, so the
  reseller edition never auto-fills one; an explicit per-product QR link always
  wins.

## 0.2.5 — 2026-07-20

Reorder alerts respect the vial's actual death date:

- **The last vial no longer gets the reconstitution buffer** — the buffer is the
  gap between finishing one vial and mixing the next, so it can't extend the
  final vial. A lone 60-day vial used to project 72 days of supply; runout now
  lands exactly on mixed date + shelf life.
- **Runout can never outlive the last vial's expiry** — ramp (titration) clients'
  week-by-week projection is now hard-capped by when their on-hand vials actually
  die, so clients whose open vial has already expired flip to overdue instead of
  showing days of phantom supply.

## 0.2.4 — 2026-07-19

Shelf-life-correct stock forecasting:

- **Demand forecast honors reconstituted shelf life** — the stock demand feeding
  Reorders, Forecast, group-buy sizing, and the order dialog now caps how long a
  mixed vial can last (default 60 days). Slow/maintenance clients on low doses were
  previously forecast as if one vial could stretch for months, so demand, par
  targets, and reorder dates all ran low.
- **Per-product shelf life** — peptides differ, so each product can now state its
  own reconstituted usable life (product editor → "Shelf life (mixed)"). Blank
  means the app-wide 60-day default; a set value wins everywhere that consumption
  is modeled, including runout alerts and per-shot consumables.

## 0.2.3 — 2026-07-18

Support channel wired in:

- **Discord support server** — the Ratatouille App Discord
  (discord.gg/EGH9DpNRSZ) is now linked from the Guide (Getting started and
  What's New) and from Settings, and the links actually open in your browser.
  License/payment questions go through a private ticket there or email, so keys
  stay private.

## 0.2.2 — 2026-07-18

Version history in the app:

- **Guide → What's New** — the app now shows its full version history (this file)
  in the Guide, next to the version you're running, so "is my app current?" and
  "which release added that feature?" are answerable in the app itself.
- **Settings** shows the running version under the title; it stays in the window
  title too.
- **Guide completeness pass** — batch auto-fill, Deliver-time artifacts (labels /
  D30 tag / packing slip), the Dashboard "Stock by peptide" panel, and a start-to-
  finish "Deliver to a client" workflow are all documented now.

## 0.2.1 — 2026-07-18

Label-flow and reporting refinements:

- **Batch flows to the label automatically** — opening Make Label at the product
  level now pre-fills Lot/Batch (and the matching CoA's QR + purity) from the oldest
  on-hand FIFO lot, the stock that ships first. Fully editable — keeping it on the
  label is your call.
- **Stock page** — labels are now a right-click on the rolling-inventory product
  (same modal as Sourcing) or on a FIFO source lot (carries that lot's batch/PO);
  the two dead-end header buttons are gone.
- **Stock reporting is yours, not the catalog's** — the dashboard/stock peptide
  picker only shows products with clients, orders, or inventory history; a supplier
  price-list import no longer floods reporting with never-stocked items.
- **Everything fits** — the app opens wide enough that every table shows all its
  columns (clamped to your screen); single columns cap-and-elide instead of pushing
  others off-screen; the label dialog opens at its natural width.
- **Guide** — label section rewritten (all entry points, name fonts, D30 tags,
  direct Bluetooth printing); Stock section documents the right-click flows.

## 0.2.0 — 2026-07-18

Label maker parity with (and past) the free web tool:

- **Name fonts** — 5 bundled OFL display faces (Bebas Neue, Archivo Black, Alfa Slab
  One, Abril Fatface, Cutive Mono) plus 3 system stacks, selectable for the hero
  name + brand on all 16 label styles. Meta text stays Oswald for legibility.
- **D30 packet tags** — new "Print to" target in Make Label: skinny die-cut tags
  (40×12 / 30×12 / 40×15 / 12×12 mm) with up to 3 free-form lines, 12 border
  packages, 8 graphic motifs, left/center align, and direct Bluetooth printing to a
  Phomemo D30 (scan once, remembered after).
- **Deliver flow** — optional "Print a packet tag (D30) after delivering" alongside
  the existing vial labels + packing slip artifacts.
- **Versioning** — the app now shows its version in the window title; both installer
  builds carry the same number.

## 0.1.0

Baseline packaged app: 10 tabs (dashboard, stock, clients, orders, finance, forecast,
optimizer, pricing, documents, settings), 16-style vial label maker with Niimbot M2
Bluetooth printing, CoA-driven QR labels, document generator, crypto-first licensing.
