TorbatYar/backend/services/hospitality/app/api/v1/qr.py
Mortezakoohjani 5c6a2e78cf feat(platform): seed service registry, deploy all modules, and fix homepage catalog.
Register all active platform services and base features in core DB so admin can manage them, add delivery/hospitality/sports-center backend phases, update apps catalog and production deploy tooling.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 12:39:51 +03:30

208 lines
7.3 KiB
Python

"""QR Menu & QR Ordering APIs — Phase 12.2."""
from __future__ import annotations
from uuid import UUID
from fastapi import APIRouter, Depends, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.deps import get_db, get_pagination, require_tenant
from app.core.security import get_current_user
from app.schemas.qr import (
CartCreate,
CartLineCreate,
CartLineRead,
CartRead,
QrCodeCreate,
QrCodeRead,
QrMenuSessionCreate,
QrMenuSessionRead,
QrOrderingSessionCreate,
QrOrderingSessionRead,
)
from app.services.qr import (
CartLineService,
CartService,
QrCodeService,
QrMenuSessionService,
QrOrderingSessionService,
)
from shared.pagination import PaginationParams
from shared.security import CurrentUser
qr_codes_router = APIRouter()
qr_menu_sessions_router = APIRouter()
qr_ordering_sessions_router = APIRouter()
carts_router = APIRouter()
cart_lines_router = APIRouter()
@qr_codes_router.post("", response_model=QrCodeRead, status_code=status.HTTP_201_CREATED)
async def create_qr_code(
body: QrCodeCreate,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await QrCodeService(db).create(tenant_id, body, actor=user)
@qr_codes_router.get("", response_model=list[QrCodeRead])
async def list_qr_codes(
tenant_id: UUID = Depends(require_tenant),
pagination: PaginationParams = Depends(get_pagination),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await QrCodeService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)
@qr_codes_router.get("/by-token/{token}", response_model=QrCodeRead)
async def get_qr_code_by_token(
token: str,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await QrCodeService(db).get_by_token(tenant_id, token)
@qr_codes_router.get("/{qr_code_id}", response_model=QrCodeRead)
async def get_qr_code(
qr_code_id: UUID,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await QrCodeService(db).get(tenant_id, qr_code_id)
@qr_menu_sessions_router.post("", response_model=QrMenuSessionRead, status_code=status.HTTP_201_CREATED)
async def create_qr_menu_session(
body: QrMenuSessionCreate,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await QrMenuSessionService(db).create(tenant_id, body, actor=user)
@qr_menu_sessions_router.get("", response_model=list[QrMenuSessionRead])
async def list_qr_menu_sessions(
tenant_id: UUID = Depends(require_tenant),
pagination: PaginationParams = Depends(get_pagination),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await QrMenuSessionService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)
@qr_menu_sessions_router.get("/by-token/{token}", response_model=QrMenuSessionRead)
async def get_qr_menu_session_by_token(
token: str,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await QrMenuSessionService(db).get_by_token(tenant_id, token)
@qr_menu_sessions_router.get("/{session_id}", response_model=QrMenuSessionRead)
async def get_qr_menu_session(
session_id: UUID,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await QrMenuSessionService(db).get(tenant_id, session_id)
@qr_ordering_sessions_router.post("", response_model=QrOrderingSessionRead, status_code=status.HTTP_201_CREATED)
async def create_qr_ordering_session(
body: QrOrderingSessionCreate,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await QrOrderingSessionService(db).create(tenant_id, body, actor=user)
@qr_ordering_sessions_router.get("", response_model=list[QrOrderingSessionRead])
async def list_qr_ordering_sessions(
tenant_id: UUID = Depends(require_tenant),
pagination: PaginationParams = Depends(get_pagination),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await QrOrderingSessionService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)
@qr_ordering_sessions_router.get("/{session_id}", response_model=QrOrderingSessionRead)
async def get_qr_ordering_session(
session_id: UUID,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await QrOrderingSessionService(db).get(tenant_id, session_id)
@qr_ordering_sessions_router.post("/{session_id}/submit", response_model=QrOrderingSessionRead)
async def submit_qr_ordering_session(
session_id: UUID,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await QrOrderingSessionService(db).submit(tenant_id, session_id, actor=user)
@carts_router.post("", response_model=CartRead, status_code=status.HTTP_201_CREATED)
async def create_cart(
body: CartCreate,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await CartService(db).create(tenant_id, body, actor=user)
@carts_router.get("", response_model=list[CartRead])
async def list_carts(
tenant_id: UUID = Depends(require_tenant),
pagination: PaginationParams = Depends(get_pagination),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await CartService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)
@carts_router.get("/{cart_id}", response_model=CartRead)
async def get_cart(
cart_id: UUID,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await CartService(db).get(tenant_id, cart_id)
@cart_lines_router.post("", response_model=CartLineRead, status_code=status.HTTP_201_CREATED)
async def create_cart_line(
body: CartLineCreate,
tenant_id: UUID = Depends(require_tenant),
db: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await CartLineService(db).add(tenant_id, body, actor=user)
@cart_lines_router.get("", response_model=list[CartLineRead])
async def list_cart_lines(
tenant_id: UUID = Depends(require_tenant),
pagination: PaginationParams = Depends(get_pagination),
db: AsyncSession = Depends(get_db),
_user: CurrentUser = Depends(get_current_user),
):
return await CartLineService(db).list(tenant_id, offset=pagination.offset, limit=pagination.page_size)