From d712a8ba4c7c03f2b4a0bfc2a4324f3028504d16 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Thu, 27 Sep 2018 14:52:36 -0400 Subject: [PATCH 1/4] setup delete triggers --- schema/triggers/gl_delete.sql | 142 +++++++++++++++++++++++++++++++++ schema/triggers/gl_insert.sql | 8 +- schema/triggers/log_delete.sql | 30 +++++++ 3 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 schema/triggers/gl_delete.sql create mode 100644 schema/triggers/log_delete.sql diff --git a/schema/triggers/gl_delete.sql b/schema/triggers/gl_delete.sql new file mode 100644 index 0000000..19690cd --- /dev/null +++ b/schema/triggers/gl_delete.sql @@ -0,0 +1,142 @@ +---------------------------handle new gl lines---------------------------------------- + +CREATE OR REPLACE FUNCTION evt.gl_insert() RETURNS trigger +LANGUAGE plpgsql +AS +$func$ +DECLARE + _mind timestamptz; + _maxd timestamptz; +BEGIN + SELECT + (SELECT min(lower(f.dur)) FROM ins INNER JOIN evt.fspr f ON f.id = ins.fspr) + ,GREATEST( + (SELECT max(lower(f.dur)) FROM ins INNER JOIN evt.fspr f ON f.id = ins.fspr), + COALESCE( + (SELECT max(lower(dur)) FROM evt.fspr WHERE prop @> '{"gltouch":"yes"}'), + (SELECT max(lower(f.dur)) FROM ins INNER JOIN evt.fspr f ON f.id = ins.fspr) + ) + ) + INTO + _mind + ,_maxd; + + WITH + agg AS ( + SELECT + acct + ,fspr + ,dur + ,coalesce(sum(amount) FILTER (WHERE amount > 0),0) debits + ,coalesce(sum(amount) FILTER (WHERE amount < 0),0) credits + FROM + ins + INNER JOIN evt.fspr f ON + f.id = ins.fspr + GROUP BY + acct + ,fspr + ,dur + ) + --get every account involved in target range + ,arng AS ( + SELECT DISTINCT + acct + FROM + agg b + ) + ,seq AS ( + WITH RECURSIVE rf (acct, id, dur, obal, debits, credits, cbal) AS + ( + SELECT + arng.acct + ,f.id + ,f.dur + ,COALESCE(b.obal::numeric(12,2),0) + ,COALESCE(b.debits::numeric(12,2),0) + COALESCE(agg.debits,0) + ,COALESCE(b.credits::numeric(12,2),0) + COALESCE(agg.credits,0) + ,COALESCE(b.cbal::numeric(12,2),0) + COALESCE(agg.debits,0) + COALESCE(agg.credits,0) + FROM + arng + INNER JOIN evt.fspr f ON + upper(f.dur) = _mind + LEFT OUTER JOIN evt.bal b ON + b.acct = arng.acct + AND b.fspr = f.id + LEFT OUTER JOIN agg ON + agg.acct = arng.acct + AND agg.fspr = f.id + + UNION ALL + + SELECT + rf.acct + ,f.id + ,f.dur + ,COALESCE(rf.cbal,0)::numeric(12,2) + ,COALESCE(b.debits,0)::numeric(12,2) + COALESCE(agg.debits,0) + ,COALESCE(b.credits,0)::numeric(12,2) + COALESCe(agg.credits,0) + ,(COALESCE(rf.cbal,0) + COALESCE(b.debits,0) + COALESCE(b.credits,0))::numeric(12,2) + COALESCE(agg.debits,0) + COALESCE(agg.credits,0) + FROM + rf + INNER JOIN evt.fspr f ON + lower(f.dur) = upper(rf.dur) + LEFT OUTER JOIN evt.bal b ON + b.acct = rf.acct + AND b.fspr = f.id + LEFT OUTER JOIN agg ON + agg.acct = rf.acct + AND agg.fspr = f.id + WHERE + lower(f.dur) <= _maxd + ) + SELECT * FROM rf WHERE lower(dur) >= _mind + ) + ,bali AS ( + INSERT INTO + evt.bal (acct, fspr, obal, debits, credits, cbal) + SELECT + acct + ,id + ,obal + ,debits + ,credits + ,cbal + FROM + seq + ON CONFLICT ON CONSTRAINT bal_pk DO UPDATE SET + obal = EXCLUDED.obal + ,debits = EXCLUDED.debits + ,credits = EXCLUDED.credits + ,cbal = EXCLUDED.cbal + ,prop = evt.bal.prop || EXCLUDED.prop + RETURNING * + ) + ,n as ( + SELECT DISTINCT + fspr + FROM + bali + ) + UPDATE + evt.fspr f + SET + prop = COALESCE(f.prop,'{}'::JSONB) || '{"gltouch":"yes"}'::jsonb + FROM + n + WHERE + f.id = n.fspr; + + PERFORM evt.balrf(); + + RETURN NULL; +END; +$func$; + +COMMENT ON FUNCTION evt.gl_insert IS 'update evt.bal with new ledger rows'; + +CREATE TRIGGER gl_insert + AFTER INSERT ON evt.gl + REFERENCING NEW TABLE AS ins + FOR EACH STATEMENT + EXECUTE PROCEDURE evt.gl_insert(); \ No newline at end of file diff --git a/schema/triggers/gl_insert.sql b/schema/triggers/gl_insert.sql index 19690cd..0aff50a 100644 --- a/schema/triggers/gl_insert.sql +++ b/schema/triggers/gl_insert.sql @@ -8,6 +8,9 @@ DECLARE _mind timestamptz; _maxd timestamptz; BEGIN + --find min and max applicable periods to roll + --min: earliest period involved in current gl posting + --max: latest period involved in any posting, or if none, the current posting SELECT (SELECT min(lower(f.dur)) FROM ins INNER JOIN evt.fspr f ON f.id = ins.fspr) ,GREATEST( @@ -27,8 +30,9 @@ BEGIN acct ,fspr ,dur - ,coalesce(sum(amount) FILTER (WHERE amount > 0),0) debits - ,coalesce(sum(amount) FILTER (WHERE amount < 0),0) credits + --put a negative in front to negate the initial debit/credit assignment + ,coalesce(-sum(amount) FILTER (WHERE amount > 0),0) debits + ,coalesce(-sum(amount) FILTER (WHERE amount < 0),0) credits FROM ins INNER JOIN evt.fspr f ON diff --git a/schema/triggers/log_delete.sql b/schema/triggers/log_delete.sql new file mode 100644 index 0000000..009e76e --- /dev/null +++ b/schema/triggers/log_delete.sql @@ -0,0 +1,30 @@ +---------------------------handle new logged event---------------------------------------- + +CREATE OR REPLACE FUNCTION evt.log_delete() RETURNS trigger + LANGUAGE plpgsql + AS + $func$ + BEGIN + DELETE + FROM + evt.gl g + WHERE EXISTS + ( + SELECT + NULL::int + FROM + g + INNER JOIN del ON + del.id = g.bprid + ); + RETURN NULL; + END; + $func$; + +COMMENT ON FUNCTION evt.log_delete IS 'perspective lines assocated with deleted event'; + +CREATE TRIGGER log_delete + AFTER DELETE ON evt.bpr + REFERENCING OLD TABLE AS del + FOR EACH STATEMENT + EXECUTE PROCEDURE evt.log_delete(); \ No newline at end of file From b372f70f12da234fc7934e60aa19e6101f5a25b1 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Thu, 27 Sep 2018 14:56:12 -0400 Subject: [PATCH 2/4] wrong file edited --- schema/triggers/gl_insert.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/schema/triggers/gl_insert.sql b/schema/triggers/gl_insert.sql index 0aff50a..45cdcdb 100644 --- a/schema/triggers/gl_insert.sql +++ b/schema/triggers/gl_insert.sql @@ -30,9 +30,9 @@ BEGIN acct ,fspr ,dur - --put a negative in front to negate the initial debit/credit assignment - ,coalesce(-sum(amount) FILTER (WHERE amount > 0),0) debits - ,coalesce(-sum(amount) FILTER (WHERE amount < 0),0) credits + put a negative in front to negate the initial debit/credit assignment + ,coalesce(sum(amount) FILTER (WHERE amount > 0),0) debits + ,coalesce(sum(amount) FILTER (WHERE amount < 0),0) credits FROM ins INNER JOIN evt.fspr f ON From e93ea9b64a9d741b680a4f14a3866de9b0d159ac Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Thu, 27 Sep 2018 14:59:17 -0400 Subject: [PATCH 3/4] reverse out --- schema/triggers/gl_delete.sql | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/schema/triggers/gl_delete.sql b/schema/triggers/gl_delete.sql index 19690cd..46b982a 100644 --- a/schema/triggers/gl_delete.sql +++ b/schema/triggers/gl_delete.sql @@ -1,6 +1,6 @@ ----------------------------handle new gl lines---------------------------------------- +---------------------------handle deleted gl lines---------------------------------------- -CREATE OR REPLACE FUNCTION evt.gl_insert() RETURNS trigger +CREATE OR REPLACE FUNCTION evt.gl_delete() RETURNS trigger LANGUAGE plpgsql AS $func$ @@ -27,8 +27,9 @@ BEGIN acct ,fspr ,dur - ,coalesce(sum(amount) FILTER (WHERE amount > 0),0) debits - ,coalesce(sum(amount) FILTER (WHERE amount < 0),0) credits + --negate initial debits credits + ,coalesce(-sum(amount) FILTER (WHERE amount > 0),0) debits + ,coalesce(-sum(amount) FILTER (WHERE amount < 0),0) credits FROM ins INNER JOIN evt.fspr f ON @@ -133,10 +134,10 @@ BEGIN END; $func$; -COMMENT ON FUNCTION evt.gl_insert IS 'update evt.bal with new ledger rows'; +COMMENT ON FUNCTION evt.gl_delete IS 'reduce evt.bal for deleted ledger rows'; -CREATE TRIGGER gl_insert +CREATE TRIGGER gl_delete AFTER INSERT ON evt.gl - REFERENCING NEW TABLE AS ins + REFERENCING OLD TABLE AS ins FOR EACH STATEMENT - EXECUTE PROCEDURE evt.gl_insert(); \ No newline at end of file + EXECUTE PROCEDURE evt.gl_delete(); \ No newline at end of file From 3f2a2f4fcfe15339613c0cd7c5afae93e58cdd75 Mon Sep 17 00:00:00 2001 From: Paul Trowbridge Date: Thu, 27 Sep 2018 16:50:11 -0400 Subject: [PATCH 4/4] add deletes --- db_deploy.sql | 147 ++++++++++++++++++++++++++++++++- schema/tables/gl.sql | 2 +- schema/triggers/gl_delete.sql | 2 +- schema/triggers/log_delete.sql | 30 ------- 4 files changed, 147 insertions(+), 34 deletions(-) delete mode 100644 schema/triggers/log_delete.sql diff --git a/db_deploy.sql b/db_deploy.sql index e487127..6163571 100644 --- a/db_deploy.sql +++ b/db_deploy.sql @@ -46,10 +46,10 @@ CREATE INDEX id_gist ON evt.fspr USING GIST (id); --------------------------relational ledger------------------------------------------ - +--DROP TABLE evt.gl CREATE TABLE evt.gl ( id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY - ,bprid INT REFERENCES evt.bpr (id) + ,bprid INT REFERENCES evt.bpr (id) ON DELETE CASCADE ,acct ltree REFERENCES evt.acct (acct) ,pstmp timestamptz DEFAULT CURRENT_TIMESTAMP --populates by trigger join to evt.fspr @@ -321,6 +321,149 @@ CREATE TRIGGER gl_insert FOR EACH STATEMENT EXECUTE PROCEDURE evt.gl_insert(); +---------------------------handle deleted gl lines---------------------------------------- + +CREATE OR REPLACE FUNCTION evt.gl_delete() RETURNS trigger +LANGUAGE plpgsql +AS +$func$ +DECLARE + _mind timestamptz; + _maxd timestamptz; +BEGIN + SELECT + (SELECT min(lower(f.dur)) FROM ins INNER JOIN evt.fspr f ON f.id = ins.fspr) + ,GREATEST( + (SELECT max(lower(f.dur)) FROM ins INNER JOIN evt.fspr f ON f.id = ins.fspr), + COALESCE( + (SELECT max(lower(dur)) FROM evt.fspr WHERE prop @> '{"gltouch":"yes"}'), + (SELECT max(lower(f.dur)) FROM ins INNER JOIN evt.fspr f ON f.id = ins.fspr) + ) + ) + INTO + _mind + ,_maxd; + + WITH + agg AS ( + SELECT + acct + ,fspr + ,dur + --negate initial debits credits + ,coalesce(-sum(amount) FILTER (WHERE amount > 0),0) debits + ,coalesce(-sum(amount) FILTER (WHERE amount < 0),0) credits + FROM + ins + INNER JOIN evt.fspr f ON + f.id = ins.fspr + GROUP BY + acct + ,fspr + ,dur + ) + --get every account involved in target range + ,arng AS ( + SELECT DISTINCT + acct + FROM + agg b + ) + ,seq AS ( + WITH RECURSIVE rf (acct, id, dur, obal, debits, credits, cbal) AS + ( + SELECT + arng.acct + ,f.id + ,f.dur + ,COALESCE(b.obal::numeric(12,2),0) + ,COALESCE(b.debits::numeric(12,2),0) + COALESCE(agg.debits,0) + ,COALESCE(b.credits::numeric(12,2),0) + COALESCE(agg.credits,0) + ,COALESCE(b.cbal::numeric(12,2),0) + COALESCE(agg.debits,0) + COALESCE(agg.credits,0) + FROM + arng + INNER JOIN evt.fspr f ON + upper(f.dur) = _mind + LEFT OUTER JOIN evt.bal b ON + b.acct = arng.acct + AND b.fspr = f.id + LEFT OUTER JOIN agg ON + agg.acct = arng.acct + AND agg.fspr = f.id + + UNION ALL + + SELECT + rf.acct + ,f.id + ,f.dur + ,COALESCE(rf.cbal,0)::numeric(12,2) + ,COALESCE(b.debits,0)::numeric(12,2) + COALESCE(agg.debits,0) + ,COALESCE(b.credits,0)::numeric(12,2) + COALESCe(agg.credits,0) + ,(COALESCE(rf.cbal,0) + COALESCE(b.debits,0) + COALESCE(b.credits,0))::numeric(12,2) + COALESCE(agg.debits,0) + COALESCE(agg.credits,0) + FROM + rf + INNER JOIN evt.fspr f ON + lower(f.dur) = upper(rf.dur) + LEFT OUTER JOIN evt.bal b ON + b.acct = rf.acct + AND b.fspr = f.id + LEFT OUTER JOIN agg ON + agg.acct = rf.acct + AND agg.fspr = f.id + WHERE + lower(f.dur) <= _maxd + ) + SELECT * FROM rf WHERE lower(dur) >= _mind + ) + ,bali AS ( + INSERT INTO + evt.bal (acct, fspr, obal, debits, credits, cbal) + SELECT + acct + ,id + ,obal + ,debits + ,credits + ,cbal + FROM + seq + ON CONFLICT ON CONSTRAINT bal_pk DO UPDATE SET + obal = EXCLUDED.obal + ,debits = EXCLUDED.debits + ,credits = EXCLUDED.credits + ,cbal = EXCLUDED.cbal + ,prop = evt.bal.prop || EXCLUDED.prop + RETURNING * + ) + ,n as ( + SELECT DISTINCT + fspr + FROM + bali + ) + UPDATE + evt.fspr f + SET + prop = COALESCE(f.prop,'{}'::JSONB) || '{"gltouch":"yes"}'::jsonb + FROM + n + WHERE + f.id = n.fspr; + + PERFORM evt.balrf(); + + RETURN NULL; +END; +$func$; + +COMMENT ON FUNCTION evt.gl_delete IS 'reduce evt.bal for deleted ledger rows'; + +CREATE TRIGGER gl_delete + AFTER DELETE ON evt.gl + REFERENCING OLD TABLE AS ins + FOR EACH STATEMENT + EXECUTE PROCEDURE evt.gl_delete(); ------------------------function that rolls balances forward------------------------------------------- diff --git a/schema/tables/gl.sql b/schema/tables/gl.sql index 9d81acb..8c8704b 100644 --- a/schema/tables/gl.sql +++ b/schema/tables/gl.sql @@ -2,7 +2,7 @@ --DROP TABLE evt.gl CREATE TABLE evt.gl ( id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY - ,bprid INT REFERENCES evt.bpr (id) + ,bprid INT REFERENCES evt.bpr (id) ON DELETE CASCADE ,acct ltree REFERENCES evt.acct (acct) ,pstmp timestamptz DEFAULT CURRENT_TIMESTAMP --populates by trigger join to evt.fspr diff --git a/schema/triggers/gl_delete.sql b/schema/triggers/gl_delete.sql index 46b982a..2d70810 100644 --- a/schema/triggers/gl_delete.sql +++ b/schema/triggers/gl_delete.sql @@ -137,7 +137,7 @@ $func$; COMMENT ON FUNCTION evt.gl_delete IS 'reduce evt.bal for deleted ledger rows'; CREATE TRIGGER gl_delete - AFTER INSERT ON evt.gl + AFTER DELETE ON evt.gl REFERENCING OLD TABLE AS ins FOR EACH STATEMENT EXECUTE PROCEDURE evt.gl_delete(); \ No newline at end of file diff --git a/schema/triggers/log_delete.sql b/schema/triggers/log_delete.sql deleted file mode 100644 index 009e76e..0000000 --- a/schema/triggers/log_delete.sql +++ /dev/null @@ -1,30 +0,0 @@ ----------------------------handle new logged event---------------------------------------- - -CREATE OR REPLACE FUNCTION evt.log_delete() RETURNS trigger - LANGUAGE plpgsql - AS - $func$ - BEGIN - DELETE - FROM - evt.gl g - WHERE EXISTS - ( - SELECT - NULL::int - FROM - g - INNER JOIN del ON - del.id = g.bprid - ); - RETURN NULL; - END; - $func$; - -COMMENT ON FUNCTION evt.log_delete IS 'perspective lines assocated with deleted event'; - -CREATE TRIGGER log_delete - AFTER DELETE ON evt.bpr - REFERENCING OLD TABLE AS del - FOR EACH STATEMENT - EXECUTE PROCEDURE evt.log_delete(); \ No newline at end of file