PartnerDetails: add birthplace, and improve toString and introduce @Tag("import")

This commit is contained in:
Michael Hoennig 2024-01-17 18:25:35 +01:00
parent 1512e0e1a5
commit 31141ad4c3
24 changed files with 207 additions and 140 deletions

View File

@ -74,3 +74,5 @@ alias pg-sql-restore='gunzip --stdout | docker exec -i hsadmin-ng-postgres psql
alias fp='grep -r '@Accepts' src | sed -e 's/^.*@/@/g' | sort -u | wc -l' alias fp='grep -r '@Accepts' src | sed -e 's/^.*@/@/g' | sort -u | wc -l'
alias spotless='./gradlew spotlessApply -x pitest -x test -x :processResources'

View File

@ -100,6 +100,7 @@ dependencies {
testImplementation 'io.rest-assured:spring-mock-mvc' testImplementation 'io.rest-assured:spring-mock-mvc'
testImplementation 'org.hamcrest:hamcrest-core:2.2' testImplementation 'org.hamcrest:hamcrest-core:2.2'
testImplementation 'org.pitest:pitest-junit5-plugin:1.2.1' testImplementation 'org.pitest:pitest-junit5-plugin:1.2.1'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
} }
dependencyManagement { dependencyManagement {
@ -237,12 +238,9 @@ test {
excludes = [ excludes = [
'net.hostsharing.hsadminng.**.generated.**', 'net.hostsharing.hsadminng.**.generated.**',
] ]
useJUnitPlatform {
test { excludeTags 'import'
systemProperty "my_variable", System.getenv("MY_VARIABLE")
} }
} }
jacocoTestReport { jacocoTestReport {
dependsOn test dependsOn test
@ -303,6 +301,17 @@ jacocoTestCoverageVerification {
} }
} }
tasks.register('importTest', Test) {
useJUnitPlatform {
includeTags 'import'
}
group 'verification'
description 'run the import jobs as tests'
}
test.dependsOn tasks.importTest
// pitest mutation testing // pitest mutation testing
pitest { pitest {
targetClasses = ['net.hostsharing.hsadminng.**'] targetClasses = ['net.hostsharing.hsadminng.**']

View File

@ -1,24 +1,27 @@
# Beispiel: juristische Person (GmbH)
```mermaid ```mermaid
classDiagram classDiagram
direction RL direction TD
namespace Geschäftspartner {
namespace Geschäftspartner {
class partner-MeierGmbH class partner-MeierGmbH
class partnerDetails-MeierGmbH
class contact-MeierGmbH class contact-MeierGmbH
class person-MeierGmbH class person-MeierGmbH
class debitor-MeierGmbH
class contact-MeierGmbH-Buha
class person-FrankMeier class person-FrankMeier
class contact-FrankMeier class contact-FrankMeier
class rel-MeierGmbH-FrankMeier class role-MeierGmbH-FrankMeier
class person-SabineMeier class person-SabineMeier
class contact-SabineMeier class contact-SabineMeier
class rel-MeierGmbH-SabineMeier class role-MeierGmbH-SabineMeier
}
class debitor-MeierGmbH
class contact-MeierGmbH-Buha
class role-MeierGmbH-Buha
}
class partner-MeierGmbH { class partner-MeierGmbH {
+person +person
@ -27,20 +30,17 @@ classDiagram
} }
partner-MeierGmbH o-- person-MeierGmbH partner-MeierGmbH o-- person-MeierGmbH
partner-MeierGmbH o-- contact-MeierGmbH partner-MeierGmbH o-- contact-MeierGmbH
partner-MeierGmbH *-- partnerDetails-MeierGmbH
class partnerDetails-MeierGmbH {
+registrationOffice
+registrationNumber
+birthName
+dateOfDeath
}
class person-MeierGmbH { class person-MeierGmbH {
+ personType: LEGAL +personType: LEGAL
+ tradeName: Meier GmbH +tradeName: Meier GmbH
+ familyName +familyName
+ givenName +givenName
+registrationOffice: AG Hamburg
+registrationNumber: ABC123434
+birthName
+birthPlace
+dateOfDeath
} }
class contact-MeierGmbH { class contact-MeierGmbH {
@ -51,8 +51,8 @@ classDiagram
class debitor-MeierGmbH { class debitor-MeierGmbH {
+Partner partner +Partner partner
+Numeric(2) debitorNumberSuffix: 00 +Numeric[2] debitorNumberSuffix: 00
+Contact billingContact +Role billingRole
+boolean billable: true +boolean billable: true
+String vatId: ID123456789 +String vatId: ID123456789
+String vatCountryCode: DE +String vatCountryCode: DE
@ -62,7 +62,7 @@ classDiagram
+String defaultPrefix: mei +String defaultPrefix: mei
} }
debitor-MeierGmbH o-- partner-MeierGmbH debitor-MeierGmbH o-- partner-MeierGmbH
debitor-MeierGmbH o-- contact-MeierGmbH-Buha debitor-MeierGmbH o-- role-MeierGmbH-Buha
class contact-MeierGmbH-Buha { class contact-MeierGmbH-Buha {
+postalAddress: Hauptstraße 5, 22345 Hamburg +postalAddress: Hauptstraße 5, 22345 Hamburg
@ -70,6 +70,16 @@ classDiagram
+emailAddresses: buha@meier-gmbh.de +emailAddresses: buha@meier-gmbh.de
} }
class role-MeierGmbH-Buha {
+RelType relType ACCOUNTING
+Person relAnchor
+Person relHolder
+Contact contact
}
role-MeierGmbH-Buha o-- person-MeierGmbH : relAnchor
role-MeierGmbH-Buha o-- person-MeierGmbH : relHolder
role-MeierGmbH-Buha o-- contact-MeierGmbH-Buha
class person-FrankMeier { class person-FrankMeier {
+ personType: NATURAL + personType: NATURAL
+ tradeName + tradeName
@ -80,18 +90,18 @@ classDiagram
class contact-FrankMeier { class contact-FrankMeier {
+postalAddress +postalAddress
+phoneNumbers: +49 40 12345-22 +phoneNumbers: +49 40 12345-22
+emailAddresses: sabine.meier@meier-gmbh.de +emailAddresses: frank.meier@meier-gmbh.de
} }
class rel-MeierGmbH-FrankMeier { class role-MeierGmbH-FrankMeier {
+RelType relType REPRESENTATIVE +RelType relType REPRESENTATIVE
+Person relAnchor +Person relAnchor
+Person relHolder +Person relHolder
+Contact contact +Contact contact
} }
rel-MeierGmbH-FrankMeier o-- person-MeierGmbH : relAnchor role-MeierGmbH-FrankMeier o-- person-MeierGmbH : relAnchor
rel-MeierGmbH-FrankMeier o-- person-FrankMeier : relHolder role-MeierGmbH-FrankMeier o-- person-FrankMeier : relHolder
rel-MeierGmbH-FrankMeier o-- contact-FrankMeier role-MeierGmbH-FrankMeier o-- contact-FrankMeier
class person-SabineMeier { class person-SabineMeier {
+personType: NATURAL +personType: NATURAL
@ -106,15 +116,15 @@ classDiagram
+emailAddresses: sabine.meier@meier-gmbh.de +emailAddresses: sabine.meier@meier-gmbh.de
} }
class rel-MeierGmbH-SabineMeier { class role-MeierGmbH-SabineMeier {
+RelType relType OPERATIONAL +RelType relType OPERATIONAL
+Person relAnchor +Person relAnchor
+Person relHolder +Person relHolder
+Contact contact +Contact contact
} }
rel-MeierGmbH-SabineMeier o-- person-MeierGmbH : relAnchor role-MeierGmbH-SabineMeier o-- person-MeierGmbH : relAnchor
rel-MeierGmbH-SabineMeier o-- person-SabineMeier : relHolder role-MeierGmbH-SabineMeier o-- person-SabineMeier : relHolder
rel-MeierGmbH-SabineMeier o-- contact-SabineMeier role-MeierGmbH-SabineMeier o-- contact-SabineMeier
namespace Enums { namespace Enums {
@ -128,24 +138,13 @@ classDiagram
class PersonType { class PersonType {
<<enumeration>> <<enumeration>>
UNKNOWN UNKNOWN: nur für Import
NATURAL NATURAL_PERSON: natürliche Person
LEGAL LEGAL_PERSON: z.B. GmbH, e.K., eG, e.V.
SOLE_REPRESENTATION INCORORATED_FIRM: z.B. OHG, Partnerschaftsgesellschaft
JOINT_REPRESENTATION UNINCORPORATED_FIRM: z.B. GbR, ARGE, Erbengemeinschaft
PUBLIC_INSTITUTION: KdöR, AöR [ohne Registergericht/Registernummer]
} }
} }
```
```mermaid
classDiagram
classA --|> classB : Inheritance
classC --* classD : Composition
classE --o classF : Aggregation
classG --> classH : Association
classI -- classJ : Link(Solid)
classK ..> classL : Dependency
classM ..|> classN : Realization
classO .. classP : Link(Dashed)
``` ```

View File

@ -51,7 +51,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
@ManyToOne @ManyToOne
@JoinColumn(name = "billingcontactuuid") @JoinColumn(name = "billingcontactuuid")
private HsOfficeContactEntity billingContact; private HsOfficeContactEntity billingContact; // TODO: migrate to billingPerson
@Column(name = "billable") @Column(name = "billable")
private boolean billable; private boolean billable;

View File

@ -27,8 +27,9 @@ public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable {
"partnerDetails") "partnerDetails")
.withProp(HsOfficePartnerDetailsEntity::getRegistrationOffice) .withProp(HsOfficePartnerDetailsEntity::getRegistrationOffice)
.withProp(HsOfficePartnerDetailsEntity::getRegistrationNumber) .withProp(HsOfficePartnerDetailsEntity::getRegistrationNumber)
.withProp(HsOfficePartnerDetailsEntity::getBirthPlace)
.withProp(HsOfficePartnerDetailsEntity::getBirthday) .withProp(HsOfficePartnerDetailsEntity::getBirthday)
.withProp(HsOfficePartnerDetailsEntity::getBirthday) .withProp(HsOfficePartnerDetailsEntity::getBirthName)
.withProp(HsOfficePartnerDetailsEntity::getDateOfDeath) .withProp(HsOfficePartnerDetailsEntity::getDateOfDeath)
.withSeparator(", ") .withSeparator(", ")
.quotedValues(false); .quotedValues(false);
@ -40,6 +41,7 @@ public class HsOfficePartnerDetailsEntity implements HasUuid, Stringifyable {
private @Column(name = "registrationoffice") String registrationOffice; private @Column(name = "registrationoffice") String registrationOffice;
private @Column(name = "registrationnumber") String registrationNumber; private @Column(name = "registrationnumber") String registrationNumber;
private @Column(name = "birthname") String birthName; private @Column(name = "birthname") String birthName;
private @Column(name = "birthplace") String birthPlace;
private @Column(name = "birthday") LocalDate birthday; private @Column(name = "birthday") LocalDate birthday;
private @Column(name = "dateofdeath") LocalDate dateOfDeath; private @Column(name = "dateofdeath") LocalDate dateOfDeath;

View File

@ -54,6 +54,7 @@ public class HsOfficePersonEntity implements HasUuid, Stringifyable {
@Override @Override
public String toShortString() { public String toShortString() {
return !StringUtils.isEmpty(tradeName) ? tradeName : (familyName + ", " + givenName); return personType + " " +
(!StringUtils.isEmpty(tradeName) ? tradeName : (familyName + ", " + givenName));
} }
} }

View File

@ -0,0 +1,18 @@
--liquibase formatted sql
-- ============================================================================
-- NUMERIC-HASH-FUNCTIONS
--changeset hash:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
do $$
begin
if starts_with ('${HSADMINNG_POSTGRES_ADMIN_USERNAME}', '$') then
RAISE EXCEPTION 'environment variable HSADMINNG_POSTGRES_ADMIN_USERNAME not set';
end if;
if starts_with ('${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}', '$') then
RAISE EXCEPTION 'environment variable HSADMINNG_POSTGRES_RESTRICTED_USERNAME not set';
end if;
end $$
--//

View File

@ -1,12 +0,0 @@
--liquibase formatted sql
-- ============================================================================
-- NUMERIC-HASH-FUNCTIONS
--changeset hash:1 endDelimiter:--//
-- ----------------------------------------------------------------------------
create function postgresAdminUserName() returns text as $$
if
$$ language sql;
--//

View File

@ -10,6 +10,7 @@ create table hs_office_partner_details
uuid uuid unique references RbacObject (uuid) initially deferred, uuid uuid unique references RbacObject (uuid) initially deferred,
registrationOffice varchar(96), registrationOffice varchar(96),
registrationNumber varchar(96), registrationNumber varchar(96),
birthPlace varchar(96),
birthName varchar(96), birthName varchar(96),
birthday date, birthday date,
dateOfDeath date dateOfDeath date

View File

@ -29,6 +29,7 @@ call generateRbacRestrictedView('hs_office_partner_details',
$updates$ $updates$
registrationOffice = new.registrationOffice, registrationOffice = new.registrationOffice,
registrationNumber = new.registrationNumber, registrationNumber = new.registrationNumber,
birthPlace = new.birthPlace,
birthName = new.birthName, birthName = new.birthName,
birthday = new.birthday, birthday = new.birthday,
dateOfDeath = new.dateOfDeath dateOfDeath = new.dateOfDeath

View File

@ -11,6 +11,8 @@ databaseChangeLog:
file: db/changelog/005-uuid-ossp-extension.sql file: db/changelog/005-uuid-ossp-extension.sql
- include: - include:
file: db/changelog/006-numeric-hash-functions.sql file: db/changelog/006-numeric-hash-functions.sql
- include:
file: db/changelog/009-check-environment.sql
- include: - include:
file: db/changelog/010-context.sql file: db/changelog/010-context.sql
- include: - include:

View File

@ -4,6 +4,7 @@ import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity; import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -16,6 +17,7 @@ class HsOfficeDebitorEntityUnitTest {
.debitorNumberSuffix((byte)67) .debitorNumberSuffix((byte)67)
.partner(HsOfficePartnerEntity.builder() .partner(HsOfficePartnerEntity.builder()
.person(HsOfficePersonEntity.builder() .person(HsOfficePersonEntity.builder()
.personType(HsOfficePersonType.LEGAL)
.tradeName("some trade name") .tradeName("some trade name")
.build()) .build())
.details(HsOfficePartnerDetailsEntity.builder().birthName("some birth name").build()) .details(HsOfficePartnerDetailsEntity.builder().birthName("some birth name").build())
@ -27,7 +29,7 @@ class HsOfficeDebitorEntityUnitTest {
final var result = given.toString(); final var result = given.toString();
assertThat(result).isEqualTo("debitor(1234567: some trade name: som)"); assertThat(result).isEqualTo("debitor(1234567: LEGAL some trade name: som)");
} }
@Test @Test

View File

@ -215,9 +215,9 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
// then // then
allTheseDebitorsAreReturned( allTheseDebitorsAreReturned(
result, result,
"debitor(1000111: First GmbH: fir)", "debitor(1000111: LEGAL First GmbH: fir)",
"debitor(1000212: Second e.K.: sec)", "debitor(1000212: LEGAL Second e.K.: sec)",
"debitor(1000313: Third OHG: thi)"); "debitor(1000313: SOLE_REPRESENTATION Third OHG: thi)");
} }
@ParameterizedTest @ParameterizedTest
@ -235,8 +235,8 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
// then: // then:
exactlyTheseDebitorsAreReturned(result, exactlyTheseDebitorsAreReturned(result,
"debitor(1000111: First GmbH: fir)", "debitor(1000111: LEGAL First GmbH: fir)",
"debitor(1000120: First GmbH: fif)"); "debitor(1000120: LEGAL First GmbH: fif)");
} }
@Test @Test
@ -264,7 +264,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
final var result = debitorRepo.findDebitorByDebitorNumber(1000313); final var result = debitorRepo.findDebitorByDebitorNumber(1000313);
// then // then
exactlyTheseDebitorsAreReturned(result, "debitor(1000313: Third OHG: thi)"); exactlyTheseDebitorsAreReturned(result, "debitor(1000313: SOLE_REPRESENTATION Third OHG: thi)");
} }
} }
@ -280,7 +280,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
final var result = debitorRepo.findDebitorByOptionalNameLike("third contact"); final var result = debitorRepo.findDebitorByOptionalNameLike("third contact");
// then // then
exactlyTheseDebitorsAreReturned(result, "debitor(1000313: Third OHG: thi)"); exactlyTheseDebitorsAreReturned(result, "debitor(1000313: SOLE_REPRESENTATION Third OHG: thi)");
} }
} }

