historic-view #92
37
.run/ImportHostingAssets into local.run.xml
Normal file
37
.run/ImportHostingAssets into local.run.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="ImportHostingAssets into local" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="env">
|
||||||
|
<map>
|
||||||
|
<entry key="HSADMINNG_POSTGRES_ADMIN_PASSWORD" value="password" />
|
||||||
|
<entry key="HSADMINNG_POSTGRES_ADMIN_USERNAME" value="postgres" />
|
||||||
|
<entry key="HSADMINNG_POSTGRES_JDBC_URL" value="jdbc:postgresql://localhost:5432/postgres" />
|
||||||
|
<entry key="HSADMINNG_POSTGRES_RESTRICTED_USERNAME" value="restricted" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value=":importHostingAssets" />
|
||||||
|
<option value="--tests" />
|
||||||
|
<option value=""net.hostsharing.hsadminng.hs.migration.ImportHostingAssets"" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<EXTENSION ID="com.intellij.execution.ExternalSystemRunConfigurationJavaExtension">
|
||||||
|
<extension name="coverage" sample_coverage="false" />
|
||||||
|
</EXTENSION>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>true</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
@ -33,37 +33,4 @@
|
|||||||
<RunAsTest>true</RunAsTest>
|
<RunAsTest>true</RunAsTest>
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
<configuration default="false" name="ImportHostingAssets" type="GradleRunConfiguration" factoryName="Gradle">
|
|
||||||
<ExternalSystemSettings>
|
|
||||||
<option name="env">
|
|
||||||
<map>
|
|
||||||
<entry key="HSADMINNG_POSTGRES_ADMIN_USERNAME" value="admin" />
|
|
||||||
<entry key="HSADMINNG_POSTGRES_RESTRICTED_USERNAME" value="restricted" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
<option name="executionName" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="externalSystemIdString" value="GRADLE" />
|
|
||||||
<option name="scriptParameters" value="" />
|
|
||||||
<option name="taskDescriptions">
|
|
||||||
<list />
|
|
||||||
</option>
|
|
||||||
<option name="taskNames">
|
|
||||||
<list>
|
|
||||||
<option value=":importHostingAssets" />
|
|
||||||
<option value="--tests" />
|
|
||||||
<option value=""net.hostsharing.hsadminng.hs.migration.ImportHostingAssets"" />
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
<option name="vmOptions" />
|
|
||||||
</ExternalSystemSettings>
|
|
||||||
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
|
|
||||||
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
|
||||||
<EXTENSION ID="com.intellij.execution.ExternalSystemRunConfigurationJavaExtension">
|
|
||||||
<extension name="coverage" sample_coverage="false" />
|
|
||||||
</EXTENSION>
|
|
||||||
<DebugAllEnabled>false</DebugAllEnabled>
|
|
||||||
<RunAsTest>true</RunAsTest>
|
|
||||||
<method v="2" />
|
|
||||||
</configuration>
|
|
||||||
</component>
|
</component>
|
@ -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';
|
|
@ -1,166 +1,39 @@
|
|||||||
|
|
||||||
-- ========================================================
|
-- ========================================================
|
||||||
-- Historization
|
-- Historization twiddle
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
CREATE TABLE "tx_history" (
|
rollback;
|
||||||
"tx_id" BIGINT NOT NULL UNIQUE,
|
begin transaction;
|
||||||
"tx_timestamp" TIMESTAMP NOT NULL,
|
call defineContext('historization testing', null, 'superuser-alex@hostsharing.net',
|
||||||
"user" VARCHAR(64) NOT NULL, -- references postgres user
|
-- 'hs_booking_project#D-1000000-hshdefaultproject:ADMIN'); -- prod+test
|
||||||
"task" VARCHAR NOT NULL
|
'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()
|
-- single version at point in time
|
||||||
RETURNS trigger
|
-- set hsadminng.tx_history_txid to (select max(txid) from tx_context where txtimestamp<='2024-08-27 12:13:13.450821');
|
||||||
LANGUAGE plpgsql STRICT AS $$
|
set hsadminng.tx_history_txid to '';
|
||||||
DECLARE
|
set hsadminng.tx_history_timestamp to '2024-08-29 12:42';
|
||||||
currentUser VARCHAR(63);
|
-- all versions
|
||||||
currentTask VARCHAR(127);
|
select tx_history_txid(), txc.txtimestamp, txc.currentUser, txc.currentTask, haex.*
|
||||||
"row" RECORD;
|
from hs_hosting_asset_ex haex
|
||||||
"alive" BOOLEAN;
|
join tx_context txc on haex.txid=txc.txid
|
||||||
"sql" varchar;
|
where haex.identifier = 'test@thi.example.org';
|
||||||
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
|
select uuid, version, type, identifier, caption from hs_hosting_asset_hv p where identifier = 'test@thi.example.org';
|
||||||
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
|
select pg_current_xact_id();
|
||||||
"row" := NEW;
|
|
||||||
"alive" := TRUE;
|
|
||||||
ELSE -- DELETE or TRUNCATE
|
|
||||||
"row" := OLD;
|
|
||||||
"alive" := FALSE;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
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; $$;
|
|
||||||
|
@ -23,8 +23,7 @@ do $$
|
|||||||
*/
|
*/
|
||||||
create table tx_context
|
create table tx_context
|
||||||
(
|
(
|
||||||
contextId bigint primary key not null,
|
txId xid8 primary key not null,
|
||||||
txId bigint not null,
|
|
||||||
txTimestamp timestamp not null,
|
txTimestamp timestamp not null,
|
||||||
currentUser varchar(63) not null, -- not the uuid, because users can be deleted
|
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
|
assumedRoles varchar(1023) not null, -- not the uuids, because roles can be deleted
|
||||||
@ -43,7 +42,7 @@ create index on tx_context using brin (txTimestamp);
|
|||||||
*/
|
*/
|
||||||
create table tx_journal
|
create table tx_journal
|
||||||
(
|
(
|
||||||
contextId bigint not null references tx_context (contextId),
|
txId xid8 not null references tx_context (txId),
|
||||||
targetTable text not null,
|
targetTable text not null,
|
||||||
targetUuid uuid not null, -- Assumes that all audited tables have a uuid column.
|
targetUuid uuid not null, -- Assumes that all audited tables have a uuid column.
|
||||||
targetOp operation not null,
|
targetOp operation not null,
|
||||||
@ -62,7 +61,7 @@ create index on tx_journal (targetTable, targetUuid);
|
|||||||
create view tx_journal_v as
|
create view tx_journal_v as
|
||||||
select txc.*, txj.targettable, txj.targetop, txj.targetuuid, txj.targetdelta
|
select txc.*, txj.targettable, txj.targetop, txj.targetuuid, txj.targetdelta
|
||||||
from tx_journal txj
|
from tx_journal txj
|
||||||
left join tx_context txc using (contextid)
|
left join tx_context txc using (txId)
|
||||||
order by txc.txtimestamp;
|
order by txc.txtimestamp;
|
||||||
--//
|
--//
|
||||||
|
|
||||||
@ -77,31 +76,31 @@ create or replace function tx_journal_trigger()
|
|||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
curTask text;
|
curTask text;
|
||||||
curContextId bigint;
|
curTxId xid8;
|
||||||
begin
|
begin
|
||||||
curTask := currentTask();
|
curTask := currentTask();
|
||||||
curContextId := txid_current()+bigIntHash(curTask);
|
curTxId := pg_current_xact_id();
|
||||||
|
|
||||||
insert
|
insert
|
||||||
into tx_context (contextId, txId, txTimestamp, currentUser, assumedRoles, currentTask, currentRequest)
|
into tx_context (txId, txTimestamp, currentUser, assumedRoles, currentTask, currentRequest)
|
||||||
values (curContextId, txid_current(), now(),
|
values ( curTxId, now(),
|
||||||
currentUser(), assumedRoles(), curTask, currentRequest())
|
currentUser(), assumedRoles(), curTask, currentRequest())
|
||||||
on conflict do nothing;
|
on conflict do nothing;
|
||||||
|
|
||||||
case tg_op
|
case tg_op
|
||||||
when 'INSERT' then insert
|
when 'INSERT' then insert
|
||||||
into tx_journal
|
into tx_journal
|
||||||
values (curContextId,
|
values (curTxId,
|
||||||
tg_table_name, new.uuid, tg_op::operation,
|
tg_table_name, new.uuid, tg_op::operation,
|
||||||
to_jsonb(new));
|
to_jsonb(new));
|
||||||
when 'UPDATE' then insert
|
when 'UPDATE' then insert
|
||||||
into tx_journal
|
into tx_journal
|
||||||
values (curContextId,
|
values (curTxId,
|
||||||
tg_table_name, old.uuid, tg_op::operation,
|
tg_table_name, old.uuid, tg_op::operation,
|
||||||
jsonb_changes_delta(to_jsonb(old), to_jsonb(new)));
|
jsonb_changes_delta(to_jsonb(old), to_jsonb(new)));
|
||||||
when 'DELETE' then insert
|
when 'DELETE' then insert
|
||||||
into tx_journal
|
into tx_journal
|
||||||
values (curContextId,
|
values (curTxId,
|
||||||
tg_table_name, old.uuid, 'DELETE'::operation,
|
tg_table_name, old.uuid, 'DELETE'::operation,
|
||||||
null::jsonb);
|
null::jsonb);
|
||||||
else raise exception 'Trigger op % not supported for %.', tg_op, tg_table_name;
|
else raise exception 'Trigger op % not supported for %.', tg_op, tg_table_name;
|
||||||
|
160
src/main/resources/db/changelog/0-basis/030-historization.sql
Normal file
160
src/main/resources/db/changelog/0-basis/030-historization.sql
Normal file
@ -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; $$;
|
||||||
|
--//
|
@ -25,16 +25,11 @@ create or replace procedure createTestCustomerTestData(
|
|||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
custRowId uuid;
|
custRowId uuid;
|
||||||
custAdminName varchar;
|
custAdminName varchar;
|
||||||
custAdminUuid uuid;
|
custAdminUuid uuid;
|
||||||
newCust test_customer;
|
newCust test_customer;
|
||||||
begin
|
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();
|
custRowId = uuid_generate_v4();
|
||||||
custAdminName = 'customer-admin@' || custPrefix || '.example.com';
|
custAdminName = 'customer-admin@' || custPrefix || '.example.com';
|
||||||
custAdminUuid = createRbacUser(custAdminName);
|
custAdminUuid = createRbacUser(custAdminName);
|
||||||
@ -77,6 +72,8 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
begin
|
||||||
|
call defineContext('creating RBAC test customer', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||||
|
|
||||||
call createTestCustomerTestData(99901, 'xxx');
|
call createTestCustomerTestData(99901, 'xxx');
|
||||||
call createTestCustomerTestData(99902, 'yyy');
|
call createTestCustomerTestData(99902, 'yyy');
|
||||||
call createTestCustomerTestData(99903, 'zzz');
|
call createTestCustomerTestData(99903, 'zzz');
|
||||||
|
@ -13,7 +13,6 @@ declare
|
|||||||
custAdminUser varchar;
|
custAdminUser varchar;
|
||||||
custAdminRole varchar;
|
custAdminRole varchar;
|
||||||
pacName varchar;
|
pacName varchar;
|
||||||
currentTask varchar;
|
|
||||||
pac test_package;
|
pac test_package;
|
||||||
begin
|
begin
|
||||||
select * from test_customer where test_customer.prefix = customerPrefix into cust;
|
select * from test_customer where test_customer.prefix = customerPrefix into cust;
|
||||||
@ -21,13 +20,9 @@ begin
|
|||||||
for t in 0..(pacCount-1)
|
for t in 0..(pacCount-1)
|
||||||
loop
|
loop
|
||||||
pacName = cust.prefix || to_char(t, 'fm00');
|
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';
|
custAdminUser = 'customer-admin@' || cust.prefix || '.example.com';
|
||||||
custAdminRole = 'test_customer#' || cust.prefix || ':ADMIN';
|
custAdminRole = 'test_customer#' || cust.prefix || ':ADMIN';
|
||||||
call defineContext(currentTask, null, 'superuser-fran@hostsharing.net', custAdminRole);
|
call defineContext('creating RBAC test package', null, 'superuser-fran@hostsharing.net', custAdminRole);
|
||||||
raise notice 'task: % by % as %', currentTask, custAdminUser, custAdminRole;
|
|
||||||
|
|
||||||
insert
|
insert
|
||||||
into test_package (customerUuid, name, description)
|
into test_package (customerUuid, name, description)
|
||||||
|
@ -11,7 +11,6 @@ create or replace procedure createdomainTestData( packageName varchar, domainCou
|
|||||||
declare
|
declare
|
||||||
pac record;
|
pac record;
|
||||||
pacAdmin varchar;
|
pacAdmin varchar;
|
||||||
currentTask varchar;
|
|
||||||
begin
|
begin
|
||||||
select p.uuid, p.name, c.prefix as custPrefix
|
select p.uuid, p.name, c.prefix as custPrefix
|
||||||
from test_package p
|
from test_package p
|
||||||
@ -21,10 +20,8 @@ begin
|
|||||||
|
|
||||||
for t in 0..(domainCount-1)
|
for t in 0..(domainCount-1)
|
||||||
loop
|
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';
|
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
|
insert
|
||||||
into test_domain (name, packageUuid)
|
into test_domain (name, packageUuid)
|
||||||
|
@ -11,17 +11,13 @@
|
|||||||
create or replace procedure createHsOfficeContactTestData(contCaption varchar)
|
create or replace procedure createHsOfficeContactTestData(contCaption varchar)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
postalAddr varchar;
|
postalAddr varchar;
|
||||||
emailAddr varchar;
|
emailAddr varchar;
|
||||||
begin
|
begin
|
||||||
currentTask = 'creating contact test-data ' || contCaption;
|
|
||||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
|
||||||
|
|
||||||
emailAddr = 'contact-admin@' || cleanIdentifier(contCaption) || '.example.com';
|
emailAddr = 'contact-admin@' || cleanIdentifier(contCaption) || '.example.com';
|
||||||
call defineContext(currentTask);
|
call defineContext('creating contact test-data');
|
||||||
perform createRbacUser(emailAddr);
|
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';
|
postalAddr := E'Vorname Nachname\nStraße Hnr\nPLZ Stadt';
|
||||||
|
|
||||||
|
@ -17,16 +17,13 @@ create or replace procedure createHsOfficePersonTestData(
|
|||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
fullName varchar;
|
fullName varchar;
|
||||||
currentTask varchar;
|
|
||||||
emailAddr varchar;
|
emailAddr varchar;
|
||||||
begin
|
begin
|
||||||
fullName := concat_ws(', ', newTradeName, newFamilyName, newGivenName);
|
fullName := concat_ws(', ', newTradeName, newFamilyName, newGivenName);
|
||||||
currentTask = 'creating person test-data ' || fullName;
|
|
||||||
emailAddr = 'person-' || left(cleanIdentifier(fullName), 32) || '@example.com';
|
emailAddr = 'person-' || left(cleanIdentifier(fullName), 32) || '@example.com';
|
||||||
call defineContext(currentTask);
|
call defineContext('creating person test-data');
|
||||||
perform createRbacUser(emailAddr);
|
perform createRbacUser(emailAddr);
|
||||||
call defineContext(currentTask, null, emailAddr);
|
call defineContext('creating person test-data', null, emailAddr);
|
||||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
|
||||||
|
|
||||||
raise notice 'creating test person: % by %', fullName, emailAddr;
|
raise notice 'creating test person: % by %', fullName, emailAddr;
|
||||||
insert
|
insert
|
||||||
|
@ -16,7 +16,6 @@ create or replace procedure createHsOfficeRelationTestData(
|
|||||||
mark varchar default null)
|
mark varchar default null)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
idName varchar;
|
idName varchar;
|
||||||
anchorPerson hs_office_person;
|
anchorPerson hs_office_person;
|
||||||
holderPerson hs_office_person;
|
holderPerson hs_office_person;
|
||||||
@ -24,9 +23,6 @@ declare
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
idName := cleanIdentifier( anchorPersonName || '-' || holderPersonName);
|
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.*
|
select p.*
|
||||||
into anchorPerson
|
into anchorPerson
|
||||||
@ -89,6 +85,8 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
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('First GmbH', 'PARTNER', 'Hostsharing eG', 'first contact');
|
||||||
call createHsOfficeRelationTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact');
|
call createHsOfficeRelationTestData('Firby', 'REPRESENTATIVE', 'First GmbH', 'first contact');
|
||||||
call createHsOfficeRelationTestData('First GmbH', 'DEBITOR', 'First GmbH', 'first contact');
|
call createHsOfficeRelationTestData('First GmbH', 'DEBITOR', 'First GmbH', 'first contact');
|
||||||
|
@ -15,7 +15,6 @@ create or replace procedure createHsOfficePartnerTestData(
|
|||||||
contactCaption varchar )
|
contactCaption varchar )
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
idName varchar;
|
idName varchar;
|
||||||
mandantPerson hs_office_person;
|
mandantPerson hs_office_person;
|
||||||
partnerRel hs_office_relation;
|
partnerRel hs_office_relation;
|
||||||
@ -23,9 +22,6 @@ declare
|
|||||||
relatedDetailsUuid uuid;
|
relatedDetailsUuid uuid;
|
||||||
begin
|
begin
|
||||||
idName := cleanIdentifier( partnerPersonName|| '-' || contactCaption);
|
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
|
select p.* from hs_office_person p
|
||||||
where p.tradeName = mandantTradeName
|
where p.tradeName = mandantTradeName
|
||||||
@ -69,13 +65,14 @@ end; $$;
|
|||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-office-partner-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
--changeset hs-office-partner-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
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', 10001, 'First GmbH', 'first contact');
|
||||||
call createHsOfficePartnerTestData('Hostsharing eG', 10002, 'Second e.K.', 'second contact');
|
call createHsOfficePartnerTestData('Hostsharing eG', 10002, 'Second e.K.', 'second contact');
|
||||||
call createHsOfficePartnerTestData('Hostsharing eG', 10003, 'Third OHG', 'third contact');
|
call createHsOfficePartnerTestData('Hostsharing eG', 10003, 'Third OHG', 'third contact');
|
||||||
|
@ -11,16 +11,11 @@
|
|||||||
create or replace procedure createHsOfficeBankAccountTestData(givenHolder varchar, givenIBAN varchar, givenBIC varchar)
|
create or replace procedure createHsOfficeBankAccountTestData(givenHolder varchar, givenIBAN varchar, givenBIC varchar)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
emailAddr varchar;
|
emailAddr varchar;
|
||||||
begin
|
begin
|
||||||
currentTask = 'creating bankaccount test-data ' || givenHolder;
|
|
||||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
|
||||||
|
|
||||||
emailAddr = 'bankaccount-admin@' || cleanIdentifier(givenHolder) || '.example.com';
|
emailAddr = 'bankaccount-admin@' || cleanIdentifier(givenHolder) || '.example.com';
|
||||||
call defineContext(currentTask);
|
|
||||||
perform createRbacUser(emailAddr);
|
perform createRbacUser(emailAddr);
|
||||||
call defineContext(currentTask, null, emailAddr);
|
call defineContext('creating bankaccount test-data', null, emailAddr);
|
||||||
|
|
||||||
raise notice 'creating test bankaccount: %', givenHolder;
|
raise notice 'creating test bankaccount: %', givenHolder;
|
||||||
insert
|
insert
|
||||||
@ -36,6 +31,8 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
begin
|
||||||
|
call defineContext('creating bankaccount test-data');
|
||||||
|
|
||||||
-- IBANs+BICs taken from https://ibanvalidieren.de/beispiele.html
|
-- IBANs+BICs taken from https://ibanvalidieren.de/beispiele.html
|
||||||
call createHsOfficeBankAccountTestData('First GmbH', 'DE02120300000000202051', 'BYLADEM1001');
|
call createHsOfficeBankAccountTestData('First GmbH', 'DE02120300000000202051', 'BYLADEM1001');
|
||||||
call createHsOfficeBankAccountTestData('Peter Smith', 'DE02500105170137075030', 'INGDDEFF');
|
call createHsOfficeBankAccountTestData('Peter Smith', 'DE02500105170137075030', 'INGDDEFF');
|
||||||
|
@ -16,15 +16,11 @@ create or replace procedure createHsOfficeDebitorTestData(
|
|||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
idName varchar;
|
idName varchar;
|
||||||
relatedDebitorRelUuid uuid;
|
relatedDebitorRelUuid uuid;
|
||||||
relatedBankAccountUuid uuid;
|
relatedBankAccountUuid uuid;
|
||||||
begin
|
begin
|
||||||
idName := cleanIdentifier( forPartnerPersonName|| '-' || forBillingContactCaption);
|
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
|
select debitorRel.uuid
|
||||||
into relatedDebitorRelUuid
|
into relatedDebitorRelUuid
|
||||||
@ -54,6 +50,8 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
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(11, 'First GmbH', 'first contact', 'fir');
|
||||||
call createHsOfficeDebitorTestData(12, 'Second e.K.', 'second contact', 'sec');
|
call createHsOfficeDebitorTestData(12, 'Second e.K.', 'second contact', 'sec');
|
||||||
call createHsOfficeDebitorTestData(13, 'Third OHG', 'third contact', 'thi');
|
call createHsOfficeDebitorTestData(13, 'Third OHG', 'third contact', 'thi');
|
||||||
|
@ -15,14 +15,9 @@ create or replace procedure createHsOfficeSepaMandateTestData(
|
|||||||
withReference varchar)
|
withReference varchar)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
relatedDebitor hs_office_debitor;
|
relatedDebitor hs_office_debitor;
|
||||||
relatedBankAccount hs_office_bankAccount;
|
relatedBankAccount hs_office_bankAccount;
|
||||||
begin
|
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
|
select debitor.* into relatedDebitor
|
||||||
from hs_office_debitor debitor
|
from hs_office_debitor debitor
|
||||||
join hs_office_relation debitorRel on debitorRel.uuid = debitor.debitorRelUuid
|
join hs_office_relation debitorRel on debitorRel.uuid = debitor.debitorRelUuid
|
||||||
@ -48,6 +43,8 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
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(10001, '11', 'DE02120300000000202051', 'ref-10001-11');
|
||||||
call createHsOfficeSepaMandateTestData(10002, '12', 'DE02100500000054540402', 'ref-10002-12');
|
call createHsOfficeSepaMandateTestData(10002, '12', 'DE02100500000054540402', 'ref-10002-12');
|
||||||
call createHsOfficeSepaMandateTestData(10003, '13', 'DE02300209000106531065', 'ref-10003-13');
|
call createHsOfficeSepaMandateTestData(10003, '13', 'DE02300209000106531065', 'ref-10003-13');
|
||||||
|
@ -13,15 +13,8 @@ create or replace procedure createHsOfficeMembershipTestData(
|
|||||||
newMemberNumberSuffix char(2) )
|
newMemberNumberSuffix char(2) )
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
relatedPartner hs_office_partner;
|
relatedPartner hs_office_partner;
|
||||||
begin
|
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
|
select partner.* from hs_office_partner partner
|
||||||
where partner.partnerNumber = forPartnerNumber into relatedPartner;
|
where partner.partnerNumber = forPartnerNumber into relatedPartner;
|
||||||
|
|
||||||
@ -40,6 +33,8 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
begin
|
||||||
|
call defineContext('creating Membership test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||||
|
|
||||||
call createHsOfficeMembershipTestData(10001, '01');
|
call createHsOfficeMembershipTestData(10001, '01');
|
||||||
call createHsOfficeMembershipTestData(10002, '02');
|
call createHsOfficeMembershipTestData(10002, '02');
|
||||||
call createHsOfficeMembershipTestData(10003, '03');
|
call createHsOfficeMembershipTestData(10003, '03');
|
||||||
|
@ -14,15 +14,9 @@ create or replace procedure createHsOfficeCoopSharesTransactionTestData(
|
|||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
membership hs_office_membership;
|
membership hs_office_membership;
|
||||||
subscriptionEntryUuid uuid;
|
subscriptionEntryUuid uuid;
|
||||||
begin
|
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
|
select m.uuid
|
||||||
from hs_office_membership m
|
from hs_office_membership m
|
||||||
join hs_office_partner p on p.uuid = m.partneruuid
|
join hs_office_partner p on p.uuid = m.partneruuid
|
||||||
@ -49,6 +43,9 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
begin
|
||||||
|
call defineContext('creating coopSharesTransaction test-data');
|
||||||
|
SET CONSTRAINTS ALL DEFERRED;
|
||||||
|
|
||||||
call createHsOfficeCoopSharesTransactionTestData(10001, '01');
|
call createHsOfficeCoopSharesTransactionTestData(10001, '01');
|
||||||
call createHsOfficeCoopSharesTransactionTestData(10002, '02');
|
call createHsOfficeCoopSharesTransactionTestData(10002, '02');
|
||||||
call createHsOfficeCoopSharesTransactionTestData(10003, '03');
|
call createHsOfficeCoopSharesTransactionTestData(10003, '03');
|
||||||
|
@ -14,15 +14,9 @@ create or replace procedure createHsOfficeCoopAssetsTransactionTestData(
|
|||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
membership hs_office_membership;
|
membership hs_office_membership;
|
||||||
lossEntryUuid uuid;
|
lossEntryUuid uuid;
|
||||||
begin
|
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
|
select m.uuid
|
||||||
from hs_office_membership m
|
from hs_office_membership m
|
||||||
join hs_office_partner p on p.uuid = m.partneruuid
|
join hs_office_partner p on p.uuid = m.partneruuid
|
||||||
@ -49,6 +43,9 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
begin
|
||||||
|
call defineContext('creating coopAssetsTransaction test-data');
|
||||||
|
SET CONSTRAINTS ALL DEFERRED;
|
||||||
|
|
||||||
call createHsOfficeCoopAssetsTransactionTestData(10001, '01');
|
call createHsOfficeCoopAssetsTransactionTestData(10001, '01');
|
||||||
call createHsOfficeCoopAssetsTransactionTestData(10002, '02');
|
call createHsOfficeCoopAssetsTransactionTestData(10002, '02');
|
||||||
call createHsOfficeCoopAssetsTransactionTestData(10003, '03');
|
call createHsOfficeCoopAssetsTransactionTestData(10003, '03');
|
||||||
|
@ -20,3 +20,10 @@ create table if not exists hs_booking_project
|
|||||||
|
|
||||||
call create_journal('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');
|
||||||
|
--//
|
||||||
|
@ -14,12 +14,8 @@ create or replace procedure createHsBookingProjectTransactionTestData(
|
|||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
relatedDebitor hs_office_debitor;
|
relatedDebitor hs_office_debitor;
|
||||||
begin
|
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
|
select debitor.* into relatedDebitor
|
||||||
from hs_office_debitor debitor
|
from hs_office_debitor debitor
|
||||||
@ -43,6 +39,8 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
begin
|
||||||
|
call defineContext('creating booking-project test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||||
|
|
||||||
call createHsBookingProjectTransactionTestData(10001, '11');
|
call createHsBookingProjectTransactionTestData(10001, '11');
|
||||||
call createHsBookingProjectTransactionTestData(10002, '12');
|
call createHsBookingProjectTransactionTestData(10002, '12');
|
||||||
call createHsBookingProjectTransactionTestData(10003, '13');
|
call createHsBookingProjectTransactionTestData(10003, '13');
|
||||||
|
@ -36,3 +36,11 @@ create table if not exists hs_booking_item
|
|||||||
|
|
||||||
call create_journal('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');
|
||||||
|
--//
|
||||||
|
|
||||||
|
@ -14,15 +14,10 @@ create or replace procedure createHsBookingItemTransactionTestData(
|
|||||||
)
|
)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
relatedProject hs_booking_project;
|
relatedProject hs_booking_project;
|
||||||
privateCloudUuid uuid;
|
privateCloudUuid uuid;
|
||||||
managedServerUuid uuid;
|
managedServerUuid uuid;
|
||||||
begin
|
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
|
select project.* into relatedProject
|
||||||
from hs_booking_project project
|
from hs_booking_project project
|
||||||
where project.caption = 'D-' || givenPartnerNumber || givenDebitorSuffix || ' default project';
|
where project.caption = 'D-' || givenPartnerNumber || givenDebitorSuffix || ' default project';
|
||||||
@ -49,7 +44,11 @@ end; $$;
|
|||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
|
declare
|
||||||
|
currentTask text;
|
||||||
begin
|
begin
|
||||||
|
call defineContext('creating booking-item test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||||
|
|
||||||
call createHsBookingItemTransactionTestData(10001, '11');
|
call createHsBookingItemTransactionTestData(10001, '11');
|
||||||
call createHsBookingItemTransactionTestData(10002, '12');
|
call createHsBookingItemTransactionTestData(10002, '12');
|
||||||
call createHsBookingItemTransactionTestData(10003, '13');
|
call createHsBookingItemTransactionTestData(10003, '13');
|
||||||
|
@ -166,6 +166,14 @@ execute procedure hs_hosting_asset_booking_item_hierarchy_check_tf();
|
|||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset hs-hosting-asset-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
--changeset hs-hosting-asset-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
call create_journal('hs_hosting_asset');
|
call create_journal('hs_hosting_asset');
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
--changeset hs-hosting-asset-MAIN-TABLE-HISTORIZATION:1 endDelimiter:--//
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
call tx_create_historicization('hs_hosting_asset');
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
create or replace procedure createHsHostingAssetTestData(givenProjectCaption varchar)
|
create or replace procedure createHsHostingAssetTestData(givenProjectCaption varchar)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
declare
|
declare
|
||||||
currentTask varchar;
|
|
||||||
relatedProject hs_booking_project;
|
relatedProject hs_booking_project;
|
||||||
relatedDebitor hs_office_debitor;
|
relatedDebitor hs_office_debitor;
|
||||||
privateCloudBI hs_booking_item;
|
privateCloudBI hs_booking_item;
|
||||||
@ -31,9 +30,7 @@ declare
|
|||||||
pgSqlInstanceUuid uuid;
|
pgSqlInstanceUuid uuid;
|
||||||
PgSqlUserUuid uuid;
|
PgSqlUserUuid uuid;
|
||||||
begin
|
begin
|
||||||
currentTask := 'creating hosting-asset test-data ' || givenProjectCaption;
|
call defineContext('creating hosting-asset test-data', null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
||||||
call defineContext(currentTask, null, 'superuser-alex@hostsharing.net', 'global#global:ADMIN');
|
|
||||||
execute format('set local hsadminng.currentTask to %L', currentTask);
|
|
||||||
|
|
||||||
select project.* into relatedProject
|
select project.* into relatedProject
|
||||||
from hs_booking_project project
|
from hs_booking_project project
|
||||||
@ -113,6 +110,8 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
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-1000111 default project');
|
||||||
call createHsHostingAssetTestData('D-1000212 default project');
|
call createHsHostingAssetTestData('D-1000212 default project');
|
||||||
call createHsHostingAssetTestData('D-1000313 default project');
|
call createHsHostingAssetTestData('D-1000313 default project');
|
||||||
|
@ -21,6 +21,8 @@ databaseChangeLog:
|
|||||||
file: db/changelog/0-basis/010-context.sql
|
file: db/changelog/0-basis/010-context.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/0-basis/020-audit-log.sql
|
file: db/changelog/0-basis/020-audit-log.sql
|
||||||
|
- include:
|
||||||
|
file: db/changelog/0-basis/030-historization.sql
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/0-basis/090-log-slow-queries-extensions.sql
|
file: db/changelog/0-basis/090-log-slow-queries-extensions.sql
|
||||||
- include:
|
- include:
|
||||||
|
@ -20,7 +20,9 @@ import org.springframework.orm.jpa.JpaSystemException;
|
|||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import java.sql.Timestamp;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -62,6 +64,54 @@ class HsBookingItemRepositoryIntegrationTest extends ContextBasedTestWithCleanup
|
|||||||
@MockBean
|
@MockBean
|
||||||
HttpServletRequest request;
|
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<Object[]> 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
|
@Nested
|
||||||
class CreateBookingItem {
|
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<Object[]> 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) {
|
private HsBookingItem givenSomeTemporaryBookingItem(final String projectCaption) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
|
@ -20,6 +20,8 @@ import org.springframework.orm.jpa.JpaSystemException;
|
|||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -57,6 +59,50 @@ class HsBookingProjectRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
@MockBean
|
@MockBean
|
||||||
HttpServletRequest request;
|
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<Object[]> 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
|
@Nested
|
||||||
class CreateBookingProject {
|
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<Object[]> 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) {
|
private HsBookingProjectRealEntity givenSomeTemporaryBookingProject(final int debitorNumber) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
|
@ -23,6 +23,8 @@ import org.springframework.orm.jpa.JpaSystemException;
|
|||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -70,6 +72,66 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
@MockBean
|
@MockBean
|
||||||
HttpServletRequest request;
|
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<Object[]> 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
|
@Nested
|
||||||
class CreateAsset {
|
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<Object[]> 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) {
|
private HsHostingAssetRealEntity givenSomeTemporaryAsset(final String projectCaption, final String identifier) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context("superuser-alex@hostsharing.net"); // needed to determine creator
|
context("superuser-alex@hostsharing.net"); // needed to determine creator
|
||||||
|
@ -610,7 +610,7 @@ public abstract class BaseOfficeDataImport extends CsvDataImport {
|
|||||||
deleteTestDataFromHsOfficeTables();
|
deleteTestDataFromHsOfficeTables();
|
||||||
resetHsOfficeSequences();
|
resetHsOfficeSequences();
|
||||||
deleteFromTestTables();
|
deleteFromTestTables();
|
||||||
deleteFromRbacTables();
|
deleteFromCommonTables();
|
||||||
|
|
||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
context(rbacSuperuser);
|
context(rbacSuperuser);
|
||||||
|
@ -249,8 +249,11 @@ public class CsvDataImport extends ContextBasedTest {
|
|||||||
context(rbacSuperuser);
|
context(rbacSuperuser);
|
||||||
// TODO.perf: could we instead skip creating test-data based on an env var?
|
// 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 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 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 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 where true").executeUpdate();
|
||||||
em.createNativeQuery("delete from hs_office_coopassetstransaction_legacy_id 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();
|
em.createNativeQuery("delete from hs_office_coopsharestransaction where true").executeUpdate();
|
||||||
@ -292,7 +295,7 @@ public class CsvDataImport extends ContextBasedTest {
|
|||||||
}).assertSuccessful();
|
}).assertSuccessful();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void deleteFromRbacTables() {
|
protected void deleteFromCommonTables() {
|
||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
context(rbacSuperuser);
|
context(rbacSuperuser);
|
||||||
em.createNativeQuery("delete from rbacuser_rv where name not like 'superuser-%'").executeUpdate();
|
em.createNativeQuery("delete from rbacuser_rv where name not like 'superuser-%'").executeUpdate();
|
||||||
|
@ -271,7 +271,7 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'iban'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_bankaccount';
|
where targettable = 'hs_office_bankaccount';
|
||||||
""");
|
""");
|
||||||
@ -281,8 +281,9 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTestWithC
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating bankaccount test-data First GmbH, hs_office_bankaccount, INSERT]",
|
"[creating bankaccount test-data, hs_office_bankaccount, INSERT, DE02120300000000202051]",
|
||||||
"[creating bankaccount test-data Second e.K., hs_office_bankaccount, INSERT]");
|
"[creating bankaccount test-data, hs_office_bankaccount, INSERT, DE02500105170137075030]",
|
||||||
|
"[creating bankaccount test-data, hs_office_bankaccount, INSERT, DE02100500000054540402]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeBankAccountEntity givenSomeTemporaryBankAccount(final String createdByUser) {
|
private HsOfficeBankAccountEntity givenSomeTemporaryBankAccount(final String createdByUser) {
|
||||||
|
@ -256,7 +256,7 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'caption'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_contact';
|
where targettable = 'hs_office_contact';
|
||||||
""");
|
""");
|
||||||
@ -266,8 +266,9 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating contact test-data first contact, hs_office_contact, INSERT]",
|
"[creating contact test-data, hs_office_contact, INSERT, first contact]",
|
||||||
"[creating contact test-data second contact, hs_office_contact, INSERT]");
|
"[creating contact test-data, hs_office_contact, INSERT, second contact]",
|
||||||
|
"[creating contact test-data, hs_office_contact, INSERT, third contact]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeContactRbacEntity givenSomeTemporaryContact(
|
private HsOfficeContactRbacEntity givenSomeTemporaryContact(
|
||||||
|
@ -220,7 +220,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'reference'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_coopassetstransaction';
|
where targettable = 'hs_office_coopassetstransaction';
|
||||||
""");
|
""");
|
||||||
@ -230,8 +230,18 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating coopAssetsTransaction test-data 1000101, hs_office_coopassetstransaction, INSERT]",
|
"[creating coopAssetsTransaction test-data, hs_office_coopassetstransaction, INSERT, ref 1000101-1]",
|
||||||
"[creating coopAssetsTransaction test-data 1000202, hs_office_coopassetstransaction, INSERT]");
|
"[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
|
@BeforeEach
|
||||||
|
@ -219,7 +219,7 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'reference'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_coopsharestransaction';
|
where targettable = 'hs_office_coopsharestransaction';
|
||||||
""");
|
""");
|
||||||
@ -229,8 +229,18 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating coopSharesTransaction test-data 1000101, hs_office_coopsharestransaction, INSERT]",
|
"[creating coopSharesTransaction test-data, hs_office_coopsharestransaction, INSERT, ref 1000101-1]",
|
||||||
"[creating coopSharesTransaction test-data 1000202, hs_office_coopsharestransaction, INSERT]");
|
"[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
|
@BeforeEach
|
||||||
|
@ -589,7 +589,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'defaultprefix'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_debitor';
|
where targettable = 'hs_office_debitor';
|
||||||
""");
|
""");
|
||||||
@ -599,8 +599,9 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating debitor test-data FirstGmbH-firstcontact, hs_office_debitor, INSERT]",
|
"[creating debitor test-data, hs_office_debitor, INSERT, fir]",
|
||||||
"[creating debitor test-data Seconde.K.-secondcontact, hs_office_debitor, INSERT]");
|
"[creating debitor test-data, hs_office_debitor, INSERT, sec]",
|
||||||
|
"[creating debitor test-data, hs_office_debitor, INSERT, thi]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeDebitorEntity givenSomeTemporaryDebitor(
|
private HsOfficeDebitorEntity givenSomeTemporaryDebitor(
|
||||||
|
@ -336,7 +336,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'membernumbersuffix'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_membership';
|
where targettable = 'hs_office_membership';
|
||||||
""");
|
""");
|
||||||
@ -346,9 +346,9 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating Membership test-data P-10001M-...01, hs_office_membership, INSERT]",
|
"[creating Membership test-data, hs_office_membership, INSERT, 01]",
|
||||||
"[creating Membership test-data P-10002M-...02, hs_office_membership, INSERT]",
|
"[creating Membership test-data, hs_office_membership, INSERT, 02]",
|
||||||
"[creating Membership test-data P-10003M-...03, hs_office_membership, INSERT]");
|
"[creating Membership test-data, hs_office_membership, INSERT, 03]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeMembershipEntity givenSomeTemporaryMembership(final String partnerTradeName, final String memberNumberSuffix) {
|
private HsOfficeMembershipEntity givenSomeTemporaryMembership(final String partnerTradeName, final String memberNumberSuffix) {
|
||||||
|
@ -433,7 +433,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'partnernumber'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_partner';
|
where targettable = 'hs_office_partner';
|
||||||
""");
|
""");
|
||||||
@ -443,8 +443,11 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating partner test-data FirstGmbH-firstcontact, hs_office_partner, INSERT]",
|
"[creating partner test-data , hs_office_partner, INSERT, 10001]",
|
||||||
"[creating partner test-data Seconde.K.-secondcontact, hs_office_partner, INSERT]");
|
"[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(
|
private HsOfficePartnerEntity givenSomeTemporaryHostsharingPartner(
|
||||||
|
@ -260,7 +260,7 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'tradename', targetdelta->>'lastname'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_person';
|
where targettable = 'hs_office_person';
|
||||||
""");
|
""");
|
||||||
@ -270,8 +270,10 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating person test-data First GmbH, hs_office_person, INSERT]",
|
"[creating person test-data, hs_office_person, INSERT, Hostsharing eG, null]",
|
||||||
"[creating person test-data Second e.K., Smith, Peter, hs_office_person, INSERT]");
|
"[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(
|
private HsOfficePersonEntity givenSomeTemporaryPerson(
|
||||||
|
@ -394,7 +394,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'mark'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_relation';
|
where targettable = 'hs_office_relation';
|
||||||
""");
|
""");
|
||||||
@ -404,8 +404,7 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating relation test-data HostsharingeG-FirstGmbH, hs_office_relation, INSERT]",
|
"[creating relation test-data, hs_office_relation, INSERT, members-announce]");
|
||||||
"[creating relation test-data FirstGmbH-Firby, hs_office_relation, INSERT]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeRelationRbacEntity givenSomeTemporaryRelationBessler(final String holderPerson, final String contact) {
|
private HsOfficeRelationRbacEntity givenSomeTemporaryRelationBessler(final String holderPerson, final String contact) {
|
||||||
|
@ -379,7 +379,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC
|
|||||||
public void auditJournalLogIsAvailable() {
|
public void auditJournalLogIsAvailable() {
|
||||||
// given
|
// given
|
||||||
final var query = em.createNativeQuery("""
|
final var query = em.createNativeQuery("""
|
||||||
select currentTask, targetTable, targetOp
|
select currentTask, targetTable, targetOp, targetdelta->>'reference'
|
||||||
from tx_journal_v
|
from tx_journal_v
|
||||||
where targettable = 'hs_office_sepamandate';
|
where targettable = 'hs_office_sepamandate';
|
||||||
""");
|
""");
|
||||||
@ -389,9 +389,9 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
"[creating SEPA-mandate test-data 1000111, hs_office_sepamandate, INSERT]",
|
"[creating SEPA-mandate test-data, hs_office_sepamandate, INSERT, ref-10001-11]",
|
||||||
"[creating SEPA-mandate test-data 1000212, hs_office_sepamandate, INSERT]",
|
"[creating SEPA-mandate test-data, hs_office_sepamandate, INSERT, ref-10002-12]",
|
||||||
"[creating SEPA-mandate test-data 1000313, hs_office_sepamandate, INSERT]");
|
"[creating SEPA-mandate test-data, hs_office_sepamandate, INSERT, ref-10003-13]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HsOfficeSepaMandateEntity givenSomeTemporarySepaMandate(final String iban) {
|
private HsOfficeSepaMandateEntity givenSomeTemporarySepaMandate(final String iban) {
|
||||||
|
@ -9,6 +9,7 @@ import org.springframework.context.annotation.Import;
|
|||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
@Import(RbacGrantsDiagramService.class)
|
@Import(RbacGrantsDiagramService.class)
|
||||||
public abstract class ContextBasedTest {
|
public abstract class ContextBasedTest {
|
||||||
@ -47,4 +48,26 @@ public abstract class ContextBasedTest {
|
|||||||
protected void context(final String currentUser) {
|
protected void context(final String currentUser) {
|
||||||
context(currentUser, null);
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user