Merge branch 'improved-rbac-generator' into remove-direct-partner-person-and-contact
# Conflicts: # src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java # src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java # src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerDetailsEntity.java # src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java # src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java # src/main/java/net/hostsharing/hsadminng/hs/office/sepamandate/HsOfficeSepaMandateEntity.java # src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/InsertTriggerGenerator.java # src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacRestrictedViewGenerator.java # src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml # src/main/resources/db/changelog/123-test-package-rbac.sql # src/main/resources/db/changelog/133-test-domain-rbac.sql # src/main/resources/db/changelog/223-hs-office-relation-rbac.md # src/main/resources/db/changelog/223-hs-office-relation-rbac.sql # src/main/resources/db/changelog/228-hs-office-relation-test-data.sql # src/main/resources/db/changelog/230-hs-office-partner.sql # src/main/resources/db/changelog/233-hs-office-partner-rbac.sql # src/main/resources/db/changelog/238-hs-office-partner-test-data.sql # src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java # src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java # src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerRestTest.java # src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java # src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java # src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java
This commit is contained in:
commit
6e663cf525
@ -10,7 +10,7 @@ classDiagram
|
||||
|
||||
namespace Partner {
|
||||
class partner-MeierGmbH
|
||||
class role-MeierGmbH
|
||||
class rel-MeierGmbH
|
||||
class personDetails-MeierGmbH
|
||||
class contactData-MeierGmbH
|
||||
class person-MeierGmbH
|
||||
@ -19,28 +19,29 @@ classDiagram
|
||||
namespace Representatives {
|
||||
class person-FrankMeier
|
||||
class contactData-FrankMeier
|
||||
class role-MeierGmbH-FrankMeier
|
||||
class rel-MeierGmbH-FrankMeier
|
||||
}
|
||||
|
||||
namespace Debitors {
|
||||
class debitor-MeierGmbH
|
||||
class contactData-MeierGmbH-Buha
|
||||
class role-MeierGmbH-Buha
|
||||
class rel-MeierGmbH-Buha
|
||||
}
|
||||
|
||||
namespace Operations {
|
||||
class person-SabineMeier
|
||||
class contactData-SabineMeier
|
||||
class role-MeierGmbH-SabineMeier
|
||||
class rel-MeierGmbH-SabineMeier
|
||||
}
|
||||
|
||||
namespace Enums {
|
||||
|
||||
class RoleType {
|
||||
class RelationType {
|
||||
<<enumeration>>
|
||||
UNKNOWN
|
||||
PARTNER
|
||||
DEBITOR
|
||||
REPRESENTATIVE
|
||||
ACCOUNTING
|
||||
OPERATIONS
|
||||
}
|
||||
|
||||
@ -64,9 +65,9 @@ classDiagram
|
||||
|
||||
class partner-MeierGmbH {
|
||||
+Numeric partnerNumber: 12345
|
||||
+Role partnerRole
|
||||
+Relation partnerRel
|
||||
}
|
||||
partner-MeierGmbH *-- role-MeierGmbH
|
||||
partner-MeierGmbH *-- rel-MeierGmbH
|
||||
|
||||
class person-MeierGmbH {
|
||||
+personType: LEGAL
|
||||
@ -90,22 +91,22 @@ classDiagram
|
||||
+emailAddresses: office@meier-gmbh.de
|
||||
}
|
||||
|
||||
class role-MeierGmbH {
|
||||
+RoleType RoleType PARTNER
|
||||
class rel-MeierGmbH {
|
||||
+RelationType type PARTNER
|
||||
+Person anchor
|
||||
+Person holder
|
||||
+Contact roleContact
|
||||
+Contact contact
|
||||
}
|
||||
role-MeierGmbH o-- person-HostsharingEG : anchor
|
||||
role-MeierGmbH o-- person-MeierGmbH : holder
|
||||
role-MeierGmbH o-- contactData-MeierGmbH
|
||||
rel-MeierGmbH o-- person-HostsharingEG : anchor
|
||||
rel-MeierGmbH o-- person-MeierGmbH : holder
|
||||
rel-MeierGmbH o-- contactData-MeierGmbH
|
||||
|
||||
%% --- Debitors ---
|
||||
|
||||
class debitor-MeierGmbH {
|
||||
+Partner partner
|
||||
+Numeric[2] debitorNumberSuffix: 00
|
||||
+Role billingRole
|
||||
+Relation debitorRel
|
||||
+boolean billable: true
|
||||
+String vatId: ID123456789
|
||||
+String vatCountryCode: DE
|
||||
@ -115,7 +116,7 @@ classDiagram
|
||||
+String defaultPrefix: mei
|
||||
}
|
||||
debitor-MeierGmbH o-- partner-MeierGmbH
|
||||
debitor-MeierGmbH *-- role-MeierGmbH-Buha
|
||||
debitor-MeierGmbH *-- rel-MeierGmbH-Buha
|
||||
|
||||
class contactData-MeierGmbH-Buha {
|
||||
+postalAddress: Hauptstraße 5, 22345 Hamburg
|
||||
@ -123,15 +124,15 @@ classDiagram
|
||||
+emailAddresses: buha@meier-gmbh.de
|
||||
}
|
||||
|
||||
class role-MeierGmbH-Buha {
|
||||
+RoleType RoleType ACCOUNTING
|
||||
class rel-MeierGmbH-Buha {
|
||||
+RelationType type DEBITOR
|
||||
+Person anchor
|
||||
+Person holder
|
||||
+Contact roleContact
|
||||
+Contact contact
|
||||
}
|
||||
role-MeierGmbH-Buha o-- person-MeierGmbH : anchor
|
||||
role-MeierGmbH-Buha o-- person-MeierGmbH : holder
|
||||
role-MeierGmbH-Buha o-- contactData-MeierGmbH-Buha
|
||||
rel-MeierGmbH-Buha o-- person-MeierGmbH : anchor
|
||||
rel-MeierGmbH-Buha o-- person-MeierGmbH : holder
|
||||
rel-MeierGmbH-Buha o-- contactData-MeierGmbH-Buha
|
||||
|
||||
%% --- Representatives ---
|
||||
|
||||
@ -148,15 +149,15 @@ classDiagram
|
||||
+emailAddresses: frank.meier@meier-gmbh.de
|
||||
}
|
||||
|
||||
class role-MeierGmbH-FrankMeier {
|
||||
+RoleType RoleType REPRESENTATIVE
|
||||
class rel-MeierGmbH-FrankMeier {
|
||||
+RelationType type REPRESENTATIVE
|
||||
+Person anchor
|
||||
+Person holder
|
||||
+Contact roleContact
|
||||
+Contact contact
|
||||
}
|
||||
role-MeierGmbH-FrankMeier o-- person-MeierGmbH : anchor
|
||||
role-MeierGmbH-FrankMeier o-- person-FrankMeier : holder
|
||||
role-MeierGmbH-FrankMeier o-- contactData-FrankMeier
|
||||
rel-MeierGmbH-FrankMeier o-- person-MeierGmbH : anchor
|
||||
rel-MeierGmbH-FrankMeier o-- person-FrankMeier : holder
|
||||
rel-MeierGmbH-FrankMeier o-- contactData-FrankMeier
|
||||
|
||||
%% --- Operations ---
|
||||
|
||||
@ -173,14 +174,14 @@ classDiagram
|
||||
+emailAddresses: sabine.meier@meier-gmbh.de
|
||||
}
|
||||
|
||||
class role-MeierGmbH-SabineMeier {
|
||||
+RoleType RoleType OPERATIONAL
|
||||
class rel-MeierGmbH-SabineMeier {
|
||||
+RelationType type OPERATIONAL
|
||||
+Person anchor
|
||||
+Person holder
|
||||
+Contact roleContact
|
||||
+Contact contact
|
||||
}
|
||||
role-MeierGmbH-SabineMeier o-- person-MeierGmbH : anchor
|
||||
role-MeierGmbH-SabineMeier o-- person-SabineMeier : holder
|
||||
role-MeierGmbH-SabineMeier o-- contactData-SabineMeier
|
||||
rel-MeierGmbH-SabineMeier o-- person-MeierGmbH : anchor
|
||||
rel-MeierGmbH-SabineMeier o-- person-SabineMeier : holder
|
||||
rel-MeierGmbH-SabineMeier o-- contactData-SabineMeier
|
||||
|
||||
```
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||
package net.hostsharing.hsadminng.hs.office.relation;
|
||||
|
||||
import net.hostsharing.hsadminng.context.Context;
|
||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeRelationshipsApi;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeRelationsApi;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonRepository;
|
||||
import net.hostsharing.hsadminng.mapper.Mapper;
|
||||
@ -22,7 +22,7 @@ import java.util.function.BiConsumer;
|
||||
|
||||
@RestController
|
||||
|
||||
public class HsOfficeRelationshipController implements HsOfficeRelationshipsApi {
|
||||
public class HsOfficeRelationController implements HsOfficeRelationsApi {
|
||||
|
||||
@Autowired
|
||||
private Context context;
|
||||
@ -31,10 +31,10 @@ public class HsOfficeRelationshipController implements HsOfficeRelationshipsApi
|
||||
private Mapper mapper;
|
||||
|
||||
@Autowired
|
||||
private HsOfficeRelationshipRepository relationshipRepo;
|
||||
private HsOfficeRelationRepository relationRepo;
|
||||
|
||||
@Autowired
|
||||
private HsOfficePersonRepository relHolderRepo;
|
||||
private HsOfficePersonRepository holderRepo;
|
||||
|
||||
@Autowired
|
||||
private HsOfficeContactRepository contactRepo;
|
||||
@ -44,79 +44,79 @@ public class HsOfficeRelationshipController implements HsOfficeRelationshipsApi
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseEntity<List<HsOfficeRelationshipResource>> listRelationships(
|
||||
public ResponseEntity<List<HsOfficeRelationResource>> listRelations(
|
||||
final String currentUser,
|
||||
final String assumedRoles,
|
||||
final UUID personUuid,
|
||||
final HsOfficeRelationshipTypeResource relationshipType) {
|
||||
final HsOfficeRelationTypeResource relationType) {
|
||||
context.define(currentUser, assumedRoles);
|
||||
|
||||
final var entities = relationshipRepo.findRelationshipRelatedToPersonUuidAndRelationshipType(personUuid,
|
||||
mapper.map(relationshipType, HsOfficeRelationshipType.class));
|
||||
final var entities = relationRepo.findRelationRelatedToPersonUuidAndRelationType(personUuid,
|
||||
mapper.map(relationType, HsOfficeRelationType.class));
|
||||
|
||||
final var resources = mapper.mapList(entities, HsOfficeRelationshipResource.class,
|
||||
RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
final var resources = mapper.mapList(entities, HsOfficeRelationResource.class,
|
||||
RELATION_ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.ok(resources);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseEntity<HsOfficeRelationshipResource> addRelationship(
|
||||
public ResponseEntity<HsOfficeRelationResource> addRelation(
|
||||
final String currentUser,
|
||||
final String assumedRoles,
|
||||
final HsOfficeRelationshipInsertResource body) {
|
||||
final HsOfficeRelationInsertResource body) {
|
||||
|
||||
context.define(currentUser, assumedRoles);
|
||||
|
||||
final var entityToSave = new HsOfficeRelationshipEntity();
|
||||
entityToSave.setRelType(HsOfficeRelationshipType.valueOf(body.getRelType()));
|
||||
entityToSave.setRelAnchor(relHolderRepo.findByUuid(body.getRelAnchorUuid()).orElseThrow(
|
||||
() -> new NoSuchElementException("cannot find relAnchorUuid " + body.getRelAnchorUuid())
|
||||
final var entityToSave = new HsOfficeRelationEntity();
|
||||
entityToSave.setType(HsOfficeRelationType.valueOf(body.getType()));
|
||||
entityToSave.setAnchor(holderRepo.findByUuid(body.getAnchorUuid()).orElseThrow(
|
||||
() -> new NoSuchElementException("cannot find anchorUuid " + body.getAnchorUuid())
|
||||
));
|
||||
entityToSave.setRelHolder(relHolderRepo.findByUuid(body.getRelHolderUuid()).orElseThrow(
|
||||
() -> new NoSuchElementException("cannot find relHolderUuid " + body.getRelHolderUuid())
|
||||
entityToSave.setHolder(holderRepo.findByUuid(body.getHolderUuid()).orElseThrow(
|
||||
() -> new NoSuchElementException("cannot find holderUuid " + body.getHolderUuid())
|
||||
));
|
||||
entityToSave.setContact(contactRepo.findByUuid(body.getContactUuid()).orElseThrow(
|
||||
() -> new NoSuchElementException("cannot find contactUuid " + body.getContactUuid())
|
||||
));
|
||||
|
||||
final var saved = relationshipRepo.save(entityToSave);
|
||||
final var saved = relationRepo.save(entityToSave);
|
||||
|
||||
final var uri =
|
||||
MvcUriComponentsBuilder.fromController(getClass())
|
||||
.path("/api/hs/office/relationships/{id}")
|
||||
.path("/api/hs/office/relations/{id}")
|
||||
.buildAndExpand(saved.getUuid())
|
||||
.toUri();
|
||||
final var mapped = mapper.map(saved, HsOfficeRelationshipResource.class,
|
||||
RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
final var mapped = mapper.map(saved, HsOfficeRelationResource.class,
|
||||
RELATION_ENTITY_TO_RESOURCE_POSTMAPPER);
|
||||
return ResponseEntity.created(uri).body(mapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseEntity<HsOfficeRelationshipResource> getRelationshipByUuid(
|
||||
public ResponseEntity<HsOfficeRelationResource> getRelationByUuid(
|
||||
final String currentUser,
|
||||
final String assumedRoles,
|
||||
final UUID relationshipUuid) {
|
||||
final UUID relationUuid) {
|
||||
|
||||
context.define(currentUser, assumedRoles);
|
||||
|
||||
final var result = relationshipRepo.findByUuid(relationshipUuid);
|
||||
final var result = relationRepo.findByUuid(relationUuid);
|
||||
if (result.isEmpty()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.ok(mapper.map(result.get(), HsOfficeRelationshipResource.class, RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER));
|
||||
return ResponseEntity.ok(mapper.map(result.get(), HsOfficeRelationResource.class, RELATION_ENTITY_TO_RESOURCE_POSTMAPPER));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseEntity<Void> deleteRelationshipByUuid(
|
||||
public ResponseEntity<Void> deleteRelationByUuid(
|
||||
final String currentUser,
|
||||
final String assumedRoles,
|
||||
final UUID relationshipUuid) {
|
||||
final UUID relationUuid) {
|
||||
context.define(currentUser, assumedRoles);
|
||||
|
||||
final var result = relationshipRepo.deleteByUuid(relationshipUuid);
|
||||
final var result = relationRepo.deleteByUuid(relationUuid);
|
||||
if (result == 0) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
@ -126,27 +126,27 @@ public class HsOfficeRelationshipController implements HsOfficeRelationshipsApi
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public ResponseEntity<HsOfficeRelationshipResource> patchRelationship(
|
||||
public ResponseEntity<HsOfficeRelationResource> patchRelation(
|
||||
final String currentUser,
|
||||
final String assumedRoles,
|
||||
final UUID relationshipUuid,
|
||||
final HsOfficeRelationshipPatchResource body) {
|
||||
final UUID relationUuid,
|
||||
final HsOfficeRelationPatchResource body) {
|
||||
|
||||
context.define(currentUser, assumedRoles);
|
||||
|
||||
final var current = relationshipRepo.findByUuid(relationshipUuid).orElseThrow();
|
||||
final var current = relationRepo.findByUuid(relationUuid).orElseThrow();
|
||||
|
||||
new HsOfficeRelationshipEntityPatcher(em, current).apply(body);
|
||||
new HsOfficeRelationEntityPatcher(em, current).apply(body);
|
||||
|
||||
final var saved = relationshipRepo.save(current);
|
||||
final var mapped = mapper.map(saved, HsOfficeRelationshipResource.class);
|
||||
final var saved = relationRepo.save(current);
|
||||
final var mapped = mapper.map(saved, HsOfficeRelationResource.class);
|
||||
return ResponseEntity.ok(mapped);
|
||||
}
|
||||
|
||||
|
||||
final BiConsumer<HsOfficeRelationshipEntity, HsOfficeRelationshipResource> RELATIONSHIP_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
||||
resource.setRelAnchor(mapper.map(entity.getRelAnchor(), HsOfficePersonResource.class));
|
||||
resource.setRelHolder(mapper.map(entity.getRelHolder(), HsOfficePersonResource.class));
|
||||
final BiConsumer<HsOfficeRelationEntity, HsOfficeRelationResource> RELATION_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> {
|
||||
resource.setAnchor(mapper.map(entity.getAnchor(), HsOfficePersonResource.class));
|
||||
resource.setHolder(mapper.map(entity.getHolder(), HsOfficePersonResource.class));
|
||||
resource.setContact(mapper.map(entity.getContact(), HsOfficeContactResource.class));
|
||||
};
|
||||
}
|
@ -1,25 +1,25 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||
package net.hostsharing.hsadminng.hs.office.relation;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationshipPatchResource;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationPatchResource;
|
||||
import net.hostsharing.hsadminng.mapper.EntityPatcher;
|
||||
import net.hostsharing.hsadminng.mapper.OptionalFromJson;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.util.UUID;
|
||||
|
||||
class HsOfficeRelationshipEntityPatcher implements EntityPatcher<HsOfficeRelationshipPatchResource> {
|
||||
class HsOfficeRelationEntityPatcher implements EntityPatcher<HsOfficeRelationPatchResource> {
|
||||
|
||||
private final EntityManager em;
|
||||
private final HsOfficeRelationshipEntity entity;
|
||||
private final HsOfficeRelationEntity entity;
|
||||
|
||||
HsOfficeRelationshipEntityPatcher(final EntityManager em, final HsOfficeRelationshipEntity entity) {
|
||||
HsOfficeRelationEntityPatcher(final EntityManager em, final HsOfficeRelationEntity entity) {
|
||||
this.em = em;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(final HsOfficeRelationshipPatchResource resource) {
|
||||
public void apply(final HsOfficeRelationPatchResource resource) {
|
||||
OptionalFromJson.of(resource.getContactUuid()).ifPresent(newValue -> {
|
||||
verifyNotNull(newValue, "contact");
|
||||
entity.setContact(em.getReference(HsOfficeContactEntity.class, newValue));
|
@ -0,0 +1,37 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relation;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface HsOfficeRelationRepository extends Repository<HsOfficeRelationEntity, UUID> {
|
||||
|
||||
Optional<HsOfficeRelationEntity> findByUuid(UUID id);
|
||||
|
||||
default List<HsOfficeRelationEntity> findRelationRelatedToPersonUuidAndRelationType(@NotNull UUID personUuid, HsOfficeRelationType relationType) {
|
||||
return findRelationRelatedToPersonUuidAndRelationTypeString(personUuid, relationType.toString());
|
||||
}
|
||||
|
||||
@Query(value = """
|
||||
SELECT p.* FROM hs_office_relation_rv AS p
|
||||
WHERE p.anchorUuid = :personUuid OR p.holderUuid = :personUuid
|
||||
""", nativeQuery = true)
|
||||
List<HsOfficeRelationEntity> findRelationRelatedToPersonUuid(@NotNull UUID personUuid);
|
||||
|
||||
@Query(value = """
|
||||
SELECT p.* FROM hs_office_relation_rv AS p
|
||||
WHERE (:relationType IS NULL OR p.type = cast(:relationType AS HsOfficeRelationType))
|
||||
AND ( p.anchorUuid = :personUuid OR p.holderUuid = :personUuid)
|
||||
""", nativeQuery = true)
|
||||
List<HsOfficeRelationEntity> findRelationRelatedToPersonUuidAndRelationTypeString(@NotNull UUID personUuid, String relationType);
|
||||
|
||||
HsOfficeRelationEntity save(final HsOfficeRelationEntity entity);
|
||||
|
||||
long count();
|
||||
|
||||
int deleteByUuid(UUID uuid);
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||
package net.hostsharing.hsadminng.hs.office.relation;
|
||||
|
||||
public enum HsOfficeRelationshipType {
|
||||
public enum HsOfficeRelationType {
|
||||
UNKNOWN,
|
||||
PARTNER,
|
||||
EX_PARTNER,
|
||||
REPRESENTATIVE,
|
||||
VIP_CONTACT,
|
||||
ACCOUNTING,
|
||||
DEBITOR,
|
||||
OPERATIONS,
|
||||
SUBSCRIBER
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface HsOfficeRelationshipRepository extends Repository<HsOfficeRelationshipEntity, UUID> {
|
||||
|
||||
Optional<HsOfficeRelationshipEntity> findByUuid(UUID id);
|
||||
|
||||
default List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuidAndRelationshipType(@NotNull UUID personUuid, HsOfficeRelationshipType relationshipType) {
|
||||
return findRelationshipRelatedToPersonUuidAndRelationshipTypeString(personUuid, relationshipType.toString());
|
||||
}
|
||||
|
||||
@Query(value = """
|
||||
SELECT p.* FROM hs_office_relationship_rv AS p
|
||||
WHERE p.relAnchorUuid = :personUuid OR p.relHolderUuid = :personUuid
|
||||
""", nativeQuery = true)
|
||||
List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuid(@NotNull UUID personUuid);
|
||||
|
||||
@Query(value = """
|
||||
SELECT p.* FROM hs_office_relationship_rv AS p
|
||||
WHERE (:relationshipType IS NULL OR p.relType = cast(:relationshipType AS HsOfficeRelationshipType))
|
||||
AND ( p.relAnchorUuid = :personUuid OR p.relHolderUuid = :personUuid)
|
||||
""", nativeQuery = true)
|
||||
List<HsOfficeRelationshipEntity> findRelationshipRelatedToPersonUuidAndRelationshipTypeString(@NotNull UUID personUuid, String relationshipType);
|
||||
|
||||
HsOfficeRelationshipEntity save(final HsOfficeRelationshipEntity entity);
|
||||
|
||||
long count();
|
||||
|
||||
int deleteByUuid(UUID uuid);
|
||||
}
|
@ -23,7 +23,7 @@ public class InsertTriggerGenerator {
|
||||
|
||||
void generateTo(final StringWriter plPgSql) {
|
||||
generateLiquibaseChangesetHeader(plPgSql);
|
||||
generateGrantInsertRoleToExistingCustomers(plPgSql);
|
||||
generateGrantInsertRoleToExistingObjects(plPgSql);
|
||||
generateInsertPermissionGrantTrigger(plPgSql);
|
||||
generateInsertCheckTrigger(plPgSql);
|
||||
plPgSql.writeLn("--//");
|
||||
@ -38,7 +38,7 @@ public class InsertTriggerGenerator {
|
||||
with("liquibaseTagPrefix", liquibaseTagPrefix));
|
||||
}
|
||||
|
||||
private void generateGrantInsertRoleToExistingCustomers(final StringWriter plPgSql) {
|
||||
private void generateGrantInsertRoleToExistingObjects(final StringWriter plPgSql) {
|
||||
getOptionalInsertSuperRole().ifPresent( superRoleDef -> {
|
||||
plPgSql.writeLn("""
|
||||
/*
|
||||
@ -100,13 +100,7 @@ public class InsertTriggerGenerator {
|
||||
|
||||
private void generateInsertCheckTrigger(final StringWriter plPgSql) {
|
||||
getOptionalInsertGrant().ifPresentOrElse(g -> {
|
||||
if (!g.getSuperRoleDef().getEntityAlias().isGlobal()) {
|
||||
if (rbacDef.isRootEntityAlias(g.getSuperRoleDef().getEntityAlias())) {
|
||||
generateInsertPermissionTriggerAllowByDirectRole(plPgSql, g);
|
||||
} else {
|
||||
generateInsertPermissionTriggerAllowByIndirectRole(plPgSql, g);
|
||||
}
|
||||
} else {
|
||||
if (g.getSuperRoleDef().getEntityAlias().isGlobal()) {
|
||||
switch (g.getSuperRoleDef().getRole()) {
|
||||
case ADMIN -> {
|
||||
generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql);
|
||||
@ -119,27 +113,23 @@ public class InsertTriggerGenerator {
|
||||
"invalid global role for INSERT permission: " + g.getSuperRoleDef().getRole());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(plPgSql, g);
|
||||
}
|
||||
},
|
||||
() -> {
|
||||
plPgSql.writeLn("""
|
||||
-- FIXME: Where is this case necessary?
|
||||
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||
before insert on ${rawSubTable}
|
||||
for each row
|
||||
-- As there is no explicit INSERT grant specified for this table,
|
||||
-- only global admins are allowed to insert any rows.
|
||||
when ( not isGlobalAdmin() )
|
||||
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||
System.err.println("WARNING: no explicit INSERT grant for " + rbacDef.getRootEntityAlias().simpleName() + " => implicitly grant INSERT to global.admin");
|
||||
generateInsertPermissionTriggerAllowOnlyGlobalAdmin(plPgSql);
|
||||
});
|
||||
}
|
||||
|
||||
private void generateInsertPermissionTriggerAllowByDirectRole(final StringWriter plPgSql, final RbacView.RbacGrantDefinition g) {
|
||||
private void generateInsertPermissionTriggerAllowByRoleOfDirectForeignKey(final StringWriter plPgSql, final RbacView.RbacGrantDefinition g) {
|
||||
plPgSql.writeLn("""
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}.
|
||||
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable},
|
||||
where the check is performed by a direct role.
|
||||
|
||||
A direct role is a role depending on a foreign key directly available in the NEW row.
|
||||
*/
|
||||
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
@ -159,51 +149,11 @@ public class InsertTriggerGenerator {
|
||||
with("referenceColumn", g.getSuperRoleDef().getEntityAlias().dependsOnColumName()));
|
||||
}
|
||||
|
||||
private void generateInsertPermissionTriggerAllowByIndirectRole(
|
||||
final StringWriter plPgSql,
|
||||
final RbacView.RbacGrantDefinition g) {
|
||||
plPgSql.writeLn("""
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}.
|
||||
*/
|
||||
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
language plpgsql as $$
|
||||
begin
|
||||
if ( not hasInsertPermission(
|
||||
( SELECT ${varName}.uuid FROM
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()),
|
||||
with("varName", g.getSuperRoleDef().getEntityAlias().aliasName()));
|
||||
plPgSql.indented(3, () -> {
|
||||
plPgSql.writeLn(
|
||||
"(" + g.getSuperRoleDef().getEntityAlias().fetchSql().sql + ") AS ${varName}",
|
||||
with("varName", g.getSuperRoleDef().getEntityAlias().aliasName()),
|
||||
with("ref", NEW.name()));
|
||||
});
|
||||
plPgSql.writeLn("""
|
||||
|
||||
), 'INSERT', '${rawSubTable}') ) then
|
||||
raise exception
|
||||
'[403] insert into ${rawSubTable} not allowed for current subjects % (%)',
|
||||
currentSubjects(), currentSubjectsUuids();
|
||||
end if;
|
||||
return NEW;
|
||||
end; $$;
|
||||
|
||||
create trigger ${rawSubTable}_insert_permission_check_tg
|
||||
before insert on ${rawSubTable}
|
||||
for each row
|
||||
execute procedure ${rawSubTable}_insert_permission_missing_tf();
|
||||
|
||||
""",
|
||||
with("rawSubTable", rbacDef.getRootEntityAlias().getRawTableName()));
|
||||
}
|
||||
|
||||
private void generateInsertPermissionTriggerAllowOnlyGlobalAdmin(final StringWriter plPgSql) {
|
||||
plPgSql.writeLn("""
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable}.
|
||||
Checks if the user or assumed roles are allowed to insert a row to ${rawSubTable},
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function ${rawSubTable}_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
|
@ -8,13 +8,11 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.StringWriter.with;
|
||||
public class RbacRestrictedViewGenerator {
|
||||
private final RbacView rbacDef;
|
||||
private final String liquibaseTagPrefix;
|
||||
private final String simpleEntityVarName;
|
||||
private final String rawTableName;
|
||||
|
||||
public RbacRestrictedViewGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
|
||||
this.rbacDef = rbacDef;
|
||||
this.liquibaseTagPrefix = liquibaseTagPrefix;
|
||||
this.simpleEntityVarName = rbacDef.getRootEntityAlias().simpleName();
|
||||
this.rawTableName = rbacDef.getRootEntityAlias().getRawTableName();
|
||||
}
|
||||
|
||||
@ -34,7 +32,7 @@ public class RbacRestrictedViewGenerator {
|
||||
|
||||
""",
|
||||
with("liquibaseTagPrefix", liquibaseTagPrefix),
|
||||
with("orderBy", rbacDef.getOrderBySqlExpression().sql),
|
||||
with("orderBy", indented(rbacDef.getOrderBySqlExpression().sql, 2)),
|
||||
with("updates", indented(rbacDef.getUpdatableColumns().stream()
|
||||
.map(c -> c + " = new." + c)
|
||||
.collect(joining(",\n")), 2)),
|
||||
|
@ -11,7 +11,7 @@ import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
|
||||
import net.hostsharing.hsadminng.persistence.HasUuid;
|
||||
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
||||
@ -812,7 +812,7 @@ public class RbacView {
|
||||
HsOfficePartnerDetailsEntity.class,
|
||||
HsOfficeBankAccountEntity.class,
|
||||
HsOfficeDebitorEntity.class,
|
||||
HsOfficeRelationshipEntity.class,
|
||||
HsOfficeRelationEntity.class,
|
||||
HsOfficeCoopAssetsTransactionEntity.class,
|
||||
HsOfficeContactEntity.class,
|
||||
HsOfficeSepaMandateEntity.class,
|
||||
@ -831,7 +831,7 @@ public class RbacView {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
System.err.println("no main method in: " + c.getName());
|
||||
System.err.println("WARNING: no main method in: " + c.getName() + " => no RBAC rules generated");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ map:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
/api/hs/office/persons/{personUUID}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
/api/hs/office/relationships/{relationshipUUID}:
|
||||
/api/hs/office/relations/{relationUUID}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
/api/hs/office/bankaccounts/{bankAccountUUID}:
|
||||
null: org.openapitools.jackson.nullable.JsonNullable
|
||||
|
@ -3,37 +3,37 @@ components:
|
||||
|
||||
schemas:
|
||||
|
||||
HsOfficeRelationshipType:
|
||||
HsOfficeRelationType:
|
||||
type: string
|
||||
enum:
|
||||
- UNKNOWN
|
||||
- PARTNER
|
||||
- EX_PARTNER
|
||||
- REPRESENTATIVE,
|
||||
- DEBITOR
|
||||
- REPRESENTATIVE
|
||||
- VIP_CONTACT
|
||||
- ACCOUNTING,
|
||||
- OPERATIONS
|
||||
- SUBSCRIBER
|
||||
|
||||
HsOfficeRelationship:
|
||||
HsOfficeRelation:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
relAnchor:
|
||||
anchor:
|
||||
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
||||
relHolder:
|
||||
holder:
|
||||
$ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson'
|
||||
relType:
|
||||
type:
|
||||
type: string
|
||||
relMark:
|
||||
mark:
|
||||
type: string
|
||||
nullable: true
|
||||
contact:
|
||||
$ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact'
|
||||
|
||||
HsOfficeRelationshipPatch:
|
||||
HsOfficeRelationPatch:
|
||||
type: object
|
||||
properties:
|
||||
contactUuid:
|
||||
@ -41,25 +41,25 @@ components:
|
||||
format: uuid
|
||||
nullable: true
|
||||
|
||||
HsOfficeRelationshipInsert:
|
||||
HsOfficeRelationInsert:
|
||||
type: object
|
||||
properties:
|
||||
relAnchorUuid:
|
||||
anchorUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
relHolderUuid:
|
||||
holderUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
relType:
|
||||
type:
|
||||
type: string
|
||||
nullable: true
|
||||
relMark:
|
||||
mark:
|
||||
type: string
|
||||
contactUuid:
|
||||
type: string
|
||||
format: uuid
|
||||
required:
|
||||
- relAnchorUuid
|
||||
- relHolderUuid
|
||||
- relType
|
||||
- anchorUuid
|
||||
- holderUuid
|
||||
- type
|
||||
- relContactUuid
|
@ -1,25 +1,25 @@
|
||||
get:
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
description: 'Fetch a single person relationship by its uuid, if visible for the current subject.'
|
||||
operationId: getRelationshipByUuid
|
||||
- hs-office-relations
|
||||
description: 'Fetch a single person relation by its uuid, if visible for the current subject.'
|
||||
operationId: getRelationByUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationshipUUID
|
||||
- name: relationUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the relationship to fetch.
|
||||
description: UUID of the relation to fetch.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
@ -28,13 +28,13 @@ get:
|
||||
|
||||
patch:
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
description: 'Updates a single person relationship by its uuid, if permitted for the current subject.'
|
||||
operationId: patchRelationship
|
||||
- hs-office-relations
|
||||
description: 'Updates a single person relation by its uuid, if permitted for the current subject.'
|
||||
operationId: patchRelation
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationshipUUID
|
||||
- name: relationUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
@ -44,14 +44,14 @@ patch:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipPatch'
|
||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelationPatch'
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
@ -59,19 +59,19 @@ patch:
|
||||
|
||||
delete:
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
description: 'Delete a single person relationship by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteRelationshipByUuid
|
||||
- hs-office-relations
|
||||
description: 'Delete a single person relation by its uuid, if permitted for the current subject.'
|
||||
operationId: deleteRelationByUuid
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
- name: relationshipUUID
|
||||
- name: relationUUID
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: UUID of the relationship to delete.
|
||||
description: UUID of the relation to delete.
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
@ -1,9 +1,9 @@
|
||||
get:
|
||||
summary: Returns a list of (optionally filtered) person relationships for a given person.
|
||||
description: Returns the list of (optionally filtered) person relationships of a given person and which are visible to the current user or any of it's assumed roles.
|
||||
summary: Returns a list of (optionally filtered) person relations for a given person.
|
||||
description: Returns the list of (optionally filtered) person relations of a given person and which are visible to the current user or any of it's assumed roles.
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
operationId: listRelationships
|
||||
- hs-office-relations
|
||||
operationId: listRelations
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
@ -13,13 +13,13 @@ get:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Prefix of name properties from relHolder or contact to filter the results.
|
||||
- name: relationshipType
|
||||
description: Prefix of name properties from holder or contact to filter the results.
|
||||
- name: relationType
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipType'
|
||||
description: Prefix of name properties from relHolder or contact to filter the results.
|
||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelationType'
|
||||
description: Prefix of name properties from holder or contact to filter the results.
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
@ -28,17 +28,17 @@ get:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
||||
$ref: './error-responses.yaml#/components/responses/Forbidden'
|
||||
|
||||
post:
|
||||
summary: Adds a new person relationship.
|
||||
summary: Adds a new person relation.
|
||||
tags:
|
||||
- hs-office-relationships
|
||||
operationId: addRelationship
|
||||
- hs-office-relations
|
||||
operationId: addRelation
|
||||
parameters:
|
||||
- $ref: './auth.yaml#/components/parameters/currentUser'
|
||||
- $ref: './auth.yaml#/components/parameters/assumedRoles'
|
||||
@ -46,7 +46,7 @@ post:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationshipInsert'
|
||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelationInsert'
|
||||
required: true
|
||||
responses:
|
||||
"201":
|
||||
@ -54,7 +54,7 @@ post:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: './hs-office-relationship-schemas.yaml#/components/schemas/HsOfficeRelationship'
|
||||
$ref: './hs-office-relations-schemas.yaml#/components/schemas/HsOfficeRelation'
|
||||
"401":
|
||||
$ref: './error-responses.yaml#/components/responses/Unauthorized'
|
||||
"403":
|
@ -35,13 +35,13 @@ paths:
|
||||
$ref: "./hs-office-persons-with-uuid.yaml"
|
||||
|
||||
|
||||
# Relationships
|
||||
# Relations
|
||||
|
||||
/api/hs/office/relationships:
|
||||
$ref: "./hs-office-relationships.yaml"
|
||||
/api/hs/office/relations:
|
||||
$ref: "./hs-office-relations.yaml"
|
||||
|
||||
/api/hs/office/relationships/{relationshipUUID}:
|
||||
$ref: "./hs-office-relationships-with-uuid.yaml"
|
||||
/api/hs/office/relations/{relationUUID}:
|
||||
$ref: "./hs-office-relations-with-uuid.yaml"
|
||||
|
||||
|
||||
# BankAccounts
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac customer
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.571772062.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.425403022.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,5 +1,6 @@
|
||||
--liquibase formatted sql
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-11T11:29:11.584886824.
|
||||
-- This code generated was by RbacViewPostgresGenerator at 2024-03-22T14:44:19.441879428.
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-OBJECT:1 endDelimiter:--//
|
||||
@ -36,8 +37,8 @@ begin
|
||||
perform createRoleWithGrants(
|
||||
testCustomerOwner(NEW),
|
||||
permissions => array['DELETE'],
|
||||
userUuids => array[currentUserUuid()],
|
||||
incomingSuperRoles => array[globalAdmin(unassumed())]
|
||||
incomingSuperRoles => array[globalAdmin(unassumed())],
|
||||
userUuids => array[currentUserUuid()]
|
||||
);
|
||||
|
||||
perform createRoleWithGrants(
|
||||
@ -72,15 +73,16 @@ create trigger insertTriggerForTestCustomer_tg
|
||||
after insert on test_customer
|
||||
for each row
|
||||
execute procedure insertTriggerForTestCustomer_tf();
|
||||
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-INSERT:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_customer.
|
||||
Checks if the user or assumed roles are allowed to insert a row to test_customer,
|
||||
where only global-admin has that permission.
|
||||
*/
|
||||
create or replace function test_customer_insert_permission_missing_tf()
|
||||
returns trigger
|
||||
@ -93,12 +95,10 @@ end; $$;
|
||||
create trigger test_customer_insert_permission_check_tg
|
||||
before insert on test_customer
|
||||
for each row
|
||||
-- As there is no explicit INSERT grant specified for this table,
|
||||
-- only global admins are allowed to insert any rows.
|
||||
when ( not isGlobalAdmin() )
|
||||
execute procedure test_customer_insert_permission_missing_tf();
|
||||
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-IDENTITY-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
@ -106,13 +106,15 @@ create trigger test_customer_insert_permission_check_tg
|
||||
call generateRbacIdentityViewFromProjection('test_customer', $idName$
|
||||
prefix
|
||||
$idName$);
|
||||
|
||||
--//
|
||||
|
||||
-- ============================================================================
|
||||
--changeset test-customer-rbac-RESTRICTED-VIEW:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
call generateRbacRestrictedView('test_customer',
|
||||
'reference',
|
||||
$orderBy$
|
||||
reference
|
||||
$orderBy$,
|
||||
$updates$
|
||||
reference = new.reference,
|
||||
prefix = new.prefix,
|
||||
@ -120,4 +122,3 @@ call generateRbacRestrictedView('test_customer',
|
||||
$updates$);
|
||||
--//
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac package
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.624847792.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.484173294.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
@ -1,6 +1,6 @@
|
||||
### rbac domain
|
||||
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-11T11:29:11.644658132.
|
||||
This code generated was by RbacViewMermaidFlowchartGenerator at 2024-03-22T14:44:19.510830235.
|
||||
|
||||
```mermaid
|
||||
%%{init:{'flowchart':{'htmlLabels':false}}}%%
|
||||
|
36
src/main/resources/db/changelog/220-hs-office-relation.sql
Normal file
36
src/main/resources/db/changelog/220-hs-office-relation.sql
Normal file
@ -0,0 +1,36 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TYPE HsOfficeRelationType AS ENUM (
|
||||
'UNKNOWN',
|
||||
'PARTNER',
|
||||
'EX_PARTNER',
|
||||
'REPRESENTATIVE',
|
||||
'DEBITOR',
|
||||
'VIP_CONTACT',
|
||||
'OPERATIONS',
|
||||
'SUBSCRIBER');
|
||||
|
||||
CREATE CAST (character varying as HsOfficeRelationType) WITH INOUT AS IMPLICIT;
|
||||
|
||||
create table if not exists hs_office_relation
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred, -- on delete cascade
|
||||
anchorUuid uuid not null references hs_office_person(uuid),
|
||||
holderUuid uuid not null references hs_office_person(uuid),
|
||||
contactUuid uuid references hs_office_contact(uuid),
|
||||
type HsOfficeRelationType not null,
|
||||
mark varchar(24)
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relation-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_relation');
|
||||
--//
|
@ -1,36 +0,0 @@
|
||||
--liquibase formatted sql
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-MAIN-TABLE:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
CREATE TYPE HsOfficeRelationshipType AS ENUM (
|
||||
'UNKNOWN',
|
||||
'PARTNER',
|
||||
'EX_PARTNER',
|
||||
'REPRESENTATIVE',
|
||||
'VIP_CONTACT',
|
||||
'ACCOUNTING',
|
||||
'OPERATIONS',
|
||||
'SUBSCRIBER');
|
||||
|
||||
CREATE CAST (character varying as HsOfficeRelationshipType) WITH INOUT AS IMPLICIT;
|
||||
|
||||
create table if not exists hs_office_relationship
|
||||
(
|
||||
uuid uuid unique references RbacObject (uuid) initially deferred, -- on delete cascade
|
||||
relAnchorUuid uuid not null references hs_office_person(uuid),
|
||||
relHolderUuid uuid not null references hs_office_person(uuid),
|
||||
contactUuid uuid references hs_office_contact(uuid),
|
||||
relType HsOfficeRelationshipType not null,
|
||||
relMark varchar(24)
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset hs-office-relationship-MAIN-TABLE-JOURNAL:1 endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
call create_journal('hs_office_relationship');
|
||||
--//
|
@ -70,11 +70,11 @@ databaseChangeLog:
|
||||
- include:
|
||||
file: db/changelog/218-hs-office-person-test-data.sql
|
||||
- include:
|
||||
file: db/changelog/220-hs-office-relationship.sql
|
||||
file: db/changelog/220-hs-office-relation.sql
|
||||
- include:
|
||||
file: db/changelog/223-hs-office-relationship-rbac.sql
|
||||
file: db/changelog/223-hs-office-relation-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/228-hs-office-relationship-test-data.sql
|
||||
file: db/changelog/228-hs-office-relation-test-data.sql
|
||||
- include:
|
||||
file: db/changelog/230-hs-office-partner.sql
|
||||
- include:
|
||||
|
@ -41,7 +41,7 @@ public class ArchitectureTest {
|
||||
"..hs.office.migration",
|
||||
"..hs.office.partner",
|
||||
"..hs.office.person",
|
||||
"..hs.office.relationship",
|
||||
"..hs.office.relation",
|
||||
"..hs.office.sepamandate",
|
||||
"..errors",
|
||||
"..mapper",
|
||||
@ -148,7 +148,7 @@ public class ArchitectureTest {
|
||||
public static final ArchRule hsOfficeContactPackageRule = classes()
|
||||
.that().resideInAPackage("..hs.office.contact..")
|
||||
.should().onlyBeAccessed().byClassesThat()
|
||||
.resideInAnyPackage("..hs.office.contact..", "..hs.office.relationship..",
|
||||
.resideInAnyPackage("..hs.office.contact..", "..hs.office.relation..",
|
||||
"..hs.office.partner..",
|
||||
"..hs.office.debitor..",
|
||||
"..hs.office.membership..",
|
||||
@ -159,7 +159,7 @@ public class ArchitectureTest {
|
||||
public static final ArchRule hsOfficePersonPackageRule = classes()
|
||||
.that().resideInAPackage("..hs.office.person..")
|
||||
.should().onlyBeAccessed().byClassesThat()
|
||||
.resideInAnyPackage("..hs.office.person..", "..hs.office.relationship..",
|
||||
.resideInAnyPackage("..hs.office.person..", "..hs.office.relation..",
|
||||
"..hs.office.partner..",
|
||||
"..hs.office.debitor..",
|
||||
"..hs.office.membership..",
|
||||
@ -167,10 +167,10 @@ public class ArchitectureTest {
|
||||
|
||||
@ArchTest
|
||||
@SuppressWarnings("unused")
|
||||
public static final ArchRule hsOfficeRelationshipPackageRule = classes()
|
||||
.that().resideInAPackage("..hs.office.relationship..")
|
||||
public static final ArchRule hsOfficeRelationPackageRule = classes()
|
||||
.that().resideInAPackage("..hs.office.relation..")
|
||||
.should().onlyBeAccessed().byClassesThat()
|
||||
.resideInAnyPackage("..hs.office.relationship..",
|
||||
.resideInAnyPackage("..hs.office.relation..",
|
||||
"..hs.office.partner..",
|
||||
"..hs.office.migration..");
|
||||
|
||||
|
@ -18,8 +18,8 @@ import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerDetailsEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.relationship.HsOfficeRelationshipType;
|
||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationType;
|
||||
import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
|
||||
import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
|
||||
import net.hostsharing.test.JpaAttempt;
|
||||
@ -127,7 +127,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
new String[]{"partner", "vip-contact", "ex-partner", "billing", "contractual", "operation"},
|
||||
SUBSCRIBER_ROLES);
|
||||
|
||||
static int relationshipId = 2000000;
|
||||
static int relationId = 2000000;
|
||||
|
||||
@Value("${spring.datasource.url}")
|
||||
private String jdbcUrl;
|
||||
@ -144,7 +144,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
private static Map<Integer, HsOfficeDebitorEntity> debitors = new WriteOnceMap<>();
|
||||
private static Map<Integer, HsOfficeMembershipEntity> memberships = new WriteOnceMap<>();
|
||||
|
||||
private static Map<Integer, HsOfficeRelationshipEntity> relationships = new WriteOnceMap<>();
|
||||
private static Map<Integer, HsOfficeRelationEntity> relations = new WriteOnceMap<>();
|
||||
private static Map<Integer, HsOfficeSepaMandateEntity> sepaMandates = new WriteOnceMap<>();
|
||||
private static Map<Integer, HsOfficeBankAccountEntity> bankAccounts = new WriteOnceMap<>();
|
||||
private static Map<Integer, HsOfficeCoopSharesTransactionEntity> coopShares = new WriteOnceMap<>();
|
||||
@ -161,6 +161,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
|
||||
@MockBean
|
||||
HttpServletRequest request;
|
||||
|
||||
@Test
|
||||
@Order(1010)
|
||||
void importBusinessPartners() {
|
||||
@ -174,33 +175,33 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1011)
|
||||
@Order(1019)
|
||||
void verifyBusinessPartners() {
|
||||
assumeThatWeAreImportingControlledTestData();
|
||||
|
||||
// no contacts yet => mostly null values
|
||||
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
17=partner(P-10017: null null, null),
|
||||
20=partner(P-10020: null null, null),
|
||||
22=partner(P-11022: null null, null),
|
||||
99=partner(P-19999: null null, null)
|
||||
17=partner(null null, null),
|
||||
20=partner(null null, null),
|
||||
22=partner(null null, null),
|
||||
99=partner(null null, null)
|
||||
}
|
||||
""");
|
||||
assertThat(toFormattedString(contacts)).isEqualTo("{}");
|
||||
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
17=debitor(D-1001700: P-10017, mih),
|
||||
20=debitor(D-1002000: P-10020, xyz),
|
||||
22=debitor(D-1102200: P-11022, xxx),
|
||||
99=debitor(D-1999900: P-19999, zzz)
|
||||
17=debitor(D-1001700: null null, null: mih),
|
||||
20=debitor(D-1002000: null null, null: xyz),
|
||||
22=debitor(D-1102200: null null, null: xxx),
|
||||
99=debitor(D-1999900: null null, null: zzz)
|
||||
}
|
||||
""");
|
||||
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
17=Membership(M-1001700, P-10017, D-1001700, [2000-12-06,), NONE),
|
||||
20=Membership(M-1002000, P-10020, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
|
||||
22=Membership(M-1102200, P-11022, D-1102200, [2021-04-01,), NONE)
|
||||
17=Membership(M-1001700, null null, null, D-1001700, [2000-12-06,), NONE),
|
||||
20=Membership(M-1002000, null null, null, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
|
||||
22=Membership(M-1102200, null null, null, D-1102200, [2021-04-01,), NONE)
|
||||
}
|
||||
""");
|
||||
}
|
||||
@ -219,15 +220,32 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
|
||||
@Test
|
||||
@Order(1021)
|
||||
void buildDebitorRelations() {
|
||||
debitors.forEach( (id, debitor) -> {
|
||||
final var debitorRel = HsOfficeRelationEntity.builder()
|
||||
.type(HsOfficeRelationType.DEBITOR)
|
||||
.anchor(debitor.getPartner().getPartnerRel().getHolder())
|
||||
.holder(debitor.getPartner().getPartnerRel().getHolder()) // just 1 debitor/partner in legacy hsadmin
|
||||
.contact(debitor.getBillingContact())
|
||||
.build();
|
||||
if (debitorRel.getAnchor() != null && debitorRel.getHolder() != null &&
|
||||
debitorRel.getContact() != null ) {
|
||||
relations.put(relationId++, debitorRel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1029)
|
||||
void verifyContacts() {
|
||||
assumeThatWeAreImportingControlledTestData();
|
||||
|
||||
assertThat(toFormattedString(partners)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
17=partner(P-10017: NP Mellies, Michael, Herr Michael Mellies ),
|
||||
20=partner(P-10020: LP JM GmbH, Herr Philip Meyer-Contract , JM GmbH),
|
||||
22=partner(P-11022: ?? Test PS, Petra Schmidt , Test PS),
|
||||
99=partner(P-19999: null null, null)
|
||||
17=partner(NP Mellies, Michael: Herr Michael Mellies ),
|
||||
20=partner(LP JM GmbH: Herr Philip Meyer-Contract , JM GmbH),
|
||||
22=partner(?? Test PS: Petra Schmidt , Test PS),
|
||||
99=partner(null null, null)
|
||||
}
|
||||
""");
|
||||
assertThat(toFormattedString(contacts)).isEqualToIgnoringWhitespace("""
|
||||
@ -257,38 +275,41 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
""");
|
||||
assertThat(toFormattedString(debitors)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
17=debitor(D-1001700: P-10017, mih),
|
||||
20=debitor(D-1002000: P-10020, xyz),
|
||||
22=debitor(D-1102200: P-11022, xxx),
|
||||
99=debitor(D-1999900: P-19999, zzz)
|
||||
17=debitor(D-1001700: NP Mellies, Michael: mih),
|
||||
20=debitor(D-1002000: LP JM GmbH: xyz),
|
||||
22=debitor(D-1102200: ?? Test PS: xxx),
|
||||
99=debitor(D-1999900: null null, null: zzz)
|
||||
}
|
||||
""");
|
||||
assertThat(toFormattedString(memberships)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
17=Membership(M-1001700, P-10017, D-1001700, [2000-12-06,), NONE),
|
||||
20=Membership(M-1002000, P-10020, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
|
||||
22=Membership(M-1102200, P-11022, D-1102200, [2021-04-01,), NONE)
|
||||
17=Membership(M-1001700, NP Mellies, Michael, D-1001700, [2000-12-06,), NONE),
|
||||
20=Membership(M-1002000, LP JM GmbH, D-1002000, [2000-12-06,2016-01-01), UNKNOWN),
|
||||
22=Membership(M-1102200, ?? Test PS, D-1102200, [2021-04-01,), NONE)
|
||||
}
|
||||
""");
|
||||
assertThat(toFormattedString(relationships)).isEqualToIgnoringWhitespace("""
|
||||
assertThat(toFormattedString(relations)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
2000000=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||
2000001=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||
2000002=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||
2000003=rel(relAnchor='LP Hostsharing eG', relType='PARTNER', relHolder='null null, null'),
|
||||
2000004=rel(relAnchor='NP Mellies, Michael', relType='OPERATIONS', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||
2000005=rel(relAnchor='NP Mellies, Michael', relType='REPRESENTATIVE', relHolder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||
2000006=rel(relAnchor='LP JM GmbH', relType='EX_PARTNER', relHolder='LP JM e.K.', contact='JM e.K.'),
|
||||
2000007=rel(relAnchor='LP JM GmbH', relType='OPERATIONS', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||
2000008=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||
2000009=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='operations-announce', relHolder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||
2000010=rel(relAnchor='LP JM GmbH', relType='REPRESENTATIVE', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||
2000011=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='members-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||
2000012=rel(relAnchor='LP JM GmbH', relType='SUBSCRIBER', relMark='customers-announce', relHolder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||
2000013=rel(relAnchor='LP JM GmbH', relType='VIP_CONTACT', relHolder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
|
||||
2000014=rel(relAnchor='?? Test PS', relType='OPERATIONS', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||
2000015=rel(relAnchor='?? Test PS', relType='REPRESENTATIVE', relHolder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||
2000016=rel(relAnchor='NP Mellies, Michael', relType='SUBSCRIBER', relMark='operations-announce', relHolder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ')
|
||||
2000000=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||
2000001=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||
2000002=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||
2000003=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'),
|
||||
2000004=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||
2000005=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||
2000006=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
|
||||
2000007=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||
2000008=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||
2000009=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
|
||||
2000010=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||
2000011=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||
2000012=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
|
||||
2000013=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
|
||||
2000014=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||
2000015=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
|
||||
2000016=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga '),
|
||||
2000017=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
|
||||
2000018=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
|
||||
2000019=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS')
|
||||
}
|
||||
""");
|
||||
}
|
||||
@ -306,15 +327,15 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1031)
|
||||
@Order(1039)
|
||||
void verifySepaMandates() {
|
||||
assumeThatWeAreImportingControlledTestData();
|
||||
|
||||
assertThat(toFormattedString(bankAccounts)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
234234=bankAccount(DE37500105177419788228: holder='Michael Mellies', bic='INGDDEFFXXX'),
|
||||
235600=bankAccount(DE02300209000106531065: holder='JM e.K.', bic='CMCIDEDD'),
|
||||
235662=bankAccount(DE49500105174516484892: holder='JM GmbH', bic='INGDDEFFXXX')
|
||||
234234=bankAccount(holder='Michael Mellies', iban='DE37500105177419788228', bic='INGDDEFFXXX'),
|
||||
235600=bankAccount(holder='JM e.K.', iban='DE02300209000106531065', bic='CMCIDEDD'),
|
||||
235662=bankAccount(holder='JM GmbH', iban='DE49500105174516484892', bic='INGDDEFFXXX')
|
||||
}
|
||||
""");
|
||||
assertThat(toFormattedString(sepaMandates)).isEqualToIgnoringWhitespace("""
|
||||
@ -338,7 +359,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1041)
|
||||
@Order(1049)
|
||||
void verifyCoopShares() {
|
||||
assumeThatWeAreImportingControlledTestData();
|
||||
|
||||
@ -365,55 +386,53 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1051)
|
||||
@Order(1059)
|
||||
void verifyCoopAssets() {
|
||||
assumeThatWeAreImportingControlledTestData();
|
||||
|
||||
assertThat(toFormattedString(coopAssets)).isEqualToIgnoringWhitespace("""
|
||||
{
|
||||
30000=CoopAssetsTransaction(M-1001700: 2000-12-06, DEPOSIT, 1280.00, for subscription A),
|
||||
31000=CoopAssetsTransaction(M-1002000: 2000-12-06, DEPOSIT, 128.00, for subscription B),
|
||||
32000=CoopAssetsTransaction(M-1001700: 2005-01-10, DEPOSIT, 2560.00, for subscription C),
|
||||
33001=CoopAssetsTransaction(M-1001700: 2005-01-10, TRANSFER, -512.00, for transfer to 10),
|
||||
33002=CoopAssetsTransaction(M-1002000: 2005-01-10, ADOPTION, 512.00, for transfer from 7),
|
||||
34001=CoopAssetsTransaction(M-1002000: 2016-12-31, CLEARING, -8.00, for cancellation D),
|
||||
34002=CoopAssetsTransaction(M-1002000: 2016-12-31, DISBURSAL, -100.00, for cancellation D),
|
||||
34003=CoopAssetsTransaction(M-1002000: 2016-12-31, LOSS, -20.00, for cancellation D)
|
||||
30000=CoopAssetsTransaction(1001700, 2000-12-06, DEPOSIT, 1280.00, for subscription A),
|
||||
31000=CoopAssetsTransaction(1002000, 2000-12-06, DEPOSIT, 128.00, for subscription B),
|
||||
32000=CoopAssetsTransaction(1001700, 2005-01-10, DEPOSIT, 2560.00, for subscription C),
|
||||
33001=CoopAssetsTransaction(1001700, 2005-01-10, TRANSFER, -512.00, for transfer to 10),
|
||||
33002=CoopAssetsTransaction(1002000, 2005-01-10, ADOPTION, 512.00, for transfer from 7),
|
||||
34001=CoopAssetsTransaction(1002000, 2016-12-31, CLEARING, -8.00, for cancellation D),
|
||||
34002=CoopAssetsTransaction(1002000, 2016-12-31, DISBURSAL, -100.00, for cancellation D),
|
||||
34003=CoopAssetsTransaction(1002000, 2016-12-31, LOSS, -20.00, for cancellation D)
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2000)
|
||||
void verifyAllPartnersHaveProperPartnerRoles() {
|
||||
void verifyAllPartnersHavePersons() {
|
||||
partners.forEach((id, p) -> {
|
||||
final var partnerRole = p.getPartnerRole();
|
||||
assertThat(partnerRole).describedAs("partner " + id + " without partnerRole").isNotNull();
|
||||
if ( id != 99 ) {
|
||||
assertThat(partnerRole.getContact()).describedAs("partner " + id + " without partnerRole.contact").isNotNull();
|
||||
assertThat(partnerRole.getContact().getLabel()).describedAs("partner " + id + " without valid partnerRole.contact").isNotNull();
|
||||
assertThat(partnerRole.getRelHolder()).describedAs("partner " + id + " without partnerRole.relHolder").isNotNull();
|
||||
assertThat(partnerRole.getRelHolder().getPersonType()).describedAs("partner " + id + " without valid partnerRole.relHolder").isNotNull();
|
||||
assertThat(p.getContact()).describedAs("partner " + id + " without contact").isNotNull();
|
||||
assertThat(p.getContact().getLabel()).describedAs("partner " + id + " without valid contact").isNotNull();
|
||||
assertThat(p.getPerson()).describedAs("partner " + id + " without person").isNotNull();
|
||||
assertThat(p.getPerson().getPersonType()).describedAs("partner " + id + " without valid person").isNotNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2001)
|
||||
void removeEmptyRelationships() {
|
||||
@Order(2009)
|
||||
void removeEmptyRelations() {
|
||||
assumeThatWeAreImportingControlledTestData();
|
||||
|
||||
// avoid a error when persisting the deliberetely invalid partner entry #99
|
||||
final var idsToRemove = new HashSet<Integer>();
|
||||
relationships.forEach( (id, r) -> {
|
||||
relations.forEach( (id, r) -> {
|
||||
// such a record
|
||||
if (r.getContact() == null || r.getContact().getLabel() == null ||
|
||||
r.getRelHolder() == null | r.getRelHolder().getPersonType() == null ) {
|
||||
r.getHolder() == null | r.getHolder().getPersonType() == null ) {
|
||||
idsToRemove.add(id);
|
||||
}
|
||||
});
|
||||
assertThat(idsToRemove.size()).isEqualTo(1); // only from partner #99 (partner+contractual roles)
|
||||
idsToRemove.forEach(id -> relationships.remove(id));
|
||||
idsToRemove.forEach(id -> relations.remove(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -424,11 +443,9 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
// avoid a error when persisting the deliberately invalid partner entry #99
|
||||
final var idsToRemove = new HashSet<Integer>();
|
||||
partners.forEach( (id, r) -> {
|
||||
final var partnerRole = r.getPartnerRole();
|
||||
|
||||
// such a record is in test data to test error messages
|
||||
if (partnerRole.getContact() == null || partnerRole.getContact().getLabel() == null ||
|
||||
partnerRole.getRelHolder() == null | partnerRole.getRelHolder().getPersonType() == null ) {
|
||||
// such a record
|
||||
if (r.getContact() == null || r.getContact().getLabel() == null ||
|
||||
r.getPerson() == null | r.getPerson().getPersonType() == null ) {
|
||||
idsToRemove.add(id);
|
||||
}
|
||||
});
|
||||
@ -443,9 +460,10 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
|
||||
// avoid a error when persisting the deliberately invalid partner entry #99
|
||||
final var idsToRemove = new HashSet<Integer>();
|
||||
debitors.forEach( (id, d) -> {
|
||||
// such a record is in test data to test error messages
|
||||
if (false) { // TODO: how can I now empty debitors?
|
||||
debitors.forEach( (id, r) -> {
|
||||
// such a record
|
||||
if (r.getBillingContact() == null || r.getBillingContact().getLabel() == null ||
|
||||
r.getPartner().getPerson() == null | r.getPartner().getPerson().getPersonType() == null ) {
|
||||
idsToRemove.add(id);
|
||||
}
|
||||
});
|
||||
@ -454,7 +472,6 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
@Order(3000)
|
||||
@Commit
|
||||
void persistEntities() {
|
||||
@ -478,7 +495,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
|
||||
jpaAttempt.transacted(() -> {
|
||||
context(rbacSuperuser);
|
||||
relationships.forEach(this::persist);
|
||||
relations.forEach(this::persist);
|
||||
}).assertSuccessful();
|
||||
|
||||
jpaAttempt.transacted(() -> {
|
||||
@ -555,7 +572,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
em.createNativeQuery("delete from hs_office_bankaccount where true").executeUpdate();
|
||||
em.createNativeQuery("delete from hs_office_partner where true").executeUpdate();
|
||||
em.createNativeQuery("delete from hs_office_partner_details where true").executeUpdate();
|
||||
em.createNativeQuery("delete from hs_office_relationship where true").executeUpdate();
|
||||
em.createNativeQuery("delete from hs_office_relation where true").executeUpdate();
|
||||
em.createNativeQuery("delete from hs_office_contact where true").executeUpdate();
|
||||
em.createNativeQuery("delete from hs_office_person where true").executeUpdate();
|
||||
}).assertSuccessful();
|
||||
@ -659,31 +676,28 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
.forEach(rec -> {
|
||||
final var person = HsOfficePersonEntity.builder().build();
|
||||
|
||||
final var partnerRelationship = HsOfficeRelationshipEntity.builder()
|
||||
.relHolder(person)
|
||||
.relType(HsOfficeRelationshipType.PARTNER)
|
||||
.relAnchor(mandant)
|
||||
final var partnerRelation = HsOfficeRelationEntity.builder()
|
||||
.holder(person)
|
||||
.type(HsOfficeRelationType.PARTNER)
|
||||
.anchor(mandant)
|
||||
.contact(null) // is set during contacts import depending on assigned roles
|
||||
.build();
|
||||
relationships.put(relationshipId++, partnerRelationship);
|
||||
relations.put(relationId++, partnerRelation);
|
||||
|
||||
final var partner = HsOfficePartnerEntity.builder()
|
||||
.partnerNumber(rec.getInteger("member_id"))
|
||||
.details(HsOfficePartnerDetailsEntity.builder().build())
|
||||
.partnerRole(partnerRelationship)
|
||||
.partnerRel(partnerRelation)
|
||||
.contact(null) // is set during contacts import depending on assigned roles
|
||||
.person(person)
|
||||
.build();
|
||||
partners.put(rec.getInteger("bp_id"), partner);
|
||||
|
||||
final var debitor = HsOfficeDebitorEntity.builder()
|
||||
.partner(partner)
|
||||
.debitorNumberSuffix((byte) 0)
|
||||
.debitorRel(
|
||||
HsOfficeRelationshipEntity.builder()
|
||||
.relType(HsOfficeRelationshipType.ACCOUNTING)
|
||||
.relAnchor(partnerRelationship.getRelHolder())
|
||||
.relHolder(null) // gets set later
|
||||
.build()
|
||||
)
|
||||
.defaultPrefix(rec.getString("member_code").replace("hsh00-", ""))
|
||||
.partner(partner)
|
||||
.billable(rec.isEmpty("free") || rec.getString("free").equals("f"))
|
||||
.vatReverseCharge(rec.getBoolean("exempt_vat"))
|
||||
.vatBusiness("GROSS".equals(rec.getString("indicator_vat"))) // TODO: remove
|
||||
@ -704,6 +718,7 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
isBlank(rec.getString("member_until"))
|
||||
? HsOfficeReasonForTermination.NONE
|
||||
: HsOfficeReasonForTermination.UNKNOWN)
|
||||
.mainDebitor(debitor)
|
||||
.build();
|
||||
memberships.put(rec.getInteger("bp_id"), membership);
|
||||
}
|
||||
@ -829,9 +844,9 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
final var partner = partners.get(bpId);
|
||||
final var debitor = debitors.get(bpId);
|
||||
|
||||
final var partnerPerson = partner.getPartnerRole().getRelHolder();
|
||||
if (containsPartnerRole(rec)) {
|
||||
initPerson(partnerPerson, rec);
|
||||
final var partnerPerson = partner.getPerson();
|
||||
if (containsPartnerRel(rec)) {
|
||||
initPerson(partner.getPerson(), rec);
|
||||
}
|
||||
|
||||
HsOfficePersonEntity contactPerson = partnerPerson;
|
||||
@ -844,71 +859,72 @@ public class ImportOfficeData extends ContextBasedTest {
|
||||
final var contact = HsOfficeContactEntity.builder().build();
|
||||
initContact(contact, rec);
|
||||
|
||||
if (containsPartnerRole(rec)) {
|
||||
assertThat(partner.getPartnerRole().getContact()).isNull();
|
||||
partner.getPartnerRole().setContact(contact);
|
||||
if (containsPartnerRel(rec)) {
|
||||
assertThat(partner.getContact()).isNull();
|
||||
partner.setContact(contact);
|
||||
partner.getPartnerRel().setContact(contact);
|
||||
}
|
||||
if (containsRole(rec, "billing")) {
|
||||
assertThat(debitor.getDebitorRel().getContact()).isNull();
|
||||
debitor.getDebitorRel().setContact(contact);
|
||||
assertThat(debitor.getBillingContact()).isNull();
|
||||
debitor.setBillingContact(contact);
|
||||
}
|
||||
if (containsRole(rec, "operation")) {
|
||||
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.OPERATIONS);
|
||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.OPERATIONS);
|
||||
}
|
||||
if (containsRole(rec, "contractual")) {
|
||||
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.REPRESENTATIVE);
|
||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.REPRESENTATIVE);
|
||||
}
|
||||
if (containsRole(rec, "ex-partner")) {
|
||||
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.EX_PARTNER);
|
||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.EX_PARTNER);
|
||||
}
|
||||
if (containsRole(rec, "vip-contact")) {
|
||||
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.VIP_CONTACT);
|
||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.VIP_CONTACT);
|
||||
}
|
||||
for (String subscriberRole: SUBSCRIBER_ROLES) {
|
||||
if (containsRole(rec, subscriberRole)) {
|
||||
addRelationship(partnerPerson, contactPerson, contact, HsOfficeRelationshipType.SUBSCRIBER)
|
||||
.setRelMark(subscriberRole.split(":")[1])
|
||||
addRelation(partnerPerson, contactPerson, contact, HsOfficeRelationType.SUBSCRIBER)
|
||||
.setMark(subscriberRole.split(":")[1])
|
||||
;
|
||||
}
|
||||
}
|
||||
verifyContainsOnlyKnownRoles(rec.getString("roles"));
|
||||
});
|
||||
|
||||
optionallyAddMissingContractualRelationships();
|
||||
optionallyAddMissingContractualRelations();
|
||||
}
|
||||
|
||||
private static void optionallyAddMissingContractualRelationships() {
|
||||
private static void optionallyAddMissingContractualRelations() {
|
||||
final var contractualMissing = new HashSet<Integer>();
|
||||
partners.forEach( (id, partner) -> {
|
||||
final var partnerPerson = partner.getPartnerRole().getRelHolder();
|
||||
if (relationships.values().stream()
|
||||
.filter(rel -> rel.getRelAnchor() == partnerPerson && rel.getRelType() == HsOfficeRelationshipType.REPRESENTATIVE)
|
||||
final var partnerPerson = partner.getPerson();
|
||||
if (relations.values().stream()
|
||||
.filter(rel -> rel.getAnchor() == partnerPerson && rel.getType() == HsOfficeRelationType.REPRESENTATIVE)
|
||||
.findFirst().isEmpty()) {
|
||||
contractualMissing.add(partner.getPartnerNumber());
|
||||
}
|
||||
});
|
||||
assertThat(contractualMissing).containsOnly(19999); // deliberately wrong partner entry
|
||||
}
|
||||
private static boolean containsRole(final Record rec, final String role) {
|
||||
final var roles = rec.getString("roles");
|
||||
return ("," + roles + ",").contains("," + role + ",");
|
||||
}
|
||||
private static boolean containsPartnerRole(final Record rec) {
|
||||
|
||||
private static boolean containsPartnerRel(final Record rec) {
|
||||
return containsRole(rec, "partner");
|
||||
}
|
||||
|
||||
private static HsOfficeRelationshipEntity addRelationship(
|
||||
private static HsOfficeRelationEntity addRelation(
|
||||
final HsOfficePersonEntity partnerPerson,
|
||||
final HsOfficePersonEntity contactPerson,
|
||||
final HsOfficeContactEntity contact,
|
||||
final HsOfficeRelationshipType representative) {
|
||||
final var rel = HsOfficeRelationshipEntity.builder()
|
||||
.relAnchor(partnerPerson)
|
||||
.relHolder(contactPerson)
|
||||
final HsOfficeRelationType representative) {
|
||||
final var rel = HsOfficeRelationEntity.builder()
|
||||
.anchor(partnerPerson)
|
||||
.holder(contactPerson)
|
||||
.contact(contact)
|
||||
.relType(representative)
|
||||
.type(representative)
|
||||
.build();
|
||||
relationships.put(relationshipId++, rel);
|
||||
relations.put(relationId++, rel);
|
||||
return rel;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||
package net.hostsharing.hsadminng.hs.office.relation;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationshipPatchResource;
|
||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeRelationPatchResource;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||
import net.hostsharing.test.PatchUnitTestBase;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -21,12 +21,12 @@ import static org.mockito.Mockito.lenient;
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HsOfficeRelationshipEntityPatcherUnitTest extends PatchUnitTestBase<
|
||||
HsOfficeRelationshipPatchResource,
|
||||
HsOfficeRelationshipEntity
|
||||
class HsOfficeRelationEntityPatcherUnitTest extends PatchUnitTestBase<
|
||||
HsOfficeRelationPatchResource,
|
||||
HsOfficeRelationEntity
|
||||
> {
|
||||
|
||||
static final UUID INITIAL_RELATIONSHIP_UUID = UUID.randomUUID();
|
||||
static final UUID INITIAL_RELATION_UUID = UUID.randomUUID();
|
||||
static final UUID PATCHED_CONTACT_UUID = UUID.randomUUID();
|
||||
|
||||
@Mock
|
||||
@ -49,24 +49,24 @@ class HsOfficeRelationshipEntityPatcherUnitTest extends PatchUnitTestBase<
|
||||
.build();
|
||||
|
||||
@Override
|
||||
protected HsOfficeRelationshipEntity newInitialEntity() {
|
||||
final var entity = new HsOfficeRelationshipEntity();
|
||||
entity.setUuid(INITIAL_RELATIONSHIP_UUID);
|
||||
entity.setRelType(HsOfficeRelationshipType.REPRESENTATIVE);
|
||||
entity.setRelAnchor(givenInitialAnchorPerson);
|
||||
entity.setRelHolder(givenInitialHolderPerson);
|
||||
protected HsOfficeRelationEntity newInitialEntity() {
|
||||
final var entity = new HsOfficeRelationEntity();
|
||||
entity.setUuid(INITIAL_RELATION_UUID);
|
||||
entity.setType(HsOfficeRelationType.REPRESENTATIVE);
|
||||
entity.setAnchor(givenInitialAnchorPerson);
|
||||
entity.setHolder(givenInitialHolderPerson);
|
||||
entity.setContact(givenInitialContact);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HsOfficeRelationshipPatchResource newPatchResource() {
|
||||
return new HsOfficeRelationshipPatchResource();
|
||||
protected HsOfficeRelationPatchResource newPatchResource() {
|
||||
return new HsOfficeRelationPatchResource();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HsOfficeRelationshipEntityPatcher createPatcher(final HsOfficeRelationshipEntity relationship) {
|
||||
return new HsOfficeRelationshipEntityPatcher(em, relationship);
|
||||
protected HsOfficeRelationEntityPatcher createPatcher(final HsOfficeRelationEntity relation) {
|
||||
return new HsOfficeRelationEntityPatcher(em, relation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,9 +74,9 @@ class HsOfficeRelationshipEntityPatcherUnitTest extends PatchUnitTestBase<
|
||||
return Stream.of(
|
||||
new JsonNullableProperty<>(
|
||||
"contact",
|
||||
HsOfficeRelationshipPatchResource::setContactUuid,
|
||||
HsOfficeRelationPatchResource::setContactUuid,
|
||||
PATCHED_CONTACT_UUID,
|
||||
HsOfficeRelationshipEntity::setContact,
|
||||
HsOfficeRelationEntity::setContact,
|
||||
newContact(PATCHED_CONTACT_UUID))
|
||||
.notNullable()
|
||||
);
|
@ -0,0 +1,43 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relation;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class HsOfficeRelationEntityUnitTest {
|
||||
|
||||
private HsOfficePersonEntity anchor = HsOfficePersonEntity.builder()
|
||||
.personType(HsOfficePersonType.LEGAL_PERSON)
|
||||
.tradeName("some trade name")
|
||||
.build();
|
||||
private HsOfficePersonEntity holder = HsOfficePersonEntity.builder()
|
||||
.personType(HsOfficePersonType.NATURAL_PERSON)
|
||||
.familyName("Meier")
|
||||
.givenName("Mellie")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
void toStringReturnsAllProperties() {
|
||||
final var given = HsOfficeRelationEntity.builder()
|
||||
.type(HsOfficeRelationType.SUBSCRIBER)
|
||||
.mark("members-announce")
|
||||
.anchor(anchor)
|
||||
.holder(holder)
|
||||
.build();
|
||||
|
||||
assertThat(given.toString()).isEqualTo("rel(anchor='LP some trade name', type='SUBSCRIBER', mark='members-announce', holder='NP Meier, Mellie')");
|
||||
}
|
||||
|
||||
@Test
|
||||
void toShortString() {
|
||||
final var given = HsOfficeRelationEntity.builder()
|
||||
.type(HsOfficeRelationType.REPRESENTATIVE)
|
||||
.anchor(anchor)
|
||||
.holder(holder)
|
||||
.build();
|
||||
|
||||
assertThat(given.toShortString()).isEqualTo("rel(anchor='LP some trade name', type='REPRESENTATIVE', holder='NP Meier, Mellie')");
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package net.hostsharing.hsadminng.hs.office.relationship;
|
||||
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
|
||||
import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class HsOfficeRelationshipEntityUnitTest {
|
||||
|
||||
private HsOfficePersonEntity anchor = HsOfficePersonEntity.builder()
|
||||
.personType(HsOfficePersonType.LEGAL_PERSON)
|
||||
.tradeName("some trade name")
|
||||
.build();
|
||||
private HsOfficePersonEntity holder = HsOfficePersonEntity.builder()
|
||||
.personType(HsOfficePersonType.NATURAL_PERSON)
|
||||
.familyName("Meier")
|
||||
.givenName("Mellie")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
void toStringReturnsAllProperties() {
|
||||
final var given = HsOfficeRelationshipEntity.builder()
|
||||
.relType(HsOfficeRelationshipType.SUBSCRIBER)
|
||||
.relMark("members-announce")
|
||||
.relAnchor(anchor)
|
||||
.relHolder(holder)
|
||||
.build();
|
||||
|
||||
assertThat(given.toString()).isEqualTo("rel(relAnchor='LP some trade name', relType='SUBSCRIBER', relMark='members-announce', relHolder='NP Meier, Mellie')");
|
||||
}
|
||||
|
||||
@Test
|
||||
void toShortString() {
|
||||
final var given = HsOfficeRelationshipEntity.builder()
|
||||
.relType(HsOfficeRelationshipType.REPRESENTATIVE)
|
||||
.relAnchor(anchor)
|
||||
.relHolder(holder)
|
||||
.build();
|
||||
|
||||
assertThat(given.toShortString()).isEqualTo("rel(relAnchor='LP some trade name', relType='REPRESENTATIVE', relHolder='NP Meier, Mellie')");
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
sourceLower=partner
|
||||
targetLower=relationship
|
||||
|
||||
sourceStudly=Partner
|
||||
targetStudly=Relationship
|
||||
|
||||
## for source in `find src -iname ""*$sourceLower*"" -type f \( -iname \*.yaml -o -iname \*.sql -o -iname \*.java \)`; do
|
||||
for source in `find src -iname ""*$sourceLower*"" -type f \( -iname \*.yaml \)`; do
|
||||
target=`echo $source | sed -e "s/$sourceStudly/$targetStudly/g" -e "s/$sourceLower/$targetLower/g"`
|
||||
echo "Generating $target from $source:"
|
||||
|
||||
mkdir -p `dirname $target`
|
||||
|
||||
sed -e 's/hs-office-partner/hs-office-relationship/g' \
|
||||
-e 's/hs_office_partner/hs_office_relationship/g' \
|
||||
-e 's/HsOfficePartner/HsOfficeRelationship/g' \
|
||||
-e 's/hsOfficePartner/hsOfficeRelationship/g' \
|
||||
-e 's/partner/relationship/g' \
|
||||
\
|
||||
-e 's/addPartner/addRelationship/g' \
|
||||
-e 's/listPartners/listRelationships/g' \
|
||||
-e 's/getPartnerByUuid/getRelationshipByUuid/g' \
|
||||
-e 's/patchPartner/patchRelationship/g' \
|
||||
-e 's/person/relHolder/g' \
|
||||
-e 's/registrationOffice/relType/g' \
|
||||
<$source >$target
|
||||
|
||||
done
|
||||
|
||||
exit
|
||||
|
||||
cat >>src/main/resources/db/changelog/db.changelog-master.yaml <<EOF
|
||||
- include:
|
||||
file: db/changelog/2X0-hs-office-$sourceLower.sql
|
||||
- include:
|
||||
file: db/changelog/2X3-hs-office-$sourceLower-rbac.sql
|
||||
- include:
|
||||
file: db/changelog/2X8-hs-office-$sourceLower-test-data.sql
|
||||
EOF
|
Loading…
Reference in New Issue
Block a user