View File

@ -287,7 +287,7 @@ class HsOfficeMembershipControllerAcceptanceTest {
// finally, the Membership is actually updated // finally, the Membership is actually updated
assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent().get() assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent().get()
.matches(mandate -> { .matches(mandate -> {
assertThat(mandate.getPartner().toShortString()).isEqualTo("First GmbH"); assertThat(mandate.getPartner().toShortString()).isEqualTo("LEGAL First GmbH");
assertThat(mandate.getMainDebitor().toString()).isEqualTo(givenMembership.getMainDebitor().toString()); assertThat(mandate.getMainDebitor().toString()).isEqualTo(givenMembership.getMainDebitor().toString());
assertThat(mandate.getMemberNumber()).isEqualTo(givenMembership.getMemberNumber()); assertThat(mandate.getMemberNumber()).isEqualTo(givenMembership.getMemberNumber());
assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,2024-01-01)"); assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,2024-01-01)");
@ -330,7 +330,7 @@ class HsOfficeMembershipControllerAcceptanceTest {
// finally, the Membership is actually updated // finally, the Membership is actually updated
assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent().get() assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent().get()
.matches(mandate -> { .matches(mandate -> {
assertThat(mandate.getPartner().toShortString()).isEqualTo("First GmbH"); assertThat(mandate.getPartner().toShortString()).isEqualTo("LEGAL First GmbH");
assertThat(mandate.getMainDebitor().toString()).isEqualTo(givenMembership.getMainDebitor().toString()); assertThat(mandate.getMainDebitor().toString()).isEqualTo(givenMembership.getMainDebitor().toString());
assertThat(mandate.getMemberNumber()).isEqualTo(givenMembership.getMemberNumber()); assertThat(mandate.getMemberNumber()).isEqualTo(givenMembership.getMemberNumber());
assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,)"); assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,)");

View File

@ -27,8 +27,7 @@ class HsOfficeMembershipEntityUnitTest {
void toStringContainsAllProps() { void toStringContainsAllProps() {
final var result = givenMembership.toString(); final var result = givenMembership.toString();
assertThat(result).isEqualTo("Membership(10001, Test Ltd., 1000100, [2020-01-01,))"); assertThat(result).isEqualTo("Membership(10001, LEGAL Test Ltd., 1000100, [2020-01-01,))");
// assertThat(result).isEqualTo("Membership(10001, Test Ltd., 1000100, [2020-01-01,))");
} }
@Test @Test

View File

@ -185,9 +185,9 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTest {
// then // then
exactlyTheseMembershipsAreReturned( exactlyTheseMembershipsAreReturned(
result, result,
"Membership(10001, First GmbH, 1000111, [2022-10-01,), NONE)", "Membership(10001, LEGAL First GmbH, 1000111, [2022-10-01,), NONE)",
"Membership(10002, Second e.K., 1000212, [2022-10-01,), NONE)", "Membership(10002, LEGAL Second e.K., 1000212, [2022-10-01,), NONE)",
"Membership(10003, Third OHG, 1000313, [2022-10-01,), NONE)"); "Membership(10003, SOLE_REPRESENTATION Third OHG, 1000313, [2022-10-01,), NONE)");
} }
@Test @Test
@ -202,7 +202,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTest {
null); null);
// then // then
exactlyTheseMembershipsAreReturned(result, "Membership(10001, First GmbH, 1000111, [2022-10-01,), NONE)"); exactlyTheseMembershipsAreReturned(result, "Membership(10001, LEGAL First GmbH, 1000111, [2022-10-01,), NONE)");
} }
@Test @Test
@ -214,7 +214,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTest {
final var result = membershipRepo.findMembershipsByOptionalPartnerUuidAndOptionalMemberNumber(null, 10002); final var result = membershipRepo.findMembershipsByOptionalPartnerUuidAndOptionalMemberNumber(null, 10002);
// then // then
exactlyTheseMembershipsAreReturned(result, "Membership(10002, Second e.K., 1000212, [2022-10-01,), NONE)"); exactlyTheseMembershipsAreReturned(result, "Membership(10002, LEGAL Second e.K., 1000212, [2022-10-01,), NONE)");
} }
} }

