// controllers/equipmentController.js const EquipmentModel = require('../models/equipmentModel'); const imageUploadService = require('../services/imageUploadService'); const EquipmentController = { // CREATE - 설비 생성 createEquipment: async (req, res) => { try { const equipmentData = req.body; // 필수 필드 검증 if (!equipmentData.equipment_code || !equipmentData.equipment_name) { return res.status(400).json({ success: false, message: '설비 코드와 설비명은 필수입니다.' }); } // 설비 코드 중복 확인 EquipmentModel.checkDuplicateCode(equipmentData.equipment_code, null, (error, isDuplicate) => { if (error) { console.error('설비 코드 중복 확인 오류:', error); return res.status(500).json({ success: false, message: '설비 코드 중복 확인 중 오류가 발생했습니다.' }); } if (isDuplicate) { return res.status(409).json({ success: false, message: '이미 사용 중인 설비 코드입니다.' }); } // 설비 생성 EquipmentModel.create(equipmentData, (error, result) => { if (error) { console.error('설비 생성 오류:', error); return res.status(500).json({ success: false, message: '설비 생성 중 오류가 발생했습니다.' }); } res.status(201).json({ success: true, message: '설비가 성공적으로 생성되었습니다.', data: result }); }); }); } catch (error) { console.error('설비 생성 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // READ ALL - 모든 설비 조회 (필터링 가능) getAllEquipments: (req, res) => { try { const filters = { workplace_id: req.query.workplace_id, equipment_type: req.query.equipment_type, status: req.query.status, search: req.query.search }; EquipmentModel.getAll(filters, (error, results) => { if (error) { console.error('설비 조회 오류:', error); return res.status(500).json({ success: false, message: '설비 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('설비 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // READ ONE - 특정 설비 조회 getEquipmentById: (req, res) => { try { const equipmentId = req.params.id; EquipmentModel.getById(equipmentId, (error, result) => { if (error) { console.error('설비 조회 오류:', error); return res.status(500).json({ success: false, message: '설비 조회 중 오류가 발생했습니다.' }); } if (!result) { return res.status(404).json({ success: false, message: '설비를 찾을 수 없습니다.' }); } res.json({ success: true, data: result }); }); } catch (error) { console.error('설비 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // READ BY WORKPLACE - 특정 작업장의 설비 조회 getEquipmentsByWorkplace: (req, res) => { try { const workplaceId = req.params.workplaceId; EquipmentModel.getByWorkplace(workplaceId, (error, results) => { if (error) { console.error('작업장 설비 조회 오류:', error); return res.status(500).json({ success: false, message: '작업장 설비 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('작업장 설비 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // READ ACTIVE - 활성 설비만 조회 getActiveEquipments: (req, res) => { try { EquipmentModel.getActive((error, results) => { if (error) { console.error('활성 설비 조회 오류:', error); return res.status(500).json({ success: false, message: '활성 설비 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('활성 설비 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // UPDATE - 설비 수정 updateEquipment: async (req, res) => { try { const equipmentId = req.params.id; const equipmentData = req.body; // 필수 필드 검증 if (!equipmentData.equipment_code || !equipmentData.equipment_name) { return res.status(400).json({ success: false, message: '설비 코드와 설비명은 필수입니다.' }); } // 설비 존재 확인 EquipmentModel.getById(equipmentId, (error, existingEquipment) => { if (error) { console.error('설비 조회 오류:', error); return res.status(500).json({ success: false, message: '설비 조회 중 오류가 발생했습니다.' }); } if (!existingEquipment) { return res.status(404).json({ success: false, message: '설비를 찾을 수 없습니다.' }); } // 설비 코드 중복 확인 (자신 제외) EquipmentModel.checkDuplicateCode(equipmentData.equipment_code, equipmentId, (error, isDuplicate) => { if (error) { console.error('설비 코드 중복 확인 오류:', error); return res.status(500).json({ success: false, message: '설비 코드 중복 확인 중 오류가 발생했습니다.' }); } if (isDuplicate) { return res.status(409).json({ success: false, message: '이미 사용 중인 설비 코드입니다.' }); } // 설비 수정 EquipmentModel.update(equipmentId, equipmentData, (error, result) => { if (error) { console.error('설비 수정 오류:', error); return res.status(500).json({ success: false, message: '설비 수정 중 오류가 발생했습니다.' }); } res.json({ success: true, message: '설비가 성공적으로 수정되었습니다.', data: result }); }); }); }); } catch (error) { console.error('설비 수정 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // UPDATE MAP POSITION - 지도상 위치 업데이트 updateMapPosition: (req, res) => { try { const equipmentId = req.params.id; const positionData = { map_x_percent: req.body.map_x_percent, map_y_percent: req.body.map_y_percent, map_width_percent: req.body.map_width_percent, map_height_percent: req.body.map_height_percent }; // workplace_id가 있으면 포함 (설비를 다른 작업장으로 이동 가능) if (req.body.workplace_id !== undefined) { positionData.workplace_id = req.body.workplace_id; } EquipmentModel.updateMapPosition(equipmentId, positionData, (error, result) => { if (error) { console.error('설비 위치 업데이트 오류:', error); return res.status(500).json({ success: false, message: '설비 위치 업데이트 중 오류가 발생했습니다.' }); } res.json({ success: true, message: '설비 위치가 성공적으로 업데이트되었습니다.', data: result }); }); } catch (error) { console.error('설비 위치 업데이트 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // DELETE - 설비 삭제 deleteEquipment: (req, res) => { try { const equipmentId = req.params.id; EquipmentModel.delete(equipmentId, (error, result) => { if (error) { console.error('설비 삭제 오류:', error); return res.status(500).json({ success: false, message: '설비 삭제 중 오류가 발생했습니다.' }); } res.json({ success: true, message: '설비가 성공적으로 삭제되었습니다.', data: result }); }); } catch (error) { console.error('설비 삭제 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET EQUIPMENT TYPES - 사용 중인 설비 유형 목록 조회 getEquipmentTypes: (req, res) => { try { EquipmentModel.getEquipmentTypes((error, results) => { if (error) { console.error('설비 유형 조회 오류:', error); return res.status(500).json({ success: false, message: '설비 유형 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('설비 유형 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET NEXT EQUIPMENT CODE - 다음 관리번호 자동 생성 getNextEquipmentCode: (req, res) => { try { const prefix = req.query.prefix || 'TKP'; EquipmentModel.getNextEquipmentCode(prefix, (error, nextCode) => { if (error) { console.error('다음 관리번호 조회 오류:', error); return res.status(500).json({ success: false, message: '다음 관리번호 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: { next_code: nextCode, prefix: prefix } }); }); } catch (error) { console.error('다음 관리번호 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // ========================================== // 설비 사진 관리 // ========================================== // ADD PHOTO - 설비 사진 추가 addPhoto: async (req, res) => { try { const equipmentId = req.params.id; const { photo_base64, description, display_order } = req.body; if (!photo_base64) { return res.status(400).json({ success: false, message: '사진 데이터가 필요합니다.' }); } // Base64 이미지를 파일로 저장 const photoPath = await imageUploadService.saveBase64Image( photo_base64, 'equipment', 'equipments' ); if (!photoPath) { return res.status(500).json({ success: false, message: '사진 저장에 실패했습니다.' }); } // DB에 사진 정보 저장 const photoData = { photo_path: photoPath, description: description || null, display_order: display_order || 0, uploaded_by: req.user?.user_id || null }; EquipmentModel.addPhoto(equipmentId, photoData, (error, result) => { if (error) { console.error('사진 정보 저장 오류:', error); return res.status(500).json({ success: false, message: '사진 정보 저장 중 오류가 발생했습니다.' }); } res.status(201).json({ success: true, message: '사진이 성공적으로 추가되었습니다.', data: result }); }); } catch (error) { console.error('사진 추가 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET PHOTOS - 설비 사진 조회 getPhotos: (req, res) => { try { const equipmentId = req.params.id; EquipmentModel.getPhotos(equipmentId, (error, results) => { if (error) { console.error('사진 조회 오류:', error); return res.status(500).json({ success: false, message: '사진 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('사진 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // DELETE PHOTO - 설비 사진 삭제 deletePhoto: async (req, res) => { try { const photoId = req.params.photoId; EquipmentModel.deletePhoto(photoId, async (error, result) => { if (error) { if (error.message === 'Photo not found') { return res.status(404).json({ success: false, message: '사진을 찾을 수 없습니다.' }); } console.error('사진 삭제 오류:', error); return res.status(500).json({ success: false, message: '사진 삭제 중 오류가 발생했습니다.' }); } // 파일 시스템에서 사진 삭제 if (result.photo_path) { await imageUploadService.deleteFile(result.photo_path); } res.json({ success: true, message: '사진이 성공적으로 삭제되었습니다.', data: { photo_id: photoId } }); }); } catch (error) { console.error('사진 삭제 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // ========================================== // 설비 임시 이동 // ========================================== // MOVE TEMPORARILY - 설비 임시 이동 moveTemporarily: (req, res) => { try { const equipmentId = req.params.id; const moveData = { target_workplace_id: req.body.target_workplace_id, target_x_percent: req.body.target_x_percent, target_y_percent: req.body.target_y_percent, target_width_percent: req.body.target_width_percent, target_height_percent: req.body.target_height_percent, from_workplace_id: req.body.from_workplace_id, from_x_percent: req.body.from_x_percent, from_y_percent: req.body.from_y_percent, reason: req.body.reason, moved_by: req.user?.user_id || null }; if (!moveData.target_workplace_id || moveData.target_x_percent === undefined || moveData.target_y_percent === undefined) { return res.status(400).json({ success: false, message: '이동할 작업장과 위치가 필요합니다.' }); } EquipmentModel.moveTemporarily(equipmentId, moveData, (error, result) => { if (error) { console.error('설비 이동 오류:', error); return res.status(500).json({ success: false, message: '설비 이동 중 오류가 발생했습니다.' }); } res.json({ success: true, message: '설비가 임시 이동되었습니다.', data: result }); }); } catch (error) { console.error('설비 이동 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // RETURN TO ORIGINAL - 설비 원위치 복귀 returnToOriginal: (req, res) => { try { const equipmentId = req.params.id; const userId = req.user?.user_id || null; EquipmentModel.returnToOriginal(equipmentId, userId, (error, result) => { if (error) { if (error.message === 'Equipment not found') { return res.status(404).json({ success: false, message: '설비를 찾을 수 없습니다.' }); } console.error('설비 복귀 오류:', error); return res.status(500).json({ success: false, message: '설비 복귀 중 오류가 발생했습니다.' }); } res.json({ success: true, message: '설비가 원위치로 복귀되었습니다.', data: result }); }); } catch (error) { console.error('설비 복귀 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET TEMPORARILY MOVED - 임시 이동된 설비 목록 getTemporarilyMoved: (req, res) => { try { EquipmentModel.getTemporarilyMoved((error, results) => { if (error) { console.error('임시 이동 설비 조회 오류:', error); return res.status(500).json({ success: false, message: '임시 이동 설비 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('임시 이동 설비 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET MOVE LOGS - 설비 이동 이력 조회 getMoveLogs: (req, res) => { try { const equipmentId = req.params.id; EquipmentModel.getMoveLogs(equipmentId, (error, results) => { if (error) { console.error('이동 이력 조회 오류:', error); return res.status(500).json({ success: false, message: '이동 이력 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('이동 이력 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // ========================================== // 설비 외부 반출/반입 // ========================================== // EXPORT EQUIPMENT - 설비 외부 반출 exportEquipment: (req, res) => { try { const equipmentId = req.params.id; const exportData = { equipment_id: equipmentId, export_date: req.body.export_date, expected_return_date: req.body.expected_return_date, destination: req.body.destination, reason: req.body.reason, notes: req.body.notes, is_repair: req.body.is_repair || false, exported_by: req.user?.user_id || null }; EquipmentModel.exportEquipment(exportData, (error, result) => { if (error) { console.error('설비 반출 오류:', error); return res.status(500).json({ success: false, message: '설비 반출 중 오류가 발생했습니다.' }); } res.status(201).json({ success: true, message: '설비가 외부로 반출되었습니다.', data: result }); }); } catch (error) { console.error('설비 반출 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // RETURN EQUIPMENT - 설비 반입 (외부에서 복귀) returnEquipment: (req, res) => { try { const logId = req.params.logId; const returnData = { return_date: req.body.return_date, new_status: req.body.new_status || 'active', notes: req.body.notes, returned_by: req.user?.user_id || null }; EquipmentModel.returnEquipment(logId, returnData, (error, result) => { if (error) { if (error.message === 'Export log not found') { return res.status(404).json({ success: false, message: '반출 기록을 찾을 수 없습니다.' }); } console.error('설비 반입 오류:', error); return res.status(500).json({ success: false, message: '설비 반입 중 오류가 발생했습니다.' }); } res.json({ success: true, message: '설비가 반입되었습니다.', data: result }); }); } catch (error) { console.error('설비 반입 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET EXTERNAL LOGS - 설비 외부 반출 이력 조회 getExternalLogs: (req, res) => { try { const equipmentId = req.params.id; EquipmentModel.getExternalLogs(equipmentId, (error, results) => { if (error) { console.error('반출 이력 조회 오류:', error); return res.status(500).json({ success: false, message: '반출 이력 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('반출 이력 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET EXPORTED EQUIPMENTS - 현재 외부 반출 중인 설비 목록 getExportedEquipments: (req, res) => { try { EquipmentModel.getExportedEquipments((error, results) => { if (error) { console.error('반출 중 설비 조회 오류:', error); return res.status(500).json({ success: false, message: '반출 중 설비 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('반출 중 설비 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // ========================================== // 설비 수리 신청 // ========================================== // CREATE REPAIR REQUEST - 수리 신청 createRepairRequest: async (req, res) => { try { const equipmentId = req.params.id; const { photo_base64_list, description, item_id, workplace_id } = req.body; // 사진 저장 (있는 경우) let photoPaths = []; if (photo_base64_list && photo_base64_list.length > 0) { for (const base64 of photo_base64_list) { const path = await imageUploadService.saveBase64Image(base64, 'repair', 'issues'); if (path) photoPaths.push(path); } } const requestData = { equipment_id: equipmentId, item_id: item_id || null, workplace_id: workplace_id || null, description: description || null, photo_paths: photoPaths.length > 0 ? photoPaths : null, reported_by: req.user?.user_id || null }; EquipmentModel.createRepairRequest(requestData, (error, result) => { if (error) { if (error.message === '설비 수리 카테고리가 없습니다') { return res.status(400).json({ success: false, message: error.message }); } console.error('수리 신청 오류:', error); return res.status(500).json({ success: false, message: '수리 신청 중 오류가 발생했습니다.' }); } res.status(201).json({ success: true, message: '수리 신청이 접수되었습니다.', data: result }); }); } catch (error) { console.error('수리 신청 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET REPAIR HISTORY - 설비 수리 이력 조회 getRepairHistory: (req, res) => { try { const equipmentId = req.params.id; EquipmentModel.getRepairHistory(equipmentId, (error, results) => { if (error) { console.error('수리 이력 조회 오류:', error); return res.status(500).json({ success: false, message: '수리 이력 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('수리 이력 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // GET REPAIR CATEGORIES - 설비 수리 항목 목록 조회 getRepairCategories: (req, res) => { try { EquipmentModel.getRepairCategories((error, results) => { if (error) { console.error('수리 항목 조회 오류:', error); return res.status(500).json({ success: false, message: '수리 항목 조회 중 오류가 발생했습니다.' }); } res.json({ success: true, data: results }); }); } catch (error) { console.error('수리 항목 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // ADD REPAIR CATEGORY - 새 수리 항목 추가 addRepairCategory: (req, res) => { try { const { item_name } = req.body; if (!item_name || !item_name.trim()) { return res.status(400).json({ success: false, message: '수리 유형 이름을 입력하세요.' }); } EquipmentModel.addRepairCategory(item_name.trim(), (error, result) => { if (error) { console.error('수리 항목 추가 오류:', error); return res.status(500).json({ success: false, message: '수리 항목 추가 중 오류가 발생했습니다.' }); } res.status(201).json({ success: true, message: result.isNew ? '새 수리 유형이 추가되었습니다.' : '기존 수리 유형을 사용합니다.', data: result }); }); } catch (error) { console.error('수리 항목 추가 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } } }; module.exports = EquipmentController;