From 2bacea7ad90c4b53474f0c0a511e9f555d429d32 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Thu, 29 Aug 2024 17:00:19 +0200 Subject: [PATCH] historic-view (#92) Co-authored-by: Michael Hoennig Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/92 Reviewed-by: Marc Sandlus --- .run/ImportHostingAssets into local.run.xml | 37 ++++ .run/ImportHostingAssets.run.xml | 33 ---- sql/examples.sql | 53 ----- sql/historization.sql | 185 +++--------------- .../db/changelog/0-basis/020-audit-log.sql | 33 ++-- .../changelog/0-basis/030-historization.sql | 160 +++++++++++++++ .../2018-test-customer-test-data.sql | 7 +- .../2028-test-package-test-data.sql | 7 +- .../2038-test-domain-test-data.sql | 5 +- .../5018-hs-office-contact-test-data.sql | 8 +- .../5028-hs-office-person-test-data.sql | 7 +- .../5038-hs-office-relation-test-data.sql | 6 +- .../5048-hs-office-partner-test-data.sql | 7 +- .../5058-hs-office-bankaccount-test-data.sql | 9 +- .../5068-hs-office-debitor-test-data.sql | 6 +- .../5078-hs-office-sepamandate-test-data.sql | 7 +- .../5108-hs-office-membership-test-data.sql | 9 +- .../5118-hs-office-coopshares-test-data.sql | 9 +- .../5128-hs-office-coopassets-test-data.sql | 9 +- .../6200-hs-booking-project.sql | 7 + .../6208-hs-booking-project-test-data.sql | 6 +- .../630-booking-item/6200-hs-booking-item.sql | 8 + .../6208-hs-booking-item-test-data.sql | 9 +- .../7010-hs-hosting-asset.sql | 10 +- .../7018-hs-hosting-asset-test-data.sql | 7 +- .../db/changelog/db.changelog-master.yaml | 4 +- ...sBookingItemRepositoryIntegrationTest.java | 69 +++++-- ...okingProjectRepositoryIntegrationTest.java | 65 ++++-- ...HostingAssetRepositoryIntegrationTest.java | 81 ++++++-- .../hs/migration/BaseOfficeDataImport.java | 2 +- .../hsadminng/hs/migration/CsvDataImport.java | 5 +- ...eBankAccountRepositoryIntegrationTest.java | 7 +- ...eContactRbacRepositoryIntegrationTest.java | 7 +- ...sTransactionRepositoryIntegrationTest.java | 16 +- ...sTransactionRepositoryIntegrationTest.java | 16 +- ...fficeDebitorRepositoryIntegrationTest.java | 7 +- ...ceMembershipRepositoryIntegrationTest.java | 8 +- ...fficePartnerRepositoryIntegrationTest.java | 9 +- ...OfficePersonRepositoryIntegrationTest.java | 8 +- ...ficeRelationRepositoryIntegrationTest.java | 5 +- ...eSepaMandateRepositoryIntegrationTest.java | 8 +- .../rbac/context/ContextBasedTest.java | 23 +++ 42 files changed, 550 insertions(+), 434 deletions(-) create mode 100644 .run/ImportHostingAssets into local.run.xml delete mode 100644 sql/examples.sql create mode 100644 src/main/resources/db/changelog/0-basis/030-historization.sql diff --git a/.run/ImportHostingAssets into local.run.xml b/.run/ImportHostingAssets into local.run.xml new file mode 100644 index 00000000..d3c7f2da --- /dev/null +++ b/.run/ImportHostingAssets into local.run.xml @@ -0,0 +1,37 @@ + + + + + + + + false + true + + + + false + true + + + \ No newline at end of file diff --git a/.run/ImportHostingAssets.run.xml b/.run/ImportHostingAssets.run.xml index 2a7b71f6..bedd7143 100644 --- a/.run/ImportHostingAssets.run.xml +++ b/.run/ImportHostingAssets.run.xml @@ -33,37 +33,4 @@ true - - - - - - - false - true - - - - false - true - - \ No newline at end of file diff --git a/sql/examples.sql b/sql/examples.sql deleted file mode 100644 index 13219654..00000000 --- a/sql/examples.sql +++ /dev/null @@ -1,53 +0,0 @@ --- ======================================================== --- First Example Entity with History --- -------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS customer ( - "id" SERIAL PRIMARY KEY, - "reference" int not null unique, -- 10000-99999 - "prefix" character(3) unique - ); - -CALL create_historicization('customer'); - - --- ======================================================== --- Second Example Entity with History --- -------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS package_type ( - "id" serial PRIMARY KEY, - "name" character varying(8) - ); - -CALL create_historicization('package_type'); - --- ======================================================== --- Third Example Entity with History --- -------------------------------------------------------- - -CREATE TABLE IF NOT EXISTS package ( - "id" serial PRIMARY KEY, - "name" character varying(5), - "customer_id" INTEGER REFERENCES customer(id) - ); - -CALL create_historicization('package'); - - --- ======================================================== --- query historical data --- -------------------------------------------------------- - - -ABORT; -BEGIN TRANSACTION; -SET LOCAL hsadminng.currentUser TO 'mih42_customer_aaa'; -SET LOCAL hsadminng.currentTask TO 'adding customer_aaa'; -INSERT INTO package (customer_id, name) VALUES (10000, 'aaa00'); -COMMIT; --- Usage: - -SET hsadminng.timestamp TO '2022-07-12 08:53:27.723315'; -SET hsadminng.timestamp TO '2022-07-12 11:38:27.723315'; -SELECT * FROM customer_hv p WHERE prefix = 'aaa'; diff --git a/sql/historization.sql b/sql/historization.sql index 1bd0db44..6f50f428 100644 --- a/sql/historization.sql +++ b/sql/historization.sql @@ -1,166 +1,39 @@ -- ======================================================== --- Historization +-- Historization twiddle -- -------------------------------------------------------- -CREATE TABLE "tx_history" ( - "tx_id" BIGINT NOT NULL UNIQUE, - "tx_timestamp" TIMESTAMP NOT NULL, - "user" VARCHAR(64) NOT NULL, -- references postgres user - "task" VARCHAR NOT NULL -); +rollback; +begin transaction; +call defineContext('historization testing', null, 'superuser-alex@hostsharing.net', +-- 'hs_booking_project#D-1000000-hshdefaultproject:ADMIN'); -- prod+test + 'hs_booking_project#D-1000313-D-1000313defaultproject:ADMIN'); -- prod+test +-- 'hs_booking_project#D-1000300-mihdefaultproject:ADMIN'); -- prod +-- 'hs_booking_project#D-1000300-mimdefaultproject:ADMIN'); -- test +-- update hs_hosting_asset set caption='lug00 b' where identifier = 'lug00' and type = 'MANAGED_WEBSPACE'; -- prod +-- update hs_hosting_asset set caption='hsh00 A ' || now()::text where identifier = 'hsh00' and type = 'MANAGED_WEBSPACE'; -- test +-- update hs_hosting_asset set caption='hsh00 B ' || now()::text where identifier = 'hsh00' and type = 'MANAGED_WEBSPACE'; -- test -CREATE TYPE "operation" AS ENUM ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE'); +-- insert into hs_hosting_asset +-- (uuid, bookingitemuuid, type, parentassetuuid, assignedtoassetuuid, identifier, caption, config, alarmcontactuuid) +-- values +-- (uuid_generate_v4(), null, 'EMAIL_ADDRESS', 'bbda5895-0569-4e20-bb4c-34f3a38f3f63'::uuid, null, +-- 'new@thi.example.org', 'some new E-Mail-Address', '{}'::jsonb, null); --- see https://www.postgresql.org/docs/current/plpgsql-trigger.html +delete from hs_hosting_asset where uuid='5aea68d2-3b55-464f-8362-b05c76c5a681'::uuid; +commit; -CREATE OR REPLACE FUNCTION historicize() - RETURNS trigger - LANGUAGE plpgsql STRICT AS $$ -DECLARE - currentUser VARCHAR(63); - currentTask VARCHAR(127); - "row" RECORD; - "alive" BOOLEAN; - "sql" varchar; -BEGIN - -- determine user_id -BEGIN - currentUser := current_setting('hsadminng.currentUser'); -EXCEPTION WHEN OTHERS THEN - currentUser := NULL; -END; - IF (currentUser IS NULL OR currentUser = '') THEN - RAISE EXCEPTION 'hsadminng.currentUser must be defined, please use "SET LOCAL ...;"'; -END IF; - RAISE NOTICE 'currentUser: %', currentUser; +-- single version at point in time +-- set hsadminng.tx_history_txid to (select max(txid) from tx_context where txtimestamp<='2024-08-27 12:13:13.450821'); +set hsadminng.tx_history_txid to ''; +set hsadminng.tx_history_timestamp to '2024-08-29 12:42'; +-- all versions +select tx_history_txid(), txc.txtimestamp, txc.currentUser, txc.currentTask, haex.* + from hs_hosting_asset_ex haex + join tx_context txc on haex.txid=txc.txid + where haex.identifier = 'test@thi.example.org'; - -- determine task - currentTask = current_setting('hsadminng.currentTask'); - assert currentTask IS NOT NULL AND length(currentTask) >= 12, - format('hsadminng.currentTask (%s) must be defined and min 12 characters long, please use "SET LOCAL ...;"', currentTask); - assert length(currentTask) <= 127, - format('hsadminng.currentTask (%s) must not be longer than 127 characters"', currentTask); +select uuid, version, type, identifier, caption from hs_hosting_asset_hv p where identifier = 'test@thi.example.org'; - IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN - "row" := NEW; - "alive" := TRUE; - ELSE -- DELETE or TRUNCATE - "row" := OLD; - "alive" := FALSE; - END IF; +select pg_current_xact_id(); - sql := format('INSERT INTO tx_history VALUES (txid_current(), now(), %1L, %2L) ON CONFLICT DO NOTHING', currentUser, currentTask); - RAISE NOTICE 'sql: %', sql; - EXECUTE sql; - sql := format('INSERT INTO %3$I_versions VALUES (DEFAULT, txid_current(), %1$L, %2$L, $1.*)', TG_OP, alive, TG_TABLE_NAME); - RAISE NOTICE 'sql: %', sql; - EXECUTE sql USING "row"; - - RETURN "row"; -END; $$; - -CREATE OR REPLACE PROCEDURE create_historical_view(baseTable varchar) - LANGUAGE plpgsql AS $$ -DECLARE -createTriggerSQL varchar; - viewName varchar; - versionsTable varchar; - createViewSQL varchar; - baseCols varchar; -BEGIN - - viewName = quote_ident(format('%s_hv', baseTable)); - versionsTable = quote_ident(format('%s_versions', baseTable)); - baseCols = (SELECT string_agg(quote_ident(column_name), ', ') - FROM information_schema.columns - WHERE table_schema = 'public' AND table_name = baseTable); - - createViewSQL = format( - 'CREATE OR REPLACE VIEW %1$s AS' || - '(' || - ' SELECT %2$s' || - ' FROM %3$s' || - ' WHERE alive = TRUE' || - ' AND version_id IN' || - ' (' || - ' SELECT max(vt.version_id) AS history_id' || - ' FROM %3$s AS vt' || - ' JOIN tx_history as txh ON vt.tx_id = txh.tx_id' || - ' WHERE txh.tx_timestamp <= current_setting(''hsadminng.timestamp'')::timestamp' || - ' GROUP BY id' || - ' )' || - ')', - viewName, baseCols, versionsTable - ); - RAISE NOTICE 'sql: %', createViewSQL; -EXECUTE createViewSQL; - -createTriggerSQL = 'CREATE TRIGGER ' || baseTable || '_historicize' || - ' AFTER INSERT OR DELETE OR UPDATE ON ' || baseTable || - ' FOR EACH ROW EXECUTE PROCEDURE historicize()'; - RAISE NOTICE 'sql: %', createTriggerSQL; -EXECUTE createTriggerSQL; - -END; $$; - -CREATE OR REPLACE PROCEDURE create_historicization(baseTable varchar) - LANGUAGE plpgsql AS $$ -DECLARE - createHistTableSql varchar; - createTriggerSQL varchar; - viewName varchar; - versionsTable varchar; - createViewSQL varchar; - baseCols varchar; -BEGIN - - -- create the history table - createHistTableSql = '' || - 'CREATE TABLE ' || baseTable || '_versions (' || - ' version_id serial PRIMARY KEY,' || - ' tx_id bigint NOT NULL REFERENCES tx_history(tx_id),' || - ' trigger_op operation NOT NULL,' || - ' alive boolean not null,' || - - ' LIKE ' || baseTable || - ' EXCLUDING CONSTRAINTS' || - ' EXCLUDING STATISTICS' || - ')'; - RAISE NOTICE 'sql: %', createHistTableSql; - EXECUTE createHistTableSql; - - -- create the historical view - viewName = quote_ident(format('%s_hv', baseTable)); - versionsTable = quote_ident(format('%s_versions', baseTable)); - baseCols = (SELECT string_agg(quote_ident(column_name), ', ') - FROM information_schema.columns - WHERE table_schema = 'public' AND table_name = baseTable); - - createViewSQL = format( - 'CREATE OR REPLACE VIEW %1$s AS' || - '(' || - ' SELECT %2$s' || - ' FROM %3$s' || - ' WHERE alive = TRUE' || - ' AND version_id IN' || - ' (' || - ' SELECT max(vt.version_id) AS history_id' || - ' FROM %3$s AS vt' || - ' JOIN tx_history as txh ON vt.tx_id = txh.tx_id' || - ' WHERE txh.tx_timestamp <= current_setting(''hsadminng.timestamp'')::timestamp' || - ' GROUP BY id' || - ' )' || - ')', - viewName, baseCols, versionsTable - ); - RAISE NOTICE 'sql: %', createViewSQL; - EXECUTE createViewSQL; - - createTriggerSQL = 'CREATE TRIGGER ' || baseTable || '_historicize' || - ' AFTER INSERT OR DELETE OR UPDATE ON ' || baseTable || - ' FOR EACH ROW EXECUTE PROCEDURE historicize()'; - RAISE NOTICE 'sql: %', createTriggerSQL; - EXECUTE createTriggerSQL; - -END; $$; diff --git a/src/main/resources/db/changelog/0-basis/020-audit-log.sql b/src/main/resources/db/changelog/0-basis/020-audit-log.sql index 4c2826e3..c231814c 100644 --- a/src/main/resources/db/changelog/0-basis/020-audit-log.sql +++ b/src/main/resources/db/changelog/0-basis/020-audit-log.sql @@ -23,13 +23,12 @@ do $$ */ create table tx_context ( - contextId bigint primary key not null, - txId bigint not null, - txTimestamp timestamp not null, - currentUser varchar(63) not null, -- not the uuid, because users can be deleted - assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted - currentTask varchar(127) not null, - currentRequest text not null + txId xid8 primary key not null, + txTimestamp timestamp not null, + currentUser varchar(63) not null, -- not the uuid, because users can be deleted + assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted + currentTask varchar(127) not null, + currentRequest text not null ); create index on tx_context using brin (txTimestamp); @@ -43,7 +42,7 @@ create index on tx_context using brin (txTimestamp); */ create table tx_journal ( - contextId bigint not null references tx_context (contextId), + txId xid8 not null references tx_context (txId), targetTable text not null, targetUuid uuid not null, -- Assumes that all audited tables have a uuid column. targetOp operation not null, @@ -62,7 +61,7 @@ create index on tx_journal (targetTable, targetUuid); create view tx_journal_v as select txc.*, txj.targettable, txj.targetop, txj.targetuuid, txj.targetdelta from tx_journal txj - left join tx_context txc using (contextid) + left join tx_context txc using (txId) order by txc.txtimestamp; --// @@ -77,31 +76,31 @@ create or replace function tx_journal_trigger() language plpgsql as $$ declare curTask text; - curContextId bigint; + curTxId xid8; begin curTask := currentTask(); - curContextId := txid_current()+bigIntHash(curTask); + curTxId := pg_current_xact_id(); insert - into tx_context (contextId, txId, txTimestamp, currentUser, assumedRoles, currentTask, currentRequest) - values (curContextId, txid_current(), now(), - currentUser(), assumedRoles(), curTask, currentRequest()) + into tx_context (txId, txTimestamp, currentUser, assumedRoles, currentTask, currentRequest) + values ( curTxId, now(), + currentUser(), assumedRoles(), curTask, currentRequest()) on conflict do nothing; case tg_op when 'INSERT' then insert into tx_journal - values (curContextId, + values (curTxId, tg_table_name, new.uuid, tg_op::operation, to_jsonb(new)); when 'UPDATE' then insert into tx_journal - values (curContextId, + values (curTxId, tg_table_name, old.uuid, tg_op::operation, jsonb_changes_delta(to_jsonb(old), to_jsonb(new))); when 'DELETE' then insert into tx_journal - values (curContextId, + values (curTxId, tg_table_name, old.uuid, 'DELETE'::operation, null::jsonb); else raise exception 'Trigger op % not supported for %.', tg_op, tg_table_name; diff --git a/src/main/resources/db/changelog/0-basis/030-historization.sql b/src/main/resources/db/changelog/0-basis/030-historization.sql new file mode 100644 index 00000000..709cb9c8 --- /dev/null +++ b/src/main/resources/db/changelog/0-basis/030-historization.sql @@ -0,0 +1,160 @@ +--liquibase formatted sql + +-- ============================================================================ +--changeset hs-global-historization-tx-history-txid:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +create or replace function tx_history_txid() + returns xid8 stable + language plpgsql as $$ +declare + historicalTxIdSetting text; + historicalTimestampSetting text; + historicalTxId xid8; + historicalTimestamp timestamp; +begin + select coalesce(current_setting('hsadminng.tx_history_txid', true), '') into historicalTxIdSetting; + select coalesce(current_setting('hsadminng.tx_history_timestamp', true), '') into historicalTimestampSetting; + if historicalTxIdSetting > '' and historicalTimestampSetting > '' then + raise exception 'either hsadminng.tx_history_txid or hsadminng.tx_history_timestamp must be set, but both are set: (%, %)', + historicalTxIdSetting, historicalTimestampSetting; + end if; + if historicalTxIdSetting = '' and historicalTimestampSetting = '' then + raise exception 'either hsadminng.tx_history_txid or hsadminng.tx_history_timestamp must be set, but both are unset or empty: (%, %)', + historicalTxIdSetting, historicalTimestampSetting; + end if; + -- just for debugging / making sure the function is only called once per query + -- raise notice 'tx_history_txid() called with: (%, %)', historicalTxIdSetting, historicalTimestampSetting; + + if historicalTxIdSetting is null or historicalTxIdSetting = '' then + select historicalTimestampSetting::timestamp into historicalTimestamp; + select max(txc.txid) from tx_context txc where txc.txtimestamp <= historicalTimestamp into historicalTxId; + else + historicalTxId = historicalTxIdSetting::xid8; + end if; + return historicalTxId; +end; $$; +--// + + +-- ============================================================================ +--changeset hs-global-historization-tx-historicize-tf:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + +create type "tx_operation" as enum ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE'); + +create or replace function tx_historicize_tf() + returns trigger + language plpgsql + strict as $$ +declare + currentUser varchar(63); + currentTask varchar(127); + "row" record; + "alive" boolean; + "sql" varchar; +begin + -- determine user_id + begin + currentUser := current_setting('hsadminng.currentUser'); + exception + when others then + currentUser := null; + end; + if (currentUser is null or currentUser = '') then + raise exception 'hsadminng.currentUser must be defined, please use "SET LOCAL ...;"'; + end if; + raise notice 'currentUser: %', currentUser; + + -- determine task + currentTask = current_setting('hsadminng.currentTask'); + assert currentTask is not null and length(currentTask) >= 12, + format('hsadminng.currentTask (%s) must be defined and min 12 characters long, please use "SET LOCAL ...;"', + currentTask); + assert length(currentTask) <= 127, + format('hsadminng.currentTask (%s) must not be longer than 127 characters"', currentTask); + + if (TG_OP = 'INSERT') or (TG_OP = 'UPDATE') then + "row" := NEW; + "alive" := true; + else -- DELETE or TRUNCATE + "row" := OLD; + "alive" := false; + end if; + + sql := format('INSERT INTO %3$I_ex VALUES (DEFAULT, pg_current_xact_id(), %1$L, %2$L, $1.*)', TG_OP, alive, TG_TABLE_NAME); + raise notice 'sql: %', sql; + execute sql using "row"; + + return "row"; +end; $$; +--// + + +-- ============================================================================ +--changeset hs-global-historization-tx-create-historicization:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- + + +create or replace procedure tx_create_historicization(baseTable varchar) + language plpgsql as $$ +declare + createHistTableSql varchar; + createTriggerSQL varchar; + viewName varchar; + exVersionsTable varchar; + createViewSQL varchar; + baseCols varchar; +begin + + -- create the history table + createHistTableSql = '' || + 'CREATE TABLE ' || baseTable || '_ex (' || + ' version_id serial PRIMARY KEY,' || + ' txid xid8 NOT NULL REFERENCES tx_context(txid),' || + ' trigger_op tx_operation NOT NULL,' || + ' alive boolean not null,' || + ' LIKE ' || baseTable || + ' EXCLUDING CONSTRAINTS' || + ' EXCLUDING STATISTICS' || + ')'; + raise notice 'sql: %', createHistTableSql; + execute createHistTableSql; + + -- create the historical view + viewName = quote_ident(format('%s_hv', baseTable)); + exVersionsTable = quote_ident(format('%s_ex', baseTable)); + baseCols = (select string_agg(quote_ident(column_name), ', ') + from information_schema.columns + where table_schema = 'public' + and table_name = baseTable); + + createViewSQL = format( + 'CREATE OR REPLACE VIEW %1$s AS' || + '(' || + -- make sure the function is only called once, not for every matching row in tx_context + ' WITH txh AS (SELECT tx_history_txid() AS txid) ' || + ' SELECT %2$s' || + ' FROM %3$s' || + ' WHERE alive = TRUE' || + ' AND version_id IN' || + ' (' || + ' SELECT max(ex.version_id) AS history_id' || + ' FROM %3$s AS ex' || + ' JOIN tx_context as txc ON ex.txid = txc.txid' || + ' WHERE txc.txid <= (SELECT txid FROM txh)' || + ' GROUP BY uuid' || + ' )' || + ')', + viewName, baseCols, exVersionsTable + ); + raise notice 'sql: %', createViewSQL; + execute createViewSQL; + + createTriggerSQL = 'CREATE TRIGGER ' || baseTable || '_tx_historicize_tg' || + ' AFTER INSERT OR DELETE OR UPDATE ON ' || baseTable || + ' FOR EACH ROW EXECUTE PROCEDURE tx_historicize_tf()'; + raise notice 'sql: %', createTriggerSQL; + execute createTriggerSQL; + +end; $$; +--// diff --git a/src/main/resources/db/changelog/2-test/201-test-customer/2018-test-customer-test-data.sql b/src/main/resources/db/changelog/2-test/201-test-customer/2018-test-customer-test-data.sql index 73c8e535..f05cbafb 100644 --- a/src/main/resources/db/changelog/2-test/201-test-customer/2018-test-customer-test-data.sql +++ b/src/main/resources/db/changelog/2-test/201-test-customer/2018-test-customer-test-data.sql @@ -25,16 +25,11 @@ create or replace procedure createTestCustomerTestData( ) language plpgsql as $$ declare - currentTask varchar; custRowId uuid; custAdminName varchar; custAdminUuid uuid; newCust test_customer; begin - currentTask = 'creating RBAC test customer #' || custReference || '/' || custPrefix; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); - custRowId = uuid_generate_v4(); custAdminName = 'customer-admin@' || custPrefix || '.example.com'; custAdminUuid = createRbacUser(custAdminName); @@ -77,6 +72,8 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating RBAC test customer', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createTestCustomerTestData(99901, 'xxx'); call createTestCustomerTestData(99902, 'yyy'); call createTestCustomerTestData(99903, 'zzz'); diff --git a/src/main/resources/db/changelog/2-test/202-test-package/2028-test-package-test-data.sql b/src/main/resources/db/changelog/2-test/202-test-package/2028-test-package-test-data.sql index f50ad480..bf4a9f3b 100644 --- a/src/main/resources/db/changelog/2-test/202-test-package/2028-test-package-test-data.sql +++ b/src/main/resources/db/changelog/2-test/202-test-package/2028-test-package-test-data.sql @@ -13,7 +13,6 @@ declare custAdminUser varchar; custAdminRole varchar; pacName varchar; - currentTask varchar; pac test_package; begin select * from test_customer where test_customer.prefix = customerPrefix into cust; @@ -21,13 +20,9 @@ begin for t in 0..(pacCount-1) loop pacName = cust.prefix || to_char(t, 'fm00'); - currentTask = 'creating RBAC test package #' || pacName || ' for customer ' || cust.prefix || ' #' || - cust.uuid; - custAdminUser = 'customer-admin@' || cust.prefix || '.example.com'; custAdminRole = 'test_customer#' || cust.prefix || ':ADMIN'; - call defineContext(currentTask, null, 'superuser-fran@hostsharing.net', custAdminRole); - raise notice 'task: % by % as %', currentTask, custAdminUser, custAdminRole; + call defineContext('creating RBAC test package', null, 'superuser-fran@hostsharing.net', custAdminRole); insert into test_package (customerUuid, name, description) diff --git a/src/main/resources/db/changelog/2-test/203-test-domain/2038-test-domain-test-data.sql b/src/main/resources/db/changelog/2-test/203-test-domain/2038-test-domain-test-data.sql index 47326f49..e2aa870f 100644 --- a/src/main/resources/db/changelog/2-test/203-test-domain/2038-test-domain-test-data.sql +++ b/src/main/resources/db/changelog/2-test/203-test-domain/2038-test-domain-test-data.sql @@ -11,7 +11,6 @@ create or replace procedure createdomainTestData( packageName varchar, domainCou declare pac record; pacAdmin varchar; - currentTask varchar; begin select p.uuid, p.name, c.prefix as custPrefix from test_package p @@ -21,10 +20,8 @@ begin for t in 0..(domainCount-1) loop - currentTask = 'creating RBAC test domain #' || t || ' for package ' || pac.name || ' #' || pac.uuid; - raise notice 'task: %', currentTask; pacAdmin = 'pac-admin-' || pac.name || '@' || pac.custPrefix || '.example.com'; - call defineContext(currentTask, null, pacAdmin, null); + call defineContext('creating RBAC test domain', null, pacAdmin, null); insert into test_domain (name, packageUuid) diff --git a/src/main/resources/db/changelog/5-hs-office/501-contact/5018-hs-office-contact-test-data.sql b/src/main/resources/db/changelog/5-hs-office/501-contact/5018-hs-office-contact-test-data.sql index 3504eaaa..fbee80ad 100644 --- a/src/main/resources/db/changelog/5-hs-office/501-contact/5018-hs-office-contact-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/501-contact/5018-hs-office-contact-test-data.sql @@ -11,17 +11,13 @@ create or replace procedure createHsOfficeContactTestData(contCaption varchar) language plpgsql as $$ declare - currentTask varchar; postalAddr varchar; emailAddr varchar; begin - currentTask = 'creating contact test-data ' || contCaption; - execute format('set local hsadminng.currentTask to %L', currentTask); - emailAddr = 'contact-admin@' || cleanIdentifier(contCaption) || '.example.com'; - call defineContext(currentTask); + call defineContext('creating contact test-data'); perform createRbacUser(emailAddr); - call defineContext(currentTask, null, emailAddr); + call defineContext('creating contact test-data', null, emailAddr); postalAddr := E'Vorname Nachname\nStraße Hnr\nPLZ Stadt'; diff --git a/src/main/resources/db/changelog/5-hs-office/502-person/5028-hs-office-person-test-data.sql b/src/main/resources/db/changelog/5-hs-office/502-person/5028-hs-office-person-test-data.sql index 775ecaa6..8900886c 100644 --- a/src/main/resources/db/changelog/5-hs-office/502-person/5028-hs-office-person-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/502-person/5028-hs-office-person-test-data.sql @@ -17,16 +17,13 @@ create or replace procedure createHsOfficePersonTestData( language plpgsql as $$ declare fullName varchar; - currentTask varchar; emailAddr varchar; begin fullName := concat_ws(', ', newTradeName, newFamilyName, newGivenName); - currentTask = 'creating person test-data ' || fullName; emailAddr = 'person-' || left(cleanIdentifier(fullName), 32) || '@example.com'; - call defineContext(currentTask); + call defineContext('creating person test-data'); perform createRbacUser(emailAddr); - call defineContext(currentTask, null, emailAddr); - execute format('set local hsadminng.currentTask to %L', currentTask); + call defineContext('creating person test-data', null, emailAddr); raise notice 'creating test person: % by %', fullName, emailAddr; insert diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql index cff9f3f3..120ffe62 100644 --- a/src/main/resources/db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5038-hs-office-relation-test-data.sql @@ -16,7 +16,6 @@ create or replace procedure createHsOfficeRelationTestData( mark varchar default null) language plpgsql as $$ declare - currentTask varchar; idName varchar; anchorPerson hs_office_person; holderPerson hs_office_person; @@ -24,9 +23,6 @@ declare begin idName := cleanIdentifier( anchorPersonName || '-' || holderPersonName); - currentTask := 'creating relation test-data ' || idName; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); select p.* into anchorPerson @@ -89,6 +85,8 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating relation test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createHsOfficeRelationTestData('First GmbH', 'PARTNER', 'Hostsharing eG', 'first contact'); call createHsOfficeRelationTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact'); call createHsOfficeRelationTestData('First GmbH', 'DEBITOR', 'First GmbH', 'first contact'); diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5048-hs-office-partner-test-data.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5048-hs-office-partner-test-data.sql index 4b63b8c2..4ac1dff9 100644 --- a/src/main/resources/db/changelog/5-hs-office/504-partner/5048-hs-office-partner-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5048-hs-office-partner-test-data.sql @@ -15,7 +15,6 @@ create or replace procedure createHsOfficePartnerTestData( contactCaption varchar ) language plpgsql as $$ declare - currentTask varchar; idName varchar; mandantPerson hs_office_person; partnerRel hs_office_relation; @@ -23,9 +22,6 @@ declare relatedDetailsUuid uuid; begin idName := cleanIdentifier( partnerPersonName|| '-' || contactCaption); - currentTask := 'creating partner test-data ' || idName; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); select p.* from hs_office_person p where p.tradeName = mandantTradeName @@ -69,13 +65,14 @@ end; $$; --// - -- ============================================================================ --changeset hs-office-partner-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--// -- ---------------------------------------------------------------------------- do language plpgsql $$ begin + call defineContext('creating partner test-data ', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createHsOfficePartnerTestData('Hostsharing eG', 10001, 'First GmbH', 'first contact'); call createHsOfficePartnerTestData('Hostsharing eG', 10002, 'Second e.K.', 'second contact'); call createHsOfficePartnerTestData('Hostsharing eG', 10003, 'Third OHG', 'third contact'); diff --git a/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5058-hs-office-bankaccount-test-data.sql b/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5058-hs-office-bankaccount-test-data.sql index 1fe73c71..338ab61c 100644 --- a/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5058-hs-office-bankaccount-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/505-bankaccount/5058-hs-office-bankaccount-test-data.sql @@ -11,16 +11,11 @@ create or replace procedure createHsOfficeBankAccountTestData(givenHolder varchar, givenIBAN varchar, givenBIC varchar) language plpgsql as $$ declare - currentTask varchar; emailAddr varchar; begin - currentTask = 'creating bankaccount test-data ' || givenHolder; - execute format('set local hsadminng.currentTask to %L', currentTask); - emailAddr = 'bankaccount-admin@' || cleanIdentifier(givenHolder) || '.example.com'; - call defineContext(currentTask); perform createRbacUser(emailAddr); - call defineContext(currentTask, null, emailAddr); + call defineContext('creating bankaccount test-data', null, emailAddr); raise notice 'creating test bankaccount: %', givenHolder; insert @@ -36,6 +31,8 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating bankaccount test-data'); + -- IBANs+BICs taken from https://ibanvalidieren.de/beispiele.html call createHsOfficeBankAccountTestData('First GmbH', 'DE02120300000000202051', 'BYLADEM1001'); call createHsOfficeBankAccountTestData('Peter Smith', 'DE02500105170137075030', 'INGDDEFF'); diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql index 2e888e29..da9a5f2e 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql @@ -16,15 +16,11 @@ create or replace procedure createHsOfficeDebitorTestData( ) language plpgsql as $$ declare - currentTask varchar; idName varchar; relatedDebitorRelUuid uuid; relatedBankAccountUuid uuid; begin idName := cleanIdentifier( forPartnerPersonName|| '-' || forBillingContactCaption); - currentTask := 'creating debitor test-data ' || idName; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); select debitorRel.uuid into relatedDebitorRelUuid @@ -54,6 +50,8 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating debitor test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createHsOfficeDebitorTestData(11, 'First GmbH', 'first contact', 'fir'); call createHsOfficeDebitorTestData(12, 'Second e.K.', 'second contact', 'sec'); call createHsOfficeDebitorTestData(13, 'Third OHG', 'third contact', 'thi'); diff --git a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql index e664d8c5..6c8aa15e 100644 --- a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5078-hs-office-sepamandate-test-data.sql @@ -15,14 +15,9 @@ create or replace procedure createHsOfficeSepaMandateTestData( withReference varchar) language plpgsql as $$ declare - currentTask varchar; relatedDebitor hs_office_debitor; relatedBankAccount hs_office_bankAccount; begin - currentTask := 'creating SEPA-mandate test-data ' || forPartnerNumber::text || forDebitorSuffix::text; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); - select debitor.* into relatedDebitor from hs_office_debitor debitor join hs_office_relation debitorRel on debitorRel.uuid = debitor.debitorRelUuid @@ -48,6 +43,8 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating SEPA-mandate test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createHsOfficeSepaMandateTestData(10001, '11', 'DE02120300000000202051', 'ref-10001-11'); call createHsOfficeSepaMandateTestData(10002, '12', 'DE02100500000054540402', 'ref-10002-12'); call createHsOfficeSepaMandateTestData(10003, '13', 'DE02300209000106531065', 'ref-10003-13'); diff --git a/src/main/resources/db/changelog/5-hs-office/510-membership/5108-hs-office-membership-test-data.sql b/src/main/resources/db/changelog/5-hs-office/510-membership/5108-hs-office-membership-test-data.sql index b8cbb45b..205efcc9 100644 --- a/src/main/resources/db/changelog/5-hs-office/510-membership/5108-hs-office-membership-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/510-membership/5108-hs-office-membership-test-data.sql @@ -13,15 +13,8 @@ create or replace procedure createHsOfficeMembershipTestData( newMemberNumberSuffix char(2) ) language plpgsql as $$ declare - currentTask varchar; relatedPartner hs_office_partner; begin - currentTask := 'creating Membership test-data ' || - 'P-' || forPartnerNumber::text || - 'M-...' || newMemberNumberSuffix; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); - select partner.* from hs_office_partner partner where partner.partnerNumber = forPartnerNumber into relatedPartner; @@ -40,6 +33,8 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating Membership test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createHsOfficeMembershipTestData(10001, '01'); call createHsOfficeMembershipTestData(10002, '02'); call createHsOfficeMembershipTestData(10003, '03'); diff --git a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql index 21d266ac..4efb55db 100644 --- a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5118-hs-office-coopshares-test-data.sql @@ -14,15 +14,9 @@ create or replace procedure createHsOfficeCoopSharesTransactionTestData( ) language plpgsql as $$ declare - currentTask varchar; membership hs_office_membership; subscriptionEntryUuid uuid; begin - currentTask = 'creating coopSharesTransaction test-data ' || givenPartnerNumber::text || givenMemberNumberSuffix; - execute format('set local hsadminng.currentTask to %L', currentTask); - SET CONSTRAINTS ALL DEFERRED; - - call defineContext(currentTask); select m.uuid from hs_office_membership m join hs_office_partner p on p.uuid = m.partneruuid @@ -49,6 +43,9 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating coopSharesTransaction test-data'); + SET CONSTRAINTS ALL DEFERRED; + call createHsOfficeCoopSharesTransactionTestData(10001, '01'); call createHsOfficeCoopSharesTransactionTestData(10002, '02'); call createHsOfficeCoopSharesTransactionTestData(10003, '03'); diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql index 1eda1de6..b3cdab98 100644 --- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql @@ -14,15 +14,9 @@ create or replace procedure createHsOfficeCoopAssetsTransactionTestData( ) language plpgsql as $$ declare - currentTask varchar; membership hs_office_membership; lossEntryUuid uuid; begin - currentTask = 'creating coopAssetsTransaction test-data ' || givenPartnerNumber || givenMemberNumberSuffix; - execute format('set local hsadminng.currentTask to %L', currentTask); - SET CONSTRAINTS ALL DEFERRED; - - call defineContext(currentTask); select m.uuid from hs_office_membership m join hs_office_partner p on p.uuid = m.partneruuid @@ -49,6 +43,9 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating coopAssetsTransaction test-data'); + SET CONSTRAINTS ALL DEFERRED; + call createHsOfficeCoopAssetsTransactionTestData(10001, '01'); call createHsOfficeCoopAssetsTransactionTestData(10002, '02'); call createHsOfficeCoopAssetsTransactionTestData(10003, '03'); diff --git a/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6200-hs-booking-project.sql b/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6200-hs-booking-project.sql index 41fc650a..564e36c0 100644 --- a/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6200-hs-booking-project.sql +++ b/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6200-hs-booking-project.sql @@ -20,3 +20,10 @@ create table if not exists hs_booking_project call create_journal('hs_booking_project'); --// + + +-- ============================================================================ +--changeset hs-booking-project-MAIN-TABLE-HISTORIZATION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call tx_create_historicization('hs_booking_project'); +--// diff --git a/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6208-hs-booking-project-test-data.sql b/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6208-hs-booking-project-test-data.sql index 5ebae299..2113ae5e 100644 --- a/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6208-hs-booking-project-test-data.sql +++ b/src/main/resources/db/changelog/6-hs-booking/620-booking-project/6208-hs-booking-project-test-data.sql @@ -14,12 +14,8 @@ create or replace procedure createHsBookingProjectTransactionTestData( ) language plpgsql as $$ declare - currentTask varchar; relatedDebitor hs_office_debitor; begin - currentTask := 'creating booking-project test-data ' || givenPartnerNumber::text || givenDebitorSuffix; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); select debitor.* into relatedDebitor from hs_office_debitor debitor @@ -43,6 +39,8 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating booking-project test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createHsBookingProjectTransactionTestData(10001, '11'); call createHsBookingProjectTransactionTestData(10002, '12'); call createHsBookingProjectTransactionTestData(10003, '13'); diff --git a/src/main/resources/db/changelog/6-hs-booking/630-booking-item/6200-hs-booking-item.sql b/src/main/resources/db/changelog/6-hs-booking/630-booking-item/6200-hs-booking-item.sql index 6c76c29f..33a93c48 100644 --- a/src/main/resources/db/changelog/6-hs-booking/630-booking-item/6200-hs-booking-item.sql +++ b/src/main/resources/db/changelog/6-hs-booking/630-booking-item/6200-hs-booking-item.sql @@ -36,3 +36,11 @@ create table if not exists hs_booking_item call create_journal('hs_booking_item'); --// + + +-- ============================================================================ +--changeset hs-booking-item-MAIN-TABLE-HISTORIZATION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call tx_create_historicization('hs_booking_item'); +--// + diff --git a/src/main/resources/db/changelog/6-hs-booking/630-booking-item/6208-hs-booking-item-test-data.sql b/src/main/resources/db/changelog/6-hs-booking/630-booking-item/6208-hs-booking-item-test-data.sql index 94c2e665..4052b5c3 100644 --- a/src/main/resources/db/changelog/6-hs-booking/630-booking-item/6208-hs-booking-item-test-data.sql +++ b/src/main/resources/db/changelog/6-hs-booking/630-booking-item/6208-hs-booking-item-test-data.sql @@ -14,15 +14,10 @@ create or replace procedure createHsBookingItemTransactionTestData( ) language plpgsql as $$ declare - currentTask varchar; relatedProject hs_booking_project; privateCloudUuid uuid; managedServerUuid uuid; begin - currentTask := 'creating booking-item test-data ' || givenPartnerNumber::text || givenDebitorSuffix; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); - select project.* into relatedProject from hs_booking_project project where project.caption = 'D-' || givenPartnerNumber || givenDebitorSuffix || ' default project'; @@ -49,7 +44,11 @@ end; $$; -- ---------------------------------------------------------------------------- do language plpgsql $$ + declare + currentTask text; begin + call defineContext('creating booking-item test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createHsBookingItemTransactionTestData(10001, '11'); call createHsBookingItemTransactionTestData(10002, '12'); call createHsBookingItemTransactionTestData(10003, '13'); diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql index 2586781e..83d6cacb 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7010-hs-hosting-asset.sql @@ -166,6 +166,14 @@ execute procedure hs_hosting_asset_booking_item_hierarchy_check_tf(); -- ============================================================================ --changeset hs-hosting-asset-MAIN-TABLE-JOURNAL:1 endDelimiter:--// -- ---------------------------------------------------------------------------- - call create_journal('hs_hosting_asset'); --// + + +-- ============================================================================ +--changeset hs-hosting-asset-MAIN-TABLE-HISTORIZATION:1 endDelimiter:--// +-- ---------------------------------------------------------------------------- +call tx_create_historicization('hs_hosting_asset'); +--// + + diff --git a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql index a74b6126..0af7e38e 100644 --- a/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql +++ b/src/main/resources/db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql @@ -11,7 +11,6 @@ create or replace procedure createHsHostingAssetTestData(givenProjectCaption varchar) language plpgsql as $$ declare - currentTask varchar; relatedProject hs_booking_project; relatedDebitor hs_office_debitor; privateCloudBI hs_booking_item; @@ -31,9 +30,7 @@ declare pgSqlInstanceUuid uuid; PgSqlUserUuid uuid; begin - currentTask := 'creating hosting-asset test-data ' || givenProjectCaption; - call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); - execute format('set local hsadminng.currentTask to %L', currentTask); + call defineContext('creating hosting-asset test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); select project.* into relatedProject from hs_booking_project project @@ -113,6 +110,8 @@ end; $$; do language plpgsql $$ begin + call defineContext('creating hosting-asset test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN'); + call createHsHostingAssetTestData('D-1000111 default project'); call createHsHostingAssetTestData('D-1000212 default project'); call createHsHostingAssetTestData('D-1000313 default project'); diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 8771ae81..17d4d40a 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -21,6 +21,8 @@ databaseChangeLog: file: db/changelog/0-basis/010-context.sql - include: file: db/changelog/0-basis/020-audit-log.sql + - include: + file: db/changelog/0-basis/030-historization.sql - include: file: db/changelog/0-basis/090-log-slow-queries-extensions.sql - include: @@ -152,4 +154,4 @@ databaseChangeLog: - include: file: db/changelog/7-hs-hosting/701-hosting-asset/7018-hs-hosting-asset-test-data.sql - include: - file: db/changelog/9-hs-global/9000-statistics.sql + file: db/changelog/9-hs-global/9000-statistics.sql diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java index 0a40aabf..ca931e44 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/item/HsBookingItemRepositoryIntegrationTest.java @@ -20,7 +20,9 @@ import org.springframework.orm.jpa.JpaSystemException; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.servlet.http.HttpServletRequest; +import java.sql.Timestamp; import java.time.LocalDate; +import java.time.ZonedDateTime; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -62,6 +64,54 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup @MockBean HttpServletRequest request; + @Test + public void auditJournalLogIsAvailable() { + // given + final var query = em.createNativeQuery(""" + select currentTask, targetTable, targetOp, targetdelta->>'caption' + from tx_journal_v + where targettable = 'hs_booking_item'; + """); + + // when + @SuppressWarnings("unchecked") final List customerLogEntries = query.getResultList(); + + // then + assertThat(customerLogEntries).map(Arrays::toString).contains( + "[creating booking-item test-data, hs_booking_item, INSERT, prod CloudServer]", + "[creating booking-item test-data, hs_booking_item, INSERT, separate ManagedServer]", + "[creating booking-item test-data, hs_booking_item, INSERT, separate ManagedWebspace]", + "[creating booking-item test-data, hs_booking_item, INSERT, some ManagedServer]", + "[creating booking-item test-data, hs_booking_item, INSERT, some ManagedWebspace]", + "[creating booking-item test-data, hs_booking_item, INSERT, some PrivateCloud]", + "[creating booking-item test-data, hs_booking_item, INSERT, test CloudServer]"); + } + + @Test + public void historizationIsAvailable() { + // given + final String nativeQuerySql = """ + select count(*) + from hs_booking_item_hv ha; + """; + + // when + historicalContext(Timestamp.from(ZonedDateTime.now().minusDays(1).toInstant())); + final var query = em.createNativeQuery(nativeQuerySql, Integer.class); + @SuppressWarnings("unchecked") final var countBefore = (Integer) query.getSingleResult(); + + // then + assertThat(countBefore).as("hs_booking_item should not contain rows for a timestamp in the past").isEqualTo(0); + + // and when + historicalContext(Timestamp.from(ZonedDateTime.now().plusHours(1).toInstant())); + em.createNativeQuery(nativeQuerySql, Integer.class); + @SuppressWarnings("unchecked") final var countAfter = (Integer) query.getSingleResult(); + + // then + assertThat(countAfter).as("hs_booking_item should contain rows for a timestamp in the future").isGreaterThan(1); + } + @Nested class CreateBookingItem { @@ -304,25 +354,6 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup } } - @Test - public void auditJournalLogIsAvailable() { - // given - final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp - from tx_journal_v - where targettable = 'hs_booking_item'; - """); - - // when - @SuppressWarnings("unchecked") final List customerLogEntries = query.getResultList(); - - // then - assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating booking-item test-data 1000111, hs_booking_item, INSERT]", - "[creating booking-item test-data 1000212, hs_booking_item, INSERT]", - "[creating booking-item test-data 1000313, hs_booking_item, INSERT]"); - } - private HsBookingItem givenSomeTemporaryBookingItem(final String projectCaption) { return jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java index b03b6c76..b3a05ffa 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/booking/project/HsBookingProjectRepositoryIntegrationTest.java @@ -20,6 +20,8 @@ import org.springframework.orm.jpa.JpaSystemException; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.servlet.http.HttpServletRequest; +import java.sql.Timestamp; +import java.time.ZonedDateTime; import java.util.Arrays; import java.util.List; @@ -57,6 +59,50 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea @MockBean HttpServletRequest request; + @Test + public void auditJournalLogIsAvailable() { + // given + final var query = em.createNativeQuery(""" + select currentTask, targetTable, targetOp, targetdelta->>'caption' + from tx_journal_v + where targettable = 'hs_booking_project'; + """); + + // when + @SuppressWarnings("unchecked") final List customerLogEntries = query.getResultList(); + + // then + assertThat(customerLogEntries).map(Arrays::toString).contains( + "[creating booking-project test-data, hs_booking_project, INSERT, D-1000111 default project]", + "[creating booking-project test-data, hs_booking_project, INSERT, D-1000212 default project]", + "[creating booking-project test-data, hs_booking_project, INSERT, D-1000313 default project]"); + } + + @Test + public void historizationIsAvailable() { + // given + final String nativeQuerySql = """ + select count(*) + from hs_booking_project_hv ha; + """; + + // when + historicalContext(Timestamp.from(ZonedDateTime.now().minusDays(1).toInstant())); + final var query = em.createNativeQuery(nativeQuerySql, Integer.class); + @SuppressWarnings("unchecked") final var countBefore = (Integer) query.getSingleResult(); + + // then + assertThat(countBefore).as("hs_booking_project_hv should not contain rows for a timestamp in the past").isEqualTo(0); + + // and when + historicalContext(Timestamp.from(ZonedDateTime.now().plusHours(1).toInstant())); + em.createNativeQuery(nativeQuerySql, Integer.class); + @SuppressWarnings("unchecked") final var countAfter = (Integer) query.getSingleResult(); + + // then + assertThat(countAfter).as("hs_booking_project_hv should contain rows for a timestamp in the future").isGreaterThan(1); + } + @Nested class CreateBookingProject { @@ -283,25 +329,6 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea } } - @Test - public void auditJournalLogIsAvailable() { - // given - final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp - from tx_journal_v - where targettable = 'hs_booking_project'; - """); - - // when - @SuppressWarnings("unchecked") final List customerLogEntries = query.getResultList(); - - // then - assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating booking-project test-data 1000111, hs_booking_project, INSERT]", - "[creating booking-project test-data 1000212, hs_booking_project, INSERT]", - "[creating booking-project test-data 1000313, hs_booking_project, INSERT]"); - } - private HsBookingProjectRealEntity givenSomeTemporaryBookingProject(final int debitorNumber) { return jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java index 469fbdf1..26861624 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java @@ -23,6 +23,8 @@ import org.springframework.orm.jpa.JpaSystemException; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.servlet.http.HttpServletRequest; +import java.sql.Timestamp; +import java.time.ZonedDateTime; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -70,6 +72,66 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu @MockBean HttpServletRequest request; + @Test + public void auditJournalLogIsAvailable() { + // given + final var query = em.createNativeQuery(""" + select currentTask, targetTable, targetOp, targetdelta->>'caption' + from tx_journal_v + where targettable = 'hs_hosting_asset'; + """); + + // when + @SuppressWarnings("unchecked") final List customerLogEntries = query.getResultList(); + + // then + assertThat(customerLogEntries).map(Arrays::toString).contains( + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, another CloudServer]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some Domain-DNS-Setup]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some Domain-HTTP-Setup]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some Domain-MBOX-Setup]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some Domain-SMTP-Setup]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some Domain-Setup]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some E-Mail-Address]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some E-Mail-Alias]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some ManagedServer]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some UnixUser for E-Mail]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some UnixUser for Website]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some Webspace]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some default MariaDB instance]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some default MariaDB user]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some default MariaDB database]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some default Postgresql instance]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some default Postgresql user]", + "[creating hosting-asset test-data, hs_hosting_asset, INSERT, some default Postgresql database]" + ); + } + + @Test + public void historizationIsAvailable() { + // given + final String nativeQuerySql = """ + select count(*) + from hs_hosting_asset_hv ha; + """; + + // when + historicalContext(Timestamp.from(ZonedDateTime.now().minusDays(1).toInstant())); + final var query = em.createNativeQuery(nativeQuerySql, Integer.class); + @SuppressWarnings("unchecked") final var countBefore = (Integer) query.getSingleResult(); + + // then + assertThat(countBefore).as("hs_hosting_asset_hv should not contain rows for a timestamp in the past").isEqualTo(0); + + // and when + historicalContext(Timestamp.from(ZonedDateTime.now().plusHours(1).toInstant())); + em.createNativeQuery(nativeQuerySql, Integer.class); + @SuppressWarnings("unchecked") final var countAfter = (Integer) query.getSingleResult(); + + // then + assertThat(countAfter).as("hs_hosting_asset_hv should contain rows for a timestamp in the future").isGreaterThan(1); + } + @Nested class CreateAsset { @@ -391,25 +453,6 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu } } - @Test - public void auditJournalLogIsAvailable() { - // given - final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp - from tx_journal_v - where targettable = 'hs_hosting_asset'; - """); - - // when - @SuppressWarnings("unchecked") final List customerLogEntries = query.getResultList(); - - // then - assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating hosting-asset test-data D-1000111 default project, hs_hosting_asset, INSERT]", - "[creating hosting-asset test-data D-1000212 default project, hs_hosting_asset, INSERT]", - "[creating hosting-asset test-data D-1000313 default project, hs_hosting_asset, INSERT]"); - } - private HsHostingAssetRealEntity givenSomeTemporaryAsset(final String projectCaption, final String identifier) { return jpaAttempt.transacted(() -> { context("superuser-alex@hostsharing.net"); // needed to determine creator diff --git a/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java b/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java index 758ab68d..9cb774d2 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java @@ -610,7 +610,7 @@ public abstract class BaseOfficeDataImport extends CsvDataImport { deleteTestDataFromHsOfficeTables(); resetHsOfficeSequences(); deleteFromTestTables(); - deleteFromRbacTables(); + deleteFromCommonTables(); jpaAttempt.transacted(() -> { context(rbacSuperuser); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/migration/CsvDataImport.java b/src/test/java/net/hostsharing/hsadminng/hs/migration/CsvDataImport.java index 2ce2e924..d10f3577 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/migration/CsvDataImport.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/migration/CsvDataImport.java @@ -249,8 +249,11 @@ public class CsvDataImport extends ContextBasedTest { context(rbacSuperuser); // TODO.perf: could we instead skip creating test-data based on an env var? em.createNativeQuery("delete from hs_hosting_asset where true").executeUpdate(); + em.createNativeQuery("delete from hs_hosting_asset_ex where true").executeUpdate(); em.createNativeQuery("delete from hs_booking_item where true").executeUpdate(); + em.createNativeQuery("delete from hs_booking_item_ex where true").executeUpdate(); em.createNativeQuery("delete from hs_booking_project where true").executeUpdate(); + em.createNativeQuery("delete from hs_booking_project_ex where true").executeUpdate(); em.createNativeQuery("delete from hs_office_coopassetstransaction where true").executeUpdate(); em.createNativeQuery("delete from hs_office_coopassetstransaction_legacy_id where true").executeUpdate(); em.createNativeQuery("delete from hs_office_coopsharestransaction where true").executeUpdate(); @@ -292,7 +295,7 @@ public class CsvDataImport extends ContextBasedTest { }).assertSuccessful(); } - protected void deleteFromRbacTables() { + protected void deleteFromCommonTables() { jpaAttempt.transacted(() -> { context(rbacSuperuser); em.createNativeQuery("delete from rbacuser_rv where name not like 'superuser-%'").executeUpdate(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java index 291b8863..5fbd89a3 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/HsOfficeBankAccountRepositoryIntegrationTest.java @@ -271,7 +271,7 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'iban' from tx_journal_v where targettable = 'hs_office_bankaccount'; """); @@ -281,8 +281,9 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating bankaccount test-data First GmbH, hs_office_bankaccount, INSERT]", - "[creating bankaccount test-data Second e.K., hs_office_bankaccount, INSERT]"); + "[creating bankaccount test-data, hs_office_bankaccount, INSERT, DE02120300000000202051]", + "[creating bankaccount test-data, hs_office_bankaccount, INSERT, DE02500105170137075030]", + "[creating bankaccount test-data, hs_office_bankaccount, INSERT, DE02100500000054540402]"); } private HsOfficeBankAccountEntity givenSomeTemporaryBankAccount(final String createdByUser) { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java index 5f5e6190..5eea0091 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/contact/HsOfficeContactRbacRepositoryIntegrationTest.java @@ -256,7 +256,7 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'caption' from tx_journal_v where targettable = 'hs_office_contact'; """); @@ -266,8 +266,9 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating contact test-data first contact, hs_office_contact, INSERT]", - "[creating contact test-data second contact, hs_office_contact, INSERT]"); + "[creating contact test-data, hs_office_contact, INSERT, first contact]", + "[creating contact test-data, hs_office_contact, INSERT, second contact]", + "[creating contact test-data, hs_office_contact, INSERT, third contact]"); } private HsOfficeContactRbacEntity givenSomeTemporaryContact( diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java index 376da64d..ad059e16 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionRepositoryIntegrationTest.java @@ -220,7 +220,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'reference' from tx_journal_v where targettable = 'hs_office_coopassetstransaction'; """); @@ -230,8 +230,18 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating coopAssetsTransaction test-data 1000101, hs_office_coopassetstransaction, INSERT]", - "[creating coopAssetsTransaction test-data 1000202, hs_office_coopassetstransaction, INSERT]"); + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000101-1]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000101-2]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000101-3]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000101-3]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000202-1]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000202-2]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000202-3]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000202-3]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000303-1]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000303-2]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000303-3]", + "[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000303-3]"); } @BeforeEach diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java index cc81f352..db1b0f39 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionRepositoryIntegrationTest.java @@ -219,7 +219,7 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'reference' from tx_journal_v where targettable = 'hs_office_coopsharestransaction'; """); @@ -229,8 +229,18 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating coopSharesTransaction test-data 1000101, hs_office_coopsharestransaction, INSERT]", - "[creating coopSharesTransaction test-data 1000202, hs_office_coopsharestransaction, INSERT]"); + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000101-1]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000101-2]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000101-3]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000101-4]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000202-1]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000202-2]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000202-3]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000202-4]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000303-1]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000303-2]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000303-3]", + "[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000303-4]"); } @BeforeEach diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java index a1fccbb9..1d16254d 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java @@ -589,7 +589,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'defaultprefix' from tx_journal_v where targettable = 'hs_office_debitor'; """); @@ -599,8 +599,9 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating debitor test-data FirstGmbH-firstcontact, hs_office_debitor, INSERT]", - "[creating debitor test-data Seconde.K.-secondcontact, hs_office_debitor, INSERT]"); + "[creating debitor test-data, hs_office_debitor, INSERT, fir]", + "[creating debitor test-data, hs_office_debitor, INSERT, sec]", + "[creating debitor test-data, hs_office_debitor, INSERT, thi]"); } private HsOfficeDebitorEntity givenSomeTemporaryDebitor( diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java index 581febd8..6e013be2 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java @@ -336,7 +336,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'membernumbersuffix' from tx_journal_v where targettable = 'hs_office_membership'; """); @@ -346,9 +346,9 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating Membership test-data P-10001M-...01, hs_office_membership, INSERT]", - "[creating Membership test-data P-10002M-...02, hs_office_membership, INSERT]", - "[creating Membership test-data P-10003M-...03, hs_office_membership, INSERT]"); + "[creating Membership test-data, hs_office_membership, INSERT, 01]", + "[creating Membership test-data, hs_office_membership, INSERT, 02]", + "[creating Membership test-data, hs_office_membership, INSERT, 03]"); } private HsOfficeMembershipEntity givenSomeTemporaryMembership(final String partnerTradeName, final String memberNumberSuffix) { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java index e365d183..2d871048 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java @@ -433,7 +433,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'partnernumber' from tx_journal_v where targettable = 'hs_office_partner'; """); @@ -443,8 +443,11 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating partner test-data FirstGmbH-firstcontact, hs_office_partner, INSERT]", - "[creating partner test-data Seconde.K.-secondcontact, hs_office_partner, INSERT]"); + "[creating partner test-data , hs_office_partner, INSERT, 10001]", + "[creating partner test-data , hs_office_partner, INSERT, 10002]", + "[creating partner test-data , hs_office_partner, INSERT, 10003]", + "[creating partner test-data , hs_office_partner, INSERT, 10004]", + "[creating partner test-data , hs_office_partner, INSERT, 10010]"); } private HsOfficePartnerEntity givenSomeTemporaryHostsharingPartner( diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java index b0e1c893..6ee4f486 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/person/HsOfficePersonRepositoryIntegrationTest.java @@ -260,7 +260,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'tradename', targetdelta->>'lastname' from tx_journal_v where targettable = 'hs_office_person'; """); @@ -270,8 +270,10 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating person test-data First GmbH, hs_office_person, INSERT]", - "[creating person test-data Second e.K., Smith, Peter, hs_office_person, INSERT]"); + "[creating person test-data, hs_office_person, INSERT, Hostsharing eG, null]", + "[creating person test-data, hs_office_person, INSERT, First GmbH, null]", + "[creating person test-data, hs_office_person, INSERT, Second e.K., null]", + "[creating person test-data, hs_office_person, INSERT, Third OHG, null]"); } private HsOfficePersonEntity givenSomeTemporaryPerson( diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java index 151d9967..b9ccb589 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java @@ -394,7 +394,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'mark' from tx_journal_v where targettable = 'hs_office_relation'; """); @@ -404,8 +404,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating relation test-data HostsharingeG-FirstGmbH, hs_office_relation, INSERT]", - "[creating relation test-data FirstGmbH-Firby, hs_office_relation, INSERT]"); + "[creating relation test-data, hs_office_relation, INSERT, members-announce]"); } private HsOfficeRelationRbacEntity givenSomeTemporaryRelationBessler(final String holderPerson, final String contact) { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java index d5fdb87d..3fb90976 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java @@ -379,7 +379,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC public void auditJournalLogIsAvailable() { // given final var query = em.createNativeQuery(""" - select currentTask, targetTable, targetOp + select currentTask, targetTable, targetOp, targetdelta->>'reference' from tx_journal_v where targettable = 'hs_office_sepamandate'; """); @@ -389,9 +389,9 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC // then assertThat(customerLogEntries).map(Arrays::toString).contains( - "[creating SEPA-mandate test-data 1000111, hs_office_sepamandate, INSERT]", - "[creating SEPA-mandate test-data 1000212, hs_office_sepamandate, INSERT]", - "[creating SEPA-mandate test-data 1000313, hs_office_sepamandate, INSERT]"); + "[creating SEPA-mandate test-data, hs_office_sepamandate, INSERT, ref-10001-11]", + "[creating SEPA-mandate test-data, hs_office_sepamandate, INSERT, ref-10002-12]", + "[creating SEPA-mandate test-data, hs_office_sepamandate, INSERT, ref-10003-13]"); } private HsOfficeSepaMandateEntity givenSomeTemporarySepaMandate(final String iban) { diff --git a/src/test/java/net/hostsharing/hsadminng/rbac/context/ContextBasedTest.java b/src/test/java/net/hostsharing/hsadminng/rbac/context/ContextBasedTest.java index 2e14c267..59704ad4 100644 --- a/src/test/java/net/hostsharing/hsadminng/rbac/context/ContextBasedTest.java +++ b/src/test/java/net/hostsharing/hsadminng/rbac/context/ContextBasedTest.java @@ -9,6 +9,7 @@ import org.springframework.context.annotation.Import; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import java.sql.Timestamp; @Import(RbacGrantsDiagramService.class) public abstract class ContextBasedTest { @@ -47,4 +48,26 @@ public abstract class ContextBasedTest { protected void context(final String currentUser) { context(currentUser, null); } + + protected void historicalContext(final Long txId) { + // set local cannot be used with query parameters + em.createNativeQuery(""" + set local hsadminng.tx_history_txid to ':txid'; + """.replace(":txid", txId.toString())).executeUpdate(); + em.createNativeQuery(""" + set local hsadminng.tx_history_timestamp to ''; + """).executeUpdate(); + } + + + protected void historicalContext(final Timestamp txTimestamp) { + // set local cannot be used with query parameters + em.createNativeQuery(""" + set local hsadminng.tx_history_timestamp to ':timestamp'; + """.replace(":timestamp", txTimestamp.toString())).executeUpdate(); + em.createNativeQuery(""" + set local hsadminng.tx_history_txid to ''; + """).executeUpdate(); + } + }