CREATE SCHEMA IF NOT EXISTS brm; CREATE TABLE brm.members ( member_id INTEGER PRIMARY KEY, nick TEXT NOT NULL, name TEXT NOT NULL, surname TEXT NOT NULL ); CREATE OR REPLACE FUNCTION brm.ensure_member( i_member_id INTEGER, i_nick TEXT, i_name TEXT, i_surname TEXT ) RETURNS INTEGER LANGUAGE SQL BEGIN ATOMIC INSERT INTO brm.members (member_id, nick, name, surname) VALUES (i_member_id, i_nick, i_name, i_surname) ON CONFLICT (member_id) DO UPDATE SET nick = EXCLUDED.nick, name = EXCLUDED.name, surname = EXCLUDED.surname RETURNING member_id; END; CREATE TABLE brm.meetings ( meeting_id INTEGER PRIMARY KEY, title TEXT NOT NULL, held_on TSTZRANGE NOT NULL ); CREATE OR REPLACE FUNCTION brm.start_meeting( i_meeting_id INTEGER, i_title TEXT ) RETURNS INTEGER LANGUAGE SQL BEGIN ATOMIC INSERT INTO brm.meetings (meeting_id, title, held_on) VALUES ( i_meeting_id, i_title, CASE WHEN now() < date_trunc('day', now()) + interval '23 hours' THEN tstzrange( now(), date_trunc('day', now()) + interval '23 hours', '[)' ) END ) RETURNING meeting_id; END; CREATE TABLE brm.votes ( vote_id SERIAL PRIMARY KEY, meeting_id INTEGER NOT NULL REFERENCES brm.meetings(meeting_id), title TEXT NOT NULL, open_time TSTZRANGE NOT NULL, is_active BOOLEAN NOT NULL DEFAULT FALSE ); CREATE TABLE brm.meeting_member_status ( member_id INTEGER NOT NULL REFERENCES brm.members(member_id), meeting_id INTEGER NOT NULL REFERENCES brm.meetings(meeting_id), in_debt BOOLEAN NOT NULL, short_tenure BOOLEAN NOT NULL, has_vote BOOLEAN NOT NULL, eligible BOOLEAN NOT NULL, present BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY (member_id, meeting_id) ); CREATE OR REPLACE FUNCTION brm.record_meeting_member_status( i_meeting_id INTEGER, i_member_id INTEGER, i_in_debt BOOLEAN, i_short_tenure BOOLEAN, i_has_vote BOOLEAN ) RETURNS INTEGER LANGUAGE SQL BEGIN ATOMIC INSERT INTO brm.meeting_member_status (member_id, meeting_id, in_debt, short_tenure, has_vote, eligible) SELECT i_member_id, i_meeting_id, i_in_debt, i_short_tenure, i_has_vote, i_has_vote RETURNING member_id; END; CREATE OR REPLACE FUNCTION brm.record_current_meeting_member_status( i_member_id INTEGER, i_in_debt BOOLEAN, i_short_tenure BOOLEAN, i_has_vote BOOLEAN ) RETURNS INTEGER LANGUAGE SQL BEGIN ATOMIC SELECT brm.record_meeting_member_status((SELECT MAX(meeting_id) FROM brm.meetings), i_member_id, i_in_debt, i_short_tenure, i_has_vote); END; CREATE TABLE brm.vote_member_status ( member_id INTEGER NOT NULL REFERENCES brm.members(member_id), meeting_id INTEGER NOT NULL REFERENCES brm.meetings(meeting_id), vote_id INTEGER NOT NULL REFERENCES brm.votes(vote_id), in_debt BOOLEAN NOT NULL, short_tenure BOOLEAN NOT NULL, has_vote BOOLEAN NOT NULL, eligible BOOLEAN NOT NULL, present BOOLEAN NOT NULL, PRIMARY KEY (member_id, meeting_id, vote_id) ); CREATE OR REPLACE FUNCTION brm.create_vote_and_init_status( i_meeting_id INTEGER, i_title TEXT ) RETURNS INTEGER LANGUAGE SQL BEGIN ATOMIC WITH new_vote AS ( INSERT INTO brm.votes (meeting_id, title, open_time, is_active) VALUES (i_meeting_id, i_title, tstzrange(now(), now()+interval '30 minutes'), TRUE) RETURNING vote_id, meeting_id ), copied AS ( INSERT INTO brm.vote_member_status ( member_id, meeting_id, vote_id, in_debt, short_tenure, has_vote, eligible ) SELECT m.member_id, m.meeting_id, v.vote_id, m.in_debt, m.short_tenure, m.has_vote, m.eligible FROM brm.meeting_member_status m JOIN new_vote v ON v.meeting_id = m.meeting_id ) SELECT vote_id FROM new_vote; END; CREATE OR REPLACE FUNCTION brm.new_vote_for_current_meeting( i_title TEXT ) RETURNS INTEGER LANGUAGE SQL BEGIN ATOMIC SELECT brm.create_vote_and_init_status((SELECT MAX(meeting_id) FROM brm.meetings), i_title); END; CREATE OR REPLACE FUNCTION brm.sync_vote_present_to_meeting(i_member_id INTEGER, i_meeting_id INTEGER, i_present BOOLEAN) RETURNS VOID LANGUAGE SQL BEGIN ATOMIC UPDATE brm.meeting_member_status SET present = i_present WHERE member_id = i_member_id AND meeting_id = i_meeting_id; END; CREATE OR REPLACE FUNCTION brm.sync_meeting_present_to_votes(i_member_id INTEGER, i_meeting_id INTEGER, i_present BOOLEAN) RETURNS VOID LANGUAGE SQL BEGIN ATOMIC UPDATE brm.vote_member_status SET present = i_present WHERE member_id = i_member_id AND meeting_id = i_meeting_id AND EXISTS (SELECT 1 FROM brm.votes WHERE meeting_id = i_meeting_id AND is_active = TRUE); END; ---------------------------------------------------------------- -- vim: set et sw=4 ts=4 :