forked from andika/membership-be
- Profile Picture\
Donation Tracking\ Validation Rejection\ Subscription Data Export\ Admin Dashboard Logo\ Admin Navbar Reorganization
This commit is contained in:
578
migrations/000_initial_schema.sql
Normal file
578
migrations/000_initial_schema.sql
Normal file
@@ -0,0 +1,578 @@
|
||||
-- ============================================================================
|
||||
-- Migration 000: Initial Database Schema
|
||||
-- ============================================================================
|
||||
-- Description: Creates all base tables, enums, and indexes for the LOAF
|
||||
-- membership platform. This migration should be run first on
|
||||
-- a fresh database.
|
||||
-- Date: 2024-12-18
|
||||
-- Author: LOAF Development Team
|
||||
-- ============================================================================
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- SECTION 1: Create ENUM Types
|
||||
-- ============================================================================
|
||||
|
||||
-- User status enum
|
||||
CREATE TYPE userstatus AS ENUM (
|
||||
'pending_email',
|
||||
'pending_validation',
|
||||
'pre_validated',
|
||||
'payment_pending',
|
||||
'active',
|
||||
'inactive',
|
||||
'canceled',
|
||||
'expired',
|
||||
'abandoned',
|
||||
'rejected'
|
||||
);
|
||||
|
||||
-- User role enum
|
||||
CREATE TYPE userrole AS ENUM (
|
||||
'guest',
|
||||
'member',
|
||||
'admin',
|
||||
'finance',
|
||||
'superadmin'
|
||||
);
|
||||
|
||||
-- RSVP status enum
|
||||
CREATE TYPE rsvpstatus AS ENUM (
|
||||
'yes',
|
||||
'no',
|
||||
'maybe'
|
||||
);
|
||||
|
||||
-- Subscription status enum
|
||||
CREATE TYPE subscriptionstatus AS ENUM (
|
||||
'active',
|
||||
'cancelled',
|
||||
'expired'
|
||||
);
|
||||
|
||||
-- Donation type enum
|
||||
CREATE TYPE donationtype AS ENUM (
|
||||
'member',
|
||||
'public'
|
||||
);
|
||||
|
||||
-- Donation status enum
|
||||
CREATE TYPE donationstatus AS ENUM (
|
||||
'pending',
|
||||
'completed',
|
||||
'failed'
|
||||
);
|
||||
|
||||
-- Invitation status enum
|
||||
CREATE TYPE invitationstatus AS ENUM (
|
||||
'pending',
|
||||
'accepted',
|
||||
'expired',
|
||||
'revoked'
|
||||
);
|
||||
|
||||
-- Import job status enum
|
||||
CREATE TYPE importjobstatus AS ENUM (
|
||||
'processing',
|
||||
'completed',
|
||||
'failed',
|
||||
'partial'
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Display progress
|
||||
SELECT 'Step 1/8 completed: ENUM types created' AS progress;
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- SECTION 2: Create Core Tables
|
||||
-- ============================================================================
|
||||
|
||||
-- Users table
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
-- Authentication
|
||||
email VARCHAR NOT NULL UNIQUE,
|
||||
password_hash VARCHAR NOT NULL,
|
||||
email_verified BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
email_verification_token VARCHAR UNIQUE,
|
||||
|
||||
-- Personal Information
|
||||
first_name VARCHAR NOT NULL,
|
||||
last_name VARCHAR NOT NULL,
|
||||
phone VARCHAR,
|
||||
address VARCHAR,
|
||||
city VARCHAR,
|
||||
state VARCHAR(2),
|
||||
zipcode VARCHAR(10),
|
||||
date_of_birth DATE,
|
||||
bio TEXT,
|
||||
|
||||
-- Profile
|
||||
profile_photo_url VARCHAR,
|
||||
|
||||
-- Social Media
|
||||
social_media_facebook VARCHAR,
|
||||
social_media_instagram VARCHAR,
|
||||
social_media_twitter VARCHAR,
|
||||
social_media_linkedin VARCHAR,
|
||||
|
||||
-- Partner Information
|
||||
partner_first_name VARCHAR,
|
||||
partner_last_name VARCHAR,
|
||||
partner_is_member BOOLEAN DEFAULT FALSE,
|
||||
partner_plan_to_become_member BOOLEAN DEFAULT FALSE,
|
||||
|
||||
-- Referral
|
||||
referred_by_member_name VARCHAR,
|
||||
lead_sources JSONB DEFAULT '[]'::jsonb,
|
||||
|
||||
-- Status & Role
|
||||
status userstatus NOT NULL DEFAULT 'pending_email',
|
||||
role userrole NOT NULL DEFAULT 'guest',
|
||||
role_id UUID, -- For dynamic RBAC (added in later migration)
|
||||
|
||||
-- Rejection Tracking
|
||||
rejection_reason TEXT,
|
||||
rejected_at TIMESTAMP WITH TIME ZONE,
|
||||
rejected_by UUID REFERENCES users(id),
|
||||
|
||||
-- Membership
|
||||
member_since DATE,
|
||||
tos_accepted BOOLEAN DEFAULT FALSE,
|
||||
tos_accepted_at TIMESTAMP WITH TIME ZONE,
|
||||
newsletter_subscribed BOOLEAN DEFAULT TRUE,
|
||||
|
||||
-- Reminder Tracking
|
||||
reminder_30_days_sent BOOLEAN DEFAULT FALSE,
|
||||
reminder_60_days_sent BOOLEAN DEFAULT FALSE,
|
||||
reminder_85_days_sent BOOLEAN DEFAULT FALSE,
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Events table
|
||||
CREATE TABLE IF NOT EXISTS events (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
-- Event Details
|
||||
title VARCHAR NOT NULL,
|
||||
description TEXT,
|
||||
location VARCHAR,
|
||||
cover_image_url VARCHAR,
|
||||
|
||||
-- Schedule
|
||||
start_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
end_at TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
-- Capacity
|
||||
capacity INTEGER,
|
||||
published BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Calendar Integration
|
||||
calendar_uid VARCHAR UNIQUE,
|
||||
microsoft_calendar_id VARCHAR,
|
||||
microsoft_calendar_sync_enabled BOOLEAN DEFAULT FALSE,
|
||||
|
||||
-- Metadata
|
||||
created_by UUID REFERENCES users(id),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Event RSVPs table
|
||||
CREATE TABLE IF NOT EXISTS event_rsvps (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
|
||||
-- RSVP Details
|
||||
rsvp_status rsvpstatus NOT NULL DEFAULT 'maybe',
|
||||
attended BOOLEAN DEFAULT FALSE,
|
||||
attended_at TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Unique constraint: one RSVP per user per event
|
||||
UNIQUE(event_id, user_id)
|
||||
);
|
||||
|
||||
-- Event Gallery table
|
||||
CREATE TABLE IF NOT EXISTS event_galleries (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
||||
|
||||
-- Image Details
|
||||
image_url VARCHAR NOT NULL,
|
||||
caption TEXT,
|
||||
order_index INTEGER DEFAULT 0,
|
||||
|
||||
-- Metadata
|
||||
uploaded_by UUID REFERENCES users(id),
|
||||
uploaded_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Display progress
|
||||
SELECT 'Step 2/8 completed: Core tables (users, events, rsvps, gallery) created' AS progress;
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- SECTION 3: Create Subscription & Payment Tables
|
||||
-- ============================================================================
|
||||
|
||||
-- Subscription Plans table
|
||||
CREATE TABLE IF NOT EXISTS subscription_plans (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
-- Plan Details
|
||||
name VARCHAR NOT NULL,
|
||||
description TEXT,
|
||||
price_cents INTEGER NOT NULL,
|
||||
billing_cycle VARCHAR NOT NULL DEFAULT 'annual',
|
||||
|
||||
-- Configuration
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
features JSONB DEFAULT '[]'::jsonb,
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Subscriptions table
|
||||
CREATE TABLE IF NOT EXISTS subscriptions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
plan_id UUID NOT NULL REFERENCES subscription_plans(id),
|
||||
|
||||
-- Stripe Integration
|
||||
stripe_subscription_id VARCHAR,
|
||||
stripe_customer_id VARCHAR,
|
||||
|
||||
-- Status & Dates
|
||||
status subscriptionstatus DEFAULT 'active',
|
||||
start_date TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
end_date TIMESTAMP WITH TIME ZONE,
|
||||
next_billing_date TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
-- Payment Details
|
||||
amount_paid_cents INTEGER,
|
||||
base_subscription_cents INTEGER NOT NULL,
|
||||
donation_cents INTEGER DEFAULT 0 NOT NULL,
|
||||
|
||||
-- Manual Payment Support
|
||||
manual_payment BOOLEAN DEFAULT FALSE NOT NULL,
|
||||
manual_payment_notes TEXT,
|
||||
manual_payment_admin_id UUID REFERENCES users(id),
|
||||
manual_payment_date TIMESTAMP WITH TIME ZONE,
|
||||
payment_method VARCHAR,
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Donations table
|
||||
CREATE TABLE IF NOT EXISTS donations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
-- Donation Details
|
||||
amount_cents INTEGER NOT NULL,
|
||||
donation_type donationtype NOT NULL DEFAULT 'public',
|
||||
status donationstatus NOT NULL DEFAULT 'pending',
|
||||
|
||||
-- Donor Information
|
||||
user_id UUID REFERENCES users(id), -- NULL for public donations
|
||||
donor_email VARCHAR,
|
||||
donor_name VARCHAR,
|
||||
|
||||
-- Payment Details
|
||||
stripe_checkout_session_id VARCHAR,
|
||||
stripe_payment_intent_id VARCHAR,
|
||||
payment_method VARCHAR,
|
||||
|
||||
-- Metadata
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Display progress
|
||||
SELECT 'Step 3/8 completed: Subscription and donation tables created' AS progress;
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- SECTION 4: Create RBAC Tables
|
||||
-- ============================================================================
|
||||
|
||||
-- Permissions table
|
||||
CREATE TABLE IF NOT EXISTS permissions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
code VARCHAR NOT NULL UNIQUE,
|
||||
name VARCHAR NOT NULL,
|
||||
description TEXT,
|
||||
module VARCHAR NOT NULL,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Roles table (for dynamic RBAC)
|
||||
CREATE TABLE IF NOT EXISTS roles (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
code VARCHAR NOT NULL UNIQUE,
|
||||
name VARCHAR NOT NULL,
|
||||
description TEXT,
|
||||
is_system_role BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by UUID REFERENCES users(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Role Permissions junction table
|
||||
CREATE TABLE IF NOT EXISTS role_permissions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
role userrole, -- Legacy enum-based role (for backward compatibility)
|
||||
role_id UUID REFERENCES roles(id) ON DELETE CASCADE, -- Dynamic role
|
||||
permission_id UUID NOT NULL REFERENCES permissions(id) ON DELETE CASCADE,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
created_by UUID REFERENCES users(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Display progress
|
||||
SELECT 'Step 4/8 completed: RBAC tables created' AS progress;
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- SECTION 5: Create Document Management Tables
|
||||
-- ============================================================================
|
||||
|
||||
-- Newsletter Archive table
|
||||
CREATE TABLE IF NOT EXISTS newsletter_archives (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
title VARCHAR NOT NULL,
|
||||
file_url VARCHAR NOT NULL,
|
||||
file_size_bytes INTEGER,
|
||||
issue_date DATE NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
uploaded_by UUID REFERENCES users(id),
|
||||
uploaded_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Financial Reports table
|
||||
CREATE TABLE IF NOT EXISTS financial_reports (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
title VARCHAR NOT NULL,
|
||||
file_url VARCHAR NOT NULL,
|
||||
file_size_bytes INTEGER,
|
||||
fiscal_period VARCHAR NOT NULL,
|
||||
report_type VARCHAR,
|
||||
|
||||
uploaded_by UUID REFERENCES users(id),
|
||||
uploaded_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Bylaws Documents table
|
||||
CREATE TABLE IF NOT EXISTS bylaws_documents (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
title VARCHAR NOT NULL,
|
||||
file_url VARCHAR NOT NULL,
|
||||
file_size_bytes INTEGER,
|
||||
version VARCHAR NOT NULL,
|
||||
effective_date DATE NOT NULL,
|
||||
description TEXT,
|
||||
is_current BOOLEAN DEFAULT TRUE,
|
||||
|
||||
uploaded_by UUID REFERENCES users(id),
|
||||
uploaded_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Display progress
|
||||
SELECT 'Step 5/8 completed: Document management tables created' AS progress;
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- SECTION 6: Create System Tables
|
||||
-- ============================================================================
|
||||
|
||||
-- Storage Usage table
|
||||
CREATE TABLE IF NOT EXISTS storage_usage (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
total_bytes_used BIGINT NOT NULL DEFAULT 0,
|
||||
max_bytes_allowed BIGINT NOT NULL DEFAULT 10737418240, -- 10GB
|
||||
last_updated TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- User Invitations table
|
||||
CREATE TABLE IF NOT EXISTS user_invitations (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
email VARCHAR NOT NULL,
|
||||
token VARCHAR NOT NULL UNIQUE,
|
||||
role userrole NOT NULL,
|
||||
status invitationstatus NOT NULL DEFAULT 'pending',
|
||||
|
||||
invited_by UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
accepted_at TIMESTAMP WITH TIME ZONE,
|
||||
revoked_at TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Import Jobs table
|
||||
CREATE TABLE IF NOT EXISTS import_jobs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
|
||||
filename VARCHAR NOT NULL,
|
||||
status importjobstatus NOT NULL DEFAULT 'processing',
|
||||
total_rows INTEGER DEFAULT 0,
|
||||
processed_rows INTEGER DEFAULT 0,
|
||||
success_count INTEGER DEFAULT 0,
|
||||
error_count INTEGER DEFAULT 0,
|
||||
error_log JSONB DEFAULT '[]'::jsonb,
|
||||
|
||||
started_by UUID REFERENCES users(id),
|
||||
started_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
completed_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Display progress
|
||||
SELECT 'Step 6/8 completed: System tables created' AS progress;
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- SECTION 7: Create Indexes
|
||||
-- ============================================================================
|
||||
|
||||
-- Users table indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_status ON users(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_role_id ON users(role_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_email_verified ON users(email_verified);
|
||||
CREATE INDEX IF NOT EXISTS idx_users_rejected_at ON users(rejected_at) WHERE rejected_at IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_users_created_at ON users(created_at);
|
||||
|
||||
-- Events table indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_events_created_by ON events(created_by);
|
||||
CREATE INDEX IF NOT EXISTS idx_events_start_at ON events(start_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_events_published ON events(published);
|
||||
|
||||
-- Event RSVPs indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_event_rsvps_event_id ON event_rsvps(event_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_event_rsvps_user_id ON event_rsvps(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_event_rsvps_rsvp_status ON event_rsvps(rsvp_status);
|
||||
|
||||
-- Event Gallery indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_event_galleries_event_id ON event_galleries(event_id);
|
||||
|
||||
-- Subscriptions indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_subscriptions_user_id ON subscriptions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_subscriptions_plan_id ON subscriptions(plan_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON subscriptions(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_subscriptions_stripe_subscription_id ON subscriptions(stripe_subscription_id);
|
||||
|
||||
-- Donations indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_donation_user ON donations(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_donation_type ON donations(donation_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_donation_status ON donations(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_donation_created ON donations(created_at);
|
||||
|
||||
-- Permissions indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_permissions_code ON permissions(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_permissions_module ON permissions(module);
|
||||
|
||||
-- Roles indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_roles_code ON roles(code);
|
||||
CREATE INDEX IF NOT EXISTS idx_roles_is_system_role ON roles(is_system_role);
|
||||
|
||||
-- Role Permissions indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_role_permissions_role ON role_permissions(role);
|
||||
CREATE INDEX IF NOT EXISTS idx_role_permissions_role_id ON role_permissions(role_id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_role_permission ON role_permissions(role, permission_id) WHERE role IS NOT NULL;
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_dynamic_role_permission ON role_permissions(role_id, permission_id) WHERE role_id IS NOT NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Display progress
|
||||
SELECT 'Step 7/8 completed: Indexes created' AS progress;
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ============================================================================
|
||||
-- SECTION 8: Initialize Default Data
|
||||
-- ============================================================================
|
||||
|
||||
-- Insert initial storage usage record
|
||||
INSERT INTO storage_usage (id, total_bytes_used, max_bytes_allowed, last_updated)
|
||||
SELECT
|
||||
gen_random_uuid(),
|
||||
0,
|
||||
10737418240, -- 10GB
|
||||
CURRENT_TIMESTAMP
|
||||
WHERE NOT EXISTS (SELECT 1 FROM storage_usage);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- Display progress
|
||||
SELECT 'Step 8/8 completed: Default data initialized' AS progress;
|
||||
|
||||
-- ============================================================================
|
||||
-- Migration Complete
|
||||
-- ============================================================================
|
||||
|
||||
SELECT '
|
||||
================================================================================
|
||||
✅ Migration 000 completed successfully!
|
||||
================================================================================
|
||||
|
||||
Database schema initialized with:
|
||||
- 10 ENUM types
|
||||
- 17 tables (users, events, subscriptions, donations, RBAC, documents, system)
|
||||
- 30+ indexes for performance
|
||||
- 1 storage usage record
|
||||
|
||||
Next steps:
|
||||
1. Run: python seed_permissions_rbac.py (to populate permissions and roles)
|
||||
2. Run: python create_admin.py (to create superadmin user)
|
||||
3. Run remaining migrations in sequence (001-010)
|
||||
|
||||
Database is ready for LOAF membership platform! 🎉
|
||||
================================================================================
|
||||
' AS migration_complete;
|
||||
Reference in New Issue
Block a user