/** * Equipment Model * * equipments + equipment_photos CRUD (MariaDB) */ const { getPool } = require('./userModel'); // ==================== 기본 CRUD ==================== async function getAll(filters = {}) { const db = getPool(); let sql = `SELECT e.*, w.workplace_name, c.category_name FROM equipments e LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id LEFT JOIN workplace_categories c ON w.category_id = c.category_id`; const conditions = []; const values = []; if (filters.workplace_id) { conditions.push('e.workplace_id = ?'); values.push(filters.workplace_id); } if (filters.equipment_type) { conditions.push('e.equipment_type = ?'); values.push(filters.equipment_type); } if (filters.status) { conditions.push('e.status = ?'); values.push(filters.status); } if (filters.search) { conditions.push('(e.equipment_name LIKE ? OR e.equipment_code LIKE ?)'); const term = `%${filters.search}%`; values.push(term, term); } if (conditions.length) sql += ' WHERE ' + conditions.join(' AND '); sql += ' ORDER BY e.equipment_code ASC'; const [rows] = await db.query(sql, values); return rows; } async function getById(id) { const db = getPool(); const [rows] = await db.query( `SELECT e.*, w.workplace_name, c.category_name FROM equipments e LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id LEFT JOIN workplace_categories c ON w.category_id = c.category_id WHERE e.equipment_id = ?`, [id] ); return rows[0] || null; } async function getByWorkplace(workplaceId) { const db = getPool(); const [rows] = await db.query( `SELECT e.*, w.workplace_name FROM equipments e LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id WHERE e.workplace_id = ? ORDER BY e.equipment_code ASC`, [workplaceId] ); return rows; } async function create(data) { const db = getPool(); const [result] = await db.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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ data.equipment_code, data.equipment_name, data.equipment_type || null, data.model_name || null, data.manufacturer || null, data.supplier || null, data.purchase_price || null, data.installation_date || null, data.serial_number || null, data.specifications || null, data.status || 'active', data.notes || null, data.workplace_id || null, data.map_x_percent || null, data.map_y_percent || null, data.map_width_percent || null, data.map_height_percent || null ] ); return getById(result.insertId); } async function update(id, data) { const db = getPool(); const fields = []; const values = []; if (data.equipment_code !== undefined) { fields.push('equipment_code = ?'); values.push(data.equipment_code); } if (data.equipment_name !== undefined) { fields.push('equipment_name = ?'); values.push(data.equipment_name); } if (data.equipment_type !== undefined) { fields.push('equipment_type = ?'); values.push(data.equipment_type || null); } if (data.model_name !== undefined) { fields.push('model_name = ?'); values.push(data.model_name || null); } if (data.manufacturer !== undefined) { fields.push('manufacturer = ?'); values.push(data.manufacturer || null); } if (data.supplier !== undefined) { fields.push('supplier = ?'); values.push(data.supplier || null); } if (data.purchase_price !== undefined) { fields.push('purchase_price = ?'); values.push(data.purchase_price || null); } if (data.installation_date !== undefined) { fields.push('installation_date = ?'); values.push(data.installation_date || null); } if (data.serial_number !== undefined) { fields.push('serial_number = ?'); values.push(data.serial_number || null); } if (data.specifications !== undefined) { fields.push('specifications = ?'); values.push(data.specifications || null); } if (data.status !== undefined) { fields.push('status = ?'); values.push(data.status); } if (data.notes !== undefined) { fields.push('notes = ?'); values.push(data.notes || null); } if (data.workplace_id !== undefined) { fields.push('workplace_id = ?'); values.push(data.workplace_id || null); } if (data.map_x_percent !== undefined) { fields.push('map_x_percent = ?'); values.push(data.map_x_percent); } if (data.map_y_percent !== undefined) { fields.push('map_y_percent = ?'); values.push(data.map_y_percent); } if (data.map_width_percent !== undefined) { fields.push('map_width_percent = ?'); values.push(data.map_width_percent); } if (data.map_height_percent !== undefined) { fields.push('map_height_percent = ?'); values.push(data.map_height_percent); } if (fields.length === 0) return getById(id); values.push(id); await db.query(`UPDATE equipments SET ${fields.join(', ')} WHERE equipment_id = ?`, values); return getById(id); } async function remove(id) { const db = getPool(); await db.query('DELETE FROM equipments WHERE equipment_id = ?', [id]); } async function getEquipmentTypes() { const db = getPool(); const [rows] = await db.query( 'SELECT DISTINCT equipment_type FROM equipments WHERE equipment_type IS NOT NULL AND equipment_type != "" ORDER BY equipment_type ASC' ); return rows.map(r => r.equipment_type); } async function getNextCode(prefix = 'TKP') { const db = getPool(); const [rows] = await db.query( 'SELECT equipment_code FROM equipments WHERE equipment_code LIKE ? ORDER BY equipment_code DESC LIMIT 1', [`${prefix}-%`] ); if (!rows.length) return `${prefix}-001`; const lastNum = parseInt(rows[0].equipment_code.replace(`${prefix}-`, ''), 10) || 0; return `${prefix}-${String(lastNum + 1).padStart(3, '0')}`; } async function checkDuplicateCode(code, excludeId) { const db = getPool(); let sql = 'SELECT equipment_id FROM equipments WHERE equipment_code = ?'; const values = [code]; if (excludeId) { sql += ' AND equipment_id != ?'; values.push(excludeId); } const [rows] = await db.query(sql, values); return rows.length > 0; } // ==================== 지도 위치 ==================== async function updateMapPosition(id, positionData) { const db = getPool(); const fields = ['map_x_percent = ?', 'map_y_percent = ?', 'map_width_percent = ?', 'map_height_percent = ?']; const values = [positionData.map_x_percent, positionData.map_y_percent, positionData.map_width_percent, positionData.map_height_percent]; if (positionData.workplace_id !== undefined) { fields.push('workplace_id = ?'); values.push(positionData.workplace_id); } values.push(id); await db.query(`UPDATE equipments SET ${fields.join(', ')} WHERE equipment_id = ?`, values); return getById(id); } // ==================== 사진 ==================== async function addPhoto(equipmentId, photoData) { const db = getPool(); const [result] = await db.query( `INSERT INTO equipment_photos (equipment_id, photo_path, description, display_order, uploaded_by) VALUES (?, ?, ?, ?, ?)`, [equipmentId, photoData.photo_path, photoData.description || null, photoData.display_order || 0, photoData.uploaded_by || null] ); return { photo_id: result.insertId, equipment_id: equipmentId, ...photoData }; } async function getPhotos(equipmentId) { const db = getPool(); const [rows] = await db.query( 'SELECT * FROM equipment_photos WHERE equipment_id = ? ORDER BY display_order ASC, created_at ASC', [equipmentId] ); return rows; } async function deletePhoto(photoId) { const db = getPool(); const [photo] = await db.query('SELECT photo_path FROM equipment_photos WHERE photo_id = ?', [photoId]); await db.query('DELETE FROM equipment_photos WHERE photo_id = ?', [photoId]); return { photo_id: photoId, photo_path: photo[0]?.photo_path }; } module.exports = { getAll, getById, getByWorkplace, create, update, remove, getEquipmentTypes, getNextCode, checkDuplicateCode, updateMapPosition, addPhoto, getPhotos, deletePhoto };