import { ReportService } from '../services/reportService.js' import { sendError } from '../utils/response.js' // import { OftenError } from '../utils/oftenError.js' import { GeneralService } from '../share/generalservice.js'; import { trim_all_array } from '../utils/trim.js' import { verifyToken, generateToken } from '../utils/token.js' import { Interface } from '../interfaces/Interface.js'; export class reportController { constructor() { this.generalService = new GeneralService(); this.reportService = new ReportService(); this.Interface = new Interface(); } async onNavigate(req, res) { this.generalService.devhint(1, 'reportController.js', 'onNavigate() start'); let organization = req.body.organization; const prommis = await this.onReportController(req, res, organization); return prommis; } async onReportController(req, res, database) { let idx = -1 let aryResult = [] try { let token = req.headers.authorization?.split(' ')[1]; const decoded = verifyToken(token); let acpTime = req.body.request.acpTime; let expTime = req.body.request.expTime; database = decoded.organization; aryResult = await this.reportService.getReportController(database, acpTime, expTime); } catch (error) { idx = 1; } finally { if (idx === 1) return sendError('เกิดข้อผิดพลาดไม่คาดคิดเกิดขึ้น', 'Unexpected error'); if (!aryResult) return sendError('ไม่พบการมีอยู่ของข้อมูล', 'Cannot Find Any Data'); try { // ✅ 1) เตรียม data สำหรับใช้คำนวณ // ถ้า service คืนมาเป็น { code, message, data: [...] } const data = Array.isArray(aryResult) ? aryResult : Array.isArray(aryResult.data) ? aryResult.data : []; // ถ้าไม่มีข้อมูลก็ไม่ต้องคำนวณ if (!data.length) { return aryResult; } // 2) แยก Budget Type const developStudentList = data.filter(i => i.trnbdgcod === '29'); const incomeList = data.filter(i => i.trnbdgcod === '33'); const incomeBachelorList = data.filter(i => i.trnbdgcod === '38'); const budgetCollegeList = data.filter(i => i.trnbdgcod === '24'); const budgetTeachingList = data.filter(i => i.trnbdgcod === '30'); const shortBudgetList = data.filter(i => i.trnbdgcod === '25'); // const totalIncome = incomeList.reduce((sum, i) => sum + parseFloat(i.actqty || 0), 0); // const totalExpense = expenseList.reduce((sum, e) => sum + parseFloat(e.actqty || 0), 0); // const netProfit = totalIncome - totalExpense; // const profitRate = totalIncome > 0 ? (netProfit / totalIncome) * 100 : 0; // const adjustedProfitRate = profitRate + 1.9; // ✅ 3) แนบ summary (เหมือนที่เราทำไปก่อนหน้า) var summary = { // DEBUG developStudentList: developStudentList, incomeList: incomeList, incomeBachelorList: incomeBachelorList, budgetCollegeList: budgetCollegeList, budgetTeachingList: budgetTeachingList, shortBudgetList: shortBudgetList, // totalIncome: totalIncome.toFixed(2), // totalExpense: totalExpense.toFixed(2), // netProfit: netProfit.toFixed(2), }; // ✅ 3.5) Create actdata table with required fields grouped by actnum var trndata = data.map(row => ({ trnprjnam: row.trnprjnam, trnexpbdg: row.trnexpbdg, trnbdgnam: row.trnbdgnam, // trnbdgcod: row.trnbdgcod, // DEBUG trncomsttnam: row.trncomsttnam, // trncomstt: row.trncomstt, // DEBUG trnacpdtm: row.trnacpdtm })); // // ✅ 4) ดึงสีจาก dtlmst (แนะนำให้เรียกจาก service เพิ่ม) // // ตัวอย่างสมมติ: คุณไป query มาจาก service ก่อนหน้าแล้วได้เป็น object แบบนี้ // // key = ชื่อหมวด (actcatnam หรือ code), value = color // const categoryColorMap = await this.reportService.getCategoryColorMap(database); // // ตัวอย่างที่คาดหวังจาก service: // // { 'ค่าอาหาร': '#FF6384', 'ค่าเดินทาง': '#36A2EB', 'ขายสินค้า': '#4BC0C0', ... } // // ✅ 5) สรุปยอดตามหมวด แล้วคำนวณ % สำหรับ expense // const expenseAgg = {}; // expenseList.forEach(row => { // const key = row.actcat; // หรือใช้รหัส category ถ้ามี เช่น row.actcatcod // const amount = parseFloat(row.actqty || 0); // expenseAgg[key] = (expenseAgg[key] || 0) + amount; // }); // const incomeAgg = {}; // incomeList.forEach(row => { // const key = row.actcat; // const amount = parseFloat(row.actqty || 0); // incomeAgg[key] = (incomeAgg[key] || 0) + amount; // }); // const expensePie = Object.entries(expenseAgg).map(([cat, value]) => { // const percent = totalExpense > 0 ? (value / totalExpense) * 100 : 0; // const color = categoryColorMap[cat] || '#CCCCCC'; // fallback สี default // return { // label: cat, // value: value.toFixed(2), // percent: percent.toFixed(2), // color // }; // }); // const incomePie = Object.entries(incomeAgg).map(([cat, value]) => { // const percent = totalIncome > 0 ? (value / totalIncome) * 100 : 0; // const color = categoryColorMap[cat] || '#CCCCCC'; // return { // label: cat, // value: value.toFixed(2), // percent: percent.toFixed(2), // color // }; // }); // // ✅ 6) แนบข้อมูล pie chart เข้า aryResult // var pie = { // expense: expensePie, // income: incomePie // }; } catch (err) { console.error('calculate summary/pie error:', err); } let arydiy = { trndata, summary, // pie, } return arydiy; } } }