fix: fix timezone handling across backend and frontend (v0.3.1)
- Add tz.py with local_strftime/to_local helpers that read system.timezone from DB and convert UTC datetimes to venue local time before formatting - Fix all strftime() calls in orders.py, reports.py, printer_service.py that were formatting UTC datetimes without timezone conversion - Fix get_order endpoint returning raw dicts without Z suffix on datetimes, causing JS new Date() to treat timestamps as local instead of UTC - Fix fmtDate() in tokens.js that stripped the T separator before parsing, breaking UTC-to-local conversion for all report date displays - Make open/partially_paid table chips more visually distinct on dashboard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
|
||||
from tz import local_strftime
|
||||
|
||||
|
||||
def _iso(dt) -> str | None:
|
||||
"""Serialize a datetime to ISO 8601 with Z suffix so browsers parse it as UTC."""
|
||||
if dt is None:
|
||||
return None
|
||||
if dt.tzinfo is None:
|
||||
return dt.isoformat() + "Z"
|
||||
return dt.isoformat()
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List, Optional
|
||||
|
||||
@@ -163,11 +173,11 @@ def get_order(order_id: int, db: Session = Depends(get_db), user: User = Depends
|
||||
"removed_ingredients": i.removed_ingredients,
|
||||
"notes": i.notes,
|
||||
"status": i.status,
|
||||
"added_at": i.added_at,
|
||||
"added_at": _iso(i.added_at),
|
||||
"printed": i.printed,
|
||||
"paid_by": i.paid_by,
|
||||
"paid_by_name": name_map.get(i.paid_by) if i.paid_by else None,
|
||||
"paid_at": i.paid_at,
|
||||
"paid_at": _iso(i.paid_at),
|
||||
"payment_method": i.payment_method,
|
||||
"paid_in_shift_id": i.paid_in_shift_id,
|
||||
}
|
||||
@@ -183,8 +193,8 @@ def get_order(order_id: int, db: Session = Depends(get_db), user: User = Depends
|
||||
"amount": l.amount,
|
||||
"payment_method": l.payment_method,
|
||||
"note": l.note,
|
||||
"created_at": l.created_at,
|
||||
"offline_at": l.offline_at,
|
||||
"created_at": _iso(l.created_at),
|
||||
"offline_at": _iso(l.offline_at) if isinstance(l.offline_at, datetime) else l.offline_at,
|
||||
"is_duplicate": l.is_duplicate,
|
||||
}
|
||||
|
||||
@@ -205,9 +215,9 @@ def get_order(order_id: int, db: Session = Depends(get_db), user: User = Depends
|
||||
"table_id": order.table_id,
|
||||
"table_name": table_name,
|
||||
"opened_by": order.opened_by,
|
||||
"opened_at": order.opened_at,
|
||||
"opened_at": _iso(order.opened_at),
|
||||
"status": order.status,
|
||||
"closed_at": order.closed_at,
|
||||
"closed_at": _iso(order.closed_at),
|
||||
"closed_by": order.closed_by,
|
||||
"notes": order.notes,
|
||||
"business_day_id": order.business_day_id,
|
||||
@@ -657,8 +667,8 @@ def print_order(
|
||||
"order_id": order.id,
|
||||
"table_name": table_name,
|
||||
"waiter_name": waiter_name,
|
||||
"opened_at": order.opened_at.strftime("%d/%m/%Y %H:%M"),
|
||||
"closed_at": order.closed_at.strftime("%d/%m/%Y %H:%M") if order.closed_at else None,
|
||||
"opened_at": local_strftime(order.opened_at, "%d/%m/%Y %H:%M"),
|
||||
"closed_at": local_strftime(order.closed_at, "%d/%m/%Y %H:%M") if order.closed_at else None,
|
||||
"status": order.status,
|
||||
"items": items_data,
|
||||
"total": grand_total,
|
||||
@@ -953,7 +963,7 @@ def print_synopsis(
|
||||
"order_id": order.id,
|
||||
"table_name": table_name,
|
||||
"waiter_name": waiter_name,
|
||||
"opened_at": order.opened_at.strftime("%d/%m/%Y %H:%M"),
|
||||
"opened_at": local_strftime(order.opened_at, "%d/%m/%Y %H:%M"),
|
||||
"items": items_data,
|
||||
"total": total,
|
||||
"paid_total": paid_total,
|
||||
|
||||
Reference in New Issue
Block a user