Files
xenia-pos-cloud/cloud_backend/main.py
bonamin d87540e08f feat: per-site QR menu mode (order vs view-only) + editable branding
Adds a sysadmin-configurable toggle so sites can disable online ordering
on the public QR menu until it's fully supported, plus editable
tagline/hours and a header image (replacing the hardcoded "Our Menu"
placeholder) — all previously hardcoded frontend strings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 09:59:35 +03:00

93 lines
3.3 KiB
Python

import os
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from config import settings
from database import engine, Base
from auth_utils import hash_password
import models.admin # noqa: F401
import models.site # noqa: F401
import models.menu_snapshot # noqa: F401
import models.online_order # noqa: F401
import models.manager_account # noqa: F401
import models.stats_snapshot # noqa: F401
from routers import auth, sites, heartbeat
from routers import menu as menu_router
from routers import orders as orders_router
from routers import manager_auth as manager_auth_router
from routers import remote_dashboard as remote_dashboard_router
def _seed_default_admin():
from sqlalchemy.orm import Session
from models.admin import Admin
with Session(engine) as db:
if not db.query(Admin).filter(Admin.username == settings.ADMIN_USERNAME).first():
db.add(Admin(
username=settings.ADMIN_USERNAME,
password_hash=hash_password(settings.ADMIN_PASSWORD),
role="sysadmin",
))
db.commit()
def _run_migrations():
"""Apply additive schema changes that create_all won't handle."""
from sqlalchemy import text
migrations = [
# Per-site order counter for public_ref generation (e.g. "ORD-0042")
"ALTER TABLE sites ADD COLUMN order_counter INTEGER NOT NULL DEFAULT 0",
# QR menu branding/config
"ALTER TABLE sites ADD COLUMN menu_mode VARCHAR NOT NULL DEFAULT 'order'",
"ALTER TABLE sites ADD COLUMN menu_tagline_en VARCHAR",
"ALTER TABLE sites ADD COLUMN menu_tagline_gr VARCHAR",
"ALTER TABLE sites ADD COLUMN menu_hours_en VARCHAR",
"ALTER TABLE sites ADD COLUMN menu_hours_gr VARCHAR",
"ALTER TABLE sites ADD COLUMN menu_header_image_url VARCHAR",
]
for sql in migrations:
try:
with engine.connect() as conn:
conn.execute(text(sql))
conn.commit()
except Exception:
pass
@asynccontextmanager
async def lifespan(app: FastAPI):
Base.metadata.create_all(bind=engine)
_run_migrations()
_seed_default_admin()
yield
app = FastAPI(title="POS Cloud Backend", lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(auth.router, prefix="/api/auth", tags=["auth"])
app.include_router(sites.router, prefix="/api/sites", tags=["sites"])
app.include_router(heartbeat.router, prefix="/api/heartbeat", tags=["heartbeat"])
app.include_router(menu_router.router, prefix="/api/menu", tags=["menu"])
app.include_router(orders_router.router, prefix="/api/orders", tags=["orders"])
app.include_router(manager_auth_router.router, prefix="/api/manager", tags=["manager"])
app.include_router(remote_dashboard_router.router,prefix="/api/remote", tags=["remote"])
os.makedirs("/app/data/site_headers", exist_ok=True)
app.mount("/static/site_headers", StaticFiles(directory="/app/data/site_headers"), name="site_headers")
@app.get("/health")
def health():
return {"status": "ok"}