142 lines
4.6 KiB
MySQL
142 lines
4.6 KiB
MySQL
|
|
|
||
|
|
|
||
|
|
CREATE TABLE role (
|
||
|
|
role_id SERIAL PRIMARY KEY,
|
||
|
|
name VARCHAR(50) UNIQUE NOT NULL, -- admin, volunteer, team_lead, manager, terry
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- COMBINED: users + admin_settings in one table
|
||
|
|
CREATE TABLE users (
|
||
|
|
user_id SERIAL PRIMARY KEY,
|
||
|
|
first_name VARCHAR(100),
|
||
|
|
last_name VARCHAR(100),
|
||
|
|
email VARCHAR(150) UNIQUE NOT NULL,
|
||
|
|
phone VARCHAR(20),
|
||
|
|
password TEXT NOT NULL,
|
||
|
|
role_id INT REFERENCES role(role_id) ON DELETE SET NULL,
|
||
|
|
admin_code CHAR(6) UNIQUE,
|
||
|
|
-- Admin settings combined here
|
||
|
|
ward_settings TEXT,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE address_database (
|
||
|
|
address_id SERIAL PRIMARY KEY,
|
||
|
|
address VARCHAR(255),
|
||
|
|
street_name VARCHAR(100),
|
||
|
|
street_type VARCHAR(50),
|
||
|
|
street_quadrant VARCHAR(50),
|
||
|
|
house_number VARCHAR(20),
|
||
|
|
house_alpha VARCHAR(10),
|
||
|
|
postal_code VARCHAR(10),
|
||
|
|
longitude DECIMAL(9,6),
|
||
|
|
latitude DECIMAL(9,6),
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE team (
|
||
|
|
team_id SERIAL PRIMARY KEY,
|
||
|
|
team_lead_id INT REFERENCES users(user_id) ON DELETE SET NULL,
|
||
|
|
volunteer_id INT REFERENCES users(user_id) ON DELETE SET NULL,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE admin_volunteers (
|
||
|
|
admin_id INT REFERENCES users(user_id) ON DELETE CASCADE,
|
||
|
|
volunteer_id INT REFERENCES users(user_id) ON DELETE CASCADE,
|
||
|
|
is_active BOOLEAN DEFAULT TRUE,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
PRIMARY KEY (admin_id, volunteer_id)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE appointment (
|
||
|
|
sched_id SERIAL PRIMARY KEY,
|
||
|
|
user_id INT REFERENCES users(user_id) ON DELETE CASCADE,
|
||
|
|
address_id INT REFERENCES address_database(address_id) ON DELETE CASCADE,
|
||
|
|
appointment_date DATE,
|
||
|
|
appointment_time TIME,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE poll(
|
||
|
|
poll_id SERIAL PRIMARY KEY,
|
||
|
|
user_id INTEGER REFERENCES users ON DELETE CASCADE,
|
||
|
|
address_id INTEGER REFERENCES address_database ON DELETE CASCADE,
|
||
|
|
donation_amount integer default 0,
|
||
|
|
is_active BOOLEAN DEFAULT TRUE,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE poll_response
|
||
|
|
(
|
||
|
|
poll_response_id SERIAL PRIMARY KEY,
|
||
|
|
poll_id INTEGER REFERENCES poll(poll_id) ON DELETE CASCADE,
|
||
|
|
respondent_postal_code VARCHAR(10), -- Postal code of respondent
|
||
|
|
question1_voted_before BOOLEAN, -- Have you voted before?
|
||
|
|
question2_vote_again BOOLEAN, -- Will you vote again for this candidate?
|
||
|
|
question3_lawn_signs INTEGER DEFAULT 0, -- How many lawn signs needed
|
||
|
|
question4_banner_signs INTEGER DEFAULT 0, -- How many banner signs needed
|
||
|
|
question5_thoughts TEXT, -- Write your thoughts
|
||
|
|
signage_status VARCHAR(50) DEFAULT 'requested' CHECK (signage_status IN ('requested', 'delivered', 'cancelled')),
|
||
|
|
is_active BOOLEAN DEFAULT TRUE,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE post (
|
||
|
|
post_id SERIAL PRIMARY KEY,
|
||
|
|
author_id INT REFERENCES users(user_id) ON DELETE CASCADE,
|
||
|
|
content TEXT,
|
||
|
|
image_url TEXT,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE availability (
|
||
|
|
availability_id SERIAL PRIMARY KEY,
|
||
|
|
user_id INT REFERENCES users(user_id) ON DELETE CASCADE,
|
||
|
|
day_of_week VARCHAR(20),
|
||
|
|
start_time TIME,
|
||
|
|
end_time TIME,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Indexes for better performance
|
||
|
|
CREATE INDEX idx_poll_response_poll_id ON poll_response(poll_id);
|
||
|
|
CREATE INDEX idx_poll_response_postal_code ON poll_response(respondent_postal_code);
|
||
|
|
CREATE INDEX idx_poll_response_signage_status ON poll_response(signage_status);
|
||
|
|
CREATE INDEX idx_poll_user_id ON poll(user_id);
|
||
|
|
|
||
|
|
-- Function to generate a 6-character random admin code
|
||
|
|
CREATE OR REPLACE FUNCTION generate_admin_code()
|
||
|
|
RETURNS trigger AS $$
|
||
|
|
BEGIN
|
||
|
|
IF (SELECT name FROM role WHERE role_id = NEW.role_id) = 'admin' THEN
|
||
|
|
NEW.admin_code := substring(md5(random()::text) FROM 1 FOR 6);
|
||
|
|
ELSE
|
||
|
|
NEW.admin_code := NULL;
|
||
|
|
END IF;
|
||
|
|
RETURN NEW;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
-- Trigger to automatically generate admin_code on INSERT
|
||
|
|
CREATE TRIGGER set_admin_code
|
||
|
|
BEFORE INSERT ON users
|
||
|
|
FOR EACH ROW
|
||
|
|
EXECUTE PROCEDURE generate_admin_code();
|
||
|
|
|
||
|
|
|
||
|
|
INSERT INTO role (role_id, name) VALUES
|
||
|
|
(1, 'admin'),
|
||
|
|
(2, 'team_lead'),
|
||
|
|
(3, 'volunteer')
|
||
|
|
ON CONFLICT DO NOTHING;
|