fa91c805fc
- DB: momo_* 테이블 12종 (users/items/makers/warehouses/stocks/stock_moves/orders/order_items/procurements/vendors/attachments/mail_logs) + 시드 - 인증: 랜딩(/) + 회원가입(/signup, bcrypt) + 로그인(MOMO/FITO 자동 분기) + /api/auth/mobile-login(JWT 토큰) - 세션: 쿠키 + Authorization Bearer 동시 지원 (모바일 앱용) - /m/* 레이아웃: 좌측 사이드바 + 헤더, 역할별 메뉴 분기 - USER 화면: 품목 검색(이미지/재고/단가) + 장바구니 + 발주 요청 + 본인 이력 + 대시보드 - ADMIN 화면: 품목/창고/재고/매입입고/발주승인/회원관리/월간 매출 통계 + 대시보드(14일 그래프, 재고 부족, 승인 대기) - 발주 승인: 트랜잭션으로 재고 차감 + 거래명세표 HTML 메일 본문 + xlsx 첨부 발송 (nodemailer) - 면세 자동 판정: 품목명 'M' 접두 시 is_tax_free=Y, 합계는 면세/과세 분리 집계 - 미들웨어: /, /signup, /api/auth/signup, /api/auth/mobile-login 공개 - 도구: scripts/migrate-momo.mjs (npm run migrate:momo), .env.momo.example - 문서: docs/MOMO_DISTRIBUTION_SPEC.md, docs/proposal.html (고객용 HTML 제안서) - 별도 RN 앱(d:/momo-mobile) 스캐폴드 작성 (Expo + EAS APK 빌드) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
210 lines
8.0 KiB
PL/PgSQL
210 lines
8.0 KiB
PL/PgSQL
-- ============================================================================
|
|
-- 모모유통 (MOMO) 유통관리 시스템 — 초기 스키마
|
|
-- 기존 FITO 테이블과 분리하기 위해 momo_ 접두사 사용
|
|
-- 실행: psql $DATABASE_URL -f db/migrations/001_momo_init.sql
|
|
-- ============================================================================
|
|
|
|
BEGIN;
|
|
|
|
-- 1. 회원 (대리점 + 관리자) ----------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_users (
|
|
objid TEXT PRIMARY KEY,
|
|
email VARCHAR(200) NOT NULL UNIQUE,
|
|
password_hash VARCHAR(200) NOT NULL,
|
|
company_name VARCHAR(200) NOT NULL,
|
|
ceo_name VARCHAR(100),
|
|
biz_no VARCHAR(20),
|
|
phone VARCHAR(50),
|
|
address VARCHAR(300),
|
|
role VARCHAR(20) NOT NULL DEFAULT 'USER', -- USER | ADMIN
|
|
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', -- ACTIVE | LOCKED | LEFT
|
|
is_del CHAR(1) DEFAULT 'N',
|
|
regdate TIMESTAMP DEFAULT NOW(),
|
|
regid TEXT,
|
|
update_date TIMESTAMP,
|
|
update_id TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_users_email ON momo_users(email);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_users_role ON momo_users(role, status);
|
|
|
|
-- 2. 제조사 ------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_makers (
|
|
objid TEXT PRIMARY KEY,
|
|
maker_name VARCHAR(200) NOT NULL,
|
|
contact VARCHAR(100),
|
|
phone VARCHAR(50),
|
|
memo TEXT,
|
|
is_del CHAR(1) DEFAULT 'N',
|
|
regdate TIMESTAMP DEFAULT NOW(),
|
|
regid TEXT
|
|
);
|
|
|
|
-- 3. 품목 --------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_items (
|
|
objid TEXT PRIMARY KEY,
|
|
item_code VARCHAR(50) NOT NULL UNIQUE,
|
|
item_name VARCHAR(200) NOT NULL,
|
|
item_detail TEXT,
|
|
maker_objid TEXT,
|
|
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', -- 'Y' = 면세 (M 접두 품목)
|
|
image_url TEXT,
|
|
attributes JSONB,
|
|
status VARCHAR(20) DEFAULT 'ACTIVE',
|
|
is_del CHAR(1) DEFAULT 'N',
|
|
regdate TIMESTAMP DEFAULT NOW(),
|
|
regid TEXT,
|
|
update_date TIMESTAMP,
|
|
update_id TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_items_status ON momo_items(status, is_del);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_items_taxfree ON momo_items(is_tax_free);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_items_name ON momo_items(item_name);
|
|
|
|
-- 4. 창고 --------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_warehouses (
|
|
objid TEXT PRIMARY KEY,
|
|
wh_code VARCHAR(50) NOT NULL UNIQUE,
|
|
wh_name VARCHAR(200) NOT NULL,
|
|
location VARCHAR(200),
|
|
wh_type VARCHAR(20) DEFAULT 'STOCK', -- STOCK | PICKUP_TEAM | MARKET | DELIVERY
|
|
is_del CHAR(1) DEFAULT 'N',
|
|
regdate TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
-- 5. 재고 (창고×품목) --------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_stocks (
|
|
objid TEXT PRIMARY KEY,
|
|
wh_objid TEXT NOT NULL,
|
|
item_objid TEXT NOT NULL,
|
|
qty NUMERIC(15,2) NOT NULL DEFAULT 0,
|
|
update_date TIMESTAMP DEFAULT NOW(),
|
|
UNIQUE(wh_objid, item_objid)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_stocks_item ON momo_stocks(item_objid);
|
|
|
|
-- 6. 입출고 이력 -------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_stock_moves (
|
|
objid TEXT PRIMARY KEY,
|
|
wh_objid TEXT NOT NULL,
|
|
item_objid TEXT NOT NULL,
|
|
move_type VARCHAR(20) NOT NULL, -- IN | OUT | ADJ | TRANSFER
|
|
qty NUMERIC(15,2) NOT NULL,
|
|
ref_type VARCHAR(20), -- ORDER | PROCUREMENT | MANUAL
|
|
ref_objid TEXT,
|
|
memo TEXT,
|
|
regdate TIMESTAMP DEFAULT NOW(),
|
|
regid TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_moves_item ON momo_stock_moves(item_objid, regdate);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_moves_ref ON momo_stock_moves(ref_type, ref_objid);
|
|
|
|
-- 7. 발주서 (대리점 → 모모유통) ---------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_orders (
|
|
objid TEXT PRIMARY KEY,
|
|
order_no VARCHAR(50) NOT NULL UNIQUE,
|
|
customer_objid TEXT NOT NULL,
|
|
order_date DATE NOT NULL DEFAULT CURRENT_DATE,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'REQUESTED',
|
|
approve_user TEXT,
|
|
approve_date TIMESTAMP,
|
|
ship_date TIMESTAMP,
|
|
invoice_no VARCHAR(50),
|
|
invoice_date DATE,
|
|
total_supply NUMERIC(15,2) DEFAULT 0,
|
|
total_vat NUMERIC(15,2) DEFAULT 0,
|
|
total_amount NUMERIC(15,2) DEFAULT 0,
|
|
total_taxfree NUMERIC(15,2) DEFAULT 0,
|
|
total_taxable NUMERIC(15,2) DEFAULT 0,
|
|
paid_amount NUMERIC(15,2) DEFAULT 0,
|
|
paid_date DATE,
|
|
memo TEXT,
|
|
is_del CHAR(1) DEFAULT 'N',
|
|
regdate TIMESTAMP DEFAULT NOW(),
|
|
regid TEXT,
|
|
update_date TIMESTAMP,
|
|
update_id TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_orders_cust ON momo_orders(customer_objid, status);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_orders_status ON momo_orders(status, order_date);
|
|
|
|
CREATE TABLE IF NOT EXISTS momo_order_items (
|
|
objid TEXT PRIMARY KEY,
|
|
order_objid TEXT NOT NULL,
|
|
item_objid TEXT NOT NULL,
|
|
item_name_snap VARCHAR(200),
|
|
unit_price NUMERIC(15,2) NOT NULL,
|
|
qty NUMERIC(15,2) NOT NULL,
|
|
is_tax_free CHAR(1) NOT NULL DEFAULT 'N',
|
|
supply_amount NUMERIC(15,2) NOT NULL DEFAULT 0,
|
|
vat_amount NUMERIC(15,2) NOT NULL DEFAULT 0,
|
|
total_amount NUMERIC(15,2) NOT NULL DEFAULT 0,
|
|
seq INT,
|
|
remark VARCHAR(200)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_order_items ON momo_order_items(order_objid);
|
|
|
|
-- 8. 매입처 / 매입발주 -------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_vendors (
|
|
objid TEXT PRIMARY KEY,
|
|
vendor_name VARCHAR(200) NOT NULL,
|
|
contact VARCHAR(100),
|
|
phone VARCHAR(50),
|
|
biz_no VARCHAR(20),
|
|
is_del CHAR(1) DEFAULT 'N'
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS momo_procurements (
|
|
objid TEXT PRIMARY KEY,
|
|
proc_no VARCHAR(50) NOT NULL UNIQUE,
|
|
vendor_objid TEXT,
|
|
proc_date DATE NOT NULL DEFAULT CURRENT_DATE,
|
|
status VARCHAR(20) DEFAULT 'OPEN',
|
|
total_amount NUMERIC(15,2) DEFAULT 0,
|
|
memo TEXT,
|
|
is_del CHAR(1) DEFAULT 'N',
|
|
regdate TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS momo_procurement_items (
|
|
objid TEXT PRIMARY KEY,
|
|
proc_objid TEXT NOT NULL,
|
|
item_objid TEXT NOT NULL,
|
|
cost_price NUMERIC(15,2) NOT NULL,
|
|
qty NUMERIC(15,2) NOT NULL,
|
|
total_amount NUMERIC(15,2) NOT NULL,
|
|
received_qty NUMERIC(15,2) DEFAULT 0
|
|
);
|
|
|
|
-- 9. 첨부 / 메일 로그 --------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS momo_attachments (
|
|
objid TEXT PRIMARY KEY,
|
|
ref_type VARCHAR(20) NOT NULL,
|
|
ref_objid TEXT NOT NULL,
|
|
file_name VARCHAR(300) NOT NULL,
|
|
file_path TEXT NOT NULL,
|
|
mime_type VARCHAR(100),
|
|
file_size BIGINT,
|
|
regdate TIMESTAMP DEFAULT NOW(),
|
|
regid TEXT
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_attach_ref ON momo_attachments(ref_type, ref_objid);
|
|
|
|
CREATE TABLE IF NOT EXISTS momo_mail_logs (
|
|
objid TEXT PRIMARY KEY,
|
|
to_email VARCHAR(200) NOT NULL,
|
|
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()
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_momo_maillogs_ref ON momo_mail_logs(ref_type, ref_objid);
|
|
|
|
COMMIT;
|