# app/modules/loyalty/routes/pages/merchant.py """ Loyalty Merchant Page Routes (HTML rendering). Merchant portal pages for: - Loyalty program (read-only view) - Loyalty program edit - Loyalty analytics (aggregate stats across all stores) Authentication: merchant_token cookie or Authorization header. Auto-discovered by the route system (merchant.py in routes/pages/ triggers registration under /merchants/loyalty/*). """ import logging from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse from sqlalchemy.orm import Session from app.api.deps import ( get_current_merchant_from_cookie_or_header, get_merchant_for_current_user_page, ) from app.core.database import get_db from app.modules.core.utils.page_context import get_context_for_frontend from app.modules.enums import FrontendType from app.modules.loyalty.services import program_service from app.modules.tenancy.models import Merchant from app.modules.tenancy.schemas.auth import UserContext from app.templates_config import templates logger = logging.getLogger(__name__) ROUTE_CONFIG = { "prefix": "/loyalty", } router = APIRouter() # ============================================================================ # Helper # ============================================================================ def _get_merchant_context( request: Request, db: Session, current_user: UserContext, **extra_context, ) -> dict: """Build template context for merchant loyalty pages.""" return get_context_for_frontend( FrontendType.MERCHANT, request, db, user=current_user, **extra_context, ) # ============================================================================ # LOYALTY PROGRAM (Read-only view) # ============================================================================ @router.get("/program", response_class=HTMLResponse, include_in_schema=False) async def merchant_loyalty_program( request: Request, current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header), merchant: Merchant = Depends(get_merchant_for_current_user_page), db: Session = Depends(get_db), ): """ Render merchant loyalty program view page. Shows read-only program configuration with link to edit. """ merchant_id = merchant.id stats = {} try: stats = program_service.get_merchant_stats(db, merchant_id) except Exception: logger.warning( f"Failed to load loyalty stats for merchant {merchant_id}", exc_info=True, ) context = _get_merchant_context( request, db, current_user, loyalty_stats=stats, merchant_id=merchant_id, ) return templates.TemplateResponse( "loyalty/merchant/program.html", context, ) # ============================================================================ # LOYALTY PROGRAM EDIT # ============================================================================ @router.get("/program/edit", response_class=HTMLResponse, include_in_schema=False) async def merchant_loyalty_program_edit( request: Request, current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header), merchant: Merchant = Depends(get_merchant_for_current_user_page), db: Session = Depends(get_db), ): """ Render merchant loyalty program edit page. Allows merchant to create, configure, and manage their loyalty program. """ context = _get_merchant_context( request, db, current_user, merchant_id=merchant.id, ) return templates.TemplateResponse( "loyalty/merchant/program-edit.html", context, ) # ============================================================================ # LOYALTY ANALYTICS # ============================================================================ @router.get("/analytics", response_class=HTMLResponse, include_in_schema=False) async def merchant_loyalty_analytics( request: Request, current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header), merchant: Merchant = Depends(get_merchant_for_current_user_page), db: Session = Depends(get_db), ): """ Render merchant loyalty analytics page. Shows aggregate loyalty program stats across all merchant stores. """ merchant_id = merchant.id stats = {} try: stats = program_service.get_merchant_stats(db, merchant_id) except Exception: logger.warning( f"Failed to load loyalty stats for merchant {merchant_id}", exc_info=True, ) context = _get_merchant_context( request, db, current_user, loyalty_stats=stats, merchant_id=merchant_id, ) return templates.TemplateResponse( "loyalty/merchant/analytics.html", context, )