-- ============================================ -- YAN AKWATI DATABASE SCHEMA - PostgreSQL -- ============================================ -- USERS TABLE CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, first_name VARCHAR(100) NOT NULL, last_name VARCHAR(100) NOT NULL, phone VARCHAR(20) UNIQUE NOT NULL, role VARCHAR(50) NOT NULL CHECK (role IN ('super_admin', 'state_chairman', 'lga_chairman', 'ward_chairman', 'polling_unit_chairman', 'member')), lga_id UUID NULL, ward_id UUID NULL, polling_unit_id UUID NULL, is_active BOOLEAN DEFAULT TRUE, last_login TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (lga_id) REFERENCES lgas(id) ON DELETE SET NULL, FOREIGN KEY (ward_id) REFERENCES wards(id) ON DELETE SET NULL, FOREIGN KEY (polling_unit_id) REFERENCES polling_units(id) ON DELETE SET NULL ); -- LGAS TABLE CREATE TABLE lgas ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(100) NOT NULL, code VARCHAR(10) UNIQUE NOT NULL, description TEXT, chairman_id UUID NULL, vice_chairman_id UUID NULL, secretary_id UUID NULL, total_members INTEGER DEFAULT 35, is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- WARDS TABLE CREATE TABLE wards ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), lga_id UUID NOT NULL, name VARCHAR(100) NOT NULL, code VARCHAR(20) UNIQUE NOT NULL, description TEXT, chairman_id UUID NULL, vice_chairman_id UUID NULL, secretary_id UUID NULL, total_members INTEGER DEFAULT 35, is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (lga_id) REFERENCES lgas(id) ON DELETE CASCADE ); -- POLLING UNITS TABLE CREATE TABLE polling_units ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), ward_id UUID NOT NULL, name VARCHAR(100) NOT NULL, code VARCHAR(20) UNIQUE NOT NULL, address TEXT, total_members INTEGER DEFAULT 20, chairman_id UUID NULL, is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (ward_id) REFERENCES wards(id) ON DELETE CASCADE ); -- MEMBERS TABLE CREATE TABLE members ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), membership_number VARCHAR(20) UNIQUE NOT NULL, first_name VARCHAR(100) NOT NULL, last_name VARCHAR(100) NOT NULL, middle_name VARCHAR(100), gender VARCHAR(10) CHECK (gender IN ('male', 'female', 'other')), date_of_birth DATE, phone VARCHAR(20), email VARCHAR(255), address TEXT, occupation VARCHAR(100), photo_url TEXT, lga_id UUID NOT NULL, ward_id UUID NOT NULL, polling_unit_id UUID NOT NULL, position VARCHAR(50) NOT NULL, voters_card_number VARCHAR(20), status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'suspended', 'deceased')), registered_by UUID, registration_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (lga_id) REFERENCES lgas(id) ON DELETE CASCADE, FOREIGN KEY (ward_id) REFERENCES wards(id) ON DELETE CASCADE, FOREIGN KEY (polling_unit_id) REFERENCES polling_units(id) ON DELETE CASCADE, FOREIGN KEY (registered_by) REFERENCES users(id) ON DELETE SET NULL ); -- ATTENDANCE TABLE CREATE TABLE attendance ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), member_id UUID NOT NULL, event_id UUID NOT NULL, check_in_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, check_out_time TIMESTAMP, status VARCHAR(20) DEFAULT 'present' CHECK (status IN ('present', 'absent', 'late', 'excused')), notes TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (member_id) REFERENCES members(id) ON DELETE CASCADE, FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE ); -- EVENTS TABLE CREATE TABLE events ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, description TEXT, event_type VARCHAR(50) CHECK (event_type IN ('meeting', 'training', 'rally', 'community_service', 'other')), start_date TIMESTAMP NOT NULL, end_date TIMESTAMP NOT NULL, venue VARCHAR(255), address TEXT, lga_id UUID NULL, ward_id UUID NULL, created_by UUID NOT NULL, is_public BOOLEAN DEFAULT TRUE, status VARCHAR(20) DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'ongoing', 'completed', 'cancelled')), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (lga_id) REFERENCES lgas(id) ON DELETE SET NULL, FOREIGN KEY (ward_id) REFERENCES wards(id) ON DELETE SET NULL, FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE ); -- TRAININGS TABLE CREATE TABLE trainings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, description TEXT, training_type VARCHAR(50), start_date TIMESTAMP NOT NULL, end_date TIMESTAMP NOT NULL, venue VARCHAR(255), max_participants INTEGER, lga_id UUID NULL, ward_id UUID NULL, created_by UUID NOT NULL, status VARCHAR(20) DEFAULT 'upcoming' CHECK (status IN ('upcoming', 'ongoing', 'completed', 'cancelled')), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (lga_id) REFERENCES lgas(id) ON DELETE SET NULL, FOREIGN KEY (ward_id) REFERENCES wards(id) ON DELETE SET NULL, FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE ); -- TRAINING_CERTIFICATES TABLE CREATE TABLE training_certificates ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), member_id UUID NOT NULL, training_id UUID NOT NULL, certificate_number VARCHAR(50) UNIQUE NOT NULL, issue_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, certificate_url TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (member_id) REFERENCES members(id) ON DELETE CASCADE, FOREIGN KEY (training_id) REFERENCES trainings(id) ON DELETE CASCADE ); -- WELFARE_REQUESTS TABLE CREATE TABLE welfare_requests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), member_id UUID NOT NULL, request_type VARCHAR(50) CHECK (request_type IN ('medical', 'financial', 'educational', 'emergency', 'other')), description TEXT NOT NULL, amount DECIMAL(15,2), status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'rejected', 'disbursed')), approved_by UUID NULL, approved_at TIMESTAMP, disbursed_at TIMESTAMP, notes TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (member_id) REFERENCES members(id) ON DELETE CASCADE, FOREIGN KEY (approved_by) REFERENCES users(id) ON DELETE SET NULL ); -- NEWS_ARTICLES TABLE CREATE TABLE news_articles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, slug VARCHAR(255) UNIQUE NOT NULL, content TEXT NOT NULL, excerpt TEXT, featured_image_url TEXT, category VARCHAR(50) CHECK (category IN ('news', 'announcement', 'press_release', 'event', 'other')), author_id UUID NOT NULL, published_at TIMESTAMP, status VARCHAR(20) DEFAULT 'draft' CHECK (status IN ('draft', 'published', 'archived')), views INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE ); -- GALLERIES TABLE CREATE TABLE galleries ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, description TEXT, cover_image_url TEXT, event_id UUID NULL, created_by UUID NOT NULL, is_published BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE SET NULL, FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE ); -- GALLERY_IMAGES TABLE CREATE TABLE gallery_images ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), gallery_id UUID NOT NULL, image_url TEXT NOT NULL, caption TEXT, display_order INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (gallery_id) REFERENCES galleries(id) ON DELETE CASCADE ); -- DOCUMENTS TABLE CREATE TABLE documents ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(255) NOT NULL, description TEXT, file_url TEXT NOT NULL, file_type VARCHAR(50), file_size BIGINT, category VARCHAR(50) CHECK (category IN ('policy', 'form', 'report', 'manual', 'other')), lga_id UUID NULL, ward_id UUID NULL, uploaded_by UUID NOT NULL, is_public BOOLEAN DEFAULT TRUE, downloads INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (lga_id) REFERENCES lgas(id) ON DELETE SET NULL, FOREIGN KEY (ward_id) REFERENCES wards(id) ON DELETE SET NULL, FOREIGN KEY (uploaded_by) REFERENCES users(id) ON DELETE CASCADE ); -- AUDIT_LOGS TABLE CREATE TABLE audit_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NULL, action VARCHAR(100) NOT NULL, entity_type VARCHAR(50), entity_id UUID, old_values JSONB, new_values JSONB, ip_address VARCHAR(45), user_agent TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL ); -- NOTIFICATIONS TABLE CREATE TABLE notifications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL, title VARCHAR(255) NOT NULL, message TEXT NOT NULL, type VARCHAR(50) CHECK (type IN ('info', 'success', 'warning', 'error')), link TEXT, is_read BOOLEAN DEFAULT FALSE, sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); -- SETTINGS TABLE CREATE TABLE settings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), key VARCHAR(100) UNIQUE NOT NULL, value TEXT, group VARCHAR(50), description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );