Michael Hoennig
2022-10-28 64461fc4dae56b3e52a5120c5fca1952f6fd5ca2
SEPA-Mandate signed date and patcher
2 files added
13 files modified
295 ■■■■ changed files
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java 15 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java 18 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcher.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java 27 ●●●● patch | view | raw | blame | history
src/main/resources/api-definition/hs-office/api-mappings.yaml 2 ●●● patch | view | raw | blame | history
src/main/resources/api-definition/hs-office/hs-office-sepamandate-schemas.yaml 20 ●●●●● patch | view | raw | blame | history
src/main/resources/db/changelog/250-hs-office-sepamandate.sql 1 ●●●● patch | view | raw | blame | history
src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql 1 ●●●● patch | view | raw | blame | history
src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java 13 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java 6 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java 98 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityUnitTest.java 21 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java
@@ -18,7 +18,7 @@
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 @@
    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<LocalDate> getValidity() {
        if (validity == null) {
            validity = Range.infinite(LocalDate.class);
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 @@
    private Mapper mapper;
    @Autowired
    private HsOfficeSepaMandateRepository SepaMandateRepo;
    private HsOfficeSepaMandateRepository sepaMandateRepo;
    @PersistenceContext
    private EntityManager em;
@@ -45,7 +47,7 @@
            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 @@
        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 @@
        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 @@
            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 @@
        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);
    }
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java
@@ -14,6 +14,7 @@
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 @@
    private static Stringify<HsOfficeSepaMandateEntity> 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 @@
    private @Column(name = "reference") String reference;
    @Column(name="agreement", columnDefinition = "date")
    private LocalDate agreement;
    @Column(name = "validity", columnDefinition = "daterange")
    private Range<LocalDate> validity;
    private Range<LocalDate> 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 String toShortString() {
        return reference;
    }
}
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcher.java
New file
@@ -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<HsOfficeSepaMandatePatchResource> {
    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);
    }
}
src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java
@@ -9,14 +9,25 @@
public class PostgresDateRange {
    public static Range<LocalDate> 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<LocalDate> range) {
        return range.lower();
    }
    public static LocalDate upperInclusiveFromPostgresDateRange(
        final Range<LocalDate> range) {
        return range.upper() != null ? range.upper().minusDays(1) : null;
    }
}
src/main/resources/api-definition/hs-office/api-mappings.yaml
@@ -29,7 +29,7 @@
            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
src/main/resources/api-definition/hs-office/hs-office-sepamandate-schemas.yaml
@@ -15,6 +15,9 @@
                    $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 @@
        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 @@
                reference:
                    type: string
                    nullable: false
                agreement:
                    type: string
                    format: date
                    nullable: false
                validFrom:
                    type: string
                    format: date
@@ -56,5 +75,6 @@
                - debitorUuid
                - bankAccountUuid
                - reference
                - agreement
                - validFrom
            additionalProperties: false
src/main/resources/db/changelog/250-hs-office-sepamandate.sql
@@ -10,6 +10,7 @@
    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
);
--//
src/main/resources/db/changelog/253-hs-office-sepamandate-rbac.sql
@@ -102,6 +102,7 @@
call generateRbacRestrictedView('hs_office_sepamandate',
    orderby => 'target.reference',
    columnUpdates => $updates$
        agreement = new.agreement,
        validity = new.validity
    $updates$);
--//
src/main/resources/db/changelog/258-hs-office-sepamandate-test-data.sql
@@ -31,8 +31,8 @@
    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; $$;
--//
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java
@@ -15,6 +15,7 @@
class HsOfficeMembershipEntityUnitTest {
    public static final LocalDate GIVEN_VALID_FROM = LocalDate.parse("2020-01-01");
    final HsOfficeMembershipEntity givenMembership = HsOfficeMembershipEntity.builder()
            .memberNumber(10001)
            .partner(TEST_PARTNER)
@@ -54,9 +55,19 @@
    }
    @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)
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateControllerAcceptanceTest.java
@@ -134,6 +134,7 @@
                                   "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 @@
                                   "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 @@
                                   "debitorUuid": "%s",
                                   "bankAccountUuid": "%s",
                                   "reference": "temp refCAT D",
                                   "agreement": "2022-10-12",
                                   "validFrom": "2022-10-13",
                                   "validTo": "2024-12-31"
                                 }
@@ -403,7 +406,7 @@
            // 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 @@
                    .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();
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityPatcherUnitTest.java
New file
@@ -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<Property> 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)
        );
    }
}
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityUnitTest.java
@@ -7,14 +7,17 @@
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 @@
        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"));
    }
}
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateRepositoryIntegrationTest.java
@@ -78,6 +78,7 @@
                        .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 @@
                        .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 @@
            // 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 @@
            // 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 @@
            // 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 @@
            // 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 @@
                    .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();