All checks were successful
- Fix platform-grouped merchant sidebar menu with core items at root level - Add merchant store management (detail page, create store, team page) - Fix store settings 500 error by removing dead stripe/API tab - Move onboarding translations to module-owned locale files - Fix onboarding banner i18n with server-side rendering + context inheritance - Refactor login language selectors to use languageSelector() function (LANG-002) - Move HTTPException handling to global exception handler in merchant routes (API-003) - Add language selector to all login pages and portal headers - Fix customer module: drop order stats from customer model, add to orders module - Fix admin menu config visibility for super admin platform context - Fix storefront auth and layout issues - Add missing i18n translations for onboarding steps (en/fr/de/lb) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
91 lines
2.6 KiB
Python
91 lines
2.6 KiB
Python
# app/modules/customers/schemas/context.py
|
|
"""
|
|
Customer context schema for dependency injection in storefront routes.
|
|
|
|
This schema provides a clean interface for customer data in API routes,
|
|
avoiding direct database model imports in the API layer.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, ConfigDict
|
|
|
|
|
|
class CustomerContext(BaseModel):
|
|
"""
|
|
Customer context for dependency injection in storefront routes.
|
|
|
|
This is a lightweight schema that contains the customer information
|
|
needed by API routes. It's populated from the Customer database model
|
|
in the authentication dependency.
|
|
|
|
Usage:
|
|
@router.get("/profile")
|
|
def get_profile(
|
|
customer: CustomerContext = Depends(get_current_customer_api),
|
|
):
|
|
return {"email": customer.email}
|
|
"""
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
# Core identification
|
|
id: int
|
|
store_id: int
|
|
email: str
|
|
customer_number: str
|
|
|
|
# Profile info
|
|
first_name: str | None = None
|
|
last_name: str | None = None
|
|
phone: str | None = None
|
|
|
|
# Preferences
|
|
marketing_consent: bool = False
|
|
preferred_language: str | None = None
|
|
|
|
# Status
|
|
is_active: bool = True
|
|
|
|
# Timestamps
|
|
created_at: datetime | None = None
|
|
updated_at: datetime | None = None
|
|
|
|
# Password hash (needed for password change endpoint)
|
|
# This is included but should not be exposed in API responses
|
|
hashed_password: str | None = None
|
|
|
|
@property
|
|
def full_name(self) -> str:
|
|
"""Get customer full name."""
|
|
if self.first_name and self.last_name:
|
|
return f"{self.first_name} {self.last_name}"
|
|
return self.email
|
|
|
|
@classmethod
|
|
def from_db_model(cls, customer) -> "CustomerContext":
|
|
"""
|
|
Create CustomerContext from a Customer database model.
|
|
|
|
Args:
|
|
customer: Customer database model instance
|
|
|
|
Returns:
|
|
CustomerContext: Pydantic schema instance
|
|
"""
|
|
return cls(
|
|
id=customer.id,
|
|
store_id=customer.store_id,
|
|
email=customer.email,
|
|
customer_number=customer.customer_number,
|
|
first_name=customer.first_name,
|
|
last_name=customer.last_name,
|
|
phone=customer.phone,
|
|
marketing_consent=customer.marketing_consent,
|
|
preferred_language=customer.preferred_language,
|
|
is_active=customer.is_active,
|
|
created_at=customer.created_at,
|
|
updated_at=customer.updated_at,
|
|
hashed_password=customer.hashed_password,
|
|
)
|