Add safe get form database (#8)

This commit is contained in:
struga 2023-10-03 14:05:32 +03:00 committed by GitHub
parent 420b93fddc
commit d817454ee6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 144 additions and 35 deletions

View File

@ -1 +1 @@
# newway
# daway

View File

@ -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<InvoicingKey> invoicesSwitchIds) throws DaoException;
}

View File

@ -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<InvoicingKey> invoicingKeys) throws DaoException;
}

View File

@ -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<InvoicingKey> invoicesSwitchIds) throws DaoException {
invoicesSwitchIds.forEach(key -> {

View File

@ -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<InvoicingKey> invoicingKeys) throws DaoException {
invoicingKeys.forEach(key -> {

View File

@ -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<PaymentWrapper> {
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));

View File

@ -53,7 +53,7 @@ public class InvoicePaymentSessionChangeFinishedMapper implements Mapper<Payment
SessionResult result =
invoicePaymentChange.getPayload().getInvoicePaymentSessionChange().getPayload().getSessionFinished()
.getResult();
PaymentRoute paymentRoute = paymentRouteDao.get(invoiceId, paymentId);
PaymentRoute paymentRoute = paymentRouteDao.safeGet(invoiceId, paymentId);
if (paymentRoute != null) {
paymentSessionInfo.setPaymentTerminal(paymentRoute.getRouteTerminalId());
}

View File

@ -1,11 +1,7 @@
package dev.vality.newway.mapper.payment.session;
import dev.vality.damsel.domain.AdditionalTransactionInfo;
import dev.vality.damsel.domain.TransactionInfo;
import dev.vality.damsel.payment_processing.InvoiceChange;
import dev.vality.damsel.payment_processing.InvoicePaymentChange;
import dev.vality.damsel.payment_processing.InvoicePaymentSessionChange;
import dev.vality.damsel.payment_processing.SessionChangePayload;
import dev.vality.geck.common.util.TypeUtil;
import dev.vality.geck.filter.Filter;
import dev.vality.geck.filter.PathConditionFilter;
@ -13,18 +9,14 @@ import dev.vality.geck.filter.condition.IsNullCondition;
import dev.vality.geck.filter.rule.PathConditionRule;
import dev.vality.machinegun.eventsink.MachineEvent;
import dev.vality.newway.domain.enums.PaymentSessionStatus;
import dev.vality.newway.domain.tables.pojos.PaymentAdditionalInfo;
import dev.vality.newway.domain.tables.pojos.PaymentSessionInfo;
import dev.vality.newway.mapper.Mapper;
import dev.vality.newway.model.InvoicingKey;
import dev.vality.newway.model.PaymentWrapper;
import dev.vality.newway.util.JsonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Map;
@Slf4j
@Component
@RequiredArgsConstructor

View File

@ -1,11 +1,7 @@
package dev.vality.newway.mapper.payment.session;
import dev.vality.damsel.domain.AdditionalTransactionInfo;
import dev.vality.damsel.domain.TransactionInfo;
import dev.vality.damsel.payment_processing.InvoiceChange;
import dev.vality.damsel.payment_processing.InvoicePaymentChange;
import dev.vality.damsel.payment_processing.InvoicePaymentSessionChange;
import dev.vality.damsel.payment_processing.SessionChangePayload;
import dev.vality.geck.common.util.TypeUtil;
import dev.vality.geck.filter.Filter;
import dev.vality.geck.filter.PathConditionFilter;
@ -13,18 +9,14 @@ import dev.vality.geck.filter.condition.IsNullCondition;
import dev.vality.geck.filter.rule.PathConditionRule;
import dev.vality.machinegun.eventsink.MachineEvent;
import dev.vality.newway.domain.enums.PaymentSessionStatus;
import dev.vality.newway.domain.tables.pojos.PaymentAdditionalInfo;
import dev.vality.newway.domain.tables.pojos.PaymentSessionInfo;
import dev.vality.newway.mapper.Mapper;
import dev.vality.newway.model.InvoicingKey;
import dev.vality.newway.model.PaymentWrapper;
import dev.vality.newway.util.JsonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Map;
@Slf4j
@Component
@RequiredArgsConstructor

View File

@ -76,7 +76,9 @@ public class InvoicingService {
InvoiceChange change,
MachineEvent machineEvent,
int changeId) {
mapEntity(paymentMappers, change, machineEvent, changeId).ifPresent(payments::add);
mapEntity(paymentMappers, change, machineEvent, changeId).ifPresent(wrapper -> {
payments.add(wrapper);
});
}
private void handleInvoiceEvent(List<InvoiceWrapper> invoices,

View File

@ -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<dev.vality.fistful.cashflow.FinalCashFlowPosting> 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<InvoiceChange> 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;
}
}

View File

@ -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<Chargeback, Integer> 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(