shop product refactoring

This commit is contained in:
2025-10-04 23:38:53 +02:00
parent 4d2866af5e
commit 0114b6c46e
68 changed files with 2234 additions and 2236 deletions

View File

@@ -1,10 +1,10 @@
# app/services/admin_service.py
"""
Admin service for managing users, shops, and import jobs.
Admin service for managing users, vendors, and import jobs.
This module provides classes and functions for:
- User management and status control
- Shop verification and activation
- Vendor verification and activation
- Marketplace import job monitoring
"""
@@ -18,13 +18,13 @@ from app.exceptions import (
UserNotFoundException,
UserStatusChangeException,
CannotModifySelfException,
ShopNotFoundException,
ShopVerificationException,
VendorNotFoundException,
VendorVerificationException,
AdminOperationException,
)
from models.schemas.marketplace_import_job import MarketplaceImportJobResponse
from models.database.marketplace_import_job import MarketplaceImportJob
from models.database.shop import Shop
from models.database.vendor import Vendor
from models.database.user import User
logger = logging.getLogger(__name__)
@@ -101,11 +101,11 @@ class AdminService:
reason="Database update failed"
)
def get_all_shops(
def get_all_vendors(
self, db: Session, skip: int = 0, limit: int = 100
) -> Tuple[List[Shop], int]:
) -> Tuple[List[Vendor], int]:
"""
Get paginated list of all shops with total count.
Get paginated list of all vendors with total count.
Args:
db: Database session
@@ -113,108 +113,108 @@ class AdminService:
limit: Maximum number of records to return
Returns:
Tuple of (shops_list, total_count)
Tuple of (vendors_list, total_count)
"""
try:
total = db.query(Shop).count()
shops = db.query(Shop).offset(skip).limit(limit).all()
return shops, total
total = db.query(Vendor).count()
vendors =db.query(Vendor).offset(skip).limit(limit).all()
return vendors, total
except Exception as e:
logger.error(f"Failed to retrieve shops: {str(e)}")
logger.error(f"Failed to retrieve vendors: {str(e)}")
raise AdminOperationException(
operation="get_all_shops",
operation="get_all_vendors",
reason="Database query failed"
)
def verify_shop(self, db: Session, shop_id: int) -> Tuple[Shop, str]:
def verify_vendor(self, db: Session, vendor_id: int) -> Tuple[Vendor, str]:
"""
Toggle shop verification status.
Toggle vendor verification status.
Args:
db: Database session
shop_id: ID of shop to verify/unverify
vendor_id: ID of vendor to verify/unverify
Returns:
Tuple of (updated_shop, status_message)
Tuple of (updated_vendor, status_message)
Raises:
ShopNotFoundException: If shop not found
ShopVerificationException: If verification fails
VendorNotFoundException: If vendor not found
VendorVerificationException: If verification fails
"""
shop = self._get_shop_by_id_or_raise(db, shop_id)
vendor = self._get_vendor_by_id_or_raise(db, vendor_id)
try:
original_status = shop.is_verified
shop.is_verified = not shop.is_verified
shop.updated_at = datetime.now(timezone.utc)
original_status = vendor.is_verified
vendor.is_verified = not vendor.is_verified
vendor.updated_at = datetime.now(timezone.utc)
# Add verification timestamp if implementing audit trail
if shop.is_verified:
shop.verified_at = datetime.now(timezone.utc)
if vendor.is_verified:
vendor.verified_at = datetime.now(timezone.utc)
db.commit()
db.refresh(shop)
db.refresh(vendor)
status_action = "verified" if shop.is_verified else "unverified"
message = f"Shop {shop.shop_code} has been {status_action}"
status_action = "verified" if vendor.is_verified else "unverified"
message = f"Vendor {vendor.vendor_code} has been {status_action}"
logger.info(message)
return shop, message
return vendor, message
except Exception as e:
db.rollback()
logger.error(f"Failed to verify shop {shop_id}: {str(e)}")
raise ShopVerificationException(
shop_id=shop_id,
logger.error(f"Failed to verify vendor {vendor_id}: {str(e)}")
raise VendorVerificationException(
vendor_id=vendor_id,
reason="Database update failed",
current_verification_status=original_status
)
def toggle_shop_status(self, db: Session, shop_id: int) -> Tuple[Shop, str]:
def toggle_vendor_status(self, db: Session, vendor_id: int) -> Tuple[Vendor, str]:
"""
Toggle shop active status.
Toggle vendor active status.
Args:
db: Database session
shop_id: ID of shop to activate/deactivate
vendor_id: ID of vendor to activate/deactivate
Returns:
Tuple of (updated_shop, status_message)
Tuple of (updated_vendor, status_message)
Raises:
ShopNotFoundException: If shop not found
VendorNotFoundException: If vendor not found
AdminOperationException: If status change fails
"""
shop = self._get_shop_by_id_or_raise(db, shop_id)
vendor = self._get_vendor_by_id_or_raise(db, vendor_id)
try:
original_status = shop.is_active
shop.is_active = not shop.is_active
shop.updated_at = datetime.now(timezone.utc)
original_status = vendor.is_active
vendor.is_active = not vendor.is_active
vendor.updated_at = datetime.now(timezone.utc)
db.commit()
db.refresh(shop)
db.refresh(vendor)
status_action = "activated" if shop.is_active else "deactivated"
message = f"Shop {shop.shop_code} has been {status_action}"
status_action = "activated" if vendor.is_active else "deactivated"
message = f"Vendor {vendor.vendor_code} has been {status_action}"
logger.info(message)
return shop, message
return vendor , message
except Exception as e:
db.rollback()
logger.error(f"Failed to toggle shop {shop_id} status: {str(e)}")
logger.error(f"Failed to toggle vendor {vendor_id} status: {str(e)}")
raise AdminOperationException(
operation="toggle_shop_status",
operation="toggle_vendor_status",
reason="Database update failed",
target_type="shop",
target_id=str(shop_id)
target_type="vendor ",
target_id=str(vendor_id)
)
def get_marketplace_import_jobs(
self,
db: Session,
marketplace: Optional[str] = None,
shop_name: Optional[str] = None,
vendor_name: Optional[str] = None,
status: Optional[str] = None,
skip: int = 0,
limit: int = 100,
@@ -225,7 +225,7 @@ class AdminService:
Args:
db: Database session
marketplace: Filter by marketplace name (case-insensitive partial match)
shop_name: Filter by shop name (case-insensitive partial match)
vendor_name: Filter by vendor name (case-insensitive partial match)
status: Filter by exact status
skip: Number of records to skip
limit: Maximum number of records to return
@@ -241,8 +241,8 @@ class AdminService:
query = query.filter(
MarketplaceImportJob.marketplace.ilike(f"%{marketplace}%")
)
if shop_name:
query = query.filter(MarketplaceImportJob.shop_name.ilike(f"%{shop_name}%"))
if vendor_name:
query = query.filter(MarketplaceImportJob.vendor_name.ilike(f"%{vendor_name}%"))
if status:
query = query.filter(MarketplaceImportJob.status == status)
@@ -283,23 +283,23 @@ class AdminService:
reason="Database query failed"
)
def get_shop_statistics(self, db: Session) -> dict:
"""Get shop statistics for admin dashboard."""
def get_vendor_statistics(self, db: Session) -> dict:
"""Get vendor statistics for admin dashboard."""
try:
total_shops = db.query(Shop).count()
active_shops = db.query(Shop).filter(Shop.is_active == True).count()
verified_shops = db.query(Shop).filter(Shop.is_verified == True).count()
total_vendors = db.query(Vendor).count()
active_vendors = db.query(Vendor).filter(Vendor.is_active == True).count()
verified_vendors = db.query(Vendor).filter(Vendor.is_verified == True).count()
return {
"total_shops": total_shops,
"active_shops": active_shops,
"verified_shops": verified_shops,
"verification_rate": (verified_shops / total_shops * 100) if total_shops > 0 else 0
"total_vendors": total_vendors,
"active_vendors": active_vendors,
"verified_vendors": verified_vendors,
"verification_rate": (verified_vendors / total_vendors * 100) if total_vendors > 0 else 0
}
except Exception as e:
logger.error(f"Failed to get shop statistics: {str(e)}")
logger.error(f"Failed to get vendor statistics: {str(e)}")
raise AdminOperationException(
operation="get_shop_statistics",
operation="get_vendor_statistics",
reason="Database query failed"
)
@@ -311,12 +311,12 @@ class AdminService:
raise UserNotFoundException(str(user_id))
return user
def _get_shop_by_id_or_raise(self, db: Session, shop_id: int) -> Shop:
"""Get shop by ID or raise ShopNotFoundException."""
shop = db.query(Shop).filter(Shop.id == shop_id).first()
if not shop:
raise ShopNotFoundException(str(shop_id), identifier_type="id")
return shop
def _get_vendor_by_id_or_raise(self, db: Session, vendor_id: int) -> Vendor:
"""Get vendor by ID or raise VendorNotFoundException."""
vendor = db.query(Vendor).filter(Vendor.id == vendor_id).first()
if not vendor :
raise VendorNotFoundException(str(vendor_id), identifier_type="id")
return vendor
def _convert_job_to_response(self, job: MarketplaceImportJob) -> MarketplaceImportJobResponse:
"""Convert database model to response schema."""
@@ -324,9 +324,9 @@ class AdminService:
job_id=job.id,
status=job.status,
marketplace=job.marketplace,
shop_id=job.shop.id if job.shop else None,
shop_code=job.shop.shop_code if job.shop else None,
shop_name=job.shop_name,
vendor_id=job.vendor.id if job.vendor else None,
vendor_code=job.vendor.vendor_code if job.vendor else None,
vendor_name=job.vendor_name,
imported=job.imported_count or 0,
updated=job.updated_count or 0,
total_processed=job.total_processed or 0,