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:--// | ||||
| --validCheckSum: 9:79e93a47a62e44c661cd8d414626e49d | ||||
| -- ---------------------------------------------------------------------------- | ||||
|  | ||||
| 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:--// | ||||
| -- ---------------------------------------------------------------------------- | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| package net.hostsharing.hsadminng.hs.office.relation; | ||||
|  | ||||
| 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.rbac.test.ContextBasedTestWithCleanup; | ||||
| 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.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; | ||||
|  | ||||
| @DataJpaTest | ||||
| @@ -29,10 +33,13 @@ import static org.assertj.core.api.Assertions.assertThat; | ||||
| class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWithCleanup { | ||||
|  | ||||
|     @Autowired | ||||
|     HsOfficeRelationRealRepository relationRealRepo; | ||||
|     HsOfficeRelationRealRepository realRelationRepo; | ||||
|  | ||||
|     @Autowired | ||||
|     HsOfficePersonRbacRepository personRepo; | ||||
|     HsOfficePersonRealRepository realPersonRepo; | ||||
|  | ||||
|     @Autowired | ||||
|     HsOfficeContactRealRepository realContactRepo; | ||||
|  | ||||
|     @PersistenceContext | ||||
|     EntityManager em; | ||||
| @@ -49,7 +56,7 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith | ||||
|             final var personUuid = determinePersonUuid(NATURAL_PERSON, "Smith"); | ||||
|  | ||||
|             // when | ||||
|             final var result = relationRealRepo.findRelationRelatedToPersonUuid(personUuid); | ||||
|             final var result = realRelationRepo.findRelationRelatedToPersonUuid(personUuid); | ||||
|  | ||||
|             // then | ||||
|             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"); | ||||
|  | ||||
|             // when: | ||||
|             final var result = relationRealRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(personUuid, REPRESENTATIVE, null, null, null); | ||||
|             final var result = realRelationRepo.findRelationRelatedToPersonUuidRelationTypeMarkPersonAndContactData(personUuid, REPRESENTATIVE, null, null, null); | ||||
|  | ||||
|             // then: | ||||
|             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) { | ||||
|         return (UUID) em.createNativeQuery(""" | ||||
|                     SELECT uuid FROM hs_office.person p | ||||
| @@ -97,4 +132,12 @@ class HsOfficeRealRelationRepositoryIntegrationTest extends ContextBasedTestWith | ||||
|                 .extracting(HsOfficeRelation::toString) | ||||
|                 .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