auto generate representative relationship if no explicit contractor set, add vip-contact and fix db enum value for ex-partner

This commit is contained in:
Michael Hoennig 2024-01-19 12:39:03 +01:00
parent a0abec6a85
commit 5d298a498f
6 changed files with 109 additions and 68 deletions

View File

@ -4,6 +4,7 @@ public enum HsOfficeRelationshipType {
UNKNOWN, UNKNOWN,
EX_PARTNER, EX_PARTNER,
REPRESENTATIVE, REPRESENTATIVE,
VIP_CONTACT,
ACCOUNTING, ACCOUNTING,
OPERATIONS OPERATIONS
} }

View File

@ -6,9 +6,12 @@ components:
HsOfficeRelationshipType: HsOfficeRelationshipType:
type: string type: string
enum: enum:
- REPRESENTATIVE - UNKNOWN
- ACCOUNTING - EX_PARTNER
- TECHNICAL - REPRESENTATIVE,
- VIP_CONTACT
- ACCOUNTING,
- OPERATIONS
HsOfficeRelationship: HsOfficeRelationship:
type: object type: object

View File

@ -4,7 +4,13 @@
--changeset hs-office-relationship-MAIN-TABLE:1 endDelimiter:--// --changeset hs-office-relationship-MAIN-TABLE:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
CREATE TYPE HsOfficeRelationshipType AS ENUM ('UNKNOWN', 'EX-PARTNER', 'REPRESENTATIVE', 'ACCOUNTING', 'OPERATIONS'); CREATE TYPE HsOfficeRelationshipType AS ENUM (
'UNKNOWN',
'EX_PARTNER',
'REPRESENTATIVE',
'VIP_CONTACT',
'ACCOUNTING',
'OPERATIONS');
CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT; CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT;

View File

