Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#19 #21

Merged
merged 3 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/java/com/eum/bank/common/dto/request/DealRequestDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.eum.bank.common.dto.request;

import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;

public class DealRequestDTO {

@Getter
public static class completeDeal{
// 거래ID
@NotEmpty(message = "거래ID를 입력해주세요.")
private Long dealId;
// 예치금
@NotEmpty(message = "예치금을 입력해주세요.")
private Long deposit;
// 수신 계좌번호 리스트
@NotEmpty(message = "수신 계좌번호를 입력해주세요.")
private String[] receiverAccountNumbers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ public static class AccountInfo {
private String accountNumber;
private Long totalBudget;
private Long availableBudget;
private Boolean isBlocked;

// fromEntity
public static AccountInfo fromEntity(Account account) {
return AccountInfo.builder()
.accountNumber(account.getAccountNumber())
.totalBudget(account.getTotalBudget())
.availableBudget(account.getAvailableBudget())
.isBlocked(account.getIsBlocked())
.build();
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/eum/bank/domain/account/entity/Account.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ public class Account extends BaseEntity {
// 계좌 사용 가능 잔액
@Column(name = "available_budget", nullable = false)
private Long availableBudget;

// 블락 여부
@Column(name = "is_blocked", nullable = false)
private Boolean isBlocked;
}
16 changes: 13 additions & 3 deletions src/main/java/com/eum/bank/service/AccountService.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public APIResponse<?> createAccount(String password) {
.password(passwordEncoder.encode(password))
.totalBudget(0L)
.availableBudget(0L)
.isBlocked(false)
.build();

accountRepository.save(account);
Expand Down Expand Up @@ -77,9 +78,18 @@ public Boolean validateAccountNumber(String accountNumber) {
return true;
}

// 계좌 검증 (계좌 존재여부 + 블락 여부)
public Account validateAccount(String accountNumber) {
Account account = accountRepository.findByAccountNumber(accountNumber).orElseThrow(() -> new IllegalArgumentException("Invalid account number : " + accountNumber));
if(account.getIsBlocked()){
throw new IllegalArgumentException("Blocked account : " + accountNumber);
}
return account;
}

// 계좌번호와 비밀번호로 계좌 조회
public APIResponse<AccountResponseDTO.AccountInfo> getAccount(String accountNumber, String password) {
Account account = accountRepository.findByAccountNumber(accountNumber).orElseThrow(() -> new IllegalArgumentException("Invalid account number"));
Account account = this.validateAccount(accountNumber);

// 비밀번호 검증
if (!passwordEncoder.matches(password, account.getPassword())) {
Expand All @@ -100,8 +110,8 @@ public APIResponse<AccountResponseDTO.AccountInfo> getAccount(String accountNumb
// 5. 통합 거래내역 생성, 각 계좌 거래내역 생성
@Transactional
public APIResponse<?> transfer(String senderAccountNumber, String receiverAccountNumber, Long amount, String password, String transferType) {
Account senderAccount = accountRepository.findByAccountNumber(senderAccountNumber).orElseThrow(() -> new IllegalArgumentException("Invalid account number"));
Account receiverAccount = accountRepository.findByAccountNumber(receiverAccountNumber).orElseThrow(() -> new IllegalArgumentException("Invalid account number"));
Account senderAccount = this.validateAccount(senderAccountNumber);
Account receiverAccount = this.validateAccount(receiverAccountNumber);

// 비밀번호 검증
if (!passwordEncoder.matches(password, senderAccount.getPassword())) {
Expand Down
76 changes: 76 additions & 0 deletions src/main/java/com/eum/bank/service/DealService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.eum.bank.service;

import com.eum.bank.common.APIResponse;
import com.eum.bank.common.dto.request.DealRequestDTO;
import com.eum.bank.common.enums.SuccessCode;
import com.eum.bank.domain.account.entity.Account;
import com.eum.bank.domain.deal.entity.Deal;
import com.eum.bank.domain.deal.entity.DealReceiver;
import com.eum.bank.repository.DealReceiverRepository;
import com.eum.bank.repository.DealRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class DealService {

private final DealRepository dealRepository;
private final AccountService accountService;
private final DealReceiverRepository dealReceiverRepository;


// 거래 성사
// 1. 거래상태 a인지 확인
// 2. 수신계좌들 검증
// 3. 최종 예치금 확인해서 차액만큼 가용금액 플러스
// 4. 수신자 계좌번호 거래에 묶기
// 5. 거래상태 b로 변경
// 6. 거래ID 반환
@Transactional
public APIResponse<Long> completeDeal(DealRequestDTO.completeDeal dto) {
// 거래 검증 및 거래 상태 a 인지 검증
Deal deal = this.validateDeal(dto.getDealId(), List.of("a"));

List<String> receiverAccountNumbers = List.of(dto.getReceiverAccountNumbers());

// 송신계좌 검증 및 잔액 확인
// 최종 예치금 - 기존 거래의 예치금 만큼 송신자 계좌의 가용금액을 마이너스
Account senderAccount = accountService.validateAccount(deal.getSenderAccount().getAccountNumber());
Long finalDeposit = dto.getDeposit() - deal.getDeposit();
if (senderAccount.getAvailableBudget() < finalDeposit) {
throw new IllegalArgumentException("잔액이 부족합니다.");
}
senderAccount.setAvailableBudget(senderAccount.getAvailableBudget() - finalDeposit);

// 수신자 계좌번호 검증하면서 DealReceiver로 만들어서 저장
for (String receiverAccountNumber : receiverAccountNumbers) {
dealReceiverRepository.save(
DealReceiver.builder()
.deal(deal)
.receiverAccount(accountService.validateAccount(receiverAccountNumber))
.build()
);
}

// 거래상태 b로 변경
deal.setStatus("b");

return APIResponse.of(SuccessCode.INSERT_SUCCESS, dealRepository.save(deal).getId());
}

// 거래ID로 존재여부 + 거래상태 검증
private Deal validateDeal(Long dealId, List<String> status) {
Deal deal = dealRepository.findById(dealId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 거래입니다."));

if (!status.contains(deal.getStatus())) {
throw new IllegalArgumentException("거래 상태가 올바르지 않습니다.");
}

return deal;
}
}
Loading