View File

@ -23,6 +23,10 @@ import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType
import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity; import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
import net.hostsharing.test.JpaAttempt; import net.hostsharing.test.JpaAttempt;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.TestWatcher;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
@ -48,6 +52,7 @@ import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateR
import static org.apache.commons.lang3.StringUtils.isBlank; import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.assertj.core.api.Fail.fail; import static org.assertj.core.api.Fail.fail;
/* /*
@ -91,7 +96,7 @@ import static org.assertj.core.api.Fail.fail;
* *
* import-office-tables # comes from .aliases file * import-office-tables # comes from .aliases file
*/ */
//@Disabled @Tag("import")
@DataJpaTest(properties = { @DataJpaTest(properties = {
"spring.datasource.url=${HSADMINNG_POSTGRES_JDBC_URL:jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers}", "spring.datasource.url=${HSADMINNG_POSTGRES_JDBC_URL:jdbc:tc:postgresql:15.5-bookworm:///spring_boot_testcontainers}",
"spring.datasource.username=${HSADMINNG_POSTGRES_ADMIN_USERNAME:admin}", "spring.datasource.username=${HSADMINNG_POSTGRES_ADMIN_USERNAME:admin}",
@ -99,6 +104,7 @@ import static org.assertj.core.api.Fail.fail;
}) })
@Import({ Context.class, JpaAttempt.class }) @Import({ Context.class, JpaAttempt.class })
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@ExtendWith(OrderedDependedTestsExtension.class)
public class ImportOfficeTables extends ContextBasedTest { public class ImportOfficeTables extends ContextBasedTest {
@Value("${spring.datasource.username}") @Value("${spring.datasource.username}")
@ -151,23 +157,23 @@ public class ImportOfficeTables extends ContextBasedTest {
// no contacts yet => mostly null values // no contacts yet => mostly null values
assertThat(partners.toString()).isEqualToIgnoringWhitespace(""" assertThat(partners.toString()).isEqualToIgnoringWhitespace("""
{ {
7=partner(null, null), 7=partner(UNKNOWN null, null),
10=partner(null, null), 10=partner(UNKNOWN null, null),
12=partner(null, null) 12=partner(UNKNOWN null, null)
} }
"""); """);
assertThat(contacts.toString()).isEqualTo("{}"); assertThat(contacts.toString()).isEqualTo("{}");
assertThat(debitors.toString()).isEqualToIgnoringWhitespace(""" assertThat(debitors.toString()).isEqualToIgnoringWhitespace("""
{ {
7=debitor(1000700: null, null: mih), 7=debitor(1000700: UNKNOWN null, null: mih),
10=debitor(1001000: null, null: xyz), 10=debitor(1001000: UNKNOWN null, null: xyz),
12=debitor(1101200: null, null: xxx)} 12=debitor(1101200: UNKNOWN null, null: xxx)}
"""); """);
assertThat(memberships.toString()).isEqualToIgnoringWhitespace(""" assertThat(memberships.toString()).isEqualToIgnoringWhitespace("""
{ {
7=Membership(10007, null, null, 1000700, [2000-12-06,), NONE), 7=Membership(10007, UNKNOWN null, null, 1000700, [2000-12-06,), NONE),
10=Membership(10010, null, null, 1001000, [2000-12-06,2016-01-01), UNKNOWN), 10=Membership(10010, UNKNOWN null, null, 1001000, [2000-12-06,2016-01-01), UNKNOWN),
12=Membership(11012, null, null, 1101200, [2021-04-01,), NONE) 12=Membership(11012, UNKNOWN null, null, 1101200, [2021-04-01,), NONE)
} }
"""); """);
} }
@ -189,9 +195,9 @@ public class ImportOfficeTables extends ContextBasedTest {
assertThat(partners.toString()).isEqualToIgnoringWhitespace(""" assertThat(partners.toString()).isEqualToIgnoringWhitespace("""
{ {
7=partner(Mellies, Michael: Herr Michael Mellies ), 7=partner(NATURAL Mellies, Michael: Herr Michael Mellies ),
10=partner(JM e.K.: Herr Philip Meyer-Contract , JM e.K.), 10=partner(LEGAL JM e.K.: Herr Philip Meyer-Contract , JM e.K.),
12=partner(Test PS: Petra Schmidt , Test PS) 12=partner(LEGAL Test PS: Petra Schmidt , Test PS)
} }
"""); """);
assertThat(contacts.toString()).isEqualToIgnoringWhitespace(""" assertThat(contacts.toString()).isEqualToIgnoringWhitespace("""
@ -205,31 +211,31 @@ public class ImportOfficeTables extends ContextBasedTest {
"""); """);
assertThat(persons.toString()).isEqualToIgnoringWhitespace(""" assertThat(persons.toString()).isEqualToIgnoringWhitespace("""
{ {
900000=person(personType='UNKNOWN', tradeName='', familyName='Mellies', givenName='Michael'), 900000=person(personType='NATURAL', tradeName='', familyName='Mellies', givenName='Michael'),
900001=person(personType='UNKNOWN', tradeName='JM e.K.', familyName='Meyer-Contract', givenName='Philip'), 900001=person(personType='LEGAL', tradeName='JM e.K.', familyName='Meyer-Contract', givenName='Philip'),
900002=person(personType='UNKNOWN', tradeName='Test PS', familyName='Schmidt', givenName='Petra') 900002=person(personType='LEGAL', tradeName='Test PS', familyName='Schmidt', givenName='Petra')
} }
"""); """);
assertThat(debitors.toString()).isEqualToIgnoringWhitespace(""" assertThat(debitors.toString()).isEqualToIgnoringWhitespace("""
{ {
7=debitor(1000700: Mellies, Michael: mih), 7=debitor(1000700: NATURAL Mellies, Michael: mih),
10=debitor(1001000: JM e.K.: xyz), 10=debitor(1001000: LEGAL JM e.K.: xyz),
12=debitor(1101200: Test PS: xxx) 12=debitor(1101200: LEGAL Test PS: xxx)
} }
"""); """);
assertThat(memberships.toString()).isEqualToIgnoringWhitespace(""" assertThat(memberships.toString()).isEqualToIgnoringWhitespace("""
{ {
7=Membership(10007, Mellies, Michael, 1000700, [2000-12-06,), NONE), 7=Membership(10007, NATURAL Mellies, Michael, 1000700, [2000-12-06,), NONE),
10=Membership(10010, JM e.K., 1001000, [2000-12-06,2016-01-01), UNKNOWN), 10=Membership(10010, LEGAL JM e.K., 1001000, [2000-12-06,2016-01-01), UNKNOWN),
12=Membership(11012, Test PS, 1101200, [2021-04-01,), NONE) 12=Membership(11012, LEGAL Test PS, 1101200, [2021-04-01,), NONE)
} }
"""); """);
assertThat(relationships.toString()).isEqualToIgnoringWhitespace(""" assertThat(relationships.toString()).isEqualToIgnoringWhitespace("""
{ {
1101=rel(relAnchor='Mellies, Michael', relType='OPERATIONS', relHolder='Mellies, Michael', contact='Herr Michael Mellies '), 1101=rel(relAnchor='NATURAL Mellies, Michael', relType='OPERATIONS', relHolder='NATURAL Mellies, Michael', contact='Herr Michael Mellies '),
1202=rel(relAnchor='JM e.K.', relType='OPERATIONS', relHolder='JM e.K.', contact='Herr Andrew Meyer-Operation , JM e.K.'), 1202=rel(relAnchor='LEGAL JM e.K.', relType='OPERATIONS', relHolder='LEGAL JM e.K.', contact='Herr Andrew Meyer-Operation , JM e.K.'),
1203=rel(relAnchor='JM e.K.', relType='REPRESENTATIVE', relHolder='JM e.K.', contact='Herr Philip Meyer-Contract , JM e.K.'), 1203=rel(relAnchor='LEGAL JM e.K.', relType='REPRESENTATIVE', relHolder='LEGAL JM e.K.', contact='Herr Philip Meyer-Contract , JM e.K.'),
1301=rel(relAnchor='Test PS', relType='REPRESENTATIVE', relHolder='Test PS', contact='Petra Schmidt , Test PS') 1301=rel(relAnchor='LEGAL Test PS', relType='REPRESENTATIVE', relHolder='LEGAL Test PS', contact='Petra Schmidt , Test PS')
} }
"""); """);
} }
@ -520,7 +526,6 @@ public class ImportOfficeTables extends ContextBasedTest {
final var person = HsOfficePersonEntity.builder() final var person = HsOfficePersonEntity.builder()
.personType(HsOfficePersonType.UNKNOWN) // TODO .personType(HsOfficePersonType.UNKNOWN) // TODO
.build(); .build();
// persons.put(rec.getInteger("bp_id"), person);
persons.put(personId++, person); persons.put(personId++, person);
final var partner = HsOfficePartnerEntity.builder() final var partner = HsOfficePartnerEntity.builder()
@ -684,6 +689,7 @@ public class ImportOfficeTables extends ContextBasedTest {
final var person = partner.getPerson(); final var person = partner.getPerson();
person.setTradeName(rec.getString("firma")); person.setTradeName(rec.getString("firma"));
determinePersonType(person);
// TODO: title+salutation: add to person // TODO: title+salutation: add to person
person.setGivenName(rec.getString("first_name")); person.setGivenName(rec.getString("first_name"));
person.setFamilyName(rec.getString("last_name")); person.setFamilyName(rec.getString("last_name"));
@ -734,6 +740,14 @@ public class ImportOfficeTables extends ContextBasedTest {
}); });
} }
private void determinePersonType(final HsOfficePersonEntity person) {
if (person.getTradeName().isBlank()) {
person.setPersonType(HsOfficePersonType.NATURAL);
} else {
person.setPersonType(HsOfficePersonType.LEGAL); // TODO: add rules if we distinguish
}
}
private HsOfficeContactEntity initContact(final HsOfficeContactEntity contact, final Record rec) { private HsOfficeContactEntity initContact(final HsOfficeContactEntity contact, final Record rec) {
contacts.put(rec.getInteger("contact_id"), contact); contacts.put(rec.getInteger("contact_id"), contact);
@ -916,3 +930,20 @@ class Record {
return null; return null;
} }
} }
class OrderedDependedTestsExtension implements TestWatcher, BeforeEachCallback {
private static boolean previousTestsPassed = true;
public void testAborted(ExtensionContext context, Throwable cause) {
previousTestsPassed = false;
}
public void testFailed(ExtensionContext context, Throwable cause) {
previousTestsPassed = false;
}
@Override
public void beforeEach(final ExtensionContext extensionContext) throws Exception {
assumeThat(previousTestsPassed).isTrue();
}
}

