[BE-53] recruitment 프레젠테이션 — API 컨트롤러·DTO·플래그

작업 내용 (설계 의도)

변경 사항

근거 TDD: “REST API 계약 recruitment 7종·인가”. recruitment UseCase(BE-52)를 REST로 노출한다. community 컨트롤러의 @ConditionalOnProperty 즉시 롤백 패턴 재사용.

포함 (전부 신규 파일):

  • presentation: RecruitmentApiController(POST /recruitments, GET /recruitments, GET /recruitments/{id}, GET /recruitments/{id}/applications, POST /recruitments/{id}/applications, POST /recruitments/{id}/cancel), ApplicationApiController(GET /applications 내 신청 목록, POST /applications/{id}/cancel) + @ConditionalOnProperty(recruitment.enabled).
    • GET /applications: 인증 principal의 userId 기준 ListMyApplicationsUseCase 호출 — 쿼리로 넘어온 applicantUserId를 신뢰하지 않고 principal로 강제해 본인 신청만 조회(FR-4 취소 FE 경로 지탱, senior-pm 보강). 응답 List<ApplicationResponse>.
  • Request DTO(presentation): CreateRecruitmentRequest(title/description/capacity/feeAmount/activityAt/applicationDeadline/communityId?)·ApplyRecruitmentRequest(paymentMethod/amount/currency) → toCommand().
  • Response는 BE-52 application Response 그대로 반환(Controller가 Entity 직접 반환 금지).
  • 인가: @AuthenticationPrincipal UserPrincipal. communityId 소속 모집의 열람/신청 인가는 UseCase가 community 규칙 위임(BE-52 경유).
  • 신청 응답은 paymentId/checkoutUrl 포함(CreateBooking 응답 형태 참조).

롤백

recruitment.enabled=false면 컨트롤러 빈 미등록 → /recruitments 전 경로 404(즉시 롤백 지점).

의존

  • BE-52 (recruitment UseCase)

다이어그램

처리 흐름

sequenceDiagram
    participant Cl as Client
    participant C as RecruitmentApiController
    participant U as ApplyRecruitmentUseCase
    Cl->>C: POST /recruitments/{id}/applications
    C->>U: execute(command)
    U-->>C: checkoutUrl/paymentId
    C-->>Cl: 200

클래스 의존

flowchart LR
    RC[RecruitmentApiController] --> CU[CreateRecruitmentUseCase]
    RC --> AU[ApplyRecruitmentUseCase]
    RC --> CanU[CancelRecruitmentUseCase]
    AC[ApplicationApiController] --> CAU[CancelApplicationUseCase]
    AC --> LMU[ListMyApplicationsUseCase]

테스트 케이스

  • 인증 사용자가 유효 본문으로 모집을 개설하면 201/200과 모집 ID를 받는다
  • 신청 요청이 checkoutUrl/paymentId를 반환한다
  • 신청 0건 모집의 신청자 목록 조회가 빈 배열을 정상 반환한다
  • 정원이 찬 모집 신청은 409로 응답한다
  • 마감 이후 신청 취소 요청은 422로 응답한다
  • 개설자가 아닌 사용자의 신청자 목록 조회는 403이다
  • GET /applications가 인증 principal 본인의 신청 목록만 반환하고 타인 신청은 노출하지 않는다
  • 신청 이력 없는 사용자의 GET /applications는 빈 배열을 정상 반환한다
  • recruitment.enabled=false면 /recruitments·/applications 경로가 404다