Michael Hoennig
2022-10-22 b3b70aaaf4d27b9d61e1ab247ccda1a336b1223b
add HsOfficeMembershipEntityPatcher
3 files added
15 files modified
290 ■■■■ changed files
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipController.java 38 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcher.java 45 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntityPatcher.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java 9 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java 18 ●●●●● patch | view | raw | blame | history
src/main/resources/api-definition/hs-office/hs-office-membership-schemas.yaml 6 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/TestHsOfficeBankAccount.java 2 ●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/contact/TestHsOfficeContact.java 2 ●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntityTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntityTest.java 4 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java 10 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java 10 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java 106 ●●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java 17 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java 6 ●●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/partner/TestHsOfficePartner.java 2 ●●● patch | view | raw | blame | history
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityTest.java 4 ●●●● patch | view | raw | blame | history
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipController.java
@@ -1,12 +1,12 @@
package net.hostsharing.hsadminng.hs.office.membership;
import com.vladmihalcea.hibernate.type.range.Range;
import net.hostsharing.hsadminng.mapper.Mapper;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeMembershipsApi;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipInsertResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipResource;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
@@ -15,13 +15,13 @@
import javax.persistence.EntityManager;
import javax.validation.Valid;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.Mapper.mapList;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
@RestController
@@ -48,7 +48,7 @@
        final var entities =
                membershipRepo.findMembershipsByOptionalPartnerUuidAndOptionalMemberNumber(partnerUuid, memberNumber);
        final var resources = Mapper.mapList(entities, HsOfficeMembershipResource.class,
        final var resources = mapList(entities, HsOfficeMembershipResource.class,
                SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.ok(resources);
    }
@@ -62,7 +62,7 @@
        context.define(currentUser, assumedRoles);
        final var entityToSave = map(body, HsOfficeMembershipEntity.class, SEPA_MANDATE_RESOURCE_TO_ENTITY_POSTMAPPER);
        final var entityToSave = mapX(body, HsOfficeMembershipEntity.class);
        entityToSave.setUuid(UUID.randomUUID());
        final var saved = membershipRepo.save(entityToSave);
@@ -122,23 +122,11 @@
        final var current = membershipRepo.findByUuid(membershipUuid).orElseThrow();
        current.setValidity(toPostgresDateRange(current.getValidity().lower(), body.getValidTo()));
//        current.setReasonForTermination(HsOfficeReasonForTermination.valueOf(body.getReasonForTermination().name()));
        current.setReasonForTermination(
                Optional.ofNullable(body.getReasonForTermination()).map(Enum::name).map(HsOfficeReasonForTermination::valueOf).orElse(current.getReasonForTermination())
        );
        new HsOfficeMembershipEntityPatcher(em, current).apply(body);
        final var saved = membershipRepo.save(current);
        final var mapped = map(saved, HsOfficeMembershipResource.class, SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.ok(mapped);
    }
    private static Range<LocalDate> toPostgresDateRange(
            final LocalDate validFrom,
            final LocalDate validTo) {
        return validTo != null
                ? Range.closedOpen(validFrom, validTo.plusDays(1))
                : Range.closedInfinite(validFrom);
    }
    final BiConsumer<HsOfficeMembershipEntity, HsOfficeMembershipResource> SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
@@ -148,7 +136,15 @@
        }
    };
    final BiConsumer<HsOfficeMembershipInsertResource, HsOfficeMembershipEntity> SEPA_MANDATE_RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
    private HsOfficeMembershipEntity mapX(
            final HsOfficeMembershipInsertResource resource,
            final Class<HsOfficeMembershipEntity> entityClass) {
        final var entity = new HsOfficeMembershipEntity();
        entity.setPartner(em.getReference(HsOfficePartnerEntity.class, resource.getPartnerUuid()));
        entity.setMainDebitor(em.getReference(HsOfficeDebitorEntity.class, resource.getMainDebitorUuid()));
        entity.setMemberNumber(resource.getMemberNumber());
        entity.setValidity(toPostgresDateRange(resource.getValidFrom(), resource.getValidTo()));
    };
        entity.setReasonForTermination(map(resource.getReasonForTermination(), HsOfficeReasonForTermination.class));
        return entity;
    }
}
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java
@@ -18,6 +18,7 @@
import java.time.LocalDate;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
@Entity
@@ -69,6 +70,10 @@
    @Type(type = "pgsql_enum")
    private HsOfficeReasonForTermination reasonForTermination;
    public void setValidTo(final LocalDate validTo) {
        validity = toPostgresDateRange(getValidity().lower(), validTo);
    }
    @Override
    public String toString() {
        return stringify.apply(this);
src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcher.java
New file
@@ -0,0 +1,45 @@
package net.hostsharing.hsadminng.hs.office.membership;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource;
import net.hostsharing.hsadminng.mapper.EntityPatcher;
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
import javax.persistence.EntityManager;
import java.util.Optional;
import java.util.UUID;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
public class HsOfficeMembershipEntityPatcher implements EntityPatcher<HsOfficeMembershipPatchResource> {
    private final EntityManager em;
    private final HsOfficeMembershipEntity entity;
    public HsOfficeMembershipEntityPatcher(
            final EntityManager em,
            final HsOfficeMembershipEntity entity) {
        this.em = em;
        this.entity = entity;
    }
    @Override
    public void apply(final HsOfficeMembershipPatchResource resource) {
        OptionalFromJson.of(resource.getMainDebitorUuid())
                .ifPresent(newValue -> {
                    verifyNotNull(newValue, "debitor");
                    entity.setMainDebitor(em.getReference(HsOfficeDebitorEntity.class, newValue));
                });
        OptionalFromJson.of(resource.getValidTo()).ifPresent(
                entity::setValidTo);
        Optional.ofNullable(resource.getReasonForTermination())
                .map(v -> map(v, HsOfficeReasonForTermination.class))
                .ifPresent(entity::setReasonForTermination);
    }
    private void verifyNotNull(final UUID newValue, final String propertyName) {
        if (newValue == null) {
            throw new IllegalArgumentException("property '" + propertyName + "' must not be null");
        }
    }
}
src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntityPatcher.java
@@ -8,13 +8,11 @@
class HsOfficePartnerDetailsEntityPatcher implements EntityPatcher<HsOfficePartnerDetailsPatchResource> {
    private final EntityManager em;
    private final HsOfficePartnerDetailsEntity entity;
    HsOfficePartnerDetailsEntityPatcher(
            final EntityManager em,
            final HsOfficePartnerDetailsEntity entity) {
        this.em = em;
        this.entity = entity;
    }
src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateController.java
@@ -21,6 +21,7 @@
import java.util.function.BiConsumer;
import static net.hostsharing.hsadminng.mapper.Mapper.map;
import static net.hostsharing.hsadminng.mapper.PostgresDateRange.toPostgresDateRange;
@RestController
@@ -124,14 +125,6 @@
        final var saved = SepaMandateRepo.save(current);
        final var mapped = map(saved, HsOfficeSepaMandateResource.class, SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER);
        return ResponseEntity.ok(mapped);
    }
    private static Range<LocalDate> toPostgresDateRange(
            final LocalDate validFrom,
            final LocalDate validTo) {
        return validTo != null
                ? Range.closedOpen(validFrom, validTo.plusDays(1))
                : Range.closedInfinite(validFrom);
    }
    final BiConsumer<HsOfficeSepaMandateEntity, HsOfficeSepaMandateResource> SEPA_MANDATE_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
src/main/java/net/hostsharing/hsadminng/mapper/PostgresDateRange.java
New file
@@ -0,0 +1,18 @@
package net.hostsharing.hsadminng.mapper;
import com.vladmihalcea.hibernate.type.range.Range;
import lombok.experimental.UtilityClass;
import java.time.LocalDate;
@UtilityClass
public class PostgresDateRange {
    public static Range<LocalDate> toPostgresDateRange(
            final LocalDate validFrom,
            final LocalDate validTo) {
        return validTo != null
                ? Range.closedOpen(validFrom, validTo.plusDays(1))
                : Range.closedInfinite(validFrom);
    }
}
src/main/resources/api-definition/hs-office/hs-office-membership-schemas.yaml
@@ -37,10 +37,16 @@
        HsOfficeMembershipPatch:
            type: object
            properties:
                mainDebitorUuid:
                    type: string
                    format: uuid
                    nullable: true
                validTo:
                    type: string
                    format: date
                    nullable: true
                reasonForTermination:
                    nullable: true
                    $ref: '#/components/schemas/HsOfficeReasonForTermination'
            additionalProperties: false
src/test/java/net/hostsharing/hsadminng/hs/office/bankaccount/TestHsOfficeBankAccount.java
@@ -4,7 +4,7 @@
public class TestHsOfficeBankAccount {
    public static final HsOfficeBankAccountEntity someBankAccount =
    public static final HsOfficeBankAccountEntity TEST_BANK_ACCOUNT =
            hsOfficeBankAccount("some bankaccount", "DE67500105173931168623", "INGDDEFFXXX");
    static public HsOfficeBankAccountEntity hsOfficeBankAccount(final String holder, final String iban, final String bic) {
src/test/java/net/hostsharing/hsadminng/hs/office/contact/TestHsOfficeContact.java
@@ -4,7 +4,7 @@
public class TestHsOfficeContact {
    public static final HsOfficeContactEntity someContact = hsOfficeContact("some contact", "some-contact@example.com");
    public static final HsOfficeContactEntity TEST_CONTACT = hsOfficeContact("some contact", "some-contact@example.com");
    static public HsOfficeContactEntity hsOfficeContact(final String label, final String emailAddr) {
        return HsOfficeContactEntity.builder()
src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntityTest.java
@@ -5,13 +5,13 @@
import java.math.BigDecimal;
import java.time.LocalDate;
import static net.hostsharing.hsadminng.hs.office.membership.TestHsMembership.testMembership;
import static net.hostsharing.hsadminng.hs.office.membership.TestHsMembership.TEST_MEMBERSHIP;
import static org.assertj.core.api.Assertions.assertThat;
class HsOfficeCoopAssetsTransactionEntityTest {
    final HsOfficeCoopAssetsTransactionEntity givenCoopAssetTransaction = HsOfficeCoopAssetsTransactionEntity.builder()
            .membership(testMembership)
            .membership(TEST_MEMBERSHIP)
            .reference("some-ref")
            .valueDate(LocalDate.parse("2020-01-01"))
            .transactionType(HsOfficeCoopAssetsTransactionType.DEPOSIT)
src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntityTest.java
@@ -4,13 +4,13 @@
import java.time.LocalDate;
import static net.hostsharing.hsadminng.hs.office.membership.TestHsMembership.testMembership;
import static net.hostsharing.hsadminng.hs.office.membership.TestHsMembership.TEST_MEMBERSHIP;
import static org.assertj.core.api.Assertions.assertThat;
class HsOfficeCoopSharesTransactionEntityTest {
    final HsOfficeCoopSharesTransactionEntity givenCoopSharesTransaction = HsOfficeCoopSharesTransactionEntity.builder()
            .membership(testMembership)
            .membership(TEST_MEMBERSHIP)
            .reference("some-ref")
            .valueDate(LocalDate.parse("2020-01-01"))
            .transactionType(HsOfficeCoopSharesTransactionType.SUBSCRIPTION)
src/test/java/net/hostsharing/hsadminng/hs/office/debitor/TestHsOfficeDebitor.java
@@ -4,16 +4,16 @@
import java.util.UUID;
import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.someContact;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.testPartner;
import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.TEST_CONTACT;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER;
@UtilityClass
public class TestHsOfficeDebitor {
    public static final HsOfficeDebitorEntity testDebitor = HsOfficeDebitorEntity.builder()
    public static final HsOfficeDebitorEntity TEST_DEBITOR = HsOfficeDebitorEntity.builder()
            .uuid(UUID.randomUUID())
            .debitorNumber(10001)
            .partner(testPartner)
            .billingContact(someContact)
            .partner(TEST_PARTNER)
            .billingContact(TEST_CONTACT)
            .build();
}
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipControllerAcceptanceTest.java
@@ -3,11 +3,11 @@
import com.vladmihalcea.hibernate.type.range.Range;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import net.hostsharing.test.Accepts;
import net.hostsharing.hsadminng.HsadminNgApplication;
import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository;
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerRepository;
import net.hostsharing.test.Accepts;
import net.hostsharing.test.JpaAttempt;
import org.json.JSONException;
import org.junit.jupiter.api.AfterEach;
@@ -300,7 +300,7 @@
            final var givenMembership = givenSomeTemporaryMembershipBessler();
            final var givenNewMainDebitor = debitorRepo.findDebitorByDebitorNumber(10003).get(0);
            final var location = RestAssured // @formatter:off
            RestAssured // @formatter:off
                .given()
                    .header("current-user", "superuser-alex@hostsharing.net")
                    .contentType(ContentType.JSON)
@@ -317,8 +317,7 @@
                    .contentType(ContentType.JSON)
                    .body("uuid", isUuidValid())
                    .body("partner.person.tradeName", is(givenMembership.getPartner().getPerson().getTradeName()))
                    // TODO.impl: implement patching the mainDebitor
                    // .body("mainDebitor.debitorNumber", is(10003))
                    .body("mainDebitor.debitorNumber", is(10003))
                    .body("memberNumber", is(givenMembership.getMemberNumber()))
                    .body("validFrom", is("2022-11-01"))
                    .body("validTo", nullValue())
@@ -329,8 +328,7 @@
            assertThat(membershipRepo.findByUuid(givenMembership.getUuid())).isPresent().get()
                    .matches(mandate -> {
                        assertThat(mandate.getPartner().toShortString()).isEqualTo("First GmbH");
                        // TODO.impl: implement patching the mainDebitor
                        // assertThat(mandate.getMainDebitor().toString()).isEqualTo(givenMembership.getMainDebitor().toString());
                        assertThat(mandate.getMainDebitor().toString()).isEqualTo(givenMembership.getMainDebitor().toString());
                        assertThat(mandate.getMemberNumber()).isEqualTo(givenMembership.getMemberNumber());
                        assertThat(mandate.getValidity().asString()).isEqualTo("[2022-11-01,)");
                        assertThat(mandate.getReasonForTermination()).isEqualTo(NONE);
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityPatcherUnitTest.java
New file
@@ -0,0 +1,106 @@
package net.hostsharing.hsadminng.hs.office.membership;
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.HsOfficeMembershipPatchResource;
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeReasonForTerminationResource;
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.debitor.TestHsOfficeDebitor.TEST_DEBITOR;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER;
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 HsOfficeMembershipEntityPatcherUnitTest extends PatchUnitTestBase<
        HsOfficeMembershipPatchResource,
        HsOfficeMembershipEntity
        > {
    private static final UUID INITIAL_MEMBERSHIP_UUID = UUID.randomUUID();
    private static final UUID INITIAL_MAIN_DEBITOR_UUID = UUID.randomUUID();
    private static final UUID PATCHED_MAIN_DEBITOR_UUID = UUID.randomUUID();
    private static final LocalDate GIVEN_VALID_FROM = LocalDate.parse("2020-04-15");
    private static final LocalDate PATCHED_VALID_TO = LocalDate.parse("2022-12-31");
    @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(HsOfficeMembershipEntity.class), any())).thenAnswer(invocation ->
                HsOfficeMembershipEntity.builder().uuid(invocation.getArgument(1)).build());
    }
    @Override
    protected HsOfficeMembershipEntity newInitialEntity() {
        final var entity = new HsOfficeMembershipEntity();
        entity.setUuid(INITIAL_MEMBERSHIP_UUID);
        entity.setMainDebitor(TEST_DEBITOR);
        entity.setPartner(TEST_PARTNER);
        entity.setValidity(Range.closedInfinite(GIVEN_VALID_FROM));
        return entity;
    }
    @Override
    protected HsOfficeMembershipPatchResource newPatchResource() {
        return new HsOfficeMembershipPatchResource();
    }
    @Override
    protected HsOfficeMembershipEntityPatcher createPatcher(final HsOfficeMembershipEntity Membership) {
        return new HsOfficeMembershipEntityPatcher(em, Membership);
    }
    @Override
    protected Stream<Property> propertyTestDescriptors() {
        return Stream.of(
                new JsonNullableProperty<>(
                        "debitor",
                        HsOfficeMembershipPatchResource::setMainDebitorUuid,
                        PATCHED_MAIN_DEBITOR_UUID,
                        HsOfficeMembershipEntity::setMainDebitor,
                        newDebitor(PATCHED_MAIN_DEBITOR_UUID))
                        .notNullable(),
                new JsonNullableProperty<>(
                        "valid",
                        HsOfficeMembershipPatchResource::setValidTo,
                        PATCHED_VALID_TO,
                        HsOfficeMembershipEntity::setValidTo),
                new SimpleProperty<>(
                        "reasonForTermination",
                        HsOfficeMembershipPatchResource::setReasonForTermination,
                        HsOfficeReasonForTerminationResource.CANCELLATION,
                        HsOfficeMembershipEntity::setReasonForTermination,
                        HsOfficeReasonForTermination.CANCELLATION)
                        .notNullable()
        );
    }
    private static HsOfficeDebitorEntity newDebitor(final UUID uuid) {
        final var newDebitor = new HsOfficeDebitorEntity();
        newDebitor.setUuid(uuid);
        return newDebitor;
    }
    private HsOfficeMembershipEntity newMembership(final UUID uuid) {
        final var newMembership = new HsOfficeMembershipEntity();
        newMembership.setUuid(uuid);
        return newMembership;
    }
}
src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntityUnitTest.java
@@ -8,17 +8,18 @@
import java.time.LocalDate;
import java.util.Arrays;
import static net.hostsharing.hsadminng.hs.office.debitor.TestHsOfficeDebitor.testDebitor;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.testPartner;
import static net.hostsharing.hsadminng.hs.office.debitor.TestHsOfficeDebitor.TEST_DEBITOR;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER;
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(testPartner)
            .mainDebitor(testDebitor)
            .validity(Range.closedInfinite(LocalDate.parse("2020-01-01")))
            .partner(TEST_PARTNER)
            .mainDebitor(TEST_DEBITOR)
            .validity(Range.closedInfinite(GIVEN_VALID_FROM))
            .build();
    @Test
@@ -52,6 +53,12 @@
        assertThat(givenMembership.getReasonForTermination()).isEqualTo(HsOfficeReasonForTermination.CANCELLATION);
    }
    @Test
    void settingValidToKeepsValidFrom() {
        givenMembership.setValidTo(LocalDate.parse("2024-12-31"));
        assertThat(givenMembership.getValidity().lower()).isEqualTo(GIVEN_VALID_FROM);
    }
    private static void invokePrePersist(final HsOfficeMembershipEntity membershipEntity)
            throws IllegalAccessException, InvocationTargetException {
        final var prePersistMethod = Arrays.stream(HsOfficeMembershipEntity.class.getDeclaredMethods())
src/test/java/net/hostsharing/hsadminng/hs/office/membership/TestHsMembership.java
@@ -5,14 +5,14 @@
import java.time.LocalDate;
import java.util.UUID;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.testPartner;
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TEST_PARTNER;
public class TestHsMembership {
    public static final HsOfficeMembershipEntity testMembership =
    public static final HsOfficeMembershipEntity TEST_MEMBERSHIP =
            HsOfficeMembershipEntity.builder()
                    .uuid(UUID.randomUUID())
                    .partner(testPartner)
                    .partner(TEST_PARTNER)
                    .memberNumber(300001)
                    .validity(Range.closedInfinite(LocalDate.parse("2020-01-01")))
                    .build();
src/test/java/net/hostsharing/hsadminng/hs/office/partner/TestHsOfficePartner.java
@@ -9,7 +9,7 @@
public class TestHsOfficePartner {
    public static final HsOfficePartnerEntity testPartner = HsOfficePartnerWithLegalPerson("Test Ltd.");
    public static final HsOfficePartnerEntity TEST_PARTNER = HsOfficePartnerWithLegalPerson("Test Ltd.");
    static public HsOfficePartnerEntity HsOfficePartnerWithLegalPerson(final String tradeName) {
        return HsOfficePartnerEntity.builder()
src/test/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntityTest.java
@@ -6,13 +6,13 @@
import java.time.LocalDate;
import static net.hostsharing.hsadminng.hs.office.debitor.TestHsOfficeDebitor.testDebitor;
import static net.hostsharing.hsadminng.hs.office.debitor.TestHsOfficeDebitor.TEST_DEBITOR;
import static org.assertj.core.api.Assertions.assertThat;
class HsOfficeSepaMandateEntityTest {
    final HsOfficeSepaMandateEntity givenSepaMandate = HsOfficeSepaMandateEntity.builder()
            .debitor(testDebitor)
            .debitor(TEST_DEBITOR)
            .reference("some-ref")
            .validity(Range.closedOpen(LocalDate.parse("2020-01-01"), LocalDate.parse("2031-01-01")))
            .bankAccount(HsOfficeBankAccountEntity.builder().iban("some label").build())