Skip to content

Commit

Permalink
Merge pull request #17 from EUM-kmu/feat/#13
Browse files Browse the repository at this point in the history
Feat/#13
  • Loading branch information
cheesecrust authored Jan 29, 2024
2 parents 6492e97 + ca0e133 commit dac3615
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 3 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'io.springfox:springfox-boot-starter:3.0.0'
implementation 'io.springfox:springfox-swagger-ui:3.0.0'
implementation 'org.springframework.security:spring-security-crypto:5.7.1'


}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,13 @@ public static class CreateAccount {
@NotEmpty(message = "비밀번호를 입력해주세요.")
private Long password;
}

// 계좌 조회 요청
@Getter
public static class GetAccount {
@NotEmpty(message = "계좌 번호를 입력해주세요.")
private String accountNumber;
@NotEmpty(message = "비밀번호를 입력해주세요.")
private String password;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.eum.bank.common.dto.request;

import com.eum.bank.domain.account.entity.Account;
import com.eum.bank.domain.account.entity.AccountTransferHistory;
import jakarta.validation.constraints.NotEmpty;
import lombok.Builder;
import lombok.Getter;

public class AccountTransferHistoryRequestDTO {

// 내역 생성
@Getter
@Builder
public static class CreateAccountTransferHistory {
@NotEmpty(message = "거래 내역을 생성할 계좌를 입력해주세요.")
private Account ownerAccount;
@NotEmpty(message = "거래 상대 계좌를 입력해주세요.")
private Account oppenentAccount;
@NotEmpty(message = "거래 금액을 입력해주세요.")
private Long transferAmount;
@NotEmpty(message = "거래 유형을 입력해주세요.")
private String transferType;
@NotEmpty(message = "거래 후 잔액을 입력해주세요.")
private Long budgetAfterTransfer;
@NotEmpty(message = "거래 메모를 입력해주세요.")
private String memo;

// toEntity
public AccountTransferHistory toEntity() {
return AccountTransferHistory.builder()
.ownerAccount(ownerAccount)
.oppenentAccount(oppenentAccount)
.transferAmount(transferAmount)
.transferType(transferType)
.budgetAfterTransfer(budgetAfterTransfer)
.memo(memo)
.build();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.eum.bank.common.dto.request;

import com.eum.bank.domain.account.entity.Account;
import com.eum.bank.domain.account.entity.TotalTransferHistory;
import jakarta.validation.constraints.NotEmpty;
import lombok.Builder;
import lombok.Getter;

public class TotalTransferHistoryRequestDTO {

@Getter
@Builder
public static class CreateTotalTransferHistory {
@NotEmpty(message = "송금자 계좌를 입력해주세요.")
private Account senderAccount;
@NotEmpty(message = "수취자 계좌를 입력해주세요.")
private Account receiverAccount;
@NotEmpty(message = "송금 금액을 입력해주세요.")
private Long transferAmount;
@NotEmpty(message = "거래유형을 입력해주세요.")
private String transferType;

// toEntity
public TotalTransferHistory toEntity() {
return TotalTransferHistory.builder()
.senderAccount(senderAccount)
.receiverAccount(receiverAccount)
.transferAmount(transferAmount)
.transferType(transferType)
.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.eum.bank.common.dto.response;

import com.eum.bank.domain.account.entity.Account;
import jakarta.validation.constraints.NotEmpty;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

public class AccountResponseDTO {
// 계좌 생성 응답
Expand All @@ -13,4 +13,22 @@ public static class Create {
@NotEmpty(message = "계좌 번호가 생성되어야 합니다.")
private String accountNumber;
}

// 계좌 조회 응답
@Builder
@Getter
public static class AccountInfo {
private String accountNumber;
private Long totalBudget;
private Long availableBudget;

// fromEntity
public static AccountInfo fromEntity(Account account) {
return AccountInfo.builder()
.accountNumber(account.getAccountNumber())
.totalBudget(account.getTotalBudget())
.availableBudget(account.getAvailableBudget())
.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.eum.bank.common.dto.response;

import com.eum.bank.domain.account.entity.TotalTransferHistory;
import lombok.Builder;
import lombok.Getter;

public class TotalTransferHistoryResponseDTO {

// 거래 내역 반환
@Builder
@Getter
public static class GetTotalTransferHistory {
private Long id;
private AccountResponseDTO.AccountInfo senderAccount;
private AccountResponseDTO.AccountInfo receiverAccount;
private Long transferAmount;
private String transferType;

// fromEntity
public static GetTotalTransferHistory fromEntity(TotalTransferHistory totalTransferHistory) {
return GetTotalTransferHistory.builder()
.id(totalTransferHistory.getId())
.senderAccount(AccountResponseDTO.AccountInfo.fromEntity(totalTransferHistory.getSenderAccount()))
.receiverAccount(AccountResponseDTO.AccountInfo.fromEntity(totalTransferHistory.getReceiverAccount()))
.transferAmount(totalTransferHistory.getTransferAmount())
.transferType(totalTransferHistory.getTransferType())
.build();
}
}
}
14 changes: 14 additions & 0 deletions src/main/java/com/eum/bank/config/PasswordEncoderConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.eum.bank.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class PasswordEncoderConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
4 changes: 3 additions & 1 deletion src/main/java/com/eum/bank/repository/AccountRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import com.eum.bank.domain.account.entity.Account;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface AccountRepository extends JpaRepository<Account, String> {
Account save(Account account);
Boolean findByAccountNumber(String accountNumber);
Optional<Account> findByAccountNumber(String accountNumber);
}
94 changes: 93 additions & 1 deletion src/main/java/com/eum/bank/service/AccountService.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
package com.eum.bank.service;

import com.eum.bank.common.APIResponse;
import com.eum.bank.common.ErrorResponse;
import com.eum.bank.common.dto.request.AccountTransferHistoryRequestDTO;
import com.eum.bank.common.dto.request.TotalTransferHistoryRequestDTO;
import com.eum.bank.common.dto.response.AccountResponseDTO;
import com.eum.bank.common.enums.ErrorCode;
import com.eum.bank.common.enums.SuccessCode;
import com.eum.bank.domain.account.entity.Account;
import com.eum.bank.domain.account.entity.AccountTransferHistory;
import com.eum.bank.domain.account.entity.TotalTransferHistory;
import com.eum.bank.repository.AccountRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.Random;

@Service
@RequiredArgsConstructor
public class AccountService {

private final AccountRepository accountRepository;
private final PasswordEncoder passwordEncoder;
private final AccountTransferHistoryService accountTransferHistoryService;
private final TotalTransferHistoryService totalTransferHistoryService;



public APIResponse<?> createAccount(Long password) {

Expand All @@ -27,7 +40,7 @@ public APIResponse<?> createAccount(Long password) {

Account account = Account.builder()
.accountNumber(accountNumber)
.password(password.toString())
.password(passwordEncoder.encode(password.toString()))
.totalBudget(0L)
.availableBudget(0L)
.build();
Expand Down Expand Up @@ -67,5 +80,84 @@ public Boolean validateAccountNumber(String accountNumber) {
return true;
}

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

// 비밀번호 검증
if (!passwordEncoder.matches(password, account.getPassword())) {
throw new IllegalArgumentException("Invalid password");
}
return APIResponse.of(SuccessCode.SELECT_SUCCESS, AccountResponseDTO.AccountInfo.builder()
.accountNumber(account.getAccountNumber())
.totalBudget(account.getTotalBudget())
.availableBudget(account.getAvailableBudget())
.build());
}

// 자유송금
// 1. 송금자 계좌, 수신자 계좌 상태 검증
// 2. 송금자 잔액 확인
// 3. 송금자 전체금액, 가용금액 마이너스
// 4. 수신자 전체금액, 가용금액 플러스
// 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"));

// 비밀번호 검증
if (!passwordEncoder.matches(password, senderAccount.getPassword())) {
throw new IllegalArgumentException("Invalid password");
}

// 송금자 잔액 검증
if (senderAccount.getAvailableBudget() < amount) {
throw new IllegalArgumentException("Insufficient balance");
}

// 송금자 잔액 마이너스
senderAccount.setTotalBudget(senderAccount.getTotalBudget() - amount);
senderAccount.setAvailableBudget(senderAccount.getAvailableBudget() - amount);


// 수신자 잔액 플러스
receiverAccount.setTotalBudget(receiverAccount.getTotalBudget() + amount);
receiverAccount.setAvailableBudget(receiverAccount.getAvailableBudget() + amount);

// 통합 거래내역 생성
TotalTransferHistory response = totalTransferHistoryService.save(
TotalTransferHistoryRequestDTO.CreateTotalTransferHistory.builder()
.senderAccount(senderAccount)
.receiverAccount(receiverAccount)
.transferAmount(amount)
.transferType(transferType)
.build()
);

// 각 계좌 거래내역 생성
accountTransferHistoryService.save(
AccountTransferHistoryRequestDTO.CreateAccountTransferHistory.builder()
.ownerAccount(senderAccount)
.oppenentAccount(receiverAccount)
.transferAmount(amount)
.transferType(transferType)
.budgetAfterTransfer(senderAccount.getAvailableBudget())
.memo("")
.build()
);
accountTransferHistoryService.save(
AccountTransferHistoryRequestDTO.CreateAccountTransferHistory.builder()
.ownerAccount(receiverAccount)
.oppenentAccount(senderAccount)
.transferAmount(-amount)
.transferType(transferType)
.budgetAfterTransfer(receiverAccount.getAvailableBudget())
.memo("")
.build()
);

return APIResponse.of(SuccessCode.INSERT_SUCCESS, response);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.eum.bank.service;

import com.eum.bank.common.dto.request.AccountTransferHistoryRequestDTO;
import com.eum.bank.domain.account.entity.AccountTransferHistory;
import com.eum.bank.repository.AccountTransferHistoryRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class AccountTransferHistoryService {

private final AccountTransferHistoryRepository accountTransferHistoryRepository;

// 저장
public AccountTransferHistory save(AccountTransferHistoryRequestDTO.CreateAccountTransferHistory dto) {
return accountTransferHistoryRepository.save(dto.toEntity());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.eum.bank.service;

import com.eum.bank.common.dto.request.TotalTransferHistoryRequestDTO;
import com.eum.bank.domain.account.entity.TotalTransferHistory;
import com.eum.bank.repository.TotalTransferHistoryRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class TotalTransferHistoryService {
private final TotalTransferHistoryRepository totalTransferHistoryRepository;

public TotalTransferHistory save(TotalTransferHistoryRequestDTO.CreateTotalTransferHistory dto) {
return totalTransferHistoryRepository.save(dto.toEntity());
}
}

0 comments on commit dac3615

Please sign in to comment.