diff --git a/src/main/java/dev/vality/wallets/hooker/handler/withdrawal/generator/WithdrawalStatusChangedHookMessageGenerator.java b/src/main/java/dev/vality/wallets/hooker/handler/withdrawal/generator/WithdrawalStatusChangedHookMessageGenerator.java index be81b4c..7c6ef03 100644 --- a/src/main/java/dev/vality/wallets/hooker/handler/withdrawal/generator/WithdrawalStatusChangedHookMessageGenerator.java +++ b/src/main/java/dev/vality/wallets/hooker/handler/withdrawal/generator/WithdrawalStatusChangedHookMessageGenerator.java @@ -5,6 +5,7 @@ import dev.vality.fistful.base.Cash; import dev.vality.fistful.withdrawal.TimestampedChange; import dev.vality.fistful.withdrawal.WithdrawalState; +import dev.vality.fistful.withdrawal.adjustment.BodyChangePlan; import dev.vality.fistful.withdrawal.status.Status; import dev.vality.swag.wallets.webhook.events.model.*; import dev.vality.wallets.hooker.domain.WebHookModel; @@ -22,6 +23,7 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; +import java.util.Objects; @Slf4j @Component @@ -56,7 +58,8 @@ protected WebhookMessage generateMessage( messageGenParams.getEventId(), messageGenParams.getCreatedAt(), messageGenParams.getExternalId(), - messageGenParams.getWithdrawalState()); + messageGenParams.getWithdrawalState(), + event.getChange().isSetAdjustment() ? event.getChange().getAdjustment().getId() : null); WebhookMessage webhookMessage = generatorService.generate(event, model, messageGenParams); webhookMessage.setParentEventId(initParenId(model, messageGenParams.getParentId())); @@ -91,7 +94,8 @@ private String initRequestBody( Long eventId, String createdAt, String externalId, - WithdrawalState withdrawalState) throws JsonProcessingException { + WithdrawalState withdrawalState, + String adjustmentId) throws JsonProcessingException { if (status.isSetFailed()) { WithdrawalFailed withdrawalFailed = new WithdrawalFailed() .withdrawalID(withdrawalId) @@ -107,7 +111,7 @@ private String initRequestBody( .withdrawalID(withdrawalId) .externalID(externalId) .fee(fee) - .body(initNewBody(withdrawalState)); + .body(initNewBody(withdrawalState, adjustmentId)); withdrawalSucceeded.setEventType(Event.EventTypeEnum.WITHDRAWAL_SUCCEEDED); withdrawalSucceeded.setEventID(eventId.toString()); withdrawalSucceeded.setOccuredAt(OffsetDateTime.parse(createdAt)); @@ -135,16 +139,27 @@ private Fee calculateFee(String withdrawalId, Long eventId, WithdrawalState with return null; } - private WithdrawalBody initNewBody(WithdrawalState withdrawalState) { + private WithdrawalBody initNewBody(WithdrawalState withdrawalState, String adjustmentId) { if (!amountChanged(withdrawalState)) { return null; } - return initBody(withdrawalState.getNewBody(), withdrawalState.getBody()); + if (withdrawalState.isSetNewBody()) { + return initBody(withdrawalState.getNewBody(), withdrawalState.getBody()); + } + + return withdrawalState.getAdjustments().stream() + .filter(adjustmentState -> Objects.equals(adjustmentState.getId(), adjustmentId)) + .map(adjustment -> adjustment.getChangesPlan().getNewBody()) + .filter(Objects::nonNull) + .map(BodyChangePlan::getNewBody) + .findFirst() + .map(newBody -> initBody(newBody, withdrawalState.getBody())) + .orElse(null); } private boolean amountChanged(WithdrawalState withdrawalState) { return withdrawalState != null - && withdrawalState.isSetNewBody(); + && (withdrawalState.isSetNewBody() || withdrawalState.isSetAdjustments()); } private WithdrawalBody initBody(Cash newBody, Cash oldBody) { diff --git a/src/test/java/dev/vality/wallets/hooker/handler/TestBeanFactory.java b/src/test/java/dev/vality/wallets/hooker/handler/TestBeanFactory.java index 953a3af..00f0f99 100644 --- a/src/test/java/dev/vality/wallets/hooker/handler/TestBeanFactory.java +++ b/src/test/java/dev/vality/wallets/hooker/handler/TestBeanFactory.java @@ -6,6 +6,9 @@ import dev.vality.fistful.destination.Destination; import dev.vality.fistful.destination.TimestampedChange; import dev.vality.fistful.withdrawal.*; +import dev.vality.fistful.withdrawal.adjustment.AdjustmentState; +import dev.vality.fistful.withdrawal.adjustment.BodyChangePlan; +import dev.vality.fistful.withdrawal.adjustment.ChangesPlan; import dev.vality.fistful.withdrawal.status.Status; import dev.vality.fistful.withdrawal.status.Succeeded; import dev.vality.kafka.common.serialization.ThriftSerializer; @@ -175,6 +178,17 @@ public static WithdrawalState createWithdrawalStateWithNewBody() { .setPostings(List.of(createFeePosting()))); } + public static WithdrawalState createWithdrawalStateWithAdjustmentState() { + return createWithdrawalState() + .setStatus(Status.succeeded(new Succeeded())) + .setAdjustments(List.of(new AdjustmentState() + .setChangesPlan(new ChangesPlan() + .setNewBody(new BodyChangePlan() + .setNewBody(createCash(1500, "USD")))))) + .setEffectiveFinalCashFlow(new FinalCashFlow() + .setPostings(List.of(createFeePosting()))); + } + public static WebHookModel createWebhookModel() { LinkedHashSet eventTypes = new LinkedHashSet<>(); eventTypes.add(EventType.WITHDRAWAL_CREATED); diff --git a/src/test/java/dev/vality/wallets/hooker/handler/WithdrawalEventHandlerTest.java b/src/test/java/dev/vality/wallets/hooker/handler/WithdrawalEventHandlerTest.java index 439c95c..ce0b788 100644 --- a/src/test/java/dev/vality/wallets/hooker/handler/WithdrawalEventHandlerTest.java +++ b/src/test/java/dev/vality/wallets/hooker/handler/WithdrawalEventHandlerTest.java @@ -104,4 +104,26 @@ void handleWithdrawalAdjustmentSucceededWebhook() { .anyMatch(body -> body.contains("\"eventType\":\"WithdrawalSucceeded\"") && body.contains("\"body\":{\"amount\":1000,\"changedAmount\":1500,\"currency\":\"USD\"}"))); } + + @Test + void handleWithdrawalAdjustmentWithAdjustmentStateSucceededWebhook() { + WebHookModel webhook = TestBeanFactory.createWebhookModel(); + when(withdrawalClient.getWithdrawalInfo(eq(TestBeanFactory.WITHDRAWAL_ID), anyLong())) + .thenReturn(TestBeanFactory.createWithdrawalStateWithAdjustmentState()); + + webHookDao.create(webhook); + + withdrawalEventService.handleEvents(List.of(TestBeanFactory.createWithdrawalEvent())); + withdrawalEventService.handleEvents(List.of(TestBeanFactory.createWithdrawalSucceeded(69L))); + withdrawalEventService.handleEvents(List.of(TestBeanFactory.createWithdrawalAdjustmentChange(70L))); + + ArgumentCaptor captor = ArgumentCaptor.forClass(WebhookMessage.class); + verify(webHookMessageSenderService, timeout(1000L).times(3)) + .send(captor.capture()); + Assertions.assertTrue(captor.getAllValues().stream() + .map(WebhookMessage::getRequestBody) + .map(String::new) + .anyMatch(body -> body.contains("\"eventType\":\"WithdrawalSucceeded\"") + && body.contains("\"body\":{\"amount\":1000,\"changedAmount\":1500,\"currency\":\"USD\"}"))); + } }