-- 자재 비교 및 발주 추적 시스템
-- 실행일: 2025.01.22

-- ================================
-- 1. materials 테이블에 해시 컬럼 추가
-- ================================

-- 자재 비교를 위한 해시 컬럼 추가
ALTER TABLE materials ADD COLUMN IF NOT EXISTS material_hash VARCHAR(32);
ALTER TABLE materials ADD COLUMN IF NOT EXISTS normalized_description TEXT;

-- 해시 인덱스 추가 (성능 최적화)
CREATE INDEX IF NOT EXISTS idx_materials_hash ON materials(material_hash);
CREATE INDEX IF NOT EXISTS idx_materials_file_hash ON materials(file_id, material_hash);

-- ================================
-- 2. 자재 비교 결과 저장 테이블
-- ================================

CREATE TABLE IF NOT EXISTS material_revisions_comparison (
    id SERIAL PRIMARY KEY,
    
    -- 비교 기본 정보
    job_no VARCHAR(50) NOT NULL,
    current_revision VARCHAR(20) NOT NULL,
    previous_revision VARCHAR(20) NOT NULL,
    current_file_id INTEGER NOT NULL,
    previous_file_id INTEGER NOT NULL,
    
    -- 비교 결과 요약
    total_current_items INTEGER DEFAULT 0,
    total_previous_items INTEGER DEFAULT 0,
    new_items_count INTEGER DEFAULT 0,
    modified_items_count INTEGER DEFAULT 0,
    removed_items_count INTEGER DEFAULT 0,
    unchanged_items_count INTEGER DEFAULT 0,
    
    -- 상세 결과 (JSON)
    comparison_details JSONB,
    
    -- 관리 정보
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by VARCHAR(100),
    
    -- 외래키
    FOREIGN KEY (current_file_id) REFERENCES files(id),
    FOREIGN KEY (previous_file_id) REFERENCES files(id),
    
    -- 유니크 제약 (같은 비교는 한 번만)
    UNIQUE(job_no, current_revision, previous_revision)
);

-- ================================
-- 3. 개별 자재 비교 상세 테이블
-- ================================

CREATE TABLE IF NOT EXISTS material_comparison_details (
    id SERIAL PRIMARY KEY,
    
    comparison_id INTEGER NOT NULL,
    material_hash VARCHAR(32) NOT NULL,
    
    -- 비교 타입
    change_type VARCHAR(20) NOT NULL, -- 'NEW', 'MODIFIED', 'REMOVED', 'UNCHANGED'
    
    -- 자재 정보
    description TEXT NOT NULL,
    size_spec VARCHAR(100),
    material_grade VARCHAR(100),
    
    -- 수량 비교
    previous_quantity DECIMAL(10,3) DEFAULT 0,
    current_quantity DECIMAL(10,3) DEFAULT 0,
    quantity_diff DECIMAL(10,3) DEFAULT 0,
    
    -- 추가 구매 필요량 (핵심!)
    additional_purchase_needed DECIMAL(10,3) DEFAULT 0,
    
    -- 분류 정보
    classified_category VARCHAR(50),
    classification_confidence DECIMAL(3,2),
    
    -- 관리 정보
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- 외래키
    FOREIGN KEY (comparison_id) REFERENCES material_revisions_comparison(id) ON DELETE CASCADE
);

-- ================================
-- 4. 발주 추적 테이블 (실제 발주 관리)
-- ================================

CREATE TABLE IF NOT EXISTS material_purchase_tracking (
    id SERIAL PRIMARY KEY,
    
    -- 연결 정보
    job_no VARCHAR(50) NOT NULL,
    material_hash VARCHAR(32) NOT NULL,
    revision VARCHAR(20) NOT NULL,
    
    -- 자재 정보
    description TEXT NOT NULL,
    size_spec VARCHAR(100),
    unit VARCHAR(10) DEFAULT 'EA',
    
    -- 수량 정보
    bom_quantity DECIMAL(10,3) NOT NULL,           -- BOM상 필요 수량
    safety_margin DECIMAL(3,2) DEFAULT 1.10,       -- 여유율 (10%)
    calculated_quantity DECIMAL(10,3) NOT NULL,    -- 계산된 구매 수량
    
    -- 발주 상태
    purchase_status VARCHAR(20) DEFAULT 'PENDING', -- 'PENDING', 'CONFIRMED', 'ORDERED', 'RECEIVED'
    confirmed_quantity DECIMAL(10,3) DEFAULT 0,    -- 확정된 발주 수량
    ordered_quantity DECIMAL(10,3) DEFAULT 0,      -- 실제 주문 수량
    received_quantity DECIMAL(10,3) DEFAULT 0,     -- 입고 수량
    
    -- 발주 정보
    purchase_order_no VARCHAR(100),
    supplier_name VARCHAR(200),
    unit_price DECIMAL(10,2),
    total_price DECIMAL(12,2),
    order_date DATE,
    delivery_date DATE,
    
    -- 관리 정보
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    confirmed_by VARCHAR(100),
    confirmed_at TIMESTAMP,
    
    -- 외래키
    FOREIGN KEY (job_no) REFERENCES jobs(job_no),
    
    -- 유니크 제약
    UNIQUE(job_no, material_hash, revision)
);

