196 lines
8.9 KiB
PL/PgSQL
196 lines
8.9 KiB
PL/PgSQL
-- Migration: Add Menu Action Access System
|
|
-- Description: Create menu_actions, user_level_menu_accesses, and user_level_menu_action_accesses tables
|
|
-- Date: 2026-01-16
|
|
|
|
-- ============================================================================
|
|
-- Step 1: Create menu_actions table
|
|
-- ============================================================================
|
|
CREATE TABLE IF NOT EXISTS menu_actions (
|
|
id SERIAL PRIMARY KEY,
|
|
menu_id INT NOT NULL,
|
|
action_code VARCHAR(50) NOT NULL,
|
|
action_name VARCHAR(255) NOT NULL,
|
|
description TEXT NULL,
|
|
path_url VARCHAR(255) NULL,
|
|
http_method VARCHAR(10) NULL,
|
|
position INT NULL,
|
|
client_id UUID NULL,
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW(),
|
|
FOREIGN KEY (menu_id) REFERENCES master_menus(id) ON DELETE CASCADE,
|
|
UNIQUE(menu_id, action_code, COALESCE(client_id, '00000000-0000-0000-0000-000000000000'::UUID))
|
|
);
|
|
|
|
-- Add indexes for performance
|
|
CREATE INDEX idx_menu_actions_menu_id ON menu_actions(menu_id);
|
|
CREATE INDEX idx_menu_actions_action_code ON menu_actions(action_code);
|
|
CREATE INDEX idx_menu_actions_client_id ON menu_actions(client_id) WHERE client_id IS NOT NULL;
|
|
CREATE INDEX idx_menu_actions_is_active ON menu_actions(is_active);
|
|
|
|
-- Add comments
|
|
COMMENT ON TABLE menu_actions IS 'Actions yang tersedia di setiap menu (view, create, edit, delete, approve, export, etc)';
|
|
COMMENT ON COLUMN menu_actions.menu_id IS 'Foreign key ke master_menus';
|
|
COMMENT ON COLUMN menu_actions.action_code IS 'Kode action: view, create, edit, delete, approve, export, etc';
|
|
COMMENT ON COLUMN menu_actions.action_name IS 'Nama action yang ditampilkan ke user';
|
|
COMMENT ON COLUMN menu_actions.path_url IS 'Optional: URL path untuk routing frontend';
|
|
COMMENT ON COLUMN menu_actions.http_method IS 'Optional: HTTP method (GET, POST, PUT, DELETE)';
|
|
|
|
-- ============================================================================
|
|
-- Step 2: Create user_level_menu_accesses table
|
|
-- ============================================================================
|
|
CREATE TABLE IF NOT EXISTS user_level_menu_accesses (
|
|
id SERIAL PRIMARY KEY,
|
|
user_level_id INT NOT NULL,
|
|
menu_id INT NOT NULL,
|
|
can_access BOOLEAN DEFAULT TRUE,
|
|
client_id UUID NULL,
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW(),
|
|
FOREIGN KEY (user_level_id) REFERENCES user_levels(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (menu_id) REFERENCES master_menus(id) ON DELETE CASCADE,
|
|
UNIQUE(user_level_id, menu_id, COALESCE(client_id, '00000000-0000-0000-0000-000000000000'::UUID))
|
|
);
|
|
|
|
-- Add indexes for performance
|
|
CREATE INDEX idx_user_level_menu_accesses_user_level_id ON user_level_menu_accesses(user_level_id);
|
|
CREATE INDEX idx_user_level_menu_accesses_menu_id ON user_level_menu_accesses(menu_id);
|
|
CREATE INDEX idx_user_level_menu_accesses_client_id ON user_level_menu_accesses(client_id) WHERE client_id IS NOT NULL;
|
|
CREATE INDEX idx_user_level_menu_accesses_is_active ON user_level_menu_accesses(is_active);
|
|
|
|
-- Add comments
|
|
COMMENT ON TABLE user_level_menu_accesses IS 'Mengatur akses user_level ke menu tertentu';
|
|
COMMENT ON COLUMN user_level_menu_accesses.user_level_id IS 'Foreign key ke user_levels';
|
|
COMMENT ON COLUMN user_level_menu_accesses.menu_id IS 'Foreign key ke master_menus';
|
|
COMMENT ON COLUMN user_level_menu_accesses.can_access IS 'Apakah user level boleh mengakses menu ini';
|
|
|
|
-- ============================================================================
|
|
-- Step 3: Create user_level_menu_action_accesses table
|
|
-- ============================================================================
|
|
CREATE TABLE IF NOT EXISTS user_level_menu_action_accesses (
|
|
id SERIAL PRIMARY KEY,
|
|
user_level_id INT NOT NULL,
|
|
menu_id INT NOT NULL,
|
|
action_code VARCHAR(50) NOT NULL,
|
|
can_access BOOLEAN DEFAULT TRUE,
|
|
client_id UUID NULL,
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
updated_at TIMESTAMP DEFAULT NOW(),
|
|
FOREIGN KEY (user_level_id) REFERENCES user_levels(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (menu_id) REFERENCES master_menus(id) ON DELETE CASCADE,
|
|
UNIQUE(user_level_id, menu_id, action_code, COALESCE(client_id, '00000000-0000-0000-0000-000000000000'::UUID))
|
|
);
|
|
|
|
-- Add indexes for performance
|
|
CREATE INDEX idx_user_level_menu_action_accesses_user_level_id ON user_level_menu_action_accesses(user_level_id);
|
|
CREATE INDEX idx_user_level_menu_action_accesses_menu_id ON user_level_menu_action_accesses(menu_id);
|
|
CREATE INDEX idx_user_level_menu_action_accesses_action_code ON user_level_menu_action_accesses(action_code);
|
|
CREATE INDEX idx_user_level_menu_action_accesses_client_id ON user_level_menu_action_accesses(client_id) WHERE client_id IS NOT NULL;
|
|
CREATE INDEX idx_user_level_menu_action_accesses_is_active ON user_level_menu_action_accesses(is_active);
|
|
|
|
-- Add comments
|
|
COMMENT ON TABLE user_level_menu_action_accesses IS 'Mengatur akses user_level ke action tertentu di dalam menu';
|
|
COMMENT ON COLUMN user_level_menu_action_accesses.user_level_id IS 'Foreign key ke user_levels';
|
|
COMMENT ON COLUMN user_level_menu_action_accesses.menu_id IS 'Foreign key ke master_menus';
|
|
COMMENT ON COLUMN user_level_menu_action_accesses.action_code IS 'Kode action (harus sesuai dengan menu_actions.action_code)';
|
|
COMMENT ON COLUMN user_level_menu_action_accesses.can_access IS 'Apakah user level boleh melakukan action ini';
|
|
|
|
-- ============================================================================
|
|
-- Step 4: Create trigger for updated_at
|
|
-- ============================================================================
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql';
|
|
|
|
-- Apply trigger to menu_actions
|
|
DROP TRIGGER IF EXISTS update_menu_actions_updated_at ON menu_actions;
|
|
CREATE TRIGGER update_menu_actions_updated_at
|
|
BEFORE UPDATE ON menu_actions
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- Apply trigger to user_level_menu_accesses
|
|
DROP TRIGGER IF EXISTS update_user_level_menu_accesses_updated_at ON user_level_menu_accesses;
|
|
CREATE TRIGGER update_user_level_menu_accesses_updated_at
|
|
BEFORE UPDATE ON user_level_menu_accesses
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- Apply trigger to user_level_menu_action_accesses
|
|
DROP TRIGGER IF EXISTS update_user_level_menu_action_accesses_updated_at ON user_level_menu_action_accesses;
|
|
CREATE TRIGGER update_user_level_menu_action_accesses_updated_at
|
|
BEFORE UPDATE ON user_level_menu_action_accesses
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- ============================================================================
|
|
-- Verification
|
|
-- ============================================================================
|
|
DO $$
|
|
DECLARE
|
|
v_menu_actions_exists BOOLEAN;
|
|
v_user_level_menu_accesses_exists BOOLEAN;
|
|
v_user_level_menu_action_accesses_exists BOOLEAN;
|
|
BEGIN
|
|
-- Check menu_actions table
|
|
SELECT EXISTS (
|
|
SELECT FROM information_schema.tables
|
|
WHERE table_schema = 'public'
|
|
AND table_name = 'menu_actions'
|
|
) INTO v_menu_actions_exists;
|
|
|
|
-- Check user_level_menu_accesses table
|
|
SELECT EXISTS (
|
|
SELECT FROM information_schema.tables
|
|
WHERE table_schema = 'public'
|
|
AND table_name = 'user_level_menu_accesses'
|
|
) INTO v_user_level_menu_accesses_exists;
|
|
|
|
-- Check user_level_menu_action_accesses table
|
|
SELECT EXISTS (
|
|
SELECT FROM information_schema.tables
|
|
WHERE table_schema = 'public'
|
|
AND table_name = 'user_level_menu_action_accesses'
|
|
) INTO v_user_level_menu_action_accesses_exists;
|
|
|
|
-- Report results
|
|
RAISE NOTICE '========================================';
|
|
RAISE NOTICE 'Migration Verification Results:';
|
|
RAISE NOTICE '========================================';
|
|
|
|
IF v_menu_actions_exists THEN
|
|
RAISE NOTICE '✓ Table menu_actions created successfully';
|
|
ELSE
|
|
RAISE WARNING '✗ Table menu_actions NOT created';
|
|
END IF;
|
|
|
|
IF v_user_level_menu_accesses_exists THEN
|
|
RAISE NOTICE '✓ Table user_level_menu_accesses created successfully';
|
|
ELSE
|
|
RAISE WARNING '✗ Table user_level_menu_accesses NOT created';
|
|
END IF;
|
|
|
|
IF v_user_level_menu_action_accesses_exists THEN
|
|
RAISE NOTICE '✓ Table user_level_menu_action_accesses created successfully';
|
|
ELSE
|
|
RAISE WARNING '✗ Table user_level_menu_action_accesses NOT created';
|
|
END IF;
|
|
|
|
RAISE NOTICE '========================================';
|
|
|
|
IF v_menu_actions_exists AND v_user_level_menu_accesses_exists AND v_user_level_menu_action_accesses_exists THEN
|
|
RAISE NOTICE 'Migration completed successfully! ✓';
|
|
ELSE
|
|
RAISE WARNING 'Migration completed with errors! Please check above.';
|
|
END IF;
|
|
|
|
RAISE NOTICE '========================================';
|
|
END $$;
|
|
|