mirror of
https://github.com/valitydev/disputes-api.git
synced 2024-11-06 00:55:23 +00:00
fix adjustments (#25)
* fix adjusments * fix adjusments * 400 when pending payment
This commit is contained in:
parent
df25417b6b
commit
e930555f06
@ -10,7 +10,7 @@ public interface CallbackNotifier {
|
||||
|
||||
void sendDisputePoolingExpired(Dispute dispute);
|
||||
|
||||
void sendDisputeReadyForCreateAdjustment(List<Dispute> disputes);
|
||||
void sendDisputesReadyForCreateAdjustment(List<Dispute> disputes);
|
||||
|
||||
void sendDisputeFailedReviewRequired(Dispute dispute, String errorCode, String errorDescription);
|
||||
|
||||
|
@ -34,13 +34,13 @@ public class DisputesTgBotCallbackNotifierImpl implements CallbackNotifier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDisputeReadyForCreateAdjustment(List<Dispute> disputes) {
|
||||
public void sendDisputesReadyForCreateAdjustment(List<Dispute> disputes) {
|
||||
var disputeReadyForCreateAdjustments = disputes.stream()
|
||||
.map(Dispute::getId)
|
||||
.map(UUID::toString)
|
||||
.map(DisputeReadyForCreateAdjustment::new)
|
||||
.toList();
|
||||
disputesTgBotService.sendDisputeReadyForCreateAdjustment(disputeReadyForCreateAdjustments);
|
||||
disputesTgBotService.sendDisputesReadyForCreateAdjustment(disputeReadyForCreateAdjustments);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,7 +26,7 @@ public class DummyCallbackNotifierImpl implements CallbackNotifier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDisputeReadyForCreateAdjustment(List<Dispute> disputes) {
|
||||
public void sendDisputesReadyForCreateAdjustment(List<Dispute> disputes) {
|
||||
log.debug("Trying to call DummyCallbackNotifierImpl.sendDisputeReadyForCreateAdjustment() {}", disputes.size());
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dev.vality.disputes.api.controller;
|
||||
|
||||
import dev.vality.disputes.exception.AuthorizationException;
|
||||
import dev.vality.disputes.exception.InvoicingPaymentStatusPendingException;
|
||||
import dev.vality.disputes.exception.NotFoundException;
|
||||
import dev.vality.disputes.exception.TokenKeeperException;
|
||||
import dev.vality.swag.disputes.model.GeneralError;
|
||||
@ -35,6 +36,14 @@ public class ErrorControllerAdvice {
|
||||
|
||||
// ----------------- 4xx -----------------------------------------------------
|
||||
|
||||
@ExceptionHandler({InvoicingPaymentStatusPendingException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Object handleInvalidMimeTypeException(InvoicingPaymentStatusPendingException e) {
|
||||
log.warn("<- Res [400]: Payment has non-final status", e);
|
||||
return new GeneralError()
|
||||
.message("Payment has non-final status");
|
||||
}
|
||||
|
||||
@ExceptionHandler({InvalidMimeTypeException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Object handleInvalidMimeTypeException(InvalidMimeTypeException e) {
|
||||
|
@ -5,4 +5,7 @@ public class InvoicingPaymentStatusPendingException extends RuntimeException {
|
||||
public InvoicingPaymentStatusPendingException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public InvoicingPaymentStatusPendingException() {
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package dev.vality.disputes.schedule;
|
||||
|
||||
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.core.AdjustmentsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@ -14,18 +14,18 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
||||
public class TaskReadyForCreateAdjustmentsService {
|
||||
public class AdjustmentsReadyNotificationTask {
|
||||
|
||||
private final CreateAdjustmentsService createAdjustmentsService;
|
||||
private final AdjustmentsService adjustmentsService;
|
||||
private final CallbackNotifier callbackNotifier;
|
||||
private final MdcTopicProducer mdcTopicProducer;
|
||||
|
||||
@Scheduled(fixedDelayString = "${dispute.fixedDelayReadyForCreateAdjustments}", initialDelayString = "${dispute.initialDelayReadyForCreateAdjustments}")
|
||||
public void processPending() {
|
||||
log.debug("Processing ReadyForCreateAdjustments get started");
|
||||
var disputes = createAdjustmentsService.getReadyDisputesForCreateAdjustment();
|
||||
var disputes = adjustmentsService.getReadyDisputesForCreateAdjustment();
|
||||
mdcTopicProducer.sendReadyForCreateAdjustments(disputes);
|
||||
callbackNotifier.sendDisputeReadyForCreateAdjustment(disputes);
|
||||
callbackNotifier.sendDisputesReadyForCreateAdjustment(disputes);
|
||||
log.info("ReadyForCreateAdjustments were processed");
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package dev.vality.disputes.schedule;
|
||||
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.handler.CreateAdjustmentHandler;
|
||||
import dev.vality.disputes.schedule.service.CreateAdjustmentsService;
|
||||
import dev.vality.disputes.schedule.core.AdjustmentsService;
|
||||
import dev.vality.disputes.schedule.handler.AdjustmentHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -20,10 +20,10 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
||||
public class TaskCreateAdjustmentsService {
|
||||
public class AdjustmentsTask {
|
||||
|
||||
private final ExecutorService disputesThreadPool;
|
||||
private final CreateAdjustmentsService createAdjustmentsService;
|
||||
private final AdjustmentsService adjustmentsService;
|
||||
@Value("${dispute.batchSize}")
|
||||
private int batchSize;
|
||||
|
||||
@ -31,7 +31,7 @@ public class TaskCreateAdjustmentsService {
|
||||
public void processPending() {
|
||||
log.debug("Processing create adjustments get started");
|
||||
try {
|
||||
var disputes = createAdjustmentsService.getDisputesForHgCall(batchSize);
|
||||
var disputes = adjustmentsService.getDisputesForHgCall(batchSize);
|
||||
var callables = disputes.stream()
|
||||
.map(this::handleCreateAdjustment)
|
||||
.collect(Collectors.toList());
|
||||
@ -46,6 +46,6 @@ public class TaskCreateAdjustmentsService {
|
||||
}
|
||||
|
||||
private Callable<UUID> handleCreateAdjustment(Dispute dispute) {
|
||||
return () -> new CreateAdjustmentHandler(createAdjustmentsService).handle(dispute);
|
||||
return () -> new AdjustmentHandler(adjustmentsService).handle(dispute);
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package dev.vality.disputes.schedule;
|
||||
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.core.CreatedDisputesService;
|
||||
import dev.vality.disputes.schedule.handler.CreatedDisputeHandler;
|
||||
import dev.vality.disputes.schedule.service.CreatedDisputesService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -19,7 +19,7 @@ import java.util.stream.Collectors;
|
||||
@ConditionalOnProperty(value = "dispute.isScheduleCreatedEnabled", havingValue = "true")
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TaskCreatedDisputesService {
|
||||
public class CreatedDisputesTask {
|
||||
|
||||
private final ExecutorService disputesThreadPool;
|
||||
private final CreatedDisputesService createdDisputesService;
|
@ -1,8 +1,8 @@
|
||||
package dev.vality.disputes.schedule;
|
||||
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.core.PendingDisputesService;
|
||||
import dev.vality.disputes.schedule.handler.PendingDisputeHandler;
|
||||
import dev.vality.disputes.schedule.service.PendingDisputesService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -19,7 +19,7 @@ import java.util.stream.Collectors;
|
||||
@ConditionalOnProperty(value = "dispute.isSchedulePendingEnabled", havingValue = "true")
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TaskPendingDisputesService {
|
||||
public class PendingDisputesTask {
|
||||
|
||||
private final ExecutorService disputesThreadPool;
|
||||
private final PendingDisputesService pendingDisputesService;
|
@ -1,39 +1,31 @@
|
||||
package dev.vality.disputes.schedule.converter;
|
||||
|
||||
import dev.vality.damsel.domain.*;
|
||||
import dev.vality.damsel.domain.InvoicePaymentAdjustmentStatusChange;
|
||||
import dev.vality.damsel.domain.InvoicePaymentCaptured;
|
||||
import dev.vality.damsel.domain.InvoicePaymentStatus;
|
||||
import dev.vality.damsel.payment_processing.InvoicePaymentAdjustmentParams;
|
||||
import dev.vality.damsel.payment_processing.InvoicePaymentAdjustmentScenario;
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.service.AdjustmentExtractor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class InvoicePaymentAdjustmentParamsConverter {
|
||||
@RequiredArgsConstructor
|
||||
public class InvoicePaymentCapturedAdjustmentParamsConverter {
|
||||
|
||||
public static final String DISPUTE_MASK = "disputeId=%s";
|
||||
private final AdjustmentExtractor adjustmentExtractor;
|
||||
|
||||
public InvoicePaymentAdjustmentParams convert(Dispute dispute) {
|
||||
var captured = new InvoicePaymentCaptured();
|
||||
var reason = getReason(dispute);
|
||||
var reason = adjustmentExtractor.getReason(dispute);
|
||||
captured.setReason(reason);
|
||||
var changedAmount = dispute.getChangedAmount();
|
||||
if (changedAmount != null) {
|
||||
var cost = new Cash(changedAmount, new CurrencyRef(dispute.getCurrencySymbolicCode()));
|
||||
captured.setCost(cost);
|
||||
}
|
||||
var params = new InvoicePaymentAdjustmentParams();
|
||||
params.setReason(reason);
|
||||
params.setScenario(getInvoicePaymentAdjustmentScenario(captured));
|
||||
return params;
|
||||
}
|
||||
|
||||
public String getReason(Dispute dispute) {
|
||||
return Optional.ofNullable(dispute.getReason())
|
||||
.map(s -> String.format(DISPUTE_MASK + ", reason=%s", dispute.getId(), s))
|
||||
.orElse(String.format(DISPUTE_MASK, dispute.getId()));
|
||||
}
|
||||
|
||||
private InvoicePaymentAdjustmentScenario getInvoicePaymentAdjustmentScenario(InvoicePaymentCaptured captured) {
|
||||
return InvoicePaymentAdjustmentScenario.status_change(new InvoicePaymentAdjustmentStatusChange(
|
||||
InvoicePaymentStatus.captured(captured)));
|
@ -0,0 +1,32 @@
|
||||
package dev.vality.disputes.schedule.converter;
|
||||
|
||||
import dev.vality.damsel.domain.InvoicePaymentAdjustmentCashFlow;
|
||||
import dev.vality.damsel.domain.InvoicePaymentCaptured;
|
||||
import dev.vality.damsel.payment_processing.InvoicePaymentAdjustmentParams;
|
||||
import dev.vality.damsel.payment_processing.InvoicePaymentAdjustmentScenario;
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.service.AdjustmentExtractor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class InvoicePaymentCashFlowAdjustmentParamsConverter {
|
||||
|
||||
private final AdjustmentExtractor adjustmentExtractor;
|
||||
|
||||
public InvoicePaymentAdjustmentParams convert(Dispute dispute) {
|
||||
var captured = new InvoicePaymentCaptured();
|
||||
var reason = adjustmentExtractor.getReason(dispute);
|
||||
captured.setReason(reason);
|
||||
var params = new InvoicePaymentAdjustmentParams();
|
||||
params.setReason(reason);
|
||||
params.setScenario(getInvoicePaymentAdjustmentScenario(dispute.getChangedAmount()));
|
||||
return params;
|
||||
}
|
||||
|
||||
private InvoicePaymentAdjustmentScenario getInvoicePaymentAdjustmentScenario(Long changedAmount) {
|
||||
return InvoicePaymentAdjustmentScenario.cash_flow(new InvoicePaymentAdjustmentCashFlow()
|
||||
.setNewAmount(changedAmount));
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package dev.vality.disputes.schedule.converter;
|
||||
|
||||
import dev.vality.damsel.domain.*;
|
||||
import dev.vality.damsel.payment_processing.InvoicePaymentAdjustmentParams;
|
||||
import dev.vality.damsel.payment_processing.InvoicePaymentAdjustmentScenario;
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.service.AdjustmentExtractor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class InvoicePaymentFailedAdjustmentParamsConverter {
|
||||
|
||||
private final AdjustmentExtractor adjustmentExtractor;
|
||||
|
||||
public InvoicePaymentAdjustmentParams convert(Dispute dispute) {
|
||||
var invoicePaymentFailed = new InvoicePaymentFailed();
|
||||
var reason = adjustmentExtractor.getReason(dispute);
|
||||
invoicePaymentFailed.setFailure(OperationFailure.failure(
|
||||
new Failure("failed_by_disputes_api").setReason(reason)));
|
||||
var params = new InvoicePaymentAdjustmentParams();
|
||||
params.setReason(reason);
|
||||
params.setScenario(getInvoicePaymentAdjustmentScenario(invoicePaymentFailed));
|
||||
return params;
|
||||
}
|
||||
|
||||
private InvoicePaymentAdjustmentScenario getInvoicePaymentAdjustmentScenario(InvoicePaymentFailed failed) {
|
||||
return InvoicePaymentAdjustmentScenario.status_change(new InvoicePaymentAdjustmentStatusChange(
|
||||
InvoicePaymentStatus.failed(failed)));
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package dev.vality.disputes.schedule.service;
|
||||
package dev.vality.disputes.schedule.core;
|
||||
|
||||
import dev.vality.damsel.domain.InvoicePaymentAdjustment;
|
||||
import dev.vality.damsel.payment_processing.InvoicePayment;
|
||||
@ -7,8 +7,10 @@ import dev.vality.disputes.constant.ErrorReason;
|
||||
import dev.vality.disputes.dao.DisputeDao;
|
||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.exception.InvoicingPaymentStatusPendingException;
|
||||
import dev.vality.disputes.schedule.converter.InvoicePaymentAdjustmentParamsConverter;
|
||||
import dev.vality.disputes.schedule.converter.InvoicePaymentCapturedAdjustmentParamsConverter;
|
||||
import dev.vality.disputes.schedule.converter.InvoicePaymentCashFlowAdjustmentParamsConverter;
|
||||
import dev.vality.disputes.schedule.converter.InvoicePaymentFailedAdjustmentParamsConverter;
|
||||
import dev.vality.disputes.schedule.service.AdjustmentExtractor;
|
||||
import dev.vality.disputes.service.external.InvoicingService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -18,16 +20,19 @@ import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings({"ParameterName", "LineLength", "MissingSwitchDefault"})
|
||||
public class CreateAdjustmentsService {
|
||||
public class AdjustmentsService {
|
||||
|
||||
private final DisputeDao disputeDao;
|
||||
private final InvoicingService invoicingService;
|
||||
private final InvoicePaymentAdjustmentParamsConverter invoicePaymentAdjustmentParamsConverter;
|
||||
private final InvoicePaymentCapturedAdjustmentParamsConverter invoicePaymentCapturedAdjustmentParamsConverter;
|
||||
private final InvoicePaymentCashFlowAdjustmentParamsConverter invoicePaymentCashFlowAdjustmentParamsConverter;
|
||||
private final InvoicePaymentFailedAdjustmentParamsConverter invoicePaymentFailedAdjustmentParamsConverter;
|
||||
private final AdjustmentExtractor adjustmentExtractor;
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@ -57,42 +62,51 @@ public class CreateAdjustmentsService {
|
||||
log.debug("GetDisputeForUpdateSkipLocked has been found {}", dispute);
|
||||
var invoicePayment = getInvoicePayment(dispute);
|
||||
if (invoicePayment == null || !invoicePayment.isSetRoute()) {
|
||||
log.error("Trying to set failed Dispute status with PAYMENT_NOT_FOUND error reason {}", dispute.getId());
|
||||
disputeDao.update(dispute.getId(), DisputeStatus.failed, ErrorReason.PAYMENT_NOT_FOUND);
|
||||
log.debug("Dispute status has been set to failed {}", dispute.getId());
|
||||
updateFailed(dispute, ErrorReason.PAYMENT_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
var invoicePaymentAdjustment = adjustmentExtractor.searchAdjustmentByDispute(invoicePayment, dispute);
|
||||
if (invoicePaymentAdjustment.isPresent()) {
|
||||
var changedAmount = adjustmentExtractor.getChangedAmount(invoicePaymentAdjustment.get(), dispute.getChangedAmount());
|
||||
log.info("Trying to set succeeded Dispute status {}", dispute);
|
||||
disputeDao.update(dispute.getId(), DisputeStatus.succeeded, changedAmount);
|
||||
log.debug("Dispute status has been set to succeeded {}", dispute.getId());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var params = invoicePaymentAdjustmentParamsConverter.convert(dispute);
|
||||
if (!adjustmentExtractor.isCashFlowAdjustmentByDisputeExist(invoicePayment, dispute)
|
||||
&& !Objects.equals(dispute.getAmount(), dispute.getChangedAmount())) {
|
||||
var params = invoicePaymentCashFlowAdjustmentParamsConverter.convert(dispute);
|
||||
var paymentAdjustment = createAdjustment(dispute, params);
|
||||
if (paymentAdjustment == null) {
|
||||
log.error("Trying to set failed Dispute status with INVOICE_NOT_FOUND error reason {}", dispute.getId());
|
||||
disputeDao.update(dispute.getId(), DisputeStatus.failed, ErrorReason.INVOICE_NOT_FOUND);
|
||||
log.debug("Dispute status has been set to failed {}", dispute.getId());
|
||||
var errorReason = ErrorReason.INVOICE_NOT_FOUND;
|
||||
updateFailed(dispute, errorReason);
|
||||
return;
|
||||
}
|
||||
} catch (InvoicingPaymentStatusPendingException e) {
|
||||
// в теории 0%, что сюда попадает выполнение кода, но если попадет, то:
|
||||
// платеж с не финальным статусом будет заблочен для создания корректировок на стороне хелгейта
|
||||
// и тогда диспут будет пулиться, пока платеж не зафиналится,
|
||||
// и тк никакой записи в коде выше нет, то пуллинг не проблема
|
||||
// а запрос в checkDisputeStatus по идемпотентности просто вернет тот же success
|
||||
log.error("Error when hg.createPaymentAdjustment() got payments status pending {}", dispute.getId(), e);
|
||||
return;
|
||||
} else {
|
||||
log.info("Creating CashFlowAdjustment was skipped {}", dispute);
|
||||
}
|
||||
if (!adjustmentExtractor.isCapturedAdjustmentByDisputeExist(invoicePayment, dispute)) {
|
||||
if (invoicePayment.getPayment().getStatus().isSetCaptured()) {
|
||||
var params = invoicePaymentFailedAdjustmentParamsConverter.convert(dispute);
|
||||
var paymentAdjustment = createAdjustment(dispute, params);
|
||||
if (paymentAdjustment == null) {
|
||||
updateFailed(dispute, ErrorReason.INVOICE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
}
|
||||
var params = invoicePaymentCapturedAdjustmentParamsConverter.convert(dispute);
|
||||
var paymentAdjustment = createAdjustment(dispute, params);
|
||||
if (paymentAdjustment == null) {
|
||||
updateFailed(dispute, ErrorReason.INVOICE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
log.info("Creating CapturedAdjustment was skipped {}", dispute);
|
||||
}
|
||||
log.info("Trying to set succeeded Dispute status {}", dispute);
|
||||
disputeDao.update(dispute.getId(), DisputeStatus.succeeded);
|
||||
log.debug("Dispute status has been set to succeeded {}", dispute.getId());
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
void updateFailed(Dispute dispute, String errorReason) {
|
||||
log.error("Trying to set failed Dispute status with {} error reason {}", errorReason, dispute.getId());
|
||||
disputeDao.update(dispute.getId(), DisputeStatus.failed, errorReason);
|
||||
log.debug("Dispute status has been set to failed {}", dispute.getId());
|
||||
}
|
||||
|
||||
private InvoicePaymentAdjustment createAdjustment(Dispute dispute, InvoicePaymentAdjustmentParams params) {
|
||||
return invoicingService.createPaymentAdjustment(dispute.getInvoiceId(), dispute.getPaymentId(), params);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package dev.vality.disputes.schedule.service;
|
||||
package dev.vality.disputes.schedule.core;
|
||||
|
||||
import dev.vality.damsel.payment_processing.InvoicePayment;
|
||||
import dev.vality.disputes.constant.ErrorReason;
|
||||
@ -11,6 +11,8 @@ import dev.vality.disputes.schedule.client.DefaultRemoteClient;
|
||||
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.schedule.service.AttachmentsService;
|
||||
import dev.vality.disputes.schedule.service.ProviderDataService;
|
||||
import dev.vality.disputes.service.external.InvoicingService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -33,7 +35,7 @@ public class CreatedDisputesService {
|
||||
|
||||
private final RemoteClient remoteClient;
|
||||
private final DisputeDao disputeDao;
|
||||
private final CreatedAttachmentsService createdAttachmentsService;
|
||||
private final AttachmentsService attachmentsService;
|
||||
private final InvoicingService invoicingService;
|
||||
private final ProviderDataService providerDataService;
|
||||
private final DefaultRemoteClient defaultRemoteClient;
|
||||
@ -64,13 +66,7 @@ public class CreatedDisputesService {
|
||||
log.debug("Dispute status has been set to failed {}", dispute.getId());
|
||||
return;
|
||||
}
|
||||
var status = invoicePayment.getPayment().getStatus();
|
||||
if (!status.isSetCaptured() && !status.isSetCancelled() && !status.isSetFailed()) {
|
||||
// не создаем диспут, пока платеж не финален
|
||||
log.warn("Payment has non-final status {} {}", status, dispute.getId());
|
||||
return;
|
||||
}
|
||||
var attachments = createdAttachmentsService.getAttachments(dispute);
|
||||
var attachments = attachmentsService.getAttachments(dispute);
|
||||
if (attachments == null || attachments.isEmpty()) {
|
||||
log.error("Trying to set failed Dispute status with NO_ATTACHMENTS error reason {}", dispute.getId());
|
||||
disputeDao.update(dispute.getId(), DisputeStatus.failed, ErrorReason.NO_ATTACHMENTS);
|
||||
@ -79,7 +75,7 @@ public class CreatedDisputesService {
|
||||
}
|
||||
var providerData = providerDataService.getProviderData(dispute.getProviderId(), dispute.getTerminalId());
|
||||
var options = providerData.getOptions();
|
||||
if ((status.isSetCaptured() && isCapturedBlockedForDispute(options))
|
||||
if ((invoicePayment.getPayment().getStatus().isSetCaptured() && isCapturedBlockedForDispute(options))
|
||||
|| isNotProvidersDisputesApiExist(options)) {
|
||||
// отправлять на ручной разбор, если выставлена опция
|
||||
// DISPUTE_FLOW_CAPTURED_BLOCKED или не выставлена DISPUTE_FLOW_PROVIDERS_API_EXIST
|
@ -1,4 +1,4 @@
|
||||
package dev.vality.disputes.schedule.service;
|
||||
package dev.vality.disputes.schedule.core;
|
||||
|
||||
import dev.vality.disputes.dao.DisputeDao;
|
||||
import dev.vality.disputes.dao.ProviderDisputeDao;
|
||||
@ -10,6 +10,7 @@ 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.handler.DisputeStatusResultHandler;
|
||||
import dev.vality.disputes.schedule.service.ProviderDataService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
@ -1,7 +1,7 @@
|
||||
package dev.vality.disputes.schedule.handler;
|
||||
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.service.CreateAdjustmentsService;
|
||||
import dev.vality.disputes.schedule.core.AdjustmentsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ -9,16 +9,16 @@ import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class CreateAdjustmentHandler {
|
||||
public class AdjustmentHandler {
|
||||
|
||||
private final CreateAdjustmentsService createAdjustmentsService;
|
||||
private final AdjustmentsService adjustmentsService;
|
||||
|
||||
public UUID handle(Dispute dispute) {
|
||||
final var currentThread = Thread.currentThread();
|
||||
final var oldName = currentThread.getName();
|
||||
currentThread.setName("dispute-created-adjustment-id-" + dispute.getId() + "-" + oldName);
|
||||
try {
|
||||
createAdjustmentsService.callHgForCreateAdjustment(dispute);
|
||||
adjustmentsService.callHgForCreateAdjustment(dispute);
|
||||
return dispute.getId();
|
||||
} catch (Throwable ex) {
|
||||
log.error("Received exception while scheduler processed callHgForCreateAdjustment", ex);
|
@ -1,7 +1,7 @@
|
||||
package dev.vality.disputes.schedule.handler;
|
||||
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.service.CreatedDisputesService;
|
||||
import dev.vality.disputes.schedule.core.CreatedDisputesService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
@ -58,7 +58,7 @@ public class DisputeStatusResultHandler {
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public void handleStatusSuccess(Dispute dispute, DisputeStatusResult result) {
|
||||
callbackNotifier.sendDisputeReadyForCreateAdjustment(List.of(dispute));
|
||||
callbackNotifier.sendDisputesReadyForCreateAdjustment(List.of(dispute));
|
||||
mdcTopicProducer.sendReadyForCreateAdjustments(List.of(dispute));
|
||||
var changedAmount = result.getStatusSuccess().getChangedAmount().orElse(null);
|
||||
log.info("Trying to set create_adjustment Dispute status {}, {}", dispute, result);
|
||||
|
@ -1,7 +1,7 @@
|
||||
package dev.vality.disputes.schedule.handler;
|
||||
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import dev.vality.disputes.schedule.service.PendingDisputesService;
|
||||
import dev.vality.disputes.schedule.core.PendingDisputesService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
package dev.vality.disputes.schedule.service;
|
||||
|
||||
import dev.vality.damsel.domain.Cash;
|
||||
import dev.vality.damsel.domain.InvoicePaymentAdjustment;
|
||||
import dev.vality.damsel.domain.InvoicePaymentStatus;
|
||||
import dev.vality.damsel.payment_processing.InvoicePayment;
|
||||
import dev.vality.disputes.domain.tables.pojos.Dispute;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -13,36 +12,37 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static dev.vality.disputes.schedule.converter.InvoicePaymentAdjustmentParamsConverter.DISPUTE_MASK;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@SuppressWarnings({"ParameterName", "LineLength"})
|
||||
public class AdjustmentExtractor {
|
||||
|
||||
public Optional<InvoicePaymentAdjustment> searchAdjustmentByDispute(InvoicePayment invoicePayment, Dispute dispute) {
|
||||
return getInvoicePaymentAdjustmentStream(invoicePayment)
|
||||
.filter(adj -> adj.getReason() != null)
|
||||
.filter(adj -> isDisputesAdjustment(adj.getReason(), dispute))
|
||||
.findFirst()
|
||||
.or(() -> getInvoicePaymentAdjustmentStream(invoicePayment)
|
||||
.filter(s -> s.getState() != null)
|
||||
.filter(s -> s.getState().isSetStatusChange())
|
||||
.filter(s -> getTargetStatus(s).isSetCaptured())
|
||||
.filter(s -> getTargetStatus(s).getCaptured().getReason() != null)
|
||||
.filter(s -> isDisputesAdjustment(getTargetStatus(s).getCaptured().getReason(), dispute))
|
||||
.findFirst());
|
||||
public static final String DISPUTE_MASK = "disputeId=%s";
|
||||
|
||||
public String getReason(Dispute dispute) {
|
||||
return Optional.ofNullable(dispute.getReason())
|
||||
.map(s -> String.format(DISPUTE_MASK + ", reason=%s", dispute.getId(), s))
|
||||
.orElse(String.format(DISPUTE_MASK, dispute.getId()));
|
||||
}
|
||||
|
||||
public Long getChangedAmount(@Nonnull InvoicePaymentAdjustment invoicePaymentAdjustment, Long changedAmount) {
|
||||
return Optional.of(invoicePaymentAdjustment)
|
||||
.map(s -> getTargetStatus(s).getCaptured().getCost())
|
||||
.map(Cash::getAmount)
|
||||
.or(() -> Optional.ofNullable(changedAmount))
|
||||
.orElse(null);
|
||||
public boolean isCashFlowAdjustmentByDisputeExist(InvoicePayment invoicePayment, Dispute dispute) {
|
||||
return getInvoicePaymentAdjustmentStream(invoicePayment)
|
||||
.filter(adj -> isDisputesAdjustment(adj.getReason(), dispute))
|
||||
.anyMatch(adj -> adj.getState() != null && adj.getState().isSetCashFlow());
|
||||
}
|
||||
|
||||
public boolean isCapturedAdjustmentByDisputeExist(InvoicePayment invoicePayment, Dispute dispute) {
|
||||
return getInvoicePaymentAdjustmentStream(invoicePayment)
|
||||
.filter(adj -> isDisputesAdjustment(adj.getReason(), dispute))
|
||||
.filter(adj -> adj.getState() != null && adj.getState().isSetStatusChange())
|
||||
.filter(adj -> getTargetStatus(adj).isSetCaptured())
|
||||
.anyMatch(adj -> isDisputesAdjustment(getTargetStatus(adj).getCaptured().getReason(), dispute));
|
||||
}
|
||||
|
||||
private Stream<InvoicePaymentAdjustment> getInvoicePaymentAdjustmentStream(InvoicePayment invoicePayment) {
|
||||
return Optional.ofNullable(invoicePayment.getAdjustments()).orElse(List.of()).stream();
|
||||
return Optional.ofNullable(invoicePayment.getAdjustments())
|
||||
.orElse(List.of())
|
||||
.stream();
|
||||
}
|
||||
|
||||
private InvoicePaymentStatus getTargetStatus(InvoicePaymentAdjustment s) {
|
||||
@ -50,6 +50,7 @@ public class AdjustmentExtractor {
|
||||
}
|
||||
|
||||
private boolean isDisputesAdjustment(String reason, Dispute dispute) {
|
||||
return !StringUtils.isBlank(reason) && reason.contains(String.format(DISPUTE_MASK, dispute.getId()));
|
||||
return !StringUtils.isBlank(reason)
|
||||
&& reason.equalsIgnoreCase(getReason(dispute));
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import java.util.List;
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class CreatedAttachmentsService {
|
||||
public class AttachmentsService {
|
||||
|
||||
private final FileMetaDao fileMetaDao;
|
||||
private final FileStorageService fileStorageService;
|
@ -3,6 +3,7 @@ package dev.vality.disputes.security;
|
||||
import dev.vality.damsel.payment_processing.InvoicePayment;
|
||||
import dev.vality.disputes.exception.AuthorizationException;
|
||||
import dev.vality.disputes.exception.BouncerException;
|
||||
import dev.vality.disputes.exception.InvoicingPaymentStatusPendingException;
|
||||
import dev.vality.disputes.exception.NotFoundException;
|
||||
import dev.vality.disputes.security.service.BouncerService;
|
||||
import dev.vality.disputes.security.service.TokenKeeperService;
|
||||
@ -93,12 +94,17 @@ public class AccessService {
|
||||
|
||||
private InvoicePayment getInvoicePayment(dev.vality.damsel.payment_processing.Invoice invoice, String paymentId) {
|
||||
log.debug("Processing invoice: {}", invoice.getInvoice().getId());
|
||||
return invoice.getPayments().stream()
|
||||
.filter(invoicePayment -> paymentId.equals(invoicePayment.getPayment().getId())
|
||||
&& invoicePayment.isSetRoute())
|
||||
var invoicePayment = invoice.getPayments().stream()
|
||||
.filter(p -> paymentId.equals(p.getPayment().getId()) && p.isSetRoute())
|
||||
.findFirst()
|
||||
// http 404
|
||||
.orElseThrow(() -> new NotFoundException(
|
||||
String.format("Payment with id: %s and filled route not found!", paymentId)));
|
||||
String.format("Payment with id: %s and filled route and status not found!", paymentId)));
|
||||
log.debug("Processing payment: {}", invoicePayment);
|
||||
var status = invoicePayment.getPayment().getStatus();
|
||||
if (!status.isSetCaptured() && !status.isSetCancelled() && !status.isSetFailed()) {
|
||||
throw new InvoicingPaymentStatusPendingException();
|
||||
}
|
||||
return invoicePayment;
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public interface DisputesTgBotService {
|
||||
|
||||
void sendDisputePoolingExpired(DisputePoolingExpired disputePoolingExpired);
|
||||
|
||||
void sendDisputeReadyForCreateAdjustment(List<DisputeReadyForCreateAdjustment> disputeReadyForCreateAdjustments);
|
||||
void sendDisputesReadyForCreateAdjustment(List<DisputeReadyForCreateAdjustment> disputeReadyForCreateAdjustments);
|
||||
|
||||
void sendDisputeFailedReviewRequired(DisputeFailedReviewRequired disputeFailedReviewRequired);
|
||||
|
||||
|
@ -51,13 +51,13 @@ public class DisputesTgBotServiceImpl implements DisputesTgBotService {
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void sendDisputeReadyForCreateAdjustment(List<DisputeReadyForCreateAdjustment> disputeReadyForCreateAdjustments) {
|
||||
var ids = disputeReadyForCreateAdjustments.stream()
|
||||
public void sendDisputesReadyForCreateAdjustment(List<DisputeReadyForCreateAdjustment> disputesReadyForCreateAdjustments) {
|
||||
var ids = disputesReadyForCreateAdjustments.stream()
|
||||
.map(DisputeReadyForCreateAdjustment::getId)
|
||||
.map(String::valueOf)
|
||||
.collect(Collectors.joining(", "));
|
||||
log.debug("Trying to call adminCallbackDisputesTgBotClient.sendDisputeReadyForCreateAdjustment() {}", ids);
|
||||
var notifications = disputeReadyForCreateAdjustments.stream()
|
||||
var notifications = disputesReadyForCreateAdjustments.stream()
|
||||
.map(Notification::disputeReadyForCreateAdjustment)
|
||||
.collect(Collectors.toList());
|
||||
adminCallbackDisputesTgBotClient.notify(new NotificationParamsRequest(notifications));
|
||||
|
@ -7,7 +7,8 @@ import dev.vality.disputes.config.WireMockSpringBootITest;
|
||||
import dev.vality.disputes.constant.ErrorReason;
|
||||
import dev.vality.disputes.dao.DisputeDao;
|
||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||
import dev.vality.disputes.schedule.converter.InvoicePaymentAdjustmentParamsConverter;
|
||||
import dev.vality.disputes.schedule.converter.InvoicePaymentCapturedAdjustmentParamsConverter;
|
||||
import dev.vality.disputes.schedule.core.AdjustmentsService;
|
||||
import dev.vality.disputes.schedule.service.config.DisputeApiTestService;
|
||||
import dev.vality.disputes.schedule.service.config.PendingDisputesTestService;
|
||||
import dev.vality.disputes.util.MockUtil;
|
||||
@ -19,7 +20,8 @@ import org.springframework.context.annotation.Import;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static dev.vality.disputes.util.MockUtil.getInvoicePaymentAdjustment;
|
||||
import static dev.vality.disputes.util.MockUtil.getCapturedInvoicePaymentAdjustment;
|
||||
import static dev.vality.disputes.util.MockUtil.getCashFlowInvoicePaymentAdjustment;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
@ -27,20 +29,22 @@ import static org.mockito.Mockito.when;
|
||||
@WireMockSpringBootITest
|
||||
@Import({PendingDisputesTestService.class})
|
||||
@SuppressWarnings({"ParameterName", "LineLength"})
|
||||
public class CreateAdjustmentsServiceTest {
|
||||
public class AdjustmentsServiceTest {
|
||||
|
||||
@Autowired
|
||||
private InvoicingSrv.Iface invoicingClient;
|
||||
@Autowired
|
||||
private DisputeDao disputeDao;
|
||||
@Autowired
|
||||
private CreateAdjustmentsService createAdjustmentsService;
|
||||
private AdjustmentsService adjustmentsService;
|
||||
@Autowired
|
||||
private DisputeApiTestService disputeApiTestService;
|
||||
@Autowired
|
||||
private PendingDisputesTestService pendingDisputesTestService;
|
||||
@Autowired
|
||||
private InvoicePaymentAdjustmentParamsConverter invoicePaymentAdjustmentParamsConverter;
|
||||
private InvoicePaymentCapturedAdjustmentParamsConverter invoicePaymentCapturedAdjustmentParamsConverter;
|
||||
@Autowired
|
||||
private AdjustmentExtractor adjustmentExtractor;
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
@ -50,40 +54,17 @@ public class CreateAdjustmentsServiceTest {
|
||||
var disputeId = UUID.fromString(disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId());
|
||||
disputeDao.update(disputeId, DisputeStatus.create_adjustment);
|
||||
var dispute = disputeDao.get(disputeId);
|
||||
createAdjustmentsService.callHgForCreateAdjustment(dispute.get());
|
||||
adjustmentsService.callHgForCreateAdjustment(dispute.get());
|
||||
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
||||
assertEquals(ErrorReason.PAYMENT_NOT_FOUND, disputeDao.get(disputeId).get().getErrorMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testDisputesAdjustmentExist() {
|
||||
var invoiceId = "20McecNnWoy";
|
||||
var paymentId = "1";
|
||||
var disputeId = UUID.fromString(disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId());
|
||||
disputeDao.update(disputeId, DisputeStatus.create_adjustment);
|
||||
var invoicePayment = MockUtil.createInvoicePayment(paymentId);
|
||||
invoicePayment.getPayment().setStatus(InvoicePaymentStatus.captured(new InvoicePaymentCaptured()));
|
||||
var dispute = disputeDao.get(disputeId);
|
||||
dispute.get().setReason("test adj");
|
||||
var adjustmentId = "adjustmentId";
|
||||
var invoicePaymentAdjustment = getInvoicePaymentAdjustment(adjustmentId, invoicePaymentAdjustmentParamsConverter.getReason(dispute.get()));
|
||||
invoicePayment.setAdjustments(List.of(invoicePaymentAdjustment));
|
||||
when(invoicingClient.getPayment(any(), any())).thenReturn(invoicePayment);
|
||||
createAdjustmentsService.callHgForCreateAdjustment(dispute.get());
|
||||
assertEquals(DisputeStatus.succeeded, disputeDao.get(disputeId).get().getStatus());
|
||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testInvoiceNotFound() {
|
||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||
var paymentId = "1";
|
||||
var invoicePayment = MockUtil.createInvoicePayment(paymentId);
|
||||
invoicePayment.getPayment().setStatus(InvoicePaymentStatus.captured(new InvoicePaymentCaptured()));
|
||||
var dispute = disputeDao.get(disputeId);
|
||||
createAdjustmentsService.callHgForCreateAdjustment(dispute.get());
|
||||
adjustmentsService.callHgForCreateAdjustment(dispute.get());
|
||||
assertEquals(DisputeStatus.failed, disputeDao.get(disputeId).get().getStatus());
|
||||
assertEquals(ErrorReason.INVOICE_NOT_FOUND, disputeDao.get(disputeId).get().getErrorMessage());
|
||||
}
|
||||
@ -92,16 +73,33 @@ public class CreateAdjustmentsServiceTest {
|
||||
@SneakyThrows
|
||||
public void testFullSuccessFlow() {
|
||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||
var paymentId = "1";
|
||||
var invoicePayment = MockUtil.createInvoicePayment(paymentId);
|
||||
invoicePayment.getPayment().setStatus(InvoicePaymentStatus.captured(new InvoicePaymentCaptured()));
|
||||
var dispute = disputeDao.get(disputeId);
|
||||
dispute.get().setReason("test adj");
|
||||
dispute.get().setChangedAmount(dispute.get().getAmount() + 1);
|
||||
var adjustmentId = "adjustmentId";
|
||||
var reason = invoicePaymentAdjustmentParamsConverter.getReason(dispute.get());
|
||||
var reason = adjustmentExtractor.getReason(dispute.get());
|
||||
when(invoicingClient.createPaymentAdjustment(any(), any(), any()))
|
||||
.thenReturn(getInvoicePaymentAdjustment(adjustmentId, reason));
|
||||
createAdjustmentsService.callHgForCreateAdjustment(dispute.get());
|
||||
.thenReturn(getCapturedInvoicePaymentAdjustment(adjustmentId, reason));
|
||||
adjustmentsService.callHgForCreateAdjustment(dispute.get());
|
||||
assertEquals(DisputeStatus.succeeded, disputeDao.get(disputeId).get().getStatus());
|
||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testDisputesAdjustmentExist() {
|
||||
var disputeId = pendingDisputesTestService.callPendingDisputeRemotely();
|
||||
var dispute = disputeDao.get(disputeId);
|
||||
dispute.get().setReason("test adj");
|
||||
dispute.get().setChangedAmount(dispute.get().getAmount() + 1);
|
||||
var adjustmentId = "adjustmentId";
|
||||
var invoicePayment = MockUtil.createInvoicePayment(dispute.get().getPaymentId());
|
||||
invoicePayment.getPayment().setStatus(InvoicePaymentStatus.captured(new InvoicePaymentCaptured()));
|
||||
invoicePayment.setAdjustments(List.of(
|
||||
getCapturedInvoicePaymentAdjustment(adjustmentId, adjustmentExtractor.getReason(dispute.get())),
|
||||
getCashFlowInvoicePaymentAdjustment(adjustmentId, adjustmentExtractor.getReason(dispute.get()))));
|
||||
when(invoicingClient.getPayment(any(), any())).thenReturn(invoicePayment);
|
||||
adjustmentsService.callHgForCreateAdjustment(dispute.get());
|
||||
assertEquals(DisputeStatus.succeeded, disputeDao.get(disputeId).get().getStatus());
|
||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||
}
|
@ -8,6 +8,7 @@ import dev.vality.disputes.constant.ErrorReason;
|
||||
import dev.vality.disputes.dao.DisputeDao;
|
||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
||||
import dev.vality.disputes.schedule.core.CreatedDisputesService;
|
||||
import dev.vality.disputes.schedule.service.config.CreatedDisputesTestService;
|
||||
import dev.vality.disputes.schedule.service.config.DisputeApiTestService;
|
||||
import dev.vality.disputes.schedule.service.config.WiremockAddressesHolder;
|
||||
@ -67,19 +68,6 @@ public class CreatedDisputesServiceTest {
|
||||
assertEquals(ErrorReason.PAYMENT_NOT_FOUND, disputeDao.get(disputeId).get().getErrorMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testSkipDisputeWhenPaymentNonFinalStatus() {
|
||||
var invoiceId = "20McecNnWoy";
|
||||
var paymentId = "1";
|
||||
var disputeId = UUID.fromString(disputeApiTestService.createDisputeViaApi(invoiceId, paymentId).getDisputeId());
|
||||
when(invoicingClient.getPayment(any(), any())).thenReturn(MockUtil.createInvoicePayment(paymentId));
|
||||
var dispute = disputeDao.get(disputeId);
|
||||
createdDisputesService.callCreateDisputeRemotely(dispute.get());
|
||||
assertEquals(DisputeStatus.created, disputeDao.get(disputeId).get().getStatus());
|
||||
disputeDao.update(disputeId, DisputeStatus.failed);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testNoAttachments() {
|
||||
|
@ -4,6 +4,7 @@ import dev.vality.disputes.config.WireMockSpringBootITest;
|
||||
import dev.vality.disputes.dao.DisputeDao;
|
||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
||||
import dev.vality.disputes.schedule.core.PendingDisputesService;
|
||||
import dev.vality.disputes.schedule.service.config.CreatedDisputesTestService;
|
||||
import dev.vality.disputes.schedule.service.config.DisputeApiTestService;
|
||||
import dev.vality.disputes.schedule.service.config.PendingDisputesTestService;
|
||||
|
@ -6,7 +6,7 @@ import dev.vality.damsel.payment_processing.InvoicingSrv;
|
||||
import dev.vality.disputes.dao.DisputeDao;
|
||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
||||
import dev.vality.disputes.schedule.service.CreatedDisputesService;
|
||||
import dev.vality.disputes.schedule.core.CreatedDisputesService;
|
||||
import dev.vality.disputes.schedule.service.ProviderIfaceBuilder;
|
||||
import dev.vality.disputes.service.external.DominantService;
|
||||
import dev.vality.disputes.util.MockUtil;
|
||||
|
@ -3,7 +3,7 @@ package dev.vality.disputes.schedule.service.config;
|
||||
import dev.vality.disputes.dao.DisputeDao;
|
||||
import dev.vality.disputes.domain.enums.DisputeStatus;
|
||||
import dev.vality.disputes.provider.ProviderDisputesServiceSrv;
|
||||
import dev.vality.disputes.schedule.service.PendingDisputesService;
|
||||
import dev.vality.disputes.schedule.core.PendingDisputesService;
|
||||
import dev.vality.disputes.schedule.service.ProviderIfaceBuilder;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -58,7 +58,9 @@ public class MockUtil {
|
||||
BankCard.class))))))
|
||||
.setCost(new Cash()
|
||||
.setCurrency(new CurrencyRef().setSymbolicCode("RUB")))
|
||||
.setStatus(InvoicePaymentStatus.pending(new InvoicePaymentPending())))
|
||||
.setStatus(InvoicePaymentStatus.failed(
|
||||
new InvoicePaymentFailed(OperationFailure.failure(
|
||||
new Failure("authorization_failed:unknown"))))))
|
||||
.setRoute(new PaymentRoute()
|
||||
.setProvider(DamselUtil.fillRequiredTBaseObject(new ProviderRef(), ProviderRef.class))
|
||||
.setTerminal(DamselUtil.fillRequiredTBaseObject(new TerminalRef(), TerminalRef.class)))
|
||||
@ -170,9 +172,10 @@ public class MockUtil {
|
||||
return DisputeStatusResult.statusPending(new DisputeStatusPendingResult());
|
||||
}
|
||||
|
||||
public static InvoicePaymentAdjustment getInvoicePaymentAdjustment(String adjustmentId, String reason) {
|
||||
public static InvoicePaymentAdjustment getCapturedInvoicePaymentAdjustment(String adjustmentId, String reason) {
|
||||
return new InvoicePaymentAdjustment()
|
||||
.setId(adjustmentId)
|
||||
.setReason(reason)
|
||||
.setState(InvoicePaymentAdjustmentState.status_change(new InvoicePaymentAdjustmentStatusChangeState()
|
||||
.setScenario(new InvoicePaymentAdjustmentStatusChange()
|
||||
.setTargetStatus(new InvoicePaymentStatus(InvoicePaymentStatus.captured(
|
||||
@ -180,6 +183,14 @@ public class MockUtil {
|
||||
.setReason(reason)))))));
|
||||
}
|
||||
|
||||
public static InvoicePaymentAdjustment getCashFlowInvoicePaymentAdjustment(String adjustmentId, String reason) {
|
||||
return new InvoicePaymentAdjustment()
|
||||
.setId(adjustmentId)
|
||||
.setReason(reason)
|
||||
.setState(InvoicePaymentAdjustmentState.cash_flow(new InvoicePaymentAdjustmentCashFlowState()
|
||||
.setScenario(new InvoicePaymentAdjustmentCashFlow().setNewAmount(10L))));
|
||||
}
|
||||
|
||||
public static Failure createFailure() {
|
||||
Failure failure = new Failure("some_error");
|
||||
failure.setSub(new SubFailure("some_suberror"));
|
||||
|
Loading…
Reference in New Issue
Block a user