Files
orion/models/database/product_translation.py
Samir Boulahtit 508e121a0e refactor: product independence - remove inheritance pattern
Change Product/ProductTranslation from "override/inheritance" pattern
(NULL = inherit from marketplace) to "independent copy" pattern
(all fields populated at creation).

Key changes:
- Remove OVERRIDABLE_FIELDS, effective_* properties, reset_* methods
- Rename get_override_info() → get_source_comparison_info()
- Update copy_to_vendor_catalog() to copy ALL fields + translations
- Replace effective_* with direct field access in services
- Remove *_overridden fields from schema, keep *_source for comparison
- Add migration to populate NULL fields from marketplace products

The marketplace_product_id FK is kept for "view original source" feature.
Rollback tag: v1.0.0-pre-product-independence

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 23:41:20 +01:00

115 lines
3.9 KiB
Python

"""Product Translation model for vendor-specific localized content.
This model stores vendor-specific translations. Translations are independent
entities with all fields populated at creation time from the source
marketplace product translation.
The marketplace product translation can be accessed via the product's
marketplace_product relationship for "view original source" comparison.
"""
from sqlalchemy import (
Column,
ForeignKey,
Index,
Integer,
String,
Text,
UniqueConstraint,
)
from sqlalchemy.orm import relationship
from app.core.database import Base
from models.database.base import TimestampMixin
class ProductTranslation(Base, TimestampMixin):
"""Vendor-specific localized content - independent copy.
Each vendor has their own translations with all fields populated
at creation time. The source marketplace translation can be accessed
for comparison via the product's marketplace_product relationship.
"""
__tablename__ = "product_translations"
id = Column(Integer, primary_key=True, index=True)
product_id = Column(
Integer,
ForeignKey("products.id", ondelete="CASCADE"),
nullable=False,
)
language = Column(String(5), nullable=False) # 'en', 'fr', 'de', 'lb'
# === LOCALIZED FIELDS (copied from marketplace at creation) ===
title = Column(String)
description = Column(Text)
short_description = Column(String(500))
# SEO Fields
meta_title = Column(String(70))
meta_description = Column(String(160))
url_slug = Column(String(255))
# === RELATIONSHIPS ===
product = relationship("Product", back_populates="translations")
__table_args__ = (
UniqueConstraint("product_id", "language", name="uq_product_translation"),
Index("idx_pt_product_id", "product_id"),
Index("idx_pt_product_language", "product_id", "language"),
)
def __repr__(self):
return (
f"<ProductTranslation(id={self.id}, "
f"product_id={self.product_id}, "
f"language='{self.language}', "
f"title='{self.title[:30] if self.title else None}...')>"
)
# === SOURCE COMPARISON METHOD ===
def _find_marketplace_translation(self):
"""Get the corresponding marketplace translation for comparison."""
product = self.product
if product and product.marketplace_product:
mp = product.marketplace_product
for t in mp.translations:
if t.language == self.language:
return t
return None
def get_source_comparison_info(self) -> dict:
"""Get current values with source values for comparison.
Returns a dict with current field values and original source values
from the marketplace product translation. Used for "view original source" feature.
"""
mp_translation = self._find_marketplace_translation()
return {
# Title
"title": self.title,
"title_source": mp_translation.title if mp_translation else None,
# Description
"description": self.description,
"description_source": mp_translation.description if mp_translation else None,
# Short Description
"short_description": self.short_description,
"short_description_source": (
mp_translation.short_description if mp_translation else None
),
# Meta Title
"meta_title": self.meta_title,
"meta_title_source": mp_translation.meta_title if mp_translation else None,
# Meta Description
"meta_description": self.meta_description,
"meta_description_source": (
mp_translation.meta_description if mp_translation else None
),
# URL Slug
"url_slug": self.url_slug,
"url_slug_source": mp_translation.url_slug if mp_translation else None,
}