feat(local_backend): reservations, print analytics, workday summary, zone-PIN management
- 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>
This commit is contained in:
48
local_backend/services/reservation_tasks.py
Normal file
48
local_backend/services/reservation_tasks.py
Normal file
@@ -0,0 +1,48 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user