introduce-partner-business-role #16

Merged
hsh-michaelhoennig merged 33 commits from introduce-partner-business-role into master 2024-02-01 14:48:16 +01:00
4 changed files with 121 additions and 74 deletions
Showing only changes of commit 4f5732df61 - Show all commits

View File

@ -1,10 +1,15 @@
package net.hostsharing.hsadminng.hs.office.partner; package net.hostsharing.hsadminng.hs.office.partner;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartnersApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartnersApi;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerInsertResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerInsertResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerResource; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerRoleInsertResource;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
import net.hostsharing.hsadminng.mapper.Mapper; import net.hostsharing.hsadminng.mapper.Mapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -56,7 +61,7 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
context.define(currentUser, assumedRoles); context.define(currentUser, assumedRoles);
final var entityToSave = mapper.map(body, HsOfficePartnerEntity.class); final var entityToSave = createPartnerEntity(body);
final var saved = partnerRepo.save(entityToSave); final var saved = partnerRepo.save(entityToSave);
@ -119,4 +124,24 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
final var mapped = mapper.map(saved, HsOfficePartnerResource.class); final var mapped = mapper.map(saved, HsOfficePartnerResource.class);
return ResponseEntity.ok(mapped); return ResponseEntity.ok(mapped);
} }
private HsOfficePartnerEntity createPartnerEntity(final HsOfficePartnerInsertResource body) {
final var entityToSave = new HsOfficePartnerEntity();
entityToSave.setPartnerNumber(body.getPartnerNumber());
entityToSave.setPartnerRole(persistPartnerRole(body.getPartnerRole()));
entityToSave.setContact(em.find(HsOfficeContactEntity.class, body.getContactUuid()));
entityToSave.setPerson(em.find(HsOfficePersonEntity.class, body.getPersonUuid()));
entityToSave.setDetails(mapper.map(body.getDetails(), HsOfficePartnerDetailsEntity.class));
return entityToSave;
}
private HsOfficeRelationshipEntity persistPartnerRole(final HsOfficePartnerRoleInsertResource resource) {
final var entity = new HsOfficeRelationshipEntity();
entity.setRelType(HsOfficeRelationshipType.PARTNER);
entity.setRelAnchor(em.find(HsOfficePersonEntity.class, resource.getRelAnchorUuid()));
entity.setRelHolder(em.find(HsOfficePersonEntity.class, resource.getRelHolderUuid()));
entity.setContact(em.find(HsOfficeContactEntity.class, resource.getContactUuid()));
em.persist(entity);
return entity;
}
} }

View File

@ -96,6 +96,8 @@ components:
format: int8 format: int8
minimum: 10000 minimum: 10000
maximum: 99999 maximum: 99999
partnerRole:
$ref: '#/components/schemas/HsOfficePartnerRoleInsert'
personUuid: personUuid:
type: string type: string
format: uuid format: uuid
@ -110,6 +112,24 @@ components:
- contactUuid - contactUuid
- details - details
HsOfficePartnerRoleInsert:
type: object
nullable: false
properties:
relAnchorUuid:
type: string
format: uuid
relHolderUuid:
type: string
format: uuid
contactUuid:
type: string
format: uuid
required:
- relAnchorUuid
- relHolderUuid
- relContactUuid
HsOfficePartnerDetailsInsert: HsOfficePartnerDetailsInsert:
type: object type: object
nullable: false nullable: false

View File

@ -62,3 +62,4 @@ components:
- relAnchorUuid - relAnchorUuid
- relHolderUuid - relHolderUuid
- relType - relType
- relContactUuid

View File

