Skip to content

Commit 00a3080

Browse files
authored
Merge pull request #32 from MUIT-UMC/feature/admin-amateurTicket
[feat] 어드민의 소극장 티켓 관리 api 구현
2 parents c58b7ba + d130423 commit 00a3080

File tree

9 files changed

+248
-1
lines changed

9 files changed

+248
-1
lines changed

src/main/java/muit/backend/apiPayLoad/code/status/ErrorStatus.java

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public enum ErrorStatus implements BaseErrorCode {
3333
JOIN_FORMAT_ERROR(HttpStatus.BAD_REQUEST, "JOIN4000", "아이디와 비밀번호는 필수 입력 값입니다."),
3434
USER_ALREADY_EXIST(HttpStatus.BAD_REQUEST, "JOIN4001", "이미 존재하는 아이디입니다"),
3535

36-
3736
// AMATEURSHOW ERROR
3837
AMATEURSHOW_NOT_FOUND(HttpStatus.NOT_FOUND, "AMATEURSHOW4000", "존재하지 않는 소극장 공연입니다.");
3938

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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.converter.AmateurTicketConverter;
8+
import muit.backend.dto.amateurTicketDTO.AmateurTicketRequestDTO;
9+
import muit.backend.dto.amateurTicketDTO.AmateurTicketResponseDTO;
10+
import muit.backend.service.AmateurTicketService;
11+
import org.springdoc.core.annotations.ParameterObject;
12+
import org.springframework.data.domain.Page;
13+
import org.springframework.data.domain.Pageable;
14+
import org.springframework.web.bind.annotation.*;
15+
16+
import java.util.Set;
17+
18+
@Tag(name = "어드민이 소극장 티켓 관리")
19+
@RestController
20+
@RequiredArgsConstructor
21+
@RequestMapping("/admin/amateur-tickets")
22+
public class AmateurTicketController {
23+
24+
private final AmateurTicketService amateurTicketService;
25+
26+
@Operation(summary = "전체 소극장 티켓 조회")
27+
@GetMapping
28+
public ApiResponse<Page<AmateurTicketResponseDTO.AmateurTicketResultListDTO>> getAllTickets(@ParameterObject Pageable pageable,
29+
@RequestParam(required = false) String keyword,
30+
@RequestParam(required = false) Set<String> selectedFields) {
31+
Page<AmateurTicketResponseDTO.AmateurTicketResultListDTO> tickets = amateurTicketService.getAllTickets(pageable, keyword, selectedFields);
32+
return ApiResponse.onSuccess(tickets);
33+
}
34+
35+
@Operation(summary = "특정 소극장 티켓 조회")
36+
@GetMapping("/{amateurShowId}")
37+
public ApiResponse<AmateurTicketResponseDTO.AmateurTicketResultDTO> getTicket(@PathVariable("amateurShowId") Long amateurShowId) {
38+
AmateurTicketResponseDTO.AmateurTicketResultDTO ticket = amateurTicketService.getTicket(amateurShowId);
39+
return ApiResponse.onSuccess(ticket);
40+
}
41+
42+
@Operation(summary = "특정 소극장 티켓 정보 수정")
43+
@PatchMapping("/{amateurShowId}/update")
44+
public ApiResponse<AmateurTicketResponseDTO.AmateurTicketResultDTO> updateTicket(@PathVariable("amateurShowId") Long amateurShowId,
45+
@RequestBody AmateurTicketRequestDTO.AmateurTicketUpdateDTO requestDTO) {
46+
AmateurTicketResponseDTO.AmateurTicketResultDTO ticket = amateurTicketService.updateTicket(amateurShowId, requestDTO);
47+
return ApiResponse.onSuccess(ticket);
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package muit.backend.converter;
2+
3+
import muit.backend.domain.entity.amateur.AmateurShow;
4+
import muit.backend.dto.amateurTicketDTO.AmateurTicketResponseDTO;
5+
6+
import java.util.Set;
7+
8+
public class AmateurTicketConverter {
9+
10+
public static AmateurTicketResponseDTO.AmateurTicketResultListDTO toAmateurTicketResultListDTO(AmateurShow amateurShow, Set<String> selectedFields, boolean isKeywordSearch) {
11+
12+
// 키워드 검색이거나 전체 조회인 경우 모든 필드 포함
13+
if (isKeywordSearch || selectedFields == null || selectedFields.isEmpty()) {
14+
return AmateurTicketResponseDTO.AmateurTicketResultListDTO.builder()
15+
.amateurShowId(amateurShow.getId())
16+
.name(amateurShow.getName())
17+
.schedule(amateurShow.getSchedule())
18+
.soldTicket(amateurShow.getSoldTicket())
19+
.totalTicket(amateurShow.getTotalTicket())
20+
.build();
21+
}
22+
23+
// selectedFields로 특정 필드만 선택한 경우
24+
return AmateurTicketResponseDTO.AmateurTicketResultListDTO.builder()
25+
.amateurShowId(amateurShow.getId()) // ID는 항상 포함
26+
.name(selectedFields.contains("name") ? amateurShow.getName() : null)
27+
.schedule(selectedFields.contains("schedule") ? amateurShow.getSchedule() : null)
28+
.soldTicket(selectedFields.contains("reservationStatus") ? amateurShow.getSoldTicket() : null)
29+
.totalTicket(selectedFields.contains("reservationStatus") ? amateurShow.getTotalTicket() : null)
30+
.build();
31+
}
32+
33+
public static AmateurTicketResponseDTO.AmateurTicketResultDTO toAmateurTicketResultDTO(AmateurShow amateurShow) {
34+
return AmateurTicketResponseDTO.AmateurTicketResultDTO.builder()
35+
.amateurShowId(amateurShow.getId())
36+
.name(amateurShow.getName())
37+
.schedule(amateurShow.getSchedule())
38+
.soldTicket(amateurShow.getSoldTicket())
39+
.totalTicket(amateurShow.getTotalTicket())
40+
.build();
41+
}
42+
}

src/main/java/muit/backend/domain/entity/amateur/AmateurShow.java

+8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import muit.backend.domain.common.BaseEntity;
99
import muit.backend.domain.entity.member.Member;
1010
import muit.backend.domain.enums.AmateurStatus;
11+
import muit.backend.dto.amateurTicketDTO.AmateurTicketRequestDTO;
1112
import muit.backend.dto.manageAmateurShowDTO.ManageAmateurShowRequestDTO;
1213

1314
import java.util.ArrayList;
@@ -105,4 +106,11 @@ public void decideAmateurShow(AmateurStatus amateurStatus, ManageAmateurShowRequ
105106

106107
}
107108

109+
public void updateAmateurTicket(AmateurTicketRequestDTO.AmateurTicketUpdateDTO requestDTO) {
110+
if(requestDTO.getName()!=null){this.name = requestDTO.getName();}
111+
if(requestDTO.getSchedule()!=null){this.schedule = requestDTO.getSchedule();}
112+
if(requestDTO.getSoldTicket()!=null){this.soldTicket = requestDTO.getSoldTicket();}
113+
if(requestDTO.getTotalTicket()!=null){this.totalTicket = requestDTO.getTotalTicket();}
114+
}
115+
108116
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package muit.backend.dto.amateurTicketDTO;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
import lombok.Setter;
7+
8+
public class AmateurTicketRequestDTO {
9+
10+
@Getter
11+
@Setter
12+
@NoArgsConstructor
13+
@AllArgsConstructor
14+
public static class AmateurTicketUpdateDTO {
15+
private String name; // 소극장 공연 이름
16+
private String schedule; // 공연 날짜/시간
17+
private Integer soldTicket; // 예매된 티켓 수
18+
private Integer totalTicket; // 전체 티켓 수
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package muit.backend.dto.amateurTicketDTO;
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.Gender;
9+
10+
public class AmateurTicketResponseDTO {
11+
12+
@Getter
13+
@Builder
14+
@AllArgsConstructor
15+
@NoArgsConstructor
16+
@JsonInclude(JsonInclude.Include.NON_NULL) // null 값을 가진 필드는 JSON 응답에서 제외
17+
public static class AmateurTicketResultListDTO { // 티켓 전체 조회
18+
private Long amateurShowId; // 소극장 공연 아이디
19+
private String name; // 소극장 공연 이름
20+
private String schedule; // 공연 날짜/시간
21+
private Integer soldTicket; // 예매된 티켓 수
22+
private Integer totalTicket; // 전체 티켓 수
23+
}
24+
25+
@Getter
26+
@Builder
27+
@AllArgsConstructor
28+
@NoArgsConstructor
29+
public static class AmateurTicketResultDTO { // 특정 티켓 조회, 수정
30+
private Long amateurShowId; // 소극장 공연 아이디
31+
private String name; // 소극장 공연 이름
32+
private String schedule; // 공연 날짜/시간
33+
private Integer soldTicket; // 예매된 티켓 수
34+
private Integer totalTicket; // 전체 티켓 수
35+
}
36+
}

src/main/java/muit/backend/repository/AmateurShowRepository.java

+6
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,10 @@ public interface AmateurShowRepository extends JpaRepository<AmateurShow, Long>
2828
"LEFT JOIN FETCH a.amateurSummary " +
2929
"WHERE a.id = :amateurShowId")
3030
Optional<AmateurShow> findByIdWithMemberAndSummary(@Param("amateurShowId") Long amateurShowId);
31+
32+
// 티켓 검색 조회
33+
@Query("SELECT a FROM AmateurShow a WHERE " +
34+
"a.name LIKE %:keyword% " +
35+
"OR a.schedule LIKE %:keyword%")
36+
Page<AmateurShow> findTicketsByKeyword(Pageable pageable, @Param("keyword") String keyword);
3137
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package muit.backend.service;
2+
3+
import muit.backend.dto.amateurTicketDTO.AmateurTicketRequestDTO;
4+
import muit.backend.dto.amateurTicketDTO.AmateurTicketResponseDTO;
5+
import org.springframework.data.domain.Page;
6+
import org.springframework.data.domain.Pageable;
7+
import org.springframework.stereotype.Service;
8+
9+
import java.util.Set;
10+
11+
@Service
12+
public interface AmateurTicketService {
13+
14+
public Page<AmateurTicketResponseDTO.AmateurTicketResultListDTO> getAllTickets(Pageable pageable,
15+
String keyword,
16+
Set<String> selectedFields);
17+
public AmateurTicketResponseDTO.AmateurTicketResultDTO getTicket(Long amateurShowId);
18+
public AmateurTicketResponseDTO.AmateurTicketResultDTO updateTicket(Long amateurShowId, AmateurTicketRequestDTO.AmateurTicketUpdateDTO requestDTO);
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package muit.backend.service;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import muit.backend.apiPayLoad.code.status.ErrorStatus;
5+
import muit.backend.apiPayLoad.exception.GeneralException;
6+
import muit.backend.converter.AmateurTicketConverter;
7+
import muit.backend.domain.entity.amateur.AmateurShow;
8+
import muit.backend.dto.amateurTicketDTO.AmateurTicketRequestDTO;
9+
import muit.backend.dto.amateurTicketDTO.AmateurTicketResponseDTO;
10+
import muit.backend.repository.AmateurShowRepository;
11+
import org.springframework.data.domain.Page;
12+
import org.springframework.data.domain.Pageable;
13+
import org.springframework.stereotype.Service;
14+
import org.springframework.transaction.annotation.Transactional;
15+
16+
import java.util.Set;
17+
18+
@Service
19+
@RequiredArgsConstructor
20+
@Transactional(readOnly = true)
21+
public class AmateurTicketServiceImpl implements AmateurTicketService {
22+
23+
private final AmateurShowRepository amateurShowRepository;
24+
25+
@Override
26+
public Page<AmateurTicketResponseDTO.AmateurTicketResultListDTO> getAllTickets(Pageable pageable,
27+
String keyword,
28+
Set<String> selectedFields) {
29+
30+
// 검색어가 있는지 확인
31+
boolean isKeywordSearch = keyword != null && !keyword.trim().isEmpty(); // 그냥 빈 검색어도 없다고 침
32+
33+
Page<AmateurShow> amateurShows;
34+
35+
// 검색어가 있으면 해당 키워드로 검색
36+
if (isKeywordSearch) {
37+
amateurShows = amateurShowRepository.findTicketsByKeyword(pageable, keyword);
38+
if(amateurShows.isEmpty()) {
39+
return Page.empty(pageable);
40+
}
41+
} else { // 검색어가 없으면 모든 소극장 공연 정보 조회
42+
amateurShows = amateurShowRepository.findAll(pageable);
43+
}
44+
45+
return amateurShows.map(amateurShow ->
46+
AmateurTicketConverter.toAmateurTicketResultListDTO(amateurShow, selectedFields, isKeywordSearch)
47+
);
48+
}
49+
50+
@Override
51+
public AmateurTicketResponseDTO.AmateurTicketResultDTO getTicket(Long amateurShowId) {
52+
AmateurShow amateurShow = amateurShowRepository.findById(amateurShowId)
53+
.orElseThrow(()-> new GeneralException(ErrorStatus.AMATEURSHOW_NOT_FOUND));
54+
55+
return AmateurTicketConverter.toAmateurTicketResultDTO(amateurShow);
56+
}
57+
58+
@Transactional
59+
@Override
60+
public AmateurTicketResponseDTO.AmateurTicketResultDTO updateTicket(Long amateurShowId, AmateurTicketRequestDTO.AmateurTicketUpdateDTO requestDTO) {
61+
AmateurShow amateurShow = amateurShowRepository.findById(amateurShowId)
62+
.orElseThrow(()-> new GeneralException(ErrorStatus.AMATEURSHOW_NOT_FOUND));
63+
64+
amateurShow.updateAmateurTicket(requestDTO);
65+
66+
return AmateurTicketConverter.toAmateurTicketResultDTO(amateurShow);
67+
}
68+
}

0 commit comments

Comments
 (0)