diff --git a/src/main/java/com/jangburich/domain/payment/application/KakaopayService.java b/src/main/java/com/jangburich/domain/payment/application/KakaopayService.java index a4d2ee1..24e3cc8 100644 --- a/src/main/java/com/jangburich/domain/payment/application/KakaopayService.java +++ b/src/main/java/com/jangburich/domain/payment/application/KakaopayService.java @@ -130,7 +130,8 @@ public ApproveResponse payApprove(String pgToken) { .orElse(null); if (storeTeam != null) { - storeTeam.updatePoint(teamChargeHistory.getPaymentAmount()); + storeTeam.addPoint(teamChargeHistory.getPaymentAmount()); + storeTeam.addRemainPoint(teamChargeHistory.getPaymentAmount()); } else { storeTeamRepository.save( StoreTeam.create(teamChargeHistory.getTeam(), store, teamChargeHistory.getPaymentAmount())); diff --git a/src/main/java/com/jangburich/domain/payment/domain/TeamChargeHistoryResponse.java b/src/main/java/com/jangburich/domain/payment/domain/TeamChargeHistoryResponse.java new file mode 100644 index 0000000..3f9f663 --- /dev/null +++ b/src/main/java/com/jangburich/domain/payment/domain/TeamChargeHistoryResponse.java @@ -0,0 +1,22 @@ +package com.jangburich.domain.payment.domain; + +import com.querydsl.core.annotations.QueryProjection; + +import lombok.Builder; + +@Builder +public record TeamChargeHistoryResponse( + Long id, + String transactionId, + Integer paymentAmount, + PaymentChargeStatus paymentChargeStatus +) { + @QueryProjection + public TeamChargeHistoryResponse(Long id, String transactionId, Integer paymentAmount, + PaymentChargeStatus paymentChargeStatus) { + this.id = id; + this.transactionId = transactionId; + this.paymentAmount = paymentAmount; + this.paymentChargeStatus = paymentChargeStatus; + } +} diff --git a/src/main/java/com/jangburich/domain/payment/domain/repository/TeamChargeHistoryRepository.java b/src/main/java/com/jangburich/domain/payment/domain/repository/TeamChargeHistoryRepository.java index 1a43279..1ce99ae 100644 --- a/src/main/java/com/jangburich/domain/payment/domain/repository/TeamChargeHistoryRepository.java +++ b/src/main/java/com/jangburich/domain/payment/domain/repository/TeamChargeHistoryRepository.java @@ -1,11 +1,19 @@ package com.jangburich.domain.payment.domain.repository; import com.jangburich.domain.payment.domain.TeamChargeHistory; +import com.jangburich.domain.payment.domain.TeamChargeHistoryResponse; +import com.jangburich.domain.team.domain.Team; + import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface TeamChargeHistoryRepository extends JpaRepository { Optional findByTransactionId(String tid); + + Page findAllByTeam(Team team, Pageable pageable); } diff --git a/src/main/java/com/jangburich/domain/store/domain/StoreTeam.java b/src/main/java/com/jangburich/domain/store/domain/StoreTeam.java index 73db450..313380c 100644 --- a/src/main/java/com/jangburich/domain/store/domain/StoreTeam.java +++ b/src/main/java/com/jangburich/domain/store/domain/StoreTeam.java @@ -37,15 +37,27 @@ public class StoreTeam extends BaseEntity { @Column(name = "point") private Integer point; - public void updatePoint(Integer point) { + @Column(name = "remain_point") + private Integer remainPoint; + + public void addPoint(Integer point) { this.point += point; } + public void addRemainPoint(Integer point) { + this.remainPoint += point; + } + + public void subRemainPoint(Integer point) { + this.remainPoint -= point; + } + public static StoreTeam create(Team team, Store store, Integer point) { StoreTeam storeTeam = new StoreTeam(); storeTeam.setTeam(team); storeTeam.setStore(store); storeTeam.setPoint(point); + storeTeam.setRemainPoint(point); return storeTeam; } } \ No newline at end of file diff --git a/src/main/java/com/jangburich/domain/store/domain/StoreTeamResponseDTO.java b/src/main/java/com/jangburich/domain/store/domain/StoreTeamResponseDTO.java new file mode 100644 index 0000000..b2be3af --- /dev/null +++ b/src/main/java/com/jangburich/domain/store/domain/StoreTeamResponseDTO.java @@ -0,0 +1,25 @@ +package com.jangburich.domain.store.domain; + +import com.jangburich.domain.team.domain.Team; +import com.querydsl.core.annotations.QueryProjection; + +import lombok.Builder; + +@Builder +public record StoreTeamResponseDTO( + Long id, + Integer point, + Long teamId, + String teamName, + Long storeId + +) { + @QueryProjection + public StoreTeamResponseDTO(Long id, Integer point, Long teamId, String teamName, Long storeId) { + this.id = id; + this.point = point; + this.teamId = teamId; + this.teamName = teamName; + this.storeId = storeId; + } +} diff --git a/src/main/java/com/jangburich/domain/store/domain/controller/StoreController.java b/src/main/java/com/jangburich/domain/store/domain/controller/StoreController.java index cb60fb4..a60bd1e 100644 --- a/src/main/java/com/jangburich/domain/store/domain/controller/StoreController.java +++ b/src/main/java/com/jangburich/domain/store/domain/controller/StoreController.java @@ -1,9 +1,5 @@ package com.jangburich.domain.store.domain.controller; -import com.jangburich.domain.store.domain.Category; -import com.jangburich.domain.store.domain.dto.condition.StoreSearchCondition; -import com.jangburich.domain.store.domain.dto.condition.StoreSearchConditionWithType; -import com.jangburich.domain.store.domain.dto.response.SearchStoresResponse; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.security.core.Authentication; @@ -18,13 +14,20 @@ import org.springframework.web.bind.annotation.RestController; import com.jangburich.domain.oauth.domain.CustomOAuthUser; +import com.jangburich.domain.store.domain.Category; import com.jangburich.domain.store.domain.StoreAdditionalInfoCreateRequestDTO; import com.jangburich.domain.store.domain.StoreCreateRequestDTO; import com.jangburich.domain.store.domain.StoreGetResponseDTO; +import com.jangburich.domain.store.domain.StoreTeamResponseDTO; import com.jangburich.domain.store.domain.StoreUpdateRequestDTO; +import com.jangburich.domain.store.domain.dto.condition.StoreSearchCondition; +import com.jangburich.domain.store.domain.dto.condition.StoreSearchConditionWithType; +import com.jangburich.domain.store.domain.dto.response.PaymentGroupDetailResponse; +import com.jangburich.domain.store.domain.dto.response.SearchStoresResponse; import com.jangburich.domain.store.domain.service.StoreService; import com.jangburich.global.payload.Message; import com.jangburich.global.payload.ResponseCustom; +import com.jangburich.utils.parser.AuthenticationParser; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -41,24 +44,26 @@ public class StoreController { @Operation(summary = "카테고리 별 가게 목록 조회", description = "카테고리 별로 가게 목록을 조회합니다.") @GetMapping public ResponseCustom> searchByCategory( - Authentication authentication, - @RequestParam(required = false, defaultValue = "3") Integer searchRadius, - @RequestParam(required = false, defaultValue = "ALL") Category category, - @ModelAttribute StoreSearchCondition storeSearchCondition, - Pageable pageable + Authentication authentication, + @RequestParam(required = false, defaultValue = "3") Integer searchRadius, + @RequestParam(required = false, defaultValue = "ALL") Category category, + @ModelAttribute StoreSearchCondition storeSearchCondition, + Pageable pageable ) { - return ResponseCustom.OK(storeService.searchByCategory(authentication, searchRadius, category, storeSearchCondition, pageable)); + return ResponseCustom.OK( + storeService.searchByCategory(authentication, searchRadius, category, storeSearchCondition, pageable)); } @Operation(summary = "매장 찾기(검색)", description = "검색어와 매장 유형에 맞는 매장을 검색합니다.") @GetMapping("/search") public ResponseCustom> searchStores( - Authentication authentication, - @RequestParam(required = false, defaultValue = "") String keyword, - @ModelAttribute StoreSearchConditionWithType storeSearchConditionWithType, - Pageable pageable + Authentication authentication, + @RequestParam(required = false, defaultValue = "") String keyword, + @ModelAttribute StoreSearchConditionWithType storeSearchConditionWithType, + Pageable pageable ) { - return ResponseCustom.OK(storeService.searchStores(authentication, keyword, storeSearchConditionWithType, pageable)); + return ResponseCustom.OK( + storeService.searchStores(authentication, keyword, storeSearchConditionWithType, pageable)); } @Operation(summary = "가게 등록", description = "신규 파트너 가게를 등록합니다.") @@ -66,32 +71,26 @@ public ResponseCustom> searchStores( public ResponseCustom createStore(Authentication authentication, @RequestBody StoreCreateRequestDTO storeCreateRequestDTO) { CustomOAuthUser customOAuth2User = (CustomOAuthUser)authentication.getPrincipal(); - storeService.CreateStore(customOAuth2User, storeCreateRequestDTO); - return ResponseCustom.OK(Message.builder() - .message("success") - .build()); + storeService.createStore(customOAuth2User, storeCreateRequestDTO); + return ResponseCustom.OK(Message.builder().message("success").build()); } @Operation(summary = "가게 추가정보 저장", description = "예약 가능 여부, 최소 선결제 금액, 선결제 사용 기간을 저장합니다.") @PostMapping("/create/additionalInfo") - public ResponseCustom createAdditionalInfo(Authentication authentication, @RequestBody - StoreAdditionalInfoCreateRequestDTO storeAdditionalInfoCreateRequestDTO) { + public ResponseCustom createAdditionalInfo(Authentication authentication, + @RequestBody StoreAdditionalInfoCreateRequestDTO storeAdditionalInfoCreateRequestDTO) { CustomOAuthUser customOAuthUser = (CustomOAuthUser)authentication.getPrincipal(); - storeService.CreateAdditionalInfo(customOAuthUser, storeAdditionalInfoCreateRequestDTO); - return ResponseCustom.OK(Message.builder() - .message("success") - .build()); + storeService.createAdditionalInfo(customOAuthUser, storeAdditionalInfoCreateRequestDTO); + return ResponseCustom.OK(Message.builder().message("success").build()); } @Operation(summary = "가게 정보 수정", description = "가게 정보를 수정합니다.") @PatchMapping("/{storeId}/update") - public ResponseCustom updateStore(Authentication authentication, @PathVariable Long storeId, @RequestBody - StoreUpdateRequestDTO storeUpdateRequestDTO) { + public ResponseCustom updateStore(Authentication authentication, @PathVariable Long storeId, + @RequestBody StoreUpdateRequestDTO storeUpdateRequestDTO) { CustomOAuthUser principal = (CustomOAuthUser)authentication.getPrincipal(); storeService.updateStore(principal, storeId, storeUpdateRequestDTO); - return ResponseCustom.OK(Message.builder() - .message("success") - .build()); + return ResponseCustom.OK(Message.builder().message("success").build()); } @Operation(summary = "가게 정보 조회", description = "가게 상세 정보를 조회합니다.") @@ -100,4 +99,21 @@ public ResponseCustom getStoreInfo(Authentication authentic CustomOAuthUser customOAuth2User = (CustomOAuthUser)authentication.getPrincipal(); return ResponseCustom.OK(storeService.getStoreInfo(customOAuth2User)); } + + @Operation(summary = "결제 그룹 조회", description = "장부 결제 그룹을 조회합니다.") + @GetMapping("/payment_group") + public ResponseCustom> getPaymentGroup(Authentication authentication, + Pageable pageable) { + return ResponseCustom.OK( + storeService.getPaymentGroup(AuthenticationParser.parseUserId(authentication), pageable)); + } + + @Operation(summary = "결제 그룹 상세 조회", description = "장부 결제 그룹을 상세 조회합니다.") + @GetMapping("/payment_group/{teamId}") + public ResponseCustom getPaymentGroupDetail(Authentication authentication, + @PathVariable Long teamId, + Pageable pageable) { + return ResponseCustom.OK( + storeService.getPaymentGroupDetail(AuthenticationParser.parseUserId(authentication), teamId, pageable)); + } } \ No newline at end of file diff --git a/src/main/java/com/jangburich/domain/store/domain/dto/response/PaymentGroupDetailResponse.java b/src/main/java/com/jangburich/domain/store/domain/dto/response/PaymentGroupDetailResponse.java new file mode 100644 index 0000000..4b3e0e2 --- /dev/null +++ b/src/main/java/com/jangburich/domain/store/domain/dto/response/PaymentGroupDetailResponse.java @@ -0,0 +1,34 @@ +package com.jangburich.domain.store.domain.dto.response; + +import org.springframework.data.domain.Page; + +import com.jangburich.domain.payment.domain.TeamChargeHistoryResponse; +import com.jangburich.domain.user.domain.User; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@RequiredArgsConstructor +public class PaymentGroupDetailResponse { + private String teamName; + private Integer point; + private Integer remainPoint; + private String teamLeaderName; + private String teamLeaderPhoneNum; + private Page historyResponses; + + public static PaymentGroupDetailResponse create(String teamName, Integer point, Integer remainPoint, + User teamLeader, Page historyResponses) { + PaymentGroupDetailResponse paymentGroupDetailResponse = new PaymentGroupDetailResponse(); + paymentGroupDetailResponse.setTeamName(teamName); + paymentGroupDetailResponse.setPoint(point); + paymentGroupDetailResponse.setRemainPoint(remainPoint); + paymentGroupDetailResponse.setTeamLeaderName(teamLeader.getNickname()); + paymentGroupDetailResponse.setTeamLeaderPhoneNum(teamLeader.getPhoneNumber()); + paymentGroupDetailResponse.setHistoryResponses(historyResponses); + return paymentGroupDetailResponse; + } +} diff --git a/src/main/java/com/jangburich/domain/store/domain/repository/StoreTeamRepository.java b/src/main/java/com/jangburich/domain/store/domain/repository/StoreTeamRepository.java index 680fa95..e05e178 100644 --- a/src/main/java/com/jangburich/domain/store/domain/repository/StoreTeamRepository.java +++ b/src/main/java/com/jangburich/domain/store/domain/repository/StoreTeamRepository.java @@ -2,10 +2,16 @@ import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import com.jangburich.domain.store.domain.Store; import com.jangburich.domain.store.domain.StoreTeam; +import com.jangburich.domain.store.domain.StoreTeamResponseDTO; public interface StoreTeamRepository extends JpaRepository { Optional findByStoreIdAndTeamId(Long store_id, Long team_id); + + Page findAllByStore(Store store, Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/com/jangburich/domain/store/domain/service/StoreService.java b/src/main/java/com/jangburich/domain/store/domain/service/StoreService.java index 3e8e1a3..324e12d 100644 --- a/src/main/java/com/jangburich/domain/store/domain/service/StoreService.java +++ b/src/main/java/com/jangburich/domain/store/domain/service/StoreService.java @@ -1,10 +1,5 @@ package com.jangburich.domain.store.domain.service; -import com.jangburich.domain.store.domain.Category; -import com.jangburich.domain.store.domain.dto.condition.StoreSearchCondition; -import com.jangburich.domain.store.domain.dto.condition.StoreSearchConditionWithType; -import com.jangburich.domain.store.domain.dto.response.SearchStoresResponse; -import com.jangburich.utils.parser.AuthenticationParser; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.security.core.Authentication; @@ -14,16 +9,29 @@ import com.jangburich.domain.oauth.domain.CustomOAuthUser; import com.jangburich.domain.owner.domain.Owner; import com.jangburich.domain.owner.domain.repository.OwnerRepository; +import com.jangburich.domain.payment.domain.TeamChargeHistoryResponse; +import com.jangburich.domain.payment.domain.repository.TeamChargeHistoryRepository; +import com.jangburich.domain.store.domain.Category; import com.jangburich.domain.store.domain.Store; import com.jangburich.domain.store.domain.StoreAdditionalInfoCreateRequestDTO; import com.jangburich.domain.store.domain.StoreCreateRequestDTO; import com.jangburich.domain.store.domain.StoreGetResponseDTO; +import com.jangburich.domain.store.domain.StoreTeam; +import com.jangburich.domain.store.domain.StoreTeamResponseDTO; import com.jangburich.domain.store.domain.StoreUpdateRequestDTO; +import com.jangburich.domain.store.domain.dto.condition.StoreSearchCondition; +import com.jangburich.domain.store.domain.dto.condition.StoreSearchConditionWithType; +import com.jangburich.domain.store.domain.dto.response.PaymentGroupDetailResponse; +import com.jangburich.domain.store.domain.dto.response.SearchStoresResponse; import com.jangburich.domain.store.domain.repository.StoreRepository; +import com.jangburich.domain.store.domain.repository.StoreTeamRepository; +import com.jangburich.domain.team.domain.Team; +import com.jangburich.domain.team.domain.repository.TeamRepository; import com.jangburich.domain.user.domain.User; import com.jangburich.domain.user.domain.repository.UserRepository; import com.jangburich.global.error.DefaultNullPointerException; import com.jangburich.global.payload.ErrorCode; +import com.jangburich.utils.parser.AuthenticationParser; import lombok.RequiredArgsConstructor; @@ -34,9 +42,12 @@ public class StoreService { private final StoreRepository storeRepository; private final OwnerRepository ownerRepository; private final UserRepository userRepository; + private final StoreTeamRepository storeTeamRepository; + private final TeamRepository teamRepository; + private final TeamChargeHistoryRepository teamChargeHistoryRepository; @Transactional - public void CreateStore(CustomOAuthUser customOAuth2User, StoreCreateRequestDTO storeCreateRequestDTO) { + public void createStore(CustomOAuthUser customOAuth2User, StoreCreateRequestDTO storeCreateRequestDTO) { User user = userRepository.findByProviderId(customOAuth2User.getUserId()) .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); @@ -47,7 +58,7 @@ public void CreateStore(CustomOAuthUser customOAuth2User, StoreCreateRequestDTO } @Transactional - public void CreateAdditionalInfo(CustomOAuthUser customOAuthUser, + public void createAdditionalInfo(CustomOAuthUser customOAuthUser, StoreAdditionalInfoCreateRequestDTO storeAdditionalInfoCreateRequestDTO) { User user = userRepository.findByProviderId(customOAuthUser.getUserId()) .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); @@ -142,23 +153,62 @@ public StoreGetResponseDTO getStoreInfo(CustomOAuthUser customOAuth2User) { return new StoreGetResponseDTO().of(store); } + public Page getPaymentGroup(String userId, Pageable pageable) { + User user = userRepository.findByProviderId(userId) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + + Owner owner = ownerRepository.findByUser(user) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + + Store store = storeRepository.findByOwner(owner) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + + return storeTeamRepository.findAllByStore(store, pageable); + } + public Page searchByCategory(final Authentication authentication, - final Integer searchRadius, - final Category category, - final StoreSearchCondition storeSearchCondition, - final Pageable pageable) { + final Integer searchRadius, + final Category category, + final StoreSearchCondition storeSearchCondition, + final Pageable pageable) { String parsed = AuthenticationParser.parseUserId(authentication); User user = userRepository.findByProviderId(parsed) - .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); - return storeRepository.findStoresByCategory(user.getUserId(), searchRadius, category, storeSearchCondition, pageable); + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + return storeRepository.findStoresByCategory(user.getUserId(), searchRadius, category, storeSearchCondition, + pageable); } public Page searchStores(final Authentication authentication, final String keyword, - final StoreSearchConditionWithType storeSearchConditionWithType, - final Pageable pageable) { + final StoreSearchConditionWithType storeSearchConditionWithType, + final Pageable pageable) { String parsed = AuthenticationParser.parseUserId(authentication); User user = userRepository.findByProviderId(parsed) - .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); return storeRepository.findStores(user.getUserId(), keyword, storeSearchConditionWithType, pageable); } + + public PaymentGroupDetailResponse getPaymentGroupDetail(String userId, Long teamId, Pageable pageable) { + User user = userRepository.findByProviderId(userId) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + + Owner owner = ownerRepository.findByUser(user) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + + Store store = storeRepository.findByOwner(owner) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_AUTHENTICATION)); + + Team team = teamRepository.findById(teamId) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_PARAMETER)); + + User teamLeader = userRepository.findById(team.getTeamLeader().getUser_id()) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_PARAMETER)); + + StoreTeam storeTeam = storeTeamRepository.findByStoreIdAndTeamId(store.getId(), team.getId()) + .orElseThrow(() -> new DefaultNullPointerException(ErrorCode.INVALID_PARAMETER)); + + Page chargeHistoryRepositoryAllByTeam = teamChargeHistoryRepository.findAllByTeam( + team, pageable); + + return PaymentGroupDetailResponse.create(team.getName(), storeTeam.getPoint(), storeTeam.getRemainPoint(), teamLeader, chargeHistoryRepositoryAllByTeam); + } }