add SEPA-Mandate entity+repository
This commit is contained in:
parent
bece972a4e
commit
d666e22297
@ -0,0 +1,64 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.sepamandate;
|
||||||
|
|
||||||
|
import com.vladmihalcea.hibernate.type.range.PostgreSQLRangeType;
|
||||||
|
import com.vladmihalcea.hibernate.type.range.Range;
|
||||||
|
import lombok.*;
|
||||||
|
import net.hostsharing.hsadminng.errors.DisplayName;
|
||||||
|
import net.hostsharing.hsadminng.Stringify;
|
||||||
|
import net.hostsharing.hsadminng.Stringifyable;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
||||||
|
import org.hibernate.annotations.TypeDef;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static net.hostsharing.hsadminng.Stringify.stringify;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "hs_office_sepamandate_rv")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@DisplayName("SEPA-Mandate")
|
||||||
|
@TypeDef(
|
||||||
|
typeClass = PostgreSQLRangeType.class,
|
||||||
|
defaultForType = Range.class
|
||||||
|
)
|
||||||
|
public class HsOfficeSepaMandateEntity implements Stringifyable {
|
||||||
|
|
||||||
|
private static Stringify<HsOfficeSepaMandateEntity> stringify = stringify(HsOfficeSepaMandateEntity.class)
|
||||||
|
.withProp(e -> e.getBankAccount().getIban())
|
||||||
|
.withProp(HsOfficeSepaMandateEntity::getReference)
|
||||||
|
.withProp(e -> e.getValidity().asString())
|
||||||
|
.withSeparator(", ")
|
||||||
|
.quotedValues(false);
|
||||||
|
|
||||||
|
private @Id UUID uuid;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "debitoruuid")
|
||||||
|
private HsOfficeDebitorEntity debitor;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "bankaccountuuid")
|
||||||
|
private HsOfficeBankAccountEntity bankAccount;
|
||||||
|
|
||||||
|
private @Column(name = "reference") String reference;
|
||||||
|
|
||||||
|
@Column(name="validity", columnDefinition = "daterange")
|
||||||
|
private Range<LocalDate> validity;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return stringify.apply(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toShortString() {
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.sepamandate;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface HsOfficeSepaMandateRepository extends Repository<HsOfficeSepaMandateEntity, UUID> {
|
||||||
|
|
||||||
|
Optional<HsOfficeSepaMandateEntity> findByUuid(UUID id);
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT mandate FROM HsOfficeSepaMandateEntity mandate
|
||||||
|
WHERE :iban is null
|
||||||
|
OR mandate.bankAccount.iban like concat(:iban, '%')
|
||||||
|
""")
|
||||||
|
List<HsOfficeSepaMandateEntity> findSepaMandateByOptionalIBAN(String iban);
|
||||||
|
|
||||||
|
HsOfficeSepaMandateEntity save(final HsOfficeSepaMandateEntity entity);
|
||||||
|
|
||||||
|
long count();
|
||||||
|
|
||||||
|
int deleteByUuid(UUID uuid);
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.debitor;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static net.hostsharing.hsadminng.hs.office.contact.TestHsOfficeContact.someContact;
|
||||||
|
import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.testPartner;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
public class TestHsOfficeDebitor {
|
||||||
|
|
||||||
|
public static final HsOfficeDebitorEntity testDebitor = HsOfficeDebitorEntity.builder()
|
||||||
|
.uuid(UUID.randomUUID())
|
||||||
|
.debitorNumber(10001)
|
||||||
|
.partner(testPartner)
|
||||||
|
.billingContact(someContact)
|
||||||
|
.build();
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.sepamandate;
|
||||||
|
|
||||||
|
import com.vladmihalcea.hibernate.type.range.Range;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
import static net.hostsharing.hsadminng.hs.office.debitor.TestHsOfficeDebitor.testDebitor;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
class HsOfficeSepaMandateEntityTest {
|
||||||
|
|
||||||
|
final HsOfficeSepaMandateEntity givenSepaMandate = HsOfficeSepaMandateEntity.builder()
|
||||||
|
.debitor(testDebitor)
|
||||||
|
.reference("some-ref")
|
||||||
|
.validity(Range.closedOpen(LocalDate.parse("2020-01-01"), LocalDate.parse("2031-01-01")))
|
||||||
|
.bankAccount(HsOfficeBankAccountEntity.builder().iban("some label").build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toStringContainsReferenceAndBankAccount() {
|
||||||
|
final var result = givenSepaMandate.toString();
|
||||||
|
|
||||||
|
assertThat(result).isEqualTo("SEPA-Mandate(some label, some-ref, [2020-01-01,2031-01-01))");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void toShortStringContainsReferenceOnly() {
|
||||||
|
final var result = givenSepaMandate.toShortString();
|
||||||
|
|
||||||
|
assertThat(result).isEqualTo("some-ref");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,462 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.sepamandate;
|
||||||
|
|
||||||
|
import com.vladmihalcea.hibernate.type.range.Range;
|
||||||
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
|
import net.hostsharing.hsadminng.context.ContextBasedTest;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountRepository;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository;
|
||||||
|
import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
|
||||||
|
import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
|
||||||
|
import net.hostsharing.test.Array;
|
||||||
|
import net.hostsharing.test.JpaAttempt;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.orm.jpa.JpaSystemException;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.grantDisplaysOf;
|
||||||
|
import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.roleNamesOf;
|
||||||
|
import static net.hostsharing.test.JpaAttempt.attempt;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||||
|
|
||||||
|
@DataJpaTest
|
||||||
|
@ComponentScan(basePackageClasses = { HsOfficeSepaMandateRepository.class, Context.class, JpaAttempt.class })
|
||||||
|
@DirtiesContext
|
||||||
|
class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
HsOfficeSepaMandateRepository sepaMandateRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
HsOfficeDebitorRepository debitorRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
HsOfficeBankAccountRepository bankAccountRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
RawRbacRoleRepository rawRoleRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
RawRbacGrantRepository rawGrantRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
EntityManager em;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
JpaAttempt jpaAttempt;
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
HttpServletRequest request;
|
||||||
|
|
||||||
|
Set<HsOfficeSepaMandateEntity> tempEntities = new HashSet<>();
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class CreateSepaMandate {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHostsharingAdmin_withoutAssumedRole_canCreateNewSepaMandate() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
final var count = sepaMandateRepo.count();
|
||||||
|
final var givenDebitor = debitorRepo.findDebitorByOptionalNameLike("First").get(0);
|
||||||
|
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike("Paul Winkler").get(0);
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = attempt(em, () -> {
|
||||||
|
final var newSepaMandate = toCleanup(HsOfficeSepaMandateEntity.builder()
|
||||||
|
.uuid(UUID.randomUUID())
|
||||||
|
.debitor(givenDebitor)
|
||||||
|
.bankAccount(givenBankAccount)
|
||||||
|
.reference("temp ref A")
|
||||||
|
.validity(Range.closedOpen(
|
||||||
|
LocalDate.parse("2020-01-01"), LocalDate.parse("2023-01-01")))
|
||||||
|
.build());
|
||||||
|
return sepaMandateRepo.save(newSepaMandate);
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.assertSuccessful();
|
||||||
|
assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeSepaMandateEntity::getUuid).isNotNull();
|
||||||
|
assertThatSepaMandateIsPersisted(result.returnedValue());
|
||||||
|
assertThat(sepaMandateRepo.count()).isEqualTo(count + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createsAndGrantsRoles() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
final var initialRoleNames = roleNamesOf(rawRoleRepo.findAll());
|
||||||
|
final var initialGrantNames = grantDisplaysOf(rawGrantRepo.findAll()).stream()
|
||||||
|
.map(s -> s.replace("-firstcontact", "-..."))
|
||||||
|
.map(s -> s.replace("PaulWinkler", "Paul..."))
|
||||||
|
.map(s -> s.replace("hs_office_", ""))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// when
|
||||||
|
attempt(em, () -> {
|
||||||
|
final var givenDebitor = debitorRepo.findDebitorByOptionalNameLike("First").get(0);
|
||||||
|
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike("Paul Winkler").get(0);
|
||||||
|
final var newSepaMandate = toCleanup(HsOfficeSepaMandateEntity.builder()
|
||||||
|
.uuid(UUID.randomUUID())
|
||||||
|
.debitor(givenDebitor)
|
||||||
|
.bankAccount(givenBankAccount)
|
||||||
|
.reference("temp ref B")
|
||||||
|
.validity(Range.closedOpen(
|
||||||
|
LocalDate.parse("2020-01-01"), LocalDate.parse("2023-01-01")))
|
||||||
|
.build());
|
||||||
|
return sepaMandateRepo.save(newSepaMandate);
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
final var all = rawRoleRepo.findAll();
|
||||||
|
assertThat(roleNamesOf(all)).containsExactlyInAnyOrder(Array.from(
|
||||||
|
initialRoleNames,
|
||||||
|
"hs_office_sepamandate#temprefB.owner",
|
||||||
|
"hs_office_sepamandate#temprefB.admin",
|
||||||
|
"hs_office_sepamandate#temprefB.agent",
|
||||||
|
"hs_office_sepamandate#temprefB.tenant",
|
||||||
|
"hs_office_sepamandate#temprefB.guest"));
|
||||||
|
assertThat(grantDisplaysOf(rawGrantRepo.findAll()))
|
||||||
|
.map(s -> s.replace("-firstcontact", "-..."))
|
||||||
|
.map(s -> s.replace("PaulWinkler", "Paul..."))
|
||||||
|
.map(s -> s.replace("hs_office_", ""))
|
||||||
|
.containsExactlyInAnyOrder(Array.fromFormatted(
|
||||||
|
initialGrantNames,
|
||||||
|
|
||||||
|
// owner
|
||||||
|
"{ grant perm * on sepamandate#temprefB to role sepamandate#temprefB.owner by system and assume }",
|
||||||
|
"{ grant role sepamandate#temprefB.owner to role global#global.admin by system and assume }",
|
||||||
|
|
||||||
|
// admin
|
||||||
|
"{ grant perm edit on sepamandate#temprefB to role sepamandate#temprefB.admin by system and assume }",
|
||||||
|
"{ grant role sepamandate#temprefB.admin to role sepamandate#temprefB.owner by system and assume }",
|
||||||
|
"{ grant role bankaccount#Paul....tenant to role sepamandate#temprefB.admin by system and assume }",
|
||||||
|
|
||||||
|
// agent
|
||||||
|
"{ grant role sepamandate#temprefB.agent to role sepamandate#temprefB.admin by system and assume }",
|
||||||
|
"{ grant role debitor#10001FirstGmbH-....tenant to role sepamandate#temprefB.agent by system and assume }",
|
||||||
|
"{ grant role sepamandate#temprefB.agent to role bankaccount#Paul....admin by system and assume }",
|
||||||
|
"{ grant role sepamandate#temprefB.agent to role debitor#10001FirstGmbH-....admin by system and assume }",
|
||||||
|
|
||||||
|
// tenant
|
||||||
|
"{ grant role sepamandate#temprefB.tenant to role sepamandate#temprefB.agent by system and assume }",
|
||||||
|
"{ grant role debitor#10001FirstGmbH-....guest to role sepamandate#temprefB.tenant by system and assume }",
|
||||||
|
"{ grant role bankaccount#Paul....guest to role sepamandate#temprefB.tenant by system and assume }",
|
||||||
|
|
||||||
|
// guest
|
||||||
|
"{ grant perm view on sepamandate#temprefB to role sepamandate#temprefB.guest by system and assume }",
|
||||||
|
"{ grant role sepamandate#temprefB.guest to role sepamandate#temprefB.tenant by system and assume }",
|
||||||
|
null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatSepaMandateIsPersisted(final HsOfficeSepaMandateEntity saved) {
|
||||||
|
final var found = sepaMandateRepo.findByUuid(saved.getUuid());
|
||||||
|
assertThat(found).isNotEmpty().get().usingRecursiveComparison().isEqualTo(saved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class FindAllSepaMandates {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void globalAdmin_withoutAssumedRole_canViewAllSepaMandates() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = sepaMandateRepo.findSepaMandateByOptionalIBAN(null);
|
||||||
|
|
||||||
|
// 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))");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void normalUser_canViewOnlyRelatedSepaMandates() {
|
||||||
|
// given:
|
||||||
|
context("bankaccount-admin@FirstGmbH.example.com");
|
||||||
|
|
||||||
|
// when:
|
||||||
|
final var result = sepaMandateRepo.findSepaMandateByOptionalIBAN(null);
|
||||||
|
|
||||||
|
// then:
|
||||||
|
exactlyTheseSepaMandatesAreReturned(
|
||||||
|
result,
|
||||||
|
"SEPA-Mandate(DE02120300000000202051, refFirstGmbH, [2022-10-01,2027-01-01))");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class FindByNameLike {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void globalAdmin_canViewAllSepaMandates() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = sepaMandateRepo.findSepaMandateByOptionalIBAN(null);
|
||||||
|
|
||||||
|
// 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))");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bankAccountAdmin_canViewRelatedSepaMandates() {
|
||||||
|
// given
|
||||||
|
context("bankaccount-admin@ThirdOHG.example.com");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = sepaMandateRepo.findSepaMandateByOptionalIBAN(null);
|
||||||
|
|
||||||
|
// then
|
||||||
|
exactlyTheseSepaMandatesAreReturned(
|
||||||
|
result,
|
||||||
|
"SEPA-Mandate(DE02300209000106531065, refThirdOHG, [2022-10-01,2027-01-01))");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class UpdateSepaMandate {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hostsharingAdmin_canUpdateValidityOfArbitrarySepaMandate() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
final var givenSepaMandate = givenSomeTemporarySepaMandateBessler("Peter Smith");
|
||||||
|
assertThatSepaMandateIsVisibleForUserWithRole(
|
||||||
|
givenSepaMandate,
|
||||||
|
"hs_office_bankaccount#PeterSmith.admin");
|
||||||
|
assertThatSepaMandateActuallyInDatabase(givenSepaMandate);
|
||||||
|
final var newValidityEnd = LocalDate.now();
|
||||||
|
|
||||||
|
// when
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
givenSepaMandate.setValidity(Range.closedOpen(
|
||||||
|
givenSepaMandate.getValidity().lower(), newValidityEnd));
|
||||||
|
return toCleanup(sepaMandateRepo.save(givenSepaMandate));
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.assertSuccessful();
|
||||||
|
|
||||||
|
sepaMandateRepo.deleteByUuid(givenSepaMandate.getUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bankAccountAdmin_canViewButNotUpdateRelatedSepaMandate() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
final var givenSepaMandate = givenSomeTemporarySepaMandateBessler("Anita Bessler");
|
||||||
|
assertThatSepaMandateIsVisibleForUserWithRole(
|
||||||
|
givenSepaMandate,
|
||||||
|
"hs_office_bankaccount#AnitaBessler.admin");
|
||||||
|
assertThatSepaMandateActuallyInDatabase(givenSepaMandate);
|
||||||
|
final var newValidityEnd = LocalDate.now();
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net", "hs_office_bankaccount#AnitaBessler.admin");
|
||||||
|
givenSepaMandate.setValidity(Range.closedOpen(
|
||||||
|
givenSepaMandate.getValidity().lower(), newValidityEnd));
|
||||||
|
return sepaMandateRepo.save(givenSepaMandate);
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.assertExceptionWithRootCauseMessage(JpaSystemException.class,
|
||||||
|
"[403] Subject ", " is not allowed to update hs_office_sepamandate uuid");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatSepaMandateActuallyInDatabase(final HsOfficeSepaMandateEntity saved) {
|
||||||
|
final var found = sepaMandateRepo.findByUuid(saved.getUuid());
|
||||||
|
assertThat(found).isNotEmpty().get().isNotSameAs(saved).usingRecursiveComparison().isEqualTo(saved);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatSepaMandateIsVisibleForUserWithRole(
|
||||||
|
final HsOfficeSepaMandateEntity entity,
|
||||||
|
final String assumedRoles) {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net", assumedRoles);
|
||||||
|
assertThatSepaMandateActuallyInDatabase(entity);
|
||||||
|
}).assertSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatSepaMandateIsNotVisibleForUserWithRole(
|
||||||
|
final HsOfficeSepaMandateEntity entity,
|
||||||
|
final String assumedRoles) {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net", assumedRoles);
|
||||||
|
final var found = sepaMandateRepo.findByUuid(entity.getUuid());
|
||||||
|
assertThat(found).isEmpty();
|
||||||
|
}).assertSuccessful();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class DeleteByUuid {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void globalAdmin_withoutAssumedRole_canDeleteAnySepaMandate() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net", null);
|
||||||
|
final var givenSepaMandate = givenSomeTemporarySepaMandateBessler("Fourth e.G.");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
sepaMandateRepo.deleteByUuid(givenSepaMandate.getUuid());
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.assertSuccessful();
|
||||||
|
assertThat(jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-fran@hostsharing.net", null);
|
||||||
|
return sepaMandateRepo.findByUuid(givenSepaMandate.getUuid());
|
||||||
|
}).assertSuccessful().returnedValue()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nonGlobalAdmin_canNotDeleteTheirRelatedSepaMandate() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net", null);
|
||||||
|
final var givenSepaMandate = givenSomeTemporarySepaMandateBessler("Third OHG");
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
|
context("bankaccount-admin@ThirdOHG.example.com");
|
||||||
|
assumeThat(sepaMandateRepo.findByUuid(givenSepaMandate.getUuid())).isPresent();
|
||||||
|
|
||||||
|
sepaMandateRepo.deleteByUuid(givenSepaMandate.getUuid());
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.assertExceptionWithRootCauseMessage(
|
||||||
|
JpaSystemException.class,
|
||||||
|
"[403] Subject ", " not allowed to delete hs_office_sepamandate");
|
||||||
|
assertThat(jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
return sepaMandateRepo.findByUuid(givenSepaMandate.getUuid());
|
||||||
|
}).assertSuccessful().returnedValue()).isPresent(); // still there
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deletingASepaMandateAlsoDeletesRelatedRolesAndGrants() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
final var initialRoleNames = Array.from(roleNamesOf(rawRoleRepo.findAll()));
|
||||||
|
final var initialGrantNames = Array.from(grantDisplaysOf(rawGrantRepo.findAll()));
|
||||||
|
final var givenSepaMandate = givenSomeTemporarySepaMandateBessler("Mel Bessler");
|
||||||
|
assertThat(rawRoleRepo.findAll().size()).as("precondition failed: unexpected number of roles created")
|
||||||
|
.isEqualTo(initialRoleNames.length + 5);
|
||||||
|
assertThat(rawGrantRepo.findAll().size()).as("precondition failed: unexpected number of grants created")
|
||||||
|
.isEqualTo(initialGrantNames.length + 14);
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
return sepaMandateRepo.deleteByUuid(givenSepaMandate.getUuid());
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.assertSuccessful();
|
||||||
|
assertThat(result.returnedValue()).isEqualTo(1);
|
||||||
|
assertThat(roleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(initialRoleNames);
|
||||||
|
assertThat(grantDisplaysOf(rawGrantRepo.findAll())).containsExactlyInAnyOrder(initialGrantNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void auditJournalLogIsAvailable() {
|
||||||
|
// given
|
||||||
|
final var query = em.createNativeQuery("""
|
||||||
|
select c.currenttask, j.targettable, j.targetop
|
||||||
|
from tx_journal j
|
||||||
|
join tx_context c on j.contextId = c.contextId
|
||||||
|
where targettable = 'hs_office_sepamandate';
|
||||||
|
""");
|
||||||
|
|
||||||
|
// when
|
||||||
|
@SuppressWarnings("unchecked") final List<Object[]> customerLogEntries = query.getResultList();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(customerLogEntries).map(Arrays::toString).contains(
|
||||||
|
"[creating SEPA-mandate test-data FirstGmbH, hs_office_sepamandate, INSERT]",
|
||||||
|
"[creating SEPA-mandate test-data Seconde.K., hs_office_sepamandate, INSERT]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
@AfterEach
|
||||||
|
void cleanup() {
|
||||||
|
tempEntities.forEach(tempSepaMandate -> {
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net", null);
|
||||||
|
System.out.println("DELETING temporary sepaMandate: " + tempSepaMandate.toString());
|
||||||
|
sepaMandateRepo.deleteByUuid(tempSepaMandate.getUuid());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net", null);
|
||||||
|
em.createQuery("DELETE FROM HsOfficeSepaMandateEntity WHERE reference like 'temp ref%'");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private HsOfficeSepaMandateEntity givenSomeTemporarySepaMandateBessler(final String bankAccountHolder) {
|
||||||
|
return jpaAttempt.transacted(() -> {
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
final var givenDebitor = debitorRepo.findDebitorByOptionalNameLike("First").get(0);
|
||||||
|
final var givenBankAccount = bankAccountRepo.findByOptionalHolderLike(bankAccountHolder).get(0);
|
||||||
|
final var newSepaMandate = HsOfficeSepaMandateEntity.builder()
|
||||||
|
.uuid(UUID.randomUUID())
|
||||||
|
.debitor(givenDebitor)
|
||||||
|
.bankAccount(givenBankAccount)
|
||||||
|
.reference("temp ref X")
|
||||||
|
.validity(Range.closedOpen(
|
||||||
|
LocalDate.parse("2020-01-01"), LocalDate.parse("2023-01-01")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
toCleanup(newSepaMandate);
|
||||||
|
|
||||||
|
return sepaMandateRepo.save(newSepaMandate);
|
||||||
|
}).assertSuccessful().returnedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HsOfficeSepaMandateEntity toCleanup(final HsOfficeSepaMandateEntity tempEntity) {
|
||||||
|
tempEntities.add(tempEntity);
|
||||||
|
return tempEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void exactlyTheseSepaMandatesAreReturned(
|
||||||
|
final List<HsOfficeSepaMandateEntity> actualResult,
|
||||||
|
final String... sepaMandateNames) {
|
||||||
|
assertThat(actualResult)
|
||||||
|
.extracting(sepaMandateEntity -> sepaMandateEntity.toString())
|
||||||
|
.containsExactlyInAnyOrder(sepaMandateNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
void allTheseSepaMandatesAreReturned(final List<HsOfficeSepaMandateEntity> actualResult, final String... sepaMandateNames) {
|
||||||
|
assertThat(actualResult)
|
||||||
|
.extracting(sepaMandateEntity -> sepaMandateEntity.toString())
|
||||||
|
.contains(sepaMandateNames);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user