Per-unit pricing for discrete products
Build and push image / build (push) Successful in 51s

Pre-rolls, edibles, and vaporizers are sold and reasoned about per unit
("$10 each") rather than as a bag total. The Add and Edit forms now ask
for "Price per unit" when the kind is discrete, and the product drawer
displays the per-unit number with the total as a small subline. Bulk
products (flower, concentrate, tincture) still take and show a total.

The stored price column remains the total, so existing data, spend
totals, sort-by-price, and bin value calculations all keep working
unchanged. Conversion (pricePerUnit × countOriginal) happens at the
form boundary on save and the inverse on edit-modal load.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 21:59:35 -04:00
parent edb8e2ac92
commit cd7aeb9d09
3 changed files with 61 additions and 9 deletions
+28 -4
View File
@@ -180,7 +180,31 @@ export function ProductDetail({
>
{(
[
["Price", fmt.money(product.price)],
[
"Price",
product.kind === "discrete" && product.countOriginal > 0 ? (
<>
{fmt.money(product.price / product.countOriginal)}
<span style={{ fontSize: 14, color: "var(--ink-3)", marginLeft: 4 }}>
/unit
</span>
<div
style={{
fontSize: 11,
color: "var(--ink-3)",
fontWeight: 400,
marginTop: 2,
fontFamily: "var(--mono)",
letterSpacing: 0,
}}
>
{fmt.money(product.price)} total
</div>
</>
) : (
fmt.money(product.price)
),
],
[
product.kind === "discrete" ? "Quantity" : "Size",
product.kind === "discrete"
@@ -189,9 +213,9 @@ export function ProductDetail({
],
["THC", `${product.thc.toFixed(1)}%`],
["CBD", `${product.cbd.toFixed(1)}%`],
] as [string, string][]
).map(([l, v]) => (
<div key={l} style={{ padding: "18px 16px", background: "var(--surface)" }}>
] as [string, React.ReactNode][]
).map(([l, v], i) => (
<div key={i} style={{ padding: "18px 16px", background: "var(--surface)" }}>
<div className="smallcaps" style={{ color: "var(--ink-3)" }}>{l}</div>
<div className="serif" style={{ fontSize: 26, marginTop: 4, fontWeight: 500 }}>{v}</div>
</div>