@ -111,6 +111,8 @@ import static org.assertj.core.api.Fail.fail;
@ExtendWith(OrderedDependedTestsExtension.class) @ExtendWith(OrderedDependedTestsExtension.class)
public class ImportOfficeData extends ContextBasedTest { public class ImportOfficeData extends ContextBasedTest {
static int relationshipId = 2000000;
@Value("${spring.datasource.username}") @Value("${spring.datasource.username}")
private String postgresAdminUser; private String postgresAdminUser;
@ -194,48 +196,54 @@ public class ImportOfficeData extends ContextBasedTest {
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
{ {
17=partner(NATURAL Mellies, Michael: Herr Michael Mellies ), 17=partner(NATURAL Mellies, Michael: Herr Michael Mellies ),
20=partner(LEGAL JM e.K.: Herr Philip Meyer-Contract , JM e.K.), 20=partner(LEGAL JM GmbH: Herr Philip Meyer-Contract , JM GmbH),
22=partner(LEGAL Test PS: Petra Schmidt , Test PS) 22=partner(LEGAL Test PS: Petra Schmidt , Test PS)
} }
"""); """);
assertThat(toFormattedString(contacts)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(contacts)).isEqualToIgnoringWhitespace("""
{ {
1101=contact(label='Herr Michael Mellies ', emailAddresses='mih@example.org'), 1101=contact(label='Herr Michael Mellies ', emailAddresses='mih@example.org'),
1201=contact(label='Frau Dr. Jenny Meyer-Billing , JM e.K.', emailAddresses='jm-billing@example.org'), 1200=contact(label='JM e.K.', emailAddresses='jm-ex-partner@example.org'),
1202=contact(label='Herr Andrew Meyer-Operation , JM e.K.', emailAddresses='am-operation@example.org'), 1201=contact(label='Frau Dr. Jenny Meyer-Billing , JM GmbH', emailAddresses='jm-billing@example.org'),
1203=contact(label='Herr Philip Meyer-Contract , JM e.K.', emailAddresses='pm-partner@example.org'), 1202=contact(label='Herr Andrew Meyer-Operation , JM GmbH', emailAddresses='am-operation@example.org'),
1203=contact(label='Herr Philip Meyer-Contract , JM GmbH', emailAddresses='pm-partner@example.org'),
1301=contact(label='Petra Schmidt , Test PS', emailAddresses='ps@example.com') 1301=contact(label='Petra Schmidt , Test PS', emailAddresses='ps@example.com')
} }
"""); """);
assertThat(toFormattedString(persons)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(persons)).isEqualToIgnoringWhitespace("""
{ {
1101=person(personType='NATURAL', tradeName='', familyName='Mellies', givenName='Michael'), 1101=person(personType='NATURAL', tradeName='', familyName='Mellies', givenName='Michael'),
1201=person(personType='LEGAL', tradeName='JM e.K.', familyName='Meyer-Billing', givenName='Jenny'), 1200=person(personType='LEGAL', tradeName='JM e.K.', familyName='', givenName=''),
1202=person(personType='LEGAL', tradeName='JM e.K.', familyName='Meyer-Operation', givenName='Andrew'), 1201=person(personType='LEGAL', tradeName='JM GmbH', familyName='Meyer-Billing', givenName='Jenny'),
1203=person(personType='LEGAL', tradeName='JM e.K.', familyName='Meyer-Contract', givenName='Philip'), 1202=person(personType='LEGAL', tradeName='JM GmbH', familyName='Meyer-Operation', givenName='Andrew'),
1203=person(personType='LEGAL', tradeName='JM GmbH', familyName='Meyer-Contract', givenName='Philip'),
1301=person(personType='LEGAL', tradeName='Test PS', familyName='Schmidt', givenName='Petra') 1301=person(personType='LEGAL', tradeName='Test PS', familyName='Schmidt', givenName='Petra')
} }
"""); """);
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
{ {
17=debitor(1001700: NATURAL Mellies, Michael: mih), 17=debitor(1001700: NATURAL Mellies, Michael: mih),
20=debitor(1002000: LEGAL JM e.K.: xyz), 20=debitor(1002000: LEGAL JM GmbH: xyz),
22=debitor(1102200: LEGAL Test PS: xxx) 22=debitor(1102200: LEGAL Test PS: xxx)
} }
"""); """);
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
{ {
17=Membership(10017, NATURAL Mellies, Michael, 1001700, [2000-12-06,), NONE), 17=Membership(10017, NATURAL Mellies, Michael, 1001700, [2000-12-06,), NONE),
20=Membership(10020, LEGAL JM e.K., 1002000, [2000-12-06,2016-01-01), UNKNOWN), 20=Membership(10020, LEGAL JM GmbH, 1002000, [2000-12-06,2016-01-01), UNKNOWN),
22=Membership(11022, LEGAL Test PS, 1102200, [2021-04-01,), NONE) 22=Membership(11022, LEGAL Test PS, 1102200, [2021-04-01,), NONE)
} }
"""); """);
assertThat(toFormattedString(relationships)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(relationships)).isEqualToIgnoringWhitespace("""
{ {
1101=rel(relAnchor='NATURAL Mellies, Michael', relType='OPERATIONS', relHolder='NATURAL Mellies, Michael', contact='Herr Michael Mellies '), 2000000=rel(relAnchor='NATURAL Mellies, Michael', relType='OPERATIONS', relHolder='NATURAL Mellies, Michael', contact='Herr Michael Mellies '),
1202=rel(relAnchor='LEGAL JM e.K.', relType='OPERATIONS', relHolder='LEGAL JM e.K.', contact='Herr Andrew Meyer-Operation , JM e.K.'), 2000001=rel(relAnchor='LEGAL JM GmbH', relType='EX_PARTNER', relHolder='LEGAL JM e.K.', contact='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.'), 2000002=rel(relAnchor='LEGAL JM GmbH', relType='OPERATIONS', relHolder='LEGAL JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
1301=rel(relAnchor='LEGAL Test PS', relType='REPRESENTATIVE', relHolder='LEGAL Test PS', contact='Petra Schmidt , Test PS') 2000003=rel(relAnchor='LEGAL JM GmbH', relType='VIP_CONTACT', relHolder='LEGAL JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000004=rel(relAnchor='LEGAL JM GmbH', relType='REPRESENTATIVE', relHolder='LEGAL JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000005=rel(relAnchor='LEGAL Test PS', relType='OPERATIONS', relHolder='LEGAL Test PS', contact='Petra Schmidt , Test PS'),
2000006=rel(relAnchor='LEGAL Test PS', relType='REPRESENTATIVE', relHolder='LEGAL Test PS', contact='Petra Schmidt , Test PS'),
2000007=rel(relAnchor='NATURAL Mellies, Michael', relType='REPRESENTATIVE', relHolder='NATURAL Mellies, Michael', contact='Herr Michael Mellies ')
} }
"""); """);
} }
@ -253,15 +261,17 @@ public class ImportOfficeData extends ContextBasedTest {
assumeThat(postgresAdminUser).isEqualTo("admin"); assumeThat(postgresAdminUser).isEqualTo("admin");
assertThat(bankAccounts.toString()).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(bankAccounts)).isEqualToIgnoringWhitespace("""
{ {
234234=bankAccount(holder='Michael Mellies', iban='DE37500105177419788228', bic='INGDDEFFXXX'), 234234=bankAccount(holder='Michael Mellies', iban='DE37500105177419788228', bic='INGDDEFFXXX'),
235662=bankAccount(holder='JM e.K.', iban='DE49500105174516484892', bic='INGDDEFFXXX') 235600=bankAccount(holder='JM e.K.', iban='DE02300209000106531065', bic='CMCIDEDD'),
235662=bankAccount(holder='JM GmbH', iban='DE49500105174516484892', bic='INGDDEFFXXX')
} }
"""); """);
assertThat(sepaMandates.toString()).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(sepaMandates)).isEqualToIgnoringWhitespace("""
{ {
234234=SEPA-Mandate(DE37500105177419788228, MH12345, 2004-06-12, [2004-06-15,)), 234234=SEPA-Mandate(DE37500105177419788228, MH12345, 2004-06-12, [2004-06-15,)),
235600=SEPA-Mandate(DE02300209000106531065, JM33344, 2004-01-15, [2004-01-20,2005-06-28)),
235662=SEPA-Mandate(DE49500105174516484892, JM33344, 2005-06-28, [2005-07-01,)) 235662=SEPA-Mandate(DE49500105174516484892, JM33344, 2005-06-28, [2005-07-01,))
} }
"""); """);
@ -686,7 +696,7 @@ public class ImportOfficeData extends ContextBasedTest {
final var debitor = debitors.get(rec.getInteger("bp_id")); final var debitor = debitors.get(rec.getInteger("bp_id"));
final var partnerPerson = partner.getPerson(); final var partnerPerson = partner.getPerson();
if (rec.getString("roles").contains("partner")) { if (containsRole(rec)) {
initPerson(partner.getPerson(), rec); initPerson(partner.getPerson(), rec);
} }
@ -700,43 +710,62 @@ public class ImportOfficeData extends ContextBasedTest {
final var contact = HsOfficeContactEntity.builder().build(); final var contact = HsOfficeContactEntity.builder().build();
initContact(contact, rec); initContact(contact, rec);
if (rec.getString("roles").contains("partner")) { if (containsRole(rec, "partner")) {
assertThat(partner.getContact()).isNull(); assertThat(partner.getContact()).isNull();
partner.setContact(contact); partner.setContact(contact);
} }
if (rec.getString("roles").contains("billing")) { if (containsRole(rec, "billing")) {
assertThat(debitor.getBillingContact()).isNull(); assertThat(debitor.getBillingContact()).isNull();
debitor.setBillingContact(contact); debitor.setBillingContact(contact);
} }
if (rec.getString("roles").contains("operation")) { if (containsRole(rec, "operation")) {
final var rel = HsOfficeRelationshipEntity.builder() addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.OPERATIONS);
.relAnchor(partnerPerson)
.relHolder(contactPerson)
.contact(contact)
.relType(HsOfficeRelationshipType.OPERATIONS)
.build();
relationships.put(contactId, rel);
} }
if (rec.getString("roles").contains("contractual")) { if (containsRole(rec, "contractual")) {
final var rel = HsOfficeRelationshipEntity.builder() addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.REPRESENTATIVE);
.relAnchor(partnerPerson)
.relHolder(contactPerson)
.contact(contact)
.relType(HsOfficeRelationshipType.REPRESENTATIVE)
.build();
relationships.put(contactId, rel);
} }
if (rec.getString("roles").contains("ex-partner")) { if (containsRole(rec, "ex-partner")) {
final var rel = HsOfficeRelationshipEntity.builder() addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.EX_PARTNER);
.relAnchor(partnerPerson)
.relHolder(contactPerson)
.contact(contact)
.relType(HsOfficeRelationshipType.EX_PARTNER)
.build();
relationships.put(contactId, rel);
} }
verifyContainsOnly(rec.getString("roles"), "partner", "ex-partner", "billing", "contractual", "operation"); if (containsRole(rec, "vip-contact")) {
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.VIP_CONTACT);
}
verifyContainsOnly(rec.getString("roles"), "partner", "vip-contact", "ex-partner", "billing", "contractual", "operation");
}); });
optionallyAddMissingContractualRelationships();
}
private static void optionallyAddMissingContractualRelationships() {
partners.forEach( (id, partner) -> {
final var partnerPerson = partner.getPerson();
if (relationships.values().stream().filter(rel -> rel.getRelHolder() == partnerPerson && rel.getRelType() == HsOfficeRelationshipType.REPRESENTATIVE).findFirst().isEmpty()) {
addRelationship(partnerPerson, partnerPerson, partner.getContact(), HsOfficeRelationshipType.REPRESENTATIVE);
}
});
}
private static boolean containsRole(final Record rec, final String role) {
final var roles = rec.getString("roles");
return ("," + roles + ",").contains("," + role + ",");
}
private static boolean containsRole(final Record rec) {
return containsRole(rec, "partner");
}
private static void addRelationship(
final HsOfficePersonEntity partnerPerson,
final HsOfficePersonEntity contactPerson,
final HsOfficeContactEntity contact,
final HsOfficeRelationshipType representative) {
final var rel = HsOfficeRelationshipEntity.builder()
.relAnchor(partnerPerson)
.relHolder(contactPerson)
.contact(contact)
.relType(representative)
.build();
relationships.put(relationshipId++, rel);
} }
private HsOfficePersonEntity initPerson(final HsOfficePersonEntity person, final Record contactRecord) { private HsOfficePersonEntity initPerson(final HsOfficePersonEntity person, final Record contactRecord) {
@ -880,8 +909,8 @@ public class ImportOfficeData extends ContextBasedTest {
result.append(firstname + " "); result.append(firstname + " ");
if (isNotBlank(lastname)) if (isNotBlank(lastname))
result.append(lastname + " "); result.append(lastname + " ");
if (result.length() > 0 && isNotBlank(firm)) { if (isNotBlank(firm)) {
result.append(", " + firm); result.append( (isBlank(result) ? "" : ", ") + firm);
} }
return result.toString(); return result.toString();
} }

View File

@ -1,12 +1,13 @@
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 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
# eine natürliche Person # eine natürliche Person, implizites contractual
1101; 17; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; partner,billing,operation 1101; 17; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; partner,billing,operation
# eine juristische Person mit drei separaten Ansprechpartnern # eine juristische Person mit drei separaten Ansprechpartnern, vip-contact und ex-partner
1201; 20; Frau; Jenny; Meyer-Billing; Dr.; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 7777777; +49 30 1111111; ; +49 30 2222222; jm-billing@example.org; billing 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
1202; 20; Herr; Andrew; Meyer-Operation; ; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 3333333; ; +49 30 4444444; am-operation@example.org; operation 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
1203; 20; Herr; Philip; Meyer-Contract; ; JM e.K.;; 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
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
# eine juristische Person mit nur einem Ansprechpartner # 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
2 # eine natürliche Person # eine natürliche Person, implizites contractual
3 1101; 17; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; partner,billing,operation
4 # eine juristische Person mit drei separaten Ansprechpartnern # eine juristische Person mit drei separaten Ansprechpartnern, vip-contact und ex-partner
5 1201; 20; Frau; Jenny; Meyer-Billing; Dr.; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 7777777; +49 30 1111111; ; +49 30 2222222; jm-billing@example.org; billing 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
6 1202; 20; Herr; Andrew; Meyer-Operation; ; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 3333333; ; +49 30 4444444; am-operation@example.org; operation 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 1203; 20; Herr; Philip; Meyer-Contract; ; JM e.K.;; 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
8 # eine juristische Person mit nur einem Ansprechpartner 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
9 1301; 22; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; partner,billing,contractual,operation # 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

View File

@ -1,3 +1,4 @@
sepa_mandat_id; bp_id; bank_customer; bank_name; bank_iban; bank_bic; mandat_ref; mandat_signed; mandat_since; mandat_until; mandat_used sepa_mandat_id; bp_id; bank_customer; bank_name; bank_iban; bank_bic; mandat_ref; mandat_signed; mandat_since; mandat_until; mandat_used
234234; 17; Michael Mellies; ING Bank AG; DE37500105177419788228; INGDDEFFXXX; MH12345; 2004-06-12; 2004-06-15; ; 2022-10-20 234234; 17; Michael Mellies; ING Bank AG; DE37500105177419788228; INGDDEFFXXX; MH12345; 2004-06-12; 2004-06-15; ; 2022-10-20
235662; 20; JM e.K.; ING Bank AG; DE49500105174516484892; INGDDEFFXXX; JM33344; 2005-06-28; 2005-07-01; ; 2016-01-18 235600; 20; JM e.K.; Targobank AG; DE02300209000106531065; CMCIDEDD; JM33344; 2004-01-15; 2004-01-20;2005-06-27 ;2016-01-18
235662; 20; JM GmbH; ING Bank AG; DE49500105174516484892; INGDDEFFXXX; JM33344; 2005-06-28; 2005-07-01; ; 2016-01-18

1 sepa_mandat_id bp_id bank_customer bank_name bank_iban bank_bic mandat_ref mandat_signed mandat_since mandat_until mandat_used
2 234234 17 Michael Mellies ING Bank AG DE37500105177419788228 INGDDEFFXXX MH12345 2004-06-12 2004-06-15 2022-10-20
3 235662 235600 20 JM e.K. ING Bank AG Targobank AG DE49500105174516484892 DE02300209000106531065 INGDDEFFXXX CMCIDEDD JM33344 2005-06-28 2004-01-15 2005-07-01 2004-01-20 2005-06-27 2016-01-18
4 235662 20 JM GmbH ING Bank AG DE49500105174516484892 INGDDEFFXXX JM33344 2005-06-28 2005-07-01 2016-01-18