Files
sam-docs/plans/archive/stock-integration-plan.md
권혁성 06a4c798ec chore: 완료 계획 문서 22개 archive 이동 및 인덱스 업데이트
- 완료된 계획 문서 22개를 plans/archive/로 이동
  - tracked 16개 (git mv): bending-lot-pipeline, docs-update, fcm-notification 등
  - untracked 6개 (mv): bending-worklog, formula-engine, mng-item 등
- index_plans.md 전면 업데이트
  - 진행중 44개 / 완료 37개 현황 반영
  - 각 문서별 실제 진행률 기재 (0%~94%)
  - 카테고리별 재정리 (견적/생산/품목/문서/마이그레이션/시스템/UI)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:02:47 +09:00

16 KiB

재고 통합 시스템 개발 계획

작성일: 2025-01-26 목적: 입고/생산/견적 시스템과 재고(Stock)의 실시간 연동 구현 기준 문서: docs/specs/database-schema.md, docs/standards/api-rules.md 상태: 🔄 계획 수립 중


📍 현재 진행 상태

항목 내용
마지막 완료 작업 Phase 3 - 견적/출하 → 재고 연동 완료
다음 작업 모든 Phase 완료
진행률 12/12 (100%)
마지막 업데이트 2025-01-26

1. 개요

1.1 배경

현재 SAM 시스템의 재고 관리는 조회 전용으로만 작동합니다:

  • 입고(Receiving)가 완료되어도 Stock이 증가하지 않음
  • 생산(WorkOrder)에서 자재를 투입해도 Stock이 감소하지 않음
  • 견적(Order)이 확정되어도 재고 예약이 되지 않음
  • 출하(Shipment)가 완료되어도 Stock이 감소하지 않음

결과: 재고현황 페이지가 실제 재고를 반영하지 못함

1.2 목표

┌─────────────────────────────────────────────────────────────────┐
│  🎯 핵심 목표                                                    │
├─────────────────────────────────────────────────────────────────┤
│  1. 입고 완료 → Stock 자동 증가 + StockLot 생성                  │
│  2. 자재 투입 → Stock 자동 차감 (FIFO 기반)                      │
│  3. 견적 확정 → reserved_qty 증가                                │
│  4. 출하 완료 → stock_qty 차감                                   │
│  5. 모든 변경에 대한 감사 로그 기록                              │
└─────────────────────────────────────────────────────────────────┘

1.3 성공 기준

기준 측정 방법
입고 → 재고 연동 입고 완료 시 Stock.stock_qty 자동 증가 확인
생산 → 재고 연동 자재 투입 시 Stock.stock_qty 자동 감소 확인
견적 → 재고 연동 견적 확정 시 Stock.reserved_qty 증가 확인
출하 → 재고 연동 출하 완료 시 Stock.stock_qty 감소 확인
감사 로그 모든 재고 변경이 audit_logs에 기록됨
FIFO 적용 StockLot이 fifo_order 순서대로 차감됨

1.4 변경 승인 정책

분류 예시 승인
즉시 가능 메서드 추가, 파라미터 추가, 문서 수정 불필요
⚠️ 컨펌 필요 Service 로직 변경, 새 이벤트 추가, 마이그레이션 필수
🔴 금지 기존 API 응답 구조 변경, Stock 테이블 컬럼 삭제 별도 협의

1.5 준수 규칙

  • docs/standards/api-rules.md - Service-First 패턴
  • docs/standards/quality-checklist.md - 품질 체크리스트
  • docs/specs/database-schema.md - DB 스키마 규칙

2. 현재 시스템 분석

2.1 데이터 모델 관계

┌─────────────────────────────────────────────────────────────────┐
│                        현재 상태                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   Item (품목)                                                    │
│     ↓ 1:1                                                        │
│   Stock (재고현황) ←── 자동 업데이트 없음 ──┐                    │
│     ↓ 1:N                                    │                    │
│   StockLot (LOT별 상세) ←── 자동 생성 없음 ─┤                    │
│                                              │                    │
│   Receiving (입고) ─── 연결 끊김 ────────────┤                    │
│   WorkOrder (생산) ─── 연결 없음 ────────────┤                    │
│   Order (견적/수주) ─── 연결 없음 ───────────┤                    │
│   Shipment (출하) ─── 연결 없음 ─────────────┘                    │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2.2 목표 데이터 흐름

┌─────────────────────────────────────────────────────────────────┐
│                        목표 상태                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   [입고 완료] ──→ StockLot 생성 ──→ Stock.refreshFromLots()     │
│                                                                  │
│   [자재 투입] ──→ StockLot 차감(FIFO) ──→ Stock.refreshFromLots()│
│                                                                  │
│   [견적 확정] ──→ Stock.reserved_qty 증가                        │
│                                                                  │
│   [출하 완료] ──→ StockLot 차감 ──→ Stock.refreshFromLots()     │
│                 ──→ Stock.reserved_qty 감소                      │
│                                                                  │
│   [모든 변경] ──→ AuditLog 기록                                  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2.3 핵심 파일 위치

