adds HsOfficePartner
This commit is contained in:
@ -20,3 +20,5 @@ map:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
/api/hs/office/relationships/{relationshipUUID}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
/api/hs/office/debitors/{debitorUUID}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
|
@ -0,0 +1,70 @@
|
||||
|
||||
components:
|
||||
|
||||
schemas:
|
||||
|
||||
HsOfficeDebitor:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
debitorNumber:
|
||||
type: integer
|
||||
format: int32
|
||||
minimum: 10000
|
||||
maximum: 99999
|
||||
partner:
|
||||
$ref: './hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartner'
|
||||
billingContact:
|
||||
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
||||
vatId:
|
||||
type: string
|
||||
vatCountryCode:
|
||||
type: string
|
||||
pattern: '^[A_Z][A-Z]$'
|
||||
vatBusiness:
|
||||
type: boolean
|
||||
|
||||
HsOfficeDebitorPatch:
|
||||
type: object
|
||||
properties:
|
||||
billingContactUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
vatId:
|
||||
type: string
|
||||
nullable: true
|
||||
vatCountryCode:
|
||||
type: string
|
||||
pattern: '^[A_Z][A-Z]$'
|
||||
nullable: true
|
||||
vatBusiness:
|
||||
type: boolean
|
||||
nullable: true
|
||||
|
||||
HsOfficeDebitorInsert:
|
||||
type: object
|
||||
properties:
|
||||
partnerUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
billingContactUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
debitorNumber:
|
||||
type: integer
|
||||
format: int32
|
||||
minimum: 10000
|
||||
maximum: 99999
|
||||
vatId:
|
||||
type: string
|
||||
vatCountryCode:
|
||||
type: string
|
||||
pattern: '^[A_Z][A-Z]$'
|
||||
vatBusiness:
|
||||
type: boolean
|
||||
required:
|
||||
- partnerUuid
|
||||
- billingContactUuid
|
@ -0,0 +1,83 @@
|
||||
get:
|
||||
tags:
|
||||
- hs-office-debitors
|
||||
description: 'Fetch a single debitor by its uuid, if visible for the current subject.'
|
||||
operationId: getDebitorByUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the debitor to fetch.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitor'
|
||||
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
patch:
|
||||
tags:
|
||||
- hs-office-debitors
|
||||
description: 'Updates a single debitor by its uuid, if permitted for the current subject.'
|
||||
operationId: patchDebitor
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
requestBody:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitorPatch'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitor'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- hs-office-debitors
|
||||
description: 'Delete a single debitor by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteDebitorByUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: debitorUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the debitor to delete.
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
"404":
|
||||
$ref: './error-responses.yaml#/components/responses/NotFound'
|
@ -0,0 +1,62 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) debitors.
|
||||
description: Returns the list of (optionally filtered) debitors which are visible to the current user or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-debitors
|
||||
operationId: listDebitors
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: name
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: Prefix of name properties from person or contact to filter the results.
|
||||
- name: debitorNumber
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: integer
|
||||
description: Debitor number of the requested debitor.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: './hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitor'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
post:
|
||||
summary: Adds a new debitor.
|
||||
tags:
|
||||
- hs-office-debitors
|
||||
operationId: addDebitor
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
requestBody:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitorInsert'
|
||||
required: true
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitor'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
"409":
|
||||
$ref: './error-responses.yaml#/components/responses/Conflict'
|
@ -35,7 +35,6 @@ paths:
|
||||
$ref: "./hs-office-persons-with-uuid.yaml"
|
||||
|
||||
|
||||
|
||||
# Relationships
|
||||
|
||||
/api/hs/office/relationships:
|
||||
@ -44,3 +43,11 @@ paths:
|
||||
/api/hs/office/relationships/{relationshipUUID}:
|
||||
$ref: "./hs-office-relationships-with-uuid.yaml"
|
||||
|
||||
|
||||
# Debitors
|
||||
|
||||
/api/hs/office/debitors:
|
||||
$ref: "./hs-office-debitors.yaml"
|
||||
|
||||
/api/hs/office/debitors/{debitorUUID}:
|
||||
$ref: "./hs-office-debitors-with-uuid.yaml"
|
||||
|
@ -63,6 +63,7 @@ do language plpgsql $$
|
||||
call createHsOfficePersonTestData('NATURAL', null, 'Smith', 'Peter');
|
||||
call createHsOfficePersonTestData('LEGAL', 'Second e.K.', 'Sandra', 'Miller');
|
||||
call createHsOfficePersonTestData('SOLE_REPRESENTATION', 'Third OHG');
|
||||
call createHsOfficePersonTestData('SOLE_REPRESENTATION', 'Fourth e.G.');
|
||||
call createHsOfficePersonTestData('JOINT_REPRESENTATION', 'Erben Bessler', 'Mel', 'Bessler');
|
||||
call createHsOfficePersonTestData('NATURAL', null, 'Bessler', 'Anita');
|
||||
call createHsOfficePersonTestData('NATURAL', null, 'Winkler', 'Paul');
|
||||
|
@ -64,10 +64,9 @@ end; $$;
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficePartnerTestData('First GmbH', 'first contact');
|
||||
|
||||
call createHsOfficePartnerTestData('Second e.K.', 'second contact');
|
||||
|
||||
call createHsOfficePartnerTestData('Third OHG', 'third contact');
|
||||
call createHsOfficePartnerTestData('Fourth e.G.', 'forth contact');
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
18
src/main/resources/db/changelog/270-hs-office-debitor.sql
Normal file
18
src/main/resources/db/changelog/270-hs-office-debitor.sql
Normal file
@ -0,0 +1,18 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table hs_office_debitor
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
partnerUuid uuid not null references hs_office_partner(uuid),
|
||||
debitorNumber numeric(5) not null,
|
||||
billingContactUuid uuid not null references hs_office_contact(uuid),
|
||||
vatId varchar(24), -- TODO.spec: here or in person?
|
||||
vatCountryCode varchar(2),
|
||||
vatBusiness boolean not null -- TODO.spec: more of such?
|
||||
-- TODO.impl: SEPA-mandate + bank account
|
||||
);
|
||||
--//
|
@ -0,0 +1,24 @@
|
||||
### hs_office_debitor RBAC Roles
|
||||
|
||||
```mermaid
|
||||
graph TD;
|
||||
%% role:debitor.owner
|
||||
role:debitor.owner --> perm:debitor.*;
|
||||
role:global.admin --> role:debitor.owner;
|
||||
|
||||
%% role:debitor.admin
|
||||
role:debitor.admin --> perm:debitor.edit;
|
||||
role:debitor.owner --> role:debitor.admin;
|
||||
|
||||
%% role:debitor.tenant
|
||||
role:debitor.tenant --> perm:debitor.view;
|
||||
%% super-roles
|
||||
role:debitor.admin --> role:debitor.tenant;
|
||||
role:partner.admin --> role:debitor.tenant;
|
||||
role:person.admin --> role:debitor.tenant;
|
||||
role:contact.admin --> role:debitor.tenant;
|
||||
%% sub-roles
|
||||
role:debitor.tenant --> role:partner.tenant;
|
||||
role:debitor.tenant --> role:person.tenant;
|
||||
role:debitor.tenant --> role:contact.tenant;
|
||||
```
|
192
src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql
Normal file
192
src/main/resources/db/changelog/273-hs-office-debitor-rbac.sql
Normal file
@ -0,0 +1,192 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-OBJECT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRelatedRbacObject('hs_office_debitor');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-ROLE-DESCRIPTORS:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRoleDescriptors('hsOfficeDebitor', 'hs_office_debitor');
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-ROLES-CREATION:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates and updates the roles and their assignments for debitor entities.
|
||||
*/
|
||||
|
||||
create or replace function hsOfficeDebitorRbacRolesTrigger()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
strict as $$
|
||||
declare
|
||||
hsOfficeDebitorTenant RbacRoleDescriptor;
|
||||
ownerRole uuid;
|
||||
adminRole uuid;
|
||||
oldPartner hs_office_partner;
|
||||
newPartner hs_office_partner;
|
||||
newPerson hs_office_person;
|
||||
oldContact hs_office_contact;
|
||||
newContact hs_office_contact;
|
||||
begin
|
||||
|
||||
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
|
||||
|
||||
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newPartner;
|
||||
select * from hs_office_person as p where p.uuid = newPartner.personUuid into newPerson;
|
||||
select * from hs_office_contact as c where c.uuid = NEW.billingContactUuid into newContact;
|
||||
|
||||
if TG_OP = 'INSERT' then
|
||||
|
||||
-- the owner role with full access for the global admins
|
||||
ownerRole = createRole(
|
||||
hsOfficeDebitorOwner(NEW),
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['*']),
|
||||
beneathRole(globalAdmin())
|
||||
);
|
||||
|
||||
-- the admin role with full access for owner
|
||||
adminRole = createRole(
|
||||
hsOfficeDebitorAdmin(NEW),
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['edit']),
|
||||
beneathRole(ownerRole)
|
||||
);
|
||||
|
||||
-- the tenant role for those related users who can view the data
|
||||
perform createRole(
|
||||
hsOfficeDebitorTenant,
|
||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']),
|
||||
beneathRoles(array[
|
||||
hsOfficeDebitorAdmin(NEW),
|
||||
hsOfficePartnerAdmin(newPartner),
|
||||
hsOfficePersonAdmin(newPerson),
|
||||
hsOfficeContactAdmin(newContact)]),
|
||||
withSubRoles(array[
|
||||
hsOfficePartnerTenant(newPartner),
|
||||
hsOfficePersonTenant(newPerson),
|
||||
hsOfficeContactTenant(newContact)])
|
||||
);
|
||||
|
||||
elsif TG_OP = 'UPDATE' then
|
||||
|
||||
if OLD.partnerUuid <> NEW.partnerUuid then
|
||||
select * from hs_office_partner as p where p.uuid = OLD.partnerUuid into oldPartner;
|
||||
|
||||
call revokeRoleFromRole( hsOfficeDebitorTenant, hsOfficePartnerAdmin(oldPartner) );
|
||||
call grantRoleToRole( hsOfficeDebitorTenant, hsOfficePartnerAdmin(newPartner) );
|
||||
|
||||
call revokeRoleFromRole( hsOfficePartnerTenant(oldPartner), hsOfficeDebitorTenant );
|
||||
call grantRoleToRole( hsOfficePartnerTenant(newPartner), hsOfficeDebitorTenant );
|
||||
end if;
|
||||
|
||||
if OLD.billingContactUuid <> NEW.billingContactUuid then
|
||||
select * from hs_office_contact as c where c.uuid = OLD.billingContactUuid into oldContact;
|
||||
|
||||
call revokeRoleFromRole( hsOfficeDebitorTenant, hsOfficeContactAdmin(oldContact) );
|
||||
call grantRoleToRole( hsOfficeDebitorTenant, hsOfficeContactAdmin(newContact) );
|
||||
|
||||
call revokeRoleFromRole( hsOfficeContactTenant(oldContact), hsOfficeDebitorTenant );
|
||||
call grantRoleToRole( hsOfficeContactTenant(newContact), hsOfficeDebitorTenant );
|
||||
end if;
|
||||
else
|
||||
raise exception 'invalid usage of TRIGGER';
|
||||
end if;
|
||||
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
/*
|
||||
An AFTER INSERT TRIGGER which creates the role structure for a new debitor.
|
||||
*/
|
||||
create trigger createRbacRolesForHsOfficeDebitor_Trigger
|
||||
after insert
|
||||
on hs_office_debitor
|
||||
for each row
|
||||
execute procedure hsOfficeDebitorRbacRolesTrigger();
|
||||
|
||||
/*
|
||||
An AFTER UPDATE TRIGGER which updates the role structure of a debitor.
|
||||
*/
|
||||
create trigger updateRbacRolesForHsOfficeDebitor_Trigger
|
||||
after update
|
||||
on hs_office_debitor
|
||||
for each row
|
||||
execute procedure hsOfficeDebitorRbacRolesTrigger();
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacIdentityView('hs_office_debitor', $idName$
|
||||
'#' || debitorNumber || ':' ||
|
||||
(select idName from hs_office_partner_iv p where p.uuid = target.partnerUuid)
|
||||
$idName$);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('hs_office_debitor',
|
||||
'target.debitorNumber',
|
||||
$updates$
|
||||
billingContactUuid = new.billingContactUuid,
|
||||
vatId = new.vatId,
|
||||
vatCountryCode = new.vatCountryCode,
|
||||
vatBusiness = new.vatBusiness
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-rbac-NEW-DEBITOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
/*
|
||||
Creates a global permission for new-debitor and assigns it to the hostsharing admins role.
|
||||
*/
|
||||
do language plpgsql $$
|
||||
declare
|
||||
addDebitorPermissions uuid[];
|
||||
globalObjectUuid uuid;
|
||||
globalAdminRoleUuid uuid ;
|
||||
begin
|
||||
call defineContext('granting global new-debitor permission to global admin role', null, null, null);
|
||||
|
||||
globalAdminRoleUuid := findRoleId(globalAdmin());
|
||||
globalObjectUuid := (select uuid from global);
|
||||
addDebitorPermissions := createPermissions(globalObjectUuid, array ['new-debitor']);
|
||||
call grantPermissionsToRole(globalAdminRoleUuid, addDebitorPermissions);
|
||||
end;
|
||||
$$;
|
||||
|
||||
/**
|
||||
Used by the trigger to prevent the add-debitor to current user respectively assumed roles.
|
||||
*/
|
||||
create or replace function addHsOfficeDebitorNotAllowedForCurrentSubjects()
|
||||
returns trigger
|
||||
language PLPGSQL
|
||||
as $$
|
||||
begin
|
||||
raise exception '[403] new-debitor not permitted for %',
|
||||
array_to_string(currentSubjects(), ';', 'null');
|
||||
end; $$;
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to create a new debitor.
|
||||
*/
|
||||
create trigger hs_office_debitor_insert_trigger
|
||||
before insert
|
||||
on hs_office_debitor
|
||||
for each row
|
||||
-- TODO.spec: who is allowed to create new debitors
|
||||
when ( not hasAssumedRole() )
|
||||
execute procedure addHsOfficeDebitorNotAllowedForCurrentSubjects();
|
||||
--//
|
||||
|
@ -0,0 +1,52 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-TEST-DATA-GENERATOR:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Creates a single debitor test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficeDebitorTestData( partnerTradeName varchar, billingContactLabel varchar )
|
||||
language plpgsql as $$
|
||||
declare
|
||||
currentTask varchar;
|
||||
idName varchar;
|
||||
relatedPartner hs_office_partner;
|
||||
relatedContact hs_office_contact;
|
||||
newDebitorNumber numeric(6);
|
||||
begin
|
||||
idName := cleanIdentifier( partnerTradeName|| '-' || billingContactLabel);
|
||||
currentTask := 'creating RBAC test debitor ' || idName;
|
||||
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
|
||||
join hs_office_person person on person.uuid = partner.personUuid
|
||||
where person.tradeName = partnerTradeName into relatedPartner;
|
||||
select c.* from hs_office_contact c where c.label = billingContactLabel into relatedContact;
|
||||
select coalesce(max(debitorNumber)+1, 10001) from hs_office_debitor into newDebitorNumber;
|
||||
|
||||
raise notice 'creating test debitor: % (#%)', idName, newDebitorNumber;
|
||||
raise notice '- using partner (%): %', relatedPartner.uuid, relatedPartner;
|
||||
raise notice '- using billingContact (%): %', relatedContact.uuid, relatedContact;
|
||||
insert
|
||||
into hs_office_debitor (uuid, partneruuid, debitornumber, billingcontactuuid, vatbusiness)
|
||||
values (uuid_generate_v4(), relatedPartner.uuid, newDebitorNumber, relatedContact.uuid, true);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-debitor-TEST-DATA-GENERATION:1 –context=dev,tc endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficeDebitorTestData('First GmbH', 'first contact');
|
||||
call createHsOfficeDebitorTestData('Second e.K.', 'second contact');
|
||||
call createHsOfficeDebitorTestData('Third OHG', 'third contact');
|
||||
end;
|
||||
$$;
|
||||
--//
|
@ -71,3 +71,9 @@ databaseChangeLog:
|
||||
file: db/changelog/233-hs-office-relationship-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/238-hs-office-relationship-test-data.sql
|
||||
- include:
|
||||
file: db/changelog/270-hs-office-debitor.sql
|
||||
- include:
|
||||
file: db/changelog/273-hs-office-debitor-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/278-hs-office-debitor-test-data.sql
|
||||
|
Reference in New Issue
Block a user