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>
This commit is contained in:
2026-06-06 18:28:55 -04:00
parent d7da7afe5e
commit 5fa1e34914
19 changed files with 769 additions and 134 deletions
+7 -4
View File
@@ -3,7 +3,7 @@
// consumed. Gone items contribute spend but NOT grams (so daily averages
// stay clean). Operates on the enriched Item[] view, not raw products.
import type { Bootstrap, Item } from "./types.js";
import type { Bin, Bootstrap, Item } from "./types.js";
import { TYPES, helpers, enrichItems } from "./types.js";
import { getToday, getStoredTimezone } from "./tz.js";
@@ -37,7 +37,8 @@ export interface Stats {
goneCount: number;
archivedCount: number;
purchaseCount: number;
overdueAudits: Item[];
overdueWeighIns: Item[];
overdueBinChecks: Bin[];
lowStockBulk: Item[];
lowStockDiscreteGroups: {
key: string;
@@ -220,7 +221,8 @@ export function computeStats(data: Bootstrap): Stats {
}
const avgGap = gaps.length > 0 ? gaps.reduce((a, b) => a + b, 0) / gaps.length : 0;
const overdueAudits = active.filter((p) => helpers.auditOverdue(p, todayStr));
const overdueWeighIns = active.filter((p) => helpers.auditOverdue(p, todayStr));
const overdueBinChecks = data.bins.filter((b) => helpers.binCheckOverdue(b, todayStr));
const lowStockBulk = active.filter(
(p) => p.kind === "bulk" && helpers.pctRemaining(p) < 0.25,
@@ -283,7 +285,8 @@ export function computeStats(data: Bootstrap): Stats {
goneCount: gone.length,
archivedCount: consumed.length + gone.length,
purchaseCount: items.length,
overdueAudits,
overdueWeighIns,
overdueBinChecks,
lowStockBulk,
lowStockDiscreteGroups,
};