feat: add import error tracking and translation tabs
Import Error Tracking:
- Add MarketplaceImportError model to store detailed error information
- Store row number, identifier, error type, message, and row data for each error
- Add API endpoint GET /admin/marketplace-import-jobs/{job_id}/errors
- Add UI to view and browse import errors in job details modal
- Support pagination and error type filtering
Translation Tabs:
- Replace flat translation list with tabbed interface on product detail page
- Add language tabs with full language names
- Add copy-to-clipboard functionality for translation content
- Improved UX with better visual separation of translations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ from .company import Company
|
||||
from .content_page import ContentPage
|
||||
from .customer import Customer, CustomerAddress
|
||||
from .inventory import Inventory
|
||||
from .marketplace_import_job import MarketplaceImportJob
|
||||
from .marketplace_import_job import MarketplaceImportError, MarketplaceImportJob
|
||||
from .marketplace_product import (
|
||||
DigitalDeliveryMethod,
|
||||
MarketplaceProduct,
|
||||
@@ -83,6 +83,7 @@ __all__ = [
|
||||
"ProductTranslation",
|
||||
# Import
|
||||
"MarketplaceImportJob",
|
||||
"MarketplaceImportError",
|
||||
# Inventory
|
||||
"Inventory",
|
||||
# Orders
|
||||
|
||||
@@ -1,10 +1,59 @@
|
||||
from sqlalchemy import Column, DateTime, ForeignKey, Index, Integer, String, Text
|
||||
from sqlalchemy import JSON, Column, DateTime, ForeignKey, Index, Integer, String, Text
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from app.core.database import Base
|
||||
from models.database.base import TimestampMixin
|
||||
|
||||
|
||||
class MarketplaceImportError(Base, TimestampMixin):
|
||||
"""
|
||||
Stores detailed information about individual import errors.
|
||||
|
||||
Each row that fails during import creates an error record with:
|
||||
- Row number from the source file
|
||||
- Identifier (marketplace_product_id if available)
|
||||
- Error type and message
|
||||
- Raw row data for review
|
||||
"""
|
||||
|
||||
__tablename__ = "marketplace_import_errors"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
import_job_id = Column(
|
||||
Integer,
|
||||
ForeignKey("marketplace_import_jobs.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
|
||||
# Error location
|
||||
row_number = Column(Integer, nullable=False)
|
||||
|
||||
# Identifier from the row (if available)
|
||||
identifier = Column(String) # marketplace_product_id, gtin, mpn, etc.
|
||||
|
||||
# Error details
|
||||
error_type = Column(String(50), nullable=False) # missing_title, missing_id, parse_error, etc.
|
||||
error_message = Column(Text, nullable=False)
|
||||
|
||||
# Raw row data for review (JSON)
|
||||
row_data = Column(JSON)
|
||||
|
||||
# Relationship
|
||||
import_job = relationship("MarketplaceImportJob", back_populates="errors")
|
||||
|
||||
__table_args__ = (
|
||||
Index("idx_import_error_job_id", "import_job_id"),
|
||||
Index("idx_import_error_type", "error_type"),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
f"<MarketplaceImportError(id={self.id}, job_id={self.import_job_id}, "
|
||||
f"row={self.row_number}, type='{self.error_type}')>"
|
||||
)
|
||||
|
||||
|
||||
class MarketplaceImportJob(Base, TimestampMixin):
|
||||
__tablename__ = "marketplace_import_jobs"
|
||||
|
||||
@@ -37,6 +86,12 @@ class MarketplaceImportJob(Base, TimestampMixin):
|
||||
# Relationships
|
||||
vendor = relationship("Vendor", back_populates="marketplace_import_jobs")
|
||||
user = relationship("User", foreign_keys=[user_id])
|
||||
errors = relationship(
|
||||
"MarketplaceImportError",
|
||||
back_populates="import_job",
|
||||
cascade="all, delete-orphan",
|
||||
order_by="MarketplaceImportError.row_number",
|
||||
)
|
||||
|
||||
# Indexes for performance
|
||||
__table_args__ = (
|
||||
|
||||
Reference in New Issue
Block a user