[BE-60] 소모임 예약 연동 — CommunityBooking + SlotInfoGateway
작업 내용 (설계 의도)
변경 사항
근거 TDD: “B3 community↔booking·SlotInfoGateway·실패 경로 비멤버 열람”. community가 기존 booking Slot을 ID로 연결해 모임 활동 일정으로 노출한다(FR-13~15). 신규 예약 메커니즘 없음, 정원은 Slot 소유(community 미관리). R1 준수 — booking import 금지, ACL 게이트웨이만.
포함 (전 레이어 수직 슬라이스, 전부 신규 파일):
- domain:
CommunityBooking(@Entity — communityId·slotId(Long ID참조)·linkedByUserId,create+ 중복 링크 멱등 가드),CommunityBookingRepositoryinterface,SlotInfoGatewayinterface +SlotInfo(community DTO: facilityId·date·timeRange·capacity). - domain service:
CommunityBookingDomainService—link(communityId, hostUserId, slotId)(CommunityDomainService.requireHost위임 후 저장)·findLinked(communityId, requesterId)(requireActiveMember인가 후 SlotInfoGateway로 표시정보 조합). - application:
LinkCommunityBookingUseCase·ListCommunityBookingsUseCase+ Command/Response. - infrastructure:
CommunityBookingRepositoryImpl+JpaRepository,SlotInfoGatewayImpl(bookingSlotRepository읽어 SlotInfo 변환). - presentation:
CommunityBookingApiController(POST/GET/communities/{communityId}/bookings) +@ConditionalOnProperty(community.booking.enabled).
주의: CommunityBookingDomainService가 CommunityDomainService를 주입해 인가를 위임(같은 도메인 내). booking은 SlotInfoGateway로만 접근.
롤백
community_bookings 테이블 신규 + 플래그. 롤백은 community.booking.enabled=false(경로 404) 또는 역방향 DDL(테이블 DROP).
의존
- 없음 (기존 community·booking 재사용만)
다이어그램
처리 흐름
sequenceDiagram participant C as CommunityBookingApiController participant U as ListCommunityBookingsUseCase participant S as CommunityBookingDomainService participant Auth as CommunityDomainService participant G as SlotInfoGateway C->>U: list(communityId, requesterId) U->>S: findLinked(communityId, requesterId) S->>Auth: requireActiveMember(communityId, requesterId) S->>G: findBy(slotId) G-->>S: SlotInfo(시설·일시·정원) S-->>C: 목록
클래스 의존
flowchart LR CBDS[CommunityBookingDomainService] --> Repo[CommunityBookingRepository] CBDS --> Auth[CommunityDomainService] CBDS --> Gw[SlotInfoGateway] GwImpl[SlotInfoGatewayImpl] -.->|implements| Gw GwImpl --> SlotRepo[booking SlotRepository]
테스트 케이스
- 방장이 예약 가능 slotId를 연결하면 CommunityBooking이 생성된다
- 멤버가 연결 목록을 조회하면 SlotInfo(시설·일시·정원)가 함께 반환된다
- 방장이 아닌 사용자의 연결 시도는 requireHost 예외(403)로 거부된다
- PRIVATE 모임 비승인자가 연결 예약 상세를 열람하면 NotCommunityMemberException(403)이다
- 연결 예약이 없는 모임 조회는 빈 목록을 정상 반환한다
- 동일 slotId 중복 연결은 멱등하게 처리된다
- 정원은 Slot의 capacity를 그대로 노출하고 community가 별도 관리하지 않는다