Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,22 @@ class Transaction(db.Model):
category = db.relationship('Category', backref=db.backref('transactions', lazy=True))


class Budget(db.Model):
id = db.Column(db.Integer, primary_key=True)
month = db.Column(db.Integer, nullable=False)
year = db.Column(db.Integer, nullable=False)
amount = db.Column(db.Float, nullable=False, default=0)

__table_args__ = (db.UniqueConstraint('month', 'year', name='_month_year_uc'),)


# Create database and tables if they don't exist
with app.app_context():
db.create_all()
if not os.path.exists(DATABASE_PATH):
db.create_all()
print("Database created successfully!")
else:
print("Database tables updated successfully!")


# Home Page (Redirect to Summary)
Expand All @@ -53,9 +64,31 @@ def index():
# Summary Page
@app.route('/summary')
def summary():
now = datetime.now()
current_month = now.month
current_year = now.year

total_income = db.session.query(db.func.sum(Transaction.amount)).filter_by(type="income").scalar() or 0
total_expense = db.session.query(db.func.sum(Transaction.amount)).filter_by(type="expense").scalar() or 0

monthly_expense = db.session.query(db.func.sum(Transaction.amount)).filter(
Transaction.type == "expense",
db.func.strftime('%m', Transaction.date) == f'{current_month:02d}',
db.func.strftime('%Y', Transaction.date) == str(current_year)
).scalar() or 0

budget = Budget.query.filter_by(month=current_month, year=current_year).first()
budget_amount = budget.amount if budget else 0

budget_percentage = 0
budget_status = 'normal'
if budget_amount > 0:
budget_percentage = (monthly_expense / budget_amount) * 100
if budget_percentage >= 100:
budget_status = 'danger'
elif budget_percentage >= 80:
budget_status = 'warning'

income_summary = db.session.query(Category.name, db.func.sum(Transaction.amount), Category.chart_color) \
.join(Transaction).filter(Transaction.type == "income") \
.group_by(Category.name, Category.chart_color).all()
Expand All @@ -72,9 +105,35 @@ def summary():
total_expense=total_expense,
income_summary=income_summary,
expense_summary=expense_summary,
categories=categories
categories=categories,
monthly_expense=monthly_expense,
budget_amount=budget_amount,
budget_percentage=min(budget_percentage, 100),
budget_status=budget_status,
current_month=calendar.month_name[current_month],
current_year=current_year
)


# Set Budget
@app.route('/set_budget', methods=['POST'])
def set_budget():
now = datetime.now()
current_month = now.month
current_year = now.year
amount = float(request.form.get('budget_amount', 0))

budget = Budget.query.filter_by(month=current_month, year=current_year).first()
if budget:
budget.amount = amount
else:
budget = Budget(month=current_month, year=current_year, amount=amount)
db.session.add(budget)

db.session.commit()
flash("Budget updated successfully!", "success")
return redirect(url_for('summary'))

@app.route('/analytics-data')
def analytics_data():
import calendar
Expand Down
Binary file modified finance.db
Binary file not shown.
60 changes: 60 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,61 @@ <h1 class="text-3xl font-bold my-5 text-center">Summary</h1>
<h3>Remaining Balance: <span class="text-blue-400">${{ total_income - total_expense }}</span></h3>
</div>

<!-- Budget Section -->
<div class="max-w-4xl mx-auto bg-gray-900 p-6 rounded-lg shadow-lg mb-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold text-white">{{ current_month }} {{ current_year }} Budget</h3>
<button onclick="toggleBudgetForm()" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg transition text-sm">
{% if budget_amount > 0 %}Edit Budget{% else %}Set Budget{% endif %}
</button>
</div>

{% if budget_amount > 0 %}
<div class="mb-4">
<div class="flex justify-between text-sm mb-2">
<span class="text-gray-300">Spent: ${{ "%.2f"|format(monthly_expense) }} / ${{ "%.2f"|format(budget_amount) }}</span>
<span class="text-gray-300">{{ "%.1f"|format(budget_percentage) }}%</span>
</div>
<div class="w-full bg-gray-700 rounded-full h-6 overflow-hidden">
<div class="h-full rounded-full transition-all duration-500 flex items-center justify-end pr-2"
style="width: {{ budget_percentage }}%;
background-color: {% if budget_status == 'danger' %}#ef4444{% elif budget_status == 'warning' %}#eab308{% else %}#22c55e{% endif %}">
{% if budget_percentage >= 10 %}
<span class="text-xs font-bold text-white">{{ "%.0f"|format(budget_percentage) }}%</span>
{% endif %}
</div>
</div>
{% if budget_status == 'danger' %}
<p class="text-red-400 text-sm mt-2 font-semibold">⚠️ Budget exceeded! You've spent over 100% of your budget.</p>
{% elif budget_status == 'warning' %}
<p class="text-yellow-400 text-sm mt-2 font-semibold">⚠️ Warning: You've spent over 80% of your budget.</p>
{% endif %}
</div>
{% else %}
<p class="text-gray-400 text-center">No budget set for this month. Click "Set Budget" to create one.</p>
{% endif %}
</div>

<!-- Budget Form Modal -->
<div id="budget-form" class="hidden fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
<div class="bg-gray-800 p-6 rounded-lg shadow-xl w-96 text-center">
<h3 class="text-blue-400 text-lg font-bold mb-4">
{% if budget_amount > 0 %}Edit{% else %}Set{% endif %} {{ current_month }} Budget
</h3>
<form action="{{ url_for('set_budget') }}" method="POST" class="space-y-4">
<label class="block text-white">Monthly Budget Amount:</label>
<input type="number" name="budget_amount" step="0.01" min="0" required
value="{{ "%.2f"|format(budget_amount) if budget_amount > 0 else '' }}"
placeholder="Enter budget amount"
class="w-full p-2 rounded-lg bg-gray-700 text-white border border-gray-600 focus:border-blue-400 focus:outline-none">
<div class="flex justify-between mt-4">
<button type="submit" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded-lg">Save</button>
<button type="button" onclick="toggleBudgetForm()" class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded-lg">Cancel</button>
</div>
</form>
</div>
</div>

<!-- Centered Add Transaction Button -->
<div class="text-center mb-6">
<button onclick="toggleTransactionForm()" class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded-lg shadow-md transition">Add New Transaction</button>
Expand Down Expand Up @@ -106,6 +161,11 @@ <h3 class="text-blue-400 text-lg font-bold mb-4">Add Transaction</h3>
const form = document.getElementById("transaction-form");
form.classList.toggle("hidden");
}

function toggleBudgetForm() {
const form = document.getElementById("budget-form");
form.classList.toggle("hidden");
}
</script>

{% endblock %}