1
0

feature/split-up-postalAddress (#118)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/118
Reviewed-by: Marc Sandlus <marc.sandlus@hostsharing.net>
This commit is contained in:
Michael Hoennig
2024-11-06 12:24:37 +01:00
parent 63af33d003
commit 6191bf16e0
19 changed files with 207 additions and 89 deletions

View File

@@ -110,7 +110,6 @@ public class HsHostingAssetControllerRestTest {
"caption": "some fake cloud-server",
"alarmContact": {
"caption": "some contact",
"postalAddress": "address of some contact",
"emailAddresses": {
"main": "some-contact@example.com"
}
@@ -141,7 +140,6 @@ public class HsHostingAssetControllerRestTest {
"caption": "some fake managed-server",
"alarmContact": {
"caption": "some contact",
"postalAddress": "address of some contact",
"emailAddresses": {
"main": "some-contact@example.com"
}

View File

@@ -1111,7 +1111,7 @@ public abstract class BaseOfficeDataImport extends CsvDataImport {
contactRecord.getString("last_name"),
contactRecord.getString("firma")));
contact.putEmailAddresses(Map.of("main", contactRecord.getString("email")));
contact.setPostalAddress(toAddress(contactRecord));
contact.putPostalAddress(toAddress(contactRecord));
contact.putPhoneNumbers(toPhoneNumbers(contactRecord));
contacts.put(contactRecord.getInteger("contact_id"), contact);
@@ -1131,36 +1131,23 @@ public abstract class BaseOfficeDataImport extends CsvDataImport {
return phoneNumbers;
}
private String toAddress(final Record rec) {
final var result = new StringBuilder();
private Map<String, String> toAddress(final Record rec) {
final var result = new LinkedHashMap<String, String>();
final var name = toName(
rec.getString("salut"),
rec.getString("title"),
rec.getString("first_name"),
rec.getString("last_name"));
if (isNotBlank(name))
result.append(name + "\n");
result.put("name", name);
if (isNotBlank(rec.getString("firma")))
result.append(rec.getString("firma") + "\n");
if (isNotBlank(rec.getString("co")))
result.append("c/o " + rec.getString("co") + "\n");
if (isNotBlank(rec.getString("street")))
result.append(rec.getString("street") + "\n");
final var zipcodeAndCity = toZipcodeAndCity(rec);
if (isNotBlank(zipcodeAndCity))
result.append(zipcodeAndCity + "\n");
return result.toString();
}
result.put("firm", name);
private String toZipcodeAndCity(final Record rec) {
final var result = new StringBuilder();
if (isNotBlank(rec.getString("country")))
result.append(rec.getString("country") + " ");
if (isNotBlank(rec.getString("zipcode")))
result.append(rec.getString("zipcode") + " ");
if (isNotBlank(rec.getString("city")))
result.append(rec.getString("city"));
return result.toString();
List.of("co", "street", "zipcode", "city", "country").forEach(key -> {
if (isNotBlank(rec.getString(key)))
result.put(key, rec.getString(key));
});
return result;
}
private String toCaption(

View File

@@ -21,10 +21,13 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import static java.util.Map.entry;
import static net.hostsharing.hsadminng.rbac.test.IsValidUuidMatcher.isUuidValid;
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
@@ -214,7 +217,11 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu
"emailAddresses": {
"main": "patched@example.org"
},
"postalAddress": "Patched Address",
"postalAddress": {
"extra": "Extra Property",
"co": "P. Patcher",
"street": "Patchstraße 5"
},
"phoneNumbers": {
"phone_office": "+01 100 123456"
}
@@ -229,7 +236,10 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu
.body("uuid", isUuidValid())
.body("caption", is("Temp patched contact"))
.body("emailAddresses", is(Map.of("main", "patched@example.org")))
.body("postalAddress", is("Patched Address"))
.body("postalAddress", hasEntry("name", givenContact.getPostalAddress().get("name"))) // unchanged
.body("postalAddress", hasEntry("extra", "Extra Property")) // unchanged
.body("postalAddress", hasEntry("co", "P. Patcher")) // patched
.body("postalAddress", hasEntry("street", "Patchstraße 5")) // patched
.body("phoneNumbers", is(Map.of("phone_office", "+01 100 123456")));
// @formatter:on
@@ -239,7 +249,11 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu
.matches(person -> {
assertThat(person.getCaption()).isEqualTo("Temp patched contact");
assertThat(person.getEmailAddresses()).containsExactlyEntriesOf(Map.of("main", "patched@example.org"));
assertThat(person.getPostalAddress()).isEqualTo("Patched Address");
assertThat(person.getPostalAddress()).containsAllEntriesOf(Map.ofEntries(
entry("name", givenContact.getPostalAddress().get("name")),
entry("co", "P. Patcher"),
entry("street", "Patchstraße 5")
));
assertThat(person.getPhoneNumbers()).containsExactlyEntriesOf(Map.of("phone_office", "+01 100 123456"));
return true;
});
@@ -264,7 +278,7 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu
"phone_office": "+01 100 123456"
}
}
""")
""")
.port(port)
.when()
.patch("http://localhost/api/hs/office/contacts/" + givenContact.getUuid())
@@ -274,7 +288,6 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu
.body("uuid", isUuidValid())
.body("caption", is(givenContact.getCaption()))
.body("emailAddresses", is(Map.of("main", "patched@example.org")))
.body("postalAddress", is(givenContact.getPostalAddress()))
.body("phoneNumbers", is(Map.of("phone_office", "+01 100 123456")));
// @formatter:on
@@ -283,12 +296,11 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu
.matches(person -> {
assertThat(person.getCaption()).isEqualTo(givenContact.getCaption());
assertThat(person.getEmailAddresses()).containsExactlyEntriesOf(Map.of("main", "patched@example.org"));
assertThat(person.getPostalAddress()).isEqualTo(givenContact.getPostalAddress());
assertThat(person.getPostalAddress()).containsExactlyInAnyOrderEntriesOf(givenContact.getPostalAddress());
assertThat(person.getPhoneNumbers()).containsExactlyEntriesOf(Map.of("phone_office", "+01 100 123456"));
return true;
});
}
}
@Nested
@@ -361,8 +373,13 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu
final var newContact = HsOfficeContactRbacEntity.builder()
.uuid(UUID.randomUUID())
.caption("Temp from " + Context.getCallerMethodNameFromStackFrame(1) )
.postalAddress(Map.ofEntries(
entry("name", RandomStringUtils.randomAlphabetic(6) + " " + RandomStringUtils.randomAlphabetic(10)),
entry("street", RandomStringUtils.randomAlphabetic(10) + randomInt(1, 99)),
entry("zipcode", "D-" + randomInt(10000, 99999)),
entry("city", RandomStringUtils.randomAlphabetic(10))
))
.emailAddresses(Map.of("main", RandomStringUtils.randomAlphabetic(10) + "@example.org"))
.postalAddress("Postal Address " + RandomStringUtils.randomAlphabetic(10))
.phoneNumbers(Map.of("phone_office", "+01 200 " + RandomStringUtils.randomNumeric(8)))
.build();
@@ -378,4 +395,8 @@ class HsOfficeContactControllerAcceptanceTest extends ContextBasedTestWithCleanu
em.createQuery("DELETE FROM HsOfficeContactRbacEntity c WHERE c.caption LIKE 'Temp %'").executeUpdate();
}).assertSuccessful();
}
private int randomInt(final int min, final int max) {
return ThreadLocalRandom.current().nextInt(min, max);
}
}

