chore: add module exceptions, locales, and fix architecture warnings

- Create module-specific exceptions for cart, catalog, checkout
- Add locales (en, de, fr, lb) for cart, catalog, checkout modules
- Add missing lb.json for existing module locales
- Add noqa comments for legitimate MOD-004 violations (core services)
- Fix validator to use correct lb.json locale code (was lu.json)
- Add noqa support for MOD-004 rule in validator

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 21:26:13 +01:00
parent cad862f469
commit 434db1560a
28 changed files with 1032 additions and 7 deletions

View File

@@ -0,0 +1,131 @@
# app/modules/catalog/exceptions.py
"""
Catalog module exceptions.
Module-specific exceptions for product catalog operations.
"""
from app.exceptions.base import (
BusinessLogicException,
ConflictException,
ResourceNotFoundException,
ValidationException,
)
class ProductNotFoundException(ResourceNotFoundException):
"""Raised when a product is not found in vendor catalog."""
def __init__(self, product_id: int, vendor_id: int | None = None):
if vendor_id:
message = f"Product with ID '{product_id}' not found in vendor {vendor_id} catalog"
else:
message = f"Product with ID '{product_id}' not found"
super().__init__(
resource_type="Product",
identifier=str(product_id),
message=message,
error_code="PRODUCT_NOT_FOUND",
)
self.details["product_id"] = product_id
if vendor_id:
self.details["vendor_id"] = vendor_id
class ProductAlreadyExistsException(ConflictException):
"""Raised when trying to add a product that already exists."""
def __init__(self, vendor_id: int, identifier: str | int):
super().__init__(
message=f"Product '{identifier}' already exists in vendor {vendor_id} catalog",
error_code="PRODUCT_ALREADY_EXISTS",
details={
"vendor_id": vendor_id,
"identifier": identifier,
},
)
class ProductNotInCatalogException(ResourceNotFoundException):
"""Raised when trying to access a product that's not in vendor's catalog."""
def __init__(self, product_id: int, vendor_id: int):
super().__init__(
resource_type="Product",
identifier=str(product_id),
message=f"Product {product_id} is not in vendor {vendor_id} catalog",
error_code="PRODUCT_NOT_IN_CATALOG",
details={
"product_id": product_id,
"vendor_id": vendor_id,
},
)
class ProductNotActiveException(BusinessLogicException):
"""Raised when trying to perform operations on inactive product."""
def __init__(self, product_id: int, vendor_id: int):
super().__init__(
message=f"Product {product_id} in vendor {vendor_id} catalog is not active",
error_code="PRODUCT_NOT_ACTIVE",
details={
"product_id": product_id,
"vendor_id": vendor_id,
},
)
class ProductValidationException(ValidationException):
"""Raised when product data validation fails."""
def __init__(
self,
message: str = "Product validation failed",
field: str | None = None,
validation_errors: dict | None = None,
):
details = {}
if validation_errors:
details["validation_errors"] = validation_errors
super().__init__(
message=message,
field=field,
details=details,
)
self.error_code = "PRODUCT_VALIDATION_FAILED"
class CannotDeleteProductException(BusinessLogicException):
"""Raised when a product cannot be deleted due to dependencies."""
def __init__(self, product_id: int, reason: str, details: dict | None = None):
super().__init__(
message=f"Cannot delete product {product_id}: {reason}",
error_code="CANNOT_DELETE_PRODUCT",
details={"product_id": product_id, "reason": reason, **(details or {})},
)
class ProductMediaException(BusinessLogicException):
"""Raised when there's an issue with product media."""
def __init__(self, product_id: int, message: str):
super().__init__(
message=message,
error_code="PRODUCT_MEDIA_ERROR",
details={"product_id": product_id},
)
__all__ = [
"CannotDeleteProductException",
"ProductAlreadyExistsException",
"ProductMediaException",
"ProductNotActiveException",
"ProductNotFoundException",
"ProductNotInCatalogException",
"ProductValidationException",
]

View File

@@ -0,0 +1,49 @@
{
"title": "Produktkatalog",
"description": "Produktkatalogverwaltung für Händler",
"products": {
"title": "Produkte",
"subtitle": "Verwalten Sie Ihren Produktkatalog",
"create": "Produkt erstellen",
"edit": "Produkt bearbeiten",
"delete": "Produkt löschen",
"empty": "Keine Produkte gefunden",
"empty_search": "Keine Produkte entsprechen Ihrer Suche"
},
"product": {
"name": "Produktname",
"description": "Beschreibung",
"sku": "Artikelnummer",
"price": "Preis",
"stock": "Bestand",
"status": "Status",
"active": "Aktiv",
"inactive": "Inaktiv"
},
"media": {
"title": "Produktmedien",
"upload": "Bild hochladen",
"delete": "Bild löschen",
"primary": "Als Hauptbild festlegen",
"error": "Medien-Upload fehlgeschlagen"
},
"validation": {
"name_required": "Produktname ist erforderlich",
"price_required": "Preis ist erforderlich",
"invalid_sku": "Ungültiges Artikelnummernformat",
"duplicate_sku": "Artikelnummer existiert bereits"
},
"messages": {
"created": "Produkt erfolgreich erstellt",
"updated": "Produkt erfolgreich aktualisiert",
"deleted": "Produkt erfolgreich gelöscht",
"not_found": "Produkt nicht gefunden",
"cannot_delete": "Produkt kann nicht gelöscht werden",
"error_loading": "Fehler beim Laden der Produkte"
},
"filters": {
"all_products": "Alle Produkte",
"active_only": "Nur aktive",
"search_placeholder": "Produkte suchen..."
}
}

