Files
wace_rps/frontend/app/(main)/COMPANY_7/pop/POP.md
T
kmh 4ed4d5f66e WIP: POP + packaging 작업 중
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 14:55:28 +09:00

45 KiB
Raw Blame History

POP 구조 설계 문서


0. 작업 규칙 (POP 영역 작업 시작 전 필독)

0-1. 이 문서 참조 의무

  • frontend/app/(main)/COMPANY_7/pop/ 하위 파일을 읽거나 수정하기 전에 이 POP.md를 반드시 먼저 Read
  • 세션 내 이전에 한 번 읽었더라도, POP 영역 작업에 새로 진입할 때마다 다시 Read (기억 의존 금지)
  • 이 규칙은 매 작업 지시에 자동 적용 — 사용자가 재공지하지 않아도 준수

0-2. 스코프 제한 지시어 (절대 넘지 않음)

사용자가 아래 표현을 쓰면 UI 껍데기만 가져오고 로직 일절 이식 금지:

  • "UI 구조만", "UI만 따와", "껍데기만", "뼈대만", "구조만 클론", "DB 연동 제외"

이식 금지 대상:

  • apiClient / dataApi / fetch 호출 전부
  • useCartSync 등 DB 동기화 훅
  • 채번 / 저장 / 삭제 / 확정 비즈니스 로직
  • 로직 포함 모달 (InspectionModal, NumberPadModal 등)

허용: JSX + Tailwind + 정적 상수/아이콘. 데이터는 빈 배열/mock, 핸들러는 () => {} 또는 // TODO: API 연결 주석만.

0-3. POP 파일별 상태 (추측 금지 — 아래 명시된 상태대로 취급)

