-- Meshkee CMS — categories for products, blogs, portfolios CREATE TABLE categories ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, business_id BIGINT NOT NULL, entity_type media_entity_type NOT NULL, parent_id BIGINT, name VARCHAR(255) NOT NULL, slug VARCHAR(255) NOT NULL, description TEXT, sort_order INTEGER NOT NULL DEFAULT 0, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT categories_business_entity_slug_unique UNIQUE (business_id, entity_type, slug), CONSTRAINT categories_business_id_fkey FOREIGN KEY (business_id) REFERENCES businesses (id) ON DELETE CASCADE, CONSTRAINT categories_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES categories (id) ON DELETE SET NULL, CONSTRAINT categories_slug_format CHECK (slug ~ '^[a-z0-9]+(?:-[a-z0-9]+)*$') ); CREATE INDEX idx_categories_business_entity ON categories (business_id, entity_type, sort_order); CREATE INDEX idx_categories_parent_id ON categories (parent_id); CREATE INDEX idx_categories_active ON categories (business_id, entity_type) WHERE is_active = TRUE; CREATE TRIGGER categories_set_updated_at BEFORE UPDATE ON categories FOR EACH ROW EXECUTE FUNCTION set_updated_at(); CREATE TABLE category_assignments ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, business_id BIGINT NOT NULL, category_id BIGINT NOT NULL, entity_type media_entity_type NOT NULL, entity_id BIGINT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT category_assignments_unique UNIQUE (category_id, entity_type, entity_id), CONSTRAINT category_assignments_business_id_fkey FOREIGN KEY (business_id) REFERENCES businesses (id) ON DELETE CASCADE, CONSTRAINT category_assignments_category_id_fkey FOREIGN KEY (category_id) REFERENCES categories (id) ON DELETE CASCADE ); CREATE INDEX idx_category_assignments_entity ON category_assignments (business_id, entity_type, entity_id); CREATE INDEX idx_category_assignments_category_id ON category_assignments (category_id); INSERT INTO permissions (name, slug, group_name, description) VALUES ('View categories', 'categories.read', 'categories', 'View categories'), ('Create categories', 'categories.create', 'categories', 'Create categories'), ('Update categories', 'categories.update', 'categories', 'Edit categories'), ('Delete categories', 'categories.delete', 'categories', 'Delete categories'); INSERT INTO role_permissions (role_id, permission_id) SELECT r.id, p.id FROM roles r JOIN permissions p ON p.slug LIKE 'categories.%' WHERE r.slug IN ('owner', 'admin'); INSERT INTO role_permissions (role_id, permission_id) SELECT r.id, p.id FROM roles r JOIN permissions p ON p.slug IN ('categories.read', 'categories.create', 'categories.update') WHERE r.slug = 'editor'; INSERT INTO role_permissions (role_id, permission_id) SELECT r.id, p.id FROM roles r JOIN permissions p ON p.slug = 'categories.read' WHERE r.slug = 'viewer';