feat: add Create Product and CRUD actions to vendor-products page

- Add "Create Product" button in header
- Update actions column to View, Edit, Delete
- Add create/edit pages with forms and vendor selector
- Add POST/PATCH API endpoints for vendor products
- Add create_product and update_product service methods

🤖 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 11:20:17 +01:00
parent ef7c79908c
commit d65ffa58f6
9 changed files with 937 additions and 6 deletions

View File

@@ -238,6 +238,78 @@ class VendorProductService:
else None,
}
def create_product(self, db: Session, data: dict) -> Product:
"""Create a new vendor product.
Args:
db: Database session
data: Product data dict
Returns:
Created Product instance
"""
product = Product(
vendor_id=data["vendor_id"],
vendor_sku=data.get("vendor_sku"),
brand=data.get("brand"),
gtin=data.get("gtin"),
price=data.get("price"),
currency=data.get("currency", "EUR"),
availability=data.get("availability"),
is_active=data.get("is_active", True),
is_featured=data.get("is_featured", False),
is_digital=data.get("is_digital", False),
description=data.get("description"),
)
db.add(product)
db.flush()
logger.info(f"Created vendor product {product.id} for vendor {data['vendor_id']}")
return product
def update_product(self, db: Session, product_id: int, data: dict) -> Product:
"""Update a vendor product.
Args:
db: Database session
product_id: Product ID to update
data: Fields to update
Returns:
Updated Product instance
"""
product = db.query(Product).filter(Product.id == product_id).first()
if not product:
raise ProductNotFoundException(product_id)
# Update allowed fields
updatable_fields = [
"vendor_sku",
"brand",
"gtin",
"price_override",
"currency_override",
"availability",
"is_active",
"is_featured",
"is_digital",
"description",
"title",
]
for field in updatable_fields:
if field in data:
setattr(product, field, data[field])
db.flush()
logger.info(f"Updated vendor product {product_id}")
return product
def remove_product(self, db: Session, product_id: int) -> dict:
"""Remove a product from vendor catalog."""
product = db.query(Product).filter(Product.id == product_id).first()
@@ -273,6 +345,9 @@ class VendorProductService:
"brand": product.brand,
"price": product.price,
"currency": product.currency,
# Effective price/currency for UI (same as price/currency for now)
"effective_price": product.price,
"effective_currency": product.currency,
"is_active": product.is_active,
"is_featured": product.is_featured,
"is_digital": product.is_digital,