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>
This commit is contained in:
2025-12-24 23:41:20 +01:00
parent 4ba911e263
commit 508e121a0e
10 changed files with 444 additions and 418 deletions

View File

@@ -171,9 +171,9 @@ class VendorProductService:
raise ProductNotFoundException(product_id)
mp = product.marketplace_product
override_info = product.get_override_info()
source_comparison_info = product.get_source_comparison_info()
# Get marketplace product translations
# Get marketplace product translations (for "view original source")
mp_translations = {}
if mp:
for t in mp.translations:
@@ -183,7 +183,7 @@ class VendorProductService:
"short_description": t.short_description,
}
# Get vendor translations (overrides)
# Get vendor translations
vendor_translations = {}
for t in product.translations:
vendor_translations[t.language] = {
@@ -198,8 +198,8 @@ class VendorProductService:
"vendor_code": product.vendor.vendor_code if product.vendor else None,
"marketplace_product_id": product.marketplace_product_id,
"vendor_sku": product.vendor_sku,
# Override info
**override_info,
# Product fields with source comparison info
**source_comparison_info,
# Vendor-specific fields
"is_featured": product.is_featured,
"is_active": product.is_active,
@@ -270,13 +270,13 @@ class VendorProductService:
"marketplace_product_id": product.marketplace_product_id,
"vendor_sku": product.vendor_sku,
"title": title,
"brand": product.effective_brand,
"effective_price": product.effective_price,
"effective_currency": product.effective_currency,
"brand": product.brand,
"price": product.price,
"currency": product.currency,
"is_active": product.is_active,
"is_featured": product.is_featured,
"is_digital": product.is_digital,
"image_url": product.effective_primary_image_url,
"image_url": product.primary_image_url,
"source_marketplace": mp.marketplace if mp else None,
"source_vendor": mp.vendor_name if mp else None,
"created_at": product.created_at.isoformat()