diff --git a/src/main/java/com/sb/web/account/domain/Wallet.java b/src/main/java/com/sb/web/account/domain/Wallet.java
index 8bd3b03..06a6b56 100644
--- a/src/main/java/com/sb/web/account/domain/Wallet.java
+++ b/src/main/java/com/sb/web/account/domain/Wallet.java
@@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
+import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@@ -29,6 +30,11 @@ public class Wallet implements Serializable {
private Long openingBalance; // 초기 잔액(부호있음: 자산+, 부채-)
private LocalDate openingDate;
private Long currentValue; // 현재 평가금액 (INVEST 전용, 수동 갱신)
+ private Long loanAmount; // 대출 실행 금액(원금, 처음 빌린 금액) (LOAN 전용)
+ private BigDecimal loanRate; // 연이자율(%) e.g. 5.25 (LOAN 전용)
+ private String loanMethod; // 상환방식: EQUAL_PAYMENT / EQUAL_PRINCIPAL / BULLET (LOAN 전용)
+ private Integer loanMonths; // 대출기간(개월) (LOAN 전용)
+ private LocalDate loanStart; // 대출시작일 (LOAN 전용)
private Integer sortOrder; // 표시 순서 (타입 내 정렬)
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
diff --git a/src/main/java/com/sb/web/account/dto/WalletRequest.java b/src/main/java/com/sb/web/account/dto/WalletRequest.java
index 5cb3c18..a940aa1 100644
--- a/src/main/java/com/sb/web/account/dto/WalletRequest.java
+++ b/src/main/java/com/sb/web/account/dto/WalletRequest.java
@@ -1,10 +1,13 @@
package com.sb.web.account.dto;
+import jakarta.validation.constraints.DecimalMax;
+import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import lombok.Data;
+import java.math.BigDecimal;
import java.time.LocalDate;
/**
@@ -37,4 +40,17 @@ public class WalletRequest {
/** 현재 평가금액 (INVEST 전용, 수동 갱신) */
private Long currentValue;
+
+ // ===== 대출(LOAN) 전용 =====
+ private Long loanAmount; // 대출 실행 금액(원금)
+
+ @DecimalMin(value = "0.0", inclusive = true)
+ @DecimalMax(value = "100.0", message = "이자율은 100% 이하여야 합니다.")
+ private BigDecimal loanRate; // 연이자율(%)
+
+ @Pattern(regexp = "EQUAL_PAYMENT|EQUAL_PRINCIPAL|BULLET|", message = "상환방식이 올바르지 않습니다.")
+ private String loanMethod; // 상환방식
+
+ private Integer loanMonths; // 대출기간(개월)
+ private LocalDate loanStart; // 대출시작일
}
diff --git a/src/main/java/com/sb/web/account/dto/WalletResponse.java b/src/main/java/com/sb/web/account/dto/WalletResponse.java
index 408d67c..2ec3b39 100644
--- a/src/main/java/com/sb/web/account/dto/WalletResponse.java
+++ b/src/main/java/com/sb/web/account/dto/WalletResponse.java
@@ -4,6 +4,7 @@ import com.sb.web.account.domain.Wallet;
import lombok.Builder;
import lombok.Data;
+import java.math.BigDecimal;
import java.time.LocalDate;
/**
@@ -31,6 +32,13 @@ public class WalletResponse {
private Long currentValue; // 평가액 직접입력값(퇴직연금·연금 등 수동 갱신). 있으면 총평가로 사용
private Boolean manualValuation; // true면 평가액 직접입력형(종목 자동계산 대신)
+ // 대출(LOAN) 전용
+ private Long loanAmount; // 대출 실행 금액(원금)
+ private BigDecimal loanRate; // 연이자율(%) e.g. 5.25
+ private String loanMethod; // EQUAL_PAYMENT / EQUAL_PRINCIPAL / BULLET
+ private Integer loanMonths; // 대출기간(개월)
+ private LocalDate loanStart; // 대출시작일
+
public static WalletResponse from(Wallet w, long balance) {
return WalletResponse.builder()
.id(w.getId())
@@ -43,6 +51,11 @@ public class WalletResponse {
.openingDate(w.getOpeningDate())
.balance(balance)
.currentValue(w.getCurrentValue())
+ .loanAmount(w.getLoanAmount())
+ .loanRate(w.getLoanRate())
+ .loanMethod(w.getLoanMethod())
+ .loanMonths(w.getLoanMonths())
+ .loanStart(w.getLoanStart())
.build();
}
}
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 308bdb2..2868871 100644
--- a/src/main/java/com/sb/web/account/service/AccountService.java
+++ b/src/main/java/com/sb/web/account/service/AccountService.java
@@ -535,6 +535,12 @@ public class AccountService {
wallet.setOpeningBalance(req.getOpeningBalance() != null ? req.getOpeningBalance() : 0L);
wallet.setOpeningDate(req.getOpeningDate());
wallet.setCurrentValue("INVEST".equals(req.getType()) ? req.getCurrentValue() : null);
+ boolean isLoan = "LOAN".equals(req.getType());
+ wallet.setLoanAmount(isLoan ? req.getLoanAmount() : null);
+ wallet.setLoanRate(isLoan ? req.getLoanRate() : null);
+ wallet.setLoanMethod(isLoan ? blankToNull(req.getLoanMethod()) : null);
+ wallet.setLoanMonths(isLoan ? req.getLoanMonths() : null);
+ wallet.setLoanStart(isLoan ? req.getLoanStart() : null);
walletMapper.update(wallet);
return WalletResponse.from(wallet, balanceMap(memberId).getOrDefault(id, wallet.getOpeningBalance()));
}
@@ -564,6 +570,7 @@ public class AccountService {
}
private Wallet toWallet(WalletRequest req) {
+ boolean isLoan = "LOAN".equals(req.getType());
return Wallet.builder()
.type(req.getType())
.name(req.getName().trim())
@@ -573,6 +580,11 @@ public class AccountService {
.openingBalance(req.getOpeningBalance() != null ? req.getOpeningBalance() : 0L)
.openingDate(req.getOpeningDate())
.currentValue("INVEST".equals(req.getType()) ? req.getCurrentValue() : null)
+ .loanAmount(isLoan ? req.getLoanAmount() : null)
+ .loanRate(isLoan ? req.getLoanRate() : null)
+ .loanMethod(isLoan ? blankToNull(req.getLoanMethod()) : null)
+ .loanMonths(isLoan ? req.getLoanMonths() : null)
+ .loanStart(isLoan ? req.getLoanStart() : null)
.build();
}
diff --git a/src/main/resources/db/account.sql b/src/main/resources/db/account.sql
index 823290a..2f24f1c 100644
--- a/src/main/resources/db/account.sql
+++ b/src/main/resources/db/account.sql
@@ -28,6 +28,11 @@ ALTER TABLE wallet ADD COLUMN IF NOT EXISTS opening_balance BIGINT NOT NULL DEFA
ALTER TABLE wallet ADD COLUMN IF NOT EXISTS opening_date DATE NULL;
ALTER TABLE wallet ADD COLUMN IF NOT EXISTS current_value BIGINT NULL;
ALTER TABLE wallet ADD COLUMN IF NOT EXISTS sort_order INT NOT NULL DEFAULT 0;
+ALTER TABLE wallet ADD COLUMN IF NOT EXISTS loan_rate DECIMAL(7,4) NULL COMMENT '연이자율(%) 예: 5.2500';
+ALTER TABLE wallet ADD COLUMN IF NOT EXISTS loan_method VARCHAR(20) NULL COMMENT '상환방식: EQUAL_PAYMENT/EQUAL_PRINCIPAL/BULLET';
+ALTER TABLE wallet ADD COLUMN IF NOT EXISTS loan_months INT NULL COMMENT '대출기간(개월)';
+ALTER TABLE wallet ADD COLUMN IF NOT EXISTS loan_start DATE NULL COMMENT '대출시작일';
+ALTER TABLE wallet ADD COLUMN IF NOT EXISTS loan_amount BIGINT NULL COMMENT '대출 실행 금액(원금, 처음 빌린 금액)';
-- 계좌번호 암호화 저장(AES-GCM)으로 평문보다 길어 VARCHAR(255) 필요 — 운영 적용 완료(CREATE TABLE 정의에 반영).
-- 매 기동 MODIFY 는 라이브 테이블 락 위험이 있어 제거. 기존 환경 확장이 필요하면 1회 수동 적용:
-- ALTER TABLE wallet MODIFY account_number VARCHAR(255) NULL;
diff --git a/src/main/resources/mapper/WalletMapper.xml b/src/main/resources/mapper/WalletMapper.xml
index 609f25d..a8454de 100644
--- a/src/main/resources/mapper/WalletMapper.xml
+++ b/src/main/resources/mapper/WalletMapper.xml
@@ -15,13 +15,20 @@
+
+
+
+
+
id, member_id, type, name, issuer, account_number, card_type,
- opening_balance, opening_date, current_value, sort_order, created_at, updated_at
+ opening_balance, opening_date, current_value,
+ loan_amount, loan_rate, loan_method, loan_months, loan_start,
+ sort_order, created_at, updated_at