From f259daced076bc11327b77052862dcb7a2c7a3be Mon Sep 17 00:00:00 2001 From: def Date: Sun, 8 Mar 2026 16:42:01 +0000 Subject: [PATCH] Add overdue detection and local time display --- VERSION | 2 +- backend/app.py | 49 ++++++++++++++++++++++++++++++------ templates/dashboard.html | 2 ++ templates/invoices/list.html | 11 ++++---- templates/payments/list.html | 2 +- 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/VERSION b/VERSION index 6e8bf73..17e51c3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0 +0.1.1 diff --git a/backend/app.py b/backend/app.py index aab2a96..048bd9b 100644 --- a/backend/app.py +++ b/backend/app.py @@ -1,6 +1,8 @@ from flask import Flask, render_template, request, redirect from db import get_db_connection from utils import generate_client_code, generate_service_code +from datetime import datetime, timezone +from zoneinfo import ZoneInfo app = Flask( __name__, @@ -8,8 +10,41 @@ app = Flask( static_folder="../static", ) +LOCAL_TZ = ZoneInfo("America/Toronto") + +def fmt_local(dt_value): + if not dt_value: + return "" + if isinstance(dt_value, str): + try: + dt_value = datetime.fromisoformat(dt_value) + except ValueError: + return str(dt_value) + if dt_value.tzinfo is None: + dt_value = dt_value.replace(tzinfo=timezone.utc) + return dt_value.astimezone(LOCAL_TZ).strftime("%Y-%m-%d %I:%M:%S %p") + +def refresh_overdue_invoices(): + conn = get_db_connection() + cursor = conn.cursor() + cursor.execute(""" + UPDATE invoices + SET status = 'overdue' + WHERE due_at IS NOT NULL + AND due_at < UTC_TIMESTAMP() + AND status IN ('pending', 'partial') + """) + conn.commit() + conn.close() + +@app.template_filter("localtime") +def localtime_filter(value): + return fmt_local(value) + @app.route("/") def index(): + refresh_overdue_invoices() + conn = get_db_connection() cursor = conn.cursor(dictionary=True) @@ -51,7 +86,7 @@ def dbtest(): cursor.execute("SELECT NOW()") result = cursor.fetchone() conn.close() - return f"

Database OK

{result[0]}

" + return f"

Database OK

DB server time (UTC): {result[0]}

Displayed local time: {fmt_local(result[0])}

" except Exception as e: return f"

Database FAILED

{e}
" @@ -174,6 +209,8 @@ def new_service(): @app.route("/invoices") def invoices(): + refresh_overdue_invoices() + conn = get_db_connection() cursor = conn.cursor(dictionary=True) cursor.execute(""" @@ -269,7 +306,7 @@ def new_invoice(): status, notes ) - VALUES (%s, %s, %s, %s, %s, %s, NOW(), %s, 'pending', %s) + VALUES (%s, %s, %s, %s, %s, %s, UTC_TIMESTAMP(), %s, 'pending', %s) """, ( client_id, service_id, @@ -354,7 +391,6 @@ def new_payment(): errors.append("CAD value at payment is required.") amount_value = None - cad_value = None if not errors: try: @@ -420,13 +456,10 @@ def new_payment(): if new_amount_paid >= float(invoice["total_amount"]): new_status = "paid" - paid_at_sql = "NOW()" elif new_amount_paid > 0: new_status = "partial" - paid_at_sql = "NULL" else: new_status = "pending" - paid_at_sql = "NULL" insert_cursor = conn.cursor() insert_cursor.execute(""" @@ -446,7 +479,7 @@ def new_payment(): received_at, notes ) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'confirmed', NOW(), %s) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'confirmed', UTC_TIMESTAMP(), %s) """, ( invoice_id, client_id, @@ -467,7 +500,7 @@ def new_payment(): UPDATE invoices SET amount_paid = %s, status = %s, - paid_at = NOW() + paid_at = UTC_TIMESTAMP() WHERE id = %s """, (new_amount_paid, new_status, invoice_id)) else: diff --git a/templates/dashboard.html b/templates/dashboard.html index df249b9..e2b60ef 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -28,5 +28,7 @@ +

Displayed times are shown in America/Toronto.

+ diff --git a/templates/invoices/list.html b/templates/invoices/list.html index cf04fba..a4ad047 100644 --- a/templates/invoices/list.html +++ b/templates/invoices/list.html @@ -12,31 +12,32 @@

Create Invoice

- + + {% for i in invoices %} - + + - - + + - {% endfor %}
ID Invoice Client Currency TotalPaidRemaining Status Issued Due
{{ i.id }} {{ i.invoice_number }} {{ i.client_code }} - {{ i.company_name }} {{ i.currency_code }} {{ i.total_amount }}{{ i.amount_paid }}{{ i.total_amount - i.amount_paid }} {{ i.status }}{{ i.issued_at }}{{ i.due_at }}{{ i.issued_at|localtime }}{{ i.due_at|localtime }}
diff --git a/templates/payments/list.html b/templates/payments/list.html index 0eea42f..7ade56e 100644 --- a/templates/payments/list.html +++ b/templates/payments/list.html @@ -33,7 +33,7 @@ {{ p.payment_amount }} {{ p.cad_value_at_payment }} {{ p.reference }} - {{ p.received_at }} + {{ p.received_at|localtime }} {% endfor %}