# MNG 문서관리 시스템 상세 기술 명세 > **작성일**: 2026-03-06 > **상태**: 운영 중 > **프로젝트**: SAM MNG (관리자 웹) > **관련**: [README.md](README.md) (API 명세) --- ## 1. 개요 ### 1.1 목적 블라인드/스크린 제조 현장의 **검사 성적서, 작업일지, 수입검사 기록** 등 품질/생산 문서를 전자화하여 관리하는 시스템. 문서 양식(Template)을 정의하면 EAV 패턴으로 데이터를 동적 저장하며, 다단계 결재 워크플로우를 지원한다. ### 1.2 핵심 특징 | 특징 | 설명 | |------|------| | **EAV 패턴** | 양식별로 다른 필드를 하나의 `document_data` 테이블에 저장 | | **2가지 양식 빌더** | 레거시 빌더 (DB 정규화) + 블록 빌더 (A4 JSON 스키마) | | **결재 워크플로우** | 작성 → 검토 → 승인 (다단계 순차 결재) | | **자동 데이터 매핑** | 작업지시서/수주 데이터에서 기본필드 자동 채움 | | **다형성 연결** | work_order, sales_order 등 다양한 모델과 연결 | | **자재 LOT 추적** | 검사 문서에서 투입 자재의 LOT 이력 조회 | ### 1.3 문서 구조 | 문서 | 설명 | |------|------| | [README.md](README.md) | API 엔드포인트, 모델 요약, FormRequest | | **이 문서** | MNG 화면별 상세, 동작원리, 데이터 흐름 | --- ## 2. 메뉴/탭 구조 ``` 생산 관리 └── 문서관리 ├── 문서 목록 /documents ← 문서 검색/필터/관리 ├── 새 문서 작성 /documents/create ← 템플릿 선택 → 폼 입력 ├── 문서 상세 /documents/{id} ← 읽기 전용 + 결재 현황 ├── 문서 수정 /documents/{id}/edit ← DRAFT/REJECTED만 ├── 인쇄 /documents/{id}/print ← 성적서 인쇄용 │ └── 문서양식 관리 ├── 양식 목록 /document-templates ← 양식 검색/관리 ├── 새 양식 (레거시) /document-templates/create ← 레거시 빌더 ├── 양식 수정 /document-templates/{id}/edit ← 자동 빌더 판별 ├── 양식 디자이너 /document-templates/block-create ← 블록 빌더 └── 블록 수정 /document-templates/{id}/block-edit ← 블록 빌더 수정 ``` --- ## 3. 파일 구조 ``` mng/ ├── app/Http/Controllers/ │ ├── DocumentController.php ← 문서 CRUD 화면 │ └── DocumentTemplateController.php ← 양식 관리 화면 ├── app/Models/Documents/ │ ├── Document.php ← 문서 모델 │ ├── DocumentApproval.php ← 결재 단계 │ ├── DocumentData.php ← EAV 데이터 │ ├── DocumentTemplate.php ← 양식 마스터 │ └── ... (기타 템플릿 관련 모델) └── resources/views/ ├── documents/ │ ├── index.blade.php ← 문서 목록 │ ├── edit.blade.php ← 문서 작성/수정 │ ├── show.blade.php ← 문서 상세 │ └── print.blade.php ← 인쇄 전용 └── document-templates/ ├── index.blade.php ← 양식 목록 ├── edit.blade.php ← 레거시 빌더 ├── block-editor.blade.php ← 블록 빌더 └── partials/ ├── block-palette.blade.php ← 블록 타입 목록 ├── block-canvas.blade.php ← 편집 캔버스 └── block-properties.blade.php ← 속성 패널 ``` --- ## 4. 데이터베이스 아키텍처 ### 4.1 테이블 관계도 ``` document_templates (양식 마스터) ├── 1:N → document_template_approval_lines (결재선 정의) ├── 1:N → document_template_basic_fields (기본필드 정의) ├── 1:N → document_template_sections (섹션 정의) │ └── 1:N → document_template_section_items (검사항목) ├── 1:N → document_template_columns (테이블 컬럼 정의) ├── 1:N → document_template_section_fields (섹션 필드) ├── 1:N → document_template_links (외부 연결 정의) │ └── 1:N → document_template_link_values (템플릿 레벨 연결값) │ └── 1:N → documents (문서 인스턴스) ├── 1:N → document_approvals (결재 진행) ├── 1:N → document_data (EAV 필드값) ├── 1:N → document_attachments (첨부파일) └── 1:N → document_links (문서 레벨 연결) ``` ### 4.2 documents (문서) | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `tenant_id` | BIGINT FK | 테넌트 격리 | | `template_id` | BIGINT FK | 사용 양식 | | `document_no` | VARCHAR UNIQUE | 문서번호 (자동 채번) | | `title` | VARCHAR | 문서 제목 | | `status` | VARCHAR(20) | 상태 (5가지) | | `linkable_type` | VARCHAR NULL | 다형성 모델 타입 | | `linkable_id` | BIGINT NULL | 다형성 모델 ID | | `submitted_at` | TIMESTAMP NULL | 결재 요청 일시 | | `completed_at` | TIMESTAMP NULL | 결재 완료 일시 | | `created_by` | BIGINT FK | 작성자 | | `deleted_at` | TIMESTAMP NULL | 소프트 삭제 | **인덱스**: `(tenant_id, status)`, `document_no`, `(linkable_type, linkable_id)` ### 4.3 document_data (EAV 필드값) | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `document_id` | BIGINT FK | 소속 문서 | | `section_id` | BIGINT FK NULL | 소속 섹션 (NULL=기본필드) | | `column_id` | BIGINT FK NULL | 소속 컬럼 (테이블 데이터용) | | `row_index` | INT | 테이블 행 번호 (기본: 0) | | `field_key` | VARCHAR | 필드 식별자 (`bf_1`, `cf_2`, `col_3`) | | `field_value` | TEXT NULL | 실제 값 | **인덱스**: `(document_id, section_id)`, `(document_id, field_key)` ### 4.4 document_approvals (결재) | 컬럼 | 타입 | 설명 | |------|------|------| | `id` | BIGINT PK | | | `document_id` | BIGINT FK | 소속 문서 | | `user_id` | BIGINT FK | 결재자 | | `step` | INT | 결재 순서 (1, 2, 3...) | | `role` | VARCHAR | 역할 (작성, 검토, 승인) | | `status` | VARCHAR(20) | PENDING / APPROVED / REJECTED | | `comment` | TEXT NULL | 결재 의견 | | `acted_at` | TIMESTAMP NULL | 처리 일시 | **인덱스**: `(document_id, step)`, `(user_id, status)` ### 4.5 document_attachments (첨부파일) | 컬럼 | 타입 | 설명 | |------|------|------| | `document_id` | BIGINT FK | 소속 문서 | | `file_id` | BIGINT FK | File 모델 연결 | | `attachment_type` | VARCHAR | `general`, `signature`, `image`, `reference` | | `description` | VARCHAR NULL | 설명 | | `created_by` | BIGINT FK | 업로드자 | --- ## 5. 양식(Template) 시스템 ### 5.1 두 가지 빌더 방식 | 방식 | 필드명 | 저장 구조 | UI | 상태 | |------|--------|----------|-----|------| | **레거시 빌더** | `builder_type = null` | 정규화 테이블들 | `edit.blade.php` | 기존 양식용 | | **블록 빌더** | `builder_type = 'block'` | `schema` JSON | `block-editor.blade.php` | 신규 양식용 | **자동 판별 로직:** ```php // DocumentTemplateController::edit() if ($template->isBlockBuilder()) { return $this->blockEdit($id); // block-editor.blade.php } else { return view('document-templates.edit'); // 레거시 } ``` ### 5.2 양식 마스터 (document_templates) | 컬럼 | 타입 | 설명 | |------|------|------| | `name` | VARCHAR | 양식명 (예: "제품검사 성적서") | | `category` | VARCHAR | 분류 (common_codes 기반) | | `title` | VARCHAR NULL | 문서 제목 템플릿 | | `company_name` | VARCHAR NULL | 회사명 | | `company_address` | VARCHAR NULL | 회사 주소 | | `company_contact` | VARCHAR NULL | 연락처 | | `footer_remark_label` | VARCHAR NULL | 비고란 라벨 | | `footer_judgement_label` | VARCHAR NULL | 판정란 라벨 | | `footer_judgement_options` | JSON NULL | 판정 선택지 (적합/부적합) | | `builder_type` | VARCHAR NULL | `block` 또는 NULL | | `schema` | JSON NULL | 블록 빌더 JSON 스키마 | | `page_config` | JSON NULL | 페이지 설정 (A4, 여백 등) | | `is_active` | BOOLEAN | 활성 여부 | ### 5.3 레거시 빌더 구성 요소 #### 결재선 (document_template_approval_lines) ``` step 1: 작성 (작성자 본인) step 2: 검토 (팀장) step 3: 승인 (부장) ``` | 컬럼 | 설명 | |------|------| | `name` | 라벨 (작성, 검토, 승인) | | `dept` | 부서 | | `role` | 역할 | | `sort_order` | 순서 | #### 기본필드 (document_template_basic_fields) 문서 상단의 고정 필드 영역. | 컬럼 | 설명 | |------|------| | `label` | 필드 라벨 (품명, LOT NO, 납기일 등) | | `field_key` | 식별자 (EAV 저장 시 사용) | | `field_type` | 입력 타입 (text, date, number, item_search) | | `default_value` | 기본값 | | `sort_order` | 순서 | **EAV 저장 시 field_key 패턴:** ``` bf_1 → 기본필드 ID 1 (예: 품명) bf_2 → 기본필드 ID 2 (예: LOT NO) bf_3 → 기본필드 ID 3 (예: 납기일) ``` #### 섹션 (document_template_sections) 검사 기준서의 섹션 단위. | 컬럼 | 설명 | |------|------| | `title` | 섹션 제목 (예: "겉모양 검사", "치수 검사") | | `image_path` | 도해 이미지 경로 (검사 부위 도면) | | `sort_order` | 순서 | #### 검사항목 (document_template_section_items) 각 섹션 내의 개별 검사항목. | 컬럼 | 타입 | 설명 | |------|------|------| | `category` | VARCHAR | 구분 (겉모양, 치수, 재질) | | `item` | VARCHAR | 검사항목명 | | `standard` | VARCHAR | 검사기준 (100mm ±5mm) | | `tolerance` | JSON NULL | 허용오차 (min/max) | | `standard_criteria` | VARCHAR NULL | 판정기준 | | `method` | VARCHAR | 검사방법 (육안, 측정) | | `measurement_type` | VARCHAR NULL | 측정 유형 | | `frequency_n` | INT NULL | 검사건수 N | | `frequency_c` | INT NULL | 합격건수 C | | `frequency` | VARCHAR NULL | 검사빈도 텍스트 | | `field_values` | JSON NULL | 확장 필드 (마이그레이션 없이 추가) | #### 테이블 컬럼 (document_template_columns) 검사 데이터 테이블의 컬럼 정의. | 컬럼 | 타입 | 설명 | |------|------|------| | `label` | VARCHAR | 컬럼 라벨 | | `width` | INT NULL | 너비 (px) | | `column_type` | VARCHAR | `text`, `check`, `complex`, `measurement`, `select` | | `group_name` | VARCHAR NULL | 상단 병합 헤더명 | | `sub_labels` | JSON NULL | complex 타입 하위 라벨 | | `sort_order` | INT | 순서 | **컬럼 타입 상세:** | 타입 | 설명 | 예시 | |------|------|------| | `text` | 단순 텍스트 입력 | 비고, 메모 | | `check` | 체크박스 (합격/부적합) | 외관 검사 합격 여부 | | `complex` | 여러 서브필드 조합 | 측정값 + 단위 + 판정 | | `measurement` | 수치 입력 | 길이: 100.5mm | | `select` | 드롭다운 선택 | 판정: 합격/불합격/보류 | #### 외부 연결 (document_template_links) 템플릿에서 외부 테이블 데이터를 참조하기 위한 정의. | 컬럼 | 설명 | |------|------| | `link_key` | 연결 식별자 | | `label` | 화면 라벨 | | `link_type` | `single` (1개 선택) / `multiple` (다중 선택) | | `source_table` | 소스 테이블 (`items`, `processes`, `users`) | | `search_params` | API 검색 추가 조건 (JSON) | | `display_fields` | 표시 필드 (title, subtitle) | | `is_required` | 필수 여부 | ### 5.4 블록 빌더 구조 **페이지 설정 (page_config):** ```json { "size": "A4", "orientation": "portrait", "margin": { "top": 20, "right": 15, "bottom": 20, "left": 15 } } ``` **스키마 (schema):** 블록 배열로 레이아웃 정의. 드래그앤드롭으로 편집. ```json { "blocks": [ { "type": "text", "x": 0, "y": 0, "width": 100, "content": "검사 성적서" }, { "type": "table", "x": 0, "y": 50, "columns": [...], "rows": [...] }, { "type": "image", "x": 200, "y": 100, "src": "..." } ] } ``` **블록 빌더 UI (3패널):** ``` ┌──────────┬────────────────────┬──────────┐ │ 블록 │ │ 속성 │ │ 팔레트 │ A4 캔버스 │ 패널 │ │ │ │ │ │ [텍스트] │ ┌──────────────┐ │ 너비: _ │ │ [이미지] │ │ 드래그앤드롭 │ │ 높이: _ │ │ [표] │ │ 블록 배치 │ │ 색상: _ │ │ [선] │ │ │ │ 폰트: _ │ │ [도형] │ └──────────────┘ │ │ └──────────┴────────────────────┴──────────┘ ``` --- ## 6. EAV 데이터 저장 패턴 ### 6.1 핵심 개념 하나의 `document_data` 테이블에 **모든 양식의 모든 필드값**을 저장. 양식이 다르면 field_key가 다르고, 같은 양식이라도 섹션/행이 다르면 section_id/row_index로 구분. ### 6.2 저장 구조 ``` document_data 레코드 예시: 기본필드 (상단 고정 영역): ┌─────────────┬────────────┬───────────┬───────────┬───────────┬─────────────┐ │ document_id │ section_id │ column_id │ row_index │ field_key │ field_value │ ├─────────────┼────────────┼───────────┼───────────┼───────────┼─────────────┤ │ 42 │ NULL │ NULL │ 0 │ bf_1 │ 블라인드A │ ← 품명 │ 42 │ NULL │ NULL │ 0 │ bf_2 │ LOT-2026-001│ ← LOT NO │ 42 │ NULL │ NULL │ 0 │ bf_3 │ 2026-03-15 │ ← 납기일 ├─────────────┼────────────┼───────────┼───────────┼───────────┼─────────────┤ 테이블 데이터 (섹션별 검사 결과): │ 42 │ 10 │ 20 │ 0 │ col_20 │ 합격 │ ← 섹션10, 컬럼20, 1행 │ 42 │ 10 │ 20 │ 1 │ col_20 │ 부적합 │ ← 섹션10, 컬럼20, 2행 │ 42 │ 10 │ 21 │ 0 │ col_21 │ 100.5 │ ← 섹션10, 컬럼21, 1행 └─────────────┴────────────┴───────────┴───────────┴───────────┴─────────────┘ ``` ### 6.3 field_key 네이밍 규칙 | 접두사 | 의미 | 예시 | |--------|------|------| | `bf_` | 기본필드 (BasicField) | `bf_1`, `bf_2` | | `cf_` | 섹션필드 (SectionField) | `cf_5`, `cf_6` | | `col_` | 컬럼 데이터 | `col_20`, `col_21` | ### 6.4 데이터 조회 패턴 ```php // 기본필드 값 조회 $data = DocumentData::where('document_id', $id) ->whereNull('section_id') ->get() ->keyBy('field_key'); $productName = $data['bf_1']->field_value; // 섹션별 테이블 데이터 조회 $rows = DocumentData::where('document_id', $id) ->where('section_id', $sectionId) ->get() ->groupBy('row_index'); ``` --- ## 7. 결재 워크플로우 ### 7.1 상태 전이 ``` DRAFT (작성중) │ ├── submit() → PENDING (결재중) │ │ │ ├── approve() [step 1] → 다음 step 대기 │ ├── approve() [step 2] → 다음 step 대기 │ ├── approve() [마지막] → APPROVED (승인) │ │ │ └── reject() → REJECTED (반려) │ │ │ └── edit → submit() → PENDING (재요청) │ └── cancel() → CANCELLED (취소) ``` ### 7.2 상태값 및 라벨 | 코드 | 라벨 | 색상 | 편집 가능 | |------|------|------|----------| | `DRAFT` | 작성중 | gray | 예 | | `PENDING` | 결재중 | yellow | 아니오 | | `APPROVED` | 승인 | green | 아니오 | | `REJECTED` | 반려 | red | 예 (수정 후 재요청) | | `CANCELLED` | 취소 | gray | 아니오 | ### 7.3 결재 단계 (Approval) ``` DocumentTemplateApprovalLine (양식 정의) ↓ (문서 생성 시 복사) DocumentApproval (문서별 결재 레코드) step 1: 작성 → PENDING → 결재자 승인 → APPROVED step 2: 검토 → PENDING → 결재자 승인 → APPROVED step 3: 승인 → PENDING → 결재자 승인 → APPROVED → 문서 전체 APPROVED ``` ### 7.4 결재 판단 메서드 ```php // Document 모델 canEdit() // DRAFT 또는 REJECTED canSubmit() // DRAFT 또는 REJECTED canApprove() // PENDING (현재 결재자만) canCancel() // DRAFT 또는 PENDING (작성자만) ``` --- ## 8. 자동 데이터 매핑 ### 8.1 개요 문서 작성/수정 시, 연결된 작업지시서(work_order)/수주(order) 데이터에서 기본필드를 **자동으로 채움**. 사용자 입력 부담을 줄이고 데이터 정확성을 보장. ### 8.2 검사 성적서 매핑 (field_key 기반) | field_key | 라벨 | 소스 | |-----------|------|------| | `product_name` | 품명 | `workOrderItem.item_name` | | `specification` | 규격 | `workOrderItem.specification` | | `lot_no` | LOT NO | `order.order_no` | | `lot_size` | LOT 크기 | `"N 개소"` (개소 수 기반) | | `client` | 발주처 | `order.client_name` | | `site_name` | 현장명 | `workOrder.project_name` | | `inspection_date` | 검사일 | `workOrderItem.options.inspection_data.inspected_at` | | `inspector` | 검사자 | 검사자 이름 | ### 8.3 작업일지 매핑 (label 기반) | label 포함 문자열 | 소스 | |------------------|------| | `발주처` | `order.client_name` | | `현장명` | `workOrder.project_name` | | `작업일자` | `now()` | | `LOT NO`, `LOT` | `order.order_no` | | `납기일`, `납기` | `order.delivery_date` | | `작업지시번호` | `workOrder.work_order_no` | | `수주일` | `order.received_at` 또는 `order.created_at` | ### 8.4 자동 매핑 흐름 ``` 문서 작성/수정 페이지 로드 ↓ DocumentController::edit() ↓ resolveAndBackfillBasicFields($template, $document) ↓ linkable_type 확인 (work_order? order?) ↓ field_key 또는 label 매칭 ↓ DB에 값이 없으면 → 소스 데이터에서 resolve ↓ 뷰에 자동 채움된 값 전달 ``` --- ## 9. 자재 LOT 추적 ### 9.1 개요 검사 성적서에서 해당 작업지시의 **투입 자재 LOT 이력**을 조회. `stock_transactions` 테이블의 OUT(투입)/IN(취소) 트랜잭션을 상쇄하여 순수 투입량을 계산. ### 9.2 추적 구조 ``` work_orders (작업지시) │ ├── stock_transactions (재고 트랜잭션) │ ├── OUT (투입): qty < 0 │ └── IN (취소/반납): qty > 0 │ → 순수 투입량 = ABS(SUM(qty)) where qty < 0 │ └── work_order_material_inputs (개소별 투입자재) └── stock_lots (LOT 정보) JOIN ``` ### 9.3 표시 내용 | 항목 | 설명 | |------|------| | 자재명 | 투입된 원자재/부자재 이름 | | LOT 번호 | 자재의 LOT 식별 번호 | | 투입 수량 | OUT 트랜잭션 합계 (절대값) | | 투입일 | 트랜잭션 일시 | --- ## 10. 화면별 상세 ### 10.1 문서 목록 (/documents) **필터 항목:** | 필터 | 타입 | 설명 | |------|------|------| | 검색 | text | 문서번호 또는 제목 | | 상태 | dropdown | DRAFT, PENDING, APPROVED, REJECTED, CANCELLED, 휴지통(admin) | | 양식분류 | dropdown | category | | 템플릿 | dropdown | template_id | | 날짜 범위 | date | created_at (from ~ to) | **목록 테이블 컬럼:** ``` 문서번호 | 제목 | 양식 | 상태 | 작성자 | 작성일 | 결재현황 ``` ### 10.2 문서 작성/수정 (/documents/create, /documents/{id}/edit) **폼 구성:** ``` ┌──────────────────────────────────────────────┐ │ 템플릿 선택 (읽기전용) │ │ 제목 (필수) │ ├──────────────────────────────────────────────┤ │ 기본 필드 (template.basicFields) │ │ ┌─────────────────┬─────────────────┐ │ │ │ 품명: [자동채움] │ LOT NO: [자동] │ │ │ │ 납기일: [날짜] │ 발주처: [자동] │ │ │ └─────────────────┴─────────────────┘ │ ├──────────────────────────────────────────────┤ │ 섹션 1: 겉모양 검사 │ │ ┌──────────────────────────────────────┐ │ │ │ 도해 이미지 (있으면) │ │ │ ├──────┬──────┬──────┬──────┬──────┤ │ │ │ 구분 │ 항목 │ 기준 │ 결과1│ 결과2│ │ │ ├──────┼──────┼──────┼──────┼──────┤ │ │ │ 치수 │ 길이 │±5mm │ [ ] │ [ ] │ │ │ │ 외관 │ 흠집 │ 없음 │ [✓] │ [✓] │ │ │ ├──────┴──────┴──────┴──────┴──────┤ │ │ │ [+ 행 추가] [행 삭제] │ │ │ └──────────────────────────────────────┘ │ ├──────────────────────────────────────────────┤ │ 외부 연결 (template.links) │ │ 품목 선택: [검색 드롭다운] │ ├──────────────────────────────────────────────┤ │ 첨부파일 │ │ [일반 문서] [서명 이미지] [검사 사진] [참고 자료] │ ├──────────────────────────────────────────────┤ │ [임시저장] [결재 요청] │ └──────────────────────────────────────────────┘ ``` ### 10.3 문서 상세 (/documents/{id}) **읽기 전용 표시:** ``` ┌──────────────────────────────────────────────┐ │ 문서번호: DOC-260306-001 상태: [🟢 승인] │ │ 제목: 블라인드A 검사 성적서 │ ├──────────────────────────────────────────────┤ │ 기본 필드 (읽기 전용) │ ├──────────────────────────────────────────────┤ │ 검사 데이터 테이블 (읽기 전용) │ ├──────────────────────────────────────────────┤ │ 결재 현황 │ │ ┌────────┬────────┬────────┐ │ │ │ 작성 │ 검토 │ 승인 │ │ │ │ 홍길동 │ 김과장 │ 박부장 │ │ │ │ ✓승인 │ ✓승인 │ ●대기 │ │ │ └────────┴────────┴────────┘ │ ├──────────────────────────────────────────────┤ │ 자재 투입 LOT (작업지시 연결 시) │ │ ┌────────┬──────────┬──────┬──────┐ │ │ │ 자재명 │ LOT 번호 │ 수량 │ 투입일│ │ │ └────────┴──────────┴──────┴──────┘ │ ├──────────────────────────────────────────────┤ │ 첨부파일 목록 │ ├──────────────────────────────────────────────┤ │ [수정] [인쇄] [결재 승인] [결재 반려] │ └──────────────────────────────────────────────┘ ``` ### 10.4 인쇄 (/documents/{id}/print) 성적서 형식의 인쇄 전용 화면. `window.print()` 호출. 작업지시 관련 자재(work_order_items) 데이터 포함. ### 10.5 양식 목록 (/document-templates) **필터:** - 검색: 양식명, 제목, 분류 - 카테고리: common_codes 기반 + 기존 데이터 폴백 - 활성 상태: 활성 / 비활성 / 휴지통(admin) **HTMX**: 필터 변경 시 테이블 영역만 부분 로드 --- ## 11. 첨부파일 유형 | 유형 | 코드 | 용도 | 예시 | |------|------|------|------| | 일반 문서 | `general` | PDF, 엑셀 등 | 규격서, 보고서 | | 서명 이미지 | `signature` | 검사 완료 서명 | 검사자 서명 사진 | | 검사 사진 | `image` | 검사 증빙 사진 | 불량 부위 촬영 | | 참고 자료 | `reference` | 참고용 문서 | KS 규격, 작업 지침 | --- ## 12. API 연동 (MNG → API) MNG 뷰에서 데이터 저장/삭제는 **API 서버를 호출**하여 처리. GET 요청(뷰 렌더링)은 MNG 컨트롤러가 직접 처리. | 작업 | MNG (GET 요청) | API (POST/PUT/DELETE) | |------|---------------|----------------------| | 목록 조회 | `DocumentController::index()` | `GET /v1/documents` | | 상세 조회 | `DocumentController::show()` | `GET /v1/documents/{id}` | | 생성 | 폼 표시만 | `POST /v1/documents` | | 수정 | 폼 표시만 | `PATCH /v1/documents/{id}` | | 삭제 | - | `DELETE /v1/documents/{id}` | | 결재 요청 | - | `POST /v1/documents/{id}/submit` | | 승인 | - | `POST /v1/documents/{id}/approve` | | 반려 | - | `POST /v1/documents/{id}/reject` | --- ## 13. 카테고리 해결 로직 양식 카테고리는 **common_codes 테이블**에서 조회하되, 없으면 **기존 데이터에서 추출**하여 폴백. ```php // DocumentTemplateController::getCategories() $categories = CommonCode::where('group', 'document_category') ->orderBy('sort_order') ->get(); if ($categories->isEmpty()) { // 폴백: 기존 템플릿의 category 값에서 중복 제거 $categories = DocumentTemplate::distinct('category') ->pluck('category') ->filter(); } ``` --- ## 14. 검사항목 확장 (field_values JSON) `document_template_section_items.field_values` JSON 컬럼으로 마이그레이션 없이 새 필드를 추가할 수 있다. ```json { "custom_field_1": "추가 기준값", "min_value": 95.0, "max_value": 105.0, "unit": "mm" } ``` > options JSON 컬럼 정책(`docs/standards/options-column-policy.md`) 준용 --- ## 15. HTMX 전체 페이지 로드 규칙 문서관리 페이지들은 JavaScript를 사용하므로 HTMX 부분 로드 시 스크립트 미실행 문제가 있다. 컨트롤러에서 HX-Request 감지 시 **HX-Redirect로 전체 페이지 리로드 강제**. ```php if ($request->header('HX-Request')) { return response('', 200)->header('HX-Redirect', route('documents.index')); } ``` --- ## 관련 문서 - [README.md](README.md) — API 엔드포인트, 모델 요약, FormRequest - [DB 스키마 — 문서/전자서명](../../system/database/documents.md) — 테이블 상세 - [게시판 시스템](../boards/README.md) — 유사한 EAV 패턴 참고 - [결재관리 시스템](../approvals/README.md) — 별도 결재 시스템 (문서관리와 독립) --- **최종 업데이트**: 2026-03-06