add missing billable and vatReverseCharge to OpenAPI and Patcher

This commit is contained in:
Michael Hoennig 2024-01-19 14:35:08 +01:00
parent 06a39c421e
commit d069e87c01
6 changed files with 65 additions and 40 deletions

View File

@ -53,8 +53,8 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
@JoinColumn(name = "billingcontactuuid") @JoinColumn(name = "billingcontactuuid")
private HsOfficeContactEntity billingContact; // TODO: migrate to billingPerson private HsOfficeContactEntity billingContact; // TODO: migrate to billingPerson
@Column(name = "billable") @Column(name = "billable", nullable = false)
private boolean billable; private Boolean billable; // not a primitive because otherwise the default would be false
@Column(name = "vatid") @Column(name = "vatid")
private String vatId; private String vatId;

View File

@ -6,6 +6,7 @@ import net.hostsharing.hsadminng.mapper.EntityPatcher;
import net.hostsharing.hsadminng.mapper.OptionalFromJson; import net.hostsharing.hsadminng.mapper.OptionalFromJson;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import java.util.Optional;
class HsOfficeDebitorEntityPatcher implements EntityPatcher<HsOfficeDebitorPatchResource> { class HsOfficeDebitorEntityPatcher implements EntityPatcher<HsOfficeDebitorPatchResource> {
@ -25,12 +26,11 @@ class HsOfficeDebitorEntityPatcher implements EntityPatcher<HsOfficeDebitorPatch
verifyNotNull(newValue, "billingContact"); verifyNotNull(newValue, "billingContact");
entity.setBillingContact(em.getReference(HsOfficeContactEntity.class, newValue)); entity.setBillingContact(em.getReference(HsOfficeContactEntity.class, newValue));
}); });
Optional.ofNullable(resource.getBillable()).ifPresent(entity::setBillable);
OptionalFromJson.of(resource.getVatId()).ifPresent(entity::setVatId); OptionalFromJson.of(resource.getVatId()).ifPresent(entity::setVatId);
OptionalFromJson.of(resource.getVatCountryCode()).ifPresent(entity::setVatCountryCode); OptionalFromJson.of(resource.getVatCountryCode()).ifPresent(entity::setVatCountryCode);
OptionalFromJson.of(resource.getVatBusiness()).ifPresent(newValue -> { Optional.ofNullable(resource.getVatBusiness()).ifPresent(entity::setVatBusiness);
verifyNotNull(newValue, "vatBusiness"); Optional.ofNullable(resource.getVatReverseCharge()).ifPresent(entity::setVatReverseCharge);
entity.setVatBusiness(newValue);
});
OptionalFromJson.of(resource.getDefaultPrefix()).ifPresent(newValue -> { OptionalFromJson.of(resource.getDefaultPrefix()).ifPresent(newValue -> {
verifyNotNull(newValue, "defaultPrefix"); verifyNotNull(newValue, "defaultPrefix");
entity.setDefaultPrefix(newValue); entity.setDefaultPrefix(newValue);

View File

@ -23,6 +23,8 @@ components:
$ref: './hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartner' $ref: './hs-office-partner-schemas.yaml#/components/schemas/HsOfficePartner'
billingContact: billingContact:
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact' $ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
billable:
type: boolean
vatId: vatId:
type: string type: string
vatCountryCode: vatCountryCode:
@ -30,6 +32,8 @@ components:
pattern: '^[A-Z][A-Z]$' pattern: '^[A-Z][A-Z]$'
vatBusiness: vatBusiness:
type: boolean type: boolean
vatReverseCharge:
type: boolean
refundBankAccount: refundBankAccount:
$ref: './hs-office-bankaccount-schemas.yaml#/components/schemas/HsOfficeBankAccount' $ref: './hs-office-bankaccount-schemas.yaml#/components/schemas/HsOfficeBankAccount'
defaultPrefix: defaultPrefix:
@ -43,6 +47,9 @@ components:
type: string type: string
format: uuid format: uuid
nullable: true nullable: true
billable:
type: boolean
nullable: false
vatId: vatId:
type: string type: string
nullable: true nullable: true
@ -52,7 +59,10 @@ components:
nullable: true nullable: true
vatBusiness: vatBusiness:
type: boolean type: boolean
nullable: true nullable: false
vatReverseCharge:
type: boolean
nullable: false
refundBankAccountUuid: refundBankAccountUuid:
type: string type: string
format: uuid format: uuid
@ -78,6 +88,8 @@ components:
format: int8 format: int8
minimum: 00 minimum: 00
maximum: 99 maximum: 99
billable:
type: boolean
vatId: vatId:
type: string type: string
vatCountryCode: vatCountryCode:
@ -85,6 +97,8 @@ components:
pattern: '^[A-Z][A-Z]$' pattern: '^[A-Z][A-Z]$'
vatBusiness: vatBusiness:
type: boolean type: boolean
vatReverseCharge:
type: boolean
refundBankAccountUuid: refundBankAccountUuid:
type: string type: string
format: uuid format: uuid
@ -96,3 +110,4 @@ components:
- partnerUuid - partnerUuid
- billingContactUuid - billingContactUuid
- defaultPrefix - defaultPrefix
- billable

View File

@ -164,9 +164,11 @@ class HsOfficeDebitorControllerAcceptanceTest {
"partnerUuid": "%s", "partnerUuid": "%s",
"billingContactUuid": "%s", "billingContactUuid": "%s",
"debitorNumberSuffix": "%s", "debitorNumberSuffix": "%s",
"billable": "true",
"vatId": "VAT123456", "vatId": "VAT123456",
"vatCountryCode": "DE", "vatCountryCode": "DE",
"vatBusiness": true, "vatBusiness": true,
"vatReverseCharge": "false",
"refundBankAccountUuid": "%s", "refundBankAccountUuid": "%s",
"defaultPrefix": "for" "defaultPrefix": "for"
} }
@ -208,7 +210,9 @@ class HsOfficeDebitorControllerAcceptanceTest {
"partnerUuid": "%s", "partnerUuid": "%s",
"billingContactUuid": "%s", "billingContactUuid": "%s",
"debitorNumberSuffix": "%s", "debitorNumberSuffix": "%s",
"defaultPrefix": "for" "defaultPrefix": "for",
"billable": "true",
"vatReverseCharge": "false"
} }
""".formatted( givenPartner.getUuid(), givenContact.getUuid(), ++nextDebitorSuffix)) """.formatted( givenPartner.getUuid(), givenContact.getUuid(), ++nextDebitorSuffix))
.port(port) .port(port)
@ -250,9 +254,11 @@ class HsOfficeDebitorControllerAcceptanceTest {
"partnerUuid": "%s", "partnerUuid": "%s",
"billingContactUuid": "%s", "billingContactUuid": "%s",
"debitorNumberSuffix": "%s", "debitorNumberSuffix": "%s",
"billable": "true",
"vatId": "VAT123456", "vatId": "VAT123456",
"vatCountryCode": "DE", "vatCountryCode": "DE",
"vatBusiness": true, "vatBusiness": true,
"vatReverseCharge": "false",
"defaultPrefix": "thi" "defaultPrefix": "thi"
} }
""" """
@ -282,9 +288,11 @@ class HsOfficeDebitorControllerAcceptanceTest {
"partnerUuid": "%s", "partnerUuid": "%s",
"billingContactUuid": "%s", "billingContactUuid": "%s",
"debitorNumberSuffix": "%s", "debitorNumberSuffix": "%s",
"billable": "true",
"vatId": "VAT123456", "vatId": "VAT123456",
"vatCountryCode": "DE", "vatCountryCode": "DE",
"vatBusiness": true, "vatBusiness": true,
"vatReverseCharge": "false",
"defaultPrefix": "for" "defaultPrefix": "for"
} }
""".formatted( givenPartnerUuid, givenContact.getUuid(), ++nextDebitorSuffix)) """.formatted( givenPartnerUuid, givenContact.getUuid(), ++nextDebitorSuffix))
@ -535,9 +543,11 @@ class HsOfficeDebitorControllerAcceptanceTest {
final var givenContact = contactRepo.findContactByOptionalLabelLike("forth contact").get(0); final var givenContact = contactRepo.findContactByOptionalLabelLike("forth contact").get(0);
final var newDebitor = HsOfficeDebitorEntity.builder() final var newDebitor = HsOfficeDebitorEntity.builder()
.debitorNumberSuffix(++nextDebitorSuffix) .debitorNumberSuffix(++nextDebitorSuffix)
.billable(true)
.partner(givenPartner) .partner(givenPartner)
.billingContact(givenContact) .billingContact(givenContact)
.defaultPrefix("abc") .defaultPrefix("abc")
.vatReverseCharge(false)
.build(); .build();
return debitorRepo.save(newDebitor); return debitorRepo.save(newDebitor);

View File

@ -36,6 +36,12 @@ class HsOfficeDebitorEntityPatcherUnitTest extends PatchUnitTestBase<
private static final boolean PATCHED_VAT_BUSINESS = false; private static final boolean PATCHED_VAT_BUSINESS = false;
private static final boolean INITIAL_BILLABLE = false;
private static final boolean PATCHED_BILLABLE = true;
private static final boolean INITIAL_VAT_REVERSE_CHARGE = true;
private static final boolean PATCHED_VAT_REVERSE_CHARGE = false;
private final HsOfficePartnerEntity givenInitialPartner = HsOfficePartnerEntity.builder() private final HsOfficePartnerEntity givenInitialPartner = HsOfficePartnerEntity.builder()
.uuid(INITIAL_PARTNER_UUID) .uuid(INITIAL_PARTNER_UUID)
.build(); .build();
@ -60,9 +66,11 @@ class HsOfficeDebitorEntityPatcherUnitTest extends PatchUnitTestBase<
entity.setUuid(INITIAL_DEBITOR_UUID); entity.setUuid(INITIAL_DEBITOR_UUID);
entity.setPartner(givenInitialPartner); entity.setPartner(givenInitialPartner);
entity.setBillingContact(givenInitialContact); entity.setBillingContact(givenInitialContact);
entity.setBillable(INITIAL_BILLABLE);
entity.setVatId("initial VAT-ID"); entity.setVatId("initial VAT-ID");
entity.setVatCountryCode("AA"); entity.setVatCountryCode("AA");
entity.setVatBusiness(true); entity.setVatBusiness(true);
entity.setVatReverseCharge(INITIAL_VAT_REVERSE_CHARGE);
entity.setDefaultPrefix("abc"); entity.setDefaultPrefix("abc");
return entity; return entity;
} }
@ -87,6 +95,12 @@ class HsOfficeDebitorEntityPatcherUnitTest extends PatchUnitTestBase<
HsOfficeDebitorEntity::setBillingContact, HsOfficeDebitorEntity::setBillingContact,
newBillingContact(PATCHED_CONTACT_UUID)) newBillingContact(PATCHED_CONTACT_UUID))
.notNullable(), .notNullable(),
new SimpleProperty<>(
"personType",
HsOfficeDebitorPatchResource::setBillable,
PATCHED_BILLABLE,
HsOfficeDebitorEntity::setBillable)
.notNullable(),
new JsonNullableProperty<>( new JsonNullableProperty<>(
"vatId", "vatId",
HsOfficeDebitorPatchResource::setVatId, HsOfficeDebitorPatchResource::setVatId,
@ -97,12 +111,24 @@ class HsOfficeDebitorEntityPatcherUnitTest extends PatchUnitTestBase<
HsOfficeDebitorPatchResource::setVatCountryCode, HsOfficeDebitorPatchResource::setVatCountryCode,
PATCHED_VAT_COUNTRY_CODE, PATCHED_VAT_COUNTRY_CODE,
HsOfficeDebitorEntity::setVatCountryCode), HsOfficeDebitorEntity::setVatCountryCode),
new JsonNullableProperty<>( new SimpleProperty<>(
"vatBusiness", "vatReverseCharge",
HsOfficeDebitorPatchResource::setVatReverseCharge,
PATCHED_VAT_REVERSE_CHARGE,
HsOfficeDebitorEntity::setVatReverseCharge)
.notNullable(),
new SimpleProperty<>(
"personType",
HsOfficeDebitorPatchResource::setVatBusiness, HsOfficeDebitorPatchResource::setVatBusiness,
PATCHED_VAT_BUSINESS, PATCHED_BILLABLE,
HsOfficeDebitorEntity::setVatBusiness) HsOfficeDebitorEntity::setVatBusiness)
.notNullable(), .notNullable(),
new SimpleProperty<>(
"personType",
HsOfficeDebitorPatchResource::setVatReverseCharge,
PATCHED_BILLABLE,
HsOfficeDebitorEntity::setVatReverseCharge)
.notNullable(),
new JsonNullableProperty<>( new JsonNullableProperty<>(
"defaultPrefix", "defaultPrefix",
HsOfficeDebitorPatchResource::setDefaultPrefix, HsOfficeDebitorPatchResource::setDefaultPrefix,

View File

@ -85,6 +85,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
.partner(givenPartner) .partner(givenPartner)
.billingContact(givenContact) .billingContact(givenContact)
.defaultPrefix("abc") .defaultPrefix("abc")
.billable(false)
.build(); .build();
return debitorRepo.save(newDebitor); return debitorRepo.save(newDebitor);
}); });
@ -96,33 +97,6 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
assertThat(debitorRepo.count()).isEqualTo(count + 1); assertThat(debitorRepo.count()).isEqualTo(count + 1);
} }
// @ParameterizedTest
// @ValueSource(strings = {"", "a", "ab", "a12", "123", "12a"})
// public void canNotCreateNewDebitorWithInvalidDefaultPrefix(final String givenPrefix) {
// // given
// context("superuser-alex@hostsharing.net");
// final var count = debitorRepo.count();
// final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("First GmbH").get(0);
// final var givenContact = contactRepo.findContactByOptionalLabelLike("first contact").get(0);
//
// // when
// final var result = attempt(em, () -> {
// final var newDebitor = HsOfficeDebitorEntity.builder()
// .debitorNumberSuffix((byte)21)
// .partner(givenPartner)
// .billingContact(givenContact)
// .defaultPrefix(givenPrefix)
// .build();
// return debitorRepo.save(newDebitor);
// });
//
// // then
// result.assertSuccessful();
// assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeDebitorEntity::getUuid).isNotNull();
// assertThatDebitorIsPersisted(result.returnedValue());
// assertThat(debitorRepo.count()).isEqualTo(count + 1);
// }
@Test @Test
public void createsAndGrantsRoles() { public void createsAndGrantsRoles() {
// given // given
@ -131,7 +105,6 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll()).stream() final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll()).stream()
// some search+replace to make the output fit into the screen width // some search+replace to make the output fit into the screen width
.map(s -> s.replace("superuser-alex@hostsharing.net", "superuser-alex")) .map(s -> s.replace("superuser-alex@hostsharing.net", "superuser-alex"))
// .map(s -> s.replace("1000422Fourthe.G.-forthcontact", "FeG"))
.map(s -> s.replace("22Fourthe.G.-forthcontact", "FeG")) .map(s -> s.replace("22Fourthe.G.-forthcontact", "FeG"))
.map(s -> s.replace("Fourthe.G.-forthcontact", "FeG")) .map(s -> s.replace("Fourthe.G.-forthcontact", "FeG"))
.map(s -> s.replace("forthcontact", "4th")) .map(s -> s.replace("forthcontact", "4th"))
@ -147,6 +120,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
.partner(givenPartner) .partner(givenPartner)
.billingContact(givenContact) .billingContact(givenContact)
.defaultPrefix("abc") .defaultPrefix("abc")
.billable(false)
.build(); .build();
return debitorRepo.save(newDebitor); return debitorRepo.save(newDebitor);
}).assertSuccessful(); }).assertSuccessful();
@ -161,7 +135,6 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
"hs_office_debitor#1000422:Fourthe.G.-forthcontact.guest")); "hs_office_debitor#1000422:Fourthe.G.-forthcontact.guest"));
assertThat(grantDisplaysOf(rawGrantRepo.findAll())) assertThat(grantDisplaysOf(rawGrantRepo.findAll()))
.map(s -> s.replace("superuser-alex@hostsharing.net", "superuser-alex")) .map(s -> s.replace("superuser-alex@hostsharing.net", "superuser-alex"))
// .map(s -> s.replace("1000422Fourthe.G.-forthcontact", "FeG"))
.map(s -> s.replace("22Fourthe.G.-forthcontact", "FeG")) .map(s -> s.replace("22Fourthe.G.-forthcontact", "FeG"))
.map(s -> s.replace("Fourthe.G.-forthcontact", "FeG")) .map(s -> s.replace("Fourthe.G.-forthcontact", "FeG"))
.map(s -> s.replace("forthcontact", "4th")) .map(s -> s.replace("forthcontact", "4th"))
@ -584,6 +557,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTest {
.billingContact(givenContact) .billingContact(givenContact)
.refundBankAccount(givenBankAccount) .refundBankAccount(givenBankAccount)
.defaultPrefix(defaultPrefix) .defaultPrefix(defaultPrefix)
.billable(true)
.build(); .build();
return debitorRepo.save(newDebitor); return debitorRepo.save(newDebitor);