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

37 정산 view api #39

Merged
merged 11 commits into from
Jul 24, 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
49 changes: 49 additions & 0 deletions src/main/java/space/space_spring/controller/PayController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package space.space_spring.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;
import space.space_spring.dto.pay.GetPayViewResponse;
import space.space_spring.dto.pay.PayReceiveInfoDto;
import space.space_spring.dto.pay.PayRequestInfoDto;
import space.space_spring.entity.UserSpace;
import space.space_spring.response.BaseResponse;
import space.space_spring.service.PayService;
import space.space_spring.util.userSpace.UserSpaceUtils;

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

@RestController
@RequiredArgsConstructor
@Slf4j
public class PayController {

private final PayService payService;
private final UserSpaceUtils userSpaceUtils;

@GetMapping("/space/{spaceId}/pay")
public BaseResponse<GetPayViewResponse> showPayListForUser(@JwtLoginAuth Long userId, @PathVariable Long spaceId) {
// TODO 1. 유저가 스페이스에 속하는 지 검증
validateIsUserInSpace(userId, spaceId);

// TODO 2. 유저가 요청한 정산 리스트 get
List<PayRequestInfoDto> payRequestInfoDtoList = payService.getPayRequestInfoForUser(userId, spaceId);

// TODO 3. 유저가 요청받은 정산 리스트 get
List<PayReceiveInfoDto> payReceiveInfoDtoList = payService.getPayReceiveInfoForUser(userId, spaceId);

return new BaseResponse<>(new GetPayViewResponse(payRequestInfoDtoList, payReceiveInfoDtoList));
}

private void validateIsUserInSpace(Long userId, Long spaceId) {
// 유저가 스페이스에 속할 경우 exception이 터지지 않을 것임
// 그렇지 않을 경우, USER_IS_NOT_IN_SPACE 예외가 터질 것임 -> 추후 exception handling 과정 필요
userSpaceUtils.isUserInSpace(userId, spaceId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public BaseResponse<PostSpaceCreateResponse> createSpace(@JwtLoginAuth Long user
return new BaseResponse<>(spaceService.createSpace(userId, postSpaceCreateRequest));
}

/**
* 테스트 용
*/
@GetMapping("/{spaceId}")
public BaseResponse<String> getSpaceHome(@JwtLoginAuth Long userId, @PathVariable Long spaceId) {
Optional<UserSpace> userInSpace = userSpaceUtils.isUserInSpace(userId, spaceId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package space.space_spring.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import space.space_spring.argument_resolver.jwtLogin.JwtLoginAuth;

import space.space_spring.dao.PayDao;
import space.space_spring.dto.chat.ChatTestRequest;
import space.space_spring.dto.chat.ChatTestResponse;
import space.space_spring.dto.jwt.JwtPayloadDto;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public BaseResponse<PostUserLoginResponse> login(@Validated @RequestBody PostUse
*/
@GetMapping("/space-choice")
public BaseResponse<GetSpaceInfoForUserResponse> showUserSpaceList(@JwtLoginAuth Long userId,
@RequestParam int size,
@RequestParam Long lastUserSpaceId) {
@RequestParam int size,
@RequestParam Long lastUserSpaceId) {

log.info("userId = {}", userId);

Expand Down
55 changes: 55 additions & 0 deletions src/main/java/space/space_spring/dao/PayDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package space.space_spring.dao;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.hibernate.validator.internal.constraintvalidators.bv.AssertFalseValidator;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import space.space_spring.entity.PayRequest;
import space.space_spring.entity.PayRequestTarget;
import space.space_spring.entity.Space;
import space.space_spring.entity.User;

import java.util.List;

@Repository
public class PayDao {

@PersistenceContext
private EntityManager em;

public List<PayRequest> findPayRequestListByUser(User user, Space space) {
// 유저가 해당 스페이스에서 요청한 정산 목록만을 select
// 아직 정산이 완료되지 않은 payRequest 엔티티만 select
String jpql = "SELECT pr FROM PayRequest pr WHERE pr.payCreateUser = :user AND pr.space = :space AND pr.isComplete = false";

return em.createQuery(jpql, PayRequest.class)
.setParameter("user", user)
.setParameter("space", space)
.getResultList();
}


public List<PayRequestTarget> findPayRequestTargetListByPayRequest(PayRequest payRequest) {
// 해당 정산 요청의 모든 타겟 엔티티를 select
String jpql = "SELECT prt FROM PayRequestTarget prt WHERE prt.payRequest = :payRequest";

return em.createQuery(jpql, PayRequestTarget.class)
.setParameter("payRequest", payRequest)
.getResultList();
}

public List<PayRequestTarget> findPayRequestTargetListByUser(User user, Space space) {
// 유저가 해당 스페이스에서 요청받은 정산 목록만을 select
// 유저가 요청받은 정산 중 아직 완료되지 않은 payRequestTarget 엔티티만 select
String jpql = "SELECT prt FROM PayRequestTarget prt " +
"JOIN prt.payRequest pr " +
"WHERE prt.targetUserId = :userId AND pr.space = :space AND pr.isComplete = false";

return em.createQuery(jpql, PayRequestTarget.class)
.setParameter("userId", user.getUserId())
.setParameter("space", space)
.getResultList();
}

}
16 changes: 16 additions & 0 deletions src/main/java/space/space_spring/dto/pay/GetPayViewResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package space.space_spring.dto.pay;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

@Getter
@AllArgsConstructor
public class GetPayViewResponse {

private List<PayRequestInfoDto> payRequestInfoDtoList = new ArrayList<>();

private List<PayReceiveInfoDto> payReceiveInfoDtoList = new ArrayList<>();
}
13 changes: 13 additions & 0 deletions src/main/java/space/space_spring/dto/pay/PayReceiveInfoDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package space.space_spring.dto.pay;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class PayReceiveInfoDto {

private String payCreatorName;

private int requestAmount;
}
17 changes: 17 additions & 0 deletions src/main/java/space/space_spring/dto/pay/PayRequestInfoDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package space.space_spring.dto.pay;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class PayRequestInfoDto {

private int totalAmount; // 정산 총 금액

private int receiveAmount; // 현재까지 받은 금액

private int totalTargetNum; // 정산 요청한 사람 수

private int receiveTargetNum; // 그 중, 돈 보낸 사람 수
}
44 changes: 44 additions & 0 deletions src/main/java/space/space_spring/entity/PayRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package space.space_spring.entity;

import jakarta.persistence.*;
import lombok.Getter;

@Getter
@Entity
@Table(name = "Pay_Request")
public class PayRequest extends BaseEntity {

@Id
@GeneratedValue
@Column(name = "pay_request_id")
private Long payRequestId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User payCreateUser; // 정산을 시작한 유저

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "space_id")
private Space space; // 정산이 이루어지는 스페이스

@Column(name = "total_amount")
private int totalAmount; // 정산의 총 금액

@Column(name = "pay_request_bank")
private String bankName; // 정산 받을 은행 이름

@Column(name = "bank_account_num")
private String bankAccountNum; // 정산 받을 은행 계좌번호

@Column(name = "is_complete")
private boolean isComplete;

public void savePayRequest(User payCreateUser, Space space, int totalAmount, String bankName, String bankAccountNum, boolean isComplete) {
this.payCreateUser = payCreateUser;
this.space = space;
this.totalAmount = totalAmount;
this.bankName = bankName;
this.bankAccountNum = bankAccountNum;
this.isComplete = isComplete;
}
}
34 changes: 34 additions & 0 deletions src/main/java/space/space_spring/entity/PayRequestTarget.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package space.space_spring.entity;

import jakarta.persistence.*;
import lombok.Getter;

@Entity
@Getter
public class PayRequestTarget extends BaseEntity {

@Id
@GeneratedValue
@Column(name = "pay_request_target_id")
private Long payRequestTargetId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "pay_request_id")
private PayRequest payRequest;

@Column(name = "target_user_id")
private Long targetUserId; // User 객체를 필드로 가지는 것보다 이게 더 낫나??

@Column(name = "request_amount")
private int requestAmount;

@Column(name = "is_complete")
private boolean isComplete;

public void savePayRequestTarget(PayRequest payRequest, Long targetUserId, int requestAmount, boolean isComplete) {
this.payRequest = payRequest;
this.targetUserId = targetUserId;
this.requestAmount = requestAmount;
this.isComplete = isComplete;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public enum BaseExceptionResponseStatus implements ResponseStatus {
* 6000: Space 오류
*/
INVALID_SPACE_CREATE(6000, HttpStatus.BAD_REQUEST.value(), "스페이스 생성 요청에서 잘못된 값이 존재합니다."),
safd(6001, HttpStatus.BAD_REQUEST.value(), "이미 존재하는 이메일입니다."),
SPACE_NOT_FOUND(6001, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 스페이스입니다."),
adff(6002, HttpStatus.BAD_REQUEST.value(), "이미 존재하는 닉네임입니다."),
baab(6003, HttpStatus.BAD_REQUEST.value(), "존재하지 않는 회원입니다."),
nff(6004, HttpStatus.BAD_REQUEST.value(), "비밀번호가 일치하지 않습니다."),
Expand Down
90 changes: 90 additions & 0 deletions src/main/java/space/space_spring/service/PayService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package space.space_spring.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import space.space_spring.dao.PayDao;
import space.space_spring.dto.pay.PayReceiveInfoDto;
import space.space_spring.dto.pay.PayRequestInfoDto;
import space.space_spring.entity.PayRequest;
import space.space_spring.entity.PayRequestTarget;
import space.space_spring.entity.Space;
import space.space_spring.entity.User;
import space.space_spring.util.space.SpaceUtils;
import space.space_spring.util.user.UserUtils;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class PayService {

private final PayDao payDao;
private final UserUtils userUtils;
private final SpaceUtils spaceUtils;

public List<PayRequestInfoDto> getPayRequestInfoForUser(Long userId, Long spaceId) {
// TODO 1. userId에 해당하는 user find
User userByUserId = userUtils.findUserByUserId(userId);

// TODO 2. spaceId에 해당하는 space find
Space spaceBySpaceId = spaceUtils.findSpaceBySpaceId(spaceId);

// TODO 3. 유저가 요청한 정산 중 진행 중인 정산 리스트 select
List<PayRequest> payRequestListByUser = payDao.findPayRequestListByUser(userByUserId, spaceBySpaceId);

// TODO 4. return 타입 구성
// 3-1. 각 payRequest 에 해당하는 모든 payRequestTarget 을 loop로 돌면서 데이터 수집
List<PayRequestInfoDto> payRequestInfoDtoList = new ArrayList<>();

for (PayRequest payRequest : payRequestListByUser) {
// 하나의 정산 요청에 대하여 ,,,
int totalAmount = payRequest.getTotalAmount();
int receiveAmount = 0;
int totalTargetNum = 0;
int receiveTargetNum = 0;

List<PayRequestTarget> payRequestTargetList = payDao.findPayRequestTargetListByPayRequest(payRequest);
for (PayRequestTarget payRequestTarget : payRequestTargetList) {
if (payRequestTarget.isComplete()) {
// 해당 타겟이 돈을 낸 경우
receiveAmount += payRequestTarget.getRequestAmount();
receiveTargetNum++;
}

totalTargetNum++;
}

PayRequestInfoDto payRequestInfoDto = new PayRequestInfoDto(totalAmount, receiveAmount, totalTargetNum, receiveTargetNum);
payRequestInfoDtoList.add(payRequestInfoDto);
}

return payRequestInfoDtoList;
}

public List<PayReceiveInfoDto> getPayReceiveInfoForUser(Long userId, Long spaceId) {
// TODO 1. userId에 해당하는 유저 find
User userByUserId = userUtils.findUserByUserId(userId);

// TODO 2. spaceId에 해당하는 space find
Space spaceBySpaceId = spaceUtils.findSpaceBySpaceId(spaceId);

// TODO 3. 유저가 요청받은 정산 중 진행 중인 정산 리스트 select
List<PayRequestTarget> payRequestTargetListByUser = payDao.findPayRequestTargetListByUser(userByUserId, spaceBySpaceId);

// TODO 4. return 타입 구성
// 3-1. 각 payRequestTarget 에 해당하는 정산 요청자, 정산 요청 금액 을 loop를 돌면서 데이터 수집
List<PayReceiveInfoDto> payReceiveInfoDtoList = new ArrayList<>();

for (PayRequestTarget payRequestTarget : payRequestTargetListByUser) {
String payCreatorName = payRequestTarget.getPayRequest().getPayCreateUser().getUserName(); // 리펙토링 필요
int requestAmount = payRequestTarget.getRequestAmount();

PayReceiveInfoDto payReceiveInfoDto = new PayReceiveInfoDto(payCreatorName, requestAmount);

payReceiveInfoDtoList.add(payReceiveInfoDto);
}

return payReceiveInfoDtoList;
}
}
Loading
Loading