Skip to content

Commit 59ca81b

Browse files
authored
Merge pull request #61 from Donut-DONationUTile/feature/wallet
Feature/wallet
2 parents 9805eec + b0675e9 commit 59ca81b

File tree

9 files changed

+231
-10
lines changed

9 files changed

+231
-10
lines changed

src/main/java/zero/eight/donut/config/SecurityConfig.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
4242
.authorizeHttpRequests((auth) -> {
4343
auth
4444
.requestMatchers(permitList).permitAll()
45+
////////////////////////////////////////
46+
/* 역할 검증이 필요한 uri 추가하기 .permit */
47+
////////////////////////////////////////
4548
.anyRequest().authenticated();
4649
})
4750
// jwtFilter를 UsernamePasswordAuthenticationFilter 앞에 추가
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package zero.eight.donut.controller;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.PathVariable;
6+
import org.springframework.web.bind.annotation.RequestMapping;
7+
import org.springframework.web.bind.annotation.RestController;
8+
import zero.eight.donut.common.response.ApiResponse;
9+
import zero.eight.donut.service.WalletService;
10+
11+
@RequiredArgsConstructor
12+
@RequestMapping("/api/wallet")
13+
@RestController
14+
public class WalletController {
15+
16+
private final WalletService walletService;
17+
18+
@GetMapping("/main")
19+
public ApiResponse<?> walletMain() {
20+
return walletService.walletMain();
21+
}
22+
23+
@GetMapping("/{giftId}")
24+
public ApiResponse<?> walletDetail(@PathVariable Long giftId) {
25+
return walletService.walletDetail(giftId);
26+
}
27+
}

src/main/java/zero/eight/donut/dto/home/receiver/ReceiverGetGiftResponseDto.java renamed to src/main/java/zero/eight/donut/dto/home/receiver/GetGiftResponseDto.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.time.LocalDateTime;
99

