feat: multi-module improvements across merchant, store, i18n, and customer systems
All checks were successful
CI / ruff (push) Successful in 12s
CI / pytest (push) Successful in 50m57s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Successful in 40s
CI / deploy (push) Successful in 51s

- 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>
This commit is contained in:
2026-03-08 23:48:25 +01:00
parent f141cc4e6a
commit a77a8a3a98
113 changed files with 3741 additions and 2923 deletions

View File

@@ -8,7 +8,6 @@ Handles customer operations for admin users across all stores.
import logging
from typing import Any
from sqlalchemy import func
from sqlalchemy.orm import Session
from app.modules.customers.exceptions import CustomerNotFoundException
@@ -98,9 +97,6 @@ class AdminCustomerService:
"customer_number": customer.customer_number,
"marketing_consent": customer.marketing_consent,
"preferred_language": customer.preferred_language,
"last_order_date": customer.last_order_date,
"total_orders": customer.total_orders,
"total_spent": float(customer.total_spent) if customer.total_spent else 0,
"is_active": customer.is_active,
"created_at": customer.created_at,
"updated_at": customer.updated_at,
@@ -134,25 +130,11 @@ class AdminCustomerService:
total = query.count()
active = query.filter(Customer.is_active == True).count() # noqa: E712
inactive = query.filter(Customer.is_active == False).count() # noqa: E712
with_orders = query.filter(Customer.total_orders > 0).count()
# Total spent across all customers
total_spent_result = query.with_entities(func.sum(Customer.total_spent)).scalar()
total_spent = float(total_spent_result) if total_spent_result else 0
# Average order value
total_orders_result = query.with_entities(func.sum(Customer.total_orders)).scalar()
total_orders = int(total_orders_result) if total_orders_result else 0
avg_order_value = total_spent / total_orders if total_orders > 0 else 0
return {
"total": total,
"active": active,
"inactive": inactive,
"with_orders": with_orders,
"total_spent": total_spent,
"total_orders": total_orders,
"avg_order_value": round(avg_order_value, 2),
}
def get_customer(
@@ -195,9 +177,6 @@ class AdminCustomerService:
"customer_number": customer.customer_number,
"marketing_consent": customer.marketing_consent,
"preferred_language": customer.preferred_language,
"last_order_date": customer.last_order_date,
"total_orders": customer.total_orders,
"total_spent": float(customer.total_spent) if customer.total_spent else 0,
"is_active": customer.is_active,
"created_at": customer.created_at,
"updated_at": customer.updated_at,