diff --git a/.aliases b/.aliases index f6673bcd..9eef231d 100644 --- a/.aliases +++ b/.aliases @@ -79,5 +79,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 gw-spotless='./gradlew spotlessApply -x pitest -x test -x :processResources' -alias gw-test='. .aliases; ./gradlew test' -alias gw-check='. .aliases; gw check -x pitest -x :dependencyCheckAnalyze' +alias gw-test='. .aliases; ./gradlew test importOfficeData' +alias gw-check='. .aliases; gw test importOfficeData check -x pitest -x :dependencyCheckAnalyze' diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipEntity.java index b9b4f980..6d5dbe11 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipEntity.java @@ -54,6 +54,9 @@ public class HsOfficeRelationshipEntity implements HasUuid, Stringifyable { @Enumerated(EnumType.STRING) private HsOfficeRelationshipType relType; + @Column(name = "reltypemark") + private String relTypeMark; + @Override public String toString() { return toString.apply(this); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipType.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipType.java index e3955c7e..9036adeb 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipType.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipType.java @@ -6,5 +6,6 @@ public enum HsOfficeRelationshipType { REPRESENTATIVE, VIP_CONTACT, ACCOUNTING, - OPERATIONS + OPERATIONS, + SUBSCRIBER } diff --git a/src/main/resources/api-definition/hs-office/hs-office-relationship-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-relationship-schemas.yaml index cb865205..7de3248a 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-relationship-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-relationship-schemas.yaml @@ -12,6 +12,7 @@ components: - VIP_CONTACT - ACCOUNTING, - OPERATIONS + - SUBSCRIBER HsOfficeRelationship: type: object @@ -25,6 +26,9 @@ components: $ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson' relType: type: string + relTypeMark: + type: string + nullable: true contact: $ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact' @@ -47,6 +51,8 @@ components: format: uuid relType: type: string + relTypeMark: + type: string nullable: true contactUuid: type: string diff --git a/src/main/resources/db/changelog/230-hs-office-relationship.sql b/src/main/resources/db/changelog/230-hs-office-relationship.sql index 942813d9..01e5b7e2 100644 --- a/src/main/resources/db/changelog/230-hs-office-relationship.sql +++ b/src/main/resources/db/changelog/230-hs-office-relationship.sql @@ -10,7 +10,8 @@ CREATE TYPE HsOfficeRelationshipType AS ENUM ( 'REPRESENTATIVE', 'VIP_CONTACT', 'ACCOUNTING', - 'OPERATIONS'); + 'OPERATIONS', + 'SUBSCRIBER'); CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT; @@ -20,7 +21,8 @@ create table if not exists hs_office_relationship relAnchorUuid uuid not null references hs_office_person(uuid), relHolderUuid uuid not null references hs_office_person(uuid), contactUuid uuid references hs_office_contact(uuid), - relType HsOfficeRelationshipType not null + relType HsOfficeRelationshipType not null, + relTypeMark varchar(24) ); --// diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java index ad1edb48..0b2fd5ab 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java @@ -22,6 +22,7 @@ import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEnti import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType; import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity; import net.hostsharing.test.JpaAttempt; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.BeforeEachCallback; @@ -113,6 +114,17 @@ import static org.assertj.core.api.Fail.fail; @ExtendWith(OrderedDependedTestsExtension.class) public class ImportOfficeData extends ContextBasedTest { + private static final String[] SUBSCRIBER_ROLES = new String[] { + "subscriber:operations-discussion", + "subscriber:operations-announce", + "subscriber:members-announce", + "subscriber:members-discussion", + "subscriber:customers-announce" + }; + private static final String[] KNOWN_ROLES = ArrayUtils.addAll( + new String[]{"partner", "vip-contact", "ex-partner", "billing", "contractual", "operation"}, + SUBSCRIBER_ROLES); + static int relationshipId = 2000000; @Value("${spring.datasource.url}") @@ -253,11 +265,14 @@ public class ImportOfficeData extends ContextBasedTest { 2000001=rel(relAnchor='LP JM GmbH', relType='EX_PARTNER', relHolder='LP JM e.K.', contact='JM e.K.'), 2000002=rel(relAnchor='LP JM GmbH', relType='OPERATIONS', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), 2000003=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), - 2000004=rel(relAnchor='LP JM GmbH', relType='REPRESENTATIVE', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), - 2000005=rel(relAnchor='?? Test PS', relType='OPERATIONS', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'), - 2000006=rel(relAnchor='?? Test PS', relType='REPRESENTATIVE', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'), - 2000007=rel(relAnchor='NP Mellies, Michael', relType='REPRESENTATIVE', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies ') - } + 2000004=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), + 2000005=rel(relAnchor='LP JM GmbH', relType='REPRESENTATIVE', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), + 2000006=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), + 2000007=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), + 2000008=rel(relAnchor='?? Test PS', relType='OPERATIONS', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'), + 2000009=rel(relAnchor='?? Test PS', relType='REPRESENTATIVE', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'), + 2000010=rel(relAnchor='NP Mellies, Michael', relType='REPRESENTATIVE', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies ') + } """); } @@ -312,10 +327,10 @@ public class ImportOfficeData extends ContextBasedTest { assertThat(toFormattedString(coopShares)).isEqualToIgnoringWhitespace(""" { - 33443=CoopShareTransaction(M-1001700, 2000-12-06, SUBSCRIPTION, 20, initial share subscription), - 33451=CoopShareTransaction(M-1002000, 2000-12-06, SUBSCRIPTION, 2, initial share subscription), - 33701=CoopShareTransaction(M-1001700, 2005-01-10, SUBSCRIPTION, 40, increase), - 33810=CoopShareTransaction(M-1002000, 2016-12-31, CANCELLATION, 22, membership ended) + 33443=CoopShareTransaction(1001700, 2000-12-06, SUBSCRIPTION, 20, initial share subscription), + 33451=CoopShareTransaction(1002000, 2000-12-06, SUBSCRIPTION, 2, initial share subscription), + 33701=CoopShareTransaction(1001700, 2005-01-10, SUBSCRIPTION, 40, increase), + 33810=CoopShareTransaction(1002000, 2016-12-31, CANCELLATION, 22, membership ended) } """); } @@ -339,14 +354,14 @@ public class ImportOfficeData extends ContextBasedTest { assertThat(toFormattedString(coopAssets)).isEqualToIgnoringWhitespace(""" { - 30000=CoopAssetsTransaction(10017, 2000-12-06, DEPOSIT, 1280.00, for subscription A), - 31000=CoopAssetsTransaction(10020, 2000-12-06, DEPOSIT, 128.00, for subscription B), - 32000=CoopAssetsTransaction(10017, 2005-01-10, DEPOSIT, 2560.00, for subscription C), - 33001=CoopAssetsTransaction(10017, 2005-01-10, TRANSFER, -512.00, for transfer to 10), - 33002=CoopAssetsTransaction(10020, 2005-01-10, ADOPTION, 512.00, for transfer from 7), - 34001=CoopAssetsTransaction(10020, 2016-12-31, CLEARING, -8.00, for cancellation D), - 34002=CoopAssetsTransaction(10020, 2016-12-31, DISBURSAL, -100.00, for cancellation D), - 34003=CoopAssetsTransaction(10020, 2016-12-31, LOSS, -20.00, for cancellation D) + 30000=CoopAssetsTransaction(1001700, 2000-12-06, DEPOSIT, 1280.00, for subscription A), + 31000=CoopAssetsTransaction(1002000, 2000-12-06, DEPOSIT, 128.00, for subscription B), + 32000=CoopAssetsTransaction(1001700, 2005-01-10, DEPOSIT, 2560.00, for subscription C), + 33001=CoopAssetsTransaction(1001700, 2005-01-10, TRANSFER, -512.00, for transfer to 10), + 33002=CoopAssetsTransaction(1002000, 2005-01-10, ADOPTION, 512.00, for transfer from 7), + 34001=CoopAssetsTransaction(1002000, 2016-12-31, CLEARING, -8.00, for cancellation D), + 34002=CoopAssetsTransaction(1002000, 2016-12-31, DISBURSAL, -100.00, for cancellation D), + 34003=CoopAssetsTransaction(1002000, 2016-12-31, LOSS, -20.00, for cancellation D) } """); } @@ -743,7 +758,13 @@ public class ImportOfficeData extends ContextBasedTest { if (containsRole(rec, "vip-contact")) { addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.VIP_CONTACT); } - verifyContainsOnly(rec.getString("roles"), "partner", "vip-contact", "ex-partner", "billing", "contractual", "operation"); + for (String subscriberRole: SUBSCRIBER_ROLES) { + if (containsRole(rec, subscriberRole)) { + addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.SUBSCRIBER) + .setRelTypeMark(subscriberRole.split(":")[1]); + } + } + verifyContainsOnlyKnownRoles(rec.getString("roles")); }); optionallyAddMissingContractualRelationships(); @@ -767,7 +788,7 @@ public class ImportOfficeData extends ContextBasedTest { return containsRole(rec, "partner"); } - private static void addRelationship( + private static HsOfficeRelationshipEntity addRelationship( final HsOfficePersonEntity partnerPerson, final HsOfficePersonEntity contactPerson, final HsOfficeContactEntity contact, @@ -779,6 +800,7 @@ public class ImportOfficeData extends ContextBasedTest { .relType(representative) .build(); relationships.put(relationshipId++, rel); + return rel; } private HsOfficePersonEntity initPerson(final HsOfficePersonEntity person, final Record contactRecord) { @@ -823,9 +845,9 @@ public class ImportOfficeData extends ContextBasedTest { return false; } - private void verifyContainsOnly(final String roles, final String... allowedRoles) { + private void verifyContainsOnlyKnownRoles(final String roles) { + final var allowedRolesSet = stream(KNOWN_ROLES).collect(Collectors.toSet()); final var givenRolesSet = stream(roles.replace(" ", "").split(",")).collect(Collectors.toSet()); - final var allowedRolesSet = stream(allowedRoles).collect(Collectors.toSet()); final var unexpectedRolesSet = new HashSet<>(givenRolesSet); unexpectedRolesSet.removeAll(allowedRolesSet); assertThat(unexpectedRolesSet).isEmpty(); diff --git a/src/test/resources/migration/contacts.csv b/src/test/resources/migration/contacts.csv index af67bce3..3f185a50 100644 --- a/src/test/resources/migration/contacts.csv +++ b/src/test/resources/migration/contacts.csv @@ -6,8 +6,8 @@ contact_id; bp_id; salut; first_name; last_name; title; firma; co; street; zip # eine juristische Person mit drei separaten Ansprechpartnern, vip-contact und ex-partner 1200; 20;; ; ; ; JM e.K.;; Wiesenweg 15; 12335; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; jm-ex-partner@example.org; ex-partner 1201; 20; Frau; Jenny; Meyer-Billing; Dr.; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 7777777; +49 30 1111111; ; +49 30 2222222; jm-billing@example.org; billing -1202; 20; Herr; Andrew; Meyer-Operation; ; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 3333333; ; +49 30 4444444; am-operation@example.org; operation,vip-contact -1203; 20; Herr; Philip; Meyer-Contract; ; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; pm-partner@example.org; partner,contractual +1202; 20; Herr; Andrew; Meyer-Operation; ; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 3333333; ; +49 30 4444444; am-operation@example.org; operation,vip-contact,subscriber:operations-announce +1203; 20; Herr; Philip; Meyer-Contract; ; JM GmbH;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; pm-partner@example.org; partner,contractual,subscriber:members-announce,subscriber:customers-announce # eine juristische Person mit nur einem Ansprechpartner und explizitem contractual 1301; 22; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; partner,billing,contractual,operation