Commit Graph

9 Commits

Author SHA1 Message Date
josh 5fa1e34914 Split audits into Weigh Ins (bulk) and Bin Checks (discrete)
Build and push image / build (push) Successful in 57s
Replaces the unified audit system with two purpose-built flows:
- Weigh Ins: rebranded audit flow for bulk products (Flower, Concentrate,
  Tincture) with scale weigh, container weigh, and estimate modes
- Bin Checks: new bin-level presence check — select a bin, scan every item,
  resolve discrepancies (wrong bin, unknown, missing), auto-records presence
  audits on verified items

Adds cadence_days and last_checked to bins table, with per-bin overdue
tracking on the dashboard and bins view.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-06 18:28:55 -04:00
josh 538e5079ab Fix 18 UX issues: confirmations, undo, drawer nav, empty states, and polish
Build and push image / build (push) Successful in 54s
Comprehensive UX audit covering modals, drawers, dashboard, and inventory.
Key changes: confirmation steps before destructive actions, undo via toast
for consume/gone/checkout, back-navigation across entity drawers, optional
ratings, discrete item count field, audit progress bar, and sortable column
affordance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-08 16:25:41 -04:00
josh a1be29ab6e Add container weight tracking for weigh-based concentrate audits
Build and push image / build (push) Successful in 1m6s
Record the total weight of a jar (product + container) at acquisition so
audits can be done by simply re-weighing the sealed jar. The tare is
derived (containerWeight − productWeight), and the audit flow offers a
"Weigh container" toggle that auto-calculates remaining product from the
scale reading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 23:11:39 -04:00
josh e7fd9af62c Add checkout/custody feature for tracking items in personal possession
Build and push image / build (push) Successful in 1m8s
Items can now be checked out of their bin into "my custody" and later
checked back in or marked consumed. Adds checkout/checkin API endpoints,
a My Custody sidebar page, CheckoutFlow and CheckinFlow modals, and
updates ProductDetail, Inventory, ConsumeFlow, and MarkGoneFlow to
handle the new checked-out status. Bulk items prompt for remaining
weight on check-in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-07 20:49:58 -04:00
josh 80034b47c5 User-supplied asset ids; brand on product; strain is the name
Build and push image / build (push) Successful in 48s
Four UX changes after using the rework for a bit:

1. Asset ids are 6-digit numbers from a roll of physical labels — server
   no longer generates them. POST /api/inventory requires assetId; the
   add-inventory form has a digits-only input that auto-focuses on entry.
2. Strain and product name are the same thing. Drop products.name; the
   strain's name supplies the display. Product creation just asks for
   "Name (strain)" and matches/creates a strain by that name.
3. Brand moves from inventory_items to products. SKUs are brand-specific,
   so all instances of a product share the brand. Brand selector lives
   on the product create/edit form, not the per-instance form.
4. Scanning an unknown SKU on the add-inventory step now opens the
   create-product subform with the SKU prefilled — one less click.

Migration: detect prior shape (products.name column present) and rename
products/inventory_items/audits to *_v1 archives, recreate empty.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 18:17:12 -04:00
josh 02dc6e523f Track inventory at the instance level, not by product
Build and push image / build (push) Successful in 46s
The products table conflated catalog ("kind of thing you scan") with
instance ("this jar I bought") — splitting it lets us record every
purchase as its own asset and autofill brand/shop/price/THC from the
last instance when scanning a known SKU.

- products: sku + strain + name + type + kind (catalog only)
- inventory_items: physical jars with short-UUID asset ids, per-batch
  brand/shop/bin/price/cannabinoids/weight, audits, lifecycle
- audits now key on inventory_id; strains lose brand_id and type
- migration: rename existing products/audits/strains to *_legacy on
  first boot so users keep historical reference, fresh start otherwise
- two-step add flow: scan SKU → select/create product → instance
  details (autofilled from last instance) → generated asset id shown
- ScanField matches asset id first, falls back to SKU
- inventory list defaults flat, "By product" toggle groups instances

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 05:59:46 -04:00
josh 1abfda7989 Use the real today everywhere
Build and push image / build (push) Successful in 53s
The client constant TODAY_STR and the bootstrap response's today field
were both hardcoded to 2026-04-25, leaving date inputs in the New
product, Audit, and Mark consumed flows seeded with a stale date and
quietly staling out every "days since" / audit-overdue calculation
across the app.

TODAY_STR now resolves at module load from new Date() in local time,
and bootstrap returns new Date().toISOString().slice(0, 10).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:20:24 -04:00
josh d335525073 Group bins by letter, sort by number, drop location
Build and push image / build (push) Successful in 46s
Bins follow an A1/A2/B1 naming convention, so the Bins page now parses
the leading letter prefix as a row group and the trailing number as the
within-row order. Each letter starts a fresh grid section; bins whose
names don't match the pattern fall into a trailing "Other" bucket
sorted alphabetically.

Removes the optional location field from bins end to end: the API
client signatures, server POST/PATCH routes, both product-flow inline
creates, the dropdown labels, the ProductDetail bin row, and the
BinsView header line. The bootstrap query explicitly projects only
id/name/capacity so the dead column doesn't leak through.

The location column stays in the bins table on disk to avoid a
migration on existing deployments — it just isn't read or written.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:07:12 -04:00
josh 027cf032be Initial commit: Apothecary v0.4.0 2026-05-03 20:19:26 -04:00