Add container weight tracking for weigh-based concentrate audits
Build and push image / build (push) Successful in 1m6s
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>
This commit is contained in:
@@ -14,6 +14,7 @@ db.pragma("foreign_keys = ON");
|
||||
archiveLegacyIfPresent();
|
||||
archiveV1IfPresent();
|
||||
migrateAddCheckoutDate();
|
||||
migrateAddContainerWeight();
|
||||
|
||||
const schema = readFileSync(join(__dirname, "schema.sql"), "utf8");
|
||||
db.exec(schema);
|
||||
@@ -26,6 +27,14 @@ function migrateAddCheckoutDate(): void {
|
||||
db.exec(`ALTER TABLE inventory_items ADD COLUMN checkout_date TEXT`);
|
||||
}
|
||||
|
||||
function migrateAddContainerWeight(): void {
|
||||
const cols = db
|
||||
.prepare(`PRAGMA table_info(inventory_items)`)
|
||||
.all() as { name: string }[];
|
||||
if (cols.length === 0 || cols.some((c) => c.name === "container_weight")) return;
|
||||
db.exec(`ALTER TABLE inventory_items ADD COLUMN container_weight REAL`);
|
||||
}
|
||||
|
||||
// One-shot migration: the original schema put per-instance fields (weight,
|
||||
// bin_id, etc.) directly on `products`. The split schema separates products
|
||||
// (catalog) from inventory_items (instance). When we detect the old shape,
|
||||
|
||||
@@ -24,6 +24,7 @@ type InventoryRow = {
|
||||
cbd: number;
|
||||
total_cannabinoids: number;
|
||||
weight: number;
|
||||
container_weight: number | null;
|
||||
last_audit_weight: number | null;
|
||||
count_original: number;
|
||||
count_last_audit: number | null;
|
||||
@@ -101,6 +102,7 @@ bootstrapRouter.get("/bootstrap", (_req, res) => {
|
||||
cbd: i.cbd,
|
||||
totalCannabinoids: i.total_cannabinoids,
|
||||
weight: i.weight,
|
||||
containerWeight: i.container_weight,
|
||||
lastAuditWeight: i.last_audit_weight,
|
||||
countOriginal: i.count_original,
|
||||
countLastAudit: i.count_last_audit,
|
||||
|
||||
@@ -15,6 +15,7 @@ type CreateBody = {
|
||||
weight?: number;
|
||||
countOriginal?: number;
|
||||
unitWeight?: number;
|
||||
containerWeight?: number | null;
|
||||
purchaseDate: string;
|
||||
};
|
||||
|
||||
@@ -53,14 +54,14 @@ inventoryRouter.post("/inventory", (req, res) => {
|
||||
id, asset_id, product_id,
|
||||
shop_id, bin_id,
|
||||
price, thc, cbd, total_cannabinoids,
|
||||
weight, last_audit_weight,
|
||||
weight, container_weight, last_audit_weight,
|
||||
count_original, count_last_audit, unit_weight,
|
||||
purchase_date, status
|
||||
) VALUES (
|
||||
@id, @assetId, @productId,
|
||||
@shopId, @binId,
|
||||
@price, @thc, @cbd, @totalCannabinoids,
|
||||
@weight, @lastAuditWeight,
|
||||
@weight, @containerWeight, @lastAuditWeight,
|
||||
@countOriginal, @countLastAudit, @unitWeight,
|
||||
@purchaseDate, 'active'
|
||||
)`,
|
||||
@@ -75,6 +76,7 @@ inventoryRouter.post("/inventory", (req, res) => {
|
||||
cbd: body.cbd ?? 0,
|
||||
totalCannabinoids: body.totalCannabinoids ?? 0,
|
||||
weight: isDiscrete ? 0 : body.weight ?? 0,
|
||||
containerWeight: isDiscrete ? null : body.containerWeight ?? null,
|
||||
lastAuditWeight: isDiscrete ? null : body.weight ?? 0,
|
||||
countOriginal: isDiscrete ? body.countOriginal ?? 0 : 0,
|
||||
countLastAudit: isDiscrete ? body.countOriginal ?? 0 : null,
|
||||
@@ -95,6 +97,7 @@ type UpdateBody = Partial<{
|
||||
cbd: number;
|
||||
totalCannabinoids: number;
|
||||
weight: number;
|
||||
containerWeight: number | null;
|
||||
countOriginal: number;
|
||||
unitWeight: number;
|
||||
purchaseDate: string;
|
||||
@@ -110,6 +113,7 @@ type ItemRow = {
|
||||
cbd: number;
|
||||
total_cannabinoids: number;
|
||||
weight: number;
|
||||
container_weight: number | null;
|
||||
last_audit_weight: number | null;
|
||||
count_original: number;
|
||||
count_last_audit: number | null;
|
||||
@@ -121,8 +125,8 @@ function doUpdate(id: string, body: UpdateBody): void {
|
||||
const existing = db
|
||||
.prepare<[string], ItemRow>(
|
||||
`SELECT id, shop_id, bin_id, product_id, price, thc, cbd,
|
||||
total_cannabinoids, weight, last_audit_weight, count_original,
|
||||
count_last_audit, unit_weight, purchase_date
|
||||
total_cannabinoids, weight, container_weight, last_audit_weight,
|
||||
count_original, count_last_audit, unit_weight, purchase_date
|
||||
FROM inventory_items WHERE id = ?`,
|
||||
)
|
||||
.get(id);
|
||||
@@ -161,6 +165,12 @@ function doUpdate(id: string, body: UpdateBody): void {
|
||||
!isDiscrete && Number.isFinite(body.weight) && (body.weight as number) >= 0
|
||||
? (body.weight as number)
|
||||
: existing.weight;
|
||||
const nextContainerWeight =
|
||||
body.containerWeight === undefined
|
||||
? existing.container_weight
|
||||
: body.containerWeight != null && Number.isFinite(body.containerWeight)
|
||||
? body.containerWeight
|
||||
: null;
|
||||
const nextCountOriginal =
|
||||
isDiscrete && Number.isFinite(body.countOriginal) && (body.countOriginal as number) >= 0
|
||||
? Math.floor(body.countOriginal as number)
|
||||
@@ -184,6 +194,7 @@ function doUpdate(id: string, body: UpdateBody): void {
|
||||
cbd = @cbd,
|
||||
total_cannabinoids = @totalCannabinoids,
|
||||
weight = @weight,
|
||||
container_weight = @containerWeight,
|
||||
last_audit_weight = @lastAuditWeight,
|
||||
count_original = @countOriginal,
|
||||
count_last_audit = @countLastAudit,
|
||||
@@ -199,6 +210,7 @@ function doUpdate(id: string, body: UpdateBody): void {
|
||||
cbd: nextCbd,
|
||||
totalCannabinoids: nextTotalCanna,
|
||||
weight: nextWeight,
|
||||
containerWeight: nextContainerWeight,
|
||||
lastAuditWeight: nextLastAuditWeight,
|
||||
countOriginal: nextCountOriginal,
|
||||
countLastAudit: nextCountLastAudit,
|
||||
|
||||
@@ -64,6 +64,7 @@ CREATE TABLE IF NOT EXISTS inventory_items (
|
||||
cbd REAL DEFAULT 0,
|
||||
total_cannabinoids REAL DEFAULT 0,
|
||||
weight REAL DEFAULT 0,
|
||||
container_weight REAL,
|
||||
last_audit_weight REAL,
|
||||
count_original INTEGER DEFAULT 0,
|
||||
count_last_audit INTEGER,
|
||||
|
||||
Reference in New Issue
Block a user