Merge pull request 'Add constraint to relation to check if anchor of debitor relation is a PARTNER' (#175) from TP-20250326_relation_contraint_check_debitor_anchor_is_partner into master
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/175 Reviewed-by: Michael Hoennig <michael.hoennig@hostsharing.net>
This commit is contained in:
@@ -32,6 +32,7 @@ create table if not exists hs_office.relation
|
|||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset michael.hoennig:hs-office-relation-unique-constraints endDelimiter:--//
|
--changeset michael.hoennig:hs-office-relation-unique-constraints endDelimiter:--//
|
||||||
|
--validCheckSum: 9:79e93a47a62e44c661cd8d414626e49d
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
|
||||||
CREATE UNIQUE INDEX unique_relation_with_mark
|
CREATE UNIQUE INDEX unique_relation_with_mark
|
||||||
@@ -49,6 +50,36 @@ CREATE UNIQUE INDEX unique_partner_relation
|
|||||||
--//
|
--//
|
||||||
|
|
||||||
|
|
||||||
|
-- =====================================================================================
|
||||||
|
--changeset timotheus.pokorra:hs-office-relation-debitor-anchor-CONSTRAINT endDelimiter:--//
|
||||||
|
-- -------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: relation_check_debitor_anchor_partner(RelationType, uuid); Type: FUNCTION; Schema: hs_office; Owner: test
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE FUNCTION hs_office.relation_check_debitor_anchor_partner(mytype hs_office.RelationType, debitoranchoruuid uuid) RETURNS boolean
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS '
|
||||||
|
declare
|
||||||
|
countPartner integer;
|
||||||
|
begin
|
||||||
|
if mytype = ''DEBITOR'' then
|
||||||
|
SELECT COUNT(*) FROM hs_office.relation r
|
||||||
|
WHERE r.type = ''PARTNER'' AND r.holderuuid = debitoranchoruuid
|
||||||
|
INTO countPartner;
|
||||||
|
if countPartner < 1 then
|
||||||
|
raise exception ''[400] invalid debitor relation: anchor person must have a PARTNER relation'';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
return true;
|
||||||
|
end; ';
|
||||||
|
|
||||||
|
ALTER TABLE hs_office.relation ADD CONSTRAINT check_debitor_anchor_person CHECK (hs_office.relation_check_debitor_anchor_partner(type, anchorUuid));
|
||||||
|
|
||||||
|
--//
|
||||||
|
|
||||||
|
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
--changeset michael.hoennig:hs-office-relation-MAIN-TABLE-JOURNAL endDelimiter:--//
|
--changeset michael.hoennig:hs-office-relation-MAIN-TABLE-JOURNAL endDelimiter:--//
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
package net.hostsharing.hsadminng.hs.office.relation;
|
package net.hostsharing.hsadminng.hs.office.relation;
|
||||||
|
|
||||||
import net.hostsharing.hsadminng.context.Context;
|
import net.hostsharing.hsadminng.context.Context;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRbacRepository;
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealRepository;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRealRepository;
|
||||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||||
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
||||||
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||||
@@ -21,6 +23,8 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.NATURAL_PERSON;
|
import static net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType.NATURAL_PERSON;
|
||||||
import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.REPRESENTATIVE;
|
import static net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType.REPRESENTATIVE;
|
||||||
|
import static net.hostsharing.hsadminng.rbac.test.EntityList.one;
|
||||||
|
import static net.hostsharing.hsadminng.rbac.test.JpaAttempt.attempt;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@DataJpaTest
|
@DataJpaTest
|
||||||
@@ -29,10 +33,13 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
|
class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficeRelationRealRepository relationRealRepo;
|
HsOfficeRelationRealRepository realRelationRepo;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
HsOfficePersonRbacRepository personRepo;
|
HsOfficePersonRealRepository realPersonRepo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
HsOfficeContactRealRepository realContactRepo;
|
||||||
|
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
EntityManager em;
|
EntityManager em;
|
||||||
@@ -49,7 +56,7 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith
|
|||||||
final var personUuid = determinePersonUuid(NATURAL_PERSON, "Smith");
|
final var personUuid = determinePersonUuid(NATURAL_PERSON, "Smith");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
final var result = relationRealRepo.findRelationRelatedToPersonUuid(personUuid);
|
final var result = realRelationRepo.findRelationRelatedToPersonUuid(personUuid);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
context("superuser-alex@hostsharing.net"); // just to be able to access RBAc-entities persons+contact
|
context("superuser-alex@hostsharing.net"); // just to be able to access RBAc-entities persons+contact
|
||||||
@@ -68,7 +75,7 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith
|
|||||||
final var personUuid = determinePersonUuid(NATURAL_PERSON, "Smith");
|
final var personUuid = determinePersonUuid(NATURAL_PERSON, "Smith");
|
||||||
|
|
||||||
// when:
|
// when:
|
||||||
final var result = relationRealRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(personUuid, REPRESENTATIVE, null, null, null);
|
final var result = realRelationRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(personUuid, REPRESENTATIVE, null, null, null);
|
||||||
|
|
||||||
// then:
|
// then:
|
||||||
context("superuser-alex@hostsharing.net"); // just to be able to access RBAc-entities persons+contact
|
context("superuser-alex@hostsharing.net"); // just to be able to access RBAc-entities persons+contact
|
||||||
@@ -79,6 +86,34 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class CreateRelation {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void canNotAddDebitorRelationWithAnchorThatIsNotAPartner() {
|
||||||
|
// given
|
||||||
|
context("superuser-alex@hostsharing.net");
|
||||||
|
|
||||||
|
final var givenPartnerPerson = hsOfficePersonRealEntity("Non-Partner Person");
|
||||||
|
final var givenContact = one(realContactRepo.findContactByOptionalCaptionLike("eleventh contact"));
|
||||||
|
|
||||||
|
// when
|
||||||
|
final var result = attempt(em, () -> {
|
||||||
|
final var newRelation = HsOfficeRelationRealEntity.builder()
|
||||||
|
.type(HsOfficeRelationType.DEBITOR)
|
||||||
|
.anchor(givenPartnerPerson)
|
||||||
|
.holder(givenPartnerPerson)
|
||||||
|
.contact(givenContact)
|
||||||
|
.build();
|
||||||
|
final var entity = realRelationRepo.save(newRelation);
|
||||||
|
return toCleanup(entity.load());
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
result.assertExceptionWithRootCauseMessage(org.postgresql.util.PSQLException.class, "ERROR: [400] invalid debitor relation: anchor person must have a PARTNER relation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private UUID determinePersonUuid(final HsOfficePersonType type, final String familyName) {
|
private UUID determinePersonUuid(final HsOfficePersonType type, final String familyName) {
|
||||||
return (UUID) em.createNativeQuery("""
|
return (UUID) em.createNativeQuery("""
|
||||||
SELECT uuid FROM hs_office.person p
|
SELECT uuid FROM hs_office.person p
|
||||||
@@ -97,4 +132,12 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith
|
|||||||
.extracting(HsOfficeRelation::toString)
|
.extracting(HsOfficeRelation::toString)
|
||||||
.containsExactlyInAnyOrder(relationNames);
|
.containsExactlyInAnyOrder(relationNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HsOfficePersonRealEntity hsOfficePersonRealEntity(final String tradeName) {
|
||||||
|
return realPersonRepo.save(HsOfficePersonRealEntity.builder()
|
||||||
|
.personType(HsOfficePersonType.NATURAL_PERSON)
|
||||||
|
.tradeName(tradeName)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user