-- ================================
-- 5. 누적 재고 현황 뷰
-- ================================

CREATE OR REPLACE VIEW material_inventory_status AS
SELECT 
    mpt.job_no,
    mpt.material_hash,
    mpt.description,
    mpt.size_spec,
    mpt.unit,
    
    -- 누적 수량
    SUM(mpt.confirmed_quantity) as total_confirmed,
    SUM(mpt.ordered_quantity) as total_ordered,
    SUM(mpt.received_quantity) as total_received,
    
    -- 현재 가용 재고
    SUM(mpt.received_quantity) as available_stock,
    
    -- 최신 리비전 정보
    MAX(mpt.revision) as latest_revision,
    MAX(mpt.updated_at) as last_updated
    
FROM material_purchase_tracking mpt
WHERE mpt.purchase_status != 'CANCELLED'
GROUP BY mpt.job_no, mpt.material_hash, mpt.description, mpt.size_spec, mpt.unit;

-- ================================
-- 6. 인덱스 생성
-- ================================

-- material_revisions_comparison 인덱스
CREATE INDEX IF NOT EXISTS idx_material_revisions_job ON material_revisions_comparison(job_no);
CREATE INDEX IF NOT EXISTS idx_material_revisions_current ON material_revisions_comparison(current_revision);

-- material_comparison_details 인덱스
CREATE INDEX IF NOT EXISTS idx_material_comparison_hash ON material_comparison_details(material_hash);
CREATE INDEX IF NOT EXISTS idx_material_comparison_type ON material_comparison_details(change_type);

-- material_purchase_tracking 인덱스
CREATE INDEX IF NOT EXISTS idx_purchase_tracking_job_hash ON material_purchase_tracking(job_no, material_hash);
CREATE INDEX IF NOT EXISTS idx_purchase_tracking_status ON material_purchase_tracking(purchase_status);
CREATE INDEX IF NOT EXISTS idx_purchase_tracking_revision ON material_purchase_tracking(revision);

-- ================================
-- 7. 해시 생성 함수 (PostgreSQL)
-- ================================

CREATE OR REPLACE FUNCTION generate_material_hash(
    description TEXT,
    size_spec TEXT DEFAULT '',
    material_grade TEXT DEFAULT ''
) RETURNS VARCHAR(32) AS $$
BEGIN
    -- 정규화: 대소문자 통일, 공백 정리
    description := UPPER(TRIM(REGEXP_REPLACE(description, '\s+', ' ', 'g')));
    size_spec := UPPER(TRIM(COALESCE(size_spec, '')));
    material_grade := UPPER(TRIM(COALESCE(material_grade, '')));
    
    -- MD5 해시 생성 (32자리)
    RETURN MD5(description || '|' || size_spec || '|' || material_grade);
END;
$$ LANGUAGE plpgsql;

-- ================================
-- 8. 기존 데이터에 해시 생성 (배치 처리)
-- ================================

-- 기존 materials 데이터에 해시 추가
UPDATE materials 
SET 
    material_hash = generate_material_hash(original_description, size_spec, material_grade),
    normalized_description = UPPER(TRIM(REGEXP_REPLACE(original_description, '\s+', ' ', 'g')))
WHERE material_hash IS NULL;

-- ================================
-- 9. 트리거 생성 (자동 해시 생성)
-- ================================

CREATE OR REPLACE FUNCTION auto_generate_material_hash()
RETURNS TRIGGER AS $$
BEGIN
    -- 새로 삽입되거나 업데이트될 때 자동으로 해시 생성
    NEW.material_hash := generate_material_hash(
        NEW.original_description, 
        NEW.size_spec, 
        NEW.material_grade
    );
    NEW.normalized_description := UPPER(TRIM(REGEXP_REPLACE(NEW.original_description, '\s+', ' ', 'g')));
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_auto_material_hash
    BEFORE INSERT OR UPDATE ON materials
    FOR EACH ROW
    EXECUTE FUNCTION auto_generate_material_hash();

-- ================================
-- 10. 완료 메시지
-- ================================

SELECT 'Material comparison and purchase tracking system created successfully!' as status; 