brmelect/brmelect.sql
2026-03-15 18:46:13 +01:00

186 lines
5.1 KiB
SQL

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 :