BEGIN; CREATE EXTENSION IF NOT EXISTS pgcrypto; DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'record_status') THEN CREATE TYPE record_status AS ENUM ('active','inactive'); END IF; END $$; CREATE TABLE IF NOT EXISTS systems ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), system_key TEXT NOT NULL UNIQUE, name TEXT NOT NULL, status record_status NOT NULL DEFAULT 'active', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); INSERT INTO systems (system_key, name, status) VALUES ('member', 'Member Center', 'active') ON CONFLICT (system_key) DO NOTHING; DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'scope_type') THEN CREATE TYPE scope_type AS ENUM ('company','site'); END IF; IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'permission_action') THEN CREATE TYPE permission_action AS ENUM ('view','create','update','delete','manage'); END IF; END $$; CREATE TABLE IF NOT EXISTS permission_groups ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), group_key TEXT NOT NULL UNIQUE, name TEXT NOT NULL, status record_status NOT NULL DEFAULT 'active', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS permission_group_members ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), group_id UUID NOT NULL REFERENCES permission_groups(id) ON DELETE CASCADE, user_sub TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT uq_permission_group_members_group_sub UNIQUE (group_id, user_sub) ); CREATE TABLE IF NOT EXISTS permission_group_permissions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), group_id UUID NOT NULL REFERENCES permission_groups(id) ON DELETE CASCADE, system TEXT NOT NULL, module TEXT NOT NULL, action TEXT NOT NULL, scope_type TEXT NOT NULL, scope_id TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_systems_system_key ON systems(system_key); CREATE INDEX IF NOT EXISTS idx_pgm_group_id ON permission_group_members(group_id); CREATE INDEX IF NOT EXISTS idx_pgm_user_sub ON permission_group_members(user_sub); CREATE INDEX IF NOT EXISTS idx_pgp_group_id ON permission_group_permissions(group_id); CREATE UNIQUE INDEX IF NOT EXISTS uq_pgp_group_rule ON permission_group_permissions(group_id, system, module, action, scope_type, scope_id); COMMIT;