db-migration #10
@ -7,6 +7,9 @@ import net.hostsharing.hsadminng.context.Context;
|
|||||||
import net.hostsharing.hsadminng.context.ContextBasedTest;
|
import net.hostsharing.hsadminng.context.ContextBasedTest;
|
||||||
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.coopassets.HsOfficeCoopAssetsTransactionEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.coopshares.HsOfficeCoopSharesTransactionEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.coopshares.HsOfficeCoopSharesTransactionType;
|
||||||
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
||||||
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeReasonForTermination;
|
import net.hostsharing.hsadminng.hs.office.membership.HsOfficeReasonForTermination;
|
||||||
@ -26,12 +29,7 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
|||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.test.annotation.Commit;
|
import org.springframework.test.annotation.Commit;
|
||||||
import org.springframework.test.annotation.Rollback;
|
|
||||||
import org.springframework.transaction.TransactionStatus;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
@ -74,6 +72,8 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
private static Map<Integer, HsOfficeMembershipEntity> memberships = new HashMap<>();
|
private static Map<Integer, HsOfficeMembershipEntity> memberships = new HashMap<>();
|
||||||
private static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new HashMap<>();
|
private static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new HashMap<>();
|
||||||
private static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new HashMap<>();
|
private static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new HashMap<>();
|
||||||
|
private static Map<Integer, HsOfficeCoopSharesTransactionEntity> coopShares = new HashMap<>();
|
||||||
|
private static Map<Integer, HsOfficeCoopAssetsTransactionEntity> assetTransactions = new HashMap<>();
|
||||||
|
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
EntityManager em;
|
EntityManager em;
|
||||||
@ -196,6 +196,27 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4)
|
||||||
|
void importCoopShares() {
|
||||||
|
|
||||||
|
try (Reader reader = resourceReader("migration/share-transactions.csv")) {
|
||||||
|
final var lines = readAllLines(reader);
|
||||||
|
importCoopShares(justHeader(lines), withoutHeader(lines));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(coopShares.toString()).isEqualToIgnoringWhitespace("""
|
||||||
|
{
|
||||||
|
33810=CoopShareTransaction(10010, 2016-12-31, CANCELLATION, 22, membership ended),
|
||||||
|
33443=CoopShareTransaction(10007, 2000-12-06, SUBSCRIPTION, 20, initial share subscription),
|
||||||
|
33701=CoopShareTransaction(10007, 2005-01-10, SUBSCRIPTION, 40, increase),
|
||||||
|
33451=CoopShareTransaction(10010, 2000-12-06, SUBSCRIPTION, 2, initial share subscription)
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(10)
|
@Order(10)
|
||||||
@Commit
|
@Commit
|
||||||
@ -263,49 +284,77 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
final var person = HsOfficePersonEntity.builder()
|
final var person = HsOfficePersonEntity.builder()
|
||||||
.personType(HsOfficePersonType.UNKNOWN) // TODO
|
.personType(HsOfficePersonType.UNKNOWN) // TODO
|
||||||
.build();
|
.build();
|
||||||
persons.put(toInt(rec.get("bp_id")), person);
|
persons.put(rec.getInteger("bp_id"), person);
|
||||||
|
|
||||||
final var partner = HsOfficePartnerEntity.builder()
|
final var partner = HsOfficePartnerEntity.builder()
|
||||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||||
.contact(HsOfficeContactEntity.builder().build())
|
.contact(HsOfficeContactEntity.builder().build())
|
||||||
.person(person)
|
.person(person)
|
||||||
.build();
|
.build();
|
||||||
partners.put(toInt(rec.get("bp_id")), partner);
|
partners.put(rec.getInteger("bp_id"), partner);
|
||||||
|
|
||||||
final var debitor = HsOfficeDebitorEntity.builder()
|
final var debitor = HsOfficeDebitorEntity.builder()
|
||||||
.partner(partner)
|
.partner(partner)
|
||||||
.debitorNumber(toInt(rec.get("member_id")))
|
.debitorNumber(rec.getInteger("member_id"))
|
||||||
// .memberCode(rec.get("member_code")) TODO
|
// .memberCode(rec.get("member_code")) TODO: add as debitor_default_prefix to debitor
|
||||||
.partner(partner)
|
.partner(partner)
|
||||||
.billingContact(partner.getContact())
|
.billingContact(partner.getContact())
|
||||||
// .memberRoles(toBool(rec.get("member_role")) TODO
|
// .memberRoles(toBool(rec.get("member_role")) TODO: add negated as membership_billable to membership
|
||||||
// .authorContract(toBool(rec.get("author_contract")) TODO
|
// .authorContract(toBool(rec.get("author_contract")) not supported
|
||||||
// .nonDisclosureContract(toBool(rec.get("nondisc_contract")) TODO
|
// .nonDisclosureContract(toBool(rec.get("nondisc_contract")) not supported
|
||||||
// .free(toBool(rec.get("free")) TODO
|
// .free(toBool(rec.get("free")) TODO: add negated as billable to debitor
|
||||||
// .vatExempt(toBool(rec.get("exempt_vat")) TODO
|
// .vatExempt(toBool(rec.get("exempt_vat")) (reverse-charge) TODO: add as vat-reverse-charge to debitor
|
||||||
.vatBusiness("GROSS".equals(rec.get("indicator_vat")))
|
.vatBusiness("GROSS".equals(rec.getString("indicator_vat"))) // TODO: remove
|
||||||
.vatId(rec.get("uid_vat"))
|
.vatId(rec.getString("uid_vat"))
|
||||||
.build();
|
.build();
|
||||||
debitors.put(toInt(rec.get("bp_id")), debitor);
|
debitors.put(rec.getInteger("bp_id"), debitor);
|
||||||
|
|
||||||
partners.put(toInt(rec.get("bp_id")), partner);
|
partners.put(rec.getInteger("bp_id"), partner);
|
||||||
|
|
||||||
if (isNotBlank(rec.get("member_since"))) {
|
if (isNotBlank(rec.getString("member_since"))) {
|
||||||
final var membership = HsOfficeMembershipEntity.builder()
|
final var membership = HsOfficeMembershipEntity.builder()
|
||||||
.partner(partner)
|
.partner(partner)
|
||||||
.memberNumber(toInt(rec.get("member_id")))
|
.memberNumber(rec.getInteger("member_id"))
|
||||||
.validity(toPostgresDateRange(localDate(rec.get("member_since")), localDate(rec.get("member_until"))))
|
.validity(toPostgresDateRange(rec.getLocalDate("member_since"), rec.getLocalDate("member_until")))
|
||||||
.reasonForTermination(
|
.reasonForTermination(
|
||||||
isBlank(rec.get("member_until"))
|
isBlank(rec.getString("member_until"))
|
||||||
? HsOfficeReasonForTermination.NONE
|
? HsOfficeReasonForTermination.NONE
|
||||||
: HsOfficeReasonForTermination.UNKNOWN) // TODO
|
: HsOfficeReasonForTermination.UNKNOWN) // TODO
|
||||||
.mainDebitor(debitor)
|
.mainDebitor(debitor)
|
||||||
.build();
|
.build();
|
||||||
memberships.put(toInt(rec.get("bp_id")), membership);
|
memberships.put(rec.getInteger("bp_id"), membership);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void importCoopShares(final String[] header, final List<String[]> records) {
|
||||||
|
|
||||||
|
final var columns = new Columns(header);
|
||||||
|
|
||||||
|
records.stream()
|
||||||
|
.map(this::trimAll)
|
||||||
|
.map(row -> new Record(columns, row))
|
||||||
|
.forEach(rec -> {
|
||||||
|
final var member = memberships.get(rec.getInteger("bp_id"));
|
||||||
|
|
||||||
|
final var shareTransaction = HsOfficeCoopSharesTransactionEntity.builder()
|
||||||
|
.membership(member)
|
||||||
|
.valueDate(rec.getLocalDate("date"))
|
||||||
|
.transactionType(
|
||||||
|
"SUBSCRIPTION".equals(rec.getString("action"))
|
||||||
|
? HsOfficeCoopSharesTransactionType.SUBSCRIPTION
|
||||||
|
: "UNSUBSCRIPTION".equals(rec.getString("action"))
|
||||||
|
? HsOfficeCoopSharesTransactionType.CANCELLATION
|
||||||
|
: HsOfficeCoopSharesTransactionType.ADJUSTMENT
|
||||||
|
)
|
||||||
|
.shareCount(rec.getInteger("quantity"))
|
||||||
|
.reference(rec.getString("comment"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
coopShares.put(rec.getInteger("member_share_id"), shareTransaction);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void importSepaMandates(final String[] header, final List<String[]> records) {
|
private void importSepaMandates(final String[] header, final List<String[]> records) {
|
||||||
|
|
||||||
final var columns = new Columns(header);
|
final var columns = new Columns(header);
|
||||||
@ -314,25 +363,25 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
.map(this::trimAll)
|
.map(this::trimAll)
|
||||||
.map(row -> new Record(columns, row))
|
.map(row -> new Record(columns, row))
|
||||||
.forEach(rec -> {
|
.forEach(rec -> {
|
||||||
final var debitor = debitors.get(toInt(rec.get("bp_id")));
|
final var debitor = debitors.get(rec.getInteger("bp_id"));
|
||||||
|
|
||||||
final var sepaMandate = HsOfficeSepaMandateEntity.builder()
|
final var sepaMandate = HsOfficeSepaMandateEntity.builder()
|
||||||
.debitor(debitor)
|
.debitor(debitor)
|
||||||
.bankAccount(HsOfficeBankAccountEntity.builder()
|
.bankAccount(HsOfficeBankAccountEntity.builder()
|
||||||
.holder(rec.get("bank_customer"))
|
.holder(rec.getString("bank_customer"))
|
||||||
// .bankName(rec.get("bank_name")) // TODO
|
// .bankName(rec.get("bank_name")) // not supported
|
||||||
.iban(rec.get("bank_iban"))
|
.iban(rec.getString("bank_iban"))
|
||||||
.bic(rec.get("bank_bic"))
|
.bic(rec.getString("bank_bic"))
|
||||||
.build())
|
.build())
|
||||||
.reference(rec.get("mandat_ref"))
|
.reference(rec.getString("mandat_ref"))
|
||||||
.agreement(LocalDate.parse(rec.get("mandat_signed")))
|
.agreement(LocalDate.parse(rec.getString("mandat_signed")))
|
||||||
.validity(toPostgresDateRange(
|
.validity(toPostgresDateRange(
|
||||||
toLocalDate(rec.get("mandat_since")),
|
rec.getLocalDate("mandat_since"),
|
||||||
toLocalDate(rec.get("mandat_until"))))
|
rec.getLocalDate("mandat_until")))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
sepaMandates.put(toInt(rec.get("sepa_mandat_id")), sepaMandate);
|
sepaMandates.put(rec.getInteger("sepa_mandat_id"), sepaMandate);
|
||||||
bankAccounts.put(toInt(rec.get("sepa_mandat_id")), sepaMandate.getBankAccount());
|
bankAccounts.put(rec.getInteger("sepa_mandat_id"), sepaMandate.getBankAccount());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,15 +393,15 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
.map(this::trimAll)
|
.map(this::trimAll)
|
||||||
.map(row -> new Record(columns, row))
|
.map(row -> new Record(columns, row))
|
||||||
.forEach(rec -> {
|
.forEach(rec -> {
|
||||||
if (isNotBlank(rec.get("roles")) && rec.get("roles").contains("billing")) {
|
if (isNotBlank(rec.getString("roles")) && rec.getString("roles").contains("billing")) {
|
||||||
|
|
||||||
final var partner = partners.get(toInt(rec.get("bp_id")));
|
final var partner = partners.get(rec.getInteger("bp_id"));
|
||||||
|
|
||||||
final var person = partner.getPerson();
|
final var person = partner.getPerson();
|
||||||
person.setTradeName(rec.get("firma"));
|
person.setTradeName(rec.getString("firma"));
|
||||||
// TODO: title+salutation
|
// TODO: title+salutation: add to person
|
||||||
person.setGivenName(rec.get("first_name"));
|
person.setGivenName(rec.getString("first_name"));
|
||||||
person.setFamilyName(rec.get("last_name"));
|
person.setFamilyName(rec.getString("last_name"));
|
||||||
|
|
||||||
initContact(partner.getContact(), rec);
|
initContact(partner.getContact(), rec);
|
||||||
|
|
||||||
@ -364,10 +413,10 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initContact(final HsOfficeContactEntity contact, final Record rec) {
|
private void initContact(final HsOfficeContactEntity contact, final Record rec) {
|
||||||
contacts.put(toInt(rec.get("contact_id")), contact);
|
contacts.put(rec.getInteger("contact_id"), contact);
|
||||||
|
|
||||||
contact.setLabel(toLabel(rec.get("salut"), rec.get("title"), rec.get("first_name"), rec.get("last_name"), rec.get("firma")));
|
contact.setLabel(toLabel(rec.getString("salut"), rec.getString("title"), rec.getString("first_name"), rec.getString("last_name"), rec.getString("firma")));
|
||||||
contact.setEmailAddresses(rec.get("email"));
|
contact.setEmailAddresses(rec.getString("email"));
|
||||||
contact.setPostalAddress(toAddress(rec));
|
contact.setPostalAddress(toAddress(rec));
|
||||||
contact.setPhoneNumbers(toPhoneNumbers(rec));
|
contact.setPhoneNumbers(toPhoneNumbers(rec));
|
||||||
}
|
}
|
||||||
@ -382,28 +431,28 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
private String toPhoneNumbers(final Record rec) {
|
private String toPhoneNumbers(final Record rec) {
|
||||||
final var result = new StringBuilder("{\n");
|
final var result = new StringBuilder("{\n");
|
||||||
if (isNotBlank(rec.get("phone_private")))
|
if (isNotBlank(rec.getString("phone_private")))
|
||||||
result.append(" \"private\": " + "\"" + rec.get("phone_private") + "\",\n");
|
result.append(" \"private\": " + "\"" + rec.getString("phone_private") + "\",\n");
|
||||||
if (isNotBlank(rec.get("phone_office")))
|
if (isNotBlank(rec.getString("phone_office")))
|
||||||
result.append(" \"office\": " + "\"" + rec.get("phone_office") + "\",\n");
|
result.append(" \"office\": " + "\"" + rec.getString("phone_office") + "\",\n");
|
||||||
if (isNotBlank(rec.get("phone_mobile")))
|
if (isNotBlank(rec.getString("phone_mobile")))
|
||||||
result.append(" \"mobile\": " + "\"" + rec.get("phone_mobile") + "\",\n");
|
result.append(" \"mobile\": " + "\"" + rec.getString("phone_mobile") + "\",\n");
|
||||||
if (isNotBlank(rec.get("fax")))
|
if (isNotBlank(rec.getString("fax")))
|
||||||
result.append(" \"fax\": " + "\"" + rec.get("fax") + "\",\n");
|
result.append(" \"fax\": " + "\"" + rec.getString("fax") + "\",\n");
|
||||||
return (result + "}").replace("\",\n}", "\"\n}");
|
return (result + "}").replace("\",\n}", "\"\n}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toAddress(final Record rec) {
|
private String toAddress(final Record rec) {
|
||||||
final var result = new StringBuilder();
|
final var result = new StringBuilder();
|
||||||
final var name = toName(rec.get("salut"), rec.get("title"), rec.get("first_name"), rec.get("last_name"));
|
final var name = toName(rec.getString("salut"), rec.getString("title"), rec.getString("first_name"), rec.getString("last_name"));
|
||||||
if (isNotBlank(name))
|
if (isNotBlank(name))
|
||||||
result.append(name + "\n");
|
result.append(name + "\n");
|
||||||
if (isNotBlank(rec.get("firma")))
|
if (isNotBlank(rec.getString("firma")))
|
||||||
result.append(rec.get("firma") + "\n");
|
result.append(rec.getString("firma") + "\n");
|
||||||
if (isNotBlank(rec.get("co")))
|
if (isNotBlank(rec.getString("co")))
|
||||||
result.append("c/o " + rec.get("co") + "\n");
|
result.append("c/o " + rec.getString("co") + "\n");
|
||||||
if (isNotBlank(rec.get("street")))
|
if (isNotBlank(rec.getString("street")))
|
||||||
result.append(rec.get("street") + "\n");
|
result.append(rec.getString("street") + "\n");
|
||||||
final var zipcodeAndCity = toZipcodeAndCity(rec);
|
final var zipcodeAndCity = toZipcodeAndCity(rec);
|
||||||
if (isNotBlank(zipcodeAndCity))
|
if (isNotBlank(zipcodeAndCity))
|
||||||
result.append(zipcodeAndCity + "\n");
|
result.append(zipcodeAndCity + "\n");
|
||||||
@ -412,12 +461,12 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
|
|
||||||
private String toZipcodeAndCity(final Record rec) {
|
private String toZipcodeAndCity(final Record rec) {
|
||||||
final var result = new StringBuilder();
|
final var result = new StringBuilder();
|
||||||
if (isNotBlank(rec.get("country")))
|
if (isNotBlank(rec.getString("country")))
|
||||||
result.append(rec.get("country") + " ");
|
result.append(rec.getString("country") + " ");
|
||||||
if (isNotBlank(rec.get("zipcode")))
|
if (isNotBlank(rec.getString("zipcode")))
|
||||||
result.append(rec.get("zipcode") + " ");
|
result.append(rec.getString("zipcode") + " ");
|
||||||
if (isNotBlank(rec.get("city")))
|
if (isNotBlank(rec.getString("city")))
|
||||||
result.append(rec.get("city"));
|
result.append(rec.getString("city"));
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,23 +495,6 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
return toLabel(salut, title, firstname, lastname, null);
|
return toLabel(salut, title, firstname, lastname, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalDate toLocalDate(final String dateString) {
|
|
||||||
if (isNotBlank(dateString)) {
|
|
||||||
return LocalDate.parse(dateString);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Integer toInt(final String value) {
|
|
||||||
return isNotBlank(value) ? Integer.parseInt(value.trim()) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private LocalDate localDate(final String dateStringNullOrBlank) {
|
|
||||||
if (isNotBlank(dateStringNullOrBlank)) {
|
|
||||||
return LocalDate.parse(dateStringNullOrBlank);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Reader resourceReader(@NotNull final String resourcePath) {
|
private Reader resourceReader(@NotNull final String resourcePath) {
|
||||||
return new InputStreamReader(getClass().getClassLoader().getResourceAsStream(resourcePath));
|
return new InputStreamReader(getClass().getClassLoader().getResourceAsStream(resourcePath));
|
||||||
@ -512,7 +544,27 @@ class Record {
|
|||||||
this.row = row;
|
this.row = row;
|
||||||
}
|
}
|
||||||
|
|
||||||
String get(final String columnName) {
|
String getString(final String columnName) {
|
||||||
return row[columns.indexOf(columnName)];
|
return row[columns.indexOf(columnName)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Integer getInteger(final String columnName) {
|
||||||
|
return toInt(getString(columnName));
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate getLocalDate(final String columnName) {
|
||||||
|
return toLocalDate(getString(columnName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer toInt(final String value) {
|
||||||
|
return isNotBlank(value) ? Integer.parseInt(value.trim()) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalDate toLocalDate(final String dateString) {
|
||||||
|
if (isNotBlank(dateString)) {
|
||||||
|
return LocalDate.parse(dateString);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user