1010
@Getter
11-
public class ReceiverGetGiftResponseDto {
11+
public class GetGiftResponseDto {
1212
private String product;
1313
private Integer price;
1414
private LocalDateTime dueDate;
@@ -18,7 +18,7 @@ public class ReceiverGetGiftResponseDto {
1818
private Long boxId;
1919

2020
@Builder
21-
public ReceiverGetGiftResponseDto(String product, Integer price, LocalDateTime dueDate, String imgUrl, Store store, Status status, Long boxId){
21+
public GetGiftResponseDto(String product, Integer price, LocalDateTime dueDate, String imgUrl, Store store, Status status, Long boxId){
2222
this.product = product;
2323
this.price = price;
2424
this.dueDate = dueDate;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package zero.eight.donut.dto.wallet;
2+
3+
import lombok.Builder;
4+
import lombok.Getter;
5+
6+
import java.time.LocalDateTime;
7+
8+
@Getter
9+
@Builder
10+
public class WalletGiftInfoDto {
11+
private long giftId; // 기프티콘 고유 ID
12+
private int days; // 디데이 남은 일수
13+
private String store; // 사용처
14+
private LocalDateTime dueDate; // 사용 기한
15+
private String product; // 상품명
16+
private int price; // 상품 금액
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package zero.eight.donut.dto.wallet;
2+
3+
import lombok.Builder;
4+
import lombok.Getter;
5+
6+
import java.util.List;
7+
8+
@Getter
9+
@Builder
10+
public class WalletResponseDto {
11+
private int receiver; // 수혜자 수
12+
private double amount; // 기프티콘 총액
13+
private int cu; // 보유 기프티콘 개수(CU)
14+
private int gs25; // 보유 기프티콘 개수(GS25)
15+
private int seveneleven; // 보유 기프티콘 개수(7eleven)
16+
private List<WalletGiftInfoDto> impendingList; // 임박 기프티콘 리스트
17+
private List<WalletGiftInfoDto> giftList; // 일반 기프티콘 리스트
18+
}

src/main/java/zero/eight/donut/exception/Success.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public enum Success {
1313
SUCCESS(HttpStatus.OK, "Request successfully processed"),
1414

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

2829
//201 CREATED SUCCESS
2930
ASSIGN_BENEFIT_SUCCESS(HttpStatus.CREATED, "Successfully assigned benefits"),
30-
DONATE_GIFT_SUCCESS(HttpStatus.CREATED, "Successfully donate gift "),
31+
DONATE_GIFT_SUCCESS(HttpStatus.CREATED, "Successfully donate gift"),
3132
CREATE_REPORT_SUCCESS(HttpStatus.CREATED, "Your report is successfully registered"),
3233
SIGN_IN_SUCCESS(HttpStatus.CREATED, "Sign in successfully"),
3334
SIGN_UP_SUCCESS(HttpStatus.CREATED, "Successfully signed up"),

src/main/java/zero/eight/donut/repository/GiftRepository.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
import org.springframework.data.jpa.repository.JpaRepository;
44
import org.springframework.data.jpa.repository.Query;
5+
import org.springframework.data.repository.query.Param;
56
import zero.eight.donut.domain.Gift;
6-
import zero.eight.donut.domain.enums.Store;
7+
import zero.eight.donut.domain.Giver;
78

89
import java.time.LocalDateTime;
910
import java.util.List;
@@ -23,4 +24,7 @@ public interface GiftRepository extends JpaRepository<Gift, Long> {
2324
@Query(value = "SELECT * FROM gift g WHERE g.status = :status AND g.is_assigned = false" +
2425
"AND g.due_date BETWEEN :startDate AND :endDate", nativeQuery = true)
2526
List<Gift> findAllByNotAssignedAndStatusAndDueDateBetween(String status,LocalDateTime startDate, LocalDateTime endDate);
27+
28+
@Query(value = "SELECT * FROM gift g WHERE g.status = 'stored' AND g.giver_id = :giverId AND g.due_date >= :today", nativeQuery = true)
29+
List<Gift> findAllByGiverAndStatusAndDueDateAfterOrToday(@Param("giverId") Long giverId, @Param("today") LocalDateTime today);
2630
}

src/main/java/zero/eight/donut/service/HomeReceiverService.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,39 @@ public ApiResponse receiverGetOneBox(Long boxId){
130130
}
131131
@Transactional
132132
public ApiResponse receiverGetOneGift(Long giftId){
133-
// 수혜자 여부 검증
134-
if (!authUtils.getCurrentUserRole().equals(Role.ROLE_RECEIVER)) {
135-
return ApiResponse.failure(Error.NOT_AUTHENTICATED_EXCEPTION);
136-
}
133+
134+
// Security Config로 책임 전가
135+
// // 수혜자 여부 검증
136+
// if (!authUtils.getCurrentUserRole().equals(Role.ROLE_RECEIVER)) {
137+
// return ApiResponse.failure(Error.NOT_AUTHENTICATED_EXCEPTION);
138+
// }
139+
137140
//Gift 있는지 확인
138141
Optional<Gift> giftOptional = giftRepository.findById(giftId);
139142
if(giftOptional.isEmpty())
140143
return ApiResponse.failure(Error.GIFT_NOT_FOUND_EXCEPTION);
144+
141145
Gift gift = giftOptional.get();
142146

143-
ReceiverGetGiftResponseDto responseDto = ReceiverGetGiftResponseDto.builder()
147+
// 재사용을 위해 함수로 변경
148+
/*
149+
GetGiftResponseDto responseDto = GetGiftResponseDto.builder()
150+
.product(gift.getProduct())
151+
.price(gift.getPrice())
152+
.dueDate(gift.getDueDate())
153+
.imgUrl(gift.getImageUrl())
154+
.store(gift.getStore())
155+
.status(gift.getStatus())
156+
.boxId(gift.getGiftbox().getId())
157+
.build();
158+
*/
159+
160+
return ApiResponse.success(Success.HOME_RECEIVER_GIFT_SUCCESS, getGiftInfo(giftId, gift));
161+
}
162+
163+
public GetGiftResponseDto getGiftInfo(Long giftId, Gift gift){
164+
165+
return GetGiftResponseDto.builder()
144166
.product(gift.getProduct())
145167
.price(gift.getPrice())
146168
.dueDate(gift.getDueDate())
@@ -149,6 +171,5 @@ public ApiResponse receiverGetOneGift(Long giftId){
149171
.status(gift.getStatus())
150172
.boxId(gift.getGiftbox().getId())
151173
.build();
152-
return ApiResponse.success(Success.HOME_RECEIVER_GIFT_SUCCESS, responseDto);
153174
}
154175
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package zero.eight.donut.service;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import org.springframework.cglib.core.Local;
5+
import org.springframework.stereotype.Service;
6+
import org.springframework.transaction.annotation.Transactional;
7+
import zero.eight.donut.common.response.ApiResponse;
8+
import zero.eight.donut.config.jwt.AuthUtils;
9+
import zero.eight.donut.domain.Gift;
10+
import zero.eight.donut.domain.Giver;
11+
import zero.eight.donut.domain.enums.Store;
12+
import zero.eight.donut.dto.auth.Role;
13+
import zero.eight.donut.dto.wallet.WalletGiftInfoDto;
14+
import zero.eight.donut.dto.wallet.WalletResponseDto;
15+
import zero.eight.donut.exception.Error;
16+
import zero.eight.donut.exception.Success;
17+
import zero.eight.donut.repository.GiftRepository;
18+
import zero.eight.donut.repository.ReceiverRepository;
19+
20+
import java.time.Duration;
21+
import java.time.LocalDateTime;
22+
import java.util.*;
23+
import java.util.stream.Collectors;
24+
25+
@RequiredArgsConstructor
26+
@Service
27+
public class WalletService {
28+
29+
private final AuthUtils authUtils;
30+
private final ReceiverRepository receiverRepository;
31+
private final GiftRepository giftRepository;
32+
private final HomeReceiverService homeReceiverService;
33+
34+
@Transactional
35+
// 월렛 화면 조회
36+
public ApiResponse<?> walletMain() {
37+
// 변수 선언
38+
LocalDateTime now = LocalDateTime.now(); // 조회 시각
39+
Giver giver = authUtils.getGiver(); // 기부자 정보
40+
int receiver = receiverRepository.countBy(); // 수혜자 수
41+
double amount = 0d; // 기프티콘 총액
42+
int cu = 0; // 보유 기프티콘 개수(CU)
43+
int gs25 = 0; // 보유 기프티콘 개수(GS25)
44+
int seveneleven = 0; // 보유 기프티콘 개수(7eleven)
45+
List<WalletGiftInfoDto> impendingList = new ArrayList<>(); // 임박 기프티콘 리스트
46+
List<WalletGiftInfoDto> giftList = new ArrayList<>(); // 일반 기프티콘 리스트
47+
48+
// 월렛 기프티콘 리스트 조회
49+
List<Gift> targetList = giftRepository.findAllByGiverAndStatusAndDueDateAfterOrToday(giver.getId(), now);
50+
51+
if (targetList != null || !targetList.isEmpty()) { // 보유 기프티콘이 있음
52+
// 사용처별 기프티콘 개수 계산
53+
Map<Store, Long> giftCountMap = countGiftsByStore(targetList);
54+
cu = Math.toIntExact(giftCountMap.get(Store.CU));
55+
gs25 = Math.toIntExact(giftCountMap.get(Store.GS25));
56+
seveneleven = Math.toIntExact(giftCountMap.get(Store.SEVENELEVEN));
57+
58+
for (Gift g : targetList) {
59+
// 기프티콘 총액 계산
60+
amount += g.getPrice();
61+
// 기프티콘 분류
62+
if (g.getDueDate().isBefore(LocalDateTime.now().plusDays(30))) { // 유효 기간 30일 이내
63+
// 임박 리스트에 할당
64+
impendingList.add(
65+
WalletGiftInfoDto.builder()
66+
.giftId(g.getId())
67+
.days(Math.toIntExact(Duration.between(now, g.getDueDate()).toDaysPart()))
68+
.store(g.getStore().getStore())
69+
.dueDate(g.getDueDate())
70+
.product(g.getProduct())
71+
.price(g.getPrice())
72+
.build()
73+
);
74+
}
75+
else { // 유효 기간 30일 이후
76+
// 일반 리스트에 할당
77+
giftList.add(
78+
WalletGiftInfoDto.builder()
79+
.giftId(g.getId())
80+
.days(Math.toIntExact(Duration.between(now, g.getDueDate()).toDaysPart()))
81+
.store(g.getStore().getStore())
82+
.dueDate(g.getDueDate())
83+
.product(g.getProduct())
84+
.price(g.getPrice())
85+
.build()
86+
);
87+
}
88+
}
89+
}
90+
91+
// response data 생성
92+
WalletResponseDto responseDto = WalletResponseDto.builder()
93+
.receiver(receiver)
94+
.amount(amount)
95+
.cu(cu)
96+
.gs25(gs25)
97+
.seveneleven(seveneleven)
98+
.impendingList(impendingList)
99+
.giftList(giftList)
100+
.build();
101+
102+
return ApiResponse.success(Success.GET_WALLET_SUCCESS, responseDto);
103+
}
104+
105+
// 사용처(store) 필드의 값마다 gift 개수 세기
106+
public Map<Store, Long> countGiftsByStore(List<Gift> giftList) {
107+
// Gift 객체 리스트를 사용처(store) 필드의 값마다 그룹화하여 각 그룹의 개수를 계산하여 Map으로 반환
108+
return giftList.stream()
109+
.collect(Collectors.groupingBy(Gift::getStore, Collectors.counting()));
110+
}
111+
112+
@Transactional
113+
public ApiResponse<?> walletDetail(Long giftId) {
114+
115+
// Security Config로 책임 전가
116+
// // 기부자 여부 검증
117+
// if (!authUtils.getCurrentUserRole().equals(Role.ROLE_GIVER)) {
118+
// return ApiResponse.failure(Error.NOT_AUTHENTICATED_EXCEPTION);
119+
// }
120+
121+
//Gift 있는지 확인
122+
Optional<Gift> giftOptional = giftRepository.findById(giftId);
123+
if(giftOptional.isEmpty())
124+
return ApiResponse.failure(Error.GIFT_NOT_FOUND_EXCEPTION);
125+
126+
Gift gift = giftOptional.get();
127+
128+
return ApiResponse.success(Success.HOME_RECEIVER_GIFT_SUCCESS, homeReceiverService.getGiftInfo(giftId, gift));
129+
}
130+
}

0 commit comments

Comments
 (0)