// models/equipmentModel.js const { getDb } = require('../dbPool'); const EquipmentModel = { // CREATE - 설비 생성 create: async (equipmentData, callback) => { try { const db = await getDb(); const query = ` INSERT INTO equipments ( equipment_code, equipment_name, equipment_type, model_name, manufacturer, supplier, purchase_price, installation_date, serial_number, specifications, status, notes, workplace_id, map_x_percent, map_y_percent, map_width_percent, map_height_percent ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `; const values = [ equipmentData.equipment_code, equipmentData.equipment_name, equipmentData.equipment_type || null, equipmentData.model_name || null, equipmentData.manufacturer || null, equipmentData.supplier || null, equipmentData.purchase_price || null, equipmentData.installation_date || null, equipmentData.serial_number || null, equipmentData.specifications || null, equipmentData.status || 'active', equipmentData.notes || null, equipmentData.workplace_id || null, equipmentData.map_x_percent || null, equipmentData.map_y_percent || null, equipmentData.map_width_percent || null, equipmentData.map_height_percent || null ]; const [result] = await db.query(query, values); callback(null, { equipment_id: result.insertId, ...equipmentData }); } catch (error) { callback(error); } }, // READ ALL - 모든 설비 조회 (필터링 옵션 포함) getAll: async (filters, callback) => { try { const db = await getDb(); let query = ` SELECT e.*, w.workplace_name, wc.category_name FROM equipments e LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id WHERE 1=1 `; const values = []; // 필터링: 작업장 ID if (filters.workplace_id) { query += ' AND e.workplace_id = ?'; values.push(filters.workplace_id); } // 필터링: 설비 유형 if (filters.equipment_type) { query += ' AND e.equipment_type = ?'; values.push(filters.equipment_type); } // 필터링: 상태 if (filters.status) { query += ' AND e.status = ?'; values.push(filters.status); } // 필터링: 검색어 (설비명, 설비코드) if (filters.search) { query += ' AND (e.equipment_name LIKE ? OR e.equipment_code LIKE ?)'; const searchTerm = `%${filters.search}%`; values.push(searchTerm, searchTerm); } query += ' ORDER BY e.equipment_code ASC'; const [rows] = await db.query(query, values); callback(null, rows); } catch (error) { callback(error); } }, // READ ONE - 특정 설비 조회 getById: async (equipmentId, callback) => { try { const db = await getDb(); const query = ` SELECT e.*, w.workplace_name, wc.category_name FROM equipments e LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id WHERE e.equipment_id = ? `; const [rows] = await db.query(query, [equipmentId]); callback(null, rows[0]); } catch (error) { callback(error); } }, // READ BY WORKPLACE - 특정 작업장의 설비 조회 getByWorkplace: async (workplaceId, callback) => { try { const db = await getDb(); const query = ` SELECT e.* FROM equipments e WHERE e.workplace_id = ? ORDER BY e.equipment_code ASC `; const [rows] = await db.query(query, [workplaceId]); callback(null, rows); } catch (error) { callback(error); } }, // READ ACTIVE - 활성 설비만 조회 getActive: async (callback) => { try { const db = await getDb(); const query = ` SELECT e.*, w.workplace_name, wc.category_name FROM equipments e LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id WHERE e.status = 'active' ORDER BY e.equipment_code ASC `; const [rows] = await db.query(query); callback(null, rows); } catch (error) { callback(error); } }, // UPDATE - 설비 수정 update: async (equipmentId, equipmentData, callback) => { try { const db = await getDb(); const query = ` UPDATE equipments SET equipment_code = ?, equipment_name = ?, equipment_type = ?, model_name = ?, manufacturer = ?, supplier = ?, purchase_price = ?, installation_date = ?, serial_number = ?, specifications = ?, status = ?, notes = ?, workplace_id = ?, map_x_percent = ?, map_y_percent = ?, map_width_percent = ?, map_height_percent = ?, updated_at = NOW() WHERE equipment_id = ? `; const values = [ equipmentData.equipment_code, equipmentData.equipment_name, equipmentData.equipment_type || null, equipmentData.model_name || null, equipmentData.manufacturer || null, equipmentData.supplier || null, equipmentData.purchase_price || null, equipmentData.installation_date || null, equipmentData.serial_number || null, equipmentData.specifications || null, equipmentData.status || 'active', equipmentData.notes || null, equipmentData.workplace_id || null, equipmentData.map_x_percent || null, equipmentData.map_y_percent || null, equipmentData.map_width_percent || null, equipmentData.map_height_percent || null, equipmentId ]; const [result] = await db.query(query, values); if (result.affectedRows === 0) { return callback(new Error('Equipment not found')); } callback(null, { equipment_id: equipmentId, ...equipmentData }); } catch (error) { callback(error); } }, // UPDATE MAP POSITION - 지도상 위치 업데이트 (선택적으로 workplace_id도 업데이트) updateMapPosition: async (equipmentId, positionData, callback) => { try { const db = await getDb(); // workplace_id가 포함된 경우 함께 업데이트 const hasWorkplaceId = positionData.workplace_id !== undefined; const query = hasWorkplaceId ? ` UPDATE equipments SET workplace_id = ?, map_x_percent = ?, map_y_percent = ?, map_width_percent = ?, map_height_percent = ?, updated_at = NOW() WHERE equipment_id = ? ` : ` UPDATE equipments SET map_x_percent = ?, map_y_percent = ?, map_width_percent = ?, map_height_percent = ?, updated_at = NOW() WHERE equipment_id = ? `; const values = hasWorkplaceId ? [ positionData.workplace_id, positionData.map_x_percent, positionData.map_y_percent, positionData.map_width_percent, positionData.map_height_percent, equipmentId ] : [ positionData.map_x_percent, positionData.map_y_percent, positionData.map_width_percent, positionData.map_height_percent, equipmentId ]; const [result] = await db.query(query, values); if (result.affectedRows === 0) { return callback(new Error('Equipment not found')); } callback(null, { equipment_id: equipmentId, ...positionData }); } catch (error) { callback(error); } }, // DELETE - 설비 삭제 delete: async (equipmentId, callback) => { try { const db = await getDb(); const query = 'DELETE FROM equipments WHERE equipment_id = ?'; const [result] = await db.query(query, [equipmentId]); if (result.affectedRows === 0) { return callback(new Error('Equipment not found')); } callback(null, { equipment_id: equipmentId }); } catch (error) { callback(error); } }, // CHECK DUPLICATE CODE - 설비 코드 중복 확인 checkDuplicateCode: async (equipmentCode, excludeEquipmentId, callback) => { try { const db = await getDb(); let query = 'SELECT equipment_id FROM equipments WHERE equipment_code = ?'; const values = [equipmentCode]; if (excludeEquipmentId) { query += ' AND equipment_id != ?'; values.push(excludeEquipmentId); } const [rows] = await db.query(query, values); callback(null, rows.length > 0); } catch (error) { callback(error); } }, // GET EQUIPMENT TYPES - 사용 중인 설비 유형 목록 조회 getEquipmentTypes: async (callback) => { try { const db = await getDb(); const query = ` SELECT DISTINCT equipment_type FROM equipments WHERE equipment_type IS NOT NULL ORDER BY equipment_type ASC `; const [rows] = await db.query(query); callback(null, rows.map(row => row.equipment_type)); } catch (error) { callback(error); } }, // GET NEXT EQUIPMENT CODE - 다음 관리번호 자동 생성 (TKP-001 형식) getNextEquipmentCode: async (prefix = 'TKP', callback) => { try { const db = await getDb(); // 해당 접두사로 시작하는 가장 큰 번호 찾기 const query = ` SELECT equipment_code FROM equipments WHERE equipment_code LIKE ? ORDER BY equipment_code DESC LIMIT 1 `; const [rows] = await db.query(query, [`${prefix}-%`]); let nextNumber = 1; if (rows.length > 0) { // TKP-001 형식에서 숫자 부분 추출 const lastCode = rows[0].equipment_code; const match = lastCode.match(new RegExp(`^${prefix}-(\\d+)$`)); if (match) { nextNumber = parseInt(match[1], 10) + 1; } } // 3자리로 패딩 (001, 002, ...) const nextCode = `${prefix}-${String(nextNumber).padStart(3, '0')}`; callback(null, nextCode); } catch (error) { callback(error); } } }; module.exports = EquipmentModel;