From b50bcbbca0d29e37f70990b7dc66705995fc8131 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 23 Jul 2024 14:33:48 +0200 Subject: [PATCH] add partnerNumber to HsOfficeDebitorEntity --- .../office/debitor/HsOfficeDebitorEntity.java | 24 ++------------ .../partner/HsOfficePartnerRepository.java | 11 +++++++ .../relation/HsOfficeRelationEntity.java | 6 ++-- .../506-debitor/5060-hs-office-debitor.sql | 1 + .../5068-hs-office-debitor-test-data.sql | 13 ++++---- .../6100-hs-booking-debitor.sql | 10 ++---- ...HostingAssetRepositoryIntegrationTest.java | 2 +- .../hs/migration/ImportOfficeData.java | 2 +- .../HsOfficeDebitorEntityUnitTest.java | 31 +++---------------- ...fficeDebitorRepositoryIntegrationTest.java | 3 -- .../office/debitor/TestHsOfficeDebitor.java | 2 +- ...ceSepaMandateControllerAcceptanceTest.java | 9 ++++-- 12 files changed, 43 insertions(+), 71 deletions(-) diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java index 9cf134c9..ad5857ab 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java @@ -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); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java index 2ae260bd..e32abb12 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java @@ -28,6 +28,17 @@ public interface HsOfficePartnerRepository extends Repository 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(); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java index 7c8cd78e..92e6ab0c 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java @@ -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; diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql index bbf72543..0a64321a 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5060-hs-office-debitor.sql @@ -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, diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql b/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql index 2e888e29..6c5cde10 100644 --- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5068-hs-office-debitor-test-data.sql @@ -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; $$; --// diff --git a/src/main/resources/db/changelog/6-hs-booking/610-booking-debitor/6100-hs-booking-debitor.sql b/src/main/resources/db/changelog/6-hs-booking/610-booking-debitor/6100-hs-booking-debitor.sql index 72d9563f..d38640fc 100644 --- a/src/main/resources/db/changelog/6-hs-booking/610-booking-debitor/6100-hs-booking-debitor.sql +++ b/src/main/resources/db/changelog/6-hs-booking/610-booking-debitor/6100-hs-booking-debitor.sql @@ -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 --// diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java index 99f0efd6..0025d8d5 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetRepositoryIntegrationTest.java @@ -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)"); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportOfficeData.java index dd1f7d2b..ec179f33 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/migration/ImportOfficeData.java @@ -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")) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java index e1250775..193a0d59 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntityUnitTest.java @@ -29,9 +29,7 @@ class HsOfficeDebitorEntityUnitTest { .debitorNumberSuffix("67") .debitorRel(givenDebitorRel) .defaultPrefix("som") - .partner(HsOfficePartnerEntity.builder() - .partnerNumber(12345) - .build()) + .partnerNumber(12345) .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()) + .partnerNumber(12345) .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()) + .partnerNumber(12345) .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()) + .partnerNumber(12345) .build(); final var result = given.getDebitorNumber(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java index dc1b3f61..e79644cf 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java @@ -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()); }); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java index b8ddf8b5..57b65678 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java @@ -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(); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java index c0f68451..40d9cee8 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java @@ -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())