create partner now taking existing contact+person uuids instead of complete (new) objects
This commit is contained in:
parent
3fa02d4a10
commit
9cd4525e2b
@ -13,6 +13,7 @@ import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
|
||||
@ControllerAdvice
|
||||
@ -34,6 +35,13 @@ public class RestResponseEntityExceptionHandler
|
||||
return errorResponse(request, httpStatus(message).orElse(HttpStatus.INTERNAL_SERVER_ERROR), message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(NoSuchElementException.class)
|
||||
protected ResponseEntity<CustomErrorResponse> handleNoSuchElementException(
|
||||
final RuntimeException exc, final WebRequest request) {
|
||||
final var message = firstLine(NestedExceptionUtils.getMostSpecificCause(exc).getMessage());
|
||||
return errorResponse(request, HttpStatus.NOT_FOUND, message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(Throwable.class)
|
||||
protected ResponseEntity<CustomErrorResponse> handleOtherExceptions(
|
||||
final Throwable exc, final WebRequest request) {
|
||||
|
@ -2,14 +2,9 @@ package net.hostsharing.hsadminng.hs.office.partner;
|
||||
|
||||
import net.hostsharing.hsadminng.Mapper;
|
||||
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.generated.api.v1.api.HsOfficePartnersApi;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeContactResource;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerResource;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerUpdateResource;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePersonResource;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -18,6 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@ -59,34 +55,25 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
|
||||
public ResponseEntity<HsOfficePartnerResource> addPartner(
|
||||
final String currentUser,
|
||||
final String assumedRoles,
|
||||
final HsOfficePartnerResource body) {
|
||||
final HsOfficePartnerInsertResource body) {
|
||||
|
||||
context.define(currentUser, assumedRoles);
|
||||
|
||||
if (body.getUuid() == null) {
|
||||
body.setUuid(UUID.randomUUID());
|
||||
}
|
||||
final var entityToSave = mapToHsOfficePartnerEntity(body);
|
||||
entityToSave.setUuid(UUID.randomUUID());
|
||||
entityToSave.setContact(contactRepo.findByUuid(body.getContactUuid()).orElseThrow(
|
||||
() -> new NoSuchElementException("cannot find contact uuid " + body.getContactUuid())
|
||||
));
|
||||
entityToSave.setPerson(personRepo.findByUuid(body.getPersonUuid()).orElseThrow(
|
||||
() -> new NoSuchElementException("cannot find person uuid " + body.getPersonUuid())
|
||||
));
|
||||
|
||||
final var entityToSave = map(body, HsOfficePartnerEntity.class);
|
||||
if (entityToSave.getContact().getUuid() != null) {
|
||||
contactRepo.findByUuid(entityToSave.getContact().getUuid()).ifPresent(entityToSave::setContact);
|
||||
} else {
|
||||
entityToSave.getContact().setUuid(UUID.randomUUID());
|
||||
entityToSave.setContact(contactRepo.save(entityToSave.getContact()));
|
||||
}
|
||||
if (entityToSave.getPerson().getUuid() != null) {
|
||||
personRepo.findByUuid(entityToSave.getPerson().getUuid()).ifPresent(entityToSave::setPerson);
|
||||
} else {
|
||||
entityToSave.getPerson().setUuid(UUID.randomUUID());
|
||||
entityToSave.setPerson(personRepo.save(entityToSave.getPerson()));
|
||||
}
|
||||
|
||||
final var saved = partnerRepo.save(entityToSave);
|
||||
|
||||
final var uri =
|
||||
MvcUriComponentsBuilder.fromController(getClass())
|
||||
.path("/api/hs/office/partners/{id}")
|
||||
.buildAndExpand(body.getUuid())
|
||||
.buildAndExpand(entityToSave.getUuid())
|
||||
.toUri();
|
||||
final var mapped = map(saved, HsOfficePartnerResource.class,
|
||||
PARTNER_ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
@ -121,18 +108,22 @@ public class HsOfficePartnerController implements HsOfficePartnersApi {
|
||||
final String currentUser,
|
||||
final String assumedRoles,
|
||||
final UUID partnerUuid,
|
||||
final HsOfficePartnerUpdateResource body) {
|
||||
final HsOfficePartnerPatchResource body) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private final BiConsumer<HsOfficePartnerResource, HsOfficePartnerEntity> PARTNER_RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
|
||||
entity.setPerson(map(resource.getPerson(), HsOfficePersonEntity.class));
|
||||
entity.setContact(map(resource.getContact(), HsOfficeContactEntity.class));
|
||||
};
|
||||
|
||||
private final BiConsumer<HsOfficePartnerEntity, HsOfficePartnerResource> PARTNER_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
||||
final BiConsumer<HsOfficePartnerEntity, HsOfficePartnerResource> PARTNER_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
||||
resource.setPerson(map(entity.getPerson(), HsOfficePersonResource.class));
|
||||
resource.setContact(map(entity.getContact(), HsOfficeContactResource.class));
|
||||
};
|
||||
|
||||
private HsOfficePartnerEntity mapToHsOfficePartnerEntity(final HsOfficePartnerInsertResource resource) {
|
||||
final var entity = new HsOfficePartnerEntity();
|
||||
entity.setBirthday(resource.getBirthday());
|
||||
entity.setBirthName(resource.getBirthName());
|
||||
entity.setDateOfDeath(resource.getDateOfDeath());
|
||||
entity.setRegistrationNumber(resource.getRegistrationNumber());
|
||||
entity.setRegistrationOffice(resource.getRegistrationOffice());
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ components:
|
||||
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
||||
- $ref: '#/components/schemas/HsOfficePartnerBase'
|
||||
|
||||
HsOfficePartnerUpdate:
|
||||
HsOfficePartnerPatch:
|
||||
allOf:
|
||||
- type: object
|
||||
properties:
|
||||
@ -43,3 +43,18 @@ components:
|
||||
type: string
|
||||
format: uuid
|
||||
- $ref: '#/components/schemas/HsOfficePartnerBase'
|
||||
|
||||
HsOfficePartnerInsert:
|
||||
allOf:
|
||||
- type: object
|
||||
properties:
|
||||
personUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
contactUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
- required:
|
||||
- personUuid
|
||||
- contactUuid
|
||||
- $ref: '#/components/schemas/HsOfficePartnerBase'
|
||||
|
@ -42,7 +42,7 @@ patch:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartnerUpdate'
|
||||
$ref: './hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartnerPatch'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
|
@ -39,7 +39,7 @@ post:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartner'
|
||||
$ref: './hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartnerInsert'
|
||||
required: true
|
||||
responses:
|
||||
"201":
|
||||
|
@ -156,7 +156,7 @@ grant all privileges on hs_office_contact_rv to restricted;
|
||||
/**
|
||||
Instead of insert trigger function for hs_office_contact_rv.
|
||||
*/
|
||||
create or replace function inserthsOfficeContact()
|
||||
create or replace function insertHsOfficeContact()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
declare
|
||||
@ -173,11 +173,11 @@ $$;
|
||||
/*
|
||||
Creates an instead of insert trigger for the hs_office_contact_rv view.
|
||||
*/
|
||||
create trigger inserthsOfficeContact_Trigger
|
||||
create trigger insertHsOfficeContact_Trigger
|
||||
instead of insert
|
||||
on hs_office_contact_rv
|
||||
for each row
|
||||
execute function inserthsOfficeContact();
|
||||
execute function insertHsOfficeContact();
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
@ -189,7 +189,7 @@ execute function inserthsOfficeContact();
|
||||
|
||||
Checks if the current subject (user / assumed role) has the permission to delete the row.
|
||||
*/
|
||||
create or replace function deletehsOfficeContact()
|
||||
create or replace function deleteHsOfficeContact()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
@ -204,11 +204,11 @@ end; $$;
|
||||
/*
|
||||
Creates an instead of delete trigger for the hs_office_contact_rv view.
|
||||
*/
|
||||
create trigger deletehsOfficeContact_Trigger
|
||||
create trigger deleteHsOfficeContact_Trigger
|
||||
instead of delete
|
||||
on hs_office_contact_rv
|
||||
for each row
|
||||
execute function deletehsOfficeContact();
|
||||
execute function deleteHsOfficeContact();
|
||||
--/
|
||||
|
||||
-- ============================================================================
|
||||
|
@ -5,6 +5,8 @@ import io.restassured.http.ContentType;
|
||||
import net.hostsharing.hsadminng.Accepts;
|
||||
import net.hostsharing.hsadminng.HsadminNgApplication;
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||
import net.hostsharing.test.JpaAttempt;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -20,7 +22,6 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.hostsharing.test.IsValidUuidMatcher.isUuidValid;
|
||||
import static net.hostsharing.test.JsonBuilder.jsonObject;
|
||||
import static net.hostsharing.test.JsonMatcher.lenientlyEquals;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -45,6 +46,12 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
@Autowired
|
||||
HsOfficePartnerRepository partnerRepo;
|
||||
|
||||
@Autowired
|
||||
HsOfficePersonRepository personRepo;
|
||||
|
||||
@Autowired
|
||||
HsOfficeContactRepository contactRepo;
|
||||
|
||||
@Autowired
|
||||
JpaAttempt jpaAttempt;
|
||||
|
||||
@ -90,70 +97,28 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
@Accepts({ "Partner:C(Create)" })
|
||||
class AddPartner {
|
||||
|
||||
private final static String NEW_PARTNER_JSON_WITHOUT_UUID =
|
||||
"""
|
||||
{
|
||||
"person": {
|
||||
"personType": "LEGAL",
|
||||
"tradeName": "Test Corp.",
|
||||
"givenName": null,
|
||||
"familyName": null
|
||||
},
|
||||
"contact": {
|
||||
"label": "Test Corp.",
|
||||
"postalAddress": "Test Corp.\\nTestweg 50\\n20001 Hamburg",
|
||||
"emailAddresses": "office@example.com",
|
||||
"phoneNumbers": "040 12345"
|
||||
},
|
||||
@Test
|
||||
void globalAdmin_withoutAssumedRole_canAddPartner_withGeneratedUuid() {
|
||||
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenPerson = personRepo.findPersonByOptionalNameLike("Ostfriesische").get(0);
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("forth").get(0);
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("current-user", "superuser-alex@hostsharing.net")
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""
|
||||
{
|
||||
"contactUuid": "%s",
|
||||
"personUuid": "%s",
|
||||
"registrationOffice": "Registergericht Hamburg",
|
||||
"registrationNumber": "123456",
|
||||
"birthName": null,
|
||||
"birthday": null,
|
||||
"dateOfDeath": null
|
||||
}
|
||||
""";
|
||||
|
||||
@Test
|
||||
void globalAdmin_withoutAssumedRole_canAddPartner_withExplicitUuid() {
|
||||
|
||||
final var givenUUID = toCleanup(UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6"));
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("current-user", "superuser-alex@hostsharing.net")
|
||||
.contentType(ContentType.JSON)
|
||||
.body(jsonObject(NEW_PARTNER_JSON_WITHOUT_UUID)
|
||||
.with("uuid", givenUUID.toString()).toString())
|
||||
.port(port)
|
||||
.when()
|
||||
.post("http://localhost/api/hs/office/partners")
|
||||
.then().assertThat()
|
||||
.statusCode(201)
|
||||
.contentType(ContentType.JSON)
|
||||
.body("uuid", is("3fa85f64-5717-4562-b3fc-2c963f66afa6"))
|
||||
.body("registrationNumber", is("123456"))
|
||||
.body("person.tradeName", is("Test Corp."))
|
||||
.body("contact.label", is("Test Corp."))
|
||||
.header("Location", startsWith("http://localhost"))
|
||||
.extract().header("Location"); // @formatter:on
|
||||
|
||||
// finally, the new partner can be accessed under the given UUID
|
||||
final var newUserUuid = UUID.fromString(
|
||||
location.substring(location.lastIndexOf('/') + 1));
|
||||
assertThat(newUserUuid).isEqualTo(givenUUID);
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
assertThat(partnerRepo.findByUuid(newUserUuid))
|
||||
.hasValueSatisfying(c -> assertThat(c.getPerson().getTradeName()).isEqualTo("Test Corp."));
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalAdmin_withoutAssumedRole_canAddPartner_withGeneratedUuid() {
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("current-user", "superuser-alex@hostsharing.net")
|
||||
.contentType(ContentType.JSON)
|
||||
.body(NEW_PARTNER_JSON_WITHOUT_UUID)
|
||||
""".formatted(givenContact.getUuid(), givenPerson.getUuid()))
|
||||
.port(port)
|
||||
.when()
|
||||
.post("http://localhost/api/hs/office/partners")
|
||||
@ -162,7 +127,8 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
.contentType(ContentType.JSON)
|
||||
.body("uuid", isUuidValid())
|
||||
.body("registrationNumber", is("123456"))
|
||||
.body("person.tradeName", is("Test Corp."))
|
||||
.body("contact.label", is(givenContact.getLabel()))
|
||||
.body("person.tradeName", is(givenPerson.getTradeName()))
|
||||
.header("Location", startsWith("http://localhost"))
|
||||
.extract().header("Location"); // @formatter:on
|
||||
|
||||
@ -171,6 +137,68 @@ class HsOfficePartnerControllerAcceptanceTest {
|
||||
location.substring(location.lastIndexOf('/') + 1)));
|
||||
assertThat(newUserUuid).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalAdmin_canNotAddPartner_ifContactDoesNotExist() {
|
||||
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenPerson = personRepo.findPersonByOptionalNameLike("Ostfriesische").get(0);
|
||||
final var givenContactUuid = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6");
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("current-user", "superuser-alex@hostsharing.net")
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""
|
||||
{
|
||||
"contactUuid": "%s",
|
||||
"personUuid": "%s",
|
||||
"registrationOffice": "Registergericht Hamburg",
|
||||
"registrationNumber": "123456",
|
||||
"birthName": null,
|
||||
"birthday": null,
|
||||
"dateOfDeath": null
|
||||
}
|
||||
""".formatted(givenContactUuid, givenPerson.getUuid()))
|
||||
.port(port)
|
||||
.when()
|
||||
.post("http://localhost/api/hs/office/partners")
|
||||
.then().log().all().assertThat()
|
||||
.statusCode(404)
|
||||
.body("message", is("cannot find contact uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalAdmin_canNotAddPartner_ifPersonDoesNotExist() {
|
||||
|
||||
context.define("superuser-alex@hostsharing.net");
|
||||
final var givenPersonUuid = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6");
|
||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("forth").get(0);
|
||||
|
||||
final var location = RestAssured // @formatter:off
|
||||
.given()
|
||||
.header("current-user", "superuser-alex@hostsharing.net")
|
||||
.contentType(ContentType.JSON)
|
||||
.body("""
|
||||
{
|
||||
"contactUuid": "%s",
|
||||
"personUuid": "%s",
|
||||
"registrationOffice": "Registergericht Hamburg",
|
||||
"registrationNumber": "123456",
|
||||
"birthName": null,
|
||||
"birthday": null,
|
||||
"dateOfDeath": null
|
||||
}
|
||||
""".formatted(givenContact.getUuid(), givenPersonUuid))
|
||||
.port(port)
|
||||
.when()
|
||||
.post("http://localhost/api/hs/office/partners")
|
||||
.then().log().all().assertThat()
|
||||
.statusCode(404)
|
||||
.body("message", is("cannot find person uuid 3fa85f64-5717-4562-b3fc-2c963f66afa6"));
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
Loading…
Reference in New Issue
Block a user