diff --git a/docs/20260421_오리지널시리즈정산내역.md b/docs/20260421_오리지널시리즈정산내역.md index 3c495fba..e0d58056 100644 --- a/docs/20260421_오리지널시리즈정산내역.md +++ b/docs/20260421_오리지널시리즈정산내역.md @@ -3,7 +3,7 @@ - [x] 기존 관리자 정산 API 패턴(`/admin/calculate`, list/excel 쌍, `StreamingResponseBody`)을 유지하는 신규 패키지 구조를 확정한다. - [x] `kr.co.vividnext.sodalive.admin.calculate.originalSeries` 패키지에 오리지널 시리즈 소지 유저 조회 API를 추가한다. - [x] `kr.co.vividnext.sodalive.admin.calculate.originalSeries` 패키지에 오리지널 시리즈 정산 내역 조회 API를 추가한다. -- [x] 정산 내역 조회 API가 `startDate`, `endDate`, `memberId`를 받아 KST 입력 날짜를 UTC 조회 범위로 변환하도록 구현한다. +- [x] 정산 내역 조회 API가 `start_date`, `end_date`, `creator_id`를 받아 KST 입력 날짜를 UTC 조회 범위로 변환하도록 구현한다. - [x] 정산 내역 조회 쿼리가 `Series(isOriginal = true) -> SeriesContent -> AudioContent -> Order` 경로를 사용해 `Content.id`, `Order.type` 기준으로 그룹화되도록 구현한다. - [x] 정산 내역 결과에 시리즈 타이틀, 콘텐츠 타이틀, 가격, 대여/소장 여부, 판매 수, 합계(캔), 합계(포인트)를 포함하도록 DTO를 추가한다. - [x] 가격은 주문에 저장된 값을 기준으로 사용하되, 대여는 `ceil(price * 0.7)` 규칙이 반영된 값으로 노출되도록 검증한다. @@ -16,8 +16,8 @@ - 오리지널 시리즈 여부는 `Series.isOriginal` 플래그를 기준으로 판단한다. - 소지 유저는 현재 코드베이스 기준 `Series.member`를 의미하는 것으로 해석한다. -- 날짜 입력 파라미터는 `startDate`, `endDate`, `memberId`로 받고, 날짜 값은 KST 기준 `00:00:00` / `23:59:59`로 해석한 뒤 `convertLocalDateTime()`으로 UTC `LocalDateTime`으로 변환한다. -- 정산 내역 조회 API는 `memberId`를 필수 필터로 사용하고, 엑셀 API는 전체 소지 유저를 순회해 시트를 생성하는 것으로 해석한다. +- 날짜 입력 파라미터는 `start_date`, `end_date`, `creator_id`로 받고, 날짜 값은 KST 기준 `00:00:00` / `23:59:59`로 해석한 뒤 `convertLocalDateTime()`으로 UTC `LocalDateTime`으로 변환한다. +- 정산 내역 조회 API는 `creator_id`를 필수 필터로 사용하고, 엑셀 API는 전체 소지 유저를 순회해 시트를 생성하는 것으로 해석한다. ## API 명세 @@ -44,11 +44,11 @@ "message": null, "data": [ { - "memberId": 1, + "creatorId": 1, "nickname": "owner-a" }, { - "memberId": 2, + "creatorId": 2, "nickname": "owner-b" } ], @@ -60,7 +60,7 @@ - `success`: 성공 여부 - `message`: 성공 메시지, 현재 구현에서는 `null` - `data`: 오리지널 시리즈 소지 유저 목록 - - `memberId`: 정산 내역 조회에 사용할 멤버 ID + - `creatorId`: 정산 내역 조회에 사용할 크리에이터 ID - `nickname`: 관리자 화면에 노출할 닉네임 - `errorProperty`: 에러 시 사용되는 필드, 성공 시 `null` @@ -73,9 +73,9 @@ - Header - 인증: 관리자 권한 필요 (`hasRole('ADMIN')`) - Query Parameter - - `startDate`: 시작일, 형식 `yyyy-MM-dd`, KST 기준 - - `endDate`: 종료일, 형식 `yyyy-MM-dd`, KST 기준 - - `memberId`: 오리지널 시리즈 소지 유저 ID + - `start_date`: 시작일, 형식 `yyyy-MM-dd`, KST 기준 + - `end_date`: 종료일, 형식 `yyyy-MM-dd`, KST 기준 + - `creator_id`: 오리지널 시리즈 소지 유저 ID - `page`: 페이지 번호, Spring `Pageable` 규칙 사용 - `size`: 페이지 크기, Spring `Pageable` 규칙 사용 - Body @@ -84,7 +84,7 @@ #### Request Example ```text -GET /admin/calculate/original-series/settlement-details?startDate=2026-04-01&endDate=2026-04-30&memberId=1&page=0&size=20 +GET /admin/calculate/original-series/settlement-details?start_date=2026-04-01&end_date=2026-04-30&creator_id=1&page=0&size=20 ``` #### Response @@ -144,15 +144,15 @@ GET /admin/calculate/original-series/settlement-details?startDate=2026-04-01&end - Header - 인증: 관리자 권한 필요 (`hasRole('ADMIN')`) - Query Parameter - - `startDate`: 시작일, 형식 `yyyy-MM-dd`, KST 기준 - - `endDate`: 종료일, 형식 `yyyy-MM-dd`, KST 기준 + - `start_date`: 시작일, 형식 `yyyy-MM-dd`, KST 기준 + - `end_date`: 종료일, 형식 `yyyy-MM-dd`, KST 기준 - Body - 없음 #### Request Example ```text -GET /admin/calculate/original-series/settlement-details/excel?startDate=2026-04-01&endDate=2026-04-30 +GET /admin/calculate/original-series/settlement-details/excel?start_date=2026-04-01&end_date=2026-04-30 ``` #### Response @@ -164,7 +164,7 @@ GET /admin/calculate/original-series/settlement-details/excel?startDate=2026-04- #### Excel 구성 - 오리지널 시리즈 소지 유저별로 시트 1개 생성 -- 시트명 형식: `{memberId}_{nickname}` +- 시트명 형식: `{nickname}` - 각 시트의 헤더 열 순서 1. `시리즈 제목` 2. `콘텐츠 제목` @@ -184,24 +184,24 @@ GET /admin/calculate/original-series/settlement-details/excel?startDate=2026-04- 1. 소지 유저 조회 - GET /admin/calculate/original-series/owners -- 응답은 ApiResponse> 형태다. +- 응답은 ApiResponse> 형태다. 2. 정산 내역 조회 - GET /admin/calculate/original-series/settlement-details -- query: startDate(yyyy-MM-dd), endDate(yyyy-MM-dd), memberId(number), page(number), size(number) +- query: start_date(yyyy-MM-dd), end_date(yyyy-MM-dd), creator_id(number), page(number), size(number) - 응답은 ApiResponse<{ totalCount: number; items: Array<{ seriesTitle: string; contentTitle: string; price: number; orderType: string; salesCount: number; totalCan: number; totalPoint: number }> }> 형태다. 3. 엑셀 다운로드 - GET /admin/calculate/original-series/settlement-details/excel -- query: startDate(yyyy-MM-dd), endDate(yyyy-MM-dd) +- query: start_date(yyyy-MM-dd), end_date(yyyy-MM-dd) - 응답은 xlsx 바이너리이며 파일명은 `original-series-settlement-details.xlsx` 이다. 구현 요구사항: - 화면 진입 시 owners API를 먼저 호출해 멤버 선택 드롭다운 데이터를 로드한다. -- 사용자가 startDate, endDate, memberId를 선택한 뒤 정산 내역 조회 API를 호출한다. +- 사용자가 start_date, end_date, creator_id를 선택한 뒤 정산 내역 조회 API를 호출한다. - 목록 테이블에는 시리즈 제목, 콘텐츠 제목, 가격, 구분, 판매 수, 합계(캔), 합계(포인트)를 그대로 표시한다. - 페이지네이션은 page/size 기반으로 처리하고 totalCount를 사용해 총 페이지 수를 계산한다. -- 엑셀 다운로드 버튼은 현재 선택된 startDate/endDate만 사용해 excel API를 호출한다. +- 엑셀 다운로드 버튼은 현재 선택된 start_date/end_date만 사용해 excel API를 호출한다. - JSON 응답은 항상 ApiResponse 래퍼의 success/data/message/errorProperty를 기준으로 처리한다. - success가 false이면 message를 우선 노출한다. - 날짜는 문자열 `yyyy-MM-dd` 형식으로 서버에 전달한다.