Skip to content

Commit 3f24939

Browse files
authored
feat: ticket api 문서 작성, 티켓 테스트 데이터 수정
1 parent 26b915e commit 3f24939

5 files changed

Lines changed: 27 additions & 100 deletions

File tree

backend/src/main/java/com/back/api/ticket/controller/TicketApi.java

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,35 @@
22

33
import java.util.List;
44

5+
import org.springframework.web.bind.annotation.PathVariable;
6+
57
import com.back.api.ticket.dto.response.TicketResponse;
8+
import com.back.global.config.swagger.ApiErrorCode;
69
import com.back.global.response.ApiResponse;
710

811
import io.swagger.v3.oas.annotations.Operation;
12+
import io.swagger.v3.oas.annotations.Parameter;
913
import io.swagger.v3.oas.annotations.tags.Tag;
1014

1115
@Tag(name = "Ticket API", description = "티켓 결제 및 조회 API")
1216
public interface TicketApi {
1317

14-
/*
1518
@Operation(
16-
summary = "결제 성공",
17-
description = "Draft Ticket을 ISSUED 상태로 변경합니다. 내부 로직 또는 PG webhook 호출용 엔드포인트입니다."
19+
summary = "내 티켓 목록 조회",
20+
description = "현재 로그인한 사용자의 모든 티켓 목록을 조회합니다."
1821
)
19-
@ApiErrorCode({
20-
"TICKET_NOT_FOUND",
21-
"UNAUTHORIZED_TICKET_ACCESS",
22-
"INVALID_TICKET_STATE"
23-
})
24-
ApiResponse<TicketResponse> confirmPayment(
25-
@Parameter(description = "티켓 ID", example = "1")
26-
@PathVariable Long ticketId
27-
);
22+
ApiResponse<List<TicketResponse>> getMyTickets();
2823

2924
@Operation(
30-
summary = "결제 실패",
31-
description = "Draft Ticket을 FAILED로 변경하고 좌석을 AVAILABLE로 복구합니다. 내부 로직 또는 PG webhook 호출용 엔드포인트입니다."
25+
summary = "내 티켓 상세 조회",
26+
description = "현재 로그인한 사용자의 특정 티켓 상세 정보를 조회합니다. 티켓 ID로 조회하며, 본인의 티켓만 조회 가능합니다."
3227
)
3328
@ApiErrorCode({
3429
"TICKET_NOT_FOUND",
35-
"INVALID_TICKET_STATE"
30+
"UNAUTHORIZED_TICKET_ACCESS"
3631
})
37-
ApiResponse<Void> failPayment(
38-
@Parameter(description = "티켓 ID", example = "1")
32+
ApiResponse<TicketResponse> getMyTicketDetails(
33+
@Parameter(description = "조회할 티켓 ID", example = "1")
3934
@PathVariable Long ticketId
4035
);
41-
*/
42-
43-
@Operation(
44-
summary = "내 티켓 목록 조회",
45-
description = "현재 로그인한 사용자의 모든 티켓 목록을 조회합니다."
46-
)
47-
ApiResponse<List<TicketResponse>> getMyTickets();
48-
49-
// TODO: API 설명츄가
5036
}

backend/src/main/java/com/back/api/ticket/controller/TicketController.java

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public ApiResponse<List<TicketResponse>> getMyTickets() {
3636
);
3737
}
3838

39+
@Override
3940
@GetMapping("/my/{ticketId}/details")
4041
public ApiResponse<TicketResponse> getMyTicketDetails(
4142
@PathVariable Long ticketId
@@ -49,30 +50,4 @@ public ApiResponse<TicketResponse> getMyTicketDetails(
4950
TicketResponse.from(ticket)
5051
);
5152
}
52-
53-
/* 외부 노출이 필요 없는 엔드포인트, 보관 차원에서 주석 처리
54-
@Override
55-
@PostMapping("/{ticketId}/payment/success")
56-
public ApiResponse<TicketResponse> confirmPayment(
57-
@PathVariable Long ticketId
58-
) {
59-
Long userId = httpRequestContext.getUser().getId();
60-
61-
Ticket ticket = ticketService.confirmPayment(ticketId, userId);
62-
63-
return ApiResponse.ok(
64-
"결제가 완료되었습니다.",
65-
TicketResponse.from(ticket)
66-
);
67-
}
68-
69-
@Override
70-
@PostMapping("/{ticketId}/payment/fail")
71-
public ApiResponse<Void> failPayment(
72-
@PathVariable Long ticketId
73-
) {
74-
ticketService.failPayment(ticketId);
75-
return ApiResponse.noContent("결제 실패 처리 완료");
76-
}
77-
*/
78-
}
53+
}

