From 865ea3657eec66146a2d116ee8f97c452c5382f3 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Fri, 22 Nov 2024 17:21:36 +0100 Subject: [PATCH] revert test --- ...OfficeCoopAssetsTransactionController.java | 20 +++-- .../changelog/1-rbac/1058-rbac-generators.sql | 2 +- ...opAssetsTransactionControllerRestTest.java | 82 ++++++++++++++++--- .../hsadminng/test/TestUuidGenerator.java | 40 ++++++++- 4 files changed, 121 insertions(+), 23 deletions(-) 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 4fb4ea51..24a1919c 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 @@ -151,17 +151,16 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse resource.setMembershipUuid(entity.getMembership().getUuid()); resource.setMembershipMemberNumber(entity.getMembership().getTaggedMemberNumber()); - // FIXME: actually needed? if (entity.getReversalAssetTx() != null) { resource.getReversalAssetTx().setRevertedAssetTxUuid(entity.getUuid()); - resource.getReversalAssetTx().setMembershipUuid(entity.getRevertedAssetTx().getMembership().getUuid()); - resource.getReversalAssetTx().setMembershipMemberNumber(entity.getRevertedAssetTx().getTaggedMemberNumber()); + resource.getReversalAssetTx().setMembershipUuid(entity.getMembership().getUuid()); + resource.getReversalAssetTx().setMembershipMemberNumber(entity.getTaggedMemberNumber()); } if (entity.getRevertedAssetTx() != null) { resource.getRevertedAssetTx().setReversalAssetTxUuid(entity.getUuid()); - resource.getRevertedAssetTx().setMembershipUuid(entity.getReversalAssetTx().getMembership().getUuid()); - resource.getRevertedAssetTx().setMembershipMemberNumber(entity.getReversalAssetTx().getTaggedMemberNumber()); + resource.getRevertedAssetTx().setMembershipUuid(entity.getMembership().getUuid()); + resource.getRevertedAssetTx().setMembershipMemberNumber(entity.getTaggedMemberNumber()); } if (entity.getAdoptionAssetTx() != null) { @@ -170,7 +169,6 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse resource.getAdoptionAssetTx().setMembershipMemberNumber(entity.getAdoptionAssetTx().getTaggedMemberNumber()); } - // FIXME: actually needed? if (entity.getTransferAssetTx() != null) { resource.getTransferAssetTx().setAdoptionAssetTxUuid(entity.getUuid()); resource.getTransferAssetTx().setMembershipUuid(entity.getTransferAssetTx().getMembership().getUuid()); @@ -179,6 +177,7 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse }; final BiConsumer RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { + if (resource.getMembershipUuid() != null) { final HsOfficeMembershipEntity membership = ofNullable(emw.find(HsOfficeMembershipEntity.class, resource.getMembershipUuid())) .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] membership.uuid %s not found".formatted( @@ -186,9 +185,14 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse entity.setMembership(membership); } if (resource.getRevertedAssetTxUuid() != null) { - entity.setRevertedAssetTx(coopAssetsTransactionRepo.findByUuid(resource.getRevertedAssetTxUuid()) + final var revertedAssetTx = coopAssetsTransactionRepo.findByUuid(resource.getRevertedAssetTxUuid()) .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] revertedEntityUuid %s not found".formatted( - resource.getRevertedAssetTxUuid())))); + resource.getRevertedAssetTxUuid()))); + entity.setRevertedAssetTx(revertedAssetTx); + if (resource.getAssetValue().negate().compareTo(revertedAssetTx.getAssetValue()) != 0) { + throw new ValidationException("given assetValue=" + resource.getAssetValue() + + " but must be negative value from reverted asset tx: " + revertedAssetTx.getAssetValue()); + } } final var adoptingMembership = determineAdoptingMembership(resource); diff --git a/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql b/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql index b8af04f4..ae68b271 100644 --- a/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql +++ b/src/main/resources/db/changelog/1-rbac/1058-rbac-generators.sql @@ -223,7 +223,7 @@ begin ) select target.* from %1$s as target - where target.uuid in (select * from accessible_uuids) + where rbac.isGlobalAdmin() or target.uuid in (select * from accessible_uuids) order by %2$s; grant all privileges on %1$s_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java index 0589356b..1fdbe4f0 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionControllerRestTest.java @@ -22,6 +22,8 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import java.math.BigDecimal; +import java.time.LocalDate; import java.util.Optional; import java.util.UUID; import java.util.function.Function; @@ -40,10 +42,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringRunner.class) class HsOfficeCoopAssetsTransactionControllerRestTest { - private static final UUID UNAVAILABLE_MEMBERSHIP_UUID = TestUuidGenerator.get(0); + private static final UUID UNAVAILABLE_MEMBERSHIP_UUID = TestUuidGenerator.use(0); private static final String UNAVAILABLE_MEMBER_NUMBER = "M-1234699"; - private static final UUID ORIGIN_MEMBERSHIP_UUID = TestUuidGenerator.get(1); + private static final UUID ORIGIN_MEMBERSHIP_UUID = TestUuidGenerator.use(1); private static final String ORIGIN_MEMBER_NUMBER = "M-1111100"; public final HsOfficeMembershipEntity ORIGIN_TARGET_MEMBER_ENTITY = HsOfficeMembershipEntity.builder() .uuid(ORIGIN_MEMBERSHIP_UUID) @@ -53,7 +55,7 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { .memberNumberSuffix(suffixOf(ORIGIN_MEMBER_NUMBER)) .build(); - private static final UUID AVAILABLE_TARGET_MEMBERSHIP_UUID = TestUuidGenerator.get(2); + private static final UUID AVAILABLE_TARGET_MEMBERSHIP_UUID = TestUuidGenerator.use(2); private static final String AVAILABLE_TARGET_MEMBER_NUMBER = "M-1234500"; public final HsOfficeMembershipEntity AVAILABLE_MEMBER_ENTITY = HsOfficeMembershipEntity.builder() .uuid(AVAILABLE_TARGET_MEMBERSHIP_UUID) @@ -63,7 +65,20 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { .memberNumberSuffix(suffixOf(AVAILABLE_TARGET_MEMBER_NUMBER)) .build(); - private static final UUID NEW_EXPLICITLY_CREATED_ASSET_TX_UUID = TestUuidGenerator.get(5); // might change if impl changes + // the following refs might change if impl changes + 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(5); + + private static final UUID SOME_EXISTING_LOSS_ASSET_TX_UUID = TestUuidGenerator.use(3); + public final HsOfficeCoopAssetsTransactionEntity SOME_EXISTING_LOSS_ASSET_TX_ENTITY = HsOfficeCoopAssetsTransactionEntity.builder() + .uuid(SOME_EXISTING_LOSS_ASSET_TX_UUID) + .membership(ORIGIN_TARGET_MEMBER_ENTITY) + .transactionType(HsOfficeCoopAssetsTransactionType.LOSS) + .assetValue(BigDecimal.valueOf(-64)) + .reference("some loss asset tx ref") + .comment("some loss asset tx comment") + .valueDate(LocalDate.parse("2024-10-15")) + .build(); @Autowired MockMvc mockMvc; @@ -195,14 +210,24 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { enum SuccessfullyCreatedTestCases { - ADOPTING_MEMBERSHIP_NUMBER_FOR_TRANSFER_MUST_BE_GIVEN_AND_AVAILABLE( + REVERTING_SIMPLE_ASSET_TRANSACTION( + requestBody -> requestBody + .with("transactionType", "REVERSAL") + .with("assetValue", "64.00") + .with("valueDate", "2024-10-15") + .with("reference", "reversal ref") + .with("comment", "reversal comment") + .with("revertedAssetTx.uuid", SOME_EXISTING_LOSS_ASSET_TX_UUID.toString()), + Expected.REVERT_RESPONSE), + + TRANSFER_TO_GIVEN_AVAILABLE_MEMBERSHIP_NUMBER( requestBody -> requestBody .with("transactionType", "TRANSFER") .with("assetValue", -64.00) .with("adoptingMembership.memberNumber", AVAILABLE_TARGET_MEMBER_NUMBER), Expected.TRANSFER_RESPONSE), - ADOPTING_MEMBERSHIP_UUID_FOR_TRANSFER_MUST_BE_GIVEN_AND_AVAILABLE( + TRANSFER_TO_GIVEN_AVAILABLE_MEMBERSHIP_UUID( requestBody -> requestBody .with("transactionType", "TRANSFER") .with("assetValue", -64.00) @@ -226,9 +251,42 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { private static class Expected { + public static final String REVERT_RESPONSE = """ + { + "uuid": "%{NEW_EXPLICITLY_CREATED_REVERSAL_ASSET_TX_UUID}", + "membership.uuid": "%{ORIGIN_MEMBERSHIP_UUID}", + "membership.memberNumber": "%{ORIGIN_MEMBER_NUMBER}", + "transactionType": "REVERSAL", + "assetValue": 64.00, + "valueDate": "2024-10-15", + "reference": "reversal ref", + "comment": "reversal comment", + "adoptionAssetTx": null, + "transferAssetTx": null, + "revertedAssetTx": { + "uuid": "%{SOME_EXISTING_LOSS_ASSET_TX_UUID}", + "membership.uuid": "%{ORIGIN_MEMBERSHIP_UUID}", + "membership.memberNumber": "%{ORIGIN_MEMBER_NUMBER}", + "transactionType": "LOSS", + "assetValue": -64.00, + "valueDate": "2024-10-15", + "reference": "some loss asset tx ref", + "comment": "some loss asset tx comment", + "adoptionAssetTx.uuid": null, + "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_LOSS_ASSET_TX_UUID}", SOME_EXISTING_LOSS_ASSET_TX_UUID.toString()); + public static final String TRANSFER_RESPONSE = """ { - "uuid": "%{NEW_EXPLICITLY_CREATED_ASSET_TX_UUID}", + "uuid": "%{NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID}", "membership.uuid": "%{ORIGIN_MEMBERSHIP_UUID}", "membership.memberNumber": "%{ORIGIN_MEMBER_NUMBER}", "transactionType": "TRANSFER", @@ -238,14 +296,14 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { "membership.memberNumber": "%{AVAILABLE_TARGET_MEMBER_NUMBER}", "transactionType": "ADOPTION", "assetValue": 64.00, - "transferAssetTx.uuid": "%{NEW_EXPLICITLY_CREATED_ASSET_TX_UUID}" + "transferAssetTx.uuid": "%{NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID}" }, "transferAssetTx": null, "revertedAssetTx": null, "reversalAssetTx": null } """ - .replace("%{NEW_EXPLICITLY_CREATED_ASSET_TX_UUID}", NEW_EXPLICITLY_CREATED_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()) @@ -269,8 +327,8 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { .accept(MediaType.APPLICATION_JSON)) // then - .andExpect(jsonPath("$", lenientlyEquals(testCase.expectedResponseBody))) - .andExpect(status().is2xxSuccessful()); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("$", lenientlyEquals(testCase.expectedResponseBody))); } @BeforeEach @@ -286,6 +344,8 @@ class HsOfficeCoopAssetsTransactionControllerRestTest { when(membershipRepo.findByUuid(eq(ORIGIN_MEMBERSHIP_UUID))).thenReturn(Optional.of(ORIGIN_TARGET_MEMBER_ENTITY)); when(membershipRepo.findByUuid(eq(AVAILABLE_TARGET_MEMBERSHIP_UUID))).thenReturn(Optional.of(AVAILABLE_MEMBER_ENTITY)); + when(coopAssetsTransactionRepo.findByUuid(SOME_EXISTING_LOSS_ASSET_TX_UUID)) + .thenReturn(Optional.of(SOME_EXISTING_LOSS_ASSET_TX_ENTITY)); when(coopAssetsTransactionRepo.save(any(HsOfficeCoopAssetsTransactionEntity.class))) .thenAnswer(invocation -> { final var entity = (HsOfficeCoopAssetsTransactionEntity) invocation.getArgument(0); diff --git a/src/test/java/net/hostsharing/hsadminng/test/TestUuidGenerator.java b/src/test/java/net/hostsharing/hsadminng/test/TestUuidGenerator.java index 1f8c10e3..b75424c1 100644 --- a/src/test/java/net/hostsharing/hsadminng/test/TestUuidGenerator.java +++ b/src/test/java/net/hostsharing/hsadminng/test/TestUuidGenerator.java @@ -3,9 +3,11 @@ package net.hostsharing.hsadminng.test; import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Queue; +import java.util.Set; import java.util.UUID; @UtilityClass @@ -23,13 +25,24 @@ public class TestUuidGenerator { uuidWithDigit(6), uuidWithDigit(7), uuidWithDigit(8), - uuidWithDigit(9) + uuidWithDigit(9), + uuidWithChar('a'), + uuidWithChar('b'), + uuidWithChar('c'), + uuidWithChar('d'), + uuidWithChar('e'), + uuidWithChar('f') ); + private static Set staticallyUsedIndexes = new HashSet<>(); + private Queue availableUuids = null; public static void start(final int firstIndex) { + if (staticallyUsedIndexes.contains(firstIndex)) { + throw new IllegalArgumentException(firstIndex + " already used statically, try higher and amend references"); + } availableUuids = new LinkedList<>(GIVEN_UUIDS.subList(firstIndex, GIVEN_UUIDS.size())); } @@ -43,11 +56,32 @@ public class TestUuidGenerator { return availableUuids.poll(); } - public static UUID get(final int index) { + /** + * Marks the UUID as used in static initializers. + * + * @param index 0..15 + * @return a constant UUID related to the given index + */ + public static UUID use(final int index) { + staticallyUsedIndexes.add(index); + return GIVEN_UUIDS.get(index); + } + + /** + * References the UUID from the given index. + * + * @param index 0..15 + * @return a constant UUID related to the given index + */ + public static UUID ref(final int index) { return GIVEN_UUIDS.get(index); } private static @NotNull UUID uuidWithDigit(final int digit) { - return UUID.fromString(ZEROES_UUID.toString().replace('0', Character.forDigit(digit, 10))); + return UUID.fromString(ZEROES_UUID.toString().replace('0', Character.forDigit(digit, 16))); + } + + private static @NotNull UUID uuidWithChar(final char hexDigit) { + return UUID.fromString(ZEROES_UUID.toString().replace('0', hexDigit)); } }