- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동) - 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/) - 기획팀 폴더 requests/ 생성 - plans/ → dev/dev_plans/ 이름 변경 - README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용) - resources.md 신규 (노션 링크용, assets/brochure 이관 예정) - CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동 - 전체 참조 경로 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14 KiB
14 KiB
BOM 아이템 ↔ Items Master 매핑 작업 계획
작성일: 2026-02-05 목적: BOM 산출 로직에서 생성하는 모든 아이템에 SAM items master의 item_code/item_id를 매핑하여, 수주 등록 시 코드 기반 아이템 관리가 가능하도록 함 상태: ✅ Phase 1, 2 완료 (검증 대기)
📍 현재 진행 상태
| 항목 | 내용 |
|---|---|
| 마지막 완료 작업 | Phase 2: BOM 산출 로직 매핑 수정 완료 |
| 다음 작업 | Phase 3: 수주 등록 화면에서 검증 |
| 진행률 | 2/3 Phase (66%) |
| 마지막 업데이트 | 2026-02-05 |
1. 개요
1.1 문제 상황
현재 상태:
- KyungdongFormulaHandler에서 22종 아이템 생성
- 그 중 5종은 item_code/item_id 없이 이름만으로 생성됨:
1. 케이스 마구리 (calculateSteelItems)
2. L바 (calculateSteelItems)
3. 무게평철12T (calculateSteelItems)
4. 검사비 (calculateDynamicItems) ← 유일한 SAM 미등록 아이템
5. 주자재(스크린/슬랫) (calculateDynamicItems) ← KD-* 코드 사용
문제점:
- 수주 등록 시 아이템 그룹핑/집계에서 코드 기반 매칭 불가
- item_code가 없으면 item_name으로만 집계되어 중복 발생
1.2 목표 상태
목표:
- BOM 산출 결과의 모든 22종 아이템에 item_code + item_id 필수
- 수주 등록 시 동일 item_code 기준으로 수량/금액 집계
기대 효과:
- 3개소에 "환봉" 각 1개씩 → item_code "90201" 기준 3개로 집계
1.3 핵심 원칙
┌─────────────────────────────────────────────────────────────────┐
│ 🎯 핵심 원칙 (CRITICAL) │
├─────────────────────────────────────────────────────────────────┤
│ 1. items master에 등록된 제품을 매핑해야 함 │
│ → 코드를 임의로 만들어내면 안됨 │
│ 2. 기존 EST-/BD-/PT- 코드 체계를 활용 │
│ 3. BOM 산출 결과의 모든 아이템에 item_code + item_id 필수 │
└─────────────────────────────────────────────────────────────────┘
1.4 변경 승인 정책
| 분류 | 예시 | 승인 |
|---|---|---|
| ✅ 즉시 가능 | BOM 로직 내 item_code/item_id 매핑 추가 | 불필요 |
| ⚠️ 컨펌 필요 | items master에 신규 아이템 등록 | 필수 |
| 🔴 금지 | items 테이블 구조 변경, 기존 코드 체계 변경 | 별도 협의 |
2. 전체 아이템 매핑 테이블 (22종)
2.1 calculateSteelItems (절곡품) - 10종
| # | BOM 아이템명 | 현재 item_code | SAM 매핑 코드 | SAM item_id | 매핑 방법 |
|---|---|---|---|---|---|
| 1 | 케이스 | null | BD-케이스-{규격} |
lookup | 규격으로 items 검색 (예: BD-케이스-500*350) |
| 2 | 케이스용 연기차단재 | null | EST-SMOKE-케이스용 |
14912 | 고정 매핑 |
| 3 | 케이스 마구리 | null | BD-마구리-{규격} |
lookup | 규격으로 items 검색 (예: BD-마구리-505*355) |
| 4 | 가이드레일 | null | BD-가이드레일-{모델}-{재질}-{규격} |
lookup | 모델+재질+규격으로 검색 |
| 5 | 레일용 연기차단재 | null | EST-SMOKE-레일용 |
14911 | 고정 매핑 |
| 6 | 하장바 | null | 00035 또는 00036 |
14158/14159 | 재질에 따라 분기 |
| 7 | L바 | null | BD-L-BAR-{모델}-{규격} |
lookup | 모델+규격으로 검색 (예: BD-L-BAR-KWE01-17*60) |
| 8 | 보강평철 | null | BD-보강평철-50 |
14790 | 고정 매핑 |
| 9 | 무게평철12T | null | 00021 |
14147 | 고정 매핑 (평철12T와 동일) |
| 10 | 환봉 | null | 90201~90204 |
14407~14410 | 파이 규격에 따라 분기 (30/35/45/50파이) |
2.2 calculatePartItems (부자재) - 5종
| # | BOM 아이템명 | 현재 item_code | SAM 매핑 코드 | SAM item_id | 매핑 방법 |
|---|---|---|---|---|---|
| 11 | 감기샤프트 | null | EST-SHAFT-{인치}-{길이} |
lookup | 인치+길이로 검색 (예: EST-SHAFT-4-6) |
| 12 | 각파이프 | null | EST-PIPE-{두께}-{길이} |
lookup | 두께+길이로 검색 (예: EST-PIPE-1.4-6000) |
| 13 | 모터받침 앵글 | null | EST-ANGLE-BRACKET-{타입} |
lookup | 타입으로 검색 (스크린용/철제300K/400K/800K) |
| 14 | 앵글 | null | EST-ANGLE-MAIN-{타입} |
lookup | 앵글타입+길이로 검색 |
| 15 | 조인트바 | null | 800361 |
14733 | 고정 매핑 |
2.3 calculateDynamicItems (동적항목) - 7종
| # | BOM 아이템명 | 현재 item_code | SAM 매핑 코드 | SAM item_id | 매핑 방법 |
|---|---|---|---|---|---|
| 16 | 검사비 | KD-INSPECTION | EST-INSPECTION |
(신규등록) | items master 신규 등록 필요 |
| 17 | 주자재(스크린) | KD-SCREEN | EST-RAW-스크린-{타입} |
lookup | 타입으로 검색 (실리카/화이바/와이어) |
| 18 | 주자재(슬랫) | KD-SLAT | EST-RAW-슬랫-{타입} |
lookup | 타입으로 검색 (방범/방화) |
| 19 | 모터 | KD-MOTOR-{용량} | EST-MOTOR-{전압}-{용량} |
lookup | 전압+용량으로 검색 |
| 20 | 제어기 | KD-CTRL-{타입} | EST-CTRL-{타입} |
lookup | 타입으로 검색 (노출형/매립형) |
| 21 | 뒷박스 | KD-CTRL-BACKBOX | EST-CTRL-뒷박스 |
14863 | 고정 매핑 |
| 22 | 브라켓 | (모터에 포함) | KD브라켓트* 또는 EST-* |
lookup | 모터 용량에 따라 분기 |
굵은 글씨: 현재 미매핑 상태 (작업 대상)
3. 대상 범위
3.1 Phase 1: 미등록 아이템 등록 (사용자 승인 필요)
| # | 작업 항목 | 상태 | 비고 |
|---|---|---|---|
| 1.1 | 검사비(EST-INSPECTION) items master 신규 등록 | ✅ | ID: 14913 |
| 1.2 | 무게평철12T → 00021(평철12T) 동일 아이템 확인 | ✅ | ID: 14147 확인 완료 |
3.2 Phase 2: BOM 산출 로직 매핑 수정
| # | 작업 항목 | 상태 | 비고 |
|---|---|---|---|
| 2.1 | calculateSteelItems: 10종 아이템에 item_code/item_id 매핑 | ✅ | withItemMapping 헬퍼 사용 |
| 2.2 | calculatePartItems: 5종 아이템에 item_code/item_id 매핑 | ✅ | withItemMapping 헬퍼 사용 |
| 2.3 | calculateDynamicItems: KD-* → EST-* 코드 변환 | ✅ | 모터/제어기/주자재 매핑 완료 |
3.3 Phase 3: 검증
| # | 작업 항목 | 상태 | 비고 |
|---|---|---|---|
| 3.1 | 견적 산출 실행 → 모든 아이템 item_code/item_id 확인 | ✅ | 18종 아이템 모두 매핑됨 |
| 3.2 | 수주 등록 → 코드 기반 아이템 그룹핑/집계 정상 동작 | ⏳ | 화면 검증 필요 |
4. 실행 환경 및 명령어
4.1 Docker 환경
# API 컨테이너 접속
docker exec -it sam-api-1 bash
# PHP Tinker 실행
docker exec sam-api-1 php artisan tinker --execute='...'
4.2 주요 확인 명령어
# SAM items master에서 특정 코드 검색
docker exec sam-api-1 php artisan tinker --execute='
$item = \App\Models\Items\Item::where("tenant_id", 287)
->where("code", "EST-INSPECTION")
->first();
echo $item ? "ID: {$item->id}, Code: {$item->code}, Name: {$item->name}" : "NOT FOUND";
'
# 코드 패턴으로 검색 (BD-*, EST-* 등)
docker exec sam-api-1 php artisan tinker --execute='
$items = \App\Models\Items\Item::where("tenant_id", 287)
->where("code", "like", "BD-마구리%")
->get(["id", "code", "name"]);
foreach ($items as $item) {
echo "{$item->id} | {$item->code} | {$item->name}" . PHP_EOL;
}
'
# 5130 chandj DB 연결 테스트
docker exec sam-api-1 php artisan tinker --execute='
$count = \Illuminate\Support\Facades\DB::connection("chandj")
->table("KDunitprice")->count();
echo "KDunitprice 총 건수: {$count}";
'
4.3 검사비 신규 등록 (Phase 1.1)
# 검사비 아이템 신규 등록
docker exec sam-api-1 php artisan tinker --execute='
$item = \App\Models\Items\Item::create([
"tenant_id" => 287,
"code" => "EST-INSPECTION",
"name" => "검사비",
"unit" => "EA",
"item_type" => "product",
"is_active" => true,
]);
echo "Created: ID={$item->id}, Code={$item->code}";
'
5. 코드 수정 가이드
5.1 수정 대상 파일
api/app/Services/Quote/FormulaHandlers/KyungdongFormulaHandler.php
5.2 수정 패턴 (예시: calculateSteelItems 내 케이스 마구리)
현재 코드 (item_code 없음):
$items[] = [
'item_name' => '케이스 마구리',
'item_code' => null, // ❌ 없음
'item_id' => null, // ❌ 없음
'quantity' => $quantity,
'unit_price' => $unitPrice,
'total_price' => $quantity * $unitPrice,
// ...
];
수정 후 (item_code/item_id 매핑):
// 규격 계산 (예: 505*355)
$spec = "{$caseWidth}*{$caseDepth}";
$itemCode = "BD-마구리-{$spec}";
// items master에서 lookup
$item = \App\Models\Items\Item::where('tenant_id', $this->tenantId)
->where('code', $itemCode)
->first();
$items[] = [
'item_name' => '케이스 마구리',
'item_code' => $item?->code ?? $itemCode, // ✅ 코드 매핑
'item_id' => $item?->id, // ✅ ID 매핑
'quantity' => $quantity,
'unit_price' => $unitPrice,
'total_price' => $quantity * $unitPrice,
// ...
];
5.3 아이템 lookup 헬퍼 메서드 추가 (권장)
/**
* items master에서 코드로 아이템 조회
*/
private function lookupItem(string $code): ?Item
{
return Item::where('tenant_id', $this->tenantId)
->where('code', $code)
->first();
}
/**
* 아이템 배열에 item_code/item_id 추가
*/
private function withItemMapping(array $item, string $code): array
{
$masterItem = $this->lookupItem($code);
return array_merge($item, [
'item_code' => $masterItem?->code ?? $code,
'item_id' => $masterItem?->id,
]);
}
6. 검증 방법
6.1 견적 산출 후 BOM 결과 확인
# 최근 견적의 BOM 결과에서 item_code 확인
docker exec sam-api-1 php artisan tinker --execute='
$quote = \App\Models\Quote::where("tenant_id", 287)
->whereNotNull("calculation_result")
->latest()
->first();
$items = $quote->calculation_result["items"] ?? [];
$noCode = array_filter($items, fn($i) => empty($i["item_code"]));
echo "총 아이템: " . count($items) . "개" . PHP_EOL;
echo "item_code 없음: " . count($noCode) . "개" . PHP_EOL;
foreach ($noCode as $i) {
echo " - {$i["item_name"]}" . PHP_EOL;
}
'
6.2 수주 등록 화면 확인
/orders/create?quoteId={ID}로 수주 등록 화면 진입- 아이템 목록에서 동일 아이템이 코드 기준으로 집계되는지 확인
- 3개소에 "환봉" 각 1개 → "환봉" 1행, 수량 3개로 표시되어야 함
7. 성공 기준
| 기준 | 검증 방법 | 달성 |
|---|---|---|
| BOM 산출 22종 아이템 전부 item_code 보유 | Phase 3.1 검증 쿼리 | ⏳ |
| BOM 산출 22종 아이템 전부 item_id 보유 | Phase 3.1 검증 쿼리 | ⏳ |
| 수주 등록 시 코드 기반 아이템 집계 정상 동작 | Phase 3.2 화면 확인 | ⏳ |
| 기존 견적 산출 금액에 영향 없음 | 기존 견적 재산출 후 금액 비교 | ⏳ |
8. 관련 소스 파일
| 파일 | 수정 여부 | 용도 |
|---|---|---|
api/app/Services/Quote/FormulaHandlers/KyungdongFormulaHandler.php |
수정 | BOM 산출 매핑 로직 추가 |
api/app/Models/Items/Item.php |
읽기 | items lookup |
react/src/components/orders/OrderRegistration.tsx |
검증 | 수주 등록 아이템 그룹핑 |
react/src/components/orders/actions.ts |
검증 | 수주 데이터 변환 |
9. 참고 정보
9.1 SAM 견적 전용 코드 체계
| 접두사 | 용도 | 예시 |
|---|---|---|
| BD- | 절곡품 (모델/규격별) | BD-케이스-500350, BD-마구리-505355 |
| EST- | 견적 산출 전용 | EST-MOTOR-220V-300K, EST-INSPECTION |
| PT- | 품목 템플릿 (규격 미포함) | PT-케이스, PT-가이드레일 |
| PM- | 제어기 부품 | PM-020 (제어기 노출형) |
9.2 5130 DB 연결 정보
# api/.env
CHANDJ_DB_HOST=sam-mysql-1
CHANDJ_DB_DATABASE=chandj
CHANDJ_DB_USERNAME=root
CHANDJ_DB_PASSWORD=root
9.3 상세 분석 문서
- 전체 분석 결과:
docs/data/analysis/bom-item-mapping-analysis.md - 견적 시스템 구조:
docs/features/quotes/README.md
10. 컨펌 대기 목록
| # | 항목 | 변경 내용 | 승인 |
|---|---|---|---|
| 1 | 검사비 신규 등록 | items master에 EST-INSPECTION 추가 | ⏳ |
| 2 | 무게평철12T 동일성 | BOM의 무게평철12T = 00021 평철12T 인지 | ⏳ |
11. 변경 이력
| 날짜 | 작업 | 변경 내용 | 파일 |
|---|---|---|---|
| 2026-02-05 | 분석 | 22종 아이템 매핑 상태 분석 완료 | bom-item-mapping-analysis.md |
| 2026-02-05 | 계획 | 작업 계획 문서 작성 | bom-item-mapping-plan.md |
| 2026-02-05 | Phase 1 | 검사비(EST-INSPECTION) ID:14913 신규 등록 | items master |
| 2026-02-05 | Phase 2 | KyungdongFormulaHandler 매핑 로직 추가 | KyungdongFormulaHandler.php |
이 문서는 /sc:plan 스킬로 생성되었습니다.