add refundBankAccount to hs_office_debitor
This commit is contained in:
parent
d98b8feaad
commit
6b6f8127bb
@ -2,8 +2,8 @@ package net.hostsharing.hsadminng.hs.office.debitor;
|
|||||||
|
|
||||||
import net.hostsharing.hsadminng.Mapper;
|
import net.hostsharing.hsadminng.Mapper;
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeDebitorsApi;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeDebitorsApi;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
|
||||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
||||||
@ -35,12 +35,6 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private HsOfficeDebitorRepository debitorRepo;
|
private HsOfficeDebitorRepository debitorRepo;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private HsOfficePartnerRepository partnerRepo;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private HsOfficeContactRepository contactRepo;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EntityManager em;
|
private EntityManager em;
|
||||||
|
|
||||||
@ -141,10 +135,16 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
|
|||||||
final BiConsumer<HsOfficeDebitorEntity, HsOfficeDebitorResource> DEBITOR_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
final BiConsumer<HsOfficeDebitorEntity, HsOfficeDebitorResource> DEBITOR_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
||||||
resource.setPartner(map(entity.getPartner(), HsOfficePartnerResource.class));
|
resource.setPartner(map(entity.getPartner(), HsOfficePartnerResource.class));
|
||||||
resource.setBillingContact(map(entity.getBillingContact(), HsOfficeContactResource.class));
|
resource.setBillingContact(map(entity.getBillingContact(), HsOfficeContactResource.class));
|
||||||
|
if ( entity.getRefundBankAccount() != null ) {
|
||||||
|
resource.setRefundBankAccount(map(entity.getRefundBankAccount(), HsOfficeBankAccountResource.class));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final BiConsumer<HsOfficeDebitorInsertResource, HsOfficeDebitorEntity> DEBITOR_RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
final BiConsumer<HsOfficeDebitorInsertResource, HsOfficeDebitorEntity> DEBITOR_RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
||||||
entity.setPartner(em.getReference(HsOfficePartnerEntity.class, resource.getPartnerUuid()));
|
entity.setPartner(em.getReference(HsOfficePartnerEntity.class, resource.getPartnerUuid()));
|
||||||
entity.setBillingContact(em.getReference(HsOfficeContactEntity.class, resource.getBillingContactUuid()));
|
entity.setBillingContact(em.getReference(HsOfficeContactEntity.class, resource.getBillingContactUuid()));
|
||||||
|
if ( resource.getRefundBankAccountUuid() != null ) {
|
||||||
|
entity.setRefundBankAccount(em.getReference(HsOfficeBankAccountEntity.class, resource.getRefundBankAccountUuid()));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import lombok.*;
|
|||||||
import net.hostsharing.hsadminng.errors.DisplayName;
|
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||||
import net.hostsharing.hsadminng.Stringify;
|
import net.hostsharing.hsadminng.Stringify;
|
||||||
import net.hostsharing.hsadminng.Stringifyable;
|
import net.hostsharing.hsadminng.Stringifyable;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||||
|
|
||||||
@ -45,6 +46,12 @@ public class HsOfficeDebitorEntity implements Stringifyable {
|
|||||||
private @Column(name = "vatcountrycode") String vatCountryCode;
|
private @Column(name = "vatcountrycode") String vatCountryCode;
|
||||||
private @Column(name = "vatbusiness") boolean vatBusiness;
|
private @Column(name = "vatbusiness") boolean vatBusiness;
|
||||||
|
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "refundbankaccountuuid")
|
||||||
|
private HsOfficeBankAccountEntity refundBankAccount;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return stringify.apply(this);
|
return stringify.apply(this);
|
||||||
|
@ -25,6 +25,8 @@ components:
|
|||||||
pattern: '^[A_Z][A-Z]$'
|
pattern: '^[A_Z][A-Z]$'
|
||||||
vatBusiness:
|
vatBusiness:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
refundBankAccount:
|
||||||
|
$ref: './hs-office-bankaccount-schemas.yaml#/components/schemas/HsOfficeBankAccount'
|
||||||
|
|
||||||
HsOfficeDebitorPatch:
|
HsOfficeDebitorPatch:
|
||||||
type: object
|
type: object
|
||||||
@ -43,6 +45,10 @@ components:
|
|||||||
vatBusiness:
|
vatBusiness:
|
||||||
type: boolean
|
type: boolean
|
||||||
nullable: true
|
nullable: true
|
||||||
|
refundBankAccountUuid:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
|
||||||
HsOfficeDebitorInsert:
|
HsOfficeDebitorInsert:
|
||||||
type: object
|
type: object
|
||||||
@ -65,6 +71,9 @@ components:
|
|||||||
pattern: '^[A_Z][A-Z]$'
|
pattern: '^[A_Z][A-Z]$'
|
||||||
vatBusiness:
|
vatBusiness:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
refundBankAccountUuid:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
required:
|
required:
|
||||||
- partnerUuid
|
- partnerUuid
|
||||||
- billingContactUuid
|
- billingContactUuid
|
||||||
|
@ -22,7 +22,7 @@ declare
|
|||||||
contact hs_office_contact;
|
contact hs_office_contact;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
idName := cleanIdentifier( anchorPersonTradeName|| '-' || holderPersonFamilyName);
|
idName := cleanIdentifier( anchorPersonTradeName || '-' || holderPersonFamilyName);
|
||||||
currentTask := 'creating RBAC test relationship ' || idName;
|
currentTask := 'creating RBAC test relationship ' || idName;
|
||||||
call defineContext(currentTask, 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);
|
execute format('set local hsadminng.currentTask to %L', currentTask);
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
### hs_office_bankaccount RBAC Roles
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
|
||||||
|
%% ---------- generated start: ----------
|
||||||
|
|
||||||
|
subgraph global
|
||||||
|
role:global.admin[global.admin]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph context
|
||||||
|
user:current([current])
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph bankaccount
|
||||||
|
|
||||||
|
subgraph roles[ ]
|
||||||
|
role:bankaccount.owner[[bankaccount.owner]]
|
||||||
|
role:bankaccount.admin[[bankaccount.admin]]
|
||||||
|
role:bankaccount.tenant[[bankaccount.tenant]]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph perms[ ]
|
||||||
|
perm:bankaccount.delete{{bankaccount.delete}}
|
||||||
|
perm:bankaccount.view{{bankaccount.view}}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
%% ---------- generated end. ----------
|
||||||
|
|
||||||
|
role:bankaccount.owner --> perm:bankaccount.delete
|
||||||
|
|
||||||
|
role:global.admin --> role:bankaccount.owner
|
||||||
|
user:current --> role:bankaccount.owner
|
||||||
|
|
||||||
|
role:bankaccount.owner --> role:bankaccount.admin
|
||||||
|
|
||||||
|
role:bankaccount.admin --> role:bankaccount.tenant
|
||||||
|
role:bankaccount.tenant --> perm:bankaccount.view
|
||||||
|
```
|
||||||
|
|
@ -28,6 +28,7 @@ create or replace function createRbacRolesForHsOfficeBankAccount()
|
|||||||
strict as $$
|
strict as $$
|
||||||
declare
|
declare
|
||||||
ownerRole uuid;
|
ownerRole uuid;
|
||||||
|
adminRole uuid;
|
||||||
begin
|
begin
|
||||||
if TG_OP <> 'INSERT' then
|
if TG_OP <> 'INSERT' then
|
||||||
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
raise exception 'invalid usage of TRIGGER AFTER INSERT';
|
||||||
@ -43,15 +44,22 @@ begin
|
|||||||
grantedByRole(globalAdmin())
|
grantedByRole(globalAdmin())
|
||||||
);
|
);
|
||||||
|
|
||||||
-- TODO.spec: assumption can not be updated
|
-- the admin role for those related users who can view the data and related records
|
||||||
|
adminRole := createRole(
|
||||||
|
hsOfficeBankAccountAdmin(NEW),
|
||||||
-- Where bankaccounts can be created, assigned, re-assigned and deleted, they cannot be updated.
|
-- Where bankaccounts can be created, assigned, re-assigned and deleted, they cannot be updated.
|
||||||
-- Thus SQL UPDATE and 'edit' permission are being implemented.
|
-- Thus SQL UPDATE and 'edit' permission are being implemented.
|
||||||
|
withoutPermissions(),
|
||||||
|
beneathRole(ownerRole)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- TODO.spec: assumption can not be updated
|
||||||
|
|
||||||
-- the tenant role for those related users who can view the data
|
-- the tenant role for those related users who can view the data
|
||||||
perform createRole(
|
perform createRole(
|
||||||
hsOfficeBankAccountTenant(NEW),
|
hsOfficeBankAccountTenant(NEW),
|
||||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']),
|
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']),
|
||||||
beneathRole(ownerRole)
|
beneathRole(adminRole)
|
||||||
);
|
);
|
||||||
|
|
||||||
return NEW;
|
return NEW;
|
||||||
|
@ -13,7 +13,7 @@ create table hs_office_debitor
|
|||||||
vatId varchar(24), -- TODO.spec: here or in person?
|
vatId varchar(24), -- TODO.spec: here or in person?
|
||||||
vatCountryCode varchar(2),
|
vatCountryCode varchar(2),
|
||||||
vatBusiness boolean not null, -- TODO.spec: more of such?
|
vatBusiness boolean not null, -- TODO.spec: more of such?
|
||||||
bankAccountUuid uuid references hs_office_bankaccount(uuid)
|
refundBankAccountUuid uuid references hs_office_bankaccount(uuid)
|
||||||
-- TODO.impl: SEPA-mandate
|
-- TODO.impl: SEPA-mandate
|
||||||
);
|
);
|
||||||
--//
|
--//
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
flowchart TB;
|
flowchart TB;
|
||||||
|
|
||||||
subgraph bankaccount;
|
subgraph bankaccount;
|
||||||
direction TB;
|
|
||||||
|
|
||||||
%% oversimplified version for now
|
%% oversimplified version for now
|
||||||
%%
|
%%
|
||||||
@ -13,36 +12,36 @@ direction TB;
|
|||||||
%% e.g. package admins could see the debitors bank account,
|
%% e.g. package admins could see the debitors bank account,
|
||||||
%% except if we do NOT use the debitor in the hosting super module.
|
%% except if we do NOT use the debitor in the hosting super module.
|
||||||
|
|
||||||
%% role:bankaccount.owner
|
role:bankaccount.tenant --> perm:bankaccount.view{{bankaccount.view}};
|
||||||
role:bankaccount.owner --> perm:bankaccount.*;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
subgraph debitor[" "];
|
subgraph debitor[" "];
|
||||||
direction TB;
|
direction TB;
|
||||||
|
|
||||||
%% role:debitor.owner
|
role:debitor.owner[[debitor.owner]]
|
||||||
role:debitor.owner --> perm:debitor.*;
|
role:debitor.owner --> perm:debitor.*{{debitor.*}};
|
||||||
role:debitor.owner --> role:bankaccount.owner;
|
|
||||||
|
|
||||||
%% role:debitor.admin
|
role:debitor.admin[[debitor.admin]]
|
||||||
role:debitor.admin --> perm:debitor.edit;
|
%% super-roles
|
||||||
role:debitor.owner --> role:debitor.admin;
|
role:debitor.owner --> role:debitor.admin;
|
||||||
|
role:partner.admin --> role:debitor.admin;
|
||||||
|
role:person.admin --> role:debitor.admin;
|
||||||
|
role:contact.admin --> role:debitor.admin;
|
||||||
|
%% sub-roles
|
||||||
|
role:debitor.admin --> role:partner.tenant;
|
||||||
|
role:debitor.admin --> role:person.tenant;
|
||||||
|
role:debitor.admin --> role:contact.tenant;
|
||||||
|
role:debitor.admin --> role:bankaccount.tenant;
|
||||||
|
|
||||||
%% role:debitor.tenant
|
role:debitor.tenant[[debitor.tenant]]
|
||||||
role:debitor.tenant --> perm:debitor.view;
|
role:debitor.tenant --> perm:debitor.view{{debitor.view}};
|
||||||
%% super-roles
|
%% super-roles
|
||||||
role:debitor.admin --> role:debitor.tenant;
|
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
|
%% sub-roles
|
||||||
role:debitor.tenant --> role:partner.tenant;
|
|
||||||
role:debitor.tenant --> role:person.tenant;
|
|
||||||
role:debitor.tenant --> role:contact.tenant;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
subgraph global;
|
subgraph global;
|
||||||
direction TB;
|
|
||||||
role:global.admin --> role:debitor.owner;
|
role:global.admin --> role:debitor.owner;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ declare
|
|||||||
newPerson hs_office_person;
|
newPerson hs_office_person;
|
||||||
oldContact hs_office_contact;
|
oldContact hs_office_contact;
|
||||||
newContact hs_office_contact;
|
newContact hs_office_contact;
|
||||||
|
newBankAccount hs_office_bankaccount;
|
||||||
begin
|
begin
|
||||||
|
|
||||||
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
|
hsOfficeDebitorTenant := hsOfficeDebitorTenant(NEW);
|
||||||
@ -42,7 +43,7 @@ begin
|
|||||||
select * from hs_office_partner as p where p.uuid = NEW.partnerUuid into newPartner;
|
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_person as p where p.uuid = newPartner.personUuid into newPerson;
|
||||||
select * from hs_office_contact as c where c.uuid = NEW.billingContactUuid into newContact;
|
select * from hs_office_contact as c where c.uuid = NEW.billingContactUuid into newContact;
|
||||||
|
select * from hs_office_bankaccount as b where b.uuid = NEW.refundBankAccountUuid into newBankAccount;
|
||||||
if TG_OP = 'INSERT' then
|
if TG_OP = 'INSERT' then
|
||||||
|
|
||||||
-- the owner role with full access for the global admins
|
-- the owner role with full access for the global admins
|
||||||
@ -55,23 +56,25 @@ begin
|
|||||||
-- the admin role with full access for owner
|
-- the admin role with full access for owner
|
||||||
adminRole = createRole(
|
adminRole = createRole(
|
||||||
hsOfficeDebitorAdmin(NEW),
|
hsOfficeDebitorAdmin(NEW),
|
||||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['edit']),
|
withoutPermissions(),
|
||||||
beneathRole(ownerRole)
|
beneathRoles(array [
|
||||||
|
hsOfficeDebitorOwner(NEW),
|
||||||
|
hsOfficePartnerAdmin(newPartner),
|
||||||
|
hsOfficePersonAdmin(newPerson),
|
||||||
|
hsOfficeContactAdmin(newContact),
|
||||||
|
hsOfficeBankAccountAdmin(newBankAccount)]),
|
||||||
|
withSubRoles(array [
|
||||||
|
hsOfficePartnerTenant(newPartner),
|
||||||
|
hsOfficePersonTenant(newPerson),
|
||||||
|
hsOfficeContactTenant(newContact),
|
||||||
|
hsOfficeBankAccountTenant(newBankAccount)])
|
||||||
);
|
);
|
||||||
|
|
||||||
-- the tenant role for those related users who can view the data
|
-- the tenant role for those related users who can view the data
|
||||||
perform createRole(
|
perform createRole(
|
||||||
hsOfficeDebitorTenant,
|
hsOfficeDebitorTenant,
|
||||||
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']),
|
grantingPermissions(forObjectUuid => NEW.uuid, permitOps => array ['view']),
|
||||||
beneathRoles(array[
|
beneathRole(hsOfficeDebitorAdmin(NEW))
|
||||||
hsOfficeDebitorAdmin(NEW),
|
|
||||||
hsOfficePartnerAdmin(newPartner),
|
|
||||||
hsOfficePersonAdmin(newPerson),
|
|
||||||
hsOfficeContactAdmin(newContact)]),
|
|
||||||
withSubRoles(array[
|
|
||||||
hsOfficePartnerTenant(newPartner),
|
|
||||||
hsOfficePersonTenant(newPerson),
|
|
||||||
hsOfficeContactTenant(newContact)])
|
|
||||||
);
|
);
|
||||||
|
|
||||||
elsif TG_OP = 'UPDATE' then
|
elsif TG_OP = 'UPDATE' then
|
||||||
@ -79,21 +82,23 @@ begin
|
|||||||
if OLD.partnerUuid <> NEW.partnerUuid then
|
if OLD.partnerUuid <> NEW.partnerUuid then
|
||||||
select * from hs_office_partner as p where p.uuid = OLD.partnerUuid into oldPartner;
|
select * from hs_office_partner as p where p.uuid = OLD.partnerUuid into oldPartner;
|
||||||
|
|
||||||
call revokeRoleFromRole( hsOfficeDebitorTenant, hsOfficePartnerAdmin(oldPartner) );
|
call revokeRoleFromRole(hsOfficeDebitorAdmin(OLD), hsOfficePartnerAdmin(oldPartner));
|
||||||
call grantRoleToRole( hsOfficeDebitorTenant, hsOfficePartnerAdmin(newPartner) );
|
call grantRoleToRole(hsOfficeDebitorAdmin(NEW), hsOfficePartnerAdmin(newPartner));
|
||||||
|
|
||||||
call revokeRoleFromRole( hsOfficePartnerTenant(oldPartner), hsOfficeDebitorTenant );
|
call revokeRoleFromRole(hsOfficePartnerTenant(oldPartner), hsOfficeDebitorAdmin(OLD));
|
||||||
call grantRoleToRole( hsOfficePartnerTenant(newPartner), hsOfficeDebitorTenant );
|
call grantRoleToRole(hsOfficePartnerTenant(newPartner), hsOfficeDebitorAdmin(NEW));
|
||||||
|
|
||||||
|
-- TODO: What about the person of the partner? And what if the person of the partner changes?
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if OLD.billingContactUuid <> NEW.billingContactUuid then
|
if OLD.billingContactUuid <> NEW.billingContactUuid then
|
||||||
select * from hs_office_contact as c where c.uuid = OLD.billingContactUuid into oldContact;
|
select * from hs_office_contact as c where c.uuid = OLD.billingContactUuid into oldContact;
|
||||||
|
|
||||||
call revokeRoleFromRole( hsOfficeDebitorTenant, hsOfficeContactAdmin(oldContact) );
|
call revokeRoleFromRole(hsOfficeDebitorAdmin(OLD), hsOfficeContactAdmin(oldContact));
|
||||||
call grantRoleToRole( hsOfficeDebitorTenant, hsOfficeContactAdmin(newContact) );
|
call grantRoleToRole(hsOfficeDebitorAdmin(NEW), hsOfficeContactAdmin(newContact));
|
||||||
|
|
||||||
call revokeRoleFromRole( hsOfficeContactTenant(oldContact), hsOfficeDebitorTenant );
|
call revokeRoleFromRole(hsOfficeContactTenant(oldContact), hsOfficeDebitorAdmin(OLD));
|
||||||
call grantRoleToRole( hsOfficeContactTenant(newContact), hsOfficeDebitorTenant );
|
call grantRoleToRole(hsOfficeContactTenant(newContact), hsOfficeDebitorAdmin(NEW));
|
||||||
end if;
|
end if;
|
||||||
else
|
else
|
||||||
raise exception 'invalid usage of TRIGGER';
|
raise exception 'invalid usage of TRIGGER';
|
||||||
|
@ -15,6 +15,7 @@ declare
|
|||||||
idName varchar;
|
idName varchar;
|
||||||
relatedPartner hs_office_partner;
|
relatedPartner hs_office_partner;
|
||||||
relatedContact hs_office_contact;
|
relatedContact hs_office_contact;
|
||||||
|
relatedBankAccountUuid uuid;
|
||||||
newDebitorNumber numeric(6);
|
newDebitorNumber numeric(6);
|
||||||
begin
|
begin
|
||||||
idName := cleanIdentifier( partnerTradeName|| '-' || billingContactLabel);
|
idName := cleanIdentifier( partnerTradeName|| '-' || billingContactLabel);
|
||||||
@ -26,14 +27,15 @@ begin
|
|||||||
join hs_office_person person on person.uuid = partner.personUuid
|
join hs_office_person person on person.uuid = partner.personUuid
|
||||||
where person.tradeName = partnerTradeName into relatedPartner;
|
where person.tradeName = partnerTradeName into relatedPartner;
|
||||||
select c.* from hs_office_contact c where c.label = billingContactLabel into relatedContact;
|
select c.* from hs_office_contact c where c.label = billingContactLabel into relatedContact;
|
||||||
|
select b.uuid from hs_office_bankaccount b where b.holder = partnerTradeName into relatedBankAccountUuid;
|
||||||
select coalesce(max(debitorNumber)+1, 10001) from hs_office_debitor into newDebitorNumber;
|
select coalesce(max(debitorNumber)+1, 10001) from hs_office_debitor into newDebitorNumber;
|
||||||
|
|
||||||
raise notice 'creating test debitor: % (#%)', idName, newDebitorNumber;
|
raise notice 'creating test debitor: % (#%)', idName, newDebitorNumber;
|
||||||
raise notice '- using partner (%): %', relatedPartner.uuid, relatedPartner;
|
raise notice '- using partner (%): %', relatedPartner.uuid, relatedPartner;
|
||||||
raise notice '- using billingContact (%): %', relatedContact.uuid, relatedContact;
|
raise notice '- using billingContact (%): %', relatedContact.uuid, relatedContact;
|
||||||
insert
|
insert
|
||||||
into hs_office_debitor (uuid, partneruuid, debitornumber, billingcontactuuid, vatbusiness)
|
into hs_office_debitor (uuid, partneruuid, debitornumber, billingcontactuuid, vatbusiness, refundbankaccountuuid)
|
||||||
values (uuid_generate_v4(), relatedPartner.uuid, newDebitorNumber, relatedContact.uuid, true);
|
values (uuid_generate_v4(), relatedPartner.uuid, newDebitorNumber, relatedContact.uuid, true, relatedBankAccountUuid);
|
||||||
end; $$;
|
end; $$;
|
||||||
--//
|
--//
|
||||||
|
|
||||||
|
@ -343,6 +343,12 @@ class HsOfficeBankAccountControllerAcceptanceTest {
|
|||||||
@BeforeEach
|
@BeforeEach
|
||||||
@AfterEach
|
@AfterEach
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context.define("superuser-alex@hostsharing.net", null);
|
||||||
|
tempBankAccountUuids.addAll(
|
||||||
|
bankAccountRepo.findByOptionalHolderLike("some temp acc").stream().map(HsOfficeBankAccountEntity::getUuid).toList()
|
||||||
|
);
|
||||||
|
});
|
||||||
tempBankAccountUuids.forEach(uuid -> {
|
tempBankAccountUuids.forEach(uuid -> {
|
||||||
jpaAttempt.transacted(() -> {
|
jpaAttempt.transacted(() -> {
|
||||||
context.define("superuser-alex@hostsharing.net", null);
|
context.define("superuser-alex@hostsharing.net", null);
|
||||||
|
@ -109,13 +109,15 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTest {
|
|||||||
assertThat(roleNamesOf(roles)).containsExactlyInAnyOrder(Array.from(
|
assertThat(roleNamesOf(roles)).containsExactlyInAnyOrder(Array.from(
|
||||||
initialRoleNames,
|
initialRoleNames,
|
||||||
"hs_office_bankaccount#sometempaccC.owner",
|
"hs_office_bankaccount#sometempaccC.owner",
|
||||||
|
"hs_office_bankaccount#sometempaccC.admin",
|
||||||
"hs_office_bankaccount#sometempaccC.tenant"
|
"hs_office_bankaccount#sometempaccC.tenant"
|
||||||
));
|
));
|
||||||
assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.from(
|
assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.from(
|
||||||
initialGrantNames,
|
initialGrantNames,
|
||||||
"{ grant role hs_office_bankaccount#sometempaccC.owner to role global#global.admin by system and assume }",
|
"{ grant role hs_office_bankaccount#sometempaccC.owner to role global#global.admin by system and assume }",
|
||||||
"{ grant perm delete on hs_office_bankaccount#sometempaccC to role hs_office_bankaccount#sometempaccC.owner by system and assume }",
|
"{ grant perm delete on hs_office_bankaccount#sometempaccC to role hs_office_bankaccount#sometempaccC.owner by system and assume }",
|
||||||
"{ grant role hs_office_bankaccount#sometempaccC.tenant to role hs_office_bankaccount#sometempaccC.owner by system and assume }",
|
"{ grant role hs_office_bankaccount#sometempaccC.tenant to role hs_office_bankaccount#sometempaccC.admin by system and assume }",
|
||||||
|
"{ grant role hs_office_bankaccount#sometempaccC.admin to role hs_office_bankaccount#sometempaccC.owner by system and assume }",
|
||||||
"{ grant perm view on hs_office_bankaccount#sometempaccC to role hs_office_bankaccount#sometempaccC.tenant by system and assume }",
|
"{ grant perm view on hs_office_bankaccount#sometempaccC to role hs_office_bankaccount#sometempaccC.tenant by system and assume }",
|
||||||
"{ grant role hs_office_bankaccount#sometempaccC.owner to user selfregistered-user-drew@hostsharing.org by global#global.admin and assume }"
|
"{ grant role hs_office_bankaccount#sometempaccC.owner to user selfregistered-user-drew@hostsharing.org by global#global.admin and assume }"
|
||||||
));
|
));
|
||||||
@ -253,9 +255,9 @@ class HsOfficeBankAccountRepositoryIntegrationTest extends ContextBasedTest {
|
|||||||
final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll());
|
final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll());
|
||||||
final var givenBankAccount = givenSomeTemporaryBankAccount("selfregistered-user-drew@hostsharing.org");
|
final var givenBankAccount = givenSomeTemporaryBankAccount("selfregistered-user-drew@hostsharing.org");
|
||||||
assertThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created")
|
assertThat(rawRoleRepo.findAll().size()).as("unexpected number of roles created")
|
||||||
.isEqualTo(initialRoleNames.size() + 2);
|
.isEqualTo(initialRoleNames.size() + 3);
|
||||||
assertThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created")
|
assertThat(rawGrantRepo.findAll().size()).as("unexpected number of grants created")
|
||||||
.isEqualTo(initialGrantNames.size() + 5);
|
.isEqualTo(initialGrantNames.size() + 6);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
|
@ -8,7 +8,9 @@ import net.hostsharing.hsadminng.context.Context;
|
|||||||
import net.hostsharing.test.JpaAttempt;
|
import net.hostsharing.test.JpaAttempt;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Nested;
|
import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -363,6 +365,7 @@ class HsOfficeContactControllerAcceptanceTest {
|
|||||||
return tempContactUuid;
|
return tempContactUuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
@AfterEach
|
@AfterEach
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
tempContactUuids.forEach(uuid -> {
|
tempContactUuids.forEach(uuid -> {
|
||||||
|
@ -5,6 +5,7 @@ import io.restassured.http.ContentType;
|
|||||||
import net.hostsharing.hsadminng.Accepts;
|
import net.hostsharing.hsadminng.Accepts;
|
||||||
import net.hostsharing.hsadminng.HsadminNgApplication;
|
import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository;
|
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository;
|
||||||
import net.hostsharing.test.JpaAttempt;
|
import net.hostsharing.test.JpaAttempt;
|
||||||
@ -55,6 +56,9 @@ class HsOfficeDebitorControllerAcceptanceTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeContactRepository contactRepo;
|
HsOfficeContactRepository contactRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
HsOfficeBankAccountRepository bankAccountRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
JpaAttempt jpaAttempt;
|
JpaAttempt jpaAttempt;
|
||||||
|
|
||||||
@ -84,7 +88,8 @@ class HsOfficeDebitorControllerAcceptanceTest {
|
|||||||
"billingContact": { "label": "first contact" },
|
"billingContact": { "label": "first contact" },
|
||||||
"vatId": null,
|
"vatId": null,
|
||||||
"vatCountryCode": null,
|
"vatCountryCode": null,
|
||||||
"vatBusiness": true
|
"vatBusiness": true,
|
||||||
|
"refundBankAccount": { "holder": "First GmbH" }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"debitorNumber": 10002,
|
"debitorNumber": 10002,
|
||||||
@ -92,7 +97,8 @@ class HsOfficeDebitorControllerAcceptanceTest {
|
|||||||
"billingContact": { "label": "second contact" },
|
"billingContact": { "label": "second contact" },
|
||||||
"vatId": null,
|
"vatId": null,
|
||||||
"vatCountryCode": null,
|
"vatCountryCode": null,
|
||||||
"vatBusiness": true
|
"vatBusiness": true,
|
||||||
|
"refundBankAccount": { "holder": "Second e.K." }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"debitorNumber": 10003,
|
"debitorNumber": 10003,
|
||||||
@ -100,7 +106,8 @@ class HsOfficeDebitorControllerAcceptanceTest {
|
|||||||
"billingContact": { "label": "third contact" },
|
"billingContact": { "label": "third contact" },
|
||||||
"vatId": null,
|
"vatId": null,
|
||||||
"vatCountryCode": null,
|
"vatCountryCode": null,
|
||||||
"vatBusiness": true
|
"vatBusiness": true,
|
||||||
|
"refundBankAccount": { "holder": "Third OHG" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
"""));
|
"""));
|
||||||
@ -137,10 +144,53 @@ class HsOfficeDebitorControllerAcceptanceTest {
|
|||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@Accepts({ "Debitor:C(Create)" })
|
@Accepts({ "Debitor:C(Create)" })
|
||||||
class AddDebitor {
|
class CreateDebitor {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_withoutAssumedRole_canAddDebitor() {
|
void globalAdmin_withoutAssumedRole_canAddDebitorWithBankAccount() {
|
||||||
|
|
||||||
|
context.define("superuser-alex@hostsharing.net");
|
||||||
|
final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Third").get(0);
|
||||||
|
final var givenContact = contactRepo.findContactByOptionalLabelLike("forth").get(0);
|
||||||
|
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike("Fourth").get(0);
|
||||||
|
|
||||||
|
final var location = RestAssured // @formatter:off
|
||||||
|
.given()
|
||||||
|
.header("current-user", "superuser-alex@hostsharing.net")
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body("""
|
||||||
|
{
|
||||||
|
"partnerUuid": "%s",
|
||||||
|
"billingContactUuid": "%s",
|
||||||
|
"debitorNumber": "%s",
|
||||||
|
"vatId": "VAT123456",
|
||||||
|
"vatCountryCode": "DE",
|
||||||
|
"vatBusiness": true,
|
||||||
|
"refundBankAccountUuid": "%s"
|
||||||
|
}
|
||||||
|
""".formatted( givenPartner.getUuid(), givenContact.getUuid(), nextDebitorNumber++, givenBankAccount.getUuid()))
|
||||||
|
.port(port)
|
||||||
|
.when()
|
||||||
|
.post("http://localhost/api/hs/office/debitors")
|
||||||
|
.then().log().all().assertThat()
|
||||||
|
.statusCode(201)
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body("uuid", isUuidValid())
|
||||||
|
.body("vatId", is("VAT123456"))
|
||||||
|
.body("billingContact.label", is(givenContact.getLabel()))
|
||||||
|
.body("partner.person.tradeName", is(givenPartner.getPerson().getTradeName()))
|
||||||
|
.body("refundBankAccount.holder", is(givenBankAccount.getHolder()))
|
||||||
|
.header("Location", startsWith("http://localhost"))
|
||||||
|
.extract().header("Location"); // @formatter:on
|
||||||
|
|
||||||
|
// finally, the new debitor can be accessed under the generated UUID
|
||||||
|
final var newUserUuid = toCleanup(UUID.fromString(
|
||||||
|
location.substring(location.lastIndexOf('/') + 1)));
|
||||||
|
assertThat(newUserUuid).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void globalAdmin_withoutAssumedRole_canAddDebitorWithoutBankAccount() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Third").get(0);
|
final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Third").get(0);
|
||||||
@ -300,7 +350,8 @@ class HsOfficeDebitorControllerAcceptanceTest {
|
|||||||
.body("", lenientlyEquals("""
|
.body("", lenientlyEquals("""
|
||||||
{
|
{
|
||||||
"partner": { person: { "tradeName": "First GmbH" } },
|
"partner": { person: { "tradeName": "First GmbH" } },
|
||||||
"billingContact": { "label": "first contact" }
|
"billingContact": { "label": "first contact" },
|
||||||
|
"refundBankAccount": { "holder": "First GmbH" }
|
||||||
}
|
}
|
||||||
""")); // @formatter:on
|
""")); // @formatter:on
|
||||||
}
|
}
|
||||||
|
@ -122,21 +122,19 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
|
|||||||
"hs_office_debitor#20002Fourthe.G.-forthcontact.tenant"));
|
"hs_office_debitor#20002Fourthe.G.-forthcontact.tenant"));
|
||||||
assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromSkippingNull(
|
assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(Array.fromSkippingNull(
|
||||||
initialGrantNames,
|
initialGrantNames,
|
||||||
|
|
||||||
"{ grant perm * on hs_office_debitor#20002Fourthe.G.-forthcontact to role hs_office_debitor#20002Fourthe.G.-forthcontact.owner by system and assume }",
|
"{ grant perm * on hs_office_debitor#20002Fourthe.G.-forthcontact to role hs_office_debitor#20002Fourthe.G.-forthcontact.owner by system and assume }",
|
||||||
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.owner to role global#global.admin by system and assume }",
|
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.owner to role global#global.admin by system and assume }",
|
||||||
|
|
||||||
"{ grant perm edit on hs_office_debitor#20002Fourthe.G.-forthcontact to role hs_office_debitor#20002Fourthe.G.-forthcontact.admin by system and assume }",
|
|
||||||
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.admin to role hs_office_debitor#20002Fourthe.G.-forthcontact.owner by system and assume }",
|
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.admin to role hs_office_debitor#20002Fourthe.G.-forthcontact.owner by system and assume }",
|
||||||
|
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.admin to role hs_office_partner#Fourthe.G.-forthcontact.admin by system and assume }",
|
||||||
|
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.admin to role hs_office_person#Fourthe.G..admin by system and assume }",
|
||||||
|
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.admin to role hs_office_contact#forthcontact.admin by system and assume }",
|
||||||
|
"{ grant role hs_office_contact#forthcontact.tenant to role hs_office_debitor#20002Fourthe.G.-forthcontact.admin by system and assume }",
|
||||||
|
"{ grant role hs_office_partner#Fourthe.G.-forthcontact.tenant to role hs_office_debitor#20002Fourthe.G.-forthcontact.admin by system and assume }",
|
||||||
|
"{ grant role hs_office_person#Fourthe.G..tenant to role hs_office_debitor#20002Fourthe.G.-forthcontact.admin by system and assume }",
|
||||||
|
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant to role hs_office_debitor#20002Fourthe.G.-forthcontact.admin by system and assume }",
|
||||||
|
|
||||||
"{ grant perm view on hs_office_debitor#20002Fourthe.G.-forthcontact to role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant by system and assume }",
|
"{ grant perm view on hs_office_debitor#20002Fourthe.G.-forthcontact to role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant by system and assume }",
|
||||||
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant to role hs_office_contact#forthcontact.admin by system and assume }",
|
|
||||||
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant to role hs_office_debitor#20002Fourthe.G.-forthcontact.admin by system and assume }",
|
|
||||||
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant to role hs_office_partner#Fourthe.G.-forthcontact.admin by system and assume }",
|
|
||||||
"{ grant role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant to role hs_office_person#Fourthe.G..admin by system and assume }",
|
|
||||||
"{ grant role hs_office_partner#Fourthe.G.-forthcontact.tenant to role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant by system and assume }",
|
|
||||||
"{ grant role hs_office_contact#forthcontact.tenant to role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant by system and assume }",
|
|
||||||
"{ grant role hs_office_person#Fourthe.G..tenant to role hs_office_debitor#20002Fourthe.G.-forthcontact.tenant by system and assume }",
|
|
||||||
|
|
||||||
null));
|
null));
|
||||||
}
|
}
|
||||||
@ -394,7 +392,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
|
|||||||
assertThat(rawRoleRepo.findAll().size()).as("precondition failed: unexpected number of roles created")
|
assertThat(rawRoleRepo.findAll().size()).as("precondition failed: unexpected number of roles created")
|
||||||
.isEqualTo(initialRoleNames.length + 3);
|
.isEqualTo(initialRoleNames.length + 3);
|
||||||
assertThat(rawGrantRepo.findAll().size()).as("precondition failed: unexpected number of grants created")
|
assertThat(rawGrantRepo.findAll().size()).as("precondition failed: unexpected number of grants created")
|
||||||
.isEqualTo(initialGrantNames.length + 12);
|
.isEqualTo(initialGrantNames.length + 11);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = jpaAttempt.transacted(() -> {
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
|
@ -24,7 +24,10 @@ public class Array {
|
|||||||
|
|
||||||
public static String[] fromSkippingNull(final List<String> initialList, final String... additionalStrings) {
|
public static String[] fromSkippingNull(final List<String> initialList, final String... additionalStrings) {
|
||||||
final var resultList = new ArrayList<>(initialList);
|
final var resultList = new ArrayList<>(initialList);
|
||||||
resultList.addAll(Arrays.stream(additionalStrings).filter(Objects::nonNull).toList());
|
resultList.addAll(Arrays.stream(additionalStrings)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(s -> s.replaceAll(" *", " "))
|
||||||
|
.toList());
|
||||||
return resultList.toArray(String[]::new);
|
return resultList.toArray(String[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user