View File

@ -21,7 +21,8 @@ class HsOfficePartnerDetailsEntityUnitTest {
final var result = given.toString(); final var result = given.toString();
assertThat(result).isEqualTo("partnerDetails(Hamburg, 12345, 2002-01-15, 2002-01-15, 2081-12-21)"); assertThat(result).isEqualTo(
"partnerDetails(Hamburg, 12345, 2002-01-15, Melly Miller, 2081-12-21)");
} }
@Test @Test

View File

@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.hs.office.partner;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -11,24 +12,30 @@ class HsOfficePartnerEntityUnitTest {
@Test @Test
void toStringContainsPersonAndContact() { void toStringContainsPersonAndContact() {
final var given = HsOfficePartnerEntity.builder() final var given = HsOfficePartnerEntity.builder()
.person(HsOfficePersonEntity.builder().tradeName("some trade name").build()) .person(HsOfficePersonEntity.builder()
.personType(HsOfficePersonType.LEGAL)
.tradeName("some trade name")
.build())
.contact(HsOfficeContactEntity.builder().label("some label").build()) .contact(HsOfficeContactEntity.builder().label("some label").build())
.build(); .build();
final var result = given.toString(); final var result = given.toString();
assertThat(result).isEqualTo("partner(some trade name: some label)"); assertThat(result).isEqualTo("partner(LEGAL some trade name: some label)");
} }
@Test @Test
void toShortStringContainsPersonAndContact() { void toShortStringContainsPersonAndContact() {
final var given = HsOfficePartnerEntity.builder() final var given = HsOfficePartnerEntity.builder()
.person(HsOfficePersonEntity.builder().tradeName("some trade name").build()) .person(HsOfficePersonEntity.builder()
.personType(HsOfficePersonType.LEGAL)
.tradeName("some trade name")
.build())
.contact(HsOfficeContactEntity.builder().label("some label").build()) .contact(HsOfficeContactEntity.builder().label("some label").build())
.build(); .build();
final var result = given.toShortString(); final var result = given.toShortString();
assertThat(result).isEqualTo("some trade name"); assertThat(result).isEqualTo("LEGAL some trade name");
} }
} }

