From d817454ee6d37d87142e029a39069914153a10e3 Mon Sep 17 00:00:00 2001 From: struga Date: Tue, 3 Oct 2023 14:05:32 +0300 Subject: [PATCH] Add safe get form database (#8) --- README.md | 2 +- .../iface/PaymentAdditionalInfoDao.java | 2 + .../dao/invoicing/iface/PaymentRouteDao.java | 2 + .../impl/PaymentAdditionalInfoDaoImpl.java | 9 +++ .../invoicing/impl/PaymentRouteDaoImpl.java | 10 +++ ...ntSessionChangeTransactionBoundMapper.java | 14 +++- ...icePaymentSessionChangeFinishedMapper.java | 2 +- ...oicePaymentSessionChangeStartedMapper.java | 8 -- ...cePaymentSessionChangeSuspendedMapper.java | 8 -- .../newway/service/InvoicingService.java | 4 +- src/test/java/dev/vality/newway/TestData.java | 74 ++++++++++++++++--- .../newway/service/InvoicingServiceTest.java | 44 ++++++++++- 12 files changed, 144 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 3ecadd1..89d6045 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# newway \ No newline at end of file +# daway \ No newline at end of file diff --git a/src/main/java/dev/vality/newway/dao/invoicing/iface/PaymentAdditionalInfoDao.java b/src/main/java/dev/vality/newway/dao/invoicing/iface/PaymentAdditionalInfoDao.java index bebf4fd..a997812 100644 --- a/src/main/java/dev/vality/newway/dao/invoicing/iface/PaymentAdditionalInfoDao.java +++ b/src/main/java/dev/vality/newway/dao/invoicing/iface/PaymentAdditionalInfoDao.java @@ -14,6 +14,8 @@ public interface PaymentAdditionalInfoDao extends GenericDao { PaymentAdditionalInfo get(String invoiceId, String paymentId) throws DaoException; + PaymentAdditionalInfo safeGet(String invoiceId, String paymentId) throws DaoException; + void switchCurrent(Set invoicesSwitchIds) throws DaoException; } \ No newline at end of file diff --git a/src/main/java/dev/vality/newway/dao/invoicing/iface/PaymentRouteDao.java b/src/main/java/dev/vality/newway/dao/invoicing/iface/PaymentRouteDao.java index 447db17..e211fa3 100644 --- a/src/main/java/dev/vality/newway/dao/invoicing/iface/PaymentRouteDao.java +++ b/src/main/java/dev/vality/newway/dao/invoicing/iface/PaymentRouteDao.java @@ -14,6 +14,8 @@ public interface PaymentRouteDao extends GenericDao { PaymentRoute get(String invoiceId, String paymentId) throws DaoException; + PaymentRoute safeGet(String invoiceId, String paymentId) throws DaoException; + void switchCurrent(Set invoicingKeys) throws DaoException; } diff --git a/src/main/java/dev/vality/newway/dao/invoicing/impl/PaymentAdditionalInfoDaoImpl.java b/src/main/java/dev/vality/newway/dao/invoicing/impl/PaymentAdditionalInfoDaoImpl.java index 84da3e1..06461ca 100644 --- a/src/main/java/dev/vality/newway/dao/invoicing/impl/PaymentAdditionalInfoDaoImpl.java +++ b/src/main/java/dev/vality/newway/dao/invoicing/impl/PaymentAdditionalInfoDaoImpl.java @@ -52,6 +52,15 @@ public class PaymentAdditionalInfoDaoImpl extends AbstractGenericDao implements new NotFoundException("PaymentAdditionalInfo not found, invoiceId=" + invoiceId + " paymentId=" + paymentId)); } + @Override + public PaymentAdditionalInfo safeGet(String invoiceId, String paymentId) throws DaoException { + Query query = getDslContext().selectFrom(PAYMENT_ADDITIONAL_INFO) + .where(PAYMENT_ADDITIONAL_INFO.INVOICE_ID.eq(invoiceId) + .and(PAYMENT_ADDITIONAL_INFO.PAYMENT_ID.eq(paymentId)) + .and(PAYMENT_ADDITIONAL_INFO.CURRENT)); + return fetchOne(query, rowMapper); + } + @Override public void switchCurrent(Set invoicesSwitchIds) throws DaoException { invoicesSwitchIds.forEach(key -> { diff --git a/src/main/java/dev/vality/newway/dao/invoicing/impl/PaymentRouteDaoImpl.java b/src/main/java/dev/vality/newway/dao/invoicing/impl/PaymentRouteDaoImpl.java index cd182e4..7010b7e 100644 --- a/src/main/java/dev/vality/newway/dao/invoicing/impl/PaymentRouteDaoImpl.java +++ b/src/main/java/dev/vality/newway/dao/invoicing/impl/PaymentRouteDaoImpl.java @@ -51,6 +51,16 @@ public class PaymentRouteDaoImpl extends AbstractGenericDao implements PaymentRo new NotFoundException("PaymentRoute not found, invoiceId=" + invoiceId + " paymentId=" + paymentId)); } + @Override + public PaymentRoute safeGet(String invoiceId, String paymentId) throws DaoException { + Query query = getDslContext().selectFrom(PAYMENT_ROUTE) + .where(PAYMENT_ROUTE.INVOICE_ID.eq(invoiceId) + .and(PAYMENT_ROUTE.PAYMENT_ID.eq(paymentId)) + .and(PAYMENT_ROUTE.CURRENT) + ); + return fetchOne(query, rowMapper); + } + @Override public void switchCurrent(Set invoicingKeys) throws DaoException { invoicingKeys.forEach(key -> { diff --git a/src/main/java/dev/vality/newway/mapper/payment/InvoicePaymentSessionChangeTransactionBoundMapper.java b/src/main/java/dev/vality/newway/mapper/payment/InvoicePaymentSessionChangeTransactionBoundMapper.java index 24b4d39..9888460 100644 --- a/src/main/java/dev/vality/newway/mapper/payment/InvoicePaymentSessionChangeTransactionBoundMapper.java +++ b/src/main/java/dev/vality/newway/mapper/payment/InvoicePaymentSessionChangeTransactionBoundMapper.java @@ -12,6 +12,7 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.machinegun.eventsink.MachineEvent; +import dev.vality.newway.dao.invoicing.iface.PaymentAdditionalInfoDao; import dev.vality.newway.domain.tables.pojos.PaymentAdditionalInfo; import dev.vality.newway.mapper.Mapper; import dev.vality.newway.model.InvoicingKey; @@ -28,6 +29,8 @@ import java.util.Map; @RequiredArgsConstructor public class InvoicePaymentSessionChangeTransactionBoundMapper implements Mapper { + private final PaymentAdditionalInfoDao paymentAdditionalInfoDao; + private Filter filter = new PathConditionFilter(new PathConditionRule( "invoice_payment_change.payload.invoice_payment_session_change.payload.session_transaction_bound", new IsNullCondition().not())); @@ -38,13 +41,17 @@ public class InvoicePaymentSessionChangeTransactionBoundMapper implements Mapper String invoiceId = event.getSourceId(); String paymentId = invoicePaymentChange.getId(); long sequenceId = event.getEventId(); - log.info("Start mapping session change transaction info, sequenceId='{}', changeId='{}', invoiceId='{}', paymentId='{}'", + log.info( + "Start mapping session change transaction info, sequenceId='{}', changeId='{}', invoiceId='{}', paymentId='{}'", sequenceId, changeId, invoiceId, paymentId); InvoicePaymentSessionChange sessionChange = invoicePaymentChange.getPayload().getInvoicePaymentSessionChange(); SessionChangePayload payload = sessionChange.getPayload(); TransactionInfo transactionInfo = payload.getSessionTransactionBound().getTrx(); - + PaymentAdditionalInfo paymentAdditionalInfo = paymentAdditionalInfoDao.safeGet(invoiceId, paymentId); PaymentAdditionalInfo additionalInfo = new PaymentAdditionalInfo(); + if (paymentAdditionalInfo != null) { + additionalInfo = paymentAdditionalInfo; + } additionalInfo.setEventCreatedAt(TypeUtil.stringToLocalDateTime(event.getCreatedAt())); additionalInfo.setInvoiceId(invoiceId); additionalInfo.setPaymentId(paymentId); @@ -69,7 +76,8 @@ public class InvoicePaymentSessionChangeTransactionBoundMapper implements Mapper } additionalInfo.setSequenceId(sequenceId); additionalInfo.setChangeId(changeId); - log.info("Payment session transaction info has been mapped, sequenceId='{}', changeId='{}', invoiceId='{}', paymentId='{}'", + log.info( + "Payment session transaction info has been mapped, sequenceId='{}', changeId='{}', invoiceId='{}', paymentId='{}'", sequenceId, changeId, invoiceId, paymentId); PaymentWrapper paymentWrapper = new PaymentWrapper(); paymentWrapper.setKey(InvoicingKey.buildKey(invoiceId, paymentId)); diff --git a/src/main/java/dev/vality/newway/mapper/payment/session/InvoicePaymentSessionChangeFinishedMapper.java b/src/main/java/dev/vality/newway/mapper/payment/session/InvoicePaymentSessionChangeFinishedMapper.java index 223d13e..e9fa3b3 100644 --- a/src/main/java/dev/vality/newway/mapper/payment/session/InvoicePaymentSessionChangeFinishedMapper.java +++ b/src/main/java/dev/vality/newway/mapper/payment/session/InvoicePaymentSessionChangeFinishedMapper.java @@ -53,7 +53,7 @@ public class InvoicePaymentSessionChangeFinishedMapper implements Mapper { + payments.add(wrapper); + }); } private void handleInvoiceEvent(List invoices, diff --git a/src/test/java/dev/vality/newway/TestData.java b/src/test/java/dev/vality/newway/TestData.java index 3f99dca..6b28e57 100644 --- a/src/test/java/dev/vality/newway/TestData.java +++ b/src/test/java/dev/vality/newway/TestData.java @@ -20,22 +20,23 @@ import dev.vality.newway.domain.enums.WithdrawalAdjustmentStatus; import dev.vality.newway.domain.enums.WithdrawalAdjustmentType; import dev.vality.newway.domain.tables.pojos.FistfulCashFlow; import dev.vality.newway.domain.tables.pojos.WithdrawalAdjustment; +import dev.vality.sink.common.serialization.impl.PaymentEventPayloadSerializer; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; import java.time.Instant; import java.time.LocalDateTime; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.UUID; +import java.time.temporal.ChronoUnit; +import java.util.*; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class TestData { public static InvoiceChange buildInvoiceChangeChargebackCreated() { InvoicePaymentChargeback invoicePaymentChargeback = - dev.vality.testcontainers.annotations.util.RandomBeans.random(InvoicePaymentChargeback.class, "context", "status", "reason", "stage"); + dev.vality.testcontainers.annotations.util.RandomBeans.random(InvoicePaymentChargeback.class, "context", + "status", "reason", "stage"); invoicePaymentChargeback.setCreatedAt(TypeUtil.temporalToString(Instant.now())); InvoicePaymentChargebackStatus invoicePaymentChargebackStatus = buildChargebackStatus(); invoicePaymentChargeback.setStatus(invoicePaymentChargebackStatus); @@ -133,7 +134,8 @@ public class TestData { private static InvoiceChange buildInvoiceChangeChargeback(InvoicePaymentChargebackChangePayload payload) { InvoicePaymentChargeback invoicePaymentChargeback = - dev.vality.testcontainers.annotations.util.RandomBeans.random(InvoicePaymentChargeback.class, "context", "status", "reason", "stage"); + dev.vality.testcontainers.annotations.util.RandomBeans.random(InvoicePaymentChargeback.class, "context", + "status", "reason", "stage"); invoicePaymentChargeback.setCreatedAt(TypeUtil.temporalToString(Instant.now())); InvoicePaymentChargebackStatus invoicePaymentChargebackStatus = buildChargebackStatus(); invoicePaymentChargeback.setStatus(invoicePaymentChargebackStatus); @@ -373,7 +375,8 @@ public class TestData { } private static List getFinalCashFlowPostings() { - dev.vality.fistful.cashflow.FinalCashFlowPosting fistfulPosting = new dev.vality.fistful.cashflow.FinalCashFlowPosting(); + dev.vality.fistful.cashflow.FinalCashFlowPosting fistfulPosting = + new dev.vality.fistful.cashflow.FinalCashFlowPosting(); fistfulPosting.setDestination( new dev.vality.fistful.cashflow.FinalCashFlowAccount() .setAccountId("1") @@ -386,7 +389,8 @@ public class TestData { fistfulPosting.setVolume(new dev.vality.fistful.base.Cash() .setAmount(100L) .setCurrency(new dev.vality.fistful.base.CurrencyRef("RUB"))); - dev.vality.fistful.cashflow.FinalCashFlowPosting providerPosting = new dev.vality.fistful.cashflow.FinalCashFlowPosting(); + dev.vality.fistful.cashflow.FinalCashFlowPosting providerPosting = + new dev.vality.fistful.cashflow.FinalCashFlowPosting(); providerPosting.setDestination( new dev.vality.fistful.cashflow.FinalCashFlowAccount() .setAccountId("3") @@ -399,7 +403,8 @@ public class TestData { providerPosting.setVolume(new dev.vality.fistful.base.Cash() .setAmount(100L) .setCurrency(new dev.vality.fistful.base.CurrencyRef("RUB"))); - dev.vality.fistful.cashflow.FinalCashFlowPosting merchantSourcePosting = new dev.vality.fistful.cashflow.FinalCashFlowPosting(); + dev.vality.fistful.cashflow.FinalCashFlowPosting merchantSourcePosting = + new dev.vality.fistful.cashflow.FinalCashFlowPosting(); merchantSourcePosting.setDestination( new dev.vality.fistful.cashflow.FinalCashFlowAccount() .setAccountId("5") @@ -412,7 +417,8 @@ public class TestData { merchantSourcePosting.setVolume(new dev.vality.fistful.base.Cash() .setAmount(200L) .setCurrency(new dev.vality.fistful.base.CurrencyRef("RUB"))); - dev.vality.fistful.cashflow.FinalCashFlowPosting merchantDestinationPosting = new dev.vality.fistful.cashflow.FinalCashFlowPosting(); + dev.vality.fistful.cashflow.FinalCashFlowPosting merchantDestinationPosting = + new dev.vality.fistful.cashflow.FinalCashFlowPosting(); merchantDestinationPosting.setDestination( new dev.vality.fistful.cashflow.FinalCashFlowAccount() .setAccountId("7") @@ -507,4 +513,52 @@ public class TestData { return timestampedChange; } + public static MachineEvent createInvoice(InvoicePaymentChangePayload invoicePaymentChangePayload) { + PaymentEventPayloadSerializer paymentEventPayloadSerializer = new PaymentEventPayloadSerializer(); + MachineEvent message = new MachineEvent(); + message.setCreatedAt(TypeUtil.temporalToString(LocalDateTime.now().truncatedTo(ChronoUnit.MICROS))); + EventPayload payload = new EventPayload(); + ArrayList invoiceChanges = new ArrayList<>(); + InvoiceChange invoiceChange = new InvoiceChange(); + + invoiceChange.setInvoicePaymentChange(new InvoicePaymentChange() + .setPayload(invoicePaymentChangePayload) + .setId("test")); + invoiceChanges.add(invoiceChange); + payload.setInvoiceChanges(invoiceChanges); + Value data = new Value(); + data.setBin(paymentEventPayloadSerializer.serialize(payload)); + message.setData(data); + return message; + } + + @NotNull + public static InvoicePaymentChangePayload createPaymentChange() { + InvoicePaymentChangePayload invoicePaymentChangePayload = new InvoicePaymentChangePayload(); + TargetInvoicePaymentStatus targetInvoicePaymentStatus = new TargetInvoicePaymentStatus(); + targetInvoicePaymentStatus.setCaptured(new InvoicePaymentCaptured()); + SessionChangePayload sessionChangePayload = new SessionChangePayload(); + SessionResult sessionResult = new SessionResult(); + sessionResult.setSucceeded(new SessionSucceeded()); + sessionChangePayload.setSessionFinished( + new SessionFinished().setResult(sessionResult)); + invoicePaymentChangePayload.setInvoicePaymentSessionChange( + new InvoicePaymentSessionChange() + .setTarget(targetInvoicePaymentStatus) + .setPayload(sessionChangePayload)); + return invoicePaymentChangePayload; + } + + @NotNull + public static InvoicePaymentChangePayload createPaymentChangeRoute() { + InvoicePaymentChangePayload invoicePaymentChangePayload = new InvoicePaymentChangePayload(); + invoicePaymentChangePayload.setInvoicePaymentRouteChanged( + new InvoicePaymentRouteChanged() + .setRoute(new PaymentRoute() + .setTerminal(new TerminalRef() + .setId(123)) + .setProvider(new ProviderRef() + .setId(321)))); + return invoicePaymentChangePayload; + } } diff --git a/src/test/java/dev/vality/newway/service/InvoicingServiceTest.java b/src/test/java/dev/vality/newway/service/InvoicingServiceTest.java index ae2fe0a..1112af6 100644 --- a/src/test/java/dev/vality/newway/service/InvoicingServiceTest.java +++ b/src/test/java/dev/vality/newway/service/InvoicingServiceTest.java @@ -1,13 +1,15 @@ package dev.vality.newway.service; -import dev.vality.damsel.payment_processing.EventPayload; -import dev.vality.damsel.payment_processing.InvoiceChange; +import dev.vality.damsel.domain.*; +import dev.vality.damsel.payment_processing.*; import dev.vality.geck.common.util.TypeUtil; import dev.vality.machinegun.eventsink.MachineEvent; +import dev.vality.machinegun.msgpack.Value; import dev.vality.newway.TestData; import dev.vality.newway.dao.invoicing.iface.CashFlowDao; import dev.vality.newway.dao.invoicing.iface.ChargebackDao; import dev.vality.newway.dao.invoicing.iface.PaymentDao; +import dev.vality.newway.dao.invoicing.iface.PaymentRouteDao; import dev.vality.newway.domain.enums.PaymentChangeType; import dev.vality.newway.domain.tables.pojos.Chargeback; import dev.vality.newway.domain.tables.pojos.Payment; @@ -15,8 +17,13 @@ import dev.vality.newway.factory.machine.event.MachineEventCopyFactory; import dev.vality.newway.handler.event.stock.impl.invoicing.InvoicingHandler; import dev.vality.newway.handler.event.stock.impl.invoicing.chargeback.*; import dev.vality.newway.mapper.Mapper; +import dev.vality.newway.mapper.payment.InvoicePaymentRouteChangedMapper; +import dev.vality.newway.mapper.payment.session.InvoicePaymentSessionChangeFinishedMapper; import dev.vality.newway.model.InvoiceWrapper; import dev.vality.sink.common.parser.impl.MachineEventParser; +import dev.vality.sink.common.serialization.impl.PaymentEventPayloadDeserializer; +import dev.vality.sink.common.serialization.impl.PaymentEventPayloadSerializer; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -25,6 +32,8 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.time.Instant; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.*; import static org.mockito.Mockito.*; @@ -41,6 +50,8 @@ public class InvoicingServiceTest { private PaymentWrapperService paymentWrapperService; @MockBean private PartyShopCacheService partyShopCacheService; + @MockBean + private PaymentRouteDao paymentRouteDao; @Mock private MachineEventCopyFactory machineEventCopyFactory; @Mock @@ -60,7 +71,8 @@ public class InvoicingServiceTest { when(right.accept(any())).thenReturn(true); rightHandlers.add(right); - when(paymentDao.get(any(), any())).thenReturn(dev.vality.testcontainers.annotations.util.RandomBeans.random(Payment.class)); + when(paymentDao.get(any(), any())).thenReturn( + dev.vality.testcontainers.annotations.util.RandomBeans.random(Payment.class)); when(machineEventCopyFactory.create(any(), any(), any(), any())).thenReturn(new Chargeback()); when(machineEventCopyFactory.create(any(), any(), any(), any(), any())).thenReturn(new Chargeback()); @@ -110,6 +122,32 @@ public class InvoicingServiceTest { verify(rightHandlers.get(0), times(1)).map(any(), any(), any()); } + @Test + public void handlerRewrites() { + InvoicingService invoicingService = new InvoicingService( + new ArrayList<>(), + rightHandlers, + List.of(new InvoicePaymentRouteChangedMapper(), + new InvoicePaymentSessionChangeFinishedMapper(paymentRouteDao)), + partyShopCacheService, + invoiceWrapperService, + paymentWrapperService, + new MachineEventParser<>(new PaymentEventPayloadDeserializer()) + ); + + MachineEvent message = TestData.createInvoice(TestData.createPaymentChange()); + MachineEvent message_2 = TestData.createInvoice(TestData.createPaymentChangeRoute()); + + EventPayload eventPayload = new EventPayload(); + eventPayload.setInvoiceChanges(Collections.singletonList(new InvoiceChange())); + when(parser.parse(any())).thenReturn(eventPayload); + + invoicingService.handleEvents(List.of(message_2, message)); + + verify(rightHandlers.get(0), times(2)).accept(any()); + verify(rightHandlers.get(0), times(2)).map(any(), any(), any()); + } + @Test public void handlerNotSupportInvoicing() { InvoicingService invoicingService = new InvoicingService(