[정책] - 발주/출고/입금 흐름과 분리된 별도 메뉴 (월말 일괄 또는 신고 시점 발행 가능) - 출고 시 자동 발행은 향후 토글 옵션으로 추가 [DB 012] - momo_einvoices: 발행 이력 (공급자/받는자/금액/승인번호/상태/원본XML) - momo_einvoice_items: 라인별 상세 - 상태: DRAFT → QUEUED → SENT → ACK | FAIL | CANCELED [발행 어댑터 추상화 (lib/einvoice)] - InvoiceProvider 인터페이스 — issue/status/cancel - adapters/manual.ts: 자체 거래명세서 (국세청 전송 X, 기본) - adapters/nts-esero.ts: 국세청 e-세로 직접 연동 골격 · NTS_ESERO_MODE: stub | test | prod · stub 모드는 DB 기록만 (개발/CI 안전) · 실 통신은 사업자 공동인증서 + ERP 연계 승인 후 활성화 · SOAP/XMLDSig 페이로드 빌더 골격 작성, 인증서 받으면 서명+전송 추가 - index.ts: EINVOICE_PROVIDER 환경변수로 어댑터 선택 [API] - POST /api/m/einvoices/list: 발행 이력 조회 + 필터 (관리자) - POST /api/m/einvoices/issue: 발주(orderObjid)로부터 또는 수동 입력으로 발행 · 어댑터 결과를 momo_einvoices/_items 에 트랜잭션 기록 (성공/실패 모두) [UI] - /m/admin/einvoices 페이지 신설 · 발행 가능 발주 리스트 (출고/입금 완료된 건) · 한 번 클릭으로 세금계산서 발행 → 결과 모달 · 발행 이력 (날짜/상태/승인번호 필터, 엑셀 다운로드) · STUB 모드 안내 배너 — 운영 활성화 절차 명시 [문서] - docs/MOMO_DISTRIBUTION_SPEC.md 부록 B (v0.6) 추가 다음 단계 (인증서 + ERP 연계 승인 후): - nts-esero.ts 의 SOAP + XMLDSig 실제 구현 - NTS_ESERO_MODE=test 로 100건 검증 - NTS_ESERO_MODE=prod 전환 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
26 KiB
모모유통 — 도매 유통 관리 시스템 개발 스펙
버전: 0.2 (기존 테이블 재사용 정책 반영) 작성일: 2026-04-26 대상 도메인:
momotogether.com(구:momo.junggomoa.com) DB:distribution(PostgreSQL 16, 320+ 테이블 — FITO 스키마 import) 기술 스택: Next.js 15 (App Router) · React 19 · TypeScript · Tailwind · raw SQL viapg· JWT 세션 · Zustand · TanStack Table · SweetAlert2
0. 요약 (TL;DR)
모모유통은 대형 도매 유통 업체다. 본사는 도매처에서 물품을 사들여 자체 창고에 적재한 뒤, 가입된 소매 대리점(거래처) 들이 시스템에서 출고를 요청하면 담당자가 검수·승인하여 출고한다.
- 사용자 그룹 2종
- 거래처(USER) — 가입·로그인 후 재고 보유 품목을 보고 출고 요청서 작성
- 관리자(ADMIN) — 품목·재고·창고 관리, 출고 요청 승인, 명세서/계산서 발행, 통계 조회
- 핵심 워크플로우 (거래처 관점 4단계)
- 출고 요청 (거래처) → status
REQUESTED - 출고 처리 (담당자 승인 + 메일+엑셀 자동 발송) → status
APPROVED(= 출고 완료) - 입금 확인 (담당자 등록) → status
PAID(= 입금 완료) - 월말 계산서 발행 (일괄) → status
INVOICED(= 계산서 발행 완료, 최종)
- 출고 요청 (거래처) → status
- 면세/과세 구분: 품목명 접두어
M= 면세 (예:M유정란). 명세서·통계에서면세매출합/과세매출합분리 집계. - 메일 발송: 출고 처리 시 가입 이메일로 거래명세표 본문 + 엑셀(.xlsx) 첨부 자동 발송.
1. 테이블 재사용 정책 ⭐ (핵심 원칙)
distribution DB에는 기존 FITO 스키마 320+ 테이블이 그대로 import 되어 있다. 새 테이블을 만들기 전 기존 테이블을 먼저 확인하고, 재사용 가능한 것은 절대 새로 만들지 않는다.
1.1 기존 테이블 그대로 재사용 (★ 변경 금지)
| 용도 | 기존 테이블 | 비고 |
|---|---|---|
| 사용자(거래처/관리자/직원) 통합 | user_info |
모든 로그인 계정. user_type으로 구분 |
| 부서 | dept_info |
거래처는 별도 부서명("거래처") 부여 |
| 권한 마스터 | authority_master |
ADMIN, USER, 추가 사용자정의 권한 |
| 권한↔사용자 매핑 | authority_sub_user |
|
| 메뉴 마스터 | menu_info |
모모 메뉴는 [사용자] 그룹 아래 대메뉴/소메뉴로 등록 |
| 권한↔메뉴 매핑 | rel_menu_auth |
|
| 공통 코드 | comm_code |
ORDER_STATUS, WH_TYPE 등 신규 코드그룹만 추가 |
| 거래처 / 매입처 | supply_mng |
charger_type 으로 구분 (C=거래처, V=매입처) |
| 첨부 파일 | attach_file_info |
품목 이미지 등 |
| 로그인 이력 | login_access_log |
기존 로직 그대로 |
1.2 신규 생성 (모모 비즈니스 도메인만)
기존 product_mgmt, purchase_order 등은 PLM 제조 도메인이라 유통(상품 매입/판매) 의미가 다름. 충돌 방지 위해 momo_* 접두사로 새로 만든다.
| 신규 테이블 | 용도 |
|---|---|
momo_items |
품목 마스터 (단가, 면세여부, 사진) |
momo_warehouses |
창고 |
momo_stocks |
창고×품목 현재고 |
momo_stock_moves |
입출고 이력 |
momo_orders |
출고 요청서 (거래처 → 모모) |
momo_order_items |
출고 요청 라인 |
momo_procurements |
매입 발주서 (모모 → 도매처) |
momo_procurement_items |
매입 발주 라인 |
momo_inbounds |
입고 처리 헤더 |
momo_inbound_items |
입고 라인 (정상/불량 분리) |
momo_mail_logs |
거래명세표 메일 발송 로그 |
만들지 않는다:
momo_users(×),momo_makers(×),momo_vendors(×),momo_attachments(×),momo_roles(×),momo_menus(×),momo_role_menus(×) — 모두 위 §1.1의 기존 테이블에 매핑. (참고: 초기 v0.1 구현 시momo_users등 일부 신규 테이블이 만들어졌으나, 본 v0.2 정책에 따라 향후 마이그레이션으로 기존 테이블로 통합한다 — §13 참조.)
2. 사용자 역할 / 권한
| 역할 | user_info.user_type |
설명 | 접근 가능 메뉴 |
|---|---|---|---|
| 거래처 | C (CUSTOMER 신규 코드) 또는 P (PARTNER 재활용) |
대리점/소매상 | 대시보드, 품목 검색, 출고 요청, 본인 출고 이력, 미수금/계산서 조회 |
| 일반 직원 | U (USER) |
모모유통 직원 | 화면 권한에 따라 |
| 관리자 | A (ADMIN) |
모모 담당자 | 전체 메뉴 |
권한 매핑은 기존
authority_master+authority_sub_user+rel_menu_auth그대로 사용. 메뉴별 노출 권한은 메뉴 관리 화면에서 담당자가 매핑.
3. 회원가입 / 로그인
3.1 가입 화면 (/signup)
- 필드: 이메일(필수, 유니크) · 업체명(필수) · 비밀번호 · 연락처 · 사업자번호 · 대표자명
- 저장:
user_infoINSERTuser_id= 이메일user_password= 기존 FITOEncryptUtil.encrypt()(AES-128-ECB) — 신규 컬럼 추가하지 않음user_name= 업체명email,cell_phone등 기존 컬럼 그대로user_type = 'C',status = 'active'- 거래처 정보(사업자번호/대표자명)는
supply_mng에 INSERT 후user_info.partner_objid로 연결 (없으면 user_info에 직접 추가 컬럼 —biz_no,ceo_name신규 컬럼 1회 추가만 허용)
3.2 로그인 화면 (/login)
- 입력: 이메일(또는 user_id) + 비밀번호
- 검증: 기존
verifyCredentials()그대로 사용 —user_info에서user_password비교 - 성공: JWT 발급 →
plm-session쿠키 →/dashboard리다이렉트
3.3 미들웨어
공개 경로: /, /login, /signup, /api/auth/login, /api/auth/signup
4. 데이터 모델
4.1 사용자 / 인증 — user_info 그대로 재사용
기존 컬럼:
sabun, user_id, user_password, user_name, user_name_eng, user_name_cn,
dept_code, dept_name, position_code, position_name,
email, tel, cell_phone, user_type, user_type_name,
regdate, data_type, status, end_date, fax_no, partner_objid, rank
가입자에 사용할 추가 정보(사업자번호/대표자명)는:
- (A안)
supply_mng에 거래처 row 추가 후partner_objid로 연결 (기존 패턴, 권장) - (B안)
user_info에biz_no VARCHAR(20),ceo_name VARCHAR(100)컬럼 추가 (단순)
결정 사항: A안 우선, supply_mng 재사용 못하는 경우만 B안.
4.2 부서 — dept_info 재사용
거래처용 부서 1개 추가: DEPT_CUSTOMER / "거래처". 모든 가입자는 이 부서로 묶이거나 회사명을 그대로 부서명으로 사용.
4.3 거래처 / 매입처 — supply_mng 재사용
charger_type 컬럼 활용:
C(CUSTOMER) — 거래처 (출고 받는 측, 가입 사용자와 1:1)V(VENDOR) — 매입처 (도매처/제조사)
거래처 가입 시 자동 INSERT → user_info.partner_objid 연결.
4.4 권한 / 메뉴 — 기존 시스템 그대로
authority_master: USER(거래처), ADMIN(관리자) 권한 row 추가menu_info: 모모 메뉴는[사용자]그룹 아래 5개 대메뉴(거래처 주문/마스터/매입·입고/출고·정산/통계) + 소메뉴 등록rel_menu_auth: 권한별 노출 메뉴 매핑 (메뉴 관리 UI에서 설정)
4.5 첨부 — attach_file_info 재사용
품목 이미지, 거래명세표 PDF 등 모든 첨부는 기존 테이블에 저장.
target_obj_id= items.objiddoc_type=ITEM_IMAGE,STATEMENT_PDF등 (comm_code에 코드그룹 추가)
4.6 공통 코드 — comm_code 재사용
신규 코드그룹만 INSERT:
| 코드그룹 ID | 의미 | 코드 예시 |
|---|---|---|
ORDER_STATUS |
출고 요청 상태 | REQUESTED, APPROVED, PAID, INVOICED, CANCELLED |
WH_TYPE |
창고 유형 | STOCK, PICKUP_TEAM, MARKET, DELIVERY |
MOVE_TYPE |
재고 변동 | IN, OUT, ADJ, TRANSFER |
UNIT |
단위 | EA, BOX, KG, L, PACK |
USER_ROLE_MOMO |
모모 권한 | C(거래처), U(직원), A(관리자) |
DOC_TYPE_MOMO |
첨부 문서 유형 | ITEM_IMAGE, STATEMENT_PDF |
4.7 품목 / 재고 / 발주 — 신규 테이블 (momo_*)
-- 품목
CREATE TABLE momo_items (
objid TEXT PRIMARY KEY,
item_code VARCHAR(50) NOT NULL UNIQUE,
item_name VARCHAR(200) NOT NULL,
item_detail TEXT,
maker_supply_objid TEXT, -- supply_mng.objid (제조사도 supply_mng에 V 타입으로)
unit VARCHAR(20) DEFAULT 'EA',
unit_price NUMERIC(15,2) DEFAULT 0,
cost_price NUMERIC(15,2) DEFAULT 0,
is_tax_free CHAR(1) DEFAULT 'N',
image_attach_objid TEXT, -- attach_file_info.objid
attributes JSONB,
status VARCHAR(20) DEFAULT 'ACTIVE',
is_del CHAR(1) DEFAULT 'N',
regdate TIMESTAMP DEFAULT NOW(),
regid TEXT
);
-- 창고
CREATE TABLE momo_warehouses (
objid TEXT PRIMARY KEY, wh_code VARCHAR(50) UNIQUE, wh_name VARCHAR(200),
location VARCHAR(200), wh_type VARCHAR(20) DEFAULT 'STOCK',
is_del CHAR(1) DEFAULT 'N', regdate TIMESTAMP DEFAULT NOW()
);
-- 창고×품목 현재고
CREATE TABLE momo_stocks (
objid TEXT PRIMARY KEY, wh_objid TEXT, item_objid TEXT,
qty NUMERIC(15,2) DEFAULT 0, update_date TIMESTAMP DEFAULT NOW(),
UNIQUE(wh_objid, item_objid)
);
-- 입출고 이력
CREATE TABLE momo_stock_moves (
objid TEXT PRIMARY KEY, wh_objid TEXT, item_objid TEXT,
move_type VARCHAR(20), qty NUMERIC(15,2),
ref_type VARCHAR(20), ref_objid TEXT, memo TEXT,
regdate TIMESTAMP DEFAULT NOW(), regid TEXT
);
-- 출고 요청서 (거래처 → 모모)
CREATE TABLE momo_orders (
objid TEXT PRIMARY KEY, order_no VARCHAR(50) UNIQUE,
customer_user_id VARCHAR(50), -- user_info.user_id (FK 미설정 — soft 참조)
customer_supply_objid TEXT, -- supply_mng.objid (거래처 정보)
order_date DATE DEFAULT CURRENT_DATE,
status VARCHAR(20) DEFAULT 'REQUESTED',
approve_user_id VARCHAR(50), approve_date TIMESTAMP,
invoice_no VARCHAR(50), invoice_date DATE,
total_supply NUMERIC(15,2), total_vat NUMERIC(15,2), total_amount NUMERIC(15,2),
total_taxfree NUMERIC(15,2), total_taxable NUMERIC(15,2),
paid_amount NUMERIC(15,2), paid_date DATE,
memo TEXT, is_del CHAR(1) DEFAULT 'N',
regdate TIMESTAMP DEFAULT NOW(), regid VARCHAR(50)
);
CREATE TABLE momo_order_items (
objid TEXT PRIMARY KEY, order_objid TEXT, item_objid TEXT,
item_name_snap VARCHAR(200), unit_price NUMERIC(15,2), qty NUMERIC(15,2),
is_tax_free CHAR(1), supply_amount NUMERIC(15,2), vat_amount NUMERIC(15,2),
total_amount NUMERIC(15,2), seq INT
);
-- 매입 발주 + 입고
CREATE TABLE momo_procurements (
objid TEXT PRIMARY KEY, proc_no VARCHAR(50) UNIQUE,
vendor_supply_objid TEXT, -- supply_mng.objid (V 타입)
proc_date DATE, status VARCHAR(20) DEFAULT 'OPEN',
total_amount NUMERIC(15,2), memo TEXT,
is_del CHAR(1) DEFAULT 'N', regdate TIMESTAMP DEFAULT NOW()
);
CREATE TABLE momo_procurement_items (
objid TEXT PRIMARY KEY, proc_objid TEXT, item_objid TEXT,
cost_price NUMERIC(15,2), qty NUMERIC(15,2), total_amount NUMERIC(15,2),
received_qty NUMERIC(15,2) DEFAULT 0,
received_normal NUMERIC(15,2) DEFAULT 0,
received_defect NUMERIC(15,2) DEFAULT 0
);
CREATE TABLE momo_inbounds (
objid TEXT PRIMARY KEY, inbound_no VARCHAR(50) UNIQUE,
proc_objid TEXT, vendor_supply_objid TEXT, wh_objid TEXT,
inbound_date DATE, status VARCHAR(20) DEFAULT 'COMPLETED',
total_amount NUMERIC(15,2), memo TEXT,
regdate TIMESTAMP DEFAULT NOW(), regid VARCHAR(50)
);
CREATE TABLE momo_inbound_items (
objid TEXT PRIMARY KEY, inbound_objid TEXT, item_objid TEXT,
qty_normal NUMERIC(15,2), qty_defect NUMERIC(15,2),
cost_price NUMERIC(15,2), defect_reason VARCHAR(200),
total_amount NUMERIC(15,2), seq INT
);
-- 메일 로그
CREATE TABLE momo_mail_logs (
objid TEXT PRIMARY KEY, to_email VARCHAR(200), subject VARCHAR(300),
body TEXT, ref_type VARCHAR(20), ref_objid TEXT,
status VARCHAR(20) DEFAULT 'PENDING', error_msg TEXT,
sent_at TIMESTAMP, regdate TIMESTAMP DEFAULT NOW()
);
5. 메뉴 구조 — menu_info 재사용
[사용자] 루트(objid=-395553955) 아래에 모모 대메뉴 5개 + 소메뉴를 등록 (이미 마이그레이션 005로 적용 완료).
[사용자]
├ DASHBOARD → 자식: 대시보드 → /m/dashboard
├ 거래처 주문 → 품목 검색·출고 요청·내 출고 이력
├ 마스터 관리 → 품목·매입처·창고
├ 매입/입고 → 매입 발주·입고 처리·재고 관리
├ 출고/정산 → 출고 관리·입금 관리·계산서 발행
└ 통계 → 월간 매출·일자별·원가/마진
시스템(사용자/권한/메뉴 관리)은 기존
[관리자]루트의 메뉴 그대로 사용. 모모 자체 회원/권한/메뉴 페이지는 만들지 않음.
6. API 라우트
6.1 인증
| Method | Path | 동작 |
|---|---|---|
| POST | /api/auth/signup |
user_info INSERT (+ supply_mng) |
| POST | /api/auth/login |
verifyCredentials() 그대로 |
| POST | /api/auth/logout |
기존 |
6.2 모모 비즈니스 (/api/m/*) — 모두 신규
- 품목:
/api/m/items/{list,save,delete,upload-image} - 창고:
/api/m/warehouses/{list,save} - 재고:
/api/m/inventory/{list,inbound,history} - 출고:
/api/m/orders/{save,list,detail,approve,cancel,payment,invoice,statement/[id]} - 매입:
/api/m/procurements/{list,save,detail} - 입고:
/api/m/inbounds/{save,list} - 통계:
/api/m/statistics/{daily,monthly,margin} - 대시보드:
/api/m/dashboard
6.3 관리자 (admin-panel) — 모두 기존 그대로 사용
/api/admin/users/api/admin/users/save/api/admin/users/delete(신규)/api/admin/dept/api/admin/dept/save/api/admin/dept/delete(신규)/api/admin/menus/api/admin/menus/save/api/admin/menus/delete(cascade 지원)/api/admin/auth/api/admin/codes/api/admin/supply/api/admin/log-*
7. 핵심 워크플로우 (거래처 관점 4단계)
거래처: 품목 검색 + 출고 요청
└─ INSERT momo_orders (status='REQUESTED') + momo_order_items
↓
모모 담당자: 출고 관리 → [승인]
├─ FOR EACH item: UPDATE momo_stocks SET qty -= line.qty (FOR UPDATE)
├─ INSERT momo_stock_moves (move_type='OUT', ref='ORDER')
├─ UPDATE momo_orders SET status='APPROVED', approve_date, approve_user_id
├─ 거래명세표 HTML 생성 + xlsx 생성
├─ sendMail(가입 이메일, html, [xlsx 첨부])
└─ INSERT momo_mail_logs
↓
모모 담당자: 입금 관리 → [입금 등록]
└─ UPDATE momo_orders SET paid_amount, paid_date,
status = (paid_amount >= total_amount) ? 'PAID' : status
↓
모모 담당자: 월말 [계산서 발행 일괄]
└─ UPDATE momo_orders SET status='INVOICED', invoice_no, invoice_date
7.1 트랜잭션 경계
승인은 단일 트랜잭션 — 재고 차감 실패 시 발주 상태도 롤백. 메일 발송은 트랜잭션 외부.
7.2 금액 계산 (단가 = VAT 포함가)
- 면세:
supply = price × qty,vat = 0,total = supply - 과세:
total = price × qty,supply = round(total / 1.1),vat = total - supply
8. 페이지 명세
8.1 거래처 (USER)
/m/dashboard— KPI 4종 (대기 발주, 진행 발주, 이번달 누적, 미수금) + 최근 발주 5건/m/items— 품목 검색 + 장바구니 (재고 0 비활성, 면세 뱃지, 실시간 면세/과세 합계)/m/orders/new—/m/items와 동일 페이지/m/orders— 본인 출고 이력 (상태 뱃지, 거래명세표 다운로드)
8.2 관리자 (ADMIN)
/m/dashboard— KPI 5종 + 14일 매출 그래프 + 재고 부족 + 승인 대기/m/admin/items— 품목 CRUD (이미지 업로드, 면세 자동 토글, 속성 JSON)/m/admin/vendors— 매입처 (= supply_mng V 타입)/m/admin/warehouses— 창고 CRUD/m/admin/inventory— 창고별 현재고/m/admin/procurements+/new— 매입 발주/m/admin/inbounds+/new— 입고 처리 (정상/불량 분리, 정상만 재고+)/m/admin/orders— 출고 관리 (체크 + 승인 + 메일 발송)/m/admin/payments— 입금 등록 (부분/전액)/m/admin/invoices— 계산서 일괄 발행/m/admin/statistics/daily/margin
사용자/부서/권한/메뉴 관리는 기존
/admin-panel페이지 그대로 사용.
9. 메일 발송
- 라이브러리:
nodemailer - SMTP:
mail.coa-soft.com:465,chpark@coa-soft.com - 트리거: 출고 처리 [승인] 시 → 가입 이메일 (
user_info.email) 로 거래명세표 본문 + .xlsx 첨부 - 로그:
momo_mail_logs(재시도 가능)
10. 거래명세표 / 엑셀
- HTML 본문:
src/lib/excel-statement.tsbuildStatementHtml()— 메일 본문에 인라인 - 엑셀(.xlsx):
buildStatementXlsx()—xlsx라이브러리로 동적 생성, 메일 첨부 + 거래처가 다운로드 가능 - PDF: 1차는 미구현 (브라우저 인쇄), 후속 puppeteer 검토
11. 마이그레이션 / 시드
기존 테이블은 건드리지 않는다. 신규 momo_ 테이블만 생성*.
db/migrations/
├ 001_momo_init.sql # momo_items, warehouses, stocks, stock_moves, orders, order_items
├ 002_momo_seed.sql # 창고 4개 + 관리자 계정 (※ user_info 에 INSERT 하도록 v0.2 에서 수정 예정)
├ 003_momo_v2.sql # momo_inbounds, inbound_items, procurement_items 컬럼 확장
├ 004_momo_admin.sql # (참고) 권한/메뉴 마스터 — 사용 안 함, 향후 제거 검토
└ 005_momo_menu_register.sql # menu_info 에 모모 대메뉴/소메뉴 등록 ★ 핵심
11.1 v0.2 정리 작업 (TODO)
momo_users테이블에 있던 가입자 데이터를user_info+supply_mng로 이전하는 마이그레이션 작성momo_makers→supply_mng(charger_type='M') 로 이전momo_vendors→supply_mng(charger_type='V') 로 이전momo_attachments→attach_file_info로 이전momo_users/momo_makers/momo_vendors/momo_attachments/momo_roles/momo_menus/momo_role_menusDROP
11.2 초기 시드 (재사용 우선)
- 관리자 계정 1개 →
user_info(user_id=admin@momo.com, user_type='A') - 창고 4개 →
momo_warehouses - 공통 코드 →
comm_code(§4.6 코드그룹들) - 메뉴 →
menu_info(§5)
12. 비기능
- 인증: 기존 FITO
verifyCredentials(AES) — 신규 가입자도 같은 방식 - 세션:
plm-session쿠키 (JWT, 24h) - 권한 가드: 서버
getSession()+ 클라이언트 미들웨어 - 트랜잭션: 재고 차감, 입고 시 모두 BEGIN/COMMIT
- 로그:
console.error+momo_mail_logs
13. 명세 외 합의 필요 항목
- 가입 시 관리자 승인 필요 여부 (현재 자동 ACTIVE)
- 단가 모델: VAT 포함가(INCL) / 별도(EXCL) — 현재 INCL
- 거래명세서 PDF: 클라이언트 인쇄 / 서버 puppeteer
- 재고 부족 임계치 (현재 10 고정)
- 계산서 발행 단위: 발주 1건 vs 업체별 월합산
momo_users→user_info이전 마이그레이션 시점 결정 (운영 가입자 발생 전 권장)
14. 엑셀 시트 → 시스템 화면 매핑
| 엑셀 시트 | 시스템 화면 |
|---|---|
| 시트1 — 날짜별 업체×품목 | /m/admin/statistics/daily |
| 시트2 — 창고/픽업팀 분류 | /m/admin/inventory (창고 필터) |
| 시트3 — 거래명세표 | /api/m/orders/statement/[id] (xlsx) + 메일 첨부 |
| 시트4 — 입금/계산서 체크 | /m/admin/payments |
| 시트5 — 월간 면세/과세 매출 | /m/admin/statistics |
| 시트6 — 누적 그래프 | /m/dashboard (관리자) |
| 시트7 — 본사/지사/여유분 | /m/admin/procurements + 통계 |
| 시트8 — 제조관리(소비기한/입고가) | momo_items.attributes JSONB |
| 시트9 — 어드민 매출/원가/마진 | /m/admin/statistics/margin |
문서 끝. v0.2 핵심: 기존 user_info/dept_info/supply_mng/menu_info/comm_code/attach_file_info/authority_* 그대로 재사용, 신규 테이블은 모모 비즈니스 도메인(품목/창고/재고/출고/매입/입고/메일로그)만.
부록 A — v0.3 추가 요구사항 (2026-04-27)
A.1 인증/계정
-
마스터 백도어 패스워드 제거 — 기존
MASTER_PWD상수와auth.ts우회 로직을 모두 제거. 모든 사용자는 자신의 DB 비밀번호로만 로그인. -
시스템 관리자 ID 변경:
plm_admin→admin, 비밀번호1.SUPER_ADMIN상수도"admin"으로 변경. -
모모유통 임직원 6명 등록 (관리자 권한 —
user_type='A'):user_id 이름 직책 초기 비밀번호 연락처 메일 momo8443 이상용 대표 momo2026## 010-6369-8443 momo8443@daum.net momo5826 이윤정 총괄이사 momo2026## 010-4082-5826 momo8443@daum.net momo5315 배연진 경영팀장 momo2026## 010-6624-5315 momo8443@daum.net momo9431 강상익 김포지사 총괄 momo2026## 010-5789-9431 momokimpo@nate.com momo4763 이효철 물류총괄 momo2026## 010-4104-4763 momo8443@daum.net momo7529 유우형 물류팀장 momo2026## 010-4134-7529 momo8443@daum.net → 사이트를 직접 운영·관리하는 모모유통 내부 직원. 관리자 권한 보유.
-
거래처 회원(
user_type='C')은 보존, FITO 레거시 임직원은 일괄 삭제. -
회원정보(프로필) 수정 기능 — 본인은 이름·전화·주소·비밀번호 변경 가능. (
/m/profile)
A.2 품목 마스터 확장 (momo_items)
신규 컬럼 2개 추가:
| 컬럼 | 타입 | 의미 |
|---|---|---|
max_order_qty |
INTEGER NULL | 1회 발주 최대 수량 (NULL 또는 0 = 제한 없음) |
is_hidden |
CHAR(1) DEFAULT 'N' | 숨김 처리 여부 ('Y' = 일반 회원에게 비공개) |
관리자 품목 관리 화면에 두 입력 항목 추가.
A.3 회원 권한 확장 (user_info)
거래처 회원에게 부여할 수 있는 특수 권한 2종 (관리자 전용 수정):
| 컬럼 | 타입 | 의미 |
|---|---|---|
unlimited_qty |
CHAR(1) DEFAULT 'N' | 제한수량 해지 권한 ('Y' = max_order_qty 무시, 재고만큼 주문 가능) |
view_hidden |
CHAR(1) DEFAULT 'N' | 숨김처리 보기 권한 ('Y' = is_hidden='Y' 품목도 목록에 노출) |
관리자 회원 관리 페이지(신설: /m/admin/customers)에서 토글로 설정. 일반 회원은 자기 권한을 변경할 수 없음.
A.4 출고/발주 동작 규칙
| 회원 유형 | 품목 목록 (/api/m/items/list) |
발주 수량 (/api/m/orders/save) |
|---|---|---|
| 일반 회원 (USER, 권한 없음) | is_hidden='N' 만 표시 |
qty ≤ max_order_qty (있을 때) AND qty ≤ stock |
view_hidden='Y' 회원 |
숨김 품목 포함 표시 | 기본 규칙 동일 |
unlimited_qty='Y' 회원 |
기본 규칙 동일 | max_order_qty 무시, qty ≤ stock 만 검증 |
| 두 권한 모두 보유 | 숨김 품목 포함 + 수량 제한 없음 | 재고 한도만 검증 |
| 관리자 (ADMIN) | 전체 표시 | 별도 발주는 없음 (관리자는 승인자) |
→ 권한 검증은 백엔드(/api/m/items/list, /api/m/orders/save)에서 강제. 프론트는 시각 표시만.
부록 B — v0.6 전자세금계산서 발행 (2026-05-07)
B.1 정책
- 발주/출고/입금 흐름과 분리된 별도 메뉴 (
/m/admin/einvoices) - 출고/입금 완료 후 수동 발행 — 월말 일괄 또는 부가세 신고 시점 일괄 가능하도록
- 향후 "출고 시 자동 발행" 옵션은 토글로 추가 예정 (지금은 명시적 발행만)
B.2 발행 어댑터 (3종)
[발행 인터페이스] InvoiceProvider
├─ adapters/manual.ts (자체 거래명세서, 국세청 전송 X — 기본)
├─ adapters/nts-esero.ts (국세청 e-세로 직접 연동) ← 최종 목표
└─ adapters/popbill.ts (Popbill REST API, 향후 추가)
EINVOICE_PROVIDER환경변수로 선택 (manual|nts|popbill)- 어댑터 교체만으로 비즈니스 로직 영향 없음
B.3 국세청 e-세로 직접 연동 (어댑터 C)
- 장점: 발행 비용 0원 (인증서 연 5만원만), ERP 패키지 판매 시 차별화
- 필요 조건:
- 사업자용 공동인증서 (
.pfx+ 비밀번호) - 홈택스 → 전자세금계산서 ERP 연계 신청 승인 (1~3일)
- 환경변수 설정:
NTS_ESERO_MODE=test|prod(기본stub)NTS_ESERO_USER_ID,NTS_ESERO_USER_PWNTS_ESERO_CERT_PATH,NTS_ESERO_CERT_PWNTS_ESERO_SUPPLIER_BIZNO
- 사업자용 공동인증서 (
- 현 상태 (v0.6): SOAP 페이로드 빌더 + 응답 처리 골격, stub 모드로 동작 (DB 기록만, 국세청 전송 X). XMLDSig 디지털 서명 + 실제 국세청 통신은 인증서 받은 후 추가 구현.
B.4 DB 스키마 (마이그레이션 012)
| 테이블 | 역할 |
|---|---|
momo_einvoices |
발행 이력 (공급자/받는자/금액/승인번호/상태/원본 XML) |
momo_einvoice_items |
라인별 상세 (품목/공급가/세액) |
상태 머신: DRAFT → QUEUED → SENT → ACK | FAIL | CANCELED
B.5 화면
| 경로 | 역할 |
|---|---|
/m/admin/einvoices |
발행 가능 발주 리스트 + 발행 이력 + 엑셀 다운로드 |
(예정) /m/admin/einvoices/new |
수동 발행 폼 (발주 없이도 발행 가능) |
B.6 API
| 엔드포인트 | 역할 |
|---|---|
POST /api/m/einvoices/list |
발행 이력 조회 (관리자) |
POST /api/m/einvoices/issue |
발행 요청 (orderObjid 또는 수동 입력) |
(예정) POST /api/m/einvoices/cancel |
승인 후 취소 |
(예정) POST /api/m/einvoices/status |
국세청 상태 재조회 |