refactor(arch): eliminate all cross-module model imports in service layer
Some checks failed
Some checks failed
Enforce MOD-025/MOD-026 rules: zero top-level cross-module model imports remain in any service file. All 66 files migrated using deferred import patterns (method-body, _get_model() helpers, instance-cached self._Model) and new cross-module service methods in tenancy. Documentation updated with Pattern 6 (deferred imports), migration plan marked complete, and violations status reflects 84→0 service-layer violations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,7 @@ from app.modules.tenancy.exceptions import (
|
||||
StoreNotActiveException,
|
||||
StoreNotFoundException,
|
||||
)
|
||||
from app.modules.tenancy.models import Store
|
||||
from app.modules.tenancy.services.store_service import store_service as _store_service
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -62,7 +62,7 @@ class CustomerService:
|
||||
CustomerValidationException: If customer data is invalid
|
||||
"""
|
||||
# Verify store exists and is active
|
||||
store = db.query(Store).filter(Store.id == store_id).first()
|
||||
store = _store_service.get_store_by_id_optional(db, store_id)
|
||||
if not store:
|
||||
raise StoreNotFoundException(str(store_id), identifier_type="id")
|
||||
|
||||
@@ -150,7 +150,7 @@ class CustomerService:
|
||||
CustomerNotActiveException: If customer account is inactive
|
||||
"""
|
||||
# Verify store exists
|
||||
store = db.query(Store).filter(Store.id == store_id).first()
|
||||
store = _store_service.get_store_by_id_optional(db, store_id)
|
||||
if not store:
|
||||
raise StoreNotFoundException(str(store_id), identifier_type="id")
|
||||
|
||||
@@ -575,5 +575,96 @@ class CustomerService:
|
||||
return customer
|
||||
|
||||
|
||||
# ========================================================================
|
||||
# Cross-module public API methods
|
||||
# ========================================================================
|
||||
|
||||
def create_customer_for_enrollment(
|
||||
self,
|
||||
db: Session,
|
||||
store_id: int,
|
||||
email: str,
|
||||
first_name: str = "",
|
||||
last_name: str = "",
|
||||
phone: str | None = None,
|
||||
) -> Customer:
|
||||
"""
|
||||
Create a customer for loyalty/external enrollment.
|
||||
|
||||
Creates a customer with an unusable password hash.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
store_id: Store ID
|
||||
email: Customer email
|
||||
first_name: First name
|
||||
last_name: Last name
|
||||
phone: Phone number
|
||||
|
||||
Returns:
|
||||
Created Customer object
|
||||
"""
|
||||
import secrets
|
||||
|
||||
unusable_hash = f"!enrollment!{secrets.token_hex(32)}"
|
||||
store_code = "STORE"
|
||||
try:
|
||||
from app.modules.tenancy.services.store_service import store_service
|
||||
|
||||
store = store_service.get_store_by_id_optional(db, store_id)
|
||||
if store:
|
||||
store_code = store.store_code
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
cust_number = self._generate_customer_number(db, store_id, store_code)
|
||||
customer = Customer(
|
||||
email=email,
|
||||
first_name=first_name,
|
||||
last_name=last_name,
|
||||
phone=phone,
|
||||
hashed_password=unusable_hash,
|
||||
customer_number=cust_number,
|
||||
store_id=store_id,
|
||||
is_active=True,
|
||||
)
|
||||
db.add(customer)
|
||||
db.flush()
|
||||
return customer
|
||||
|
||||
def get_customer_by_id(self, db: Session, customer_id: int) -> Customer | None:
|
||||
"""
|
||||
Get customer by ID without store scope.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
customer_id: Customer ID
|
||||
|
||||
Returns:
|
||||
Customer object or None
|
||||
"""
|
||||
return db.query(Customer).filter(Customer.id == customer_id).first()
|
||||
|
||||
def get_store_customer_count(self, db: Session, store_id: int) -> int:
|
||||
"""
|
||||
Count customers for a store.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
store_id: Store ID
|
||||
|
||||
Returns:
|
||||
Customer count
|
||||
"""
|
||||
from sqlalchemy import func
|
||||
|
||||
return (
|
||||
db.query(func.count(Customer.id))
|
||||
.filter(Customer.store_id == store_id)
|
||||
.scalar()
|
||||
or 0
|
||||
)
|
||||
|
||||
|
||||
# Singleton instance
|
||||
customer_service = CustomerService()
|
||||
|
||||
Reference in New Issue
Block a user