# app/modules/marketplace/services/marketplace_widgets.py """ Marketplace dashboard widget provider. Provides widgets for marketplace-related data on vendor and admin dashboards. Implements the DashboardWidgetProviderProtocol. Widgets provided: - recent_imports: List of recent import jobs with status """ import logging from sqlalchemy.orm import Session from app.modules.contracts.widgets import ( DashboardWidget, DashboardWidgetProviderProtocol, ListWidget, WidgetContext, WidgetListItem, ) logger = logging.getLogger(__name__) class MarketplaceWidgetProvider: """ Widget provider for marketplace module. Provides dashboard widgets for import jobs and other marketplace data. """ @property def widgets_category(self) -> str: return "marketplace" def _map_status_to_display(self, status: str) -> str: """Map job status to widget status indicator.""" status_map = { "pending": "neutral", "processing": "warning", "completed": "success", "completed_with_errors": "warning", "failed": "error", } return status_map.get(status, "neutral") def get_vendor_widgets( self, db: Session, vendor_id: int, context: WidgetContext | None = None, ) -> list[DashboardWidget]: """ Get marketplace widgets for a vendor dashboard. Args: db: Database session vendor_id: ID of the vendor context: Optional filtering/scoping context Returns: List of DashboardWidget objects for the vendor """ from app.modules.marketplace.models import MarketplaceImportJob limit = context.limit if context else 5 # Get recent imports for this vendor jobs = ( db.query(MarketplaceImportJob) .filter(MarketplaceImportJob.vendor_id == vendor_id) .order_by(MarketplaceImportJob.created_at.desc()) .limit(limit) .all() ) items = [ WidgetListItem( id=job.id, title=f"Import #{job.id}", subtitle=f"{job.marketplace} - {job.language.upper()}", status=self._map_status_to_display(job.status), timestamp=job.created_at, url=f"/vendor/marketplace/imports/{job.id}", metadata={ "total_processed": job.total_processed or 0, "imported_count": job.imported_count or 0, "error_count": job.error_count or 0, "status": job.status, }, ) for job in jobs ] # Get total count for "view all" indicator total_count = ( db.query(MarketplaceImportJob) .filter(MarketplaceImportJob.vendor_id == vendor_id) .count() ) return [ DashboardWidget( key="marketplace.recent_imports", widget_type="list", title="Recent Imports", category="marketplace", data=ListWidget( items=items, total_count=total_count, view_all_url="/vendor/marketplace/imports", ), icon="download", description="Latest product import jobs", order=20, ) ] def get_platform_widgets( self, db: Session, platform_id: int, context: WidgetContext | None = None, ) -> list[DashboardWidget]: """ Get marketplace widgets for the admin/platform dashboard. Args: db: Database session platform_id: ID of the platform context: Optional filtering/scoping context Returns: List of DashboardWidget objects for the platform """ from sqlalchemy.orm import joinedload from app.modules.marketplace.models import MarketplaceImportJob from app.modules.tenancy.models import Vendor, VendorPlatform limit = context.limit if context else 5 # Get vendor IDs for this platform vendor_ids_subquery = ( db.query(VendorPlatform.vendor_id) .filter(VendorPlatform.platform_id == platform_id) .subquery() ) # Get recent imports across all vendors in the platform jobs = ( db.query(MarketplaceImportJob) .options(joinedload(MarketplaceImportJob.vendor)) .filter(MarketplaceImportJob.vendor_id.in_(vendor_ids_subquery)) .order_by(MarketplaceImportJob.created_at.desc()) .limit(limit) .all() ) items = [ WidgetListItem( id=job.id, title=f"Import #{job.id}", subtitle=job.vendor.name if job.vendor else "Unknown Vendor", status=self._map_status_to_display(job.status), timestamp=job.created_at, url=f"/admin/marketplace/imports/{job.id}", metadata={ "vendor_id": job.vendor_id, "vendor_code": job.vendor.vendor_code if job.vendor else None, "marketplace": job.marketplace, "total_processed": job.total_processed or 0, "imported_count": job.imported_count or 0, "error_count": job.error_count or 0, "status": job.status, }, ) for job in jobs ] # Get total count for platform total_count = ( db.query(MarketplaceImportJob) .filter(MarketplaceImportJob.vendor_id.in_(vendor_ids_subquery)) .count() ) return [ DashboardWidget( key="marketplace.recent_imports", widget_type="list", title="Recent Imports", category="marketplace", data=ListWidget( items=items, total_count=total_count, view_all_url="/admin/marketplace/letzshop", ), icon="download", description="Latest product import jobs across all vendors", order=20, ) ] # Singleton instance marketplace_widget_provider = MarketplaceWidgetProvider() __all__ = ["MarketplaceWidgetProvider", "marketplace_widget_provider"]