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

@@ -5,6 +5,7 @@ Orders module database models.
This module contains the canonical implementations of order-related models.
"""
from app.modules.orders.models.customer_order_stats import CustomerOrderStats
from app.modules.orders.models.invoice import (
Invoice,
InvoiceStatus,
@@ -15,6 +16,7 @@ from app.modules.orders.models.order import Order, OrderItem
from app.modules.orders.models.order_item_exception import OrderItemException
__all__ = [
"CustomerOrderStats",
"Order",
"OrderItem",
"OrderItemException",

View File

@@ -0,0 +1,52 @@
# app/modules/orders/models/customer_order_stats.py
"""
Customer order statistics model.
Tracks per-customer order aggregates (total orders, total spent, etc.)
owned by the orders module. This separates order stats from the
customer profile data owned by the customers module.
"""
from sqlalchemy import Column, DateTime, ForeignKey, Index, Integer, UniqueConstraint
from sqlalchemy.orm import relationship
from app.core.database import Base
from models.database.base import TimestampMixin
class CustomerOrderStats(Base, TimestampMixin):
"""Aggregated order statistics per customer per store."""
__tablename__ = "customer_order_stats"
id = Column(Integer, primary_key=True, index=True)
store_id = Column(
Integer, ForeignKey("stores.id"), nullable=False, index=True
)
customer_id = Column(
Integer, ForeignKey("customers.id"), nullable=False, index=True
)
total_orders = Column(Integer, nullable=False, default=0)
total_spent_cents = Column(Integer, nullable=False, default=0)
last_order_date = Column(DateTime(timezone=True), nullable=True)
first_order_date = Column(DateTime(timezone=True), nullable=True)
# Relationships
store = relationship("Store")
customer = relationship("Customer")
__table_args__ = (
UniqueConstraint(
"store_id", "customer_id", name="uq_customer_order_stats_store_customer"
),
Index("idx_customer_order_stats_customer", "customer_id"),
)
def __repr__(self):
return (
f"<CustomerOrderStats("
f"store_id={self.store_id}, "
f"customer_id={self.customer_id}, "
f"total_orders={self.total_orders}, "
f"total_spent_cents={self.total_spent_cents})>"
)