@@ -29,20 +29,22 @@ public class TransferServiceImpl implements TransferService {
2929 public void fillMoneyBox (Long memberId , Long moneyBoxAccountId , BigDecimal amount , String password ) {
3030 log .info ("머니박스 채우기 시작 - 회원 ID: {}, 머니박스: {}, 금액: {}" , memberId , moneyBoxAccountId , amount );
3131
32- // 1. 회원의 주계좌 조회
33- Account fromAccount = accountService .getMainAccountByMemberId (memberId );
32+ // 1. 회원의 주계좌 ID 조회
33+ Long fromAccountId = accountService .getMainAccountIdByMemberId (memberId );
3434
3535 // 2. 동일한 계좌로 이체하는지 체크
36- if (fromAccount . getId () .equals (moneyBoxAccountId )) {
36+ if (fromAccountId .equals (moneyBoxAccountId )) {
3737 throw new CustomException (ErrorCode .INVALID_TRANSFER_SAME_ACCOUNT );
3838 }
3939
4040 // 3. 머니박스 계좌 소유권 검증
4141 accountService .validateAccountOwnership (moneyBoxAccountId , memberId );
4242
43- // 4. 이체 실행
44- executeTransfer (fromAccount , moneyBoxAccountId , amount , password ,
45- ReferenceType .MONEY_BOX_DEPOSIT , null );
43+ // 4. 비밀번호 검증
44+ accountService .validateAccountPassword (fromAccountId , password );
45+
46+ // 5. 이체 실행
47+ executeTransfer (fromAccountId , moneyBoxAccountId , amount , ReferenceType .MONEY_BOX_DEPOSIT , null );
4648
4749 log .info ("머니박스 채우기 완료 - 회원 ID: {}, 머니박스: {}, 금액: {}" , memberId , moneyBoxAccountId , amount );
4850 }
@@ -51,64 +53,60 @@ public void fillMoneyBox(Long memberId, Long moneyBoxAccountId, BigDecimal amoun
5153 public void sponsorBucket (Long sponsorMemberId , Long bucketId , BigDecimal amount , String password ) {
5254 log .info ("버킷 후원 시작 - 후원자 ID: {}, 버킷 ID: {}, 금액: {}" , sponsorMemberId , bucketId , amount );
5355
54- // 1. 후원자의 주계좌 조회
55- Account fromAccount = accountService .getMainAccountByMemberId (sponsorMemberId );
56+ // 1. 후원자의 주계좌 ID 조회
57+ Long fromAccountId = accountService .getMainAccountIdByMemberId (sponsorMemberId );
5658
5759 // 2. 버킷리스트 ID로 머니박스 계좌 조회
5860 Long moneyBoxAccountId = getMoneyBoxAccountIdByBucketId (bucketId );
5961
60- // 3. 이체 실행 (후원은 소유권 검증 없음)
61- executeTransfer (fromAccount , moneyBoxAccountId , amount , password ,
62- ReferenceType .BUCKET_FUNDING , bucketId );
62+ // 3. 비밀번호 검증
63+ accountService .validateAccountPassword (fromAccountId , password );
64+
65+ // 4. 이체 실행
66+ executeTransfer (fromAccountId , moneyBoxAccountId , amount , ReferenceType .BUCKET_FUNDING , bucketId );
6367
6468 log .info ("버킷 후원 완료 - 후원자 ID: {}, 버킷 ID: {}, 금액: {}" , sponsorMemberId , bucketId , amount );
6569 }
6670
6771 @ Override
68- public void transferBetweenAccounts (Long fromAccountId , Long toAccountId , BigDecimal amount ,
69- ReferenceType referenceType , Long referenceId ) {
70- log .info ("내부 시스템 이체 시작 - 출금: {}, 입금: {}, 금액: {}, 참조: {}" , fromAccountId , toAccountId , amount , referenceType );
71-
72- // 1. 계좌 조회 (잠금 적용)
73- Account fromAccount = accountService .findByIdWithLock (fromAccountId );
74- Account toAccount = accountService .findByIdWithLock (toAccountId );
72+ public BigDecimal withdrawAllFromMoneyBox (Long memberId , Long moneyBoxAccountId , ReferenceType referenceType , Long referenceId ) {
73+ log .info ("머니박스 전액 인출 시작 - 회원 ID: {}, 머니박스: {}, 참조: {}" , memberId , moneyBoxAccountId , referenceType );
7574
76- // 2. 잔액 검증
77- if (fromAccount .getBalance ().compareTo (amount ) < 0 ) {
78- throw new CustomException (ErrorCode .INSUFFICIENT_BALANCE );
75+ // 1. 회원의 주계좌 ID 조회
76+ Long mainAccountId = accountService .getMainAccountIdByMemberId (memberId );
77+
78+ // 2. 머니박스 계좌 조회 및 잔액 확인
79+ Account moneyBoxAccount = accountService .findByIdWithLock (moneyBoxAccountId );
80+ BigDecimal balance = moneyBoxAccount .getBalance ();
81+
82+ // 3. 잔액이 0보다 클 때만 이체 실행
83+ if (balance .compareTo (BigDecimal .ZERO ) > 0 ) {
84+ executeTransfer (moneyBoxAccountId , mainAccountId , balance , referenceType , referenceId );
85+ log .info ("머니박스 전액 인출 완료 - 회원 ID: {}, 머니박스: {} → 주계좌: {}, 인출금액: {}" ,
86+ memberId , moneyBoxAccountId , mainAccountId , balance );
87+ return balance ;
88+ } else {
89+ log .info ("머니박스 전액 인출 완료 - 회원 ID: {}, 머니박스: {}, 잔액이 0이므로 이체하지 않음" ,
90+ memberId , moneyBoxAccountId );
91+ return BigDecimal .ZERO ;
7992 }
80-
81- // 3. 계좌 잔액 업데이트
82- accountService .debitBalance (fromAccountId , amount );
83- accountService .creditBalance (toAccountId , amount );
84-
85- // 4. 거래 내역 기록 (이중 기입 방식)
86- transactionService .recordTransfer (fromAccount , toAccount , amount , referenceType , referenceType .getDescription (), referenceId );
87-
88- log .info ("내부 시스템 이체 완료 - 출금: {}, 입금: {}, 금액: {}" , fromAccountId , toAccountId , amount );
8993 }
9094
91- private void executeTransfer (Account fromAccount , Long toAccountId , BigDecimal amount ,
92- String password , ReferenceType referenceType , Long referenceId ) {
93- // 1. 비밀번호 검증
94- accountService .validateAccountPassword (fromAccount .getId (), password );
95-
96- // 2. 잔액 검증
97- accountService .validateSufficientBalance (fromAccount .getId (), amount );
98-
99- // 3. 계좌 조회 (락 걸기)
100- Account lockedFromAccount = accountService .findByIdWithLock (fromAccount .getId ());
95+ private void executeTransfer (Long fromAccountId , Long toAccountId , BigDecimal amount ,
96+ ReferenceType referenceType , Long referenceId ) {
97+ // 1. 계좌 조회 (락 걸기)
98+ Account fromAccount = accountService .findByIdWithLock (fromAccountId );
10199 Account toAccount = accountService .findByIdWithLock (toAccountId );
102100
103- // 4 . 출금
104- accountService .debitBalance (lockedFromAccount .getId (), amount );
101+ // 2 . 출금 (잔액 검증도 처리)
102+ accountService .debitBalance (fromAccount .getId (), amount );
105103
106- // 5 . 입금
104+ // 3 . 입금
107105 accountService .creditBalance (toAccount .getId (), amount );
108106
109- // 6 . 거래내역 2건 생성
107+ // 4 . 거래내역 2건 생성
110108 transactionService .recordTransfer (
111- lockedFromAccount ,
109+ fromAccount ,
112110 toAccount ,
113111 amount ,
114112 referenceType ,
@@ -117,6 +115,31 @@ private void executeTransfer(Account fromAccount, Long toAccountId, BigDecimal a
117115 );
118116 }
119117
118+ @ Override
119+ public void payInterest (Long memberId , BigDecimal interestAmount , Long bucketListId ) {
120+ log .info ("이자 지급 시작 - 회원 ID: {}, 이자: {}, 버킷리스트 ID: {}" , memberId , interestAmount , bucketListId );
121+
122+ // 1. 회원의 주계좌 조회
123+ Long mainAccountId = accountService .getMainAccountIdByMemberId (memberId );
124+ Account mainAccount = accountService .findByIdWithLock (mainAccountId );
125+
126+ // 2. 실제 주계좌 잔액에 이자 추가
127+ accountService .creditBalance (mainAccount .getId (), interestAmount );
128+
129+ // 3. 이자 거래 기록 생성 (상대방: 하나이음)
130+ transactionService .recordDeposit (
131+ mainAccount ,
132+ interestAmount ,
133+ null , // 상대방 계좌 없음 (은행에서 지급)
134+ "하나이음" , // 상대방 이름
135+ ReferenceType .MONEY_BOX_INTEREST ,
136+ ReferenceType .MONEY_BOX_INTEREST .getDescription (),
137+ bucketListId
138+ );
139+
140+ log .info ("목표 달성 이자 지급 완료: 주계좌 {}, 이자: {}" , mainAccount .getId (), interestAmount );
141+ }
142+
120143 private Long getMoneyBoxAccountIdByBucketId (Long bucketId ) {
121144 // 1. 버킷리스트 조회 -> 머니박스 계좌 ID 조회
122145 BucketList bucketList = bucketListRepository .findByIdAndDeletedFalse (bucketId )
@@ -132,4 +155,5 @@ private Long getMoneyBoxAccountIdByBucketId(Long bucketId) {
132155
133156 return accountId ;
134157 }
158+
135159}
0 commit comments