diff --git a/src/main/java/com/sb/web/account/dto/RepaymentRequest.java b/src/main/java/com/sb/web/account/dto/RepaymentRequest.java index bd984e9..4f9d971 100644 --- a/src/main/java/com/sb/web/account/dto/RepaymentRequest.java +++ b/src/main/java/com/sb/web/account/dto/RepaymentRequest.java @@ -8,7 +8,7 @@ import lombok.Data; import java.time.LocalDate; /** - * 대출/카드 상환·납부 요청. 원금은 이체, 이자는 지출로 분리 생성된다. + * 대출/카드 상환·납부 요청. 원금은 이체, 이자·연회비는 지출로 분리 생성된다. */ @Data public class RepaymentRequest { @@ -28,6 +28,9 @@ public class RepaymentRequest { @PositiveOrZero(message = "이자는 0 이상이어야 합니다.") private Long interest; + @PositiveOrZero(message = "연회비는 0 이상이어야 합니다.") + private Long annualFee; + @Size(max = 255, message = "메모는 255자 이내여야 합니다.") private String memo; } diff --git a/src/main/java/com/sb/web/account/service/AccountService.java b/src/main/java/com/sb/web/account/service/AccountService.java index 6763adf..90fcd09 100644 --- a/src/main/java/com/sb/web/account/service/AccountService.java +++ b/src/main/java/com/sb/web/account/service/AccountService.java @@ -292,13 +292,14 @@ public class AccountService { /* ===================== 상환/납부 ===================== */ - /** 대출/카드 상환·납부: 원금은 이체(부채↓), 이자는 지출로 분리해 2건 생성 */ + /** 대출/카드 상환·납부: 원금은 이체(부채↓), 이자·연회비는 지출로 분리 생성 */ @Transactional public void repay(RepaymentRequest req, Long memberId) { long principal = req.getPrincipal() != null ? req.getPrincipal() : 0L; long interest = req.getInterest() != null ? req.getInterest() : 0L; - if (principal <= 0 && interest <= 0) { - throw new ApiException(HttpStatus.BAD_REQUEST, "원금 또는 이자를 입력하세요."); + long annualFee = req.getAnnualFee() != null ? req.getAnnualFee() : 0L; + if (principal <= 0 && interest <= 0 && annualFee <= 0) { + throw new ApiException(HttpStatus.BAD_REQUEST, "원금·이자·연회비 중 하나는 입력하세요."); } requireOwnedWallet(req.getFromWalletId(), memberId); Wallet target = walletMapper.findByIdAndMember(req.getTargetWalletId(), memberId); @@ -308,6 +309,9 @@ public class AccountService { if (!"LOAN".equals(target.getType()) && !"CARD".equals(target.getType())) { throw new ApiException(HttpStatus.BAD_REQUEST, "상환 대상은 대출/카드만 가능합니다."); } + if (annualFee > 0 && !"CARD".equals(target.getType())) { + throw new ApiException(HttpStatus.BAD_REQUEST, "연회비는 카드 상환에만 입력할 수 있습니다."); + } if (req.getFromWalletId().equals(req.getTargetWalletId())) { throw new ApiException(HttpStatus.BAD_REQUEST, "출금/대상 계좌가 같을 수 없습니다."); } @@ -336,6 +340,18 @@ public class AccountService { .memo(req.getMemo() != null ? req.getMemo() : "이자") .build()); } + // 연회비: 지출 (카드, 출금 계좌에서, 분류=연회비) + if (annualFee > 0) { + mapper.insert(AccountEntry.builder() + .memberId(memberId) + .entryDate(req.getEntryDate()) + .type("EXPENSE") + .category("연회비") + .amount(annualFee) + .walletId(req.getFromWalletId()) + .memo(req.getMemo() != null ? req.getMemo() : "연회비") + .build()); + } } /* ===================== 계좌/카드 (사용자별) ===================== */