@ -6,9 +6,10 @@ import net.hostsharing.hsadminng.HsadminNgApplication;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
import net.hostsharing.test.Accepts; import net.hostsharing.test.Accepts;
import net.hostsharing.test.JpaAttempt; import net.hostsharing.test.JpaAttempt;
import org.json.JSONException;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -24,8 +25,7 @@ import java.util.UUID;
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid; import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
import static net.hostsharing.test.JsonMatcher.lenientlyEquals; import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.startsWith;
@SpringBootTest( @SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
@ -33,6 +33,8 @@ import static org.hamcrest.Matchers.startsWith;
) )
class HsOfficePartnerControllerAcceptanceTest { class HsOfficePartnerControllerAcceptanceTest {
private static final UUID GIVEN_NON_EXISTING_PERSON_UUID = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6");
@LocalServerPort @LocalServerPort
private Integer port; private Integer port;
@ -63,7 +65,7 @@ class HsOfficePartnerControllerAcceptanceTest {
class ListPartners { class ListPartners {
@Test @Test
void globalAdmin_withoutAssumedRoles_canViewAllPartners_ifNoCriteriaGiven() throws JSONException { void globalAdmin_withoutAssumedRoles_canViewAllPartners_ifNoCriteriaGiven() {
RestAssured // @formatter:off RestAssured // @formatter:off
.given() .given()
@ -74,40 +76,7 @@ class HsOfficePartnerControllerAcceptanceTest {
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(200) .statusCode(200)
.contentType("application/json") .contentType("application/json")
.body("", lenientlyEquals(""" .body("", hasSize(5));
[
{
"person": { "familyName": "Smith" },
"partnerRole": { },
"contact": { "label": "fifth contact" },
"details": { "birthday": "1987-10-31" }
},
{
"person": { "tradeName": "First GmbH" },
"partnerRole": { },
"contact": { "label": "first contact" },
"details": { "registrationOffice": "Hamburg" }
},
{
"person": { "tradeName": "Third OHG" },
"partnerRole": { },
"contact": { "label": "third contact" },
"details": { "registrationOffice": "Hamburg" }
},
{
"person": { "tradeName": "Second e.K." },
"partnerRole": { },
"contact": { "label": "second contact" },
"details": { "registrationOffice": "Hamburg" }
},
{
"person": { "personType": "INCORPORATED_FIRM" },
"partnerRole": { },
"contact": { "label": "fourth contact" },
"details": { "registrationOffice": "Hamburg" }
}
]
"""));
// @formatter:on // @formatter:on
} }
} }
@ -121,6 +90,7 @@ class HsOfficePartnerControllerAcceptanceTest {
void globalAdmin_withoutAssumedRole_canAddPartner() { void globalAdmin_withoutAssumedRole_canAddPartner() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
final var givenPerson = personRepo.findPersonByOptionalNameLike("Third").get(0); final var givenPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
@ -131,14 +101,24 @@ class HsOfficePartnerControllerAcceptanceTest {
.body(""" .body("""
{ {
"partnerNumber": "12345", "partnerNumber": "12345",
"contactUuid": "%s", "partnerRole": {
"relAnchorUuid": "%s",
"relHolderUuid": "%s",
"contactUuid": "%s"
},
"personUuid": "%s", "personUuid": "%s",
"contactUuid": "%s",
"details": { "details": {
"registrationOffice": "Temp Registergericht Aurich", "registrationOffice": "Temp Registergericht Aurich",
"registrationNumber": "111111" "registrationNumber": "111111"
} }
} }
""".formatted(givenContact.getUuid(), givenPerson.getUuid())) """.formatted(
givenMandantPerson.getUuid(),
givenPerson.getUuid(),
givenContact.getUuid(),
givenPerson.getUuid(),
givenContact.getUuid()))
.port(port) .port(port)
.when() .when()
.post("http://localhost/api/hs/office/partners") .post("http://localhost/api/hs/office/partners")
@ -163,6 +143,7 @@ class HsOfficePartnerControllerAcceptanceTest {
void globalAdmin_canNotAddPartner_ifContactDoesNotExist() { void globalAdmin_canNotAddPartner_ifContactDoesNotExist() {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
final var givenPerson = personRepo.findPersonByOptionalNameLike("Third").get(0); final var givenPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
final var givenContactUuid = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6"); final var givenContactUuid = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6");
@ -173,11 +154,21 @@ class HsOfficePartnerControllerAcceptanceTest {
.body(""" .body("""
{ {
"partnerNumber": "12345", "partnerNumber": "12345",
"contactUuid": "%s", "partnerRole": {
"relAnchorUuid": "%s",
"relHolderUuid": "%s",
"contactUuid": "%s"
},
"personUuid": "%s", "personUuid": "%s",
"contactUuid": "%s",
"details": {} "details": {}
} }
""".formatted(givenContactUuid, givenPerson.getUuid())) """.formatted(
givenMandantPerson,
givenPerson.getUuid(),
givenContactUuid,
givenPerson.getUuid(),
givenContactUuid))
.port(port) .port(port)
.when() .when()
.post("http://localhost/api/hs/office/partners") .post("http://localhost/api/hs/office/partners")
@ -192,7 +183,6 @@ class HsOfficePartnerControllerAcceptanceTest {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var mandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0); final var mandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
final var givenPersonUuid = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6");
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
final var location = RestAssured // @formatter:off final var location = RestAssured // @formatter:off
@ -204,9 +194,8 @@ class HsOfficePartnerControllerAcceptanceTest {
"partnerNumber": "12345", "partnerNumber": "12345",
"partnerRole": { "partnerRole": {
"relAnchorUuid": "%s", "relAnchorUuid": "%s",
"relType": "PARTNER", "relHolderUuid": "%s",
"relHolder": "%s", "contact": "%s"
"contact": "%s",
}, },
"personUuid": "%s", "personUuid": "%s",
"contactUuid": "%s", "contactUuid": "%s",
@ -214,16 +203,16 @@ class HsOfficePartnerControllerAcceptanceTest {
} }
""".formatted( """.formatted(
mandantPerson.getUuid(), mandantPerson.getUuid(),
givenPersonUuid, GIVEN_NON_EXISTING_PERSON_UUID,
givenContact.getUuid(), givenContact.getUuid(),
givenPersonUuid, GIVEN_NON_EXISTING_PERSON_UUID,
givenContact.getUuid())) givenContact.getUuid()))
.port(port) .port(port)
.when() .when()
.post("http://localhost/api/hs/office/partners") .post("http://localhost/api/hs/office/partners")
.then().log().all().assertThat() .then().log().all().assertThat()
.statusCode(400) .statusCode(400)
.body("message", is("Unable to find Person with uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6")); .body("message", is("Unable to find Person with uuid " + GIVEN_NON_EXISTING_PERSON_UUID));
// @formatter:on // @formatter:on
} }
} }
@ -306,7 +295,7 @@ class HsOfficePartnerControllerAcceptanceTest {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenPartner = givenSomeTemporaryPartnerBessler(); final var givenPartner = givenSomeTemporaryPartnerBessler();
final var givenPerson = personRepo.findPersonByOptionalNameLike("Third").get(0); final var givenPerson = personRepo.findPersonByOptionalNameLike("Third").get(0);
final var givenContact = contactRepo.findContactByOptionalLabelLike("forth").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
final var location = RestAssured // @formatter:off final var location = RestAssured // @formatter:off
.given() .given()
@ -314,7 +303,7 @@ class HsOfficePartnerControllerAcceptanceTest {
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body(""" .body("""
{ {
"debitorNumerPrefix": "12345", "partnerNumber": "12345",
"contactUuid": "%s", "contactUuid": "%s",
"personUuid": "%s", "personUuid": "%s",
"details": { "details": {
@ -333,6 +322,7 @@ class HsOfficePartnerControllerAcceptanceTest {
.statusCode(200) .statusCode(200)
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body("uuid", isUuidValid()) .body("uuid", isUuidValid())
.body("partnerNumber", is(givenPartner.getPartnerNumber()))
.body("details.registrationNumber", is("222222")) .body("details.registrationNumber", is("222222"))
.body("contact.label", is(givenContact.getLabel())) .body("contact.label", is(givenContact.getLabel()))
.body("person.tradeName", is(givenPerson.getTradeName())); .body("person.tradeName", is(givenPerson.getTradeName()));
@ -467,9 +457,20 @@ class HsOfficePartnerControllerAcceptanceTest {
private HsOfficePartnerEntity givenSomeTemporaryPartnerBessler() { private HsOfficePartnerEntity givenSomeTemporaryPartnerBessler() {
return jpaAttempt.transacted(() -> { return jpaAttempt.transacted(() -> {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0);
final var givenPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0); final var givenPerson = personRepo.findPersonByOptionalNameLike("Erben Bessler").get(0);
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").get(0);
final var partnerRole = new HsOfficeRelationshipEntity();
partnerRole.setRelType(HsOfficeRelationshipType.PARTNER);
partnerRole.setRelAnchor(givenMandantPerson);
partnerRole.setRelHolder(givenPerson);
partnerRole.setContact(givenContact);
em.persist(partnerRole);
final var newPartner = HsOfficePartnerEntity.builder() final var newPartner = HsOfficePartnerEntity.builder()
.partnerRole(partnerRole)
.person(givenPerson) .person(givenPerson)
.contact(givenContact) .contact(givenContact)
.details(HsOfficePartnerDetailsEntity.builder() .details(HsOfficePartnerDetailsEntity.builder()