refactor: migrate modules from re-exports to canonical implementations

Move actual code implementations into module directories:
- orders: 5 services, 4 models, order/invoice schemas
- inventory: 3 services, 2 models, 30+ schemas
- customers: 3 services, 2 models, customer schemas
- messaging: 3 services, 2 models, message/notification schemas
- monitoring: background_tasks_service
- marketplace: 5+ services including letzshop submodule
- dev_tools: code_quality_service, test_runner_service
- billing: billing_service
- contracts: definition.py

Legacy files in app/services/, models/database/, models/schema/
now re-export from canonical module locations for backwards
compatibility. Architecture validator passes with 0 errors.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-29 21:28:56 +01:00
parent b5a803cde8
commit de83875d0a
99 changed files with 19413 additions and 15357 deletions

View File

@@ -1,117 +1,19 @@
# models/database/order_item_exception.py
"""
Order Item Exception model for tracking unmatched products during marketplace imports.
LEGACY LOCATION - Re-exports from module for backwards compatibility.
When a marketplace order contains a GTIN that doesn't match any product in the
vendor's catalog, the order is still imported but the item is linked to a
placeholder product and an exception is recorded here for resolution.
The canonical implementation is now in:
app/modules/orders/models/order_item_exception.py
This file exists to maintain backwards compatibility with code that
imports from the old location. All new code should import directly
from the module:
from app.modules.orders.models import OrderItemException
"""
from sqlalchemy import (
Column,
DateTime,
ForeignKey,
Index,
Integer,
String,
Text,
)
from sqlalchemy.orm import relationship
from app.modules.orders.models.order_item_exception import OrderItemException
from app.core.database import Base
from models.database.base import TimestampMixin
class OrderItemException(Base, TimestampMixin):
"""
Tracks unmatched order items requiring admin/vendor resolution.
When a marketplace order is imported and a product cannot be found by GTIN,
the order item is linked to a placeholder product and this exception record
is created. The order cannot be confirmed until all exceptions are resolved.
"""
__tablename__ = "order_item_exceptions"
id = Column(Integer, primary_key=True, index=True)
# Link to the order item (one-to-one)
order_item_id = Column(
Integer,
ForeignKey("order_items.id", ondelete="CASCADE"),
nullable=False,
unique=True,
)
# Vendor ID for efficient querying (denormalized from order)
vendor_id = Column(
Integer, ForeignKey("vendors.id"), nullable=False, index=True
)
# Original data from marketplace (preserved for matching)
original_gtin = Column(String(50), nullable=True, index=True)
original_product_name = Column(String(500), nullable=True)
original_sku = Column(String(100), nullable=True)
# Exception classification
# product_not_found: GTIN not in vendor catalog
# gtin_mismatch: GTIN format issue
# duplicate_gtin: Multiple products with same GTIN
exception_type = Column(
String(50), nullable=False, default="product_not_found"
)
# Resolution status
# pending: Awaiting resolution
# resolved: Product has been assigned
# ignored: Marked as ignored (still blocks confirmation)
status = Column(String(50), nullable=False, default="pending", index=True)
# Resolution details (populated when resolved)
resolved_product_id = Column(
Integer, ForeignKey("products.id"), nullable=True
)
resolved_at = Column(DateTime(timezone=True), nullable=True)
resolved_by = Column(Integer, ForeignKey("users.id"), nullable=True)
resolution_notes = Column(Text, nullable=True)
# Relationships
order_item = relationship("OrderItem", back_populates="exception")
vendor = relationship("Vendor")
resolved_product = relationship("Product")
resolver = relationship("User")
# Composite indexes for common queries
__table_args__ = (
Index("idx_exception_vendor_status", "vendor_id", "status"),
Index("idx_exception_gtin", "vendor_id", "original_gtin"),
)
def __repr__(self):
return (
f"<OrderItemException(id={self.id}, "
f"order_item_id={self.order_item_id}, "
f"gtin='{self.original_gtin}', "
f"status='{self.status}')>"
)
@property
def is_pending(self) -> bool:
"""Check if exception is pending resolution."""
return self.status == "pending"
@property
def is_resolved(self) -> bool:
"""Check if exception has been resolved."""
return self.status == "resolved"
@property
def is_ignored(self) -> bool:
"""Check if exception has been ignored."""
return self.status == "ignored"
@property
def blocks_confirmation(self) -> bool:
"""Check if this exception blocks order confirmation."""
# Both pending and ignored exceptions block confirmation
return self.status in ("pending", "ignored")
__all__ = [
"OrderItemException",
]