From f326194c991bff9599456fec37e2516b603b01cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Fri, 13 Feb 2026 03:41:20 +0900 Subject: [PATCH] =?UTF-8?q?feat:=EC=A0=9C=ED=92=88=EA=B2=80=EC=82=AC=20?= =?UTF-8?q?=EC=84=B1=EC=A0=81=EC=84=9C=20=EC=96=91=EC=8B=9D=20=EC=8B=9C?= =?UTF-8?q?=EB=8D=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- .../ProductInspectionTemplateSeeder.php | 378 ++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 database/seeders/ProductInspectionTemplateSeeder.php diff --git a/database/seeders/ProductInspectionTemplateSeeder.php b/database/seeders/ProductInspectionTemplateSeeder.php new file mode 100644 index 00000000..3f93a930 --- /dev/null +++ b/database/seeders/ProductInspectionTemplateSeeder.php @@ -0,0 +1,378 @@ +getTemplateDefinition(); + + $this->cleanupExisting($def['name']); + + $template = DocumentTemplate::create([ + 'tenant_id' => $this->tenantId, + 'name' => $def['name'], + 'category' => '품질/제품검사', + 'title' => $def['title'], + 'company_name' => '케이디산업', + 'footer_remark_label' => '부적합 내용', + 'footer_judgement_label' => '종합판정', + 'footer_judgement_options' => ['합격', '불합격'], + 'is_active' => true, + ]); + + $this->createApprovalLines($template->id); + $this->createBasicFields($template->id); + + foreach ($def['sections'] as $i => $sectionDef) { + $this->createSection($template->id, $sectionDef['title'], $sectionDef['items'], $i + 1); + } + + $this->createSectionFields($template->id); + $this->createColumns($template->id, $def['columns']); + + $this->command->info("✅ {$def['name']} (ID: {$template->id})"); + } + + private function getTemplateDefinition(): array + { + return [ + 'name' => '제품검사 성적서', + 'title' => '제 품 검 사 성 적 서', + 'sections' => [ + [ + 'title' => '제품검사 기준서', + 'items' => [], + ], + [ + 'title' => '제품검사 DATA', + 'items' => [ + [ + 'category' => '외관', + 'item' => '외관검사', + 'standard' => '사용상 결함이 없을 것', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '기능', + 'item' => '작동상태', + 'standard' => '정상 작동', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '기능', + 'item' => '개폐속도', + 'standard' => '규정 속도 범위 이내', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '성능', + 'item' => '방연성능', + 'standard' => '기준 적합', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '성능', + 'item' => '차연성능', + 'standard' => '기준 적합', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '성능', + 'item' => '내화성능', + 'standard' => '기준 적합', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '안전', + 'item' => '안전장치', + 'standard' => '정상 작동', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '안전', + 'item' => '비상개방', + 'standard' => '정상 작동', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '설치', + 'item' => '전기배선', + 'standard' => '규정 적합', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '설치', + 'item' => '설치상태', + 'standard' => '규정 적합', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + [ + 'category' => '부속', + 'item' => '부속품', + 'standard' => '누락 없음', + 'method' => 'visual', + 'measurement_type' => 'checkbox', + 'frequency' => '전수', + 'frequency_n' => null, + 'frequency_c' => null, + ], + ], + ], + ], + 'columns' => [ + ['label' => 'NO', 'column_type' => 'text', 'width' => '50px', 'sort_order' => 1], + ['label' => '검사항목', 'column_type' => 'text', 'width' => '120px', 'sort_order' => 2], + ['label' => '검사기준', 'column_type' => 'text', 'width' => '200px', 'sort_order' => 3], + ['label' => '판정', 'column_type' => 'select', 'width' => '100px', 'sort_order' => 4], + ], + ]; + } + + /** + * 결재라인: 작성(품질) / 검토(품질QC) / 승인(경영) + */ + private function createApprovalLines(int $templateId): void + { + $lines = [ + ['name' => '작성', 'dept' => '품질', 'role' => '담당자', 'sort_order' => 1], + ['name' => '검토', 'dept' => '품질', 'role' => 'QC', 'sort_order' => 2], + ['name' => '승인', 'dept' => '경영', 'role' => '대표', 'sort_order' => 3], + ]; + + foreach ($lines as $line) { + DocumentTemplateApprovalLine::create(array_merge( + ['template_id' => $templateId], + $line, + )); + } + } + + /** + * 기본정보 필드 (제품검사) + */ + private function createBasicFields(int $templateId): void + { + $fields = [ + ['label' => '납품명', 'field_type' => 'text', 'sort_order' => 1], + ['label' => '제품명', 'field_type' => 'text', 'sort_order' => 2], + ['label' => '발주처', 'field_type' => 'text', 'sort_order' => 3], + ['label' => 'LOT NO', 'field_type' => 'text', 'sort_order' => 4], + ['label' => '로트크기', 'field_type' => 'text', 'sort_order' => 5], + ['label' => '검사일자', 'field_type' => 'date', 'sort_order' => 6], + ['label' => '검사자', 'field_type' => 'text', 'sort_order' => 7], + ]; + + foreach ($fields as $field) { + DocumentTemplateBasicField::create(array_merge( + ['template_id' => $templateId], + $field, + )); + } + } + + /** + * 검사 섹션 + 항목 + */ + private function createSection(int $templateId, string $title, array $items, int $sortOrder): void + { + $section = DocumentTemplateSection::create([ + 'template_id' => $templateId, + 'title' => $title, + 'sort_order' => $sortOrder, + ]); + + foreach ($items as $i => $item) { + DocumentTemplateSectionItem::create(array_merge( + ['section_id' => $section->id, 'sort_order' => $i + 1], + $item, + )); + } + } + + /** + * 검사 기준서 동적 필드 정의 (중간검사와 동일 구조) + * + * category, item, standard(text_with_criteria), + * tolerance(json_tolerance), method(select_api→measurement_type 자동매핑), + * measurement_type(select), frequency(composite_frequency) + */ + private function createSectionFields(int $templateId): void + { + $fields = [ + [ + 'field_key' => 'category', + 'label' => '분류', + 'field_type' => 'text', + 'width' => '65px', + 'is_required' => false, + 'sort_order' => 0, + ], + [ + 'field_key' => 'item', + 'label' => '검사항목', + 'field_type' => 'text', + 'width' => '130px', + 'is_required' => true, + 'sort_order' => 1, + ], + [ + 'field_key' => 'standard', + 'label' => '검사 기준/범위', + 'field_type' => 'text_with_criteria', + 'width' => '220px', + 'is_required' => false, + 'sort_order' => 2, + ], + [ + 'field_key' => 'tolerance', + 'label' => '공차/범위', + 'field_type' => 'json_tolerance', + 'width' => '85px', + 'is_required' => false, + 'sort_order' => 3, + ], + [ + 'field_key' => 'method', + 'label' => '검사방식', + 'field_type' => 'select_api', + 'width' => '110px', + 'is_required' => false, + 'options' => [ + 'api_endpoint' => '/api/admin/common-codes/inspection_method', + 'auto_map' => [ + 'target_field' => 'measurement_type', + 'mapping' => [ + 'visual' => 'checkbox', + 'check' => 'numeric', + 'mill_sheet' => 'single_value', + 'substitute_cert' => 'substitute', + 'certified_agency' => 'single_value', + 'other' => 'text', + ], + ], + ], + 'sort_order' => 4, + ], + [ + 'field_key' => 'measurement_type', + 'label' => '측정유형', + 'field_type' => 'select', + 'width' => '100px', + 'is_required' => false, + 'options' => [ + 'choices' => [ + ['code' => 'checkbox', 'name' => 'OK/NG 체크'], + ['code' => 'numeric', 'name' => '수치입력(3)'], + ['code' => 'single_value', 'name' => '단일값'], + ['code' => 'substitute', 'name' => '성적서 대체'], + ['code' => 'text', 'name' => '자유입력'], + ], + ], + 'sort_order' => 5, + ], + [ + 'field_key' => 'frequency', + 'label' => '검사주기', + 'field_type' => 'composite_frequency', + 'width' => '120px', + 'is_required' => false, + 'sort_order' => 6, + ], + ]; + + foreach ($fields as $field) { + DocumentTemplateSectionField::create(array_merge( + ['template_id' => $templateId], + $field, + )); + } + } + + /** + * 데이터 테이블 컬럼 + */ + private function createColumns(int $templateId, array $columns): void + { + foreach ($columns as $col) { + DocumentTemplateColumn::create(array_merge( + ['template_id' => $templateId], + $col, + )); + } + } + + private function cleanupExisting(string $name): void + { + $existing = DocumentTemplate::where('tenant_id', $this->tenantId) + ->where('name', $name) + ->first(); + + if (! $existing) { + return; + } + + DocumentTemplateColumn::where('template_id', $existing->id)->delete(); + DocumentTemplateSectionField::where('template_id', $existing->id)->delete(); + $sections = DocumentTemplateSection::where('template_id', $existing->id)->get(); + foreach ($sections as $section) { + DocumentTemplateSectionItem::where('section_id', $section->id)->delete(); + } + DocumentTemplateSection::where('template_id', $existing->id)->delete(); + DocumentTemplateBasicField::where('template_id', $existing->id)->delete(); + DocumentTemplateApprovalLine::where('template_id', $existing->id)->delete(); + $existing->forceDelete(); + } +} \ No newline at end of file