View File

@ -177,9 +177,9 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
// then // then
allThesePartnersAreReturned( allThesePartnersAreReturned(
result, result,
"partner(Third OHG: third contact)", "partner(SOLE_REPRESENTATION Third OHG: third contact)",
"partner(Second e.K.: second contact)", "partner(LEGAL Second e.K.: second contact)",
"partner(First GmbH: first contact)"); "partner(LEGAL First GmbH: first contact)");
} }
@Test @Test
@ -191,7 +191,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
final var result = partnerRepo.findPartnerByOptionalNameLike(null); final var result = partnerRepo.findPartnerByOptionalNameLike(null);
// then: // then:
exactlyThesePartnersAreReturned(result, "partner(First GmbH: first contact)"); exactlyThesePartnersAreReturned(result, "partner(LEGAL First GmbH: first contact)");
} }
} }
@ -207,7 +207,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTest {
final var result = partnerRepo.findPartnerByOptionalNameLike("third contact"); final var result = partnerRepo.findPartnerByOptionalNameLike("third contact");
// then // then
exactlyThesePartnersAreReturned(result, "partner(Third OHG: third contact)"); exactlyThesePartnersAreReturned(result, "partner(SOLE_REPRESENTATION Third OHG: third contact)");
} }
} }

View File

@ -11,29 +11,32 @@ class HsOfficePersonEntityUnitTest {
@Test @Test
void getDisplayReturnsTradeNameIfAvailable() { void getDisplayReturnsTradeNameIfAvailable() {
final var givenPersonEntity = HsOfficePersonEntity.builder() final var givenPersonEntity = HsOfficePersonEntity.builder()
.personType(HsOfficePersonType.LEGAL)
.tradeName("some trade name") .tradeName("some trade name")
.build(); .build();
final var actualDisplay = givenPersonEntity.toShortString(); final var actualDisplay = givenPersonEntity.toShortString();
assertThat(actualDisplay).isEqualTo("some trade name"); assertThat(actualDisplay).isEqualTo("LEGAL some trade name");
} }
@Test @Test
void getDisplayReturnsFamilyAndGivenNameIfNoTradeNameAvailable() { void getDisplayReturnsFamilyAndGivenNameIfNoTradeNameAvailable() {
final var givenPersonEntity = HsOfficePersonEntity.builder() final var givenPersonEntity = HsOfficePersonEntity.builder()
.personType(HsOfficePersonType.NATURAL)
.familyName("some family name") .familyName("some family name")
.givenName("some given name") .givenName("some given name")
.build(); .build();
final var actualDisplay = givenPersonEntity.toShortString(); final var actualDisplay = givenPersonEntity.toShortString();
assertThat(actualDisplay).isEqualTo("some family name, some given name"); assertThat(actualDisplay).isEqualTo("NATURAL some family name, some given name");
} }
@Test @Test
void toShortStringWithTradeNameReturnsTradeName() { void toShortStringWithTradeNameReturnsTradeName() {
final var givenPersonEntity = HsOfficePersonEntity.builder() final var givenPersonEntity = HsOfficePersonEntity.builder()
.personType(HsOfficePersonType.LEGAL)
.tradeName("some trade name") .tradeName("some trade name")
.familyName("some family name") .familyName("some family name")
.givenName("some given name") .givenName("some given name")
@ -41,19 +44,20 @@ class HsOfficePersonEntityUnitTest {
final var actualDisplay = givenPersonEntity.toShortString(); final var actualDisplay = givenPersonEntity.toShortString();
assertThat(actualDisplay).isEqualTo("some trade name"); assertThat(actualDisplay).isEqualTo("LEGAL some trade name");
} }
@Test @Test
void toShortStringWithoutTradeNameReturnsFamilyAndGivenName() { void toShortStringWithoutTradeNameReturnsFamilyAndGivenName() {
final var givenPersonEntity = HsOfficePersonEntity.builder() final var givenPersonEntity = HsOfficePersonEntity.builder()
.personType(HsOfficePersonType.NATURAL)
.familyName("some family name") .familyName("some family name")
.givenName("some given name") .givenName("some given name")
.build(); .build();
final var actualDisplay = givenPersonEntity.toShortString(); final var actualDisplay = givenPersonEntity.toShortString();
assertThat(actualDisplay).isEqualTo("some family name, some given name"); assertThat(actualDisplay).isEqualTo("NATURAL some family name, some given name");
} }
@Test @Test

View File

@ -144,10 +144,10 @@ class HsOfficePersonRepositoryIntegrationTest extends ContextBasedTest {
// then // then
allThesePersonsAreReturned( allThesePersonsAreReturned(
result, result,
"Smith, Peter", "NATURAL Smith, Peter",
"Second e.K.", "LEGAL Second e.K.",
"Third OHG", "SOLE_REPRESENTATION Third OHG",
"Erben Bessler"); "JOINT_REPRESENTATION Erben Bessler");
} }
@Test @Test

View File

@ -159,9 +159,9 @@ class HsOfficeRelationshipRepositoryIntegrationTest extends ContextBasedTest {
// then // then
allTheseRelationshipsAreReturned( allTheseRelationshipsAreReturned(
result, result,
"rel(relAnchor='First GmbH', relType='REPRESENTATIVE', relHolder='Smith, Peter', contact='first contact')", "rel(relAnchor='LEGAL First GmbH', relType='REPRESENTATIVE', relHolder='NATURAL Smith, Peter', contact='first contact')",
"rel(relAnchor='Third OHG', relType='REPRESENTATIVE', relHolder='Smith, Peter', contact='third contact')", "rel(relAnchor='SOLE_REPRESENTATION Third OHG', relType='REPRESENTATIVE', relHolder='NATURAL Smith, Peter', contact='third contact')",
"rel(relAnchor='Second e.K.', relType='REPRESENTATIVE', relHolder='Smith, Peter', contact='second contact')"); "rel(relAnchor='LEGAL Second e.K.', relType='REPRESENTATIVE', relHolder='NATURAL Smith, Peter', contact='second contact')");
} }
@Test @Test
@ -176,7 +176,7 @@ class HsOfficeRelationshipRepositoryIntegrationTest extends ContextBasedTest {
// then: // then:
exactlyTheseRelationshipsAreReturned( exactlyTheseRelationshipsAreReturned(
result, result,
"rel(relAnchor='First GmbH', relType='REPRESENTATIVE', relHolder='Smith, Peter', contact='first contact')"); "rel(relAnchor='LEGAL First GmbH', relType='REPRESENTATIVE', relHolder='NATURAL Smith, Peter', contact='first contact')");
} }
} }

