import { pool } from '../config.js'; /** * Analysis Model * 處理 5 Why 分析記錄相關的資料庫操作 */ class Analysis { /** * 建立新的分析記錄 */ static async create(analysisData) { const { user_id, finding, job_content, output_language } = analysisData; try { const [result] = await pool.execute( `INSERT INTO analyses (user_id, finding, job_content, output_language, status) VALUES (?, ?, ?, ?, 'pending')`, [user_id, finding, job_content, output_language] ); return await this.findById(result.insertId); } catch (error) { throw new Error(`Error creating analysis: ${error.message}`); } } /** * 根據 ID 取得分析記錄 */ static async findById(id) { try { const [rows] = await pool.execute( 'SELECT * FROM analyses WHERE id = ?', [id] ); return rows[0] || null; } catch (error) { throw new Error(`Error finding analysis: ${error.message}`); } } /** * 更新分析狀態 */ static async updateStatus(id, status, errorMessage = null) { try { await pool.execute( 'UPDATE analyses SET status = ?, error_message = ? WHERE id = ?', [status, errorMessage, id] ); } catch (error) { throw new Error(`Error updating analysis status: ${error.message}`); } } /** * 儲存分析結果 */ static async saveResult(id, resultData) { const { problem_restatement, analysis_result, processing_time } = resultData; try { const connection = await pool.getConnection(); await connection.beginTransaction(); try { // 更新主分析記錄 await connection.execute( `UPDATE analyses SET problem_restatement = ?, analysis_result = ?, processing_time = ?, status = 'completed' WHERE id = ?`, [problem_restatement, JSON.stringify(analysis_result), processing_time, id] ); // 儲存分析角度 if (analysis_result.analyses && Array.isArray(analysis_result.analyses)) { for (const perspective of analysis_result.analyses) { const [perspectiveResult] = await connection.execute( `INSERT INTO analysis_perspectives (analysis_id, perspective, perspective_icon, root_cause, permanent_solution, logic_check_forward, logic_check_backward, logic_valid) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [ id, perspective.perspective, perspective.perspectiveIcon || null, perspective.rootCause || null, perspective.countermeasure?.permanent || null, perspective.logicCheck?.forward || null, perspective.logicCheck?.backward || null, perspective.logicCheck?.isValid !== false ] ); const perspectiveId = perspectiveResult.insertId; // 儲存 5 Why 詳細記錄 if (perspective.whys && Array.isArray(perspective.whys)) { for (const why of perspective.whys) { if (why && why.level) { await connection.execute( `INSERT INTO analysis_whys (perspective_id, level, question, answer, is_verified, verification_note) VALUES (?, ?, ?, ?, ?, ?)`, [ perspectiveId, why.level, why.question, why.answer, why.isVerified !== false, why.verificationNote || null ] ); } } } } } await connection.commit(); connection.release(); return await this.findById(id); } catch (error) { await connection.rollback(); connection.release(); throw error; } } catch (error) { throw new Error(`Error saving analysis result: ${error.message}`); } } /** * 取得使用者的分析記錄(分頁) */ static async getByUserId(userId, page = 1, limit = 10, filters = {}) { const offset = (page - 1) * limit; let query = 'SELECT * FROM analyses WHERE user_id = ?'; let countQuery = 'SELECT COUNT(*) as total FROM analyses WHERE user_id = ?'; const whereParams = [userId]; const whereClauses = []; // 篩選條件 if (filters.status) { whereClauses.push('status = ?'); whereParams.push(filters.status); } if (filters.date_from) { whereClauses.push('created_at >= ?'); whereParams.push(filters.date_from); } if (filters.date_to) { whereClauses.push('created_at <= ?'); whereParams.push(filters.date_to); } if (filters.search) { whereClauses.push('finding LIKE ?'); whereParams.push(`%${filters.search}%`); } if (whereClauses.length > 0) { const whereClause = ' AND ' + whereClauses.join(' AND '); query += whereClause; countQuery += whereClause; } query += ' ORDER BY created_at DESC LIMIT ? OFFSET ?'; try { const [rows] = await pool.execute(query, [...whereParams, limit, offset]); const [countResult] = await pool.execute(countQuery, whereParams); return { data: rows, pagination: { page, limit, total: countResult[0].total, totalPages: Math.ceil(countResult[0].total / limit) } }; } catch (error) { throw new Error(`Error getting user analyses: ${error.message}`); } } /** * 取得所有分析記錄(管理員用) */ static async getAll(page = 1, limit = 10, filters = {}) { const offset = (page - 1) * limit; let query = ` SELECT a.*, u.username, u.employee_id FROM analyses a JOIN users u ON a.user_id = u.id `; let countQuery = 'SELECT COUNT(*) as total FROM analyses a JOIN users u ON a.user_id = u.id'; const whereParams = []; const whereClauses = []; // 篩選條件 if (filters.status) { whereClauses.push('a.status = ?'); whereParams.push(filters.status); } if (filters.user_id) { whereClauses.push('a.user_id = ?'); whereParams.push(filters.user_id); } if (filters.search) { whereClauses.push('(a.finding LIKE ? OR u.username LIKE ?)'); const searchTerm = `%${filters.search}%`; whereParams.push(searchTerm, searchTerm); } if (whereClauses.length > 0) { const whereClause = ' WHERE ' + whereClauses.join(' AND '); query += whereClause; countQuery += whereClause; } query += ' ORDER BY a.created_at DESC LIMIT ? OFFSET ?'; try { const [rows] = await pool.execute(query, [...whereParams, limit, offset]); const [countResult] = await pool.execute(countQuery, whereParams); return { data: rows, pagination: { page, limit, total: countResult[0].total, totalPages: Math.ceil(countResult[0].total / limit) } }; } catch (error) { throw new Error(`Error getting all analyses: ${error.message}`); } } /** * 取得分析詳細資料(含角度和 Whys) */ static async getFullAnalysis(id) { try { // 取得主記錄 const analysis = await this.findById(id); if (!analysis) return null; // 取得分析角度 const [perspectives] = await pool.execute( 'SELECT * FROM analysis_perspectives WHERE analysis_id = ? ORDER BY id', [id] ); // 為每個角度取得 Whys for (const perspective of perspectives) { const [whys] = await pool.execute( 'SELECT * FROM analysis_whys WHERE perspective_id = ? ORDER BY level', [perspective.id] ); perspective.whys = whys; } analysis.perspectives = perspectives; return analysis; } catch (error) { throw new Error(`Error getting full analysis: ${error.message}`); } } /** * 刪除分析記錄 */ static async delete(id) { try { await pool.execute('DELETE FROM analyses WHERE id = ?', [id]); return true; } catch (error) { throw new Error(`Error deleting analysis: ${error.message}`); } } /** * 取得最近的分析記錄 */ static async getRecent(limit = 100) { try { const [rows] = await pool.execute( 'SELECT * FROM recent_analyses LIMIT ?', [limit] ); return rows; } catch (error) { throw new Error(`Error getting recent analyses: ${error.message}`); } } /** * 取得統計資料 */ static async getStatistics(userId = null) { try { let query = ` SELECT COUNT(*) as total, COUNT(CASE WHEN status = 'completed' THEN 1 END) as completed, COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed, COUNT(CASE WHEN status = 'processing' THEN 1 END) as processing, AVG(processing_time) as avg_processing_time, MAX(created_at) as last_analysis_at FROM analyses `; const params = []; if (userId) { query += ' WHERE user_id = ?'; params.push(userId); } const [rows] = await pool.execute(query, params); return rows[0]; } catch (error) { throw new Error(`Error getting statistics: ${error.message}`); } } } export default Analysis;