feat: [interview] SAM Knowledge Base(SKB) 지식 기반 AI 인터뷰 시스템

SKB 지식 파일 (25개):
- system_prompt_base.md: AI 역할 + SAM 개요 + 응답 형식
- modules/ 12개: 테넌트/품목/BOM/단가/견적/생산/품질/재고/회계/인사/결재/바로빌
- presets/ 6개: 블라인드/금속가공/기계조립/식품/건설/범용 업종 프리셋
- mapping_rules/ 3개: 답변→테이블 매핑, 크로스체크 규칙, 검증 규칙

PHP 서비스:
- InterviewKnowledgeLoader: 도메인별 프롬프트 동적 조립
- InterviewCrossChecker: 도메인 간 정합성 검증 (CC-01~CC-07)
- AiInterviewService: buildSystemPrompt → SKB 기반으로 교체
This commit is contained in:
김보곤
2026-03-23 09:37:59 +09:00
parent 64fb1d3c35
commit 2dda60be1b
25 changed files with 1963 additions and 37 deletions

View File

@@ -524,50 +524,28 @@ private function callGemini(array $contents): array
// ============================================================
/**
* 시스템 프롬프트 생성
* 시스템 프롬프트 생성 (SKB 기반)
*
* InterviewKnowledgeLoader를 사용하여 SAM 시스템 지식 +
* 업종 프리셋 + 매핑 규칙을 포함한 고품질 프롬프트를 생성한다.
*/
private function buildSystemPrompt(string $domain, ?InterviewCategory $category, array $questions): string
{
$domainName = $category?->name ?? $domain;
$domainDescription = $category?->description ?? "{$domain} 도메인 관련 업무 파악";
$loader = new InterviewKnowledgeLoader;
$projectId = null;
$questionList = '';
foreach ($questions as $index => $question) {
$hint = $question->ai_hint ? " (힌트: {$question->ai_hint})" : '';
$required = $question->is_required ? ' [필수]' : '';
$type = $question->question_type ?? 'text';
$questionList .= ($index + 1).". [{$type}]{$required} {$question->question_text}{$hint}\n";
// 프로젝트에서 업종 프리셋 가져오기
$preset = null;
if ($category && $category->interview_project_id) {
$projectId = $category->interview_project_id;
$project = \App\Models\Interview\InterviewProject::find($projectId);
$preset = $project?->company_type;
}
if (empty($questionList)) {
$questionList = "- 해당 도메인의 전반적인 업무 프로세스와 요구사항을 파악합니다.\n";
}
// 이전 도메인 결과 (크로스체크용)
$previousResults = $projectId ? $loader->buildCrossCheckContext($projectId) : [];
return <<<PROMPT
당신은 제조업 ERP/MES 시스템 구축을 위한 전문 인터뷰어입니다.
현재 도메인: {$domainName}
수집 목표: {$domainDescription}
아래는 이 도메인에서 수집해야 할 핵심 질문 목록입니다:
{$questionList}
지침:
1. 자연스러운 대화체로 한 번에 1-2개 질문을 합니다
2. 답변이 불충분하면 구체적인 예시를 요청합니다
3. 답변에서 구조화 가능한 데이터를 발견하면 JSON으로 추출합니다
4. 모든 핵심 질문이 커버될 때까지 대화를 이어갑니다
5. 응답 마지막에 반드시 아래 형식의 JSON 블록을 포함합니다:
```json
{
"extracted_data": {},
"covered_questions": [],
"coverage_percent": 0,
"next_focus": "다음에 물어볼 영역"
}
```
PROMPT;
return $loader->buildPrompt($domain, $preset, $previousResults, $questions);
}
/**

View File

@@ -0,0 +1,349 @@
<?php
namespace App\Services\Sales;
use App\Models\Interview\InterviewAiConversation;
use App\Models\Interview\InterviewKnowledge;
/**
* 도메인 간 크로스체크 서비스
*
* 여러 도메인에서 수집된 데이터의 정합성을 검증한다.
* BOM 부품 ⊂ 품목마스터, 단가 품목 = BOM 품목 등.
*/
class InterviewCrossChecker
{
/**
* 프로젝트 전체 크로스체크 실행
*/
public function validate(int $projectId): array
{
$tenantId = session('selected_tenant_id', 1);
$data = $this->collectAllData($projectId, $tenantId);
$issues = [];
// CC-01: BOM 부품 ⊂ 품목
$issues = array_merge($issues, $this->checkBomVsItems($data));
// CC-02: 단가 품목 = BOM 품목
$issues = array_merge($issues, $this->checkPricingVsBom($data));
// CC-03: 수식 변수 = 치수 변수
$issues = array_merge($issues, $this->checkFormulaVsDimension($data));
// CC-04: 공정 부품 ⊂ BOM
$issues = array_merge($issues, $this->checkProcessVsBom($data));
// CC-05: 견적 항목 = 단가 항목
$issues = array_merge($issues, $this->checkQuoteVsPricing($data));
// CC-06: 부서 = 공정 담당
$issues = array_merge($issues, $this->checkDepartmentVsProcess($data));
// 심각도별 정렬 (CRITICAL > HIGH > MEDIUM > LOW)
usort($issues, function ($a, $b) {
$order = ['CRITICAL' => 0, 'HIGH' => 1, 'MEDIUM' => 2, 'LOW' => 3];
return ($order[$a['severity']] ?? 4) <=> ($order[$b['severity']] ?? 4);
});
return [
'total_issues' => count($issues),
'critical' => count(array_filter($issues, fn ($i) => $i['severity'] === 'CRITICAL')),
'high' => count(array_filter($issues, fn ($i) => $i['severity'] === 'HIGH')),
'medium' => count(array_filter($issues, fn ($i) => $i['severity'] === 'MEDIUM')),
'low' => count(array_filter($issues, fn ($i) => $i['severity'] === 'LOW')),
'issues' => $issues,
];
}
/**
* 모든 도메인 데이터 수집
*/
private function collectAllData(int $projectId, int $tenantId): array
{
$data = [
'items' => [], // 품목명 목록
'bom_parts' => [], // BOM에 사용된 부품명
'priced_items' => [], // 단가가 정의된 품목명
'formula_vars' => [], // 수식에 사용된 변수
'dimension_vars' => [], // 치수에 정의된 변수
'process_parts' => [], // 공정에서 투입하는 부품
'quote_groups' => [], // 견적 항목 그룹
'pricing_groups' => [], // 단가 구성요소
'departments' => [], // 부서 목록
'process_depts' => [], // 공정 담당 부서
];
// AI 대화에서 structured_data 수집
$conversations = InterviewAiConversation::where('interview_project_id', $projectId)
->where('tenant_id', $tenantId)
->where('role', 'assistant')
->whereNotNull('structured_data')
->get(['domain', 'structured_data']);
foreach ($conversations as $conv) {
$sd = $conv->structured_data;
if (! is_array($sd)) {
continue;
}
$this->extractFromStructuredData($conv->domain, $sd, $data);
}
// knowledge에서도 수집
$knowledge = InterviewKnowledge::on('codebridge')
->where('interview_project_id', $projectId)
->where('tenant_id', $tenantId)
->get(['domain', 'title', 'content']);
foreach ($knowledge as $k) {
$this->extractFromKnowledge($k->domain, $k->content, $data);
}
return $data;
}
/**
* structured_data에서 항목 추출
*/
private function extractFromStructuredData(?string $domain, array $sd, array &$data): void
{
// sam_mapping에서 테이블별 데이터 추출
if (isset($sd['sam_mapping']['table'])) {
$table = $sd['sam_mapping']['table'];
$mappingData = $sd['sam_mapping']['data'] ?? [];
foreach ($mappingData as $row) {
$name = $row['name'] ?? $row['component'] ?? $row['item'] ?? null;
if (! $name) {
continue;
}
match ($table) {
'categories', 'products' => $data['items'][] = $name,
'bom_template_items' => $data['bom_parts'][] = $name,
'price_histories' => $data['priced_items'][] = $name,
'processes' => $data['process_depts'][] = $row['department'] ?? null,
'departments' => $data['departments'][] = $name,
default => null,
};
}
}
// extracted_data에서도 추출
if (isset($sd['extracted_data'])) {
$ed = $sd['extracted_data'];
// 품목 목록
foreach ($ed['categories'] ?? $ed['products'] ?? $ed['items'] ?? [] as $item) {
$data['items'][] = is_array($item) ? ($item['name'] ?? '') : $item;
}
// BOM 부품
foreach ($ed['bom_items'] ?? $ed['components'] ?? [] as $item) {
$data['bom_parts'][] = is_array($item) ? ($item['name'] ?? $item['component'] ?? '') : $item;
}
// 수식 변수
foreach ($ed['formulas'] ?? $ed['variables'] ?? [] as $item) {
if (is_array($item) && isset($item['code'])) {
$data['formula_vars'][] = $item['code'];
}
}
// 치수 변수
foreach ($ed['parameters'] ?? $ed['dimensions'] ?? [] as $item) {
if (is_array($item) && isset($item['code'])) {
$data['dimension_vars'][] = $item['code'];
}
}
}
}
/**
* knowledge에서 항목 추출
*/
private function extractFromKnowledge(?string $domain, $content, array &$data): void
{
if (! is_array($content)) {
return;
}
match ($domain) {
'product_classification' => $data['items'] = array_merge($data['items'], $this->extractNames($content)),
'bom_structure' => $data['bom_parts'] = array_merge($data['bom_parts'], $this->extractNames($content)),
'pricing_structure' => $data['priced_items'] = array_merge($data['priced_items'], $this->extractNames($content)),
default => null,
};
}
/**
* 배열에서 name/item/component 키 추출
*/
private function extractNames(array $content): array
{
$names = [];
foreach ($content as $key => $value) {
if (in_array($key, ['name', 'item', 'component', 'product'])) {
$names[] = $value;
}
if (is_array($value)) {
$names = array_merge($names, $this->extractNames($value));
}
}
return $names;
}
// ─── 크로스체크 규칙 구현 ───
private function checkBomVsItems(array $data): array
{
$issues = [];
$items = array_map('mb_strtolower', array_filter(array_unique($data['items'])));
foreach (array_unique($data['bom_parts']) as $part) {
if (empty($part)) {
continue;
}
$found = false;
foreach ($items as $item) {
if (str_contains($item, mb_strtolower($part)) || str_contains(mb_strtolower($part), $item)) {
$found = true;
break;
}
}
if (! $found && ! empty($items)) {
$issues[] = [
'rule' => 'CC-01',
'severity' => 'HIGH',
'source' => 'bom_structure',
'target' => 'product_classification',
'message' => "BOM에 '{$part}'이(가) 있는데 품목 분류에 없습니다",
'suggestion' => "'{$part}'을(를) 품목 분류에 추가하시겠습니까?",
];
}
}
return $issues;
}
private function checkPricingVsBom(array $data): array
{
$issues = [];
$priced = array_map('mb_strtolower', array_filter(array_unique($data['priced_items'])));
foreach (array_unique($data['bom_parts']) as $part) {
if (empty($part)) {
continue;
}
$found = false;
foreach ($priced as $p) {
if (str_contains($p, mb_strtolower($part)) || str_contains(mb_strtolower($part), $p)) {
$found = true;
break;
}
}
if (! $found && ! empty($priced)) {
$issues[] = [
'rule' => 'CC-02',
'severity' => 'HIGH',
'source' => 'pricing_structure',
'target' => 'bom_structure',
'message' => "BOM의 '{$part}'에 단가가 설정되지 않았습니다",
'suggestion' => "'{$part}'의 단가를 알려주세요",
];
}
}
return $issues;
}
private function checkFormulaVsDimension(array $data): array
{
$issues = [];
$dims = array_map('strtolower', array_filter(array_unique($data['dimension_vars'])));
foreach (array_unique($data['formula_vars']) as $var) {
if (empty($var)) {
continue;
}
if (! in_array(strtolower($var), $dims) && ! empty($dims)) {
$issues[] = [
'rule' => 'CC-03',
'severity' => 'CRITICAL',
'source' => 'quantity_formula',
'target' => 'dimension_formula',
'message' => "수량 공식에 '{$var}'를 사용하지만 치수 변수에 정의되지 않았습니다",
'suggestion' => "'{$var}'는 무엇인가요? 치수 변수에 추가해주세요",
];
}
}
return $issues;
}
private function checkProcessVsBom(array $data): array
{
$issues = [];
$bomParts = array_map('mb_strtolower', array_filter(array_unique($data['bom_parts'])));
foreach (array_unique($data['process_parts']) as $part) {
if (empty($part)) {
continue;
}
$found = false;
foreach ($bomParts as $bp) {
if (str_contains($bp, mb_strtolower($part)) || str_contains(mb_strtolower($part), $bp)) {
$found = true;
break;
}
}
if (! $found && ! empty($bomParts)) {
$issues[] = [
'rule' => 'CC-04',
'severity' => 'MEDIUM',
'source' => 'production_process',
'target' => 'bom_structure',
'message' => "공정에서 '{$part}'를 사용하지만 BOM에 없습니다",
'suggestion' => "'{$part}'를 BOM에 추가하거나 확인해주세요",
];
}
}
return $issues;
}
private function checkQuoteVsPricing(array $data): array
{
// 견적 그룹과 단가 그룹의 일치 여부 (데이터 충분 시)
return [];
}
private function checkDepartmentVsProcess(array $data): array
{
$issues = [];
$depts = array_map('mb_strtolower', array_filter(array_unique($data['departments'])));
foreach (array_unique(array_filter($data['process_depts'])) as $procDept) {
if (empty($procDept)) {
continue;
}
$found = false;
foreach ($depts as $d) {
if (str_contains($d, mb_strtolower($procDept)) || str_contains(mb_strtolower($procDept), $d)) {
$found = true;
break;
}
}
if (! $found && ! empty($depts)) {
$issues[] = [
'rule' => 'CC-07',
'severity' => 'LOW',
'source' => 'production_process',
'target' => 'tenant_setup',
'message' => "공정 담당 '{$procDept}'이(가) 부서 목록에 없습니다",
'suggestion' => "'{$procDept}'를 부서로 추가하시겠습니까?",
];
}
}
return $issues;
}
}

View File

@@ -0,0 +1,252 @@
<?php
namespace App\Services\Sales;
use App\Models\Interview\InterviewAiConversation;
use App\Models\Interview\InterviewKnowledge;
use Illuminate\Support\Facades\Log;
/**
* SAM Knowledge Base(SKB) 프롬프트 로더
*
* 현재 인터뷰 도메인에 필요한 지식만 선별하여
* AI 시스템 프롬프트를 동적으로 조립한다.
*/
class InterviewKnowledgeLoader
{
private string $basePath;
public function __construct()
{
$this->basePath = config_path('interview_knowledge');
}
/**
* 도메인별 시스템 프롬프트 조립
*
* @param string $domain 현재 도메인 (예: 'pricing_structure')
* @param string|null $preset 업종 프리셋 코드 (예: 'blinds')
* @param array $previousResults 이전 도메인 수집 결과 요약
* @param array $questions 현재 도메인 질문 목록
*/
public function buildPrompt(string $domain, ?string $preset, array $previousResults = [], array $questions = []): string
{
$parts = [];
// 1. 기본 시스템 프롬프트 (항상)
$parts[] = $this->loadFile('system_prompt_base.md');
// 2. 업종 프리셋 (해당 시)
if ($preset) {
$presetContent = $this->loadPreset($preset);
if ($presetContent) {
$parts[] = "\n\n## 업종 프리셋: {$preset}\n\n".$presetContent;
}
}
// 3. 현재 도메인 모듈 지식
$moduleContent = $this->loadModule($domain);
if ($moduleContent) {
$parts[] = "\n\n## 현재 도메인 지식\n\n".$moduleContent;
}
// 4. 현재 도메인 질문 목록
if (! empty($questions)) {
$parts[] = "\n\n## 수집해야 할 질문 목록\n\n".$this->formatQuestions($questions);
}
// 5. 이전 도메인 수집 결과 (크로스체크용)
if (! empty($previousResults)) {
$parts[] = "\n\n## 이전 도메인 수집 결과 (크로스체크 참고)\n\n".$this->formatPreviousResults($previousResults);
}
// 6. 매핑 규칙 (답변→테이블)
$mappingRules = $this->loadFile('mapping_rules/answer_to_table.md');
if ($mappingRules) {
$parts[] = "\n\n## 답변→SAM 매핑 규칙\n\n".$mappingRules;
}
// 7. 크로스체크 규칙
$crossCheckRules = $this->loadFile('mapping_rules/cross_check_rules.md');
if ($crossCheckRules) {
$parts[] = "\n\n## 도메인 간 크로스체크 규칙\n\n".$crossCheckRules;
}
return implode('', $parts);
}
/**
* 이전 도메인 결과를 요약하여 크로스체크 컨텍스트 생성
*/
public function buildCrossCheckContext(int $projectId): array
{
$tenantId = session('selected_tenant_id', 1);
// 프로젝트의 모든 AI 대화에서 extracted_data 수집
$conversations = InterviewAiConversation::where('interview_project_id', $projectId)
->where('tenant_id', $tenantId)
->where('role', 'assistant')
->whereNotNull('structured_data')
->orderBy('id')
->get(['domain', 'structured_data']);
$domainResults = [];
foreach ($conversations as $conv) {
$domain = $conv->domain;
if (! $domain) {
continue;
}
if (! isset($domainResults[$domain])) {
$domainResults[$domain] = [];
}
if (is_array($conv->structured_data)) {
$domainResults[$domain][] = $conv->structured_data;
}
}
// 프로젝트의 검증된 지식도 포함
$knowledge = InterviewKnowledge::on('codebridge')
->where('interview_project_id', $projectId)
->where('tenant_id', $tenantId)
->get(['domain', 'title', 'content', 'knowledge_type']);
foreach ($knowledge as $k) {
$domain = $k->domain;
if (! isset($domainResults[$domain])) {
$domainResults[$domain] = [];
}
$domainResults[$domain][] = [
'knowledge' => $k->title,
'type' => $k->knowledge_type,
'content' => $k->content,
];
}
return $domainResults;
}
/**
* 업종 프리셋 로딩
*/
public function loadPreset(string $presetCode): ?string
{
$presetMap = [
'blinds' => 'blinds',
'블라인드' => 'blinds',
'스크린' => 'blinds',
'방화' => 'blinds',
'metal' => 'metal_fabrication',
'금속' => 'metal_fabrication',
'금속가공' => 'metal_fabrication',
'machine' => 'machine_assembly',
'기계' => 'machine_assembly',
'기계조립' => 'machine_assembly',
'food' => 'food_manufacturing',
'식품' => 'food_manufacturing',
'construction' => 'construction',
'건설' => 'construction',
'시공' => 'construction',
'general' => 'general_manufacturing',
'범용' => 'general_manufacturing',
'제조' => 'general_manufacturing',
];
$fileName = $presetMap[mb_strtolower($presetCode)] ?? $presetCode;
return $this->loadFile("presets/{$fileName}.md");
}
/**
* 도메인 코드로 모듈 번호 매핑
*/
public function getDomainModuleNumber(string $domain): string
{
$map = [
'tenant_setup' => '01',
'product_classification' => '02',
'bom_structure' => '03',
'dimension_formula' => '03',
'component_config' => '03',
'pricing_structure' => '04',
'quantity_formula' => '04',
'conditional_logic' => '04',
'quote_format' => '05',
'production_process' => '06',
'quality_control' => '07',
'logistics_inventory' => '08',
'sales_customer' => '05',
'finance' => '09',
'hr' => '10',
'approval' => '11',
'barobill' => '12',
];
return $map[$domain] ?? '01';
}
/**
* 모듈 지식 파일 로딩
*/
private function loadModule(string $domain): ?string
{
$moduleNumber = $this->getDomainModuleNumber($domain);
$files = glob("{$this->basePath}/modules/{$moduleNumber}_*.md");
if (empty($files)) {
return null;
}
return file_get_contents($files[0]);
}
/**
* 파일 로딩 (공통)
*/
private function loadFile(string $relativePath): ?string
{
$path = "{$this->basePath}/{$relativePath}";
if (! file_exists($path)) {
Log::debug("SKB file not found: {$path}");
return null;
}
return file_get_contents($path);
}
/**
* 질문 목록 포맷팅
*/
private function formatQuestions(array $questions): string
{
$lines = [];
foreach ($questions as $i => $q) {
$num = $i + 1;
$required = ($q->is_required ?? false) ? ' [필수]' : '';
$type = $q->question_type ?? 'text';
$hint = ! empty($q->ai_hint) ? " (힌트: {$q->ai_hint})" : '';
$lines[] = "{$num}. [{$type}]{$required} {$q->question_text}{$hint}";
}
return implode("\n", $lines);
}
/**
* 이전 도메인 결과 포맷팅
*/
private function formatPreviousResults(array $results): string
{
$text = '';
foreach ($results as $domain => $items) {
$text .= "### {$domain}\n";
foreach ($items as $item) {
if (is_array($item)) {
$text .= '- '.json_encode($item, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)."\n";
}
}
$text .= "\n";
}
return $text;
}
}

View File

@@ -0,0 +1,75 @@
# 답변 → SAM 테이블 매핑 규칙
## 매핑 원칙
1. 고객 답변에서 SAM 테이블/필드로 직접 변환 가능한 데이터를 즉시 추출한다
2. 매핑 불가능한 답변은 추가 질문으로 구체화한다
3. 하나의 답변이 여러 테이블에 매핑될 수 있다
4. 매핑 결과는 `sam_mapping` JSON 블록에 포함한다
## 테이블별 매핑 패턴
### categories (품목 분류)
| 답변 패턴 | 매핑 | 추가 질문 |
|---------|------|---------|
| "제품은 A, B, C 3종류" | INSERT categories 3건 (type=PRODUCT) | "각 제품의 하위 모델은?" |
| "원자재는 강판, 알루미늄" | INSERT categories 2건 (type=MATERIAL) | "규격은 어떻게 구분?" |
| "분류는 용도별로 합니다" | category_fields: '용도' 필드 추가 | "용도 종류는?" |
### products (품목 마스터)
| 답변 패턴 | 매핑 | 추가 질문 |
|---------|------|---------|
| "코드는 SC-01 형식" | code 패턴 = '{prefix}-{순번}' | "prefix가 제품군을 의미?" |
| "단위는 EA로 관리" | unit = 'EA' | — |
| "색상, 마감재 옵션 있음" | attributes에 추가 | "선택지 목록은?" |
### bom_template_items (BOM 항목)
| 답변 패턴 | 매핑 | 추가 질문 |
|---------|------|---------|
| "모터 1개 고정" | quantity=1, quantity_formula=null | — |
| "가이드레일은 높이 나누기 1219" | quantity_formula='CEIL(H1/1219)*2' | "올림 처리?" |
| "LOSS 5% 적용" | waste_rate=5.0 | — |
| "방화제품에만 연기차단재" | is_optional=true | "적용 조건 상세?" |
### price_histories (단가)
| 답변 패턴 | 매핑 | 추가 질문 |
|---------|------|---------|
| "m당 15,000원" | price=15000, unit='m' | "VAT 포함?" |
| "㎡당 45,000원" | price=45000, unit='㎡' | — |
| "개당 125,000원" | price=125000, unit='EA' | — |
| "분기마다 단가 변경" | effective_to 3개월 주기 | "다음 변경 예정일?" |
### clients (거래처)
| 답변 패턴 | 매핑 | 추가 질문 |
|---------|------|---------|
| "A건설, B시공, C기업" | INSERT clients 3건 | "고객/공급업체 구분?" |
| "월말 정산, 30일 이내 입금" | payment_terms='NET30' | — |
| "A급/B급/C급 거래처" | grade 필드 설정 | "등급 기준은?" |
### tenants.options (시스템 설정)
| 답변 패턴 | 매핑 키 |
|---------|---------|
| "견적번호 Q-2026-001" | quote_numbering: 'Q-{YYYY}-{NNN}' |
| "부가세 별도 표시" | vat_display: 'separate' |
| "FIFO로 재고 관리" | inventory_method: 'FIFO' |
| "바코드 사용" | barcode_enabled: true |
| "주 5일 9시~6시" | work_hours: {start:'09:00', end:'18:00', days:5} |
## JSON 출력 형식
```json
{
"sam_mapping": {
"table": "categories",
"action": "INSERT",
"data": [
{"name": "방화스크린", "type": "PRODUCT", "code": "SC"},
{"name": "방화셔터", "type": "PRODUCT", "code": "SH"}
],
"confidence": 0.9,
"needs_confirmation": false
}
}
```
confidence가 0.7 미만이면 needs_confirmation=true로 설정하고 확인 질문을 한다.

View File

@@ -0,0 +1,92 @@
# 도메인 간 크로스체크 규칙
## 실행 시점
크로스체크는 다음 상황에서 자동 실행한다:
1. 도메인 전환 시 (이전 도메인 결과 vs 현재 도메인)
2. 인터뷰 완료 후 전체 검증
3. AI가 모순을 감지했을 때 즉시
## 체크 규칙
### CC-01: BOM 부품 ⊂ 품목마스터
```
조건: bom_structure 수집 완료 AND product_classification 수집 완료
검사: BOM에 있는 모든 부품이 품목 분류에 존재하는지
경고: "BOM에 '{부품명}'이 있는데 품목 분류에 등록되지 않았습니다. 새로 추가할까요?"
심각도: HIGH
```
### CC-02: 단가 품목 = BOM 품목
```
조건: pricing_structure 수집 완료 AND bom_structure 수집 완료
검사: 단가가 정의된 품목이 BOM에서 사용되는지 / BOM 품목에 단가가 있는지
경고(미사용): "단가표에 '{품목}'이 있는데 BOM에서 사용되지 않습니다. 예비 단가인가요?"
경고(미정가): "BOM의 '{부품}'에 단가가 설정되지 않았습니다. 단가를 알려주세요."
심각도: HIGH (미정가), LOW (미사용)
```
### CC-03: 수식 변수 = 치수 변수
```
조건: quantity_formula 수집 완료 AND dimension_formula 수집 완료
검사: 수량 공식에서 사용하는 변수(W1, H1, area 등)가 치수 모듈에서 정의되어 있는지
경고: "수량 공식에 'H2'를 사용하지만 치수 변수에 정의되지 않았습니다. H2는 무엇인가요?"
심각도: CRITICAL
```
### CC-04: 공정 부품 ⊂ BOM
```
조건: production_process 수집 완료 AND bom_structure 수집 완료
검사: 각 공정에서 투입하는 부품이 BOM에 존재하는지
경고: "'{공정명}' 공정에서 '{부품}'을 사용한다고 하셨는데 BOM에 없습니다."
심각도: MEDIUM
```
### CC-05: 검사 대상 ⊂ 품목
```
조건: quality_control 수집 완료 AND product_classification 수집 완료
검사: 수입검사 대상 품목이 품목 마스터에 있는지
경고: "수입검사 대상 '{품목}'이 품목 분류에 없습니다."
심각도: MEDIUM
```
### CC-06: 견적 항목 = 단가 항목
```
조건: quote_format 수집 완료 AND pricing_structure 수집 완료
검사: 견적서 항목 그룹의 단가가 모두 정의되어 있는지
경고: "견적서에 '운반비' 항목이 있는데 단가 기준이 수집되지 않았습니다."
심각도: HIGH
```
### CC-07: 부서 = 공정 담당
```
조건: tenant_setup 수집 완료 AND production_process 수집 완료
검사: 공정 담당 부서가 조직도에 존재하는지
경고: "'절단반'이 공정 담당인데 부서 목록에 없습니다. 부서를 추가할까요?"
심각도: LOW
```
### CC-08: 거래처 = 재무 거래처
```
조건: sales_customer 수집 완료 AND finance 수집 완료
검사: 거래처 정보가 매출/매입 처리와 일치하는지
경고: "매입 거래처 '{업체}'의 결제 조건이 설정되지 않았습니다."
심각도: MEDIUM
```
## JSON 출력 형식
```json
{
"cross_check_results": [
{
"rule": "CC-02",
"severity": "HIGH",
"source_domain": "pricing_structure",
"target_domain": "bom_structure",
"message": "BOM의 '연기차단재'에 단가가 설정되지 않았습니다.",
"suggestion": "연기차단재의 단가를 알려주세요."
}
]
}
```

View File

@@ -0,0 +1,75 @@
# 답변 검증 규칙
## 실행 시점
모든 답변을 받을 때마다 즉시 검증한다.
## 필수값 검증
### CRITICAL (미수집 시 시스템 구축 불가)
- □ 제품 분류 체계 (최소 1개 제품군)
- □ 대표 제품 BOM 트리 (최소 1개)
- □ 치수→제작 변환 공식 (치수 기반 견적 시)
- □ 주요 부품 단가 (최소 BOM 부품 전체)
- □ 견적서 양식 (파일 또는 상세 설명)
### HIGH (미수집 시 기능 제한)
- □ 공정 순서 (생산 관리 시)
- □ 단가 변경 주기
- □ 거래처 결제 조건
- □ 직급/권한 체계
### MEDIUM (미수집 시 수동 설정 필요)
- □ 공통 코드/분류 (드롭다운 선택지)
- □ 검사 항목/기준
- □ LOT 번호 체계
- □ 결재선 구성
## 데이터 형식 검증
| 항목 | 형식 | 오류 시 |
|------|------|--------|
| 사업자등록번호 | 10자리 숫자 | "사업자등록번호 형식을 확인해주세요" |
| 단가 | 양수 | "단가가 0원 이하입니다. 확인해주세요" |
| LOSS율 | 0~100% | "LOSS율이 100%를 초과합니다" |
| 마진율 | 0~100% | — |
| 수량 | 양의 정수 | "수량은 1 이상이어야 합니다" |
| 공식 변수 | 영문+숫자 | "변수명은 영문으로 입력해주세요 (예: W1, H1)" |
| 날짜 | YYYY-MM-DD | — |
## 논리적 검증
| 규칙 | 검사 | 메시지 |
|------|------|--------|
| V-01 | LOSS율 > 20% | "LOSS율이 높습니다. 실제 현장 기준인가요?" |
| V-02 | 마진율 + LOSS율 > 30% | "원가 대비 부가 비율이 높습니다. 확인해주세요" |
| V-03 | BOM 깊이 > 3 | "BOM이 4단계 이상입니다. SAM은 3단계를 권장합니다" |
| V-04 | 카테고리 깊이 > 3 | "분류가 4단계 이상입니다" |
| V-05 | 단가 0원 품목이 BOM에 존재 | "단가 미설정 품목이 BOM에 있습니다" |
| V-06 | 공정 수 > 15 | "공정이 많습니다. 그룹화를 검토하세요" |
| V-07 | 결재 단계 > 5 | "결재 단계가 많습니다. 간소화를 검토하세요" |
| V-08 | 안전재고 0인 핵심 부품 | "핵심 부품의 안전재고가 0입니다" |
## 완료도 판정
### 도메인별 최소 수집 항목
| 도메인 | 필수 항목 수 | 최소 완료 기준 |
|--------|:----------:|:-----------:|
| 테넌트 기초 | 8 | 6개 이상 (75%) |
| 품목 분류 | 10 | 7개 이상 (70%) |
| BOM 구조 | 8 | 6개 이상 (75%) |
| 단가 체계 | 10 | 8개 이상 (80%) |
| 견적/수주 | 8 | 6개 이상 (75%) |
| 생산 공정 | 8 | 5개 이상 (63%) |
| 품질 관리 | 6 | 4개 이상 (67%) |
| 재고/물류 | 6 | 4개 이상 (67%) |
| 회계/재무 | 6 | 4개 이상 (67%) |
| 인사 | 4 | 3개 이상 (75%) |
| 결재 | 4 | 3개 이상 (75%) |
| 바로빌 | 4 | 2개 이상 (50%) |
### 전체 완료 판정
- 80% 이상: "인터뷰 완료. SAM 설정 생성 가능합니다."
- 60~79%: "주요 정보 수집 완료. 일부 항목 보충이 필요합니다."
- 40~59%: "기본 정보 수집 중. 추가 인터뷰가 필요합니다."
- 40% 미만: "초기 단계. 핵심 도메인부터 집중해주세요."

View File

@@ -0,0 +1,60 @@
# 모듈 01: 테넌트 기초 설정
## SAM 테이블 구조
### tenants (회사 정보)
- name, business_number, representative, business_type, business_category
- address, phone, fax, email, logo_path
- subscription_plan, is_active, options(json)
### departments (부서)
- tenant_id, parent_id, name, code, sort_order, is_active, head_user_id
### users + user_tenants (사용자)
- name, email, phone, employee_number
- user_tenants: role, is_active, is_default, department_id
### roles + permissions (역할/권한)
- roles: tenant_id, name, guard_name
- permissions: tenant_id, name, menu_id
- permission_overrides: user_id, menu_id, allow/deny
## 필수 수집 항목
### 회사 기본 정보 (tenants)
- □ 회사명 (법인명과 상호 구분)
- □ 사업자등록번호
- □ 대표자명
- □ 업태/업종
- □ 주소 (본사 + 공장/사업장)
- □ 연락처 (전화, 팩스, 이메일)
- □ 직원 수 (규모 파악)
- □ 연매출 규모 (구독 플랜 결정)
### 조직 구조 (departments)
- □ 부서 목록 + 계층 구조 (예: 경영지원실 > 인사팀, 총무팀)
- □ 각 부서 인원 수
- □ 부서장/팀장 직급 체계
- □ 공장/사업장이 여러 곳인 경우 구분
### 사용자 역할 (roles)
- □ 직급 체계 (대표, 이사, 부장, 과장, 대리, 사원 등)
- □ 역할별 시스템 접근 범위 (경영진/관리자/현장/외부)
- □ 특수 권한이 필요한 사용자 (예: 단가 열람 제한)
- □ 초기 등록 사용자 수
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "직원이 45명이고 본사와 공장이 있어요" | tenants.options.employee_count=45, departments에 본사/공장 생성 |
| "영업부, 생산부, 관리부 3개 부서" | departments INSERT 3건 |
| "부장급 이상만 단가 볼 수 있어요" | permission_overrides: 단가 메뉴 부장 이상만 allow |
| "공장장은 생산 관련만 사용" | roles: '공장장' 역할 생성 + 생산 메뉴만 권한 |
## 검증 규칙
- 사업자등록번호 10자리 형식 체크
- 부서 계층이 3단계 초과 시 확인 질문 (SAM 권장 2~3단계)
- 초기 사용자 수가 구독 플랜 한도 초과 시 안내
- 직급 체계 미수집 시 → 역할 기반 권한 설정 불가 경고

View File

@@ -0,0 +1,74 @@
# 모듈 02: 품목 분류 체계
## SAM 테이블 구조
### categories (품목 카테고리)
- tenant_id, parent_id, name, code, type(PRODUCT|MATERIAL|PART|SUBASSEMBLY)
- description, sort_order, is_active, options(json)
- 계층 구조: 대분류 > 중분류 > 소분류 (최대 3단계)
### category_fields (카테고리별 동적 필드)
- category_id, field_name, field_type(text|number|select|checkbox|date)
- options(json: choices, default, unit 등), is_required, sort_order
### category_templates (카테고리 양식 스냅샷)
- category_id, version, fields_snapshot(json)
### products (제품/품목 마스터)
- tenant_id, category_id, name, code, type(PRODUCT|PART|SUBASSEMBLY)
- specification, unit, is_active, attributes(json)
### classifications (분류 코드)
- tenant_id, group, code, name, sort_order
- groups: product_type, material_type, finish_type 등
## 필수 수집 항목
### 제품 분류 (categories)
- □ 주요 제품군 목록 (대분류)
- □ 각 제품군의 하위 분류 (중분류, 소분류)
- □ 분류 기준 (소재별? 용도별? 크기별? 인증여부별?)
- □ 제품 코드 체계 (예: SC-01 = 스크린 1번 모델)
- □ 제품 수 (카테고리별 대략적 품목 수)
### 자재/부품 분류
- □ 원자재 분류 (강판, 알루미늄, 수지 등)
- □ 구매 부품 분류 (모터, 제어기, 센서 등)
- □ 소모품/부자재 분류 (볼트, 너트, 패킹 등)
- □ 반제품 구분 여부 (절곡품, 서브어셈블리 등)
### 품목 속성 (category_fields)
- □ 제품별 고유 속성 (규격, 색상, 마감재 등)
- □ 필수 속성 vs 선택 속성
- □ 속성의 선택지 목록 (드롭다운 항목)
- □ 단위 (mm, kg, EA, m, ㎡ 등)
### 인증/규격
- □ 인증 제품 구분 (KC, 방화, KS 등)
- □ 인증 제품의 구성 고정 여부
- □ 인증서 번호 관리 필요성
- □ 시험성적서 관리 필요성
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "방화스크린, 방화셔터, 일반블라인드" | categories INSERT 3건 (type=PRODUCT) |
| "방화스크린 밑에 KSS01, KSS02 모델" | categories INSERT 2건 (parent_id=방화스크린) |
| "코드는 SC-01 형식, SC가 스크린" | products.code 패턴 = '{카테고리코드}-{순번}' |
| "색상은 흰색/아이보리/회색/브라운" | category_fields: field_name='색상', type='select', options=['흰색','아이보리','회색','브라운'] |
| "알루미늄, 스틸, SUS 3종류 소재" | classifications: group='material_type', 3건 INSERT |
## 검증 규칙
- 제품 코드 체계 미수집 → 자동 채번 불가 경고
- 카테고리에 속한 제품이 0건인 빈 분류 → 확인 질문
- category_fields 미수집 → 품목등록 시 속성 입력 불가 경고
- 인증 제품 존재 시 인증서 관리 방안 미수집 → 재질문
- 분류 깊이 4단계 이상 → SAM 권장 3단계 이하 안내
## 크로스체크
- → BOM: 여기서 정의한 품목이 BOM에서 모두 사용되는지
- → 단가: 모든 품목에 단가가 매핑되는지
- → 생산: 자체 생산 품목과 외주 품목 구분이 공정에 반영되는지

View File

@@ -0,0 +1,75 @@
# 모듈 03: 설계/BOM 구조
## SAM 테이블 구조
### models (설계 모델)
- tenant_id, code, name, category_id, description, status(DRAFT|RELEASED|ARCHIVED)
- 제품군별 마스터 모델 정의
### model_versions (모델 버전)
- model_id, version_no, status(DRAFT|RELEASED), released_at
- 설계 변경 시 버전 관리
### bom_templates (BOM 템플릿)
- model_version_id, name, description, is_default
### bom_template_items (BOM 항목)
- bom_template_id, component_type(MATERIAL|PRODUCT), component_id
- quantity, quantity_formula, waste_rate, is_optional
- sort_order, parent_item_id (다단계 BOM)
### product_components (제품 구성 부품)
- product_id, ref_type(MATERIAL|PRODUCT), ref_id
- quantity, waste_rate, sort_order
## 필수 수집 항목
### 제품 모델 (models)
- □ 제품 모델 코드 체계 (예: KSS-01 = 스크린 1호)
- □ 모델 수 (대략)
- □ 모델 변경 관리 여부 (ECN/ECO 프로세스)
- □ 모델별 도면 관리 여부
### BOM 구조 (bom_templates)
- □ 대표 제품 1개의 BOM 트리 (완제품→부품 관계)
- □ BOM 레벨 깊이 (1단계? 2단계? 3단계?)
- □ 반제품(서브어셈블리) 존재 여부
- □ 공통 부품 목록 (모든 제품에 공통)
- □ 옵션 부품 목록 (선택적 적용)
- □ 대체품/호환품 관리 필요성
### 수량 결정 (bom_template_items)
- □ 고정 수량 부품 (항상 1개, 2개 등)
- □ 계산 수량 부품 (치수 기반: CEIL(H1/피치) 등)
- □ LOSS율 적용 품목과 비율
- □ 최소 수량 제한 (예: 최소 2개 이상)
### 기존 BOM 자료
- □ BOM 엑셀 파일
- □ 도면 파일 (참고용)
- □ 부품 목록표
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "스크린은 가이드레일, 케이스, 모터, 제어기로 구성" | bom_template_items INSERT 4건 |
| "가이드레일은 높이에 따라 개수가 달라요" | quantity_formula = 'CEIL(H1/1219)*2' |
| "스크린원단은 5% 여유를 줍니다" | waste_rate = 5.0 |
| "연기차단재는 방화제품에만 들어갑니다" | is_optional = true, 조건 기록 |
| "절곡품은 반제품으로 관리합니다" | component_type = 'PRODUCT', type = 'SUBASSEMBLY' |
## 검증 규칙
- BOM 트리 미수집 → 견적 자동 계산 불가 경고 (최우선 수집 항목)
- quantity_formula 참조 변수가 치수 모듈에서 미정의 → 재질문
- waste_rate가 20% 초과 → "LOSS율이 높은데 맞나요?" 확인
- BOM 깊이 4단계 이상 → SAM 권장 3단계, 구조 재논의
- 대체품 있다고 했는데 구체적 매핑 미수집 → 재질문
## 크로스체크
- ← 품목분류: BOM 부품이 모두 categories에 존재하는지
- → 단가: BOM 부품 전체에 단가가 매핑되는지
- → 수량수식: quantity_formula의 변수가 치수 모듈에 정의되어 있는지
- → 생산공정: 각 부품의 투입 공정이 정의되어 있는지

View File

@@ -0,0 +1,77 @@
# 모듈 04: 단가 체계
## SAM 테이블 구조
### price_histories (단가 이력)
- tenant_id, product_id, material_id, price, unit
- effective_from, effective_to (시간축 관리)
- price_type(purchase|sale|internal), currency
- created_by, options(json)
### 관련 테이블
- products.unit_price (현재 단가 캐시)
- quote_formulas.formula (견적 계산식에서 단가 참조)
- bom_template_items.waste_rate (LOSS율)
## 필수 수집 항목
### 단가 관리 방식
- □ 현재 단가 관리 도구 (엑셀/ERP/구두)
- □ 단가표 파일 (엑셀 업로드)
- □ 단가 변경 주기 (수시/월/분기/연)
- □ 단가 변경 승인 프로세스 (누가 결정?)
### 단가 구성요소
- □ 재료비 (원자재 단가)
- □ 가공비 (자체/외주 가공 단가)
- □ 관리비/경비 비율
- □ 이윤율
- □ 운반비/설치비 별도 여부
### 단가 유형별
- □ 면적 기반 (원/㎡) — 스크린원단, 판재 등
- □ 길이 기반 (원/m) — 가이드레일, 파이프 등
- □ 중량 기반 (원/kg) — 강판, 알루미늄 등
- □ 수량 기반 (원/EA) — 모터, 제어기, 볼트 등
- □ 복합 단가 (길이×두께, 용량별 등)
### 차등 단가
- □ 고객 등급별 단가 차이
- □ 수량 할인 (대량 구매 시)
- □ 프로젝트별 특별 단가
- □ 계약 단가 vs 시장 단가
### LOSS율/마진
- □ LOSS율 적용 품목 및 비율
- □ LOSS 유형 구분 (절단/가공/불량)
- □ 마진율 설정 방식 (일괄/품목별/카테고리별)
- □ 최소 마진율 기준
### 환율/수입
- □ 수입 자재 여부
- □ 환율 적용 방식
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "가이드레일 m당 15,000원" | price_histories: product_id=GR, price=15000, unit='m' |
| "분기마다 단가 검토합니다" | tenants.options.pricing_update_cycle='quarterly' |
| "A급 거래처는 5% 할인" | clients.grade='A', pricing_rules.discount=5 |
| "스크린원단 LOSS 5%" | bom_template_items.waste_rate=5.0 |
| "마진율은 품목별로 다릅니다" | tenants.options.margin_type='per_item' |
## 검증 규칙
- 단가가 0원인 BOM 품목 존재 → 경고
- 면적/길이 단가의 단위 미확인 → "㎡당인가요? m당인가요?" 재질문
- LOSS율이 품목별로 다르다고 했는데 구체 수치 미수집 → 재질문
- 단가 변경 주기 미수집 → price_histories 설정 불가 경고
- 수입 자재가 있는데 환율 적용 방식 미수집 → 재질문
## 크로스체크
- ← BOM: BOM의 모든 부품에 단가가 정의되어 있는지
- ← 품목: 단가가 있는데 품목 마스터에 미등록인 항목
- → 견적: 견적서 항목 그룹과 단가 구성요소의 일치 여부
- → 수량수식: 수량 × 단가 계산이 실제 견적 금액과 일치하는지

View File

@@ -0,0 +1,89 @@
# 모듈 05: 견적/수주 관리
## SAM 테이블 구조
### quotes (견적)
- tenant_id, client_id, quote_number, title, status(DRAFT|SUBMITTED|APPROVED|REJECTED)
- total_amount, vat_amount, discount_rate, validity_days
- revision_no, parent_quote_id (개정 관리)
- options(json), created_by
### quote_items (견적 항목)
- quote_id, product_id, item_name, specification
- quantity, unit_price, amount, discount_rate
- group_name (재료비/노무비/경비 등), sort_order
### quote_formulas (견적 계산식)
- quote_id, category_id, formula_type, formula, variables(json)
- 치수 입력 → BOM 자동 계산 → 견적 금액 산출
### orders (수주)
- tenant_id, client_id, quote_id, order_number, status
- delivery_date, total_amount, options(json)
### order_items (수주 항목)
- order_id, product_id, quantity, unit_price, amount
- design_code, specification
### clients (거래처)
- tenant_id, name, business_number, type(CUSTOMER|VENDOR|BOTH)
- grade, payment_terms, credit_limit, contact_person
## 필수 수집 항목
### 견적 프로세스
- □ 견적 요청 → 작성 → 승인 → 제출 흐름
- □ 견적 작성자 (영업? 설계? 관리자?)
- □ 견적 승인 절차 (결재선)
- □ 견적 유효기간 (보통 몇 일?)
- □ 견적 개정 관리 (수정 시 이력 유지?)
### 견적서 양식
- □ 현재 사용 중인 견적서 양식 파일
- □ 항목 그룹 구분 (재료비/노무비/경비/이윤/부가세)
- □ 소계/합계 계산 구조
- □ 할인 적용 방식 (일괄/항목별)
- □ 부가세 표시 방식 (별도/포함)
- □ 견적 번호 체계
### 견적 계산
- □ 치수 입력 → 자동 계산 여부
- □ 오픈사이즈 → 제작사이즈 변환 공식
- □ BOM 자동 전개 → 수량/단가 자동 계산
- □ 수동 항목 추가 (설치비, 운반비 등)
### 수주 전환
- □ 견적 → 수주 전환 프로세스
- □ 수주 확정 시 필요 정보 (납기, PO번호 등)
- □ 수주 → 생산 연계 방식
### 특수 요구
- □ 다중 양식 (관급용/민간용/수출용)
- □ 산출내역서 별도 제출
- □ 위치별/층별 개별 산출
- □ 다국어 견적서
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "견적번호는 Q-2026-001 형식" | tenants.options.quote_numbering='Q-{YYYY}-{NNN}' |
| "유효기간 30일" | quotes.validity_days=30 |
| "재료비, 노무비, 경비로 구분" | quote_items.group_name 3종 |
| "부가세 별도 표시" | tenants.options.vat_display='separate' |
| "견적은 팀장 승인 후 제출" | approval_forms: 견적 결재선 설정 |
## 검증 규칙
- 견적 양식 미수집 → 출력물 생성 불가 경고 (필수)
- 치수→BOM 자동 계산인데 BOM 미수집 → BOM 모듈 먼저 완료 안내
- 항목 그룹이 단가 구성요소와 불일치 → 크로스체크 경고
- 수주 전환 프로세스 미수집 → 영업 플로우 미완성 경고
## 크로스체크
- ← 단가: 견적 항목 금액 = BOM 수량 × 단가 검증
- ← BOM: 자동 견적 시 BOM 전개 결과와 견적 항목 일치
- ← 치수: 오픈사이즈→제작사이즈 공식 적용 결과 검증
- → 수주: 견적→수주 전환 시 데이터 이관 항목 확인
- → 생산: 수주 확정 → 작업지시 생성 연계

View File

@@ -0,0 +1,79 @@
# 모듈 06: 생산/공정 관리
## SAM 테이블 구조
### processes (공정 정의)
- tenant_id, name, code, department_id, sort_order
- standard_time, unit, description
### work_orders (작업지시)
- tenant_id, order_id, product_id, quantity, status
- planned_start, planned_end, actual_start, actual_end
- assigned_department_id, priority
### production_results (생산 실적)
- work_order_id, process_id, quantity_produced, quantity_defective
- worker_id, start_time, end_time, options(json)
### 관련 테이블
- lots (LOT 추적), material_receipts (자재 투입)
- nonconforming_reports (부적합 보고)
## 필수 수집 항목
### 공정 흐름
- □ 주요 공정 순서 (절단→가공→조립→검사→포장 등)
- □ 각 공정별 작업 내용
- □ 공정별 담당 부서/작업반
- □ 공정별 표준 작업시간
- □ 병렬 공정 여부 (동시 진행 가능한 공정)
- □ 외주 가공 공정
### 생산 계획
- □ 생산 계획 수립 주기 (일/주/월)
- □ 계획 수립 기준 (수주 기반? 재고 기반?)
- □ 납기 계산 방식 (리드타임 합산?)
- □ 생산 능력(Capa) 관리 여부
### 작업지시
- □ 작업지시서 양식 (파일 수집)
- □ 작업지시 단위 (수주별? 제품별? LOT별?)
- □ 작업지시 발행 → 시작 → 완료 흐름
- □ 우선순위 관리 방식
### 생산 실적
- □ 실적 보고 방식 (실시간? 일일? 바코드?)
- □ 불량 보고 및 처리 방식
- □ 재작업 프로세스
- □ 실적 데이터 입력자 (작업자? 관리자?)
### 설비/장비
- □ 주요 설비 목록
- □ 설비별 일일 가동 시간
- □ 설비 보전/점검 주기
- □ 설비 고장 시 대응 방식
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "절단→절곡→조립→검사→포장 5공정" | processes INSERT 5건 (sort_order 1~5) |
| "조립은 1팀이 담당" | processes.department_id = 조립1팀 |
| "절단은 표준 30분" | processes.standard_time=30, unit='분' |
| "주 단위 생산 계획" | tenants.options.production_planning='weekly' |
| "수주별로 작업지시 발행" | tenants.options.work_order_unit='per_order' |
## 검증 규칙
- 공정 순서 미수집 → 작업지시/실적 관리 불가 경고 (필수)
- 공정이 있는데 담당 부서 미매핑 → 재질문
- 표준시간 미수집 → 납기 자동 계산 불가 경고
- 외주 공정이 있는데 외주 관리 방식 미수집 → 재질문
- 불량 처리 방식 미수집 → 품질 모듈과 연계 질문
## 크로스체크
- ← BOM: 각 공정에서 투입되는 자재가 BOM에 존재하는지
- ← 품목: 생산 대상 품목이 품목 마스터에 등록되어 있는지
- → 품질: 검사 공정의 검사 기준이 정의되어 있는지
- → 재고: 완제품 입고 프로세스와 연계

View File

@@ -0,0 +1,62 @@
# 모듈 07: 품질 관리
## SAM 테이블 구조
### material_inspections (수입검사)
- tenant_id, material_receipt_id, inspector_id, status, result(PASS|FAIL|CONDITIONAL)
- inspection_date, options(json)
### material_inspection_items (검사 항목)
- inspection_id, item_name, standard, method, result, judgment
### nonconforming_reports (부적합 보고)
- tenant_id, type, source, product_id, lot_id
- defect_type, quantity, description, corrective_action, status
### audit_checklists (점검표)
- tenant_id, name, category, items(json)
## 필수 수집 항목
### 수입검사
- □ 수입검사 대상 품목 (전수? 샘플? 품목별 다름?)
- □ 검사 항목 (외관, 치수, 기능, 성적서 등)
- □ 합격 기준 (수치 기준, 허용 범위)
- □ 검사 장비 목록
- □ 불합격 시 처리 (반품, 특채, 재검사)
### 공정검사
- □ 공정 중 자주검사 항목
- □ 순회검사 주기/방법
- □ 검사 기록 방식 (체크시트, 바코드 등)
### 완제품검사
- □ 출하 전 최종 검사 항목
- □ 시험성적서 발행 여부
- □ 검사 성적서 보관 기간
### 불량 관리
- □ 불량 유형 분류 (외관, 치수, 기능, 원자재 등)
- □ 불량 처리 프로세스 (폐기, 재작업, 특채)
- □ 시정/예방 조치 프로세스
- □ 불량률 목표 (KPI)
### 인증
- □ 보유 인증 (ISO 9001, ISO 14001, KC 등)
- □ 인증 심사 주기
- □ 인증 관련 문서 관리 필요성
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "강판은 전수검사, 볼트는 샘플" | material_inspections 정책 설정 |
| "외관, 치수, 두께 3가지 검사" | material_inspection_items 3건 |
| "불량은 외관불량, 치수불량 구분" | classifications: group='defect_type' |
| "ISO 9001 인증 보유" | tenants.options.certifications=['ISO9001'] |
## 크로스체크
- ← 품목: 수입검사 대상 품목이 품목 마스터에 있는지
- ← 생산: 공정검사 위치가 공정 순서와 일치하는지
- → 거래처: 불합격 시 공급업체 관리와 연계

View File

@@ -0,0 +1,63 @@
# 모듈 08: 재고/물류 관리
## SAM 테이블 구조
### material_receipts (자재 입고)
- tenant_id, vendor_id, receipt_number, receipt_date, status
- items: material_id, quantity, unit_price, lot_number
### lots (LOT 관리)
- tenant_id, lot_number, product_id, material_id
- quantity, remaining_quantity, manufactured_date, expiry_date, status
### stocks (재고)
- tenant_id, product_id, warehouse_id, quantity, reserved_quantity
### lot_sales (LOT 소진)
- lot_id, order_item_id, quantity, sale_date
## 필수 수집 항목
### 입출고 프로세스
- □ 자재 입고 프로세스 (발주→입고→검사→입고확정)
- □ 제품 출고 프로세스 (수주→출하지시→출고→납품)
- □ 입출고 전표 양식
### 창고/저장소
- □ 창고 수와 위치 (본사, 공장, 외부 등)
- □ 창고 내 구역 구분 (원자재/반제품/완제품/불량)
- □ 적재 방식 (FIFO, LIFO, 지정 위치)
### 재고 관리
- □ 안전재고 기준 (품목별 최소 보유량)
- □ 재고 실사 주기 (월/분기/연)
- □ 바코드/QR 사용 여부
- □ 재고 평가 방법 (이동평균, 선입선출, 총평균)
### LOT 추적
- □ LOT 관리 필요 품목 범위
- □ LOT 번호 체계
- □ LOT 추적 수준 (원자재→완제품? 공정별?)
- □ 유효기한 관리 필요성
### 운송/배송
- □ 배송 방식 (자가/택배/화물)
- □ 배송 지역 범위
- □ 포장 규격/방법
- □ 반품 처리 프로세스
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "본사 창고, 공장 창고 2곳" | warehouses INSERT 2건 |
| "강판은 안전재고 500kg" | stock_settings: product_id, safety_stock=500 |
| "바코드로 입출고 관리" | tenants.options.barcode_enabled=true |
| "LOT은 입고일+순번" | tenants.options.lot_format='{YYYYMMDD}-{NNN}' |
## 크로스체크
- ← 품목: 재고 관리 대상 품목이 품목 마스터에 있는지
- ← 생산: 완제품 입고 프로세스와 생산 실적 연계
- ← 품질: 입고 → 수입검사 → 재고확정 흐름 확인
- → 회계: 재고 금액 = 수량 × 단가 정합성

View File

@@ -0,0 +1,73 @@
# 모듈 09: 회계/재무 관리
## SAM 테이블 구조
### sales (매출)
- tenant_id, client_id, order_id, sale_date, amount, vat_amount
- payment_method, status, tax_invoice_id, options(json)
### purchases (매입)
- tenant_id, vendor_id, purchase_date, amount, vat_amount
- category(자재/외주/경비), status, tax_invoice_id
### deposits (입금)
- tenant_id, client_id, deposit_date, amount, method
- sale_id, memo, status
### withdrawals (출금)
- tenant_id, vendor_id, withdrawal_date, amount, method
- purchase_id, memo, status
### expected_expenses (예상지출)
- tenant_id, purchase_id, expected_date, amount, status
### bad_debts (회수불능금)
- tenant_id, client_id, amount, reason, status
## 필수 수집 항목
### 매출/매입
- □ 매출 인식 시점 (출하? 검수? 세금계산서 발행?)
- □ 매입 인식 시점 (입고? 세금계산서 수취?)
- □ 세금계산서 발행 방식 (전자/종이/바로빌)
- □ 매출/매입 분류 체계 (계정과목)
### 입금/출금
- □ 결제 조건 (선금/중도금/잔금 비율)
- □ 결제 수단 (계좌이체/어음/카드/현금)
- □ 수금 주기 (월말/납품 후 N일)
- □ 미수금 관리 방식
- □ 미지급금 관리 방식
### 원가 관리
- □ 원가 계산 방식 (실제원가/표준원가)
- □ 원가 구성 항목 (재료비/노무비/경비)
- □ 간접비 배부 기준
- □ 손익 분석 단위 (프로젝트별/월별/제품별)
### 예산/계획
- □ 예산 수립 여부
- □ 월별 실적 대비 예산 관리
- □ 자금 계획 관리 필요성
### 바로빌 연동
- □ 바로빌 사용 여부
- □ 전자세금계산서 자동 발행
- □ 카드 매출 조회
- □ 은행 계좌 조회
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "납품 후 30일 이내 입금" | clients.payment_terms='NET30' |
| "세금계산서는 바로빌로" | tenants.options.tax_invoice_provider='barobill' |
| "선금 30%, 잔금 70%" | tenants.options.payment_split=[30,70] |
| "월별로 손익 분석합니다" | tenants.options.pnl_unit='monthly' |
## 크로스체크
- ← 견적: 견적 금액 → 매출 금액 정합성
- ← 거래처: 결제 조건이 거래처별로 설정되어 있는지
- ← 재고: 재고 금액과 매입 금액 정합성
- → 바로빌: 바로빌 연동 설정이 완료되어 있는지

View File

@@ -0,0 +1,59 @@
# 모듈 10: 인사/급여 관리
## SAM 관련 기능
### 근태 관리
- 출퇴근 기록, 근무시간 계산
- 연장/야간/휴일 근무
### 급여 관리
- 기본급, 수당, 공제 항목
- 급여 명세서 발행
### 휴가 관리
- 연차, 특별휴가, 경조사
- 휴가 잔여일 관리
### 인사 정보
- 직원 정보, 인사 발령
- 직급/직위 체계
## 필수 수집 항목
### 근무 체계
- □ 근무 형태 (주 5일/교대/시차 등)
- □ 정규 근무시간 (09:00~18:00 등)
- □ 출퇴근 기록 방식 (카드/지문/앱/수기)
- □ 연장근무 승인 프로세스
- □ 교대 근무 패턴 (해당 시)
### 급여 구조
- □ 급여 체계 (월급제/시급제/연봉제)
- □ 급여일 (매월 N일)
- □ 기본급 외 수당 항목 (직책수당, 자격수당, 식대 등)
- □ 공제 항목 (4대보험, 소득세, 조합비 등)
- □ 상여금 지급 기준
### 휴가 정책
- □ 연차 부여 기준 (근속 연수별)
- □ 특별휴가 종류 (경조사, 보건, 교육 등)
- □ 휴가 승인 프로세스
### 조직/인사
- □ 직급 체계 (사원→대리→과장→차장→부장→이사)
- □ 인사 평가 주기
- □ 교육 훈련 관리 필요성
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "9시~6시 주5일 근무" | work_settings: start=09:00, end=18:00, days=5 |
| "매월 25일 급여 지급" | tenants.options.payday=25 |
| "입사 1년 미만은 연차 11일" | leave_policies: year=0, days=11 |
## 크로스체크
- ← 부서: 인사 조직과 부서 구조 일치 여부
- → 생산: 작업자 배정과 인사 정보 연계
- → 회계: 급여 지출과 재무 연계

View File

@@ -0,0 +1,54 @@
# 모듈 11: 결재/문서 관리
## SAM 테이블 구조
### approvals (결재 문서)
- tenant_id, form_id, title, content(json), status(DRAFT|PENDING|APPROVED|REJECTED)
- requester_id, current_step, options(json)
### approval_steps (결재 단계)
- approval_id, step_order, approver_id, status, comment
- approved_at, delegated_from_id
### approval_forms (결재 양식)
- tenant_id, name, code, fields(json), approval_line_config(json)
- target_type (견적, 구매, 휴가 등과 연계)
### documents (문서)
- tenant_id, template_id, title, content, version, status
## 필수 수집 항목
### 결재 체계
- □ 결재선 구성 (순차/병렬/조건부)
- □ 결재 단계 수 (보통 2~4단계)
- □ 결재 권한 기준 (직급? 직책? 금액?)
- □ 전결 규정 (금액별 전결 범위)
- □ 대결/후결 규정
### 결재 대상
- □ 견적서 결재 (금액 기준)
- □ 구매 요청 결재
- □ 휴가 신청 결재
- □ 경비 청구 결재
- □ 기타 결재 문서 종류
### 문서 관리
- □ 문서 양식 목록
- □ 문서 번호 체계
- □ 문서 보관 기간
- □ 전자문서 vs 종이문서
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "견적은 팀장→부장→이사 순서" | approval_forms: 견적, 3단계 순차 결재 |
| "100만원 이하는 팀장 전결" | approval_forms: amount_threshold=1000000, 1단계 |
| "구매요청서, 견적서, 휴가신청 3종" | approval_forms INSERT 3건 |
## 크로스체크
- ← 견적: 견적 결재선 설정이 견적 프로세스와 일치
- ← 인사: 휴가 결재선과 부서 구조 일치
- ← 조직: 결재자 직급이 조직도에 존재

View File

@@ -0,0 +1,60 @@
# 모듈 12: 바로빌/외부 연동
## SAM 테이블 구조
### barobill_members (바로빌 회원)
- tenant_id, biz_no, corp_name, cert_key, is_active
- server_mode(test|production), options(json)
### 관련 기능
- 전자세금계산서 발행/조회
- 카드 매출 자동 수집
- 은행 계좌 거래내역 조회
- 카카오톡/SMS 알림 발송
- 홈택스 연동
## 필수 수집 항목
### 전자세금계산서
- □ 현재 세금계산서 발행 방식 (종이/전자/홈택스 직접)
- □ 월 평균 발행 건수
- □ 발행 담당자
- □ 매출/매입 세금계산서 자동 연동 필요성
### 카드/은행
- □ 법인카드 사용 여부 + 카드사 목록
- □ 주거래 은행 + 계좌 수
- □ 카드 매출 자동 수집 필요성
- □ 은행 거래내역 자동 조회 필요성
### 알림 서비스
- □ 카카오톡 알림톡 사용 의향
- □ SMS 발송 필요성
- □ 이메일 알림 범위
### 기타 외부 연동
- □ 기존 사용 중인 외부 서비스
- □ 택배/물류 연동 필요성
- □ PG 결제 연동 필요성
- □ 공공데이터 연동 (기상청, 국세청 등)
## 매핑 규칙
| 고객 답변 | SAM 매핑 |
|---------|---------|
| "바로빌로 세금계산서 발행 중" | barobill_members 설정 + 연동 활성화 |
| "법인카드 2장 (삼성, 현대)" | 바로빌 카드 등록 2건 |
| "카카오톡 알림 필요" | 바로빌 카카오톡 채널 설정 |
| "세금계산서 월 50건 정도" | 구독 플랜 결정 참고 |
## 검증 규칙
- 바로빌 사용 시 사업자등록번호 필수 (테넌트 기초 모듈과 연계)
- 월 발행 건수에 따른 요금제 안내
- 테스트 모드에서 먼저 연동 후 운영 전환 안내
## 크로스체크
- ← 테넌트: 사업자등록번호가 테넌트 정보와 일치
- ← 회계: 매출/매입 세금계산서와 회계 연동
- → Fake 서비스: 데모 시 Fake 모드 활용 안내

View File

@@ -0,0 +1,39 @@
# 업종 프리셋: 블라인드/스크린/방화셔터
## 업종 특성
- 치수 기반 주문생산 (수주 → 설계 → 생산)
- 오픈사이즈 → 제작사이즈 변환 공식이 핵심
- BOM이 치수에 따라 동적 변화 (모터 용량, 가이드레일 수 등)
- 방화 인증 제품은 구성 변경 불가
- 현장 설치 필요 (설치비 별도 산출)
## SAM 활성화 권장 모듈
- ✅ 품목분류: 제품군별 카테고리 (스크린, 셔터, 블라인드)
- ✅ 설계/BOM: 모델별 BOM, 치수 기반 자동 전개
- ✅ 견적: 오픈사이즈 입력 → 자동 견적
- ✅ 단가: 면적/길이/수량 기반 복합 단가
- ✅ 생산: 절단→절곡→조립→검사→포장
- ✅ 품질: 방화 인증 검사, 수입검사
- ⬜ 재고: 부품 재고 (완제품은 주문생산이라 재고 적음)
- ⬜ 회계: 기본 매출/매입
- ⬜ 인사: 소규모면 간소화
## 인터뷰 우선순위
1. 제품 분류 + 모델 코드 체계
2. BOM 구조 (대표 제품 1개 먼저)
3. 치수→제작 변환 공식
4. 부품별 선택 조건 (모터 용량, 가이드레일 등)
5. 단가 체계 (면적/길이 기반)
6. 견적서 양식
## AI가 미리 알고 있는 것
- 가이드레일 표준 길이: 1219, 2438, 3048, 3305mm
- 모터 용량 범위: 150K~1000K (무게 기반 선택)
- 케이스 크기: 소재 + 높이에 따라 결정
- 방화스크린: 내화시험 1~3시간, 구성 고정
- 설치유형: 벽면형, 측면형, 천장형 → 부품 차이
## 예상 질문 힌트
- "혹시 방화 인증 제품이 있으신가요? 방화 제품은 구성이 고정이라 별도 관리가 필요합니다"
- "가이드레일 길이 조합은 어떻게 하시나요? 보통 1219mm, 2438mm를 조합하시죠?"
- "모터 용량 선택이 무게 기반인가요, 면적 기반인가요?"

View File

@@ -0,0 +1,36 @@
# 업종 프리셋: 건설/시공
## 업종 특성
- 프로젝트(현장) 기반 원가 관리
- 위치별(층/부호) 산출내역서
- 실행예산 vs 견적 비교 관리
- 설치/시공 인력 관리 (노무비)
- 하도급/협력업체 관리
## SAM 활성화 권장 모듈
- ✅ 품목분류: 제품+시공 분류
- ✅ 견적: 위치별 산출, 관급/민간 양식
- ✅ 단가: 관급단가, 실행단가 이중 관리
- ✅ 생산: 시공 일정, 작업일보
- ⬜ BOM: 단순 BOM (설치 자재)
- ✅ 회계: 프로젝트별 손익
- ✅ 인사: 현장 인력 관리
## 인터뷰 우선순위
1. 시공 유형 (신축/리모델링/유지보수)
2. 견적 양식 (관급/민간)
3. 산출내역서 구조
4. 실행예산 관리
5. 하도급/협력업체
6. 현장 인력 관리
## AI가 미리 알고 있는 것
- 관급공사: 내역서 양식 규정, 일위대가, 품셈
- 민간공사: 자유 양식, 실적 기반
- 원가 구조: 재료비 + 노무비 + 경비 + 일반관리비 + 이윤
- 하도급법: 하도급대금 30일 이내 지급
## 예상 질문 힌트
- "주로 관급공사인가요, 민간공사인가요?"
- "산출내역서를 층별/부호별로 작성하시나요?"
- "실행예산과 견적 금액을 별도로 관리하시나요?"

View File

@@ -0,0 +1,36 @@
# 업종 프리셋: 식품 제조
## 업종 특성
- LOT/유통기한 추적 필수 (식품안전법)
- HACCP/GMP 인증 기반 품질 관리
- 원재료 시세 변동 (농산물, 수입원료)
- 배합 비율 기반 BOM (레시피)
- 계량 단위 다양 (kg, L, 포, 박스)
## SAM 활성화 권장 모듈
- ✅ 품목분류: 원재료/반제품/완제품
- ✅ BOM: 배합 비율(레시피) 기반
- ✅ 단가: 원재료 시세 연동
- ✅ 생산: 배합→가공→포장→검사
- ✅ 품질: HACCP, 미생물/이화학 검사
- ✅ 재고: LOT 추적, 유통기한, FIFO 필수
- ✅ 회계: 원가 분석 (원재료비 변동)
## 인터뷰 우선순위
1. 제품 종류 + 원재료 목록
2. 배합 비율 (레시피)
3. LOT 관리 체계
4. 유통기한 관리
5. 품질 검사 항목 (HACCP)
6. 재고 관리 (FIFO)
## AI가 미리 알고 있는 것
- HACCP 7원칙: 위해분석, CCP, 한계기준, 모니터링, 개선조치, 검증, 기록
- LOT 추적: 원재료 LOT → 생산 LOT → 출하 LOT 연계
- 유통기한: 제조일+보존일수, 또는 고정 날짜
- 계량: 투입량 오차 허용 범위 관리
## 예상 질문 힌트
- "HACCP 인증을 받으셨나요? CCP 관리 포인트가 어디인가요?"
- "원재료 LOT에서 완제품 LOT까지 추적이 필요하신가요?"
- "유통기한은 제조일 기준 몇 일로 설정하시나요?"

View File

@@ -0,0 +1,27 @@
# 업종 프리셋: 범용 제조업
## 업종 특성
- 특정 업종에 해당하지 않는 일반 제조업
- 표준 MRP/MES 패턴 적용
- 모든 모듈을 균형있게 파악 필요
## SAM 활성화 권장 모듈
- ✅ 전체 모듈 균형 파악 후 결정
- 인터뷰 과정에서 필요 모듈 자동 판별
## 인터뷰 우선순위
1. 회사 개요 + 주요 제품
2. 생산 방식 (주문생산/재고생산/혼합)
3. 현재 시스템/도구 (ERP/엑셀/수작업)
4. 가장 불편한 점 (Pain Point)
5. 위 결과에 따라 도메인 순서 자동 결정
## AI가 미리 알고 있는 것
- 주문생산(MTO): 수주 → 설계 → 자재 → 생산 → 출하
- 재고생산(MTS): 수요예측 → 생산계획 → 생산 → 재고 → 출하
- 혼합형: 주요 부품 재고생산 + 완제품 주문조립(ATO)
## 예상 질문 힌트
- "주로 주문을 받고 생산하시나요, 아니면 미리 만들어 놓으시나요?"
- "현재 ERP나 관리 프로그램을 사용하고 계신가요?"
- "업무 중 가장 불편하거나 시간이 많이 걸리는 부분은 어디인가요?"

View File

@@ -0,0 +1,37 @@
# 업종 프리셋: 기계조립
## 업종 특성
- 다단계 BOM (완제품 → 서브어셈블리 → 부품 → 원자재)
- 구매 부품 비중 높음 (모터, 센서, 베어링 등)
- 리드타임 관리 중요 (부품 수급 일정)
- 대체품/호환품 관리 필요
- 시리얼 번호(S/N) 추적
## SAM 활성화 권장 모듈
- ✅ 품목분류: 기능별 부품 카테고리
- ✅ BOM: 다단계 BOM (3~4레벨)
- ✅ 단가: 수량 기반 (원/EA)
- ✅ 생산: 조립 라인 공정
- ✅ 품질: 조립 검사, 기능 시험
- ✅ 재고: 부품 안전재고, MRP
- ✅ 견적: 표준 견적 (BOM 기반)
- ✅ 회계: 원가 분석
## 인터뷰 우선순위
1. 제품 구조 (완제품 → 유닛 → 부품)
2. BOM 트리 (대표 제품)
3. 핵심 구매 부품 목록
4. 조립 공정 순서
5. 리드타임/납기 관리
6. 대체품 관리
## AI가 미리 알고 있는 것
- BOM 3~4단계가 일반적
- 구매 부품: MOQ(최소발주수량), 리드타임, 대체품
- 조립 공정: 서브어셈블리 조립 → 본체 조립 → 시험 → 포장
- S/N 추적: 고가 부품, 보증 대상 부품
## 예상 질문 힌트
- "제품이 여러 유닛으로 나뉘나요? 서브어셈블리 개념이 있나요?"
- "구매 부품 중 리드타임이 긴 것은 어떤 건가요?"
- "동일 기능의 대체 부품을 관리하시나요?"

View File

@@ -0,0 +1,38 @@
# 업종 프리셋: 금속가공
## 업종 특성
- 소재(강판, SUS, 알루미늄) 중심 원가 구조
- 절단/절곡/용접/도장 등 가공 공정 중심
- 중량 기반 단가가 주력 (원/kg)
- 외주 가공 비중 높음
- LOSS율(절단 스크랩) 관리 중요
## SAM 활성화 권장 모듈
- ✅ 품목분류: 소재별 + 가공유형별
- ✅ BOM: 원자재 → 가공품 1~2단계
- ✅ 단가: 중량 기반 + 가공비 별도
- ✅ 생산: 절단→가공→검사 공정
- ✅ 품질: 치수 검사, 표면 검사
- ✅ 재고: 원자재 재고 관리 (안전재고)
- ⬜ 견적: 수동 견적이 많으면 간소화
- ⬜ 회계: 기본 매출/매입
## 인터뷰 우선순위
1. 소재 종류와 규격
2. 가공 공정 순서
3. 단가 구조 (소재비 + 가공비)
4. LOSS율 (절단 스크랩 비율)
5. 외주 가공 관리
6. 재고/안전재고
## AI가 미리 알고 있는 것
- 강판 규격: 두께(t), 폭(W), 길이(L) → 중량 = t×W×L×비중
- 비중: 철 7.85, SUS 7.93, 알루미늄 2.71
- 절단 LOSS율: 보통 3~10%
- 가공비: 절단(원/컷), 절곡(원/벤드), 용접(원/m)
- 도금/도장: 면적 기반 (원/㎡)
## 예상 질문 힌트
- "소재는 주로 어떤 것을 사용하시나요? 강판, SUS, 알루미늄 중에서?"
- "절단 시 스크랩 비율은 어느 정도 되시나요?"
- "가공비는 절단 건당, 절곡 건당으로 계산하시나요?"

View File

@@ -0,0 +1,67 @@
# SAM AI 인터뷰어 시스템 프롬프트
당신은 **(주)코드브릿지엑스**가 개발한 **SAM(Smart Automation Management)** ERP/MES 시스템의 전문 도입 컨설턴트입니다.
## 당신의 역할
고객사(제조업체)를 방문하여, SAM 시스템에 필요한 모든 업무 정보를 체계적으로 수집하는 **AI 인터뷰어**입니다. 당신은 SAM 시스템의 모든 모듈, 테이블, 비즈니스 로직을 학습한 상태이며, 수집한 정보를 SAM 설정으로 직접 변환할 수 있습니다.
## SAM 시스템 개요
SAM은 **멀티테넌트 클라우드 ERP/MES** 시스템입니다:
- 하나의 시스템에 여러 고객사(테넌트)가 독립적으로 운영
- 각 테넌트는 고유한 품목, BOM, 단가, 공정, 견적 양식을 설정
- 견적 → 수주 → 생산 → 출하 → 정산의 비즈니스 플로우
- 전자결재, 바코드, 전자세금계산서 연동
## 핵심 모듈 (학습 완료)
| 모듈 | 역할 | 핵심 테이블 |
|------|------|-----------|
| 품목분류 | 제품/자재/부품 카테고리 관리 | categories, category_fields |
| 설계/BOM | 제품 모델 설계, BOM 구성 | models, model_versions, bom_templates |
| 단가 | 시간축 단가 관리, 원가 구성 | price_histories |
| 견적 | 자동 견적 계산, 개정 관리 | quotes, quote_items, quote_formulas |
| 수주 | 견적→수주 변환, 납기 관리 | orders, order_items |
| 생산 | 작업지시, 공정, 생산 실적 | work_orders, production_results |
| 품질 | 수입검사, 공정검사, 부적합 | material_inspections, nonconforming_reports |
| 재고 | 입출고, LOT 추적, 안전재고 | material_receipts, lots, stocks |
| 회계 | 매출/매입, 입출금, 세금계산서 | sales, purchases, deposits |
| 인사 | 근태, 급여, 휴가 | HR 테이블들 |
| 결재 | 전자결재, 승인 워크플로우 | approvals, approval_steps |
| 거래처 | 고객/공급업체 관리 | clients |
## 인터뷰 지침
### 대화 방식
1. **자연스러운 한국어 대화체**를 사용한다 (존댓말)
2. 한 번에 **1~2개 질문**만 한다 (폭격 금지)
3. 답변이 모호하면 **구체적 예시**를 요청한다
4. 전문 용어를 쓸 때는 **쉬운 설명**을 함께 한다
5. 고객의 현재 방식을 **존중**하며, SAM으로의 전환을 자연스럽게 안내한다
### 데이터 수집 원칙
1. 답변에서 **구조화 가능한 데이터**를 발견하면 즉시 JSON으로 추출한다
2. SAM 테이블에 **매핑 불가능한 답변**은 추가 질문으로 구체화한다
3. **필수 항목**이 누락되면 대화를 이어가며 자연스럽게 재질문한다
4. 이전 도메인에서 수집한 데이터와 **모순**이 있으면 확인 질문한다
### 응답 형식
모든 응답 마지막에 반드시 아래 JSON 블록을 포함한다:
```json
{
"extracted_data": {
"테이블명": [{"필드": "값"}]
},
"covered_questions": [1, 3, 5],
"coverage_percent": 45,
"next_focus": "다음에 물어볼 영역",
"warnings": ["BOM에 '보강재'가 있는데 품목 분류에 없음"],
"sam_mapping": {
"table": "categories",
"action": "INSERT",
"data": [{"name": "방화스크린", "type": "PRODUCT"}]
}
}
```