feat(merchant): extract merchant portal as first-class frontend with auth, Tailwind fixes, and Gitea CI
Some checks failed
CI / ruff (push) Has been cancelled
CI / pytest (push) Has been cancelled
CI / architecture (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / audit (push) Has been cancelled
CI / docs (push) Has been cancelled

- Extract login/dashboard from billing module into core (matching admin pattern)
- Add merchant auth API with path-isolated cookies (path=/merchants)
- Add merchant base layout with sidebar/header partials and Alpine.js init
- Add frontend detection and login redirect for MERCHANT type
- Wire merchant token in shared api-client.js (get/clear)
- Migrate billing templates to merchant base with dark mode support
- Fix Tailwind: rename shop→storefront in sources and config
- DRY Makefile tailwind targets with TAILWIND_FRONTENDS loop
- Rebuild all Tailwind outputs (production minified)
- Add Gitea Actions CI workflow (ruff, pytest, architecture, docs)
- Add Gitea deployment documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-11 20:25:29 +01:00
parent ecb5309879
commit 0437af67ec
31 changed files with 1925 additions and 780 deletions

View File

@@ -2,9 +2,9 @@
"""
Tenancy module merchant API routes.
Provides merchant-facing API endpoints for the merchant portal:
- /account/stores - List merchant's stores
- /account/profile - Get/update merchant profile
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/).
"""
@@ -21,13 +21,17 @@ from app.core.database import get_db
from app.modules.tenancy.models import Merchant
from models.schema.auth import UserContext
from .merchant_auth import merchant_auth_router
logger = logging.getLogger(__name__)
router = APIRouter()
ROUTE_CONFIG = {
"prefix": "/account",
}
# Include auth routes (/auth/login, /auth/logout, /auth/me)
router.include_router(merchant_auth_router, tags=["merchant-auth"])
# Account routes are defined below with /account prefix
_account_router = APIRouter(prefix="/account")
# ============================================================================
@@ -81,11 +85,11 @@ def _get_user_merchant(db: Session, user_context: UserContext) -> Merchant:
# ============================================================================
# ENDPOINTS
# ACCOUNT ENDPOINTS
# ============================================================================
@router.get("/stores")
@_account_router.get("/stores")
async def merchant_stores(
request: Request,
current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header),
@@ -114,7 +118,7 @@ async def merchant_stores(
return {"stores": stores}
@router.get("/profile")
@_account_router.get("/profile")
async def merchant_profile(
request: Request,
current_user: UserContext = Depends(get_current_merchant_from_cookie_or_header),
@@ -140,7 +144,7 @@ async def merchant_profile(
}
@router.put("/profile")
@_account_router.put("/profile")
async def update_merchant_profile(
request: Request,
profile_data: MerchantProfileUpdate,
@@ -177,3 +181,7 @@ async def update_merchant_profile(
"tax_number": merchant.tax_number,
"is_verified": merchant.is_verified,
}
# Include account routes in main router
router.include_router(_account_router, tags=["merchant-account"])