Skip to content

Commit

Permalink
feat #15: 사용자 출금 신청폼,출금 신청,사용자 출금 신청 내역 기능 구현
Browse files Browse the repository at this point in the history
- 출금 신청폼은 신청이력이 있는 경우 최신 내역에서 은행,계좌번호를 같이 불러온다
- 신청 이력이 없는경우는 예치금만 불러온다
- 출금 신청시 돈이 미리 빠져나간다(사용자가 사용할수도있어서)
  • Loading branch information
shzero211 committed Nov 6, 2022
1 parent 8814ba4 commit 0e6c848
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@
@Configuration
@Profile("test")
public class TestInitData {
private boolean initDataDone=false;
@Bean
CommandLineRunner initData(MemberService memberService, PasswordEncoder passwordEncoder, PostService postService, ProductService productService, CartService cartService, OrderService orderService){
return args -> {
//initData가 1번만 사용될수 있도록 설정
if(initDataDone)return;
initDataDone=true;

String password=passwordEncoder.encode("1234");
//회원 가입
Member member1=memberService.join("user1",password,"[email protected]","author1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ public enum EventType{
PAYMENT("상품결제"),
CHARGE_FOR_REFUND("상품환불로인한 충전"),
SALES_RECEIVE("도서판매자로서 정산받음"),
EXCHANGE("환전");
EXCHANGE_APPLY("환전 신청"),
EXCHANGE_APPROVE("환전 승인"),
EXCHANGE_REJECT("환전 거절");


private final String message; //converter 에서 사용될 변수 값

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package com.ebook.multbooks.app.withdraw.controller;

import com.ebook.multbooks.app.cash.service.CashService;
import com.ebook.multbooks.app.member.service.MemberService;
import com.ebook.multbooks.app.withdraw.dto.WithDrawApplyForm;
import com.ebook.multbooks.app.withdraw.dto.WithDrawListDto;
import com.ebook.multbooks.app.withdraw.entity.WithDraw;
import com.ebook.multbooks.app.withdraw.service.WithDrawService;
import com.ebook.multbooks.global.rq.Rq;
import com.ebook.multbooks.global.util.Util;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
Expand All @@ -10,29 +17,47 @@
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.List;

@RequestMapping("/withdraw")
@RequiredArgsConstructor
@Controller
public class WithDrawController {
private final Rq rq;

private final WithDrawService withDrawService;
/*
* 출금 페이지로 이동
* 출금 작성 페이지로 이동
* */
@PreAuthorize("isAuthenticated()")
@GetMapping("/apply")
public String showApply(Model model){

public String showApply(Model model,String errorMsg){
WithDrawApplyForm withDrawApplyForm=withDrawService.getWithDrawApplyForm(rq.getId());
model.addAttribute("withDrawApplyForm",withDrawApplyForm);
model.addAttribute("errorMsg",errorMsg);
return "withdraw/apply";
}
/*
* 출금 처리 후
* 로그인 한사람 출금 내역
* */
@PreAuthorize("isAuthenticated()")
@GetMapping("/list")
public String showList(Model model){
List<WithDrawListDto> withDrawListDtos=withDrawService.getMyWithDrawApplyList(rq.getId());
model.addAttribute("withDrawList",withDrawListDtos);
return "withdraw/list";
}
/*
* 출금 신청 후
* 내역으로 이동
* */
@PreAuthorize("isAuthenticated()")
@PostMapping("/apply")
public String apply(){
return "withdraw/list";
public String apply(WithDrawApplyForm withDrawApplyForm){
try{
withDrawService.withDrawApply(withDrawApplyForm, rq.getId());
}catch (Exception exception){
return "redirect:/withdraw/apply/?errorMsg="+ Util.url.encode(exception.getMessage());
}
return "redirect:/withdraw/list";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ebook.multbooks.app.withdraw.dto;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class WithDrawApplyForm {
private int price;
private long restCash;
private String bankName;
private String bankAccount;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.ebook.multbooks.app.withdraw.dto;

import com.ebook.multbooks.app.cash.entity.CashLog;
import com.ebook.multbooks.app.member.entity.Member;
import lombok.Builder;
import lombok.Data;

import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import java.time.LocalDateTime;

@Data
@Builder
public class WithDrawListDto {
private int price;
private String bankName;
private String bankAccount;
private LocalDateTime withDrawDate;

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class WithDraw extends BaseEntity {
private int price;
private String bankName;
private String bankAccount;
private LocalDateTime WithDrawDate;
private LocalDateTime withDrawDate;

@ManyToOne(fetch = FetchType.LAZY)
private Member member;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
package com.ebook.multbooks.app.withdraw.repository;

import com.ebook.multbooks.app.member.entity.Member;
import com.ebook.multbooks.app.withdraw.entity.WithDraw;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;
import java.util.Optional;

public interface WithDrawRepository extends JpaRepository<WithDraw,Long> {

Optional<WithDraw> findFirstByMemberOrderByCreateDateDesc(Member member);
@Query("select w from WithDraw w where w.member= :member Order by w.createDate DESC")
List<WithDraw> getMyWithDrawList(@Param("member") Member member);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.ebook.multbooks.app.withdraw.service;

import com.ebook.multbooks.app.cash.entity.CashLog;
import com.ebook.multbooks.app.cash.event.EventType;
import com.ebook.multbooks.app.member.entity.Member;
import com.ebook.multbooks.app.member.repository.MemberRepository;
import com.ebook.multbooks.app.member.service.MemberService;
import com.ebook.multbooks.app.withdraw.dto.WithDrawApplyForm;
import com.ebook.multbooks.app.withdraw.dto.WithDrawListDto;
import com.ebook.multbooks.app.withdraw.entity.WithDraw;
import com.ebook.multbooks.app.withdraw.repository.WithDrawRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class WithDrawService {
private final WithDrawRepository withDrawRepository;
private final MemberService memberService;
/*
* 출금 작성폼 반환 메서드
* */
public WithDrawApplyForm getWithDrawApplyForm(long memberId){
Member loginMember=memberService.getMemberById(memberId);
WithDraw recentWithDraw=getRecentWithDraw(loginMember);//최근 인출내역
if(recentWithDraw==null){
return WithDrawApplyForm.builder().restCash(loginMember.getRestCash()).build();//보유 예치금만 포함
}
return WithDrawApplyForm.builder()
.bankAccount(recentWithDraw.getBankAccount())
.bankName(recentWithDraw.getBankName())
.restCash(loginMember.getRestCash())
.build();//예치금+은행관련정보도 포함
}

private WithDraw getRecentWithDraw(Member member) {
return withDrawRepository.findFirstByMemberOrderByCreateDateDesc(member).orElse(null);
}

/*
* 출금 신청
* */
public void withDrawApply(WithDrawApplyForm withDrawApplyForm,long memberId) {
Member actor=memberService.getMemberById(memberId);
if(actor.getRestCash()< withDrawApplyForm.getPrice()){
throw new RuntimeException("예치금보다 더많은 금액을 출금 할수 없습니다!");
}
//로그 기록과 회원 예치금 수정
CashLog cashLog=memberService.addCashAndReturnCashLog(actor, -1*withDrawApplyForm.getPrice(), EventType. EXCHANGE_APPLY);
WithDraw withDraw=WithDraw.builder()
.bankName(withDrawApplyForm.getBankName())
.bankAccount(withDrawApplyForm.getBankAccount())
.price(withDrawApplyForm.getPrice())
.member(actor)
.cashLog(cashLog)
.build();
withDrawRepository.save(withDraw);

}

/*
* 내 출금 신청 내역 보기
* */
public List<WithDrawListDto> getMyWithDrawApplyList(long id) {
Member actor=memberService.getMemberById(id);
List<WithDraw> withDraws=withDrawRepository.getMyWithDrawList(actor);
List<WithDrawListDto> withDrawListDtos=withDraws.stream().map(withDraw ->
WithDrawListDto
.builder()
.price(withDraw.getPrice())
.bankAccount(withDraw.getBankAccount())
.bankName(withDraw.getBankName())
.withDrawDate(withDraw.getWithDrawDate())
.build()).toList();
return withDrawListDtos;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html layout:decorate="~{/adm/layout/layout}">

<head>
<title>관리자 홈</title>
</head>

<main layout:fragment="main">
<div class="container mx-auto flex-grow flex items-center justify-center">
<form method="post" th:action>
<p>에치금</p>
<p th:text="${withDrawApplyForm.restCash}"></p>
<input name="restCash" th:value="${withDrawApplyForm.restCash}" hidden>
<div class="mb-6">
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">은행</label>
<input type="text" id="backName" name="bankName" th:value="${withDrawApplyForm.bankName}" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 dark:shadow-sm-light" placeholder="은행" required>
</div>
<div class="mb-6">
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">계좌번호</label>
<input type="text" id="bankAccount" name="bankAccount" th:value="${withDrawApplyForm.bankAccount}" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 dark:shadow-sm-light" placeholder="계좌" required>
</div>
<div class="mb-6">
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300">출금 금액</label>
<input type="number" id="price" name="price" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 dark:shadow-sm-light" placeholder="금액" required>
</div>
<button type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">출금</button>
</form>
</div>
</main>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html layout:decorate="~{/adm/layout/layout}">

<head>
<title>내 출금 내역</title>
</head>

<main layout:fragment="main">
<div class="container mx-auto">
<div>
<h1>내 출금 내역</h1>

<div class="overflow-x-auto">
<table class="table table-compact w-full">
<thead>
<tr>
<th>품목 번호</th>
<th>은행 이름</th>
<th>은행 계좌</th>
<th>출금 금액</th>
<th>출금 날짜</th>
</tr>
</thead>

<tbody>
<tr th:each="withDraw, idx : ${withDrawList}" class="text-center">

<td th:text="${idx.count}"></td>
<td th:text="${withDraw.bankName}"></td>
<td th:text="${withDraw.bankAccount}"></td>
<td th:text="${withDraw.price}"></td>
<td th:text="${withDraw.withDrawDate}"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</main>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.ebook.multbooks.withdraw;

import com.ebook.multbooks.app.member.entity.Member;
import com.ebook.multbooks.app.member.repository.MemberRepository;
import com.ebook.multbooks.app.withdraw.dto.WithDrawApplyForm;
import com.ebook.multbooks.app.withdraw.entity.WithDraw;
import com.ebook.multbooks.app.withdraw.repository.WithDrawRepository;
import com.ebook.multbooks.app.withdraw.service.WithDrawService;
import org.aspectj.lang.annotation.After;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Profile;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;

@SpringBootTest
@Transactional
@ActiveProfiles({"test","secret"})
public class WithDrawServiceTest {
@Autowired
private WithDrawService withDrawService;
@Autowired
private MemberRepository memberRepository;

@Autowired
private WithDrawRepository withDrawRepository;

@Test
public void getWithDrawApplyForm(){
/*결제 내여*/
//Given
Member loginMember=memberRepository.findByUsername("user1").get();
//When
WithDrawApplyForm withDrawApplyForm = withDrawService.getWithDrawApplyForm(loginMember.getId());
//Then
assertEquals(withDrawApplyForm.getBankAccount(),null);
assertEquals(withDrawApplyForm.getBankName(),null);
assertNotEquals(withDrawApplyForm.getRestCash(),0);

withDrawRepository.save(WithDraw.builder().bankAccount("123").bankName("우리은행").member(loginMember).withDrawDate(LocalDateTime.now()).build());
withDrawApplyForm = withDrawService.getWithDrawApplyForm(loginMember.getId());
assertEquals(withDrawApplyForm.getBankName(),"우리은행");
assertEquals(withDrawApplyForm.getBankAccount(),"123");
assertEquals(withDrawApplyForm.getRestCash(),100000);

}
}

0 comments on commit 0e6c848

Please sign in to comment.