View File

@@ -19,6 +19,19 @@ class HsOfficeContactPatcherUnitTest extends PatchUnitTestBase<
> {
private static final UUID INITIAL_CONTACT_UUID = UUID.randomUUID();
private static final Map<String, String> PATCH_POSTAL_ADDRESS = patchMap(
entry("name", "Patty Patch"),
entry("street", "Patchstreet 10"),
entry("zipcode", null),
entry("city", "Hamburg")
);
private static final Map<String, String> PATCHED_POSTAL_ADDRESS = patchMap(
entry("name", "Patty Patch"),
entry("street", "Patchstreet 10"),
entry("city", "Hamburg")
);
private static final Map<String, String> PATCH_EMAIL_ADDRESSES = patchMap(
entry("main", "patched@example.com"),
entry("paul", null),
@@ -46,6 +59,11 @@ class HsOfficeContactPatcherUnitTest extends PatchUnitTestBase<
final var entity = new HsOfficeContactRbacEntity();
entity.setUuid(INITIAL_CONTACT_UUID);
entity.setCaption("initial caption");
entity.putPostalAddress(Map.ofEntries(
entry("name", "Ina Initial"),
entry("street", "Initialstraße 50"),
entry("zipcode", "20000"),
entry("city", "Hamburg")));
entity.putEmailAddresses(Map.ofEntries(
entry("main", "initial@example.org"),
entry("paul", "paul@example.com"),
@@ -54,7 +72,6 @@ class HsOfficeContactPatcherUnitTest extends PatchUnitTestBase<
entry("phone_office", "+49 40 12345-00"),
entry("phone_mobile", "+49 1555 1234567"),
entry("fax", "+49 40 12345-90")));
entity.setPostalAddress("Initialstraße 50\n20000 Hamburg");
return entity;
}
@@ -77,24 +94,26 @@ class HsOfficeContactPatcherUnitTest extends PatchUnitTestBase<
"patched caption",
HsOfficeContactRbacEntity::setCaption),
new SimpleProperty<>(
"resources",
"postalAddress",
HsOfficeContactPatchResource::setPostalAddress,
PATCH_POSTAL_ADDRESS,
HsOfficeContactRbacEntity::putPostalAddress,
PATCHED_POSTAL_ADDRESS)
.notNullable(),
new SimpleProperty<>(
"emailAddresses",
HsOfficeContactPatchResource::setEmailAddresses,
PATCH_EMAIL_ADDRESSES,
HsOfficeContactRbacEntity::putEmailAddresses,
PATCHED_EMAIL_ADDRESSES)
.notNullable(),
new SimpleProperty<>(
"resources",
"phoneNumbers",
HsOfficeContactPatchResource::setPhoneNumbers,
PATCH_PHONE_NUMBERS,
HsOfficeContactRbacEntity::putPhoneNumbers,
PATCHED_PHONE_NUMBERS)
.notNullable(),
new JsonNullableProperty<>(
"patched given name",
HsOfficeContactPatchResource::setPostalAddress,
"patched given name",
HsOfficeContactRbacEntity::setPostalAddress)
.notNullable()
);
}
}

