feat: enhance vendor product edit form with all mandatory fields

- Add translations support with language tabs (EN, FR, DE, LU)
- Add product identifiers: vendor SKU with auto-generate, brand, GTIN, GTIN type
- Add pricing fields: price (incl. VAT), sale price, currency, VAT rate
- Add primary image field with preview
- Add product status (active, featured) checkboxes
- Add optional supplier info section
- Pre-populate form with existing product data from API
- Add form validation (isFormValid method)
- Make is_digital read-only (derived from marketplace product)

🤖 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-25 12:58:00 +01:00
parent 63396ea6b6
commit b25d119899
4 changed files with 456 additions and 104 deletions

View File

@@ -198,6 +198,9 @@ 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,
# Product identifiers
"gtin": product.gtin,
"gtin_type": product.gtin_type or "ean13",
# Product fields with source comparison info
**source_comparison_info,
# Vendor-specific fields
@@ -275,29 +278,67 @@ class VendorProductService:
Args:
db: Database session
product_id: Product ID to update
data: Fields to update
data: Fields to update (may include translations dict)
Returns:
Updated Product instance
"""
product = db.query(Product).filter(Product.id == product_id).first()
from models.database.product_translation import ProductTranslation
product = (
db.query(Product)
.options(joinedload(Product.translations))
.filter(Product.id == product_id)
.first()
)
if not product:
raise ProductNotFoundException(product_id)
# Update allowed fields
# Handle translations separately
if "translations" in data and data["translations"]:
existing_translations = {t.language: t for t in product.translations}
for lang, trans_data in data["translations"].items():
if lang in existing_translations:
# Update existing translation
if "title" in trans_data:
existing_translations[lang].title = trans_data["title"]
if "description" in trans_data:
existing_translations[lang].description = trans_data["description"]
else:
# Create new translation
new_trans = ProductTranslation(
product_id=product_id,
language=lang,
title=trans_data.get("title"),
description=trans_data.get("description"),
)
db.add(new_trans)
# Handle price (convert to cents)
if "price" in data and data["price"] is not None:
product.price = data["price"] # Uses property setter to convert to cents
if "sale_price" in data:
product.sale_price = data["sale_price"] # Uses property setter
if "cost" in data:
product.cost = data["cost"] # Uses property setter
# Update other allowed fields
# Note: is_digital is derived from marketplace_product, not directly updatable
updatable_fields = [
"vendor_sku",
"brand",
"gtin",
"price_override",
"currency_override",
"availability",
"gtin_type",
"currency",
"tax_rate_percent",
"is_active",
"is_featured",
"is_digital",
"description",
"title",
"primary_image_url",
"supplier",
]
for field in updatable_fields: