Merge branch 'dev'
This commit is contained in:
@@ -8,7 +8,7 @@ import lombok.Data;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 대출/카드 상환·납부 요청. 원금은 이체, 이자는 지출로 분리 생성된다.
|
* 대출/카드 상환·납부 요청. 원금은 이체, 이자·연회비는 지출로 분리 생성된다.
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class RepaymentRequest {
|
public class RepaymentRequest {
|
||||||
@@ -28,6 +28,9 @@ public class RepaymentRequest {
|
|||||||
@PositiveOrZero(message = "이자는 0 이상이어야 합니다.")
|
@PositiveOrZero(message = "이자는 0 이상이어야 합니다.")
|
||||||
private Long interest;
|
private Long interest;
|
||||||
|
|
||||||
|
@PositiveOrZero(message = "연회비는 0 이상이어야 합니다.")
|
||||||
|
private Long annualFee;
|
||||||
|
|
||||||
@Size(max = 255, message = "메모는 255자 이내여야 합니다.")
|
@Size(max = 255, message = "메모는 255자 이내여야 합니다.")
|
||||||
private String memo;
|
private String memo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,13 +292,14 @@ public class AccountService {
|
|||||||
|
|
||||||
/* ===================== 상환/납부 ===================== */
|
/* ===================== 상환/납부 ===================== */
|
||||||
|
|
||||||
/** 대출/카드 상환·납부: 원금은 이체(부채↓), 이자는 지출로 분리해 2건 생성 */
|
/** 대출/카드 상환·납부: 원금은 이체(부채↓), 이자·연회비는 지출로 분리 생성 */
|
||||||
@Transactional
|
@Transactional
|
||||||
public void repay(RepaymentRequest req, Long memberId) {
|
public void repay(RepaymentRequest req, Long memberId) {
|
||||||
long principal = req.getPrincipal() != null ? req.getPrincipal() : 0L;
|
long principal = req.getPrincipal() != null ? req.getPrincipal() : 0L;
|
||||||
long interest = req.getInterest() != null ? req.getInterest() : 0L;
|
long interest = req.getInterest() != null ? req.getInterest() : 0L;
|
||||||
if (principal <= 0 && interest <= 0) {
|
long annualFee = req.getAnnualFee() != null ? req.getAnnualFee() : 0L;
|
||||||
throw new ApiException(HttpStatus.BAD_REQUEST, "원금 또는 이자를 입력하세요.");
|
if (principal <= 0 && interest <= 0 && annualFee <= 0) {
|
||||||
|
throw new ApiException(HttpStatus.BAD_REQUEST, "원금·이자·연회비 중 하나는 입력하세요.");
|
||||||
}
|
}
|
||||||
requireOwnedWallet(req.getFromWalletId(), memberId);
|
requireOwnedWallet(req.getFromWalletId(), memberId);
|
||||||
Wallet target = walletMapper.findByIdAndMember(req.getTargetWalletId(), memberId);
|
Wallet target = walletMapper.findByIdAndMember(req.getTargetWalletId(), memberId);
|
||||||
@@ -308,6 +309,9 @@ public class AccountService {
|
|||||||
if (!"LOAN".equals(target.getType()) && !"CARD".equals(target.getType())) {
|
if (!"LOAN".equals(target.getType()) && !"CARD".equals(target.getType())) {
|
||||||
throw new ApiException(HttpStatus.BAD_REQUEST, "상환 대상은 대출/카드만 가능합니다.");
|
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())) {
|
if (req.getFromWalletId().equals(req.getTargetWalletId())) {
|
||||||
throw new ApiException(HttpStatus.BAD_REQUEST, "출금/대상 계좌가 같을 수 없습니다.");
|
throw new ApiException(HttpStatus.BAD_REQUEST, "출금/대상 계좌가 같을 수 없습니다.");
|
||||||
}
|
}
|
||||||
@@ -336,6 +340,18 @@ public class AccountService {
|
|||||||
.memo(req.getMemo() != null ? req.getMemo() : "이자")
|
.memo(req.getMemo() != null ? req.getMemo() : "이자")
|
||||||
.build());
|
.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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================== 계좌/카드 (사용자별) ===================== */
|
/* ===================== 계좌/카드 (사용자별) ===================== */
|
||||||
|
|||||||
Reference in New Issue
Block a user