이름을 바꾸면 그 센터를 쓰던 기존 출고 건과 어긋날 수 있어 수정 경로를
막는다. 잘못 등록한 센터는 삭제 후 새로 등록.
- 목록 행: 이름 input+저장 버튼 → 읽기 전용 텍스트
- center_edit 라우터에서 name 폼 파라미터 제거(활성/정렬만 수정)
- 행이 좁아져 그리드 최소폭 340px → 240px
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
센터 목록은 이름 등록·조회·관리가 목적이므로 "사용중" 표시를 없애고
활성/비활성/삭제만 남긴다. 좌우 2단(추가 카드 360px + 900px 고정 목록)
대신 상단 추가·검색 바 + 다중 컬럼 그리드로 바꿔 29개 이상 센터를
한 화면에서 훑을 수 있게 했다.
- 행마다 폼 하나(formaction/name=active)로 저장·토글·삭제 처리
- 상태는 배지 대신 좌측 점(활성 초록 / 비활성 회색+흐리게)
- 클라이언트 검색 필터, 카운트 실시간 갱신
- 라우터에서 center_in_use 조회 제거(화면에서 미사용)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
모든 박스(제품별 + 혼합)를 센터에 담아 미배분 잔여가 0 이 되면 ② 요약의
"센터 배분" 칸에 빨간 "전체 배분 완료" 도장을 찍는다. 처음 완료될 때만
찍히는 애니메이션이 돌고, 하나라도 빼면 도장이 사라진다. 재계산하면
기록도 초기화된다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 혼합 박스 도장이 흐리게 보이던 원인: 부모(.cpg-box-title)에 opacity 를
주면 자식 도장까지 함께 흐려진다 → 제목은 색만 낮추고 도장은 opacity 1.
- 렌더할 때마다 모든 도장에 애니메이션이 다시 걸리던 문제: 이미 찍힌
항목을 stamped 로 기억해 새로 완료된 도장(.is-new)에만 애니메이션.
잔여가 다시 생기거나 재계산하면 기록을 지워 다음 완료 때 다시 찍힌다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- ② 제품별 카드에서 "쿠팡박스" 배지 제거(모든 규칙이 같은 박스명이라 무의미)
- 배분이 끝난 제품 카드·혼합 박스에 파란 "배분 완료" 도장(살짝 기울어진
테두리, 찍히는 애니메이션)
- 완료된 카드는 글자를 회색으로 낮추고, 혼합 박스는 상자 아이콘까지
흑백 처리해 남은 카드와 한눈에 구분되게 함
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
③ 센터 분배에서 혼합 박스 줄 아래에 무엇이 몇 개 들어가는지 트리로
펼쳐 보여준다. 2박스 이상이면 총 개수와 함께 "(4개 × 2박스)" 를 덧붙인다.
수량을 바꾸면 트리 수치도 즉시 갱신된다. 단일 제품 박스는 트리가 없다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- ③ 센터 분배: 목록에서 센터를 고르는 즉시 추가된다. "+ 센터 추가" 버튼
제거. 고른 뒤 선택값을 비워 같은 센터를 다시 고를 수 있게 한다.
- 담기 대화상자: 센터 select 를 추가된 센터 버튼 목록으로 바꿔 한 번에
대상을 고른다(현재 대상은 검은 버튼 + aria-pressed).
tests/js: 센터 추가를 change 이벤트로, 대화상자 센터 버튼 표시·전환·
선택한 센터로 담기는지까지 검증. 전체 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
47e09b9 되돌리기로 cupang.css 내용이 20260829e 시점으로 돌아갔지만,
브라우저에 20260829f(핸들 스타일 포함)가 캐시돼 있을 수 있어 새 버전으로
올린다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Pointer Events 기반으로 바꾸고(터치·펜 지원, setPointerCapture 로 창 밖
이동에도 이벤트 유실 없음) 업무툴 수준의 조작 피드백을 붙였다.
- 드래그 핸들(⠿)에서만 드래그 시작 → 카드 클릭/텍스트 선택과 충돌 없음
- 커서를 따라오는 고스트에 "잔여 N박스" 배지, 담을 수 없는 위치에서는
빨간 테두리로 금지 표시
- 대상 센터에 "○○ — 여기에 담기" 플레이스홀더를 끼워 놓일 자리를 보여줌
- 센터 목록 위/아래 44px 안에 커서가 오면 자동 스크롤(센터가 많을 때 필수)
- pointermove 처리는 requestAnimationFrame 으로 1프레임 1회만 실행
- pointercancel / 창 blur / Esc 에서 드래그를 안전하게 취소
SortableJS 도입은 보류했다. 웨일에서 네이티브 DnD 가 시작조차 되지 않아
어차피 fallback 모드로만 동작하고, 브라우저 실측 검증 수단이 없는 상태에서
의존성만 늘어난다.
tests/js: 핸들 밖 드래그 차단·고스트 배지·플레이스홀더·금지 표시·Esc 취소
시나리오 추가(rAF 지연을 고려해 프레임 대기). 전체 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
웨일에서 카드를 눌러 움직여도 드래그 미리보기조차 생기지 않았다 =
HTML5 네이티브 DnD 가 시작 자체를 못 한 것. 브라우저 구현에 기대는
draggable/dragstart 를 걷어내고 마우스 이벤트로 직접 구현했다.
- mousedown 후 4px 이상 이동하면 드래그 시작, 카드 복제본(고스트)이
커서를 따라온다. 커서 아래 센터 패널은 elementFromPoint 로 찾아 강조.
- mouseup 위치의 센터에 놓으면 수량 대화상자가 열린다. ③ 카드 여백에
놓아도 센터가 하나면 그 센터로, ③ 밖이면 안내만 띄우고 담지 않는다.
- Esc 로 드래그 취소. 카드 위에서 손을 뗀 경우에만 뒤따르는 click 을
1회 무시해, 드래그 후에도 클릭 경로가 막히지 않는다.
tests/js: 드래그 시작 임계값·고스트 생성/제거·대상 강조·여백 드롭·
③ 밖 드롭·클릭 대체 경로까지 마우스 이벤트로 검증. 전체 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
드래그가 브라우저에서 먹지 않던 문제를 추정 대신 실패 가능 지점별로
전부 막았다.
- dragstart 리스너를 카드 요소에 직접 바인딩(위임으로는 잡히지 않는
환경 대비). 렌더할 때마다 다시 바인딩한다.
- dragenter/dragover 를 모두 preventDefault — 하나만 막으면 드롭을
거부하는 브라우저가 있다.
- 드롭 대상 범위를 ③ 카드 전체로 확대하고, 대상 패널은
closest → elementFromPoint → (센터가 하나면) 그 센터 순으로 찾는다.
패널 사이 여백에 놓아도 담긴다.
- dataTransfer.setData/getData 가 막힌 환경 대비로 dragKey 를 따로 보관해
드롭 시 사용한다. 그래도 못 읽으면 클릭으로 담으라는 안내를 띄운다.
- 드래그 중에는 ③ 영역에 점선 강조를 준다.
- 드래그 직후 발생하는 click 은 무시해 대화상자가 두 번 뜨지 않게 한다.
센터 선택 목록은 이름 가나다순 정렬(한글 음절은 코드포인트 순).
tests/js: 여백 드롭·dragenter·setData 차단 환경 시나리오 추가. 전체 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
드래그가 먹지 않던 원인: 드롭 대상이 점선 상자(.cpg-dist-drop) 안쪽으로
한정돼 센터 카드 여백에 놓으면 dragover 에서 preventDefault 가 걸리지
않았다 → 드롭 대상을 센터 패널 전체로 넓혔다. 카드를 클릭해도 같은
대화상자가 열리는 대체 경로도 추가.
- ③ 은 처음에 비어 있고, 셀렉트에서 고른 센터만 패널로 추가된다(✕ 로 제거,
제거하면 담긴 박스는 잔여로 복귀)
- 드롭/클릭 시 대화상자에서 박스 수량을 입력한다. "잔여 전부 담기" 버튼으로
남은 수량을 한 번에 담을 수 있고, Enter 로 확정 / Esc 로 취소
- 센터에 담긴 줄과 센터 합계에 박스 수와 상품 수(박스×입수량)를 함께 표시
- 요약 카드에도 잔여 개수(잔여 박스 × 입수량)를 표시
tests/js: jsdom 으로 계산→드래그→대화상자→수량 수정→제거까지 36개 항목을
검증하는 UI 테스트 추가(README 에 실행법). 전체 통과 확인.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
① 박스 계산: 제품명·수량만 입력(결과 열 제거). 수량 칸에서 Tab 은 다음
행 수량으로 이동하고 마지막 행이면 새 행을 추가한다. Enter 는 계산.
② 박스 요약: 제품별 박스/자투리 혼합 박스 카드가 드래그 소스. 표시되는
수치는 센터에 배분하고 남은 "잔여" 기준으로 실시간 갱신되며, KPI 는
총 박스 / 센터 배분 / 미배분 잔여 3개로 바꿨다.
③ 센터 분배: 활성 입고센터(cupang_centers)만 표시. 카드를 끌어다 놓으면
해당 센터에 1박스가 담기고, 박스 수량을 직접 입력할 수 있다(잔여를
넘으면 자동으로 잘림). ✕ 로 빼면 잔여로 되돌아간다.
혼합 박스는 내용이 서로 달라 1장 = 1박스로 취급한다. 분배 내역은 화면
안에서만 유지(DB 저장 없음)하며, 재계산하면 근거가 바뀌므로 초기화한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 제품 드롭다운은 제품명만 표시(박스·입수량 병기 제거)
- 표 머리글 가운데 정렬 + 굵게
- 셀 옆에 나타나던 "…"" 제거: input/button 이 든 셀까지 text-overflow:
ellipsis 가 걸려 빈 말줄임표가 그려졌다. 말줄임은 글자 셀에만 적용
- 혼합 박스 그림의 호수 추출 로직 삭제 → 항상 "쿠팡박스" 표기(글자 수에
맞춰 라벨 크기 11px)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
상자 SVG 안에 "2호"처럼 호수만 넣는다("쿠팡 " 접두어 제거).
채움 색 위에서도 읽히도록 흰색 외곽선(paint-order: stroke)을 준다.
aria-label 도 "2호 박스"로 바꿔 스크린리더에서 구분 가능하게 함.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
itemcode_db 목록에 없는 상품도 제품명·제품코드를 직접 입력해 등록할 수
있게 왼쪽 카드 상단에 폼 추가. 기존 POST /cupang/products (upsert)를
그대로 사용하며 같은 제품코드는 덮어쓴다. itemcode 검색이 비활성인
환경에서도 동작하도록 search_enabled 분기 밖에 둔다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
제품명 열이 남는 폭을 전부 가져가면서 다른 열이 눌려 헤더가 "박…"
처럼 잘렸다. 제품명 열에 고정 폭 180px 을 주고 수량 78 / 박스·입수량
116 / 숫자 64 / 삭제 40 으로 되돌려, 남는 폭은 지정 폭 비율대로
나눠 갖게 한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
요약 카드에 남아 있던 margin-top:16px 이 2열 그리드에서 오른쪽 카드를
아래로 밀고 있었다 → 0 으로.
가로 스크롤: fixed 레이아웃에서도 셀 내용이 밖으로 삐져나오면 래퍼가
스크롤되므로 th/td 에 overflow:hidden + text-overflow:ellipsis 를 주고
래퍼는 overflow-x:hidden 으로 고정. 열 폭도 축소(수량 68 / 박스 96 /
숫자 46 / 삭제 34). 드롭다운 라벨은 "미라네 1호 세트 (2호·8)" 처럼
"쿠팡 " 접두어를 떼어 짧게 표기.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
.erp-input 의 min-width:240px 때문에 수량 칸이 넓어져 표가 가로로
넘쳤다. 계산표를 table-layout:fixed + colgroup 고정폭으로 바꾸고
수량/선택 입력의 min-width 를 해제, 셀 여백을 8px 6px 로 축소.
박스명·입수량 열을 "박스 / 입수량" 한 열로 합치고(쿠팡 2호 · 8개),
헤더를 박스/낱개/필요 로 줄이고 삭제 버튼을 ✕ 아이콘으로 바꿔 열 수를
8 → 7 로 줄였다.
2열 그리드를 align-items:stretch 로 두고 카드를 flex column 으로 만들어
좌우 카드 높이를 맞춘다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
입력표와 요약을 좌우 2열 그리드로 배치(1280px 이하는 세로 쌓기).
입력표는 자체 스크롤(max-height + sticky thead)로 행이 늘어도 카드가
잘리지 않게 하고, 요약 그리드 최소 폭을 줄여 좁은 열에서도 카드가
한 줄에 맞게 조정.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
하단 "박스명별 합계" 표를 요약 카드로 교체.
- KPI 3개: 총 박스 / 제품별 박스 / 혼합 박스(자투리 N개)
- 제품별 카드: 몇 박스 + 자투리 몇 개(딱 맞으면 "딱 맞음")
- 자투리 혼합 박스: 박스 1개당 카드로 어떤 상품이 몇 개 들어가는지 표시.
상자 SVG(뚜껑 열림·내용물 차오름), 채움률 바, 카드 등장 애니메이션.
prefers-reduced-motion 에서는 애니메이션 비활성.
혼합 계산은 서버 _pack_leftovers: 박스 용량을 1 로 두고 제품 1개 =
1/units_per_box 부피로 환산, 같은 박스명끼리만 채운다. 부동소수 오차를
피하려고 Fraction 사용. 한 제품 자투리가 두 박스로 나뉘는 것은 허용해
박스 수가 최소가 되게 한다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
달력 상단 "박스 계산" 버튼 → /cupang/box-calc. 제품명+수량을 여러 행
입력하면 제품별 박스 수·남은 낱개·총 필요 박스와 박스명별 합계를 계산.
수량/제품을 고치고 "계산 / 재계산" 으로 다시 계산할 수 있다(수량 칸에서
Enter 도 동일). 저장하지 않는 계산 전용 화면.
계산은 POST /cupang/api/box-calc 에서 store.compute_boxes 로 수행 —
클라이언트 계산을 신뢰하지 않는다. 입수량 규칙이 없는 제품은 "미설정"
으로 표시하고 합계에서 제외.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
제품명/제품코드 헤더 클릭으로 오름·내림차순 토글. Intl.Collator(ko,
numeric) 사용해 "미라네 2호"가 "미라네 10호"보다 앞에 오도록 정렬.
검색 비활성 상태에서도 동작하게 스크립트를 search_enabled 밖에 배치.
박스 입수량 14건(미라네 1~7호, 황토 김치통 1~7호) 시드 SQL 추가.
피킹비 전용 컬럼이 없어 memo 에 기록.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- ItemcodeReader.last_error 추가, _run 실패 시 logger.exception + 메시지 보존
- /api/products/all 응답에 error/count 추가
- products 화면: 결과 0 일 때 조회오류/사유 표시 (그냥 '결과 없음' 대신)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- erp 셸 height:100vh + body overflow:hidden, .erp-page 가 남은 높이 채우고 내부 스크롤
- 휴가 달력: 6주 행이 가용 높이 균등 분할(유동), 날짜 셀 height:100%, 선택일 패널 내부 스크롤
- 쿠팡 출고 폼: 라인 패널 고정 900px 높이 → 가용 높이 채움
- CORM/Order 는 별도 창이라 해당 없음
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
진짜 원인: erp.css .erp-input{min-width:240px} 가 width:185 를 눌러 240 고정.
헤더 입력 규칙에 min-width:185px 추가로 해결. 캐시 버전 c 로 bump.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
브라우저가 옛 cupang.css/erp-shell.css 를 캐시해 최근 레이아웃 변경
(헤더 185px, 콘텐츠 1550px 등)이 반영되지 않던 문제. 링크에 버전 쿼리 추가.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 헤더 입력 185px 특이도 강화(.cpg .cpg-header-grid .erp-field>input)
- 라인 추가/삭제 버튼을 "품목 라인" 제목행 우측으로 이동(하단 footer 제거)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 공통 헤더 450px, 품목 라인 900x900 내부 스크롤
- 저장/취소 위 구분선 제거
- 라인 추가 + 라인 삭제 버튼을 품목 라인 하단 우측에 배치
- 행별 ✕ 삭제 제거 → "라인 삭제"가 마지막 라인 삭제(최소 1줄 유지)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>