View File

@@ -2,6 +2,8 @@ package net.hostsharing.hsadminng.hs.office.contact;
import java.util.Map;
import static java.util.Map.entry;
public class HsOfficeContactRbacTestEntity {
public static final HsOfficeContactRbacEntity TEST_RBAC_CONTACT = hsOfficeContact("some contact", "some-contact@example.com");
@@ -9,7 +11,12 @@ public class HsOfficeContactRbacTestEntity {
static public HsOfficeContactRbacEntity hsOfficeContact(final String caption, final String emailAddr) {
return HsOfficeContactRbacEntity.builder()
.caption(caption)
.postalAddress("address of " + caption)
.postalAddress(Map.ofEntries(
entry("name", "M. Meyer"),
entry("street", "Teststraße 11"),
entry("zipcode", "D-12345"),
entry("city", "Berlin")
))
.emailAddresses(Map.of("main", emailAddr))
.build();
}

View File

@@ -2,6 +2,8 @@ package net.hostsharing.hsadminng.hs.office.contact;
import java.util.Map;
import static java.util.Map.entry;
public class HsOfficeContactRealTestEntity {
public static final HsOfficeContactRealEntity TEST_REAL_CONTACT = hsOfficeContact("some contact", "some-contact@example.com");
@@ -9,7 +11,12 @@ public class HsOfficeContactRealTestEntity {
static public HsOfficeContactRealEntity hsOfficeContact(final String caption, final String emailAddr) {
return HsOfficeContactRealEntity.builder()
.caption(caption)
.postalAddress("address of " + caption)
.postalAddress(Map.ofEntries(
entry("name", "M. Meyer"),
entry("street", "Teststraße 11"),
entry("zipcode", "D-12345"),
entry("city", "Berlin")
))
.emailAddresses(Map.of("main", emailAddr))
.build();
}

View File

@@ -460,9 +460,12 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
"type": "DEBITOR",
"contact": {
"caption": "first contact",
"postalAddress": "Vorname Nachname\\nStraße Hnr\\nPLZ Stadt",
"emailAddresses": { "main": "contact-admin@firstcontact.example.com" },
"phoneNumbers": { "phone_office": "+49 123 1234567" }
"postalAddress": {
"country": "Germany"
},
"emailAddresses": { "main": "contact-admin@firstcontact.example.com" },
"phoneNumbers": { "phone_office": "+49 123 1234567" }
}
}
},
"debitorNumber": 1000111,
@@ -476,10 +479,11 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
"mark": null,
"contact": {
"caption": "first contact",
"postalAddress": "Vorname Nachname\\nStraße Hnr\\nPLZ Stadt",
"emailAddresses": { "main": "contact-admin@firstcontact.example.com" },
"phoneNumbers": { "phone_office": "+49 123 1234567" }
}
"postalAddress": {
"country": "Germany"
},
"emailAddresses": { "main": "contact-admin@firstcontact.example.com" },
"phoneNumbers": { "phone_office": "+49 123 1234567" }
},
"details": {
"registrationOffice": "Hamburg",

View File

@@ -199,7 +199,9 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
"type": "REPRESENTATIVE",
"contact": {
"caption": "first contact",
"postalAddress": "Vorname Nachname\\nStraße Hnr\\nPLZ Stadt",
"postalAddress": {
"country": "Germany"
},
"emailAddresses": {
"main": "contact-admin@firstcontact.example.com"
},

View File

@@ -55,8 +55,11 @@ class HsOfficeScenarioTests extends ScenarioTest {
.given("tradeName", "Test AG")
.given("contactCaption", "Test AG - Hamburg")
.given("postalAddress", """
Shanghai-Allee 1
20123 Hamburg
"firm": "Test AG",
"street": "Shanghai-Allee 1",
"zipcode": "20123",
"city": "Hamburg",
"country": "Germany"
""")
.given("officePhoneNumber", "+49 40 654321-0")
.given("emailAddress", "hamburg@test-ag.example.org")
@@ -75,8 +78,11 @@ class HsOfficeScenarioTests extends ScenarioTest {
.given("familyName", "Matthieu")
.given("contactCaption", "Michelle Matthieu")
.given("postalAddress", """
An der Wandse 34
22123 Hamburg
"name": "Michelle Matthieu",
"street": "An der Wandse 34",
"zipcode": "22123",
"city": "Hamburg",
"country": "Germany"
""")
.given("officePhoneNumber", "+49 40 123456")
.given("emailAddress", "michelle.matthieu@example.org")
@@ -94,8 +100,11 @@ class HsOfficeScenarioTests extends ScenarioTest {
.given("representativeFamilyName", "Trust")
.given("representativeGivenName", "Tracy")
.given("representativePostalAddress", """
An der Alster 100
20000 Hamburg
"name": "Michelle Matthieu",
"street": "An der Alster 100",
"zipcode": "20000",
"city": "Hamburg",
"country": "Germany"
""")
.given("representativePhoneNumber", "+49 40 123456")
.given("representativeEMailAddress", "tracy.trust@example.org")
@@ -172,12 +181,18 @@ class HsOfficeScenarioTests extends ScenarioTest {
void shouldReplaceContactData() {
new ReplaceContactData(this)
.given("partnerName", "Test AG")
.given("newContactCaption", "Test AG - Norden")
.given("newContactCaption", "Test AG - China")
.given("newPostalAddress", """
Am Hafen 11
26506 Norden
""")
.given("newOfficePhoneNumber", "+49 4931 654321-0")
"firm": "Test AG",
"name": "Fi Zhong-Kha",
"building": "Thi Chi Koh Building",
"street": "No.2 Commercial Second Street",
"district": "Niushan Wei Wu",
"city": "Dongguan City",
"province": "Guangdong Province",
"country": "China"
""")
.given("newOfficePhoneNumber", "++15 999 654321" )
.given("newEmailAddress", "norden@test-ag.example.org")
.doRun();
}

View File

@@ -27,7 +27,9 @@ public class AmendContactData extends UseCase<AmendContactData> {
httpPatch("/api/hs/office/contacts/%{partnerContactUuid}", usingJsonBody("""
{
"caption": ${newContactCaption???},
"postalAddress": ${newPostalAddress???},
"postalAddress": {
%{newPostalAddress???}
},
"phoneNumbers": {
"office": ${newOfficePhoneNumber???}
},

View File

@@ -27,7 +27,9 @@ public class ReplaceContactData extends UseCase<ReplaceContactData> {
httpPost("/api/hs/office/contacts", usingJsonBody("""
{
"caption": ${newContactCaption},
"postalAddress": ${newPostalAddress???},
"postalAddress": {
%{newPostalAddress???}
},
"phoneNumbers": {
"phone": ${newOfficePhoneNumber???}
},
@@ -37,16 +39,18 @@ public class ReplaceContactData extends UseCase<ReplaceContactData> {
}
"""))
.expecting(CREATED).expecting(JSON),
"Please check first if that contact already exists, if so, use it's UUID below."
);
"Please check first if that contact already exists, if so, use it's UUID below.",
"If any `postalAddress` sub-properties besides those specified in the API " +
"(currently `firm`, `name`, `co`, `street`, `zipcode`, `city`, `country`) " +
"its values might not appear in external systems.");
withTitle("Replace the Contact-Reference in the Partner-Relation", () ->
httpPatch("/api/hs/office/relations/%{partnerRelationUuid}", usingJsonBody("""
{
"contactUuid": ${Contact: %{newContactCaption}}
}
"""))
.expecting(OK)
httpPatch("/api/hs/office/relations/%{partnerRelationUuid}", usingJsonBody("""
{
"contactUuid": ${Contact: %{newContactCaption}}
}
"""))
.expecting(OK)
);
return null;

View File

@@ -42,7 +42,9 @@ public class AddRepresentativeToPartner extends UseCase<AddRepresentativeToPartn
httpPost("/api/hs/office/contacts", usingJsonBody("""
{
"caption": "%{representativeGivenName} %{representativeFamilyName}",
"postalAddress": ${representativePostalAddress},
"postalAddress": {
%{representativePostalAddress}
},
"phoneNumbers": {
"main": ${representativePhoneNumber}
},

View File

@@ -44,7 +44,9 @@ public class CreatePartner extends UseCase<CreatePartner> {
httpPost("/api/hs/office/contacts", usingJsonBody("""
{
"caption": ${contactCaption},
"postalAddress": ${postalAddress???},
"postalAddress": {
%{postalAddress???}
},
"phoneNumbers": {
"office": ${officePhoneNumber???}
},