import { AccountingSumService } from '../services/accountingSumService.js' import { sendError } from '../utils/response.js' import { GeneralService } from '../share/generalservice.js'; import { trim_all_array } from '../utils/trim.js' import { verifyToken, generateToken } from '../utils/token.js' export class accountingSum { constructor() { this.generalService = new GeneralService(); this.accountingSumService = new AccountingSumService(); } async onNavigate(req, res) { this.generalService.devhint(1, 'AccountingSum.js', 'onNavigate() start'); let organization = req.body.organization; const prommis = await this.onAccountingSum(req, res, organization); return prommis; } async onAccountingSum(req, res, database) { let idx = -1 let result = [] var aryResult try { let token = req.body.request.token; const decoded = verifyToken(token); let id = decoded.id let username = decoded.name database = decoded.organization result = await this.accountingSumService.getAccountingSum(database, id); // เช็คกับ db กลาง ส่ง jwttoken ออกมา // if(result){ // if(result.acttyp == 'e'){ // // (ยังไม่มีการใช้งาน) // } // } } catch (error) { idx = 1; } finally { if (idx === 1) return sendError('เกิดข้อผิดพลาดไม่คาดคิดเกิดขึ้น', 'Unexpected error'); if (!result) return sendError('ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง', 'Invalid credentials'); try { // ✅ 1) เตรียม data สำหรับใช้คำนวณ // ถ้า service คืนมาเป็น { code, message, data: [...] } const data = Array.isArray(result) ? result : Array.isArray(result.data) ? result.data : []; // ถ้าไม่มีข้อมูลก็ไม่ต้องคำนวณ if (!data.length) { return result; } // ✅ 2) แยก income / expense const incomeList = data.filter(i => i.acttyp === 'i'); const expenseList = data.filter(e => e.acttyp === 'e'); 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 = { totalIncome: totalIncome.toFixed(2), totalExpense: totalExpense.toFixed(2), netProfit: netProfit.toFixed(2), profitRate: profitRate.toFixed(2) + ' %', adjustedProfitRate: adjustedProfitRate.toFixed(2) + ' %', period: '30 วัน' }; // ✅ 4) ดึงสีจาก dtlmst (แนะนำให้เรียกจาก service เพิ่ม) // ตัวอย่างสมมติ: คุณไป query มาจาก service ก่อนหน้าแล้วได้เป็น object แบบนี้ // key = ชื่อหมวด (actcatnam หรือ code), value = color const categoryColorMap = await this.accountingSumService.getCategoryColorMap(database); // ตัวอย่างที่คาดหวังจาก service: // { 'ค่าอาหาร': '#FF6384', 'ค่าเดินทาง': '#36A2EB', 'ขายสินค้า': '#4BC0C0', ... } // ✅ 5) สรุปยอดตามหมวด แล้วคำนวณ % สำหรับ expense const expenseAgg = {}; expenseList.forEach(row => { const key = row.actcatnam; // หรือใช้รหัส category ถ้ามี เช่น row.actcatcod const amount = parseFloat(row.actqty || 0); expenseAgg[key] = (expenseAgg[key] || 0) + amount; }); const incomeAgg = {}; incomeList.forEach(row => { const key = row.actcatnam; 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 เข้า result var pie = { expense: expensePie, income: incomePie }; } catch (err) { console.error('calculate summary/pie error:', err); } let arydiy = { summary, pie } return arydiy; } } }