From d464a4cf612de1aff20ee62fc8bfef18f763cf56 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 6 Dec 2024 14:57:32 +0100 Subject: [PATCH] add endpoint HTTP GET /api/hs/office/partners/P-{partnerNumber} --- .../partner/HsOfficePartnerController.java | 17 ++++++++ .../partner/HsOfficePartnerRepository.java | 2 +- ...hs-office-partners-with-partnerNumber.yaml | 28 +++++++++++++ .../api-definition/hs-office/hs-office.yaml | 3 ++ ...fficeDebitorRepositoryIntegrationTest.java | 2 +- ...iceMembershipControllerAcceptanceTest.java | 8 ++-- .../HsOfficePartnerControllerRestTest.java | 39 +++++++++++++++++++ ...fficePartnerRepositoryIntegrationTest.java | 2 +- 8 files changed, 94 insertions(+), 7 deletions(-) create mode 100644 src/main/resources/api-definition/hs-office/hs-office-partners-with-partnerNumber.yaml diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java index a375174b..f3c25bd5 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java @@ -104,6 +104,23 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { return ResponseEntity.ok(mapper.map(result.get(), HsOfficePartnerResource.class)); } + @Override + @Transactional(readOnly = true) + @Timed("app.office.partners.api.getSinglePartnerByPartnerNumber") + public ResponseEntity getSinglePartnerByPartnerNumber( + final String currentSubject, + final String assumedRoles, + final Integer partnerNumber) { + + context.define(currentSubject, assumedRoles); + + final var result = partnerRepo.findPartnerByPartnerNumber(partnerNumber); + if (result.isEmpty()) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(mapper.map(result.get(), HsOfficePartnerResource.class)); + } + @Override @Transactional @Timed("app.office.partners.api.deletePartnerByUuid") diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java index 282d3db3..3ae4a26a 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepository.java @@ -32,7 +32,7 @@ public interface HsOfficePartnerRepository extends Repository findPartnerByOptionalNameLike(String name); @Timed("app.office.partners.repo.findPartnerByPartnerNumber") - HsOfficePartnerEntity findPartnerByPartnerNumber(Integer partnerNumber); + Optional findPartnerByPartnerNumber(Integer partnerNumber); @Timed("app.office.partners.repo.save") HsOfficePartnerEntity save(final HsOfficePartnerEntity entity); diff --git a/src/main/resources/api-definition/hs-office/hs-office-partners-with-partnerNumber.yaml b/src/main/resources/api-definition/hs-office/hs-office-partners-with-partnerNumber.yaml new file mode 100644 index 00000000..b402048f --- /dev/null +++ b/src/main/resources/api-definition/hs-office/hs-office-partners-with-partnerNumber.yaml @@ -0,0 +1,28 @@ +get: + tags: + - hs-office-partners + description: 'Fetch a single business partner by its partner-number (prefixed with "P-"), if visible for the current subject.' + operationId: getSinglePartnerByPartnerNumber + parameters: + - $ref: 'auth.yaml#/components/parameters/currentSubject' + - $ref: 'auth.yaml#/components/parameters/assumedRoles' + - name: partnerNumber + in: path + required: true + schema: + type: integer + minimum: 10000 + maximum: 99999 + description: partner-number (prefixed with "P-") of the partner to fetch. + responses: + "200": + description: OK + content: + 'application/json': + schema: + $ref: 'hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartner' + + "401": + $ref: 'error-responses.yaml#/components/responses/Unauthorized' + "403": + $ref: 'error-responses.yaml#/components/responses/Forbidden' diff --git a/src/main/resources/api-definition/hs-office/hs-office.yaml b/src/main/resources/api-definition/hs-office/hs-office.yaml index e8e7816d..71aa708b 100644 --- a/src/main/resources/api-definition/hs-office/hs-office.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office.yaml @@ -13,6 +13,9 @@ paths: /api/hs/office/partners: $ref: "hs-office-partners.yaml" + /api/hs/office/partners/P-{partnerNumber}: + $ref: "hs-office-partners-with-partnerNumber.yaml" + /api/hs/office/partners/{partnerUUID}: $ref: "hs-office-partners-with-uuid.yaml" diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java index 781077cb..fb0c0c94 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java @@ -83,7 +83,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean // given context("superuser-alex@hostsharing.net"); final var count = debitorRepo.count(); - final var givenPartner = partnerRepo.findPartnerByPartnerNumber(10001); + final var givenPartner = partnerRepo.findPartnerByPartnerNumber(10001).orElseThrow(); final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH")); final var givenContact = one(contactrealRepo.findContactByOptionalCaptionLike("first contact")); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java index c2dd44c1..9f609e53 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java @@ -112,16 +112,16 @@ class HsOfficeMembershipControllerAcceptanceTest extends ContextBasedTestWithCle void globalAdmin_canViewMembershipsByPartnerUuid() { context.define("superuser-alex@hostsharing.net"); - final var partner = partnerRepo.findPartnerByPartnerNumber(10001); + final var partner = partnerRepo.findPartnerByPartnerNumber(10001).orElseThrow(); RestAssured // @formatter:off - .given() + .given() .header("current-subject", "superuser-alex@hostsharing.net") .port(port) - .when() + .when() .queryParam("partnerUuid", partner.getUuid() ) .get("http://localhost/api/hs/office/memberships") - .then().log().all().assertThat() + .then().log().all().assertThat() .statusCode(200) .contentType("application/json") .body("", lenientlyEquals(""" diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java index dbc6081b..4d016725 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java @@ -168,6 +168,45 @@ class HsOfficePartnerControllerRestTest { } } + @Nested + class GetSinglePartnerByPartnerNumber { + + @Test + void respondWithPartner_ifPartnerNumberIsAvailable() throws Exception { + // given + when(partnerRepo.findPartnerByPartnerNumber(12345)).thenReturn(Optional.of(HsOfficePartnerEntity.builder() + .partnerNumber(12345) + .build())); + + // when + mockMvc.perform(MockMvcRequestBuilders + .get("/api/hs/office/partners/P-12345") + .header("current-subject", "superuser-alex@hostsharing.net") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + + // then + .andExpect(status().isOk()) + .andExpect(jsonPath("partnerNumber", is("P-12345"))); + } + + @Test + void respondNotFound_ifPartnerNumberIsNotAvailable() throws Exception { + // given + when(partnerRepo.findPartnerByPartnerNumber(12345)).thenReturn(Optional.empty()); + + // when + mockMvc.perform(MockMvcRequestBuilders + .get("/api/hs/office/partners/P-12345") + .header("current-subject", "superuser-alex@hostsharing.net") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + + // then + .andExpect(status().isNotFound()); + } + } + @Nested class DeletePartner { diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java index 79ff449d..92683a6b 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java @@ -243,7 +243,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean context("superuser-alex@hostsharing.net"); // when - final var result = partnerRepo.findPartnerByPartnerNumber(10001); + final var result = partnerRepo.findPartnerByPartnerNumber(10001).orElseThrow(); // then assertThat(result)