카드 매입 승인 경로 Spring Boot 3 전환 (ACX-E2E-1785394564819)
This commit is contained in:
parent
52dee34ff3
commit
ec34b302cf
1 changed files with 118 additions and 0 deletions
|
|
@ -0,0 +1,118 @@
|
||||||
|
package com.acquirex.approval.service;
|
||||||
|
|
||||||
|
import com.acquirex.approval.domain.ApprovalStatus;
|
||||||
|
import com.acquirex.approval.domain.CardAcquisitionApproval;
|
||||||
|
import com.acquirex.approval.dto.ApprovalRequest;
|
||||||
|
import com.acquirex.approval.dto.ApprovalResponse;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for card acquisition approval processing.
|
||||||
|
* Migrated to Spring Boot 3 with Jakarta EE 9+ compatibility.
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class CardAcquisitionApprovalService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CardAcquisitionApprovalService.class);
|
||||||
|
private static final BigDecimal MAX_APPROVAL_AMOUNT = new BigDecimal("1000000.00");
|
||||||
|
private static final BigDecimal HIGH_RISK_THRESHOLD = new BigDecimal("500000.00");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a card acquisition approval request.
|
||||||
|
* @param request the approval request
|
||||||
|
* @return the approval response
|
||||||
|
*/
|
||||||
|
public ApprovalResponse processApproval(ApprovalRequest request) {
|
||||||
|
log.info("Processing approval request: {}", request.getRequestId());
|
||||||
|
validateRequest(request);
|
||||||
|
ApprovalStatus status = determineApprovalStatus(request.getAmount());
|
||||||
|
String approvedBy = determineApprover(status);
|
||||||
|
CardAcquisitionApproval approval = createApproval(request, status, approvedBy);
|
||||||
|
log.info("Approval processed: requestId={}, status={}, amount={}",
|
||||||
|
request.getRequestId(), status, request.getAmount());
|
||||||
|
return buildResponse(approval, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the approval request.
|
||||||
|
* @param request the request to validate
|
||||||
|
* @throws IllegalArgumentException if validation fails
|
||||||
|
*/
|
||||||
|
void validateRequest(ApprovalRequest request) {
|
||||||
|
if (request.getCardNumber() == null || request.getCardNumber().length() < 13) {
|
||||||
|
throw new IllegalArgumentException("Invalid card number format");
|
||||||
|
}
|
||||||
|
if (request.getMerchantId() == null || request.getMerchantId().isBlank()) {
|
||||||
|
throw new IllegalArgumentException("Merchant ID is required");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine approval status based on amount.
|
||||||
|
* @param amount the transaction amount
|
||||||
|
* @return the determined status
|
||||||
|
*/
|
||||||
|
ApprovalStatus determineApprovalStatus(BigDecimal amount) {
|
||||||
|
if (amount.compareTo(MAX_APPROVAL_AMOUNT) > 0) return ApprovalStatus.REJECTED;
|
||||||
|
if (amount.compareTo(HIGH_RISK_THRESHOLD) > 0) return ApprovalStatus.PENDING;
|
||||||
|
return ApprovalStatus.APPROVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the approver based on status.
|
||||||
|
* @param status the approval status
|
||||||
|
* @return the approver identifier
|
||||||
|
*/
|
||||||
|
String determineApprover(ApprovalStatus status) {
|
||||||
|
return switch (status) {
|
||||||
|
case APPROVED, REJECTED -> "SYSTEM";
|
||||||
|
case PENDING -> "MANUAL_REVIEW";
|
||||||
|
case CANCELLED -> "CANCELLED";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the approval record.
|
||||||
|
*/
|
||||||
|
CardAcquisitionApproval createApproval(ApprovalRequest request, ApprovalStatus status, String approvedBy) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
return new CardAcquisitionApproval(
|
||||||
|
generateId(), request.getRequestId(), maskCardNumber(request.getCardNumber()),
|
||||||
|
request.getMerchantId(), request.getAmount(), status, now, now, approvedBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the approval response.
|
||||||
|
*/
|
||||||
|
ApprovalResponse buildResponse(CardAcquisitionApproval approval, ApprovalStatus status) {
|
||||||
|
String message = switch (status) {
|
||||||
|
case APPROVED -> "Card acquisition approved successfully";
|
||||||
|
case REJECTED -> "Card acquisition rejected: amount exceeds limit";
|
||||||
|
case PENDING -> "Card acquisition pending manual review";
|
||||||
|
case CANCELLED -> "Card acquisition cancelled";
|
||||||
|
};
|
||||||
|
return new ApprovalResponse(approval.getId(), approval.getRequestId(), status,
|
||||||
|
approval.getAmount(), approval.getUpdatedAt(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mask card number for logging/security.
|
||||||
|
*/
|
||||||
|
String maskCardNumber(String cardNumber) {
|
||||||
|
if (cardNumber == null || cardNumber.length() < 4) return "****";
|
||||||
|
return "****-****-****-" + cardNumber.substring(cardNumber.length() - 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate unique ID for approval records.
|
||||||
|
*/
|
||||||
|
Long generateId() {
|
||||||
|
return UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue