카드 매입 승인 경로 Spring Boot 3 전환 #14

Merged
forge-bot merged 8 commits from forge/ACX-E2E-1785394564819-attempt-15-run-1519df48912e into main 2026-07-30 14:15:50 +00:00
Showing only changes of commit 1b88ac69fc - Show all commits

View file

@ -0,0 +1,86 @@
package com.acquirex.approval;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
/**
* 카드 매입 서비스 + 리포지토리.
* Spring Boot 3 전환: jakarta.transaction.Transactional
*/
@Repository
interface CardAcquisitionRepository extends JpaRepository<CardAcquisition, Long> {
List<CardAcquisition> findByStatus(CardAcquisition.ApprovalStatus status);
List<CardAcquisition> findByMerchantId(String merchantId);
}
@Service
@Transactional
public class CardAcquisitionService {
private final CardAcquisitionRepository repository;
public CardAcquisitionService(CardAcquisitionRepository repository) {
this.repository = repository;
}
public CardAcquisition createAcquisition(String cardNumber, String merchantId, BigDecimal amount) {
validateAmount(amount);
CardAcquisition acquisition = new CardAcquisition(cardNumber, merchantId, amount);
return repository.save(acquisition);
}
@Transactional(readOnly = true)
public Optional<CardAcquisition> findById(Long id) {
return repository.findById(id);
}
@Transactional(readOnly = true)
public List<CardAcquisition> findAll() {
return repository.findAll();
}
@Transactional(readOnly = true)
public List<CardAcquisition> findByStatus(CardAcquisition.ApprovalStatus status) {
return repository.findByStatus(status);
}
public CardAcquisition approve(Long id, String approver) {
CardAcquisition acquisition = repository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("매입 요청을 찾을 수 없습니다: " + id));
if (acquisition.getStatus() != CardAcquisition.ApprovalStatus.PENDING) {
throw new IllegalStateException("대기 상태의 요청만 승인할 수 있습니다.");
}
acquisition.approve(approver);
return repository.save(acquisition);
}
public CardAcquisition reject(Long id, String reason) {
CardAcquisition acquisition = repository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("매입 요청을 찾을 수 없습니다: " + id));
if (acquisition.getStatus() != CardAcquisition.ApprovalStatus.PENDING) {
throw new IllegalStateException("대기 상태의 요청만 거절할 수 있습니다.");
}
acquisition.reject(reason);
return repository.save(acquisition);
}
public CardAcquisition cancel(Long id) {
CardAcquisition acquisition = repository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("매입 요청을 찾을 수 없습니다: " + id));
if (acquisition.getStatus() == CardAcquisition.ApprovalStatus.APPROVED) {
throw new IllegalStateException("이미 승인된 요청은 취소할 수 없습니다.");
}
acquisition.cancel();
return repository.save(acquisition);
}
private void validateAmount(BigDecimal amount) {
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("매입 금액은 0보다 커야 합니다.");
}
}
}