05/31 Phase 1: initial codes

This commit is contained in:
2026-05-31 10:03:28 -04:00
parent b0a5ce5399
commit b0c0bd363b
35 changed files with 2871 additions and 164 deletions
View File
+13
View File
@@ -0,0 +1,13 @@
from functools import wraps
from flask import redirect, url_for
from flask_login import current_user
def login_required_custom(f):
"""Redundant wrapper — Flask-Login handles this, but kept for explicitness."""
@wraps(f)
def decorated(*args, **kwargs):
if not current_user.is_authenticated:
return redirect(url_for('auth.login'))
return f(*args, **kwargs)
return decorated
+47
View File
@@ -0,0 +1,47 @@
from flask import current_app
from flask_login import current_user
def format_currency(amount, symbol=None, show_sign=False):
"""Format a number as currency using the app's configured symbol."""
if amount is None:
return ''
try:
amount = float(amount)
except (TypeError, ValueError):
return ''
if symbol is None:
try:
symbol = current_user.currency_symbol if current_user.is_authenticated \
else current_app.config.get('APP_CURRENCY_SYMBOL', '$')
except Exception:
symbol = '$'
formatted = f"{symbol}{abs(amount):,.2f}"
if show_sign:
if amount < 0:
formatted = f"-{formatted}"
elif amount > 0:
formatted = f"+{formatted}"
elif amount < 0:
formatted = f"-{formatted}"
return formatted
def format_percent(value, decimals=1):
if value is None:
return ''
return f"{float(value):.{decimals}f}%"
def format_large_number(value):
"""Abbreviate large numbers: 1,500,000 → 1.5M"""
if value is None:
return ''
value = float(value)
if abs(value) >= 1_000_000:
return f"{value / 1_000_000:.1f}M"
if abs(value) >= 1_000:
return f"{value / 1_000:.1f}K"
return f"{value:.2f}"