1. 초기 데이터 수정 처리 
2. withdrawForm.jsp 주소 설계 및 name 속성 확인 
3. AccountController 출금 인증 검사, 유효성 검사 추가 
4. AccountService 출금 기능 구현 및 트랜잭션 처리 
5. MyBatis 맵퍼 확인 및 쿼리 확인

출금 페이지 화면

데이터 초기화 값 수정

INSERT INTO user_tb(username, password, fullname, created_at) values('길동', '1234',
'고', now());
INSERT INTO user_tb(username, password, fullname, created_at) values('둘리', '1234',
'애기공룡', now());
INSERT INTO user_tb(username, password, fullname, created_at) values('콜', '1234',
'마이', now());
INSERT INTO user_tb(username, password, fullname, created_at) values('홍아', '1234',
'항아', now());


INSERT INTO account_tb(number, password, balance, user_id, created_at)
values('1111', '1234', 1200, 1, now());
INSERT INTO account_tb(number, password, balance, user_id, created_at)
values('2222', '1234', 2200, 2, now());
INSERT INTO account_tb(number, password, balance, user_id, created_at)
values('3333', '1234', 0, 3, now());



-- 이체 내역을 기록 ( 1번 계좌에서 2번 계좌로 100원을 이체 한다) 
INSERT INTO history_tb(amount, w_balance, d_balance, 
					   w_account_id, d_account_id, created_at)
VALUES (100, 800, 1200, 1, 2, now());

-- 출금 내역 ( 1번계좌에서 100원을 출금 처리 )
INSERT INTO history_tb(amount, w_balance, d_balance, 
					   w_account_id, d_account_id, created_at)
VALUES (100, 700, null, 1, null, now());


-- 입금 내역 (1번 계좌에 500원 입금 처리 )
INSERT INTO history_tb(amount, w_balance, d_balance, 
					   w_account_id, d_account_id, created_at)
VALUES (500, null, 1200, null, 1, now());

-- 입금 내역 (2번 계좌에 1000원 입금 처리 )
INSERT INTO history_tb(amount, w_balance, d_balance, 
					   w_account_id, d_account_id, created_at)
VALUES (100, null, 2200, null, 2, now());

출금 페이지 인증 처리 코드 추가

AccountController

// 출금 페이지 
@GetMapping("/withdraw")
public String withdraw() {
	
	User principal = (User)session.getAttribute(Define.PRINCIPAL);
	if(principal == null) {
		throw new UnAuthorizedException("로그인 먼저 해주세요", HttpStatus.UNAUTHORIZED);
	}
	
	return "/account/withdrawForm";
}

AccountController

... 생략 
	
// 출금 처리 기능
@PostMapping("/withdraw-proc")
public String withdrawProc(WithdrawFormDto withdrawFormDto) {
	
	User principal = (User)session.getAttribute(Define.PRINCIPAL);
	if(principal == null) {
		throw new UnAuthorizedException("로그인 먼저 해주세요", HttpStatus.UNAUTHORIZED);
	}
	if(withdrawFormDto.getAmount() == null) {
		throw new CustomRestfullException("금액을 입력 하세요", HttpStatus.BAD_REQUEST);
	}
	
	if( withdrawFormDto.getAmount().longValue() <= 0) {
		throw new CustomRestfullException("출금액이 0원 이하일 수는 없습니다", HttpStatus.BAD_REQUEST);
	}
	
	if(withdrawFormDto.getWAccountNumber() == null || 
			withdrawFormDto.getWAccountNumber().isEmpty()) {
		throw new CustomRestfullException("계좌 번호를 입력해주세요", HttpStatus.BAD_REQUEST);
	}
	
	if(withdrawFormDto.getWAccountPassword() == null || 
			withdrawFormDto.getWAccountPassword().isEmpty()) {
		throw new CustomRestfullException("계좌 비밀 번호를 입력해주세요", HttpStatus.BAD_REQUEST);
	}
	
	accountService.updateAccountWithdraw(withdrawFormDto, principal.getId());
	
	return "redirect:/account/list";
}
	
}

AccountService 출금 기능 추가