View File

@@ -0,0 +1,49 @@
{
"title": "Product Catalog",
"description": "Product catalog management for vendors",
"products": {
"title": "Products",
"subtitle": "Manage your product catalog",
"create": "Create Product",
"edit": "Edit Product",
"delete": "Delete Product",
"empty": "No products found",
"empty_search": "No products match your search"
},
"product": {
"name": "Product Name",
"description": "Description",
"sku": "SKU",
"price": "Price",
"stock": "Stock",
"status": "Status",
"active": "Active",
"inactive": "Inactive"
},
"media": {
"title": "Product Media",
"upload": "Upload Image",
"delete": "Delete Image",
"primary": "Set as Primary",
"error": "Media upload failed"
},
"validation": {
"name_required": "Product name is required",
"price_required": "Price is required",
"invalid_sku": "Invalid SKU format",
"duplicate_sku": "SKU already exists"
},
"messages": {
"created": "Product created successfully",
"updated": "Product updated successfully",
"deleted": "Product deleted successfully",
"not_found": "Product not found",
"cannot_delete": "Cannot delete product",
"error_loading": "Error loading products"
},
"filters": {
"all_products": "All Products",
"active_only": "Active Only",
"search_placeholder": "Search products..."
}
}

View File

@@ -0,0 +1,49 @@
{
"title": "Catalogue produits",
"description": "Gestion du catalogue produits pour les vendeurs",
"products": {
"title": "Produits",
"subtitle": "Gérez votre catalogue de produits",
"create": "Créer un produit",
"edit": "Modifier le produit",
"delete": "Supprimer le produit",
"empty": "Aucun produit trouvé",
"empty_search": "Aucun produit ne correspond à votre recherche"
},
"product": {
"name": "Nom du produit",
"description": "Description",
"sku": "Référence",
"price": "Prix",
"stock": "Stock",
"status": "Statut",
"active": "Actif",
"inactive": "Inactif"
},
"media": {
"title": "Médias du produit",
"upload": "Télécharger une image",
"delete": "Supprimer l'image",
"primary": "Définir comme image principale",
"error": "Échec du téléchargement"
},
"validation": {
"name_required": "Le nom du produit est requis",
"price_required": "Le prix est requis",
"invalid_sku": "Format de référence invalide",
"duplicate_sku": "La référence existe déjà"
},
"messages": {
"created": "Produit créé avec succès",
"updated": "Produit mis à jour avec succès",
"deleted": "Produit supprimé avec succès",
"not_found": "Produit non trouvé",
"cannot_delete": "Impossible de supprimer le produit",
"error_loading": "Erreur lors du chargement des produits"
},
"filters": {
"all_products": "Tous les produits",
"active_only": "Actifs uniquement",
"search_placeholder": "Rechercher des produits..."
}
}

View File

@@ -0,0 +1,49 @@
{
"title": "Produktkatalog",
"description": "Produktkatalogverwaltung fir Händler",
"products": {
"title": "Produkter",
"subtitle": "Verwalte Äre Produktkatalog",
"create": "Produkt erstellen",
"edit": "Produkt beaarbechten",
"delete": "Produkt läschen",
"empty": "Keng Produkter fonnt",
"empty_search": "Keng Produkter entspriechen Ärer Sich"
},
"product": {
"name": "Produktnumm",
"description": "Beschreiwung",
"sku": "Artikelnummer",
"price": "Präis",
"stock": "Bestand",
"status": "Status",
"active": "Aktiv",
"inactive": "Inaktiv"
},
"media": {
"title": "Produktmedien",
"upload": "Bild eroplueden",
"delete": "Bild läschen",
"primary": "Als Haaptbild setzen",
"error": "Medien-Upload feelgeschloen"
},
"validation": {
"name_required": "Produktnumm ass erfuerderlech",
"price_required": "Präis ass erfuerderlech",
"invalid_sku": "Ongëlteg Artikelnummerformat",
"duplicate_sku": "Artikelnummer existéiert schonn"
},
"messages": {
"created": "Produkt erfollegräich erstallt",
"updated": "Produkt erfollegräich aktualiséiert",
"deleted": "Produkt erfollegräich geläscht",
"not_found": "Produkt net fonnt",
"cannot_delete": "Produkt kann net geläscht ginn",
"error_loading": "Feeler beim Lueden vun de Produkter"
},
"filters": {
"all_products": "All Produkter",
"active_only": "Nëmmen aktiv",
"search_placeholder": "Produkter sichen..."
}
}