introduce-partner-business-role #16

Merged
hsh-michaelhoennig merged 33 commits from introduce-partner-business-role into master 2024-02-01 14:48:16 +01:00
7 changed files with 62 additions and 28 deletions
Showing only changes of commit 53c3b04ba1 - Show all commits

View File

@ -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 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-spotless='./gradlew spotlessApply -x pitest -x test -x :processResources'
alias gw-test='. .aliases; ./gradlew test' alias gw-test='. .aliases; ./gradlew test importOfficeData'
alias gw-check='. .aliases; gw check -x pitest -x :dependencyCheckAnalyze' alias gw-check='. .aliases; gw test importOfficeData check -x pitest -x :dependencyCheckAnalyze'

View File

@ -54,6 +54,9 @@ public class HsOfficeRelationshipEntity implements HasUuid, Stringifyable {
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private HsOfficeRelationshipType relType; private HsOfficeRelationshipType relType;
@Column(name = "reltypemark")
private String relTypeMark;
@Override @Override
public String toString() { public String toString() {
return toString.apply(this); return toString.apply(this);

View File

@ -6,5 +6,6 @@ public enum HsOfficeRelationshipType {
REPRESENTATIVE, REPRESENTATIVE,
VIP_CONTACT, VIP_CONTACT,
ACCOUNTING, ACCOUNTING,
OPERATIONS OPERATIONS,
SUBSCRIBER
} }

View File

@ -12,6 +12,7 @@ components:
- VIP_CONTACT - VIP_CONTACT
- ACCOUNTING, - ACCOUNTING,
- OPERATIONS - OPERATIONS
- SUBSCRIBER
HsOfficeRelationship: HsOfficeRelationship:
type: object type: object
@ -25,6 +26,9 @@ components:
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson' $ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
relType: relType:
type: string type: string
relTypeMark:
type: string
nullable: true
contact: contact:
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact' $ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
@ -47,6 +51,8 @@ components:
format: uuid format: uuid
relType: relType:
type: string type: string
relTypeMark:
type: string
nullable: true nullable: true
contactUuid: contactUuid:
type: string type: string

View File

@ -10,7 +10,8 @@ CREATE TYPE HsOfficeRelationshipType AS ENUM (
'REPRESENTATIVE', 'REPRESENTATIVE',
'VIP_CONTACT', 'VIP_CONTACT',
'ACCOUNTING', 'ACCOUNTING',
'OPERATIONS'); 'OPERATIONS',
'SUBSCRIBER');
CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT; 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), relAnchorUuid uuid not null references hs_office_person(uuid),
relHolderUuid uuid not null references hs_office_person(uuid), relHolderUuid uuid not null references hs_office_person(uuid),
contactUuid uuid references hs_office_contact(uuid), contactUuid uuid references hs_office_contact(uuid),
relType HsOfficeRelationshipType not null relType HsOfficeRelationshipType not null,
relTypeMark varchar(24)
); );
--// --//

View File

