db-migration #10
@ -1,5 +1,5 @@
|
||||
package net.hostsharing.hsadminng.hs.office.membership;
|
||||
|
||||
public enum HsOfficeReasonForTermination {
|
||||
NONE, CANCELLATION, TRANSFER, DEATH, LIQUIDATION, EXPULSION;
|
||||
NONE, CANCELLATION, TRANSFER, DEATH, LIQUIDATION, EXPULSION, UNKNOWN;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.hostsharing.hsadminng.hs.office.person;
|
||||
|
||||
public enum HsOfficePersonType {
|
||||
UNKNOWN,
|
||||
NATURAL,
|
||||
LEGAL,
|
||||
SOLE_REPRESENTATION,
|
||||
|
@ -54,6 +54,7 @@ public class HsOfficeSepaMandateEntity implements Stringifyable {
|
||||
|
||||
@Column(name = "validity", columnDefinition = "daterange")
|
||||
@Type(PostgreSQLRangeType.class)
|
||||
@Builder.Default
|
||||
private Range<LocalDate> validity = Range.infinite(LocalDate.class);
|
||||
|
||||
public void setValidFrom(final LocalDate validFrom) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
--changeset hs-office-person-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TYPE HsOfficePersonType AS ENUM ('NATURAL', 'LEGAL', 'SOLE_REPRESENTATION', 'JOINT_REPRESENTATION');
|
||||
CREATE TYPE HsOfficePersonType AS ENUM ('UNKNOWN', 'NATURAL', 'LEGAL', 'SOLE_REPRESENTATION', 'JOINT_REPRESENTATION');
|
||||
|
||||
CREATE CAST (character varying as HsOfficePersonType) WITH INOUT AS IMPLICIT;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
--changeset hs-office-membership-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TYPE HsOfficeReasonForTermination AS ENUM ('NONE', 'CANCELLATION', 'TRANSFER', 'DEATH', 'LIQUIDATION', 'EXPULSION');
|
||||
CREATE TYPE HsOfficeReasonForTermination AS ENUM ('NONE', 'CANCELLATION', 'TRANSFER', 'DEATH', 'LIQUIDATION', 'EXPULSION', 'UNKNOWN');
|
||||
|
||||
CREATE CAST (character varying as HsOfficeReasonForTermination) WITH INOUT AS IMPLICIT;
|
||||
|
||||
|
@ -3,10 +3,19 @@ package net.hostsharing.hsadminng.hs.office.migration;
|
||||
import com.opencsv.CSVParserBuilder;
|
||||
import com.opencsv.CSVReader;
|
||||
import com.opencsv.CSVReaderBuilder;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeReasonForTermination;
|
||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||
import net.hostsharing.test.JpaAttempt;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.io.IOException;
|
||||
@ -14,27 +23,53 @@ import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
@DataJpaTest
|
||||
@Import({ Context.class, JpaAttempt.class })
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class ImportBusinessPartners {
|
||||
|
||||
private Map<Integer, HsOfficePartnerEntity> partners = new HashMap<>();
|
||||
private Map<Integer, HsOfficeMembershipEntity> members = new HashMap<>();
|
||||
private static Map<Integer, HsOfficePartnerEntity> partners = new HashMap<>();
|
||||
private static Map<Integer, HsOfficeDebitorEntity> debitors = new HashMap<>();
|
||||
private static Map<Integer, HsOfficeMembershipEntity> memberships = new HashMap<>();
|
||||
|
||||
@Test
|
||||
void importsBusinessPartners() throws Exception {
|
||||
@Order(1)
|
||||
void importsBusinessPartners() {
|
||||
|
||||
try (Reader reader = resourceReader("migration/business_partners.csv")) {
|
||||
try (Reader reader = resourceReader("migration/business-partners.csv")) {
|
||||
final var records = readAllLines(reader);
|
||||
|
||||
importsBusinessPartners(records);
|
||||
|
||||
assertThat(records).hasSize(4);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
void importsContacts() {
|
||||
|
||||
try (Reader reader = resourceReader("migration/contacts.csv")) {
|
||||
final var records = readAllLines(reader);
|
||||
importsContacts(records);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void afterAll() {
|
||||
System.out.println(partners);
|
||||
System.out.println(debitors);
|
||||
System.out.println(memberships);
|
||||
|
||||
}
|
||||
|
||||
@ -54,14 +89,157 @@ public class ImportBusinessPartners {
|
||||
}
|
||||
|
||||
private void importsBusinessPartners(final List<String[]> records) {
|
||||
records.forEach( record -> {
|
||||
records.stream()
|
||||
.map(this::trimAll)
|
||||
.forEach(record -> {
|
||||
|
||||
final var partner = HsOfficePartnerEntity.builder()
|
||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||
.contact(HsOfficeContactEntity.builder().build())
|
||||
.person(HsOfficePersonEntity.builder()
|
||||
.personType(HsOfficePersonType.UNKNOWN) // TODO
|
||||
.build())
|
||||
.build();
|
||||
partners.put(toInt(record[0]), partner);
|
||||
|
||||
HsOfficePersonEntity.builder()
|
||||
.tradeName(record[])
|
||||
final var debitor = HsOfficeDebitorEntity.builder()
|
||||
.partner(partner)
|
||||
.debitorNumber(toInt(record[1]))
|
||||
// .memberCode(record[2]) TODO
|
||||
.partner(partner)
|
||||
.billingContact(partner.getContact())
|
||||
// .free(toBool(record[8])) TODO
|
||||
.vatBusiness("GROSS".equals(record[10]))
|
||||
.vatId(record[11])
|
||||
.build();
|
||||
|
||||
.build();
|
||||
});
|
||||
partners.put(toInt(record[0]), partner);
|
||||
|
||||
if (isNotBlank(record[3])) {
|
||||
final var membership = HsOfficeMembershipEntity.builder()
|
||||
.partner(partner)
|
||||
.memberNumber(toInt(record[1]))
|
||||
.validity(toPostgresDateRange(localDate(record[3]), localDate(record[4])))
|
||||
.reasonForTermination(
|
||||
isBlank(record[4])
|
||||
? HsOfficeReasonForTermination.NONE
|
||||
: HsOfficeReasonForTermination.UNKNOWN) // TODO
|
||||
.mainDebitor(debitor)
|
||||
.build();
|
||||
memberships.put(toInt(record[0]), membership);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void importsContacts(final List<String[]> records) {
|
||||
records.stream()
|
||||
.map(this::trimAll)
|
||||
.forEach(record -> {
|
||||
|
||||
final var partner = partners.get(toInt(record[1]));
|
||||
|
||||
final var contact = partner.getContact();
|
||||
contact.setLabel(toLabel(record[2], record[5], record[3], record[4], record[6]));
|
||||
contact.setEmailAddresses(record[16]);
|
||||
contact.setPostalAddress(toAddress(record));
|
||||
contact.setPhoneNumbers(toPhoneNumbers(record));
|
||||
|
||||
final var person = partner.getPerson();
|
||||
person.setTradeName(record[6]);
|
||||
// TODO: title+salutation
|
||||
person.setFamilyName(record[3]);
|
||||
person.setGivenName(record[4]);
|
||||
});
|
||||
}
|
||||
|
||||
private String[] trimAll(final String[] record) {
|
||||
for (int i = 0; i < record.length; ++i) {
|
||||
if (record[i] != null) {
|
||||
record[i] = record[i].trim();
|
||||
}
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
private String toPhoneNumbers(final String[] record) {
|
||||
final var result = new StringBuilder("{\n");
|
||||
if (isNotBlank(record[12]))
|
||||
result.append(" \"private\": " + "\"" + record[12] + "\",\n");
|
||||
if (isNotBlank(record[13]))
|
||||
result.append(" \"office\": " + "\"" + record[13] + "\",\n");
|
||||
if (isNotBlank(record[14]))
|
||||
result.append(" \"mobile\": " + "\"" + record[14] + "\",\n");
|
||||
if (isNotBlank(record[15]))
|
||||
result.append(" \"fax\": " + "\"" + record[15] + "\",\n");
|
||||
return (result + "}").replace("\",\n}", "\"\n}");
|
||||
}
|
||||
|
||||
private String toAddress(final String[] record) {
|
||||
final var result = new StringBuilder();
|
||||
final var name = toName(record[2], record[5], record[3], record[4]);
|
||||
if (isNotBlank(name))
|
||||
result.append(name + "\n");
|
||||
if (isNotBlank(record[6]))
|
||||
result.append(record[6] + "\n");
|
||||
if (isNotBlank(record[7]))
|
||||
result.append("c/o " + record[7] + "\n");
|
||||
if (isNotBlank(record[8]))
|
||||
result.append(record[8] + "\n");
|
||||
final var zipcodeAndCity = toZipcodeAndCity(record);
|
||||
if (isNotBlank(zipcodeAndCity))
|
||||
result.append(zipcodeAndCity + "\n");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String toZipcodeAndCity(final String[] record) {
|
||||
final var result = new StringBuilder();
|
||||
if (isNotBlank(record[11]))
|
||||
result.append(record[11] + " ");
|
||||
if (isNotBlank(record[9]))
|
||||
result.append(record[9] + " ");
|
||||
if (isNotBlank(record[10]))
|
||||
result.append(record[10]);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String toLabel(
|
||||
final String salut,
|
||||
final String title,
|
||||
final String firstname,
|
||||
final String lastname,
|
||||
final String firm) {
|
||||
final var result = new StringBuilder();
|
||||
if (isNotBlank(salut))
|
||||
result.append(salut + " ");
|
||||
if (isNotBlank(title))
|
||||
result.append(title + " ");
|
||||
if (isNotBlank(firstname))
|
||||
result.append(firstname + " ");
|
||||
if (isNotBlank(lastname))
|
||||
result.append(lastname + " ");
|
||||
if (result.length() > 0 && isNotBlank(firm)) {
|
||||
result.append(", " + firm);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String toName(final String salut, final String title, final String firstname, final String lastname) {
|
||||
return toLabel(salut, title, firstname, lastname, null);
|
||||
}
|
||||
|
||||
private static Integer toInt(final String value) {
|
||||
return isNotBlank(value) ? Integer.parseInt(value.trim()) : 0;
|
||||
}
|
||||
|
||||
private static Integer toInteger(final String value) {
|
||||
return isNotBlank(value) ? Integer.parseInt(value.trim()) : null;
|
||||
}
|
||||
|
||||
private LocalDate localDate(final String dateStringNullOrBlank) {
|
||||
if (isNotBlank(dateStringNullOrBlank)) {
|
||||
return LocalDate.parse(dateStringNullOrBlank);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Reader resourceReader(@NotNull final String resourcePath) {
|
||||
|
4
src/test/resources/migration/business-partners.csv
Normal file
4
src/test/resources/migration/business-partners.csv
Normal file
@ -0,0 +1,4 @@
|
||||
bp_id;member_id;member_code;member_since;member_until;member_role;author_contract;nondisc_contract;free;exempt_vat;indicator_vat;uid_vat
|
||||
7;10007;mih;2000-12-06;;Aufsichtsrat;2006-10-15;2001-10-15;false;false;NET;DE-VAT-007
|
||||
10;10010;xyz;2000-12-06;2015-12-31;;;;false;false;GROSS;
|
||||
12;11012;xxx;2021-04-01;;;;;true;true;GROSS;
|
|
@ -1,4 +0,0 @@
|
||||
bp_id; member_id; member_code; member_since; member_until; member_role; author_contract;nondisc_contract; free; exempt_vat; indicator_vat; uid_vat
|
||||
7; 10007; mih; 2000-12-06; ; Aufsichtsrat; 2006-10-15; 2001-10-15; false; false; NET; DE-VAT-007
|
||||
10; 10010; xyz; 2000-12-06; 2015-12-31; ; ; ; false; false; GROSS;
|
||||
12; 11012; xxx; 2021-04-01; ; ; ; ; true; true; GROSS;
|
Gitea Version: 1.22.6 |