diff --git a/CLAUDE.md b/CLAUDE.md index dd62af6..c04a166 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -818,7 +818,6 @@ sudo supervisorctl restart sam-mng-worker:* | Skill | 설명 | |-------|------| | `pptx-skill` | PowerPoint 생성 | -| `ppt-auto-generator` | 마크다운/텍스트에서 PPT 생성 | | `pdf-template-skill` | PDF 템플릿 분석/생성 | | `text-analyzer-skill` | 텍스트 분석 및 PDF 구조 매핑 | | `proposal-skill` | 제안서 생성 | diff --git a/INDEX.md b/INDEX.md index ef94ff0..33cb281 100644 --- a/INDEX.md +++ b/INDEX.md @@ -24,6 +24,10 @@ | 견적관리 | `features/quotes/README.md` | 견적 시스템, BOM 계산 | | 급여관리 API | `frontend/api-specs/payroll-api.md` | 급여관리 API 전체 명세 (18개 엔드포인트) | | 바로빌 회계 API | `frontend/api-specs/barobill-api.md` | 카드/은행/홈택스 REST API (42개 엔드포인트) | +| 바로빌 시스템 | `features/barobill/README.md` | SOAP 연동, 테스트/운영 모드, 과금, 멀티테넌트, 이관 계획 | +| 바로빌 출시 계획 | `dev/dev_plans/barobill-service-launch-plan.md` | 4단계 출시 로드맵 (SOAP 이관→UI→베타→출시) | +| 재공품 생산 정책 | `rules/wip-production-policy.md` | 재공품(WIP) 개념, 제조업 공통 패턴, SAM 처리 방식 | +| 재고생산관리 API | `frontend/api-specs/stock-production-api.md` | 재고생산 API 명세 (기존 수주 API + STOCK 타입) | | 결재관리 | `dev/dev_plans/approval-system-unification-plan.md` | MNG→API 결재 통합 계획 | | API 품질 | `system/api-code-quality-audit.md` | 정석 패턴 R1~R6, 안티패턴, 보안, 체크리스트 | | API 학습 | `dev/guides/api-request-lifecycle.md` | Client API로 배우는 요청 생명주기 8단계 | @@ -138,6 +142,7 @@ DB 도메인별: | [pricing-policy.md](rules/pricing-policy.md) | 단가 정책 | | [numbering-rules.md](rules/numbering-rules.md) | 채번 규칙 | | [client-policy.md](rules/client-policy.md) | 고객사 관리 정책 | +| [wip-production-policy.md](rules/wip-production-policy.md) | 재공품(WIP) 생산 정책 (개념, MTS/MTO/ATO, 제조업 공통 패턴) | | [billing-policy.md](rules/billing-policy.md) | 과금 정책 (CONFIDENTIAL) | | [customer-pricing.md](rules/customer-pricing.md) | 고객 요금표 | | [partner-commission.md](rules/partner-commission.md) | 영업파트너 수당 체계 | @@ -164,14 +169,19 @@ DB 도메인별: | [ai/README.md](features/ai/README.md) | AI 분석 | | [card-vehicle/README.md](features/card-vehicle/README.md) | 법인카드·차량 | | [settlement/README.md](features/settlement/README.md) | 정산 | +| [sales/stock-production.md](features/sales/stock-production.md) | 재고생산관리 (내부 오더 방식, 수주 테이블 공유) | | [sales/demo-tenant-policy.md](features/sales/demo-tenant-policy.md) | 영업파트너 데모 테넌트 정책 (3-Tier 전략) | | [sales/demo-tenant-usage-guide.md](features/sales/demo-tenant-usage-guide.md) | 데모 테넌트 사용 가이드 (영업파트너/관리자용) | +| [barobill/README.md](features/barobill/README.md) | 바로빌 연동 시스템 (SOAP API, 테스트/운영 모드, 과금, 이관 계획) | +| [barobill/tenant-onboarding.md](features/barobill/tenant-onboarding.md) | 바로빌 테넌트 온보딩 (개념 정의, 6단계 프로세스, 베타테스트와의 차이) | | [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 | | [quality-management/README.md](features/quality-management/README.md) | 품질관리 (제품검사, 실적신고) | | [approvals/README.md](features/approvals/README.md) | 결재관리 시스템 | | [approvals/mng-api-comparison.md](features/approvals/mng-api-comparison.md) | 결재관리 MNG↔API 비교 분석 및 React 구현 가이드 | | [email/README.md](features/email/README.md) | 이메일 시스템 (테넌트별 SMTP 설정, 프리셋, 연결 테스트) | | [construction-pmis/bim-viewer.md](features/construction-pmis/bim-viewer.md) | BIM 뷰어 (Three.js 기반 웹 3D 건물 모델 뷰어) | +| [rd/README.md](features/rd/README.md) | R&D 메뉴 전체 개요 | +| [rd/fire-shutter-drawing-guide-rail.md](features/rd/fire-shutter-drawing-guide-rail.md) | 방화셔터 가이드레일 SVG/3D 렌더링 기술 명세 | --- @@ -230,6 +240,7 @@ DB 도메인별: | [20260314_api_quality_improvement_deploy.md](dev/changes/20260314_api_quality_improvement_deploy.md) | API 품질 개선 배포 — 테스트 56개 + N+1 최적화 3건 (근거 문서 포함) | | [20260315_eval_removal_safe_math_evaluator.md](dev/changes/20260315_eval_removal_safe_math_evaluator.md) | API 보안 개선 — eval() 3건 제거, SafeMathEvaluator 도입 | | [20260316_sales_policy_changes.md](changes/20260316_sales_policy_changes.md) | 영업 정책 변경 — 수당 구조 개편 및 무료 체험 폐지 | +| [20260316_stock_production_order.md](dev/changes/20260316_stock_production_order.md) | 재고생산관리 기능 추가 (STOCK 타입, 절곡 공정 자동, 생산지시 연동) | --- @@ -260,7 +271,9 @@ DB 도메인별: | [barobill-api.md](frontend/api-specs/barobill-api.md) | 바로빌 회계 데이터 API 명세 (42개 엔드포인트) | | [equipment-api.md](requests/equipment-frontend-request.md) | 설비관리 React 프론트엔드 구현 요청 (26개 엔드포인트 + 화면 가이드) | | [vehicle-api.md](frontend/api-specs/vehicle-api.md) | 차량관리 API 명세 (20개 엔드포인트: 차량목록, 차량일지, 정비이력, 사진) | +| [stock-production-api.md](frontend/api-specs/stock-production-api.md) | 재고생산관리 API 명세 (기존 수주 API + STOCK 타입) | | [vehicle-react-implementation.md](plans/vehicle-react-implementation.md) | 차량관리 React 구현 요청서 (3개 메뉴, 컴포넌트 구조, 타입 정의) | +| [stock-production-react-request.md](plans/stock-production-react-request.md) | 재고생산관리 React 구현 요청서 (수주 화면 단순화, API 스펙 포함) | ### frontend/integration/ — 프론트엔드 개발 가이드 diff --git a/brochure/v1/slides/brochure-2page-back.html b/brochure/v1/slides/brochure-2page-back.html index a285d16..b0aca52 100644 --- a/brochure/v1/slides/brochure-2page-back.html +++ b/brochure/v1/slides/brochure-2page-back.html @@ -200,8 +200,8 @@

점검/납기 알림

-

이카운트 연동

-

기존 ERP 동기화

+

바로빌 회계

+

세금계산서·카드

diff --git a/dev/changes/20260316_stock_production_order.md b/dev/changes/20260316_stock_production_order.md new file mode 100644 index 0000000..be34261 --- /dev/null +++ b/dev/changes/20260316_stock_production_order.md @@ -0,0 +1,173 @@ +# 재고생산관리 기능 추가 + +**날짜:** 2026-03-16 +**작업자:** Claude Code + +--- + +## 변경 개요 + +수주 없이 재고 목적으로 생산하는 경우를 관리하는 **재고생산관리** 기능을 추가했다. +기존 `orders` 테이블을 공유하며, `order_type_code = 'STOCK'`으로 일반 수주와 구분한다. + +### 설계 원칙 + +- **내부 오더(Internal Order)** 패턴 — 재고생산도 수주로 취급 +- 기존 테이블/API 재사용 — 별도 테이블/엔드포인트 없음 +- 하류 시스템(작업지시, 생산, 출하, 품질검사) 변경 없이 동작 + +--- + +## 수정된 파일 + +### 커밋 1: `feat: [order] 재고생산관리(STOCK) 타입 추가` + +| 파일 | 변경 내용 | +|------|----------| +| `app/Models/Orders/Order.php` | `TYPE_STOCK = 'STOCK'` 상수 추가 | +| `app/Http/Requests/Order/StoreOrderRequest.php` | STOCK validation 허용, `production_reason`/`target_stock_qty` 옵션 추가 | +| `app/Http/Requests/Order/UpdateOrderRequest.php` | 동일 | +| `app/Services/OrderService.php` | STK 채번, stats `order_type` 필터, 매출 생성 스킵 | +| `app/Http/Controllers/Api/V1/OrderController.php` | stats에 `order_type` 파라미터 전달 | + +### 커밋 2: `feat: [order] 재고생산 생산지시 자동 처리` + +| 파일 | 변경 내용 | +|------|----------| +| `app/Services/OrderService.php` | `store()`: STOCK → `site_name='재고생산'` 자동 설정 | +| `app/Services/OrderService.php` | `createProductionOrder()`: STOCK 분기 추가 (절곡 자동, project_name, scheduled_date) | +| `lang/ko/error.php` | `bending_process_not_found` 에러 메시지 추가 | +| `lang/en/error.php` | 동일 (영문) | + +--- + +## 상세 변경 사항 + +### 1. Order 모델 — 타입 상수 + +```php +public const TYPE_ORDER = 'ORDER'; // 수주 +public const TYPE_PURCHASE = 'PURCHASE'; // 발주 +public const TYPE_STOCK = 'STOCK'; // 재고생산 (신규) +``` + +### 2. 채번 규칙 + +| 타입 | 접두사 | 형식 | 예시 | +|------|--------|------|------| +| ORDER | `ORD` | `ORD{YYYYMMDD}{NNNN}` | `ORD202603160001` | +| STOCK | `STK` | `STK{YYYYMMDD}{NNNN}` | `STK202603160001` | + +### 3. store() — STOCK 자동 처리 + +```php +if ($isStock) { + $data['site_name'] = '재고생산'; +} +``` + +### 4. createProductionOrder() — STOCK 분기 + +| 항목 | ORDER (기존) | STOCK (신규) | +|------|-------------|-------------| +| 공정 매칭 | BOM item_id → process_items 매핑 | **절곡 공정 직접 할당** (BOM 스킵) | +| project_name | `order.site_name ?? client_name` | `'재고생산'` 고정 | +| scheduled_date | `order.delivery_date` | `now()` | +| 매출 생성 | `sales_recognition` 정책 적용 | **생성 안 함** | + +절곡 공정 조회: +```php +$bendingProcess = Process::where('tenant_id', $tenantId) + ->where('process_name', '절곡') + ->where('is_active', true) + ->first(); +``` + +### 5. stats() — order_type 필터 + +```php +public function stats(?string $orderType = null): array +``` + +`GET /api/v1/orders/stats?order_type=STOCK` 으로 재고생산 전용 통계 조회 가능. + +### 6. 매출 생성 스킵 + +```php +if ($status === Order::STATUS_CONFIRMED + && $order->order_type_code !== Order::TYPE_STOCK // STOCK 제외 + && $order->shouldCreateSaleOnConfirm()) { +``` + +--- + +## 영향범위 분석 + +| 영역 | 영향 | 이유 | +|------|------|------| +| 기존 수주(ORDER) | ❌ 없음 | `$isStock` 조건 분기, else 블록에서 기존 코드 그대로 실행 | +| 기존 발주(PURCHASE) | ❌ 없음 | 동일 | +| 작업지시(WorkOrder) | ✅ 정상 동작 | `sales_order_id` FK로 연결, 절곡 공정 할당됨 | +| 생산/품질검사 | ❌ 없음 | WorkOrder 기반 하류 시스템, Order 타입 무관 | +| 출하(Shipment) | ❌ 없음 | WorkOrder 참조, Order.site_name 미사용 | +| 캘린더 | ✅ 표시됨 | `project_name='재고생산'`, `scheduled_date=now()` | +| 생산지시 목록 | ✅ 표시됨 | `site_name='재고생산'`으로 현장명 표시 | + +--- + +## 버그 수정 (2026-03-17) + +### 커밋 3: `fix: [production] 생산지시 생성 시 $isStock 미정의 오류 및 수량 정수 변환` + +| 파일 | 변경 내용 | +|------|----------| +| `app/Services/OrderService.php` | `DB::transaction` 클로저 `use`절에 `$isStock` 변수 추가 | +| `app/Services/OrderService.php` | `work_order_items.quantity`를 `(int)` 캐스팅하여 정수로 저장 | + +**원인**: `$isStock`가 line 1242에서 정의되지만, `DB::transaction` 클로저의 `use`절에 포함되지 않아 클로저 내부에서 참조 불가 → 500 에러 발생 + +### 커밋 4: `fix: [production] 생산지시 생성 시 $process 미정의 오류 수정` + +| 파일 | 변경 내용 | +|------|----------| +| `app/Services/OrderService.php` | `$process = null;` 초기화 추가 (if 블록 밖에서도 참조 가능하도록) | + +**원인**: `$process`가 `if ($processId)` 블록 안에서만 정의되지만, 블록 밖 line 1420에서 team_id 결정 시 참조 → 공정 없는 품목 처리 시 500 에러 발생 + +### 커밋 5 (React): `fix: [stocks] 재고생산 수량을 정수로 표시` + +| 파일 | 변경 내용 | +|------|----------| +| `src/components/stocks/actions.ts` | `transformItemApiToFrontend`에서 `Math.floor(Number())` 적용 | +| `src/components/stocks/actions.ts` | 금액 필드도 `Number()`로 안전한 형변환 적용 | + +**원인**: API의 Eloquent `decimal:4` 캐스트가 수량을 `"1.0000"` 문자열로 반환하여 프론트엔드에서 소수점 그대로 표시 + +--- + +## 테스트 체크리스트 + +- [x] STOCK 수주 생성 → `order_no` STK 접두사 확인 +- [x] STOCK 수주 생성 → `site_name='재고생산'` 자동 설정 확인 +- [ ] STOCK 수주 확정 → 매출 자동 생성 안 됨 확인 +- [x] STOCK 생산지시 생성 → 절곡 공정 자동 선택 확인 +- [x] STOCK 생산지시 생성 → `project_name='재고생산'` 확인 +- [x] STOCK 생산지시 생성 → `scheduled_date=today` 확인 +- [ ] 기존 ORDER 수주 생산지시 → 기존 BOM 매칭 정상 동작 확인 +- [ ] 생산지시 목록에서 STOCK 건 표시 확인 +- [x] 생산지시 생성 시 `$isStock` 미정의 오류 수정 확인 +- [x] 생산지시 생성 시 `$process` 미정의 오류 수정 확인 +- [x] `work_order_items.quantity` 정수 저장 확인 +- [x] 프론트엔드 수량 정수 표시 확인 + +--- + +## 관련 문서 + +- [재고생산관리 기능 설명](../../features/sales/stock-production.md) +- [재고생산관리 API 명세](../../frontend/api-specs/stock-production-api.md) +- [프론트엔드 구현 요청서](../../frontend/requests/stock-production-react-request.md) + +--- + +**최종 업데이트**: 2026-03-17 diff --git a/dev/dev_plans/barobill-service-launch-plan.md b/dev/dev_plans/barobill-service-launch-plan.md new file mode 100644 index 0000000..860a120 --- /dev/null +++ b/dev/dev_plans/barobill-service-launch-plan.md @@ -0,0 +1,242 @@ +# 바로빌 서비스 출시 단계별 준비 계획 + +> **작성일**: 2026-03-17 +> **상태**: 계획 수립 +> **담당**: R&D실 + +--- + +## 1. 개요 + +### 1.1 목적 + +MNG에서 운영 중인 바로빌 연동 시스템을 서비스(API+React)로 이관하여, 멀티테넌트 고객이 직접 사용할 수 있는 SaaS 형태로 출시한다. + +### 1.2 현재 상태 + +- **MNG (백오피스)**: 바로빌 SOAP 연동 완료, tenant_id=1 (코드브릿지엑스)에서 실무 운영 중 +- **API**: DB 모델 15개 + REST API 42개 엔드포인트 구현 완료 (데이터 조회/분개용) +- **React**: 바로빌 설정 페이지 기본 구현 + +### 1.3 목표 + +고객(테넌트)이 SAM 서비스에서 바로빌 기능을 직접 설정하고 사용할 수 있도록 한다: +- 계좌조회, 카드내역, 홈택스 세금계산서 자동 수집 +- 전자세금계산서 발행 +- 카카오톡/SMS 알림 + +--- + +## 2. 단계별 로드맵 + +``` +Phase 1 Phase 2 Phase 3 Phase 4 +SOAP 이관 UI 구현 베타테스트 정식 출시 +(API 개발) (React 개발) (내부→외부) (온보딩 가동) +───────────── → ───────────── → ───────────── → ───────────── +``` + +--- + +## 3. Phase 1: SOAP 연동 이관 (API 개발) + +> **핵심**: MNG의 BarobillService를 API로 이관하여 멀티테넌트 지원 + +### 3.1 작업 목록 + +| # | 작업 | 상세 | 난이도 | +|---|------|------|--------| +| 1-1 | BarobillService 이관 | MNG 1,761줄 → API로 이동, 멀티테넌트 리팩토링 | 상 | +| 1-2 | 회원사 관리 API | 등록/수정/조회/상태확인 엔드포인트 | 중 | +| 1-3 | 인증서 관리 API | 등록URL/유효성/만료일 조회 엔드포인트 | 중 | +| 1-4 | 계좌 관리 API | 등록/목록/입출금 조회 엔드포인트 | 중 | +| 1-5 | 카드 관리 API | 등록/수정/해지/사용내역 조회 엔드포인트 | 중 | +| 1-6 | 세금계산서 발행 API | 작성/발행/조회 엔드포인트 | 상 | +| 1-7 | 동기화 스케줄러 | 은행/카드/홈택스 자동 수집 (Queue Job) | 중 | +| 1-8 | 테스트/운영 모드 전환 API | 회원사별 server_mode 전환 | 하 | + +### 3.2 기술 과제 + +| 과제 | 설명 | 대응 방안 | +|------|------|----------| +| CERTKEY 관리 | 현재 전역 1개 → 멀티테넌트 대응 필요 | 바로빌 파트너 계약 구조 확인 후 결정 | +| PHP SOAP 확장 | API 서버에 `php-soap` 설치 필요 | Docker/서버 환경 확인 | +| 암호화 키 공유 | MNG/API 간 `APP_KEY` 동일해야 복호화 가능 | 현재 동일 키 사용 중 (확인 필요) | +| 동기화 부하 | 테넌트 수 증가 시 SOAP 호출량 증가 | Queue 분산, 호출 간격 조절 | + +### 3.3 환경 준비 + +```bash +# API 서버에 PHP SOAP 확장 확인 +php -m | grep soap + +# 없으면 설치 (개발 서버 Level 2) +sudo apt install php8.4-soap +sudo systemctl restart php8.4-fpm + +# .env 설정 추가 +BAROBILL_CERT_KEY_TEST=<테스트 인증키> +BAROBILL_CERT_KEY_PROD=<운영 인증키> +BAROBILL_CORP_NUM=<파트너 사업자번호> +BAROBILL_TEST_MODE=true +``` + +--- + +## 4. Phase 2: UI 구현 (React 개발) + +> **핵심**: 고객이 직접 바로빌을 설정하고 데이터를 조회할 수 있는 화면 + +### 4.1 작업 목록 + +| # | 작업 | 상세 | 난이도 | +|---|------|------|--------| +| 2-1 | 바로빌 설정 페이지 | 회원사 등록/수정, 서버 모드 표시 | 중 | +| 2-2 | 인증서 관리 화면 | 등록 URL 안내, 유효기간 표시, 갱신 알림 | 중 | +| 2-3 | 계좌 관리 화면 | 등록 계좌 목록, 등록 URL 안내 | 중 | +| 2-4 | 카드 관리 화면 | 등록 카드 목록, 추가/해지 | 중 | +| 2-5 | 카드 거래내역 조회 | 기간별 조회, 분개 연동, 숨김/분할 | 상 | +| 2-6 | 은행 거래내역 조회 | 기간별 조회, 분개 연동, 오버라이드/분할 | 상 | +| 2-7 | 홈택스 세금계산서 | 매출/매입 조회, 분개 연동 | 중 | +| 2-8 | 세금계산서 발행 화면 | 작성/발행 폼, 미리보기 | 상 | + +### 4.2 화면 구성 (메뉴 구조) + +``` +재무관리 +├─ 계좌관리 +│ ├─ 보유계좌 관리 (바로빌 계좌 등록 포함) +│ └─ 계좌 입출금 내역 +├─ 카드관리 +│ ├─ 법인카드 관리 (바로빌 카드 등록 포함) +│ └─ 카드 사용내역 +├─ 세금계산서 +│ ├─ 매출 세금계산서 +│ ├─ 매입 세금계산서 +│ └─ 세금계산서 발행 +└─ 설정 + └─ 바로빌 연동 설정 (인증서, 모드, 충전잔액) +``` + +--- + +## 5. Phase 3: 베타테스트 + +> **핵심**: 내부 → 외부 순서로 검증, 테스트 모드 사용 + +### 5.1 내부 베타테스트 + +| 항목 | 내용 | +|------|------| +| **대상** | tenant_id=1 (코드브릿지엑스 본사) | +| **기간** | 2주 | +| **모드** | 테스트 모드 | +| **검증 항목** | 전체 기능 동작, UI/UX, 데이터 정합성 | +| **비교 기준** | MNG 운영 데이터와 서비스 데이터 일치 확인 | + +**내부 베타 체크리스트**: + +- [ ] 회원사 등록/수정 정상 동작 +- [ ] 인증서 등록 URL 정상 접근 +- [ ] 계좌 등록 및 입출금 내역 조회 +- [ ] 카드 등록 및 사용내역 조회 +- [ ] 홈택스 매출/매입 세금계산서 수집 +- [ ] 세금계산서 발행 (테스트 서버) +- [ ] 분개 연동 정상 동작 +- [ ] 동기화 스케줄러 자동 수집 확인 +- [ ] MNG 데이터와 서비스 데이터 일치 + +### 5.2 외부 베타테스트 + +| 항목 | 내용 | +|------|------| +| **대상** | 선별 고객사 2~3곳 | +| **기간** | 2~4주 | +| **모드** | 테스트 모드 | +| **검증 항목** | 실사용 시나리오, 다양한 사업자 유형, 피드백 수집 | + +**외부 베타 체크리스트**: + +- [ ] 다양한 사업자번호로 회원 등록 +- [ ] 다양한 은행/카드사 연동 확인 +- [ ] 고객 직접 인증서/계좌/카드 등록 가능 확인 +- [ ] 고객 피드백 수집 및 반영 +- [ ] 성능 (다수 테넌트 동시 동기화) + +--- + +## 6. Phase 4: 정식 출시 + +> **핵심**: 운영 모드 전환, 과금 시작, 온보딩 프로세스 가동 + +### 6.1 출시 준비 체크리스트 + +**인프라**: +- [ ] API 서버 `php-soap` 확장 설치 확인 +- [ ] 운영 `.env`에 `BAROBILL_CERT_KEY_PROD`, `BAROBILL_CORP_NUM` 설정 +- [ ] `BAROBILL_TEST_MODE=false` 설정 +- [ ] 동기화 스케줄러 Supervisor 등록 +- [ ] 바로빌 운영 CERTKEY 충전잔액 확보 + +**과금**: +- [ ] `barobill_pricing_policies` 요금 정책 데이터 입력 +- [ ] 월정액 구독 자동 과금 배치 등록 (매월 1일) +- [ ] 과금 내역 고객 조회 화면 (선택) + +**운영**: +- [ ] 인증서 만료 알림 (이메일/카카오톡) +- [ ] 충전잔액 부족 알림 +- [ ] 동기화 실패 알림 및 재시도 로직 +- [ ] 바로빌 장애 시 대응 매뉴얼 + +### 6.2 온보딩 프로세스 정립 + +정식 출시 후 신규 고객 가입 시: + +``` +계약 → 테넌트 생성 → 회원등록(테스트) → 인증서/계좌/카드 → 검증 → 운영전환 → 실무사용 +``` + +> 상세 프로세스: `features/barobill/tenant-onboarding.md` 참조 + +--- + +## 7. 바로빌 파트너 정책 확인 필요 사항 + +> **경고: 개발 착수 전 바로빌 측에 확인해야 할 사항** + +| # | 확인 사항 | 이유 | 현재 상태 | +|---|----------|------|----------| +| 1 | 멀티테넌트 CERTKEY 구조 | 파트너 1개 키로 다수 회원사 관리 가능한지 | 미확인 | +| 2 | 테스트 서버 제한 | 테스트 API 호출 횟수/기간 제한 | 미확인 | +| 3 | 과금 구조 | 파트너 단가표 (건당/월정액) | 미확인 | +| 4 | SLA | 바로빌 API 가용성 보장 수준 | 미확인 | +| 5 | 회원사 대량 등록 | 일괄 등록 API 또는 제한 | 미확인 | +| 6 | 인증서 대리 등록 | 고객 대신 등록 가능 여부 | 미확인 | + +--- + +## 8. 리스크 및 대응 + +| 리스크 | 영향 | 대응 | +|--------|------|------| +| 바로빌 API 장애 | 거래 데이터 수집 중단 | 재시도 로직 + 장애 알림 | +| 인증서 만료 | 계좌/세금계산서 조회 불가 | 만료 30일 전 알림 | +| SOAP 호출 지연 | 페이지 응답 지연 | 비동기 Queue 처리 | +| 테넌트 급증 | 동기화 부하 | 호출 간격 분산, 우선순위 큐 | +| 충전잔액 부족 | API 호출 실패 | 잔액 모니터링 + 자동 알림 | + +--- + +## 관련 문서 + +| 문서 | 설명 | +|------|------| +| [바로빌 연동 시스템](../../features/barobill/README.md) | 전체 구조, 모드, 과금 | +| [테넌트 온보딩](../../features/barobill/tenant-onboarding.md) | 온보딩 6단계 프로세스 | +| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | REST API 42개 엔드포인트 | +| [이관 현황](../../system/migration-status.md) | MNG→API+React 전체 이관 현황 | + +--- + +**최종 업데이트**: 2026-03-17 diff --git a/dev/dev_plans/barobill-service-launch-plan.pptx b/dev/dev_plans/barobill-service-launch-plan.pptx new file mode 100644 index 0000000..975631d Binary files /dev/null and b/dev/dev_plans/barobill-service-launch-plan.pptx differ diff --git a/features/barobill/README.md b/features/barobill/README.md new file mode 100644 index 0000000..075756a --- /dev/null +++ b/features/barobill/README.md @@ -0,0 +1,398 @@ +# 바로빌(Barobill) 연동 시스템 + +> **작성일**: 2026-03-17 +> **상태**: MNG 운영 중 / 서비스 이관 준비 + +--- + +## 1. 개요 + +### 1.1 목적 + +바로빌은 전자세금계산서, 계좌조회, 카드내역, 홈택스 연동, 카카오톡/SMS 발송 등을 제공하는 SOAP 기반 B2B 서비스다. SAM에서 재무/회계 데이터를 자동 수집하고 세금계산서를 발행하기 위해 연동한다. + +### 1.2 현재 상태 + +| 항목 | MNG (백오피스) | API (서비스) | React (프론트) | +|------|:------------:|:----------:|:------------:| +| SOAP 연동 서비스 | ✅ 완료 (1,761줄) | 기본 설정만 | — | +| 회원사 관리 | ✅ 운영 중 | 모델만 존재 | 설정 페이지 | +| 카드 거래 조회 | ✅ 운영 중 | ✅ REST API 16개 | — | +| 은행 거래 조회 | ✅ 운영 중 | ✅ REST API 13개 | — | +| 홈택스 세금계산서 | ✅ 운영 중 | ✅ REST API 13개 | — | +| 카카오톡/SMS | ✅ 운영 중 | — | — | +| 과금 시스템 | ✅ 구현 완료 | — | — | + +> **핵심**: tenant_id=1 (코드브릿지엑스 본사)에서 실무 운영 중. 서비스 이관 시 멀티테넌트 SOAP 연동이 핵심 과제. + +### 1.3 바로빌 공식 자료 + +- 개발자 센터: `https://dev.barobill.co.kr/` +- 운영 WSDL: `https://ws.baroservice.com/` +- 테스트 WSDL: `https://testws.baroservice.com/` + +--- + +## 2. 테스트 모드 vs 운영 모드 + +> **경고: 개발 시 반드시 테스트 모드를 사용한다. 운영 모드는 실제 과금이 발생한다.** + +### 2.1 모드 비교 + +| 항목 | 테스트 모드 | 운영 모드 | +|------|-----------|----------| +| WSDL 엔드포인트 | `https://testws.baroservice.com/` | `https://ws.baroservice.com/` | +| CERTKEY | 테스트용 별도 발급 | 운영용 별도 발급 | +| 과금 | ❌ 무과금 | ✅ 실제 과금 | +| 데이터 | 테스트 데이터 (초기화 가능) | 실제 세금계산서/거래 데이터 | +| 국세청 전송 | ❌ 미전송 | ✅ 실제 전송 | +| 회원사 등록 | 테스트 서버에 등록 | 운영 서버에 등록 | +| 인증서 | 테스트 인증서 사용 가능 | 실제 공동인증서 필수 | + +### 2.2 모드 전환 구조 + +``` +┌───────────────────────────────────────────────────────┐ +│ 모드 결정 흐름 │ +├───────────────────────────────────────────────────────┤ +│ │ +│ 1. BarobillMember.server_mode │ +│ └─ 'test' 또는 'production' (회원사별 설정) │ +│ │ +│ 2. BarobillService.switchServerMode(isTestMode) │ +│ └─ SOAP 클라이언트 재초기화 │ +│ └─ initializeConfig() 호출 │ +│ │ +│ 3. initializeConfig() │ +│ ├─ DB 우선: BarobillConfig.getActive(isTestMode) │ +│ │ └─ environment = 'test' | 'production' │ +│ └─ .env 폴백: │ +│ ├─ test → BAROBILL_CERT_KEY_TEST │ +│ └─ prod → BAROBILL_CERT_KEY_PROD │ +│ │ +│ 4. SOAP URL 구성 │ +│ ├─ test → testws.baroservice.com/* │ +│ └─ prod → ws.baroservice.com/* │ +│ │ +└───────────────────────────────────────────────────────┘ +``` + +### 2.3 설정 우선순위 + +1. **DB 설정** (`barobill_configs` 테이블) — 최우선 +2. **.env 환경변수** — DB 설정 없을 때 폴백 + +```php +// BarobillService::initializeConfig() +$dbConfig = BarobillConfig::getActive($this->isTestMode); + +if ($dbConfig) { + // DB에서 cert_key, corp_num, base_url 사용 +} else { + // .env에서 BAROBILL_CERT_KEY_TEST/PROD, BAROBILL_CORP_NUM 사용 +} +``` + +### 2.4 환경변수 + +```bash +# .env (MNG, API 동일) +BAROBILL_CERT_KEY_TEST=<테스트 인증키> +BAROBILL_CERT_KEY_PROD=<운영 인증키> +BAROBILL_CORP_NUM=<파트너 사업자번호> +BAROBILL_TEST_MODE=true # 기본값: 테스트 모드 +``` + +### 2.5 개발 시 주의사항 + +``` +✅ 로컬/개발 서버: BAROBILL_TEST_MODE=true (기본값) +✅ 운영 서버: BAROBILL_TEST_MODE=false + 운영 CERTKEY +✅ 회원사별 server_mode로 개별 전환 가능 +❌ 테스트 CERTKEY로 운영 서버 호출 불가 (에러 -11102) +❌ 운영 모드에서 테스트 데이터 생성 금지 (실제 과금) +``` + +--- + +## 3. 아키텍처 + +### 3.1 전체 데이터 흐름 + +``` +바로빌 SOAP API (ws.baroservice.com) + │ + │ SOAP (6개 서비스) + ▼ +┌─────────────────────────────────┐ +│ MNG (BarobillService) │ +│ ├─ CORPSTATE — 회원사 관리 │ +│ ├─ TI — 전자세금계산서 │ +│ ├─ BANKACCOUNT — 계좌조회 │ +│ ├─ CARD — 카드조회 │ +│ ├─ KAKAOTALK — 알림톡 │ +│ └─ SMS — 문자 발송 │ +└──────────┬──────────────────────┘ + │ MySQL 저장 + ▼ +┌─────────────────────────────────┐ +│ MySQL (samdb) │ +│ ├─ barobill_members │ +│ ├─ barobill_card_transactions │ +│ ├─ barobill_bank_transactions │ +│ ├─ hometax_invoices │ +│ └─ (18개 테이블) │ +└──────────┬──────────────────────┘ + │ REST API + ▼ +┌─────────────────────────────────┐ +│ API (42개 엔드포인트) │ +│ ├─ /api/v1/barobill-card-* │ +│ ├─ /api/v1/barobill-bank-* │ +│ └─ /api/v1/hometax-invoices/* │ +└──────────┬──────────────────────┘ + │ + ▼ +┌─────────────────────────────────┐ +│ React (사용자 UI) │ +│ └─ BarobillIntegration 컴포넌트│ +└─────────────────────────────────┘ +``` + +### 3.2 SOAP 서비스 목록 + +| 서비스 | WSDL 경로 | 기능 | +|--------|----------|------| +| CORPSTATE | `/CORPSTATE.asmx` | 회원사 등록/조회/수정 | +| TI | `/TI.asmx` | 전자세금계산서 발행/조회 | +| BANKACCOUNT | `/BANKACCOUNT.asmx` | 계좌 등록/입출금 내역 조회 | +| CARD | `/CARD.asmx` | 카드 등록/사용내역 조회 | +| KAKAOTALK | `/KAKAOTALK.asmx` | 카카오톡 알림톡 발송 | +| SMS | `/SMS.asmx` | 문자 메시지 발송 | + +### 3.3 인증 구조 + +``` +모든 API 호출 + └─ CERTKEY (파트너 인증키) — 필수 파라미터 + ├─ 바로빌 파트너 계약 시 발급 + ├─ 테스트/운영 별도 키 + └─ BarobillService.call()에서 자동 주입 +``` + +--- + +## 4. 과금 정책 + +### 4.1 바로빌 과금 구조 (SAM 내부 정책) + +| 서비스 | 월정액 | 비고 | +|--------|-------|------| +| 계좌조회 (`bank_account`) | 10,000원/월 | 테넌트별 | +| 카드내역 (`card`) | 10,000원/월 | 테넌트별 | +| 홈택스 매입/매출 (`hometax`) | 0원 | 본사 부담 (무료 제공) | + +### 4.2 추가 과금 (건별) + +`BarobillPricingPolicy` 모델 기반: + +| 서비스 | 무료 기본량 | 추가 과금 단위 | 추가 금액 | +|--------|-----------|-------------|----------| +| 법인카드 등록 (`card`) | 정책 설정값 | 정책 설정값 | 정책 설정값 | +| 계산서 발행 (`tax_invoice`) | 정책 설정값 | 건당 | 정책 설정값 | +| 계좌조회 수집 (`bank_account`) | 정책 설정값 | 정책 설정값 | 정책 설정값 | + +> 과금 계산: `BarobillPricingPolicy::calculateBilling(usageCount)` — 무료 제공량 초과분만 과금 + +### 4.3 과금 처리 흐름 + +``` +매월 1일 (배치) + └─ BarobillBillingService::processMonthlyBilling() + ├─ 활성 구독 조회 (BarobillSubscription::active()) + ├─ 이미 과금된 기록 중복 방지 + ├─ BarobillBillingRecord 생성 (subscription 타입) + └─ BarobillMonthlySummary 갱신 + +건별 발생 시 + └─ BarobillBillingService::recordUsage() + ├─ BarobillBillingRecord 생성 (usage 타입) + └─ BarobillMonthlySummary 갱신 +``` + +### 4.4 테스트 모드에서의 과금 + +``` +✅ 테스트 모드: 바로빌 API 호출에 대한 바로빌 측 과금 없음 +✅ SAM 내부 과금 시스템은 모드와 무관하게 기록 가능 (테스트용) +❌ 운영 모드: 바로빌 측 실제 과금 발생 (충전잔액 차감) +``` + +--- + +## 5. 멀티테넌트 처리 + +### 5.1 데이터 격리 + +모든 바로빌 테이블은 `tenant_id` 컬럼으로 데이터를 격리한다. + +``` +tenant_id=1 (코드브릿지엑스) → 본사 실무 데이터 +tenant_id=N (고객사) → 해당 고객사 데이터만 접근 +``` + +### 5.2 회원사별 설정 + +각 테넌트는 `barobill_members` 테이블에 독립된 바로빌 회원사 정보를 가진다: + +| 컬럼 | 설명 | +|------|------| +| `tenant_id` | 테넌트 FK | +| `biz_no` | 사업자번호 (UNIQUE with tenant_id) | +| `barobill_id` | 바로빌 로그인 ID | +| `barobill_pwd` | 바로빌 비밀번호 (Laravel Encryption) | +| `server_mode` | `test` 또는 `production` (회원사별 전환) | +| `status` | `active` / `inactive` / `pending` | + +### 5.3 서비스 이관 시 고려사항 + +``` +🔴 필수: 테넌트별 CERTKEY 관리 방안 (현재는 전역 1개) +🔴 필수: 테넌트 온보딩 시 바로빌 회원 자동 등록 플로우 +🟡 중요: 테스트→운영 모드 전환 프로세스 정의 +🟡 중요: 과금 정책을 테넌트별로 다르게 적용 가능하도록 확장 +🟢 권장: 바로빌 API 호출 로그/모니터링 +``` + +--- + +## 6. 프로젝트별 코드 위치 + +### 6.1 MNG (`/home/aweso/sam/mng`) + +| 유형 | 경로 | +|------|------| +| 서비스 | `app/Services/Barobill/BarobillService.php` (1,761줄, 핵심) | +| 서비스 | `app/Services/Barobill/HometaxSyncService.php` | +| 서비스 | `app/Services/Barobill/BarobillBillingService.php` | +| 서비스 | `app/Services/Barobill/BarobillUsageService.php` | +| 서비스 | `app/Services/Barobill/BarobillBankSyncService.php` | +| 모델 | `app/Models/Barobill/` (18개 모델) | +| 컨트롤러 | `app/Http/Controllers/Barobill/` (7개) | +| Admin API | `app/Http/Controllers/Api/Admin/Barobill/` (7개) | +| 뷰 | `resources/views/barobill/` (10개 페이지) | + +### 6.2 API (`/home/aweso/sam/api`) + +| 유형 | 경로 | +|------|------| +| 서비스 | `app/Services/BarobillService.php` (기본 설정만) | +| 모델 | `app/Models/Barobill/` (15개) | +| 모델 | `app/Models/Tenants/BarobillSetting.php` | +| 컨트롤러 | `app/Http/Controllers/Api/V1/Barobill*Controller.php` | +| 마이그레이션 | `database/migrations/` (19개 바로빌 관련) | + +### 6.3 React (`/home/aweso/sam/react`) + +| 유형 | 경로 | +|------|------| +| 컴포넌트 | `src/components/settings/BarobillIntegration/` | +| 페이지 | `/settings/barobill-integration` | + +--- + +## 7. DB 테이블 구조 + +### 7.1 테이블 목록 + +| 테이블 | 용도 | 마이그레이션 위치 | +|--------|------|-----------------| +| `barobill_members` | 회원사 정보 | API | +| `barobill_configs` | API 설정 (test/prod 분리) | API | +| `barobill_settings` | 테넌트별 서비스 설정 | API | +| `barobill_subscriptions` | 월정액 구독 | API | +| `barobill_billing_records` | 과금 기록 | API | +| `barobill_monthly_summaries` | 월별 과금 요약 | API | +| `barobill_pricing_policies` | 요금 정책 | API | +| `hometax_invoices` | 홈택스 세금계산서 | API | +| `hometax_invoice_journals` | 세금계산서 분개 | API | +| `barobill_bank_transactions` | 은행 거래 내역 | API | +| `barobill_bank_transaction_overrides` | 은행 적요 수정 | API | +| `barobill_bank_transaction_splits` | 은행 거래 분할 | API | +| `barobill_bank_sync_status` | 은행 동기화 상태 | API | +| `barobill_card_transactions` | 카드 거래 내역 | API | +| `barobill_card_transaction_splits` | 카드 거래 분할 | API | +| `barobill_card_transaction_amount_logs` | 카드 금액 수정 로그 | API | +| `barobill_card_transaction_hides` | 카드 거래 숨김 | API | +| `account_codes` | 계정과목 마스터 | API | + +### 7.2 핵심 테이블 스키마 + +**barobill_members**: +- `tenant_id` + `biz_no` UNIQUE +- `server_mode`: `test` | `production` +- `barobill_pwd`: Laravel Encryption (복호화 가능, API 호출 시 필요) + +**hometax_invoices**: +- `tenant_id` + `nts_confirm_num` + `invoice_type` UNIQUE +- `invoice_type`: `sales` | `purchase` +- `tax_type`: 1=과세, 2=영세, 3=면세 +- `issue_type`: 1=정발행, 2=역발행 + +--- + +## 8. 에러 코드 매핑 + +| 코드 | 의미 | 대응 | +|------|------|------| +| -11101 | 사업자번호 미설정/유효하지 않음 | 회원사 정보 확인 | +| -11102 | CERTKEY 유효하지 않음 | 테스트/운영 키 확인 | +| -11103 | 인증서 만료/유효하지 않음 | 공동인증서 갱신 | +| -11104 | 미등록 사업자 | 회원사 등록 먼저 | +| -11105 | 이미 등록된 사업자 | 중복 등록 방지 | +| -26001 | 공동인증서 미등록 | 인증서 등록 안내 | +| -32001 | 사업자번호 형식 오류 | 10자리 숫자 확인 | +| -32010 | 이미 등록된 사업자번호 | 기존 회원 확인 | +| -32011 | 이미 등록된 아이디 | 다른 아이디 사용 | + +--- + +## 9. 서비스 이관 계획 + +### 9.1 이관 범위 + +| 기능 | MNG (현재) | API 이관 | React 이관 | 우선순위 | +|------|:---------:|:-------:|:---------:|:-------:| +| SOAP 연동 서비스 | ✅ | 🔴 필수 | — | P1 | +| 회원사 등록/관리 | ✅ | 🔴 필수 | 🔴 필수 | P1 | +| 테스트/운영 모드 전환 | ✅ | 🔴 필수 | 🟡 관리자 | P1 | +| 카드 거래 동기화 | ✅ | 🟡 중요 | ✅ 완료 | P2 | +| 은행 거래 동기화 | ✅ | 🟡 중요 | — | P2 | +| 홈택스 동기화 | ✅ | 🟡 중요 | — | P2 | +| 세금계산서 발행 | ✅ | 🟡 중요 | 🟡 중요 | P2 | +| 과금 시스템 | ✅ | 🟢 권장 | 🟢 권장 | P3 | +| 카카오톡/SMS | ✅ | 🟢 권장 | — | P3 | + +### 9.2 이관 시 핵심 과제 + +1. **SOAP 서비스 이관**: MNG의 `BarobillService` (1,761줄)를 API로 이동 +2. **멀티테넌트 CERTKEY**: 테넌트별로 바로빌 파트너 계약이 필요한지, 공용 CERTKEY로 처리 가능한지 확인 +3. **테스트 모드 관리**: 신규 테넌트는 테스트 모드로 시작 → 관리자가 운영 모드로 전환 +4. **동기화 스케줄러**: MNG에서 실행 중인 은행/카드/홈택스 동기화를 API Queue로 이관 +5. **인증서 관리**: 공동인증서 등록 URL을 테넌트 사용자에게 제공하는 플로우 + +--- + +## 관련 문서 + +| 문서 | 설명 | +|------|------| +| [테넌트 온보딩](./tenant-onboarding.md) | 온보딩 개념 정의, 테스트→운영 전환 프로세스 | +| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | 카드/은행/홈택스 REST API 42개 엔드포인트 | +| [바로빌 회원 마이그레이션](../../dev/guides/barobill-members-migration.md) | 회원 데이터 이관 가이드 | +| [바로빌 카카오톡](../barobill-kakaotalk/README.md) | 카카오톡 알림톡 연동 | +| [재무관리](../finance/README.md) | 재무/자금관리 전체 개요 | + +--- + +**최종 업데이트**: 2026-03-17 diff --git a/features/barobill/tenant-onboarding.md b/features/barobill/tenant-onboarding.md new file mode 100644 index 0000000..859a67a --- /dev/null +++ b/features/barobill/tenant-onboarding.md @@ -0,0 +1,190 @@ +# 바로빌 테넌트 온보딩 프로세스 + +> **작성일**: 2026-03-17 +> **상태**: 설계 중 (서비스 이관 준비) + +--- + +## 1. 온보딩(Onboarding)이란 + +### 1.1 정의 + +**온보딩**: 새로운 고객(테넌트)이 서비스에 가입하여 실제 사용을 시작하기까지의 초기 설정 과정. + +SAM 바로빌 맥락에서는 **정식 계약 고객이 바로빌 연동 기능(계좌조회, 카드내역, 세금계산서 등)을 실무에서 사용할 수 있도록 초기 세팅하는 일련의 절차**를 의미한다. + +### 1.2 온보딩 vs 베타테스트 + +| 구분 | 온보딩 | 베타테스트 | +|------|--------|----------| +| **대상** | 정식 계약 고객 | 서비스 출시 전 검증 참여자 | +| **목적** | 고객이 기능을 쓸 수 있게 초기 세팅 | 서비스 안정성/기능 검증 | +| **시점** | 고객 가입할 때마다 반복 발생 | 서비스 출시 전 1회성 | +| **테스트 모드** | 초기 세팅 확인용으로 잠깐 사용 가능 | 전체 기간 테스트 모드로 운영 | +| **데이터** | 실제 업무 데이터 | 검증용 테스트 데이터 | +| **과금** | 정식 과금 (운영 모드 전환 후) | 무과금 | + +### 1.3 단계별 관계 + +서비스 이관 완료 후 다음 순서로 진행한다: + +``` +서비스 이관 (개발) + └─ 베타테스트 (출시 전 검증) + └─ 정식 출시 + └─ 테넌트 온보딩 (고객 가입 시마다 반복) +``` + +--- + +## 2. 바로빌 온보딩 전체 흐름 + +### 2.1 단계별 프로세스 + +``` +Phase 1: 테넌트 계약 +┌──────────────────────────────────────────┐ +│ 고객사 SAM 서비스 계약 체결 │ +│ └─ SAM 테넌트 생성 (tenant_id 발급) │ +│ └─ 바로빌 서비스 이용 여부 확인 │ +└──────────────────────┬───────────────────┘ + ▼ +Phase 2: 바로빌 회원 등록 (테스트 모드) +┌──────────────────────────────────────────┐ +│ 바로빌 회원사 등록 (BarobillService) │ +│ ├─ 사업자번호, 상호, 대표자 등록 │ +│ ├─ 바로빌 ID/PW 생성 │ +│ ├─ server_mode = 'test' (기본값) │ +│ └─ 테스트 서버에서 연동 확인 │ +└──────────────────────┬───────────────────┘ + ▼ +Phase 3: 인증서 및 계좌/카드 연결 +┌──────────────────────────────────────────┐ +│ 공동인증서 등록 │ +│ ├─ getCertificateRegistUrl() → 고객 직접│ +│ ├─ 인증서 유효성 확인 │ +│ └─ 인증서 만료일 모니터링 설정 │ +│ │ +│ 계좌 연결 │ +│ ├─ getBankAccountScrapRequestUrl() │ +│ └─ 고객이 직접 계좌 등록 │ +│ │ +│ 카드 연결 │ +│ ├─ registCard() │ +│ └─ 카드사별 등록 │ +└──────────────────────┬───────────────────┘ + ▼ +Phase 4: 연동 검증 +┌──────────────────────────────────────────┐ +│ 테스트 모드에서 기능 확인 │ +│ ├─ 계좌 입출금 내역 조회 확인 │ +│ ├─ 카드 사용내역 조회 확인 │ +│ ├─ 홈택스 세금계산서 수집 확인 │ +│ └─ 문제 없으면 다음 단계 │ +└──────────────────────┬───────────────────┘ + ▼ +Phase 5: 운영 모드 전환 +┌──────────────────────────────────────────┐ +│ 관리자가 server_mode → 'production' 전환 │ +│ ├─ 운영 CERTKEY로 SOAP 재연결 │ +│ ├─ 실제 데이터 수집 시작 │ +│ └─ 과금 시작 (구독 등록) │ +└──────────────────────┬───────────────────┘ + ▼ +Phase 6: 실무 사용 시작 +┌──────────────────────────────────────────┐ +│ 정기 동기화 스케줄러 활성화 │ +│ ├─ 은행 거래 자동 수집 │ +│ ├─ 카드 내역 자동 수집 │ +│ ├─ 홈택스 세금계산서 자동 수집 │ +│ └─ 월정액 과금 자동 처리 │ +└──────────────────────────────────────────┘ +``` + +### 2.2 역할 분담 + +| 단계 | 수행 주체 | 설명 | +|------|----------|------| +| 테넌트 생성 | SAM 관리자 | MNG에서 테넌트 생성 | +| 회원사 등록 | SAM 관리자 또는 고객 | 사업자 정보 입력 | +| 인증서 등록 | **고객 직접** | 바로빌 제공 URL에서 직접 등록 | +| 계좌/카드 등록 | **고객 직접** | 바로빌 제공 URL에서 직접 등록 | +| 연동 검증 | SAM 관리자 | 테스트 모드에서 데이터 수집 확인 | +| 운영 전환 | SAM 관리자 | `server_mode` 변경 | + +--- + +## 3. 테스트 모드 활용 + +### 3.1 온보딩에서의 테스트 모드 역할 + +테스트 모드는 **온보딩 Phase 2~4에서 연동을 검증**하기 위해 사용한다. + +``` +✅ 바로빌 회원 등록이 정상적으로 되는지 확인 +✅ 인증서/계좌/카드 연결이 작동하는지 확인 +✅ API 호출이 정상 응답하는지 확인 +❌ 실제 세금계산서 발행 (국세청 미전송) +❌ 실제 거래 데이터 수집 (테스트 데이터만) +``` + +### 3.2 테스트 모드 체크리스트 + +Phase 4 (연동 검증) 완료 기준: + +- [ ] 바로빌 회원 상태: `active` +- [ ] 공동인증서: 등록됨 + 유효기간 확인 +- [ ] 계좌: 1개 이상 등록, 입출금 조회 응답 정상 +- [ ] 카드: 1개 이상 등록, 사용내역 조회 응답 정상 +- [ ] 홈택스: 매출/매입 세금계산서 수집 응답 정상 +- [ ] 에러 없이 모든 API 호출 성공 + +### 3.3 운영 전환 체크리스트 + +Phase 5 (운영 모드 전환) 전 확인: + +- [ ] 테스트 모드 검증 완료 +- [ ] 고객 동의 (실제 과금 시작 안내) +- [ ] 운영 CERTKEY 설정 확인 +- [ ] 구독 등록 (월정액 과금 설정) +- [ ] `server_mode` → `production` 전환 +- [ ] 운영 모드에서 첫 데이터 수집 성공 확인 + +--- + +## 4. 개발 시 주의사항 + +### 4.1 개발 단계에서의 테스트 모드 + +온보딩 프로세스와 별개로, **서비스 이관 개발 중에는 항상 테스트 모드를 사용**한다. + +| 단계 | 모드 | 이유 | +|------|------|------| +| 서비스 이관 개발 | 테스트 | 코드 검증, 무과금 | +| 베타테스트 | 테스트 | 실사용 시나리오 검증, 무과금 | +| 고객 온보딩 Phase 2~4 | 테스트 | 연동 설정 확인, 무과금 | +| 고객 온보딩 Phase 5~ | **운영** | 실무 사용, 과금 시작 | + +### 4.2 서비스 이관 완료 후 출시 순서 + +``` +1. 서비스 이관 개발 완료 (테스트 모드) +2. 내부 베타테스트 (tenant_id=1, 코드브릿지엑스, 테스트 모드) +3. 외부 베타테스트 (선별 고객 2~3곳, 테스트 모드) +4. 정식 출시 +5. 신규 고객 온보딩 프로세스 가동 (반복) +``` + +--- + +## 관련 문서 + +| 문서 | 설명 | +|------|------| +| [바로빌 연동 시스템](./README.md) | 전체 구조, 테스트/운영 모드, 과금 정책 | +| [바로빌 API 명세](../../frontend/api-specs/barobill-api.md) | REST API 42개 엔드포인트 | +| [데모 테넌트 정책](../sales/demo-tenant-policy.md) | 영업파트너 데모 테넌트 3-Tier 전략 | + +--- + +**최종 업데이트**: 2026-03-17 diff --git a/features/rd/README.md b/features/rd/README.md index 1483160..a095c96 100644 --- a/features/rd/README.md +++ b/features/rd/README.md @@ -20,6 +20,7 @@ R&D 메뉴는 SAM 플랫폼의 **연구개발 및 내부 도구** 모음이다. | **README.md** (이 문서) | 전체 개요, 메뉴 구조, 컨트롤러 매핑 | | [planning-design.md](planning-design.md) | 기획디자인 스토리보드 에디터 기술 명세 | | [design-insight.md](design-insight.md) | 디자인 인사이트 UI/UX 연구 도구 (100종 패턴, AI 프롬프트) | +| [fire-shutter-drawing-guide-rail.md](fire-shutter-drawing-guide-rail.md) | 방화셔터 도면 가이드레일 SVG/3D 렌더링 | ### 1.3 하위 메뉴 구조 @@ -35,7 +36,8 @@ R&D │ ├── 편집 /rd/ai-quotation/{id}/edit │ └── 문서 /rd/ai-quotation/{id}/document ├── 기획디자인 /rd/planning-design -└── 디자인 인사이트 /rd/design-insight +├── 디자인 인사이트 /rd/design-insight +└── 방화셔터 도면 /rd/fire-shutter-drawing ``` --- @@ -96,6 +98,7 @@ if ($request->header('HX-Request')) { | AI 견적 | Blade + Alpine.js | AiQuotationService | ai_quotations | 운영 중 | | **기획디자인** | **Blade + Alpine.js (SPA)** | **없음 (localStorage)** | **없음** | **운영 중** | | **디자인 인사이트** | **Blade + Alpine.js (SPA)** | **없음 (localStorage)** | **없음** | **운영 중** | +| **방화셔터 도면** | **Blade + JS (SVG/Three.js)** | **RdController** | **없음** | **운영 중** | --- @@ -103,6 +106,7 @@ if ($request->header('HX-Request')) { - [기획디자인 스토리보드 에디터](planning-design.md) — 블록 에디터, 서식, 인쇄, 내보내기 - [디자인 인사이트](design-insight.md) — UI/UX 연구 도구 (100종 패턴, AI 프롬프트 복사) +- [방화셔터 도면 가이드레일](fire-shutter-drawing-guide-rail.md) — 가이드레일 SVG/3D 렌더링 기술 명세 - [조직도 관리 기술문서](../../projects/org-chart/) — 조직도 시스템 상세 (별도 프로젝트 문서) --- diff --git a/features/rd/fire-shutter-drawing-guide-rail.md b/features/rd/fire-shutter-drawing-guide-rail.md new file mode 100644 index 0000000..a279ade --- /dev/null +++ b/features/rd/fire-shutter-drawing-guide-rail.md @@ -0,0 +1,203 @@ +# 방화셔터 도면 — 가이드레일 렌더링 + +> **작성일**: 2026-03-16 +> **상태**: 운영 중 +> **파일**: `mng/resources/views/rd/fire-shutter-drawing/index.blade.php` +> **라우트**: `GET /rd/fire-shutter-drawing` + +--- + +## 1. 개요 + +### 1.1 목적 + +방화셔터 가이드레일의 **2D 평면도(SVG)**와 **3D 렌더링(Three.js)**을 구현한다. +제품 유형(스크린형/철재스라트)에 따라 다른 프로파일을 렌더링하며, 각 부재(마감재, 본체, C형, 벽연형)의 절곡 치수를 시각화한다. + +### 1.2 제품 유형별 차이 + +| 항목 | 스크린형 | 철재스라트 | +|------|---------|-----------| +| 본체 형상 | C채널 (lip-flange-sideWall-backWall) | 15세그먼트 절곡 프로파일 | +| 마감재 절곡 | 10-11-110-30-15-15-15 (J-hook) | 10-13-120-25-15 (상단) / +19-14-15 (하단) | +| 벽연결 부재 | ③ C형 30-45-30 + ④ D형 11-23-40-23-11 | ④ 벽연형 30-45-30 | +| 전체 치수 | depth × width (가변) | 130mm × 75mm | + +--- + +## 2. 철재스라트 가이드레일 + +### 2.1 부재 구성 + +``` +┌──────────────────────────────────────────────────┐ +│ ① 마감재 SUS 1.2T (빨간색, 상/하 2장) │ +│ ┌────────────────────────────────────────────┐ │ +│ │ ② 본체 EGI 1.55T (회색, 15세그먼트 절곡) │ │ +│ │ ┌──────────────────────────────────────┐ │ │ +│ │ │ 개구부 (슬랫 통과 공간) │ │ │ +│ │ └──────────────────────────────────────┘ │ │ +│ └────────────────────────────────────────────┘ │ +│ │ +│ ④ 벽연형 EGI 1.55T (갈색, ㄷ자 30-45-30) │ +│ ■■■■■ ← 방화벽 │ +└──────────────────────────────────────────────────┘ +``` + +### 2.2 ② 본체 절곡 프로파일 (15세그먼트) + +정석 도면 기준, 시작점 `(0, 60)`: + +| Seg | 방향 | 치수(mm) | 좌표 | 설명 | +|-----|------|---------|------|------| +| 1 | 10→ | 10 | (0,60)→(10,60) | 좌측 립 | +| 2 | 60↑ | 60 | (0,60)→(0,0) | 좌측벽 상부 | +| 3 | 90→ | 90 | (0,0)→(90,0) | 상단 플랜지 | +| 4 | 21↓ | 21 | (90,0)→(90,21) | 상부 립 | +| 5 | 78← | 78 | (90,21)→(12,21) | **상부 내부 선반 (넓은)** | +| 6 | 30↓ | 30 | (12,21)→(12,51) | 내부 벽 | +| 7 | 43→ | 43 | (12,51)→(55,51) | **하부 내부 선반** | +| 8 | 15↓ | 15 | (55,51)→(55,66) | 스텝 하강 | +| 9 | 20→ | 20 | (55,66)→(75,66) | 스텝 수평 | +| 10 | 15↑ | 15 | (75,66)→(75,51) | 스텝 상승 | +| 11 | 15→ | 15 | (75,51)→(90,51) | 스텝 수평 | +| 12 | 21↓ | 21 | (90,51)→(90,72) | 하부 립 | +| 13 | 90← | 90 | (90,72)→(0,72) | 하단 플랜지 | +| 14 | 12↑ | 12 | (0,72)→(0,60) | 좌측벽 하부 | +| 15 | 10→ | 10 | (0,60)→(10,60) | 립 (Seg1과 겹침) | + +> **핵심**: 내부 개구부(스텝 구조)가 **하부**(y=51~66)에 위치한다. 상부(y=21)에는 넓은 78mm 선반, 하부에는 43mm 선반 + 15-20-15-15 스텝이 배치된다. + +### 2.3 ① 마감재 절곡 (SUS 1.2T) + +**상단**: `10←lip + 13↓tab + 120→body + 25↓ + 15←` +**하단**: `10←lip + 13↑tab + 120→body + 25↑ + 19← + 14↓ + 15←` + +### 2.4 ④ 벽연형 (EGI 1.55T) + +ㄷ자 형태: `30(깊이) × 45(높이)`, 우측 열림. 본체 좌측에 위치, 세로 중앙 정렬. + +--- + +## 3. 2D 평면도 (SVG) 구현 + +### 3.1 좌표계 + +``` +X축: 깊이 (LEFT=벽/방화벽 → RIGHT=개구부/실내) +Y축: 높이 (TOP → BOTTOM) +스케일: sc = 4 (1mm = 4px) +``` + +### 3.2 본체 위치 계산 + +```javascript +const ox2 = w4x + w4depth + (7 + 0.75) * sc; +// ④ 벽연형 끝에서 7mm + 반두께(0.75mm) 간격 +``` + +### 3.3 색상 체계 + +| 부재 | 색상 | HEX | +|------|------|-----| +| ② 본체 EGI | 회색 | `#4b5563` (fill) / `#94a3b8` (stroke) | +| ① 마감재 SUS | 빨간색 | `#ef4444` | +| ④ 벽연형 EGI | 갈색 | `#8b6c5c` | + +### 3.4 치수 라벨 + +각 부재의 절곡 치수를 **해당 부재 색상**으로 표시한다: +- ② 본체: 회색(`#94a3b8`)으로 14개 세그먼트 치수 +- ① 마감재: 빨간색(`#ef4444`)으로 상/하단 각 7개 치수 +- ④ 벽연형: 갈색(`#8b6c5c`)으로 30 × 45 + +--- + +## 4. 3D 렌더링 (Three.js) 구현 + +### 4.1 좌표계 매핑 + +``` +2D 평면도 → 3D Shape (ExtrudeGeometry) +────────────────────────────────────────────── +plan_y (높이 0→72) → X (0 → rw=75, 중앙 정렬) +plan_x (깊이 0→90) → Y (반전: Y = bYO + 90 - plan_x) + Y=0: 개구부/실내, Y=rd: 벽 +``` + +### 4.2 본체 세그먼트 변환 헬퍼 + +```javascript +function bSeg(px, py, pw, ph) { + // 평면도 좌표 (px, py, pw, ph) → THREE.Shape 좌표 + const x1 = bXO + py, x2 = bXO + py + ph; + const y1 = bYO + 90 - px - pw, y2 = bYO + 90 - px; + const s = new THREE.Shape(); + s.moveTo(x1,y1); s.lineTo(x2,y1); + s.lineTo(x2,y2); s.lineTo(x1,y2); s.lineTo(x1,y1); + return s; +} +``` + +### 4.3 재질 + +| 부재 | Material | 속성 | +|------|----------|------| +| ② 본체 / ④ 벽연형 | `MeshStandardMaterial` | color: `0x64748b`, metalness: 0.5, roughness: 0.4 | +| ① 마감재 SUS | `MeshStandardMaterial` | color: `0x9ca3af`, metalness: 0.7, roughness: 0.25 | + +### 4.4 배치 + +```javascript +// 좌측 레일: 셔터 중심에서 -hw 위치 +railGroupL.position.set(-hw - rw/2, 0, rd/2); +// 우측 레일: scale.x = -1 (좌우 반전) +railGroupR.position.set(hw + rw/2, 0, rd/2); +``` + +--- + +## 5. 스크린형 가이드레일 + +### 5.1 부재 구성 + +| 부재 | 색상 | 절곡 치수 | +|------|------|----------| +| ② 가이드레일 EGI | 파란색 `#3b82f6` | lip-flange-sideWall-backWall (가변) | +| ① 마감재 SUS | 빨간색 `#ef4444` | 10-11-110-30-15-15-15 (J-hook) | +| ③ C형 EGI | 초록색 `#22c55e` | 30-45-30 | +| ④ D형 EGI | 주황색 `#f97316` | 11-23-40-23-11 | + +### 5.2 치수 라벨 + +각 부재 색상에 맞춰 모든 절곡 치수를 `font-size="7"` 라벨로 표시한다. + +--- + +## 6. 소스 코드 위치 + +| 함수/섹션 | 줄 번호 (대략) | 설명 | +|----------|-------------|------| +| 스크린형 2D 평면도 | ~830~1055 | SVG 렌더링 (bodySvg, bk3Svg, bk4Svg, trim1Svg) | +| 철재스라트 2D 평면도 | ~1058~1320 | SVG 렌더링 (② 본체 15세그먼트, ①, ④) | +| `renderGrFront()` | ~1330 | 정면도 SVG | +| `createRailGroup()` | ~2639 | 3D 가이드레일 생성 (스크린/철재 분기) | +| 철재 3D 프로파일 | ~2795~2816 | `bSeg()` 헬퍼로 15세그먼트 + ④ + ① | + +--- + +## 7. 참조 자료 + +- 정석 도면: 가이드레일 본체 (EGI 1.55mm) 절곡도 +- 치수: 90(상단) - 21(상부립) - 78(선반) - 30(내부벽) - 43(선반) - 15-20-15-15(스텝) - 21(하부립) - 90(하단) - 12(좌측하) - 10(립) - 60(좌측상) + +--- + +## 관련 문서 + +- [R&D 메뉴 README](README.md) — R&D 전체 메뉴 구조 +- [기획디자인 스토리보드](planning-design.md) — 블록 에디터 + +--- + +**최종 업데이트**: 2026-03-16 diff --git a/features/sales/demo-tenant-policy.md b/features/sales/demo-tenant-policy.md index b769361..308e202 100644 --- a/features/sales/demo-tenant-policy.md +++ b/features/sales/demo-tenant-policy.md @@ -101,7 +101,6 @@ | 사용자 초대 | ✅ | 최대 5명 | | 리포트/통계 | ✅ | 제한 없음 | | 바로빌 연동 | ❌ | 실제 금융 연동 차단 | -| 이카운트 연동 | ❌ | 외부 시스템 연동 차단 | | 파일 저장 | ✅ | 최대 1GB | | AI 토큰 | ✅ | 월 10만 토큰 | @@ -184,7 +183,7 @@ class DemoLimitMiddleware // 2. 수량 제한 체크 $limits = $tenant->demo_limits; - // 3. 금지 기능 체크 (바로빌, 이카운트 등) + // 3. 금지 기능 체크 (바로빌 등 외부 연동) if ($this->isBlockedFeature($request)) { return response()->json(['error' => '데모에서 사용할 수 없는 기능입니다.'], 403); } @@ -226,7 +225,7 @@ class DemoDataSeeder 3. demo_expires_at = NULL 4. subscription → status='active', plan='starter'/'business' 5. 기존 데이터 유지 (마이그레이션 불필요) - 6. 추가 기능 활성화 (바로빌, 이카운트 등) + 6. 추가 기능 활성화 (바로빌 등 외부 연동) ``` --- diff --git a/features/sales/demo-tenant-usage-guide.md b/features/sales/demo-tenant-usage-guide.md index d5a1449..89537f4 100644 --- a/features/sales/demo-tenant-usage-guide.md +++ b/features/sales/demo-tenant-usage-guide.md @@ -141,7 +141,7 @@ POST /api/v1/demo-tenants/{id}/convert |------|---------|---------| | 테넌트 유형 | `DEMO_TRIAL` | `STD` (정식) | | 만료일 | 30일 제한 | 제한 없음 | -| 기능 제한 | 바로빌/이카운트 차단 | 전체 기능 사용 | +| 기능 제한 | 바로빌 등 외부 연동 차단 | 전체 기능 사용 | | 데이터 | 그대로 유지 | 그대로 유지 | > 고객이 체험 중 입력한 데이터가 정식 환경에 그대로 이어진다. 데이터 재입력이 불필요하다. @@ -290,7 +290,7 @@ php artisan demo:check-inactive --days=3 ``` 1. POST /{id}/convert 로 정식 전환 2. 고객 데이터는 그대로 유지됨 (재입력 불필요) -3. 바로빌, 이카운트 등 외부 연동 기능 활성화 +3. 바로빌 등 외부 연동 기능 활성화 ``` ### 7.4 체험 기간 부족 시 diff --git a/features/sales/stock-production.md b/features/sales/stock-production.md new file mode 100644 index 0000000..8780539 --- /dev/null +++ b/features/sales/stock-production.md @@ -0,0 +1,168 @@ +# 재고생산관리 + +> **작성일**: 2026-03-16 +> **상태**: 설계 확정 + +--- + +## 1. 개요 + +### 1.1 목적 + +수주 없이 **재고 목적으로 생산**하는 경우를 관리하는 기능이다. + +SAM 시스템은 `수주 → 작업지시 → 생산`의 흐름으로 동작하므로, 수주가 없으면 작업지시를 생성할 수 없다. 재고생산관리는 **내부 오더(Internal Order)** 개념으로, 재고생산도 일종의 수주로 취급하여 기존 생산 흐름을 그대로 활용한다. + +### 1.2 핵심 원칙 + +- 기존 `orders` 테이블을 **공유**한다 (별도 테이블 없음) +- `order_type_code = 'STOCK'`으로 일반 수주(`ORDER`)와 구분한다 +- 하류 시스템(작업지시, 생산, 출하, 품질검사)은 **변경 없이 동작**한다 +- 화면은 수주관리를 **단순화**한 형태이다 + +--- + +## 2. 수주관리와의 관계 + +### 2.1 테이블 공유 구조 + +``` +orders 테이블 +├── order_type_code = 'ORDER' → 수주관리 (거래처 주문) +├── order_type_code = 'PURCHASE' → 발주관리 +└── order_type_code = 'STOCK' → 재고생산관리 (내부 오더) +``` + +### 2.2 기능 비교 + +| 항목 | 수주관리 (ORDER) | 재고생산관리 (STOCK) | +|------|-----------------|---------------------| +| 거래처 | ✅ 필수 | ❌ 불필요 | +| 견적 연결 | ✅ 가능 | ❌ 불필요 | +| 현장/납기/배송 | ✅ 사용 | ❌ 불필요 | +| 할인 | ✅ 적용 | ❌ 불필요 | +| 금액 계산 | ✅ 자동 | ❌ 불필요 (단가 0 가능) | +| 매출 인식 | ✅ 자동/수동 | ❌ 생성 안 함 | +| 개소/구역 (OrderNode) | ✅ N-depth 트리 | ❌ 불필요 | +| 품목 등록 | ✅ 상세 | ✅ 품목 + 수량만 | +| 작업지시 생성 | ✅ 동일 | ✅ 동일 | +| 생산/출하/품질검사 | ✅ 동일 | ✅ 동일 | +| 채번 접두사 | `ORD` | `STK` | + +### 2.3 재고생산 전용 필드 + +`orders.options` JSON에 재고생산 전용 속성을 저장한다: + +| 필드 | 타입 | 설명 | +|------|------|------| +| `production_reason` | string | 생산 사유 (예: "시즌 대비", "안전재고 확보") | +| `target_stock_qty` | number | 목표 재고 수량 | + +--- + +## 3. 업무 흐름 + +``` +재고생산 등록 (DRAFT) + │ order_type_code = 'STOCK' + │ 품목 + 수량만 입력 + ↓ +재고생산 확정 (CONFIRMED) + │ ※ 매출 생성 안 함 (일반 수주와 차이) + ↓ +생산지시 생성 (WorkOrder) + │ 기존 수주→생산지시 흐름 동일 + ↓ +생산 실행 → 품질검사 → 출하 + │ 기존 생산관리 흐름 동일 + ↓ +완료 (COMPLETED) +``` + +--- + +## 4. 메뉴 위치 + +``` +판매관리 +├── 거래처관리 +├── 견적관리 +├── 수주관리 +├── 재고생산관리 ← 신규 +└── 단가관리 +``` + +--- + +## 5. 재공품(WIP) 개념 + +재고생산의 대상 품목은 **재공품(Work-In-Process)**이다. + +- 수주를 받지 않았지만, 회사 내에서 **이미 정해진 절곡품**을 미리 생산 +- 작업자들의 **유휴시간에 앞으로 나갈 물건을 미리 제작**하는 행위 +- 실제 수주가 들어오면 이미 만들어둔 재공품을 사용하여 **납기 단축** + +``` +유휴시간 → 재공품 미리 생산 → 재고 적재 + ↓ +실제 수주 → 재고에서 재공품 사용 → 납기 단축 +``` + +### 5.1 현재 구현 범위 (Phase 1) + +- ✅ 재고생산 등록/목록/상세/수정/삭제 +- ✅ 생산지시 생성 (절곡 공정 자동 선택) +- ✅ 생산지시 목록에 표시 +- ✅ 작업지시 목록에 표시 +- ✅ 생산현황판에 표시 +- ✅ 작업실적 조회에 표시 + +### 5.2 향후 과제 (Phase 2) + +> **작업자 화면 절곡 탭 — 재공품 사양 정보 연동** + +현재 STOCK 건은 OrderNode(개소)가 없어 BendingInfoBuilder가 동작하지 않는다. +절곡 작업자 화면에서 다음 정보가 누락된다: + +| 누락 정보 | 원인 | 해결 방향 | +|----------|------|----------| +| W/H (가로/세로) | OrderNode.options 없음 | 품목 마스터에 규격 정보 보유 → 등록 시 가져오기 | +| bending_info | BendingInfoBuilder 실패 (rootNodes 없음) | 품목별 표준 BOM 활용 또는 수동 입력 | +| 동적 자재 목록 | dynamic_bom 미생성 | 품목별 표준 BOM에서 자재 목록 생성 | +| 제품코드 | nodeOptions 없음 | 품목 마스터의 item_code 활용 | + +**해결 전략**: 재공품은 이미 정해진 규격품이므로, 품목관리의 품목 정보(규격, BOM)를 +재고생산 등록 시 `work_order_item.options`에 채워넣는 방식으로 해결 가능. + +--- + +## 6. API + +기존 수주관리 API를 그대로 사용한다. `order_type=STOCK` 파라미터로 필터링한다. + +> **상세 API 명세**: `frontend/api-specs/stock-production-api.md` + +--- + +## 7. 영향범위 검토 결과 + +| 메뉴 | 수정 필요 | 비고 | +|------|:--------:|------| +| 재고생산관리 (신규) | ✅ React 구현 | 수주 화면 단순화 | +| 생산지시 목록 | ⚠️ 소규모 | 납기/거래처 `-` 표시 (프론트) | +| 생산현황판 | ❌ 없음 | project_name='재고생산' 정상 표시 | +| 작업지시 목록 | ❌ 없음 | null fallback 처리 완비 | +| 작업실적 조회 | ❌ 없음 | Order 정보 미참조 | +| 작업자 화면 (절곡) | ⚠️ Phase 2 | bending_info/W/H 누락 (향후 과제) | + +--- + +## 관련 문서 + +- [재고생산관리 API 명세](../../frontend/api-specs/stock-production-api.md) +- [수주 DB 스키마](../../system/database/sales.md) +- [생산 DB 스키마](../../system/database/production.md) + +--- + +**최종 업데이트**: 2026-03-16 diff --git a/frontend/api-specs/stock-production-api.md b/frontend/api-specs/stock-production-api.md new file mode 100644 index 0000000..b6212c7 --- /dev/null +++ b/frontend/api-specs/stock-production-api.md @@ -0,0 +1,369 @@ +# 재고생산관리 API 명세 + +> **작성일**: 2026-03-16 +> **상태**: 설계 확정 +> **대상**: React 프론트엔드 개발자 + +--- + +## 1. 개요 + +### 1.1 목적 + +재고생산관리는 **수주 없이 재고 목적으로 생산**하는 경우를 위한 기능이다. +기존 수주관리(Order) API를 **그대로 사용**하되, `order_type_code: 'STOCK'`으로 구분한다. + +### 1.2 핵심 원칙 + +- 별도 API 엔드포인트 없음 — 기존 `/api/v1/orders` 사용 +- `order_type_code` 필터로 수주(`ORDER`)와 재고생산(`STOCK`)을 분리 +- 화면은 수주관리를 **단순화**한 형태 (거래처, 견적, 배송, 할인 등 불필요) +- 하류 시스템(작업지시, 생산, 출하)은 **동일하게 동작** + +--- + +## 2. API 엔드포인트 + +> **기본 URL**: `/api/v1/orders` +> **인증**: `Bearer Token` (Sanctum) + `API Key` + +### 2.1 목록 조회 + +``` +GET /api/v1/orders?order_type=STOCK +``` + +| 파라미터 | 타입 | 필수 | 설명 | +|----------|------|:----:|------| +| `order_type` | string | ✅ | `STOCK` 고정 | +| `page` | int | - | 페이지 (기본: 1) | +| `size` | int | - | 페이지 크기 (기본: 20) | +| `q` | string | - | 검색어 (생산번호, 메모) | +| `status` | string | - | 상태 필터 (`DRAFT`, `CONFIRMED` 등) | +| `date_from` | date | - | 등록일 시작 | +| `date_to` | date | - | 등록일 종료 | + +**응답 예시**: + +```json +{ + "success": true, + "message": "message.order.fetched", + "data": { + "data": [ + { + "id": 42, + "order_no": "STK202603160001", + "order_type_code": "STOCK", + "status_code": "DRAFT", + "quantity": "100.0000", + "memo": "봄 시즌 대비 재고 확보", + "options": { + "production_reason": "시즌 대비", + "target_stock_qty": 500 + }, + "items": [ + { + "id": 1, + "item_name": "25mm 알루미늄 블라인드", + "specification": "W1000 x H2000", + "quantity": "100.0000", + "unit_price": "15000.00" + } + ], + "created_at": "2026-03-16T10:30:00Z" + } + ], + "current_page": 1, + "last_page": 1, + "total": 1 + } +} +``` + +--- + +### 2.2 통계 조회 + +``` +GET /api/v1/orders/stats?order_type=STOCK +``` + +| 파라미터 | 타입 | 필수 | 설명 | +|----------|------|:----:|------| +| `order_type` | string | ✅ | `STOCK` 고정 | + +**응답 예시**: + +```json +{ + "success": true, + "data": { + "total": 15, + "draft": 3, + "confirmed": 5, + "in_progress": 4, + "completed": 2, + "cancelled": 1, + "total_amount": 0, + "confirmed_amount": 0 + } +} +``` + +--- + +### 2.3 생성 + +``` +POST /api/v1/orders +``` + +**요청 본문**: + +```json +{ + "order_type_code": "STOCK", + "memo": "봄 시즌 대비 재고 확보", + "options": { + "production_reason": "시즌 대비", + "target_stock_qty": 500 + }, + "items": [ + { + "item_id": 10, + "item_name": "25mm 알루미늄 블라인드", + "specification": "W1000 x H2000", + "quantity": 100, + "unit_price": 0, + "unit": "EA" + } + ] +} +``` + +**필수 필드**: + +| 필드 | 타입 | 필수 | 설명 | +|------|------|:----:|------| +| `order_type_code` | string | ✅ | `STOCK` 고정 | +| `items` | array | ✅ | 생산할 품목 목록 | +| `items[].item_name` | string | ✅ | 품목명 | +| `items[].quantity` | number | ✅ | 수량 | +| `items[].unit_price` | number | ✅ | 단가 (재고생산은 `0` 가능) | + +**선택 필드**: + +| 필드 | 타입 | 설명 | +|------|------|------| +| `memo` | string | 비고 | +| `options.production_reason` | string | 생산 사유 | +| `options.target_stock_qty` | number | 목표 재고 수량 | +| `items[].item_id` | int | 품목 마스터 ID | +| `items[].specification` | string | 규격 | +| `items[].unit` | string | 단위 | + +**사용하지 않는 필드** (수주 전용): + +``` +❌ client_id, client_name, client_contact → 거래처 없음 +❌ site_name → API가 '재고생산'으로 자동 설정 +❌ quote_id → 견적 없음 +❌ delivery_date, delivery_method_code → 납기/배송 불필요 +❌ discount_rate, discount_amount → 할인 없음 +❌ sales_recognition → 매출 인식 불필요 +❌ options.shipping_cost_code → 운임비용 불필요 +❌ options.receiver, receiver_contact → 수신자 불필요 +❌ options.shipping_address → 배송지 불필요 +``` + +> **자동 생성**: `order_no`는 `STK{YYYYMMDD}{NNNN}` 형식으로 서버에서 자동 생성 + +--- + +### 2.4 단건 조회 + +``` +GET /api/v1/orders/{id} +``` + +기존 수주 조회와 동일. `order_type_code`가 `STOCK`인지 프론트에서 확인. + +--- + +### 2.5 수정 + +``` +PUT /api/v1/orders/{id} +``` + +생성과 동일한 필드 사용. `order_type_code`는 변경하지 않는다. + +--- + +### 2.6 삭제 + +``` +DELETE /api/v1/orders/{id} +``` + +기존 수주 삭제와 동일. + +--- + +### 2.7 상태 변경 + +``` +PATCH /api/v1/orders/{id}/status +``` + +```json +{ + "status": "CONFIRMED" +} +``` + +**상태 흐름** (수주와 동일): + +``` +DRAFT → CONFIRMED → IN_PROGRESS → COMPLETED + └─────→ CANCELLED ──→ DRAFT (복구) +``` + +> **재고생산 특수**: `CONFIRMED` 상태 진입 시 매출 자동 생성이 **발생하지 않음** + +--- + +### 2.8 생산지시 생성 + +``` +POST /api/v1/orders/{id}/production-order +``` + +재고생산은 **절곡 공정이 자동 선택**된다 (API에서 처리). `process_ids` 전달 불필요. + +```json +{ + "priority": "normal", + "memo": "재고생산 작업" +} +``` + +--- + +**API 자동 처리 항목** (STOCK 타입): + +| 항목 | 일반 수주 | 재고생산 (자동) | +|------|----------|---------------| +| 현장명 (`project_name`) | `site_name` 또는 `client_name` | `'재고생산'` 고정 | +| 공정 | BOM item_id → process_items 매칭 | **절곡 공정 자동 선택** | +| 작업예정일 (`scheduled_date`) | `delivery_date` | **생성일 (now())** | +| 매출 생성 | `sales_recognition` 정책 적용 | **생성 안 함** | + +> 프론트에서 `process_ids`, `scheduled_date`를 전달하지 않아도 API가 자동 처리 + +--- + +## 3. 채번 규칙 + +| 주문 유형 | 접두사 | 예시 | +|----------|--------|------| +| 수주 (ORDER) | `ORD` | `ORD202603160001` | +| 재고생산 (STOCK) | `STK` | `STK202603160001` | + +--- + +## 4. 화면 설계 가이드 + +### 4.1 수주관리 화면 vs 재고생산관리 화면 + +``` +┌─ 수주관리 ──────────────────┐ ┌─ 재고생산관리 ───────────────┐ +│ │ │ │ +│ [거래처 정보] │ │ [생산 정보] │ +│ - 거래처 선택 │ │ - 생산 사유 (텍스트) │ +│ - 현장명 │ │ - 목표 재고 수량 │ +│ - 배송/납기일 │ │ - 비고 │ +│ - 운임비용 │ │ │ +│ - 견적 연결 │ ├──────────────────────────────┤ +│ - 할인 │ │ [품목 목록] │ +│ - 매출 인식 방식 │ │ - 품목 선택 │ +│ │ │ - 수량 │ +│ [개소/구역 (OrderNode)] │ │ - 규격 │ +│ - N-depth 트리 구조 │ │ │ +│ │ │ (단가/금액/할인 불필요) │ +│ [품목 목록] │ │ (개소/구역 불필요) │ +│ - 품목, 수량, 단가, 할인 │ │ │ +│ - floor_code, symbol_code │ └──────────────────────────────┘ +│ - 금액 계산 │ +│ │ +└──────────────────────────────┘ +``` + +### 4.2 목록 페이지 표시 컬럼 + +| 컬럼 | 설명 | +|------|------| +| 생산번호 | `order_no` (STK...) | +| 상태 | `status_code` (상태 배지) | +| 품목 | 대표 품목명 + (외 N건) | +| 수량 | 총 수량 | +| 생산 사유 | `options.production_reason` | +| 등록일 | `created_at` | + +### 4.3 상태 배지 색상 (수주와 동일) + +| 상태 | 라벨 | 색상 | +|------|------|------| +| `DRAFT` | 등록 | gray | +| `CONFIRMED` | 확정 | blue | +| `IN_PROGRESS` | 진행중 | yellow | +| `IN_PRODUCTION` | 생산중 | orange | +| `PRODUCED` | 생산완료 | green | +| `COMPLETED` | 완료 | green | +| `CANCELLED` | 취소 | red | + +--- + +## 5. 구현 체크리스트 + +### 프론트엔드 (React) + +- [ ] 재고생산관리 메뉴/라우트 추가 +- [ ] 목록 페이지: `GET /api/v1/orders?order_type=STOCK` +- [ ] 통계 카드: `GET /api/v1/orders/stats?order_type=STOCK` +- [ ] 생성 폼: `order_type_code: 'STOCK'` 필수 전송 +- [ ] 상세/수정 페이지: 수주 화면 단순화 (거래처/견적/배송/할인 제거) +- [ ] 생산지시 생성 버튼: `POST /api/v1/orders/{id}/production-order` +- [ ] 상태 변경: `PATCH /api/v1/orders/{id}/status` + +### 프론트엔드 — 생산지시 목록 수정 + +- [ ] 생산지시 목록에서 `order_type_code`가 `STOCK`인 건: 납기 컬럼 `-` 표시 +- [ ] 생산지시 생성 UI: STOCK 수주는 공정 선택 불필요 (API가 절곡 자동 선택) + +### 백엔드 (API) — 완료 + +- [x] `Order::TYPE_STOCK = 'STOCK'` 상수 추가 +- [x] StoreOrderRequest에 `STOCK` validation 추가 +- [x] UpdateOrderRequest에 `STOCK` validation 추가 +- [x] 재고생산 채번: `STK{YYYYMMDD}{NNNN}` +- [x] stats()에 `order_type` 필터 추가 +- [x] STOCK 타입 확정 시 매출 자동 생성 스킵 +- [x] options에 `production_reason`, `target_stock_qty` 필드 추가 +- [x] store()에서 STOCK 타입 `site_name = '재고생산'` 자동 설정 +- [x] createProductionOrder()에서 STOCK: `project_name = '재고생산'` 고정 +- [x] createProductionOrder()에서 STOCK: 절곡 공정 자동 선택 +- [x] createProductionOrder()에서 STOCK: `scheduled_date = now()` 자동 설정 + +--- + +## 관련 문서 + +- 수주관리: 기존 수주 API는 동일 엔드포인트 (`/api/v1/orders`) +- 작업지시: `POST /api/v1/orders/{id}/production-order` +- 품목관리: `rules/item-policy.md` + +--- + +**최종 업데이트**: 2026-03-16 diff --git a/guides/generate-pricing-guide.cjs b/guides/generate-pricing-guide.cjs index c29462a..f0f081f 100644 --- a/guides/generate-pricing-guide.cjs +++ b/guides/generate-pricing-guide.cjs @@ -172,7 +172,6 @@ async function main() { ['QR코드 관리', '1,020만원', '5만원'], ['사진/출하 관리', '1,920만원', '10만원'], ['검사/토큰 적용', '1,020만원', '5만원'], - ['이카운트 연동', '1,920만원', '10만원'], ]; // 테이블 헤더 @@ -291,7 +290,6 @@ async function main() { s5.addText('단체 가입', { x: 5.2, y: 2.85, w: 4.3, h: 0.45, fontSize: 14, bold: true, color: C.orange, align: 'center', valign: 'middle', fontFace: 'Arial' }); const groupItems = [ ['단체 수당', '30%', C.orange], - ['유치 파트너 수당', '3%', C.blue], ]; groupItems.forEach((item, i) => { const iy = 3.4 + i * 0.45; @@ -307,7 +305,7 @@ async function main() { s5.addShape(pres.ShapeType.roundRect, { x: 1.5, y: 4.75, w: 2, h: 0.35, rectRadius: 0.06, fill: { color: C.green } }); s5.addText('합계 25%', { x: 1.5, y: 4.75, w: 2, h: 0.35, fontSize: 11, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: 'Arial' }); s5.addShape(pres.ShapeType.roundRect, { x: 6.2, y: 4.75, w: 2, h: 0.35, rectRadius: 0.06, fill: { color: C.orange } }); - s5.addText('합계 33%', { x: 6.2, y: 4.75, w: 2, h: 0.35, fontSize: 11, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: 'Arial' }); + s5.addText('합계 30%', { x: 6.2, y: 4.75, w: 2, h: 0.35, fontSize: 11, bold: true, color: C.white, align: 'center', valign: 'middle', fontFace: 'Arial' }); // ═══════════════════════════════════════════════════════ // 슬라이드 6: 수당 계산 예시 @@ -442,14 +440,13 @@ async function main() { const s8 = pres.addSlide(); s8.background = { fill: C.white }; addFooter(s8); - addPageTitle(s8, '고객에게 제안할 수 있는 할인 4가지'); + addPageTitle(s8, '고객에게 제안할 수 있는 할인 3가지'); addSlideNumber(s8, 8, TOTAL); const discounts = [ { title: '개발비 할인', desc: '%, 정액, 전액면제', impact: '수당 영향 있음', impactColor: C.red, bg: C.redBg, border: 'FFCDD2', color: C.red, icon: '1' }, { title: '구독료 할인', desc: '최대 50%까지', impact: '수당 영향 없음', impactColor: C.green, bg: C.greenBg, border: C.greenBorder, color: C.green, icon: '2' }, - { title: '무료 체험', desc: '1주일(7일)', impact: '수당 영향 없음', impactColor: C.green, bg: C.blueBg, border: C.blueBorder, color: C.blue, icon: '3' }, - { title: '개발비-구독료 연동', desc: 'ON/OFF 선택', impact: '개발비 변동 시 영향', impactColor: 'F57F17', bg: C.orangeBg, border: C.orangeBorder, color: C.orange, icon: '4' }, + { title: '개발비-구독료 연동', desc: 'ON/OFF 선택', impact: '개발비 변동 시 영향', impactColor: 'F57F17', bg: C.orangeBg, border: C.orangeBorder, color: C.orange, icon: '3' }, ]; discounts.forEach((d, i) => { @@ -473,7 +470,7 @@ async function main() { s8.addShape(pres.ShapeType.roundRect, { x: 0.5, y: 4.3, w: 9, h: 0.6, rectRadius: 0.08, fill: { color: 'E8F5E9' }, line: { color: 'A5D6A7', width: 0.5 } }); s8.addText([ { text: '💡 영업 팁: ', options: { fontSize: 11, bold: true, color: C.green } }, - { text: '구독료 할인 + 무료 체험은 고객에게 혜택을 주면서 내 수당은 안 줄어드는 좋은 전략!', options: { fontSize: 11, color: '1B5E20' } }, + { text: '구독료 할인은 고객에게 혜택을 주면서 내 수당은 안 줄어드는 좋은 전략!', options: { fontSize: 11, color: '1B5E20' } }, ], { x: 0.7, y: 4.3, w: 8.6, h: 0.6, valign: 'middle', fontFace: 'Arial' }); // ═══════════════════════════════════════════════════════ @@ -499,7 +496,7 @@ async function main() { ], { x: 0.5, y: 1.2, w: 9, h: 0.7, align: 'center', valign: 'middle', fontFace: 'Arial' }); // 실전 예시 - s9.addText('실전 예시: 제조업 기본 패키지, 10% 할인, 무료 체험 1주일', { + s9.addText('실전 예시: 제조업 기본 패키지, 10% 할인', { x: 0.5, y: 2.1, w: 9, h: 0.35, fontSize: 11, bold: true, color: C.text, fontFace: 'Arial' }); @@ -508,9 +505,9 @@ async function main() { ['개발비 할인 10%', '2,000 × 10%', '-200만원', C.red], ['최종 개발비', '', '1,800만원', C.green], ['월 구독료', '', '50만원', C.blue], - ['유료 개월수', '12 - 7일(무료)', '약 11.77개월', 'CE93D8'], - ['연간 구독료', '50 × 11.77', '약 588만원', C.blue], - ['1년차 총 비용', '1,800 + 588', '2,388만원', C.orange], + ['유료 개월수', '12개월', '12개월', 'CE93D8'], + ['연간 구독료', '50 × 12', '600만원', C.blue], + ['1년차 총 비용', '1,800 + 600', '2,400만원', C.orange], ]; calcData.forEach((row, i) => { @@ -602,7 +599,7 @@ async function main() { // 4 Steps const steps = [ { num: '1', title: '상품 고르기', desc: '필수 상품 자동체크\n추가 상품 선택', color: C.green, bg: C.greenBg }, - { num: '2', title: '할인 설정', desc: '개발비/구독료 할인\n무료 체험 기간', color: C.blue, bg: C.blueBg }, + { num: '2', title: '할인 설정', desc: '개발비/구독료 할인\n연동 ON/OFF', color: C.blue, bg: C.blueBg }, { num: '3', title: '가입유형 선택', desc: '개인 가입\n단체 가입', color: C.orange, bg: C.orangeBg }, { num: '4', title: '결과 확인!', desc: '최종 비용\n내 수당', color: '7B1FA2', bg: 'F3E5F5' }, ]; @@ -654,9 +651,9 @@ async function main() { addSlideNumber(s12, 12, TOTAL); const tips = [ - { situation: '초기 비용 부담이 클 때', strategy: '개발비 할인 + 무료 체험 1주일', color: C.green, bg: C.greenBg }, + { situation: '초기 비용 부담이 클 때', strategy: '개발비 할인 + 구독료 할인 조합', color: C.green, bg: C.greenBg }, { situation: '매달 비용이 부담될 때', strategy: '구독료 할인 (최대 50%)', color: C.blue, bg: C.blueBg }, - { situation: '기존 시스템이 있을 때', strategy: '이카운트 연동 모듈 추천', color: C.orange, bg: C.orangeBg }, + { situation: '세금계산서·카드 관리 필요', strategy: '바로빌 부가 서비스 안내 (기본 포함)', color: C.orange, bg: C.orangeBg }, { situation: '대형 제조업체', strategy: '기본 패키지 + 공정관리 + 품질관리', color: '7B1FA2', bg: 'F3E5F5' }, { situation: '여러 업체를 묶을 수 있을 때', strategy: '단체 가입 (수당률 30%로 UP!)', color: C.red, bg: C.redBg }, ]; @@ -675,7 +672,7 @@ async function main() { const faqs = [ ['"왜 비싸요?"', '기존 ERP 5천만~1억 vs SAM 2천만원 + AI 포함'], ['"구독료가 아까운데?"', '자체 서버 월 200만+ vs SAM 월 50만원'], - ['"무료 체험 안 돼요?"', '1주일(7일) 무료 체험 가능!'], + ['"추가 할인 안 돼요?"', '구독료 최대 50%까지 할인 가능!'], ]; faqs.forEach((f, i) => { const fy = 4.5 + i * 0.3; @@ -710,7 +707,7 @@ async function main() { const keyPoints = [ '개발비 = 한 번 | 구독료 = 매달', '수당 = 최종 개발비 × 수당률', - '구독료 할인/무료 체험 → 수당 영향 없음', + '구독료 할인 → 수당 영향 없음', ]; keyPoints.forEach((kp, i) => { s13.addShape(pres.ShapeType.roundRect, { x: 2, y: 3.85 + i * 0.42, w: 6, h: 0.35, rectRadius: 0.06, fill: { color: '1B2838' }, line: { color: '2A3A4A', width: 0.5 } }); diff --git a/guides/price-simulator-partner-guide.md b/guides/price-simulator-partner-guide.md index fd4f42b..5b8eb26 100644 --- a/guides/price-simulator-partner-guide.md +++ b/guides/price-simulator-partner-guide.md @@ -60,7 +60,7 @@ SAM의 요금은 **딱 두 가지**로 구성된다. | QR코드 관리 | 1,020만원 | 5만원 | 제품에 QR코드 부착, 이력 추적 | | 사진/출하 관리 | 1,920만원 | 10만원 | 출하 사진 촬영·등록, 배송 관리 | | 검사/토큰 적용 | 1,020만원 | 5만원 | 품질 검사, AI 토큰 활용 | -| 이카운트 연동 | 1,920만원 | 10만원 | 기존 이카운트 ERP와 데이터 연동 | + ### 3.3 통합 패키지 (대형 프로젝트용) @@ -84,7 +84,7 @@ SAM의 요금은 **딱 두 가지**로 구성된다. ## 4. 할인/프로모션 (고객에게 제안할 수 있는 것들) -가격 시뮬레이터에서 **4가지 할인**을 조합할 수 있다. +가격 시뮬레이터에서 **3가지 할인**을 조합할 수 있다. ### 4.1 개발비 할인 @@ -102,18 +102,7 @@ SAM의 요금은 **딱 두 가지**로 구성된다. 예) 구독료 50만원/월 → 20% 할인 → 40만원/월 ``` -### 4.3 무료 체험 기간 - -서비스 시작 후 1주일(7일) 동안 구독료를 면제한다. - -| 무료 기간 | 1년 중 실제 내는 개월 | -|----------|:------------------:| -| 없음 | 12개월 | -| 1주일(7일) | 거의 12개월 | - -> **참고**: 1주일(7일) 무료 체험은 연간 비용에 미미한 영향을 주므로, 유료 개월수는 거의 12개월로 계산한다. - -### 4.4 개발비-구독료 연동 (선택) +### 4.3 개발비-구독료 연동 (선택) 개발비를 깎아주면 구독료도 같은 비율로 자동 조정하는 기능이다. @@ -141,7 +130,7 @@ SAM의 요금은 **딱 두 가지**로 구성된다. └─────────────────────────────────────────────────────┘ ``` -### 예시: 제조업 기본 패키지, 10% 할인, 무료 체험 1주일 +### 예시: 제조업 기본 패키지, 10% 할인 | 항목 | 계산 | 금액 | |------|------|-----:| @@ -149,9 +138,9 @@ SAM의 요금은 **딱 두 가지**로 구성된다. | 개발비 할인 | 2,000 × 10% | -200만원 | | **최종 개발비** | - | **1,800만원** | | 월 구독료 | - | 50만원 | -| 유료 개월수 | 거의 12개월 (1주일 무료) | 약 12개월 | -| 연 구독료 | 50 × 약 12 | 약 600만원 | -| **1년차 총 비용** | 1,800 + 약 600 | **약 2,400만원** | +| 유료 개월수 | 12개월 | 12개월 | +| 연 구독료 | 50 × 12 | 600만원 | +| **1년차 총 비용** | 1,800 + 600 | **2,400만원** | > 2년차부터는 구독료만 내면 된다: 50만원 × 12 = **600만원/년** @@ -177,12 +166,11 @@ SAM의 요금은 **딱 두 가지**로 구성된다. | | 개인 가입 | 단체 가입 | |---|:---:|:---:| | **파트너 수당** | **20%** | **30%** | -| **유치 파트너 수당** | 5% | 3% | -| **합계** | **25%** | **33%** | +| **유치 파트너 수당** | 5% | - | +| **매니저 수당** | 첫달 구독료 | - | -- **개인 가입**: 개별 고객이 직접 계약 -- **단체 가입**: 여러 고객을 묶어서 한꺼번에 계약 -- **매니저 수당**: 개발비 요율이 아닌, 첫달 구독료를 별도 지급 +- **개인 가입**: 개별 고객이 직접 계약 (파트너 20% + 유치 파트너 5% + 매니저 수당) +- **단체 가입**: 여러 고객을 묶어서 한꺼번에 계약 (단체 수당 30%) ### 6.3 수당 계산 예시 (제조업 기본 패키지) @@ -297,7 +285,6 @@ SAM의 요금은 **딱 두 가지**로 구성된다. **Step 3: 할인 설정** - 개발비 할인: % 또는 정액 - 구독료 할인: 0~50% -- 무료 체험 기간: 없음 / 1주일(7일) - 개발비-구독료 연동: ON/OFF **Step 4: 가입 유형 선택** @@ -326,11 +313,11 @@ SAM의 요금은 **딱 두 가지**로 구성된다. ### Q2. 구독료를 깎아줘도 수당이 줄어드나? -**아니다.** 수당은 개발비에서만 계산한다. 구독료 할인, 무료 체험은 수당에 영향 없다. +**아니다.** 수당은 개발비에서만 계산한다. 구독료 할인은 수당에 영향 없다. ### Q3. 단체 가입이 수당률이 더 높은가? -**그렇다.** 단체 가입은 단체 수당 30% + 유치 파트너 3% = 33%이다. 개인 가입은 파트너 20% + 유치 파트너 5% = 25%이므로 단체가 더 높다. +**그렇다.** 단체 가입은 수당률 30%, 개인 가입은 파트너 20% + 유치 파트너 5% = 25%이므로 단체가 더 높다. ### Q4. 수당은 한 번에 받나? @@ -340,11 +327,7 @@ SAM의 요금은 **딱 두 가지**로 구성된다. **0원이다.** 개발비가 0원이면 수당도 0원이다. 전액 면제는 최저 개발비가 0원인 상품에서만 가능하다. -### Q6. 무료 체험 기간을 주면 나한테 손해인가? - -**아니다.** 무료 체험은 구독료에만 영향을 주고, 수당은 개발비 기준이므로 파트너 수당에는 영향이 없다. 오히려 고객 유치가 쉬워질 수 있다. - -### Q7. 2년차부터는 고객이 얼마를 내나? +### Q6. 2년차부터는 고객이 얼마를 내나? 2년차부터는 **구독료만** 낸다. 예를 들어 월 구독료 50만원이면 연 600만원이다. diff --git a/guides/sam-pricing-simple-guide.md b/guides/sam-pricing-simple-guide.md index f6a46f5..3c9237a 100644 --- a/guides/sam-pricing-simple-guide.md +++ b/guides/sam-pricing-simple-guide.md @@ -58,7 +58,7 @@ | QR코드 관리 | 1,020만원 | 5만원 | 제품 이력 추적이 필요한 곳 | | 사진/출하 관리 | 1,920만원 | 10만원 | 출하·배송 기록이 중요한 곳 | | 검사/토큰 적용 | 1,020만원 | 5만원 | 품질검사 + AI 활용이 필요한 곳 | -| 이카운트 연동 | 1,920만원 | 10만원 | 기존에 이카운트를 쓰는 곳 | + ### 대형 패키지 (큰 프로젝트용) @@ -103,14 +103,14 @@ ┌─ 개인 가입 ─────────────────┐ ┌─ 단체 가입 ─────────────────┐ │ │ │ │ │ 파트너 수당: 20% │ │ 단체 수당: 30% │ -│ 유치 파트너 수당: 5% │ │ 유치 파트너 수당: 3% │ -│ ───────────── │ │ ───────────── │ -│ 합계: 25% │ │ 합계: 33% │ +│ 유치 파트너 수당: 5% │ │ │ +│ ───────────── │ │ (여러 고객 묶어서 계약) │ +│ 합계: 25% │ │ │ │ │ │ │ -│ (개별 고객이 직접 계약) │ │ (여러 고객 묶어서 계약) │ +│ (개별 고객이 직접 계약) │ │ │ │ │ │ │ -│ + 매니저 수당: 첫달 구독료 │ │ + 매니저 수당: 첫달 구독료 │ -│ (별도 지급) │ │ (별도 지급) │ +│ + 매니저 수당: 첫달 구독료 │ │ │ +│ (별도 지급) │ │ │ └──────────────────────────────┘ └──────────────────────────────┘ ``` @@ -121,18 +121,18 @@ | | 개인 가입 | 단체 가입 | |---|---:|---:| | 파트너/단체 수당 | **400만원** | **600만원** | -| 유치 파트너 수당 | 100만원 | 60만원 | -| **합계** | **500만원** | **660만원** | -| + 매니저 수당 (별도) | 첫달 구독료 50만원 | 첫달 구독료 50만원 | +| 유치 파트너 수당 | 100만원 | - | +| **합계** | **500만원** | **600만원** | +| + 매니저 수당 (별도) | 첫달 구독료 50만원 | - | **10% 할인(1,800만원)으로 판매한 경우:** | | 개인 가입 | 단체 가입 | |---|---:|---:| | 파트너/단체 수당 | **360만원** | **540만원** | -| 유치 파트너 수당 | 90만원 | 54만원 | -| **합계** | **450만원** | **594만원** | -| + 매니저 수당 (별도) | 첫달 구독료 50만원 | 첫달 구독료 50만원 | +| 유치 파트너 수당 | 90만원 | - | +| **합계** | **450만원** | **540만원** | +| + 매니저 수당 (별도) | 첫달 구독료 50만원 | - | > 할인하면 내 수당도 줄어든다. **정가에 가깝게 팔수록 수당이 크다!** > 매니저 수당은 개발비 요율이 아니라, 첫달 구독료를 별도 지급하는 형태이다. @@ -354,9 +354,9 @@ Step 1 Step 2 Step 3 Step 4 |----------|-----------| | 초기 비용 부담이 클 때 | 개발비 할인 + 구독료 할인 | | 매달 비용이 부담될 때 | 구독료 할인 (최대 50%) | -| 기존 시스템(이카운트)이 있을 때 | 이카운트 연동 모듈 추천 | +| 세금계산서·카드 관리가 필요할 때 | 바로빌 부가 서비스 안내 (기본 포함) | | 대형 제조업체 | 기본 패키지 + 공정관리 + 품질관리 | -| 여러 업체를 묶을 수 있을 때 | 단체 가입 (수당률 33%로 UP!) | +| 여러 업체를 묶을 수 있을 때 | 단체 가입 (수당률 30%로 UP!) | ### 고객이 자주 하는 질문과 답변 @@ -394,11 +394,11 @@ Step 1 Step 2 Step 3 Step 4 ### Q3. 단체 가입이 뭔가? -여러 고객을 묶어서 한꺼번에 계약하는 것이다. 단체 수당 30% + 유치 파트너 3% = **합계 33%**를 받는다. +여러 고객을 묶어서 한꺼번에 계약하는 것이다. **단체 수당 30%**를 받는다. ### Q4. 유치 파트너 수당이 뭔가? -나를 유치한 상위 파트너에게 지급되는 수당이다. 개인 가입 시 개발비의 **5%**, 단체 가입 시 **3%**가 지급된다. +나를 유치한 상위 파트너에게 지급되는 수당이다. 개인 가입 시 개발비의 **5%**가 지급된다. ### Q5. 매니저 수당이 뭔가? diff --git a/guides/sam-pricing-simple-guide.pptx b/guides/sam-pricing-simple-guide.pptx index 712e0ed..686efbb 100644 Binary files a/guides/sam-pricing-simple-guide.pptx and b/guides/sam-pricing-simple-guide.pptx differ diff --git a/plans/stock-production-react-request.md b/plans/stock-production-react-request.md new file mode 100644 index 0000000..d8eedbe --- /dev/null +++ b/plans/stock-production-react-request.md @@ -0,0 +1,341 @@ +# 재고생산관리 React 구현 요청서 + +> **작성일**: 2026-03-16 +> **요청자**: R&D 실장 +> **대상**: 프론트엔드 개발자 +> **우선순위**: 🟡 중요 +> **API 상태**: ✅ 구현 완료 (개발서버 배포됨) + +--- + +## 1. 개요 + +수주 없이 **재고 목적으로 생산**하는 경우를 관리하는 메뉴를 추가한다. +기존 수주관리 API를 그대로 사용하며, `order_type_code = 'STOCK'`으로 구분한다. + +### 1.1 구현 대상 + +| 메뉴 | 위치 | 설명 | 난이도 | +|------|------|------|:------:| +| **재고생산관리** | 판매관리 > 재고생산관리 | 재고생산 등록/목록/상세/수정/삭제 | **낮음** (수주 화면 복제 후 단순화) | + +### 1.2 참고 문서 + +| 문서 | 경로 | 용도 | +|------|------|------| +| **API 명세** (필독) | `docs/frontend/api-specs/stock-production-api.md` | 전체 엔드포인트, 요청/응답 형식 | +| 기능 설명 | `docs/features/sales/stock-production.md` | 비즈니스 개념, 수주와의 관계 | + +### 1.3 핵심 원칙 + +``` +✅ 수주관리 화면을 복제한 뒤 불필요한 필드 제거 +✅ API는 기존 /api/v1/orders 그대로 사용 (order_type=STOCK 필터) +✅ 생성 시 order_type_code: 'STOCK' 필수 전송 +❌ 별도 API 엔드포인트 없음 +❌ 거래처, 견적, 배송, 할인, 개소(Node) 관련 UI 불필요 +``` + +--- + +## 2. 파일 구조 (제안) + +기존 수주관리 구조를 따른다. + +``` +src/ +├── app/[locale]/(protected)/sales/order-management-sales/ +│ └── stocks/ # 재고생산관리 (신규) +│ ├── page.tsx # 목록 페이지 +│ └── [id]/ +│ ├── page.tsx # 상세 페이지 +│ └── production-order/ +│ └── page.tsx # 생산지시 생성 페이지 +│ +├── components/orders/ +│ └── StockProductionRegistration.tsx # 재고생산 등록/수정 폼 (신규) +│ └── (기존 actions.ts에 함수 추가 또는 별도 stockActions.ts) +``` + +> **대안**: `stocks/` 대신 기존 수주관리 페이지에서 `order_type` 탭으로 분리하는 방식도 가능. 실장 판단에 따름. + +--- + +## 3. 화면별 구현 가이드 + +### 3.1 재고생산 목록 페이지 + +**경로**: `/sales/order-management-sales/stocks` + +**수주관리 목록 페이지를 복제**한 뒤 다음을 변경: + +| 항목 | 수주관리 (현재) | 재고생산 (변경) | +|------|---------------|---------------| +| 페이지 제목 | 수주관리 | **재고생산관리** | +| API 호출 | `getOrders()` | `getOrders({ order_type: 'STOCK' })` | +| 통계 API | `getOrderStats()` | `getOrderStats({ order_type: 'STOCK' })` → `GET /api/v1/orders/stats?order_type=STOCK` | +| 표시 컬럼 | 수주번호, 거래처, 현장명, 수량, 납기, 금액... | **생산번호, 품목, 수량, 생산사유, 등록일, 상태** | +| 통계 카드 | 이번달 수주금액, 분할대기... | 전체, 등록, 확정, 진행중, 완료 (또는 간소화) | + +**목록 테이블 컬럼**: + +| 컬럼 | 데이터 | 비고 | +|------|--------|------| +| 번호 | 글로벌 인덱스 | | +| 생산번호 | `order_no` (STK...) | 배지 스타일 | +| 품목 | 대표 `items[0].item_name` + (외 N건) | | +| 수량 | 총 수량 | | +| 생산 사유 | `options.production_reason` | 없으면 `-` | +| 등록일 | `created_at` | YYYY-MM-DD | +| 상태 | `status_code` | 배지 (수주와 동일 색상) | +| 작업 | 상세보기, 삭제 | | + +**제거할 컬럼**: 거래처, 현장명, 납기, 금액 + +### 3.2 재고생산 등록/수정 폼 + +**수주 등록 폼(`OrderRegistration.tsx`)을 복제**한 뒤 다음을 변경: + +#### 제거할 섹션 + +``` +❌ 거래처 선택 (client_id, client_name, client_contact) +❌ 현장명 (site_name) — API가 '재고생산'으로 자동 설정 +❌ 견적 선택 (quote_id) / 견적에서 가져오기 +❌ 배송 정보 (delivery_date, delivery_method_code) +❌ 운임비용 (options.shipping_cost_code) +❌ 수신자 정보 (options.receiver, receiver_contact, shipping_address) +❌ 할인 (discount_rate, discount_amount) +❌ 금액 계산 (supply_amount, tax_amount, total_amount) +❌ 매출 인식 (sales_recognition) +❌ 개소/구역 (OrderNode) 트리 구조 +``` + +#### 유지할 섹션 + +``` +✅ 생산 사유 (options.production_reason) — 텍스트 입력 +✅ 목표 재고 수량 (options.target_stock_qty) — 숫자 입력 +✅ 비고 (memo) — 텍스트 입력 +✅ 품목 목록 (items[]) — 품목 선택 + 수량 입력 +``` + +#### 품목 입력 테이블 + +| 필드 | 타입 | 필수 | 비고 | +|------|------|:----:|------| +| 품목 | 품목 선택 (ItemAddDialog) | ✅ | item_id, item_name, item_code | +| 규격 | 텍스트 | - | specification | +| 수량 | 숫자 | ✅ | quantity | +| 단위 | 텍스트 | - | unit (기본: EA) | + +> **단가/금액은 불필요**하지만, API validation에서 `unit_price`가 required이므로 `0`을 전송 + +#### API 요청 예시 + +```json +{ + "order_type_code": "STOCK", + "memo": "봄 시즌 대비 재고 확보", + "options": { + "production_reason": "시즌 대비", + "target_stock_qty": 500 + }, + "items": [ + { + "item_id": 10, + "item_name": "25mm 알루미늄 블라인드", + "specification": "W1000 x H2000", + "quantity": 100, + "unit_price": 0, + "unit": "EA" + } + ] +} +``` + +### 3.3 재고생산 상세 페이지 + +**수주 상세(`OrderSalesDetailView.tsx`)를 복제**한 뒤 단순화: + +| 섹션 | 표시 | +|------|------| +| 생산번호 (order_no) | ✅ | +| 상태 (status_code) | ✅ 배지 | +| 생산 사유 | ✅ `options.production_reason` | +| 목표 재고 수량 | ✅ `options.target_stock_qty` | +| 비고 | ✅ `memo` | +| 품목 목록 | ✅ 테이블 (품목명, 규격, 수량) | +| 거래처/현장/납기/금액 | ❌ 제거 | +| 개소/구역 트리 | ❌ 제거 | + +**액션 버튼**: +- 수정 (DRAFT 상태만) +- 삭제 (DRAFT 상태만) +- 확정 (`PATCH /api/v1/orders/{id}/status` → `{ "status": "CONFIRMED" }`) +- 생산지시 생성 (CONFIRMED 상태만) → 기존 생산지시 생성 페이지 재사용 + +### 3.4 생산지시 생성 페이지 + +**기존 `[id]/production-order/page.tsx`를 재사용** 가능. + +STOCK 수주의 생산지시는 API가 자동 처리하므로 프론트에서 특별한 분기 불필요: + +| 항목 | API 자동 처리 | +|------|-------------| +| 공정 선택 | 절곡 공정 자동 선택 (process_ids 전달 불필요) | +| 현장명 | `'재고생산'` 고정 | +| 작업예정일 | `now()` 자동 (scheduled_date 전달 불필요) | + +> 단, 공정 매칭 미리보기 UI에서 STOCK 수주가 BOM 없이도 "절곡" 공정으로 표시되도록 조건 분기 필요할 수 있음. + +### 3.5 생산지시 목록 — STOCK 건 표시 (기존 페이지 수정) + +**경로**: `/sales/order-management-sales/production-orders/page.tsx` + +STOCK 타입 재고생산의 생산지시도 이 목록에 표시된다. 변경 필요 사항: + +| 컬럼 | 현재 | STOCK 건 표시 | +|------|------|-------------| +| 현장명 | `siteName` | `'재고생산'` (API가 자동 설정하므로 변경 불필요) | +| 거래처 | `clientName` | 빈 값 또는 `-` | +| 납기 | `deliveryDate` | `-` 표시 (STOCK은 delivery_date 없음) | +| 생산지시일 | `productionOrderedAt` | 정상 표시 | + +**구현 방법**: API 응답에 `order_type_code`가 이미 포함됨. 프론트 types에 추가: + +```typescript +// types.ts 수정 +interface ApiProductionOrder { + // ... 기존 필드 + order_type_code?: string; // 추가 +} + +// transform 함수에서 +orderTypeCode: data.order_type_code || 'ORDER', +``` + +테이블 렌더링에서: + +```typescript +// 납기 컬럼 +{item.orderTypeCode === 'STOCK' ? '-' : item.deliveryDate} + +// 거래처 컬럼 +{item.orderTypeCode === 'STOCK' ? '-' : item.clientName} +``` + +--- + +## 4. 메뉴 등록 + +메뉴 위치: + +``` +판매관리 +├── 거래처관리 +├── 견적관리 +├── 수주관리 +├── 재고생산관리 ← 신규 (수주관리 아래) +└── 단가관리 +``` + +> 메뉴 등록은 MNG 메뉴 동기화 기능으로 별도 처리. 프론트에서는 라우트만 구현. + +--- + +## 5. 수주관리와의 차이 요약 + +``` +┌─ 수주관리 ──────────────────┐ ┌─ 재고생산관리 ───────────────┐ +│ │ │ │ +│ 거래처 선택 │ │ 생산 사유 (텍스트) │ +│ 현장명 │ │ 목표 재고 수량 │ +│ 견적 연결 │ │ 비고 │ +│ 배송/납기/운임 │ │ │ +│ 할인/금액 계산 │ ├──────────────────────────────┤ +│ 매출 인식 방식 │ │ 품목 목록 │ +│ │ │ - 품목 선택 │ +│ 개소/구역 트리 (OrderNode) │ │ - 수량만 입력 │ +│ 품목 목록 (상세) │ │ (단가/금액/할인 불필요) │ +│ - 단가, 할인, 금액 계산 │ │ (개소/구역 불필요) │ +│ - floor_code, symbol_code │ │ │ +│ │ └──────────────────────────────┘ +└──────────────────────────────┘ +``` + +--- + +## 6. API 빠른 참조 + +### 6.1 목록 조회 + +``` +GET /api/v1/orders?order_type=STOCK&page=1&size=20 +``` + +### 6.2 통계 + +``` +GET /api/v1/orders/stats?order_type=STOCK +``` + +### 6.3 생성 + +``` +POST /api/v1/orders +Content-Type: application/json + +{ + "order_type_code": "STOCK", + "memo": "...", + "options": { "production_reason": "...", "target_stock_qty": 500 }, + "items": [{ "item_name": "...", "quantity": 100, "unit_price": 0 }] +} +``` + +### 6.4 상태 변경 + +``` +PATCH /api/v1/orders/{id}/status +{ "status": "CONFIRMED" } +``` + +### 6.5 생산지시 생성 + +``` +POST /api/v1/orders/{id}/production-order +{ "priority": "normal" } +``` + +> 공정/예정일은 API가 자동 처리 (절곡 공정, scheduled_date=now()) + +### 6.6 수정/삭제 + +``` +PUT /api/v1/orders/{id} — 수정 +DELETE /api/v1/orders/{id} — 삭제 +``` + +--- + +## 7. 구현 체크리스트 + +- [ ] `stocks/page.tsx` — 재고생산 목록 페이지 +- [ ] `stocks/[id]/page.tsx` — 재고생산 상세 페이지 +- [ ] `StockProductionRegistration.tsx` — 등록/수정 폼 (수주 폼 단순화) +- [ ] Server Actions — `getOrders({ order_type: 'STOCK' })` 등 (기존 actions.ts 활용) +- [ ] 생산지시 목록 — STOCK 건 납기 `-` 표시, `order_type_code` 타입 추가 +- [ ] 메뉴 라우트 등록 + +--- + +## 관련 문서 + +- [API 명세 (상세)](../frontend/api-specs/stock-production-api.md) +- [기능 설명](../features/sales/stock-production.md) +- [개발 변경이력](../dev/changes/20260316_stock_production_order.md) + +--- + +**최종 업데이트**: 2026-03-16 diff --git a/rules/customer-pricing.md b/rules/customer-pricing.md index 7427563..5e0e155 100644 --- a/rules/customer-pricing.md +++ b/rules/customer-pricing.md @@ -36,7 +36,7 @@ SAM 서비스 도입 시 고객에게 안내하는 요금 체계를 정리한다 | QR코드 관리 | 1,020만원 | 5만원 | | 사진/출하 관리 | 1,920만원 | 10만원 | | 검사/토큰 적용 | 1,020만원 | 5만원 | -| 이카운트 연동 | 1,920만원 | 10만원 | + ### 2.3 통합 패키지 diff --git a/rules/customer-pricing.pptx b/rules/customer-pricing.pptx index f96693b..4d5d297 100644 Binary files a/rules/customer-pricing.pptx and b/rules/customer-pricing.pptx differ diff --git a/rules/slides/customer-pricing/convert.cjs b/rules/slides/customer-pricing/convert.cjs new file mode 100644 index 0000000..feaf880 --- /dev/null +++ b/rules/slides/customer-pricing/convert.cjs @@ -0,0 +1,27 @@ +const path = require('path'); +const fs = require('fs'); +module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')); + +const PptxGenJS = require('pptxgenjs'); +const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')); + +async function main() { + const pres = new PptxGenJS(); + pres.defineLayout({ name: 'CUSTOM_16x9', width: 10, height: 5.625 }); + pres.layout = 'CUSTOM_16x9'; + + const dir = __dirname; + const slides = fs.readdirSync(dir) + .filter(f => f.startsWith('slide-') && f.endsWith('.html')) + .sort(); + + for (const file of slides) { + await html2pptx(path.join(dir, file), pres); + } + + const output = path.join(dir, '..', '..', 'customer-pricing.pptx'); + await pres.writeFile({ fileName: output }); + console.log('PPTX created:', output); +} + +main().catch(console.error); diff --git a/rules/slides/customer-pricing/slide-03.html b/rules/slides/customer-pricing/slide-03.html index 925e39a..0d49032 100644 --- a/rules/slides/customer-pricing/slide-03.html +++ b/rules/slides/customer-pricing/slide-03.html @@ -92,12 +92,7 @@

1,020만원

5만원

- -
-

이카운트 연동

-

1,920만원

-

10만원

-
+

통합 패키지

diff --git a/rules/wip-production-policy.md b/rules/wip-production-policy.md new file mode 100644 index 0000000..43a90ab --- /dev/null +++ b/rules/wip-production-policy.md @@ -0,0 +1,326 @@ +# 재공품(WIP) 생산 정책 + +> **작성일**: 2026-03-16 +> **상태**: 설계 확정 + +--- + +## 1. 개요 + +### 1.1 목적 + +제조업에서 **재공품(WIP, Work-In-Process)** 생산이 왜 필요하고, SAM 시스템에서 어떻게 처리하는지 정의한다. + +### 1.2 대상 독자 + +- SAM을 도입하는 모든 제조업체 +- 시스템 운영자 및 생산관리 담당자 +- 개발팀 (기능 설계 시 참고) + +--- + +## 2. 재공품이란 + +### 2.1 정의 + +재공품(WIP)은 **완성품이 되기 전 단계의 중간 생산물**이다. + +블라인드/스크린 제조업에서는 절곡 가공된 **가이드레일, 케이스, 마구리, 바텀바** 등이 대표적인 재공품이다. 이 부품들은 최종 제품(블라인드)에 조립되기 전까지는 재공품 상태로 재고에 보관된다. + +``` +원자재 (알루미늄 코일, 철판 등) + ↓ 절곡 가공 +재공품 (가이드레일, 케이스, 바텀바 등) ← 이 단계 + ↓ 조립 +완성품 (블라인드, 스크린) + ↓ 출하 +고객 납품 +``` + +### 2.2 재공품 vs 완성품 vs 원자재 + +| 구분 | 설명 | 예시 | +|------|------|------| +| **원자재** | 가공 전 소재 | 알루미늄 코일, 철판, SUS판 | +| **재공품 (WIP)** | 가공 완료, 조립 전 | 가이드레일, 케이스, 바텀바, 마구리 | +| **완성품** | 출하 가능 상태 | 완성된 블라인드, 스크린 | + +--- + +## 3. 왜 재공품을 미리 만드는가 + +### 3.1 제조업의 현실 + +모든 제조업에는 **수주가 몰리는 성수기**와 **한가한 비수기**가 존재한다. + +``` +┌────────────────────────────────────────────────┐ +│ 수주량 │ +│ ▲ │ +│ │ ╱╲ ╱╲ │ +│ │ ╱╲ ╱ ╲ ╱ ╲ ╱╲ │ +│ │╱ ╲╱ ╲╱ ╲╱ ╲ │ +│ └──────────────────────────── ▶ 시간 │ +│ 비수기 성수기 비수기 성수기 │ +│ │ +│ ✕ 비수기: 작업자 유휴 → 인건비 낭비 │ +│ ✕ 성수기: 작업 폭주 → 납기 지연 │ +└────────────────────────────────────────────────┘ +``` + +### 3.2 재공품 미리 생산의 효과 + +``` +┌─────────────────────────────────────────────────┐ +│ │ +│ ① 유휴시간 활용 │ +│ 비수기에 작업자들이 놀지 않고 재공품 생산 │ +│ → 인건비 대비 생산성 향상 │ +│ │ +│ ② 납기 단축 │ +│ 수주가 들어오면 이미 만들어둔 재공품 사용 │ +│ → 절곡 가공 시간 절약 → 납기 3~5일 단축 │ +│ │ +│ ③ 생산 평준화 │ +│ 성수기 작업 부하를 비수기로 분산 │ +│ → 잔업/야근 감소 → 품질 안정 │ +│ │ +│ ④ 긴급 수주 대응 │ +│ 재고가 있으면 긴급 주문도 즉시 대응 가능 │ +│ → 고객 만족도 향상 → 수주 확보 │ +│ │ +└─────────────────────────────────────────────────┘ +``` + +### 3.3 어떤 품목을 미리 만드는가 + +모든 재공품을 무작정 만들지는 않는다. **다음 조건에 해당하는 품목**만 미리 생산한다: + +| 조건 | 설명 | 예시 | +|------|------|------| +| **규격 표준화** | 사이즈/재질이 정해져 있음 | 가이드레일 2438mm, 3000mm | +| **수요 빈도 높음** | 자주 출고되는 품목 | 주력 제품의 핵심 부품 | +| **가공 시간 김** | 만들기 시간이 오래 걸림 | 절곡 가공 (절단→벤딩→용접) | +| **보관 용이** | 장기 보관해도 품질 저하 없음 | 금속 부품 (부식 방지 처리 완료) | + +> **주의**: 주문 제작품(고객 맞춤 사이즈)은 재공품 대상이 아니다. 표준 규격품만 해당한다. + +--- + +## 4. SAM 시스템에서의 처리 방식 + +### 4.1 설계 원칙 + +SAM은 **수주 → 생산지시 → 작업지시 → 생산**의 흐름으로 동작한다. 수주가 없으면 생산지시를 생성할 수 없는 구조이다. + +재공품 생산은 수주가 없지만 생산이 필요한 경우이므로, **내부 오더(Internal Order)** 개념을 도입하여 해결한다. + +``` +일반 수주: 고객 주문 → 수주 등록 → 생산지시 → 작업지시 → 생산 +재공품 생산: (주문 없음) → 재고생산 등록 → 생산지시 → 작업지시 → 생산 + ↑ + 내부 오더 (order_type_code = 'STOCK') +``` + +### 4.2 기존 테이블 공유 + +재공품 생산을 위해 별도 테이블을 만들지 않는다. 기존 `orders` 테이블에 `order_type_code = 'STOCK'`을 추가하여 구분한다. + +``` +orders 테이블 +├── ORDER → 고객 수주 (거래처 주문) +├── PURCHASE → 발주 (자재 구매) +└── STOCK → 재고생산 (내부 오더, 재공품) +``` + +**이유**: +- 하류 시스템(작업지시, 생산, 품질검사, 출하)을 **변경 없이** 재활용 +- 생산 통계에 재공품 생산량도 **자동 포함** +- 이력 관리(누가, 언제, 얼마나 재공품을 생산했는지) **기존 구조로 추적** + +### 4.3 재공품 생산 흐름 + +``` +┌─────────────────────────────────────────────────┐ +│ │ +│ 1. 재고생산 등록 │ +│ ├─ 품목 선택 (이미 정해진 재공품) │ +│ ├─ 수량 입력 │ +│ ├─ 생산 사유 입력 (선택) │ +│ └─ order_type_code = 'STOCK' 자동 설정 │ +│ │ +│ 2. 재고생산 확정 │ +│ ├─ 상태: DRAFT → CONFIRMED │ +│ └─ ※ 매출 생성 안 함 (내부 오더이므로) │ +│ │ +│ 3. 생산지시 생성 │ +│ ├─ 절곡 공정 자동 선택 │ +│ ├─ 현장명 = '재고생산' 자동 설정 │ +│ ├─ 작업예정일 = 오늘 날짜 │ +│ └─ 작업지시(WorkOrder) 생성 │ +│ │ +│ 4. 절곡 작업 수행 │ +│ ├─ 작업자가 절곡 공정 수행 │ +│ ├─ 자재 투입 기록 │ +│ ├─ 중간검사 │ +│ └─ 작업 완료 처리 │ +│ │ +│ 5. 재고 입고 │ +│ ├─ 완성된 재공품 → 재고(Stock Lot) 등록 │ +│ └─ 향후 수주 시 재고에서 출고 │ +│ │ +└─────────────────────────────────────────────────┘ +``` + +### 4.4 일반 수주와의 차이 + +| 항목 | 일반 수주 | 재공품 생산 | +|------|----------|-----------| +| 트리거 | 고객 주문 | 생산 계획 (유휴시간 활용) | +| 거래처 | 있음 | 없음 (내부 오더) | +| 견적 | 있음 (선택) | 없음 | +| 납기 | 고객 요청일 | 없음 (가능한 빨리) | +| 공정 선택 | BOM 기반 자동 매칭 | 절곡 공정 고정 | +| 금액/매출 | 계산 + 매출 인식 | 없음 | +| 현장명 | 고객 현장 | '재고생산' 고정 | +| 채번 | `ORD20260316xxxx` | `STK20260316xxxx` | +| 생산 결과 | 고객 출하 | 재고 입고 | + +--- + +## 5. 재공품 재고 관리 + +### 5.1 재공품 재고의 생명주기 + +``` +재공품 생산 완료 + ↓ +재고 입고 (Stock Lot 생성) + ↓ +재고 보관 (창고/적재대) + ↓ +수주 접수 → 재고 확인 + ↓ +재고에서 출고 → 조립 → 완성품 + ↓ +고객 출하 +``` + +### 5.2 재고 확인 시점 + +수주가 들어오면 시스템에서 **해당 재공품이 재고에 있는지 자동 확인**한다: + +- **재고 있음** → 절곡 공정 스킵, 바로 조립 단계로 이동 → 납기 단축 +- **재고 없음** → 일반 생산 흐름 (절곡 공정부터 시작) + +### 5.3 안전재고와 목표 수량 + +재고생산 등록 시 `목표 재고 수량(target_stock_qty)`을 설정할 수 있다. + +| 항목 | 설명 | +|------|------| +| 목표 재고 수량 | 이 수량만큼 재고를 유지하고 싶은 목표 | +| 현재 재고 수량 | Stock Lot에서 조회 | +| 생산 필요 수량 | 목표 - 현재 = 부족분 | + +--- + +## 6. 제조업 공통 패턴 + +### 6.1 Make-to-Stock (MTS) vs Make-to-Order (MTO) + +SAM 시스템은 기본적으로 **MTO(주문생산)** 방식이다. 재공품 생산은 **MTS(재고생산)** 방식을 부분적으로 도입한 것이다. + +| 전략 | 설명 | SAM 적용 | +|------|------|----------| +| **MTO** (주문생산) | 수주 → 생산 | 일반 수주 (`ORDER`) | +| **MTS** (재고생산) | 예측 → 생산 → 재고 | 재고생산 (`STOCK`) | +| **ATO** (주문조립) | 재공품 재고 + 수주 → 조립 | MTS + MTO 결합 | + +블라인드/스크린 제조에서는 **ATO 패턴**이 가장 효율적이다: + +``` +MTS: 표준 재공품 미리 생산 (절곡) + ↓ +ATO: 수주 → 재공품 + 맞춤 부품 → 조립 → 출하 + ↓ + 납기 단축 + 유휴시간 활용 +``` + +### 6.2 다른 제조업 적용 사례 + +재공품 생산은 블라인드/스크린에 국한되지 않는다. **모든 제조업**에서 동일한 패턴이 적용된다: + +| 업종 | 원자재 | 재공품 (WIP) | 완성품 | +|------|--------|-------------|--------| +| **블라인드/스크린** | 알루미늄 코일, 철판 | 가이드레일, 케이스, 바텀바 | 블라인드, 스크린 | +| **가구** | 목재, MDF | 재단된 판재, 엣지밴딩 부품 | 책상, 의자, 캐비닛 | +| **자동차** | 철강, 플라스틱 | 프레스 부품, 엔진 블록 | 자동차 | +| **전자제품** | PCB 원판, 칩 | 조립된 PCB, 하우징 | 스마트폰, TV | +| **식품** | 밀가루, 설탕 | 반죽, 소스 | 빵, 과자 | +| **의류** | 원단, 실 | 재단 원단, 염색 원단 | 완성 의류 | + +### 6.3 재공품 생산의 핵심 가치 + +``` +┌─────────────────────────────────────────────────┐ +│ │ +│ 💰 비용 절감 │ +│ 유휴 인건비를 생산으로 전환 │ +│ → 작업자가 놀지 않고 가치를 창출 │ +│ │ +│ ⏱️ 납기 단축 │ +│ 수주 → 즉시 조립 가능 (절곡 공정 스킵) │ +│ → 고객 만족도 향상 │ +│ │ +│ 📊 생산 평준화 │ +│ 성수기/비수기 작업량 균등화 │ +│ → 잔업 감소, 품질 안정 │ +│ │ +│ 🚀 경쟁력 확보 │ +│ 빠른 납기 = 수주 확보 │ +│ → 매출 증대 │ +│ │ +└─────────────────────────────────────────────────┘ +``` + +--- + +## 7. 주의사항 + +### 7.1 과잉 생산 방지 + +재공품을 너무 많이 만들면 **재고 비용 증가**와 **사장 재고(불용 재고)** 문제가 발생한다. + +| 위험 | 설명 | 대응 | +|------|------|------| +| 과잉 재고 | 수요보다 많이 생산 | 목표 수량 설정, 주기적 재고 점검 | +| 사장 재고 | 규격 변경/단종으로 사용 불가 | 표준 규격품만 대상, 수요 예측 기반 | +| 보관 비용 | 창고 공간 점유 | 적정 재고 수준 유지 | +| 품질 저하 | 장기 보관 시 녹/변색 | 보관 환경 관리, 선입선출(FIFO) | + +### 7.2 생산 대상 품목 선정 기준 + +``` +❌ 주문 맞춤 제작품 (고객 사이즈) +❌ 수요 불확실 품목 +❌ 원자재 가격 변동이 큰 품목 +❌ 보관이 어려운 품목 + +✅ 표준 규격품 (정해진 사이즈) +✅ 출고 빈도 높은 품목 +✅ 가공 시간이 긴 품목 +✅ 장기 보관 가능 품목 +``` + +--- + +## 관련 문서 + +- [재고생산관리 기능 설명](../features/sales/stock-production.md) +- [재고생산관리 API 명세](../frontend/api-specs/stock-production-api.md) +- [품목 정책](item-policy.md) + +--- + +**최종 업데이트**: 2026-03-16