134 lines
5.9 KiB
Python
134 lines
5.9 KiB
Python
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)
|