# 에이전트 정산 기능 QA 계획 ## QA 목표 - 최근 구현된 agent authorization 및 settlement 기능에서 남아 있는 실제 결함을 백엔드 관점으로 점검한다. - 범위는 `src/main/kotlin/kr/co/vividnext/sodalive/admin/partner/agent/**`, `src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/**`로 한정한다. - 이미 수용된 두 가지 저우선순위 이슈(빈 finalized 기간 미생성, 중복 finalize 동시성 rough edge)는 제외한다. ## 작업 체크리스트 - [x] 관련 모듈/테스트/기존 작업 문서를 확인해 QA 범위를 정리한다. - [x] 백엔드 QA 시나리오를 20개 이상 도출하고 P0/P1/P2로 분류한다. - [x] P0/P1 시나리오를 중심으로 기존 테스트와 실행형 검증 명령을 수행한다. - [x] 실패 시 재현 경로와 실제 증거를 확보해 결함 여부를 확정한다. - [x] 최종 PASS/FAIL 판정을 정리하고 검증 기록을 남긴다. ## 검증 대상 축 - assignment create/remove 시간 경계 동작 - ratio create/update 검증과 history 동작 - calculate 5개 카테고리 조회 - snapshot finalize 및 finalized 조회 - provenance/source detail 무결성 - 신규 validation과 기존 동작의 상호작용 ## 시나리오 목록 ### P0 - [x] assignment 생성: 유효한 agent/creator/assignedAt이면 신규 이력 row가 생성된다. - [ ] assignment 생성: agentId와 creatorId가 같으면 거부된다. - [x] assignment 생성: agent가 AGENT 역할이 아니면 거부된다. - [x] assignment 생성: creator가 CREATOR 역할이 아니면 거부된다. - [x] assignment 생성: 활성 소속과 시간이 겹치면 거부된다. - [x] assignment 생성: 이전 소속의 `unassignedAt`과 동일한 `assignedAt`은 허용된다. - [x] assignment 해제: 활성 소속이면 `unassignedAt`이 기록된다. - [x] assignment 해제: `unassignedAt <= assignedAt`이면 거부된다. - [x] assigned creator 목록 조회: 다른 agent 소속 creator는 제외된다. - [x] assigned creator 목록 조회: 미래 `assignedAt`만 가진 예약 소속은 현재 목록에 노출되지 않아야 한다. - [x] assigned creator 목록 조회: 미래 `unassignedAt`이 있는 현재 소속은 종료 전까지 유지되어야 한다. - [x] ratio 생성: 유효한 `effectiveFrom`이면 활성 row 종료 후 신규 이력 row가 추가된다. - [x] ratio 생성/수정: `settlementRatio`가 0..100 범위를 벗어나면 거부된다. - [x] ratio 생성/수정: 과거 closed history 구간과 겹치는 `effectiveFrom`이면 거부된다. - [x] calculate 조회: 5개 카테고리 모두 거래 시점 assignment를 기준으로 agent가 갈린다. - [x] calculate 조회: 5개 카테고리 모두 거래 시점 ratio를 기준으로 agentSettlementAmount가 계산된다. - [x] calculate 조회: content는 콘텐츠 개별 ratio와 creator 기본 ratio fallback을 모두 반영한다. - [x] calculate 조회: 일반 정산/채널후원 모두 agent ratio 이력이 없으면 10% fallback이 적용된다. - [x] snapshot finalize: LIVE finalize는 immutable snapshot과 source detail을 함께 저장한다. - [x] snapshot finalize: 기간 내 source row가 여러 개면 summary FK는 비우고 provenance detail만 남긴다. - [x] finalized read: 5개 카테고리 모두 동일 기간 finalized snapshot을 live 계산보다 우선 사용한다. - [x] snapshot finalize: 동일 기간/타입/agent 재요청은 중복 저장 없이 alreadyFinalized=true를 반환한다. ### P1 - [ ] admin finalize: 대상 member가 없으면 실패한다. - [ ] admin finalize: 대상 member가 AGENT 역할이 아니면 실패한다. - [x] agent controller: 익명 사용자는 creator/list 조회에 실패한다. - [x] admin finalize controller: 익명 사용자는 finalize 호출에 실패한다. - [x] channel donation 조회: 분할 정산 레코드가 있어도 후원 건수는 distinct useCan 기준이다. - [ ] calculate 조회: 기간 내 결과가 없으면 total=0, items=[]로 일관되게 반환된다. - [ ] assigned creator 목록 조회: 정렬/페이지네이션이 creatorId desc 기준으로 유지된다. ### P2 - [ ] snapshot read: snapshot pagination이 `creatorId desc` 기준으로 안정적이다. - [ ] ratio 목록 조회: current/history가 페이지 응답에서 누락 없이 노출된다. - [x] provenance detail 합계는 snapshot summary 합계와 일치한다. - [ ] finalized 이후 ratio/assignment 변경이 생겨도 동일 finalized 기간 응답은 변하지 않는다. ## 검증 기록 ### 1차 QA - 무엇을: - assignment/ratio/calculate/snapshot/controller 축의 기존 테스트를 집중 실행했다. - `assigned creator list`의 시간창(window) 처리 누락 여부를 임시 DataJpa 재현 테스트로 검증했다. - 왜: - 기존 테스트가 보장하는 범위와, 목록 조회처럼 테스트 공백이 있는 시간 경계 시나리오를 분리해서 확인해야 실제 latent bug를 잡을 수 있기 때문이다. - 어떻게: - 성공: `./gradlew test --tests kr.co.vividnext.sodalive.admin.partner.agent.assignment.AdminAgentCreatorServiceTest --tests kr.co.vividnext.sodalive.admin.partner.agent.ratio.AgentSettlementRatioServiceTest --tests kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateServiceTest --tests kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateQueryRepositoryTest --tests kr.co.vividnext.sodalive.admin.partner.agent.settlement.AdminAgentSettlementSnapshotServiceTest --tests kr.co.vividnext.sodalive.admin.partner.agent.settlement.AdminAgentSettlementSnapshotControllerTest --tests kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateControllerTest` → BUILD SUCCESSFUL - 성공: `./gradlew test --tests kr.co.vividnext.sodalive.admin.partner.agent.assignment.AdminAgentCreatorControllerTest --tests kr.co.vividnext.sodalive.admin.partner.agent.ratio.AdminAgentSettlementRatioControllerTest` → BUILD SUCCESSFUL - 실패 재현 1: 임시 QA 테스트에서 미래 `assignedAt` 예약 소속 목록 노출 검증 → `TEST-kr.co.vividnext.sodalive.partner.agent.calculate.AgentAssignedCreatorFutureWindowQaTest.xml` 기준 `expected <0> but was <1>` - 실패 재현 2: 임시 QA 테스트에서 미래 `unassignedAt` 이전 현재 소속 유지 검증 → `TEST-kr.co.vividnext.sodalive.partner.agent.calculate.AgentAssignedCreatorFutureWindowQaTest.xml` 기준 `expected <1> but was <0>` ### 2차 QA 문서 정리 - 무엇을: - 이후 수정/테스트로 증거가 확보된 QA 항목만 문서 상태를 최신화했다. - 왜: - 현재 QA 문서는 일부 항목이 이미 수정/검증되었는데도 실패 메모나 미체크 상태로 남아 있어, 실제 상태와 문서가 어긋나 있었기 때문이다. - 어떻게: - `src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepositoryTest.kt:91-110` 확인 → 현재 시각 활성 구간 creator list 회귀 테스트가 미래 `assignedAt` 미노출 / 미래 `unassignedAt` 이전 유지 두 조건을 함께 검증함을 확인했다. - `docs/20260408_에이전트권한및정산기능추가.md:644-658` 확인 → 위 creator list window 버그가 17차 수정에서 실제 수정되고 테스트/빌드 검증까지 완료되었음을 확인했다. - `src/test/kotlin/kr/co/vividnext/sodalive/admin/partner/agent/settlement/AdminAgentSettlementSnapshotServiceTest.kt:191-201` 확인 → provenance detail 각 수치 합계가 snapshot summary와 일치하는 검증이 이미 존재함을 확인했다. - 위 세 근거에 따라 creator list 2개 항목의 실패 메모를 제거하고, `provenance detail 합계` 항목을 완료 처리했다.