mirror of
https://github.com/valitydev/midgard.git
synced 2024-11-06 01:05:21 +00:00
PROX-266: Clearing MTS Bank. Testing and debugging application
This commit is contained in:
parent
bc78208d16
commit
371149ddd4
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
[submodule "build_utils"]
|
||||
path = build_utils
|
||||
url = git@github.com:rbkmoney/build_utils.git
|
||||
branch = master
|
16
Jenkinsfile
vendored
Normal file
16
Jenkinsfile
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
#!groovy
|
||||
build('midgard', 'java-maven') {
|
||||
checkoutRepo()
|
||||
loadBuildUtils()
|
||||
|
||||
def javaServicePipeline
|
||||
runStage('load JavaService pipeline') {
|
||||
javaServicePipeline = load("build_utils/jenkins_lib/pipeJavaService.groovy")
|
||||
}
|
||||
|
||||
def serviceName = env.REPO_NAME
|
||||
def mvnArgs = '-DjvmArgs="-Xmx256m"'
|
||||
def useJava11 = false
|
||||
|
||||
javaServicePipeline(serviceName, useJava11, mvnArgs)
|
||||
}
|
1
build_utils
Submodule
1
build_utils
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 3e57e009cc329db6c3760434286c96ed98a5ba83
|
@ -7,7 +7,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@EnableScheduling
|
||||
@ServletComponentScan
|
||||
@SpringBootApplication(scanBasePackages = {"com.rbkmoney.midgard_adapter"})
|
||||
@SpringBootApplication(scanBasePackages = {"com.rbkmoney.midgard.adapter.mts"})
|
||||
public class MidgardAdapterMtsApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
@ -1,6 +0,0 @@
|
||||
package com.rbkmoney.midgard.adapter.mts.helpers;
|
||||
|
||||
/** Вспомогательный класс для работы с клиринговым файлом */
|
||||
public class ClearingFileHelper {
|
||||
|
||||
}
|
@ -1,13 +1,12 @@
|
||||
package com.rbkmoney.midgard.adapter.mts.sevices;
|
||||
|
||||
import com.rbkmoney.midgard.ClearingAdapterException;
|
||||
import com.rbkmoney.midgard.ClearingAdapterSrv;
|
||||
import com.rbkmoney.midgard.ClearingDataPackage;
|
||||
import com.rbkmoney.midgard.ClearingEventResponse;
|
||||
import com.rbkmoney.midgard.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.thrift.TException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ClearingAdapterService implements ClearingAdapterSrv.Iface {
|
||||
@ -15,17 +14,18 @@ public class ClearingAdapterService implements ClearingAdapterSrv.Iface {
|
||||
private static final int FIRST_PACKAGE = 1;
|
||||
|
||||
@Override
|
||||
public void startClearingEvent(long clearingId) throws ClearingAdapterException, TException {
|
||||
public String startClearingEvent(long clearingId) throws ClearingAdapterException, TException {
|
||||
//TODO: возможно придется выпилить так как запуск клиринга первым пакетом мне кажется более элегантным
|
||||
|
||||
return "1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendClearingDataPackage(ClearingDataPackage dataPackage) throws ClearingAdapterException, TException {
|
||||
public ClearingDataPackageTag sendClearingDataPackage(String upload_id, ClearingDataPackage dataPackage) throws ClearingAdapterException, TException {
|
||||
log.info("Data package have received: {}", dataPackage);
|
||||
if (dataPackage == null) {
|
||||
log.error("Received empty data package!");
|
||||
return;
|
||||
return new ClearingDataPackageTag();
|
||||
}
|
||||
if (dataPackage.getPackageNumber() == FIRST_PACKAGE) {
|
||||
createXmlFile(dataPackage);
|
||||
@ -42,8 +42,15 @@ public class ClearingAdapterService implements ClearingAdapterSrv.Iface {
|
||||
}
|
||||
log.info("Data package {} for clearing event {} processed", dataPackage.getPackageNumber(),
|
||||
dataPackage.getClearingId());
|
||||
return new ClearingDataPackageTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completeClearingEvent(String upload_id, long clearing_id, List<ClearingDataPackageTag> tags) throws ClearingAdapterException, TException {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void createXmlFile(ClearingDataPackage clearingDataPackage) {
|
||||
writeHeader(clearingDataPackage.getClearingId());
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ server:
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: @name@
|
||||
name: clearing_adapter_mts
|
||||
|
||||
retry-policy:
|
||||
maxAttempts: 10
|
@ -1,30 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFr1nKABCADBJY7N/TwoPNMqcZcGt5FdLc3lBjrOSOR4xzSGrmpIRWvvmi/Q
|
||||
cuuVE37cNbXPdktQbl/ToUoeruX9mq/DEzrKQVeohX/eusCJIHseZ54k8EiLoRny
|
||||
J3buE4SgayXWJCN/MikEXCR1GR4/GiuiAeN6FryF31000/A8z6ioyqRT1j5PF1Df
|
||||
wbjZTzxjDnR3NrZEDakRy5H6u97LL3iihGE8/HAb1at502a3MFX/aJ8BBP3U23Tf
|
||||
PvssGQWLl6uaCy9zIFojbfSVTlj/SqJH4Ev8nTy50JmA/AtGc//zZmIH4hjn0bb0
|
||||
q3EicLhbyScX/FL07Iz0U+SYoSRR+GC2tNlbABEBAAG0C3Rlc3RrZXlzaWduiQFO
|
||||
BBMBCAA4FiEELt04yuhovxuvpAui8n771Ido0vQFAlr1nKACGwMFCwkIBwIGFQoJ
|
||||
CAsCBBYCAwECHgECF4AACgkQ8n771Ido0vR3xAgAj7piDo5tkm/hO7ga6fm/5p2s
|
||||
64XU3rPj+vgs0bM1Xu/cs9ytXtncD9+H8l8bZAbjI1hI6zb60e9wf1ApUgeTRn1m
|
||||
FxzahVqhzR1MRqFc6ex698+vWa3G4411T3VDdDeC5uOdxGgp12652XH7mzz9Alz6
|
||||
u9gBn6mBwC2lKGxAbHjAwP4BuKasOLB8WUc7zO1D3uvAw7dMCtA6ScF8wgNeokDl
|
||||
F1APJ+gSko6biC2hS/l4QLR/GugpducuHJnpUOqUec2YNkRVpJKttU44HlGi/5Dm
|
||||
qrciJM2HiD5tnu/P0luvpar9+J83ZpYDbJvjYVQHfuwmuoYRWgoitHovbO3PEbkB
|
||||
DQRa9ZygAQgAwke/bZRbLhrXIIhxMjtiEgTTSsM4OpFc70/qJhB8Zq9kBl2td2fF
|
||||
85zILRpRW/sRr3iwHqWao4Zqi3SRwDjWGxfBgLhtNHnrEawnmdK/EOhnQ2+napc5
|
||||
u9t/mLi1HVknkxpO8Ua35Wrm8hRt9+v1IsUz2yyBvYS8hT6Ea/Bv7c0CMTWXeV1I
|
||||
4Ji7541Irru5XJ2V5v/Hs7N3WHH7agHVYNRLse+FIkBSBcijCDn1ZsUSYR9aHURa
|
||||
l0+NH9Bqw/KTdZQHTU6w7jXVA3R6io8bNaSu7eyIlPyCL8Lll+9I5eGNy4fzC8sl
|
||||
QJQJSZOa/e+6O8S5J32hvMzHdqMKJ/s2EwARAQABiQE2BBgBCAAgFiEELt04yuho
|
||||
vxuvpAui8n771Ido0vQFAlr1nKACGwwACgkQ8n771Ido0vTBkQf9ErGyb+LmI/Rf
|
||||
+YqBwdJLmAjQbFdQJaofuJWDH2iIK+nb5+VOFOa1Pm1MiqpjiwSiMSMNucaya+8m
|
||||
7MxQ+LV+8HSGZlMhzJHjQ78NRWt9x8V4yI8HSz/vWSE6T11zUKLCfOfYRznTzTSC
|
||||
Fpyjofs7ADgsuSBEHiR4GjZCeZ3sXUvS94Yri5vsdfTL9EkdycAewk+NiS3II1QE
|
||||
+QzqJpOraqYowXGLBozDKX6dj+wGeX04vMmHKAbcQsQPAq+JgD8VgKTzMPR6Ztnp
|
||||
n9+sglSZZBACzRfJmYmai7mM0s2dIi1FYpRPQQURrbN8u4AjPzSNpJ23q0hBUj5D
|
||||
ecwtZig8fQ==
|
||||
=l0ss
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
@ -13,10 +13,10 @@
|
||||
<artifactId>midgard-service</artifactId>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<name>Midgard Clearing</name>
|
||||
<name>Midgard Clearing Service</name>
|
||||
<description>Application for work with clearing data</description>
|
||||
<properties>
|
||||
<server.port>8023</server.port>
|
||||
<server.port>8022</server.port>
|
||||
<!-- Environment settings -->
|
||||
<flyway.version>5.2.4</flyway.version>
|
||||
<jooq.version>3.11.7</jooq.version>
|
||||
@ -97,7 +97,37 @@
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney.maven.plugins</groupId>
|
||||
<artifactId>pg-embedded-plugin</artifactId>
|
||||
<version>1.3</version>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney.geck</groupId>
|
||||
<artifactId>serializer</artifactId>
|
||||
<version>0.6.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.benas</groupId> <!-- Ha Ha! Benis! -->
|
||||
<artifactId>random-beans</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney.hg-mock</groupId>
|
||||
<artifactId>generator</artifactId>
|
||||
<version>0.9.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.opentable.components</groupId>
|
||||
<artifactId>otj-pg-embedded</artifactId>
|
||||
<version>0.12.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@ -110,7 +140,7 @@
|
||||
<plugin>
|
||||
<groupId>com.rbkmoney.maven.plugins</groupId>
|
||||
<artifactId>pg-embedded-plugin</artifactId>
|
||||
<version>1.3</version>
|
||||
<version>1.4</version>
|
||||
<configuration>
|
||||
<port>${local.pg.port}</port>
|
||||
<dbName>midgard</dbName>
|
||||
|
@ -5,5 +5,5 @@ import org.jooq.generated.midgard.tables.pojos.ClearingTransactionCashFlow;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ClearingCashFlowDao extends ClearingDao<List<ClearingTransactionCashFlow>> {
|
||||
public interface ClearingCashFlowDao extends ClearingDao<List<ClearingTransactionCashFlow>, Long> {
|
||||
}
|
||||
|
@ -35,13 +35,16 @@ public class ClearingCashFlowDaoImpl extends AbstractGenericDao implements Clear
|
||||
Query query = getDslContext().insertInto(CLEARING_TRANSACTION_CASH_FLOW).set(record);
|
||||
executeWithReturn(query, keyHolder);
|
||||
}
|
||||
return keyHolder.getKey().longValue();
|
||||
return cashFlowList.stream()
|
||||
.map(cashFlow -> cashFlow.getSourceEventId())
|
||||
.findFirst()
|
||||
.orElse(0L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClearingTransactionCashFlow> get(String sourceEventId) throws DaoException {
|
||||
public List<ClearingTransactionCashFlow> get(Long sourceEventId) throws DaoException {
|
||||
Query query = getDslContext().selectFrom(CLEARING_TRANSACTION_CASH_FLOW)
|
||||
.where(CLEARING_TRANSACTION_CASH_FLOW.SOURCE_EVENT_ID.eq(Long.parseLong(sourceEventId)));
|
||||
.where(CLEARING_TRANSACTION_CASH_FLOW.SOURCE_EVENT_ID.eq(sourceEventId));
|
||||
return fetch(query, cashFlowRowMapper);
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,14 @@ import org.jooq.generated.midgard.tables.pojos.ClearingEventInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ClearingEventInfoDao extends ClearingDao<ClearingEventInfo> {
|
||||
public interface ClearingEventInfoDao extends ClearingDao<ClearingEventInfo, Long> {
|
||||
|
||||
ClearingEventInfo getClearingEvent(long eventId);
|
||||
|
||||
void updateClearingStatus(Long clearingId, ClearingEventStatus status);
|
||||
|
||||
List<ClearingEventInfo> getClearingEventsByStatus(ClearingEventStatus status);
|
||||
List<ClearingEventInfo> getAllClearingEvents(ClearingEventStatus status);
|
||||
|
||||
Long prepareTransactionData(long clearingId, String providerId);
|
||||
Long prepareTransactionData(long clearingId, int providerId);
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class ClearingEventInfoDaoImpl extends AbstractGenericDao implements Clea
|
||||
public Long save(ClearingEventInfo clearingEvent) throws DaoException {
|
||||
log.debug("Adding new clearing event for provider: {}", clearingEvent.getProviderId());
|
||||
ClearingEventInfoRecord record = getDslContext().newRecord(CLEARING_EVENT_INFO, clearingEvent);
|
||||
Query query = getDslContext().insertInto(CLEARING_EVENT_INFO).set(record);
|
||||
Query query = getDslContext().insertInto(CLEARING_EVENT_INFO).set(record).returning(CLEARING_EVENT_INFO.ID);
|
||||
GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
|
||||
executeWithReturn(query, keyHolder);
|
||||
log.debug("Clearing event for provider {} have been added", clearingEvent.getProviderId());
|
||||
@ -46,10 +46,10 @@ public class ClearingEventInfoDaoImpl extends AbstractGenericDao implements Clea
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClearingEventInfo get(String id) throws DaoException {
|
||||
public ClearingEventInfo get(Long id) throws DaoException {
|
||||
log.debug("Getting a clearing event info with id {}", id);
|
||||
Query query = getDslContext().selectFrom(CLEARING_EVENT_INFO)
|
||||
.where(CLEARING_EVENT_INFO.ID.eq(Long.parseLong(id)));
|
||||
.where(CLEARING_EVENT_INFO.ID.eq(id));
|
||||
ClearingEventInfo clearingEvent = fetchOne(query, clearingEventsRowMapper);
|
||||
log.debug("Clearing event: {}", clearingEvent);
|
||||
return clearingEvent;
|
||||
@ -74,18 +74,18 @@ public class ClearingEventInfoDaoImpl extends AbstractGenericDao implements Clea
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClearingEventInfo> getClearingEventsByStatus(ClearingEventStatus status) throws DaoException {
|
||||
public List<ClearingEventInfo> getAllClearingEvents(ClearingEventStatus status) throws DaoException {
|
||||
Query query = getDslContext().selectFrom(CLEARING_EVENT_INFO)
|
||||
.where(CLEARING_EVENT_INFO.STATUS.eq(status));
|
||||
return fetch(query, clearingEventsRowMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long prepareTransactionData(long clearingId, String providerId) {
|
||||
public Long prepareTransactionData(long clearingId, int providerId) {
|
||||
PrepareTransactionData prepareTransactionData = new PrepareTransactionData();
|
||||
prepareTransactionData.setClearingId(clearingId);
|
||||
prepareTransactionData.setProviderId(providerId);
|
||||
prepareTransactionData.execute();
|
||||
prepareTransactionData.setSrcClearingId(clearingId);
|
||||
prepareTransactionData.setSrcProviderId(providerId);
|
||||
executeProc(prepareTransactionData);
|
||||
return clearingId;
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import com.rbkmoney.midgard.service.clearing.dao.common.ClearingDao;
|
||||
import com.rbkmoney.midgard.service.clearing.exception.DaoException;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingRefund;
|
||||
|
||||
public interface ClearingRefundDao extends ClearingDao<ClearingRefund> {
|
||||
public interface ClearingRefundDao extends ClearingDao<ClearingRefund, String> {
|
||||
|
||||
ClearingRefund getRefund(String transactionId) throws DaoException;
|
||||
|
||||
|
@ -3,6 +3,7 @@ package com.rbkmoney.midgard.service.clearing.dao.common;
|
||||
import com.rbkmoney.midgard.service.clearing.exception.DaoException;
|
||||
import org.jooq.*;
|
||||
import org.jooq.conf.ParamType;
|
||||
import org.jooq.impl.AbstractRoutine;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.DefaultConfiguration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
@ -29,6 +30,7 @@ public abstract class AbstractGenericDao extends NamedParameterJdbcDaoSupport im
|
||||
setDataSource(dataSource);
|
||||
Configuration configuration = new DefaultConfiguration();
|
||||
configuration.set(SQLDialect.POSTGRES_9_5);
|
||||
configuration.set(dataSource);
|
||||
this.dslContext = DSL.using(configuration);
|
||||
}
|
||||
|
||||
@ -36,6 +38,11 @@ public abstract class AbstractGenericDao extends NamedParameterJdbcDaoSupport im
|
||||
return dslContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeProc(AbstractRoutine<Void> procedure) {
|
||||
procedure.execute(dslContext.configuration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int execute(Query query) throws DaoException {
|
||||
return execute(query, -1);
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.rbkmoney.midgard.service.clearing.dao.common;
|
||||
|
||||
public interface ClearingDao<T> extends Dao {
|
||||
public interface ClearingDao<T, V> extends Dao {
|
||||
|
||||
Long save(T element);
|
||||
|
||||
T get(String id);
|
||||
T get(V id);
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.rbkmoney.midgard.service.clearing.dao.common;
|
||||
|
||||
import com.rbkmoney.midgard.service.clearing.exception.DaoException;
|
||||
import org.jooq.Query;
|
||||
import org.jooq.impl.AbstractRoutine;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
@ -11,6 +12,8 @@ import java.util.List;
|
||||
|
||||
public interface Dao {
|
||||
|
||||
void executeProc(AbstractRoutine<Void> procedure);
|
||||
|
||||
int execute(Query query);
|
||||
|
||||
int execute(Query query, int expectedRowsAffected) throws DaoException;
|
||||
|
@ -8,7 +8,7 @@ import org.jooq.generated.midgard.tables.pojos.FailureTransaction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TransactionsDao extends ClearingDao<ClearingTransaction> {
|
||||
public interface TransactionsDao extends ClearingDao<ClearingTransaction, String> {
|
||||
|
||||
ClearingTransaction getTransaction(String invoiceId, String paymentId) throws DaoException;
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.rbkmoney.midgard.service.clearing.decorators;
|
||||
|
||||
import com.rbkmoney.midgard.ClearingAdapterSrv;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class ClearingAdapter {
|
||||
|
||||
private ClearingAdapterSrv.Iface adapter;
|
||||
|
||||
private String adapterName;
|
||||
|
||||
private int adapterId;
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.rbkmoney.midgard.service.clearing.exception;
|
||||
|
||||
public class AdapterNotFoundException extends RuntimeException {
|
||||
|
||||
public AdapterNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AdapterNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public AdapterNotFoundException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public AdapterNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +1,25 @@
|
||||
package com.rbkmoney.midgard.service.clearing.handlers;
|
||||
|
||||
import com.rbkmoney.midgard.ClearingAdapterException;
|
||||
import com.rbkmoney.midgard.ClearingAdapterSrv;
|
||||
import com.rbkmoney.midgard.ClearingDataPackage;
|
||||
import com.rbkmoney.midgard.Transaction;
|
||||
import com.rbkmoney.midgard.*;
|
||||
import com.rbkmoney.midgard.service.clearing.decorators.ClearingAdapter;
|
||||
import com.rbkmoney.midgard.service.clearing.dao.clearing_cash_flow.ClearingCashFlowDao;
|
||||
import com.rbkmoney.midgard.service.clearing.dao.clearing_info.ClearingEventInfoDao;
|
||||
import com.rbkmoney.midgard.service.clearing.dao.clearing_refund.ClearingRefundDao;
|
||||
import com.rbkmoney.midgard.service.clearing.dao.transaction.TransactionsDao;
|
||||
import com.rbkmoney.midgard.service.clearing.exception.AdapterNotFoundException;
|
||||
import com.rbkmoney.midgard.service.clearing.utils.MappingUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.thrift.TException;
|
||||
import org.jooq.generated.midgard.enums.ClearingTrxType;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingEventTransactionInfo;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingRefund;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingTransaction;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingTransactionCashFlow;
|
||||
import org.jooq.generated.midgard.tables.pojos.*;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jooq.generated.midgard.enums.ClearingTrxType.*;
|
||||
import static org.jooq.generated.midgard.enums.ClearingTrxType.PAYMENT;
|
||||
import static org.jooq.generated.midgard.enums.ClearingTrxType.REFUND;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@ -35,8 +32,9 @@ public class ClearingEventHandler implements Handler {
|
||||
|
||||
private final ClearingCashFlowDao cashFlowDao;
|
||||
|
||||
// TODO: адаптеров может быть много. Реализовать выбор из нескольких согласно provider id
|
||||
private final ClearingAdapterSrv.Iface clearingAdapterService;
|
||||
private final ClearingEventInfoDao clearingEventInfoDao;
|
||||
|
||||
private final List<ClearingAdapter> adapters;
|
||||
|
||||
@Value("${clearing-service.package-size}")
|
||||
private int packageSize;
|
||||
@ -45,18 +43,33 @@ public class ClearingEventHandler implements Handler {
|
||||
|
||||
@Override
|
||||
public void handle(Long clearingId) {
|
||||
int packagesCount = getClearingTransactionPackagesCount(clearingId);
|
||||
for (int packageNumber = INIT_PACKAGE_NUMBER; packageNumber < packagesCount; packageNumber++) {
|
||||
ClearingDataPackage dataPackage = getClearingTransactionPackage(clearingId, packageNumber);
|
||||
try {
|
||||
//TODO: нужно предварительно получить конкретный адаптер из списка
|
||||
clearingAdapterService.sendClearingDataPackage(dataPackage);
|
||||
} catch (ClearingAdapterException ex) {
|
||||
//TODO: придумать обработку ошибки
|
||||
log.error("Error occurred while processing the package by the adapter", ex);
|
||||
} catch (TException ex) {
|
||||
log.error("Вata transfer error", ex);
|
||||
try {
|
||||
ClearingEventInfo clearingEventInfo = clearingEventInfoDao.get(clearingId);
|
||||
int providerId = clearingEventInfo == null ? 0 : clearingEventInfo.getProviderId();
|
||||
ClearingAdapter clearingAdapter = adapters.stream()
|
||||
.filter(clrAdapter -> clrAdapter.getAdapterId() == providerId)
|
||||
.findFirst()
|
||||
.orElseThrow(() ->
|
||||
new AdapterNotFoundException("Adapter with provider id " + providerId + " not found"));
|
||||
ClearingAdapterSrv.Iface adapter = clearingAdapter.getAdapter();
|
||||
|
||||
String uploadId = adapter.startClearingEvent(clearingId);
|
||||
int packagesCount = getClearingTransactionPackagesCount(clearingId);
|
||||
List<ClearingDataPackageTag> tagList = new ArrayList<>();
|
||||
|
||||
for (int packageNumber = INIT_PACKAGE_NUMBER; packageNumber < packagesCount; packageNumber++) {
|
||||
ClearingDataPackage dataPackage = getClearingTransactionPackage(clearingId, packageNumber);
|
||||
ClearingDataPackageTag tag = adapter.sendClearingDataPackage(uploadId, dataPackage);
|
||||
tagList.add(tag);
|
||||
}
|
||||
adapter.completeClearingEvent(uploadId, clearingId, tagList);
|
||||
|
||||
} catch (ClearingAdapterException ex) {
|
||||
log.error("Error occurred while processing the package by the adapter", ex);
|
||||
//TODO: реализовать корректную обработку ошибки
|
||||
} catch (TException e) {
|
||||
log.error("Error communicating with adapter", e);
|
||||
// TODO: реализовать корректную обработку ошибки
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +96,7 @@ public class ClearingEventHandler implements Handler {
|
||||
private Transaction getTransaction(ClearingEventTransactionInfo info) {
|
||||
ClearingTransaction clearingTransaction = transactionsDao.get(info.getTransactionId());
|
||||
List<ClearingTransactionCashFlow> cashFlowList =
|
||||
cashFlowDao.get(clearingTransaction.getEventId().toString());
|
||||
cashFlowDao.get(clearingTransaction.getEventId());
|
||||
return MappingUtils.transformClearingTransaction(clearingTransaction, cashFlowList);
|
||||
}
|
||||
|
||||
@ -92,7 +105,7 @@ public class ClearingEventHandler implements Handler {
|
||||
ClearingTransaction clearingTransaction =
|
||||
transactionsDao.getTransaction(refund.getInvoiceId(), refund.getPaymentId());
|
||||
List<ClearingTransactionCashFlow> cashFlowList =
|
||||
cashFlowDao.get(clearingTransaction.getEventId().toString());
|
||||
cashFlowDao.get(clearingTransaction.getEventId());
|
||||
return MappingUtils.transformRefundTransaction(clearingTransaction, cashFlowList, refund);
|
||||
}
|
||||
|
||||
@ -104,7 +117,7 @@ public class ClearingEventHandler implements Handler {
|
||||
|
||||
private int getClearingTransactionPackagesCount(long clearingId) {
|
||||
int packagesCount = transactionsDao.getProcessedClearingTransactionCount(clearingId);
|
||||
return (int) Math.floor((double) packagesCount / packageSize);
|
||||
return (int) Math.ceil((double) packagesCount / packageSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class ClearingEventService implements ClearingServiceSrv.Iface {
|
||||
@Override
|
||||
public void startClearingEvent(ClearingEvent clearingEvent) {
|
||||
long eventId = clearingEvent.getEventId();
|
||||
String providerId = clearingEvent.getProviderId();
|
||||
int providerId = clearingEvent.getProviderId();
|
||||
log.info("Starting clearing event for provider id {}", providerId);
|
||||
// Подготовка транзакций для клиринга
|
||||
Long clearingId = prepareClearingEvent(eventId, providerId);
|
||||
@ -54,14 +54,16 @@ public class ClearingEventService implements ClearingServiceSrv.Iface {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long prepareClearingEvent(long eventId, String providerId) {
|
||||
public Long prepareClearingEvent(long eventId, int providerId) {
|
||||
Long clearingId = createNewClearingEvent(eventId, providerId);
|
||||
clearingEventInfoDao.prepareTransactionData(clearingId, providerId);
|
||||
return clearingId;
|
||||
}
|
||||
|
||||
//TODO: рассмотреть вариант, когда для банка присутствует незавершенное клиринговое событие.
|
||||
private Long createNewClearingEvent(long eventId, String providerId) {
|
||||
// TODO: рассмотреть вариант, когда для банка присутствует незавершенное клиринговое событие.
|
||||
// Возможно имеет смысл анализировать статус незавершенного события и в зависимости от этого
|
||||
// завершать зависшее событие и начинать его заново, либо отбивать пришедшее с ошибкой
|
||||
private Long createNewClearingEvent(long eventId, int providerId) {
|
||||
log.trace("Creating new clearing event for provider {} by event ", providerId, eventId);
|
||||
ClearingEventInfo clearingEvent = new ClearingEventInfo();
|
||||
clearingEvent.setProviderId(providerId);
|
||||
|
@ -23,7 +23,7 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
public class ClearingRevisionService implements GenericService {
|
||||
|
||||
private final ClearingEventInfoDao clearingEventInfoDao;
|
||||
private final ClearingEventInfoDao eventInfoDao;
|
||||
|
||||
private final ClearingRevisionHandler revisionHandler;
|
||||
|
||||
@ -32,9 +32,9 @@ public class ClearingRevisionService implements GenericService {
|
||||
public void process() {
|
||||
|
||||
log.info("Clearing revision process get started");
|
||||
List<ClearingEventInfo> clearingEvents = clearingEventInfoDao.getClearingEventsByStatus(ClearingEventStatus.EXECUTE);
|
||||
List<ClearingEventInfo> clearingEvents = eventInfoDao.getAllClearingEvents(ClearingEventStatus.EXECUTE);
|
||||
List<Long> clearingIds = clearingEvents.stream()
|
||||
.map(event -> event.getId())
|
||||
.map(ClearingEventInfo::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
log.debug("Active clearing event IDs: {}", clearingIds);
|
||||
|
@ -11,6 +11,7 @@ import org.jooq.generated.midgard.tables.pojos.ClearingRefund;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingTransaction;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingTransactionCashFlow;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -23,12 +24,13 @@ public final class MappingUtils {
|
||||
trx.setInvoiceId(payment.getInvoiceId());
|
||||
trx.setPaymentId(payment.getPaymentId());
|
||||
trx.setProviderId(payment.getRouteProviderId());
|
||||
//TODO: что то придумать с tran_id
|
||||
|
||||
trx.setTransactionId(payment.getInvoiceId() + "_" + payment.getPaymentId());
|
||||
trx.setTransactionDate(payment.getCreatedAt());
|
||||
trx.setTransactionAmount(payment.getAmount());
|
||||
trx.setTransactionCurrency(payment.getCurrencyCode());
|
||||
trx.setTransactionClearingState(TransactionClearingState.READY);
|
||||
|
||||
trx.setPartyId(payment.getPartyId());
|
||||
trx.setShopId(payment.getShopId());
|
||||
|
||||
@ -37,9 +39,6 @@ public final class MappingUtils {
|
||||
trx.setPayerBankCardBin(payment.getPayerBankCardBin());
|
||||
trx.setPayerBankCardMaskedPan(payment.getPayerBankCardMaskedPan());
|
||||
trx.setPayerBankCardTokenProvider(payment.getPayerBankCardTokenProvider());
|
||||
trx.setFee(payment.getFee());
|
||||
trx.setExternalFee(payment.getExternalFee());
|
||||
trx.setProviderFee(payment.getProviderFee());
|
||||
trx.setExtra(payment.getSessionPayloadTransactionBoundTrxExtraJson());
|
||||
return trx;
|
||||
}
|
||||
@ -62,11 +61,11 @@ public final class MappingUtils {
|
||||
Transaction tran = new Transaction();
|
||||
GeneralTransactionInfo generalTranInfo = new GeneralTransactionInfo();
|
||||
generalTranInfo.setTransactionId(clrTran.getTransactionId());
|
||||
//TODO: перешнать в строку по отпределенному формату
|
||||
generalTranInfo.setTransactionDate(clrTran.getTransactionDate().toString());
|
||||
//TODO: проверить корректность получения даты на адаптере
|
||||
generalTranInfo.setTransactionDate(clrTran.getTransactionDate().toInstant(ZoneOffset.UTC).toString());
|
||||
generalTranInfo.setTransactionAmount(clrTran.getTransactionAmount());
|
||||
generalTranInfo.setTransactionCurrency(clrTran.getTransactionCurrency());
|
||||
generalTranInfo.setMcc(clrTran.getMcc());
|
||||
generalTranInfo.setMcc(clrTran.getMcc() == null ? 0 : clrTran.getMcc());
|
||||
tran.setGeneralTransactionInfo(generalTranInfo);
|
||||
|
||||
TransactionCardInfo tranCardInfo = new TransactionCardInfo();
|
||||
@ -80,6 +79,7 @@ public final class MappingUtils {
|
||||
Content additionalTranData = new Content();
|
||||
additionalTranData.setType("String");
|
||||
//TODO: Возможно так же стоит передавать строку, но не факт
|
||||
//TODO: проверить на конкретном extra
|
||||
additionalTranData.setData(clrTran.getExtra().getBytes());
|
||||
|
||||
tran.setAdditionalTransactionData(additionalTranData);
|
||||
@ -95,30 +95,34 @@ public final class MappingUtils {
|
||||
|
||||
private static TransactionCashFlow transformCashFlow(ClearingTransactionCashFlow cashFlow) {
|
||||
TransactionCashFlow tranCashFlow = new TransactionCashFlow();
|
||||
tranCashFlow.setObjType(CashFlowChangeType.valueOf(cashFlow.getObjType().name()));
|
||||
tranCashFlow.setAmount(cashFlow.getAmount());
|
||||
tranCashFlow.setCurrencyCode(cashFlow.getCurrencyCode());
|
||||
|
||||
tranCashFlow.setSourceAccountId(cashFlow.getSourceAccountId());
|
||||
tranCashFlow.setSourceAccountType(CashFlowAccountType.valueOf(cashFlow.getSourceAccountType().getName()));
|
||||
tranCashFlow.setSourceAccountType(CashFlowAccountType.valueOf(cashFlow.getSourceAccountType().name()));
|
||||
tranCashFlow.setSourceAccountTypeValue(cashFlow.getSourceAccountTypeValue());
|
||||
|
||||
tranCashFlow.setDestinationAccountId(cashFlow.getDestinationAccountId());
|
||||
tranCashFlow.setDestinationAccountType(
|
||||
CashFlowAccountType.valueOf(cashFlow.getDestinationAccountType().getName()));
|
||||
CashFlowAccountType.valueOf(cashFlow.getDestinationAccountType().name()));
|
||||
tranCashFlow.setDestinationAccountTypeValue(cashFlow.getDestinationAccountTypeValue());
|
||||
tranCashFlow.setObjType(CashFlowChangeType.valueOf(cashFlow.getObjType().getName()));
|
||||
return tranCashFlow;
|
||||
}
|
||||
|
||||
public static ClearingTransactionCashFlow transformCashFlow(CashFlow cashFlow) {
|
||||
ClearingTransactionCashFlow tranCashFlow = new ClearingTransactionCashFlow();
|
||||
tranCashFlow.setObjType(PaymentChangeType.valueOf(cashFlow.getObjType().name()));
|
||||
tranCashFlow.setAmount(cashFlow.getAmount());
|
||||
tranCashFlow.setCurrencyCode(cashFlow.getCurrencyCode());
|
||||
|
||||
tranCashFlow.setSourceAccountId(cashFlow.getSourceAccountId());
|
||||
tranCashFlow.setSourceAccountType(CashFlowAccount.valueOf(cashFlow.getSourceAccountType().getName()));
|
||||
tranCashFlow.setSourceAccountType(CashFlowAccount.valueOf(cashFlow.getSourceAccountType().name()));
|
||||
tranCashFlow.setSourceAccountTypeValue(cashFlow.getSourceAccountTypeValue());
|
||||
|
||||
tranCashFlow.setDestinationAccountId(cashFlow.getDestinationAccountId());
|
||||
tranCashFlow.setDestinationAccountType(CashFlowAccount.valueOf(cashFlow.getDestinationAccountType().getName()));
|
||||
tranCashFlow.setDestinationAccountType(CashFlowAccount.valueOf(cashFlow.getDestinationAccountType().name()));
|
||||
tranCashFlow.setDestinationAccountTypeValue(cashFlow.getDestinationAccountTypeValue());
|
||||
tranCashFlow.setObjType(PaymentChangeType.valueOf(cashFlow.getObjType().getName()));
|
||||
return tranCashFlow;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.rbkmoney.midgard.service.config;
|
||||
|
||||
import com.rbkmoney.midgard.ClearingAdapterSrv;
|
||||
import com.rbkmoney.midgard.service.clearing.decorators.ClearingAdapter;
|
||||
import com.rbkmoney.midgard.service.config.props.MtsAdapterProps;
|
||||
import com.rbkmoney.woody.thrift.impl.http.THSpawnClientBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -19,4 +20,11 @@ public class ClearingServiceConfig {
|
||||
.build(ClearingAdapterSrv.Iface.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClearingAdapter mtsClearingAdapter(MtsAdapterProps props) throws IOException {
|
||||
return new ClearingAdapter(mtsClearingAdapterThriftClient(props),
|
||||
props.getName(),
|
||||
props.getProviderId());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ CREATE TABLE midgard.clearing_transaction (
|
||||
event_id BIGINT NOT NULL,
|
||||
invoice_id CHARACTER VARYING NOT NULL,
|
||||
payment_id CHARACTER VARYING NOT NULL,
|
||||
provider_id INT NOT NULL,
|
||||
provider_id INTEGER NOT NULL,
|
||||
transaction_id CHARACTER VARYING NOT NULL,
|
||||
transaction_date TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||||
transaction_amount BIGINT NOT NULL,
|
||||
@ -15,8 +15,6 @@ CREATE TABLE midgard.clearing_transaction (
|
||||
transaction_clearing_state transaction_clearing_state NOT NULL,
|
||||
party_id CHARACTER VARYING NOT NULL,
|
||||
shop_id CHARACTER VARYING NOT NULL,
|
||||
terminal_id VARCHAR(8) NULL,
|
||||
optional_json CHARACTER VARYING NULL,
|
||||
mcc INTEGER NULL,
|
||||
payer_bank_card_token CHARACTER VARYING NULL,
|
||||
payer_bank_card_payment_system CHARACTER VARYING NULL,
|
||||
@ -24,9 +22,6 @@ CREATE TABLE midgard.clearing_transaction (
|
||||
payer_bank_card_masked_pan CHARACTER VARYING NULL,
|
||||
payer_bank_card_token_provider CHARACTER VARYING NULL,
|
||||
extra CHARACTER VARYING NULL,
|
||||
fee BIGINT NULL,
|
||||
provider_fee BIGINT NULL,
|
||||
external_fee BIGINT NULL,
|
||||
comment CHARACTER VARYING NULL,
|
||||
clearing_id BIGINT NULL,
|
||||
last_act_time TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT (now() at time zone 'utc'),
|
||||
@ -63,9 +58,9 @@ CREATE INDEX clearing_refund_state_idx ON midgard.clearing_refund (payment_id, i
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
CREATE TYPE midgard.cash_flow_account AS ENUM ('MERCHANT', 'PROVIDER', 'SYSTEM', 'EXTERNAL', 'WALLET');
|
||||
CREATE TYPE midgard.cash_flow_account AS ENUM ('merchant', 'provider', 'system', 'external', 'wallet');
|
||||
|
||||
CREATE TYPE midgard.payment_change_type AS ENUM ('PAYMENT', 'REFUND', 'ADJUSTMENT', 'PAYOUT');
|
||||
CREATE TYPE midgard.payment_change_type AS ENUM ('payment', 'refund', 'adjustment', 'payout');
|
||||
|
||||
CREATE TABLE midgard.clearing_transaction_cash_flow(
|
||||
id BIGSERIAL NOT NULL,
|
||||
@ -93,7 +88,7 @@ CREATE TABLE midgard.clearing_event_info (
|
||||
id BIGSERIAL NOT NULL,
|
||||
event_id BIGINT NOT NULL,
|
||||
date TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT (now() at time zone 'utc'),
|
||||
provider_id VARCHAR(100) NOT NULL,
|
||||
provider_id INTEGER NOT NULL,
|
||||
status clearing_event_status NOT NULL,
|
||||
CONSTRAINT clearing_event_info_PK PRIMARY KEY (id)
|
||||
);
|
||||
|
@ -1,35 +1,35 @@
|
||||
CREATE OR REPLACE FUNCTION midgard.prepare_transaction_data(clearing_id bigint, provider_id varchar(100))
|
||||
CREATE OR REPLACE FUNCTION midgard.prepare_transaction_data(src_clearing_id bigint, src_provider_id int)
|
||||
RETURNS VOID
|
||||
LANGUAGE PLPGSQL
|
||||
IMMUTABLE
|
||||
VOLATILE
|
||||
PARALLEL SAFE
|
||||
AS $$
|
||||
BEGIN
|
||||
/** Получение списка готовых к клиринговому событию транзакций */
|
||||
WITH clearing_trx_cte as (
|
||||
SELECT clearing_id,
|
||||
SELECT src_clearing_id as clearing_id,
|
||||
trx.transaction_id,
|
||||
'PAYMENT' as trx_type
|
||||
cast('PAYMENT' as midgard.clearing_trx_type) as trx_type
|
||||
FROM midgard.clearing_transaction trx
|
||||
WHERE trx.provider_id = provider_id
|
||||
WHERE trx.provider_id = src_provider_id
|
||||
AND trx.transaction_clearing_state in ('READY', 'FAILED')
|
||||
),
|
||||
|
||||
clearing_refund_trx_cte as (
|
||||
SELECT clearing_id,
|
||||
SELECT src_clearing_id as clearing_id,
|
||||
refund_trx.transaction_id,
|
||||
'REFUND' as trx_type
|
||||
cast('REFUND' as midgard.clearing_trx_type) as trx_type
|
||||
FROM midgard.clearing_refund refund_trx
|
||||
JOIN midgard.clearing_transaction trx
|
||||
ON trx.provider_id = provider_id
|
||||
ON trx.provider_id = src_provider_id
|
||||
AND refund_trx.invoice_id = trx.invoice_id
|
||||
AND refund_trx.payment_id = trx.payment_id
|
||||
WHERE refund_trx.transaction_clearing_state in ('READY', 'FAILED')
|
||||
WHERE refund_trx.clearing_state in ('READY', 'FAILED')
|
||||
),
|
||||
|
||||
ordered_clearing_trx_cte as (
|
||||
SELECT clearing_id, transaction_id, trx_type, trx_state,
|
||||
row_number() over(partition BY clearing_id ORDER BY trx_state, transaction_id) as row_num
|
||||
SELECT clearing_id, transaction_id, trx_type,
|
||||
row_number() over(partition BY clearing_id ORDER BY trx_type, transaction_id) as row_num
|
||||
FROM (
|
||||
SELECT * FROM clearing_trx_cte
|
||||
UNION ALL
|
||||
@ -37,23 +37,23 @@ BEGIN
|
||||
) cte
|
||||
)
|
||||
|
||||
INSERT INTO midgard.clearing_event_info(clearing_id, transaction_id, transaction_type, state, row_number)
|
||||
SELECT clearing_id, transaction_id, trx_type, trx_state, row_num
|
||||
INSERT INTO midgard.clearing_event_transaction_info(clearing_id, transaction_id, transaction_type, row_number)
|
||||
SELECT clearing_id, transaction_id, trx_type, row_num
|
||||
FROM ordered_clearing_trx_cte;
|
||||
|
||||
/** Перевести статус добавленных в клиринговый эвент транзакций в статус "ACTIVE" */
|
||||
UPDATE midgard.clearing_transaction
|
||||
SET transaction_clearing_state = 'ACTIVE'
|
||||
SET transaction_clearing_state = cast('ACTIVE' as midgard.transaction_clearing_state)
|
||||
WHERE transaction_id IN (SELECT transaction_id
|
||||
FROM midgard.clearing_event_info cei
|
||||
WHERE cei.clearing_id = clearing_id
|
||||
FROM midgard.clearing_event_transaction_info cei
|
||||
WHERE cei.clearing_id = src_clearing_id
|
||||
and transaction_type = 'PAYMENT');
|
||||
|
||||
UPDATE midgard.clearing_refund
|
||||
SET clearing_state = 'ACTIVE'
|
||||
SET clearing_state = cast('ACTIVE' as midgard.transaction_clearing_state)
|
||||
WHERE transaction_id IN (SELECT transaction_id
|
||||
FROM midgard.clearing_event_info cei
|
||||
WHERE cei.clearing_id = clearing_id
|
||||
FROM midgard.clearing_event_transaction_info cei
|
||||
WHERE cei.clearing_id = src_clearing_id
|
||||
and transaction_type = 'REFUND');
|
||||
|
||||
END;
|
||||
|
@ -1,12 +0,0 @@
|
||||
package com.rbkmoney.midgard.base.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class SimpleTest {
|
||||
|
||||
@Test
|
||||
public void simpleTest() {
|
||||
//TODO: write tests
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
package com.rbkmoney.midgard.base.tests.integration;
|
||||
|
||||
import com.opentable.db.postgres.embedded.EmbeddedPostgres;
|
||||
import com.rbkmoney.midgard.service.MidgardClearingApplication;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
import static org.springframework.boot.test.util.TestPropertyValues.Type.MAP;
|
||||
|
||||
/**
|
||||
* Created by jeckep on 08.02.17.
|
||||
*/
|
||||
@Slf4j
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||
@TestPropertySource(properties = {"bm.pollingEnabled=false"})
|
||||
@ContextConfiguration(classes = {MidgardClearingApplication.class},
|
||||
initializers = AbstractIntegrationTest.Initializer.class)
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||
public abstract class AbstractIntegrationTest {
|
||||
|
||||
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
@Parameter(defaultValue = "${project.build.directory}")
|
||||
private static String projectBuildDir;
|
||||
|
||||
private static final int port = 15432;
|
||||
|
||||
private static final String dbName = "midgard";
|
||||
|
||||
private static final String dbUser = "postgres";
|
||||
|
||||
private static final String dbPassword = "postgres";
|
||||
|
||||
private static final String jdbcUrl = "jdbc:postgresql://localhost:" + port + "/" + dbName;
|
||||
|
||||
private EmbeddedPostgres postgres;
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
|
||||
TestPropertyValues.of("spring.datasource.url=" + jdbcUrl,
|
||||
"spring.datasource.username=" + dbUser,
|
||||
"spring.datasource.password=" + dbPassword,
|
||||
"flyway.url=" + jdbcUrl,
|
||||
"flyway.user=" + dbUser,
|
||||
"flyway.password=" + dbPassword)
|
||||
.applyTo(configurableApplicationContext.getEnvironment(), MAP, "testcontainers");
|
||||
|
||||
if (postgres == null) {
|
||||
startPgServer();
|
||||
createDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
private void startPgServer() {
|
||||
try {
|
||||
log.info("The PG server is starting...");
|
||||
EmbeddedPostgres.Builder builder = EmbeddedPostgres.builder();
|
||||
String dbDir = prepareDbDir(projectBuildDir);
|
||||
log.info("Dir for PG files: " + dbDir);
|
||||
builder.setDataDirectory(dbDir);
|
||||
builder.setPort(port);
|
||||
postgres = builder.start();
|
||||
log.info("The PG server was started!");
|
||||
} catch (IOException e) {
|
||||
log.error("An error occurred while starting server ", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void createDatabase() {
|
||||
try (Connection conn = postgres.getPostgresDatabase().getConnection()) {
|
||||
Statement statement = conn.createStatement();
|
||||
statement.execute("CREATE DATABASE " + dbName);
|
||||
statement.close();
|
||||
} catch (SQLException e) {
|
||||
log.error("An error occurred while creating the database "+ dbName, e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void dropScheme(String schemaName) {
|
||||
log.debug("Delete {} scheme", schemaName);
|
||||
DataSource database = postgres.getDatabase(dbUser, dbName);
|
||||
try (Connection connection = database.getConnection()) {
|
||||
Statement statement = connection.createStatement();
|
||||
statement.execute("DROP SCHEMA " + schemaName + " CASCADE");
|
||||
statement.close();
|
||||
} catch (SQLException ex) {
|
||||
log.error("An error occurred while drop the schema " + schemaName);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private String prepareDbDir(String projectBuildDir) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
String currentDate = dateFormat.format(new Date());
|
||||
String dir = projectBuildDir + File.separator + "pgdata_" + currentDate;
|
||||
log.info("Postgres source files in {}", dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() throws IOException {
|
||||
if (postgres != null) {
|
||||
postgres.close();
|
||||
postgres = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.rbkmoney.midgard.base.tests.integration;
|
||||
|
||||
import com.rbkmoney.midgard.ClearingEvent;
|
||||
import com.rbkmoney.midgard.service.clearing.services.ClearingEventService;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class ClearingEventIntegrationTest extends AbstractIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private ClearingEventService clearingEventService;
|
||||
|
||||
private ClearingEvent clearingEvent;
|
||||
|
||||
@Test
|
||||
public void clearingEventIntegrationTest() throws InterruptedException {
|
||||
|
||||
ClearingEvent clearingEvent = new ClearingEvent();
|
||||
clearingEvent.setEventId(1);
|
||||
clearingEvent.setProviderId(100);
|
||||
//TODO: write integration tests
|
||||
|
||||
ReentrantLock lock = new ReentrantLock();
|
||||
try {
|
||||
lock.lock();
|
||||
|
||||
lock.tryLock(60L, TimeUnit.SECONDS);
|
||||
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.rbkmoney.midgard.base.tests.unit;
|
||||
|
||||
import com.rbkmoney.midgard.Transaction;
|
||||
import org.jooq.generated.feed.tables.pojos.Payment;
|
||||
import org.jooq.generated.feed.tables.pojos.Refund;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingRefund;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingTransaction;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingTransactionCashFlow;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.rbkmoney.midgard.base.tests.unit.data.TestTransactionsData.*;
|
||||
import static com.rbkmoney.midgard.service.clearing.utils.MappingUtils.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class MappingTest {
|
||||
|
||||
@Test
|
||||
public void transactionTest() {
|
||||
Payment payment = getTestPayment();
|
||||
ClearingTransaction transaction = transformTransaction(payment);
|
||||
ClearingTransaction testClearingTransaction = getTestClearingTransaction();
|
||||
assertEquals("Resulting clearing transaction is not equal to the reference",
|
||||
transaction, testClearingTransaction);
|
||||
|
||||
List<ClearingTransactionCashFlow> clearingTransactionCashFlowList = new ArrayList<>();
|
||||
clearingTransactionCashFlowList.add(getTestClearingTransactionCashFlow());
|
||||
Transaction protoTransaction = transformClearingTransaction(transaction, clearingTransactionCashFlowList);
|
||||
Transaction testProtoTransaction = getTestProtoTransaction();
|
||||
assertEquals("Resulting transaction is not equal to the reference",
|
||||
protoTransaction, testProtoTransaction);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refundTransactionTest() {
|
||||
Refund testRefund = getTestRefund();
|
||||
ClearingRefund clearingRefund = transformRefund(testRefund);
|
||||
ClearingRefund testClearingRefund = getTestClearingRefund();
|
||||
assertEquals("Resulting clearing refund transaction is not equal to the reference",
|
||||
clearingRefund, testClearingRefund);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
package com.rbkmoney.midgard.base.tests.unit.data;
|
||||
|
||||
import com.rbkmoney.midgard.*;
|
||||
import org.jooq.generated.feed.tables.pojos.CashFlow;
|
||||
import org.jooq.generated.feed.tables.pojos.Payment;
|
||||
import org.jooq.generated.feed.tables.pojos.Refund;
|
||||
import org.jooq.generated.midgard.enums.TransactionClearingState;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingRefund;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingTransaction;
|
||||
import org.jooq.generated.midgard.tables.pojos.ClearingTransactionCashFlow;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class TestTransactionsData {
|
||||
|
||||
private static final LocalDateTime dateTIme =
|
||||
LocalDateTime.of(2019, 01, 12, 12, 12, 44);
|
||||
|
||||
public static Payment getTestPayment() {
|
||||
Payment payment = new Payment();
|
||||
|
||||
payment.setEventId(1L);
|
||||
payment.setEventCreatedAt(dateTIme);
|
||||
payment.setInvoiceId("invoice_1");
|
||||
payment.setPaymentId("payment_1");
|
||||
payment.setRouteProviderId(1);
|
||||
payment.setCreatedAt(dateTIme);
|
||||
payment.setAmount(1000L);
|
||||
payment.setCurrencyCode("RUB");
|
||||
payment.setPartyId("pt_1");
|
||||
payment.setShopId("sh_1");
|
||||
|
||||
payment.setPayerBankCardToken("token_1");
|
||||
payment.setPayerBankCardPaymentSystem("visa");
|
||||
payment.setPayerBankCardBin("454545");
|
||||
payment.setPayerBankCardMaskedPan("4545 45** **** 9809");
|
||||
payment.setPayerBankCardTokenProvider("provider_1");
|
||||
payment.setSessionPayloadTransactionBoundTrxExtraJson("extra json");
|
||||
|
||||
return payment;
|
||||
}
|
||||
|
||||
public static ClearingTransaction getTestClearingTransaction() {
|
||||
ClearingTransaction trx = new ClearingTransaction();
|
||||
|
||||
trx.setEventId(1L);
|
||||
trx.setInvoiceId("invoice_1");
|
||||
trx.setPaymentId("payment_1");
|
||||
trx.setProviderId(1);
|
||||
trx.setTransactionId(trx.getInvoiceId() + "_" + trx.getPaymentId());
|
||||
trx.setTransactionDate(dateTIme);
|
||||
trx.setTransactionAmount(1000L);
|
||||
trx.setTransactionCurrency("RUB");
|
||||
trx.setTransactionClearingState(TransactionClearingState.READY);
|
||||
trx.setPartyId("pt_1");
|
||||
trx.setShopId("sh_1");
|
||||
|
||||
trx.setPayerBankCardToken("token_1");
|
||||
trx.setPayerBankCardPaymentSystem("visa");
|
||||
trx.setPayerBankCardBin("454545");
|
||||
trx.setPayerBankCardMaskedPan("4545 45** **** 9809");
|
||||
trx.setPayerBankCardTokenProvider("provider_1");
|
||||
trx.setExtra("extra json");
|
||||
|
||||
return trx;
|
||||
}
|
||||
|
||||
public static CashFlow getTestCashFlow() {
|
||||
CashFlow cashFlow = new CashFlow();
|
||||
|
||||
cashFlow.setAmount(1000L);
|
||||
cashFlow.setCurrencyCode("RUB");
|
||||
cashFlow.setSourceAccountId(1L);
|
||||
cashFlow.setSourceAccountType(org.jooq.generated.feed.enums.CashFlowAccount.merchant);
|
||||
cashFlow.setSourceAccountTypeValue("1000");
|
||||
cashFlow.setDestinationAccountId(2L);
|
||||
cashFlow.setDestinationAccountType(org.jooq.generated.feed.enums.CashFlowAccount.system);
|
||||
cashFlow.setDestinationAccountTypeValue("20");
|
||||
cashFlow.setObjType(org.jooq.generated.feed.enums.PaymentChangeType.payment);
|
||||
|
||||
return cashFlow;
|
||||
}
|
||||
|
||||
public static ClearingTransactionCashFlow getTestClearingTransactionCashFlow() {
|
||||
ClearingTransactionCashFlow tranCashFlow = new ClearingTransactionCashFlow();
|
||||
|
||||
tranCashFlow.setAmount(1000L);
|
||||
tranCashFlow.setCurrencyCode("RUB");
|
||||
tranCashFlow.setSourceAccountId(1L);
|
||||
tranCashFlow.setSourceAccountType(org.jooq.generated.midgard.enums.CashFlowAccount.merchant);
|
||||
tranCashFlow.setSourceAccountTypeValue("1000");
|
||||
tranCashFlow.setDestinationAccountId(2L);
|
||||
tranCashFlow.setDestinationAccountType(org.jooq.generated.midgard.enums.CashFlowAccount.system);
|
||||
tranCashFlow.setDestinationAccountTypeValue("20");
|
||||
tranCashFlow.setObjType(org.jooq.generated.midgard.enums.PaymentChangeType.payment);
|
||||
|
||||
return tranCashFlow;
|
||||
}
|
||||
|
||||
public static TransactionCashFlow getTestTransactionCashFlow() {
|
||||
TransactionCashFlow tranCashFlow = new TransactionCashFlow();
|
||||
|
||||
tranCashFlow.setAmount(1000L);
|
||||
tranCashFlow.setCurrencyCode("RUB");
|
||||
tranCashFlow.setSourceAccountId(1L);
|
||||
tranCashFlow.setSourceAccountType(CashFlowAccountType.merchant);
|
||||
tranCashFlow.setSourceAccountTypeValue("1000");
|
||||
tranCashFlow.setDestinationAccountId(2L);
|
||||
tranCashFlow.setDestinationAccountType(CashFlowAccountType.system);
|
||||
tranCashFlow.setDestinationAccountTypeValue("20");
|
||||
tranCashFlow.setObjType(CashFlowChangeType.payment);
|
||||
|
||||
return tranCashFlow;
|
||||
}
|
||||
|
||||
public static Transaction getTestProtoTransaction() {
|
||||
Transaction trx = new Transaction();
|
||||
|
||||
GeneralTransactionInfo generalTranInfo = new GeneralTransactionInfo();
|
||||
generalTranInfo.setTransactionId("invoice_1_payment_1");
|
||||
generalTranInfo.setTransactionDate(dateTIme.toInstant(ZoneOffset.UTC).toString());
|
||||
generalTranInfo.setTransactionAmount(1000L);
|
||||
generalTranInfo.setTransactionCurrency("RUB");
|
||||
generalTranInfo.setMcc(0);
|
||||
trx.setGeneralTransactionInfo(generalTranInfo);
|
||||
|
||||
TransactionCardInfo tranCardInfo = new TransactionCardInfo();
|
||||
tranCardInfo.setPayerBankCardToken("token_1");
|
||||
tranCardInfo.setPayerBankCardBin("454545");
|
||||
tranCardInfo.setPayerBankCardMaskedPan("4545 45** **** 9809");
|
||||
tranCardInfo.setPayerBankCardPaymentSystem("visa");
|
||||
tranCardInfo.setPayerBankCardTokenProvider("provider_1");
|
||||
trx.setTransactionCardInfo(tranCardInfo);
|
||||
|
||||
Content additionalTranData = new Content();
|
||||
additionalTranData.setType("String");
|
||||
//TODO: Возможно так же стоит передавать строку, но не факт
|
||||
additionalTranData.setData("extra json".getBytes());
|
||||
|
||||
trx.setAdditionalTransactionData(additionalTranData);
|
||||
List<TransactionCashFlow> transactionCashFlowList = new ArrayList<>();
|
||||
transactionCashFlowList.add(getTestTransactionCashFlow());
|
||||
trx.setTransactionCashFlow(transactionCashFlowList);
|
||||
|
||||
return trx;
|
||||
}
|
||||
|
||||
public static Refund getTestRefund() {
|
||||
Refund refund = new Refund();
|
||||
|
||||
refund.setEventId(3L);
|
||||
refund.setInvoiceId("invoice_3");
|
||||
refund.setPaymentId("payment_3");
|
||||
refund.setPartyId("pt_3");
|
||||
refund.setShopId("sh_3");
|
||||
refund.setCreatedAt(dateTIme);
|
||||
refund.setAmount(1000L);
|
||||
refund.setCurrencyCode("RUB");
|
||||
refund.setReason("some reason");
|
||||
refund.setDomainRevision(1L);
|
||||
|
||||
return refund;
|
||||
}
|
||||
|
||||
public static ClearingRefund getTestClearingRefund() {
|
||||
ClearingRefund clearingRefund = new ClearingRefund();
|
||||
|
||||
clearingRefund.setEventId(3L);
|
||||
clearingRefund.setInvoiceId("invoice_3");
|
||||
clearingRefund.setPaymentId("payment_3");
|
||||
clearingRefund.setPartyId("pt_3");
|
||||
clearingRefund.setShopId("sh_3");
|
||||
clearingRefund.setCreatedAt(dateTIme);
|
||||
clearingRefund.setAmount(1000L);
|
||||
clearingRefund.setCurrencyCode("RUB");
|
||||
clearingRefund.setReason("some reason");
|
||||
clearingRefund.setDomainRevision(1L);
|
||||
clearingRefund.setClearingState(TransactionClearingState.READY);
|
||||
|
||||
return clearingRefund;
|
||||
}
|
||||
|
||||
private TestTransactionsData() {}
|
||||
|
||||
}
|
4
pom.xml
4
pom.xml
@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<version>2.1.0.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
@ -100,7 +100,7 @@
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>midgard-proto</artifactId>
|
||||
<version>1.4-1651ed1</version>
|
||||
<version>1.7-a90a857</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
|
Loading…
Reference in New Issue
Block a user