* 수량 컬럼: w-20 → w-14 (header), QtyInput w-16 → w-11
* 비고 컬럼: w-32 → w-20
* 품명은 무제한 폭으로 둬서 줄어든 만큼 자동 확장
화면/이미지 공유/인쇄 모두 동일하게 적용 (캡처 영역 내 변경).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
노인 사용자(거래처 사장님 등) 도 따라할 수 있도록 큰 글씨 + 단계별 안내.
User-Agent 자동 감지로 해당 기기 가이드 우선 표시, 탭으로 다른 기기 전환 가능.
* 안드로이드: Chrome → 앱 설치 배너 → 4단계
* 아이폰: Safari → 공유 → 홈 화면에 추가 → 5단계 (사파리 필수 경고 강조)
* PC: QR 코드 (휴대폰 카메라로 즉시 안내 페이지 이동)
모바일 로그인 화면 하단에 "📱 휴대폰 홈 화면에 앱처럼 설치하는 방법" 링크 추가.
middleware publicPaths 에 /install 추가 (비로그인 접근 허용).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Google Play 데이터 보안 섹션에서 '계정 URL 삭제' 필드에 넣을 페이지.
앱 내 self-service 삭제가 없는 B2B 앱이므로 이메일/전화 요청 절차를
명시한 정적 안내 페이지로 처리.
* 삭제 요청 방법 (이메일/전화)
* 처리 기간 (14일 이내)
* 삭제되는 데이터 vs 법령상 보관되는 데이터
* /privacy 와 동일하게 middleware 인증 면제
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PWABuilder 가 .aab 빌드 시 생성한 keystore 의 SHA-256 으로 갱신.
Play App Signing 활성화 후 Play 가 별도 서명 키를 발급하면 그 SHA-256 도
배열에 추가해 두 개 다 인정되도록 해야 함.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Play Store TWA(Trusted Web Activity) 풀스크린 동작에 필수. 안드로이드 앱
패키지 com.momotogether.app 의 서명 SHA-256 을 momotogether.com 도메인이
인정한다고 선언.
* 현재 SHA-256: 로컬 업로드용 키(android.keystore in ~/Downloads/momo-twa)
* Play App Signing 이 별도 서명 키를 발급하면 그 SHA-256 도 배열에 추가 필요
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- /privacy 라우트: 인증 미들웨어 면제. 시행일/수집항목/보유기간/제3자/안전성/연락처
- 추적·광고 SDK 없이 ERP 운영 데이터만 다루는 자체 서비스 기준으로 작성
- middleware publicPaths 에 /privacy 추가
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
editable 조건을 PAID/PARTIAL 만 → REQUESTED/PARTIAL/PAID/RECEIVED 로 확장.
OPEN(작성중)/CANCELLED 만 차단. 입금 의존성은 이미 해제됐고, 이번 변경으로
'발주요청 상태라 입고 입력이 불가합니다' 차단 메시지 제거.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
신규 업무 흐름: 매입발주 작성 → 발주요청 → (순서 무관) 입고 / 입금
- 발주요청(REQUESTED) 단계에서 입금 처리 없이 바로 입고 가능
- 입고완료(RECEIVED) / 입고중(PARTIAL) 건도 그 이후에 입금 처리 가능
- 이미 입금완료(PAID) 인 발주에 추가 입고가 들어와도 상태는 PAID 유지
변경 파일:
- proc-payments/confirm: 입금 허용 상태 REQUESTED → REQUESTED/PARTIAL/RECEIVED
- proc-payments/list: 노출 상태 (REQUESTED,PAID) → (REQUESTED,PARTIAL,RECEIVED,PAID)
- inbounds/page: 기본 필터 PAID_OR_PARTIAL → INBOUNDABLE (REQUESTED+PARTIAL+PAID)
드롭다운에 '발주요청만' 옵션 추가, 안내 문구 갱신
- inbounds/save: 입고 후 상태 갱신 시 PAID 면 덮어쓰지 않음
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
레이아웃 영향 없는 범위에서 가독성 ↑:
- text-[11px] → text-[13px]
- text-[12px] → text-[14px]
- 작은 배지/REMARK 등은 기존 비율 유지 (9→11, 10→12)
화면/이미지 공유/인쇄 동일하게 굵고 큰 텍스트로 나옴.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 거래명세표(admin/orders) 캡처 영역 전체 font-bold [&_*]:font-bold — 가독성 ↑
- 발주서(admin/procurements) 캡처 영역도 동일하게 bold 적용
화면/이미지 공유/인쇄 모두 굵게 표시
- 매입 발주서 관리 좌:우 레이아웃: 360px → 480px (왼쪽 리스트 더 넓게)
- 발주서 품명 컬럼 width 220px 로 제한 (단위/수량/단가/금액 열에 공간 양보)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
긴 동적 리스트(거래처/창고/품목/공급업체/매입발주)의 native <select> 를
검색 가능한 SearchableSelect 로 교체. 항목 50~100건이라도 타이핑으로 즉시 필터.
대상:
- admin/orders 출고처리: 거래처 변경
- admin/inventory: 검색 창고 / 매입입고 모달(창고+품목) / 재고이동 모달(출발+도착+품목)
- admin/inbounds/new: 매입발주 / 공급업체 / 입고창고 / 품목
- admin/procurements/new: 품목
- admin/inventory/history: 창고 필터
상태/유형 등 짧은 고정 옵션 select 는 native 그대로 (드롭다운 클릭 즉시 선택이 빠름).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- admin-panel 헤더 '← 사용자' 링크가 삭제된 /dashboard 로 가서 404 발생
- 동일 패턴: login 페이지 fallback redirect 도 /m/orders/new 로 정정
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
내 출고 이력처럼 검색 조건 변경 즉시 리스트 갱신 — 조회 버튼 불필요.
useEffect 의존성을 빈 배열 → [load] (load 의 deps 에 검색 조건 포함)
패턴으로 통일.
- admin/orders: status/dateFrom/dateTo/keyword 변경 시 즉시
- admin/payments: dateFrom/dateTo/keyword/payFilter
- admin/inventory: whFilter/keyword (load 를 useCallback 으로 wrap)
기타 페이지(invoices/inbounds/procurements/proc-payments/einvoices) 는
이미 [load] 패턴으로 자동 갱신 적용된 상태.
root cause: .js-no-export 인 input 의 cssText 캡쳐 시점에 이미
display:none 이 적용되어 있어, finally 의 cssText 원복이 display:none 을
다시 적용 → input 이 영구히 사라짐.
수정:
- 진입 순서: input cssText 캡쳐 FIRST → 그 다음 .js-no-export display:none
- 원복 순서: cssText FIRST → 그 다음 display 원복 (역순)
- 이로써 cssText 의 'display:none' 잔류 방지
부수: admin/orders 의 '출고' 버튼은 출고완료(APPROVED) 발주에서 숨김 —
'editable && (출고)' → 'STATUS === REQUESTED && (출고)'.
1) capture-share: display:none 으로 빈 input 숨기던 처리 제거.
외형(border/bg/padding) 만 잠시 제거하고 cssText 로 원복. 캡쳐 후
날짜 input 이 사라지던 문제 fix (React 가 같은 DOM 재사용 시 hidden
상태로 남던 케이스 회피).
2) 처리 중 로딩 오버레이 — components/ui/Loading 컴포넌트 활용:
· admin/orders 페이지 (busy = 일괄 출고)
· admin/orders StatementPreview (shipping = 단건 출고)
· admin/inbounds (busy = 입고 저장)
· admin/proc-payments (busy = 입금 처리)
가운데 spinner + 메시지 + 반투명 black overlay.
문제:
- 거래명세표 이미지 공유 시 input 박스(테두리/배경/그림자) 가 그대로 노출
- 발주번호 'O2605140012'/발주일자 텍스트가 좁은 폭에서 wrap 되어 깨짐
- 비고 빈 인풋이 영역만 차지
수정:
- capture-share: 캡쳐 직전 모든 input/select/textarea 의 border/bg/
shadow/padding 제거. select 는 appearance:none 으로 화살표도 가림.
값 비어있는 input 은 display:none. 캡쳐 후 cssText 로 일괄 복원.
- admin/orders: 발주번호/발주일자 영역 whitespace-nowrap + flex 로 변경.
요청: 출고관리 detail 에 '환불 추가' 버튼. 누르면 표 상단에 환불 라인
생성. 수량=1 고정, 단가 양수로 입력 시 내부에서 음수로 저장 → 총합
자동 차감.
- lines/save API: kind 'REFUND' 추가. admin 만 허용. 단가 양수 받아
음수로 저장. is_tax_free='Y' (면세) 처리. seq=0 으로 박아 상단 정렬.
- detail/route.ts: ORDER BY 에 REFUND 우선 노출.
- admin/orders UI: '환불 추가' 버튼 (rose), ExtraRow 가 REFUND 도 처리
(음수 표시 — 빨간 글씨, 수량 1 고정 잠금).
- USER /m/orders: items.filter(KIND !== 'REFUND') — 사용자 화면에서
환불 라인 비공개. 합계는 DB 의 차감된 값 그대로 노출 (사용자에게
최종 청구 금액 표시).
ORD-20260514-0001 → O2605140001 (O + YY MM DD + 0001, 11자리)
PRC-20260514-0001 → P2605140001 (P + YY MM DD + 0001, 11자리)
- genOrderNo / genProcNo 4개 함수: prefix 변경 + ymd 6자리 (YY)
- LIKE prefix||'%' 패턴은 그대로 — 새 prefix 가 자동 적용됨
- 운영 DB 기존 데이터 일괄 UPDATE 완료 (orders 22건, procurements 4건)
menu_info 에 등록된 활성 URL prefix 는 m/* 와 admin/* 뿐 — 그 외 폴더는
옛 FITO/우성 레거시. 사용자 토글 시 진입되던 /dashboard 더미 페이지 포함
전부 정리.
삭제 폴더 (총 23개):
- dashboard (영업현황/제품별현황 더미)
- approval/bom/cost/cost-mgmt/cs/delivery/fund/inventory
- order/part/part-mgmt/procurement-std/product/product-mgmt
- production/project/purchase/purchase-order/quality/sales/scm/work
유지: m/, admin/, profile/. /api/admin/* 와 /api/approval 등 API 라우트는
admin-panel 의 일부 inline 컴포넌트가 참조하므로 그대로 둠.
tsc 타입 체크 통과.
- payments/invoices/items/proc-payments/einvoices 5개 페이지에서
px-4 py-3 → px-3 py-1.5 일괄 축소. 한 화면에 더 많은 행 표시.
- items: 작업(Pencil/Trash) 셀에 whitespace-nowrap + w-[80px], 품목명
컬럼 max-w-[260px] truncate (긴 이름은 title 으로 hover)
- viewMode 기본값 'by-wh' → 'by-item' 으로 변경 (사용자 선호).
- 품목 가로 모드 본문 첫 행: '전체 합계' (emerald 강조)
· 발주수량 합 = Σ 모든 창고의 STOCK
· 여유분 합 = Σ 모든 창고의 AVAILABLE (음수면 rose)
- 이후 본사 창고 → 김포 시장 7줄 그대로 노출.
- header: 관리자 토글 클릭 시 router.push('/admin-panel?tab=user'),
사용자로 돌아갈 때 '/m/orders/new'. 사이드바만 바뀌고 콘텐츠는 그대로
남아 혼동되던 UX 개선.
- sidebar ADMIN_SYSTEM_MENU 의 '공급업체 관리' 항목 제거 — admin-panel
에서 이미 supply 탭 제거됐기 때문에 클릭 시 이상한 페이지로 가던 문제 fix.
공급업체 관리는 m/admin/vendors 별도 메뉴 사용.
1) '수기 발주' → '수기 출고' 라벨 변경 (버튼/타이틀).
2) detail STOCK_QTY: 거래처 default_wh_objid 분기 제거 → 항상 STOCK 류
전체 합산 표시. customer=admin 또는 김포 시장 등 default 가 빈 창고일
때 현재고 0 으로 표시되던 버그 fix. 실제 출고 차감은 approve 시
default_wh_objid 또는 STOCK 첫 창고 기준 그대로.
3) /api/m/orders/delete (admin) — REQUESTED 상태 발주만 hard delete.
수기 출고로 잘못 생성한 빈 발주 정리용. einvoice/items/orders 일괄.
4) 출고관리 detail (REQUESTED) 에 '삭제' 버튼 추가 — 반려 옆.
5) admin-panel 의 '공급업체관리' 메뉴 제거 (m/admin/vendors 별도 메뉴 사용).
매입 발주서 작성 패턴처럼 출고관리 안에서 직접 빈 발주 → 거래처 → 품목 채워가는 흐름.
신규 API:
- /api/m/orders/create-empty (admin) — 빈 발주 INSERT
· status='REQUESTED', customer 임시 admin, HQ 기본 supplier snapshot
- /api/m/orders/update-customer (admin) — 발주의 거래처 변경
· 변경 시 새 거래처 statement_branch 기반 supplier snapshot 재계산
· REQUESTED/APPROVED 만 변경 허용 (입금 후 잠금)
UI (/m/admin/orders):
- '수기 발주' 버튼 → 즉시 create-empty 호출 → 리스트 새로고침 + 새 row
자동 활성화 (모달/redirect 제거)
- detail 의 거래명세서 안 '귀하' 줄 → editable 시 CustomerEditor (select)
- 액션바에 '+ 품목 추가' 버튼 → AdminItemPickerModal (재고 있는 품목 검색)
· items/add API 호출, ITEM 라인 일괄 INSERT
매트릭스 뷰 — 행: 품목, 열: 창고 7개, 셀: 발주수량/여유분 2행.
- 발주수량 = 현재 보유 재고 (momo_stocks.qty)
- 여유분 = 현재고 - 기간 내 발주(REQUESTED/APPROVED/INVOICED/PAID)
의 출고 예정 수량 (거래처 default 창고 기준)
- 기간 필터: dateFrom/dateTo (기본 이번 주 월 ~ 오늘) + '금주' 버튼
- 엑셀 다운로드 지원
- 여유분 음수면 rose 강조 (재고 부족 경고)
운영 DB menu_info 9000420 등록 (parent 9000400 출고/정산).
USER 가 본인의 출고요청/출고완료 발주에 직접:
- 신규 품목 추가 (피커 모달 — /api/m/items/list 재고 있는 품목 검색)
- 택배비 단가/수량 인라인 수정 + 라인 삭제
- 용차 단가/수량 인라인 수정 + 라인 삭제
신규 API:
- /api/m/orders/items/add — ITEM 추가 (재고/숨김/한도 검증, admin 우회)
- /api/m/orders/lines/save — 가드 풀어서 REQUESTED + APPROVED 둘 다 허용
UI:
- detail modal 상단 액션 바: '+ 품목 추가' / '택배 추가/+1' / '용차 추가/+1'
- 표 안의 택배/용차 행에 수량/단가 QtyInput → onBlur 자동저장
- ItemPickerModal — 키워드 검색 + 행별 수량 입력 → 일괄 추가
전화 요청 등 시 admin 이 거래처를 대신해 발주를 작성할 수 있도록.
- /m/admin/orders 헤더에 '수기 발주' 버튼 + SearchableSelect 거래처 picker
→ 선택 후 /m/orders/new?customerObjid=momoNNN 로 이동
- /m/orders/new 가 query param customerObjid 받음:
· admin 일 때만 활성 (USER 가 query 박아도 무시)
· 상단 배너에 거래처명 표시 + 취소 링크
· save 호출 시 body 에 customerObjid 포함
- /api/m/orders/save: admin 이 body.customerObjid 명시하면 그걸로
발주 INSERT (supplier_branch snapshot 도 해당 거래처 기준)
통계 페이지 4개에 거래명세서 기준(전체/본사/김포) 필터 추가:
- /m/admin/statistics (월간 매출)
- /m/admin/statistics/daily (일자별)
- /m/admin/statistics/margin (원가/마진)
- /m/admin/statistics/pivot (거래처×일자)
각 API 의 WHERE 절에
COALESCE(O.supplier_branch, U.statement_branch, 'HQ') = $N
추가. supplier_branch snapshot 우선, 옛 발주는 user_info.statement_branch
폴백. ALL/생략 시 전체.
admin-panel 권한 및 사용자 관리 섹션에 '거래명세서 관리' 항목 추가
— activeTab='statement-branches' 시 /m/admin/statement-branches iframe
으로 로드 (기존 페이지 재사용, 별도 컴포넌트 중복 없음).
- 사용자 detail modal editable: REQUESTED → REQUESTED + APPROVED 모두 허용
- items/update API USER 가드: 동일하게 REQUESTED + APPROVED 허용
- 안내 문구 상태별로 분기
품목 추가/택배비 수정은 다음 단계에서 작업.
지사관리:
- WHERE COALESCE(supplier_branch, statement_branch, 'HQ') != 'HQ'
→ 본사 발주 완전 제외, 김포 등 지사 명의 계산서만
- snapshot 우선 (supplier_branch) → 옛 발주 폴백 (user_info.statement_branch)
- UI: 본사 row 표시 분기 제거, '본사 외' 명시
창고이동 통계:
- 본사 계열(HQ_*) → 김포 계열(KIMPO_*) 이동만 필터링
- 같은 본사 내 이동, 같은 김포 내 이동, 김포→본사 역방향 모두 제외
사용자 요구 — 지사 수수료 페이지는 본사 거래처를 보여줄 필요 없음.
계산서가 김포 등 지사 명의로 발행된 발주만 표시.
- 그룹핑 기준: COALESCE(supplier_branch, user.statement_branch, 'HQ')
· 발주 시점의 supplier_branch snapshot 우선 (= 계산서 발행 명의)
· 옛 발주(snapshot 없음) 는 거래처 statement_branch 폴백
- WHERE branch != 'HQ' 로 본사 제외
- UI: 본사 분기 제거 (모든 행이 지사)
A. 유통기한 임박 알림 (/m/admin/expiry-alerts)
- momo_inbounds.expiry_date/completed_by 컬럼 운영 DB 추가
- inbounds/save API: 입고 시 expiryDate/completedBy 함께 저장
- 페이지: 만료/7일이내/30일이내 분류 카드 + 행별 D-N 뱃지
- 빠른 필터 (7/14/30/60/90일)
B. 창고 이동 통계 (/m/admin/transfers)
- stock_moves WHERE ref_type='TRANSFER' AND move_type='OUT' 기준
- 출발창고 / 도착창고 / 품목 / 수량 / 단가(cost_price) / 금액
- 이동자(regid + user_name), 이동일시, 메모
- 합계 카드 + 엑셀 다운로드
운영 DB:
- ALTER TABLE momo_inbounds ADD COLUMN expiry_date, completed_by
- 인덱스 idx_momo_inbounds_expiry
- menu_info: 9000511 (유통기한), 9000512 (창고이동) 등록 — 통계 메뉴 산하
신규 메뉴 /m/admin/branch-fee — 거래처의 statement_branch(HQ/KIMPO 등)
기준으로 매출/원가/순수 마진 그룹핑 + 지사(HQ 외) 의 마진 × 20% =
본사 수수료 자동 계산.
표시:
- 합계 카드 4개: 총 매출 / 총 마진 / 본사 수수료 합 / 지사 실수령 합
- 지사별 표: 매출/원가/마진/수수료/실수령(마진-수수료)
- 본사(HQ) 행은 수수료 0 (— 표시)
집계 범위: 출고완료(APPROVED)/계산서발행(INVOICED)/입금완료(PAID) 발주.
운영 DB 의 menu_info objid=9000510 으로 등록 완료. (parent 9000500 통계)