Files
orion/models/database/marketplace_import_job.py
Samir Boulahtit 9920430b9e fix: correct tojson|safe usage in templates and update validator
- Remove |safe from |tojson in HTML attributes (x-data) - quotes must
  become " for browsers to parse correctly
- Update LANG-002 and LANG-003 architecture rules to document correct
  |tojson usage patterns:
  - HTML attributes: |tojson (no |safe)
  - Script blocks: |tojson|safe
- Fix validator to warn when |tojson|safe is used in x-data (breaks
  HTML attribute parsing)
- Improve code quality across services, APIs, and tests

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 22:59:51 +01:00

114 lines
3.6 KiB
Python

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"
id = Column(Integer, primary_key=True, index=True)
vendor_id = Column(Integer, ForeignKey("vendors.id"), nullable=False, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
# Import configuration
marketplace = Column(String, nullable=False, index=True, default="Letzshop")
source_url = Column(String, nullable=False)
language = Column(
String(5), nullable=False, default="en"
) # Language for translations
# Status tracking
status = Column(
String, nullable=False, default="pending"
) # pending, processing, completed, failed, completed_with_errors
# Results
imported_count = Column(Integer, default=0)
updated_count = Column(Integer, default=0)
error_count = Column(Integer, default=0)
total_processed = Column(Integer, default=0)
# Error handling
error_message = Column(Text)
# Timestamps
started_at = Column(DateTime(timezone=True))
completed_at = Column(DateTime(timezone=True))
# 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__ = (
Index("idx_import_vendor_status", "vendor_id", "status"),
Index("idx_import_vendor_created", "vendor_id", "created_at"),
Index("idx_import_user_marketplace", "user_id", "marketplace"),
)
def __repr__(self):
return (
f"<MarketplaceImportJob(id={self.id}, vendor_id={self.vendor_id}, "
f"marketplace='{self.marketplace}', status='{self.status}', "
f"imported={self.imported_count})>"
)