# app/modules/tenancy/routes/api/merchant.py """ Tenancy module merchant API routes. Aggregates all merchant tenancy routes: - /auth/* - Merchant authentication (login, logout, /me) - /account/* - Merchant account management (stores, profile) Auto-discovered by the route system (merchant.py in routes/api/). """ import logging from fastapi import APIRouter, Depends, Query, Request from sqlalchemy.orm import Session from app.api.deps import get_current_merchant_api, get_merchant_for_current_user from app.core.database import get_db from app.modules.tenancy.schemas import ( MerchantPortalProfileResponse, MerchantPortalProfileUpdate, MerchantPortalStoreListResponse, ) from app.modules.tenancy.schemas.auth import UserContext from app.modules.tenancy.services.merchant_service import merchant_service from .email_verification import email_verification_api_router from .merchant_auth import merchant_auth_router logger = logging.getLogger(__name__) router = APIRouter() # Include auth routes (/auth/login, /auth/logout, /auth/me, /auth/forgot-password, /auth/reset-password) router.include_router(merchant_auth_router, tags=["merchant-auth"]) # Include email verification routes (/resend-verification) router.include_router(email_verification_api_router, tags=["email-verification"]) # Account routes are defined below with /account prefix _account_router = APIRouter(prefix="/account") # ============================================================================ # ACCOUNT ENDPOINTS # ============================================================================ @_account_router.get("/stores", response_model=MerchantPortalStoreListResponse) async def merchant_stores( request: Request, skip: int = Query(0, ge=0, description="Number of records to skip"), limit: int = Query(100, ge=1, le=200, description="Max records to return"), merchant=Depends(get_merchant_for_current_user), db: Session = Depends(get_db), ): """ List all stores belonging to the merchant. Returns a paginated list of store summaries for the authenticated merchant. """ stores, total = merchant_service.get_merchant_stores( db, merchant.id, skip=skip, limit=limit ) return MerchantPortalStoreListResponse( stores=stores, total=total, skip=skip, limit=limit, ) @_account_router.get("/profile", response_model=MerchantPortalProfileResponse) async def merchant_profile( request: Request, merchant=Depends(get_merchant_for_current_user), ): """ Get the authenticated merchant's profile information. Returns merchant details including contact info, business details, and verification status. """ return merchant @_account_router.put("/profile", response_model=MerchantPortalProfileResponse) async def update_merchant_profile( request: Request, profile_data: MerchantPortalProfileUpdate, current_user: UserContext = Depends(get_current_merchant_api), merchant=Depends(get_merchant_for_current_user), db: Session = Depends(get_db), ): """ Update the authenticated merchant's profile information. Accepts partial updates - only provided fields are changed. """ # Apply only the fields that were explicitly provided update_data = profile_data.model_dump(exclude_unset=True) for field_name, value in update_data.items(): setattr(merchant, field_name, value) db.commit() db.refresh(merchant) logger.info( f"Merchant profile updated: merchant_id={merchant.id}, " f"user={current_user.username}, fields={list(update_data.keys())}" ) return merchant # Include account routes in main router router.include_router(_account_router, tags=["merchant-account"])