Skip to content

Commit

Permalink
Merge pull request #61 from Donut-DONationUTile/feature/wallet
Browse files Browse the repository at this point in the history
Feature/wallet
  • Loading branch information
Kang1221 authored Apr 25, 2024
2 parents 9805eec + b0675e9 commit 59ca81b
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 10 deletions.
3 changes: 3 additions & 0 deletions src/main/java/zero/eight/donut/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.authorizeHttpRequests((auth) -> {
auth
.requestMatchers(permitList).permitAll()
////////////////////////////////////////
/* 역할 검증이 필요한 uri 추가하기 .permit */
////////////////////////////////////////
.anyRequest().authenticated();
})
// jwtFilter를 UsernamePasswordAuthenticationFilter 앞에 추가
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/zero/eight/donut/controller/WalletController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package zero.eight.donut.controller;

import lombok.RequiredArgsConstructor;
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 zero.eight.donut.common.response.ApiResponse;
import zero.eight.donut.service.WalletService;

@RequiredArgsConstructor
@RequestMapping("/api/wallet")
@RestController
public class WalletController {

private final WalletService walletService;

@GetMapping("/main")
public ApiResponse<?> walletMain() {
return walletService.walletMain();
}

@GetMapping("/{giftId}")
public ApiResponse<?> walletDetail(@PathVariable Long giftId) {
return walletService.walletDetail(giftId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import java.time.LocalDateTime;

@Getter
public class ReceiverGetGiftResponseDto {
public class GetGiftResponseDto {
private String product;
private Integer price;
private LocalDateTime dueDate;
Expand All @@ -18,7 +18,7 @@ public class ReceiverGetGiftResponseDto {
private Long boxId;

@Builder
public ReceiverGetGiftResponseDto(String product, Integer price, LocalDateTime dueDate, String imgUrl, Store store, Status status, Long boxId){
public GetGiftResponseDto(String product, Integer price, LocalDateTime dueDate, String imgUrl, Store store, Status status, Long boxId){
this.product = product;
this.price = price;
this.dueDate = dueDate;
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/zero/eight/donut/dto/wallet/WalletGiftInfoDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package zero.eight.donut.dto.wallet;

import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
@Builder
public class WalletGiftInfoDto {
private long giftId; // 기프티콘 고유 ID
private int days; // 디데이 남은 일수
private String store; // 사용처
private LocalDateTime dueDate; // 사용 기한
private String product; // 상품명
private int price; // 상품 금액
}
18 changes: 18 additions & 0 deletions src/main/java/zero/eight/donut/dto/wallet/WalletResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package zero.eight.donut.dto.wallet;

import lombok.Builder;
import lombok.Getter;

import java.util.List;

@Getter
@Builder
public class WalletResponseDto {
private int receiver; // 수혜자 수
private double amount; // 기프티콘 총액
private int cu; // 보유 기프티콘 개수(CU)
private int gs25; // 보유 기프티콘 개수(GS25)
private int seveneleven; // 보유 기프티콘 개수(7eleven)
private List<WalletGiftInfoDto> impendingList; // 임박 기프티콘 리스트
private List<WalletGiftInfoDto> giftList; // 일반 기프티콘 리스트
}
3 changes: 2 additions & 1 deletion src/main/java/zero/eight/donut/exception/Success.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public enum Success {
SUCCESS(HttpStatus.OK, "Request successfully processed"),

// 200 OK SUCCESS
GET_WALLET_SUCCESS(HttpStatus.OK, "Success in getting wallet info"),
HOME_GIVER_SUCCESS(HttpStatus.OK, "Get request for giver's home info completed successfully"),
HOME_RECEIVER_SUCCESS(HttpStatus.OK, "Get request for receiver's home info completed successfully"),
HOME_RECEIVER_BOX_SUCCESS(HttpStatus.OK, "Get request for receiver's giftbox info completed successfully"),
Expand All @@ -27,7 +28,7 @@ public enum Success {

//201 CREATED SUCCESS
ASSIGN_BENEFIT_SUCCESS(HttpStatus.CREATED, "Successfully assigned benefits"),
DONATE_GIFT_SUCCESS(HttpStatus.CREATED, "Successfully donate gift "),
DONATE_GIFT_SUCCESS(HttpStatus.CREATED, "Successfully donate gift"),
CREATE_REPORT_SUCCESS(HttpStatus.CREATED, "Your report is successfully registered"),
SIGN_IN_SUCCESS(HttpStatus.CREATED, "Sign in successfully"),
SIGN_UP_SUCCESS(HttpStatus.CREATED, "Successfully signed up"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import zero.eight.donut.domain.Gift;
import zero.eight.donut.domain.enums.Store;
import zero.eight.donut.domain.Giver;

import java.time.LocalDateTime;
import java.util.List;
Expand All @@ -23,4 +24,7 @@ public interface GiftRepository extends JpaRepository<Gift, Long> {
@Query(value = "SELECT * FROM gift g WHERE g.status = :status AND g.is_assigned = false" +
"AND g.due_date BETWEEN :startDate AND :endDate", nativeQuery = true)
List<Gift> findAllByNotAssignedAndStatusAndDueDateBetween(String status,LocalDateTime startDate, LocalDateTime endDate);

@Query(value = "SELECT * FROM gift g WHERE g.status = 'stored' AND g.giver_id = :giverId AND g.due_date >= :today", nativeQuery = true)
List<Gift> findAllByGiverAndStatusAndDueDateAfterOrToday(@Param("giverId") Long giverId, @Param("today") LocalDateTime today);
}
33 changes: 27 additions & 6 deletions src/main/java/zero/eight/donut/service/HomeReceiverService.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,39 @@ public ApiResponse receiverGetOneBox(Long boxId){
}
@Transactional
public ApiResponse receiverGetOneGift(Long giftId){
// 수혜자 여부 검증
if (!authUtils.getCurrentUserRole().equals(Role.ROLE_RECEIVER)) {
return ApiResponse.failure(Error.NOT_AUTHENTICATED_EXCEPTION);
}

// Security Config로 책임 전가
// // 수혜자 여부 검증
// if (!authUtils.getCurrentUserRole().equals(Role.ROLE_RECEIVER)) {
// return ApiResponse.failure(Error.NOT_AUTHENTICATED_EXCEPTION);
// }

//Gift 있는지 확인
Optional<Gift> giftOptional = giftRepository.findById(giftId);
if(giftOptional.isEmpty())
return ApiResponse.failure(Error.GIFT_NOT_FOUND_EXCEPTION);

Gift gift = giftOptional.get();

ReceiverGetGiftResponseDto responseDto = ReceiverGetGiftResponseDto.builder()
// 재사용을 위해 함수로 변경
/*
GetGiftResponseDto responseDto = GetGiftResponseDto.builder()
.product(gift.getProduct())
.price(gift.getPrice())
.dueDate(gift.getDueDate())
.imgUrl(gift.getImageUrl())
.store(gift.getStore())
.status(gift.getStatus())
.boxId(gift.getGiftbox().getId())
.build();
*/

return ApiResponse.success(Success.HOME_RECEIVER_GIFT_SUCCESS, getGiftInfo(giftId, gift));
}

public GetGiftResponseDto getGiftInfo(Long giftId, Gift gift){

return GetGiftResponseDto.builder()
.product(gift.getProduct())
.price(gift.getPrice())
.dueDate(gift.getDueDate())
Expand All @@ -149,6 +171,5 @@ public ApiResponse receiverGetOneGift(Long giftId){
.status(gift.getStatus())
.boxId(gift.getGiftbox().getId())
.build();
return ApiResponse.success(Success.HOME_RECEIVER_GIFT_SUCCESS, responseDto);
}
}
130 changes: 130 additions & 0 deletions src/main/java/zero/eight/donut/service/WalletService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package zero.eight.donut.service;

import lombok.RequiredArgsConstructor;
import org.springframework.cglib.core.Local;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import zero.eight.donut.common.response.ApiResponse;
import zero.eight.donut.config.jwt.AuthUtils;
import zero.eight.donut.domain.Gift;
import zero.eight.donut.domain.Giver;
import zero.eight.donut.domain.enums.Store;
import zero.eight.donut.dto.auth.Role;
import zero.eight.donut.dto.wallet.WalletGiftInfoDto;
import zero.eight.donut.dto.wallet.WalletResponseDto;
import zero.eight.donut.exception.Error;
import zero.eight.donut.exception.Success;
import zero.eight.donut.repository.GiftRepository;
import zero.eight.donut.repository.ReceiverRepository;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class WalletService {

private final AuthUtils authUtils;
private final ReceiverRepository receiverRepository;
private final GiftRepository giftRepository;
private final HomeReceiverService homeReceiverService;

@Transactional
// 월렛 화면 조회
public ApiResponse<?> walletMain() {
// 변수 선언
LocalDateTime now = LocalDateTime.now(); // 조회 시각
Giver giver = authUtils.getGiver(); // 기부자 정보
int receiver = receiverRepository.countBy(); // 수혜자 수
double amount = 0d; // 기프티콘 총액
int cu = 0; // 보유 기프티콘 개수(CU)
int gs25 = 0; // 보유 기프티콘 개수(GS25)
int seveneleven = 0; // 보유 기프티콘 개수(7eleven)
List<WalletGiftInfoDto> impendingList = new ArrayList<>(); // 임박 기프티콘 리스트
List<WalletGiftInfoDto> giftList = new ArrayList<>(); // 일반 기프티콘 리스트

// 월렛 기프티콘 리스트 조회
List<Gift> targetList = giftRepository.findAllByGiverAndStatusAndDueDateAfterOrToday(giver.getId(), now);

if (targetList != null || !targetList.isEmpty()) { // 보유 기프티콘이 있음
// 사용처별 기프티콘 개수 계산
Map<Store, Long> giftCountMap = countGiftsByStore(targetList);
cu = Math.toIntExact(giftCountMap.get(Store.CU));
gs25 = Math.toIntExact(giftCountMap.get(Store.GS25));
seveneleven = Math.toIntExact(giftCountMap.get(Store.SEVENELEVEN));

for (Gift g : targetList) {
// 기프티콘 총액 계산
amount += g.getPrice();
// 기프티콘 분류
if (g.getDueDate().isBefore(LocalDateTime.now().plusDays(30))) { // 유효 기간 30일 이내
// 임박 리스트에 할당
impendingList.add(
WalletGiftInfoDto.builder()
.giftId(g.getId())
.days(Math.toIntExact(Duration.between(now, g.getDueDate()).toDaysPart()))
.store(g.getStore().getStore())
.dueDate(g.getDueDate())
.product(g.getProduct())
.price(g.getPrice())
.build()
);
}
else { // 유효 기간 30일 이후
// 일반 리스트에 할당
giftList.add(
WalletGiftInfoDto.builder()
.giftId(g.getId())
.days(Math.toIntExact(Duration.between(now, g.getDueDate()).toDaysPart()))
.store(g.getStore().getStore())
.dueDate(g.getDueDate())
.product(g.getProduct())
.price(g.getPrice())
.build()
);
}
}
}

// response data 생성
WalletResponseDto responseDto = WalletResponseDto.builder()
.receiver(receiver)
.amount(amount)
.cu(cu)
.gs25(gs25)
.seveneleven(seveneleven)
.impendingList(impendingList)
.giftList(giftList)
.build();

return ApiResponse.success(Success.GET_WALLET_SUCCESS, responseDto);
}

// 사용처(store) 필드의 값마다 gift 개수 세기
public Map<Store, Long> countGiftsByStore(List<Gift> giftList) {
// Gift 객체 리스트를 사용처(store) 필드의 값마다 그룹화하여 각 그룹의 개수를 계산하여 Map으로 반환
return giftList.stream()
.collect(Collectors.groupingBy(Gift::getStore, Collectors.counting()));
}

@Transactional
public ApiResponse<?> walletDetail(Long giftId) {

// Security Config로 책임 전가
// // 기부자 여부 검증
// if (!authUtils.getCurrentUserRole().equals(Role.ROLE_GIVER)) {
// return ApiResponse.failure(Error.NOT_AUTHENTICATED_EXCEPTION);
// }

//Gift 있는지 확인
Optional<Gift> giftOptional = giftRepository.findById(giftId);
if(giftOptional.isEmpty())
return ApiResponse.failure(Error.GIFT_NOT_FOUND_EXCEPTION);

Gift gift = giftOptional.get();

return ApiResponse.success(Success.HOME_RECEIVER_GIFT_SUCCESS, homeReceiverService.getGiftInfo(giftId, gift));
}
}

0 comments on commit 59ca81b

Please sign in to comment.