- New reservations module: model, schema, router (CRUD + status updates + upcoming alerts) and background task for auto-expiring stale reservations - Reports: print_products, print_categories, print_tables analytics endpoints plus meta_products and business_day_summary for workday close/view flow - printer_service: configurable font sizes/weights, donut/bar chart print layout helpers, analytics print blocks per printer - tables/schemas: surfaced color, zone, and other new fields on Table, Product, User, Printer - demo_seed.py for quick dev DB population; wipe_database.py utility Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
1.6 KiB
Python
49 lines
1.6 KiB
Python
"""Background task: auto-mark overdue pending reservations as no_show."""
|
|
import asyncio
|
|
import logging
|
|
from datetime import datetime, timezone, timedelta
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Grace period after reserved_for before a pending reservation becomes no_show
|
|
NO_SHOW_GRACE_MINUTES = 30
|
|
|
|
# How often the checker runs
|
|
CHECK_INTERVAL_SECONDS = 300 # 5 minutes
|
|
|
|
|
|
async def _run_no_show_checker():
|
|
# Import here to avoid circular imports at module load time
|
|
from database import SessionLocal
|
|
from models.reservation import Reservation
|
|
|
|
while True:
|
|
await asyncio.sleep(CHECK_INTERVAL_SECONDS)
|
|
try:
|
|
db = SessionLocal()
|
|
try:
|
|
cutoff = datetime.now(timezone.utc) - timedelta(minutes=NO_SHOW_GRACE_MINUTES)
|
|
overdue = (
|
|
db.query(Reservation)
|
|
.filter(
|
|
Reservation.status == "pending",
|
|
Reservation.reserved_for < cutoff,
|
|
)
|
|
.all()
|
|
)
|
|
if overdue:
|
|
for r in overdue:
|
|
r.status = "no_show"
|
|
r.updated_at = datetime.now(timezone.utc)
|
|
db.commit()
|
|
logger.info("no_show_checker: marked %d reservation(s) as no_show", len(overdue))
|
|
finally:
|
|
db.close()
|
|
except Exception:
|
|
logger.exception("no_show_checker: unexpected error")
|
|
|
|
|
|
async def start_reservation_tasks() -> asyncio.Task:
|
|
task = asyncio.create_task(_run_no_show_checker())
|
|
return task
|