The Reports feature transforms your transaction data into actionable insights through interactive charts, spending breakdowns, and exportable reports. Analyze your financial habits across different time periods and wallets.
# From app/routes/report.py:72-76cat_query = query.filter(Transaction.type == db_type)category_stats = cat_query.with_entities( Category.name, func.sum(Transaction.amount)).outerjoin(Category, Transaction.category_id == Category.id) .group_by(Category.name).all()pie_labels = [item[0] if item[0] else "Chưa phân loại" for item in category_stats]pie_data = [float(item[1]) for item in category_stats]
# From app/routes/report.py:102-108# Group by daydaily_data = {}for t in transactions_for_line: day_str = t.date.strftime('%d/%m') daily_data[day_str] = daily_data.get(day_str, 0) + float(t.amount)line_chart_data["labels"] = list(daily_data.keys())line_chart_data["data"] = list(daily_data.values())
# From app/routes/report.py:94-100# Group by monthmonthly_data = {m: 0 for m in range(1, 13)}for t in transactions_for_line: monthly_data[t.date.month] += float(t.amount)line_chart_data["labels"] = [f"Tháng {m}" for m in range(1, 13)]line_chart_data["data"] = [monthly_data[m] for m in range(1, 13)]
The dashboard includes AI-generated financial insights:
GET /api/dashboard-insights
This feature uses the chatbot engine to generate personalized advice:
# From app/routes/ai.py:168-225transactions = Transaction.query.filter( Transaction.user_id == user_id, Transaction.date >= first_day).all()total_income = sum(t.amount for t in transactions if t.type == 'thu')total_expense = sum(t.amount for t in transactions if t.type == 'chi')context_text = f"Thống kê tháng này - Thu nhập: {int(total_income):,} VND. Chi tiêu: {int(total_expense):,} VND."question = ( "Dựa vào số liệu trên, hãy đưa ra 3 lời khuyên tài chính. " "YÊU CẦU NGHIÊM NGẶT ĐỂ ĐỊNH DẠNG: " "1. TUYỆT ĐỐI KHÔNG chào hỏi, KHÔNG xưng hô. " "2. TUYỆT ĐỐI KHÔNG có câu dẫn dắt. " "3. Trả về ĐÚNG 3 dòng, mỗi dòng là một lời khuyên trực tiếp. " "4. Độ dài tối đa: Dưới 15 chữ cho MỖI dòng. " "5. Không dùng markdown, không dùng icon.")
Response:
{ "status": "success", "data": [ "Chi tiêu đang vượt 36% so với thu nhập", "Nên cắt giảm ăn uống xuống 2.5 triệu", "Cố gắng tiết kiệm ít nhất 20% thu nhập" ]}
The AI prompt is heavily constrained to return exactly 3 short, actionable tips in a consistent format for dashboard display.
# From app/routes/ai.py:171-177user_setting = UserSetting.query.get(user_id)if user_setting and user_setting.ai_suggestions == 0: return jsonify({ 'status': 'disabled', 'message': 'Tính năng AI đang bị tắt.' })
# From app/routes/report.py:78-83# Groups all transaction types in ONE query instead of 3 separate queriestype_stats = query.with_entities( Transaction.type, func.sum(Transaction.amount)).group_by(Transaction.type).all()