Add event handler cash change (#28)

This commit is contained in:
struga 2023-11-17 15:24:30 +03:00 committed by GitHub
parent 83f79b0f69
commit 566a3958bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 237 additions and 4 deletions

View File

@ -6,7 +6,7 @@
<parent>
<groupId>dev.vality</groupId>
<artifactId>service-parent-pom</artifactId>
<version>2.1.7</version>
<version>2.1.8</version>
</parent>
<artifactId>daway</artifactId>
@ -168,8 +168,7 @@
<dependency>
<groupId>dev.vality</groupId>
<artifactId>damsel</artifactId>
<!-- TODO: bump version in parent -->
<version>1.597-bfedcb9</version>
<version>1.611-958e5f0</version>
</dependency>
<dependency>
<groupId>dev.vality</groupId>

View File

@ -0,0 +1,17 @@
package dev.vality.daway.dao.invoicing.iface;
import dev.vality.dao.GenericDao;
import dev.vality.daway.domain.tables.pojos.PaymentCashChange;
import dev.vality.daway.exception.DaoException;
import dev.vality.daway.model.InvoicingKey;
import java.util.List;
import java.util.Set;
public interface PaymentCashChangeDao extends GenericDao {
void saveBatch(List<PaymentCashChange> paymentCashChanges) throws DaoException;
void switchCurrent(Set<InvoicingKey> invoicingKeys) throws DaoException;
}

View File

@ -0,0 +1,83 @@
package dev.vality.daway.dao.invoicing.impl;
import dev.vality.dao.impl.AbstractGenericDao;
import dev.vality.daway.dao.invoicing.iface.PaymentCashChangeDao;
import dev.vality.daway.domain.tables.pojos.PaymentCashChange;
import dev.vality.daway.domain.tables.records.PaymentCashChangeRecord;
import dev.vality.daway.domain.tables.records.PaymentFeeRecord;
import dev.vality.daway.exception.DaoException;
import dev.vality.daway.model.InvoicingKey;
import dev.vality.mapper.RecordRowMapper;
import org.jooq.Query;
import org.jooq.impl.DSL;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static dev.vality.daway.domain.Tables.PAYMENT_CASH_CHANGE;
import static dev.vality.daway.domain.tables.PaymentFee.PAYMENT_FEE;
@Component
public class PaymentCashChangeDaoImpl extends AbstractGenericDao implements PaymentCashChangeDao {
private final RowMapper<PaymentCashChange> cashChangeRowMapper;
public PaymentCashChangeDaoImpl(DataSource dataSource) {
super(dataSource);
cashChangeRowMapper = new RecordRowMapper<>(PAYMENT_CASH_CHANGE, PaymentCashChange.class);
}
@Override
public void saveBatch(List<PaymentCashChange> paymentCashChanges) throws DaoException {
List<Query> queries = paymentCashChanges.stream()
.map(cashChange -> getDslContext().newRecord(PAYMENT_CASH_CHANGE, cashChange))
.map(this::prepareInsertQuery)
.collect(Collectors.toList());
batchExecute(queries);
}
private Query prepareInsertQuery(PaymentCashChangeRecord record) {
return getDslContext().insertInto(PAYMENT_CASH_CHANGE)
.set(record)
.onConflict(
PAYMENT_CASH_CHANGE.INVOICE_ID,
PAYMENT_CASH_CHANGE.PAYMENT_ID,
PAYMENT_CASH_CHANGE.SEQUENCE_ID,
PAYMENT_CASH_CHANGE.CHANGE_ID
)
.doNothing();
}
@Override
public void switchCurrent(Set<InvoicingKey> invoicingKeys) throws DaoException {
invoicingKeys.forEach(key -> {
setOldPaymentFeeNotCurrent(key);
setLatestPaymentFeeCurrent(key);
});
}
private void setOldPaymentFeeNotCurrent(InvoicingKey key) {
execute(getDslContext().update(PAYMENT_CASH_CHANGE)
.set(PAYMENT_CASH_CHANGE.CURRENT, false)
.where(PAYMENT_CASH_CHANGE.INVOICE_ID.eq(key.getInvoiceId())
.and(PAYMENT_CASH_CHANGE.PAYMENT_ID.eq(key.getPaymentId()))
.and(PAYMENT_CASH_CHANGE.CURRENT))
);
}
private void setLatestPaymentFeeCurrent(InvoicingKey key) {
execute(getDslContext().update(PAYMENT_CASH_CHANGE)
.set(PAYMENT_CASH_CHANGE.CURRENT, true)
.where(PAYMENT_CASH_CHANGE.ID.eq(
DSL.select(DSL.max(PAYMENT_CASH_CHANGE.ID))
.from(PAYMENT_CASH_CHANGE)
.where(PAYMENT_CASH_CHANGE.INVOICE_ID.eq(key.getInvoiceId())
.and(PAYMENT_CASH_CHANGE.PAYMENT_ID.eq(key.getPaymentId())))
))
);
}
}

View File

@ -0,0 +1,39 @@
package dev.vality.daway.handler.wrapper.payment;
import dev.vality.daway.dao.invoicing.iface.PaymentCashChangeDao;
import dev.vality.daway.domain.tables.pojos.PaymentCashChange;
import dev.vality.daway.handler.wrapper.WrapperHandler;
import dev.vality.daway.model.PaymentWrapper;
import dev.vality.daway.util.PaymentWrapperUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Component
public class PaymentCashChangeWrapperHandler implements WrapperHandler<PaymentWrapper> {
private final PaymentCashChangeDao paymentCashChangeDao;
@Override
public boolean accept(List<PaymentWrapper> wrappers) {
return wrappers.stream()
.map(PaymentWrapper::getPaymentCashChange)
.anyMatch(Objects::nonNull);
}
@Override
public void saveBatch(List<PaymentWrapper> wrappers) {
List<PaymentWrapper> processableWrappers = wrappers.stream()
.filter(paymentWrapper -> Objects.nonNull(paymentWrapper.getPaymentFee()))
.collect(Collectors.toList());
List<PaymentCashChange> paymentFees = processableWrappers.stream()
.map(PaymentWrapper::getPaymentCashChange)
.collect(Collectors.toList());
paymentCashChangeDao.saveBatch(paymentFees);
paymentCashChangeDao.switchCurrent(PaymentWrapperUtil.getInvoicingKeys(processableWrappers));
}
}

View File

@ -0,0 +1,72 @@
package dev.vality.daway.mapper.payment;
import dev.vality.damsel.domain.Cash;
import dev.vality.damsel.payment_processing.InvoiceChange;
import dev.vality.damsel.payment_processing.InvoicePaymentCashChanged;
import dev.vality.damsel.payment_processing.InvoicePaymentChange;
import dev.vality.daway.domain.tables.pojos.PaymentCashChange;
import dev.vality.daway.mapper.Mapper;
import dev.vality.daway.model.InvoicingKey;
import dev.vality.daway.model.PaymentWrapper;
import dev.vality.geck.common.util.TypeUtil;
import dev.vality.geck.filter.Filter;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class InvoicePaymentCashChangedMapper implements Mapper<PaymentWrapper> {
private Filter filter = new PathConditionFilter(new PathConditionRule(
"invoice_payment_change.payload.invoice_payment_cash_changed",
new IsNullCondition().not()));
@Override
public PaymentWrapper map(InvoiceChange change, MachineEvent event, Integer changeId) {
InvoicePaymentChange invoicePaymentChange = change.getInvoicePaymentChange();
String invoiceId = event.getSourceId();
String paymentId = invoicePaymentChange.getId();
long sequenceId = event.getEventId();
log.info("Start mapping payment cash change, sequenceId='{}', changeId='{}', invoiceId='{}', paymentId='{}'",
sequenceId, changeId, invoiceId, paymentId);
InvoicePaymentCashChanged invoicePaymentCashChanged =
invoicePaymentChange.getPayload().getInvoicePaymentCashChanged();
PaymentWrapper paymentWrapper = new PaymentWrapper();
paymentWrapper.setKey(InvoicingKey.buildKey(invoiceId, paymentId));
PaymentCashChange cashChange = new PaymentCashChange();
cashChange.setWtime(null);
cashChange.setId(null);
cashChange.setChangeId(changeId);
cashChange.setSequenceId(sequenceId);
cashChange.setPaymentId(paymentId);
cashChange.setInvoiceId(invoiceId);
cashChange.setCurrent(true);
cashChange.setEventCreatedAt(TypeUtil.stringToLocalDateTime(event.getCreatedAt()));
Cash newCash = invoicePaymentCashChanged.getNewCash();
cashChange.setNewAmount(newCash.getAmount());
cashChange.setNewCurrencyCode(newCash.getCurrency().getSymbolicCode());
Cash oldCash = invoicePaymentCashChanged.getOldCash();
cashChange.setOldAmount(oldCash.getAmount());
cashChange.setOldCurrencyCode(oldCash.getCurrency().getSymbolicCode());
paymentWrapper.setPaymentCashChange(cashChange);
log.info("Payment cash has been mapped, sequenceId='{}', changeId='{}', invoiceId='{}', paymentId='{}'",
sequenceId, changeId, invoiceId, paymentId);
return paymentWrapper;
}
@Override
public Filter<InvoiceChange> getFilter() {
return filter;
}
}

View File

@ -19,5 +19,6 @@ public class PaymentWrapper {
private PaymentFee paymentFee;
private PaymentRoute paymentRoute;
private CashFlowWrapper cashFlowWrapper;
private PaymentCashChange paymentCashChange;
private InvoicingKey key;
}

View File

@ -0,0 +1,20 @@
CREATE TABLE dw.payment_cash_change
(
id bigserial NOT NULL,
event_created_at timestamp without time zone NOT NULL,
invoice_id character varying NOT NULL,
payment_id character varying NOT NULL,
new_amount bigint NOT NULL,
new_currency_code character varying NOT NULL,
old_amount bigint NOT NULL,
old_currency_code character varying NOT NULL,
current BOOLEAN NOT NULL DEFAULT false,
wtime timestamp without time zone NOT NULL DEFAULT (now() AT TIME ZONE 'utc'::text),
sequence_id bigint,
change_id integer,
CONSTRAINT payment_cash_change_pkey PRIMARY KEY (id),
CONSTRAINT payment_cash_change_uniq UNIQUE (invoice_id, payment_id, sequence_id, change_id)
);

View File

@ -7,6 +7,7 @@ import dev.vality.daway.dao.invoicing.impl.PaymentDaoImpl;
import dev.vality.daway.domain.enums.PaymentChangeType;
import dev.vality.daway.domain.tables.pojos.CashFlow;
import dev.vality.daway.domain.tables.pojos.CashFlowLink;
import dev.vality.daway.domain.tables.pojos.PaymentCashChange;
import dev.vality.daway.domain.tables.pojos.PaymentFee;
import dev.vality.daway.model.CashFlowWrapper;
import dev.vality.daway.model.InvoicingKey;
@ -112,7 +113,8 @@ public class PaymentWrapperServiceTest {
assertEquals(expected.getCashFlowWrapper().getCashFlowLink(), cashFlowLinkDao.get(invoiceId, paymentId));
assertEquals(
new HashSet<>(expected.getCashFlowWrapper().getCashFlows()),
new HashSet<>(cashFlowDao.getByObjId(expected.getCashFlowWrapper().getCashFlowLink().getId(), PaymentChangeType.payment))
new HashSet<>(cashFlowDao.getByObjId(expected.getCashFlowWrapper().getCashFlowLink().getId(),
PaymentChangeType.payment))
);
}