{
  "issueId": "4041",
  "environment": "dev",
  "source": "Redmine #4041 QA checklist - sales line payment method selection",
  "scenario": "sales-line-payment-method-selection",
  "sourceText": "ADMIN(bigs_jjm), TA(jjmta01) 각각 실제 UI에서 업체관리 > 가맹점관리 > 현재 영업라인 조회 모달을 열고 BP100060의 MID를 선택/저장한다.\n수기/ISP MID만 활성 선택할 수 있고 단말기 MID selector는 비활성 상태여야 한다.\n수기 후보가 3개이므로 두 번째 수기 선택 시 첫 번째가 해제되어 타입별 1개임을 확인한다.\nISP 1개 선택 후 저장하고 모달 재오픈 시 유지 확인.\n기본 VE 계정 jjmve01 소속 BP100488은 ADMIN UI에서 수기 MID를 저장한 뒤 jjmve01 인증 context로 GET /api/v1/store/departments/{departmentId}를 호출해 payload.paymentMethods의 MANUAL MID ID와 available 값이 저장값과 일치하는지 확인한다.\n저장은 실제 UI로만 수행하고, 검증 종료 후 제품이 제공하는 공식 MID 선택 DELETE API로 선택값을 제거한 뒤 관리자 API/UI에서 null·미선택을 확인한다. 스토어 API는 선택값이 null이어도 활성 영업라인을 기본 결제수단으로 반환할 수 있으므로 원복 후 값은 증거로 기록한다.\nserial; retain-on-failure trace; JSON/text/screenshot evidence.",
  "scope": "dev ADMIN(bigs_jjm)과 TA(jjmta01)가 BP100060 현재 영업라인 모달에서 수기/ISP 결제 MID를 타입별 한 개 선택·저장하는지 검증하고, ADMIN UI로 기본 VE(jjmve01) 소속 BP100488의 수기 MID를 저장했을 때 스토어 가맹점 상세 API에 반영되는지 검증한다.",
  "roles": [
    "ADMIN",
    "TA",
    "VE"
  ],
  "subjectAccounts": [
    {
      "role": "ADMIN",
      "label": "bigs_jjm",
      "envRole": "ADMIN"
    },
    {
      "role": "TA",
      "label": "jjmta01",
      "envRole": "TA"
    },
    {
      "role": "VE",
      "label": "jjmve01",
      "envRole": "VE"
    }
  ],
  "checklist": [
    "ADMIN(bigs_jjm), TA(jjmta01) 각각 실제 UI에서 업체관리 > 가맹점관리 > 현재 영업라인 조회 모달을 열고 MID를 선택/저장한다.",
    "수기/ISP MID만 선택할 수 있고 단말기 MID selector는 비활성 상태여야 한다.",
    "수기 후보가 3개이므로 두 번째 수기 선택 시 첫 번째가 해제되어 타입별 1개임을 확인한다.",
    "ISP 1개 선택 후 저장하고 모달 재오픈 시 유지 확인.",
    "ADMIN UI에서 기본 VE 계정 jjmve01 소속 BP100488의 수기 MID를 저장한 뒤 jjmve01 인증 context의 payload.paymentMethods MANUAL 값이 저장값과 일치하는지 확인.",
    "각 테스트는 최초 null selection을 확인하고 검증 후 공식 MID 선택 DELETE API로 정리한 다음 관리자 API/UI에서 null·미선택을 확인하고 스토어 API 원복 후 값을 기록.",
    "선택 저장은 실제 UI의 저장 버튼으로만 수행하며, 데이터 정리는 제품의 공식 선택 해제 DELETE API로 수행한다.",
    "역할별 테스트를 serial로 실행하고 실패 시 trace와 JSON/text/screenshot 증거를 남긴다."
  ],
  "routeCandidates": "../../../../qa-results/issues/4041/dev/route-candidates.json",
  "setupSteps": [
    {
      "name": "가맹점 결제 MID 선택 및 null 원복",
      "kind": "data-update",
      "role": "ADMIN",
      "application": "admin",
      "targetRoles": [
        "ADMIN",
        "TA"
      ],
      "description": "ADMIN/TA는 BP100060의 수기/ISP MID를 실제 UI에서 임시 선택·저장한다. ADMIN은 jjmve01 소속 BP100488의 수기 MID도 실제 UI로 저장한다. 검증 종료 시 공식 선택 해제 DELETE API로 임시 선택을 제거한다.",
      "spec": "sales-line-payment-method-selection.spec.ts",
      "required": true,
      "mutation": "temporary",
      "guardEnv": "QA_4041_ALLOW_MID_SELECTION_MUTATION",
      "navigation": {
        "name": "업체관리 > 가맹점관리",
        "path": "/business/vendor-manage"
      },
      "target": {
        "type": "vendor-mid-selection",
        "roles": [
          "ADMIN",
          "TA"
        ],
        "description": "전체 선택 규칙: 박재민_가맹_한결데 / BP100060 / 11f1-33eb-927a3697-87a8-000000000001. VE API 반영: A_주홍석_가맹3 / BP100488 / 11f1-3f1c-09912f8c-8bc6-000000000001"
      },
      "actions": [
        {
          "name": "두 번째 수기 MID 선택",
          "intent": "수기 후보 3개 중 lucy04084m을 선택하고 첫 번째 수기 MID가 자동 해제되는지 확인한다.",
          "selector": "input[type=checkbox][aria-label='수기 MID 선택']",
          "required": true
        },
        {
          "name": "ISP MID 선택",
          "intent": "bigshrtg000m ISP MID를 선택한다.",
          "selector": "input[type=checkbox][aria-label='ISP MID 선택']",
          "required": true
        },
        {
          "name": "UI 저장",
          "intent": "정확한 저장 버튼을 눌러 PUT mid-selection 요청을 발생시킨다.",
          "selector": "button:has-text('저장')",
          "required": true
        }
      ],
      "restore": {
        "required": true,
        "description": "각 테스트의 finally 단계에서 선택한 MID별 공식 DELETE endpoint를 호출하고, 관리자 GET은 모두 null, 재오픈 UI는 모두 미선택인지 확인한다. 스토어 API는 선택 null 상태에서도 활성 MID를 기본 결제수단으로 반환할 수 있어 원복 후 응답을 증거로 기록한다.",
        "spec": "sales-line-payment-method-selection.spec.ts"
      },
      "evidence": [
        {
          "name": "선택 유지 및 null 원복 screenshot",
          "description": "저장 후 재오픈 상태와 원복 후 재오픈 상태를 역할별 PNG로 첨부한다."
        },
        {
          "name": "API/UI 검증 JSON 및 text",
          "description": "UI PUT request body/status, 관리자 선택 GET, 기본 VE 스토어 paymentMethods, 정리 DELETE status를 JSON과 Markdown으로 첨부한다."
        },
        {
          "name": "실패 trace",
          "description": "실패한 역할에 Playwright trace zip을 첨부한다."
        }
      ]
    }
  ],
  "pages": [
    {
      "name": "가맹점관리",
      "application": "admin",
      "roles": [
        "ADMIN",
        "TA"
      ],
      "path": "/business/vendor-manage",
      "tenantParam": "tenantId",
      "recordsSelector": "[data-route-keep-alive-active=true] [role=row]",
      "detailOpenSelector": "[role=row] button:has-text('5')",
      "dataRequestUrlPattern": "/api/v1/pgmids/vendors/.*/mid-selection"
    },
    {
      "name": "스토어 가맹점 상세 API",
      "application": "store",
      "roles": [
        "VE"
      ],
      "path": "/api/v1/store/departments/11f1-3f1c-09912f8c-8bc6-000000000001",
      "tenantParam": "tenantId",
      "dataRequestUrlPattern": "/api/v1/store/departments/"
    }
  ]
}
