feat(cafe24): 옵션값+품목 통합 목록, 드래그 순서, 옵션값 불러오기

- 옵션 1개 상품은 한 행에 썸네일·옵션값 이름·품목코드(복사)·자체코드·
  추가금액·진열·판매를 두고 「저장」 한 번으로 옵션 PUT → 품목 PUT.
- 옵션 없는 상품: 행 추가/삭제 후 저장 → 옵션 생성 → 카페24가 부여한
  품목코드를 재시도 조회(products.wait_for_variants)로 받아 자체코드·
  추가금액·썸네일까지 이어서 반영.
- 순서 드래그는 품목 display_order 로 저장(옵션값 재배열 PUT 은 위치 짝맞춤
  때문에 품목코드↔이름이 뒤바뀔 수 있어 사용하지 않음).
- 「옵션값 불러오기」: 탭/공백 구분 텍스트(이름·판매가·추가금액·자체코드)
  붙여넣기 → 행 자동 채움. 기존 옵션은 이름으로 짝지어 코드/금액만.
- 옵션 2개 이상(조합) 상품은 기존 2열 화면 유지.
- 모달 JS 를 app/static/cafe24-options.js 로 분리. 유닛테스트 90 통과,
  통합 하네스 통과, 헤드리스 크롬 렌더 확인.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-18 23:25:52 +09:00
parent be0d44ded6
commit 8125a59366
8 changed files with 1002 additions and 360 deletions
+20 -2
View File
@@ -149,7 +149,7 @@ Admin API(OAuth)로는 스킨 파일을 읽거나 쓸 방법이 없다(`config.p
상품 클릭 시 `/products/{no}/pane` 이 편집기 조각과 패널 조각을 **한 응답**(`_panes.html`,
`[data-pane=editor]`/`[data-pane=side]`)으로 돌려주고 JS 가 각각 끼운다 — 카페24 상품
조회는 1회. 옵션/품목은 패널의 「팝업에서 관리」 버튼으로 **모달**(`#cf24-options-modal`,
최대 1280px·높이 90vh — 왼쪽 옵션 정의(340px) / 오른쪽 품목 표, 두 열 모두 창 바닥까지 각자 스크롤. 품목코드 클릭 = 클립보드 복사)을 열 때 JSON 으로 따로 불러온다(호출 2회
최대 1280px·높이 90vh — 옵션 1개 상품은 옵션값+품목 통합 목록, 조합 상품은 왼쪽 옵션 정의(340px) / 오른쪽 품목 표. 품목코드 클릭 = 클립보드 복사. 로직은 `app/static/cafe24-options.js`)을 열 때 JSON 으로 따로 불러온다(호출 2회
절약). 380px 패널은 품목 표를 담기에 좁아(실측) 별도 창으로 뺐다. 모달은 페이지에 하나만
두고(패널 조각 교체와 무관) 다른 상품을 고르면 닫힌다. 저장 안 한 변경(`.is-dirty`)이
있으면 닫을 때 확인창.
@@ -462,7 +462,25 @@ cafe24_oauth_tokens 저장
- "옵션별 상품 이름" 은 옵션값(`option_text`)이고, "옵션별 썸네일" 은 `option_image_file`
(+ `option_link_image` 에도 같은 경로) 이며,
화면의 옵션값 썸네일은 **`option_image_file` → `option_link_image` → 그 옵션값을 가진
품목의 `image`** 순으로 있는 것을 보여준다. 카페24 관리자에서 "옵션 연결 이미지"로만
품목의 `image`** 순으로 있는 것을 보여준다.
- **통합 목록**(`app/static/cafe24-options.js`): 옵션이 1개(옵션명 하나)인 상품은 옵션값과
품목이 1:1 이므로 한 행에 드래그핸들 · 썸네일 · 옵션값 이름 · 품목코드(클릭 복사) ·
자체 품목코드 · 추가금액 · 진열 · 판매를 두고 「저장」 한 번에 옵션 PUT(이름/썸네일/
표시방식, **원래 순서로** 짝지어 전송) → 품목 PUT(자체코드/추가금액/진열/판매/순서)
순으로 반영한다. 옵션이 없는 상품은 행을 추가/삭제해 두고 저장하면 옵션 생성(POST) →
카페24가 부여한 품목코드를 `products.wait_for_variants`(읽기 지연 재시도)로 받아 →
자체코드/추가금액을 품목 PUT → 썸네일이 있으면 옵션 PUT 까지 이어서 한다.
옵션이 2개 이상(조합)인 상품은 1:1 이 아니라 2열 화면(옵션 정의 / 품목 표)을 쓴다.
- **순서 드래그**는 품목의 `display_order`(문서: 조합형 품목 진열순서 1~300)로 저장한다.
옵션값 배열을 재배열해 PUT 하지 **않는다** — 카페24는 `original_options` 와 `options`
를 위치로 짝지어 이름을 바꾸므로, 재배열하면 품목코드와 이름이 뒤바뀔 수 있다
(품목코드는 주문 이력이 참조한다). 조합형(T)이 아닌 옵션은 핸들을 숨긴다.
카페24 GET variants 응답에 `display_order` 가 없어 다시 열었을 때 순서는 카페24가
돌려주는 순서를 따른다.
- **옵션값 불러오기**: 텍스트(탭 또는 두 칸 이상 공백 구분 — 이름 · 판매가 · 추가금액 ·
자체코드, 판매가는 무시, 추가금액 「-」는 0)를 붙여넣어 행에 채운다. 옵션이 있는 상품은
이름(공백 무시)으로 짝을 찾아 자체코드/추가금액만 채우고, 없는 이름은 건너뛴다(옵션값
추가는 API 미지원). 카페24 관리자에서 "옵션 연결 이미지"로만
등록한 상품은 `option_image_file` 이 비어 있고 품목 `image` 에만 나타난다(실물 —
버튼 이미지만 보면 "없음"으로 오인했던 사고). 품목은 모달 오른쪽 열에 표(이미지 ·
옵션 · 품목코드 · 자체코드 · 추가금액 · 진열 · 판매)로 그린다. "옵션별 상품코드/추가금액/진열" 은 품목