From 64461fc4dae56b3e52a5120c5fca1952f6fd5ca2 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 28 Oct 2022 13:44:48 +0200 Subject: [PATCH] SEPA-Mandate signed date and patcher --- .../membership/HsOfficeMembershipEntity.java | 15 ++- .../HsOfficeSepaMandateController.java | 18 ++-- .../HsOfficeSepaMandateEntity.java | 24 ++++- .../HsOfficeSepaMandateEntityPatcher.java | 26 +++++ .../hsadminng/mapper/PostgresDateRange.java | 27 +++-- .../hs-office/api-mappings.yaml | 2 +- .../hs-office-sepamandate-schemas.yaml | 20 ++++ .../changelog/250-hs-office-sepamandate.sql | 1 + .../253-hs-office-sepamandate-rbac.sql | 1 + .../258-hs-office-sepamandate-test-data.sql | 4 +- .../HsOfficeMembershipEntityUnitTest.java | 13 ++- ...ceSepaMandateControllerAcceptanceTest.java | 6 +- ...fficeSepaMandateEntityPatcherUnitTest.java | 98 +++++++++++++++++++ .../HsOfficeSepaMandateEntityUnitTest.java | 21 +++- ...eSepaMandateRepositoryIntegrationTest.java | 19 ++-- 15 files changed, 261 insertions(+), 34 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcher.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java index d887e358..7bcdc86a 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java @@ -18,7 +18,7 @@ import javax.persistence.*; import java.time.LocalDate; import java.util.UUID; -import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange; +import static net.hostsharing.hsadminng.mapper.PostgresDateRange.*; import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @Entity @@ -73,13 +73,22 @@ public class HsOfficeMembershipEntity implements Stringifyable { private HsOfficeReasonForTermination reasonForTermination; public void setValidFrom(final LocalDate validFrom) { - validity = toPostgresDateRange(validFrom, getValidity().upper()); + setValidity(toPostgresDateRange(validFrom, getValidTo())); } public void setValidTo(final LocalDate validTo) { - validity = toPostgresDateRange(getValidity().lower(), validTo); + setValidity(toPostgresDateRange(getValidFrom(), validTo)); } + public LocalDate getValidFrom() { + return lowerInclusiveFromPostgresDateRange(getValidity()); + } + + public LocalDate getValidTo() { + return upperInclusiveFromPostgresDateRange(getValidity()); + } + + public Range getValidity() { if (validity == null) { validity = Range.infinite(LocalDate.class); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java index 60983c1b..2b8ad073 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java @@ -1,5 +1,7 @@ package net.hostsharing.hsadminng.hs.office.sepamandate; +import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntityPatcher; +import net.hostsharing.hsadminng.mapper.Mapper; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeSepaMandatesApi; import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeSepaMandateInsertResource; @@ -32,7 +34,7 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { private Mapper mapper; @Autowired - private HsOfficeSepaMandateRepository SepaMandateRepo; + private HsOfficeSepaMandateRepository sepaMandateRepo; @PersistenceContext private EntityManager em; @@ -45,7 +47,7 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { final String iban) { context.define(currentUser, assumedRoles); - final var entities = SepaMandateRepo.findSepaMandateByOptionalIban(iban); + final var entities = sepaMandateRepo.findSepaMandateByOptionalIban(iban); final var resources = mapper.mapList(entities, HsOfficeSepaMandateResource.class, SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER); @@ -63,7 +65,7 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { final var entityToSave = mapper.map(body, HsOfficeSepaMandateEntity.class, SEPA_MANDATE_RESOURCE_TO_ENTITY_POSTMAPPER); - final var saved = SepaMandateRepo.save(entityToSave); + final var saved = sepaMandateRepo.save(entityToSave); final var uri = MvcUriComponentsBuilder.fromController(getClass()) @@ -84,7 +86,7 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { context.define(currentUser, assumedRoles); - final var result = SepaMandateRepo.findByUuid(sepaMandateUuid); + final var result = sepaMandateRepo.findByUuid(sepaMandateUuid); if (result.isEmpty()) { return ResponseEntity.notFound().build(); } @@ -100,7 +102,7 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { final UUID sepaMandateUuid) { context.define(currentUser, assumedRoles); - final var result = SepaMandateRepo.deleteByUuid(sepaMandateUuid); + final var result = sepaMandateRepo.deleteByUuid(sepaMandateUuid); if (result == 0) { return ResponseEntity.notFound().build(); } @@ -118,11 +120,11 @@ public class HsOfficeSepaMandateController implements HsOfficeSepaMandatesApi { context.define(currentUser, assumedRoles); - final var current = SepaMandateRepo.findByUuid(sepaMandateUuid).orElseThrow(); + final var current = sepaMandateRepo.findByUuid(sepaMandateUuid).orElseThrow(); - current.setValidity(toPostgresDateRange(current.getValidity().lower(), body.getValidTo())); + new HsOfficeSepaMandateEntityPatcher(current).apply(body); - final var saved = SepaMandateRepo.save(current); + final var saved = sepaMandateRepo.save(current); final var mapped = mapper.map(saved, HsOfficeSepaMandateResource.class, SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER); return ResponseEntity.ok(mapped); } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java index a4120d8e..a07770a5 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java @@ -14,6 +14,7 @@ import javax.persistence.*; import java.time.LocalDate; import java.util.UUID; +import static net.hostsharing.hsadminng.mapper.PostgresDateRange.*; import static net.hostsharing.hsadminng.stringify.Stringify.stringify; @Entity @@ -33,6 +34,7 @@ public class HsOfficeSepaMandateEntity implements Stringifyable { private static Stringify stringify = stringify(HsOfficeSepaMandateEntity.class) .withProp(e -> e.getBankAccount().getIban()) .withProp(HsOfficeSepaMandateEntity::getReference) + .withProp(HsOfficeSepaMandateEntity::getAgreement) .withProp(e -> e.getValidity().asString()) .withSeparator(", ") .quotedValues(false); @@ -51,8 +53,27 @@ public class HsOfficeSepaMandateEntity implements Stringifyable { private @Column(name = "reference") String reference; + @Column(name="agreement", columnDefinition = "date") + private LocalDate agreement; + @Column(name = "validity", columnDefinition = "daterange") - private Range validity; + private Range validity = Range.infinite(LocalDate.class); + + public void setValidFrom(final LocalDate validFrom) { + setValidity(toPostgresDateRange(validFrom, getValidTo())); + } + + public void setValidTo(final LocalDate validTo) { + setValidity(toPostgresDateRange(getValidFrom(), validTo)); + } + + public LocalDate getValidFrom() { + return lowerInclusiveFromPostgresDateRange(getValidity()); + } + + public LocalDate getValidTo() { + return upperInclusiveFromPostgresDateRange(getValidity()); + } @Override public String toString() { @@ -63,4 +84,5 @@ public class HsOfficeSepaMandateEntity implements Stringifyable { public String toShortString() { return reference; } + } diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcher.java b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcher.java new file mode 100644 index 00000000..4d71577c --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcher.java @@ -0,0 +1,26 @@ +package net.hostsharing.hsadminng.hs.office.sepamandate; + +import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeSepaMandatePatchResource; +import net.hostsharing.hsadminng.mapper.EntityPatcher; +import net.hostsharing.hsadminng.mapper.OptionalFromJson; + +public class HsOfficeSepaMandateEntityPatcher implements EntityPatcher { + + private final HsOfficeSepaMandateEntity entity; + + public HsOfficeSepaMandateEntityPatcher(final HsOfficeSepaMandateEntity entity) { + this.entity = entity; + } + + @Override + public void apply(final HsOfficeSepaMandatePatchResource resource) { + OptionalFromJson.of(resource.getReference()).ifPresent( + entity::setReference); + OptionalFromJson.of(resource.getAgreement()).ifPresent( + entity::setAgreement); + OptionalFromJson.of(resource.getValidFrom()).ifPresent( + entity::setValidFrom); + OptionalFromJson.of(resource.getValidTo()).ifPresent( + entity::setValidTo); + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java b/src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java index fd70ed04..c360db1a 100644 --- a/src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java +++ b/src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java @@ -9,14 +9,25 @@ import java.time.LocalDate; public class PostgresDateRange { public static Range toPostgresDateRange( - final LocalDate validFrom, - final LocalDate validTo) { - return validFrom != null - ? validTo != null - ? Range.closedOpen(validFrom, validTo.plusDays(1)) - : Range.closedInfinite(validFrom) - : validTo != null - ? Range.infiniteOpen(validTo.plusDays(1)) + final LocalDate lowerInclusive, + final LocalDate upperInclusive) { + return lowerInclusive != null + ? upperInclusive != null + ? Range.closedOpen(lowerInclusive, upperInclusive.plusDays(1)) + : Range.closedInfinite(lowerInclusive) + : upperInclusive != null + ? Range.infiniteOpen(upperInclusive.plusDays(1)) : Range.infinite(LocalDate.class); } + + public static LocalDate lowerInclusiveFromPostgresDateRange( + final Range range) { + return range.lower(); + } + + public static LocalDate upperInclusiveFromPostgresDateRange( + final Range range) { + return range.upper() != null ? range.upper().minusDays(1) : null; + } + } diff --git a/src/main/resources/api-definition/hs-office/api-mappings.yaml b/src/main/resources/api-definition/hs-office/api-mappings.yaml index 8f6f076e..11778eb0 100644 --- a/src/main/resources/api-definition/hs-office/api-mappings.yaml +++ b/src/main/resources/api-definition/hs-office/api-mappings.yaml @@ -29,7 +29,7 @@ map: null: org.openapitools.jackson.nullable.JsonNullable /api/hs/office/debitors/{debitorUUID}: null: org.openapitools.jackson.nullable.JsonNullable - /api/hs/office/sepamandates/{debitorUUID}: + /api/hs/office/sepamandates/{sepaMandateUUID}: null: org.openapitools.jackson.nullable.JsonNullable /api/hs/office/memberships/{membershipUUID}: null: org.openapitools.jackson.nullable.JsonNullable diff --git a/src/main/resources/api-definition/hs-office/hs-office-sepamandate-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-sepamandate-schemas.yaml index e4189a0f..dd2af7fd 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-sepamandate-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-sepamandate-schemas.yaml @@ -15,6 +15,9 @@ components: $ref: './hs-office-bankaccount-schemas.yaml#/components/schemas/HsOfficeBankAccount' reference: type: string + agreement: + type: string + format: date validFrom: type: string format: date @@ -25,9 +28,21 @@ components: HsOfficeSepaMandatePatch: type: object properties: + reference: + type: string + nullable: true + agreement: + type: string + format: date + nullable: true + validFrom: + type: string + format: date + nullable: true validTo: type: string format: date + nullable: true additionalProperties: false HsOfficeSepaMandateInsert: @@ -44,6 +59,10 @@ components: reference: type: string nullable: false + agreement: + type: string + format: date + nullable: false validFrom: type: string format: date @@ -56,5 +75,6 @@ components: - debitorUuid - bankAccountUuid - reference + - agreement - validFrom additionalProperties: false diff --git a/src/main/resources/db/changelog/250-hs-office-sepamandate.sql b/src/main/resources/db/changelog/250-hs-office-sepamandate.sql index b87b872e..fa60716f 100644 --- a/src/main/resources/db/changelog/250-hs-office-sepamandate.sql +++ b/src/main/resources/db/changelog/250-hs-office-sepamandate.sql @@ -10,6 +10,7 @@ create table if not exists hs_office_sepamandate debitorUuid uuid not null references hs_office_debitor(uuid), bankAccountUuid uuid not null references hs_office_bankaccount(uuid), reference varchar(96) not null, + agreement date not null, validity daterange not null ); --// diff --git a/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql b/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql index 85569e6e..f63bf649 100644 --- a/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql +++ b/src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql @@ -102,6 +102,7 @@ call generateRbacIdentityView('hs_office_sepamandate', idNameExpression => 'targ call generateRbacRestrictedView('hs_office_sepamandate', orderby => 'target.reference', columnUpdates => $updates$ + agreement = new.agreement, validity = new.validity $updates$); --// diff --git a/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql b/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql index d96bfcb5..eb96d1a0 100644 --- a/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql +++ b/src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql @@ -31,8 +31,8 @@ begin raise notice '- using debitor (%): %', relatedDebitor.uuid, relatedDebitor; raise notice '- using bankAccount (%): %', relatedBankAccount.uuid, relatedBankAccount; insert - into hs_office_sepamandate (uuid, debitoruuid, bankAccountuuid, reference, validity) - values (uuid_generate_v4(), relatedDebitor.uuid, relatedBankAccount.uuid, 'ref'||idName, daterange('20221001' , '20261231', '[]')); + into hs_office_sepamandate (uuid, debitoruuid, bankAccountuuid, reference, agreement, validity) + values (uuid_generate_v4(), relatedDebitor.uuid, relatedBankAccount.uuid, 'ref'||idName, '20220930', daterange('20221001' , '20261231', '[]')); end; $$; --// diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java index 2c07d140..8bc26cf4 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java @@ -15,6 +15,7 @@ import static org.assertj.core.api.Assertions.assertThat; class HsOfficeMembershipEntityUnitTest { public static final LocalDate GIVEN_VALID_FROM = LocalDate.parse("2020-01-01"); + final HsOfficeMembershipEntity givenMembership = HsOfficeMembershipEntity.builder() .memberNumber(10001) .partner(TEST_PARTNER) @@ -53,10 +54,20 @@ class HsOfficeMembershipEntityUnitTest { assertThat(givenMembership.getReasonForTermination()).isEqualTo(HsOfficeReasonForTermination.CANCELLATION); } + @Test + void settingValidFromKeepsValidTo() { + givenMembership.setValidFrom(LocalDate.parse("2020-01-01")); + assertThat(givenMembership.getValidFrom()).isEqualTo(LocalDate.parse("2020-01-01")); + assertThat(givenMembership.getValidTo()).isNull(); + + } + @Test void settingValidToKeepsValidFrom() { givenMembership.setValidTo(LocalDate.parse("2024-12-31")); - assertThat(givenMembership.getValidity().lower()).isEqualTo(GIVEN_VALID_FROM); + assertThat(givenMembership.getValidFrom()).isEqualTo(GIVEN_VALID_FROM); + assertThat(givenMembership.getValidTo()).isEqualTo(LocalDate.parse("2024-12-31")); + } private static void invokePrePersist(final HsOfficeMembershipEntity membershipEntity) diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java index 343325ae..100a411e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java @@ -134,6 +134,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest { "debitorUuid": "%s", "bankAccountUuid": "%s", "reference": "temp ref CAT A", + "agreement": "2020-01-02", "validFrom": "2022-10-13" } """.formatted(givenDebitor.getUuid(), givenBankAccount.getUuid())) @@ -200,6 +201,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest { "debitorUuid": "%s", "bankAccountUuid": "%s", "reference": "temp ref CAT C", + "agreement": "2022-10-12", "validFrom": "2022-10-13", "validTo": "2024-12-31" } @@ -229,6 +231,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest { "debitorUuid": "%s", "bankAccountUuid": "%s", "reference": "temp refCAT D", + "agreement": "2022-10-12", "validFrom": "2022-10-13", "validTo": "2024-12-31" } @@ -403,7 +406,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest { // finally, the sepaMandate is actually updated assertThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent().get() .matches(mandate -> { - assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,)"); + assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,2023-03-31)"); return true; }); } @@ -480,6 +483,7 @@ class HsOfficeSepaMandateControllerAcceptanceTest { .debitor(givenDebitor) .bankAccount(givenBankAccount) .reference("temp ref CAT Z") + .agreement(LocalDate.parse("2022-10-31")) .validity(Range.closedOpen( LocalDate.parse("2022-11-01"), LocalDate.parse("2023-03-31"))) .build(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java new file mode 100644 index 00000000..7b025ecc --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java @@ -0,0 +1,98 @@ +package net.hostsharing.hsadminng.hs.office.sepamandate; + +import com.vladmihalcea.hibernate.type.range.Range; +import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity; +import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeSepaMandatePatchResource; +import net.hostsharing.test.PatchUnitTestBase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import javax.persistence.EntityManager; +import java.time.LocalDate; +import java.util.UUID; +import java.util.stream.Stream; + +import static net.hostsharing.hsadminng.hs.office.bankaccount.TestHsOfficeBankAccount.TEST_BANK_ACCOUNT; +import static net.hostsharing.hsadminng.hs.office.debitor.TestHsOfficeDebitor.TEST_DEBITOR; +import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; + +@TestInstance(PER_CLASS) +@ExtendWith(MockitoExtension.class) +class HsOfficeSepaMandateEntityPatcherUnitTest extends PatchUnitTestBase< + HsOfficeSepaMandatePatchResource, + HsOfficeSepaMandateEntity + > { + + private static final UUID INITIAL_SepaMandate_UUID = UUID.randomUUID(); + private static final LocalDate GIVEN_VALID_FROM = LocalDate.parse("2020-04-15"); + private static final LocalDate PATCHED_VALID_FROM = LocalDate.parse("2022-10-30"); + private static final LocalDate PATCHED_VALID_TO = LocalDate.parse("2022-12-31"); + private static final LocalDate PATCHED_AGREEMENT = LocalDate.parse("2022-11-01"); + private static final String PATCHED_REFERENCE = "ref sepamandate-patched"; + + @Mock + private EntityManager em; + + @BeforeEach + void initMocks() { + lenient().when(em.getReference(eq(HsOfficeDebitorEntity.class), any())).thenAnswer(invocation -> + HsOfficeDebitorEntity.builder().uuid(invocation.getArgument(1)).build()); + lenient().when(em.getReference(eq(HsOfficeSepaMandateEntity.class), any())).thenAnswer(invocation -> + HsOfficeSepaMandateEntity.builder().uuid(invocation.getArgument(1)).build()); + } + + @Override + protected HsOfficeSepaMandateEntity newInitialEntity() { + final var entity = new HsOfficeSepaMandateEntity(); + entity.setUuid(INITIAL_SepaMandate_UUID); + entity.setDebitor(TEST_DEBITOR); + entity.setBankAccount(TEST_BANK_ACCOUNT); + entity.setReference("ref sepamandate"); + entity.setAgreement(LocalDate.parse("2022-10-28")); + entity.setValidity(Range.closedInfinite(GIVEN_VALID_FROM)); + return entity; + } + + @Override + protected HsOfficeSepaMandatePatchResource newPatchResource() { + return new HsOfficeSepaMandatePatchResource(); + } + + @Override + protected HsOfficeSepaMandateEntityPatcher createPatcher(final HsOfficeSepaMandateEntity sepaMandate) { + return new HsOfficeSepaMandateEntityPatcher(sepaMandate); + } + + @Override + protected Stream propertyTestDescriptors() { + return Stream.of( + new JsonNullableProperty<>( + "reference", + HsOfficeSepaMandatePatchResource::setReference, + PATCHED_REFERENCE, + HsOfficeSepaMandateEntity::setReference), + + new JsonNullableProperty<>( + "agreement", + HsOfficeSepaMandatePatchResource::setAgreement, + PATCHED_AGREEMENT, + HsOfficeSepaMandateEntity::setAgreement), + new JsonNullableProperty<>( + "validfrom", + HsOfficeSepaMandatePatchResource::setValidFrom, + PATCHED_VALID_FROM, + HsOfficeSepaMandateEntity::setValidFrom), + new JsonNullableProperty<>( + "validto", + HsOfficeSepaMandatePatchResource::setValidTo, + PATCHED_VALID_TO, + HsOfficeSepaMandateEntity::setValidTo) + ); + } +} diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityUnitTest.java index 02dee978..7ba77e0e 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityUnitTest.java @@ -7,14 +7,17 @@ import org.junit.jupiter.api.Test; import java.time.LocalDate; import static net.hostsharing.hsadminng.hs.office.debitor.TestHsOfficeDebitor.TEST_DEBITOR; +import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange; import static org.assertj.core.api.Assertions.assertThat; class HsOfficeSepaMandateEntityUnitTest { + public static final LocalDate GIVEN_VALID_FROM = LocalDate.parse("2020-01-01"); + public static final LocalDate GIVEN_VALID_TO = LocalDate.parse("2030-12-31"); final HsOfficeSepaMandateEntity givenSepaMandate = HsOfficeSepaMandateEntity.builder() .debitor(TEST_DEBITOR) .reference("some-ref") - .validity(Range.closedOpen(LocalDate.parse("2020-01-01"), LocalDate.parse("2031-01-01"))) + .validity(toPostgresDateRange(GIVEN_VALID_FROM, GIVEN_VALID_TO)) .bankAccount(HsOfficeBankAccountEntity.builder().iban("some label").build()) .build(); @@ -31,4 +34,20 @@ class HsOfficeSepaMandateEntityUnitTest { assertThat(result).isEqualTo("some-ref"); } + + @Test + void settingValidFromKeepsValidTo() { + givenSepaMandate.setValidFrom(LocalDate.parse("2023-12-31")); + assertThat(givenSepaMandate.getValidFrom()).isEqualTo(LocalDate.parse("2023-12-31")); + assertThat(givenSepaMandate.getValidTo()).isEqualTo(GIVEN_VALID_TO); + + } + + @Test + void settingValidToKeepsValidFrom() { + givenSepaMandate.setValidTo(LocalDate.parse("2024-12-31")); + assertThat(givenSepaMandate.getValidFrom()).isEqualTo(GIVEN_VALID_FROM); + assertThat(givenSepaMandate.getValidTo()).isEqualTo(LocalDate.parse("2024-12-31")); + } + } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java index 818c7bc4..98d5ecb7 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java @@ -78,6 +78,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest { .debitor(givenDebitor) .bankAccount(givenBankAccount) .reference("temp ref A") + .agreement(LocalDate.parse( "2020-01-02")) .validity(Range.closedOpen( LocalDate.parse("2020-01-01"), LocalDate.parse("2023-01-01"))) .build(); @@ -110,6 +111,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest { .debitor(givenDebitor) .bankAccount(givenBankAccount) .reference("temp ref B") + .agreement(LocalDate.parse("2020-01-02")) .validity(Range.closedOpen( LocalDate.parse("2020-01-01"), LocalDate.parse("2023-01-01"))) .build(); @@ -178,9 +180,9 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest { // then allTheseSepaMandatesAreReturned( result, - "SEPA-Mandate(DE02120300000000202051, refFirstGmbH, [2022-10-01,2027-01-01))", - "SEPA-Mandate(DE02100500000054540402, refSeconde.K., [2022-10-01,2027-01-01))", - "SEPA-Mandate(DE02300209000106531065, refThirdOHG, [2022-10-01,2027-01-01))"); + "SEPA-Mandate(DE02120300000000202051, refFirstGmbH, 2022-09-30, [2022-10-01,2027-01-01))", + "SEPA-Mandate(DE02100500000054540402, refSeconde.K., 2022-09-30, [2022-10-01,2027-01-01))", + "SEPA-Mandate(DE02300209000106531065, refThirdOHG, 2022-09-30, [2022-10-01,2027-01-01))"); } @Test @@ -194,7 +196,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest { // then: exactlyTheseSepaMandatesAreReturned( result, - "SEPA-Mandate(DE02120300000000202051, refFirstGmbH, [2022-10-01,2027-01-01))"); + "SEPA-Mandate(DE02120300000000202051, refFirstGmbH, 2022-09-30, [2022-10-01,2027-01-01))"); } } @@ -212,9 +214,9 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest { // then exactlyTheseSepaMandatesAreReturned( result, - "SEPA-Mandate(DE02120300000000202051, refFirstGmbH, [2022-10-01,2027-01-01))", - "SEPA-Mandate(DE02100500000054540402, refSeconde.K., [2022-10-01,2027-01-01))", - "SEPA-Mandate(DE02300209000106531065, refThirdOHG, [2022-10-01,2027-01-01))"); + "SEPA-Mandate(DE02120300000000202051, refFirstGmbH, 2022-09-30, [2022-10-01,2027-01-01))", + "SEPA-Mandate(DE02100500000054540402, refSeconde.K., 2022-09-30, [2022-10-01,2027-01-01))", + "SEPA-Mandate(DE02300209000106531065, refThirdOHG, 2022-09-30, [2022-10-01,2027-01-01))"); } @Test @@ -228,7 +230,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest { // then exactlyTheseSepaMandatesAreReturned( result, - "SEPA-Mandate(DE02300209000106531065, refThirdOHG, [2022-10-01,2027-01-01))"); + "SEPA-Mandate(DE02300209000106531065, refThirdOHG, 2022-09-30, [2022-10-01,2027-01-01))"); } } @@ -420,6 +422,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest { .debitor(givenDebitor) .bankAccount(givenBankAccount) .reference("temp ref X") + .agreement(LocalDate.parse( "2020-01-02")) .validity(Range.closedOpen( LocalDate.parse("2020-01-01"), LocalDate.parse("2023-01-01"))) .build();