File size: 4,684 Bytes
af1d8cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from typing import Optional, List
from sqlmodel import Field, SQLModel, Relationship
from datetime import datetime

class User(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    email: str = Field(index=True, unique=True)
    password_hash: str
    full_name: Optional[str] = None
    created_at: datetime = Field(default_factory=datetime.utcnow)
    
    items: List["WardrobeItem"] = Relationship(back_populates="owner")
    outfits: List["Outfit"] = Relationship(back_populates="owner")
    measurements: Optional["UserMeasurements"] = Relationship(back_populates="user")
    clicks: List["AffiliateClick"] = Relationship(back_populates="user")

class Brand(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(unique=True, index=True)
    logo_url: Optional[str] = None
    password_hash: str = "mock_hash" # For B2B login
    
    products: List["AffiliateProduct"] = Relationship(back_populates="brand_rel")

class AffiliateProduct(SQLModel, table=True):
    """Represents a product from a brand partner"""
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    brand: str
    price: float
    commission_rate: float = 0.05  # 5% default
    original_url: str
    image_url: str
    category: str
    
    brand_id: Optional[int] = Field(default=None, foreign_key="brand.id")
    brand_rel: Optional[Brand] = Relationship(back_populates="products")
    
    clicks: List["AffiliateClick"] = Relationship(back_populates="product")

class AffiliateClick(SQLModel, table=True):
    """Log of every click on an affiliate link"""
    id: Optional[int] = Field(default=None, primary_key=True)
    product_id: int = Field(foreign_key="affiliateproduct.id")
    user_id: Optional[int] = Field(default=None, foreign_key="user.id")
    timestamp: datetime = Field(default_factory=datetime.utcnow)
    converted: bool = False # Mock conversion status
    commission_earned: float = 0.0
    
    product: Optional[AffiliateProduct] = Relationship(back_populates="clicks")
    user: Optional[User] = Relationship(back_populates="clicks")

class UserMeasurements(SQLModel, table=True):
    """Store user body measurements for size recommendations"""
    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: int = Field(foreign_key="user.id", unique=True)
    height_cm: Optional[float] = None
    weight_kg: Optional[float] = None
    chest_cm: Optional[float] = None
    waist_cm: Optional[float] = None
    hip_cm: Optional[float] = None
    preferred_fit: Optional[str] = "regular"  # slim, regular, loose
    updated_at: datetime = Field(default_factory=datetime.utcnow)
    
    user: Optional[User] = Relationship(back_populates="measurements")

class BrandSizeMapping(SQLModel, table=True):
    """Cross-brand size translation mappings"""
    id: Optional[int] = Field(default=None, primary_key=True)
    brand_name: str = Field(index=True)
    category: str  # tops, bottoms, shoes, etc.
    size_label: str  # S, M, L, 32, 34, etc.
    chest_min: Optional[float] = None
    chest_max: Optional[float] = None
    waist_min: Optional[float] = None
    waist_max: Optional[float] = None
    hip_min: Optional[float] = None
    hip_max: Optional[float] = None
    region: str = "US"  # US, EU, UK, etc.

class SizeRecommendation(SQLModel, table=True):
    """Store size recommendations for wardrobe items"""
    id: Optional[int] = Field(default=None, primary_key=True)
    user_id: int = Field(foreign_key="user.id")
    wardrobe_item_id: int = Field(foreign_key="wardrobeitem.id")
    brand_name: str
    recommended_size: str
    confidence_score: float  # 0.0 to 1.0
    alternative_sizes: Optional[str] = None  # JSON array of alternatives
    reasoning: Optional[str] = None  # Why this size was recommended
    created_at: datetime = Field(default_factory=datetime.utcnow)

class WardrobeItem(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    owner_id: Optional[int] = Field(default=None, foreign_key="user.id")
    image_url: str
    category: str  # e.g., 'top', 'bottom', 'shoes'
    tags: Optional[str] = None
    created_at: datetime = Field(default_factory=datetime.utcnow)
    
    owner: Optional[User] = Relationship(back_populates="items")

class Outfit(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    owner_id: Optional[int] = Field(default=None, foreign_key="user.id")
    items_json: str # JSON string of item IDs
    created_at: datetime = Field(default_factory=datetime.utcnow)
    
    owner: Optional[User] = Relationship(back_populates="outfits")