From 188cb9733ef6c4e2013daf2d5e969bcb8aa304bd Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 26 Jan 2024 09:30:31 +0100 Subject: [PATCH] add-subscriber-role (#14) Co-authored-by: Michael Hoennig Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/14 Reviewed-by: Timotheus Pokorra --- .aliases | 4 +- .../HsOfficeRelationshipEntity.java | 4 ++ .../HsOfficeRelationshipType.java | 3 +- .../hs-office-relationship-schemas.yaml | 6 ++ .../changelog/230-hs-office-relationship.sql | 6 +- .../238-hs-office-relationship-test-data.sql | 9 ++- .../hs/office/migration/ImportOfficeData.java | 65 +++++++++++++------ .../HsOfficeRelationshipEntityUnitTest.java | 12 ++++ src/test/resources/migration/contacts.csv | 4 +- 9 files changed, 82 insertions(+), 31 deletions(-) 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..22cf712a 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 @@ -26,6 +26,7 @@ public class HsOfficeRelationshipEntity implements HasUuid, Stringifyable { private static Stringify toString = stringify(HsOfficeRelationshipEntity.class, "rel") .withProp(Fields.relAnchor, HsOfficeRelationshipEntity::getRelAnchor) .withProp(Fields.relType, HsOfficeRelationshipEntity::getRelType) + .withProp(Fields.relMark, HsOfficeRelationshipEntity::getRelMark) .withProp(Fields.relHolder, HsOfficeRelationshipEntity::getRelHolder) .withProp(Fields.contact, HsOfficeRelationshipEntity::getContact); @@ -54,6 +55,9 @@ public class HsOfficeRelationshipEntity implements HasUuid, Stringifyable { @Enumerated(EnumType.STRING) private HsOfficeRelationshipType relType; + @Column(name = "relmark") + private String relMark; + @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..8fb5abb2 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 + relMark: + type: string + nullable: true contact: $ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact' @@ -48,6 +52,8 @@ components: relType: type: string nullable: true + relMark: + type: string contactUuid: type: string format: uuid 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..18d21da2 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, + relMark varchar(24) ); --// diff --git a/src/main/resources/db/changelog/238-hs-office-relationship-test-data.sql b/src/main/resources/db/changelog/238-hs-office-relationship-test-data.sql index a46cf7ce..534ae512 100644 --- a/src/main/resources/db/changelog/238-hs-office-relationship-test-data.sql +++ b/src/main/resources/db/changelog/238-hs-office-relationship-test-data.sql @@ -12,7 +12,8 @@ create or replace procedure createHsOfficeRelationshipTestData( anchorPersonTradeName varchar, holderPersonFamilyName varchar, relationshipType HsOfficeRelationshipType, - contactLabel varchar) + contactLabel varchar, + mark varchar default null) language plpgsql as $$ declare currentTask varchar; @@ -36,8 +37,8 @@ begin raise notice '- using holder person (%): %', holderPerson.uuid, holderPerson; raise notice '- using contact (%): %', contact.uuid, contact; insert - into hs_office_relationship (uuid, relanchoruuid, relholderuuid, reltype, contactUuid) - values (uuid_generate_v4(), anchorPerson.uuid, holderPerson.uuid, relationshipType, contact.uuid); + into hs_office_relationship (uuid, relanchoruuid, relholderuuid, reltype, relmark, contactUuid) + values (uuid_generate_v4(), anchorPerson.uuid, holderPerson.uuid, relationshipType, mark, contact.uuid); end; $$; --// @@ -76,6 +77,8 @@ do language plpgsql $$ call createHsOfficeRelationshipTestData('Second e.K.', 'Smith', 'REPRESENTATIVE', 'second contact'); call createHsOfficeRelationshipTestData('Third OHG', 'Smith', 'REPRESENTATIVE', 'third contact'); + + call createHsOfficeRelationshipTestData('Third OHG', 'Smith', 'SUBSCRIBER', 'third contact', 'members-announce'); end; $$; --// 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..30c153ec 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', relMark='operations-announce', 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', relMark='members-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), + 2000007=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='customers-announce', 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,14 @@ 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) + .setRelMark(subscriberRole.split(":")[1]) + ; + } + } + verifyContainsOnlyKnownRoles(rec.getString("roles")); }); optionallyAddMissingContractualRelationships(); @@ -767,7 +789,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 +801,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 +846,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/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipEntityUnitTest.java index 45049ef8..59433fa2 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relationship/HsOfficeRelationshipEntityUnitTest.java @@ -19,6 +19,18 @@ class HsOfficeRelationshipEntityUnitTest { .givenName("Mellie") .build(); + @Test + void toStringReturnsAllProperties() { + final var given = HsOfficeRelationshipEntity.builder() + .relType(HsOfficeRelationshipType.SUBSCRIBER) + .relMark("members-announce") + .relAnchor(anchor) + .relHolder(holder) + .build(); + + assertThat(given.toString()).isEqualTo("rel(relAnchor='LP some trade name', relType='SUBSCRIBER', relMark='members-announce', relHolder='NP Meier, Mellie')"); + } + @Test void toShortString() { final var given = HsOfficeRelationshipEntity.builder() 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