상품 예약 게시
작성: seokjin8678ProductPublishReserve
Section titled “ProductPublishReserve”상품 게시 예약을 표현하는 엔티티입니다.
폴더 단위 게시 예약 요청을 받지만, 실제 예약 행은 ProductPublishProvider별로 생성됩니다. 예를 들어 같은 폴더를 VINGLE, CAFE24에 예약하면
ProductPublishReserve는 2개 생성됩니다.
예약 행은 다음 정보를 가집니다.
memberId: 예약한 회원folderId: 게시할 상품 폴더provider: 게시 대상 제공자reservedAt: 예약 실행 시간
예약 수량은 ProductPublishReserve에 저장하지 않습니다. 예약 가능 여부를 계산할 때 예약 행들의 folderId를 모아 ProductFolder.productCount를
조회해 합산합니다.
예약 생성 API는 POST /publish/reserves입니다.
요청은 folderId, providers, reserveAt을 받습니다.
예약 생성 시 다음 제약을 검증합니다.
- 예약 시간은 현재 시간 + 1분 이상, 현재 시간 + 1달 이내여야 합니다.
- 예약 시간 기준 ±30분 범위에 있는 다른 폴더 예약의 상품 개수 합과 신규 폴더의
productCount합이 500개 이상이면 예약할 수 없습니다. - 같은 폴더에 예약 행이 이미 존재하면, 이후 다른 provider 예약도 기존
reservedAt과 같은 시간으로만 추가할 수 있습니다. - 같은 폴더의 기존 provider는 중복 예약하지 않습니다.
- 다른 폴더 예약과는 5분 이상 간격이 필요합니다. (게시 순서 꼬임 방지)
같은 폴더에 대한 provider 추가 예약은 기존 예약 시간으로만 가능하며, 이 경우 이미 해당 폴더의 상품 개수가 용량 제한에 반영되어 있으므로 신규 예약 수량으로 다시 더하지 않습니다.
예약 생성 시 provider별 예약 행을 저장하고, 각 예약 행마다 ProductPublishReserveJob을 reservedAt 시점으로 예약합니다.
Job 실행 시 예약 행을 다시 조회합니다.
- 예약 행이 없으면 취소된 것으로 보고 종료합니다.
- 예약 행이 존재하면
ProductPublishService.publishByFolder(memberId, folderId, setOf(provider))를 호출합니다. - 게시 호출 후 해당 예약 행의 상태를 변경합니다.
예약 취소 API는 DELETE /publish/reserves/{productPublishReserveId}입니다.
취소는 폴더 단위가 아니라 ProductPublishReserve 단위로 수행합니다. 따라서 같은 폴더에 여러 provider 예약이 있을 때 하나의 provider 예약만 취소할 수
있습니다.
취소 시 예약 행이 없거나, 예약 행의 memberId가 요청 회원과 다르면 존재하지 않는 예약으로 처리합니다.
예약 조회 API는 다음과 같습니다.
GET /publish/reserves: 회원의 예약 목록 조회GET /publish/reserves/folders/{folderId}: 특정 폴더의 예약 목록 조회GET /publish/reserves/{productPublishReserveId}: 예약 상세 조회
목록 조회는 cursorProductPublishReserveId 기반 커서 페이징을 사용하며, sortDirection을 지원합니다.