Skip to content

Commit 84f2646

Browse files
authored
Merge pull request #33 from MUIT-UMC/fix/corsConfig
[fix] CORS 에러 해결 설정 추가
2 parents 00a3080 + 599eaf3 commit 84f2646

8 files changed

+221
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package muit.backend.config;
2+
3+
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.web.servlet.config.annotation.CorsRegistry;
6+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
7+
8+
@Configuration
9+
public class WebConfig implements WebMvcConfigurer {
10+
@Override
11+
public void addCorsMappings(CorsRegistry registry) {
12+
registry.addMapping("/**")
13+
.allowedOrigins("http://localhost:5173")
14+
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH")
15+
.allowedHeaders("*")
16+
.allowCredentials(true)
17+
.maxAge(3600);
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package muit.backend.controller;
2+
3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.tags.Tag;
5+
import lombok.RequiredArgsConstructor;
6+
import muit.backend.apiPayLoad.ApiResponse;
7+
import muit.backend.dto.manageReservDTO.ManageReservResponseDTO;
8+
import muit.backend.service.ManageReservService;
9+
import org.springdoc.core.annotations.ParameterObject;
10+
import org.springframework.data.domain.Page;
11+
import org.springframework.data.domain.Pageable;
12+
import org.springframework.web.bind.annotation.GetMapping;
13+
import org.springframework.web.bind.annotation.RequestMapping;
14+
import org.springframework.web.bind.annotation.RequestParam;
15+
import org.springframework.web.bind.annotation.RestController;
16+
17+
import java.util.Set;
18+
19+
@Tag(name = "어드민이 공연 예약 관리")
20+
@RestController
21+
@RequiredArgsConstructor
22+
@RequestMapping("/admin/amateur-reservations")
23+
public class ManageReservController {
24+
25+
private final ManageReservService manageReservService;
26+
27+
@Operation(summary = "전체 공연 예약 조회")
28+
@GetMapping
29+
public ApiResponse<Page<ManageReservResponseDTO.ManageReservResultListDTO>> getAllReservations(@ParameterObject Pageable pageable,
30+
@RequestParam(required = false) String keyword,
31+
@RequestParam(required = false) Set<String> selectedFields) {
32+
Page<ManageReservResponseDTO.ManageReservResultListDTO> reservations = manageReservService.getAllReservations(pageable, keyword, selectedFields);
33+
return ApiResponse.onSuccess(reservations);
34+
}
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package muit.backend.converter;
2+
3+
import muit.backend.domain.entity.amateur.AmateurShow;
4+
import muit.backend.domain.entity.member.MemberTicket;
5+
import muit.backend.domain.entity.member.Reservation;
6+
import muit.backend.dto.manageReservDTO.ManageReservResponseDTO;
7+
8+
import java.util.Set;
9+
10+
public class ManageReservConverter {
11+
12+
// reservation에서 amateurshow 가져오기
13+
private static AmateurShow getAmateurShowFromReservation(Reservation reservation) {
14+
return reservation.getMemberTicketList().stream()
15+
.findFirst() // 아무 티켓이나 봐도 같은 공연이니 첫 번째 것 사용
16+
.map(memberTicket -> memberTicket.getAmateurTicket().getAmateurShow())
17+
.orElse(null);
18+
}
19+
20+
public static ManageReservResponseDTO.ManageReservResultListDTO toManageReservResultListDTO(Reservation reservation, Set<String> selectedFields, boolean isKeywordSearch) {
21+
22+
// 키워드 검색이거나 전체 조회인 경우 모든 필드 포함
23+
if (isKeywordSearch || selectedFields == null || selectedFields.isEmpty()) {
24+
AmateurShow amateurShow = getAmateurShowFromReservation(reservation);
25+
26+
return ManageReservResponseDTO.ManageReservResultListDTO.builder()
27+
.reservationId(reservation.getId())
28+
.memberName(reservation.getMember().getName())
29+
.amateurShowName(amateurShow.getName())
30+
.schedule(amateurShow.getSchedule())
31+
.place(amateurShow.getPlace())
32+
.quantity(reservation.getMemberTicketList().stream()
33+
.findFirst()
34+
.map(MemberTicket::getQuantity)
35+
.orElse(null))
36+
.reservationStatus(reservation.getStatus())
37+
.build();
38+
}
39+
40+
// selectedFields로 특정 필드만 선택한 경우
41+
AmateurShow amateurShow = getAmateurShowFromReservation(reservation);
42+
return ManageReservResponseDTO.ManageReservResultListDTO.builder()
43+
.reservationId(reservation.getId()) // ID는 항상 포함
44+
.amateurShowName(selectedFields.contains("amateurShowName") ?
45+
(amateurShow != null ? amateurShow.getName() : null) : null)
46+
.schedule(selectedFields.contains("schedule") ?
47+
(amateurShow != null ? amateurShow.getSchedule() : null) : null)
48+
.reservationStatus(selectedFields.contains("reservationStatus") ?
49+
reservation.getStatus() : null)
50+
.build();
51+
}
52+
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package muit.backend.dto.manageReservDTO;
2+
3+
public class ManageReservRequestDTO {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package muit.backend.dto.manageReservDTO;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Getter;
7+
import lombok.NoArgsConstructor;
8+
import muit.backend.domain.enums.ReservationStatus;
9+
10+
public class ManageReservResponseDTO {
11+
12+
@Getter
13+
@Builder
14+
@AllArgsConstructor
15+
@NoArgsConstructor
16+
@JsonInclude(JsonInclude.Include.NON_NULL) // null 값을 가진 필드는 JSON 응답에서 제외
17+
public static class ManageReservResultListDTO { // 소극장 공연 관리 내역 전체 조회
18+
private Long reservationId; // 소극장 예약 id
19+
private String memberName; // 예약자(사용자)명
20+
private String amateurShowName; // 소극장 공연명
21+
private String schedule; // 소극장 공연 날짜/시간
22+
private String place; // 소극장 공연 장소
23+
private Integer quantity;
24+
private ReservationStatus reservationStatus; // 예약 상태 (예약 중, 예약 완료, 사용 완료, 취소 중, 취소 완료)
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package muit.backend.repository;
2+
3+
import muit.backend.domain.entity.member.Reservation;
4+
import org.springframework.data.domain.Page;
5+
import org.springframework.data.domain.Pageable;
6+
import org.springframework.data.jpa.repository.JpaRepository;
7+
import org.springframework.data.jpa.repository.Query;
8+
import org.springframework.data.repository.query.Param;
9+
10+
public interface ReservationRepository extends JpaRepository<Reservation, Long> {
11+
12+
// 검색어가 있을 때
13+
@Query("SELECT r FROM Reservation r " +
14+
"JOIN FETCH r.member m " +
15+
"JOIN FETCH r.memberTicketList mt " +
16+
"JOIN FETCH mt.amateurTicket at " +
17+
"JOIN FETCH at.amateurShow ams " +
18+
"WHERE m.name LIKE CONCAT('%', :keyword, '%') " +
19+
"OR ams.name LIKE CONCAT('%', :keyword, '%') " +
20+
"OR ams.place LIKE CONCAT('%', :keyword, '%') " +
21+
"OR ams.schedule LIKE CONCAT('%', :keyword, '%')")
22+
Page<Reservation> findByKeyword(Pageable pageable, @Param("keyword") String keyword);
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package muit.backend.service;
2+
3+
import muit.backend.dto.manageReservDTO.ManageReservResponseDTO;
4+
import org.springframework.data.domain.Page;
5+
import org.springframework.data.domain.Pageable;
6+
import org.springframework.stereotype.Service;
7+
8+
import java.util.Set;
9+
10+
@Service
11+
public interface ManageReservService {
12+
13+
public Page<ManageReservResponseDTO.ManageReservResultListDTO> getAllReservations(Pageable pageable, String keyword, Set<String> selectedFields);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package muit.backend.service;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import muit.backend.converter.AmateurTicketConverter;
5+
import muit.backend.converter.ManageReservConverter;
6+
import muit.backend.domain.entity.amateur.AmateurShow;
7+
import muit.backend.domain.entity.member.Reservation;
8+
import muit.backend.dto.manageReservDTO.ManageReservResponseDTO;
9+
import muit.backend.repository.ReservationRepository;
10+
import org.springframework.data.domain.Page;
11+
import org.springframework.data.domain.Pageable;
12+
import org.springframework.stereotype.Service;
13+
import org.springframework.transaction.annotation.Transactional;
14+
15+
import java.util.Set;
16+
17+
@Service
18+
@RequiredArgsConstructor
19+
@Transactional(readOnly = true)
20+
public class ManageReservServiceImpl implements ManageReservService {
21+
22+
private final ReservationRepository reservationRepository;
23+
24+
@Override
25+
public Page<ManageReservResponseDTO.ManageReservResultListDTO> getAllReservations(Pageable pageable, String keyword, Set<String> selectedFields) {
26+
27+
// 검색어가 있는지 확인
28+
boolean isKeywordSearch = keyword != null && !keyword.trim().isEmpty(); // 그냥 빈 검색어도 없다고 침
29+
30+
Page<Reservation> reservations;
31+
32+
// 검색어가 있으면 해당 키워드로 검색
33+
if (isKeywordSearch) {
34+
reservations = reservationRepository.findByKeyword(pageable, keyword);
35+
if(reservations.isEmpty()) {
36+
return Page.empty(pageable);
37+
}
38+
} else { // 검색어가 없으면 모든 소극장 공연 정보 조회
39+
reservations = reservationRepository.findAll(pageable);
40+
}
41+
42+
return reservations.map(reservation ->
43+
ManageReservConverter.toManageReservResultListDTO(reservation, selectedFields, isKeywordSearch)
44+
);
45+
}
46+
}

0 commit comments

Comments
 (0)