View File

@ -376,7 +376,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get() assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get()
.matches(mandate -> { .matches(mandate -> {
assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(1000111: First GmbH: fir)"); assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(1000111: LEGAL First GmbH: fir)");
assertThat(mandate.getBankAccount().toShortString()).isEqualTo("First GmbH"); assertThat(mandate.getBankAccount().toShortString()).isEqualTo("First GmbH");
assertThat(mandate.getReference()).isEqualTo("temp ref CAT Z - patched"); assertThat(mandate.getReference()).isEqualTo("temp ref CAT Z - patched");
assertThat(mandate.getValidFrom()).isEqualTo("2020-06-05"); assertThat(mandate.getValidFrom()).isEqualTo("2020-06-05");
@ -417,7 +417,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest {
// finally, the sepaMandate is actually updated // finally, the sepaMandate is actually updated
assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get() assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get()
.matches(mandate -> { .matches(mandate -> {
assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(1000111: First GmbH: fir)"); assertThat(mandate.getDebitor().toString()).isEqualTo("debitor(1000111: LEGAL First GmbH: fir)");
assertThat(mandate.getBankAccount().toShortString()).isEqualTo("First GmbH"); assertThat(mandate.getBankAccount().toShortString()).isEqualTo("First GmbH");
assertThat(mandate.getReference()).isEqualTo("temp ref CAT Z"); assertThat(mandate.getReference()).isEqualTo("temp ref CAT Z");
assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,2023-01-01)"); assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,2023-01-01)");