mirror of
https://github.com/valitydev/disputes-api.git
synced 2024-11-06 00:55:23 +00:00
add disputes-tg-bot usage (#23)
* rename AdminManagementServlet * add disputes-tg-bot usage * add dummy for tg bot usages * add mapping * remove texeption catcher * bumps deps, remove debug endpoint * rename * rename * disable isScheduleReadyForCreateAdjustmentsEnabled * fix tests * up pg versino * refactor ProviderRouting * add handleUnexpectedResultMapping tests cases * checkstyle * maven-site issue * bump workflow * bump workflow * bump workflow * review fixes
This commit is contained in:
parent
0f39485afc
commit
df25417b6b
@ -48,7 +48,7 @@
|
|||||||
Если при финальном статусе платежа `captured` создавать на провайдере диспут является не желательной ситуацией, можно
|
Если при финальном статусе платежа `captured` создавать на провайдере диспут является не желательной ситуацией, можно
|
||||||
установить опцию в терминале `DISPUTE_FLOW_CAPTURED_BLOCKED` и пулять
|
установить опцию в терминале `DISPUTE_FLOW_CAPTURED_BLOCKED` и пулять
|
||||||
состояние
|
состояние
|
||||||
в топик\тг-провайдер-бот\filebeat на ручной разбор (`ManualParsing` module)
|
в топик\тг-провайдер-бот\filebeat на ручной разбор (`AdminManagement` module)
|
||||||
|
|
||||||
Не все провайдеры на данный момент поддерживают работу с диспутами по `API`.
|
Не все провайдеры на данный момент поддерживают работу с диспутами по `API`.
|
||||||
Предполагается такой способ действия при этой ситуации:
|
Предполагается такой способ действия при этой ситуации:
|
||||||
@ -111,7 +111,7 @@
|
|||||||
- если это captured платеж и выставлена опция `DISPUTE_FLOW_CAPTURED_BLOCKED` , то тоже отправляет на ручной разбор
|
- если это captured платеж и выставлена опция `DISPUTE_FLOW_CAPTURED_BLOCKED` , то тоже отправляет на ручной разбор
|
||||||
|
|
||||||
Далее, через внутрений трифт-интерфейс саппорт получает способ манипулировать диспутом для его
|
Далее, через внутрений трифт-интерфейс саппорт получает способ манипулировать диспутом для его
|
||||||
обработки (`ManualParsingDisputesService`)
|
обработки (`AdminManagementDisputesService`)
|
||||||
|
|
||||||
- Перед переводом диспута в финальный статус саппорт должен будет забиндить айди созданного диспута в провайдере через
|
- Перед переводом диспута в финальный статус саппорт должен будет забиндить айди созданного диспута в провайдере через
|
||||||
ручку `BindCreated()`. Здесь особенность, что этот метод фильтрует возможность биндить диспуты только созданные
|
ручку `BindCreated()`. Здесь особенность, что этот метод фильтрует возможность биндить диспуты только созданные
|
||||||
|
20
pom.xml
20
pom.xml
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>dev.vality</groupId>
|
<groupId>dev.vality</groupId>
|
||||||
<artifactId>service-parent-pom</artifactId>
|
<artifactId>service-parent-pom</artifactId>
|
||||||
<version>3.0.2</version>
|
<version>3.0.4</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>disputes-api</artifactId>
|
<artifactId>disputes-api</artifactId>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>dev.vality</groupId>
|
<groupId>dev.vality</groupId>
|
||||||
<artifactId>disputes-proto</artifactId>
|
<artifactId>disputes-proto</artifactId>
|
||||||
<version>1.23-37a5ad1</version>
|
<version>1.26-fc8e34f</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>dev.vality</groupId>
|
<groupId>dev.vality</groupId>
|
||||||
@ -62,6 +62,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>dev.vality</groupId>
|
<groupId>dev.vality</groupId>
|
||||||
<artifactId>damsel</artifactId>
|
<artifactId>damsel</artifactId>
|
||||||
|
<version>1.648-ad715bd</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>dev.vality</groupId>
|
<groupId>dev.vality</groupId>
|
||||||
@ -87,6 +88,16 @@
|
|||||||
<artifactId>adapter-flow-lib</artifactId>
|
<artifactId>adapter-flow-lib</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>dev.vality.woody</groupId>
|
||||||
|
<artifactId>woody-thrift</artifactId>
|
||||||
|
<version>2.0.8</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>dev.vality.woody</groupId>
|
||||||
|
<artifactId>woody-api</artifactId>
|
||||||
|
<version>2.0.8</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--spring-->
|
<!--spring-->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -217,6 +228,11 @@
|
|||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>32.0.0-jre</version>
|
<version>32.0.0-jre</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.opentelemetry</groupId>
|
||||||
|
<artifactId>opentelemetry-semconv</artifactId>
|
||||||
|
<version>1.29.0-alpha</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--test-->
|
<!--test-->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package dev.vality.disputes.admin.callback;
|
||||||
|
|
||||||
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface CallbackNotifier {
|
||||||
|
|
||||||
|
void sendDisputeAlreadyCreated(Dispute dispute);
|
||||||
|
|
||||||
|
void sendDisputePoolingExpired(Dispute dispute);
|
||||||
|
|
||||||
|
void sendDisputeReadyForCreateAdjustment(List<Dispute> disputes);
|
||||||
|
|
||||||
|
void sendDisputeFailedReviewRequired(Dispute dispute, String errorCode, String errorDescription);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package dev.vality.disputes.admin.callback;
|
||||||
|
|
||||||
|
import dev.vality.disputes.admin.DisputeAlreadyCreated;
|
||||||
|
import dev.vality.disputes.admin.DisputeFailedReviewRequired;
|
||||||
|
import dev.vality.disputes.admin.DisputePoolingExpired;
|
||||||
|
import dev.vality.disputes.admin.DisputeReadyForCreateAdjustment;
|
||||||
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
|
import dev.vality.disputes.service.external.DisputesTgBotService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@ConditionalOnProperty(value = "service.disputes-tg-bot.admin.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings({"LineLength"})
|
||||||
|
public class DisputesTgBotCallbackNotifierImpl implements CallbackNotifier {
|
||||||
|
|
||||||
|
private final DisputesTgBotService disputesTgBotService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDisputeAlreadyCreated(Dispute dispute) {
|
||||||
|
disputesTgBotService.sendDisputeAlreadyCreated(new DisputeAlreadyCreated(dispute.getId().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDisputePoolingExpired(Dispute dispute) {
|
||||||
|
disputesTgBotService.sendDisputePoolingExpired(new DisputePoolingExpired(dispute.getId().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDisputeReadyForCreateAdjustment(List<Dispute> disputes) {
|
||||||
|
var disputeReadyForCreateAdjustments = disputes.stream()
|
||||||
|
.map(Dispute::getId)
|
||||||
|
.map(UUID::toString)
|
||||||
|
.map(DisputeReadyForCreateAdjustment::new)
|
||||||
|
.toList();
|
||||||
|
disputesTgBotService.sendDisputeReadyForCreateAdjustment(disputeReadyForCreateAdjustments);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDisputeFailedReviewRequired(Dispute dispute, String errorCode, String errorDescription) {
|
||||||
|
disputesTgBotService.sendDisputeFailedReviewRequired(
|
||||||
|
new DisputeFailedReviewRequired(dispute.getId().toString(), errorCode)
|
||||||
|
.setErrorDescription(errorDescription));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package dev.vality.disputes.admin.callback;
|
||||||
|
|
||||||
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@ConditionalOnProperty(value = "service.disputes-tg-bot.admin.enabled", havingValue = "false")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings({"LineLength"})
|
||||||
|
public class DummyCallbackNotifierImpl implements CallbackNotifier {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDisputeAlreadyCreated(Dispute dispute) {
|
||||||
|
log.debug("Trying to call DummyCallbackNotifierImpl.sendDisputeAlreadyCreated() {}", dispute.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDisputePoolingExpired(Dispute dispute) {
|
||||||
|
log.debug("Trying to call DummyCallbackNotifierImpl.sendDisputePoolingExpired() {}", dispute.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDisputeReadyForCreateAdjustment(List<Dispute> disputes) {
|
||||||
|
log.debug("Trying to call DummyCallbackNotifierImpl.sendDisputeReadyForCreateAdjustment() {}", disputes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDisputeFailedReviewRequired(Dispute dispute, String errorCode, String errorDescription) {
|
||||||
|
log.debug("Trying to call DummyCallbackNotifierImpl.sendDisputeFailedReviewRequired() {}", dispute.getId());
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package dev.vality.disputes.manualparsing;
|
package dev.vality.disputes.admin.management;
|
||||||
|
|
||||||
import dev.vality.disputes.admin.*;
|
import dev.vality.disputes.admin.*;
|
||||||
import dev.vality.disputes.dao.DisputeDao;
|
import dev.vality.disputes.dao.DisputeDao;
|
||||||
@ -31,7 +31,7 @@ import static dev.vality.disputes.api.service.ApiDisputesService.DISPUTE_PENDING
|
|||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
||||||
public class ManualParsingDisputesService {
|
public class AdminManagementDisputesService {
|
||||||
|
|
||||||
private final DisputeDao disputeDao;
|
private final DisputeDao disputeDao;
|
||||||
private final ProviderDisputeDao providerDisputeDao;
|
private final ProviderDisputeDao providerDisputeDao;
|
||||||
@ -48,11 +48,12 @@ public class ManualParsingDisputesService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var cancelReason = cancelParams.getCancelReason().orElse(null);
|
var cancelReason = cancelParams.getCancelReason().orElse(null);
|
||||||
|
var mapping = cancelParams.getMapping().orElse(null);
|
||||||
log.debug("GetForUpdateSkipLocked has been found {}", dispute);
|
log.debug("GetForUpdateSkipLocked has been found {}", dispute);
|
||||||
if (DISPUTE_PENDING.contains(dispute.getStatus())) {
|
if (DISPUTE_PENDING.contains(dispute.getStatus())) {
|
||||||
// используется не failed, а cancelled чтоб можно было понять, что зафейлен по внешнему вызову
|
// используется не failed, а cancelled чтоб можно было понять, что зафейлен по внешнему вызову
|
||||||
log.warn("Trying to set cancelled Dispute status {}, {}", dispute, cancelReason);
|
log.warn("Trying to set cancelled Dispute status {}, {}, {}", dispute, mapping, cancelReason);
|
||||||
disputeDao.update(dispute.getId(), DisputeStatus.cancelled, cancelReason);
|
disputeDao.update(dispute.getId(), DisputeStatus.cancelled, cancelReason, mapping);
|
||||||
log.debug("Dispute status has been set to cancelled {}", dispute);
|
log.debug("Dispute status has been set to cancelled {}", dispute);
|
||||||
} else {
|
} else {
|
||||||
log.info("Request was skipped by inappropriate status {}", dispute);
|
log.info("Request was skipped by inappropriate status {}", dispute);
|
||||||
@ -133,6 +134,7 @@ public class ManualParsingDisputesService {
|
|||||||
disputeResult.setProviderTrxId(dispute.getProviderTrxId());
|
disputeResult.setProviderTrxId(dispute.getProviderTrxId());
|
||||||
disputeResult.setStatus(dispute.getStatus().name());
|
disputeResult.setStatus(dispute.getStatus().name());
|
||||||
disputeResult.setErrorMessage(dispute.getErrorMessage());
|
disputeResult.setErrorMessage(dispute.getErrorMessage());
|
||||||
|
disputeResult.setMapping(dispute.getMapping());
|
||||||
disputeResult.setAmount(String.valueOf(dispute.getAmount()));
|
disputeResult.setAmount(String.valueOf(dispute.getAmount()));
|
||||||
disputeResult.setChangedAmount(Optional.ofNullable(dispute.getChangedAmount())
|
disputeResult.setChangedAmount(Optional.ofNullable(dispute.getChangedAmount())
|
||||||
.map(String::valueOf)
|
.map(String::valueOf)
|
@ -1,4 +1,4 @@
|
|||||||
package dev.vality.disputes.manualparsing;
|
package dev.vality.disputes.admin.management;
|
||||||
|
|
||||||
import dev.vality.disputes.admin.*;
|
import dev.vality.disputes.admin.*;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -12,28 +12,28 @@ import java.util.ArrayList;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@SuppressWarnings({"ParameterName", "LineLength"})
|
@SuppressWarnings({"ParameterName", "LineLength"})
|
||||||
public class ManualParsingHandler implements ManualParsingServiceSrv.Iface {
|
public class AdminManagementHandler implements AdminManagementServiceSrv.Iface {
|
||||||
|
|
||||||
private final ManualParsingDisputesService manualParsingDisputesService;
|
private final AdminManagementDisputesService adminManagementDisputesService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancelPending(CancelParamsRequest cancelParamsRequest) throws TException {
|
public void cancelPending(CancelParamsRequest cancelParamsRequest) throws TException {
|
||||||
for (var cancelParam : cancelParamsRequest.getCancelParams()) {
|
for (var cancelParam : cancelParamsRequest.getCancelParams()) {
|
||||||
manualParsingDisputesService.cancelPendingDispute(cancelParam);
|
adminManagementDisputesService.cancelPendingDispute(cancelParam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void approvePending(ApproveParamsRequest approveParamsRequest) throws TException {
|
public void approvePending(ApproveParamsRequest approveParamsRequest) throws TException {
|
||||||
for (var approveParam : approveParamsRequest.getApproveParams()) {
|
for (var approveParam : approveParamsRequest.getApproveParams()) {
|
||||||
manualParsingDisputesService.approvePendingDispute(approveParam);
|
adminManagementDisputesService.approvePendingDispute(approveParam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindCreated(BindParamsRequest bindParamsRequest) throws TException {
|
public void bindCreated(BindParamsRequest bindParamsRequest) throws TException {
|
||||||
for (var bindParam : bindParamsRequest.getBindParams()) {
|
for (var bindParam : bindParamsRequest.getBindParams()) {
|
||||||
manualParsingDisputesService.bindCreatedDispute(bindParam);
|
adminManagementDisputesService.bindCreatedDispute(bindParam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ public class ManualParsingHandler implements ManualParsingServiceSrv.Iface {
|
|||||||
public DisputeResult getDisputes(DisputeParamsRequest disputeParamsRequest) throws TException {
|
public DisputeResult getDisputes(DisputeParamsRequest disputeParamsRequest) throws TException {
|
||||||
var disputeResult = new DisputeResult(new ArrayList<>());
|
var disputeResult = new DisputeResult(new ArrayList<>());
|
||||||
for (var disputeParams : disputeParamsRequest.getDisputeParams()) {
|
for (var disputeParams : disputeParamsRequest.getDisputeParams()) {
|
||||||
var dispute = manualParsingDisputesService.getDispute(disputeParams, disputeParamsRequest.isWithAttachments());
|
var dispute = adminManagementDisputesService.getDispute(disputeParams, disputeParamsRequest.isWithAttachments());
|
||||||
if (dispute != null) {
|
if (dispute != null) {
|
||||||
disputeResult.getDisputes().add(dispute);
|
disputeResult.getDisputes().add(dispute);
|
||||||
}
|
}
|
@ -1,8 +1,7 @@
|
|||||||
package dev.vality.disputes.manualparsing;
|
package dev.vality.disputes.admin.management;
|
||||||
|
|
||||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
import dev.vality.disputes.provider.Attachment;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.slf4j.MDC;
|
import org.slf4j.MDC;
|
||||||
@ -11,26 +10,28 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@SuppressWarnings({"ParameterName", "LineLength"})
|
@SuppressWarnings({"ParameterName", "LineLength"})
|
||||||
public class ManualParsingTopic {
|
public class MdcTopicProducer {
|
||||||
|
|
||||||
@Value("${manual-parsing-topic.enabled}")
|
@Value("${service.mdc-topic-producer.enabled}")
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
public void sendCreated(Dispute dispute, List<Attachment> attachments, DisputeStatus disputeStatus) {
|
public void sendCreated(Dispute dispute, DisputeStatus disputeStatus, String errorMessage) {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var contextMap = MDC.getCopyOfContextMap() == null ? new HashMap<String, String>() : MDC.getCopyOfContextMap();
|
var contextMap = getContextMap();
|
||||||
contextMap.put("dispute_id", dispute.getId().toString());
|
contextMap.put("dispute_id", dispute.getId().toString());
|
||||||
var attachmentsCollect = attachments.stream().map(Attachment::toString).collect(Collectors.joining(", "));
|
|
||||||
contextMap.put("dispute_attachments", attachmentsCollect);
|
|
||||||
contextMap.put("dispute_status", disputeStatus.name());
|
contextMap.put("dispute_status", disputeStatus.name());
|
||||||
|
if (errorMessage != null) {
|
||||||
|
contextMap.put("dispute_error_message", errorMessage);
|
||||||
|
}
|
||||||
MDC.setContextMap(contextMap);
|
MDC.setContextMap(contextMap);
|
||||||
log.warn("Manual parsing case");
|
log.warn("Manual parsing case");
|
||||||
MDC.clear();
|
MDC.clear();
|
||||||
@ -40,7 +41,7 @@ public class ManualParsingTopic {
|
|||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var contextMap = MDC.getCopyOfContextMap() == null ? new HashMap<String, String>() : MDC.getCopyOfContextMap();
|
var contextMap = getContextMap();
|
||||||
contextMap.put("dispute_id", dispute.getId().toString());
|
contextMap.put("dispute_id", dispute.getId().toString());
|
||||||
contextMap.put("dispute_status", DisputeStatus.manual_pending.name());
|
contextMap.put("dispute_status", DisputeStatus.manual_pending.name());
|
||||||
MDC.setContextMap(contextMap);
|
MDC.setContextMap(contextMap);
|
||||||
@ -52,11 +53,15 @@ public class ManualParsingTopic {
|
|||||||
if (!enabled || disputes.isEmpty()) {
|
if (!enabled || disputes.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var contextMap = MDC.getCopyOfContextMap() == null ? new HashMap<String, String>() : MDC.getCopyOfContextMap();
|
var contextMap = getContextMap();
|
||||||
contextMap.put("dispute_ids", disputes.stream().map(Dispute::getId).map(String::valueOf).collect(Collectors.joining(", ")));
|
contextMap.put("dispute_ids", disputes.stream().map(Dispute::getId).map(String::valueOf).collect(Collectors.joining(", ")));
|
||||||
contextMap.put("dispute_status", DisputeStatus.create_adjustment.name());
|
contextMap.put("dispute_status", DisputeStatus.create_adjustment.name());
|
||||||
MDC.setContextMap(contextMap);
|
MDC.setContextMap(contextMap);
|
||||||
log.warn("Ready for CreateAdjustments case");
|
log.warn("Ready for CreateAdjustments case");
|
||||||
MDC.clear();
|
MDC.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getContextMap() {
|
||||||
|
return MDC.getCopyOfContextMap() == null ? new HashMap<>() : MDC.getCopyOfContextMap();
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,30 +0,0 @@
|
|||||||
package dev.vality.disputes.api;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
|
||||||
import dev.vality.disputes.admin.CancelParamsRequest;
|
|
||||||
import dev.vality.disputes.admin.ManualParsingServiceSrv;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@RequestMapping({"/disputes"})
|
|
||||||
@Slf4j
|
|
||||||
public class CancelController {
|
|
||||||
|
|
||||||
private final ManualParsingServiceSrv.Iface manualParsingHandler;
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper().registerModule(new Jdk8Module());
|
|
||||||
|
|
||||||
@PostMapping("/cancel")
|
|
||||||
@SneakyThrows
|
|
||||||
public void cancelPending(@RequestBody String body) {
|
|
||||||
log.debug("cancelPending {}", body);
|
|
||||||
manualParsingHandler.cancelPending(objectMapper.readValue(body, CancelParamsRequest.class));
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,8 +12,8 @@ public class Status200ResponseConverter {
|
|||||||
public Status200Response convert(Dispute dispute) {
|
public Status200Response convert(Dispute dispute) {
|
||||||
var body = new Status200Response();
|
var body = new Status200Response();
|
||||||
body.setStatus(getStatus(dispute));
|
body.setStatus(getStatus(dispute));
|
||||||
if (!StringUtils.isBlank(dispute.getErrorMessage())) {
|
if (!StringUtils.isBlank(dispute.getMapping())) {
|
||||||
body.setReason(new GeneralError(dispute.getErrorMessage()));
|
body.setReason(new GeneralError(dispute.getMapping()));
|
||||||
}
|
}
|
||||||
if (dispute.getChangedAmount() != null) {
|
if (dispute.getChangedAmount() != null) {
|
||||||
body.setChangedAmount(dispute.getChangedAmount());
|
body.setChangedAmount(dispute.getChangedAmount());
|
||||||
|
@ -5,6 +5,8 @@ import dev.vality.bouncer.decisions.ArbiterSrv;
|
|||||||
import dev.vality.damsel.domain_config.RepositoryClientSrv;
|
import dev.vality.damsel.domain_config.RepositoryClientSrv;
|
||||||
import dev.vality.damsel.payment_processing.InvoicingSrv;
|
import dev.vality.damsel.payment_processing.InvoicingSrv;
|
||||||
import dev.vality.damsel.payment_processing.PartyManagementSrv;
|
import dev.vality.damsel.payment_processing.PartyManagementSrv;
|
||||||
|
import dev.vality.disputes.admin.AdminCallbackServiceSrv;
|
||||||
|
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
||||||
import dev.vality.file.storage.FileStorageSrv;
|
import dev.vality.file.storage.FileStorageSrv;
|
||||||
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
import dev.vality.token.keeper.TokenAuthenticatorSrv;
|
||||||
import dev.vality.woody.thrift.impl.http.THSpawnClientBuilder;
|
import dev.vality.woody.thrift.impl.http.THSpawnClientBuilder;
|
||||||
@ -81,6 +83,26 @@ public class ApplicationConfig {
|
|||||||
.build(PartyManagementSrv.Iface.class);
|
.build(PartyManagementSrv.Iface.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ProviderDisputesServiceSrv.Iface providerDisputesTgBotClient(
|
||||||
|
@Value("${service.disputes-tg-bot.provider.url}") Resource resource,
|
||||||
|
@Value("${service.disputes-tg-bot.provider.networkTimeout}") int networkTimeout) throws IOException {
|
||||||
|
return new THSpawnClientBuilder()
|
||||||
|
.withNetworkTimeout(networkTimeout)
|
||||||
|
.withAddress(resource.getURI())
|
||||||
|
.build(ProviderDisputesServiceSrv.Iface.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AdminCallbackServiceSrv.Iface adminCallbackDisputesTgBotClient(
|
||||||
|
@Value("${service.disputes-tg-bot.admin.url}") Resource resource,
|
||||||
|
@Value("${service.disputes-tg-bot.admin.networkTimeout}") int networkTimeout) throws IOException {
|
||||||
|
return new THSpawnClientBuilder()
|
||||||
|
.withNetworkTimeout(networkTimeout)
|
||||||
|
.withAddress(resource.getURI())
|
||||||
|
.build(AdminCallbackServiceSrv.Iface.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ExecutorService disputesThreadPool(@Value("${dispute.batchSize}") int threadPoolSize) {
|
public ExecutorService disputesThreadPool(@Value("${dispute.batchSize}") int threadPoolSize) {
|
||||||
final var threadFactory = new ThreadFactoryBuilder()
|
final var threadFactory = new ThreadFactoryBuilder()
|
||||||
|
@ -24,7 +24,7 @@ public class NetworkConfig {
|
|||||||
|
|
||||||
public static final String HEALTH = "/actuator/health";
|
public static final String HEALTH = "/actuator/health";
|
||||||
public static final String MERCHANT = "/disputes-api/v1/merchant";
|
public static final String MERCHANT = "/disputes-api/v1/merchant";
|
||||||
public static final String MANUAL = "/disputes-api/v1/manual-parsing";
|
public static final String ADMIN_MANAGEMENT = "/disputes-api/v1/admin-management";
|
||||||
public static final String CALLBACK = "/disputes-api/v1/callback";
|
public static final String CALLBACK = "/disputes-api/v1/callback";
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -39,7 +39,7 @@ public class NetworkConfig {
|
|||||||
var enabledPaths = servletPath.startsWith(restEndpoint)
|
var enabledPaths = servletPath.startsWith(restEndpoint)
|
||||||
|| servletPath.startsWith(HEALTH)
|
|| servletPath.startsWith(HEALTH)
|
||||||
|| servletPath.startsWith(MERCHANT)
|
|| servletPath.startsWith(MERCHANT)
|
||||||
|| servletPath.startsWith(MANUAL)
|
|| servletPath.startsWith(ADMIN_MANAGEMENT)
|
||||||
|| servletPath.startsWith(CALLBACK);
|
|| servletPath.startsWith(CALLBACK);
|
||||||
if ((request.getLocalPort() == restPort) && !enabledPaths) {
|
if ((request.getLocalPort() == restPort) && !enabledPaths) {
|
||||||
response.sendError(404, "Unknown address");
|
response.sendError(404, "Unknown address");
|
||||||
|
68
src/main/java/dev/vality/disputes/config/OtelConfig.java
Normal file
68
src/main/java/dev/vality/disputes/config/OtelConfig.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package dev.vality.disputes.config;
|
||||||
|
|
||||||
|
import dev.vality.disputes.config.properties.OtelProperties;
|
||||||
|
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||||
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
|
import io.opentelemetry.api.common.Attributes;
|
||||||
|
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
|
||||||
|
import io.opentelemetry.context.propagation.ContextPropagators;
|
||||||
|
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
|
||||||
|
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||||
|
import io.opentelemetry.sdk.resources.Resource;
|
||||||
|
import io.opentelemetry.sdk.trace.SdkTracerProvider;
|
||||||
|
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
|
||||||
|
import io.opentelemetry.sdk.trace.samplers.Sampler;
|
||||||
|
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class OtelConfig {
|
||||||
|
|
||||||
|
private final OtelProperties otelProperties;
|
||||||
|
|
||||||
|
@Value("${spring.application.name}")
|
||||||
|
private String applicationName;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public OpenTelemetry openTelemetryConfig() {
|
||||||
|
var resource = Resource.getDefault()
|
||||||
|
.merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName)));
|
||||||
|
var sdkTracerProvider = SdkTracerProvider.builder()
|
||||||
|
.addSpanProcessor(BatchSpanProcessor.builder(OtlpHttpSpanExporter.builder()
|
||||||
|
.setEndpoint(otelProperties.getResource())
|
||||||
|
.setTimeout(Duration.ofMillis(otelProperties.getTimeout()))
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.setSampler(Sampler.alwaysOn())
|
||||||
|
.setResource(resource)
|
||||||
|
.build();
|
||||||
|
var openTelemetrySdk = OpenTelemetrySdk.builder()
|
||||||
|
.setTracerProvider(sdkTracerProvider)
|
||||||
|
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
|
||||||
|
.build();
|
||||||
|
registerGlobalOpenTelemetry(openTelemetrySdk);
|
||||||
|
return openTelemetrySdk;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerGlobalOpenTelemetry(OpenTelemetry openTelemetry) {
|
||||||
|
try {
|
||||||
|
GlobalOpenTelemetry.set(openTelemetry);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("please initialize the ObservabilitySdk before starting the application");
|
||||||
|
GlobalOpenTelemetry.resetForTest();
|
||||||
|
try {
|
||||||
|
GlobalOpenTelemetry.set(openTelemetry);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.warn("unable to set GlobalOpenTelemetry", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package dev.vality.disputes.config.properties;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "otel")
|
||||||
|
public class OtelProperties {
|
||||||
|
|
||||||
|
private String resource;
|
||||||
|
private Long timeout;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package dev.vality.disputes.constant;
|
||||||
|
|
||||||
|
public class ModerationPrefix {
|
||||||
|
|
||||||
|
public static final String DISPUTES_UNKNOWN_MAPPING = "disputes_unknown_mapping";
|
||||||
|
|
||||||
|
}
|
@ -113,28 +113,32 @@ public class DisputeDao extends AbstractGenericDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public UUID update(UUID disputeId, DisputeStatus status) {
|
public UUID update(UUID disputeId, DisputeStatus status) {
|
||||||
return update(disputeId, status, null, null, null, null);
|
return update(disputeId, status, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID update(UUID disputeId, DisputeStatus status, LocalDateTime nextCheckAfter) {
|
public UUID update(UUID disputeId, DisputeStatus status, LocalDateTime nextCheckAfter) {
|
||||||
return update(disputeId, status, nextCheckAfter, null, null, null);
|
return update(disputeId, status, nextCheckAfter, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID update(UUID disputeId, DisputeStatus status, String errorMessage) {
|
public UUID update(UUID disputeId, DisputeStatus status, String errorMessage) {
|
||||||
return update(disputeId, status, null, errorMessage, null, null);
|
return update(disputeId, status, null, errorMessage, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID update(UUID disputeId, DisputeStatus status, String errorMessage, String mapping) {
|
||||||
|
return update(disputeId, status, null, errorMessage, null, null, mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID update(UUID disputeId, DisputeStatus status, Long changedAmount) {
|
public UUID update(UUID disputeId, DisputeStatus status, Long changedAmount) {
|
||||||
return update(disputeId, status, null, null, changedAmount, null);
|
return update(disputeId, status, null, null, changedAmount, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID update(UUID disputeId, DisputeStatus status, Long changedAmount,
|
public UUID update(UUID disputeId, DisputeStatus status, Long changedAmount,
|
||||||
Boolean skipCallHgForCreateAdjustment) {
|
Boolean skipCallHgForCreateAdjustment) {
|
||||||
return update(disputeId, status, null, null, changedAmount, skipCallHgForCreateAdjustment);
|
return update(disputeId, status, null, null, changedAmount, skipCallHgForCreateAdjustment, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UUID update(UUID disputeId, DisputeStatus status, LocalDateTime nextCheckAfter, String errorMessage,
|
private UUID update(UUID disputeId, DisputeStatus status, LocalDateTime nextCheckAfter, String errorMessage,
|
||||||
Long changedAmount, Boolean skipCallHgForCreateAdjustment) {
|
Long changedAmount, Boolean skipCallHgForCreateAdjustment, String mapping) {
|
||||||
var set = getDslContext().update(DISPUTE)
|
var set = getDslContext().update(DISPUTE)
|
||||||
.set(DISPUTE.STATUS, status);
|
.set(DISPUTE.STATUS, status);
|
||||||
if (nextCheckAfter != null) {
|
if (nextCheckAfter != null) {
|
||||||
@ -143,6 +147,9 @@ public class DisputeDao extends AbstractGenericDao {
|
|||||||
if (errorMessage != null) {
|
if (errorMessage != null) {
|
||||||
set = set.set(DISPUTE.ERROR_MESSAGE, errorMessage);
|
set = set.set(DISPUTE.ERROR_MESSAGE, errorMessage);
|
||||||
}
|
}
|
||||||
|
if (mapping != null) {
|
||||||
|
set = set.set(DISPUTE.MAPPING, mapping);
|
||||||
|
}
|
||||||
if (changedAmount != null) {
|
if (changedAmount != null) {
|
||||||
set = set.set(DISPUTE.CHANGED_AMOUNT, changedAmount);
|
set = set.set(DISPUTE.CHANGED_AMOUNT, changedAmount);
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,12 @@ public class MerchantDisputesHandler implements MerchantDisputesServiceSrv.Iface
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DisputeStatusResult checkDisputeStatus(DisputeContext disputeContext) throws DisputeNotFound, TException {
|
public DisputeStatusResult checkDisputeStatus(DisputeContext disputeContext) throws TException {
|
||||||
var response = disputesApiDelegate.status(getRequestID(), disputeContext.getDisputeId(), false).getBody();
|
var response = disputesApiDelegate.status(getRequestID(), disputeContext.getDisputeId(), false).getBody();
|
||||||
return switch (response.getStatus()) {
|
return switch (response.getStatus()) {
|
||||||
case PENDING -> DisputeStatusResult.statusPending(new DisputeStatusPendingResult());
|
case PENDING -> DisputeStatusResult.statusPending(new DisputeStatusPendingResult());
|
||||||
case FAILED -> DisputeStatusResult.statusFail(new DisputeStatusFailResult(getErrorMessage(response)));
|
case FAILED ->
|
||||||
|
DisputeStatusResult.statusFail(new DisputeStatusFailResult().setMapping(getMapping(response)));
|
||||||
case SUCCEEDED -> DisputeStatusResult.statusSuccess(new DisputeStatusSuccessResult());
|
case SUCCEEDED -> DisputeStatusResult.statusSuccess(new DisputeStatusSuccessResult());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -44,7 +45,7 @@ public class MerchantDisputesHandler implements MerchantDisputesServiceSrv.Iface
|
|||||||
return UUID.randomUUID().toString();
|
return UUID.randomUUID().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getErrorMessage(Status200Response response) {
|
private String getMapping(Status200Response response) {
|
||||||
return Optional.ofNullable(response.getReason())
|
return Optional.ofNullable(response.getReason())
|
||||||
.map(GeneralError::getMessage)
|
.map(GeneralError::getMessage)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dev.vality.disputes.schedule;
|
package dev.vality.disputes.schedule;
|
||||||
|
|
||||||
import dev.vality.disputes.manualparsing.ManualParsingTopic;
|
import dev.vality.disputes.admin.callback.CallbackNotifier;
|
||||||
|
import dev.vality.disputes.admin.management.MdcTopicProducer;
|
||||||
import dev.vality.disputes.schedule.service.CreateAdjustmentsService;
|
import dev.vality.disputes.schedule.service.CreateAdjustmentsService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -16,13 +17,15 @@ import org.springframework.stereotype.Service;
|
|||||||
public class TaskReadyForCreateAdjustmentsService {
|
public class TaskReadyForCreateAdjustmentsService {
|
||||||
|
|
||||||
private final CreateAdjustmentsService createAdjustmentsService;
|
private final CreateAdjustmentsService createAdjustmentsService;
|
||||||
private final ManualParsingTopic manualParsingTopic;
|
private final CallbackNotifier callbackNotifier;
|
||||||
|
private final MdcTopicProducer mdcTopicProducer;
|
||||||
|
|
||||||
@Scheduled(fixedDelayString = "${dispute.fixedDelayReadyForCreateAdjustments}", initialDelayString = "${dispute.initialDelayReadyForCreateAdjustments}")
|
@Scheduled(fixedDelayString = "${dispute.fixedDelayReadyForCreateAdjustments}", initialDelayString = "${dispute.initialDelayReadyForCreateAdjustments}")
|
||||||
public void processPending() {
|
public void processPending() {
|
||||||
log.debug("Processing ReadyForCreateAdjustments get started");
|
log.debug("Processing ReadyForCreateAdjustments get started");
|
||||||
var disputes = createAdjustmentsService.getReadyDisputesForCreateAdjustment();
|
var disputes = createAdjustmentsService.getReadyDisputesForCreateAdjustment();
|
||||||
manualParsingTopic.sendReadyForCreateAdjustments(disputes);
|
mdcTopicProducer.sendReadyForCreateAdjustments(disputes);
|
||||||
|
callbackNotifier.sendDisputeReadyForCreateAdjustment(disputes);
|
||||||
log.info("ReadyForCreateAdjustments were processed");
|
log.info("ReadyForCreateAdjustments were processed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package dev.vality.disputes.schedule.catcher;
|
||||||
|
|
||||||
|
import dev.vality.disputes.schedule.model.ProviderData;
|
||||||
|
import dev.vality.disputes.schedule.service.ExternalGatewayChecker;
|
||||||
|
import dev.vality.woody.api.flow.error.WRuntimeException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
||||||
|
public class WRuntimeExceptionCatcher {
|
||||||
|
|
||||||
|
private final ExternalGatewayChecker externalGatewayChecker;
|
||||||
|
|
||||||
|
public void catchProvidersDisputesApiNotExist(ProviderData providerData, Runnable runnable, Runnable defaultRemoteClientRunnable) {
|
||||||
|
try {
|
||||||
|
runnable.run();
|
||||||
|
} catch (WRuntimeException e) {
|
||||||
|
if (externalGatewayChecker.isProvidersDisputesApiNotExist(providerData, e)) {
|
||||||
|
// отправлять на ручной разбор, если API диспутов на провайдере не реализовано
|
||||||
|
// (тогда при тесте соединения вернется 404)
|
||||||
|
log.warn("Trying to call defaultRemoteClient.createDispute(), externalGatewayChecker", e);
|
||||||
|
defaultRemoteClientRunnable.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void catchUnexpectedResultMapping(Runnable runnable, Consumer<WRuntimeException> unexpectedResultMappingHandler) {
|
||||||
|
try {
|
||||||
|
runnable.run();
|
||||||
|
} catch (WRuntimeException e) {
|
||||||
|
if (externalGatewayChecker.isProvidersDisputesUnexpectedResultMapping(e)) {
|
||||||
|
unexpectedResultMappingHandler.accept(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package dev.vality.disputes.schedule.client;
|
||||||
|
|
||||||
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
|
import dev.vality.disputes.provider.Attachment;
|
||||||
|
import dev.vality.disputes.provider.DisputeCreatedResult;
|
||||||
|
import dev.vality.disputes.schedule.model.ProviderData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface DefaultRemoteClient {
|
||||||
|
|
||||||
|
Boolean routeUrlEquals(ProviderData providerData);
|
||||||
|
|
||||||
|
DisputeCreatedResult createDispute(Dispute dispute, List<Attachment> attachments, ProviderData providerData);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package dev.vality.disputes.schedule.client;
|
||||||
|
|
||||||
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
|
import dev.vality.disputes.provider.Attachment;
|
||||||
|
import dev.vality.disputes.provider.DisputeCreatedResult;
|
||||||
|
import dev.vality.disputes.schedule.converter.DisputeParamsConverter;
|
||||||
|
import dev.vality.disputes.schedule.model.ProviderData;
|
||||||
|
import dev.vality.disputes.service.external.DisputesTgBotService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@ConditionalOnProperty(value = "service.disputes-tg-bot.provider.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@SuppressWarnings({"ParameterName", "LineLength"})
|
||||||
|
public class DisputesTgBotRemoteClientImpl implements DefaultRemoteClient {
|
||||||
|
|
||||||
|
private final DisputesTgBotService disputesTgBotService;
|
||||||
|
private final DisputeParamsConverter disputeParamsConverter;
|
||||||
|
|
||||||
|
@Value("${service.disputes-tg-bot.provider.url}")
|
||||||
|
private String routeUrl;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean routeUrlEquals(ProviderData providerData) {
|
||||||
|
return StringUtils.equalsIgnoreCase(providerData.getRouteUrl(), routeUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DisputeCreatedResult createDispute(Dispute dispute, List<Attachment> attachments, ProviderData providerData) {
|
||||||
|
log.debug("Trying to build disputeParams {}", dispute.getId());
|
||||||
|
var disputeParams = disputeParamsConverter.convert(dispute, attachments, providerData.getOptions());
|
||||||
|
providerData.setRouteUrl(routeUrl);
|
||||||
|
log.debug("Trying to disputesTgBotService.createDispute() call {}", dispute.getId());
|
||||||
|
var result = disputesTgBotService.createDispute(disputeParams);
|
||||||
|
log.info("disputesTgBotService.createDispute() has been called {} {}", dispute.getId(), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package dev.vality.disputes.schedule.client;
|
||||||
|
|
||||||
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
|
import dev.vality.disputes.provider.Attachment;
|
||||||
|
import dev.vality.disputes.provider.DisputeCreatedResult;
|
||||||
|
import dev.vality.disputes.provider.DisputeCreatedSuccessResult;
|
||||||
|
import dev.vality.disputes.schedule.model.ProviderData;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@ConditionalOnProperty(value = "service.disputes-tg-bot.provider.enabled", havingValue = "false")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@SuppressWarnings({"ParameterName", "LineLength"})
|
||||||
|
public class DummyRemoteClientImpl implements DefaultRemoteClient {
|
||||||
|
|
||||||
|
private final String routeUrl = "tg-bot";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean routeUrlEquals(ProviderData providerData) {
|
||||||
|
return StringUtils.equalsIgnoreCase(providerData.getRouteUrl(), routeUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DisputeCreatedResult createDispute(Dispute dispute, List<Attachment> attachments, ProviderData providerData) {
|
||||||
|
log.debug("Trying to call DummyRemoteClientImpl.createDispute() {}", dispute.getId());
|
||||||
|
providerData.setRouteUrl(routeUrl);
|
||||||
|
return DisputeCreatedResult.successResult(new DisputeCreatedSuccessResult(UUID.randomUUID().toString()));
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ import dev.vality.disputes.schedule.converter.DisputeContextConverter;
|
|||||||
import dev.vality.disputes.schedule.converter.DisputeParamsConverter;
|
import dev.vality.disputes.schedule.converter.DisputeParamsConverter;
|
||||||
import dev.vality.disputes.schedule.model.ProviderData;
|
import dev.vality.disputes.schedule.model.ProviderData;
|
||||||
import dev.vality.disputes.schedule.service.ProviderIfaceBuilder;
|
import dev.vality.disputes.schedule.service.ProviderIfaceBuilder;
|
||||||
|
import dev.vality.disputes.schedule.service.ProviderRouting;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -22,17 +23,18 @@ import java.util.List;
|
|||||||
@SuppressWarnings({"ParameterName", "LineLength"})
|
@SuppressWarnings({"ParameterName", "LineLength"})
|
||||||
public class RemoteClient {
|
public class RemoteClient {
|
||||||
|
|
||||||
|
private final ProviderRouting providerRouting;
|
||||||
private final ProviderIfaceBuilder providerIfaceBuilder;
|
private final ProviderIfaceBuilder providerIfaceBuilder;
|
||||||
private final DisputeContextConverter disputeContextConverter;
|
|
||||||
private final DisputeParamsConverter disputeParamsConverter;
|
private final DisputeParamsConverter disputeParamsConverter;
|
||||||
|
private final DisputeContextConverter disputeContextConverter;
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public DisputeCreatedResult createDispute(Dispute dispute, List<Attachment> attachments, ProviderData providerData) {
|
public DisputeCreatedResult createDispute(Dispute dispute, List<Attachment> attachments, ProviderData providerData) {
|
||||||
log.debug("Trying to call dominant for RemoteClient {}", dispute.getId());
|
providerRouting.initRouteUrl(providerData);
|
||||||
|
log.debug("Trying to call ProviderIfaceBuilder {}", dispute.getId());
|
||||||
|
var remoteClient = providerIfaceBuilder.buildTHSpawnClient(providerData.getRouteUrl());
|
||||||
log.debug("Trying to build disputeParams {}", dispute.getId());
|
log.debug("Trying to build disputeParams {}", dispute.getId());
|
||||||
var disputeParams = disputeParamsConverter.convert(dispute, attachments, providerData.getOptions());
|
var disputeParams = disputeParamsConverter.convert(dispute, attachments, providerData.getOptions());
|
||||||
log.debug("Trying to call ProviderIfaceBuilder {}", dispute.getId());
|
|
||||||
var remoteClient = providerIfaceBuilder.buildTHSpawnClient(providerData);
|
|
||||||
log.debug("Trying to routed remote provider's createDispute() call {}", dispute.getId());
|
log.debug("Trying to routed remote provider's createDispute() call {}", dispute.getId());
|
||||||
var result = remoteClient.createDispute(disputeParams);
|
var result = remoteClient.createDispute(disputeParams);
|
||||||
log.info("Routed remote provider's createDispute() has been called {} {}", dispute.getId(), result);
|
log.info("Routed remote provider's createDispute() has been called {} {}", dispute.getId(), result);
|
||||||
@ -41,11 +43,11 @@ public class RemoteClient {
|
|||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public DisputeStatusResult checkDisputeStatus(Dispute dispute, ProviderDispute providerDispute, ProviderData providerData) {
|
public DisputeStatusResult checkDisputeStatus(Dispute dispute, ProviderDispute providerDispute, ProviderData providerData) {
|
||||||
log.debug("Trying to call dominant for RemoteClient {}", dispute.getId());
|
providerRouting.initRouteUrl(providerData);
|
||||||
|
log.debug("Trying to call ProviderIfaceBuilder {}", dispute.getId());
|
||||||
|
var remoteClient = providerIfaceBuilder.buildTHSpawnClient(providerData.getRouteUrl());
|
||||||
log.debug("Trying to build disputeContext {}", dispute.getId());
|
log.debug("Trying to build disputeContext {}", dispute.getId());
|
||||||
var disputeContext = disputeContextConverter.convert(dispute, providerDispute, providerData.getOptions());
|
var disputeContext = disputeContextConverter.convert(dispute, providerDispute, providerData.getOptions());
|
||||||
log.debug("Trying to call ProviderIfaceBuilder {}", dispute.getId());
|
|
||||||
var remoteClient = providerIfaceBuilder.buildTHSpawnClient(providerData);
|
|
||||||
log.debug("Trying to routed remote provider's checkDisputeStatus() call {}", dispute.getId());
|
log.debug("Trying to routed remote provider's checkDisputeStatus() call {}", dispute.getId());
|
||||||
var result = remoteClient.checkDisputeStatus(disputeContext);
|
var result = remoteClient.checkDisputeStatus(disputeContext);
|
||||||
log.info("Routed remote provider's checkDisputeStatus() has been called {} {}", dispute.getId(), result);
|
log.info("Routed remote provider's checkDisputeStatus() has been called {} {}", dispute.getId(), result);
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
package dev.vality.disputes.schedule.handler;
|
||||||
|
|
||||||
|
import dev.vality.disputes.admin.callback.CallbackNotifier;
|
||||||
|
import dev.vality.disputes.admin.management.MdcTopicProducer;
|
||||||
|
import dev.vality.disputes.dao.DisputeDao;
|
||||||
|
import dev.vality.disputes.dao.ProviderDisputeDao;
|
||||||
|
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||||
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
|
import dev.vality.disputes.domain.tables.pojos.ProviderDispute;
|
||||||
|
import dev.vality.disputes.polling.ExponentialBackOffPollingServiceWrapper;
|
||||||
|
import dev.vality.disputes.provider.DisputeCreatedResult;
|
||||||
|
import dev.vality.disputes.schedule.client.DefaultRemoteClient;
|
||||||
|
import dev.vality.disputes.schedule.model.ProviderData;
|
||||||
|
import dev.vality.disputes.utils.ErrorFormatter;
|
||||||
|
import dev.vality.woody.api.flow.error.WRuntimeException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import static dev.vality.disputes.constant.ModerationPrefix.DISPUTES_UNKNOWN_MAPPING;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
||||||
|
public class DisputeCreateResultHandler {
|
||||||
|
|
||||||
|
private final DisputeDao disputeDao;
|
||||||
|
private final ExponentialBackOffPollingServiceWrapper exponentialBackOffPollingService;
|
||||||
|
private final DefaultRemoteClient defaultRemoteClient;
|
||||||
|
private final ProviderDisputeDao providerDisputeDao;
|
||||||
|
private final CallbackNotifier callbackNotifier;
|
||||||
|
private final MdcTopicProducer mdcTopicProducer;
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public void handleSuccessResult(Dispute dispute, DisputeCreatedResult result, ProviderData providerData) {
|
||||||
|
var nextCheckAfter = exponentialBackOffPollingService.prepareNextPollingInterval(dispute, providerData.getOptions());
|
||||||
|
providerDisputeDao.save(new ProviderDispute(result.getSuccessResult().getProviderDisputeId(), dispute.getId()));
|
||||||
|
log.info("Trying to set pending Dispute status {}, {}", dispute, result);
|
||||||
|
var isDefaultRouteUrl = defaultRemoteClient.routeUrlEquals(providerData);
|
||||||
|
disputeDao.update(dispute.getId(), !isDefaultRouteUrl ? DisputeStatus.pending : DisputeStatus.manual_pending, nextCheckAfter);
|
||||||
|
log.debug("Dispute status has been set to pending {}", dispute.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public void handleFailResult(Dispute dispute, DisputeCreatedResult result) {
|
||||||
|
var failure = result.getFailResult().getFailure();
|
||||||
|
var errorMessage = ErrorFormatter.getErrorMessage(failure);
|
||||||
|
if (errorMessage.startsWith(DISPUTES_UNKNOWN_MAPPING)) {
|
||||||
|
handleUnexpectedResultMapping(dispute, failure.getCode(), failure.getReason());
|
||||||
|
} else {
|
||||||
|
log.warn("Trying to set failed Dispute status {}, {}", dispute.getId(), errorMessage);
|
||||||
|
disputeDao.update(dispute.getId(), DisputeStatus.failed, errorMessage, failure.getCode());
|
||||||
|
log.debug("Dispute status has been set to failed {}", dispute.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public void handleAlreadyExistResult(Dispute dispute) {
|
||||||
|
callbackNotifier.sendDisputeAlreadyCreated(dispute);
|
||||||
|
mdcTopicProducer.sendCreated(dispute, DisputeStatus.already_exist_created, "dispute already exist");
|
||||||
|
log.info("Trying to set {} Dispute status {}", DisputeStatus.already_exist_created, dispute);
|
||||||
|
disputeDao.update(dispute.getId(), DisputeStatus.already_exist_created);
|
||||||
|
log.debug("Dispute status has been set to {} {}", DisputeStatus.already_exist_created, dispute.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public void handleUnexpectedResultMapping(Dispute dispute, WRuntimeException e) {
|
||||||
|
var errorMessage = e.getErrorDefinition().getErrorReason();
|
||||||
|
handleUnexpectedResultMapping(dispute, errorMessage, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleUnexpectedResultMapping(Dispute dispute, String errorCode, String errorDescription) {
|
||||||
|
callbackNotifier.sendDisputeFailedReviewRequired(dispute, errorCode, errorDescription);
|
||||||
|
var errorMessage = ErrorFormatter.getErrorMessage(errorCode, errorDescription);
|
||||||
|
mdcTopicProducer.sendCreated(dispute, DisputeStatus.manual_created, errorMessage);
|
||||||
|
log.warn("Trying to set manual_created Dispute status {}, {}", dispute.getId(), errorMessage);
|
||||||
|
disputeDao.update(dispute.getId(), DisputeStatus.manual_created, errorMessage);
|
||||||
|
log.debug("Dispute status has been set to manual_created {}", dispute.getId());
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,26 @@
|
|||||||
package dev.vality.disputes.schedule.handler;
|
package dev.vality.disputes.schedule.handler;
|
||||||
|
|
||||||
|
import dev.vality.disputes.admin.callback.CallbackNotifier;
|
||||||
|
import dev.vality.disputes.admin.management.MdcTopicProducer;
|
||||||
|
import dev.vality.disputes.constant.ErrorReason;
|
||||||
import dev.vality.disputes.dao.DisputeDao;
|
import dev.vality.disputes.dao.DisputeDao;
|
||||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
import dev.vality.disputes.polling.ExponentialBackOffPollingServiceWrapper;
|
import dev.vality.disputes.polling.ExponentialBackOffPollingServiceWrapper;
|
||||||
import dev.vality.disputes.provider.DisputeStatusResult;
|
import dev.vality.disputes.provider.DisputeStatusResult;
|
||||||
import dev.vality.disputes.utils.ErrorFormatter;
|
import dev.vality.disputes.utils.ErrorFormatter;
|
||||||
|
import dev.vality.woody.api.flow.error.WRuntimeException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static dev.vality.disputes.constant.ModerationPrefix.DISPUTES_UNKNOWN_MAPPING;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ -22,6 +29,8 @@ public class DisputeStatusResultHandler {
|
|||||||
|
|
||||||
private final DisputeDao disputeDao;
|
private final DisputeDao disputeDao;
|
||||||
private final ExponentialBackOffPollingServiceWrapper exponentialBackOffPollingService;
|
private final ExponentialBackOffPollingServiceWrapper exponentialBackOffPollingService;
|
||||||
|
private final CallbackNotifier callbackNotifier;
|
||||||
|
private final MdcTopicProducer mdcTopicProducer;
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
public void handleStatusPending(Dispute dispute, DisputeStatusResult result, Map<String, String> options) {
|
public void handleStatusPending(Dispute dispute, DisputeStatusResult result, Map<String, String> options) {
|
||||||
@ -36,17 +45,48 @@ public class DisputeStatusResultHandler {
|
|||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
public void handleStatusFail(Dispute dispute, DisputeStatusResult result) {
|
public void handleStatusFail(Dispute dispute, DisputeStatusResult result) {
|
||||||
var errorMessage = ErrorFormatter.getErrorMessage(result.getStatusFail().getFailure());
|
var failure = result.getStatusFail().getFailure();
|
||||||
log.warn("Trying to set failed Dispute status {}, {}", dispute.getId(), errorMessage);
|
var errorMessage = ErrorFormatter.getErrorMessage(failure);
|
||||||
disputeDao.update(dispute.getId(), DisputeStatus.failed, errorMessage);
|
if (errorMessage.startsWith(DISPUTES_UNKNOWN_MAPPING)) {
|
||||||
log.debug("Dispute status has been set to failed {}", dispute.getId());
|
handleUnexpectedResultMapping(dispute, failure.getCode(), failure.getReason());
|
||||||
|
} else {
|
||||||
|
log.warn("Trying to set failed Dispute status {}, {}", dispute.getId(), errorMessage);
|
||||||
|
disputeDao.update(dispute.getId(), DisputeStatus.failed, errorMessage, failure.getCode());
|
||||||
|
log.debug("Dispute status has been set to failed {}", dispute.getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
public void handleStatusSuccess(Dispute dispute, DisputeStatusResult result) {
|
public void handleStatusSuccess(Dispute dispute, DisputeStatusResult result) {
|
||||||
|
callbackNotifier.sendDisputeReadyForCreateAdjustment(List.of(dispute));
|
||||||
|
mdcTopicProducer.sendReadyForCreateAdjustments(List.of(dispute));
|
||||||
var changedAmount = result.getStatusSuccess().getChangedAmount().orElse(null);
|
var changedAmount = result.getStatusSuccess().getChangedAmount().orElse(null);
|
||||||
log.info("Trying to set create_adjustment Dispute status {}, {}", dispute, result);
|
log.info("Trying to set create_adjustment Dispute status {}, {}", dispute, result);
|
||||||
disputeDao.update(dispute.getId(), DisputeStatus.create_adjustment, changedAmount);
|
disputeDao.update(dispute.getId(), DisputeStatus.create_adjustment, changedAmount);
|
||||||
log.debug("Dispute status has been set to create_adjustment {}", dispute.getId());
|
log.debug("Dispute status has been set to create_adjustment {}", dispute.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public void handlePoolingExpired(Dispute dispute) {
|
||||||
|
callbackNotifier.sendDisputePoolingExpired(dispute);
|
||||||
|
mdcTopicProducer.sendPoolingExpired(dispute);
|
||||||
|
log.warn("Trying to set manual_pending Dispute status with POOLING_EXPIRED error reason {}", dispute.getId());
|
||||||
|
disputeDao.update(dispute.getId(), DisputeStatus.manual_pending, ErrorReason.POOLING_EXPIRED);
|
||||||
|
log.debug("Dispute status has been set to manual_pending {}", dispute.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
public void handleUnexpectedResultMapping(Dispute dispute, WRuntimeException e) {
|
||||||
|
var errorMessage = e.getErrorDefinition().getErrorReason();
|
||||||
|
handleUnexpectedResultMapping(dispute, errorMessage, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleUnexpectedResultMapping(Dispute dispute, String errorCode, String errorDescription) {
|
||||||
|
callbackNotifier.sendDisputeFailedReviewRequired(dispute, errorCode, errorDescription);
|
||||||
|
var errorMessage = ErrorFormatter.getErrorMessage(errorCode, errorDescription);
|
||||||
|
mdcTopicProducer.sendCreated(dispute, DisputeStatus.manual_pending, errorMessage);
|
||||||
|
log.warn("Trying to set manual_pending Dispute status {}, {}", dispute.getId(), errorMessage);
|
||||||
|
disputeDao.update(dispute.getId(), DisputeStatus.manual_pending, errorMessage);
|
||||||
|
log.debug("Dispute status has been set to manual_pending {}", dispute.getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,5 +11,6 @@ public class ProviderData {
|
|||||||
|
|
||||||
private Map<String, String> options;
|
private Map<String, String> options;
|
||||||
private String defaultProviderUrl;
|
private String defaultProviderUrl;
|
||||||
|
private String routeUrl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,15 @@ package dev.vality.disputes.schedule.service;
|
|||||||
import dev.vality.damsel.payment_processing.InvoicePayment;
|
import dev.vality.damsel.payment_processing.InvoicePayment;
|
||||||
import dev.vality.disputes.constant.ErrorReason;
|
import dev.vality.disputes.constant.ErrorReason;
|
||||||
import dev.vality.disputes.dao.DisputeDao;
|
import dev.vality.disputes.dao.DisputeDao;
|
||||||
import dev.vality.disputes.dao.ProviderDisputeDao;
|
|
||||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
import dev.vality.disputes.domain.tables.pojos.ProviderDispute;
|
|
||||||
import dev.vality.disputes.manualparsing.ManualParsingTopic;
|
|
||||||
import dev.vality.disputes.polling.ExponentialBackOffPollingServiceWrapper;
|
|
||||||
import dev.vality.disputes.provider.Attachment;
|
|
||||||
import dev.vality.disputes.provider.DisputeCreatedResult;
|
import dev.vality.disputes.provider.DisputeCreatedResult;
|
||||||
|
import dev.vality.disputes.schedule.catcher.WRuntimeExceptionCatcher;
|
||||||
|
import dev.vality.disputes.schedule.client.DefaultRemoteClient;
|
||||||
import dev.vality.disputes.schedule.client.RemoteClient;
|
import dev.vality.disputes.schedule.client.RemoteClient;
|
||||||
|
import dev.vality.disputes.schedule.handler.DisputeCreateResultHandler;
|
||||||
|
import dev.vality.disputes.schedule.model.ProviderData;
|
||||||
import dev.vality.disputes.service.external.InvoicingService;
|
import dev.vality.disputes.service.external.InvoicingService;
|
||||||
import dev.vality.disputes.utils.ErrorFormatter;
|
|
||||||
import dev.vality.woody.api.flow.error.WRuntimeException;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -31,18 +28,17 @@ import static dev.vality.disputes.constant.TerminalOptionsField.DISPUTE_FLOW_PRO
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
@SuppressWarnings({"MemberName", "ParameterName", "LineLength", "MissingSwitchDefault"})
|
||||||
public class CreatedDisputesService {
|
public class CreatedDisputesService {
|
||||||
|
|
||||||
private final RemoteClient remoteClient;
|
private final RemoteClient remoteClient;
|
||||||
private final DisputeDao disputeDao;
|
private final DisputeDao disputeDao;
|
||||||
private final ProviderDisputeDao providerDisputeDao;
|
|
||||||
private final CreatedAttachmentsService createdAttachmentsService;
|
private final CreatedAttachmentsService createdAttachmentsService;
|
||||||
private final InvoicingService invoicingService;
|
private final InvoicingService invoicingService;
|
||||||
private final ExponentialBackOffPollingServiceWrapper exponentialBackOffPollingService;
|
|
||||||
private final ProviderDataService providerDataService;
|
private final ProviderDataService providerDataService;
|
||||||
private final ExternalGatewayChecker externalGatewayChecker;
|
private final DefaultRemoteClient defaultRemoteClient;
|
||||||
private final ManualParsingTopic manualParsingTopic;
|
private final DisputeCreateResultHandler disputeCreateResultHandler;
|
||||||
|
private final WRuntimeExceptionCatcher wRuntimeExceptionCatcher;
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
public List<Dispute> getCreatedDisputesForUpdateSkipLocked(int batchSize) {
|
public List<Dispute> getCreatedDisputesForUpdateSkipLocked(int batchSize) {
|
||||||
@ -87,54 +83,40 @@ public class CreatedDisputesService {
|
|||||||
|| isNotProvidersDisputesApiExist(options)) {
|
|| isNotProvidersDisputesApiExist(options)) {
|
||||||
// отправлять на ручной разбор, если выставлена опция
|
// отправлять на ручной разбор, если выставлена опция
|
||||||
// DISPUTE_FLOW_CAPTURED_BLOCKED или не выставлена DISPUTE_FLOW_PROVIDERS_API_EXIST
|
// DISPUTE_FLOW_CAPTURED_BLOCKED или не выставлена DISPUTE_FLOW_PROVIDERS_API_EXIST
|
||||||
log.warn("finishTaskWithManualParsingFlowActivation, options capt={}, apiExist={}", isCapturedBlockedForDispute(options), isNotProvidersDisputesApiExist(options));
|
log.warn("Trying to call defaultRemoteClient.createDispute(), options capt={}, apiExist={}", isCapturedBlockedForDispute(options), isNotProvidersDisputesApiExist(options));
|
||||||
finishTaskWithManualParsingFlowActivation(dispute, attachments, DisputeStatus.manual_created);
|
wRuntimeExceptionCatcher.catchUnexpectedResultMapping(
|
||||||
|
() -> {
|
||||||
|
var result = defaultRemoteClient.createDispute(dispute, attachments, providerData);
|
||||||
|
finishTask(dispute, result, providerData);
|
||||||
|
},
|
||||||
|
e -> disputeCreateResultHandler.handleUnexpectedResultMapping(dispute, e));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
wRuntimeExceptionCatcher.catchUnexpectedResultMapping(
|
||||||
var result = remoteClient.createDispute(dispute, attachments, providerData);
|
() -> wRuntimeExceptionCatcher.catchProvidersDisputesApiNotExist(
|
||||||
finishTask(dispute, attachments, result, options);
|
providerData,
|
||||||
} catch (WRuntimeException e) {
|
() -> {
|
||||||
if (externalGatewayChecker.isNotProvidersDisputesApiExist(providerData, e)) {
|
var result = remoteClient.createDispute(dispute, attachments, providerData);
|
||||||
// отправлять на ручной разбор, если API диспутов на провайдере не реализовано
|
finishTask(dispute, result, providerData);
|
||||||
// (тогда при тесте соединения вернется 404)
|
},
|
||||||
log.warn("finishTaskWithManualParsingFlowActivation with externalGatewayChecker", e);
|
() -> wRuntimeExceptionCatcher.catchUnexpectedResultMapping(
|
||||||
finishTaskWithManualParsingFlowActivation(dispute, attachments, DisputeStatus.manual_created);
|
() -> {
|
||||||
return;
|
var result = defaultRemoteClient.createDispute(dispute, attachments, providerData);
|
||||||
}
|
finishTask(dispute, result, providerData);
|
||||||
throw e;
|
},
|
||||||
}
|
e -> disputeCreateResultHandler.handleUnexpectedResultMapping(dispute, e))),
|
||||||
|
e -> disputeCreateResultHandler.handleUnexpectedResultMapping(dispute, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
void finishTask(Dispute dispute, List<Attachment> attachments, DisputeCreatedResult result, Map<String, String> options) {
|
void finishTask(Dispute dispute, DisputeCreatedResult result, ProviderData providerData) {
|
||||||
switch (result.getSetField()) {
|
switch (result.getSetField()) {
|
||||||
case SUCCESS_RESULT -> {
|
case SUCCESS_RESULT -> disputeCreateResultHandler.handleSuccessResult(dispute, result, providerData);
|
||||||
var nextCheckAfter = exponentialBackOffPollingService.prepareNextPollingInterval(dispute, options);
|
case FAIL_RESULT -> disputeCreateResultHandler.handleFailResult(dispute, result);
|
||||||
log.info("Trying to set pending Dispute status {}, {}", dispute, result);
|
case ALREADY_EXIST_RESULT -> disputeCreateResultHandler.handleAlreadyExistResult(dispute);
|
||||||
providerDisputeDao.save(new ProviderDispute(result.getSuccessResult().getProviderDisputeId(), dispute.getId()));
|
|
||||||
disputeDao.update(dispute.getId(), DisputeStatus.pending, nextCheckAfter);
|
|
||||||
log.debug("Dispute status has been set to pending {}", dispute.getId());
|
|
||||||
}
|
|
||||||
case FAIL_RESULT -> {
|
|
||||||
var errorMessage = ErrorFormatter.getErrorMessage(result.getFailResult().getFailure());
|
|
||||||
log.warn("Trying to set failed Dispute status {}, {}", dispute.getId(), errorMessage);
|
|
||||||
disputeDao.update(dispute.getId(), DisputeStatus.failed, errorMessage);
|
|
||||||
log.debug("Dispute status has been set to failed {}", dispute.getId());
|
|
||||||
}
|
|
||||||
case ALREADY_EXIST_RESULT ->
|
|
||||||
finishTaskWithManualParsingFlowActivation(dispute, attachments, DisputeStatus.already_exist_created);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
|
||||||
void finishTaskWithManualParsingFlowActivation(Dispute dispute, List<Attachment> attachments, DisputeStatus disputeStatus) {
|
|
||||||
manualParsingTopic.sendCreated(dispute, attachments, disputeStatus);
|
|
||||||
log.info("Trying to set {} Dispute status {}", disputeStatus, dispute);
|
|
||||||
disputeDao.update(dispute.getId(), disputeStatus);
|
|
||||||
log.debug("Dispute status has been set to {} {}", disputeStatus, dispute.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isCapturedBlockedForDispute(Map<String, String> options) {
|
private boolean isCapturedBlockedForDispute(Map<String, String> options) {
|
||||||
return options.containsKey(DISPUTE_FLOW_CAPTURED_BLOCKED);
|
return options.containsKey(DISPUTE_FLOW_CAPTURED_BLOCKED);
|
||||||
}
|
}
|
||||||
|
@ -22,23 +22,32 @@ public class ExternalGatewayChecker {
|
|||||||
private final CloseableHttpClient httpClient;
|
private final CloseableHttpClient httpClient;
|
||||||
private final ProviderRouting providerRouting;
|
private final ProviderRouting providerRouting;
|
||||||
|
|
||||||
public boolean isNotProvidersDisputesApiExist(ProviderData providerData, WRuntimeException e) {
|
public boolean isProvidersDisputesUnexpectedResultMapping(WRuntimeException e) {
|
||||||
return e.getErrorDefinition() != null
|
return e.getErrorDefinition() != null
|
||||||
&& e.getErrorDefinition().getGenerationSource() == WErrorSource.EXTERNAL
|
&& e.getErrorDefinition().getGenerationSource() == WErrorSource.EXTERNAL
|
||||||
&& e.getErrorDefinition().getErrorType() == WErrorType.UNEXPECTED_ERROR
|
&& e.getErrorDefinition().getErrorType() == WErrorType.UNEXPECTED_ERROR
|
||||||
&& e.getErrorDefinition().getErrorSource() == WErrorSource.INTERNAL
|
&& e.getErrorDefinition().getErrorSource() == WErrorSource.INTERNAL
|
||||||
&& isNotFoundProvidersDisputesApi(providerData);
|
&& e.getErrorDefinition().getErrorReason() != null
|
||||||
|
&& e.getErrorDefinition().getErrorReason().contains("Unexpected result, code = ");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isProvidersDisputesApiNotExist(ProviderData providerData, WRuntimeException e) {
|
||||||
|
return e.getErrorDefinition() != null
|
||||||
|
&& e.getErrorDefinition().getGenerationSource() == WErrorSource.EXTERNAL
|
||||||
|
&& e.getErrorDefinition().getErrorType() == WErrorType.UNEXPECTED_ERROR
|
||||||
|
&& e.getErrorDefinition().getErrorSource() == WErrorSource.INTERNAL
|
||||||
|
&& isProvidersDisputesApiNotFound(providerData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private Boolean isNotFoundProvidersDisputesApi(ProviderData providerData) {
|
private Boolean isProvidersDisputesApiNotFound(ProviderData providerData) {
|
||||||
return httpClient.execute(new HttpGet(getRouteUrl(providerData)), isNotFoundResponse());
|
return httpClient.execute(new HttpGet(getRouteUrl(providerData)), isNotFoundResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getRouteUrl(ProviderData providerData) {
|
private String getRouteUrl(ProviderData providerData) {
|
||||||
var routeUrl = providerRouting.getRouteUrl(providerData);
|
providerRouting.initRouteUrl(providerData);
|
||||||
log.debug("Check adapter connection, routeUrl={}", routeUrl);
|
log.debug("Check adapter connection, routeUrl={}", providerData.getRouteUrl());
|
||||||
return routeUrl;
|
return providerData.getRouteUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpClientResponseHandler<Boolean> isNotFoundResponse() {
|
private HttpClientResponseHandler<Boolean> isNotFoundResponse() {
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package dev.vality.disputes.schedule.service;
|
package dev.vality.disputes.schedule.service;
|
||||||
|
|
||||||
import dev.vality.disputes.constant.ErrorReason;
|
|
||||||
import dev.vality.disputes.dao.DisputeDao;
|
import dev.vality.disputes.dao.DisputeDao;
|
||||||
import dev.vality.disputes.dao.ProviderDisputeDao;
|
import dev.vality.disputes.dao.ProviderDisputeDao;
|
||||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||||
import dev.vality.disputes.manualparsing.ManualParsingTopic;
|
|
||||||
import dev.vality.disputes.polling.ExponentialBackOffPollingServiceWrapper;
|
import dev.vality.disputes.polling.ExponentialBackOffPollingServiceWrapper;
|
||||||
import dev.vality.disputes.polling.PollingInfoService;
|
import dev.vality.disputes.polling.PollingInfoService;
|
||||||
import dev.vality.disputes.provider.DisputeStatusResult;
|
import dev.vality.disputes.provider.DisputeStatusResult;
|
||||||
|
import dev.vality.disputes.schedule.catcher.WRuntimeExceptionCatcher;
|
||||||
import dev.vality.disputes.schedule.client.RemoteClient;
|
import dev.vality.disputes.schedule.client.RemoteClient;
|
||||||
import dev.vality.disputes.schedule.handler.DisputeStatusResultHandler;
|
import dev.vality.disputes.schedule.handler.DisputeStatusResultHandler;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -24,7 +23,7 @@ import java.util.Map;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
@SuppressWarnings({"MemberName", "ParameterName", "LineLength", "MissingSwitchDefault"})
|
||||||
public class PendingDisputesService {
|
public class PendingDisputesService {
|
||||||
|
|
||||||
private final RemoteClient remoteClient;
|
private final RemoteClient remoteClient;
|
||||||
@ -34,7 +33,7 @@ public class PendingDisputesService {
|
|||||||
private final ExponentialBackOffPollingServiceWrapper exponentialBackOffPollingService;
|
private final ExponentialBackOffPollingServiceWrapper exponentialBackOffPollingService;
|
||||||
private final ProviderDataService providerDataService;
|
private final ProviderDataService providerDataService;
|
||||||
private final DisputeStatusResultHandler disputeStatusResultHandler;
|
private final DisputeStatusResultHandler disputeStatusResultHandler;
|
||||||
private final ManualParsingTopic manualParsingTopic;
|
private final WRuntimeExceptionCatcher wRuntimeExceptionCatcher;
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
public List<Dispute> getPendingDisputesForUpdateSkipLocked(int batchSize) {
|
public List<Dispute> getPendingDisputesForUpdateSkipLocked(int batchSize) {
|
||||||
@ -65,15 +64,16 @@ public class PendingDisputesService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pollingInfoService.isDeadline(dispute)) {
|
if (pollingInfoService.isDeadline(dispute)) {
|
||||||
manualParsingTopic.sendPoolingExpired(dispute);
|
disputeStatusResultHandler.handlePoolingExpired(dispute);
|
||||||
log.error("Trying to set manual_pending Dispute status with POOLING_EXPIRED error reason {}", dispute.getId());
|
|
||||||
disputeDao.update(dispute.getId(), DisputeStatus.manual_pending, ErrorReason.POOLING_EXPIRED);
|
|
||||||
log.debug("Dispute status has been set to manual_pending {}", dispute.getId());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.debug("ProviderDispute has been found {}", dispute.getId());
|
log.debug("ProviderDispute has been found {}", dispute.getId());
|
||||||
var result = remoteClient.checkDisputeStatus(dispute, providerDispute, providerData);
|
wRuntimeExceptionCatcher.catchUnexpectedResultMapping(
|
||||||
finishTask(dispute, result, providerData.getOptions());
|
() -> {
|
||||||
|
var result = remoteClient.checkDisputeStatus(dispute, providerDispute, providerData);
|
||||||
|
finishTask(dispute, result, providerData.getOptions());
|
||||||
|
},
|
||||||
|
e -> disputeStatusResultHandler.handleUnexpectedResultMapping(dispute, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
|
@ -38,7 +38,7 @@ public class ProviderDataService {
|
|||||||
var terminal = dominantAsyncService.getTerminal(payment.getRoute().getTerminal());
|
var terminal = dominantAsyncService.getTerminal(payment.getRoute().getTerminal());
|
||||||
var proxy = dominantAsyncService.getProxy(provider.get().getProxy().getRef());
|
var proxy = dominantAsyncService.getProxy(provider.get().getProxy().getRef());
|
||||||
return ProviderData.builder()
|
return ProviderData.builder()
|
||||||
.options(OptionsExtractors.mergeOptions(provider.get(), proxy.get(), terminal.get()))
|
.options(OptionsExtractors.mergeOptions(provider.get(), proxy.get(), terminal.get()))
|
||||||
.defaultProviderUrl(proxy.get().getUrl())
|
.defaultProviderUrl(proxy.get().getUrl())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package dev.vality.disputes.schedule.service;
|
|||||||
|
|
||||||
import dev.vality.disputes.config.properties.AdaptersConnectionProperties;
|
import dev.vality.disputes.config.properties.AdaptersConnectionProperties;
|
||||||
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
||||||
import dev.vality.disputes.schedule.model.ProviderData;
|
|
||||||
import dev.vality.woody.thrift.impl.http.THSpawnClientBuilder;
|
import dev.vality.woody.thrift.impl.http.THSpawnClientBuilder;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -18,12 +17,10 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@SuppressWarnings({"AbbreviationAsWordInName", "LineLength"})
|
@SuppressWarnings({"AbbreviationAsWordInName", "LineLength"})
|
||||||
public class ProviderIfaceBuilder {
|
public class ProviderIfaceBuilder {
|
||||||
|
|
||||||
private final ProviderRouting providerRouting;
|
|
||||||
private final AdaptersConnectionProperties adaptersConnectionProperties;
|
private final AdaptersConnectionProperties adaptersConnectionProperties;
|
||||||
|
|
||||||
@Cacheable(value = "adapters", key = "#providerData.defaultProviderUrl", cacheManager = "adaptersCacheManager")
|
@Cacheable(value = "adapters", key = "#root.args[0]", cacheManager = "adaptersCacheManager")
|
||||||
public ProviderDisputesServiceSrv.Iface buildTHSpawnClient(ProviderData providerData) {
|
public ProviderDisputesServiceSrv.Iface buildTHSpawnClient(String routeUrl) {
|
||||||
var routeUrl = providerRouting.getRouteUrl(providerData);
|
|
||||||
log.info("Creating new client for url: {}", routeUrl);
|
log.info("Creating new client for url: {}", routeUrl);
|
||||||
return new THSpawnClientBuilder()
|
return new THSpawnClientBuilder()
|
||||||
.withNetworkTimeout((int) TimeUnit.SECONDS.toMillis(adaptersConnectionProperties.getTimeoutSec()))
|
.withNetworkTimeout((int) TimeUnit.SECONDS.toMillis(adaptersConnectionProperties.getTimeoutSec()))
|
||||||
|
@ -18,12 +18,12 @@ public class ProviderRouting {
|
|||||||
private static final String DISPUTES_URL_POSTFIX_DEFAULT = "disputes";
|
private static final String DISPUTES_URL_POSTFIX_DEFAULT = "disputes";
|
||||||
private static final String OPTION_DISPUTES_URL_FIELD_NAME = "disputes_url";
|
private static final String OPTION_DISPUTES_URL_FIELD_NAME = "disputes_url";
|
||||||
|
|
||||||
public String getRouteUrl(ProviderData providerData) {
|
public void initRouteUrl(ProviderData providerData) {
|
||||||
var url = providerData.getOptions().get(OPTION_DISPUTES_URL_FIELD_NAME);
|
var url = providerData.getOptions().get(OPTION_DISPUTES_URL_FIELD_NAME);
|
||||||
if (ObjectUtils.isEmpty(url)) {
|
if (ObjectUtils.isEmpty(url)) {
|
||||||
url = createDefaultRouteUrl(providerData.getDefaultProviderUrl());
|
url = createDefaultRouteUrl(providerData.getDefaultProviderUrl());
|
||||||
}
|
}
|
||||||
return url;
|
providerData.setRouteUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createDefaultRouteUrl(String defaultProviderUrl) {
|
private String createDefaultRouteUrl(String defaultProviderUrl) {
|
||||||
|
24
src/main/java/dev/vality/disputes/service/external/DisputesTgBotService.java
vendored
Normal file
24
src/main/java/dev/vality/disputes/service/external/DisputesTgBotService.java
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package dev.vality.disputes.service.external;
|
||||||
|
|
||||||
|
import dev.vality.disputes.admin.DisputeAlreadyCreated;
|
||||||
|
import dev.vality.disputes.admin.DisputeFailedReviewRequired;
|
||||||
|
import dev.vality.disputes.admin.DisputePoolingExpired;
|
||||||
|
import dev.vality.disputes.admin.DisputeReadyForCreateAdjustment;
|
||||||
|
import dev.vality.disputes.provider.DisputeCreatedResult;
|
||||||
|
import dev.vality.disputes.provider.DisputeParams;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface DisputesTgBotService {
|
||||||
|
|
||||||
|
DisputeCreatedResult createDispute(DisputeParams disputeParams);
|
||||||
|
|
||||||
|
void sendDisputeAlreadyCreated(DisputeAlreadyCreated disputeAlreadyCreated);
|
||||||
|
|
||||||
|
void sendDisputePoolingExpired(DisputePoolingExpired disputePoolingExpired);
|
||||||
|
|
||||||
|
void sendDisputeReadyForCreateAdjustment(List<DisputeReadyForCreateAdjustment> disputeReadyForCreateAdjustments);
|
||||||
|
|
||||||
|
void sendDisputeFailedReviewRequired(DisputeFailedReviewRequired disputeFailedReviewRequired);
|
||||||
|
|
||||||
|
}
|
75
src/main/java/dev/vality/disputes/service/external/impl/DisputesTgBotServiceImpl.java
vendored
Normal file
75
src/main/java/dev/vality/disputes/service/external/impl/DisputesTgBotServiceImpl.java
vendored
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package dev.vality.disputes.service.external.impl;
|
||||||
|
|
||||||
|
import dev.vality.disputes.admin.*;
|
||||||
|
import dev.vality.disputes.provider.DisputeCreatedResult;
|
||||||
|
import dev.vality.disputes.provider.DisputeParams;
|
||||||
|
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
||||||
|
import dev.vality.disputes.service.external.DisputesTgBotService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings({"LineLength"})
|
||||||
|
public class DisputesTgBotServiceImpl implements DisputesTgBotService {
|
||||||
|
|
||||||
|
public final ProviderDisputesServiceSrv.Iface providerDisputesTgBotClient;
|
||||||
|
public final AdminCallbackServiceSrv.Iface adminCallbackDisputesTgBotClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public DisputeCreatedResult createDispute(DisputeParams disputeParams) {
|
||||||
|
log.debug("Trying to call providerDisputesTgBotClient.createDispute() {} {}", disputeParams.getDisputeId(), disputeParams.getTransactionContext().getInvoiceId());
|
||||||
|
var invoice = providerDisputesTgBotClient.createDispute(disputeParams);
|
||||||
|
log.debug("providerDisputesTgBotClient.createDispute() has been called {} {}", disputeParams.getDisputeId(), disputeParams.getTransactionContext().getInvoiceId());
|
||||||
|
return invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public void sendDisputeAlreadyCreated(DisputeAlreadyCreated disputeAlreadyCreated) {
|
||||||
|
log.debug("Trying to call adminCallbackDisputesTgBotClient.sendDisputeAlreadyCreated() {}", disputeAlreadyCreated.getId());
|
||||||
|
adminCallbackDisputesTgBotClient.notify(
|
||||||
|
new NotificationParamsRequest(List.of(Notification.disputeAlreadyCreated(disputeAlreadyCreated))));
|
||||||
|
log.debug("adminCallbackDisputesTgBotClient.sendDisputeAlreadyCreated() has been called {}", disputeAlreadyCreated.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public void sendDisputePoolingExpired(DisputePoolingExpired disputePoolingExpired) {
|
||||||
|
log.debug("Trying to call adminCallbackDisputesTgBotClient.sendDisputePoolingExpired() {}", disputePoolingExpired.getId());
|
||||||
|
adminCallbackDisputesTgBotClient.notify(
|
||||||
|
new NotificationParamsRequest(List.of(Notification.disputePoolingExpired(disputePoolingExpired))));
|
||||||
|
log.debug("adminCallbackDisputesTgBotClient.sendDisputePoolingExpired() has been called {}", disputePoolingExpired.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public void sendDisputeReadyForCreateAdjustment(List<DisputeReadyForCreateAdjustment> disputeReadyForCreateAdjustments) {
|
||||||
|
var ids = disputeReadyForCreateAdjustments.stream()
|
||||||
|
.map(DisputeReadyForCreateAdjustment::getId)
|
||||||
|
.map(String::valueOf)
|
||||||
|
.collect(Collectors.joining(", "));
|
||||||
|
log.debug("Trying to call adminCallbackDisputesTgBotClient.sendDisputeReadyForCreateAdjustment() {}", ids);
|
||||||
|
var notifications = disputeReadyForCreateAdjustments.stream()
|
||||||
|
.map(Notification::disputeReadyForCreateAdjustment)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
adminCallbackDisputesTgBotClient.notify(new NotificationParamsRequest(notifications));
|
||||||
|
log.debug("adminCallbackDisputesTgBotClient.sendDisputeReadyForCreateAdjustment() has been called {}", ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public void sendDisputeFailedReviewRequired(DisputeFailedReviewRequired disputeFailedReviewRequired) {
|
||||||
|
log.debug("Trying to call adminCallbackDisputesTgBotClient.sendDisputeFailedReviewRequired() {}", disputeFailedReviewRequired.getId());
|
||||||
|
adminCallbackDisputesTgBotClient.notify(
|
||||||
|
new NotificationParamsRequest(List.of(Notification.disputeFailedReviewRequired(disputeFailedReviewRequired))));
|
||||||
|
log.debug("adminCallbackDisputesTgBotClient.sendDisputeFailedReviewRequired() has been called {}", disputeFailedReviewRequired.getId());
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package dev.vality.disputes.servlet;
|
package dev.vality.disputes.servlet;
|
||||||
|
|
||||||
import dev.vality.disputes.admin.ManualParsingServiceSrv;
|
import dev.vality.disputes.admin.AdminManagementServiceSrv;
|
||||||
import dev.vality.woody.thrift.impl.http.THServiceBuilder;
|
import dev.vality.woody.thrift.impl.http.THServiceBuilder;
|
||||||
import jakarta.servlet.*;
|
import jakarta.servlet.*;
|
||||||
import jakarta.servlet.annotation.WebServlet;
|
import jakarta.servlet.annotation.WebServlet;
|
||||||
@ -8,11 +8,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@WebServlet("/disputes-api/v1/manual-parsing")
|
@WebServlet("/disputes-api/v1/admin-management")
|
||||||
public class ManualParsingServlet extends GenericServlet {
|
public class AdminManagementServlet extends GenericServlet {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ManualParsingServiceSrv.Iface manualParsingHandler;
|
private AdminManagementServiceSrv.Iface adminManagementHandler;
|
||||||
|
|
||||||
private Servlet servlet;
|
private Servlet servlet;
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ public class ManualParsingServlet extends GenericServlet {
|
|||||||
public void init(ServletConfig config) throws ServletException {
|
public void init(ServletConfig config) throws ServletException {
|
||||||
super.init(config);
|
super.init(config);
|
||||||
servlet = new THServiceBuilder()
|
servlet = new THServiceBuilder()
|
||||||
.build(ManualParsingServiceSrv.Iface.class, manualParsingHandler);
|
.build(AdminManagementServiceSrv.Iface.class, adminManagementHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -12,4 +12,11 @@ public class ErrorFormatter {
|
|||||||
}
|
}
|
||||||
return TErrorUtil.toStringVal(failure);
|
return TErrorUtil.toStringVal(failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getErrorMessage(String errorCode, String errorDescription) {
|
||||||
|
if (!StringUtils.isBlank(errorDescription)) {
|
||||||
|
return errorCode + ": " + errorDescription;
|
||||||
|
}
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,17 @@ service:
|
|||||||
shops:
|
shops:
|
||||||
poolSize: 10
|
poolSize: 10
|
||||||
ttlSec: 86400
|
ttlSec: 86400
|
||||||
|
disputes-tg-bot:
|
||||||
|
provider:
|
||||||
|
url: http://localhost:8022/change_it
|
||||||
|
networkTimeout: 5000
|
||||||
|
enabled: false
|
||||||
|
admin:
|
||||||
|
url: http://localhost:8022/change_it
|
||||||
|
networkTimeout: 5000
|
||||||
|
enabled: false
|
||||||
|
mdc-topic-producer:
|
||||||
|
enabled: true
|
||||||
adapters:
|
adapters:
|
||||||
connection:
|
connection:
|
||||||
timeoutSec: 30
|
timeoutSec: 30
|
||||||
@ -106,18 +117,15 @@ dispute:
|
|||||||
isScheduleCreatedEnabled: true
|
isScheduleCreatedEnabled: true
|
||||||
isSchedulePendingEnabled: true
|
isSchedulePendingEnabled: true
|
||||||
isScheduleCreateAdjustmentsEnabled: true
|
isScheduleCreateAdjustmentsEnabled: true
|
||||||
isScheduleReadyForCreateAdjustmentsEnabled: true
|
isScheduleReadyForCreateAdjustmentsEnabled: false
|
||||||
|
|
||||||
time:
|
time:
|
||||||
config:
|
config:
|
||||||
max-time-polling-min: 600
|
max-time-polling-min: 600
|
||||||
|
|
||||||
manual-parsing-topic:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
testcontainers:
|
testcontainers:
|
||||||
postgresql:
|
postgresql:
|
||||||
tag: '11.4'
|
tag: '14.12'
|
||||||
|
|
||||||
http-client:
|
http-client:
|
||||||
requestTimeout: 60000
|
requestTimeout: 60000
|
||||||
@ -125,3 +133,7 @@ http-client:
|
|||||||
connectionTimeout: 10000
|
connectionTimeout: 10000
|
||||||
maxTotalPooling: 200
|
maxTotalPooling: 200
|
||||||
defaultMaxPerRoute: 200
|
defaultMaxPerRoute: 200
|
||||||
|
|
||||||
|
otel:
|
||||||
|
resource: http://localhost:4318/v1/traces
|
||||||
|
timeout: 60000
|
||||||
|
2
src/main/resources/db/migration/V3__add_mapping.sql
Normal file
2
src/main/resources/db/migration/V3__add_mapping.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE dspt.dispute
|
||||||
|
ADD COLUMN "mapping" CHARACTER VARYING;
|
@ -1,4 +1,4 @@
|
|||||||
package dev.vality.disputes.manualparsing;
|
package dev.vality.disputes.admin.management;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
@ -16,10 +16,8 @@ import lombok.Data;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -28,43 +26,49 @@ import java.util.List;
|
|||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RequestMapping({"/debug/disputes-api/manual-parsing"})
|
@RequestMapping({"/debug/disputes-api/admin-management"})
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DebugManualParsingController {
|
public class DebugAdminManagementController {
|
||||||
|
|
||||||
private final ManualParsingServiceSrv.Iface manualParsingHandler;
|
private final AdminManagementServiceSrv.Iface adminManagementHandler;
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper().registerModule(new Jdk8Module());
|
private final ObjectMapper objectMapper = new ObjectMapper().registerModule(new Jdk8Module());
|
||||||
|
|
||||||
@PostMapping("/cancel")
|
@PostMapping("/cancel")
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void cancelPending(@RequestBody String body) {
|
public void cancelPending(@RequestBody String body) {
|
||||||
log.debug("cancelPending {}", body);
|
log.debug("cancelPending {}", body);
|
||||||
manualParsingHandler.cancelPending(objectMapper.readValue(body, CancelParamsRequest.class));
|
adminManagementHandler.cancelPending(objectMapper.readValue(body, CancelParamsRequest.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/approve")
|
@PostMapping("/approve")
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void approvePending(@RequestBody String body) {
|
public void approvePending(@RequestBody String body) {
|
||||||
log.debug("approvePending {}", body);
|
log.debug("approvePending {}", body);
|
||||||
manualParsingHandler.approvePending(objectMapper.readValue(body, ApproveParamsRequest.class));
|
adminManagementHandler.approvePending(objectMapper.readValue(body, ApproveParamsRequest.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/bind")
|
@PostMapping("/bind")
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void bindCreated(@RequestBody String body) {
|
public void bindCreated(@RequestBody String body) {
|
||||||
log.debug("bindCreated {}", body);
|
log.debug("bindCreated {}", body);
|
||||||
manualParsingHandler.bindCreated(objectMapper.readValue(body, BindParamsRequest.class));
|
adminManagementHandler.bindCreated(objectMapper.readValue(body, BindParamsRequest.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/get")
|
@PostMapping("/get")
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public DisputeResult getDisputes(@RequestBody String body) {
|
public DisputeResult getDisputes(@RequestBody String body) {
|
||||||
log.debug("getDispute {}", body);
|
log.debug("getDispute {}", body);
|
||||||
var dispute = manualParsingHandler.getDisputes(objectMapper.readValue(body, DisputeParamsRequest.class));
|
var dispute = adminManagementHandler.getDisputes(objectMapper.readValue(body, DisputeParamsRequest.class));
|
||||||
return objectMapper.convertValue(dispute, new TypeReference<>() {
|
return objectMapper.convertValue(dispute, new TypeReference<>() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/disputes")
|
||||||
|
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||||
|
public void defaultRouteUrl() {
|
||||||
|
log.info("hi");
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@ -1,9 +1,9 @@
|
|||||||
package dev.vality.disputes.manualparsing;
|
package dev.vality.disputes.admin.management;
|
||||||
|
|
||||||
|
import dev.vality.disputes.admin.AdminManagementServiceSrv;
|
||||||
import dev.vality.disputes.admin.Attachment;
|
import dev.vality.disputes.admin.Attachment;
|
||||||
import dev.vality.disputes.admin.Dispute;
|
import dev.vality.disputes.admin.Dispute;
|
||||||
import dev.vality.disputes.admin.DisputeResult;
|
import dev.vality.disputes.admin.DisputeResult;
|
||||||
import dev.vality.disputes.admin.ManualParsingServiceSrv;
|
|
||||||
import dev.vality.disputes.config.SpringBootUTest;
|
import dev.vality.disputes.config.SpringBootUTest;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -19,17 +19,17 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
|
|
||||||
@SpringBootUTest
|
@SpringBootUTest
|
||||||
public class DebugManualParsingControllerTest {
|
public class DebugAdminManagementControllerTest {
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private ManualParsingServiceSrv.Iface manualParsingHandler;
|
private AdminManagementServiceSrv.Iface adminManagementHandler;
|
||||||
@Autowired
|
@Autowired
|
||||||
private DebugManualParsingController debugManualParsingController;
|
private DebugAdminManagementController debugAdminManagementController;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void checkSerialization() {
|
public void checkSerialization() {
|
||||||
debugManualParsingController.approvePending("""
|
debugAdminManagementController.approvePending("""
|
||||||
{
|
{
|
||||||
"approveParams": [
|
"approveParams": [
|
||||||
{
|
{
|
||||||
@ -39,7 +39,7 @@ public class DebugManualParsingControllerTest {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
debugManualParsingController.cancelPending("""
|
debugAdminManagementController.cancelPending("""
|
||||||
{
|
{
|
||||||
"cancelParams": [
|
"cancelParams": [
|
||||||
{
|
{
|
||||||
@ -49,7 +49,7 @@ public class DebugManualParsingControllerTest {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
debugManualParsingController.cancelPending("""
|
debugAdminManagementController.cancelPending("""
|
||||||
{
|
{
|
||||||
"cancelParams": [
|
"cancelParams": [
|
||||||
{
|
{
|
||||||
@ -59,7 +59,7 @@ public class DebugManualParsingControllerTest {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
debugManualParsingController.bindCreated("""
|
debugAdminManagementController.bindCreated("""
|
||||||
{
|
{
|
||||||
"bindParams": [
|
"bindParams": [
|
||||||
{
|
{
|
||||||
@ -77,9 +77,9 @@ public class DebugManualParsingControllerTest {
|
|||||||
randomed.setDisputes(List.of(
|
randomed.setDisputes(List.of(
|
||||||
randomThrift(Dispute.class).setAttachments(List.of(new Attachment().setData(b))),
|
randomThrift(Dispute.class).setAttachments(List.of(new Attachment().setData(b))),
|
||||||
randomThrift(Dispute.class).setAttachments(List.of(new Attachment().setData(a)))));
|
randomThrift(Dispute.class).setAttachments(List.of(new Attachment().setData(a)))));
|
||||||
given(manualParsingHandler.getDisputes(any()))
|
given(adminManagementHandler.getDisputes(any()))
|
||||||
.willReturn(randomed);
|
.willReturn(randomed);
|
||||||
var disputes = debugManualParsingController.getDisputes("""
|
var disputes = debugAdminManagementController.getDisputes("""
|
||||||
{
|
{
|
||||||
"disputeParams": [
|
"disputeParams": [
|
||||||
{
|
{
|
@ -1,4 +1,4 @@
|
|||||||
package dev.vality.disputes.manualparsing;
|
package dev.vality.disputes.admin.management;
|
||||||
|
|
||||||
import dev.vality.disputes.config.WireMockSpringBootITest;
|
import dev.vality.disputes.config.WireMockSpringBootITest;
|
||||||
import dev.vality.disputes.dao.DisputeDao;
|
import dev.vality.disputes.dao.DisputeDao;
|
||||||
@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
|
|
||||||
@WireMockSpringBootITest
|
@WireMockSpringBootITest
|
||||||
@Import({PendingDisputesTestService.class})
|
@Import({PendingDisputesTestService.class})
|
||||||
public class DebugManualParsingHandlerTest {
|
public class DebugAdminManagementHandlerTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DisputeDao disputeDao;
|
private DisputeDao disputeDao;
|
||||||
@ -31,19 +31,19 @@ public class DebugManualParsingHandlerTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PendingDisputesTestService pendingDisputesTestService;
|
private PendingDisputesTestService pendingDisputesTestService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private DebugManualParsingController debugManualParsingController;
|
private DebugAdminManagementController debugAdminManagementController;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCancelCreateAdjustment() {
|
public void testCancelCreateAdjustment() {
|
||||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||||
debugManualParsingController.cancelPending(getCancelRequest(disputeId.toString()));
|
debugAdminManagementController.cancelPending(getCancelRequest(disputeId.toString()));
|
||||||
assertEquals(DisputeStatus.cancelled, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.cancelled, disputeDao.get(disputeId).get().getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCancelPending() {
|
public void testCancelPending() {
|
||||||
var disputeId = createdDisputesTestService.callCreateDisputeRemotely();
|
var disputeId = createdDisputesTestService.callCreateDisputeRemotely();
|
||||||
debugManualParsingController.cancelPending(getCancelRequest(disputeId.toString()));
|
debugAdminManagementController.cancelPending(getCancelRequest(disputeId.toString()));
|
||||||
assertEquals(DisputeStatus.cancelled, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.cancelled, disputeDao.get(disputeId).get().getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,14 +51,14 @@ public class DebugManualParsingHandlerTest {
|
|||||||
public void testCancelFailed() {
|
public void testCancelFailed() {
|
||||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
debugManualParsingController.cancelPending(getCancelRequest(disputeId.toString()));
|
debugAdminManagementController.cancelPending(getCancelRequest(disputeId.toString()));
|
||||||
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testApproveCreateAdjustmentWithCallHg() {
|
public void testApproveCreateAdjustmentWithCallHg() {
|
||||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||||
debugManualParsingController.approvePending(getApproveRequest(disputeId.toString(), false));
|
debugAdminManagementController.approvePending(getApproveRequest(disputeId.toString(), false));
|
||||||
assertEquals(DisputeStatus.create_adjustment, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.create_adjustment, disputeDao.get(disputeId).get().getStatus());
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ public class DebugManualParsingHandlerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testApproveCreateAdjustmentWithSkipHg() {
|
public void testApproveCreateAdjustmentWithSkipHg() {
|
||||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||||
debugManualParsingController.approvePending(getApproveRequest(disputeId.toString(), true));
|
debugAdminManagementController.approvePending(getApproveRequest(disputeId.toString(), true));
|
||||||
assertEquals(DisputeStatus.succeeded, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.succeeded, disputeDao.get(disputeId).get().getStatus());
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ public class DebugManualParsingHandlerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testApprovePendingWithSkipHg() {
|
public void testApprovePendingWithSkipHg() {
|
||||||
var disputeId = createdDisputesTestService.callCreateDisputeRemotely();
|
var disputeId = createdDisputesTestService.callCreateDisputeRemotely();
|
||||||
debugManualParsingController.approvePending(getApproveRequest(disputeId.toString(), true));
|
debugAdminManagementController.approvePending(getApproveRequest(disputeId.toString(), true));
|
||||||
assertEquals(DisputeStatus.succeeded, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.succeeded, disputeDao.get(disputeId).get().getStatus());
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ public class DebugManualParsingHandlerTest {
|
|||||||
public void testApproveFailed() {
|
public void testApproveFailed() {
|
||||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
debugManualParsingController.approvePending(getApproveRequest(disputeId.toString(), true));
|
debugAdminManagementController.approvePending(getApproveRequest(disputeId.toString(), true));
|
||||||
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ public class DebugManualParsingHandlerTest {
|
|||||||
public void testBindCreatedCreateAdjustment() {
|
public void testBindCreatedCreateAdjustment() {
|
||||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||||
var providerDisputeId = generateId();
|
var providerDisputeId = generateId();
|
||||||
debugManualParsingController.bindCreated(getBindCreatedRequest(disputeId.toString(), providerDisputeId));
|
debugAdminManagementController.bindCreated(getBindCreatedRequest(disputeId.toString(), providerDisputeId));
|
||||||
assertEquals(DisputeStatus.create_adjustment, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.create_adjustment, disputeDao.get(disputeId).get().getStatus());
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ public class DebugManualParsingHandlerTest {
|
|||||||
public void testBindCreatedPending() {
|
public void testBindCreatedPending() {
|
||||||
var disputeId = createdDisputesTestService.callCreateDisputeRemotely();
|
var disputeId = createdDisputesTestService.callCreateDisputeRemotely();
|
||||||
var providerDisputeId = generateId();
|
var providerDisputeId = generateId();
|
||||||
debugManualParsingController.bindCreated(getBindCreatedRequest(disputeId.toString(), providerDisputeId));
|
debugAdminManagementController.bindCreated(getBindCreatedRequest(disputeId.toString(), providerDisputeId));
|
||||||
assertEquals(DisputeStatus.pending, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.pending, disputeDao.get(disputeId).get().getStatus());
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ public class DebugManualParsingHandlerTest {
|
|||||||
var providerDisputeId = generateId();
|
var providerDisputeId = generateId();
|
||||||
var disputeId = disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId();
|
var disputeId = disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId();
|
||||||
disputeDao.update(UUID.fromString(disputeId), DisputeStatus.manual_created);
|
disputeDao.update(UUID.fromString(disputeId), DisputeStatus.manual_created);
|
||||||
debugManualParsingController.bindCreated(getBindCreatedRequest(disputeId, providerDisputeId));
|
debugAdminManagementController.bindCreated(getBindCreatedRequest(disputeId, providerDisputeId));
|
||||||
assertEquals(DisputeStatus.manual_pending, disputeDao.get(UUID.fromString(disputeId)).get().getStatus());
|
assertEquals(DisputeStatus.manual_pending, disputeDao.get(UUID.fromString(disputeId)).get().getStatus());
|
||||||
disputeDao.update(UUID.fromString(disputeId), DisputeStatus.failed);
|
disputeDao.update(UUID.fromString(disputeId), DisputeStatus.failed);
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ public class DebugManualParsingHandlerTest {
|
|||||||
var providerDisputeId = generateId();
|
var providerDisputeId = generateId();
|
||||||
var disputeId = disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId();
|
var disputeId = disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId();
|
||||||
disputeDao.update(UUID.fromString(disputeId), DisputeStatus.already_exist_created);
|
disputeDao.update(UUID.fromString(disputeId), DisputeStatus.already_exist_created);
|
||||||
debugManualParsingController.bindCreated(getBindCreatedRequest(disputeId, providerDisputeId));
|
debugAdminManagementController.bindCreated(getBindCreatedRequest(disputeId, providerDisputeId));
|
||||||
assertEquals(DisputeStatus.pending, disputeDao.get(UUID.fromString(disputeId)).get().getStatus());
|
assertEquals(DisputeStatus.pending, disputeDao.get(UUID.fromString(disputeId)).get().getStatus());
|
||||||
disputeDao.update(UUID.fromString(disputeId), DisputeStatus.failed);
|
disputeDao.update(UUID.fromString(disputeId), DisputeStatus.failed);
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ public class DebugManualParsingHandlerTest {
|
|||||||
public void testGetDispute() {
|
public void testGetDispute() {
|
||||||
WiremockUtils.mockS3AttachmentDownload();
|
WiremockUtils.mockS3AttachmentDownload();
|
||||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||||
var disputes = debugManualParsingController.getDisputes(getGetDisputeRequest(disputeId.toString(), true));
|
var disputes = debugAdminManagementController.getDisputes(getGetDisputeRequest(disputeId.toString(), true));
|
||||||
assertEquals(1, disputes.getDisputes().size());
|
assertEquals(1, disputes.getDisputes().size());
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
package dev.vality.disputes.api;
|
package dev.vality.disputes.api;
|
||||||
|
|
||||||
import dev.vality.damsel.payment_processing.InvoicingSrv;
|
import dev.vality.damsel.payment_processing.InvoicingSrv;
|
||||||
|
import dev.vality.disputes.admin.AdminManagementServiceSrv;
|
||||||
import dev.vality.disputes.admin.CancelParamsRequest;
|
import dev.vality.disputes.admin.CancelParamsRequest;
|
||||||
import dev.vality.disputes.admin.ManualParsingServiceSrv;
|
|
||||||
import dev.vality.disputes.callback.DisputeCallbackParams;
|
import dev.vality.disputes.callback.DisputeCallbackParams;
|
||||||
import dev.vality.disputes.callback.ProviderDisputesCallbackServiceSrv;
|
import dev.vality.disputes.callback.ProviderDisputesCallbackServiceSrv;
|
||||||
import dev.vality.disputes.config.WireMockSpringBootITest;
|
import dev.vality.disputes.config.WireMockSpringBootITest;
|
||||||
@ -53,11 +53,11 @@ public class ServletTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void manualServletTest() {
|
public void adminManagementServletTest() {
|
||||||
var iface = new THSpawnClientBuilder()
|
var iface = new THSpawnClientBuilder()
|
||||||
.withAddress(new URI("http://127.0.0.1:" + serverPort + MANUAL))
|
.withAddress(new URI("http://127.0.0.1:" + serverPort + ADMIN_MANAGEMENT))
|
||||||
.withNetworkTimeout(5000)
|
.withNetworkTimeout(5000)
|
||||||
.build(ManualParsingServiceSrv.Iface.class);
|
.build(AdminManagementServiceSrv.Iface.class);
|
||||||
var request = DamselUtil.fillRequiredTBaseObject(
|
var request = DamselUtil.fillRequiredTBaseObject(
|
||||||
new CancelParamsRequest(),
|
new CancelParamsRequest(),
|
||||||
CancelParamsRequest.class
|
CancelParamsRequest.class
|
||||||
|
@ -17,12 +17,15 @@ import dev.vality.file.storage.FileStorageSrv;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static dev.vality.disputes.constant.ModerationPrefix.DISPUTES_UNKNOWN_MAPPING;
|
||||||
import static dev.vality.disputes.util.MockUtil.*;
|
import static dev.vality.disputes.util.MockUtil.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@ -49,6 +52,8 @@ public class CreatedDisputesServiceTest {
|
|||||||
private WiremockAddressesHolder wiremockAddressesHolder;
|
private WiremockAddressesHolder wiremockAddressesHolder;
|
||||||
@Autowired
|
@Autowired
|
||||||
private CreatedDisputesTestService createdDisputesTestService;
|
private CreatedDisputesTestService createdDisputesTestService;
|
||||||
|
@LocalServerPort
|
||||||
|
private int serverPort;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@ -92,7 +97,7 @@ public class CreatedDisputesServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void testManualCreatedWhenIsNotProvidersDisputesApiExist() {
|
public void testManualPendingWhenIsNotProvidersDisputesApiExist() {
|
||||||
var invoiceId = "20McecNnWoy";
|
var invoiceId = "20McecNnWoy";
|
||||||
var paymentId = "1";
|
var paymentId = "1";
|
||||||
var disputeId = UUID.fromString(disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId());
|
var disputeId = UUID.fromString(disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId());
|
||||||
@ -105,7 +110,7 @@ public class CreatedDisputesServiceTest {
|
|||||||
when(dominantService.getProxy(any())).thenReturn(createProxy().get());
|
when(dominantService.getProxy(any())).thenReturn(createProxy().get());
|
||||||
var dispute = disputeDao.get(disputeId);
|
var dispute = disputeDao.get(disputeId);
|
||||||
createdDisputesService.callCreateDisputeRemotely(dispute.get());
|
createdDisputesService.callCreateDisputeRemotely(dispute.get());
|
||||||
assertEquals(DisputeStatus.manual_created, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.manual_pending, disputeDao.get(disputeId).get().getStatus());
|
||||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +143,83 @@ public class CreatedDisputesServiceTest {
|
|||||||
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
public void testManualCreatedWhenDisputeCreatedFailResultWithDisputesUnknownMapping() {
|
||||||
|
var invoiceId = "20McecNnWoy";
|
||||||
|
var paymentId = "1";
|
||||||
|
var disputeId = UUID.fromString(disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId());
|
||||||
|
var invoicePayment = MockUtil.createInvoicePayment(paymentId);
|
||||||
|
invoicePayment.getPayment().setStatus(InvoicePaymentStatus.captured(new InvoicePaymentCaptured()));
|
||||||
|
when(invoicingClient.getPayment(any(), any())).thenReturn(invoicePayment);
|
||||||
|
when(fileStorageClient.generateDownloadUrl(any(), any())).thenReturn(wiremockAddressesHolder.getDownloadUrl());
|
||||||
|
var terminal = createTerminal().get();
|
||||||
|
terminal.getOptions().putAll(getOptions());
|
||||||
|
when(dominantService.getTerminal(any())).thenReturn(terminal);
|
||||||
|
when(dominantService.getProvider(any())).thenReturn(createProvider().get());
|
||||||
|
when(dominantService.getProxy(any())).thenReturn(createProxy().get());
|
||||||
|
var providerMock = mock(ProviderDisputesServiceSrv.Client.class);
|
||||||
|
var disputeCreatedFailResult = createDisputeCreatedFailResult();
|
||||||
|
disputeCreatedFailResult.getFailResult().getFailure().setCode(DISPUTES_UNKNOWN_MAPPING);
|
||||||
|
when(providerMock.createDispute(any())).thenReturn(disputeCreatedFailResult);
|
||||||
|
when(providerIfaceBuilder.buildTHSpawnClient(any())).thenReturn(providerMock);
|
||||||
|
var dispute = disputeDao.get(disputeId);
|
||||||
|
createdDisputesService.callCreateDisputeRemotely(dispute.get());
|
||||||
|
assertEquals(DisputeStatus.manual_created, disputeDao.get(disputeId).get().getStatus());
|
||||||
|
assertTrue(disputeDao.get(disputeId).get().getErrorMessage().contains(DISPUTES_UNKNOWN_MAPPING));
|
||||||
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
public void testManualCreatedWhenUnexpectedResultMapping() {
|
||||||
|
var invoiceId = "20McecNnWoy";
|
||||||
|
var paymentId = "1";
|
||||||
|
var disputeId = UUID.fromString(disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId());
|
||||||
|
var invoicePayment = MockUtil.createInvoicePayment(paymentId);
|
||||||
|
invoicePayment.getPayment().setStatus(InvoicePaymentStatus.captured(new InvoicePaymentCaptured()));
|
||||||
|
when(invoicingClient.getPayment(any(), any())).thenReturn(invoicePayment);
|
||||||
|
when(fileStorageClient.generateDownloadUrl(any(), any())).thenReturn(wiremockAddressesHolder.getDownloadUrl());
|
||||||
|
var terminal = createTerminal().get();
|
||||||
|
terminal.getOptions().putAll(getOptions());
|
||||||
|
when(dominantService.getTerminal(any())).thenReturn(terminal);
|
||||||
|
when(dominantService.getProvider(any())).thenReturn(createProvider().get());
|
||||||
|
// routeUrl = "http://127.0.0.1:8023/disputes" == exist api
|
||||||
|
when(dominantService.getProxy(any())).thenReturn(createProxyWithRealAddress(serverPort).get());
|
||||||
|
var providerMock = mock(ProviderDisputesServiceSrv.Client.class);
|
||||||
|
when(providerMock.createDispute(any())).thenThrow(getUnexpectedResultWException());
|
||||||
|
when(providerIfaceBuilder.buildTHSpawnClient(any())).thenReturn(providerMock);
|
||||||
|
var dispute = disputeDao.get(disputeId);
|
||||||
|
createdDisputesService.callCreateDisputeRemotely(dispute.get());
|
||||||
|
assertEquals(DisputeStatus.manual_created, disputeDao.get(disputeId).get().getStatus());
|
||||||
|
assertTrue(disputeDao.get(disputeId).get().getErrorMessage().contains("Unexpected result"));
|
||||||
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
public void testManualPendingWhenUnexpectedResult() {
|
||||||
|
var invoiceId = "20McecNnWoy";
|
||||||
|
var paymentId = "1";
|
||||||
|
var disputeId = UUID.fromString(disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId());
|
||||||
|
var invoicePayment = MockUtil.createInvoicePayment(paymentId);
|
||||||
|
invoicePayment.getPayment().setStatus(InvoicePaymentStatus.captured(new InvoicePaymentCaptured()));
|
||||||
|
when(invoicingClient.getPayment(any(), any())).thenReturn(invoicePayment);
|
||||||
|
when(fileStorageClient.generateDownloadUrl(any(), any())).thenReturn(wiremockAddressesHolder.getDownloadUrl());
|
||||||
|
var terminal = createTerminal().get();
|
||||||
|
terminal.getOptions().putAll(getOptions());
|
||||||
|
when(dominantService.getTerminal(any())).thenReturn(terminal);
|
||||||
|
when(dominantService.getProvider(any())).thenReturn(createProvider().get());
|
||||||
|
when(dominantService.getProxy(any())).thenReturn(createProxyNotFoundCase(serverPort).get());
|
||||||
|
var providerMock = mock(ProviderDisputesServiceSrv.Client.class);
|
||||||
|
when(providerMock.createDispute(any())).thenThrow(getUnexpectedResultWException());
|
||||||
|
when(providerIfaceBuilder.buildTHSpawnClient(any())).thenReturn(providerMock);
|
||||||
|
var dispute = disputeDao.get(disputeId);
|
||||||
|
createdDisputesService.callCreateDisputeRemotely(dispute.get());
|
||||||
|
assertEquals(DisputeStatus.manual_pending, disputeDao.get(disputeId).get().getStatus());
|
||||||
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void testDisputeCreatedAlreadyExistResult() {
|
public void testDisputeCreatedAlreadyExistResult() {
|
||||||
|
@ -15,8 +15,10 @@ import org.springframework.context.annotation.Import;
|
|||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static dev.vality.disputes.constant.ModerationPrefix.DISPUTES_UNKNOWN_MAPPING;
|
||||||
import static dev.vality.disputes.util.MockUtil.*;
|
import static dev.vality.disputes.util.MockUtil.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@ -77,6 +79,37 @@ public class PendingDisputesServiceTest {
|
|||||||
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
public void testManualPendingWhenStatusFailResultWithDisputesUnknownMapping() {
|
||||||
|
var disputeId = createdDisputesTestService.callCreateDisputeRemotely();
|
||||||
|
var providerMock = mock(ProviderDisputesServiceSrv.Client.class);
|
||||||
|
var disputeStatusFailResult = createDisputeStatusFailResult();
|
||||||
|
disputeStatusFailResult.getStatusFail().getFailure().setCode(DISPUTES_UNKNOWN_MAPPING);
|
||||||
|
when(providerMock.checkDisputeStatus(any())).thenReturn(disputeStatusFailResult);
|
||||||
|
when(providerIfaceBuilder.buildTHSpawnClient(any())).thenReturn(providerMock);
|
||||||
|
var dispute = disputeDao.get(disputeId);
|
||||||
|
pendingDisputesService.callPendingDisputeRemotely(dispute.get());
|
||||||
|
assertEquals(DisputeStatus.manual_pending, disputeDao.get(disputeId).get().getStatus());
|
||||||
|
assertTrue(disputeDao.get(disputeId).get().getErrorMessage().contains(DISPUTES_UNKNOWN_MAPPING));
|
||||||
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
public void testManualPendingWhenUnexpectedResultMapping() {
|
||||||
|
var disputeId = createdDisputesTestService.callCreateDisputeRemotely();
|
||||||
|
var providerMock = mock(ProviderDisputesServiceSrv.Client.class);
|
||||||
|
when(providerMock.checkDisputeStatus(any())).thenThrow(getUnexpectedResultWException());
|
||||||
|
when(providerIfaceBuilder.buildTHSpawnClient(any())).thenReturn(providerMock);
|
||||||
|
var dispute = disputeDao.get(disputeId);
|
||||||
|
pendingDisputesService.callPendingDisputeRemotely(dispute.get());
|
||||||
|
assertEquals(DisputeStatus.manual_pending, disputeDao.get(disputeId).get().getStatus());
|
||||||
|
assertTrue(disputeDao.get(disputeId).get().getErrorMessage().contains("Unexpected result"));
|
||||||
|
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void testDisputeStatusPendingResult() {
|
public void testDisputeStatusPendingResult() {
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package dev.vality.disputes.schedule.service.config;
|
||||||
|
|
||||||
|
import dev.vality.disputes.admin.AdminCallbackServiceSrv;
|
||||||
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
|
||||||
|
@TestConfiguration
|
||||||
|
public class CallbackNotifierTestConfig {
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private AdminCallbackServiceSrv.Iface adminCallbackDisputesTgBotClient;
|
||||||
|
|
||||||
|
}
|
@ -27,7 +27,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@TestComponent
|
@TestComponent
|
||||||
@Import({DisputeApiTestService.class, RemoteClientTestConfig.class})
|
@Import({DisputeApiTestService.class, RemoteClientTestConfig.class, DefaultRemoteClientTestConfig.class, CallbackNotifierTestConfig.class})
|
||||||
@SuppressWarnings({"ParameterName", "LineLength"})
|
@SuppressWarnings({"ParameterName", "LineLength"})
|
||||||
public class CreatedDisputesTestService {
|
public class CreatedDisputesTestService {
|
||||||
|
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package dev.vality.disputes.schedule.service.config;
|
||||||
|
|
||||||
|
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
||||||
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
|
||||||
|
@TestConfiguration
|
||||||
|
public class DefaultRemoteClientTestConfig {
|
||||||
|
|
||||||
|
@MockBean
|
||||||
|
private ProviderDisputesServiceSrv.Iface providerDisputesTgBotClient;
|
||||||
|
|
||||||
|
}
|
@ -14,6 +14,10 @@ import dev.vality.file.storage.NewFileResult;
|
|||||||
import dev.vality.geck.common.util.TypeUtil;
|
import dev.vality.geck.common.util.TypeUtil;
|
||||||
import dev.vality.token.keeper.AuthData;
|
import dev.vality.token.keeper.AuthData;
|
||||||
import dev.vality.token.keeper.AuthDataStatus;
|
import dev.vality.token.keeper.AuthDataStatus;
|
||||||
|
import dev.vality.woody.api.flow.error.WErrorDefinition;
|
||||||
|
import dev.vality.woody.api.flow.error.WErrorSource;
|
||||||
|
import dev.vality.woody.api.flow.error.WErrorType;
|
||||||
|
import dev.vality.woody.api.flow.error.WRuntimeException;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
import org.apache.thrift.TSerializer;
|
import org.apache.thrift.TSerializer;
|
||||||
@ -81,8 +85,16 @@ public class MockUtil {
|
|||||||
.setProxy(new Proxy().setRef(new ProxyRef().setId(1))));
|
.setProxy(new Proxy().setRef(new ProxyRef().setId(1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CompletableFuture<ProxyDefinition> createProxyNotFoundCase(Integer port) {
|
||||||
|
return createProxy("http://127.0.0.1:" + port + "/debug/disputes-api/admin-management");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompletableFuture<ProxyDefinition> createProxyWithRealAddress(Integer port) {
|
||||||
|
return createProxy("http://127.0.0.1:" + port);
|
||||||
|
}
|
||||||
|
|
||||||
public static CompletableFuture<ProxyDefinition> createProxy() {
|
public static CompletableFuture<ProxyDefinition> createProxy() {
|
||||||
return createProxy("http://ya.ru");
|
return createProxy("http://127.0.0.1:8023");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompletableFuture<ProxyDefinition> createProxy(String url) {
|
public static CompletableFuture<ProxyDefinition> createProxy(String url) {
|
||||||
@ -173,4 +185,13 @@ public class MockUtil {
|
|||||||
failure.setSub(new SubFailure("some_suberror"));
|
failure.setSub(new SubFailure("some_suberror"));
|
||||||
return failure;
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static WRuntimeException getUnexpectedResultWException() {
|
||||||
|
var errorDefinition = new WErrorDefinition(WErrorSource.EXTERNAL);
|
||||||
|
errorDefinition.setErrorReason("Unexpected result, code = resp_status_error, description = " +
|
||||||
|
"Tek seferde en fazla 4,000.00 işem yapılabilir.");
|
||||||
|
errorDefinition.setErrorType(WErrorType.UNEXPECTED_ERROR);
|
||||||
|
errorDefinition.setErrorSource(WErrorSource.INTERNAL);
|
||||||
|
return new WRuntimeException(errorDefinition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user