RBAC generator with conditional grants used for REPRESENTATIVE-Relation #33
@ -16,6 +16,7 @@ import org.hibernate.annotations.NotFound;
|
|||||||
import org.hibernate.annotations.NotFoundAction;
|
import org.hibernate.annotations.NotFoundAction;
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
|||||||
public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
||||||
|
|
||||||
public static final String DEBITOR_NUMBER_TAG = "D-";
|
public static final String DEBITOR_NUMBER_TAG = "D-";
|
||||||
|
public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$";
|
||||||
|
|
||||||
private static Stringify<HsOfficeDebitorEntity> stringify =
|
private static Stringify<HsOfficeDebitorEntity> stringify =
|
||||||
stringify(HsOfficeDebitorEntity.class, "debitor")
|
stringify(HsOfficeDebitorEntity.class, "debitor")
|
||||||
@ -75,8 +77,9 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
@NotFound(action = NotFoundAction.IGNORE)
|
@NotFound(action = NotFoundAction.IGNORE)
|
||||||
private HsOfficePartnerEntity partner;
|
private HsOfficePartnerEntity partner;
|
||||||
|
|
||||||
@Column(name = "debitornumbersuffix", columnDefinition = "numeric(2)")
|
@Column(name = "debitornumbersuffix", length = 2)
|
||||||
private Byte debitorNumberSuffix; // TODO maybe rather as a formatted String?
|
@Pattern(regexp = TWO_DECIMAL_DIGITS)
|
||||||
|
private String debitorNumberSuffix;
|
||||||
|
|
||||||
@ManyToOne(cascade = { PERSIST, MERGE, REFRESH, DETACH }, optional = false)
|
@ManyToOne(cascade = { PERSIST, MERGE, REFRESH, DETACH }, optional = false)
|
||||||
@JoinColumn(name = "debitorreluuid", nullable = false)
|
@JoinColumn(name = "debitorreluuid", nullable = false)
|
||||||
@ -109,7 +112,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
.filter(partner -> debitorNumberSuffix != null)
|
.filter(partner -> debitorNumberSuffix != null)
|
||||||
.map(HsOfficePartnerEntity::getPartnerNumber)
|
.map(HsOfficePartnerEntity::getPartnerNumber)
|
||||||
.map(Object::toString)
|
.map(Object::toString)
|
||||||
.map(partnerNumber -> partnerNumber + String.format("%02d", debitorNumberSuffix))
|
.map(partnerNumber -> partnerNumber + debitorNumberSuffix)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +141,7 @@ public class HsOfficeDebitorEntity implements HasUuid, Stringifyable {
|
|||||||
JOIN hs_office_relation debitorRel
|
JOIN hs_office_relation debitorRel
|
||||||
ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR'
|
ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR'
|
||||||
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
||||||
|| to_char(debitorNumberSuffix, 'fm00') as idName
|
|| debitorNumberSuffix as idName
|
||||||
FROM hs_office_debitor AS debitor
|
FROM hs_office_debitor AS debitor
|
||||||
"""))
|
"""))
|
||||||
.withRestrictedViewOrderBy(SQL.projection("defaultPrefix"))
|
.withRestrictedViewOrderBy(SQL.projection("defaultPrefix"))
|
||||||
|
@ -14,6 +14,7 @@ import net.hostsharing.hsadminng.stringify.Stringifyable;
|
|||||||
import org.hibernate.annotations.Type;
|
import org.hibernate.annotations.Type;
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -44,6 +45,7 @@ import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
|
|||||||
public class HsOfficeMembershipEntity implements HasUuid, Stringifyable {
|
public class HsOfficeMembershipEntity implements HasUuid, Stringifyable {
|
||||||
|
|
||||||
public static final String MEMBER_NUMBER_TAG = "M-";
|
public static final String MEMBER_NUMBER_TAG = "M-";
|
||||||
|
public static final String TWO_DECIMAL_DIGITS = "^([0-9]{2})$";
|
||||||
|
|
||||||
private static Stringify<HsOfficeMembershipEntity> stringify = stringify(HsOfficeMembershipEntity.class)
|
private static Stringify<HsOfficeMembershipEntity> stringify = stringify(HsOfficeMembershipEntity.class)
|
||||||
.withProp(e -> MEMBER_NUMBER_TAG + e.getMemberNumber())
|
.withProp(e -> MEMBER_NUMBER_TAG + e.getMemberNumber())
|
||||||
@ -61,6 +63,7 @@ public class HsOfficeMembershipEntity implements HasUuid, Stringifyable {
|
|||||||
private HsOfficePartnerEntity partner;
|
private HsOfficePartnerEntity partner;
|
||||||
|
|
||||||
@Column(name = "membernumbersuffix", length = 2)
|
@Column(name = "membernumbersuffix", length = 2)
|
||||||
|
@Pattern(regexp = TWO_DECIMAL_DIGITS)
|
||||||
private String memberNumberSuffix;
|
private String memberNumberSuffix;
|
||||||
|
|
||||||
@Column(name = "validity", columnDefinition = "daterange")
|
@Column(name = "validity", columnDefinition = "daterange")
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
create table hs_office_debitor
|
create table hs_office_debitor
|
||||||
(
|
(
|
||||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||||
debitorNumberSuffix numeric(2) not null,
|
debitorNumberSuffix char(2) not null check (debitorNumberSuffix::text ~ '^[0-9][0-9]$'),
|
||||||
debitorRelUuid uuid not null references hs_office_relation(uuid),
|
debitorRelUuid uuid not null references hs_office_relation(uuid),
|
||||||
billable boolean not null default true,
|
billable boolean not null default true,
|
||||||
vatId varchar(24), -- TODO.spec: here or in person?
|
vatId varchar(24), -- TODO.spec: here or in person?
|
||||||
|
@ -201,7 +201,7 @@ create trigger hs_office_debitor_insert_permission_check_tg
|
|||||||
JOIN hs_office_relation debitorRel
|
JOIN hs_office_relation debitorRel
|
||||||
ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR'
|
ON debitorRel.anchorUuid = partnerRel.holderUuid AND debitorRel.type = 'DEBITOR'
|
||||||
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
WHERE debitorRel.uuid = debitor.debitorRelUuid)
|
||||||
|| to_char(debitorNumberSuffix, 'fm00') as idName
|
|| debitorNumberSuffix as idName
|
||||||
FROM hs_office_debitor AS debitor
|
FROM hs_office_debitor AS debitor
|
||||||
$idName$);
|
$idName$);
|
||||||
--//
|
--//
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
create or replace procedure createHsOfficeSepaMandateTestData(
|
create or replace procedure createHsOfficeSepaMandateTestData(
|
||||||
forPartnerNumber numeric(5),
|
forPartnerNumber numeric(5),
|
||||||
forDebitorSuffix numeric(2),
|
forDebitorSuffix char(2),
|
||||||
forIban varchar,
|
forIban varchar,
|
||||||
withReference varchar)
|
withReference varchar)
|
||||||
language plpgsql as $$
|
language plpgsql as $$
|
||||||
@ -48,9 +48,9 @@ end; $$;
|
|||||||
|
|
||||||
do language plpgsql $$
|
do language plpgsql $$
|
||||||
begin
|
begin
|
||||||
call createHsOfficeSepaMandateTestData(10001, 11, 'DE02120300000000202051', 'ref-10001-11');
|
call createHsOfficeSepaMandateTestData(10001, '11', 'DE02120300000000202051', 'ref-10001-11');
|
||||||
call createHsOfficeSepaMandateTestData(10002, 12, 'DE02100500000054540402', 'ref-10002-12');
|
call createHsOfficeSepaMandateTestData(10002, '12', 'DE02100500000054540402', 'ref-10002-12');
|
||||||
call createHsOfficeSepaMandateTestData(10003, 13, 'DE02300209000106531065', 'ref-10003-13');
|
call createHsOfficeSepaMandateTestData(10003, '13', 'DE02300209000106531065', 'ref-10003-13');
|
||||||
end;
|
end;
|
||||||
$$;
|
$$;
|
||||||
--//
|
--//
|
||||||
|
@ -12,8 +12,7 @@ create table if not exists hs_office_membership
|
|||||||
(
|
(
|
||||||
uuid uuid unique references RbacObject (uuid) initially deferred,
|
uuid uuid unique references RbacObject (uuid) initially deferred,
|
||||||
partnerUuid uuid not null references hs_office_partner(uuid),
|
partnerUuid uuid not null references hs_office_partner(uuid),
|
||||||
memberNumberSuffix char(2) not null check (
|
memberNumberSuffix char(2) not null check (memberNumberSuffix::text ~ '^[0-9][0-9]$'),
|
||||||
memberNumberSuffix::text ~ '^[0-9][0-9]$'),
|
|
||||||
validity daterange not null,
|
validity daterange not null,
|
||||||
reasonForTermination HsOfficeReasonForTermination not null default 'NONE',
|
reasonForTermination HsOfficeReasonForTermination not null default 'NONE',
|
||||||
membershipFeeBillable boolean not null default true,
|
membershipFeeBillable boolean not null default true,
|
||||||
|
@ -722,7 +722,7 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Fourth").get(0);
|
final var givenPartner = partnerRepo.findPartnerByOptionalNameLike("Fourth").get(0);
|
||||||
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").get(0);
|
final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth contact").get(0);
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix(++nextDebitorSuffix)
|
.debitorNumberSuffix(nextDebitorSuffix())
|
||||||
.billable(true)
|
.billable(true)
|
||||||
.debitorRel(
|
.debitorRel(
|
||||||
HsOfficeRelationEntity.builder()
|
HsOfficeRelationEntity.builder()
|
||||||
@ -751,4 +751,8 @@ class HsOfficeDebitorControllerAcceptanceTest extends ContextBasedTestWithCleanu
|
|||||||
System.out.printf("deleted %d entities%n", count);
|
System.out.printf("deleted %d entities%n", count);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String nextDebitorSuffix() {
|
||||||
|
return String.format("%02d", nextDebitorSuffix++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ class HsOfficeDebitorEntityUnitTest {
|
|||||||
@Test
|
@Test
|
||||||
void toStringContainsPartnerAndContact() {
|
void toStringContainsPartnerAndContact() {
|
||||||
final var given = HsOfficeDebitorEntity.builder()
|
final var given = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)67)
|
.debitorNumberSuffix("67")
|
||||||
.debitorRel(givenDebitorRel)
|
.debitorRel(givenDebitorRel)
|
||||||
.defaultPrefix("som")
|
.defaultPrefix("som")
|
||||||
.partner(HsOfficePartnerEntity.builder()
|
.partner(HsOfficePartnerEntity.builder()
|
||||||
@ -43,7 +43,7 @@ class HsOfficeDebitorEntityUnitTest {
|
|||||||
void toShortStringContainsDebitorNumber() {
|
void toShortStringContainsDebitorNumber() {
|
||||||
final var given = HsOfficeDebitorEntity.builder()
|
final var given = HsOfficeDebitorEntity.builder()
|
||||||
.debitorRel(givenDebitorRel)
|
.debitorRel(givenDebitorRel)
|
||||||
.debitorNumberSuffix((byte)67)
|
.debitorNumberSuffix("67")
|
||||||
.partner(HsOfficePartnerEntity.builder()
|
.partner(HsOfficePartnerEntity.builder()
|
||||||
.partnerNumber(12345)
|
.partnerNumber(12345)
|
||||||
.build())
|
.build())
|
||||||
@ -58,7 +58,7 @@ class HsOfficeDebitorEntityUnitTest {
|
|||||||
void getDebitorNumberWithPartnerNumberAndDebitorNumberSuffix() {
|
void getDebitorNumberWithPartnerNumberAndDebitorNumberSuffix() {
|
||||||
final var given = HsOfficeDebitorEntity.builder()
|
final var given = HsOfficeDebitorEntity.builder()
|
||||||
.debitorRel(givenDebitorRel)
|
.debitorRel(givenDebitorRel)
|
||||||
.debitorNumberSuffix((byte)67)
|
.debitorNumberSuffix("67")
|
||||||
.partner(HsOfficePartnerEntity.builder()
|
.partner(HsOfficePartnerEntity.builder()
|
||||||
.partnerNumber(12345)
|
.partnerNumber(12345)
|
||||||
.build())
|
.build())
|
||||||
@ -73,7 +73,7 @@ class HsOfficeDebitorEntityUnitTest {
|
|||||||
void getDebitorNumberWithoutPartnerReturnsNull() {
|
void getDebitorNumberWithoutPartnerReturnsNull() {
|
||||||
final var given = HsOfficeDebitorEntity.builder()
|
final var given = HsOfficeDebitorEntity.builder()
|
||||||
.debitorRel(givenDebitorRel)
|
.debitorRel(givenDebitorRel)
|
||||||
.debitorNumberSuffix((byte)67)
|
.debitorNumberSuffix("67")
|
||||||
.partner(null)
|
.partner(null)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ class HsOfficeDebitorEntityUnitTest {
|
|||||||
void getDebitorNumberWithoutPartnerNumberReturnsNull() {
|
void getDebitorNumberWithoutPartnerNumberReturnsNull() {
|
||||||
final var given = HsOfficeDebitorEntity.builder()
|
final var given = HsOfficeDebitorEntity.builder()
|
||||||
.debitorRel(givenDebitorRel)
|
.debitorRel(givenDebitorRel)
|
||||||
.debitorNumberSuffix((byte)67)
|
.debitorNumberSuffix("67")
|
||||||
.partner(HsOfficePartnerEntity.builder().build())
|
.partner(HsOfficePartnerEntity.builder().build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// when
|
// when
|
||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)21)
|
.debitorNumberSuffix("21")
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.type(HsOfficeRelationType.DEBITOR)
|
||||||
.anchor(givenPartnerPerson)
|
.anchor(givenPartnerPerson)
|
||||||
@ -121,7 +121,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
// when
|
// when
|
||||||
final var result = attempt(em, () -> {
|
final var result = attempt(em, () -> {
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)21)
|
.debitorNumberSuffix("21")
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.type(HsOfficeRelationType.DEBITOR)
|
||||||
.anchor(givenPartnerPerson)
|
.anchor(givenPartnerPerson)
|
||||||
@ -156,7 +156,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var givenDebitorPerson = one(personRepo.findPersonByOptionalNameLike("Fourth eG"));
|
final var givenDebitorPerson = one(personRepo.findPersonByOptionalNameLike("Fourth eG"));
|
||||||
final var givenContact = one(contactRepo.findContactByOptionalLabelLike("fourth contact"));
|
final var givenContact = one(contactRepo.findContactByOptionalLabelLike("fourth contact"));
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)22)
|
.debitorNumberSuffix("22")
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.type(HsOfficeRelationType.DEBITOR)
|
||||||
.anchor(givenPartnerPerson)
|
.anchor(givenPartnerPerson)
|
||||||
@ -613,7 +613,7 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
|
|||||||
final var givenBankAccount =
|
final var givenBankAccount =
|
||||||
bankAccountHolder != null ? one(bankAccountRepo.findByOptionalHolderLike(bankAccountHolder)) : null;
|
bankAccountHolder != null ? one(bankAccountRepo.findByOptionalHolderLike(bankAccountHolder)) : null;
|
||||||
final var newDebitor = HsOfficeDebitorEntity.builder()
|
final var newDebitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte)20)
|
.debitorNumberSuffix("20")
|
||||||
.debitorRel(HsOfficeRelationEntity.builder()
|
.debitorRel(HsOfficeRelationEntity.builder()
|
||||||
.type(HsOfficeRelationType.DEBITOR)
|
.type(HsOfficeRelationType.DEBITOR)
|
||||||
.anchor(givenPartnerPerson)
|
.anchor(givenPartnerPerson)
|
||||||
|
@ -10,7 +10,7 @@ import static net.hostsharing.hsadminng.hs.office.partner.TestHsOfficePartner.TE
|
|||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class TestHsOfficeDebitor {
|
public class TestHsOfficeDebitor {
|
||||||
|
|
||||||
public byte DEFAULT_DEBITOR_SUFFIX = 0;
|
public String DEFAULT_DEBITOR_SUFFIX = "00";
|
||||||
|
|
||||||
public static final HsOfficeDebitorEntity TEST_DEBITOR = HsOfficeDebitorEntity.builder()
|
public static final HsOfficeDebitorEntity TEST_DEBITOR = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix(DEFAULT_DEBITOR_SUFFIX)
|
.debitorNumberSuffix(DEFAULT_DEBITOR_SUFFIX)
|
||||||
|
@ -724,7 +724,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
|||||||
relations.put(relationId++, debitorRel);
|
relations.put(relationId++, debitorRel);
|
||||||
|
|
||||||
final var debitor = HsOfficeDebitorEntity.builder()
|
final var debitor = HsOfficeDebitorEntity.builder()
|
||||||
.debitorNumberSuffix((byte) 0)
|
.debitorNumberSuffix("00")
|
||||||
.partner(partner)
|
.partner(partner)
|
||||||
.debitorRel(debitorRel)
|
.debitorRel(debitorRel)
|
||||||
.defaultPrefix(rec.getString("member_code").replace("hsh00-", ""))
|
.defaultPrefix(rec.getString("member_code").replace("hsh00-", ""))
|
||||||
|
Loading…
Reference in New Issue
Block a user