1) ITEM 라인 수량을 QtyInput 인라인 인풋으로 (REQUESTED/APPROVED 상태).
onBlur/Enter 시 /api/m/orders/items/update 호출 → 자동 저장.
2) 비고(REMARK) 는 이미 onBlur 자동 저장이었음. 출고요청/출고완료 모두
editable 이라 동작.
3) ExtraRow(택배/용차) 의 V(저장) 버튼 제거. onBlur 시 자동 저장으로 변경
— label/단가/수량 어느 인풋이든 포커스 떠나면 자동 commit.
4) 모든 라인 수정 작업 (saveRemark/saveItemQty/upsertExtra/deleteExtra)
에서 onReload + onReloadList 동시 호출 → 왼쪽 발주 리스트의 합계도
즉시 반영.
부수: 운영 DB 의 모든 user_info 비밀번호를 '1' 로 reset (사용자 요청).
리스트:
- 기본 표시 = PAID + INVOICED 만 (APPROVED 출고완료 제외)
- 상태 필터 옵션도 PAID/INVOICED 만
발행 가드:
- frontend: 선택 + PAID + 미발행만 issue 가능
- API: UPDATE 조건 status='PAID' (이전엔 APPROVED 도 허용했음)
- 매입 발주서 editable 재조정: OPEN/REQUESTED 만 수정 가능. RECEIVED/
PARTIAL/PAID/CANCELLED 는 수정 불가. lines/save API 가드도 동일.
- 공급업체 select 를 SearchableSelect 로 교체 (typeahead):
· 매입 발주서 관리 페이지의 발주서 폼 (page.tsx)
· 매입 발주 신규 작성 페이지 (new/page.tsx)
운영 DB 의 매입 발주/입고/관련 stock_moves 데이터는 직접 모두 삭제했음
(사용자 명시 요청). UI 에 깨끗한 상태로 보임.
운영 DB 직접 점검 후 발견:
- supply_mng.objid 는 numeric NOT NULL (TEXT 아님) → 'MOMOSUP000000001'
같은 문자열 INSERT 가 cast fail 로 80개 다 fail 하고 supply_mng = 0개
잔존 상태였음. 운영 DB 에는 직접 80개 박아둠 (objid 1..80).
- 035 마이그레이션도 동일 패턴(numeric objid)으로 재작성. 매 deploy 안전.
직전 deploy #137 (485aea4) 빌드 실패 원인:
- procurements/page.tsx 의 deleteProc 에서 setActiveId(null) → state 가
string 이라 타입 에러. setActiveId("") 로 수정.
직전 batch 가 운영 반영 후에도 supply_mng 가 10개로 유지된다는 사용자 신고.
원인 추정: 031/032/033 의 DO block 안에서 어딘가 fail → migrate-momo.mjs 가
process.exit(1) → 그 뒤 마이그레이션 (034, 035) 실행 자체 못 함.
→ 031/032/033 본문을 SELECT 1; 로 NO-OP 화. fail 지점 우회.
→ 035 가 단독으로 회원 135 + 공급업체 80 + 제조사 메뉴 삭제 모두 처리.
· DO block 없이 plain SQL 만 (각 statement 가 별도 transaction)
· supply_mng: 통째 DELETE 후 80개 plain INSERT
· user_info: user_type='U' DELETE 후 ON CONFLICT (user_id) UPSERT
· 매 deploy 안전 — UPSERT 라 중복 INSERT 도 OK
- 매입 발주서: OPEN 일 때 삭제 버튼 노출, 라인 포함 hard delete
· 신규 API /api/m/procurements/delete (status='OPEN' 만 허용)
- 매입 발주 editable: STATUS === 'OPEN' → STATUS not in (PAID, CANCELLED)
· lines/save API 가드도 동일 (PAID/CANCELLED 만 차단)
- 035_supply_mng_plain_reload.sql: 직전 DO block 마이그레이션이 어디서
fail 하는지 추적 불가 → 가장 단순한 plain SQL 로 supply_mng 다 비우고
엑셀 기준 80개 INSERT ON CONFLICT(supply_code) UPSERT
· momo_items/momo_procurements 의 vendor_objid 모두 NULL 처리
· UNIQUE INDEX 보장 후 INSERT — 매 deploy 안전
진짜 root cause — 019_proc_terms.sql 이 매 deploy 시
DELETE FROM supply_mng;
INSERT INTO supply_mng ... 10개 시드 (VND-001 ~ VND-010)
를 실행해서 supply_mng 가 항상 10개로 reset 되고 있었음.
→ 019 의 supply_mng 시드 부분 제거 (납품조건 ALTER 만 유지).
034 신설 — idempotent 매 deploy 안전 실행:
- product_lines 컬럼 보장
- supply_code UNIQUE 인덱스 보장 (ON CONFLICT 동작)
- 옛 'VND-*' 시드는 items/procurements 의 vendor_objid 끊은 후 DELETE
- 엑셀 80개 INSERT ON CONFLICT (supply_code) DO UPDATE
- sentinel 가드 없이 매번 안전 — 사용자 추가 supply (다른 supply_code) 는 보존
1) delete API: MASTER_OBJID/OBJID 가 numeric 가 아닐 때 ::numeric cast 가
매칭 0건으로 silent fail. ::text 양쪽 비교로 안전하게.
2) 추가/제거 버튼: h-9 w-24 → h-12 w-32, cursor-pointer + hover 색상
강화. 가운데 컬럼 min-w-[120px] 로 클릭 영역 넓힘.
근본 원인:
- 008_makers_menu.sql: 매 deploy 시 제조사 관리 메뉴를 status='active' 로
되돌려놓아 사용자가 메뉴 삭제해도 다음 배포 때 부활.
- 023_seed_momo_vendors_from_xlsx.sql: 매 deploy 시 옛 100개 공급업체를
비-idempotent 한 INSERT 로 박아 supply_mng 가 영원히 옛 데이터로 원복.
→ 두 파일을 빈 NO-OP 으로 교체.
033_force_reload_v2.sql 신설 (sentinel 가드 momo_migration_marks 기반):
- 제조사 메뉴 menu_info objid=9000204 삭제
- momo_einvoice_items/einvoices/stock_moves(ORDER)/order_items/orders 통째
- user_info user_type='U' 다 삭제 후 momo001..momo135 ON CONFLICT UPSERT
· 본사팀 85 (HQ), 김포팀 50 (KIMPO), 카테고리별 default_wh 매핑, 비번 '1'
- supply_mng 다 삭제 후 80개 INSERT (엑셀 모모유통 제조사 리스트 26.05.12)
· product_lines 컬럼 ALTER (DO block 밖)
사용자 요청 — 구매자가 수량 변경 요청하면 담당자가 거래명세표에서 수기로
수정하고 다시 입금 요청하는 흐름. 출고요청(REQUESTED) 뿐만 아니라
출고완료(APPROVED) / 계산서발행(INVOICED) 까지 수정 가능해야 함.
- editable: order.STATUS === 'REQUESTED' → STATUS !== 'PAID' && !== 'CANCELED'
- items/update API 의 admin 가드는 이미 PAID/CANCELED 외 모두 허용
- 수정하면 사용자 측 명세표도 그대로 갱신 (detail API 가 동일 데이터 반환)
사용자 요청 — docs 의 엑셀 두 파일을 기준으로:
- 회원(user_info user_type='U') 전부 삭제 후 momo001..momo135 신규 등록
· 본사팀(85): 창고픽업 WH001 / 시장픽업 WH002 / 용차배송 WH003
· 김포팀(50): 김포지사 WH004 / 창고픽업 WH005 / 시장픽업 WH007 / 용차배송 WH006
· statement_branch: 본사='HQ' / 김포='KIMPO'
· 비번 '1' (AES 암호화)
- 공급업체(supply_mng) 전부 삭제 후 80개 신규 등록 (제조사 리스트 엑셀 기준)
· supply_mng 에 product_lines TEXT 컬럼 추가하여 제품명 보관
· items.vendor_objid 는 NULL 처리 (참조 무결성)
1회성 sentinel — momo_migration_marks 테이블로 가드. 신규 데이터가
다음 deploy 때 또 지워지는 사고 방지.
사용자 명시 요청 — supplier snapshot 이전의 옛 발주 데이터를 통째로
비우고 신규 발주만 운용. 사용자가 새로 등록하기로 함.
⚠️ migrate-momo.mjs 가 매 deploy 시 모든 .sql 을 재실행하므로 raw DELETE
를 그대로 박으면 신규 발주가 다음 deploy 때 또 지워지는 사고가 남.
→ sentinel 테이블 momo_migration_marks 도입, 1회만 실행되도록 가드.
삭제 범위:
- momo_einvoice_items (발주연결분)
- momo_einvoices WHERE order_objid IS NOT NULL
- momo_stock_moves WHERE ref_type='ORDER'
- momo_order_items 전체
- momo_orders 전체
보존: momo_stocks.qty — 사용자가 inventory 메뉴에서 직접 보정.
기존: 거래명세표 발급 때마다 user_info.statement_branch + branches table
을 실시간 조회 → 사용자의 기준 명세표를 바꾸거나, branches 의 계좌/
전화/이메일을 수정하면 과거 이미 찍힌 명세표까지 함께 바뀌어버림.
수정: 출고요청(REQUESTED) 시점에 supplier 8개 컬럼을 momo_orders 행에
박아두고, 이후 detail/statement/approve 는 이 snapshot 을 사용.
- 마이그레이션 030: momo_orders 에 supplier_branch / supplier_name /
supplier_ceo / supplier_bank_account / supplier_phone / supplier_email
/ supplier_biz_no / supplier_address 컬럼 추가 (idempotent IF NOT EXISTS)
- save: 발주 INSERT 시 getSupplierByBranch(user.statement_branch) 호출 결과
를 그대로 박음
- detail/statement/approve: snapshot 컬럼이 있으면 그것을 사용, 없으면
옛 발주용 폴백으로 user_info.statement_branch → branches table 조회
직전 commit 에서 버튼 자체를 통째로 지웠던 게 잘못. 출고요청 건은
admin 이 화면에서 택배/용차 라인을 추가/수정해야 함.
- 화면: 버튼 항상 보임 (editable 시)
- 이미지 공유 캡처: .js-no-export 클래스로 hide (capture-share.ts 동작)
momo 영역에서 미사용. FITO 레거시 잔존 코드 정리:
- sidebar.tsx: __sys_code 가상 메뉴 항목 제거
- admin-panel/page.tsx: code 탭/메뉴/CodeManagement 함수 삭제
- admin-panel/code-form/: 폼 페이지 디렉토리 통째로 삭제
- api/admin/codes/: list/detail/save 라우트 통째로 삭제
/api/common/code-list (조회 전용) 는 product/part-change 등이
드롭다운 로드용으로 쓰고 있어 보존.
- 마이그레이션 029 후 wh_type 이 새 enum(HQ_STOCK/KIMPO_STOCK 등)
으로 바뀌면서 detail/approve 의 wh_type='STOCK' 필터가 매칭 안 됨
→ 거래명세표 현재고가 전부 0 으로 표시됨 (재고 부족 N건 오탐).
- detail: 거래처 default_wh_objid 우선 + IN ('STOCK','HQ_STOCK','KIMPO_STOCK') 폴백
- approve: fallback 창고 lookup 도 동일하게 IN 절 확장
- 거래명세표 헤더 레이아웃: grid-cols-1 sm:grid-cols-2 → flex justify-between
으로 변경, 발주번호 라인과 공급자 박스가 항상 가로 배치(공급자 오른쪽 정렬)
- 거래명세표에서 '+ 택배 추가 / + 용차 추가' 버튼 제거 (요청)
기존 5개 (objid/wh_code 그대로 유지 — 재고 이동·입출고 데이터 보존):
- WH001 본사창고 → 본사 창고 (HQ_STOCK)
- WH002 시장픽업 → 본사 시장 (HQ_MARKET)
- WH003 용차배송 → 본사 용차 (HQ_CHARTER)
- WH004 창고픽업팀 → 김포지사 (KIMPO_BRANCH)
- WH005 김포창고 → 김포 창고 (KIMPO_STOCK)
신규 2개 (idempotent INSERT):
- WH006 김포 용차 (KIMPO_CHARTER)
- WH007 김포 시장 (KIMPO_MARKET)
총 7개. 사용자 요청한 본사 3 + 김포 4 구성 정확히 맞춤.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
증상: momo-erp container 가 force-recreate 될 때 traefik docker provider 가
새 컨테이너의 라벨을 재인식 못 해 momotogether.com 요청이 Gitea 라우터로
fallback 되는 사고 (사용자 화면에 Gitea 500 에러 페이지 노출).
deploy.yml 의 docker compose up 직후 `docker restart traefik` 1회 추가.
1~2초 다른 도메인 잠시 down 되지만 라우터 정합성 보장됨.
병행: cron watchdog (/usr/local/bin/momo-traefik-watchdog.sh, 3분 간격)이
production HTML 의 "모모유통" 문자열 검증해 비정상 시 traefik 자동 재시작.
deploy 외 임의 시점 사고에도 최대 3분 안에 자동 복구.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
마이그레이션 028:
- momo_statement_branches 테이블 신설 (code PK / name / bank_account / phone / email 등)
- HQ, KIMPO 기본 시드 INSERT (사용자가 관리자 페이지에서 편집 가능)
- 메뉴: 시스템 그룹에 '기준 명세표 관리' (M_ASBR / menu_info 9000310)
라이브러리 (src/lib/momo-branches.ts):
- 하드코딩 → DB 조회로 변경 (60초 in-memory 캐시)
- getSupplierByBranch 가 async — detail/statement/approve API 도 await 추가
- 저장 시 invalidateBranchCache() 호출
페이지/API (관리자 전용):
- /m/admin/statement-branches : list + 등록/수정/삭제 모달
- POST /api/m/admin/statement-branches/list
- POST /api/m/admin/statement-branches/save (regist / update / delete)
사용자 수정 폼:
- "기준 거래명세서" select 옵션이 하드코딩 본사/김포 → DB 의 branches list 동적 fetch
창고 관리:
- WH_TYPE 카테고리 5개 → 7개 (옛 enum 도 라벨 매핑은 유지)
· HQ_STOCK 본사 창고
· HQ_CHARTER 본사 용차
· HQ_MARKET 본사 시장
· KIMPO_BRANCH 김포지사
· KIMPO_STOCK 김포 창고
· KIMPO_CHARTER 김포 용차
· KIMPO_MARKET 김포 시장
- 신규 추가 시 select 는 위 7개만 노출, 기존 데이터 (STOCK 등) 는 라벨로 자연 표시
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
마이그레이션 027:
- user_info 에 statement_branch VARCHAR(10) DEFAULT 'HQ' 컬럼 추가
- 기존 사용자 일괄 'HQ' 로 채움
라이브러리:
- src/lib/momo-branches.ts 신설 — HQ / KIMPO 두 branch 의 공급자 정보 정의
· HQ: 기업은행 434-115361-01-016 (이상용) / 010-6369-8443 / momo8443@daum.net
· KIMPO: 농협 351-1383-7634-13 (모모유통) / 010-5789-9431 / momokimpo@nate.com
- getSupplierByBranch(branch) helper
거래명세표 supplier 분기 (3개 API):
- /api/m/orders/detail: order.STATEMENT_BRANCH 따라 supplier 객체 결정
- /api/m/orders/statement/[id]: xlsx 다운로드도 동일
- /api/m/orders/approve: 메일 발송 stmt 도 동일
사용자 수정 폼:
- /api/admin/users/detail: statement_branch 반환 (default 'HQ')
- /api/admin/users/save: statement_branch 받아 UPDATE
- /admin-panel/user-form: "기준 거래명세서" select 추가 (본사/김포)
흐름: 거래처 사용자의 기준을 김포로 설정 → 그 사용자의 발주에 대한 거래명세표 supplier 가 김포 정보로 표시
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1) 매입 발주서 관리(/m/admin/procurements):
- 조회조건 flex-wrap → flex-nowrap + overflow-x-auto (모바일 한 줄, 가로 스크롤)
- 공급업체 select → SearchableSelect (타이핑으로 결과 내 검색)
- 폰트/높이 축소 (h-9 → h-8, text-sm → text-xs)
2) 매입 입금관리(/m/admin/proc-payments): 동일 한 줄 정비
3) 창고 관리(/m/admin/warehouses):
- WH_TYPE 에 KIMPO "김포 창고" 카테고리 추가 + 라벨/배지색 등록
- 신규 창고 추가 시 select 옵션에 자동 노출
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 매입 발주 관리(/m/admin/procurements):
· 날짜 from~to + 공급업체 select 추가 (기본: 오늘 - 30일 ~ 오늘)
· 조회 버튼 제거 — state 변경 시 자동 fetch
- 내 발주 이력(/m/orders):
· 날짜 기본값을 오늘 - 30일 ~ 오늘로 설정 (URL 파라미터 우선 적용)
- 출고 처리(/m/admin/orders) 검색바:
· 모바일에서 label 풀어진 5단 grid → 한 줄 flex-wrap 으로 압축 (h-8 + text-xs)
· 모바일 폼이 화면을 너무 차지하던 문제 해소
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
지난 commit 의 026 이 ON CONFLICT(objid) 로 INSERT 시도 → menu_info 에 PK/unique 없어 PG 에러.
패턴: INSERT WHERE NOT EXISTS + 그 다음 별도 UPDATE WHERE objid=... 로 idempotent 처리.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1) 사이드바 메뉴 누락 fix (마이그레이션 026):
- FITO menu_info 테이블에 9000304 '매입 입금관리', 9000305 '재고이력' INSERT
- 기존 입고/재고 seq 재정렬 (11→12, 12→13)
- momo_menus 만으로는 사이드바에 안 나옴 — menu_info 가 사이드바의 진짜 소스
2) 재고이력 표시 개선:
- inventory/history API: REF_TYPE_LABEL (한글) + COUNTER_WH_NAME (이동 시 상대 창고) 추가
- inventory/transfer 라우트: stock_moves 의 ref_objid 에 상대 창고 objid 박음
- StockHistoryModal + history page: "INBOUND" → "입고", TRANSFER 시 "→ XX창고/← XX창고" 표시
3) 자동조회 (조회 버튼 없이 즉시):
- m/orders (내발주이력): 날짜 from~to + 상태 input 추가 + state dep useEffect
- m/orders/new (출고요청): "재고있는 품목만 / 전체 품목" 필터 추가 + 250ms 디바운스 자동 fetch
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1) 입고 처리 (m/admin/inbounds):
- 노출 대상: REQUESTED+PARTIAL → PAID+PARTIAL 로 변경 (입금 안 된 발주는 입고 불가)
- editable 조건 / STATUS 라벨/색상 PAID 추가
- 안내 문구 갱신
2) 재고이력 메뉴 (마이그레이션 025):
- M_AINVH '재고이력' 메뉴 매입 그룹 sort 34 에 INSERT (페이지는 기존 /m/admin/inventory/history 활용)
3) 재고관리 페이지 (m/admin/inventory):
- 데스크탑 표/모바일 카드 모두 행마다 "이력" 버튼 추가
- 클릭 시 StockHistoryModal 팝업 — 해당 품목 + 해당 창고 한정 이력 조회 (POST /api/m/inventory/history)
매입 흐름 완성: 매입발주(REQUESTED) → 입금관리(PAID) → 입고처리(RECEIVED)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
매입 흐름: 매입발주(REQUESTED) → 매입 입금관리(PAID) → 입고 처리(RECEIVED)
DB (마이그레이션 024):
- momo_procurements 에 paid_date, paid_amount, paid_method, paid_memo 컬럼 추가
- 매입 그룹 메뉴 sort 재정렬: 매입발주 30, 입금관리(신설) 31, 입고처리 32, 재고관리 33
- M_APROCPAY '매입 입금관리' /m/admin/proc-payments 메뉴 INSERT (ON CONFLICT idempotent)
UI/API:
- /m/admin/proc-payments 페이지 — 발주요청/입금완료 분리 카드 + 입금 처리 모달 (금액/방법/메모)
- 조회조건: 날짜 from~to + 공급업체 + 상태 (즉시 반영)
- POST /api/m/admin/proc-payments/list — REQUESTED|PAID 만 노출
- POST /api/m/admin/proc-payments/confirm — REQUESTED → PAID 전환 + paid_* 채움
다음 단계 (별도 batch): 입고 처리 페이지에서 PAID 만 노출 + 입고 시 RECEIVED 전환
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1) 삭제:
- src/app/(main)/m/admin/makers/page.tsx
- src/app/api/m/makers/{list,save,delete}/route.ts
(메뉴 DB 의 제조사 항목은 이전 commit 9705a04 에서 이미 제거됨)
2) 마이그레이션 023:
- docs/모모유통 제조사 리스트(26.05.12).xlsx 의 80개 업체를 supply_mng 에 일괄 등록
- idempotent: supply_name 중복 시 SKIP (NOT EXISTS)
- supply_code: MM-NNNN 자동 채번 (기존 max(objid) + ROW_NUMBER)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
기존: 마지막 컬럼에 "보기" 버튼 + tr onClick 둘 다 있어 중복
변경: 동작 컬럼 + 보기 버튼 제거. tr 자체 클릭 시 상세 모달 (openDetail) 호출 — 이미 onClick 박혀있어 동작 동일.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
권한 fix — order.customer_objid 와 매칭 시:
- 기존: user.objid 만 비교 → FITO 사용자(objid 없음)는 항상 fail → "권한 없음"
- 변경: user.objid ?? user.userId 와 customer_objid 매칭, 또는 user.userId 와 직접 매칭
- 적용: items/update, lines/save, cancel, statement, items/remark (5개 API)
출고요청 리스트(m/orders/new) UI:
- table 의 min-w-[640px] 제거 + table-fixed 적용
- 수량 컬럼 폭 180px → 112px, "담기" 버튼 텍스트 제거 (+ 아이콘만)
- 폰트 11~12px 로 축소
- 모바일 화면 한 줄에 들어오도록
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
invoices(계산서 발행) page:
- 조회조건 추가: 거래처(SearchableSelect) / 날짜 from~to / 상태
- 조회 버튼 제거 — 입력하면 즉시 클라이언트사이드 필터 적용
- "조회 결과 합계" 카드: 면세 / 과세(공급+세액) / 합계 분리 표시
- "선택 합산" 카드: 체크박스로 고른 건들의 면세/과세/합계 실시간 합산
- 표 행마다 면세/과세 컬럼 추가
- 전체 선택 체크박스 (헤더)
deploy.yml:
- docker compose up 흐름 강화: down --remove-orphans 후 docker rm -f momo-erp 로 잔존 컨테이너 강제 제거 + --force-recreate
- 수동 SSH 배포 + 자동 배포 겹쳤을 때 "container name already in use" 충돌 자동 해소
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 품목관리(items):
· STATUS 컬럼 표시/필터/폼에서 제거 (전부 ACTIVE 가 default — 사용자 사용 안 함)
· 조회조건에 공급업체 SearchableSelect 추가 (이미 백엔드 vendorObjid 지원)
- 계산서 발행(einvoices):
· 조회조건에 거래처 SearchableSelect 추가 (customers list API 사용)
· 페이지 하단 tfoot 에 면세 합계 / 과세 합계 / 총 합계 분리 표시
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 결제 계좌번호 셀: <br/> 줄바꿈 제거 + whitespace-nowrap + width 110px 로 한 줄 표시
- 총 합계 (VAT포함) 셀: whitespace-nowrap + 폰트 11px 로 좁은 셀에서도 한 줄
- 거래처 이메일(귀하 아래 라인) 표시 제거 — 외부 공유용 이미지에 사용자 이메일 노출 불필요
m/admin/orders 와 m/orders 두 곳 동일 적용.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
기존: REQUESTED 상태만 수정 가능 (admin/user 동일)
변경:
- USER: REQUESTED 만 (기존 그대로)
- ADMIN: PAID/CANCELED 가 아니면 모두 (REQUESTED / SHIPPED 등 입금완료 전까지)
items/update, lines/save 두 API 동일 적용. 입금완료(PAID) 이후나 취소건은 admin 도 수정 불가.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
기존: user.role === "USER" 일 때 숨김 → 거래처라도 role 필드 비어있으면 노출되는 버그
변경: user.isAdmin === true || role === "ADMIN" 일 때만 노출 → 그 외는 모두 숨김
admin 계정만 거래명세표 이미지 공유 가능.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
기존: mount 시 한 번만 history sentinel push → 사용자가 navigation 하면 sentinel 잃어버려 토스트 안 뜸.
변경: usePathname 의존성 useEffect → pathname 변경마다 sentinel 새로 push. lastBackRef 도 ref 로 변경(렌더 의존성 없이 상태 유지).
+ swal toast z-index 9999 강제 (다른 모달 위)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- middleware: User-Agent 가 모바일이면 /login → /m/login 으로 redirect (서버 측 분기)
- auth-store.logout: window 가 모바일이면 /m/login, 아니면 /login (클라이언트 측 분기)
- BackButtonGuard: TWA 일부 환경에서 display-mode 가 standalone 으로 보고되지 않는 케이스 대응 — fullscreen/minimal-ui 도 포함, 모바일 UA 면 무조건 활성화
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
m/orders 페이지의 거래명세표 DetailModal 에서 "이미지 공유" 버튼이 모든 사용자에게 노출되던 문제.
useAuthStore 의 user.role === "USER" 이면 버튼 hide. ADMIN 은 그대로 표시.
엑셀 다운로드 버튼은 그대로 유지 (사용자가 자기 주문 명세는 엑셀로 받을 수 있음).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/components/back-button-guard.tsx 신규: standalone(PWA/TWA) 모드에서만 작동
· 첫 뒤로가기 → sweetalert2 toast("한 번 더 누르면 앱이 종료됩니다") 표시
· 2초 안에 두 번째 뒤로가기 → history.back() 으로 native back 위임 → 앱 종료
· 일반 브라우저(non-standalone) 사용자에게는 영향 없음
- src/app/layout.tsx 의 RootLayout 에 BackButtonGuard 마운트
- src/app/(auth)/m/login/page.tsx 에 1.5초 스플래시 overlay 추가
· 모모 로고 + "모모유통 ERP" + spinner ("로딩 중...")
· z-60 fixed inset-0, 1.5s 후 opacity fade-out
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/lib/capture-share.ts 에 forceWidth 옵션 추가 → 캡처 직전 임시로 node width 강제 + 즉시 원복
- 출고 처리(거래명세표) 와 매입발주서 관리의 이미지 공유 호출에 forceWidth: 1100 적용
- 모바일 화면(좁은 viewport)에서 좁아진 표/품명 셀이 한 줄로 펼쳐져 엑셀 가로 출력처럼 캡처됨
- m/orders 페이지의 inline captureAndShare 를 capture-share lib 으로 통일 (toJpeg fallback / AbortError 처리 공유)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/app/(auth)/m/login/page.tsx 신규 — 한 화면에 딱 맞는 모바일 layout (logo + form + 푸터, safe-area inset 적용)
- middleware.ts publicPaths 에 /m/login + PWA 자원(/manifest.json, /sw.js, /.well-known) 추가
- 세션 있는 상태로 /m/login 진입 시 /m/dashboard 로 자동 redirect
- manifest.json 의 start_url 을 /m/login 으로 변경 → TWA APK 가 앱 실행 시 바로 로그인 화면
로그인 성공 시 /m/dashboard 로 이동 (기존 /login 은 API 응답의 redirectTo 사용, 모바일은 hardcode).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.0.0 APK (com.momotogether.erp) 의 서명 인증서 SHA-256 을 Digital Asset Links 에 등록.
이 commit 이 production 에 배포되면 TWA 앱이 URL bar 없이 풀스크린으로 동작.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- public/manifest.json + service worker(sw.js) 추가
- icon PNG 변환 (192/512/180)
- public/.well-known/assetlinks.json placeholder (Bubblewrap 빌드 후 APK 서명 SHA256 채울 자리)
- layout.tsx 에 manifest/theme-color/apple-touch-icon 메타데이터 + 서비스 워커 등록 스크립트 추가
Bubblewrap 으로 APK 빌드 시 https://www.momotogether.com/manifest.json 을 source 로 사용.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
운영 서비스 목록, 데이터 볼륨 위치, 노출 포트, 운영 중 적용한 hotfix(Mailu DNSSEC/MariaDB 11.8 등), Phase 별 이관 체크리스트.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WebContent/ (JSP + SmartEditor2 + 정적 자원) 와 src/com/ (Spring Controller/Service/Mapper) 디렉토리 전체 삭제. 총 2,191 파일.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
docker compose build 시 latest 태그가 새 sha 로 갱신되면서 옛 sha 가 untagged
상태로 남아 매 배포마다 누적되던 문제. docker image prune -f 로 dangling 만 회수
(다른 프로젝트의 사용 중 이미지는 안 건드림).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>