refactor: migrate vendor auth, profile, team, dashboard, settings to modules
Tenancy module (identity & organizational hierarchy): - vendor_auth.py: login, logout, /me endpoints - vendor_profile.py: vendor profile get/update - vendor_team.py: team management, roles, permissions, invitations Core module (foundational non-domain features): - vendor_dashboard.py: dashboard statistics - vendor_settings.py: localization, business info, letzshop settings All routes auto-discovered via is_self_contained=True. Deleted 5 legacy files from app/api/v1/vendor/. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
21
app/api/v1/vendor/__init__.py
vendored
21
app/api/v1/vendor/__init__.py
vendored
@@ -24,23 +24,18 @@ Self-contained modules (auto-discovered from app/modules/{module}/routes/api/ven
|
||||
- cms: Content pages management
|
||||
- customers: Customer management
|
||||
- payments: Payment configuration, Stripe connect, transactions
|
||||
- tenancy: Public vendor info lookup
|
||||
- tenancy: Vendor info, auth, profile, team management
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
# Import all sub-routers (legacy routes that haven't been migrated to modules)
|
||||
from . import (
|
||||
auth,
|
||||
dashboard,
|
||||
email_settings,
|
||||
email_templates,
|
||||
media,
|
||||
messages,
|
||||
notifications,
|
||||
profile,
|
||||
settings,
|
||||
team,
|
||||
)
|
||||
|
||||
# Create vendor router
|
||||
@@ -51,18 +46,14 @@ router = APIRouter()
|
||||
# ============================================================================
|
||||
# These routes return JSON and are mounted at /api/v1/vendor/*
|
||||
|
||||
# Authentication (no prefix, specific routes like /auth/login)
|
||||
router.include_router(auth.router, tags=["vendor-auth"])
|
||||
|
||||
# Vendor management (with prefixes: /dashboard/*, /profile/*, /settings/*)
|
||||
router.include_router(dashboard.router, tags=["vendor-dashboard"])
|
||||
router.include_router(profile.router, tags=["vendor-profile"])
|
||||
router.include_router(settings.router, tags=["vendor-settings"])
|
||||
# Email configuration
|
||||
router.include_router(email_templates.router, tags=["vendor-email-templates"])
|
||||
router.include_router(email_settings.router, tags=["vendor-email-settings"])
|
||||
|
||||
# Business operations (with prefixes: /team/*)
|
||||
router.include_router(team.router, tags=["vendor-team"])
|
||||
# Services (with prefixes: /media/*, etc.)
|
||||
router.include_router(media.router, tags=["vendor-media"])
|
||||
router.include_router(notifications.router, tags=["vendor-notifications"])
|
||||
router.include_router(messages.router, tags=["vendor-messages"])
|
||||
|
||||
# Services (with prefixes: /media/*, etc.)
|
||||
router.include_router(media.router, tags=["vendor-media"])
|
||||
|
||||
@@ -15,6 +15,7 @@ core_module = ModuleDefinition(
|
||||
description="Dashboard, settings, and profile management. Required for basic operation.",
|
||||
version="1.0.0",
|
||||
is_core=True,
|
||||
is_self_contained=True,
|
||||
features=[
|
||||
"dashboard",
|
||||
"settings",
|
||||
|
||||
4
app/modules/core/routes/__init__.py
Normal file
4
app/modules/core/routes/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# app/modules/core/routes/__init__.py
|
||||
"""
|
||||
Core module route registration.
|
||||
"""
|
||||
12
app/modules/core/routes/api/__init__.py
Normal file
12
app/modules/core/routes/api/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# app/modules/core/routes/api/__init__.py
|
||||
"""
|
||||
Core module API routes.
|
||||
|
||||
Vendor routes:
|
||||
- /dashboard/* - Dashboard statistics
|
||||
- /settings/* - Vendor settings management
|
||||
"""
|
||||
|
||||
from .vendor import vendor_router
|
||||
|
||||
__all__ = ["vendor_router"]
|
||||
19
app/modules/core/routes/api/vendor.py
Normal file
19
app/modules/core/routes/api/vendor.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# app/modules/core/routes/api/vendor.py
|
||||
"""
|
||||
Core module vendor API routes.
|
||||
|
||||
Aggregates:
|
||||
- /dashboard/* - Dashboard statistics
|
||||
- /settings/* - Vendor settings management
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from .vendor_dashboard import vendor_dashboard_router
|
||||
from .vendor_settings import vendor_settings_router
|
||||
|
||||
vendor_router = APIRouter()
|
||||
|
||||
# Aggregate sub-routers
|
||||
vendor_router.include_router(vendor_dashboard_router, tags=["vendor-dashboard"])
|
||||
vendor_router.include_router(vendor_settings_router, tags=["vendor-settings"])
|
||||
@@ -1,4 +1,4 @@
|
||||
# app/api/v1/vendor/dashboard.py
|
||||
# app/modules/core/routes/api/vendor_dashboard.py
|
||||
"""
|
||||
Vendor dashboard and statistics endpoints.
|
||||
|
||||
@@ -26,11 +26,11 @@ from app.modules.analytics.schemas import (
|
||||
VendorRevenueStats,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/dashboard")
|
||||
vendor_dashboard_router = APIRouter(prefix="/dashboard")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@router.get("/stats", response_model=VendorDashboardStatsResponse)
|
||||
@vendor_dashboard_router.get("/stats", response_model=VendorDashboardStatsResponse)
|
||||
def get_vendor_dashboard_stats(
|
||||
request: Request,
|
||||
current_user: UserContext = Depends(get_current_vendor_api),
|
||||
@@ -1,4 +1,4 @@
|
||||
# app/api/v1/vendor/settings.py
|
||||
# app/modules/core/routes/api/vendor_settings.py
|
||||
"""
|
||||
Vendor settings and configuration endpoints.
|
||||
|
||||
@@ -18,7 +18,7 @@ from app.services.platform_settings_service import platform_settings_service
|
||||
from app.services.vendor_service import vendor_service
|
||||
from models.schema.auth import UserContext
|
||||
|
||||
router = APIRouter(prefix="/settings")
|
||||
vendor_settings_router = APIRouter(prefix="/settings")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Supported languages for dropdown
|
||||
@@ -154,7 +154,7 @@ class LetzshopFeedSettingsUpdate(BaseModel):
|
||||
return v
|
||||
|
||||
|
||||
@router.get("")
|
||||
@vendor_settings_router.get("")
|
||||
def get_vendor_settings(
|
||||
current_user: UserContext = Depends(get_current_vendor_api),
|
||||
db: Session = Depends(get_db),
|
||||
@@ -318,7 +318,7 @@ def get_vendor_settings(
|
||||
}
|
||||
|
||||
|
||||
@router.put("/business-info")
|
||||
@vendor_settings_router.put("/business-info")
|
||||
def update_business_info(
|
||||
business_info: BusinessInfoUpdate,
|
||||
current_user: UserContext = Depends(get_current_vendor_api),
|
||||
@@ -360,7 +360,7 @@ def update_business_info(
|
||||
}
|
||||
|
||||
|
||||
@router.put("/letzshop")
|
||||
@vendor_settings_router.put("/letzshop")
|
||||
def update_letzshop_settings(
|
||||
letzshop_config: LetzshopFeedSettingsUpdate,
|
||||
current_user: UserContext = Depends(get_current_vendor_api),
|
||||
@@ -394,7 +394,7 @@ def update_letzshop_settings(
|
||||
}
|
||||
|
||||
|
||||
@router.put("/localization")
|
||||
@vendor_settings_router.put("/localization")
|
||||
def update_localization_settings(
|
||||
localization_config: LocalizationSettingsUpdate,
|
||||
current_user: UserContext = Depends(get_current_vendor_api),
|
||||
@@ -2,10 +2,21 @@
|
||||
"""
|
||||
Tenancy module API routes.
|
||||
|
||||
Includes:
|
||||
Vendor routes:
|
||||
- /info/{vendor_code} - Public vendor info lookup
|
||||
- /auth/* - Vendor authentication (login, logout, /me)
|
||||
- /profile/* - Vendor profile management
|
||||
- /team/* - Team member management, roles, permissions
|
||||
"""
|
||||
|
||||
from .vendor import vendor_router
|
||||
from .vendor_auth import vendor_auth_router
|
||||
from .vendor_profile import vendor_profile_router
|
||||
from .vendor_team import vendor_team_router
|
||||
|
||||
__all__ = ["vendor_router"]
|
||||
__all__ = [
|
||||
"vendor_router",
|
||||
"vendor_auth_router",
|
||||
"vendor_profile_router",
|
||||
"vendor_team_router",
|
||||
]
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
"""
|
||||
Tenancy module vendor API routes.
|
||||
|
||||
Provides public vendor information lookup for:
|
||||
- Vendor login pages to display branding
|
||||
- Public vendor profile lookup
|
||||
Aggregates all vendor tenancy routes:
|
||||
- /info/{vendor_code} - Public vendor info lookup
|
||||
- /auth/* - Vendor authentication (login, logout, /me)
|
||||
- /profile/* - Vendor profile management
|
||||
- /team/* - Team member management, roles, permissions
|
||||
|
||||
These endpoints do NOT require authentication - they provide
|
||||
public information about vendors.
|
||||
The tenancy module owns identity and organizational hierarchy.
|
||||
"""
|
||||
|
||||
import logging
|
||||
@@ -80,3 +81,17 @@ def get_vendor_info(
|
||||
owner_email=vendor.company.owner.email,
|
||||
owner_username=vendor.company.owner.username,
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Aggregate Sub-Routers
|
||||
# ============================================================================
|
||||
# Include all tenancy vendor routes (auth, profile, team)
|
||||
|
||||
from .vendor_auth import vendor_auth_router
|
||||
from .vendor_profile import vendor_profile_router
|
||||
from .vendor_team import vendor_team_router
|
||||
|
||||
vendor_router.include_router(vendor_auth_router, tags=["vendor-auth"])
|
||||
vendor_router.include_router(vendor_profile_router, tags=["vendor-profile"])
|
||||
vendor_router.include_router(vendor_team_router, tags=["vendor-team"])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# app/api/v1/vendor/auth.py
|
||||
# app/modules/tenancy/routes/api/vendor_auth.py
|
||||
"""
|
||||
Vendor team authentication endpoints.
|
||||
|
||||
@@ -27,7 +27,7 @@ from middleware.vendor_context import get_current_vendor
|
||||
from models.schema.auth import UserContext
|
||||
from models.schema.auth import LogoutResponse, UserLogin, VendorUserResponse
|
||||
|
||||
router = APIRouter(prefix="/auth")
|
||||
vendor_auth_router = APIRouter(prefix="/auth")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class VendorLoginResponse(BaseModel):
|
||||
vendor_role: str
|
||||
|
||||
|
||||
@router.post("/login", response_model=VendorLoginResponse)
|
||||
@vendor_auth_router.post("/login", response_model=VendorLoginResponse)
|
||||
def vendor_login(
|
||||
user_credentials: UserLogin,
|
||||
request: Request,
|
||||
@@ -156,7 +156,7 @@ def vendor_login(
|
||||
)
|
||||
|
||||
|
||||
@router.post("/logout", response_model=LogoutResponse)
|
||||
@vendor_auth_router.post("/logout", response_model=LogoutResponse)
|
||||
def vendor_logout(response: Response):
|
||||
"""
|
||||
Vendor team member logout.
|
||||
@@ -177,7 +177,7 @@ def vendor_logout(response: Response):
|
||||
return LogoutResponse(message="Logged out successfully")
|
||||
|
||||
|
||||
@router.get("/me", response_model=VendorUserResponse)
|
||||
@vendor_auth_router.get("/me", response_model=VendorUserResponse)
|
||||
def get_current_vendor_user(
|
||||
user: UserContext = Depends(get_current_vendor_api), db: Session = Depends(get_db)
|
||||
):
|
||||
@@ -1,4 +1,4 @@
|
||||
# app/api/v1/vendor/profile.py
|
||||
# app/modules/tenancy/routes/api/vendor_profile.py
|
||||
"""
|
||||
Vendor profile management endpoints.
|
||||
|
||||
@@ -17,11 +17,11 @@ from app.services.vendor_service import vendor_service
|
||||
from models.schema.auth import UserContext
|
||||
from models.schema.vendor import VendorResponse, VendorUpdate
|
||||
|
||||
router = APIRouter(prefix="/profile")
|
||||
vendor_profile_router = APIRouter(prefix="/profile")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@router.get("", response_model=VendorResponse)
|
||||
@vendor_profile_router.get("", response_model=VendorResponse)
|
||||
def get_vendor_profile(
|
||||
current_user: UserContext = Depends(get_current_vendor_api),
|
||||
db: Session = Depends(get_db),
|
||||
@@ -31,7 +31,7 @@ def get_vendor_profile(
|
||||
return vendor
|
||||
|
||||
|
||||
@router.put("", response_model=VendorResponse)
|
||||
@vendor_profile_router.put("", response_model=VendorResponse)
|
||||
def update_vendor_profile(
|
||||
vendor_update: VendorUpdate,
|
||||
current_user: UserContext = Depends(get_current_vendor_api),
|
||||
@@ -1,4 +1,4 @@
|
||||
# app/api/v1/vendor/teams.py
|
||||
# app/modules/tenancy/routes/api/vendor_team.py
|
||||
"""
|
||||
Vendor team member management endpoints.
|
||||
|
||||
@@ -40,7 +40,7 @@ from models.schema.team import (
|
||||
UserPermissionsResponse,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/team")
|
||||
vendor_team_router = APIRouter(prefix="/team")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ logger = logging.getLogger(__name__)
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/members", response_model=TeamMemberListResponse)
|
||||
@vendor_team_router.get("/members", response_model=TeamMemberListResponse)
|
||||
def list_team_members(
|
||||
request: Request,
|
||||
include_inactive: bool = False,
|
||||
@@ -91,7 +91,7 @@ def list_team_members(
|
||||
)
|
||||
|
||||
|
||||
@router.post("/invite", response_model=InvitationResponse)
|
||||
@vendor_team_router.post("/invite", response_model=InvitationResponse)
|
||||
def invite_team_member(
|
||||
invitation: TeamMemberInvite,
|
||||
request: Request,
|
||||
@@ -165,7 +165,7 @@ def invite_team_member(
|
||||
)
|
||||
|
||||
|
||||
@router.post("/accept-invitation", response_model=InvitationAcceptResponse) # public
|
||||
@vendor_team_router.post("/accept-invitation", response_model=InvitationAcceptResponse) # public
|
||||
def accept_invitation(acceptance: InvitationAccept, db: Session = Depends(get_db)):
|
||||
"""
|
||||
Accept a team invitation and activate account.
|
||||
@@ -215,7 +215,7 @@ def accept_invitation(acceptance: InvitationAccept, db: Session = Depends(get_db
|
||||
)
|
||||
|
||||
|
||||
@router.get("/members/{user_id}", response_model=TeamMemberResponse)
|
||||
@vendor_team_router.get("/members/{user_id}", response_model=TeamMemberResponse)
|
||||
def get_team_member(
|
||||
user_id: int,
|
||||
request: Request,
|
||||
@@ -244,7 +244,7 @@ def get_team_member(
|
||||
return TeamMemberResponse(**member)
|
||||
|
||||
|
||||
@router.put("/members/{user_id}", response_model=TeamMemberResponse)
|
||||
@vendor_team_router.put("/members/{user_id}", response_model=TeamMemberResponse)
|
||||
def update_team_member(
|
||||
user_id: int,
|
||||
update_data: TeamMemberUpdate,
|
||||
@@ -288,7 +288,7 @@ def update_team_member(
|
||||
return TeamMemberResponse(**member)
|
||||
|
||||
|
||||
@router.delete("/members/{user_id}")
|
||||
@vendor_team_router.delete("/members/{user_id}")
|
||||
def remove_team_member(
|
||||
user_id: int,
|
||||
request: Request,
|
||||
@@ -320,7 +320,7 @@ def remove_team_member(
|
||||
return {"message": "Team member removed successfully", "user_id": user_id}
|
||||
|
||||
|
||||
@router.post("/members/bulk-remove", response_model=BulkRemoveResponse)
|
||||
@vendor_team_router.post("/members/bulk-remove", response_model=BulkRemoveResponse)
|
||||
def bulk_remove_team_members(
|
||||
bulk_remove: BulkRemoveRequest,
|
||||
request: Request,
|
||||
@@ -365,7 +365,7 @@ def bulk_remove_team_members(
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/roles", response_model=RoleListResponse)
|
||||
@vendor_team_router.get("/roles", response_model=RoleListResponse)
|
||||
def list_roles(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
@@ -395,7 +395,7 @@ def list_roles(
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/me/permissions", response_model=UserPermissionsResponse)
|
||||
@vendor_team_router.get("/me/permissions", response_model=UserPermissionsResponse)
|
||||
def get_my_permissions(
|
||||
request: Request,
|
||||
permissions: list[str] = Depends(get_user_permissions),
|
||||
@@ -434,7 +434,7 @@ def get_my_permissions(
|
||||
# ============================================================================
|
||||
|
||||
|
||||
@router.get("/statistics", response_model=TeamStatistics)
|
||||
@vendor_team_router.get("/statistics", response_model=TeamStatistics)
|
||||
def get_team_statistics(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
Reference in New Issue
Block a user