revert test

This commit is contained in:
Michael Hoennig 2024-11-22 17:21:36 +01:00
parent d6d24803cd
commit 865ea3657e
4 changed files with 121 additions and 23 deletions

View File

@ -151,17 +151,16 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
resource.setMembershipUuid(entity.getMembership().getUuid()); resource.setMembershipUuid(entity.getMembership().getUuid());
resource.setMembershipMemberNumber(entity.getMembership().getTaggedMemberNumber()); resource.setMembershipMemberNumber(entity.getMembership().getTaggedMemberNumber());
// FIXME: actually needed?
if (entity.getReversalAssetTx() != null) { if (entity.getReversalAssetTx() != null) {
resource.getReversalAssetTx().setRevertedAssetTxUuid(entity.getUuid()); resource.getReversalAssetTx().setRevertedAssetTxUuid(entity.getUuid());
resource.getReversalAssetTx().setMembershipUuid(entity.getRevertedAssetTx().getMembership().getUuid()); resource.getReversalAssetTx().setMembershipUuid(entity.getMembership().getUuid());
resource.getReversalAssetTx().setMembershipMemberNumber(entity.getRevertedAssetTx().getTaggedMemberNumber()); resource.getReversalAssetTx().setMembershipMemberNumber(entity.getTaggedMemberNumber());
} }
if (entity.getRevertedAssetTx() != null) { if (entity.getRevertedAssetTx() != null) {
resource.getRevertedAssetTx().setReversalAssetTxUuid(entity.getUuid()); resource.getRevertedAssetTx().setReversalAssetTxUuid(entity.getUuid());
resource.getRevertedAssetTx().setMembershipUuid(entity.getReversalAssetTx().getMembership().getUuid()); resource.getRevertedAssetTx().setMembershipUuid(entity.getMembership().getUuid());
resource.getRevertedAssetTx().setMembershipMemberNumber(entity.getReversalAssetTx().getTaggedMemberNumber()); resource.getRevertedAssetTx().setMembershipMemberNumber(entity.getTaggedMemberNumber());
} }
if (entity.getAdoptionAssetTx() != null) { if (entity.getAdoptionAssetTx() != null) {
@ -170,7 +169,6 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
resource.getAdoptionAssetTx().setMembershipMemberNumber(entity.getAdoptionAssetTx().getTaggedMemberNumber()); resource.getAdoptionAssetTx().setMembershipMemberNumber(entity.getAdoptionAssetTx().getTaggedMemberNumber());
} }
// FIXME: actually needed?
if (entity.getTransferAssetTx() != null) { if (entity.getTransferAssetTx() != null) {
resource.getTransferAssetTx().setAdoptionAssetTxUuid(entity.getUuid()); resource.getTransferAssetTx().setAdoptionAssetTxUuid(entity.getUuid());
resource.getTransferAssetTx().setMembershipUuid(entity.getTransferAssetTx().getMembership().getUuid()); resource.getTransferAssetTx().setMembershipUuid(entity.getTransferAssetTx().getMembership().getUuid());
@ -179,6 +177,7 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
}; };
final BiConsumer<HsOfficeCoopAssetsTransactionInsertResource, HsOfficeCoopAssetsTransactionEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> { final BiConsumer<HsOfficeCoopAssetsTransactionInsertResource, HsOfficeCoopAssetsTransactionEntity> RESOURCE_TO_ENTITY_POSTMAPPER = (resource, entity) -> {
if (resource.getMembershipUuid() != null) { if (resource.getMembershipUuid() != null) {
final HsOfficeMembershipEntity membership = ofNullable(emw.find(HsOfficeMembershipEntity.class, resource.getMembershipUuid())) final HsOfficeMembershipEntity membership = ofNullable(emw.find(HsOfficeMembershipEntity.class, resource.getMembershipUuid()))
.orElseThrow(() -> new EntityNotFoundException("ERROR: [400] membership.uuid %s not found".formatted( .orElseThrow(() -> new EntityNotFoundException("ERROR: [400] membership.uuid %s not found".formatted(
@ -186,9 +185,14 @@ public class HsOfficeCoopAssetsTransactionController implements HsOfficeCoopAsse
entity.setMembership(membership); entity.setMembership(membership);
} }
if (resource.getRevertedAssetTxUuid() != null) { 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( .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); final var adoptingMembership = determineAdoptingMembership(resource);

View File

@ -223,7 +223,7 @@ begin
) )
select target.* select target.*
from %1$s as 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; order by %2$s;
grant all privileges on %1$s_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME}; grant all privileges on %1$s_rv to ${HSADMINNG_POSTGRES_RESTRICTED_USERNAME};

View File

@ -22,6 +22,8 @@ import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
@ -40,10 +42,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
class HsOfficeCoopAssetsTransactionControllerRestTest { 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 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"; private static final String ORIGIN_MEMBER_NUMBER = "M-1111100";
public final HsOfficeMembershipEntity ORIGIN_TARGET_MEMBER_ENTITY = HsOfficeMembershipEntity.builder() public final HsOfficeMembershipEntity ORIGIN_TARGET_MEMBER_ENTITY = HsOfficeMembershipEntity.builder()
.uuid(ORIGIN_MEMBERSHIP_UUID) .uuid(ORIGIN_MEMBERSHIP_UUID)
@ -53,7 +55,7 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
.memberNumberSuffix(suffixOf(ORIGIN_MEMBER_NUMBER)) .memberNumberSuffix(suffixOf(ORIGIN_MEMBER_NUMBER))
.build(); .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"; private static final String AVAILABLE_TARGET_MEMBER_NUMBER = "M-1234500";
public final HsOfficeMembershipEntity AVAILABLE_MEMBER_ENTITY = HsOfficeMembershipEntity.builder() public final HsOfficeMembershipEntity AVAILABLE_MEMBER_ENTITY = HsOfficeMembershipEntity.builder()
.uuid(AVAILABLE_TARGET_MEMBERSHIP_UUID) .uuid(AVAILABLE_TARGET_MEMBERSHIP_UUID)
@ -63,7 +65,20 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
.memberNumberSuffix(suffixOf(AVAILABLE_TARGET_MEMBER_NUMBER)) .memberNumberSuffix(suffixOf(AVAILABLE_TARGET_MEMBER_NUMBER))
.build(); .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 @Autowired
MockMvc mockMvc; MockMvc mockMvc;
@ -195,14 +210,24 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
enum SuccessfullyCreatedTestCases { 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 requestBody -> requestBody
.with("transactionType", "TRANSFER") .with("transactionType", "TRANSFER")
.with("assetValue", -64.00) .with("assetValue", -64.00)
.with("adoptingMembership.memberNumber", AVAILABLE_TARGET_MEMBER_NUMBER), .with("adoptingMembership.memberNumber", AVAILABLE_TARGET_MEMBER_NUMBER),
Expected.TRANSFER_RESPONSE), Expected.TRANSFER_RESPONSE),
ADOPTING_MEMBERSHIP_UUID_FOR_TRANSFER_MUST_BE_GIVEN_AND_AVAILABLE( TRANSFER_TO_GIVEN_AVAILABLE_MEMBERSHIP_UUID(
requestBody -> requestBody requestBody -> requestBody
.with("transactionType", "TRANSFER") .with("transactionType", "TRANSFER")
.with("assetValue", -64.00) .with("assetValue", -64.00)
@ -226,9 +251,42 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
private static class Expected { 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 = """ 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.uuid": "%{ORIGIN_MEMBERSHIP_UUID}",
"membership.memberNumber": "%{ORIGIN_MEMBER_NUMBER}", "membership.memberNumber": "%{ORIGIN_MEMBER_NUMBER}",
"transactionType": "TRANSFER", "transactionType": "TRANSFER",
@ -238,14 +296,14 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
"membership.memberNumber": "%{AVAILABLE_TARGET_MEMBER_NUMBER}", "membership.memberNumber": "%{AVAILABLE_TARGET_MEMBER_NUMBER}",
"transactionType": "ADOPTION", "transactionType": "ADOPTION",
"assetValue": 64.00, "assetValue": 64.00,
"transferAssetTx.uuid": "%{NEW_EXPLICITLY_CREATED_ASSET_TX_UUID}" "transferAssetTx.uuid": "%{NEW_EXPLICITLY_CREATED_TRANSFER_ASSET_TX_UUID}"
}, },
"transferAssetTx": null, "transferAssetTx": null,
"revertedAssetTx": null, "revertedAssetTx": null,
"reversalAssetTx": 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_MEMBERSHIP_UUID}", ORIGIN_MEMBERSHIP_UUID.toString())
.replace("%{ORIGIN_MEMBER_NUMBER}", ORIGIN_MEMBER_NUMBER) .replace("%{ORIGIN_MEMBER_NUMBER}", ORIGIN_MEMBER_NUMBER)
.replace("%{AVAILABLE_MEMBERSHIP_UUID}", AVAILABLE_TARGET_MEMBERSHIP_UUID.toString()) .replace("%{AVAILABLE_MEMBERSHIP_UUID}", AVAILABLE_TARGET_MEMBERSHIP_UUID.toString())
@ -269,8 +327,8 @@ class HsOfficeCoopAssetsTransactionControllerRestTest {
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
// then // then
.andExpect(jsonPath("$", lenientlyEquals(testCase.expectedResponseBody))) .andExpect(status().is2xxSuccessful())
.andExpect(status().is2xxSuccessful()); .andExpect(jsonPath("$", lenientlyEquals(testCase.expectedResponseBody)));
} }
@BeforeEach @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(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(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))) when(coopAssetsTransactionRepo.save(any(HsOfficeCoopAssetsTransactionEntity.class)))
.thenAnswer(invocation -> { .thenAnswer(invocation -> {
final var entity = (HsOfficeCoopAssetsTransactionEntity) invocation.getArgument(0); final var entity = (HsOfficeCoopAssetsTransactionEntity) invocation.getArgument(0);

View File

@ -3,9 +3,11 @@ package net.hostsharing.hsadminng.test;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
@UtilityClass @UtilityClass
@ -23,13 +25,24 @@ public class TestUuidGenerator {
uuidWithDigit(6), uuidWithDigit(6),
uuidWithDigit(7), uuidWithDigit(7),
uuidWithDigit(8), uuidWithDigit(8),
uuidWithDigit(9) uuidWithDigit(9),
uuidWithChar('a'),
uuidWithChar('b'),
uuidWithChar('c'),
uuidWithChar('d'),
uuidWithChar('e'),
uuidWithChar('f')
); );
private static Set<Integer> staticallyUsedIndexes = new HashSet<>();
private Queue<UUID> availableUuids = null; private Queue<UUID> availableUuids = null;
public static void start(final int firstIndex) { 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())); availableUuids = new LinkedList<>(GIVEN_UUIDS.subList(firstIndex, GIVEN_UUIDS.size()));
} }
@ -43,11 +56,32 @@ public class TestUuidGenerator {
return availableUuids.poll(); 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); return GIVEN_UUIDS.get(index);
} }
private static @NotNull UUID uuidWithDigit(final int digit) { 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));
} }
} }