Accept isolated budget versus actual trial with documented capture limitation
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
CREATE TABLE ib_budgets (
|
||||
id bigserial PRIMARY KEY, lot_id bigint NOT NULL REFERENCES ic_lots(id),
|
||||
version integer NOT NULL CHECK(version>0), previous_id bigint UNIQUE REFERENCES ib_budgets(id),
|
||||
dimensions jsonb NOT NULL, amounts jsonb NOT NULL, evidence text NOT NULL CHECK(length(evidence)>=3),
|
||||
actor_id bigint NOT NULL REFERENCES users(id), created_at timestamptz NOT NULL, UNIQUE(lot_id,version)
|
||||
);
|
||||
CREATE TABLE ib_decisions (
|
||||
id bigserial PRIMARY KEY, budget_id bigint UNIQUE NOT NULL REFERENCES ib_budgets(id), version integer NOT NULL,
|
||||
decision text NOT NULL CHECK(decision IN ('approved','refused')), reason text NOT NULL CHECK(length(reason)>=3),
|
||||
actor_id bigint NOT NULL REFERENCES users(id), created_at timestamptz NOT NULL
|
||||
);
|
||||
CREATE TABLE ib_comparisons (
|
||||
id bigserial PRIMARY KEY, lot_id bigint NOT NULL REFERENCES ic_lots(id), version integer NOT NULL CHECK(version>0),
|
||||
previous_id bigint UNIQUE REFERENCES ib_comparisons(id), budget_id bigint NOT NULL REFERENCES ib_budgets(id),
|
||||
result_id bigint NOT NULL REFERENCES ic_results(id), snapshot jsonb NOT NULL,
|
||||
actor_id bigint NOT NULL REFERENCES users(id), created_at timestamptz NOT NULL, UNIQUE(lot_id,version)
|
||||
);
|
||||
CREATE TABLE ib_commands (
|
||||
id bigserial PRIMARY KEY, lot_id bigint NOT NULL REFERENCES ic_lots(id),actor_id bigint NOT NULL REFERENCES users(id),
|
||||
action text NOT NULL CHECK(action IN ('propose','decide','compare')),command_key text NOT NULL,request_hash text NOT NULL,
|
||||
result jsonb NOT NULL,created_at timestamptz NOT NULL,UNIQUE(lot_id,actor_id,action,command_key)
|
||||
);
|
||||
CREATE TABLE ib_events(id bigserial PRIMARY KEY,command_id bigint UNIQUE NOT NULL REFERENCES ib_commands(id),payload jsonb NOT NULL,created_at timestamptz NOT NULL);
|
||||
CREATE TABLE ib_outbox(event_id bigint PRIMARY KEY REFERENCES ib_events(id),state text NOT NULL CHECK(state='captured_no_stock_or_accounting'));
|
||||
CREATE OR REPLACE FUNCTION sgf_ib_integrity() RETURNS trigger LANGUAGE plpgsql AS $$
|
||||
DECLARE lid bigint; prior bigint; n integer; b ib_budgets; r ic_results; ref jsonb;
|
||||
BEGIN
|
||||
PERFORM sgf_ic_environment();
|
||||
IF TG_TABLE_NAME='ib_decisions' THEN
|
||||
SELECT * INTO STRICT b FROM ib_budgets WHERE id=NEW.budget_id;
|
||||
lid=b.lot_id;
|
||||
ELSE lid=NEW.lot_id; END IF;
|
||||
PERFORM 1 FROM companies WHERE id=(SELECT company_id FROM ic_lots WHERE id=lid) FOR UPDATE;
|
||||
IF TG_TABLE_NAME='ib_decisions' THEN
|
||||
IF b.actor_id=NEW.actor_id OR b.version<>NEW.version OR EXISTS(SELECT 1 FROM ib_budgets WHERE previous_id=b.id) THEN RAISE EXCEPTION 'SGF_IB_DECISION_VERSION_IDENTITY'; END IF;
|
||||
ELSIF TG_TABLE_NAME='ib_commands' THEN RETURN NEW;
|
||||
ELSE
|
||||
IF TG_TABLE_NAME='ib_budgets' THEN
|
||||
SELECT coalesce(max(version),0) INTO n FROM ib_budgets WHERE lot_id=lid;
|
||||
IF n>0 THEN SELECT id INTO STRICT prior FROM ib_budgets WHERE lot_id=lid AND version=n; END IF;
|
||||
ELSE
|
||||
SELECT coalesce(max(version),0) INTO n FROM ib_comparisons WHERE lot_id=lid;
|
||||
IF n>0 THEN SELECT id INTO STRICT prior FROM ib_comparisons WHERE lot_id=lid AND version=n; END IF;
|
||||
SELECT * INTO STRICT b FROM ib_budgets WHERE id=NEW.budget_id AND lot_id=lid;
|
||||
SELECT * INTO STRICT r FROM ic_results WHERE id=NEW.result_id AND lot_id=lid;
|
||||
IF NOT EXISTS(SELECT 1 FROM ib_decisions WHERE budget_id=b.id AND decision='approved') OR EXISTS(SELECT 1 FROM ib_budgets WHERE previous_id=b.id)
|
||||
OR NOT EXISTS(SELECT 1 FROM ic_decisions WHERE result_id=r.id AND decision='approved') OR EXISTS(SELECT 1 FROM ic_results WHERE previous_id=r.id)
|
||||
THEN RAISE EXCEPTION 'SGF_IB_APPROVED_CURRENT_REFERENCES'; END IF;
|
||||
FOR ref IN SELECT value FROM jsonb_each(r.snapshot->'refs') LOOP
|
||||
IF ref<>'null'::jsonb THEN PERFORM sgf_ic_input_current((ref->>'id')::bigint,lid,(ref->>'version')::integer); END IF;
|
||||
END LOOP;
|
||||
END IF;
|
||||
IF NEW.version<>n+1 OR (n=0 AND NEW.previous_id IS NOT NULL) OR (n>0 AND NEW.previous_id IS DISTINCT FROM prior) THEN RAISE EXCEPTION 'SGF_IB_VERSION'; END IF;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END; $$;
|
||||
CREATE TRIGGER ib_budget_integrity BEFORE INSERT ON ib_budgets FOR EACH ROW EXECUTE FUNCTION sgf_ib_integrity();
|
||||
CREATE TRIGGER ib_decision_integrity BEFORE INSERT ON ib_decisions FOR EACH ROW EXECUTE FUNCTION sgf_ib_integrity();
|
||||
CREATE TRIGGER ib_comparison_integrity BEFORE INSERT ON ib_comparisons FOR EACH ROW EXECUTE FUNCTION sgf_ib_integrity();
|
||||
CREATE TRIGGER ib_command_integrity BEFORE INSERT ON ib_commands FOR EACH ROW EXECUTE FUNCTION sgf_ib_integrity();
|
||||
Reference in New Issue
Block a user