implement coop-asset-TRANSFER-transaction reversal #125
@ -227,7 +227,7 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
|
||||
throw new ValidationException("REVERSAL asset transaction requires revertedAssetTx.uuid");
|
||||
}
|
||||
final var revertedAssetTx = coopAssetsTransactionRepo.findByUuid(resource.getRevertedAssetTxUuid())
|
||||
.orElseThrow(() -> new EntityNotFoundException("ERROR: [400] revertedEntityUuid %s not found".formatted(
|
||||
.orElseThrow(() -> new EntityNotFoundException("ERROR: [400] revertedAssetTx.uuid %s not found".formatted(
|
||||
resource.getRevertedAssetTxUuid())));
|
||||
revertedAssetTx.setReversalAssetTx(entity);
|
||||
entity.setRevertedAssetTx(revertedAssetTx);
|
||||
|
@ -30,6 +30,7 @@ import java.util.function.Function;
|
||||
|
||||
import static net.hostsharing.hsadminng.rbac.test.JsonBuilder.jsonObject;
|
||||
import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@ -42,6 +43,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@RunWith(SpringRunner.class)
|
||||
class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
|
||||
// If you need to run just a single test-case in this data-driven test-method,
|
||||
// set SINGLE_TEST_CASE_EXECUTION to true and make sure you do NOT EVER commit it to git!
|
||||
private static final boolean SINGLE_TEST_CASE_EXECUTION = false;
|
||||
|
||||
private static final UUID UNAVAILABLE_MEMBERSHIP_UUID = TestUuidGenerator.use(0);
|
||||
private static final String UNAVAILABLE_MEMBER_NUMBER = "M-1234699";
|
||||
|
||||
@ -68,8 +73,8 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
// The following refs depend on the implementation of the respective implementation and might change if it changes.
|
||||
// The same TestUuidGenerator.ref(#) does NOT mean the UUIDs refer to the same entity,
|
||||
// its rather coincidence because different test-cases have different execution paths in the production code.
|
||||
private static final UUID NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID = TestUuidGenerator.ref(4);
|
||||
private static final UUID NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID = TestUuidGenerator.ref(4);
|
||||
private static final UUID NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID = TestUuidGenerator.ref(6);
|
||||
private static final UUID NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID = TestUuidGenerator.ref(6);
|
||||
|
||||
private static final UUID SOME_EXISTING_LOSS_ASSET_TX_UUID = TestUuidGenerator.use(3);
|
||||
public final HsOfficeCoopAssetsTransactionEntity SOME_EXISTING_LOSS_ASSET_TX_ENTITY = HsOfficeCoopAssetsTransactionEntity.builder()
|
||||
@ -82,6 +87,33 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
.valueDate(LocalDate.parse("2024-10-15"))
|
||||
.build();
|
||||
|
||||
private static final UUID SOME_EXISTING_TRANSFER_ASSET_TX_UUID = TestUuidGenerator.use(4);
|
||||
public final HsOfficeCoopAssetsTransactionEntity SOME_EXISTING_TRANSFER_ASSET_TX_ENTITY = HsOfficeCoopAssetsTransactionEntity.builder()
|
||||
.uuid(SOME_EXISTING_TRANSFER_ASSET_TX_UUID)
|
||||
.membership(ORIGIN_TARGET_MEMBER_ENTITY)
|
||||
.transactionType(HsOfficeCoopAssetsTransactionType.TRANSFER)
|
||||
.assetValue(BigDecimal.valueOf(-256))
|
||||
.reference("some transfer asset tx ref")
|
||||
.comment("some transfer asset tx comment")
|
||||
.valueDate(LocalDate.parse("2024-10-15"))
|
||||
.build();
|
||||
|
||||
private static final UUID SOME_EXISTING_ADOPTION_ASSET_TX_UUID = TestUuidGenerator.use(5);
|
||||
public final HsOfficeCoopAssetsTransactionEntity SOME_EXISTING_ADOPTION_ASSET_TX_ENTITY = HsOfficeCoopAssetsTransactionEntity.builder()
|
||||
.uuid(SOME_EXISTING_ADOPTION_ASSET_TX_UUID)
|
||||
.membership(ORIGIN_TARGET_MEMBER_ENTITY)
|
||||
.transactionType(HsOfficeCoopAssetsTransactionType.TRANSFER)
|
||||
.assetValue(SOME_EXISTING_TRANSFER_ASSET_TX_ENTITY.getAssetValue().negate())
|
||||
.reference("some adoption asset tx ref")
|
||||
.comment("some adoption asset tx comment")
|
||||
.valueDate(LocalDate.parse("2024-10-15"))
|
||||
.transferAssetTx(SOME_EXISTING_TRANSFER_ASSET_TX_ENTITY)
|
||||
.build();
|
||||
|
||||
{
|
||||
SOME_EXISTING_TRANSFER_ASSET_TX_ENTITY.setAdoptionAssetTx(SOME_EXISTING_ADOPTION_ASSET_TX_ENTITY);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
MockMvc mockMvc;
|
||||
|
||||
@ -192,8 +224,10 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
@EnumSource(BadRequestTestCases.class)
|
||||
void respondWithBadRequest(final BadRequestTestCases testCase) throws Exception {
|
||||
// HOWTO: run just a single test-case in a data-driven test-method
|
||||
// org.assertj.core.api.Assumptions.assumeThat(
|
||||
// testCase == ADOPTING_MEMBERSHIP_NUMBER_FOR_TRANSFER_MUST_BE_GIVEN_AND_AVAILABLE).isTrue();
|
||||
// - set SINGLE_TEST_CASE_EXECUTION to true - see above
|
||||
// - select the test case enum value you want to run
|
||||
assumeThat(!SINGLE_TEST_CASE_EXECUTION ||
|
||||
testCase == BadRequestTestCases.ADOPTING_MEMBERSHIP_NUMBER_FOR_TRANSFER_MUST_BE_GIVEN_AND_AVAILABLE).isTrue();
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
@ -217,10 +251,10 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
.with("transactionType", "REVERSAL")
|
||||
.with("assetValue", "64.00")
|
||||
.with("valueDate", "2024-10-15")
|
||||
.with("reference", "reversal ref")
|
||||
.with("comment", "reversal comment")
|
||||
.with("reference", "reversal of loss ref")
|
||||
.with("comment", "reversal of loss asset tx comment")
|
||||
.with("revertedAssetTx.uuid", SOME_EXISTING_LOSS_ASSET_TX_UUID.toString()),
|
||||
Expected.REVERT_RESPONSE),
|
||||
Expected.REVERT_LOSS_RESPONSE),
|
||||
|
||||
TRANSFER_TO_GIVEN_AVAILABLE_MEMBERSHIP_NUMBER(
|
||||
requestBody -> requestBody
|
||||
@ -235,7 +269,17 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
.with("assetValue", -64.00)
|
||||
.with("membership.uuid", ORIGIN_MEMBERSHIP_UUID.toString())
|
||||
.with("adoptingMembership.uuid", AVAILABLE_TARGET_MEMBERSHIP_UUID.toString()),
|
||||
Expected.TRANSFER_RESPONSE);
|
||||
Expected.TRANSFER_RESPONSE),
|
||||
|
||||
REVERTING_TRANSFER_ASSET_TRANSACTION_IMPLICITLY_REVERTS_ADOPTING_ASSET_TRANSACTION(
|
||||
requestBody -> requestBody
|
||||
.with("transactionType", "REVERSAL")
|
||||
.with("assetValue", "256.00")
|
||||
.with("valueDate", "2024-10-15")
|
||||
.with("reference", "reversal of transfer ref")
|
||||
.with("comment", "reversal of transfer asset tx comment")
|
||||
.with("revertedAssetTx.uuid", SOME_EXISTING_TRANSFER_ASSET_TX_UUID.toString()),
|
||||
Expected.REVERT_TRANSFER_RESPONSE);
|
||||
|
||||
private final Function<JsonBuilder, JsonBuilder> givenBodyTransformation;
|
||||
private final String expectedResponseBody;
|
||||
@ -253,7 +297,7 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
|
||||
private static class Expected {
|
||||
|
||||
public static final String REVERT_RESPONSE = """
|
||||
public static final String REVERT_LOSS_RESPONSE = """
|
||||
{
|
||||
"uuid": "%{NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID}",
|
||||
"membership.uuid": "%{ORIGIN_MEMBERSHIP_UUID}",
|
||||
@ -261,8 +305,8 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
"transactionType": "REVERSAL",
|
||||
"assetValue": 64.00,
|
||||
"valueDate": "2024-10-15",
|
||||
"reference": "reversal ref",
|
||||
"comment": "reversal comment",
|
||||
"reference": "reversal of loss ref",
|
||||
"comment": "reversal of loss asset tx comment",
|
||||
"adoptionAssetTx": null,
|
||||
"transferAssetTx": null,
|
||||
"revertedAssetTx": {
|
||||
@ -281,7 +325,9 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
}
|
||||
}
|
||||
"""
|
||||
.replace("%{NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID}", NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID.toString())
|
||||
.replace(
|
||||
"%{NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID}",
|
||||
NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID.toString())
|
||||
.replace("%{ORIGIN_MEMBERSHIP_UUID}", ORIGIN_MEMBERSHIP_UUID.toString())
|
||||
.replace("%{ORIGIN_MEMBER_NUMBER}", ORIGIN_MEMBER_NUMBER)
|
||||
.replace("%{SOME_EXISTING_LOSS_ASSET_TX_UUID}", SOME_EXISTING_LOSS_ASSET_TX_UUID.toString());
|
||||
@ -305,20 +351,57 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
"reversalAssetTx": null
|
||||
}
|
||||
"""
|
||||
.replace("%{NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID}", NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID.toString())
|
||||
.replace(
|
||||
"%{NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID}",
|
||||
NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID.toString())
|
||||
.replace("%{ORIGIN_MEMBERSHIP_UUID}", ORIGIN_MEMBERSHIP_UUID.toString())
|
||||
.replace("%{ORIGIN_MEMBER_NUMBER}", ORIGIN_MEMBER_NUMBER)
|
||||
.replace("%{AVAILABLE_MEMBERSHIP_UUID}", AVAILABLE_TARGET_MEMBERSHIP_UUID.toString())
|
||||
.replace("%{AVAILABLE_TARGET_MEMBER_NUMBER}", AVAILABLE_TARGET_MEMBER_NUMBER);
|
||||
|
||||
public static final String REVERT_TRANSFER_RESPONSE = """
|
||||
{
|
||||
"uuid": "%{NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID}",
|
||||
"membership.uuid": "%{ORIGIN_MEMBERSHIP_UUID}",
|
||||
"membership.memberNumber": "%{ORIGIN_MEMBER_NUMBER}",
|
||||
"transactionType": "REVERSAL",
|
||||
"assetValue": 256.00,
|
||||
"valueDate": "2024-10-15",
|
||||
"reference": "reversal of transfer ref",
|
||||
"comment": "reversal of transfer asset tx comment",
|
||||
"adoptionAssetTx": null,
|
||||
"transferAssetTx": null,
|
||||
"revertedAssetTx": {
|
||||
"uuid": "%{SOME_EXISTING_TRANSFER_ASSET_TX_UUID}",
|
||||
"membership.uuid": "%{ORIGIN_MEMBERSHIP_UUID}",
|
||||
"membership.memberNumber": "%{ORIGIN_MEMBER_NUMBER}",
|
||||
"transactionType": "TRANSFER",
|
||||
"assetValue": -256.00,
|
||||
"valueDate": "2024-10-15",
|
||||
"reference": "some transfer asset tx ref",
|
||||
"comment": "some transfer asset tx comment",
|
||||
"adoptionAssetTx.uuid": "%{SOME_EXISTING_ADOPTION_ASSET_TX_UUID}",
|
||||
"transferAssetTx.uuid": null,
|
||||
"revertedAssetTx.uuid": null,
|
||||
"reversalAssetTx.uuid": "%{NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID}"
|
||||
}
|
||||
}
|
||||
"""
|
||||
.replace(
|
||||
"%{NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID}",
|
||||
NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID.toString())
|
||||
.replace("%{ORIGIN_MEMBERSHIP_UUID}", ORIGIN_MEMBERSHIP_UUID.toString())
|
||||
.replace("%{ORIGIN_MEMBER_NUMBER}", ORIGIN_MEMBER_NUMBER)
|
||||
.replace("%{SOME_EXISTING_TRANSFER_ASSET_TX_UUID}", SOME_EXISTING_TRANSFER_ASSET_TX_UUID.toString())
|
||||
.replace("%{SOME_EXISTING_ADOPTION_ASSET_TX_UUID}", SOME_EXISTING_ADOPTION_ASSET_TX_UUID.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(SuccessfullyCreatedTestCases.class)
|
||||
void respondWithSuccessfullyCreated(final SuccessfullyCreatedTestCases testCase) throws Exception {
|
||||
// uncomment, if you need to run just a single test-case in this data-driven test-method
|
||||
// org.assertj.core.api.Assumptions.assumeThat(
|
||||
// testCase == ADOPTING_MEMBERSHIP_UUID_FOR_TRANSFER_MUST_BE_GIVEN_AND_AVAILABLE).isTrue();
|
||||
assumeThat(!SINGLE_TEST_CASE_EXECUTION ||
|
||||
testCase == SuccessfullyCreatedTestCases.REVERTING_TRANSFER_ASSET_TRANSACTION_IMPLICITLY_REVERTS_ADOPTING_ASSET_TRANSACTION).isTrue();
|
||||
|
||||
// when
|
||||
mockMvc.perform(MockMvcRequestBuilders
|
||||
@ -335,10 +418,11 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
|
||||
@BeforeEach
|
||||
void initMocks() {
|
||||
TestUuidGenerator.start(4);
|
||||
TestUuidGenerator.start(6);
|
||||
|
||||
when(emw.find(eq(HsOfficeMembershipEntity.class), eq(ORIGIN_MEMBERSHIP_UUID))).thenReturn(ORIGIN_TARGET_MEMBER_ENTITY);
|
||||
when(emw.find(eq(HsOfficeMembershipEntity.class), eq(AVAILABLE_TARGET_MEMBERSHIP_UUID))).thenReturn(AVAILABLE_MEMBER_ENTITY);
|
||||
when(emw.find(eq(HsOfficeMembershipEntity.class), eq(AVAILABLE_TARGET_MEMBERSHIP_UUID))).thenReturn(
|
||||
AVAILABLE_MEMBER_ENTITY);
|
||||
|
||||
final var availableMemberNumber = Integer.valueOf(AVAILABLE_TARGET_MEMBER_NUMBER.substring("M-".length()));
|
||||
when(membershipRepo.findMembershipByMemberNumber(eq(availableMemberNumber))).thenReturn(AVAILABLE_MEMBER_ENTITY);
|
||||
@ -348,6 +432,10 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
|
||||
|
||||
when(coopAssetsTransactionRepo.findByUuid(SOME_EXISTING_LOSS_ASSET_TX_UUID))
|
||||
.thenReturn(Optional.of(SOME_EXISTING_LOSS_ASSET_TX_ENTITY));
|
||||
when(coopAssetsTransactionRepo.findByUuid(SOME_EXISTING_TRANSFER_ASSET_TX_UUID))
|
||||
.thenReturn(Optional.of(SOME_EXISTING_TRANSFER_ASSET_TX_ENTITY));
|
||||
when(coopAssetsTransactionRepo.findByUuid(SOME_EXISTING_ADOPTION_ASSET_TX_UUID))
|
||||
.thenReturn(Optional.of(SOME_EXISTING_ADOPTION_ASSET_TX_ENTITY));
|
||||
when(coopAssetsTransactionRepo.save(any(HsOfficeCoopAssetsTransactionEntity.class)))
|
||||
.thenAnswer(invocation -> {
|
||||
final var entity = (HsOfficeCoopAssetsTransactionEntity) invocation.getArgument(0);
|
||||
|
@ -63,6 +63,9 @@ public class TestUuidGenerator {
|
||||
* @return a constant UUID related to the given index
|
||||
*/
|
||||
public static UUID use(final int index) {
|
||||
if (staticallyUsedIndexes.contains(index)) {
|
||||
throw new IllegalArgumentException("index " + index + " already used statically");
|
||||
}
|
||||
staticallyUsedIndexes.add(index);
|
||||
return GIVEN_UUIDS.get(index);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user