feat: add unified admin Marketplace Letzshop page

- Add new Marketplace section in admin sidebar with Letzshop sub-item
- Remove old Import and Letzshop Orders items from Product Catalog
- Create unified Letzshop management page with 3 tabs:
  - Products tab: Import/Export functionality
  - Orders tab: Order management with confirm/reject/tracking
  - Settings tab: API credentials and CSV URLs
- Add unified jobs table showing imports, exports, and order syncs
- Implement vendor autocomplete using Tom Select library (CDN + fallback)
- Add /vendors/{vendor_id}/jobs API endpoint for unified job listing
- Move database queries to service layer (LetzshopOrderService)
- Add LetzshopJobItem and LetzshopJobsListResponse schemas
- Include Tom Select CSS/JS assets as local fallback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-14 18:27:04 +01:00
parent bacd79eeac
commit 45b09d6d90
14 changed files with 2589 additions and 8 deletions

View File

@@ -31,6 +31,8 @@ from models.schema.letzshop import (
LetzshopCredentialsCreate,
LetzshopCredentialsResponse,
LetzshopCredentialsUpdate,
LetzshopJobItem,
LetzshopJobsListResponse,
LetzshopOrderListResponse,
LetzshopOrderResponse,
LetzshopSuccessResponse,
@@ -478,3 +480,47 @@ def trigger_vendor_sync(
message=f"Sync failed: {e}",
errors=[str(e)],
)
# ============================================================================
# Jobs (Unified view of imports, exports, and syncs)
# ============================================================================
@router.get(
"/vendors/{vendor_id}/jobs",
response_model=LetzshopJobsListResponse,
)
def list_vendor_letzshop_jobs(
vendor_id: int = Path(..., description="Vendor ID"),
job_type: str | None = Query(None, description="Filter: import, export, order_sync"),
status: str | None = Query(None, description="Filter by status"),
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
):
"""
Get unified list of Letzshop-related jobs for a vendor.
Combines product imports, exports, and order syncs.
"""
order_service = get_order_service(db)
try:
order_service.get_vendor_or_raise(vendor_id)
except VendorNotFoundError:
raise ResourceNotFoundException("Vendor", str(vendor_id))
# Use service layer for database queries
jobs_data, total = order_service.list_letzshop_jobs(
vendor_id=vendor_id,
job_type=job_type,
status=status,
skip=skip,
limit=limit,
)
# Convert dict data to Pydantic models
jobs = [LetzshopJobItem(**job) for job in jobs_data]
return LetzshopJobsListResponse(jobs=jobs, total=total)