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"
{result[0]}
" + return f"DB server time (UTC): {result[0]}
Displayed local time: {fmt_local(result[0])}
" except Exception as e: return f"{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.
+