... 생략 
	
// 출금 기능 로직 고민해 보기  
// 1. 계좌 존재 여부 확인 -> select query
// 2. 본인 계좌 여부 확인 ->
// 3. 계좌 비번 확인 
// 4. 잔액 여부 확인 
// 5. 출금 처리 -> update query 
// 6. 거래 내역 등록 -> insert query
// 7. 트랜잭션 처리 
@Transactional
public void updateAccountWithdraw(WithdrawFormDto withdrawFormDto, Integer principalId) {
	Account accountEntity = accountRepository.findByNumber(withdrawFormDto.getWAccountNumber());
	// 1 
	if(accountEntity == null) {
		throw new CustomRestfullException("해당 계좌가 없습니다", HttpStatus.BAD_REQUEST);
	}
	// 2
	if(accountEntity.getUserId() != principalId) {
		throw new CustomRestfullException("본인 소유 계좌가 아닙니다", HttpStatus.UNAUTHORIZED);
	}
	// 3   
	if(accountEntity.getPassword().equals(withdrawFormDto.getWAccountPassword()) == false) {
		throw new CustomRestfullException("출금 계좌 비밀번호가 틀렸습니다", HttpStatus.UNAUTHORIZED);
	}
	// 4 
	if(accountEntity.getBalance() < withdrawFormDto.getAmount()) {
		throw new CustomRestfullException("계좌 잔액이 부족 합니다", HttpStatus.BAD_REQUEST);
	}
	// 5 (모델 객체 상태값 변경 처리) 
	accountEntity.withdraw(withdrawFormDto.getAmount());
	accountRepository.updateById(accountEntity);
	// 6 거래 내역 등록 
	History history = new History();
	history.setAmount(withdrawFormDto.getAmount());
	history.setWBalance(accountEntity.getBalance()); // !! 
	history.setDBalance(null);
	history.setWAccountId(accountEntity.getId());
	history.setDAccountId(null);
	
	int resultRowCount = historyRepository.insert(history);
	if(resultRowCount != 1) {
		throw new CustomRestfullException("정상 처리 되지 않았습니다", HttpStatus.INTERNAL_SERVER_ERROR);
	}
}

... 생략

Account 모델 클래스 확인

package com.tenco.bank.repository.model;

import java.sql.Timestamp;

import lombok.Data;

/**
 * 모델 클래스 (Value Object 역할만 하는것은 아니다) 
 */
@Data
public class Account {
	
	private Integer id;
	private String number; 
	private String password; 
	private Long balance; 
	private Integer userId; 
	private Timestamp createdAt; 
	
	public void withdraw(Long amount) {
		this.balance -= amount;
	}
	
	public void deposit(Long amount) {
		this.balance += amount;
	}
	
	// 패스워드 체크
	// 잔액 여부 확인 (출금시) 
	// 계좌 소유자 확인 
}

History 모델 클래스 확인

package com.tenco.bank.repository.model;

import java.sql.Timestamp;

import lombok.Data;

@Data
public class History {
	
	private Integer id;
	private Long amount;
	private Long wBalance;
	private Long dBalance;
	private Integer wAccountId;
	private Integer dAccountId;
	private Timestamp createdAt;
}

AccountRepository 기능 추가

@Mapper // mybatis 연결 처리 
public interface AccountRepository {
	
	... 생략 
	public Account findByNumber(String number); 
}

HistoryRepository 코드 확인

@Mapper // 반드시 지정하기 ! 
public interface HistoryRepository {
	
	public int insert(History history); 
	... 생략 	
}

account.xml

<select id="findByNumber"  resultType="com.tenco.bank.repository.model.Account">
	select * from account_tb where number = #{number}
</select>

history.xml

<insert id="insert"
	parameterType="com.tenco.bank.repository.model.History">
	insert into
	history_tb(
	amount, w_balance, d_balance,
	w_account_id, d_account_id
	)
	values(
	#{amount}, #{wBalance}, #{dBalance},
	#{wAccountId}, #{dAccountId}
	)
</insert>

: 로직 검사 확인

 

+ Recent posts