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 69 additions and 24 deletions
Showing only changes of commit 170aa5e462 - Show all commits

View File

@ -0,0 +1,21 @@
package net.hostsharing.hsadminng.errors;
import net.hostsharing.hsadminng.hs.office.migration.HasUuid;
import java.util.UUID;
public class ReferenceNotFoundException extends RuntimeException {
private final Class<?> entityClass;
private final UUID uuid;
public <E extends HasUuid> ReferenceNotFoundException(final Class<E> entityClass, final UUID uuid, final Throwable exc) {
super(exc);
this.entityClass = entityClass;
this.uuid = uuid;
}
@Override
public String getMessage() {
return "Cannot resolve " + entityClass.getSimpleName() +" with uuid " + uuid;
}
}

View File

@ -45,7 +45,7 @@ public class RestResponseEntityExceptionHandler
protected ResponseEntity<CustomErrorResponse> handleJpaExceptions( protected ResponseEntity<CustomErrorResponse> handleJpaExceptions(
final RuntimeException exc, final WebRequest request) { final RuntimeException exc, final WebRequest request) {
final var message = line(NestedExceptionUtils.getMostSpecificCause(exc).getMessage(), 0); final var message = line(NestedExceptionUtils.getMostSpecificCause(exc).getMessage(), 0);
return errorResponse(request, httpStatus(message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message); return errorResponse(request, httpStatus(exc, message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message);
} }
@ExceptionHandler(NoSuchElementException.class) @ExceptionHandler(NoSuchElementException.class)
@ -55,6 +55,12 @@ public class RestResponseEntityExceptionHandler
return errorResponse(request, HttpStatus.NOT_FOUND, message); return errorResponse(request, HttpStatus.NOT_FOUND, message);
} }
@ExceptionHandler(ReferenceNotFoundException.class)
protected ResponseEntity<CustomErrorResponse> handleReferenceNotFoundException(
final ReferenceNotFoundException exc, final WebRequest request) {
return errorResponse(request, HttpStatus.BAD_REQUEST, exc.getMessage());
}
@ExceptionHandler({ JpaObjectRetrievalFailureException.class, EntityNotFoundException.class }) @ExceptionHandler({ JpaObjectRetrievalFailureException.class, EntityNotFoundException.class })
protected ResponseEntity<CustomErrorResponse> handleJpaObjectRetrievalFailureException( protected ResponseEntity<CustomErrorResponse> handleJpaObjectRetrievalFailureException(
final RuntimeException exc, final WebRequest request) { final RuntimeException exc, final WebRequest request) {
@ -74,8 +80,9 @@ public class RestResponseEntityExceptionHandler
@ExceptionHandler(Throwable.class) @ExceptionHandler(Throwable.class)
protected ResponseEntity<CustomErrorResponse> handleOtherExceptions( protected ResponseEntity<CustomErrorResponse> handleOtherExceptions(
final Throwable exc, final WebRequest request) { final Throwable exc, final WebRequest request) {
final var message = firstMessageLine(NestedExceptionUtils.getMostSpecificCause(exc)); final var causingException = NestedExceptionUtils.getMostSpecificCause(exc);
return errorResponse(request, httpStatus(message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message); final var message = firstMessageLine(causingException);
return errorResponse(request, httpStatus(causingException, message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message);
} }
@Override @Override
@ -138,7 +145,10 @@ public class RestResponseEntityExceptionHandler
} }
} }
private Optional<HttpStatus> httpStatus(final String message) { private Optional<HttpStatus> httpStatus(final Throwable causingException, final String message) {
if ( EntityNotFoundException.class.isInstance(causingException) ) {
return Optional.of(HttpStatus.BAD_REQUEST);
}
if (message.startsWith("ERROR: [")) { if (message.startsWith("ERROR: [")) {
for (HttpStatus status : HttpStatus.values()) { for (HttpStatus status : HttpStatus.values()) {
if (message.startsWith("ERROR: [" + status.value() + "]")) { if (message.startsWith("ERROR: [" + status.value() + "]")) {

View File

@ -1,12 +1,14 @@
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.errors.ReferenceNotFoundException;
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; 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.generated.api.v1.model.HsOfficePartnerRoleInsertResource;
import net.hostsharing.hsadminng.hs.office.migration.HasUuid;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity; import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType; import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
@ -129,8 +131,8 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
final var entityToSave = new HsOfficePartnerEntity(); final var entityToSave = new HsOfficePartnerEntity();
entityToSave.setPartnerNumber(body.getPartnerNumber()); entityToSave.setPartnerNumber(body.getPartnerNumber());
entityToSave.setPartnerRole(persistPartnerRole(body.getPartnerRole())); entityToSave.setPartnerRole(persistPartnerRole(body.getPartnerRole()));
entityToSave.setContact(em.find(HsOfficeContactEntity.class, body.getContactUuid())); entityToSave.setContact(ref(HsOfficeContactEntity.class, body.getContactUuid()));
entityToSave.setPerson(em.find(HsOfficePersonEntity.class, body.getPersonUuid())); entityToSave.setPerson(ref(HsOfficePersonEntity.class, body.getPersonUuid()));
entityToSave.setDetails(mapper.map(body.getDetails(), HsOfficePartnerDetailsEntity.class)); entityToSave.setDetails(mapper.map(body.getDetails(), HsOfficePartnerDetailsEntity.class));
return entityToSave; return entityToSave;
} }
@ -138,10 +140,20 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
private HsOfficeRelationshipEntity persistPartnerRole(final HsOfficePartnerRoleInsertResource resource) { private HsOfficeRelationshipEntity persistPartnerRole(final HsOfficePartnerRoleInsertResource resource) {
final var entity = new HsOfficeRelationshipEntity(); final var entity = new HsOfficeRelationshipEntity();
entity.setRelType(HsOfficeRelationshipType.PARTNER); entity.setRelType(HsOfficeRelationshipType.PARTNER);
entity.setRelAnchor(em.find(HsOfficePersonEntity.class, resource.getRelAnchorUuid())); entity.setRelAnchor(ref(HsOfficePersonEntity.class, resource.getRelAnchorUuid()));
entity.setRelHolder(em.find(HsOfficePersonEntity.class, resource.getRelHolderUuid())); entity.setRelHolder(ref(HsOfficePersonEntity.class, resource.getRelHolderUuid()));
entity.setContact(em.find(HsOfficeContactEntity.class, resource.getContactUuid())); entity.setContact(ref(HsOfficeContactEntity.class, resource.getContactUuid()));
em.persist(entity); em.persist(entity);
return entity; return entity;
} }
private <E extends HasUuid> E ref(final Class<E> entityClass, final UUID uuid) {
try {
final var e = em.getReference(entityClass, uuid);
em.contains(e);
return e;
} catch (final Throwable exc) {
throw new ReferenceNotFoundException(entityClass, uuid, exc);
}
}
} }

View File

@ -4,7 +4,9 @@ import io.restassured.RestAssured;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import net.hostsharing.hsadminng.HsadminNgApplication; import net.hostsharing.hsadminng.HsadminNgApplication;
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.contact.HsOfficeContactRepository; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
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.HsOfficeRelationshipEntity;
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType; import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
@ -33,7 +35,8 @@ import static org.hamcrest.Matchers.*;
) )
class HsOfficePartnerControllerAcceptanceTest { class HsOfficePartnerControllerAcceptanceTest {
private static final UUID GIVEN_NON_EXISTING_PERSON_UUID = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6"); // private static final UUID GIVEN_NON_EXISTING_UUID = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6");
private static final UUID GIVEN_NON_EXISTING_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000");
@LocalServerPort @LocalServerPort
private Integer port; private Integer port;
@ -145,16 +148,15 @@ class HsOfficePartnerControllerAcceptanceTest {
context.define("superuser-alex@hostsharing.net"); context.define("superuser-alex@hostsharing.net");
final var givenMandantPerson = personRepo.findPersonByOptionalNameLike("Hostsharing eG").get(0); 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 location = RestAssured // @formatter:off final var location = RestAssured // @formatter:off
.given() .given()
.header("current-user", "superuser-alex@hostsharing.net") .header("current-user", "superuser-alex@hostsharing.net")
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.body(""" .body("""
{ {
"partnerNumber": "12345", "partnerNumber": "12345",
"partnerRole": { "partnerRole": {
"relAnchorUuid": "%s", "relAnchorUuid": "%s",
"relHolderUuid": "%s", "relHolderUuid": "%s",
"contactUuid": "%s" "contactUuid": "%s"
@ -164,17 +166,17 @@ class HsOfficePartnerControllerAcceptanceTest {
"details": {} "details": {}
} }
""".formatted( """.formatted(
givenMandantPerson, givenMandantPerson.getUuid(),
givenPerson.getUuid(), givenPerson.getUuid(),
givenContactUuid, GIVEN_NON_EXISTING_UUID,
givenPerson.getUuid(), givenPerson.getUuid(),
givenContactUuid)) GIVEN_NON_EXISTING_UUID))
.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 Contact with uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6")); .body("message", is("Unable to find " + HsOfficeContactEntity.class.getName() + " with id " + GIVEN_NON_EXISTING_UUID));
// @formatter:on // @formatter:on
} }
@ -195,7 +197,7 @@ class HsOfficePartnerControllerAcceptanceTest {
"partnerRole": { "partnerRole": {
"relAnchorUuid": "%s", "relAnchorUuid": "%s",
"relHolderUuid": "%s", "relHolderUuid": "%s",
"contact": "%s" "contactUuid": "%s"
}, },
"personUuid": "%s", "personUuid": "%s",
"contactUuid": "%s", "contactUuid": "%s",
@ -203,16 +205,16 @@ class HsOfficePartnerControllerAcceptanceTest {
} }
""".formatted( """.formatted(
mandantPerson.getUuid(), mandantPerson.getUuid(),
GIVEN_NON_EXISTING_PERSON_UUID, GIVEN_NON_EXISTING_UUID,
givenContact.getUuid(), givenContact.getUuid(),
GIVEN_NON_EXISTING_PERSON_UUID, GIVEN_NON_EXISTING_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 " + GIVEN_NON_EXISTING_PERSON_UUID)); .body("message", is("Unable to find " + HsOfficePersonEntity.class.getName() + " with id " + GIVEN_NON_EXISTING_UUID));
// @formatter:on // @formatter:on
} }
} }