move Parter+Debitor person+contact to related Relationsship #20

Merged
hsh-michaelhoennig merged 101 commits from remove-direct-partner-person-and-contact into master 2024-03-28 12:15:14 +01:00
2 changed files with 79 additions and 59 deletions
Showing only changes of commit 2c552ff90a - Show all commits

View File

@ -69,7 +69,7 @@ public class HsOfficePartnerEntity implements Stringifyable, HasUuid {
private Integer partnerNumber; private Integer partnerNumber;
@ManyToOne(cascade = CascadeType.ALL) @ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "partnerReluuid", nullable = false) @JoinColumn(name = "partnerreluuid", nullable = false)
private HsOfficeRelationEntity partnerRel; private HsOfficeRelationEntity partnerRel;
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH }, optional = true) @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH }, optional = true)

View File

@ -191,10 +191,10 @@ public class ImportOfficeData extends ContextBasedTest {
assertThat(toFormattedString(contacts)).isEqualTo("{}"); assertThat(toFormattedString(contacts)).isEqualTo("{}");
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
{ {
17=debitor(D-1001700: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), mih), 17=debitor(D-1001700: rel(anchor='null null, null', type='DEBITOR'), mih),
20=debitor(D-1002000: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), xyz), 20=debitor(D-1002000: rel(anchor='null null, null', type='DEBITOR'), xyz),
22=debitor(D-1102200: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), xxx), 22=debitor(D-1102200: rel(anchor='null null, null', type='DEBITOR'), xxx),
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), zzz) 99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz)
} }
"""); """);
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
@ -278,7 +278,7 @@ public class ImportOfficeData extends ContextBasedTest {
17=debitor(D-1001700: rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael'), mih), 17=debitor(D-1001700: rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael'), mih),
20=debitor(D-1002000: rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH'), xyz), 20=debitor(D-1002000: rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH'), xyz),
22=debitor(D-1102200: rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS'), xxx), 22=debitor(D-1102200: rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS'), xxx),
99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), zzz) 99=debitor(D-1999900: rel(anchor='null null, null', type='DEBITOR'), zzz)
} }
"""); """);
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace(""" assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
@ -292,25 +292,29 @@ public class ImportOfficeData extends ContextBasedTest {
{ {
2000000=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), 2000000=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000001=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), 2000001=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000002=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), 2000002=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000003=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'), 2000003=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000004=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'), 2000004=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
2000005=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'), 2000005=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'), 2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000007=rel(anchor='null null, null', type='DEBITOR', holder='null null, null'), 2000007=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000008=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), 2000008=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000009=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '), 2000009=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'),
2000010=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'), 2000010=rel(anchor='null null, null', type='DEBITOR'),
2000011=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), 2000011=rel(anchor='null null, null', type='DEBITOR'),
2000012=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), 2000012=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000013=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'), 2000013=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
2000014=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), 2000014=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
2000015=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), 2000015=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000016=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'), 2000016=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000017=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'), 2000017=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
2000018=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'), 2000018=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000019=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'), 2000019=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000020=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ') 2000020=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
2000021=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
2000022=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000023=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
2000024=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ')
} }
"""); """);
} }
@ -425,7 +429,7 @@ public class ImportOfficeData extends ContextBasedTest {
void removeEmptyRelations() { void removeEmptyRelations() {
assumeThatWeAreImportingControlledTestData(); assumeThatWeAreImportingControlledTestData();
// avoid a error when persisting the deliberetely invalid partner entry #99 // avoid a error when persisting the deliberately invalid partner entry #99
final var idsToRemove = new HashSet<Integer>(); final var idsToRemove = new HashSet<Integer>();
relations.forEach( (id, r) -> { relations.forEach( (id, r) -> {
// such a record // such a record
@ -434,8 +438,12 @@ public class ImportOfficeData extends ContextBasedTest {
idsToRemove.add(id); idsToRemove.add(id);
} }
}); });
assertThat(idsToRemove.size()).isEqualTo(2); // partner #99 + Hostsharing eG itself
idsToRemove.forEach(id -> relations.remove(id)); // expected relations created from partner #99 + Hostsharing eG itself
idsToRemove.forEach(id -> {
System.out.println("removing unused relation: " + relations.get(id).toString());
relations.remove(id);
});
} }
@Test @Test
@ -454,8 +462,12 @@ public class ImportOfficeData extends ContextBasedTest {
idsToRemove.add(id); idsToRemove.add(id);
} }
}); });
assertThat(idsToRemove.size()).isEqualTo(1); // only from partner #99
idsToRemove.forEach(id -> partners.remove(id)); // expected partners created from partner #99 + Hostsharing eG itself
idsToRemove.forEach(id -> {
System.out.println("removing unused partner: " + partners.get(id).toString());
partners.remove(id);
});
} }
@Test @Test
@ -506,13 +518,23 @@ public class ImportOfficeData extends ContextBasedTest {
jpaAttempt.transacted(() -> { jpaAttempt.transacted(() -> {
context(rbacSuperuser); context(rbacSuperuser);
partners.forEach(this::persist); partners.forEach((id, partner) -> {
// TODO: this is ugly and I don't know why it's suddenly necessary
partner.getPartnerRel().setAnchor(em.merge(partner.getPartnerRel().getAnchor()));
partner.getPartnerRel().setHolder(em.merge(partner.getPartnerRel().getHolder()));
partner.getPartnerRel().setContact(em.merge(partner.getPartnerRel().getContact()));
partner.setPartnerRel(em.merge(partner.getPartnerRel()));
em.persist(partner);
});
updateLegacyIds(partners, "hs_office_partner_legacy_id", "bp_id"); updateLegacyIds(partners, "hs_office_partner_legacy_id", "bp_id");
}).assertSuccessful(); }).assertSuccessful();
jpaAttempt.transacted(() -> { jpaAttempt.transacted(() -> {
context(rbacSuperuser); context(rbacSuperuser);
debitors.forEach(this::persist); debitors.forEach((id, debitor) -> {
debitor.setDebitorRel(em.merge(debitor.getDebitorRel()));
em.persist(debitor);
});
}).assertSuccessful(); }).assertSuccessful();
jpaAttempt.transacted(() -> { jpaAttempt.transacted(() -> {
@ -682,13 +704,10 @@ public class ImportOfficeData extends ContextBasedTest {
.forEach(rec -> { .forEach(rec -> {
final var person = HsOfficePersonEntity.builder().build(); final var person = HsOfficePersonEntity.builder().build();
final var partnerRel = HsOfficeRelationEntity.builder() final var partnerRel = addRelation(
.holder(person) HsOfficeRelationType.PARTNER, mandant, person,
.type(HsOfficeRelationType.PARTNER) null // is set during contacts import depending on assigned roles
.anchor(mandant) );
.contact(null) // is set during contacts import depending on assigned roles
.build();
relations.put(relationId++, partnerRel);
final var partner = HsOfficePartnerEntity.builder() final var partner = HsOfficePartnerEntity.builder()
.partnerNumber(rec.getInteger("member_id")) .partnerNumber(rec.getInteger("member_id"))
@ -697,11 +716,11 @@ public class ImportOfficeData extends ContextBasedTest {
.build(); .build();
partners.put(rec.getInteger("bp_id"), partner); partners.put(rec.getInteger("bp_id"), partner);
final var debitorRel = HsOfficeRelationEntity.builder() final var debitorRel = addRelation(
.type(HsOfficeRelationType.DEBITOR) HsOfficeRelationType.DEBITOR, partnerRel.getHolder(), // partner person
.anchor(partnerRel.getHolder()) null, // will be set in contacts import
.holder(partnerRel.getHolder()) // currently debitor = partner null // will beset in contacts import
.build(); );
relations.put(relationId++, debitorRel); relations.put(relationId++, debitorRel);
final var debitor = HsOfficeDebitorEntity.builder() final var debitor = HsOfficeDebitorEntity.builder()
@ -856,14 +875,14 @@ public class ImportOfficeData extends ContextBasedTest {
final var partnerPerson = partner.getPartnerRel().getHolder(); final var partnerPerson = partner.getPartnerRel().getHolder();
if (containsPartnerRel(rec)) { if (containsPartnerRel(rec)) {
initPerson(partnerPerson, rec); addPerson(partnerPerson, rec);
} }
HsOfficePersonEntity contactPerson = partnerPerson; HsOfficePersonEntity contactPerson = partnerPerson;
if (!StringUtils.equals(rec.getString("firma"), partnerPerson.getTradeName()) || if (!StringUtils.equals(rec.getString("firma"), partnerPerson.getTradeName()) ||
!StringUtils.equals(rec.getString("first_name"), partnerPerson.getGivenName()) || !StringUtils.equals(rec.getString("first_name"), partnerPerson.getGivenName()) ||
!StringUtils.equals(rec.getString("last_name"), partnerPerson.getFamilyName())) { !StringUtils.equals(rec.getString("last_name"), partnerPerson.getFamilyName())) {
contactPerson = initPerson(HsOfficePersonEntity.builder().build(), rec); contactPerson = addPerson(HsOfficePersonEntity.builder().build(), rec);
} }
final var contact = HsOfficeContactEntity.builder().build(); final var contact = HsOfficeContactEntity.builder().build();
@ -875,23 +894,24 @@ public class ImportOfficeData extends ContextBasedTest {
} }
if (containsRole(rec, "billing")) { if (containsRole(rec, "billing")) {
assertThat(debitor.getDebitorRel().getContact()).isNull(); assertThat(debitor.getDebitorRel().getContact()).isNull();
debitor.getDebitorRel().setHolder(contactPerson);
debitor.getDebitorRel().setContact(contact); debitor.getDebitorRel().setContact(contact);
} }
if (containsRole(rec, "operation")) { if (containsRole(rec, "operation")) {
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.OPERATIONS); addRelation(HsOfficeRelationType.OPERATIONS, partnerPerson, contactPerson, contact);
} }
if (containsRole(rec, "contractual")) { if (containsRole(rec, "contractual")) {
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.REPRESENTATIVE); addRelation(HsOfficeRelationType.REPRESENTATIVE, partnerPerson, contactPerson, contact);
} }
if (containsRole(rec, "ex-partner")) { if (containsRole(rec, "ex-partner")) {
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.EX_PARTNER); addRelation(HsOfficeRelationType.EX_PARTNER, partnerPerson, contactPerson, contact);
} }
if (containsRole(rec, "vip-contact")) { if (containsRole(rec, "vip-contact")) {
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.VIP_CONTACT); addRelation(HsOfficeRelationType.VIP_CONTACT, partnerPerson, contactPerson, contact);
} }
for (String subscriberRole: SUBSCRIBER_ROLES) { for (String subscriberRole: SUBSCRIBER_ROLES) {
if (containsRole(rec, subscriberRole)) { if (containsRole(rec, subscriberRole)) {
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.SUBSCRIBER) addRelation(HsOfficeRelationType.SUBSCRIBER, partnerPerson, contactPerson, contact)
.setMark(subscriberRole.split(":")[1]) .setMark(subscriberRole.split(":")[1])
; ;
} }
@ -924,21 +944,21 @@ public class ImportOfficeData extends ContextBasedTest {
} }
private static HsOfficeRelationEntity addRelation( private static HsOfficeRelationEntity addRelation(
final HsOfficePersonEntity partnerPerson, final HsOfficeRelationType type,
final HsOfficePersonEntity contactPerson, final HsOfficePersonEntity anchor,
final HsOfficeContactEntity contact, final HsOfficePersonEntity holder,
final HsOfficeRelationType representative) { final HsOfficeContactEntity contact) {
final var rel = HsOfficeRelationEntity.builder() final var rel = HsOfficeRelationEntity.builder()
.anchor(partnerPerson) .anchor(anchor)
.holder(contactPerson) .holder(holder)
.contact(contact) .contact(contact)
.type(representative) .type(type)
.build(); .build();
relations.put(relationId++, rel); relations.put(relationId++, rel);
return rel; return rel;
} }
private HsOfficePersonEntity initPerson(final HsOfficePersonEntity person, final Record contactRecord) { private HsOfficePersonEntity addPerson(final HsOfficePersonEntity person, final Record contactRecord) {
// TODO: title+salutation: add to person // TODO: title+salutation: add to person
person.setGivenName(contactRecord.getString("first_name")); person.setGivenName(contactRecord.getString("first_name"));
person.setFamilyName(contactRecord.getString("last_name")); person.setFamilyName(contactRecord.getString("last_name"));