Compare commits
3 Commits
19f962cf2e
...
1e5bc03407
Author | SHA1 | Date | |
---|---|---|---|
|
1e5bc03407 | ||
|
2e609884bf | ||
|
683c2f0ce4 |
@ -3,6 +3,6 @@ package net.hostsharing.hsadminng.hs.office.relationship;
|
|||||||
public enum HsOfficeRelationshipType {
|
public enum HsOfficeRelationshipType {
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
REPRESENTATIVE,
|
REPRESENTATIVE,
|
||||||
ACCOUNTING_CONTACT,
|
ACCOUNTING,
|
||||||
TECHNICAL_CONTACT
|
OPERATIONS
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- REPRESENTATIVE
|
- REPRESENTATIVE
|
||||||
- ACCOUNTING_CONTACT
|
- ACCOUNTING
|
||||||
- TECHNICAL_CONTACT
|
- TECHNICAL
|
||||||
|
|
||||||
HsOfficeRelationship:
|
HsOfficeRelationship:
|
||||||
type: object
|
type: object
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
--changeset hs-office-relationship-MAIN-TABLE:1 endDelimiter:--//
|
--changeset hs-office-relationship-MAIN-TABLE:1 endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
CREATE TYPE HsOfficeRelationshipType AS ENUM ('UNKNOWN', 'REPRESENTATIVE', 'ACCOUNTING_CONTACT', 'TECHNICAL_CONTACT');
|
CREATE TYPE HsOfficeRelationshipType AS ENUM ('UNKNOWN', 'REPRESENTATIVE', 'ACCOUNTING', 'OPERATIONS');
|
||||||
|
|
||||||
CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT;
|
CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT;
|
||||||
|
|
||||||
|
@ -35,9 +35,7 @@ import jakarta.persistence.EntityManager;
|
|||||||
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.PersistenceContext;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -45,6 +43,7 @@ import java.time.LocalDate;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static java.util.Arrays.stream;
|
import static java.util.Arrays.stream;
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
@ -102,8 +101,8 @@ import static org.assertj.core.api.Fail.fail;
|
|||||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
public class ImportOfficeTables extends ContextBasedTest {
|
public class ImportOfficeTables extends ContextBasedTest {
|
||||||
|
|
||||||
@Value("${spring.datasource.url}")
|
@Value("${spring.datasource.username}")
|
||||||
private String jdbcUrl;
|
private String postgresAdminUser;
|
||||||
|
|
||||||
// TODO: use real rbacSuperuser for actual import
|
// TODO: use real rbacSuperuser for actual import
|
||||||
private static final String rbacSuperuser = "superuser-alex@hostsharing.net";
|
private static final String rbacSuperuser = "superuser-alex@hostsharing.net";
|
||||||
@ -145,16 +144,16 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !"admin".equals(System.getenv("ADMIN_USER") )) {
|
if ( !"admin".equals(postgresAdminUser) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no contacts yet => mostly null values
|
// no contacts yet => mostly null values
|
||||||
assertThat(partners.toString()).isEqualToIgnoringWhitespace("""
|
assertThat(partners.toString()).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
7=partner(null, null: null),
|
7=partner(null, null),
|
||||||
10=partner(null, null: null),
|
10=partner(null, null),
|
||||||
12=partner(null, null: null)
|
12=partner(null, null)
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(contacts.toString()).isEqualTo("{}");
|
assertThat(contacts.toString()).isEqualTo("{}");
|
||||||
@ -184,7 +183,7 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !"admin".equals(System.getenv("HSADMINNG_POSTGRES_ADMIN_USERNAME") )) {
|
if ( !"admin".equals(postgresAdminUser) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,11 +196,11 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
""");
|
""");
|
||||||
assertThat(contacts.toString()).isEqualToIgnoringWhitespace("""
|
assertThat(contacts.toString()).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
71=contact(label='Herr Michael Mellies ', emailAddresses='mih@example.org'),
|
1101=contact(label='Herr Michael Mellies ', emailAddresses='mih@example.org'),
|
||||||
101=contact(label='Frau Dr. Jenny Meyer-Billing , JM e.K.', emailAddresses='jm-billing@example.org'),
|
1201=contact(label='Frau Dr. Jenny Meyer-Billing , JM e.K.', emailAddresses='jm-billing@example.org'),
|
||||||
102=contact(label='Herr Andrew Meyer-Operation , JM e.K.', emailAddresses='am-operation@example.org'),
|
1202=contact(label='Herr Andrew Meyer-Operation , JM e.K.', emailAddresses='am-operation@example.org'),
|
||||||
103=contact(label='Herr Philip Meyer-Contract , JM e.K.', emailAddresses='pm-contractual@example.org'),
|
1203=contact(label='Herr Philip Meyer-Contract , JM e.K.', emailAddresses='pm-partner@example.org'),
|
||||||
121=contact(label='Petra Schmidt , Test PS', emailAddresses='ps@example.com')
|
1301=contact(label='Petra Schmidt , Test PS', emailAddresses='ps@example.com')
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
assertThat(persons.toString()).isEqualToIgnoringWhitespace("""
|
assertThat(persons.toString()).isEqualToIgnoringWhitespace("""
|
||||||
@ -227,9 +226,10 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
""");
|
""");
|
||||||
assertThat(relationships.toString()).isEqualToIgnoringWhitespace("""
|
assertThat(relationships.toString()).isEqualToIgnoringWhitespace("""
|
||||||
{
|
{
|
||||||
71=rel(relAnchor='Mellies, Michael', relType='TECHNICAL_CONTACT', relHolder='Mellies, Michael', contact='Herr Michael Mellies '),
|
1101=rel(relAnchor='Mellies, Michael', relType='OPERATIONS', relHolder='Mellies, Michael', contact='Herr Michael Mellies '),
|
||||||
102=rel(relAnchor='JM e.K.', relType='TECHNICAL_CONTACT', relHolder='JM e.K.', contact='Herr Andrew Meyer-Operation , JM e.K.'),
|
1202=rel(relAnchor='JM e.K.', relType='OPERATIONS', relHolder='JM e.K.', contact='Herr Andrew Meyer-Operation , JM e.K.'),
|
||||||
121=rel(relAnchor='Test PS', relType='TECHNICAL_CONTACT', relHolder='Test PS', contact='Petra Schmidt , Test PS')
|
1203=rel(relAnchor='JM e.K.', relType='REPRESENTATIVE', relHolder='JM e.K.', contact='Herr Philip Meyer-Contract , JM e.K.'),
|
||||||
|
1301=rel(relAnchor='Test PS', relType='REPRESENTATIVE', relHolder='Test PS', contact='Petra Schmidt , Test PS')
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
@ -245,7 +245,7 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !"admin".equals(System.getenv("HSADMINNG_POSTGRES_ADMIN_USERNAME") )) {
|
if ( !"admin".equals(postgresAdminUser) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +274,7 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !"admin".equals(System.getenv("HSADMINNG_POSTGRES_ADMIN_USERNAME") )) {
|
if ( !"admin".equals(postgresAdminUser) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +299,7 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !"admin".equals(System.getenv("ADMIN_USER") )) {
|
if ( !"admin".equals(postgresAdminUser) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,12 +486,28 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
.withQuoteChar('"')
|
.withQuoteChar('"')
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (CSVReader csvReader = new CSVReaderBuilder(reader)
|
final var filteredReader = skippingEmptyAndCommentLines(reader);
|
||||||
|
try (CSVReader csvReader = new CSVReaderBuilder(filteredReader)
|
||||||
.withCSVParser(parser)
|
.withCSVParser(parser)
|
||||||
.build()) {
|
.build()) {
|
||||||
return csvReader.readAll();
|
return csvReader.readAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static Reader skippingEmptyAndCommentLines(Reader reader) throws IOException {
|
||||||
|
try (var bufferedReader = new BufferedReader(reader);
|
||||||
|
StringWriter writer = new StringWriter()) {
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
|
if (!line.isBlank() && !line.startsWith("#")) {
|
||||||
|
writer.write(line);
|
||||||
|
writer.write("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StringReader(writer.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void importBusinessPartners(final String[] header, final List<String[]> records) {
|
private void importBusinessPartners(final String[] header, final List<String[]> records) {
|
||||||
|
|
||||||
@ -657,9 +673,12 @@ 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.getString("roles"))) {
|
|
||||||
final var contactId = rec.getInteger("contact_id");
|
final var contactId = rec.getInteger("contact_id");
|
||||||
|
|
||||||
|
if (rec.getString("roles").isBlank()) {
|
||||||
|
fail("empty roles assignment not allowed for contact_id: " + contactId);
|
||||||
|
}
|
||||||
|
|
||||||
final var partner = partners.get(rec.getInteger("bp_id"));
|
final var partner = partners.get(rec.getInteger("bp_id"));
|
||||||
final var debitor = debitors.get(rec.getInteger("bp_id"));
|
final var debitor = debitors.get(rec.getInteger("bp_id"));
|
||||||
|
|
||||||
@ -672,23 +691,45 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
final var contact = HsOfficeContactEntity.builder().build();
|
final var contact = HsOfficeContactEntity.builder().build();
|
||||||
contacts.put(contactId, initContact(contact, rec));
|
contacts.put(contactId, initContact(contact, rec));
|
||||||
|
|
||||||
if (rec.getString("roles").contains("contractual")) {
|
var imported = false;
|
||||||
|
if (rec.getString("roles").contains("partner")) {
|
||||||
|
assertThat(partner.getContact()).isNull();
|
||||||
partner.setContact(contact);
|
partner.setContact(contact);
|
||||||
|
imported = true;
|
||||||
}
|
}
|
||||||
if (rec.getString("roles").contains("billing")) {
|
if (rec.getString("roles").contains("billing")) {
|
||||||
|
assertThat(debitor.getBillingContact()).isNull();
|
||||||
debitor.setBillingContact(contact);
|
debitor.setBillingContact(contact);
|
||||||
|
imported = true;
|
||||||
}
|
}
|
||||||
if (rec.getString("roles").contains("operation")) {
|
if (rec.getString("roles").contains("operation")) {
|
||||||
final var rel = HsOfficeRelationshipEntity.builder()
|
final var rel = HsOfficeRelationshipEntity.builder()
|
||||||
.relAnchor(partner.getPerson())
|
.relAnchor(partner.getPerson())
|
||||||
.relHolder(person)
|
.relHolder(person)
|
||||||
.contact(contact)
|
.contact(contact)
|
||||||
.relType(HsOfficeRelationshipType.TECHNICAL_CONTACT)
|
.relType(HsOfficeRelationshipType.OPERATIONS)
|
||||||
.build();
|
.build();
|
||||||
relationships.put(contactId, rel);
|
relationships.put(contactId, rel);
|
||||||
|
imported = true;
|
||||||
}
|
}
|
||||||
} else {
|
if (rec.getString("roles").contains("contractual")) {
|
||||||
fail("contact without role: " + rec);
|
final var rel = HsOfficeRelationshipEntity.builder()
|
||||||
|
.relAnchor(partner.getPerson())
|
||||||
|
.relHolder(person)
|
||||||
|
.contact(contact)
|
||||||
|
.relType(HsOfficeRelationshipType.REPRESENTATIVE)
|
||||||
|
.build();
|
||||||
|
relationships.put(contactId, rel);
|
||||||
|
imported = true;
|
||||||
|
}
|
||||||
|
if (!imported) {
|
||||||
|
final var rel = HsOfficeRelationshipEntity.builder()
|
||||||
|
.relAnchor(partner.getPerson())
|
||||||
|
.relHolder(person)
|
||||||
|
.contact(contact)
|
||||||
|
.relType(HsOfficeRelationshipType.UNKNOWN)
|
||||||
|
.build();
|
||||||
|
relationships.put(contactId, rel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -788,7 +829,7 @@ public class ImportOfficeTables extends ContextBasedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Reader resourceReader(@NotNull final String resourcePath) {
|
private Reader resourceReader(@NotNull final String resourcePath) {
|
||||||
return new InputStreamReader(getClass().getClassLoader().getResourceAsStream(resourcePath));
|
return new InputStreamReader(requireNonNull(getClass().getClassLoader().getResourceAsStream(resourcePath)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Reader fileReader(@NotNull final Path filePath) throws IOException {
|
private Reader fileReader(@NotNull final Path filePath) throws IOException {
|
||||||
|
@ -153,7 +153,7 @@ class HsOfficeRelationshipControllerAcceptanceTest {
|
|||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
HsOfficeRelationshipTypeResource.ACCOUNTING_CONTACT,
|
HsOfficeRelationshipTypeResource.ACCOUNTING,
|
||||||
givenAnchorPerson.getUuid(),
|
givenAnchorPerson.getUuid(),
|
||||||
givenHolderPerson.getUuid(),
|
givenHolderPerson.getUuid(),
|
||||||
givenContact.getUuid()))
|
givenContact.getUuid()))
|
||||||
@ -164,7 +164,7 @@ class HsOfficeRelationshipControllerAcceptanceTest {
|
|||||||
.statusCode(201)
|
.statusCode(201)
|
||||||
.contentType(ContentType.JSON)
|
.contentType(ContentType.JSON)
|
||||||
.body("uuid", isUuidValid())
|
.body("uuid", isUuidValid())
|
||||||
.body("relType", is("ACCOUNTING_CONTACT"))
|
.body("relType", is("ACCOUNTING"))
|
||||||
.body("relAnchor.tradeName", is("Third OHG"))
|
.body("relAnchor.tradeName", is("Third OHG"))
|
||||||
.body("relHolder.givenName", is("Paul"))
|
.body("relHolder.givenName", is("Paul"))
|
||||||
.body("contact.label", is("forth contact"))
|
.body("contact.label", is("forth contact"))
|
||||||
@ -197,7 +197,7 @@ class HsOfficeRelationshipControllerAcceptanceTest {
|
|||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
HsOfficeRelationshipTypeResource.ACCOUNTING_CONTACT,
|
HsOfficeRelationshipTypeResource.ACCOUNTING,
|
||||||
givenAnchorPersonUuid,
|
givenAnchorPersonUuid,
|
||||||
givenHolderPerson.getUuid(),
|
givenHolderPerson.getUuid(),
|
||||||
givenContact.getUuid()))
|
givenContact.getUuid()))
|
||||||
@ -230,7 +230,7 @@ class HsOfficeRelationshipControllerAcceptanceTest {
|
|||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
HsOfficeRelationshipTypeResource.ACCOUNTING_CONTACT,
|
HsOfficeRelationshipTypeResource.ACCOUNTING,
|
||||||
givenAnchorPerson.getUuid(),
|
givenAnchorPerson.getUuid(),
|
||||||
givenHolderPersonUuid,
|
givenHolderPersonUuid,
|
||||||
givenContact.getUuid()))
|
givenContact.getUuid()))
|
||||||
@ -263,7 +263,7 @@ class HsOfficeRelationshipControllerAcceptanceTest {
|
|||||||
"contactUuid": "%s"
|
"contactUuid": "%s"
|
||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
HsOfficeRelationshipTypeResource.ACCOUNTING_CONTACT,
|
HsOfficeRelationshipTypeResource.ACCOUNTING,
|
||||||
givenAnchorPerson.getUuid(),
|
givenAnchorPerson.getUuid(),
|
||||||
givenHolderPerson.getUuid(),
|
givenHolderPerson.getUuid(),
|
||||||
givenContactUuid))
|
givenContactUuid))
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
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
|
||||||
71; 7; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; contractual,billing,operation
|
|
||||||
101; 10; 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
|
# eine natürliche Person
|
||||||
102; 10; 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
|
1101; 7; Herr; Michael; Mellies; ; ; ; Kleine Freiheit 50; 26524; Hage; DE; ; +49 4931 123456; +49 1522 123456;; mih@example.org; partner,billing,operation
|
||||||
103; 10; Herr; Philip; Meyer-Contract; ; JM e.K.;; Waldweg 5; 11001; Berlin; DE; +49 30 6666666; +49 30 5555555; ; +49 30 6666666; pm-contractual@example.org; contractual
|
|
||||||
121; 12; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; billing,contractual,operation
|
# eine juristische Person mit drei separaten Ansprechpartnern
|
||||||
|
1201; 10; 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
|
||||||
|
1202; 10; 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
|
||||||
|
1203; 10; 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
|
||||||
|
|
||||||
|
# eine juristische Person mit nur einem Ansprechpartner
|
||||||
|
1301; 12; ; Petra; Schmidt; ; Test PS;; ; ; ; ; ; ; ; ; ps@example.com; partner,billing,contractual,operation
|
||||||
|
|
Loading…
Reference in New Issue
Block a user