31 lines
1.3 KiB
SQL
31 lines
1.3 KiB
SQL
-- Weight-based products (e.g. fish sold per ons/kg).
|
|||
|
|
-- One weighing = one order_items row: quantity stays 1, the weight goes in `weight`.
|
||
|
|
|
||
|
|
ALTER TABLE products
|
||
|
|
ADD COLUMN sell_by VARCHAR(20) NOT NULL DEFAULT 'unit';
|
||
|
|
|
||
|
|
ALTER TABLE products
|
||
|
|
ADD CONSTRAINT chk_products_sell_by
|
||
|
|
CHECK (sell_by IN ('unit', 'weight'));
|
||
|
|
|
||
|
|
ALTER TABLE order_items
|
||
|
|
ADD COLUMN weight DECIMAL(12,3),
|
||
|
|
ADD COLUMN unit_id UUID REFERENCES units(id) ON DELETE RESTRICT;
|
||
|
|
|
||
|
|
-- A weighed line always carries a positive weight...
|
||
|
|
ALTER TABLE order_items
|
||
|
|
ADD CONSTRAINT chk_order_items_weight_positive
|
||
|
|
CHECK (weight IS NULL OR weight > 0);
|
||
|
|
|
||
|
|
-- ...and always represents exactly one weighing, so its quantity is pinned to 1.
|
||
|
|
-- This is what makes billable quantity unambiguous and keeps void all-or-nothing.
|
||
|
|
ALTER TABLE order_items
|
||
|
|
ADD CONSTRAINT chk_order_items_weight_single_line
|
||
|
|
CHECK (weight IS NULL OR quantity = 1);
|
||
|
|
|
||
|
|
CREATE INDEX idx_order_items_unit_id ON order_items(unit_id);
|
||
|
|
|
||
|
|
COMMENT ON COLUMN products.sell_by IS 'How the product is sold: unit (discrete count) or weight (weighed per transaction)';
|
||
|
|
COMMENT ON COLUMN order_items.weight IS 'Weighed amount in unit_id units; NULL for unit-priced products. Price is weight * unit_price.';
|
||
|
|
COMMENT ON COLUMN order_items.unit_id IS 'Snapshot of the product unit at sale time, so historical lines keep their meaning';
|