-- +goose Up -- Owner-configurable extra fields on the order intake form — the fixed -- device_type/brand/model/serial_number/problem_description columns cover -- the common case, but every repair shop ends up wanting a couple of -- business-specific questions (warranty seal intact? PIN code? came with a -- charger?) without a code change each time. field_key is an opaque -- generated id (see internal/customfields), never derived from the label, -- so renaming a field later never orphans already-stored values. CREATE TABLE order_field_definitions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), field_key TEXT NOT NULL UNIQUE, label TEXT NOT NULL, field_type TEXT NOT NULL CHECK (field_type IN ('text', 'number', 'select', 'checkbox')), -- JSON array of strings, only meaningful (and only validated) for type='select'. options JSONB, required BOOLEAN NOT NULL DEFAULT false, position INT NOT NULL DEFAULT 0, -- Archiving (not deleting) a field keeps its historical values readable -- on old orders — see internal/customfields' package doc — while hiding -- it from new orders and the active-fields validation set. is_active BOOLEAN NOT NULL DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- One JSONB blob per order (field_key -> value) rather than an EAV table — -- there's no need to query orders BY a custom field's value anywhere in -- this app (Kanban/search filter on the fixed columns only), so the -- flexibility of a real table would buy nothing but join complexity. ALTER TABLE orders ADD COLUMN custom_fields JSONB NOT NULL DEFAULT '{}';