backend/src/main/java/com/back/global/init/perf/PerfSeatDataInitializer.java

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public void init() {
4040
log.info("Seat 초기 데이터 생성 중: Event #3 ({}) - 500석 (VIP-A 50석, R-C 100석, S-B 150석, A-D 200석)",
4141
event3.getTitle());
4242

43-
List<Seat> seats3 = createSeatsForEvent3(event3);
43+
List<Seat> seats3 = createSeatsForEvent3and4(event3);
4444
seatRepository.saveAll(seats3);
4545
totalSeats += seats3.size();
4646

@@ -55,7 +55,7 @@ public void init() {
5555
log.info("Seat 초기 데이터 생성 중: Event #4 ({}) - 100석 (VIP-E 20석, R-G 30석, S-F 30석, A-H 20석)",
5656
event4.getTitle());
5757

58-
List<Seat> seats4 = createSeatsForEvent4(event4);
58+
List<Seat> seats4 = createSeatsForEvent3and4(event4);
5959
seatRepository.saveAll(seats4);
6060
totalSeats += seats4.size();
6161

@@ -73,7 +73,7 @@ public void init() {
7373
* - S: B1~B150 (150석)
7474
* - A: D1~D200 (200석)
7575
*/
76-
private List<Seat> createSeatsForEvent3(Event event) {
76+
private List<Seat> createSeatsForEvent3and4(Event event) {
7777
List<Seat> seats = new ArrayList<>();
7878

7979
// VIP: A1 ~ A50 (50석)
@@ -98,38 +98,4 @@ private List<Seat> createSeatsForEvent3(Event event) {
9898

9999
return seats;
100100
}
101-
102-
/**
103-
* Event #4용 좌석 생성
104-
* - 총 100석
105-
* - VIP: E1~E20 (20석)
106-
* - R: G1~G30 (30석)
107-
* - S: F1~F30 (30석)
108-
* - A: H1~H20 (20석)
109-
*/
110-
private List<Seat> createSeatsForEvent4(Event event) {
111-
List<Seat> seats = new ArrayList<>();
112-
113-
// VIP: E1 ~ E20 (20석)
114-
for (int i = 1; i <= 20; i++) {
115-
seats.add(Seat.createSeat(event, "E" + i, SeatGrade.VIP, event.getMaxPrice()));
116-
}
117-
118-
// R: G1 ~ G30 (30석)
119-
for (int i = 1; i <= 30; i++) {
120-
seats.add(Seat.createSeat(event, "G" + i, SeatGrade.R, event.getMaxPrice() - 20000));
121-
}
122-
123-
// S: F1 ~ F30 (30석)
124-
for (int i = 1; i <= 30; i++) {
125-
seats.add(Seat.createSeat(event, "F" + i, SeatGrade.S, event.getMinPrice() + 30000));
126-
}
127-
128-
// A: H1 ~ H20 (20석)
129-
for (int i = 1; i <= 20; i++) {
130-
seats.add(Seat.createSeat(event, "H" + i, SeatGrade.A, event.getMinPrice()));
131-
}
132-
133-
return seats;
134-
}
135101
}

perf/k6-scripts/scenarios/getTicketDetail.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,4 @@ export function getTicketDetail(baseUrl, jwt, testId, ticketId) {
7878
}
7979

8080
return res;
81-
}
81+
}

perf/k6-scripts/tests/getTicketDetail.test.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ export const options = {
2222
*
2323
* 테스트 데이터 구조 (Event #4 기준):
2424
* - 총 사용자: 500명 (test1@test.com ~ test500@test.com)
25-
* - Event #4: CLOSED 상태, 100석 (모두 ISSUED 티켓)
25+
* - Event #4: CLOSED 상태, 500석 (모두 ISSUED 티켓)
2626
* - 티켓 배정: 순환 배정
2727
* → ticketId 1: userId 1
2828
* → ticketId 2: userId 2
2929
* → ...
30-
* → ticketId 100: userId 100
30+
* → ticketId 500: userId 500
3131
*
3232
* 시나리오:
33-
* - VU 1~100만 활성화 (티켓을 가진 사용자만 테스트)
33+
* - VU 1~500만 활성화 (티켓을 가진 사용자만 테스트)
3434
* - 각 VU는 자신의 티켓 ID로 상세 조회
3535
* - VU 1 → ticketId 1, VU 2 → ticketId 2, ...
3636
*
@@ -40,8 +40,8 @@ export const options = {
4040
* - DB 단건 조회 성능 확인
4141
*
4242
* 주의:
43-
* - PEAK_VUS는 100 이하로 설정 권장 (티켓이 100장만 존재)
44-
* - 100 초과 시 존재하지 않는 ticketId 조회로 404 에러 발생
43+
* - PEAK_VUS는 500 이하로 설정 권장 (티켓이 500장만 존재)
44+
* - 500 초과 시 존재하지 않는 ticketId 조회로 404 에러 발생
4545
*/
4646
export function setup() {
4747
const secret = __ENV.JWT_SECRET;
@@ -54,13 +54,13 @@ export function setup() {
5454
parseInt(__ENV.PEAK_VUS || "100", 10)
5555
);
5656

57-
// 티켓이 있는 사용자(1~100)만 토큰 생성
58-
const ticketOwnerCount = 100;
57+
// 티켓이 있는 사용자(1~500)만 토큰 생성
58+
const ticketOwnerCount = 500;
5959
const effectiveVus = Math.min(maxVus, ticketOwnerCount);
6060

6161
// VU당 JWT 토큰 생성
6262
const tokens = Array.from({ length: effectiveVus }, (_, i) => {
63-
const userId = i + 1; // userId 1~100
63+
const userId = i + 1; // userId 1~500
6464
return generateJWT(
6565
{
6666
id: userId,
@@ -102,4 +102,4 @@ export default function (data) {
102102

103103
// 사용자가 티켓 상세를 확인하는 시간 (0.5~2.0초)
104104
sleep(Math.random() * 1.5 + 0.5);
105-
}
105+
}

0 commit comments

Comments
 (0)