# 모모유통 — 도매 유통 관리 시스템 개발 스펙 > **버전**: 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 via `pg` · JWT 세션 · Zustand · TanStack Table · SweetAlert2 --- ## 0. 요약 (TL;DR) 모모유통은 **대형 도매 유통 업체**다. 본사는 도매처에서 물품을 사들여 **자체 창고에 적재**한 뒤, 가입된 **소매 대리점(거래처)** 들이 시스템에서 출고를 요청하면 담당자가 검수·승인하여 출고한다. - **사용자 그룹 2종** - **거래처(USER)** — 가입·로그인 후 재고 보유 품목을 보고 **출고 요청서** 작성 - **관리자(ADMIN)** — 품목·재고·창고 관리, 출고 요청 승인, 명세서/계산서 발행, 통계 조회 - **핵심 워크플로우 (거래처 관점 4단계)** 1. 출고 요청 (거래처) → status `REQUESTED` 2. 출고 처리 (담당자 승인 + 메일+엑셀 자동 발송) → status `APPROVED` (= 출고 완료) 3. 입금 확인 (담당자 등록) → status `PAID` (= 입금 완료) 4. 월말 계산서 발행 (일괄) → status `INVOICED` (= 계산서 발행 완료, 최종) - **면세/과세 구분**: 품목명 접두어 `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_info` INSERT** - `user_id` = 이메일 - `user_password` = 기존 FITO `EncryptUtil.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.objid - `doc_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_*`)** ```sql -- 품목 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.ts` `buildStatementHtml()` — 메일 본문에 인라인 - 엑셀(.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_menus` DROP ### 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'` = 일반 회원에게 비공개) | 관리자 [품목 관리](src/app/(main)/m/admin/items/page.tsx) 화면에 두 입력 항목 추가. ### 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`)에서 강제. 프론트는 시각 표시만.