06/02 Update functionalities
This commit is contained in:
+20
-1
@@ -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'])
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
Reference in New Issue
Block a user