rbac-optimization #80
@ -15,9 +15,6 @@ import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL;
|
||||
import net.hostsharing.hsadminng.stringify.Stringify;
|
||||
import net.hostsharing.hsadminng.stringify.Stringifyable;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.JoinFormula;
|
||||
import org.hibernate.annotations.NotFound;
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
@ -77,22 +74,8 @@ public class HsOfficeDebitorEntity implements RbacObject, Stringifyable {
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
@ManyToOne
|
||||
@JoinFormula(
|
||||
referencedColumnName = "uuid",
|
||||
value = """
|
||||
(
|
||||
SELECT DISTINCT partner.uuid
|
||||
FROM hs_office_partner_rv partner
|
||||
JOIN hs_office_relation_rv dRel
|
||||
ON dRel.uuid = debitorreluuid AND dRel.type = 'DEBITOR'
|
||||
JOIN hs_office_relation_rv pRel
|
||||
ON pRel.uuid = partner.partnerRelUuid AND pRel.type = 'PARTNER'
|
||||
WHERE pRel.holderUuid = dRel.anchorUuid
|
||||
)
|
||||
""")
|
||||
@NotFound(action = NotFoundAction.IGNORE)
|
||||
private HsOfficePartnerEntity partner;
|
||||
@Column(name = "partnernumber", columnDefinition = "numeric(5) not null")
|
||||
private Integer partnerNumber; // redundant to HsOfficePartnerEntity.partnerNumber for performance reasons
|
||||
|
||||
@Column(name = "debitornumbersuffix", length = 2)
|
||||
@Pattern(regexp = TWO_DECIMAL_DIGITS)
|
||||
@ -125,9 +108,8 @@ public class HsOfficeDebitorEntity implements RbacObject, Stringifyable {
|
||||
private String defaultPrefix;
|
||||
|
||||
private String getDebitorNumberString() {
|
||||
return ofNullable(partner)
|
||||
return ofNullable(partnerNumber)
|
||||
.filter(partner -> debitorNumberSuffix != null)
|
||||
.map(HsOfficePartnerEntity::getPartnerNumber)
|
||||
.map(Object::toString)
|
||||
.map(partnerNumber -> partnerNumber + debitorNumberSuffix)
|
||||
.orElse(null);
|
||||
|
@ -28,6 +28,17 @@ public interface HsOfficePartnerRepository extends Repository<HsOfficePartnerEnt
|
||||
List<HsOfficePartnerEntity> findPartnerByOptionalNameLike(String name);
|
||||
HsOfficePartnerEntity findPartnerByPartnerNumber(Integer partnerNumber);
|
||||
|
||||
@Query("""
|
||||
SELECT DISTINCT partner
|
||||
FROM HsOfficePartnerEntity partner
|
||||
JOIN HsOfficeRelationEntity dRel
|
||||
ON dRel.uuid = :debitorUuid AND dRel.type = 'DEBITOR'
|
||||
JOIN HsOfficeRelationEntity pRel
|
||||
ON pRel.uuid = partner.partnerRel.uuid AND pRel.type = 'PARTNER'
|
||||
WHERE pRel.holder.uuid = dRel.anchor.uuid
|
||||
""")
|
||||
HsOfficePartnerEntity findPartnerByDebitorUuid(UUID debitorUuid);
|
||||
|
||||
HsOfficePartnerEntity save(final HsOfficePartnerEntity entity);
|
||||
|
||||
long count();
|
||||
|
@ -56,15 +56,15 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable {
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
@ManyToOne
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "anchoruuid")
|
||||
private HsOfficePersonEntity anchor;
|
||||
|
||||
@ManyToOne
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "holderuuid")
|
||||
private HsOfficePersonEntity holder;
|
||||
|
||||
@ManyToOne
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "contactuuid")
|
||||
private HsOfficeContactEntity contact;
|
||||
|
||||
|
@ -8,6 +8,7 @@ create table hs_office_debitor
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||
version int not null default 0,
|
||||
partnerNumber numeric(5) not null, -- redundant to hs_office_partner.partnerNumber for performance reasons
|
||||
debitorNumberSuffix char(2) not null check (debitorNumberSuffix::text ~ '^[0-9][0-9]$'),
|
||||
debitorRelUuid uuid not null references hs_office_relation(uuid),
|
||||
billable boolean not null default true,
|
||||
|
@ -9,7 +9,8 @@
|
||||
Creates a single debitor test record.
|
||||
*/
|
||||
create or replace procedure createHsOfficeDebitorTestData(
|
||||
withDebitorNumberSuffix numeric(5),
|
||||
forPartnerNumber numeric(5),
|
||||
withDebitorNumberSuffix numeric(2),
|
||||
forPartnerPersonName varchar,
|
||||
forBillingContactCaption varchar,
|
||||
withDefaultPrefix varchar
|
||||
@ -42,8 +43,8 @@ begin
|
||||
-- raise exception 'creating test debitor: (uuid=%, debitorRelUuid=%, debitornumbersuffix=%, billable=%, vatbusiness=%, vatreversecharge=%, refundbankaccountuuid=%, defaultprefix=%)',
|
||||
-- uuid_generate_v4(), relatedDebitorRelUuid, withDebitorNumberSuffix, true, true, false, relatedBankAccountUuid, withDefaultPrefix;
|
||||
insert
|
||||
into hs_office_debitor (uuid, debitorRelUuid, debitornumbersuffix, billable, vatbusiness, vatreversecharge, refundbankaccountuuid, defaultprefix)
|
||||
values (uuid_generate_v4(), relatedDebitorRelUuid, withDebitorNumberSuffix, true, true, false, relatedBankAccountUuid, withDefaultPrefix);
|
||||
into hs_office_debitor (uuid, debitorRelUuid, partnerNumber, debitornumbersuffix, billable, vatbusiness, vatreversecharge, refundbankaccountuuid, defaultprefix)
|
||||
values (uuid_generate_v4(), relatedDebitorRelUuid, forPartnerNumber, withDebitorNumberSuffix, true, true, false, relatedBankAccountUuid, withDefaultPrefix);
|
||||
end; $$;
|
||||
--//
|
||||
|
||||
@ -54,9 +55,9 @@ end; $$;
|
||||
|
||||
do language plpgsql $$
|
||||
begin
|
||||
call createHsOfficeDebitorTestData(11, 'First GmbH', 'first contact', 'fir');
|
||||
call createHsOfficeDebitorTestData(12, 'Second e.K.', 'second contact', 'sec');
|
||||
call createHsOfficeDebitorTestData(13, 'Third OHG', 'third contact', 'thi');
|
||||
call createHsOfficeDebitorTestData( 10001, 11, 'First GmbH', 'first contact', 'fir');
|
||||
call createHsOfficeDebitorTestData( 10002, 12, 'Second e.K.', 'second contact', 'sec');
|
||||
call createHsOfficeDebitorTestData( 10003, 13, 'Third OHG', 'third contact', 'thi');
|
||||
end;
|
||||
$$;
|
||||
--//
|
||||
|
@ -1,17 +1,13 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-booking-debitor-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
--changeset hs-booking-debitor-EXTRACTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create view hs_booking_debitor_xv as
|
||||
select debitor.uuid,
|
||||
debitor.version,
|
||||
(partner.partnerNumber::varchar || debitor.debitorNumberSuffix)::numeric as debitorNumber,
|
||||
(debitor.partnerNumber::varchar || debitor.debitorNumberSuffix)::numeric as debitorNumber,
|
||||
debitor.defaultPrefix
|
||||
from hs_office_debitor debitor
|
||||
-- RBAC for debitor is sufficient, for faster access we are bypassing RBAC for the join tables
|
||||
join hs_office_relation debitorRel on debitor.debitorReluUid=debitorRel.uuid
|
||||
join hs_office_relation partnerRel on partnerRel.holderUuid=debitorRel.anchorUuid
|
||||
join hs_office_partner partner on partner.partnerReluUid=partnerRel.uuid;
|
||||
from hs_office_debitor debitor -- not from _rv for performance, nothing really secret here
|
||||
--//
|
||||
|
@ -208,8 +208,8 @@ class HsHostingAssetRepositoryIntegrationTest extends ContextBasedTestWithCleanu
|
||||
// then
|
||||
exactlyTheseAssetsAreReturned(
|
||||
result,
|
||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, sec01, some Webspace, MANAGED_SERVER:vm1012, D-1000212:D-1000212 default project:separate ManagedWebspace)",
|
||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, fir01, some Webspace, MANAGED_SERVER:vm1011, D-1000111:D-1000111 default project:separate ManagedWebspace)",
|
||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, sec01, some Webspace, MANAGED_SERVER:vm1012, D-1000212:D-1000212 default project:separate ManagedWebspace)",
|
||||
"HsHostingAssetEntity(MANAGED_WEBSPACE, thi01, some Webspace, MANAGED_SERVER:vm1013, D-1000313:D-1000313 default project:separate ManagedWebspace)");
|
||||
}
|
||||
|
||||
|
@ -759,7 +759,7 @@ public class ImportOfficeData extends CsvDataImport {
|
||||
|
||||
final var debitor = HsOfficeDebitorEntity.builder()
|
||||
.debitorNumberSuffix("00")
|
||||
.partner(partner)
|
||||
.partnerNumber(partner.getPartnerNumber())
|
||||
.debitorRel(debitorRel)
|
||||
.defaultPrefix(rec.getString("member_code").replace("hsh00-", ""))
|
||||
.billable(rec.isEmpty("free") || rec.getString("free").equals("f"))
|
||||
|
@ -29,9 +29,7 @@ class HsOfficeDebitorEntityUnitTest {
|
||||
.debitorNumberSuffix("67")
|
||||
.debitorRel(givenDebitorRel)
|
||||
.defaultPrefix("som")
|
||||
.partner(HsOfficePartnerEntity.builder()
|
||||
.partnerNumber(12345)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
final var result = given.toString();
|
||||
@ -44,9 +42,7 @@ class HsOfficeDebitorEntityUnitTest {
|
||||
final var given = HsOfficeDebitorEntity.builder()
|
||||
.debitorRel(givenDebitorRel)
|
||||
.debitorNumberSuffix("67")
|
||||
.partner(HsOfficePartnerEntity.builder()
|
||||
.partnerNumber(12345)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
final var result = given.toShortString();
|
||||
@ -59,9 +55,7 @@ class HsOfficeDebitorEntityUnitTest {
|
||||
final var given = HsOfficeDebitorEntity.builder()
|
||||
.debitorRel(givenDebitorRel)
|
||||
.debitorNumberSuffix("67")
|
||||
.partner(HsOfficePartnerEntity.builder()
|
||||
.partnerNumber(12345)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
final var result = given.getDebitorNumber();
|
||||
@ -69,25 +63,12 @@ class HsOfficeDebitorEntityUnitTest {
|
||||
assertThat(result).isEqualTo(1234567);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getDebitorNumberWithoutPartnerReturnsNull() {
|
||||
final var given = HsOfficeDebitorEntity.builder()
|
||||
.debitorRel(givenDebitorRel)
|
||||
.debitorNumberSuffix("67")
|
||||
.partner(null)
|
||||
.build();
|
||||
|
||||
final var result = given.getDebitorNumber();
|
||||
|
||||
assertThat(result).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getDebitorNumberWithoutPartnerNumberReturnsNull() {
|
||||
final var given = HsOfficeDebitorEntity.builder()
|
||||
.debitorRel(givenDebitorRel)
|
||||
.debitorNumberSuffix("67")
|
||||
.partner(HsOfficePartnerEntity.builder().build())
|
||||
.partnerNumber(null)
|
||||
.build();
|
||||
|
||||
final var result = given.getDebitorNumber();
|
||||
@ -100,9 +81,7 @@ class HsOfficeDebitorEntityUnitTest {
|
||||
final var given = HsOfficeDebitorEntity.builder()
|
||||
.debitorRel(givenDebitorRel)
|
||||
.debitorNumberSuffix(null)
|
||||
.partner(HsOfficePartnerEntity.builder()
|
||||
.partnerNumber(12345)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
final var result = given.getDebitorNumber();
|
||||
|
@ -485,9 +485,6 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
||||
em.refresh(foundEntity);
|
||||
Hibernate.initialize(foundEntity);
|
||||
assertThat(foundEntity).isNotSameAs(saved);
|
||||
if (withPartner) {
|
||||
assertThat(foundEntity.getPartner()).isNotNull();
|
||||
}
|
||||
assertThat(foundEntity.getDebitorRel()).extracting(HsOfficeRelationEntity::toString)
|
||||
.isEqualTo(saved.getDebitorRel().toString());
|
||||
});
|
||||
|
@ -19,7 +19,7 @@ public class TestHsOfficeDebitor {
|
||||
.anchor(HsOfficePersonEntity.builder().build())
|
||||
.contact(TEST_CONTACT)
|
||||
.build())
|
||||
.partner(TEST_PARTNER)
|
||||
.partnerNumber(TEST_PARTNER.getPartnerNumber())
|
||||
.defaultPrefix("abc")
|
||||
.build();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import io.restassured.http.ContentType;
|
||||
import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountRepository;
|
||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository;
|
||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository;
|
||||
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
||||
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||
import org.json.JSONException;
|
||||
@ -42,6 +43,9 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
|
||||
@Autowired
|
||||
HsOfficeSepaMandateRepository sepaMandateRepo;
|
||||
|
||||
@Autowired
|
||||
HsOfficePartnerRepository partnerRepo;
|
||||
|
||||
@Autowired
|
||||
HsOfficeDebitorRepository debitorRepo;
|
||||
|
||||
@ -493,8 +497,9 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
|
||||
return jpaAttempt.transacted(() -> {
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenDebitor = debitorRepo.findDebitorByDebitorNumber(debitorNumber).get(0);
|
||||
final var bankAccountHolder = ofNullable(givenDebitor.getPartner().getPartnerRel().getHolder().getTradeName())
|
||||
.orElse(givenDebitor.getPartner().getPartnerRel().getHolder().getFamilyName());
|
||||
final var givenPartner = partnerRepo.findPartnerByDebitorUuid(givenDebitor.getUuid());
|
||||
final var bankAccountHolder = ofNullable(givenPartner.getPartnerRel().getHolder().getTradeName())
|
||||
.orElse(givenPartner.getPartnerRel().getHolder().getFamilyName());
|
||||
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike(bankAccountHolder).get(0);
|
||||
final var newSepaMandate = HsOfficeSepaMandateEntity.builder()
|
||||
.uuid(UUID.randomUUID())
|
||||
|
Loading…
Reference in New Issue
Block a user