{
  "issueId": "3888",
  "environment": "dev",
  "scenario": "transaction-offset-dedup",
  "source": "Redmine #3888 + user-provided QA checklist 2026-07-27",
  "sourceText": "주홍석님의 QA 요청입니다. 상계 이벤트가 중복 처리될 때 거래내역의 상계 금액이 두 배로 표시되는 현상을 수정했습니다. 거래일시/취소일시 2026-07-27 15:44:19, PG사 루시페이먼츠, 계약·MID명 A_주홍석_단말기정산한도_루시, 법인 A_주홍석_정산법인, 가맹점 A_주홍석_단말기정산분리_가맹(BP100548), 취소금액 80,000원, 수수료 10%, 정산금액 72,000원이며 상계 이력이 없는 거래를 대상으로 가맹점만 상계 40,000원을 두 번 처리한 뒤 실제 정산금액 기준 36,000원과 누적 72,000원이 표시되고, 새로고침·재진입 후에도 144,000원으로 중복되지 않는지 확인합니다.",
  "scope": "개발계 기본 ADMIN 계정으로 지정 취소 거래 1건에 가맹점만 부분상계를 40,000원씩 두 번 수행하고 거래내역 API와 목록/상세 화면에서 상계금액 및 완료 상태의 일관성과 중복 방지를 검증한다.",
  "roles": [
    "ADMIN"
  ],
  "checklist": [
    "거래내역 화면에서 지정 거래의 취소금액 80,000원, 수수료 10%, 정산금액 72,000원 및 상계 이력 없음 확인",
    "가맹점만 상계 옵션으로 40,000원을 부분상계한 뒤 화면 상계금액 36,000원 확인",
    "같은 거래에 나머지 40,000원을 상계한 뒤 누적 상계금액 72,000원 확인",
    "상계 완료 후 여러 번 새로고침하고 목록에서 나갔다 재진입해도 상계금액이 72,000원으로 유지되고 144,000원으로 중복되지 않는지 확인",
    "거래 목록과 상세 화면의 상계금액 72,000원 및 상계 완료 상태가 동일한지 확인"
  ],
  "setupSteps": [
    {
      "name": "개발계 ADMIN 로그인 및 지정 거래 확인",
      "kind": "state-verify",
      "role": "ADMIN",
      "application": "admin",
      "description": "거래일시 2026-07-27 15:44:19, 가맹점 BP100548, 취소금액 80,000원인 취소 거래가 1건이고 상계 이력이 없는지 API와 화면에서 확인한다.",
      "required": true,
      "mutation": "none",
      "navigation": {
        "name": "거래내역",
        "path": "/trade-history-v2"
      }
    },
    {
      "name": "가맹점만 부분상계 2회 처리",
      "kind": "data-update",
      "role": "ADMIN",
      "application": "admin",
      "description": "지정 거래에 가맹점만 상계 40,000원을 두 번 처리한다. 실행 전 거래의 상계금액이 0원 또는 36,000원 또는 72,000원인지 확인하고, 72,000원인 경우 추가 요청을 보내지 않는다.",
      "required": true,
      "mutation": "persistent",
      "guardEnv": "QA_3888_ALLOW_MUTATION",
      "navigation": {
        "name": "거래내역",
        "path": "/trade-history-v2"
      }
    }
  ],
  "pages": [
    {
      "name": "거래내역",
      "application": "admin",
      "path": "/trade-history-v2",
      "tenantParam": "tenantId",
      "roles": [
        "ADMIN"
      ],
      "dataRequestUrlPattern": "/api/v2/transactions",
      "recordsSelector": "[role='grid']"
    }
  ]
}
