ALTER TABLE users ADD COLUMN family_admin_id BIGINT; CREATE TABLE IF NOT EXISTS families ( id uuid PRIMARY KEY NOT NULL, admin_id BIGINT NOT NULL, member_id BIGINT NOT NULL, -- status indicates the member status -- SELF/CLOSED are the state of the admin member when they create a family group or close it. status TEXT NOT NULL CHECK (status IN ('SELF', 'CLOSED', 'INVITED', 'ACCEPTED', 'DECLINED', 'REVOKED', 'REMOVED', 'LEFT')), token TEXT UNIQUE, percentage INTEGER NOT NULL DEFAULT -1, created_at bigint NOT NULL DEFAULT now_utc_micro_seconds(), updated_at bigint NOT NULL DEFAULT now_utc_micro_seconds(), CONSTRAINT fk_family_admin_id FOREIGN KEY (admin_id) REFERENCES users (user_id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS fk_families_admin_id ON families (admin_id); -- check to ensure that the member is not part of or is admin of another family group CREATE UNIQUE INDEX uidx_one_family_check on families (member_id, status) where status in ('ACCEPTED', 'SELF'); -- index to ensure that there's only one entry for admin and member. CREATE UNIQUE INDEX uidx_families_member_mapping on families (admin_id, member_id); ALTER TABLE families ADD CONSTRAINT families_member_state_constraint CHECK ( (admin_id != member_id and status not in ('SELF','CLOSED') or (admin_id = member_id and status in ('SELF', 'CLOSED')))); CREATE TRIGGER update_families_updated_at BEFORE UPDATE ON families FOR EACH ROW EXECUTE PROCEDURE trigger_updated_at_microseconds_column();