shop product refactoring

This commit is contained in:
2025-10-04 23:38:53 +02:00
parent 4d2866af5e
commit 0114b6c46e
68 changed files with 2234 additions and 2236 deletions

View File

@@ -1,15 +1,14 @@
# models/schemas/__init__.py
"""API models package - Pydantic models for request/response validation."""
from . import auth
# Import API model modules
from . import base
from . import auth
from . import marketplace_product
from . import stock
from . import shop
from . import marketplace_import_job
from . import marketplace_product
from . import stats
from . import stock
from . import vendor
# Common imports for convenience
from .base import * # Base Pydantic models
@@ -18,7 +17,7 @@ __all__ = [
"auth",
"marketplace_product",
"stock",
"shop",
"vendor",
"marketplace_import_job",
"stats",
]

View File

@@ -2,12 +2,15 @@
import re
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
class UserRegister(BaseModel):
email: EmailStr = Field(..., description="Valid email address")
username: str = Field(..., description="Username")
password: str = Field(..., description="Password")
# Keep security validation in Pydantic for auth
@field_validator("username")
@@ -24,6 +27,7 @@ class UserRegister(BaseModel):
raise ValueError("Password must be at least 6 characters long")
return v
class UserLogin(BaseModel):
username: str = Field(..., description="Username")
password: str = Field(..., description="Password")
@@ -33,6 +37,7 @@ class UserLogin(BaseModel):
def validate_username(cls, v):
return v.strip()
class UserResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
@@ -44,6 +49,7 @@ class UserResponse(BaseModel):
created_at: datetime
updated_at: datetime
class LoginResponse(BaseModel):
access_token: str
token_type: str = "bearer"

View File

@@ -6,7 +6,7 @@ from pydantic import BaseModel, Field, field_validator
class MarketplaceImportJobRequest(BaseModel):
url: str = Field(..., description="URL to CSV file from marketplace")
marketplace: str = Field(default="Letzshop", description="Marketplace name")
shop_code: str = Field(..., description="Shop code to associate products with")
vendor_code: str = Field(..., description="Vendor code to associate products with")
batch_size: Optional[int] = Field(1000, description="Processing batch size")
# Removed: gt=0, le=10000 constraints - let service handle
@@ -18,7 +18,7 @@ class MarketplaceImportJobRequest(BaseModel):
raise ValueError("URL must start with http:// or https://")
return v
@field_validator("marketplace", "shop_code")
@field_validator("marketplace", "vendor_code")
@classmethod
def validate_strings(cls, v):
return v.strip()
@@ -27,9 +27,9 @@ class MarketplaceImportJobResponse(BaseModel):
job_id: int
status: str
marketplace: str
shop_id: int
shop_code: Optional[str] = None
shop_name: str
vendor_id: int
vendor_code: Optional[str] = None
vendor_name: str
message: Optional[str] = None
imported: Optional[int] = 0
updated: Optional[int] = 0

View File

@@ -43,7 +43,7 @@ class MarketplaceProductBase(BaseModel):
shipping: Optional[str] = None
currency: Optional[str] = None
marketplace: Optional[str] = None
shop_name: Optional[str] = None
vendor_name: Optional[str] = None
class MarketplaceProductCreate(MarketplaceProductBase):
marketplace_product_id: str = Field(..., description="MarketplaceProduct identifier")

View File

@@ -6,7 +6,7 @@ from pydantic import BaseModel, ConfigDict, Field, field_validator
from models.schemas.marketplace_product import MarketplaceProductResponse
class ProductCreate(BaseModel):
marketplace_product_id: str = Field(..., description="MarketplaceProduct ID to add to shop")
marketplace_product_id: str = Field(..., description="MarketplaceProduct ID to add to vendor ")
product_id: Optional[str] = None
price: Optional[float] = None # Removed: ge=0 constraint
sale_price: Optional[float] = None # Removed: ge=0 constraint
@@ -21,7 +21,7 @@ class ProductCreate(BaseModel):
class ProductResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
shop_id: int
vendor_id: int
marketplace_product: MarketplaceProductResponse
product_id: Optional[str]
price: Optional[float]

View File

@@ -10,7 +10,7 @@ class StatsResponse(BaseModel):
unique_brands: int
unique_categories: int
unique_marketplaces: int = 0
unique_shops: int = 0
unique_vendors: int = 0
total_stock_entries: int = 0
total_inventory_quantity: int = 0
@@ -18,5 +18,5 @@ class StatsResponse(BaseModel):
class MarketplaceStatsResponse(BaseModel):
marketplace: str
total_products: int
unique_shops: int
unique_vendors: int
unique_brands: int

View File

@@ -1,13 +1,13 @@
# shop.py - Keep basic format validation, remove business logic
# vendor.py - Keep basic format validation, remove business logic
import re
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel, ConfigDict, Field, field_validator
class ShopCreate(BaseModel):
shop_code: str = Field(..., description="Unique shop identifier")
shop_name: str = Field(..., description="Display name of the shop")
description: Optional[str] = Field(None, description="Shop description")
class VendorCreate(BaseModel):
vendor_code: str = Field(..., description="Unique vendor identifier")
vendor_name: str = Field(..., description="Display name of the vendor ")
description: Optional[str] = Field(None, description="Vendor description")
contact_email: Optional[str] = None
contact_phone: Optional[str] = None
website: Optional[str] = None
@@ -23,8 +23,8 @@ class ShopCreate(BaseModel):
raise ValueError("Invalid email format")
return v.lower() if v else v
class ShopUpdate(BaseModel):
shop_name: Optional[str] = None
class VendorUpdate(BaseModel):
vendor_name: Optional[str] = None
description: Optional[str] = None
contact_email: Optional[str] = None
contact_phone: Optional[str] = None
@@ -39,11 +39,11 @@ class ShopUpdate(BaseModel):
raise ValueError("Invalid email format")
return v.lower() if v else v
class ShopResponse(BaseModel):
class VendorResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
shop_code: str
shop_name: str
vendor_code: str
vendor_name: str
description: Optional[str]
owner_id: int
contact_email: Optional[str]
@@ -56,8 +56,8 @@ class ShopResponse(BaseModel):
created_at: datetime
updated_at: datetime
class ShopListResponse(BaseModel):
shops: List[ShopResponse]
class VendorListResponse(BaseModel):
vendors: List[VendorResponse]
total: int
skip: int
limit: int