diff --git a/build.gradle b/build.gradle index 876ff878..fc287915 100644 --- a/build.gradle +++ b/build.gradle @@ -445,3 +445,8 @@ tasks.register('convertMarkdownToHtml') { } } convertMarkdownToHtml.dependsOn scenarioTests + +// shortcut for compiling all files +tasks.register('compile') { + dependsOn 'compileJava', 'compileTestJava' +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java index 06bec54e..83c42e7b 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionController.java @@ -1,9 +1,13 @@ package net.hostsharing.hsadminng.hs.office.coopassets; import net.hostsharing.hsadminng.context.Context; -import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeCoopAssetsApi; -import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.*; import net.hostsharing.hsadminng.errors.MultiValidationException; +import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficeCoopAssetsApi; +import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionInsertResource; +import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionResource; +import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource; +import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity; +import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipRepository; import net.hostsharing.hsadminng.mapper.StandardMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.annotation.DateTimeFormat; @@ -20,7 +24,11 @@ import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; -import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.*; +import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.CLEARING; +import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.DEPOSIT; +import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.DISBURSAL; +import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.LOSS; +import static net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeCoopAssetsTransactionTypeResource.TRANSFER; @RestController public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAssetsApi { @@ -34,6 +42,9 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse @Autowired private HsOfficeCoopAssetsTransactionRepository coopAssetsTransactionRepo; + @Autowired + private HsOfficeMembershipRepository membershipRepo; + @Override @Transactional(readOnly = true) public ResponseEntity> getListOfCoopAssets( @@ -63,7 +74,10 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse context.define(currentSubject, assumedRoles); validate(requestBody); - final var entityToSave = mapper.map(requestBody, HsOfficeCoopAssetsTransactionEntity.class, RESOURCE_TO_ENTITY_POSTMAPPER); + final var entityToSave = mapper.map( + requestBody, + HsOfficeCoopAssetsTransactionEntity.class, + RESOURCE_TO_ENTITY_POSTMAPPER); final var saved = coopAssetsTransactionRepo.save(entityToSave); final var uri = @@ -78,7 +92,7 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse @Override @Transactional(readOnly = true) public ResponseEntity getSingleCoopAssetTransactionByUuid( - final String currentSubject, final String assumedRoles, final UUID assetTransactionUuid) { + final String currentSubject, final String assumedRoles, final UUID assetTransactionUuid) { context.define(currentSubject, assumedRoles); @@ -101,7 +115,7 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse private static void validateDebitTransaction( final HsOfficeCoopAssetsTransactionInsertResource requestBody, final ArrayList violations) { - if (List.of(DEPOSIT, ADOPTION).contains(requestBody.getTransactionType()) + if (List.of(DEPOSIT, HsOfficeCoopAssetsTransactionTypeResource.ADOPTION).contains(requestBody.getTransactionType()) && requestBody.getAssetValue().signum() < 0) { violations.add("for %s, assetValue must be positive but is \"%.2f\"".formatted( requestBody.getTransactionType(), requestBody.getAssetValue())); @@ -128,9 +142,58 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse } final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { - if ( resource.getRevertedAssetTxUuid() != null ) { + if (resource.getRevertedAssetTxUuid() != null) { entity.setRevertedAssetTx(coopAssetsTransactionRepo.findByUuid(resource.getRevertedAssetTxUuid()) - .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] reverseEntityUuid %s not found".formatted(resource.getRevertedAssetTxUuid())))); + .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] revertedEntityUuid %s not found".formatted( + resource.getRevertedAssetTxUuid())))); + } + + final var adoptingMembership = determineAdoptingMembership(resource); + if (adoptingMembership != null) { + final var adoptingAssetTx = coopAssetsTransactionRepo.save( + HsOfficeCoopAssetsTransactionEntity.builder() + .membership(adoptingMembership) + .transactionType(HsOfficeCoopAssetsTransactionType.ADOPTION) + .assetTransferTx(entity) + .assetValue(entity.getAssetValue().negate()) + .comment(entity.getComment()) + .reference(entity.getReference()) + .valueDate(entity.getValueDate()) + .build()); + entity.setAssetAdoptionAssetTx(adoptingAssetTx); } }; + + private HsOfficeMembershipEntity determineAdoptingMembership(final HsOfficeCoopAssetsTransactionInsertResource resource) { + final var adoptingMembershipUuid = resource.getAdoptingMembershipUuid(); + final var adoptingMembershipMemberNumber = resource.getAdoptingMembershipMemberNumber(); + if (adoptingMembershipUuid != null && adoptingMembershipMemberNumber != null) { + throw new IllegalArgumentException( + "[400] either adoptingMembership.uuid or adoptingMembership.memberNumber can be given, not both"); + } + + if (adoptingMembershipUuid != null) { + final var adoptingMembership = membershipRepo.findByUuid(adoptingMembershipUuid); + return adoptingMembership.orElseThrow(() -> + new IllegalArgumentException( + "[400] adoptingMembership.uuid='" + adoptingMembershipUuid + "' not found or not accessible")); + } + + if (adoptingMembershipMemberNumber != null) { + final var adoptingMemberNumber = Integer.valueOf(adoptingMembershipMemberNumber.substring("M-".length())); + final var adoptingMembership = membershipRepo.findMembershipByMemberNumber(adoptingMemberNumber); + if (adoptingMembership != null) { + return adoptingMembership; + } + throw new IllegalArgumentException("[400] adoptingMembership.memberNumber='" + adoptingMembershipMemberNumber + + "' not found or not accessible"); + } + + if (resource.getTransactionType() == TRANSFER) { + throw new IllegalArgumentException( + "[400] either adoptingMembership.uuid or adoptingMembership.memberNumber must be given for " + TRANSFER); + } + + return null; + } }; diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java index cc2e504b..cb075734 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java @@ -50,8 +50,11 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, BaseE .withProp(HsOfficeCoopAssetsTransactionEntity::getAssetValue) .withProp(HsOfficeCoopAssetsTransactionEntity::getReference) .withProp(HsOfficeCoopAssetsTransactionEntity::getComment) + // FIXME: try short form with just method reference .withProp(at -> ofNullable(at.getRevertedAssetTx()).map(HsOfficeCoopAssetsTransactionEntity::toShortString).orElse(null)) - .withProp(at -> ofNullable(at.getReversalAssetTx()).map(HsOfficeCoopAssetsTransactionEntity::toShortString).orElse(null)) + .withProp(at -> ofNullable(at.getAssetReversalTx()).map(HsOfficeCoopAssetsTransactionEntity::toShortString).orElse(null)) + .withProp(at -> ofNullable(at.getAssetAdoptionAssetTx()).map(HsOfficeCoopAssetsTransactionEntity::toShortString).orElse(null)) + .withProp(at -> ofNullable(at.getAssetTransferTx()).map(HsOfficeCoopAssetsTransactionEntity::toShortString).orElse(null)) .quotedValues(false); @Id @@ -95,15 +98,23 @@ public class HsOfficeCoopAssetsTransactionEntity implements Stringifyable, BaseE @Column(name = "comment") private String comment; - /** - * Optionally, the UUID of the corresponding transaction for an reversal transaction. - */ + // Optionally, the UUID of the corresponding transaction for a reversal transaction. @OneToOne @JoinColumn(name = "revertedassettxuuid") private HsOfficeCoopAssetsTransactionEntity revertedAssetTx; + // and the other way around @OneToOne(mappedBy = "revertedAssetTx") - private HsOfficeCoopAssetsTransactionEntity reversalAssetTx; + private HsOfficeCoopAssetsTransactionEntity assetReversalTx; + + // Optionally, the UUID of the corresponding transaction for a transfer transaction. + @OneToOne + @JoinColumn(name = "assetadoptiontxuuid") + private HsOfficeCoopAssetsTransactionEntity assetAdoptionAssetTx; + + // and the other way around + @OneToOne(mappedBy = "assetAdoptionAssetTx") + private HsOfficeCoopAssetsTransactionEntity assetTransferTx; @Override public HsOfficeCoopAssetsTransactionEntity load() { diff --git a/src/main/resources/api-definition/hs-office/hs-office-coopassets-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-coopassets-schemas.yaml index 30725a82..4474b221 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-coopassets-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-coopassets-schemas.yaml @@ -32,15 +32,22 @@ components: type: string comment: type: string + adoptionAssetTx: + # a TRANSFER tx must refer to the related ADOPTION tx + $ref: '#/components/schemas/HsOfficeRelatedCoopAssetsTransaction' + transferAssetTx: + # an ADOPTION tx must refer to the related TRANSFER tx + $ref: '#/components/schemas/HsOfficeRelatedCoopAssetsTransaction' revertedAssetTx: - $ref: '#/components/schemas/HsOfficeReferencedCoopAssetsTransaction' + # a REVERSAL tx must refer to the related tx, which can be of any type but REVERSAL + $ref: '#/components/schemas/HsOfficeRelatedCoopAssetsTransaction' reversalAssetTx: - $ref: '#/components/schemas/HsOfficeReferencedCoopAssetsTransaction' + # a reverted tx, which can be any but REVERSAL, must refer to the related REVERSAL tx + $ref: '#/components/schemas/HsOfficeRelatedCoopAssetsTransaction' - HsOfficeReferencedCoopAssetsTransaction: + HsOfficeRelatedCoopAssetsTransaction: description: - Similar to `HsOfficeCoopAssetsTransaction` but without the self-referencing properties - (`revertedAssetTx` and `reversalAssetTx`), to avoid recursive JSON. + Similar to `HsOfficeCoopAssetsTransaction` but just the UUID of the related property, to avoid recursive JSON. type: object properties: uuid: @@ -58,6 +65,22 @@ components: type: string comment: type: string + adoptionAssetTx.uuid: + description: a TRANSFER tx must refer to the related ADOPTION tx + type: string + format: uuid + transferAssetTx.uuid: + description: an ADOPTION tx must refer to the related TRANSFER tx + type: string + format: uuid + revertedAssetTx.uuid: + description: a REVERSAL tx must refer to the related tx, which can be of any type but REVERSAL + type: string + format: uuid + reversalAssetTx.uuid: + description: a reverted tx, which can be any but REVERSAL, must refer to the related REVERSAL tx + type: string + format: uuid HsOfficeCoopAssetsTransactionInsert: type: object @@ -83,6 +106,14 @@ components: revertedAssetTx.uuid: type: string format: uuid + adoptingMembership.uuid: + type: string + format: uuid + adoptingMembership.memberNumber: + type: string + minLength: 9 + maxLength: 9 + pattern: 'M-[0-9]{7}' required: - membership.uuid - transactionType diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5120-hs-office-coopassets.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5120-hs-office-coopassets.sql index 8feac5da..ce076885 100644 --- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5120-hs-office-coopassets.sql +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5120-hs-office-coopassets.sql @@ -24,7 +24,8 @@ create table if not exists hs_office.coopassettx valueDate date not null, assetValue numeric(12,2) not null, -- https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_money reference varchar(48) not null, - revertedAssetTxUuid uuid unique REFERENCES hs_office.coopassettx(uuid) DEFERRABLE INITIALLY DEFERRED, + revertedAssetTxuUid uuid unique REFERENCES hs_office.coopassettx(uuid) DEFERRABLE INITIALLY DEFERRED, + assetAdoptionTxUuid uuid unique REFERENCES hs_office.coopassettx(uuid) DEFERRABLE INITIALLY DEFERRED, comment varchar(512) ); --// @@ -35,9 +36,20 @@ create table if not exists hs_office.coopassettx -- ---------------------------------------------------------------------------- alter table hs_office.coopassettx - add constraint reverse_entry_missing - check ( transactionType = 'REVERSAL' and revertedAssetTxUuid is not null - or transactionType <> 'REVERSAL' and revertedAssetTxUuid is null); + add constraint reversal_asset_tx_must_have_reverted_asset_tx + check (transactionType <> 'REVERSAL' or revertedAssetTxuUid is not null); + +alter table hs_office.coopassettx + add constraint non_reversal_asset_tx_must_not_have_reverted_asset_tx + check (transactionType = 'REVERSAL' or revertedAssetTxuUid is null or transactionType = 'REVERSAL'); + +alter table hs_office.coopassettx + add constraint transfer_asset_tx_must_have_adopted_asset_tx + check (transactionType <> 'TRANSFER' or assetAdoptionTxUuid is not null); + +alter table hs_office.coopassettx + add constraint non_transfer_asset_tx_must_not_have_adopted_asset_tx + check (transactionType = 'TRANSFER' or assetAdoptionTxUuid is null); --// -- ============================================================================ diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql index ac43a731..a7bc6c55 100644 --- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql +++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5128-hs-office-coopassets-test-data.sql @@ -27,7 +27,7 @@ begin raise notice 'creating test coopAssetsTransaction: %', givenPartnerNumber || givenMemberNumberSuffix; lossEntryUuid := uuid_generate_v4(); insert - into hs_office.coopassettx(uuid, membershipuuid, transactiontype, valuedate, assetvalue, reference, comment, revertedAssetTxUuid) + into hs_office.coopassettx(uuid, membershipuuid, transactiontype, valuedate, assetvalue, reference, comment, revertedAssetTxuUid) values (uuid_generate_v4(), membership.uuid, 'DEPOSIT', '2010-03-15', 320.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-1', 'initial deposit', null), (uuid_generate_v4(), membership.uuid, 'DISBURSAL', '2021-09-01', -128.00, 'ref '||givenPartnerNumber || givenMemberNumberSuffix||'-2', 'partial disbursal', null), diff --git a/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java b/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java index 0bdf47da..0d5670cb 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/migration/BaseOfficeDataImport.java @@ -867,14 +867,14 @@ public abstract class BaseOfficeDataImport extends CsvDataImport { if (assetTransaction.getTransactionType() == HsOfficeCoopAssetsTransactionType.REVERSAL) { final var negativeValue = assetTransaction.getAssetValue().negate(); - final var revertedAssetTx = coopAssets.values().stream().filter(a -> + final var reversalAssetTx = coopAssets.values().stream().filter(a -> a.getTransactionType() != HsOfficeCoopAssetsTransactionType.REVERSAL && a.getMembership() == assetTransaction.getMembership() && a.getAssetValue().equals(negativeValue)) .findAny() .orElseThrow(() -> new IllegalStateException( "cannot determine asset reverse entry for reversal " + assetTransaction)); - assetTransaction.setRevertedAssetTx(revertedAssetTx); + assetTransaction.setAssetReversalTx(reversalAssetTx); } coopAssets.put(rec.getInteger("member_asset_id"), assetTransaction); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntityUnitTest.java index 96a0edfb..261e1af2 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntityUnitTest.java @@ -20,7 +20,6 @@ class HsOfficeCoopAssetsTransactionEntityUnitTest { .comment("some comment") .build(); - final HsOfficeCoopAssetsTransactionEntity givenCoopAssetReversalTransaction = HsOfficeCoopAssetsTransactionEntity.builder() .membership(TEST_MEMBERSHIP) .reference("some-ref") @@ -31,6 +30,16 @@ class HsOfficeCoopAssetsTransactionEntityUnitTest { .revertedAssetTx(givenCoopAssetTransaction) .build(); + final HsOfficeCoopAssetsTransactionEntity givenAdoptedCoopAssetTransaction = HsOfficeCoopAssetsTransactionEntity.builder() + .membership(TEST_MEMBERSHIP) + .reference("some-ref") + .valueDate(LocalDate.parse("2020-01-15")) + .transactionType(HsOfficeCoopAssetsTransactionType.ADOPTION) + .assetValue(new BigDecimal("128.00")) + .comment("some comment") + .revertedAssetTx(givenCoopAssetTransaction) + .build(); + final HsOfficeCoopAssetsTransactionEntity givenEmptyCoopAssetsTransaction = HsOfficeCoopAssetsTransactionEntity.builder().build(); @Test @@ -49,6 +58,15 @@ class HsOfficeCoopAssetsTransactionEntityUnitTest { assertThat(result).isEqualTo("CoopAssetsTransaction(M-1000101: 2020-01-01, DEPOSIT, 128.00, some-ref, some comment, M-1000101:REV:-128.00)"); } + @Test + void toStringWithAdoptedAssetTxContainsRevertedAssetTx() { + givenCoopAssetTransaction.setAssetAdoptionAssetTx(givenAdoptedCoopAssetTransaction); + + final var result = givenCoopAssetTransaction.toString(); + + assertThat(result).isEqualTo("CoopAssetsTransaction(M-1000101: 2020-01-01, DEPOSIT, 128.00, some-ref, some comment, M-1000101:ADO:+128.00)"); + } + @Test void toShortStringContainsOnlyMemberNumberSuffixAndSharesCountOnly() { final var result = givenCoopAssetTransaction.toShortString(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntityUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntityUnitTest.java index 6394a8d7..bef9af31 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntityUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopshares/HsOfficeCoopSharesTransactionEntityUnitTest.java @@ -40,7 +40,7 @@ class HsOfficeCoopSharesTransactionEntityUnitTest { } @Test - void toStringWithRevertedAssetTxContainsRevertedAssetTx() { + void toStringWithRelatedAssetTxContainsRelatedAssetTx() { givenCoopSharesTransaction.setRevertedShareTx(givenCoopShareReversalTransaction); final var result = givenCoopSharesTransaction.toString(); diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/HsOfficeScenarioTests.java b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/HsOfficeScenarioTests.java index 0f7362df..304eb4f6 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/HsOfficeScenarioTests.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/HsOfficeScenarioTests.java @@ -17,6 +17,7 @@ import net.hostsharing.hsadminng.hs.office.scenarios.membership.CreateMembership import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets.CreateCoopAssetsDepositTransaction; import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets.CreateCoopAssetsDisbursalTransaction; import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets.CreateCoopAssetsRevertTransaction; +import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopassets.CreateCoopAssetsTransferTransaction; import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares.CreateCoopSharesCancellationTransaction; import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares.CreateCoopSharesRevertTransaction; import net.hostsharing.hsadminng.hs.office.scenarios.membership.coopshares.CreateCoopSharesSubscriptionTransaction; @@ -77,8 +78,8 @@ class HsOfficeScenarioTests extends ScenarioTest { @Test @Order(1011) - @Produces(explicitly = "Partner: P-31011 - Michelle Matthieu", implicitly = { "Person: Michelle Matthieu", - "Contact: Michelle Matthieu" }) + @Produces(explicitly = "Partner: P-31011 - Michelle Matthieu", + implicitly = { "Person: Michelle Matthieu", "Contact: Michelle Matthieu" }) void shouldCreateNaturalPersonAsPartner() { new CreatePartner(this) .given("partnerNumber", "P-31011") @@ -336,7 +337,7 @@ class HsOfficeScenarioTests extends ScenarioTest { @Test @Order(4201) @Requires("Membership: M-3101000 - Test AG") - @Produces("Coop-Shares SUBSCRIPTION Transaction") + @Produces("Coop-Shares M-3101000 - Test AG - SUBSCRIPTION Transaction") void shouldSubscribeCoopShares() { new CreateCoopSharesSubscriptionTransaction(this) .given("memberNumber", "M-3101000") @@ -360,8 +361,8 @@ class HsOfficeScenarioTests extends ScenarioTest { @Test @Order(4202) - @Requires("Coop-Shares SUBSCRIPTION Transaction") - @Produces("Coop-Shares CANCELLATION Transaction") + @Requires("Coop-Shares M-3101000 - Test AG - SUBSCRIPTION Transaction") + @Produces("Coop-Shares M-3101000 - Test AG - CANCELLATION Transaction") void shouldCancelCoopSharesSubscription() { new CreateCoopSharesCancellationTransaction(this) .given("memberNumber", "M-3101000") @@ -375,7 +376,7 @@ class HsOfficeScenarioTests extends ScenarioTest { @Test @Order(4301) @Requires("Membership: M-3101000 - Test AG") - @Produces("Coop-Assets DEPOSIT Transaction") + @Produces("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction") void shouldSubscribeCoopAssets() { new CreateCoopAssetsDepositTransaction(this) .given("memberNumber", "M-3101000") @@ -388,7 +389,7 @@ class HsOfficeScenarioTests extends ScenarioTest { @Test @Order(4302) - @Requires("Coop-Assets DEPOSIT Transaction") + @Requires("Membership: M-3101000 - Test AG") void shouldRevertCoopAssetsSubscription() { new CreateCoopAssetsRevertTransaction(this) .given("memberNumber", "M-3101000") @@ -399,8 +400,8 @@ class HsOfficeScenarioTests extends ScenarioTest { @Test @Order(4302) - @Requires("Coop-Assets DEPOSIT Transaction") - @Produces("Coop-Assets DISBURSAL Transaction") + @Requires("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction") + @Produces("Coop-Assets M-3101000 - Test AG - DISBURSAL Transaction") void shouldDisburseCoopAssets() { new CreateCoopAssetsDisbursalTransaction(this) .given("memberNumber", "M-3101000") @@ -411,6 +412,21 @@ class HsOfficeScenarioTests extends ScenarioTest { .doRun(); } + @Test + @Order(4303) + @Requires("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction") + @Produces("Coop-Assets M-3101000 - Test AG - TRANSFER Transaction") + void shouldTransferCoopAssets() { + new CreateCoopAssetsTransferTransaction(this) + .given("transferringMemberNumber", "M-3101000") + .given("adoptingMemberNumber", "M-4303000") + .given("reference", "transfer 2024-01-15") + .given("valueToDisburse", 2 * 64) + .given("comment", "transfer assets from M-3101000 to M-4303000") + .given("transactionDate", "2024-02-15") + .doRun(); + } + @Test @Order(4900) @Requires("Membership: M-3101000 - Test AG") diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/membership/coopassets/CreateCoopAssetsRevertTransaction.java b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/membership/coopassets/CreateCoopAssetsRevertTransaction.java index a83c21a2..60d85fbe 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/membership/coopassets/CreateCoopAssetsRevertTransaction.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/membership/coopassets/CreateCoopAssetsRevertTransaction.java @@ -10,7 +10,7 @@ public class CreateCoopAssetsRevertTransaction extends CreateCoopAssetsTransacti requires("CoopAssets-Transaction with incorrect assetValue", alias -> new CreateCoopAssetsDepositTransaction(testSuite) .given("memberNumber", "%{memberNumber}") - .given("reference", "sign %{dateOfIncorrectTransaction}") // same as revertedAssetTx + .given("reference", "sign %{dateOfIncorrectTransaction}") // same as relatedAssetTx .given("assetValue", 10) .given("comment", "coop-assets deposit transaction with wrong asset value") .given("transactionDate", "%{dateOfIncorrectTransaction}") @@ -20,7 +20,7 @@ public class CreateCoopAssetsRevertTransaction extends CreateCoopAssetsTransacti @Override protected HttpResponse run() { given("transactionType", "REVERSAL"); - given("assetValue", -100); + given("assetValue", -10); given("revertedAssetTx", uuid("CoopAssets-Transaction with incorrect assetValue")); return super.run(); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/membership/coopassets/CreateCoopAssetsTransaction.java b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/membership/coopassets/CreateCoopAssetsTransaction.java index 56bc2a55..fbe4b8d5 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/membership/coopassets/CreateCoopAssetsTransaction.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/scenarios/membership/coopassets/CreateCoopAssetsTransaction.java @@ -32,7 +32,8 @@ public abstract class CreateCoopAssetsTransaction extends UseCase new CreatePartner(testSuite, alias) + .given("partnerNumber", toPartnerNumber("%{adoptingMemberNumber}")) + .given("personType", "LEGAL_PERSON") + .given("tradeName", "New AG") + .given("contactCaption", "New AG - Board of Directors") + .given("emailAddress", "board-of-directors@new-ag.example.org") + ); + + requires("Membership: New AG", alias -> new CreateMembership(testSuite) + .given("partnerNumber", toPartnerNumber("%{adoptingMemberNumber}")) + .given("partnerName", "New AG") + .given("validFrom", "2024-11-15") + .given("newStatus", "ACTIVE") + .given("membershipFeeBillable", "true") + ); + } + + @Override + protected HttpResponse run() { + introduction("Additionally to the TRANSFER, the ADOPTION is automatically booked for the receiving member."); + + given("memberNumber", "%{transferringMemberNumber}"); + given("transactionType", "TRANSFER"); + given("assetValue", "-%{valueToDisburse}"); + given("assetValue", "-%{valueToDisburse}"); + return super.run(); + } + + private String toPartnerNumber(final String resolvableString) { + final var memberNumber = ScenarioTest.resolve(resolvableString, DROP_COMMENTS); + return "P-" + memberNumber.substring("M-".length(), 7); + } +}