From 5d2933c1764628359d7babe665789e8ecec63eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Thu, 12 Mar 2026 11:12:52 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20[equipment]=20API=20Phase=201=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=ED=98=84=ED=99=A9=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 상태 변경: API+React 미구현 → API Phase 1 완료 - API 구현 현황 섹션 추가 (모델, 서비스, 컨트롤러, 라우트 26개) - MNG→API 변환 규칙, DB 연결 분리 설명 추가 - Phase 로드맵 (Phase 1 완료, Phase 2-3 미착수) --- features/equipment/README.md | 332 +++++++++++++++++++++-------------- 1 file changed, 197 insertions(+), 135 deletions(-) diff --git a/features/equipment/README.md b/features/equipment/README.md index 175568d..2fc1b12 100644 --- a/features/equipment/README.md +++ b/features/equipment/README.md @@ -1,7 +1,7 @@ # 설비관리 (Equipment Management) > **작성일**: 2026-02-27 -> **상태**: MNG R&D 완료 / API+React 미구현 +> **상태**: MNG R&D 완료 / API Phase 1 완료 / React 미구현 > **최종 갱신**: 2026-03-12 --- @@ -10,21 +10,21 @@ ### 1.1 목적 -생산 설비의 등록, 점검, 수리이력을 체계적으로 관리한다. MNG 관리자 패널에서 Blade/HTMX 기반으로 R&D가 완료되었으며, 본 시스템(API + React)으로의 서비스 구축이 필요하다. +생산 설비의 등록, 점검, 수리이력을 체계적으로 관리한다. MNG 관리자 패널에서 Blade/HTMX 기반으로 R&D가 완료되었으며, API 백엔드 구현이 완료되어 React 프론트엔드 연동을 진행할 수 있다. ### 1.2 핵심 기능 -| 기능 | 설명 | MNG 구현 | -|------|------|:--------:| -| 설비 대시보드 | 현황 카드(총/가동/유휴/폐기), 유형별 통계, 최근 수리 | ✅ | -| 설비 대장 (CRUD) | 등록/수정/삭제/복원, SoftDeletes | ✅ | -| 설비 점검 | 6주기(일일~반년), 그리드 셀 토글, 종합판정 | ✅ | -| 점검 템플릿 | 설비별 점검항목 정의, 주기간 복사 | ✅ | -| 수리이력 | 사내/외주, 비용, 시간, 업체 관리 | ✅ | -| 설비 사진 | GCS 업로드, 압축(1MB), 최대 10장 | ✅ | -| 엑셀 Import | 미리보기 + 일괄등록, 이미지 포함 | ✅ | -| 모바일 점검 | QR 스캔 → 모바일 점검 화면 | ✅ | -| 설비-공정 매핑 | N:N 관계, 주 설비 여부 | ✅ | +| 기능 | 설명 | MNG | API | +|------|------|:---:|:---:| +| 설비 대시보드 | 현황 카드(총/가동/유휴/폐기), 유형별 통계 | ✅ | ✅ | +| 설비 대장 (CRUD) | 등록/수정/삭제/복원, SoftDeletes | ✅ | ✅ | +| 설비 점검 | 6주기(일일~반년), 그리드 셀 토글, 종합판정 | ✅ | ✅ | +| 점검 템플릿 | 설비별 점검항목 정의, 주기간 복사 | ✅ | ✅ | +| 수리이력 | 사내/외주, 비용, 시간, 업체 관리 | ✅ | ✅ | +| 설비 사진 | 파일 업로드/삭제 | ✅ | ✅ | +| 엑셀 Import | 미리보기 + 일괄등록, 이미지 포함 | ✅ | — | +| 모바일 점검 | QR 스캔 → 모바일 점검 화면 | ✅ | — | +| 설비-공정 매핑 | N:N 관계, 주 설비 여부 | ✅ | ✅ | --- @@ -43,6 +43,18 @@ | `equipment_repairs` | 수리이력 | `2026_02_25_100400` | | `equipment_process` | 설비-공정 매핑 (N:N pivot) | `2026_02_25_100500` | +추가 마이그레이션: + +| 마이그레이션 | 설명 | +|-------------|------| +| `2026_02_28_100000` | `sub_manager_id` 컬럼 추가 | +| `2026_02_28_100100` | templates에 `inspection_cycle` 추가 + 유니크 변경 | +| `2026_02_28_100200` | inspections에 `inspection_cycle` 추가 + 유니크 변경 | +| `2026_03_12_100000` | `equipments`, `equipment_repairs`에 `options` JSON 추가 | +| `2026_03_12_100001` | 기본 DB에 테이블 존재 보장 (`hasTable` 체크) | + +> **DB 연결 참고**: 기존 MNG 마이그레이션이 `codebridge` DB에 테이블을 생성했으나, API에서는 기본 DB(`sam`/`sam_prod`)에 테이블이 필요하다. `2026_03_12_100001` 마이그레이션이 기본 DB에 테이블이 없으면 최신 스키마로 생성한다. + ### 2.2 ERD 개요 ``` @@ -73,6 +85,7 @@ equipments (설비 마스터) | `install_date` | date | 설치일 | | `purchase_price` | decimal(15,2) | 구입가격 | | `useful_life` | int | 내용연수 | +| `options` | json | 확장 속성 JSON | | `sort_order` | int | 정렬순서 | #### `equipment_inspection_templates` @@ -119,23 +132,160 @@ equipments (설비 마스터) | `cost` | decimal(15,2) | 수리비용 | | `vendor` | varchar(100) | 외주업체 | | `repaired_by` | FK → users | 수리자 | +| `options` | json | 확장 속성 JSON | --- -## 3. MNG 구현 현황 +## 3. API 구현 현황 (Phase 1 완료) -### 3.1 모델 (`mng/app/Models/Equipment/`) +### 3.1 모델 (`api/app/Models/Equipment/`) -| 모델 | 파일 | 특이사항 | -|------|------|---------| -| `Equipment` | `Equipment.php` | BelongsToTenant, SoftDeletes, `connection='codebridge'` | -| `EquipmentInspection` | `EquipmentInspection.php` | BelongsToTenant | -| `EquipmentInspectionDetail` | `EquipmentInspectionDetail.php` | 결과 순환 로직 (`getNextResult`) | -| `EquipmentInspectionTemplate` | `EquipmentInspectionTemplate.php` | BelongsToTenant | -| `EquipmentRepair` | `EquipmentRepair.php` | BelongsToTenant, SoftDeletes | -| `EquipmentProcess` | `EquipmentProcess.php` | pivot 모델 | +| 모델 | Traits | 특이사항 | +|------|--------|---------| +| `Equipment` | Auditable, BelongsToTenant, ModelTrait, SoftDeletes | `options` cast, `getOption()`/`setOption()` | +| `EquipmentInspection` | Auditable, BelongsToTenant, ModelTrait | — | +| `EquipmentInspectionDetail` | ModelTrait | `getNextResult()`, `getResultSymbol()` static | +| `EquipmentInspectionTemplate` | Auditable, BelongsToTenant, ModelTrait | — | +| `EquipmentRepair` | Auditable, BelongsToTenant, ModelTrait, SoftDeletes | `options` cast, `getOption()`/`setOption()` | +| `EquipmentProcess` | — | pivot 모델 | -### 3.2 서비스 (`mng/app/Services/`) +### 3.2 Enum (`api/app/Enums/InspectionCycle.php`) + +6개 점검주기를 관리하는 헬퍼 클래스: + +| 주기 | 코드 | period 형식 | 그리드 열 | +|------|------|------------|----------| +| 일일 | `daily` | `2026-03` (년-월) | 1~31일 | +| 주간 | `weekly` | `2026` (년) | 1~52주 | +| 월간 | `monthly` | `2026` (년) | 1~12월 | +| 2개월 | `bimonthly` | `2026` (년) | 1~6 | +| 분기 | `quarterly` | `2026` (년) | 1~4분기 | +| 반년 | `semiannual` | `2026` (년) | 상/하반기 | + +주요 메서드: `columnLabels()`, `resolveCheckDate()`, `resolvePeriod()`, `isNonWorkingDay()`, `getHolidayDates(int $tenantId)` + +> **MNG→API 변환**: `getHolidayDates()`가 `session('selected_tenant_id')` 대신 명시적 `$tenantId` 매개변수를 받는다. + +### 3.3 서비스 (`api/app/Services/Equipment/`) + +모든 서비스는 `extends Service` (base class)를 사용하며, 쓰기 작업은 `DB::transaction()`으로 감싼다. + +| 서비스 | 핵심 메서드 | +|--------|-----------| +| `EquipmentService` | `index()`, `show()`, `store()`, `update()`, `destroy()`, `restore()`, `toggleActive()`, `stats()`, `options()` | +| `EquipmentInspectionService` | `getInspections()`, `toggleDetail()`, `setResult()`, `updateNotes()`, `resetInspection()`, `saveTemplate()`, `updateTemplate()`, `deleteTemplate()`, `copyTemplates()`, `getActiveCycles()` | +| `EquipmentRepairService` | `index()`, `store()`, `update()`, `destroy()` | +| `EquipmentPhotoService` | `index()`, `store()`, `destroy()` | + +### 3.4 컨트롤러 (`api/app/Http/Controllers/V1/Equipment/`) + +| 컨트롤러 | DI | 메서드 | +|---------|-----|-------| +| `EquipmentController` | `EquipmentService` | index, show, store, update, destroy, restore, toggleActive, stats, options | +| `EquipmentInspectionController` | `EquipmentInspectionService` | index, toggleDetail, setResult, updateNotes, resetInspection, templates, storeTemplate, updateTemplate, deleteTemplate, copyTemplates | +| `EquipmentRepairController` | `EquipmentRepairService` | index, store, update, destroy | +| `EquipmentPhotoController` | `EquipmentPhotoService` | index, store, destroy | + +### 3.5 FormRequest (`api/app/Http/Requests/V1/Equipment/`) + +| 클래스 | 용도 | +|--------|------| +| `StoreEquipmentRequest` | 설비 등록 (코드 unique per tenant) | +| `UpdateEquipmentRequest` | 설비 수정 (`sometimes` 규칙) | +| `StoreEquipmentRepairRequest` | 수리이력 등록/수정 | +| `StoreInspectionTemplateRequest` | 점검항목 등록 (cycle enum 검증) | +| `ToggleInspectionDetailRequest` | 점검 셀 토글 | +| `UpdateInspectionNotesRequest` | 점검 메모/판정 수정 | + +### 3.6 API 라우트 (`api/routes/api/v1/equipment.php`) + +26개 엔드포인트, prefix: `/v1/equipment` + +``` +설비 CRUD (9): + GET /v1/equipment → index (목록+검색+필터) + GET /v1/equipment/options → options (드롭다운 데이터) + GET /v1/equipment/stats → stats (대시보드 통계) + POST /v1/equipment → store + GET /v1/equipment/{id} → show + PUT /v1/equipment/{id} → update + DELETE /v1/equipment/{id} → destroy (soft delete) + POST /v1/equipment/{id}/restore → restore + PATCH /v1/equipment/{id}/toggle → toggleActive + +점검 템플릿 (5): + GET /v1/equipment/{id}/templates → templates (활성 주기 목록) + POST /v1/equipment/{id}/templates → storeTemplate + PUT /v1/equipment/templates/{templateId} → updateTemplate + DELETE /v1/equipment/templates/{templateId} → deleteTemplate + POST /v1/equipment/{id}/templates/copy → copyTemplates + +점검 (5): + GET /v1/equipment/inspections → index (그리드 데이터) + PATCH /v1/equipment/inspections/toggle → toggleDetail (셀 토글) + PATCH /v1/equipment/inspections/set-result → setResult (결과 직접 설정) + PATCH /v1/equipment/inspections/notes → updateNotes (메모/판정) + DELETE /v1/equipment/inspections/reset → resetInspection (초기화) + +수리이력 (4): + GET /v1/equipment/repairs → index + POST /v1/equipment/repairs → store + PUT /v1/equipment/repairs/{id} → update + DELETE /v1/equipment/repairs/{id} → destroy + +사진 (3): + GET /v1/equipment/{id}/photos → index + POST /v1/equipment/{id}/photos → store + DELETE /v1/equipment/{id}/photos/{fileId} → destroy +``` + +### 3.7 i18n 메시지 + +**성공 메시지** (`lang/ko/message.php` → `equipment.*`): + +| 키 | 메시지 | +|----|--------| +| `created` | 설비가 등록되었습니다. | +| `updated` | 설비 정보가 수정되었습니다. | +| `deleted` | 설비가 삭제되었습니다. | +| `restored` | 설비가 복원되었습니다. | +| `inspection_saved` | 점검 정보가 저장되었습니다. | +| `inspection_reset` | 점검 데이터가 초기화되었습니다. | +| `template_created` | 점검항목이 추가되었습니다. | +| `template_copied` | 점검항목이 복사되었습니다. | +| `repair_created` | 수리이력이 등록되었습니다. | +| `photo_uploaded` | 사진이 업로드되었습니다. | + +**에러 메시지** (`lang/ko/error.php` → `equipment.*`): + +| 키 | 메시지 | +|----|--------| +| `not_found` | 설비 정보를 찾을 수 없습니다. | +| `template_not_found` | 점검항목을 찾을 수 없습니다. | +| `inspection_not_found` | 점검 데이터를 찾을 수 없습니다. | +| `repair_not_found` | 수리이력을 찾을 수 없습니다. | +| `photo_not_found` | 사진을 찾을 수 없습니다. | +| `invalid_cycle` | 유효하지 않은 점검주기입니다. | +| `no_source_templates` | 복사할 점검항목이 없습니다. | + +### 3.8 MNG→API 변환 규칙 적용 + +| MNG 패턴 | API 변환 | +|----------|---------| +| `$connection = 'codebridge'` | 제거 (기본 connection 사용) | +| `session('selected_tenant_id')` | `$this->tenantId()` | +| `auth()->id()` | `$this->apiUserId()` | +| `DB::connection('codebridge')` | `DB::` (기본 connection) | +| MNG 직접 validate | FormRequest 분리 | +| 직접 문자열 에러 메시지 | `__('error.equipment.*')` i18n | +| — | `Auditable` trait 추가 | +| — | `DB::transaction()` 쓰기 래핑 | + +--- + +## 4. MNG 구현 현황 + +### 4.1 서비스 (`mng/app/Services/`) | 서비스 | 핵심 메서드 | |--------|-----------| @@ -145,99 +295,7 @@ equipments (설비 마스터) | `EquipmentPhotoService` | `uploadPhotos()`, `uploadPhotoFromPath()`, `deletePhoto()`, `getPhotoUrls()`, `compressImage()` | | `EquipmentImportService` | `preview()`, `import()` — 엑셀 헤더 매핑, 이미지 추출, 중복 처리 | -### 3.3 Enum (`mng/app/Enums/InspectionCycle.php`) - -6개 점검주기를 관리하는 헬퍼 클래스: - -| 주기 | 코드 | 라벨 | period 형식 | 그리드 열 | -|------|------|------|------------|----------| -| 일일 | `daily` | 일일 | `2026-03` (년-월) | 1~31일 | -| 주간 | `weekly` | 주간 | `2026` (년) | 1~52주 | -| 월간 | `monthly` | 월간 | `2026` (년) | 1~12월 | -| 2개월 | `bimonthly` | 2개월 | `2026` (년) | 1~6 (2개월 단위) | -| 분기 | `quarterly` | 분기 | `2026` (년) | 1~4분기 | -| 반년 | `semiannual` | 반년 | `2026` (년) | 상/하반기 | - -주요 메서드: `columnLabels()`, `resolveCheckDate()`, `resolvePeriod()`, `isNonWorkingDay()`, `getHolidayDates()` - -### 3.4 컨트롤러 - -| 컨트롤러 | 경로 | 역할 | -|---------|------|------| -| `EquipmentController` | `app/Http/Controllers/` | 웹 뷰 렌더링 (dashboard, index, create, show, edit, inspections, repairs, import, guide) | -| `Api\Admin\EquipmentController` | `app/Http/Controllers/Api/Admin/` | CRUD + 사진 + 템플릿 조회 + 엑셀 Import | -| `Api\Admin\EquipmentInspectionController` | 위 동일 | 점검 그리드 조회, 셀 토글, 결과 설정, 노트, 초기화, 템플릿 CRUD, 주기 복사 | -| `Api\Admin\EquipmentRepairController` | 위 동일 | 수리이력 CRUD | - -### 3.5 Request 클래스 (`mng/app/Http/Requests/`) - -| 클래스 | 용도 | -|--------|------| -| `StoreEquipmentRequest` | 설비 등록 (코드 unique per tenant) | -| `UpdateEquipmentRequest` | 설비 수정 (코드 unique ignore self) | -| `StoreEquipmentRepairRequest` | 수리이력 등록 | -| `StoreEquipmentInspectionRequest` | 점검 기록 | - -### 3.6 라우트 구조 - -**웹 라우트** (`routes/web.php`): - -``` -/equipment → dashboard -/equipment/registry → index (목록) -/equipment/registry/create → create (등록) -/equipment/registry/{id} → show (상세) -/equipment/registry/{id}/edit → edit (수정) -/equipment/inspections → inspections (점검) -/equipment/repairs → repairs (수리이력) -/equipment/repairs/create → repairCreate -/equipment/import → import (엑셀) -/equipment/guide → guide (가이드) -``` - -**API 라우트** (`routes/api.php`, prefix: `/admin/equipment`): - -``` -설비 CRUD: - GET /admin/equipment → index - POST /admin/equipment → store - GET /admin/equipment/{id} → show - PUT /admin/equipment/{id} → update - DELETE /admin/equipment/{id} → destroy - POST /admin/equipment/{id}/restore → restore - -점검 템플릿: - GET /admin/equipment/{id}/templates → templates - POST /admin/equipment/{id}/templates → storeTemplate - PUT /admin/equipment/templates/{templateId} → updateTemplate - DELETE /admin/equipment/templates/{templateId} → deleteTemplate - POST /admin/equipment/{id}/templates/copy → copyTemplates - -점검: - GET /admin/equipment/inspections → index - PATCH /admin/equipment/inspections/detail → toggleDetail - PATCH /admin/equipment/inspections/notes → updateNotes - PATCH /admin/equipment/inspections/set-result → setResult - DELETE /admin/equipment/inspections/reset → resetInspection - DELETE /admin/equipment/inspections/reset-all → resetAllInspections - -수리이력: - GET /admin/equipment/repairs → index - POST /admin/equipment/repairs → store - PUT /admin/equipment/repairs/{id} → update - DELETE /admin/equipment/repairs/{id} → destroy - -사진: - POST /admin/equipment/{id}/photos → uploadPhotos - GET /admin/equipment/{id}/photos → photos - DELETE /admin/equipment/{id}/photos/{fileId} → deletePhoto - -Import: - POST /admin/equipment/import/preview → importPreview - POST /admin/equipment/import → importExecute -``` - -### 3.7 뷰 파일 (`mng/resources/views/equipment/`) +### 4.2 뷰 파일 (`mng/resources/views/equipment/`) ``` equipment/ @@ -264,13 +322,11 @@ equipment/ └── repair-history.blade.php # 수리이력 탭 ``` -모바일: `mng/resources/views/mobile/inspection/show.blade.php` - --- -## 4. 비즈니스 규칙 +## 5. 비즈니스 규칙 -### 4.1 설비 상태 +### 5.1 설비 상태 | 상태 | 코드 | 설명 | |------|------|------| @@ -278,13 +334,13 @@ equipment/ | 유휴 | `idle` | 일시 정지 | | 폐기 | `disposed` | 사용 중단 | -### 4.2 점검 권한 +### 5.2 점검 권한 - 관리자(`isAdmin`): 모든 설비 점검 가능 - 일반 사용자: `manager_id` 또는 `sub_manager_id`와 일치하는 설비만 점검 가능 - 권한 없는 사용자가 점검 시도 시 403 응답 -### 4.3 점검 결과 순환 +### 5.3 점검 결과 순환 셀 클릭 시 결과가 순환한다: @@ -292,38 +348,44 @@ equipment/ (빈칸) → good(○) → bad(X) → repaired(△) → (빈칸) ``` -### 4.4 휴일/주말 점검 제한 +### 5.4 휴일/주말 점검 제한 - 일일 점검(`daily`)에서 주말(토/일) 및 `holidays` 테이블 등록 휴일에는 점검 기록 불가 - 다른 주기(weekly/monthly 등)에는 제한 없음 -### 4.5 설비 사진 +### 5.5 설비 사진 - 최대 10장 -- 업로드 시 자동 압축 (장축 2048px, JPEG 품질 85→40 점진 감소, 1MB 이하) -- PNG 투명도 있으면 PNG 유지, 없으면 JPEG 변환 -- GCS(Google Cloud Storage)에 저장, Signed URL로 조회 +- 업로드 시 자동 압축 (MNG에서 구현, API에서는 `File` 모델 연동) +- GCS(Google Cloud Storage)에 저장 -### 4.6 엑셀 Import +### 5.6 엑셀 Import (MNG 전용) -- 한글/영문 헤더 자동 매핑 (설비코드↔equipment_code 등) -- 상태 한글 변환 (가동→active, 유휴→idle 등) -- 중복 처리: skip(건너뜀) 또는 overwrite(덮어쓰기) 선택 +- 한글/영문 헤더 자동 매핑 +- 중복 처리: skip 또는 overwrite 선택 - 엑셀 내 이미지(Drawing) 자동 추출 후 GCS 업로드 +- API에서는 미구현 (Phase 2+ 검토) --- -## 5. 참고: MNG에서의 DB 연결 +## 6. 향후 계획 -MNG 모델은 `$connection = 'codebridge'`를 사용한다. 본 시스템(API)에서는 기본 connection을 사용하므로 모델 이관 시 이 속성을 제거해야 한다. +| 단계 | 내용 | 상태 | +|------|------|------| +| Phase 1 | API 백엔드 (모델, 서비스, 컨트롤러, 라우트) | ✅ 완료 | +| Phase 2 | React 프론트엔드 | 미착수 | +| Phase 3 | 테스트 + Swagger 문서 | 미착수 | +| 추가 | 엑셀 Import API | 검토 중 | +| 추가 | 모바일 점검 (React) | 검토 중 | --- ## 관련 문서 +- [서비스 구축 계획](../../dev/dev_plans/equipment-service-build-plan.md) - [MNG 구조](../../system/mng-structure.md) - [DB 스키마 — 공통](../../system/database/commons.md) -- [options 컬럼 정책](../../dev/standards/options-column-policy.md) — 신규 테이블 생성 시 참고 +- [options 컬럼 정책](../../dev/standards/options-column-policy.md) ---