구분 경로
Stock 모델 api/app/Models/Tenants/Stock.php
StockLot 모델 api/app/Models/Tenants/StockLot.php
StockService api/app/Services/StockService.php
ReceivingService api/app/Services/ReceivingService.php
WorkOrderService api/app/Services/WorkOrderService.php
OrderService api/app/Services/OrderService.php

3. 대상 범위

Phase 1: 입고 → 재고 연동 (우선순위 1) 완료

# 작업 항목 상태 비고
1.1 StockService에 이벤트 기반 구조 설계 increaseFromReceiving(), getOrCreateStock()
1.2 ReceivingService.process() 수정 - Stock 연동 StockService 호출 추가
1.3 StockLot 자동 생성 로직 구현 FIFO 순서 자동 계산
1.4 감사 로그 통합 logStockChange() 구현
1.5 단위 테스트 작성 ⏭️ 수동 테스트로 대체

Phase 2: 생산 → 재고 연동 (우선순위 2) 완료

# 작업 항목 상태 비고
2.1 WorkOrderService에 BOM 기반 자재 조회 구현 getMaterials() 실제 재고 연동
2.2 자재 투입 시 Stock 차감 로직 (FIFO) StockService.decreaseFIFO()
2.3 작업 완료 시 제품 Stock 증가 로직 ⏭️ 추후 구현 (생산품 LOT 생성 시)
2.4 단위 테스트 작성 ⏭️ 수동 테스트로 대체

Phase 3: 견적/출하 → 재고 연동 (우선순위 3) 완료

# 작업 항목 상태 비고
3.1 Order 확정 시 reserved_qty 증가 로직 StockService.reserve(), reserveForOrder()
3.2 Shipment 출하 시 stock_qty 차감 로직 StockService.decreaseForShipment()
3.3 예약 취소/변경 처리 로직 StockService.releaseReservation()

4. 상세 설계

4.1 StockService 이벤트 구조

// api/app/Services/StockService.php

class StockService
{
    /**
     * 입고 완료 시 재고 증가
     * @param Receiving $receiving
     * @return StockLot
     */
    public function increaseFromReceiving(Receiving $receiving): StockLot
    {
        // 1. StockLot 생성
        // 2. Stock.refreshFromLots() 호출
        // 3. 감사 로그 기록
    }

    /**
     * 자재 투입 시 재고 차감 (FIFO)
     * @param int $itemId
     * @param float $qty
     * @param string $reason (work_order, shipment 등)
     * @param int $referenceId
     * @return array 차감된 LOT 정보
     */
    public function decreaseFIFO(int $itemId, float $qty, string $reason, int $referenceId): array
    {
        // 1. StockLot을 fifo_order 순서로 조회
        // 2. 필요 수량만큼 차감 (여러 LOT에 걸칠 수 있음)
        // 3. Stock.refreshFromLots() 호출
        // 4. 감사 로그 기록
    }

    /**
     * 재고 예약
     * @param int $itemId
     * @param float $qty
     * @param int $orderId
     */
    public function reserve(int $itemId, float $qty, int $orderId): void
    {
        // 1. Stock.reserved_qty 증가
        // 2. Stock.available_qty 재계산
        // 3. 감사 로그 기록
    }

    /**
     * 예약 해제
     */
    public function releaseReservation(int $itemId, float $qty, int $orderId): void
    {
        // reserved_qty 감소
    }
}

4.2 ReceivingService 수정 사항

// api/app/Services/ReceivingService.php - process() 메서드 수정

public function process(Receiving $receiving, array $data): Receiving
{
    return DB::transaction(function () use ($receiving, $data) {
        // 기존 로직 유지
        $receiving->update([
            'receiving_qty' => $data['receiving_qty'],
            'receiving_date' => $data['receiving_date'],
            'lot_no' => $data['lot_no'],
            'status' => 'completed',
        ]);

        // 🆕 재고 연동 추가
        app(StockService::class)->increaseFromReceiving($receiving);

        return $receiving->fresh();
    });
}

4.3 WorkOrderService 수정 사항

// api/app/Services/WorkOrderService.php - registerMaterialInput() 수정

public function registerMaterialInput(WorkOrder $workOrder, array $data): void
{
    DB::transaction(function () use ($workOrder, $data) {
        // 기존 감사 로그 유지

        // 🆕 재고 차감 추가
        $stockService = app(StockService::class);

        foreach ($data['materials'] as $material) {
            $stockService->decreaseFIFO(
                itemId: $material['item_id'],
                qty: $material['qty'],
                reason: 'work_order_input',
                referenceId: $workOrder->id
            );
        }
    });
}

