06/02 Update functionalities

This commit is contained in:
2026-06-02 15:28:31 -04:00
parent c429de7bcd
commit 814ec90581
3 changed files with 62 additions and 7 deletions
+20 -1
View File
@@ -1,10 +1,13 @@
from datetime import date
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
from flask_login import login_required
from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Length, Optional
from sqlalchemy import func, extract
from app.extensions import db
from app.models.account import Account
from app.models.transaction import Transaction
from app.services.account_service import calc_balance
accounts_bp = Blueprint('accounts', __name__, url_prefix='/accounts')
@@ -63,11 +66,27 @@ def index():
credit_accounts = [a for a in all_accounts if a.account_type == 'credit_card']
accounts = credit_accounts if tab == 'credit' else bank_accounts
# Monthly charges per credit card (current month expenses)
today = date.today()
monthly_charges = {}
if credit_accounts:
rows = db.session.query(
Transaction.account_id,
func.sum(Transaction.amount)
).filter(
Transaction.transaction_type == 'expense',
extract('year', Transaction.date) == today.year,
extract('month', Transaction.date) == today.month,
Transaction.account_id.in_([a.id for a in credit_accounts])
).group_by(Transaction.account_id).all()
monthly_charges = {row[0]: float(row[1]) for row in rows}
return render_template('accounts/index.html',
accounts=accounts,
tab=tab,
bank_count=len(bank_accounts),
credit_count=len(credit_accounts))
credit_count=len(credit_accounts),
monthly_charges=monthly_charges)
@accounts_bp.route('/new', methods=['GET', 'POST'])
+8
View File
@@ -241,6 +241,14 @@ def transfer():
form.from_account_id.choices = _account_choices()
form.to_account_id.choices = _account_choices()
if request.method == 'GET':
prefill_to = request.args.get('to_account_id', '')
prefill_desc = request.args.get('description', '')
if prefill_to:
form.to_account_id.data = prefill_to
if prefill_desc:
form.description.data = prefill_desc
if form.validate_on_submit():
if form.from_account_id.data == form.to_account_id.data:
flash('Source and destination accounts must be different.', 'warning')
+34 -6
View File
@@ -27,6 +27,8 @@
{% for acct in accounts %}
<div class="col-12 col-md-6 col-xl-4">
<div class="pcard" style="border-left: 4px solid {{ acct.color }};">
<!-- Header: icon + name + menu -->
<div class="d-flex justify-content-between align-items-start">
<div class="d-flex align-items-center gap-2">
<div style="width:36px;height:36px;border-radius:9px;background:{{ acct.color }}22;color:{{ acct.color }};display:flex;align-items:center;justify-content:center;font-size:18px;">
@@ -52,33 +54,59 @@
</div>
</div>
{% if tab == 'credit' %}
<!-- Amount Owed + Monthly Charges -->
{% set owed = [0, -acct.balance] | max %}
{% set charges = monthly_charges.get(acct.id, 0) %}
<div class="d-flex gap-3 mt-3">
<div style="flex:1;background:#fff5f5;border-radius:8px;padding:10px 12px;">
<div style="font-size:10px;color:#991b1b;font-weight:600;text-transform:uppercase;letter-spacing:.04em;margin-bottom:2px;">Amount Owed</div>
<div class="mono {% if owed > 0 %}text-expense{% else %}" style="color:#10b981;{% endif %}font-size:20px;font-weight:700;">
{% if owed > 0 %}-{% endif %}{{ owed | currency }}
</div>
</div>
<div style="flex:1;background:#fafafa;border-radius:8px;padding:10px 12px;">
<div style="font-size:10px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.04em;margin-bottom:2px;">This Month</div>
<div class="mono text-expense" style="font-size:20px;font-weight:700;">
{% if charges > 0 %}-{% endif %}{{ charges | currency }}
</div>
</div>
</div>
{% endif %}
{% if acct.notes %}
<div style="font-size:12px;color:var(--muted);margin-top:10px;">{{ acct.notes }}</div>
{% endif %}
<!-- Action buttons -->
{% if tab == 'credit' %}
<div class="d-flex gap-2 mt-3">
<a href="{{ url_for('transactions.transfer', to_account_id=acct.id, description='Credit Card Payment — ' ~ acct.name) }}"
class="btn btn-sm flex-fill btn-danger" style="font-size:12px;">
<i class="bi bi-send me-1"></i>Pay Card
</a>
<a href="{{ url_for('transactions.index', tab='expense', account_id=acct.id) }}"
class="btn btn-sm flex-fill" style="font-size:11px;background:#fee2e2;color:#991b1b;border:none;">
<i class="bi bi-arrow-up-circle me-1"></i>Charges
class="btn btn-sm flex-fill btn-outline-secondary" style="font-size:12px;">
<i class="bi bi-list-ul me-1"></i>Charges
</a>
<a href="{{ url_for('transactions.new', type='expense') }}"
class="btn btn-sm flex-fill" style="font-size:11px;background:#f1f5f9;color:#475569;border:none;">
<i class="bi bi-plus-lg me-1"></i>Add Charge
class="btn btn-sm" style="font-size:12px;background:#f1f5f9;color:#475569;border:none;" title="Add Charge">
<i class="bi bi-plus-lg"></i>
</a>
</div>
{% else %}
<div class="d-flex gap-2 mt-3">
<a href="{{ url_for('transactions.index', tab='expense', account_id=acct.id) }}"
class="btn btn-sm flex-fill" style="font-size:11px;background:#f1f5f9;color:#475569;border:none;">
class="btn btn-sm flex-fill btn-outline-secondary" style="font-size:12px;">
<i class="bi bi-list-ul me-1"></i>Transactions
</a>
<a href="{{ url_for('transactions.new', type='income') }}"
class="btn btn-sm flex-fill" style="font-size:11px;background:#d1fae5;color:#065f46;border:none;">
class="btn btn-sm flex-fill" style="font-size:12px;background:#d1fae5;color:#065f46;border:none;">
<i class="bi bi-plus-lg me-1"></i>Add Income
</a>
</div>
{% endif %}
</div>
</div>
{% endfor %}