Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PP-12360 Refactor more submit refund code to improve readability #5472

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 96 additions & 40 deletions src/main/java/uk/gov/pay/connector/refund/service/RefundService.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,50 @@ public ChargeRefundResponse submitRefund(GatewayAccountEntity gatewayAccountEnti
GatewayAccountCredentialsEntity gatewayAccountCredentialsEntity = gatewayAccountCredentialsService.findCredentialFromCharge(charge, gatewayAccountEntity)
.orElseThrow(() -> new GatewayAccountCredentialsNotFoundException("Unable to find gateway account credentials to use to refund charge."));

RefundEntity refundEntity = createRefund(charge, gatewayAccountEntity, refundRequest);
List<Refund> existingRefunds = findRefunds(charge);
ExternalChargeRefundAvailability refundAvailability = providers
.byName(PaymentGatewayName.valueFrom(charge.getPaymentGatewayName()))
.getExternalChargeRefundAvailability(charge, existingRefunds);

if (isRefundUnavailableDueToDispute(charge, refundAvailability)) {
throw RefundException.unavailableDueToChargeDisputed();
}

if (refundAvailability != EXTERNAL_AVAILABLE) {
logger.warn("Charge not available for refund - charge_external_id={}, status={}, refund_status={}, account_id={}, operation_type=Refund, provider={}, provider_type={}",
charge.getExternalId(),
charge.getExternalStatus(),
refundAvailability,
gatewayAccountEntity.getId(),
charge.getPaymentGatewayName(),
gatewayAccountEntity.getType());

throw RefundException.notAvailableForRefundException(charge.getExternalId(), refundAvailability);
}

long availableAmount = calculateAmountAvailableToRefund(charge, existingRefunds);

if (availableAmount != refundRequest.getAmountAvailableForRefund()) {
logger.info("Refund request has a mismatch on amount available for refund - charge_external_id={}, amount_actually_available_for_refund={}, refund_amount_available_in_request={}",
charge.getExternalId(), availableAmount, refundRequest.getAmountAvailableForRefund());
throw RefundException.refundAmountAvailableMismatchException("Refund Amount Available Mismatch");
}

if (availableAmount - refundRequest.getAmount() < 0) {
logger.info("Charge doesn't have sufficient amount for refund - charge_external_id={}, status={}, refund_status={}, account_id={}, operation_type=Refund, provider={}, provider_type={}, amount_available_refund={}, amount_requested_refund={}",
charge.getExternalId(),
charge.getExternalStatus(),
refundAvailability,
gatewayAccountEntity.getId(),
charge.getPaymentGatewayName(),
gatewayAccountEntity.getType(),
availableAmount,
refundRequest.getAmount());

throw RefundException.notAvailableForRefundException("Not sufficient amount available for refund", NOT_SUFFICIENT_AMOUNT_AVAILABLE);
}

RefundEntity refundEntity = createRefundEntity(refundRequest, gatewayAccountEntity, charge);

GatewayRefundResponse gatewayRefundResponse = providers
.byName(PaymentGatewayName.valueFrom(charge.getPaymentGatewayName()))
Expand All @@ -109,27 +152,27 @@ public ChargeRefundResponse submitRefund(GatewayAccountEntity gatewayAccountEnti
return new ChargeRefundResponse(gatewayRefundResponse, updatedRefundEntity);
}

@Transactional
@SuppressWarnings("WeakerAccess")
public RefundEntity createRefund(Charge charge, GatewayAccountEntity gatewayAccountEntity, RefundRequest refundRequest) {
List<Refund> refundList = findRefunds(charge);
long availableAmount = validateRefundAndGetAvailableAmount(charge, gatewayAccountEntity, refundRequest, refundList);
RefundEntity refundEntity = createRefundEntity(refundRequest, gatewayAccountEntity, charge);

logger.info("Card refund request sent - charge_external_id={}, status={}, amount={}, transaction_id={}, account_id={}, operation_type=Refund, amount_available_refund={}, amount_requested_refund={}, provider={}, provider_type={}, user_external_id={}",
charge.getExternalId(),
charge.getExternalStatus(),
charge.getAmount(),
charge.getGatewayTransactionId(),
gatewayAccountEntity.getId(),
availableAmount,
refundRequest.getAmount(),
charge.getPaymentGatewayName(),
gatewayAccountEntity.getType(),
refundRequest.getUserExternalId());

return refundEntity;
}
// @Transactional
// @SuppressWarnings("WeakerAccess")
// public RefundEntity createRefund(Charge charge, GatewayAccountEntity gatewayAccountEntity, RefundRequest refundRequest) {
// List<Refund> refundList = findRefunds(charge);
// long availableAmount = validateRefundAndGetAvailableAmount(charge, gatewayAccountEntity, refundRequest, refundList);
// RefundEntity refundEntity = createRefundEntity(refundRequest, gatewayAccountEntity, charge);
//
// logger.info("Card refund request sent - charge_external_id={}, status={}, amount={}, transaction_id={}, account_id={}, operation_type=Refund, amount_available_refund={}, amount_requested_refund={}, provider={}, provider_type={}, user_external_id={}",
// charge.getExternalId(),
// charge.getExternalStatus(),
// charge.getAmount(),
// charge.getGatewayTransactionId(),
// gatewayAccountEntity.getId(),
// availableAmount,
// refundRequest.getAmount(),
// charge.getPaymentGatewayName(),
// gatewayAccountEntity.getType(),
// refundRequest.getUserExternalId());
//
// return refundEntity;
// }

public Optional<RefundEntity> findByChargeExternalIdAndGatewayTransactionId(String chargeExternalId, String gatewayTransactionId) {
return refundDao.findByChargeExternalIdAndGatewayTransactionId(chargeExternalId, gatewayTransactionId);
Expand Down Expand Up @@ -250,6 +293,10 @@ private void checkIfChargeIsRefundableOrTerminate(Charge reloadedCharge, Externa
throw RefundException.notAvailableForRefundException(reloadedCharge.getExternalId(), refundAvailability);
}
}

private boolean isRefundUnavailableDueToDispute(Charge charge, ExternalChargeRefundAvailability refundAvailability) {
return refundAvailability == EXTERNAL_UNAVAILABLE && charge.getDisputed() != null && charge.getDisputed().equals(Boolean.TRUE);
}

/**
* <p>Worldpay -> Worldpay doesn't return reference. We use our externalId because that's what we sent in the
Expand All @@ -268,28 +315,37 @@ private Optional<String> getTransactionId(RefundEntity refundEntity, GatewayRefu
} else return Optional.empty();
}

private long validateRefundAndGetAvailableAmount(Charge charge,
GatewayAccountEntity gatewayAccountEntity,
RefundRequest refundRequest,
List<Refund> refundList) {
ExternalChargeRefundAvailability refundAvailability;

refundAvailability = providers
.byName(PaymentGatewayName.valueFrom(charge.getPaymentGatewayName()))
.getExternalChargeRefundAvailability(charge, refundList);
checkIfChargeIsRefundableOrTerminate(charge, refundAvailability, gatewayAccountEntity);

// private long validateRefundAndGetAvailableAmount(Charge charge,
// GatewayAccountEntity gatewayAccountEntity,
// RefundRequest refundRequest,
// List<Refund> refundList) {
// ExternalChargeRefundAvailability refundAvailability;
//
// refundAvailability = providers
// .byName(PaymentGatewayName.valueFrom(charge.getPaymentGatewayName()))
// .getExternalChargeRefundAvailability(charge, refundList);
// checkIfChargeIsRefundableOrTerminate(charge, refundAvailability, gatewayAccountEntity);
//
// // We re-check the database for any newly created refunds that could have been made when we were making the
// // network request to find the external refund-ability
// List<Refund> updatedRefunds = checkForNewRefunds(charge, refundList);
//
// long availableToBeRefunded = getTotalAmountAvailableToBeRefunded(charge, updatedRefunds);
// checkIfRefundRequestIsInConflictOrTerminate(refundRequest, charge, availableToBeRefunded);
//
// checkIfRefundAmountWithinLimitOrTerminate(refundRequest, charge, refundAvailability,
// gatewayAccountEntity, availableToBeRefunded);
//
// return availableToBeRefunded;
// }

private long calculateAmountAvailableToRefund(Charge charge,
List<Refund> refundList) {
// We re-check the database for any newly created refunds that could have been made when we were making the
// network request to find the external refund-ability
List<Refund> updatedRefunds = checkForNewRefunds(charge, refundList);

long availableToBeRefunded = getTotalAmountAvailableToBeRefunded(charge, updatedRefunds);
checkIfRefundRequestIsInConflictOrTerminate(refundRequest, charge, availableToBeRefunded);

checkIfRefundAmountWithinLimitOrTerminate(refundRequest, charge, refundAvailability,
gatewayAccountEntity, availableToBeRefunded);

return availableToBeRefunded;
return getTotalAmountAvailableToBeRefunded(charge, updatedRefunds);
}

private List<Refund> checkForNewRefunds(Charge charge, List<Refund> refundList) {
Expand Down
Loading