4.4 감사 로그 구조

필드
auditable_type Stock
auditable_id Stock ID
event stock_increase, stock_decrease, stock_reserve
old_values 변경 전 수량
new_values 변경 후 수량 + 사유 + 참조 ID

5. 작업 절차

Step 1: Phase 1 - 입고 → 재고 연동

1.1 StockService 이벤트 메서드 추가
├── increaseFromReceiving() 구현
├── 감사 로그 통합
└── 단위 테스트

1.2 ReceivingService.process() 수정
├── 기존 로직 분석
├── StockService 호출 추가
└── 트랜잭션 보장

1.3 StockLot 자동 생성
├── Receiving 정보로 StockLot 생성
├── fifo_order 자동 계산
└── Stock.refreshFromLots() 호출

1.4 테스트 및 검증
├── 입고 생성 → 입고처리 → Stock 확인
└── 감사 로그 확인

Step 2: Phase 2 - 생산 → 재고 연동

2.1 BOM 기반 자재 조회 구현
├── 품목의 BOM 정보 조회
├── Mock 데이터 제거
└── 실제 자재 목록 반환

2.2 자재 투입 시 Stock 차감
├── decreaseFIFO() 구현
├── 여러 LOT 걸쳐 차감 처리
└── 재고 부족 시 예외 처리

2.3 작업 완료 시 제품 Stock 증가
├── 생산된 제품의 StockLot 생성
├── Stock.refreshFromLots() 호출
└── 감사 로그 기록

Step 3: Phase 3 - 견적/출하 → 재고 연동

3.1 Order 확정 시 예약
├── reserve() 호출
├── available_qty 감소
└── 오버부킹 방지 검증

3.2 Shipment 출하 시 차감
├── decreaseFIFO() 호출
├── reserved_qty 동시 감소
└── 감사 로그 기록

6. 컨펌 대기 목록

API 내부 로직 변경 등 승인 필요 항목

# 항목 변경 내용 영향 범위 상태
1 ReceivingService.process() Stock 연동 로직 추가 입고 프로세스 대기
2 WorkOrderService.registerMaterialInput() Stock 차감 로직 추가 생산 프로세스 대기
3 ShipmentService (신규) Stock 차감 로직 추가 출하 프로세스 대기

7. 리스크 및 대응

7.1 데이터 정합성 리스크

리스크 확률 영향 대응
트랜잭션 실패 시 Stock만 변경됨 높음 DB 트랜잭션으로 원자성 보장
동시 요청 시 재고 충돌 높음 비관적 락(FOR UPDATE) 적용
재고 부족 상태에서 차감 시도 높음 사전 검증 + 예외 처리

7.2 성능 리스크

리스크 확률 영향 대응
LOT가 많을 경우 FIFO 조회 느림 낮음 fifo_order 인덱스 확인
refreshFromLots() 빈번 호출 낮음 필요 시에만 호출 (이미 구현됨)

8. 변경 이력

날짜 항목 변경 내용 파일 승인
2025-01-26 Phase 3 견적/출하→재고 연동 구현 완료 StockService, OrderService, ShipmentService
2025-01-26 Phase 2 생산→재고 연동 구현 완료 StockService, WorkOrderService
2025-01-26 Phase 1 입고→재고 연동 구현 완료 StockService, ReceivingService
2025-01-26 - 문서 초안 작성 - -

9. 참고 문서

  • API 규칙: docs/standards/api-rules.md
  • 품질 체크리스트: docs/standards/quality-checklist.md
  • DB 스키마: docs/specs/database-schema.md

10. 자기완결성 점검 결과

10.1 체크리스트 검증

# 검증 항목 상태 비고
1 작업 목적이 명확한가? 1.1 배경, 1.2 목표
2 성공 기준이 정의되어 있는가? 1.3 성공 기준
3 작업 범위가 구체적인가? 섹션 3 대상 범위
4 의존성이 명시되어 있는가? 2.3 핵심 파일 위치
5 참고 파일 경로가 정확한가? 섹션 9 참고 문서
6 단계별 절차가 실행 가능한가? 섹션 5 작업 절차
7 검증 방법이 명시되어 있는가? 1.3 성공 기준
8 모호한 표현이 없는가?

10.2 새 세션 시뮬레이션 테스트

질문 답변 가능 참조 섹션
Q1. 이 작업의 목적은 무엇인가? 1.1 배경, 1.2 목표
Q2. 어디서부터 시작해야 하는가? 3. 대상 범위 Phase 1
Q3. 어떤 파일을 수정해야 하는가? 2.3 핵심 파일 위치
Q4. 작업 완료 확인 방법은? 1.3 성공 기준
Q5. 막혔을 때 참고 문서는? 9. 참고 문서

결과: 5/5 통과 → 자기완결성 확보


이 문서는 /sc:plan 스킬로 생성되었습니다.