// controllers/equipmentController.js const EquipmentModel = require('../models/equipmentModel'); const imageUploadService = require('../services/imageUploadService'); const logger = require('../utils/logger'); 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: '설비 코드와 설비명은 필수입니다.' }); } const isDuplicate = await EquipmentModel.checkDuplicateCode(equipmentData.equipment_code, null); if (isDuplicate) { return res.status(409).json({ success: false, message: '이미 사용 중인 설비 코드입니다.' }); } const result = await EquipmentModel.create(equipmentData); res.status(201).json({ success: true, message: '설비가 성공적으로 생성되었습니다.', data: result }); } catch (err) { logger.error('설비 생성 오류:', err); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // READ ALL - 모든 설비 조회 getAllEquipments: async (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 }; const results = await EquipmentModel.getAll(filters); res.json({ success: true, data: results }); } catch (err) { logger.error('설비 조회 오류:', err); res.status(500).json({ success: false, message: '설비 조회 중 오류가 발생했습니다.' }); } }, // READ ONE - 특정 설비 조회 getEquipmentById: async (req, res) => { try { const result = await EquipmentModel.getById(req.params.id); if (!result) { return res.status(404).json({ success: false, message: '설비를 찾을 수 없습니다.' }); } res.json({ success: true, data: result }); } catch (err) { logger.error('설비 조회 오류:', err); res.status(500).json({ success: false, message: '설비 조회 중 오류가 발생했습니다.' }); } }, // READ BY WORKPLACE - 특정 작업장의 설비 조회 getEquipmentsByWorkplace: async (req, res) => { try { const results = await EquipmentModel.getByWorkplace(req.params.workplaceId); res.json({ success: true, data: results }); } catch (err) { logger.error('작업장 설비 조회 오류:', err); res.status(500).json({ success: false, message: '작업장 설비 조회 중 오류가 발생했습니다.' }); } }, // READ ACTIVE - 활성 설비만 조회 getActiveEquipments: async (req, res) => { try { const results = await EquipmentModel.getActive(); res.json({ success: true, data: results }); } catch (err) { logger.error('활성 설비 조회 오류:', err); 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: '설비 코드와 설비명은 필수입니다.' }); } const existingEquipment = await EquipmentModel.getById(equipmentId); if (!existingEquipment) { return res.status(404).json({ success: false, message: '설비를 찾을 수 없습니다.' }); } const isDuplicate = await EquipmentModel.checkDuplicateCode(equipmentData.equipment_code, equipmentId); if (isDuplicate) { return res.status(409).json({ success: false, message: '이미 사용 중인 설비 코드입니다.' }); } const result = await EquipmentModel.update(equipmentId, equipmentData); res.json({ success: true, message: '설비가 성공적으로 수정되었습니다.', data: result }); } catch (err) { logger.error('설비 수정 오류:', err); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, // UPDATE MAP POSITION - 지도상 위치 업데이트 updateMapPosition: async (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 }; if (req.body.workplace_id !== undefined) { positionData.workplace_id = req.body.workplace_id; } const result = await EquipmentModel.updateMapPosition(equipmentId, positionData); res.json({ success: true, message: '설비 위치가 성공적으로 업데이트되었습니다.', data: result }); } catch (err) { logger.error('설비 위치 업데이트 오류:', err); res.status(500).json({ success: false, message: '설비 위치 업데이트 중 오류가 발생했습니다.' }); } }, // DELETE - 설비 삭제 deleteEquipment: async (req, res) => { try { const result = await EquipmentModel.delete(req.params.id); res.json({ success: true, message: '설비가 성공적으로 삭제되었습니다.', data: result }); } catch (err) { logger.error('설비 삭제 오류:', err); res.status(500).json({ success: false, message: '설비 삭제 중 오류가 발생했습니다.' }); } }, // GET EQUIPMENT TYPES - 사용 중인 설비 유형 목록 조회 getEquipmentTypes: async (req, res) => { try { const results = await EquipmentModel.getEquipmentTypes(); res.json({ success: true, data: results }); } catch (err) { logger.error('설비 유형 조회 오류:', err); res.status(500).json({ success: false, message: '설비 유형 조회 중 오류가 발생했습니다.' }); } }, // GET NEXT EQUIPMENT CODE - 다음 관리번호 자동 생성 getNextEquipmentCode: async (req, res) => { try { const prefix = req.query.prefix || 'TKP'; const nextCode = await EquipmentModel.getNextEquipmentCode(prefix); res.json({ success: true, data: { next_code: nextCode, prefix } }); } catch (err) { logger.error('다음 관리번호 조회 오류:', err); res.status(500).json({ success: false, message: '다음 관리번호 조회 중 오류가 발생했습니다.' }); } }, // ========================================== // 설비 사진 관리 // ========================================== 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: '사진 데이터가 필요합니다.' }); } const photoPath = await imageUploadService.saveBase64Image(photo_base64, 'equipment', 'equipments'); if (!photoPath) { return res.status(500).json({ success: false, message: '사진 저장에 실패했습니다.' }); } const photoData = { photo_path: photoPath, description: description || null, display_order: display_order || 0, uploaded_by: req.user?.user_id || null }; const result = await EquipmentModel.addPhoto(equipmentId, photoData); res.status(201).json({ success: true, message: '사진이 성공적으로 추가되었습니다.', data: result }); } catch (err) { logger.error('사진 추가 오류:', err); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } }, getPhotos: async (req, res) => { try { const results = await EquipmentModel.getPhotos(req.params.id); res.json({ success: true, data: results }); } catch (err) { logger.error('사진 조회 오류:', err); res.status(500).json({ success: false, message: '사진 조회 중 오류가 발생했습니다.' }); } }, deletePhoto: async (req, res) => { try { const result = await EquipmentModel.deletePhoto(req.params.photoId); if (result.photo_path) { await imageUploadService.deleteFile(result.photo_path); } res.json({ success: true, message: '사진이 성공적으로 삭제되었습니다.', data: { photo_id: req.params.photoId } }); } catch (err) { if (err.message === 'Photo not found') { return res.status(404).json({ success: false, message: '사진을 찾을 수 없습니다.' }); } logger.error('사진 삭제 오류:', err); res.status(500).json({ success: false, message: '사진 삭제 중 오류가 발생했습니다.' }); } }, // ========================================== // 설비 임시 이동 // ========================================== moveTemporarily: async (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: '이동할 작업장과 위치가 필요합니다.' }); } const result = await EquipmentModel.moveTemporarily(equipmentId, moveData); res.json({ success: true, message: '설비가 임시 이동되었습니다.', data: result }); } catch (err) { logger.error('설비 이동 오류:', err); res.status(500).json({ success: false, message: '설비 이동 중 오류가 발생했습니다.' }); } }, returnToOriginal: async (req, res) => { try { const result = await EquipmentModel.returnToOriginal(req.params.id, req.user?.user_id || null); res.json({ success: true, message: '설비가 원위치로 복귀되었습니다.', data: result }); } catch (err) { if (err.message === 'Equipment not found') { return res.status(404).json({ success: false, message: '설비를 찾을 수 없습니다.' }); } logger.error('설비 복귀 오류:', err); res.status(500).json({ success: false, message: '설비 복귀 중 오류가 발생했습니다.' }); } }, getTemporarilyMoved: async (req, res) => { try { const results = await EquipmentModel.getTemporarilyMoved(); res.json({ success: true, data: results }); } catch (err) { logger.error('임시 이동 설비 조회 오류:', err); res.status(500).json({ success: false, message: '임시 이동 설비 조회 중 오류가 발생했습니다.' }); } }, getMoveLogs: async (req, res) => { try { const results = await EquipmentModel.getMoveLogs(req.params.id); res.json({ success: true, data: results }); } catch (err) { logger.error('이동 이력 조회 오류:', err); res.status(500).json({ success: false, message: '이동 이력 조회 중 오류가 발생했습니다.' }); } }, // ========================================== // 설비 외부 반출/반입 // ========================================== exportEquipment: async (req, res) => { try { const exportData = { equipment_id: req.params.id, 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 }; const result = await EquipmentModel.exportEquipment(exportData); res.status(201).json({ success: true, message: '설비가 외부로 반출되었습니다.', data: result }); } catch (err) { logger.error('설비 반출 오류:', err); res.status(500).json({ success: false, message: '설비 반출 중 오류가 발생했습니다.' }); } }, returnEquipment: async (req, res) => { try { 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 }; const result = await EquipmentModel.returnEquipment(req.params.logId, returnData); res.json({ success: true, message: '설비가 반입되었습니다.', data: result }); } catch (err) { if (err.message === 'Export log not found') { return res.status(404).json({ success: false, message: '반출 기록을 찾을 수 없습니다.' }); } logger.error('설비 반입 오류:', err); res.status(500).json({ success: false, message: '설비 반입 중 오류가 발생했습니다.' }); } }, getExternalLogs: async (req, res) => { try { const results = await EquipmentModel.getExternalLogs(req.params.id); res.json({ success: true, data: results }); } catch (err) { logger.error('반출 이력 조회 오류:', err); res.status(500).json({ success: false, message: '반출 이력 조회 중 오류가 발생했습니다.' }); } }, getExportedEquipments: async (req, res) => { try { const results = await EquipmentModel.getExportedEquipments(); res.json({ success: true, data: results }); } catch (err) { logger.error('반출 중 설비 조회 오류:', err); res.status(500).json({ success: false, message: '반출 중 설비 조회 중 오류가 발생했습니다.' }); } }, // ========================================== // 설비 수리 신청 // ========================================== 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 }; const result = await EquipmentModel.createRepairRequest(requestData); res.status(201).json({ success: true, message: '수리 신청이 접수되었습니다.', data: result }); } catch (err) { if (err.message === '설비 수리 카테고리가 없습니다') { return res.status(400).json({ success: false, message: err.message }); } logger.error('수리 신청 오류:', err); res.status(500).json({ success: false, message: '수리 신청 중 오류가 발생했습니다.' }); } }, getRepairHistory: async (req, res) => { try { const results = await EquipmentModel.getRepairHistory(req.params.id); res.json({ success: true, data: results }); } catch (err) { logger.error('수리 이력 조회 오류:', err); res.status(500).json({ success: false, message: '수리 이력 조회 중 오류가 발생했습니다.' }); } }, getRepairCategories: async (req, res) => { try { const results = await EquipmentModel.getRepairCategories(); res.json({ success: true, data: results }); } catch (err) { logger.error('수리 항목 조회 오류:', err); res.status(500).json({ success: false, message: '수리 항목 조회 중 오류가 발생했습니다.' }); } }, addRepairCategory: async (req, res) => { try { const { item_name } = req.body; if (!item_name || !item_name.trim()) { return res.status(400).json({ success: false, message: '수리 유형 이름을 입력하세요.' }); } const result = await EquipmentModel.addRepairCategory(item_name.trim()); res.status(201).json({ success: true, message: result.isNew ? '새 수리 유형이 추가되었습니다.' : '기존 수리 유형을 사용합니다.', data: result }); } catch (err) { logger.error('수리 항목 추가 오류:', err); res.status(500).json({ success: false, message: '수리 항목 추가 중 오류가 발생했습니다.' }); } } }; module.exports = EquipmentController;