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