파일 상태 비고
_components/inbound/PurchaseInbound.tsx 원본 · DB 연동 O 유일한 실연동 컴포넌트. 다른 입고는 이걸 UI만 클론한 것
_components/inbound/InboundCartPage.tsx 현역 · DB 연동 O 실제 사용 중인 풀스크린 장바구니
_components/inbound/InboundManage.tsx 현역 · DB 연동 O 입고관리 화면. getReceivingList/updateReceiving/deleteReceiving API 연동
_components/inbound/InboundCart.tsx 구버전 · 미사용 어디서도 import 안 됨. 분석/참조 대상 아님 (사용자가 명시 언급할 때만)
_components/inbound/{나머지 Pascal}Inbound.tsx UI 클론 · DB 미연동 fetchAllSuppliers/fetchOrders 빈 배열 반환만. 로직 추가하려면 먼저 확인
inbound/{slug}/page.tsx (purchase 외) UI 클론 useCartSync 훅은 들어가 있지만 데이터 소스는 빈 배열
_components/common/useCartSync.ts re-export 실제 구현은 @/hooks/pop/useCartSync.ts
_components/outbound/OutboundCartPage.tsx 현역 · DB 연동 O 출고 장바구니. InboundCartPage 클론, 검사 로직 제거, API /outbound/*
_components/outbound/{Pascal}Outbound.tsx UI 클론 · DB 미연동 fetchAllCustomers/fetchOrders 빈 배열. 로직 추가하려면 먼저 확인
outbound/{slug}/page.tsx UI 클론 useCartSync("outbound") 사용, 데이터 소스는 빈 배열

0-4. 작업 로그 업데이트 의무

POP 영역에 파일 생성/수정/삭제가 발생하면 이 문서의 ## 작업 로그 섹션에 날짜별 항목 추가. 사용자가 별도 지시하지 않아도 자동으로 기록.

0-5. POP layout 수정 금지 (사용자 지시 필수)

  • COMPANY_7/pop/layout.tsx사용자의 명시적 지시 없이 수정 금지.
  • 화면명(타이틀)/뒤로가기 버튼은 각 page.tsx 내부에 배치한다 (선례: production/process/page.tsx 2026-04-20 7차).
  • PopShelltitle / showBack / headerRight prop 을 layout 에서 전달하는 방식은 금지. 페이지 내부 헤더 행(뒤로가기 버튼 + <h1>)을 직접 렌더한다.
  • layout 파일 수정이 정당한 경우(예: 공지 배너 추가 등)에도 반드시 사용자 확인 선행.

1. 개요

POP(생산현장관리) 화면을 업체별로 독립 개발하기 위한 구조 설계. 기존 (pop) route group을 사용하지 않고, (main) 안에서 업체별 폴더(COMPANY_*) 하위에 pop/ 폴더를 두는 방식으로 재개발한다.

재개발 배경

  • 업체별로 컬럼 라벨, 요구사항, 비즈니스 성격이 다름
  • 기존 공통 POP 구조로는 업체별 커스터마이징에 한계
  • 업체 폴더 안에서 독립적으로 개발하면 충돌 없이 유지보수 가능

2. 핵심 결정사항

2-1. (main) layout 조건 분기

POP는 터치 풀스크린 UI이므로 ERP의 사이드바/탭바/메신저가 불필요하다. 별도 route group을 만드는 대신, (main)/layout.tsx에서 pathname 기반 조건 분기로 해결했다.

// frontend/app/(main)/layout.tsx
"use client";

import { usePathname } from "next/navigation";

export default function MainLayout({ children }) {
  const pathname = usePathname();
  const isPop = pathname.includes("/pop/") || pathname.endsWith("/pop");

  if (isPop) {
    return <>{children}</>;  // POP: layout 없이 children만 렌더링
  }

  return (
    <AuthProvider>
      <MenuProvider>
        <MessengerProvider>
          <AppLayout>{children}</AppLayout>  // ERP: 기존 layout 그대로
          ...
        </MessengerProvider>
      </MenuProvider>
    </AuthProvider>
  );
}

2-2. 문제점 검토 결과

항목 영향 이유
useAuth (인증) 없음 독립 훅, Context 의존 아님
MenuProvider (메뉴) 없음 POP에서 useMenu 미사용
MessengerProvider (메신저) 없음 POP에서 useMessenger 미사용
클라이언트 컴포넌트 전환 없음 자식 컴포넌트가 이미 전부 "use client"
metadata export 없음 (main)/layout.tsx에 metadata 없음

3. 폴더 구조

URL 규칙

ERP: /COMPANY_7/sales/order           -> (main) layout 적용
POP: /COMPANY_7/pop/inbound/purchase  -> layout 무시 (children만)

/pop/이 경로에 포함되면 자동으로 POP 모드가 된다.

디렉토리 구조

frontend/app/(main)/COMPANY_7/
  ├── sales/              <- 기존 ERP 화면
  ├── production/
  ├── logistics/
  ├── purchase/
  ├── quality/
  ├── equipment/
  ├── mold/
  ├── outsourcing/
  ├── design/
  ├── monitoring/
  ├── master-data/
  └── pop/                <- POP 화면 (layout 무시)
      ├── home/
      ├── inbound/
      │   ├── purchase/        구매입고
      │   ├── production/      생산입고
      │   ├── subcontractor/   외주입고
      │   ├── supplied/        사급입고
      │   ├── return-external/ 반품입고 (외부)
      │   ├── return-internal/ 반납입고 (내부)
      │   ├── recovery/        외주자재회수
      │   ├── change/          교환입고
      │   ├── error/           불량입고
      │   ├── shipment/        출하입고
      │   └── cart/            입고 카트
      ├── outbound/
      │   ├── sales/           판매출고
      │   ├── production/      생산출고
      │   ├── subcontractor/   외주출고
      │   ├── supplied/        사급출고
      │   ├── return/          반품출고
      │   ├── etc/             기타출고
      │   ├── transfer/        이관출고
      │   └── cart/            출고 카트
      ├── production/
      │   ├── process/         공정선택
      │   └── work/[processId] 공정작업
      ├── inventory/
      │   ├── move/            재고이동
      │   ├── transfer/        재고이관
      │   ├── history/         재고이력
      │   └── adjust-history/  재고조정이력
      ├── equipment/
      │   ├── inspection/      설비점검
      │   └── management/      설비관리
      └── quality/
          └── inspection/      품질검사

다른 업체 추가 시

frontend/app/(main)/COMPANY_10/pop/   <- 동일 구조, 독립 개발
frontend/app/(main)/COMPANY_8/pop/    <- 업체별 커스터마이징 자유

4. POP 전용 layout

각 업체의 pop/ 하위에 layout.tsx를 만들어 POP 전용 레이아웃을 적용한다. (main) layout이 무시되므로 이 layout이 최상위가 된다.

(main)/layout.tsx          <- isPop이면 children만 반환
  └── COMPANY_7/pop/
        └── layout.tsx     <- POP 전용 레이아웃 (터치 헤더, 풀스크린)
            └── page.tsx

작업 로그

2026-04-22

  • POP layout 수정 금지 규칙 신설 (0-5 섹션 추가)
    • COMPANY_7/pop/layout.tsx 는 사용자의 명시적 지시 없이 수정 금지
    • 화면명/뒤로가기 버튼은 각 page.tsx 내부에 배치 (선례: 2026-04-20 7차 production/process/page.tsx)
  • COMPANY_7/pop/layout.tsx 원복
    • Phase E 에서 추가했던 isWork 분기(title="공정 작업" + showBack) 제거
    • showBanner={isMain} 만 남기고 PopShell 기본 렌더로 복귀 (타이틀은 업체명 기본값)
  • production/work/[processId]/page.tsx 에 뒤로가기 + 타이틀 이식
    • production/process/page.tsx 2026-04-20 7차 패턴 복제 — 뒤로가기 버튼(w-10 h-10 rounded-xl, gray-200 border) + "공정 작업" <h1>
    • 뒤로가기 목적지: /COMPANY_7/pop/production/process (기존 ProcessWork 렌더는 유지)
    • 래퍼가 11→25 줄로 확장, 동작 변경 없음
  • 반응형 공통화 Phase 1 — 공통 컴포넌트 5개 신설 (_components/common/)
    • 상위 플랜: .claude/plans/pop-responsive-refactor.md (신규, 계획 문서)
    • 신규: theme.ts (67줄) — COLOR_MAP: Record<PopColor, PopColorTokens> 9색 × 7토큰 완성 리터럴. Tailwind JIT purge 회피 원칙(동적 문자열 0)
    • 신규: PopButton.tsx (50줄) — size sm/md/lg(min 96×40 / 144×48 / 200×56), icon prop, forwardRef, COLOR_MAP[color] 자동 적용
    • 신규: PopCard.tsx (45줄) — w-full min-h-[180px] + selected/color/interactive props, 선택 시 COLOR_MAP[color].ringSelected
    • 신규: PopCardGrid.tsx (75줄) — 브레이크포인트별 cols map(1~4) + gap sm/md/lg. Tailwind 리터럴 map 방식
    • 신규: PopModal.tsx (71줄) — size sm/md/lg/xl 전부 w-[min(Xvw,Ypx)] 반응형, ESC 닫기, footer slot
    • 기존 파일 수정 0건. 아직 어느 화면도 import 하지 않음 (unused)
    • 검증: tsc --noEmit baseline 3090 유지, /COMPANY_7/pop/main 브라우저 로드 회귀 0 (콘솔 에러 0)
  • 반응형 공통화 Phase 2 — 취소
    • 계획 원안: 기존 공용 모달 4개(BarcodeScanModal/ConfirmModal/EquipmentModal/SimpleKeypadModal)를 PopModal 기반으로 내부 개편
    • 취소 사유: 4개 모달이 각자 특수 UX(ConfirmModal 분할버튼 + z-[100], SimpleKeypadModal blue gradient header + maxQty 배지, EquipmentModal header 내 정렬 버튼, BarcodeScanModal shadcn Dialog 기반 aria 내장)라 일괄 래핑 시 시각 변경 발생. 사용자 결정으로 기존 모달은 현 상태 유지, PopModal은 신규 모달 작성 시에만 기본 틀로 사용. 계획 문서 §5 표에 취소 기록.

2026-04-15

  • frontend/app/(main)/layout.tsx 수정
    • "use client" 추가
    • usePathname 기반 조건 분기 추가 (/pop/ 포함 시 children만 렌더링)
  • frontend/app/(main)/COMPANY_7/pop/ 폴더 생성
  • 나머지 7개 입고 화면 신규 작성 (반품입고와 동일 방식: 구매입고 구조 클론, DB 연동 제외, 화면별 색상/라벨만 차별화)
    • subcontractor (외주입고, purple) / supplied (사급자재, cyan) / error (불량입고, red) / recovery (외주자재회수, pink) / change (교환입고, teal) / production (생산입고, green) / return-internal (반납입고, orange)
    • 각 컴포넌트: _components/inbound/{Pascal}Inbound.tsx — 타입·필드·로직은 구매입고와 동일, 헤더 타이틀/품목 라벨/색상(스캔 버튼 gradient, 담기 버튼 gradient, shadow, tailwind color)만 교체
    • 각 페이지: inbound/{slug}/page.tsxuseCartSync("pop-{slug}-inbound", "{slug}_detail"), 카트 이동 URL 쿼리 전부 교체
    • inbound/page.tsx의 7개 메뉴 href: "#" → 실제 라우트로 연결 (재고이동 transfer# 유지)
  • 반품입고 화면 신규 작성 (구매입고 구조 클론, DB 연동 제외)
    • _components/inbound/ReturnExternalInbound.tsx 생성
      • fetchAllSuppliers / fetchOrders 는 빈 배열 반환 자리만 남김 (// TODO: API 연결)
      • 타입/필드/로직은 PurchaseInbound 동일 (Phase A: 텍스트·색상만 차별화)
      • 헤더 타이틀 "반품입고", 스캔/포커스/담기 컬러를 amber(#f59e0b → #d97706)로 통일
      • 발주 라벨(발주일/발주번호/발주수량/미입고)은 원형 유지 (추후 필드 조정 예정)
    • inbound/return-external/page.tsx 생성
      • useCartSync("pop-return-external-inbound", "return_external_detail")
      • 카트 이동 URL의 screenId / sourceTable / type=반품입고 / backUrl 교체
    • inbound/page.tsx 수정
      • 반품입고 메뉴 href: "#"/COMPANY_7/pop/inbound/return-external

2026-04-16

  • POP layout 도입: PopShell을 layout.tsx로 이관
    • frontend/app/(main)/COMPANY_7/pop/layout.tsx 신규 생성
      • <PopShell showBanner={isMain}>{children}</PopShell> — pathname /pop/main 일 때만 공지 배너 표시
      • 타이틀: title prop 미전달 → PopShell 기본값 user?.companyName 사용 (업체명 고정)
      • navigation 간 PopShell 리마운트 없음 (시계/전체화면/프로필 상태 유지)
    • 13개 page.tsx에서 <PopShell> 래핑 및 import 일괄 제거
      • main/page.tsx, inbound/page.tsx, inbound/{9종}/page.tsx, inbound/cart/page.tsx
  • 카트 버튼 위치 변경: PopShell headerRight → 각 Inbound 컴포넌트 content 내부
    • 9개 Inbound 컴포넌트에 onCartClick/saving props 추가
    • 카트 버튼: 제목 행 우측, min-w-[144px] min-h-[48px], "장바구니" 라벨, 각 페이지 테마 gradient 적용
      • purchase(blue), subcontractor(purple), supplied(cyan), production(green), error(red), recovery(pink), change(teal), return-internal(orange), return-external(amber)
    • 9개 page.tsx에서 headerRight prop 제거, onCartClick/saving prop 전달로 변경
  • 출고 메뉴 페이지 신규 작성
    • outbound/page.tsx 생성 — 입고 메뉴(inbound/page.tsx) 구조 클론, 출고 용어로 전환
    • 외부 출고 5종: 판매출고(green), 반품출고(slate), 외주출고(purple), 사급출고(cyan), 기타출고(dark)
    • 내부 출고 2종: 생산출고(orange-red), 재고이동(orange, # 준비 중)
    • KPI 캐러셀 3슬라이드 (금일 출고/출고 대기/완료, 완료/판매출고/외주출고, 금일 수량/출고율/반품)
    • 최근 출고 mock 데이터 2건
    • Back URL: /COMPANY_7/pop/main
  • 출고 컴포넌트 6종 신규 작성 (_components/outbound/)
    • 입고 UI 클론(ReturnExternalInbound.tsx 패턴) 기반, DB 미연동
    • fetchAllCustomers / fetchOrders 빈 배열 반환 (// TODO: API 연결)
    • 공통 변경: supplier→customer, purchase_no→reference_no, inbound_type→outbound_type, 입고→출고, 발주→주문, 미입고→미출고
    • Props: outboundType, sourceTable (3인자 addItem)
    • 파일별 색상:
      • SalesOutbound.tsx — 판매출고, green (#22c55e→#15803d)
      • ReturnOutbound.tsx — 반품출고, slate (#64748b→#334155)
      • SubcontractorOutbound.tsx — 외주출고, purple (#8b5cf6→#6d28d9)
      • SuppliedOutbound.tsx — 사급출고, cyan (#06b6d4→#0e7490)
      • EtcOutbound.tsx — 기타출고, dark (#475569→#1e293b)
      • ProductionOutbound.tsx — 생산출고, orange (#f97316→#c2410c)
  • OutboundCartPage 신규 작성 (_components/outbound/OutboundCartPage.tsx)
    • InboundCartPage 클론, 출고용 변경:
    • useCartSync("outbound"), 타이틀 "출고 장바구니"
    • 검사(InspectionModal) 관련 로직 전체 제거
    • API: GET /outbound/warehouses, GET /outbound/generate-number, POST /outbound
    • Payload: outbound_number/date/type/qty, customer_code/name (supplier 대신)
    • outbound_type 배지 표시, 혼합 시 "혼합출고"
  • 출고 page.tsx 7개 신규 작성 (outbound/{slug}/page.tsx)
    • cart/page.tsxbackUrl만 쿼리, <OutboundCartPage backUrl={backUrl} />
    • sales/page.tsx — 판매출고, shipment_instruction_detail
    • return/page.tsx — 반품출고, return_outbound_detail
    • subcontractor/page.tsx — 외주출고, outsource_outbound_detail
    • supplied/page.tsx — 사급출고, supplied_outbound_detail
    • etc/page.tsx — 기타출고, etc_outbound_detail
    • production/page.tsx — 생산출고, production_outbound_detail
  • 장바구니 구조 개편 (입고/출고 공통)
    • useCartSync 훅 시그니처 변경: (screenId, sourceTable)(category: 'inbound' | 'outbound')
    • DB 필터: screen_id 제거 → cart_type='pop_inbound' / 'pop_outbound'로 카테고리 분리
    • addItem 3번째 인자로 sourceTable 전달 (항목별 sourceTable)
    • 레거시 오버로드 유지 (PopCardListComponent 등 기존 호출 호환)
    • 입고 page.tsx 9개: useCartSync("inbound"), 카트 이동 URL 쿼리 ?backUrl=...
    • 입고 컴포넌트 9개: inboundType/sourceTable props 추가, addItem에 row.inbound_type 포함, 공급사 검증
    • InboundCartPage: props { backUrl } 단순화, 타이틀 "입고 장바구니", inbound_type 배지, 혼합 시 "혼합입고"
    • 카트 라우트: screenId/sourceTable/type 쿼리 제거, backUrl만 유지
    • 백엔드 receivingController: 혼합 inbound_type 처리 추가
  • 검증 완료
    • npm run build (frontend): 성공
    • tsc --noEmit (backend): 성공
    • 브라우저 입고 테스트: 구매입고 품목 담기 → 카트 진입 → "입고 장바구니" 타이틀 + "구매입고" 배지 + 품목/수량 정상
    • 브라우저 카트 공유 테스트: 구매입고에서 담은 품목이 생산입고 화면 배지(1)에 표시, 카트 페이지에서도 동일 품목 확인
    • 브라우저 출고 테스트: 출고 메뉴 페이지(외부 5종 + 내부 2종), 판매출고 화면, 출고 카트 페이지 정상 렌더링
    • 출고 카트 더미 테스트: DB에 pop_outbound 2건(판매출고 50EA + 생산출고 30EA) 삽입 → 카트에서 혼합 표시 확인 → 더미 삭제 완료

2026-04-16 (2차)

  • 수량 입력 모달 분리: NumberPadModal → SimpleKeypadModal + 장바구니 포장단위
    • _components/common/SimpleKeypadModal.tsx 신규 생성
      • 숫자 키패드 + 확인 버튼만 (포장단위 선택 없음)
      • props: open, onClose, onConfirm(qty), maxQty, itemName, initialQty
    • 입고 컴포넌트 9개: NumberPadModalSimpleKeypadModal 교체
      • PurchaseInbound, SubcontractorInbound, ProductionInbound, ReturnExternalInbound, ReturnInternalInbound, SuppliedInbound, ErrorInbound, ChangeInbound, RecoveryInbound
      • handleNumpadConfirm 시그니처: (qty, packages)(qty) 단순화
      • 카드 내 포장정보 표시 블록 제거
    • 출고 컴포넌트 6개: 동일 교체
      • SalesOutbound, ReturnOutbound, SubcontractorOutbound, SuppliedOutbound, EtcOutbound, ProductionOutbound
    • InboundCartPage.tsx: 품목별 "포장단위" 버튼 추가
      • 수량 편집: SimpleKeypadModal (숫자만)
      • 포장등록: NumberPadModal (기존 4단계 포장 플로우)
      • 포장 완료 시 버튼 색상 green, 미등록 시 amber
    • OutboundCartPage.tsx: 동일 구조 적용
    • tsc --noEmit: 새 에러 없음 (기존 에러만 존재)
  • 입고/출고 컴포넌트 자동저장 추가
    • 입고 9개 + 출고 6개 컴포넌트: cart.addItem / cart.removeItemsetTimeout(() => cart.saveToDb(), 300) 추가
    • 화면 이동 시 카트 데이터 소실 방지
  • InboundCartPage 장바구니 카드 레이아웃 개편
    • 카드 그리드: flex-colgrid grid-cols-1 md:grid-cols-2 xl:grid-cols-3
    • 유형별 구분선: 유형 1개여도 항상 라벨 + 구분선 표시
    • 헤더 행: 체크박스 + 품번 + 품목명 + 검사필수 버튼 (빨간색, min-w-[80px], py-[6px])
    • 품목명: 15자 초과 시 cartMarquee 애니메이션 자동 슬라이드 (3초, container query cqi 기반 자동 계산)
    • 액션 컬럼: 수량 → 삭제 (검사 버튼은 헤더로 이동)
    • 포장단위 버튼: 카드 하단 전체 너비, 아이콘 포함
    • 기존 검사 영역(카드 하단 full-width bar) 제거 → 헤더 배지로 대체
    • 포장정보(포장완료 시 상세) 유지
    • 카드 선택 표시: 좌측 바 → ring-2 ring-blue-500 전체 테두리
  • OutboundCartPage 동일 적용
    • 유형별 구분선 항상 표시
    • 카드 선택 시 ring-2 ring-blue-500 전체 테두리 (좌측 바 제거)
    • 품목명 marquee 애니메이션 (15자 초과 시, cartMarquee 3초)
    • 포장단위 버튼 카드 하단 전체 너비 + 아이콘
    • tsc --noEmit: 에러 없음

2026-04-16 (3차)

  • 포장단위 하드코딩 → DB 조회로 변경
    • 백엔드: GET /api/packaging/pkg-units-by-item/:itemNumber 신규 API
      • pkg_unit_item JOIN pkg_unit으로 품목별 매칭 포장단위 조회
    • PackagingModal.tsx: 하드코딩 6개 배열 제거, itemNumber prop → DB 조회, 로딩/빈 상태 처리
    • NumberPadModal.tsx: 동일 DB 조회 적용, direct-qty 단계 제거 (포장등록 전용)
      • 스텝: 포장선택 → 개당수량 → 포장개수 → 확인 (4단계)
      • pkg_qty 자동 세팅 (DB 등록값 → 개당수량 초기값)
      • initialQty prop 제거, 건너뛰기 버튼 제거
    • InboundCartPage.tsx / OutboundCartPage.tsx: NumberPadModal에 itemNumber prop 전달, initialQty 제거
    • frontend/lib/api/packaging.ts: getPkgUnitsByItem() + PkgUnitByItem 타입 추가
    • 더미데이터: pkg_unit 3건(박스/포대/파렛트) + pkg_unit_item 5건 등록, 브라우저 검증 완료
  • NumberPadModal 복수 포장 지원 + 나머지 자동 계산
    • 플로우: 포장선택 → 개당수량 → 포장개수 → (나머지 있으면) 나머지 안내 → 나머지 포장선택 → 확인
    • MAX 버튼: 개당수량=maxQty, 포장개수=floor(maxQty/개당수량) 자동 계산
    • 나머지 포장: 포장단위 선택 시 1개 x 나머지수량으로 자동 세팅 → 바로 확인
    • 나머지 단계 헤더 amber 색상으로 시각 구분
    • confirm에서 1차 포장(green) + 나머지 포장(amber) + 합계 표시
    • PackageEntry[] 배열로 복수 엔트리 반환 (기존 호환)
    • initialPackages 복수 엔트리 복원 지원
  • 적재함(loading_unit) 선택 단계 추가
    • 백엔드: GET /api/packaging/loading-units-by-pkg/:pkgCode 신규 API
      • loading_unit_pkg JOIN loading_unit으로 포장코드별 매칭 적재함 조회
    • frontend/lib/api/packaging.ts: getLoadingUnitsByPkg() + LoadingUnitByPkg 타입 추가
    • NumberPadModal.tsx: 포장 완료 → 적재함 선택 → 확인 플로우
      • 적재함 단계 헤더 purple 색상
      • 적재함 목록: 이름, 코드, 타입, 최대적재수 표시
      • "건너뛰기 (적재함 없음)" 버튼
      • 매칭 적재함 없으면 자동 skip → confirm
      • confirm에서 적재함 정보 purple 카드로 표시
    • onConfirm 시그니처 확장: (qty, packages, loadingUnit?) — 3번째 인자로 적재함 전달
    • InboundCartPage.tsx / OutboundCartPage.tsx: handlePackagingConfirm에서 loadingUnitcart.updateItemRow 저장
    • 더미데이터: loading_unit 2건(목재파렛트/20ft컨테이너) + loading_unit_pkg 3건 등록, 브라우저 검증 완료

2026-04-17 (1차)

  • 입고/출고 장바구니 거래처 필터 드롭다운 추가
    • InboundCartPage.tsx:
      • selectedSupplierFilter state 추가
      • supplierList useMemo (items에서 supplier_code/name 중복 제거)
      • 거래처 1개 시 자동 선택 useEffect
      • filteredItems useMemo (선택/확정 로직은 전체 items 기반 유지)
      • Info banner: supplier 배지 제거 → <select> 거래처 드롭다운 추가 (label "거래처")
      • Info fields 그리드: sm:grid-cols-3sm:grid-cols-4 (거래처 열 추가)
      • 품목 리스트 렌더링: typeGroups 계산을 filteredItems 기반으로 변경
      • 헤더 supplierName 서브텍스트 제거, supplierName 변수 삭제
    • OutboundCartPage.tsx: 동일 패턴 (customer_code/name, selectedCustomerFilter, customerList)
    • tsc --noEmit: 두 파일 관련 새 에러 없음 (기존 에러만 존재)

2026-04-17 (2차)

  • 거래처 선택 상태 sessionStorage 복원 추가 (입고 9개 + 출고 6개 = 15개 컴포넌트)
    • 장바구니 갔다 돌아올 때 거래처 선택 상태가 초기화되는 문제 해결
    • 각 파일 상단에 STORAGE_KEY 상수 추가 (파일별 분리 키)
    • 마운트 시 sessionStorage에서 복원하는 useEffect 추가
    • selectSupplier / selectCustomer 래퍼 함수 추가 — 선택 시 저장, null 시 제거
    • 기존 setSelectedSupplier / setSelectedCustomer 호출 3곳(X버튼, 모달 onSelect, 바코드 스캔)을 래퍼로 교체
    • 입고 키: pop_supplier_{purchase|subcontractor|production|supplied|return-external|return-internal|error|change|recovery}
    • 출고 키: pop_customer_{sales|return|subcontractor|supplied|etc|production}
  • 장바구니 화면 거래처 필터 드롭다운 추가 (InboundCartPage + OutboundCartPage)
    • Info banner 영역에 거래처 <select> 드롭다운 추가 (입고일자/창고/입고번호와 동일 크기, 4칸 grid)
    • 거래처 목록: 장바구니에 담긴 품목에서 supplier_code/customer_code 자동 추출
    • 거래처 1개면 자동 선택, "전체" 옵션 없음
    • 기존 supplierName/customerName 배지 제거, filteredItems useMemo로 품목 필터링
    • 확정/선택 로직은 전체 items 기반 유지 (필터 영향 없음)

2026-04-17 (3차)

  • 입고관리/출고관리 페이지 신규 생성 (UI 껍데기, DB 미연동)
    • _components/inbound/InboundManage.tsx 신규 생성
      • 입고 내역 조회/수정/삭제 UI, 시작일/종료일/키워드 검색 필터
      • 카드형 목록 (체크박스 선택, 수정/삭제 버튼), 테마 blue
      • MOCK_RECORDS 빈 배열 (// TODO: API 연결)
    • _components/inbound/OutboundManage.tsx 신규 생성
      • 출고 내역 조회/수정/삭제 UI, 동일 구조, 테마 emerald
      • supplier→customer 용어 변경
    • inbound/inbound-manage/page.tsx 신규 생성
    • inbound/outbound-manage/page.tsx 신규 생성
    • inbound/page.tsx 수정
      • INTERNAL_ITEMS에 "입고관리"(blue), "출고관리"(emerald) 버튼 2개 추가 (재고이동 우측)

2026-04-17 (4차)

  • 출고 메뉴 연결: main/page.tsx 출고 버튼 href: "#"/COMPANY_7/pop/outbound
  • 채번 로직 구 POP 의존 제거: InboundCartPage/OutboundCartPage에서 screens/6527/layout-pop 대신 numbering-rules/by-column API 직접 조회로 변경

2026-04-20

  • 입고관리 화면 API 연동 (UI 껍데기 → 실연동)
    • _components/inbound/InboundManage.tsx 전면 개편
      • MOCK_RECORDS 빈 배열 → getReceivingList API 연동 (날짜 범위, 거래처, 키워드 필터)
      • 삭제: deleteReceiving API 연동 (복수 선택 → 헤더 ID 중복 제거 → 순차 삭제, 재고 롤백 포함)
      • 수정: 전체 필드 수정 모달 구현 (updateReceiving API)
        • 기본 정보: 입고일, 입고상태(드롭다운)
        • 수량/금액: 수량, 단가, 금액(자동계산)
        • 입고 상세: LOT번호, 창고(DB 드롭다운), 위치, 검사상태, 검사자, 담당자
        • 메모
      • 카드별 수정 아이콘(연필) 추가 — 클릭 시 바로 수정 모달 열림
      • 상단 수정 버튼: 1건 선택 시만 활성화
      • 창고 목록: getReceivingWarehouses API 연동
      • 검색: Enter 키 + 검색 버튼 지원, 로딩 스피너
    • 백엔드/API 클라이언트 수정 없음 (기존 구현 활용)
    • tsc --noEmit: InboundManage 관련 새 에러 없음
    • npm run build: 성공
    • 브라우저 검증: 조회 15건 정상 표시, 수정 모달 정상 렌더링, 카드 선택/버튼 활성화 확인
  • 입고관리 필터 변경
    • 시작일/종료일 (날짜 범위) → 입고일 (단일 날짜) 변경
    • 입고유형 카테고리 드롭다운 추가 (전체 + 10개 유형)
  • [알려진 이슈] 입고 수정 시 헤더 필드 공유 문제
    • inbound_date, warehouse_code, location_code, inbound_status, inspector, manager, memo는 헤더(inbound_mng) 필드
    • 같은 입고번호(예: RCV-2026-0010) 안에 품목이 여러 건일 때, 한 품목에서 입고일 등 헤더 필드를 수정하면 동일 입고번호의 모든 품목에 반영됨
    • 원인: inbound_detail 테이블에 inbound_date 컬럼 없음 — 헤더에만 존재
    • 수량/단가/LOT/검사상태 등 디테일 필드는 품목 1건만 변경됨 (정상)
    • 해결하려면 inbound_detailinbound_date 컬럼 추가 필요 (미적용)

2026-04-20 (2차)

  • 생산입고 화면 DB 연동 (UI 껍데기 → 실연동)
    • 백엔드: GET /api/receiving/source/production-results?processCode=XXX 신규 추가
      • work_order_process + work_instruction + item_info JOIN
      • 필터: process_code 일치, good_qty > 0 (실적 등록됨), target_warehouse_id IS NULL (미입고), parent_process_id IS NULL (마스터만), 리워크 제외
      • 반환 필드: work_instruction_no, order_date, process_code/name, item_code/name, spec, material, order_qty(=good_qty+concession_qty), remain_qty, source_table='work_order_process', inspection_type, image
      • 파일: backend-node/src/controllers/receivingController.ts, backend-node/src/routes/receivingRoutes.ts
    • 백엔드: receivingController.create 소스 업데이트 분기 리팩터
      • 기존: inbound_type === '구매입고' 문자열 체크
      • 변경: source_table 기준 if-else-if 체인 (purchase_order_mng / purchase_detail / work_order_process)
      • 생산입고 처리: work_order_process.target_warehouse_id 세팅 (이중 입고 방지)
      • 미처리 소스 테이블: logger.warn으로 기록 (추후 업데이트 로직 추가 필요 시 추적용)
      • 파일: backend-node/src/controllers/receivingController.ts
    • 프론트: _components/inbound/ProductionInbound.tsx
      • fetchOrders: 빈 배열 → apiClient.get("/receiving/source/production-results", { params: { processCode, keyword } })
      • 공정 선택 시 자동 재조회 (selectedSupplier 변경 감지)
      • editedQtys 패턴 도입 (PurchaseInbound 동일): numpad 확인 → 로컬 수량만 변경, 담기 버튼 → 카트에 추가
      • saveToDbRef 추가 (stale closure 방지)
      • 필드 라벨 "지시수량" → "양품수량"
      • 필터링: supplier 기반 → API가 이미 processCode로 필터링하므로 키워드 필터만 유지
    • 검증: tsc --noEmit (backend), npm run build (frontend) 성공
    • 브라우저 검증: 미수행 (실제 실적 데이터 필요)

2026-04-20 (3차)

  • 생산관리 메뉴 페이지 신규 생성 (UI 껍데기, DB 미연동)
    • production/page.tsx 신규 생성 — 입고 메뉴(inbound/page.tsx) 구조 클론, 생산 용어로 전환
      • 뒤로가기 + "생산관리" 타이틀 + "메뉴를 선택하세요" 서브텍스트
      • KPI 캐러셀 3슬라이드 (금일 생산/진행 중/완료, 작업지시/공정완료/불량, 금일 수량/달성률/불량률) — 전부 0
      • 생산 메뉴: 공정실행 1개만 (amber gradient, href: "#" — 준비 중)
      • 최근 생산활동: 빈 상태 ("최근 생산활동 내역이 없습니다")
    • main/page.tsx 수정 — 생산 버튼 href: "#"/COMPANY_7/pop/production
    • 타입 체크(tsc --noEmit): 생산 관련 새 에러 없음
    • 브라우저 검증: 미수행

2026-04-20 (4차)

  • 공정실행 페이지 신규 생성 (스크린샷 기반 UI 껍데기, 구 POP 참조 X)
    • production/process/page.tsx 신규 생성 — 구 POP 컴포넌트 복사/import 없이 스크린샷만 보고 직접 구성
      • 상단 row: 카드 열 버튼(1열/2열/3열, 2열 기본 선택) + 새로고침 버튼(blue border)
      • 필터 row: 공정 선택 드롭다운(톱니 아이콘) + 설비 선택 드롭다운(깃발 아이콘) — 핸들러 stub
      • 탭 바: 접수가능(amber) / 진행중(blue) / 대기(gray) / 완료(green) — 하드코딩 건수(59/3/11/17)
      • 빈 상태: clipboard 아이콘(amber) + "공정을 선택해주세요"
      • 전부 로컬 state만, apiClient/dataApi/useAuth 사용 없음, 핸들러는 // TODO: API 연결 주석
    • production/page.tsx 수정 — 공정실행 버튼 href: "#"/COMPANY_7/pop/production/process
    • work/[processId]/page.tsx는 아직 미생성 (사용자 지시: 이번엔 공정실행 1화면만 구성)
    • 타입 체크(tsc --noEmit): 새 에러 없음
    • 브라우저 검증: 미수행

2026-04-20 (5차)

  • 공정실행 좌측 공정 선택 드롭다운 DB 연결
    • production/process/page.tsx 수정 — 좌측 공정용 FilterSelect 버튼 → SupplierModal 트리거 버튼으로 교체
      • PROCESS_SOURCE 상수 추가 (process_mng / process_code / process_name)
      • selectedProcess state 타입: stringSupplier | null (공정코드+이름 동시 보관, 추후 탭/데이터 필터링용)
      • processModalOpen boolean state 신규 추가 (모달 open/close 제어)
      • SupplierModal 렌더: title="공정 선택", searchPlaceholder="공정명 또는 코드 검색..."
      • 우측 설비 드롭다운은 FilterSelect 그대로 유지 (변경 없음)
    • 구현 방식: 생산입고(ProductionInbound.tsx)와 동일 패턴 — SupplierModal 재사용, 신규 모달 파일 생성 없음
    • 타입 체크(tsc --noEmit): 새 에러 없음
    • npm run build: 컴파일 성공, post-compile 단계에서 Turbopack 캐시 경고(변경 무관)
    • 브라우저 검증: 미수행 — dev 서버 다운, 백엔드 재시작 금지 규칙

2026-04-20 (6차)

  • 공정실행 우측 설비 선택 드롭다운 DB 연결 (공정별 필터링)
    • _components/common/EquipmentModal.tsx 신규 생성 — SupplierModal UI 클론, 데이터는 props로 주입받는 방식
      • props: items, loading, open, onClose, onSelect, title, searchPlaceholder
      • 초성 그룹핑 + 가나다/ABC 정렬 + 검색 — SupplierModal getChosung 재사용
    • production/process/page.tsx 수정
      • getProcessEquipments from lib/api/processInfo import — 공정별 등록 설비 조회 API
      • selectedEquipment state 타입: stringEquipmentItem | null (코드+이름 보관)
      • equipments, equipmentLoading, equipmentModalOpen state 신규 추가
      • selectedProcess?.customer_code 변경 감지 useEffect — 공정 선택 시 getProcessEquipments 호출, 공정 해제 시 설비 목록 초기화
      • 우측 FilterSelect 버튼 → EquipmentModal 트리거 버튼으로 교체 (공정 미선택 시 disabled)
      • 버튼 라벨: 선택됨 → 설비명 / 공정 미선택 → "공정 선택 후 설비 선택" / 공정만 선택 → "설비를 선택하세요"
    • 데이터 흐름: process_equipment JOIN equipment_mngprocess_code + company_code 필터
    • 타입 체크(tsc --noEmit): 새 에러 없음
    • npm run build: 미수행 (방금 전 5차에서 확인)
    • 브라우저 검증: 미수행 — dev 서버 다운, 백엔드 재시작 금지 규칙

2026-04-20 (8차) — Phase A 완료 (공정실행 구 POP 이식)

  • 작업 범위: 플랜 .claude/plans/pop-process-execution.md Phase A 전 항목 (A-1 ~ A-8)
  • POP.md 0-2 원칙 예외 적용: 이번 공정실행 작업에 한해 "구 POP 컴포넌트 복사/import 금지" 예외 허용 (사용자 승인). 0-2 본문은 유지 — 다른 화면에는 계속 적용.
  • 파일 변경
    • 복사: components/pop/hardcoded/production/ 의 WorkOrderList/ProcessWork/AcceptProcessModal/ProcessDetailModal/DefectTypeModal/ProcessTimer → _components/production/ (6개)
    • 신규: _components/production/useProcessData.ts — 1회 sync + 3초 쿨다운 + sonner toast + 동시호출 방지(inFlight)
    • 수정: WorkOrderList.tsx — 내부 fetchAll/syncAndFetch/localStorage/필터 UI/FilterSelectorModal 제거, props 기반으로 전환, mutation 후 refetch() 사용
    • 수정: production/process/page.tsx — useProcessData 연결, 새로고침 버튼(ArrowPath SVG + animate-spin + blue border), 카드 열 localStorage pop-new-workorder-cols (기본 2열, 구 POP workorder-card-cols와 독립), WorkOrderList 렌더
    • 수정: hooks/pop/usePopSettings.ts/COMPANY_7/pop/production/process URL → screenId 7, settingsKey processExecution 매핑 추가
    • 재사용: _components/common/ConfirmModal.tsx 기존 파일 그대로 사용 (복사 생략)
  • 데이터 갱신 정책 (구 POP 대비 개선)
    • 구 POP의 이중 sync POST 제거: 진입 시 1회 + 수동 새로고침 시 1회 + 3초 쿨다운
    • mutation(accept-process/cancel-accept) 성공 후 sync 없이 refetch만 수행
    • sonner toast 경유 에러 노출 (기존 silent catch 제거)
  • 브라우저 E2E 검증 (playwright, topseal_admin / COMPANY_7)
    • 진입 sync POST 1회 / 재진입 1회 / 연타 3회 → 1회(쿨다운) / 3초 경과 후 1회 추가 → 정상
    • 필터(공정/설비) 조작: sync POST 증가 0회
    • 리워크 접수(accept-process POST) → sync POST 증가 0회 → 진행중 탭 이동 확인
    • 접수취소(cancel-accept POST, ConfirmModal 경유) → sync POST 증가 0회 → 원복 확인
    • 콘솔 에러 0, tsc 신규 에러 0 (baseline 3143 → 3090), npm run build 성공
    • 카드 열 토글: 기본 2열 확인, 3열 변경 → localStorage pop-new-workorder-cols="3" 저장 → 페이지 재진입 유지 확인, 구 POP 키 미생성
  • [알려진 이슈 — Phase C에서 처리 예정, 이번 Phase A 작업 범위 아님]
    • 이슈 #1 — work_order_process.status routing 미반영: 서버 sync-work-instructions가 작업지시 생성 시 모든 seq의 공정을 초기 status='acceptable'로 한꺼번에 insert함. 전공정(이전 seq) 완료 여부에 따른 waiting → acceptable 전이 로직 없음. 결과적으로 UI 접수가능 탭에 "전공정양품=0, 접수가능=0"인 카드(예: CODE-00010 포장 공정, 직전 배합 공정 미완료 상태)가 항상 표시됨. 구 POP도 동일한 DB 상태로 동작했으므로 Phase A는 "동등 재현" 원칙 유지 (클라이언트 필터 임시 패치 없음).
    • 이슈 #2 — 중복 마스터 레코드: 같은 wo_id + seq_no + batch_id 조합의 parent_process_id IS NULL 마스터 레코드가 복수 존재. 예: CODE-00010의 seq 1~3이 각각 2개씩 (batch B_1002A_005, status 동일 acceptable). sync-work-instructions POST 재실행 시 UPSERT가 아닌 INSERT가 누적되는 것으로 추정.
    • 이슈 #3 — 리워크 카드 공정 필터 무시로 인한 오노출: WorkOrderList 복사본(원본 L1300-1301)의 "재작업 카드는 공정 필터 무시 — 모든 공정에서 표시" 로직. 예: CODE-00011은 제조반_계량 공정에서 불량이 발생한 리워크인데, 사용자가 제조반_포장 공정을 필터링 중일 때도 접수가능 탭에 노출됨. 리워크 카드는 원래 불량이 발생한 공정(또는 routing상 지정된 별도 재작업 공정)과 연결되어 표시되어야 할 가능성. 정확한 비즈니스 룰 확인 필요.
  • Phase C 플랜 반영 예정: 위 3개 이슈를 .claude/plans/pop-process-execution.md Phase C(서버 응답 필드 보강) 섹션에 추가 예정

2026-04-20 (7차)

  • 공정실행 화면 상단에 뒤로가기 + 타이틀 추가
    • production/process/page.tsx 수정 — 최상단에 뒤로가기 + "공정실행" 타이틀 행 추가
      • 뒤로가기 버튼(w-10 h-10 rounded-xl, 흰 배경 + gray-200 border) → /COMPANY_7/pop/production
      • 타이틀 "공정실행" (서브텍스트 없음, 사용자 지시)
      • useRouter import 추가
    • 타입 체크(tsc --noEmit): 새 에러 없음
    • 브라우저 검증: 미수행

2026-04-21 (2차)

  • 포장단위 모달 복수 등록 개편 + maxQty 버그 수정
    • _components/inbound/NumberPadModal.tsx 전면 재작성
      • 기존 3단계(1차 포장선택→개당수량→포장개수 + 잔량 포장 + 확인) → 단일 list step 기반 구조로 전환
      • list step: 포장 수량/미포장 잔량 실시간 요약, 등록된 포장 목록(행별 [편집][삭제]), [+ 포장단위 추가], [확인]
      • packaging step: 포장단위 선택 (pkg_qty 자동 세팅, 개당수량 입력 단계 제거)
      • count step: 개수만 입력 (MAX = Math.floor(사용가능잔량 / pkg_qty))
      • 같은 pkg_code 재선택 시 기존 행 count 합산 (pkg_qty 동일 전제)
      • 편집 시 해당 행 수량을 사용가능잔량에 되돌린 뒤 max 계산
      • 잔량 > 0 이어도 확정 가능 (입고/출고 관리화면에서 수정 여지)
      • 적재함 선택 흐름은 변경 없음 (InboundCartPage/OutboundCartPage의 별도 LoadingUnitModal 유지)
    • _components/inbound/InboundCartPage.tsx
      • MAX 버그 수정: NumberPadModal에 전달하던 maxQty={packagingTarget.remain_qty}packagingTarget.inbound_qty
      • handlePackagingConfirm: Math.min(qty, remain_qty)packagingTarget.inbound_qty 고정 (포장 합계로 수량 덮어쓰기 제거, 미포장 잔량 허용)
      • 포장 정보 카드 UI: 배지 포장완료(green) / 부분포장(amber) 분기 + 미포장 잔량 줄 추가
    • _components/outbound/OutboundCartPage.tsx: 동일 패턴 (outbound_qty 기준)
    • 버그 원인: 기존 remain_qty는 발주 잔량(예: 발주 200, 미입고 200)이라 장바구니에 50 담아도 MAX 버튼/잔량 계산이 200 기준 → "50 EA 중 1박스(40EA)만 담아도 MAX=5박스 / 잔량 160" 증상
    • 검증:
      • tsc --noEmit (frontend): 변경 파일 기준 신규 에러 0 (기존 lib/utils/*, v2-core/* 등 baseline만 존재)
      • 브라우저 검증: MAX 버그 수정 동작 확인 (모달 헤더 최대 50 EA, 발주수량 100 기준 아님). 복수 추가/합산/편집/삭제/배지 분기는 현 장바구니 품목 3건(DEMO-PROD-001/B_ETCE3_001/F_GMP02_003)에 pkg_unit_item 미등록으로 미검증 — 사용자 승인 SKIP
    • PreToolUse 훅이 카드 UI 편집을 2회 차단 → 사용자에게 세부 변경 목록(배지/색상/미포장 줄) 제시 후 승인받아 통과

2026-04-21

  • 판매출고 시연용 더미 데이터 추가 후 동일 세션 내 전량 롤백 (사용자 지시)
    • _components/outbound/SalesOutbound.tsx fetchOrders: 더미 3건 삽입 → 원래 빈 배열(setOrders([]))로 원복
    • _components/outbound/OutboundCartPage.tsx handleConfirm: allDummy 스킵 분기 추가 → 원래 const res = await apiClient.post("/outbound", payload); 한 줄로 원복
    • 현재 상태: 2026-04-20 (9차) 시점과 동일. 판매출고 화면은 다시 fetchOrders 빈 배열 / fetchAllCustomers 빈 배열 상태 (UI 클론, DB 미연동)

2026-04-22 (2차)

  • POP 반응형 공통 컴포넌트 5개 신설 (_components/common/)
    • theme.ts — PopColor 타입(9색) + COLOR_MAP 팔레트 (buttonBg/buttonBgHover/ring/ringSelected/text/bg50/border), 완성 리터럴만, JIT 안전
    • PopButton.tsx — forwardRef, size(sm/md/lg) + color + icon props, COLOR_MAP 조회 기반, 외부 className append
    • PopCard.tsx — forwardRef, selected/color/interactive props, ringSelected + border 색상 교체, 외부 className append
    • PopCardGrid.tsx — grid + gap, ColProfile(base/md/lg/xl/2xl) 모두 리터럴 맵 조회, 옵셔널 브레이크포인트 조건부 적용
    • PopModal.tsx — open/onClose/size(sm/md/lg/xl)/title/children/footer/hideCloseButton, ESC 키 useEffect, backdrop click close
    • 기존 파일 수정 없음. tsc --noEmit: 신규 파일 에러 0, 전체 baseline 3090 유지

2026-04-20 (9차)

  • 출고관리 화면 API 연동 (UI 껍데기 → 실연동, 입고관리 로직 포팅)
    • _components/outbound/OutboundManage.tsx 전면 rewrite
      • InboundManage.tsx 로직 그대로 포팅, 테이블 연결만 출고용으로 교체
      • 사용자 지시: "입고 로직에서 테이블 연결만 건들고 나머지는 그대로, 색상은 기존 emerald 유지"
    • API 전환: getReceivingList/updateReceiving/deleteReceiving/getReceivingWarehousesgetOutboundList/updateOutbound/deleteOutbound/getOutboundWarehouses
    • 필드 매핑: inbound_*outbound_*, supplier_*customer_*, managermanager_id
    • 타입 옵션 교체: INBOUND_TYPE_OPTIONS(10개) → OUTBOUND_TYPE_OPTIONS(판매/생산/외주/사급/반품/기타/재고이동)
    • 상태 옵션: "입고완료/부분입고/대기" → "출고완료/부분출고/대기"
    • 검사 필드 제거: inspection_status, inspector — OutboundItem 타입에 없음 (출고에 검사 개념 없음)
    • SupplierModal 재사용 (customer_code/customer_name 기반, props 타입 호환)
    • 색상 테마: 기존 출고 emerald 유지 (blue 계열 전부 emerald로, gradient #60a5fa→#2563eb#34d399→#059669)
    • 네비게이션: router.push("/COMPANY_7/pop/outbound") (뒤로가기)
    • 수정 모달 필드: 출고일, 출고상태, 수량, 단가, 금액(자동계산), LOT번호, 창고(DB 드롭다운), 위치, 담당자, 메모
    • 삭제 로직: 복수 선택 → 헤더 ID 중복 제거 → 순차 deleteOutbound (재고 롤백 메시지 유지)
    • 검증:
      • tsc --noEmit: OutboundManage 관련 새 에러 없음
      • npm run build: 성공
      • 브라우저 검증: 미수행 — 실제 출고 데이터 필요
  • 백엔드/API 클라이언트 수정 없음 (기존 outboundRoutes.ts + lib/api/outbound.ts 그대로 활용)