Skip to content

Commit cd47d13

Browse files
authored
Merge pull request #189 from 9oormthon-univ/feat/excel
Feat/excel
2 parents ec3a7c5 + 525164b commit cd47d13

File tree

7 files changed

+388
-113
lines changed

7 files changed

+388
-113
lines changed

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ dependencies {
6464
implementation 'com.sun.xml.ws:jaxws-rt:2.3.1'
6565
implementation 'org.glassfish.metro:webservices-rt:2.4.4'
6666
implementation fileTree(dir: 'libs', include: ['*.jar'])
67+
68+
// excel
69+
implementation 'org.apache.poi:poi:5.2.3' // .xls
70+
implementation 'org.apache.poi:poi-ooxml:5.2.3' // .xlsx
6771
}
6872

6973
tasks.named('test') {
Lines changed: 133 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package com.jangburich.domain.store.controller;
22

3-
import com.jangburich.domain.store.dto.response.StoreSearchDetailsResponse;
3+
import java.net.URLEncoder;
4+
import java.nio.charset.StandardCharsets;
5+
import java.time.LocalDate;
6+
import java.time.format.DateTimeFormatter;
47
import java.util.List;
58

69
import org.springframework.data.domain.Page;
710
import org.springframework.data.domain.Pageable;
11+
import org.springframework.http.HttpHeaders;
812
import org.springframework.http.MediaType;
13+
import org.springframework.http.ResponseEntity;
914
import org.springframework.security.core.Authentication;
1015
import org.springframework.web.bind.annotation.GetMapping;
1116
import org.springframework.web.bind.annotation.PatchMapping;
@@ -27,6 +32,7 @@
2732
import com.jangburich.domain.store.dto.response.OrdersTodayResponse;
2833
import com.jangburich.domain.store.dto.response.PaymentGroupDetailResponse;
2934
import com.jangburich.domain.store.dto.response.SearchStoresResponse;
35+
import com.jangburich.domain.store.dto.response.StoreSearchDetailsResponse;
3036
import com.jangburich.domain.store.dto.response.StoreTeamResponse;
3137
import com.jangburich.domain.store.service.StoreService;
3238
import com.jangburich.global.payload.Message;
@@ -44,108 +50,130 @@
4450
@RequestMapping("/store")
4551
public class StoreController {
4652

47-
private final StoreService storeService;
48-
49-
@Operation(summary = "카테고리 별 가게 목록 조회", description = "카테고리 별로 가게 목록을 조회합니다.")
50-
@PostMapping("/category")
51-
public ResponseCustom<Page<SearchStoresResponse>> searchByCategory(
52-
Authentication authentication,
53-
@RequestParam(required = false, defaultValue = "3") Integer searchRadius,
54-
@RequestParam(required = false, defaultValue = "ALL") Category category,
55-
Double lat,
56-
Double lon, Pageable pageable) {
57-
return ResponseCustom.OK(
58-
storeService.searchByCategory(AuthenticationParser.parseUserId(authentication), searchRadius, category, lat, lon,
59-
pageable));
60-
}
61-
62-
@Operation(summary = "매장 찾기(검색)", description = "검색어와 매장 유형에 맞는 매장을 검색합니다.")
63-
@GetMapping("/search")
64-
public ResponseCustom<Page<SearchStoresResponse>> searchStores(
65-
Authentication authentication,
66-
@RequestParam(required = false, defaultValue = "") String keyword, Pageable pageable) {
67-
return ResponseCustom.OK(
68-
storeService.searchStores(AuthenticationParser.parseUserId(authentication), keyword, pageable));
69-
}
70-
71-
@Operation(summary = "매장 상세 페이지 조회", description = "매장을 상세 조회합니다.")
72-
@GetMapping("/{storeId}")
73-
public ResponseCustom<StoreSearchDetailsResponse> storeSearchDetails(
74-
Authentication authentication,
75-
@PathVariable Long storeId
76-
) {
77-
return ResponseCustom.OK(storeService.storeSearchDetails(AuthenticationParser.parseUserId(authentication), storeId));
78-
}
79-
80-
@Operation(summary = "가게 등록", description = "신규 파트너 가게를 등록합니다.")
81-
@PostMapping(value = "/create", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
82-
public ResponseCustom<Message> createStore(
83-
Authentication authentication,
84-
@Parameter(name = "image", description = "업로드 사진 데이터") @RequestPart(value = "image") MultipartFile image,
85-
@RequestPart(value = "store") StoreCreateRequestDTO storeCreateRequestDTO,
86-
@RequestPart(value = "menuImages", required = false) List<MultipartFile> menuImages) {
87-
88-
storeService.createStore(AuthenticationParser.parseUserId(authentication), storeCreateRequestDTO, image,
89-
menuImages);
90-
return ResponseCustom.OK(Message.builder().message("success").build());
91-
}
92-
93-
94-
@Operation(summary = "가게 정보 수정", description = "가게 정보를 수정합니다.")
95-
@PatchMapping("/update")
96-
public ResponseCustom<Message> updateStore(Authentication authentication,
97-
@RequestBody StoreUpdateRequestDTO storeUpdateRequestDTO) {
98-
storeService.updateStore(AuthenticationParser.parseUserId(authentication), storeUpdateRequestDTO);
99-
return ResponseCustom.OK(Message.builder().message("success").build());
100-
}
101-
102-
@Operation(summary = "가게 정보 조회", description = "가게 상세 정보를 조회합니다.")
103-
@GetMapping("")
104-
public ResponseCustom<StoreGetResponseDTO> getStoreInfo(Authentication authentication) {
105-
return ResponseCustom.OK(storeService.getStoreInfo(AuthenticationParser.parseUserId(authentication)));
106-
}
107-
108-
@Operation(summary = "결제 그룹 조회", description = "장부 결제 그룹을 조회합니다.")
109-
@GetMapping("/payment_group")
110-
public ResponseCustom<List<StoreTeamResponse>> getPaymentGroup(Authentication authentication) {
111-
return ResponseCustom.OK(
112-
storeService.getPaymentGroup(AuthenticationParser.parseUserId(authentication)));
113-
}
114-
115-
@Operation(summary = "결제 그룹 상세 조회", description = "장부 결제 그룹을 상세 조회합니다.")
116-
@GetMapping("/payment_group/{teamId}")
117-
public ResponseCustom<PaymentGroupDetailResponse> getPaymentGroupDetail(Authentication authentication,
118-
@PathVariable Long teamId) {
119-
return ResponseCustom.OK(
120-
storeService.getPaymentGroupDetail(AuthenticationParser.parseUserId(authentication), teamId));
121-
}
122-
123-
@Operation(summary = "결제 내역 조회", description = "가게에서 일어난 결제 내역을 조회합니다.")
124-
@GetMapping("/payment_history")
125-
public ResponseCustom<?> getPaymentHistory(Authentication authentication) {
126-
return ResponseCustom.OK(
127-
storeService.getPaymentHistory(AuthenticationParser.parseUserId(authentication)));
128-
}
129-
130-
@Operation(summary = "지난 주문 조회", description = "가게에 있는 지난 주문을 조회합니다")
131-
@GetMapping("/orders/last")
132-
public ResponseCustom<List<OrdersGetResponse>> getLastOrders(Authentication authentication) {
133-
List<OrdersGetResponse> ordersLast = storeService.getOrdersLast(
134-
AuthenticationParser.parseUserId(authentication));
135-
return ResponseCustom.OK(ordersLast);
136-
}
137-
138-
@Operation(summary = "오늘 주문 조회", description = "가게에 있는 오늘 주문을 조회합니다")
139-
@GetMapping("/orders/today")
140-
public ResponseCustom<OrdersTodayResponse> getTodayOrders(Authentication authentication) {
141-
return ResponseCustom.OK(storeService.getTodayOrders(
142-
AuthenticationParser.parseUserId(authentication)));
143-
}
144-
145-
@Operation(summary = "주문 상세 조회", description = "가게에 있는 주문을 상세 조회합니다")
146-
@GetMapping("/orders/{ordersId}")
147-
public ResponseCustom<OrdersDetailResponse> getOrders(Authentication authentication, @RequestParam Long orderId) {
148-
return ResponseCustom.OK(
149-
storeService.getOrderDetails(AuthenticationParser.parseUserId(authentication), orderId));
150-
}
53+
private final StoreService storeService;
54+
55+
@Operation(summary = "카테고리 별 가게 목록 조회", description = "카테고리 별로 가게 목록을 조회합니다.")
56+
@PostMapping("/category")
57+
public ResponseCustom<Page<SearchStoresResponse>> searchByCategory(
58+
Authentication authentication,
59+
@RequestParam(required = false, defaultValue = "3") Integer searchRadius,
60+
@RequestParam(required = false, defaultValue = "ALL") Category category,
61+
Double lat,
62+
Double lon, Pageable pageable) {
63+
return ResponseCustom.OK(
64+
storeService.searchByCategory(AuthenticationParser.parseUserId(authentication), searchRadius, category, lat,
65+
lon,
66+
pageable));
67+
}
68+
69+
@Operation(summary = "매장 찾기(검색)", description = "검색어와 매장 유형에 맞는 매장을 검색합니다.")
70+
@GetMapping("/search")
71+
public ResponseCustom<Page<SearchStoresResponse>> searchStores(
72+
Authentication authentication,
73+
@RequestParam(required = false, defaultValue = "") String keyword, Pageable pageable) {
74+
return ResponseCustom.OK(
75+
storeService.searchStores(AuthenticationParser.parseUserId(authentication), keyword, pageable));
76+
}
77+
78+
@Operation(summary = "매장 상세 페이지 조회", description = "매장을 상세 조회합니다.")
79+
@GetMapping("/{storeId}")
80+
public ResponseCustom<StoreSearchDetailsResponse> storeSearchDetails(
81+
Authentication authentication,
82+
@PathVariable Long storeId
83+
) {
84+
return ResponseCustom.OK(
85+
storeService.storeSearchDetails(AuthenticationParser.parseUserId(authentication), storeId));
86+
}
87+
88+
@Operation(summary = "가게 등록", description = "신규 파트너 가게를 등록합니다.")
89+
@PostMapping(value = "/create", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
90+
public ResponseCustom<Message> createStore(
91+
Authentication authentication,
92+
@Parameter(name = "image", description = "업로드 사진 데이터") @RequestPart(value = "image") MultipartFile image,
93+
@RequestPart(value = "store") StoreCreateRequestDTO storeCreateRequestDTO,
94+
@RequestPart(value = "menuImages", required = false) List<MultipartFile> menuImages) {
95+
96+
storeService.createStore(AuthenticationParser.parseUserId(authentication), storeCreateRequestDTO, image,
97+
menuImages);
98+
return ResponseCustom.OK(Message.builder().message("success").build());
99+
}
100+
101+
@Operation(summary = "가게 정보 수정", description = "가게 정보를 수정합니다.")
102+
@PatchMapping("/update")
103+
public ResponseCustom<Message> updateStore(Authentication authentication,
104+
@RequestBody StoreUpdateRequestDTO storeUpdateRequestDTO) {
105+
storeService.updateStore(AuthenticationParser.parseUserId(authentication), storeUpdateRequestDTO);
106+
return ResponseCustom.OK(Message.builder().message("success").build());
107+
}
108+
109+
@Operation(summary = "가게 정보 조회", description = "가게 상세 정보를 조회합니다.")
110+
@GetMapping("")
111+
public ResponseCustom<StoreGetResponseDTO> getStoreInfo(Authentication authentication) {
112+
return ResponseCustom.OK(storeService.getStoreInfo(AuthenticationParser.parseUserId(authentication)));
113+
}
114+
115+
@Operation(summary = "결제 그룹 조회", description = "장부 결제 그룹을 조회합니다.")
116+
@GetMapping("/payment_group")
117+
public ResponseCustom<List<StoreTeamResponse>> getPaymentGroup(Authentication authentication) {
118+
return ResponseCustom.OK(
119+
storeService.getPaymentGroup(AuthenticationParser.parseUserId(authentication)));
120+
}
121+
122+
@Operation(summary = "결제 그룹 상세 조회", description = "장부 결제 그룹을 상세 조회합니다.")
123+
@GetMapping("/payment_group/{teamId}")
124+
public ResponseCustom<PaymentGroupDetailResponse> getPaymentGroupDetail(Authentication authentication,
125+
@PathVariable Long teamId) {
126+
return ResponseCustom.OK(
127+
storeService.getPaymentGroupDetail(AuthenticationParser.parseUserId(authentication), teamId));
128+
}
129+
130+
@Operation(summary = "결제 내역 조회", description = "가게에서 일어난 결제 내역을 조회합니다.")
131+
@GetMapping("/payment_history")
132+
public ResponseCustom<?> getPaymentHistory(Authentication authentication) {
133+
return ResponseCustom.OK(
134+
storeService.getPaymentHistory(AuthenticationParser.parseUserId(authentication)));
135+
}
136+
137+
@Operation(summary = "지난 주문 조회", description = "가게에 있는 지난 주문을 조회합니다")
138+
@GetMapping("/orders/last")
139+
public ResponseCustom<List<OrdersGetResponse>> getLastOrders(Authentication authentication) {
140+
List<OrdersGetResponse> ordersLast = storeService.getOrdersLast(
141+
AuthenticationParser.parseUserId(authentication));
142+
return ResponseCustom.OK(ordersLast);
143+
}
144+
145+
@Operation(summary = "오늘 주문 조회", description = "가게에 있는 오늘 주문을 조회합니다")
146+
@GetMapping("/orders/today")
147+
public ResponseCustom<OrdersTodayResponse> getTodayOrders(Authentication authentication) {
148+
return ResponseCustom.OK(storeService.getTodayOrders(
149+
AuthenticationParser.parseUserId(authentication)));
150+
}
151+
152+
@Operation(summary = "주문 상세 조회", description = "가게에 있는 주문을 상세 조회합니다")
153+
@GetMapping("/orders/{ordersId}")
154+
public ResponseCustom<OrdersDetailResponse> getOrders(Authentication authentication, @RequestParam Long orderId) {
155+
return ResponseCustom.OK(
156+
storeService.getOrderDetails(AuthenticationParser.parseUserId(authentication), orderId));
157+
}
158+
159+
@Operation(summary = "가게 엑셀 다운로드", description = "가게 장부 세부 내역을 엑셀로 제공합니다.")
160+
@GetMapping("/excel")
161+
public ResponseEntity<?> getExcel(
162+
// Authentication authentication,
163+
@RequestParam(defaultValue = "1") Integer period
164+
) {
165+
byte[] excel = storeService.createExcel("test-owner", period);
166+
167+
String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
168+
String fileName = "장부_세부내역_" + period + "개월_" + today + ".xlsx";
169+
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
170+
.replace("+", "%20");
171+
172+
HttpHeaders headers = new HttpHeaders();
173+
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
174+
headers.set("Content-Disposition",
175+
"attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
176+
177+
return ResponseEntity.ok().headers(headers).body(excel);
178+
}
151179
}
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
package com.jangburich.domain.store.domain;
22

3-
import java.time.LocalDate;
43
import java.time.LocalDateTime;
54

5+
import com.jangburich.domain.point.domain.TransactionType;
66
import com.querydsl.core.annotations.QueryProjection;
77

88
public record StoreChargeHistoryResponse(
99
Long id,
1010
LocalDateTime createdAt,
1111
String teamName,
12-
Integer transactionedPoint
12+
Long teamId,
13+
Integer transactionedPoint,
14+
TransactionType transactionType
1315
) {
1416
@QueryProjection
15-
public StoreChargeHistoryResponse(Long id, LocalDateTime createdAt, String teamName, Integer transactionedPoint) {
17+
public StoreChargeHistoryResponse(Long id, LocalDateTime createdAt, String teamName, Long teamId,
18+
Integer transactionedPoint, TransactionType transactionType) {
1619
this.id = id;
1720
this.createdAt = createdAt;
1821
this.teamName = teamName;
22+
this.teamId = teamId;
1923
this.transactionedPoint = transactionedPoint;
24+
this.transactionType = transactionType;
2025
}
2126
}

src/main/java/com/jangburich/domain/store/domain/StoreTeam.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ public class StoreTeam extends BaseEntity {
4848
@Column(name = "prepaid_expiration_date")
4949
private LocalDate prepaidExpirationDate;
5050

51+
@Column(name = "prepay_count")
52+
private Integer prepayCount;
53+
5154
public void updatePersonalAllocatedPoint(Integer point) {
5255
this.personalAllocatedPoint = point;
5356
}

src/main/java/com/jangburich/domain/store/domain/StoreTeamResponseDTO.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
public record StoreTeamResponseDTO(
1111
Long id,
1212
Integer remainPoint,
13+
Integer point,
1314
Long teamId,
1415
String teamName,
1516
String teamDescription,
@@ -18,10 +19,11 @@ public record StoreTeamResponseDTO(
1819

1920
) {
2021
@QueryProjection
21-
public StoreTeamResponseDTO(Long id, Integer remainPoint, Long teamId, String teamName, String teamDescription,
22-
Long storeId, LocalDateTime updatedAt) {
22+
public StoreTeamResponseDTO(Long id, Integer remainPoint, Integer point, Long teamId, String teamName,
23+
String teamDescription, Long storeId, LocalDateTime updatedAt) {
2324
this.id = id;
2425
this.remainPoint = remainPoint;
26+
this.point = point;
2527
this.teamId = teamId;
2628
this.teamName = teamName;
2729
this.teamDescription = teamDescription;

src/main/java/com/jangburich/domain/store/service/PrepayService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public Message prepay(String userId, PrepayRequest prepayRequest) {
6969
.transactionedPoint(prepayRequest.prepayAmount())
7070
.user(user)
7171
.store(store)
72+
.team(team)
7273
.build();
7374

7475
pointTransactionRepository.save(pointTransaction);
@@ -94,6 +95,7 @@ public Message prepay(String userId, PrepayRequest prepayRequest) {
9495
StoreTeam storeTeam = storeAndTeam.get();
9596
storeTeam.setPersonalAllocatedPoint(prepayRequest.personalAllocatedAmount());
9697
storeTeam.recharge(prepayRequest.prepayAmount());
98+
storeTeam.setPrepayCount(storeTeam.getPrepayCount() + 1);
9799

98100
return Message.builder()
99101
.message("매장 선결제가 완료되었습니다.")

0 commit comments

Comments
 (0)