@ -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.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.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback;
@ -113,6 +114,17 @@ import static org.assertj.core.api.Fail.fail;
@ExtendWith(OrderedDependedTestsExtension.class) @ExtendWith(OrderedDependedTestsExtension.class)
public class ImportOfficeData extends ContextBasedTest { 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; static int relationshipId = 2000000;
@Value("${spring.datasource.url}") @Value("${spring.datasource.url}")
@ -253,10 +265,13 @@ public class ImportOfficeData extends ContextBasedTest {
2000001=rel(relAnchor='LP JM GmbH', relType='EX_PARTNER', relHolder='LP JM e.K.', contact='JM e.K.'), 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'), 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'), 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'), 2000004=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000005=rel(relAnchor='?? Test PS', relType='OPERATIONS', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'), 2000005=rel(relAnchor='LP JM GmbH', relType='REPRESENTATIVE', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000006=rel(relAnchor='?? Test PS', relType='REPRESENTATIVE', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'), 2000006=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000007=rel(relAnchor='NP Mellies, Michael', relType='REPRESENTATIVE', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies ') 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(""" assertThat(toFormattedString(coopShares)).isEqualToIgnoringWhitespace("""
{ {
33443=CoopShareTransaction(M-1001700, 2000-12-06, SUBSCRIPTION, 20, initial share subscription), 33443=CoopShareTransaction(1001700, 2000-12-06, SUBSCRIPTION, 20, initial share subscription),
33451=CoopShareTransaction(M-1002000, 2000-12-06, SUBSCRIPTION, 2, initial share subscription), 33451=CoopShareTransaction(1002000, 2000-12-06, SUBSCRIPTION, 2, initial share subscription),
33701=CoopShareTransaction(M-1001700, 2005-01-10, SUBSCRIPTION, 40, increase), 33701=CoopShareTransaction(1001700, 2005-01-10, SUBSCRIPTION, 40, increase),
33810=CoopShareTransaction(M-1002000, 2016-12-31, CANCELLATION, 22, membership ended) 33810=CoopShareTransaction(1002000, 2016-12-31, CANCELLATION, 22, membership ended)
} }
"""); """);
} }
@ -339,14 +354,14 @@ public class ImportOfficeData extends ContextBasedTest {
assertThat(toFormattedString(coopAssets)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(coopAssets)).isEqualToIgnoringWhitespace("""
{ {
30000=CoopAssetsTransaction(10017, 2000-12-06, DEPOSIT, 1280.00, for subscription A), 30000=CoopAssetsTransaction(1001700, 2000-12-06, DEPOSIT, 1280.00, for subscription A),
31000=CoopAssetsTransaction(10020, 2000-12-06, DEPOSIT, 128.00, for subscription B), 31000=CoopAssetsTransaction(1002000, 2000-12-06, DEPOSIT, 128.00, for subscription B),
32000=CoopAssetsTransaction(10017, 2005-01-10, DEPOSIT, 2560.00, for subscription C), 32000=CoopAssetsTransaction(1001700, 2005-01-10, DEPOSIT, 2560.00, for subscription C),
33001=CoopAssetsTransaction(10017, 2005-01-10, TRANSFER, -512.00, for transfer to 10), 33001=CoopAssetsTransaction(1001700, 2005-01-10, TRANSFER, -512.00, for transfer to 10),
33002=CoopAssetsTransaction(10020, 2005-01-10, ADOPTION, 512.00, for transfer from 7), 33002=CoopAssetsTransaction(1002000, 2005-01-10, ADOPTION, 512.00, for transfer from 7),
34001=CoopAssetsTransaction(10020, 2016-12-31, CLEARING, -8.00, for cancellation D), 34001=CoopAssetsTransaction(1002000, 2016-12-31, CLEARING, -8.00, for cancellation D),
34002=CoopAssetsTransaction(10020, 2016-12-31, DISBURSAL, -100.00, for cancellation D), 34002=CoopAssetsTransaction(1002000, 2016-12-31, DISBURSAL, -100.00, for cancellation D),
34003=CoopAssetsTransaction(10020, 2016-12-31, LOSS, -20.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")) { if (containsRole(rec, "vip-contact")) {
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.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(); optionallyAddMissingContractualRelationships();
@ -767,7 +788,7 @@ public class ImportOfficeData extends ContextBasedTest {
return containsRole(rec, "partner"); return containsRole(rec, "partner");
} }
private static void addRelationship( private static HsOfficeRelationshipEntity addRelationship(
final HsOfficePersonEntity partnerPerson, final HsOfficePersonEntity partnerPerson,
final HsOfficePersonEntity contactPerson, final HsOfficePersonEntity contactPerson,
final HsOfficeContactEntity contact, final HsOfficeContactEntity contact,
@ -779,6 +800,7 @@ public class ImportOfficeData extends ContextBasedTest {
.relType(representative) .relType(representative)
.build(); .build();
relationships.put(relationshipId++, rel); relationships.put(relationshipId++, rel);
return rel;
} }
private HsOfficePersonEntity initPerson(final HsOfficePersonEntity person, final Record contactRecord) { private HsOfficePersonEntity initPerson(final HsOfficePersonEntity person, final Record contactRecord) {
@ -823,9 +845,9 @@ public class ImportOfficeData extends ContextBasedTest {
return false; 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 givenRolesSet = stream(roles.replace(" ", "").split(",")).collect(Collectors.toSet());
final var allowedRolesSet = stream(allowedRoles).collect(Collectors.toSet());
final var unexpectedRolesSet = new HashSet<>(givenRolesSet); final var unexpectedRolesSet = new HashSet<>(givenRolesSet);
unexpectedRolesSet.removeAll(allowedRolesSet); unexpectedRolesSet.removeAll(allowedRolesSet);
assertThat(unexpectedRolesSet).isEmpty(); assertThat(unexpectedRolesSet).isEmpty();

View File

@ -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 # 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 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 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 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 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 # eine juristische Person mit nur einem Ansprechpartner und explizitem contractual
1301; 22; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; partner,billing,contractual,operation 1301; 22; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; partner,billing,contractual,operation

1 contact_id; bp_id; salut; first_name; last_name; title; firma; co; street; zipcode;city; country; phone_private; phone_office; phone_mobile; fax; email; roles
6 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
7 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
8 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
9 # eine juristische Person mit nur einem Ansprechpartner und explizitem contractual
10 1301; 22; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; partner,billing,contractual,operation
11
12
13