-- Location-specific store maps for the mobile map manager. -- Maps are scoped to a household-owned physical store location. CREATE TABLE IF NOT EXISTS location_maps ( id BIGSERIAL PRIMARY KEY, household_id INTEGER NOT NULL REFERENCES households(id) ON DELETE CASCADE, store_location_id INTEGER NOT NULL REFERENCES store_locations(id) ON DELETE CASCADE, name VARCHAR(120) NOT NULL DEFAULT 'Store Map', width INTEGER NOT NULL DEFAULT 1000 CHECK (width > 0), height INTEGER NOT NULL DEFAULT 700 CHECK (height > 0), status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'published', 'archived')), version INTEGER NOT NULL DEFAULT 1 CHECK (version > 0), created_by INTEGER REFERENCES users(id) ON DELETE SET NULL, updated_by INTEGER REFERENCES users(id) ON DELETE SET NULL, published_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_location_maps_location_status ON location_maps(household_id, store_location_id, status, updated_at DESC); CREATE UNIQUE INDEX IF NOT EXISTS uq_location_maps_draft_location ON location_maps(store_location_id) WHERE status = 'draft'; CREATE UNIQUE INDEX IF NOT EXISTS uq_location_maps_published_location ON location_maps(store_location_id) WHERE status = 'published'; CREATE TABLE IF NOT EXISTS location_map_objects ( id BIGSERIAL PRIMARY KEY, location_map_id BIGINT NOT NULL REFERENCES location_maps(id) ON DELETE CASCADE, zone_id INTEGER REFERENCES store_location_zones(id) ON DELETE SET NULL, type VARCHAR(30) NOT NULL DEFAULT 'zone' CHECK (type IN ( 'zone', 'aisle', 'entrance', 'checkout', 'shelf', 'wall', 'department', 'anchor', 'other' )), label VARCHAR(160) NOT NULL DEFAULT '', x NUMERIC(10, 2) NOT NULL DEFAULT 0, y NUMERIC(10, 2) NOT NULL DEFAULT 0, width NUMERIC(10, 2) NOT NULL DEFAULT 160 CHECK (width > 0), height NUMERIC(10, 2) NOT NULL DEFAULT 100 CHECK (height > 0), rotation NUMERIC(7, 2) NOT NULL DEFAULT 0, locked BOOLEAN NOT NULL DEFAULT FALSE, visible BOOLEAN NOT NULL DEFAULT TRUE, sort_order INTEGER NOT NULL DEFAULT 0, metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_location_map_objects_map_order ON location_map_objects(location_map_id, sort_order, id); CREATE INDEX IF NOT EXISTS idx_location_map_objects_zone ON location_map_objects(zone_id);