Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ public class AdminApprovalListResponseDTO {
private String email;
private String phone;
private String showName;
private String amateurShowStatus;
private String approvalStatus;
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private AdminApprovalListResponseDTO toApprovalDto(AmateurShow show) {
.email(registrant.getEmail())
.phone(registrant.getPhone())
.showName(show.getName())
.amateurShowStatus(show.getStatus().name())
.approvalStatus(show.getApprovalStatus().name())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,6 @@ public static class MyShowAmateurShowList { // 극장 공연 리스트 조회
private String schedule;
private String posterImageUrl;
private AmateurShowStatus status;
private String rejectReason;
}
}
2 changes: 2 additions & 0 deletions src/main/java/cc/backend/amateurShow/entity/AmateurShow.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,11 @@ public void reviseShowInfo(String hashtag, String summary, String account, Strin

public void approve(){
this.approvalStatus = ApprovalStatus.APPROVED;
this.status = AmateurShowStatus.YET;
}
public void reject(String rejectReason){
this.approvalStatus = ApprovalStatus.REJECTED;
this.status = AmateurShowStatus.REJECT;
this.rejectReason = rejectReason;

}
Comment on lines 160 to 169
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Unconditional status transitions may corrupt lifecycle state.

The approve() and reject() methods unconditionally set the status field without considering its current value:

  • approve() always sets status = YET, even if the show is already ONGOING or ENDED
  • reject() always sets status = REJECT, regardless of current state

Potential issues:

  1. If an admin approves a show that has already started (ONGOING), it gets reset to YET
  2. If an admin processes approval/rejection for a show after it ended, the temporal state is lost
  3. Status transitions don't follow a proper state machine pattern

Recommendations:

  • Consider whether status should be updated at all during approval/rejection, since approvalStatus already tracks approval state
  • If status must change, add guards to prevent invalid transitions
  • Document the intended relationship between status and approvalStatus
  • Consider whether approval/rejection should only be allowed when status is YET
🔒 Suggested defensive logic
 public void approve(){
     this.approvalStatus = ApprovalStatus.APPROVED;
-    this.status = AmateurShowStatus.YET;
+    // Only set status to YET if not already in a more advanced state
+    if (this.status != AmateurShowStatus.ONGOING && this.status != AmateurShowStatus.ENDED) {
+        this.status = AmateurShowStatus.YET;
+    }
 }
 public void reject(String rejectReason){
     this.approvalStatus = ApprovalStatus.REJECTED;
-    this.status = AmateurShowStatus.REJECT;
+    // Only set status to REJECT if not already ended
+    if (this.status != AmateurShowStatus.ENDED) {
+        this.status = AmateurShowStatus.REJECT;
+    }
     this.rejectReason = rejectReason;
-
 }
🤖 Prompt for AI Agents
In @src/main/java/cc/backend/amateurShow/entity/AmateurShow.java around lines
160 - 169, The approve() and reject(String) methods unconditionally overwrite
the lifecycle field status (AmateurShowStatus) which can corrupt state; update
approve() and reject() to only change approvalStatus while either (a) not
modifying status at all, or (b) guarding status mutations so they only occur
from an allowed prior state (e.g., only change status when current status ==
AmateurShowStatus.YET), and reject attempts from invalid states by throwing an
IllegalStateException or returning a boolean result; ensure these guards live in
the approve() and reject() methods and document the intended relationship
between status and approvalStatus in the method Javadoc.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
public enum AmateurShowStatus {
YET, // 지금 날짜가 공연 날짜 안에 없을 때 (아직 공연 예정)
ONGOING, // 지금 날짜가 공연 날짜 안에 있을 때 (예매 진행 중)
ENDED; // 지금 날짜가 공연 날짜보다 지났을 때 (공연 종료됨)
ENDED, // 지금 날짜가 공연 날짜보다 지났을 때 (공연 종료됨)
REJECT;
}
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ public Slice<AmateurShowResponseDTO.MyShowAmateurShowList> getMyAmateurShow(Long
.schedule(schedule)
.posterImageUrl(show.getPosterImageUrl())
.status(show.getStatus())
.rejectReason(show.getRejectReason())
.build();
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class MemberTicketController {

private final MemberTicketService memberTicketService;

@GetMapping("{amateurShowId}/showSimple")
@GetMapping("/{amateurShowId}/showSimple")
@Operation(
summary = "소극장 공연 티켓 예매 - 공연 정보 간략 보기 API",
description = "소극장 공연 티켓 예매 동안 보이는 모든 (화면 공연 사진, 공연 제목, 공연 장소)에 대해 나옵니다.",
Expand All @@ -42,7 +42,7 @@ public ApiResponse<AmateurShowSimpleDTO> getSimpleAmateurShow(@Parameter(name =
return ApiResponse.onSuccess(memberTicketService.getSimpleAmateurShow(amateurShowId));
}

@GetMapping("{amateurShowId}/selectRound")
@GetMapping("/{amateurShowId}/selectRound")
@Operation(
summary = "소극장 공연 티켓 예매 첫화면 - 회차(날짜) 선택 API",
description = "소극장 공연 티켓 예매 첫화면에서 공연 회차를 선택하기전 조회하는 기능입니다. 등록된 공연의 모든 회차가 조회 됩니다.",
Expand Down Expand Up @@ -73,7 +73,7 @@ public ApiResponse<List<RoundsListDTO>> getAmateurRounds(@PathVariable Long amat
return ApiResponse.onSuccess(memberTicketService.getRoundsList(member.getId(), amateurShowId));
}

@GetMapping("{amateurShowId}/selectTicket")
@GetMapping("/{amateurShowId}/selectTicket")
@Operation(
summary = "소극장 공연 티켓 예매 두번째 화면 - 티켓 종류 선택 API",
description = "소극장 공연 티켓 예매 두번째화면에서 티켓 종류를 선택하기 전 조회하는 기능입니다. 등록된 공연의 모든 티켓이 조회됩니다.",
Expand Down Expand Up @@ -102,7 +102,7 @@ public ApiResponse<List<AmateurTicketListDTO>> getAmateurTicketList(@PathVariabl

}

@PostMapping("{amateurShowId}/reserve")
@PostMapping("/{amateurShowId}/reserve")
@Operation(summary = "소극장 공연 티켓 생성 API",
description = "소극장 공연 티켓을 생성하는 기능입니다. 공연 회차, 인원, 티켓 종류를 선택해 생성합니다.",
parameters = {
Expand Down