from __future__ import annotations from datetime import date from flask import Blueprint, jsonify, redirect, render_template, request, session, url_for from flask_login import current_user, login_required from ..extensions import db from ..forms import PreferencesForm, UserCategoryForm from ..models import Category from ..services.analytics import ( compare_years, daily_totals, monthly_summary, payment_method_totals, quarterly_totals, range_totals, top_expenses, weekday_totals, yearly_category_totals, yearly_overview, yearly_totals, ) from ..services.audit import log_action from ..services.i18n import translate as _ from ..services.settings import get_bool_setting main_bp = Blueprint('main', __name__) @main_bp.route('/') def index(): if current_user.is_authenticated: return redirect(url_for('main.dashboard')) return redirect(url_for('auth.login')) @main_bp.post('/language') def set_language(): lang = request.form.get('language', 'pl') if lang not in ['pl', 'en']: lang = 'pl' session['language'] = lang if current_user.is_authenticated: current_user.language = lang db.session.commit() return redirect(request.form.get('next') or request.referrer or url_for('main.index')) @main_bp.route('/dashboard') @login_required def dashboard(): today = date.today() year = request.args.get('year', today.year, type=int) month = request.args.get('month', today.month, type=int) expenses, total, category_totals, alerts = monthly_summary(current_user.id, year, month) chart_categories = [{'label': k, 'amount': float(v)} for k, v in category_totals.items()] chart_payments = payment_method_totals(current_user.id, year, month) return render_template('main/dashboard.html', expenses=expenses, total=total, category_totals=category_totals, alerts=alerts, selected_year=year, selected_month=month, chart_categories=chart_categories, chart_payments=chart_payments) @main_bp.route('/statistics') @login_required def statistics(): year = request.args.get('year', date.today().year, type=int) month = request.args.get('month', 0, type=int) start_year = request.args.get('start_year', max(year - 4, 2000), type=int) end_year = request.args.get('end_year', year, type=int) if start_year > end_year: start_year, end_year = end_year, start_year return render_template('main/statistics.html', selected_year=year, selected_month=month, start_year=start_year, end_year=end_year) @main_bp.route('/analytics/data') @login_required def analytics_data(): year = request.args.get('year', date.today().year, type=int) month = request.args.get('month', 0, type=int) month = month or None start_year = request.args.get('start_year', max(year - 4, 2000), type=int) end_year = request.args.get('end_year', year, type=int) if start_year > end_year: start_year, end_year = end_year, start_year return jsonify({ 'yearly_totals': yearly_totals(current_user.id, year, month), 'daily_totals': daily_totals(current_user.id, year, month), 'category_totals': yearly_category_totals(current_user.id, year, month), 'payment_methods': payment_method_totals(current_user.id, year, month), 'top_expenses': top_expenses(current_user.id, year, month), 'overview': yearly_overview(current_user.id, year, month), 'comparison': compare_years(current_user.id, year, month), 'range_totals': range_totals(current_user.id, start_year, end_year, month), 'quarterly_totals': quarterly_totals(current_user.id, year, month), 'weekday_totals': weekday_totals(current_user.id, year, month), }) @main_bp.route('/preferences', methods=['GET', 'POST']) @login_required def preferences(): form = PreferencesForm(obj=current_user) form.language.choices = [('pl', _('language.polish')), ('en', _('language.english'))] form.theme.choices = [('light', _('theme.light')), ('dark', _('theme.dark'))] form.report_frequency.choices = [('off', _('report.off')), ('daily', _('report.daily')), ('weekly', _('report.weekly')), ('monthly', _('report.monthly'))] category_form = UserCategoryForm(prefix='cat') if request.method == 'POST' and 'language' in request.form and form.validate(): current_user.language = form.language.data current_user.theme = form.theme.data current_user.report_frequency = form.report_frequency.data if get_bool_setting('reports_enabled', True) else 'off' current_user.default_currency = form.default_currency.data db.session.commit() flash = __import__('flask').flash flash(_('flash.settings_saved'), 'success') return redirect(url_for('main.preferences')) if request.method == 'POST' and 'cat-key' in request.form and category_form.validate(): key = f'u{current_user.id}_{category_form.key.data.strip().lower()}' category = Category.query.filter_by(user_id=current_user.id, key=key).first() if not category: category = Category(user_id=current_user.id, key=key, name=category_form.name_en.data.strip(), is_active=True) db.session.add(category) category.name = category_form.name_en.data.strip() category.name_pl = category_form.name_pl.data.strip() category.name_en = category_form.name_en.data.strip() category.color = category_form.color.data db.session.commit() log_action('user_category_saved', 'category', category.id, owner=current_user.id) flash = __import__('flask').flash flash(_('flash.category_saved'), 'success') return redirect(url_for('main.preferences')) my_categories = Category.query.filter_by(user_id=current_user.id).order_by(Category.name_pl).all() report_options_enabled = get_bool_setting('reports_enabled', True) return render_template('main/preferences.html', form=form, category_form=category_form, my_categories=my_categories, report_options_enabled=report_options_enabled)