Improve the frontend and fix TODOs

This commit is contained in:
Urtzi Alfaro
2025-10-24 13:05:04 +02:00
parent 07c33fa578
commit 61376b7a9f
100 changed files with 8284 additions and 3419 deletions

View File

@@ -3,7 +3,7 @@
Tenant schemas - FIXED VERSION
"""
from pydantic import BaseModel, Field, validator
from pydantic import BaseModel, Field, field_validator, ValidationInfo
from typing import Optional, List, Dict, Any
from datetime import datetime
from uuid import UUID
@@ -20,31 +20,34 @@ class BakeryRegistration(BaseModel):
business_model: Optional[str] = Field(default="individual_bakery")
coupon_code: Optional[str] = Field(None, max_length=50, description="Promotional coupon code")
@validator('phone')
@field_validator('phone')
@classmethod
def validate_spanish_phone(cls, v):
"""Validate Spanish phone number"""
# Remove spaces and common separators
phone = re.sub(r'[\s\-\(\)]', '', v)
# Spanish mobile: +34 6/7/8/9 + 8 digits
# Spanish landline: +34 9 + 8 digits
patterns = [
r'^(\+34|0034|34)?[6789]\d{8}$', # Mobile
r'^(\+34|0034|34)?9\d{8}$', # Landline
]
if not any(re.match(pattern, phone) for pattern in patterns):
raise ValueError('Invalid Spanish phone number')
return v
@validator('business_type')
@field_validator('business_type')
@classmethod
def validate_business_type(cls, v):
valid_types = ['bakery', 'coffee_shop', 'pastry_shop', 'restaurant']
if v not in valid_types:
raise ValueError(f'Business type must be one of: {valid_types}')
return v
@validator('business_model')
@field_validator('business_model')
@classmethod
def validate_business_model(cls, v):
if v is None:
return v
@@ -72,7 +75,8 @@ class TenantResponse(BaseModel):
created_at: datetime
# ✅ FIX: Add custom validator to convert UUID to string
@validator('id', 'owner_id', pre=True)
@field_validator('id', 'owner_id', mode='before')
@classmethod
def convert_uuid_to_string(cls, v):
"""Convert UUID objects to strings for JSON serialization"""
if isinstance(v, UUID):
@@ -89,21 +93,26 @@ class TenantAccessResponse(BaseModel):
permissions: List[str]
class TenantMemberResponse(BaseModel):
"""Tenant member response - FIXED VERSION"""
"""Tenant member response - FIXED VERSION with enriched user data"""
id: str
user_id: str
role: str
is_active: bool
joined_at: Optional[datetime]
# Enriched user fields (populated via service layer)
user_email: Optional[str] = None
user_full_name: Optional[str] = None
user: Optional[Dict[str, Any]] = None # Full user object for compatibility
# ✅ FIX: Add custom validator to convert UUID to string
@validator('id', 'user_id', pre=True)
@field_validator('id', 'user_id', mode='before')
@classmethod
def convert_uuid_to_string(cls, v):
"""Convert UUID objects to strings for JSON serialization"""
if isinstance(v, UUID):
return str(v)
return v
class Config:
from_attributes = True
@@ -135,6 +144,42 @@ class TenantMemberUpdate(BaseModel):
role: Optional[str] = Field(None, pattern=r'^(owner|admin|member|viewer)$')
is_active: Optional[bool] = None
class AddMemberWithUserCreate(BaseModel):
"""Schema for adding member with optional user creation (pilot phase)"""
# For existing users
user_id: Optional[str] = Field(None, description="ID of existing user to add")
# For new user creation
create_user: bool = Field(False, description="Whether to create a new user")
email: Optional[str] = Field(None, description="Email for new user (if create_user=True)")
full_name: Optional[str] = Field(None, min_length=2, max_length=100, description="Full name for new user")
password: Optional[str] = Field(None, min_length=8, max_length=128, description="Password for new user")
phone: Optional[str] = Field(None, description="Phone number for new user")
language: Optional[str] = Field("es", pattern="^(es|en|eu)$", description="Preferred language")
timezone: Optional[str] = Field("Europe/Madrid", description="User timezone")
# Common fields
role: str = Field(..., pattern=r'^(admin|member|viewer)$', description="Role in the tenant")
@field_validator('email', 'full_name', 'password')
@classmethod
def validate_user_creation_fields(cls, v, info: ValidationInfo):
"""Validate that required fields are present when creating a user"""
if info.data.get('create_user') and info.field_name in ['email', 'full_name', 'password']:
if not v:
raise ValueError(f"{info.field_name} is required when create_user is True")
return v
@field_validator('user_id')
@classmethod
def validate_user_id_or_create(cls, v, info: ValidationInfo):
"""Ensure either user_id or create_user is provided"""
if not v and not info.data.get('create_user'):
raise ValueError("Either user_id or create_user must be provided")
if v and info.data.get('create_user'):
raise ValueError("Cannot specify both user_id and create_user")
return v
class TenantSubscriptionUpdate(BaseModel):
"""Schema for updating tenant subscription"""
plan: str = Field(..., pattern=r'^(basic|professional|enterprise)$')
@@ -151,7 +196,8 @@ class TenantStatsResponse(BaseModel):
subscription_plan: str
subscription_status: str
@validator('tenant_id', pre=True)
@field_validator('tenant_id', mode='before')
@classmethod
def convert_uuid_to_string(cls, v):
"""Convert UUID objects to strings for JSON serialization"""
if isinstance(v, UUID):