http-get endpoints for partner, debitor and memberhip-number #135
@ -57,11 +57,11 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
|
|||||||
final String currentSubject,
|
final String currentSubject,
|
||||||
final String assumedRoles,
|
final String assumedRoles,
|
||||||
final String name,
|
final String name,
|
||||||
final String debitorNumber) {
|
final String partnerNumber) {
|
||||||
context.define(currentSubject, assumedRoles);
|
context.define(currentSubject, assumedRoles);
|
||||||
|
|
||||||
final var entities = debitorNumber != null
|
final var entities = partnerNumber != null
|
||||||
? debitorRepo.findDebitorByDebitorNumber(cropTag("D-", debitorNumber))
|
? debitorRepo.findDebitorByPartnerNumber(cropTag("P-", partnerNumber))
|
||||||
: debitorRepo.findDebitorByOptionalNameLike(name);
|
: debitorRepo.findDebitorByOptionalNameLike(name);
|
||||||
|
|
||||||
final var resources = mapper.mapList(entities, HsOfficeDebitorResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
final var resources = mapper.mapList(entities, HsOfficeDebitorResource.class, ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||||
@ -133,6 +133,23 @@ public class HsOfficeDebitorController implements HsOfficeDebitorsApi {
|
|||||||
return ResponseEntity.ok(mapper.map(result.get(), HsOfficeDebitorResource.class, ENTITY_TO_RESOURCE_POSTMAPPER));
|
return ResponseEntity.ok(mapper.map(result.get(), HsOfficeDebitorResource.class, ENTITY_TO_RESOURCE_POSTMAPPER));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
@Timed("app.office.debitors.api.getSingleDebitorByDebitorNumber")
|
||||||
|
public ResponseEntity<HsOfficeDebitorResource> getSingleDebitorByDebitorNumber(
|
||||||
|
final String currentSubject,
|
||||||
|
final String assumedRoles,
|
||||||
|
final Integer debitorNumber) {
|
||||||
|
|
||||||
|
context.define(currentSubject, assumedRoles);
|
||||||
|
|
||||||
|
final var result = debitorRepo.findDebitorByDebitorNumber(debitorNumber);
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(mapper.map(result.get(), HsOfficeDebitorResource.class, ENTITY_TO_RESOURCE_POSTMAPPER));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
@Timed("app.office.debitors.api.deleteDebitorByUuid")
|
@Timed("app.office.debitors.api.deleteDebitorByUuid")
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.debitor;
|
package net.hostsharing.hsadminng.hs.office.debitor;
|
||||||
|
|
||||||
import io.micrometer.core.annotation.Timed;
|
import io.micrometer.core.annotation.Timed;
|
||||||
|
import net.hostsharing.hsadminng.lambda.Reducer;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.Repository;
|
import org.springframework.data.repository.Repository;
|
||||||
|
|
||||||
@ -19,15 +20,20 @@ public interface HsOfficeDebitorRepository extends Repository<HsOfficeDebitorEnt
|
|||||||
ON partner.partnerRel.holder = debitor.debitorRel.anchor
|
ON partner.partnerRel.holder = debitor.debitorRel.anchor
|
||||||
AND partner.partnerRel.type = 'PARTNER' AND debitor.debitorRel.type = 'DEBITOR'
|
AND partner.partnerRel.type = 'PARTNER' AND debitor.debitorRel.type = 'DEBITOR'
|
||||||
WHERE partner.partnerNumber = :partnerNumber
|
WHERE partner.partnerNumber = :partnerNumber
|
||||||
AND debitor.debitorNumberSuffix = :debitorNumberSuffix
|
AND (:debitorNumberSuffix IS NULL OR debitor.debitorNumberSuffix = :debitorNumberSuffix)
|
||||||
""")
|
""")
|
||||||
@Timed("app.office.debitors.repo.findDebitorByPartnerNumberAndDebitorNumberSuffix")
|
@Timed("app.office.debitors.repo.findDebitorByPartnerNumberAndDebitorNumberSuffix")
|
||||||
List<HsOfficeDebitorEntity> findDebitorByPartnerNumberAndDebitorNumberSuffix(int partnerNumber, String debitorNumberSuffix);
|
List<HsOfficeDebitorEntity> findDebitorByPartnerNumberAndOptionalDebitorNumberSuffix(int partnerNumber, String debitorNumberSuffix);
|
||||||
|
|
||||||
default List<HsOfficeDebitorEntity> findDebitorByDebitorNumber(int debitorNumber) {
|
default Optional<HsOfficeDebitorEntity> findDebitorByDebitorNumber(int debitorNumber) {
|
||||||
final var partnerNumber = debitorNumber / 100;
|
final var partnerNumber = debitorNumber / 100;
|
||||||
final String suffix = String.format("%02d", debitorNumber % 100);
|
final String suffix = String.format("%02d", debitorNumber % 100);
|
||||||
final var result = findDebitorByPartnerNumberAndDebitorNumberSuffix(partnerNumber, suffix);
|
final var result = findDebitorByPartnerNumberAndOptionalDebitorNumberSuffix(partnerNumber, suffix);
|
||||||
|
return result.stream().reduce(Reducer::toSingleElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
default List<HsOfficeDebitorEntity> findDebitorByPartnerNumber(int partnerNumber) {
|
||||||
|
final var result = findDebitorByPartnerNumberAndOptionalDebitorNumberSuffix(partnerNumber, null);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ map:
|
|||||||
- type: string:uuid => java.util.UUID
|
- type: string:uuid => java.util.UUID
|
||||||
- type: string:format => java.lang.String
|
- type: string:format => java.lang.String
|
||||||
- type: number:currency => java.math.BigDecimal
|
- type: number:currency => java.math.BigDecimal
|
||||||
|
- type: number:integer => java.lang.Integer
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
/api/hs/office/partners/{partnerUUID}:
|
/api/hs/office/partners/{partnerUUID}:
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- hs-office-debitors
|
||||||
|
description: 'Fetch a single debitor by its debitorNumber, if visible for the current subject.'
|
||||||
|
operationId: getSingleDebitorByDebitorNumber
|
||||||
|
parameters:
|
||||||
|
- $ref: 'auth.yaml#/components/parameters/currentSubject'
|
||||||
|
- $ref: 'auth.yaml#/components/parameters/assumedRoles'
|
||||||
|
- name: debitorNumber
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
format: integer
|
||||||
|
minimum: 1000000
|
||||||
hsh-michaelhoennig marked this conversation as resolved
Outdated
|
|||||||
|
maximum: 9999999
|
||||||
|
description: debitor-number of the debitor to fetch.
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
'application/json':
|
||||||
|
schema:
|
||||||
|
$ref: 'hs-office-debitor-schemas.yaml#/components/schemas/HsOfficeDebitor'
|
||||||
|
|
||||||
|
"401":
|
||||||
|
$ref: 'error-responses.yaml#/components/responses/Unauthorized'
|
||||||
|
"403":
|
||||||
|
$ref: 'error-responses.yaml#/components/responses/Forbidden'
|
@ -13,15 +13,15 @@ get:
|
|||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
description: Prefix of name properties from person or contact to filter the results.
|
description: Prefix of name properties from person or contact to filter the results.
|
||||||
- name: debitorNumber
|
- name: partnerNumber
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
minLength: 9
|
minLength: 9
|
||||||
maxLength: 9
|
maxLength: 9
|
||||||
pattern: 'D-[0-9]{7}'
|
pattern: 'P-[0-9]{5}'
|
||||||
description: Debitor number of the requested debitor.
|
description: Partner number of the requested debitor.
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
|
@ -61,6 +61,9 @@ paths:
|
|||||||
/api/hs/office/debitors:
|
/api/hs/office/debitors:
|
||||||
$ref: "hs-office-debitors.yaml"
|
$ref: "hs-office-debitors.yaml"
|
||||||
|
|
||||||
|
/api/hs/office/debitors/D-{debitorNumber}:
|
||||||
|
$ref: "hs-office-debitors-with-debitorNumber.yaml"
|
||||||
|
|
||||||
/api/hs/office/debitors/{debitorUUID}:
|
/api/hs/office/debitors/{debitorUUID}:
|
||||||
$ref: "hs-office-debitors-with-uuid.yaml"
|
$ref: "hs-office-debitors-with-uuid.yaml"
|
||||||
|
|
||||||
|
@ -233,7 +233,56 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void globalAdmin_withoutAssumedRoles_canFindDebitorDebitorByDebitorNumber() {
|
void globalAdmin_withoutAssumedRoles_canGetDebitorByDebitorNumber() {
|
||||||
|
|
||||||
|
RestAssured // @formatter:off
|
||||||
|
.given()
|
||||||
|
.header("current-subject", "superuser-alex@hostsharing.net")
|
||||||
|
.port(port)
|
||||||
|
.when()
|
||||||
|
.get("http://localhost/api/hs/office/debitors/P-10002")
|
||||||
|
.then().log().all().assertThat()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType("application/json")
|
||||||
|
.body("", lenientlyEquals("""
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"debitorNumber": "D-1000211",
|
||||||
|
"partner": { "partnerNumber": "P-10002" },
|
||||||
|
"debitorRel": {
|
||||||
|
"contact": { "caption": "second contact" }
|
||||||
|
},
|
||||||
|
"vatId": null,
|
||||||
|
"vatCountryCode": null,
|
||||||
|
"vatBusiness": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"debitorNumber": "D-1000212",
|
||||||
|
"partner": { "partnerNumber": "P-10002" },
|
||||||
|
"debitorRel": {
|
||||||
|
"contact": { "caption": "second contact" }
|
||||||
|
},
|
||||||
|
"vatId": null,
|
||||||
|
"vatCountryCode": null,
|
||||||
|
"vatBusiness": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"debitorNumber": "D-1000213",
|
||||||
|
"partner": { "partnerNumber": "P-10002" },
|
||||||
|
"debitorRel": {
|
||||||
|
"contact": { "caption": "second contact" }
|
||||||
|
},
|
||||||
|
"vatId": null,
|
||||||
|
"vatCountryCode": null,
|
||||||
|
"vatBusiness": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""));
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void globalAdmin_withoutAssumedRoles_canFindDebitorsByPartnerNumber() {
|
||||||
|
|
||||||
RestAssured // @formatter:off
|
RestAssured // @formatter:off
|
||||||
.given()
|
.given()
|
||||||
|
@ -50,7 +50,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
HsOfficePartnerRepository partnerRepo;
|
HsOfficePartnerRepository partnerRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeContactRealRepository contactrealRepo;
|
HsOfficeContactRealRepository contactRealRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficePersonRealRepository personRepo;
|
HsOfficePersonRealRepository personRepo;
|
||||||
@ -85,7 +85,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var count = debitorRepo.count();
|
final var count = debitorRepo.count();
|
||||||
final var givenPartner = partnerRepo.findPartnerByPartnerNumber(10001).orElseThrow();
|
final var givenPartner = partnerRepo.findPartnerByPartnerNumber(10001).orElseThrow();
|
||||||
final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH"));
|
final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH"));
|
||||||
final var givenContact = one(contactrealRepo.findContactByOptionalCaptionLike("first contact"));
|
final var givenContact = one(contactRealRepo.findContactByOptionalCaptionLike("first contact"));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
@ -119,7 +119,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// given
|
// given
|
||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH"));
|
final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH"));
|
||||||
final var givenContact = one(contactrealRepo.findContactByOptionalCaptionLike("first contact"));
|
final var givenContact = one(contactRealRepo.findContactByOptionalCaptionLike("first contact"));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
@ -158,7 +158,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
attempt(em, () -> {
|
attempt(em, () -> {
|
||||||
final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH"));
|
final var givenPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First GmbH"));
|
||||||
final var givenDebitorPerson = one(personRepo.findPersonByOptionalNameLike("Fourth eG"));
|
final var givenDebitorPerson = one(personRepo.findPersonByOptionalNameLike("Fourth eG"));
|
||||||
final var givenContact = one(contactrealRepo.findContactByOptionalCaptionLike("fourth contact"));
|
final var givenContact = one(contactRealRepo.findContactByOptionalCaptionLike("fourth contact"));
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix("22")
|
.debitorNumberSuffix("22")
|
||||||
.debitorRel(HsOfficeRelationRealEntity.builder()
|
.debitorRel(HsOfficeRelationRealEntity.builder()
|
||||||
@ -278,7 +278,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class FindByDebitorNumberLike {
|
class FindByDebitorNumber {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void globalAdmin_canViewAllDebitors() {
|
public void globalAdmin_canViewAllDebitors() {
|
||||||
@ -288,6 +288,23 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// when
|
// when
|
||||||
final var result = debitorRepo.findDebitorByDebitorNumber(1000313);
|
final var result = debitorRepo.findDebitorByDebitorNumber(1000313);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result).map(Object::toString).contains(
|
||||||
|
"debitor(D-1000313: rel(anchor='IF Third OHG', type='DEBITOR', holder='IF Third OHG'), thi)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class FindByPartnerNumber {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void globalAdmin_canViewAllDebitors() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = debitorRepo.findDebitorByPartnerNumber(10003);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
exactlyTheseDebitorsAreReturned(result,
|
exactlyTheseDebitorsAreReturned(result,
|
||||||
"debitor(D-1000313: rel(anchor='IF Third OHG', type='DEBITOR', holder='IF Third OHG'), thi)");
|
"debitor(D-1000313: rel(anchor='IF Third OHG', type='DEBITOR', holder='IF Third OHG'), thi)");
|
||||||
@ -324,7 +341,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
"hs_office.relation#FourtheG-with-DEBITOR-FourtheG:ADMIN", true);
|
"hs_office.relation#FourtheG-with-DEBITOR-FourtheG:ADMIN", true);
|
||||||
final var givenNewPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First"));
|
final var givenNewPartnerPerson = one(personRepo.findPersonByOptionalNameLike("First"));
|
||||||
final var givenNewBillingPerson = one(personRepo.findPersonByOptionalNameLike("Firby"));
|
final var givenNewBillingPerson = one(personRepo.findPersonByOptionalNameLike("Firby"));
|
||||||
final var givenNewContact = one(contactrealRepo.findContactByOptionalCaptionLike("sixth contact"));
|
final var givenNewContact = one(contactRealRepo.findContactByOptionalCaptionLike("sixth contact"));
|
||||||
final var givenNewBankAccount = one(bankAccountRepo.findByOptionalHolderLike("first"));
|
final var givenNewBankAccount = one(bankAccountRepo.findByOptionalHolderLike("first"));
|
||||||
final String givenNewVatId = "NEW-VAT-ID";
|
final String givenNewVatId = "NEW-VAT-ID";
|
||||||
final String givenNewVatCountryCode = "NC";
|
final String givenNewVatCountryCode = "NC";
|
||||||
@ -613,7 +630,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
context("superuser-alex@hostsharing.net");
|
context("superuser-alex@hostsharing.net");
|
||||||
final var givenPartner = one(partnerRepo.findPartnerByOptionalNameLike(partnerName));
|
final var givenPartner = one(partnerRepo.findPartnerByOptionalNameLike(partnerName));
|
||||||
final var givenPartnerPerson = givenPartner.getPartnerRel().getHolder();
|
final var givenPartnerPerson = givenPartner.getPartnerRel().getHolder();
|
||||||
final var givenContact = one(contactrealRepo.findContactByOptionalCaptionLike(contactCaption));
|
final var givenContact = one(contactRealRepo.findContactByOptionalCaptionLike(contactCaption));
|
||||||
final var givenBankAccount =
|
final var givenBankAccount =
|
||||||
bankAccountHolder != null ? one(bankAccountRepo.findByOptionalHolderLike(bankAccountHolder)) : null;
|
bankAccountHolder != null ? one(bankAccountRepo.findByOptionalHolderLike(bankAccountHolder)) : null;
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
|
@ -524,7 +524,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest extends ContextBasedTestWithCl
|
|||||||
private HsOfficeSepaMandateEntity givenSomeTemporarySepaMandateForDebitorNumber(final int debitorNumber) {
|
private HsOfficeSepaMandateEntity givenSomeTemporarySepaMandateForDebitorNumber(final int debitorNumber) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context.define("superuser-alex@hostsharing.net");
|
context.define("superuser-alex@hostsharing.net");
|
||||||
final var givenDebitor = debitorRepo.findDebitorByDebitorNumber(debitorNumber).get(0);
|
final var givenDebitor = debitorRepo.findDebitorByDebitorNumber(debitorNumber).orElseThrow();
|
||||||
final var bankAccountHolder = ofNullable(givenDebitor.getPartner().getPartnerRel().getHolder().getTradeName())
|
final var bankAccountHolder = ofNullable(givenDebitor.getPartner().getPartnerRel().getHolder().getTradeName())
|
||||||
.orElse(givenDebitor.getPartner().getPartnerRel().getHolder().getFamilyName());
|
.orElse(givenDebitor.getPartner().getPartnerRel().getHolder().getFamilyName());
|
||||||
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike(bankAccountHolder).get(0);
|
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike(bankAccountHolder).get(0);
|
||||||
|
Loading…
Reference in New Issue
Block a user
wieder rein