Spaces:
Paused
Paused
| from sqlalchemy.orm import validates | |
| from sqlalchemy import event | |
| from datetime import datetime | |
| from typing import List, Optional, Dict | |
| from pydantic import BaseModel, EmailStr, validator | |
| from .models import User, Product, Order, Event, Notification | |
| import re | |
| # Role schemas | |
| class RoleBase(BaseModel): | |
| name: str | |
| description: str | |
| permissions: List[str] = [] | |
| class RoleCreate(RoleBase): | |
| pass | |
| class RoleUpdate(RoleBase): | |
| name: Optional[str] = None | |
| description: Optional[str] = None | |
| permissions: Optional[List[str]] = None | |
| class RoleInDB(RoleBase): | |
| id: int | |
| created_at: datetime | |
| updated_at: Optional[datetime] = None | |
| class Config: | |
| from_attributes = True | |
| class BranchBase(BaseModel): | |
| name: str | |
| address: str | |
| phone: str | |
| email: EmailStr | |
| is_active: bool = True | |
| class BranchCreate(BranchBase): | |
| pass | |
| class BranchInDB(BranchBase): | |
| id: int | |
| created_at: datetime | |
| updated_at: Optional[datetime] = None | |
| class Config: | |
| from_attributes = True | |
| # Update User schemas | |
| class UserBase(BaseModel): | |
| email: EmailStr | |
| username: str | |
| full_name: str | |
| is_active: bool = True | |
| is_superuser: bool = False | |
| branch_id: Optional[int] = None | |
| class UserCreate(UserBase): | |
| password: str | |
| role_ids: Optional[List[int]] = None # IDs of roles to assign | |
| class UserUpdate(BaseModel): | |
| email: Optional[EmailStr] = None | |
| username: Optional[str] = None | |
| full_name: Optional[str] = None | |
| is_active: Optional[bool] = None | |
| is_superuser: Optional[bool] = None | |
| password: Optional[str] = None | |
| branch_id: Optional[int] = None | |
| role_ids: Optional[List[int]] = None | |
| class UserInDB(UserBase): | |
| id: int | |
| created_at: datetime | |
| roles: List[RoleInDB] | |
| class Config: | |
| from_attributes = True | |
| class ProductBase(BaseModel): | |
| name: str | |
| description: str | |
| price: float | |
| category: str | |
| inventory_count: int | |
| seller_id: int | |
| branch_id: int | |
| class ProductCreate(ProductBase): | |
| pass | |
| class ProductInDB(ProductBase): | |
| id: int | |
| created_at: datetime | |
| updated_at: Optional[datetime] = None | |
| class Config: | |
| from_attributes = True | |
| class OrderItemBase(BaseModel): | |
| product_id: int | |
| quantity: int | |
| price: float | |
| class OrderItemCreate(OrderItemBase): | |
| pass | |
| class OrderItemInDB(OrderItemBase): | |
| id: int | |
| order_id: int | |
| class Config: | |
| from_attributes = True | |
| class OrderBase(BaseModel): | |
| customer_id: int | |
| branch_id: int | |
| total_amount: float | |
| status: str = "pending" | |
| items: List[OrderItemCreate] | |
| class OrderCreate(OrderBase): | |
| pass | |
| class OrderInDB(OrderBase): | |
| id: int | |
| created_at: datetime | |
| updated_at: Optional[datetime] = None | |
| items: List[OrderItemInDB] | |
| class Config: | |
| from_attributes = True | |
| class NotificationBase(BaseModel): | |
| user_id: int | |
| title: str | |
| message: str | |
| type: str | |
| data: Optional[dict] = None | |
| read: bool = False | |
| class NotificationCreate(NotificationBase): | |
| pass | |
| class NotificationInDB(NotificationBase): | |
| id: int | |
| created_at: datetime | |
| class Config: | |
| from_attributes = True | |
| class EventBase(BaseModel): | |
| title: str | |
| description: str | |
| start_time: datetime | |
| end_time: datetime | |
| is_all_day: bool = False | |
| reminder_minutes: int = 30 | |
| def end_time_after_start_time(cls, v, values): | |
| if 'start_time' in values and v <= values['start_time']: | |
| raise ValueError('end_time must be after start_time') | |
| return v | |
| def valid_reminder_minutes(cls, v): | |
| if v < 0: | |
| raise ValueError('reminder_minutes cannot be negative') | |
| return v | |
| class EventCreate(EventBase): | |
| attendees: List[str] = [] | |
| class EventUpdate(BaseModel): | |
| title: Optional[str] = None | |
| description: Optional[str] = None | |
| start_time: Optional[datetime] = None | |
| end_time: Optional[datetime] = None | |
| is_all_day: Optional[bool] = None | |
| reminder_minutes: Optional[int] = None | |
| attendees: Optional[List[str]] = None | |
| def valid_reminder_minutes(cls, v): | |
| if v is not None and v < 0: | |
| raise ValueError('reminder_minutes cannot be negative') | |
| return v | |
| class EventInDB(EventBase): | |
| id: int | |
| user_id: int | |
| attendees: List[str] | |
| status: str | |
| attendee_responses: Dict[str, str] | |
| created_at: datetime | |
| updated_at: Optional[datetime] = None | |
| reminder_sent: bool = False | |
| is_recurring: bool = False | |
| recurrence_group: Optional[str] = None | |
| parent_event_id: Optional[int] = None | |
| sequence_number: Optional[int] = None | |
| class Config: | |
| from_attributes = True | |
| class RecurringEventCreate(EventCreate): | |
| recurrence_pattern: str | |
| recurrence_end_date: Optional[datetime] = None | |
| def valid_recurrence_pattern(cls, v): | |
| valid_patterns = ['daily', 'weekly', 'monthly', 'yearly'] | |
| if v not in valid_patterns: | |
| raise ValueError(f'recurrence_pattern must be one of: {", ".join(valid_patterns)}') | |
| return v | |
| def end_date_after_start_time(cls, v, values): | |
| if v is not None and 'start_time' in values and v <= values['start_time']: | |
| raise ValueError('recurrence_end_date must be after start_time') | |
| return v | |
| class RecurringEventUpdate(EventUpdate): | |
| recurrence_pattern: Optional[str] = None | |
| recurrence_end_date: Optional[datetime] = None | |
| def valid_recurrence_pattern(cls, v): | |
| if v is not None: | |
| valid_patterns = ['daily', 'weekly', 'monthly', 'yearly'] | |
| if v not in valid_patterns: | |
| raise ValueError(f'recurrence_pattern must be one of: {", ".join(valid_patterns)}') | |
| return v | |
| def validate_email(self, key, email): | |
| if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email): | |
| raise ValueError('Invalid email address') | |
| return email | |
| def validate_username(self, key, username): | |
| if len(username) < 3: | |
| raise ValueError('Username must be at least 3 characters long') | |
| return username | |
| def validate_inventory(self, key, count): | |
| if count < 0: | |
| raise ValueError('Inventory count cannot be negative') | |
| return count | |
| def validate_price(self, key, price): | |
| if price < 0: | |
| raise ValueError('Price cannot be negative') | |
| return price | |
| # Event listeners for automatic timestamps | |
| def set_created_at(mapper, connection, target): | |
| target.created_at = datetime.utcnow() | |
| target.updated_at = datetime.utcnow() | |
| def set_updated_at(mapper, connection, target): | |
| target.updated_at = datetime.utcnow() | |
| def set_order_created_at(mapper, connection, target): | |
| target.created_at = datetime.utcnow() | |
| target.updated_at = datetime.utcnow() | |
| def set_order_updated_at(mapper, connection, target): | |
| target.updated_at = datetime.utcnow() | |
| def set_event_created_at(mapper, connection, target): | |
| target.created_at = datetime.utcnow() | |
| target.updated_at = datetime.utcnow() | |
| def set_event_updated_at(mapper, connection, target): | |
| target.updated_at = datetime.utcnow() | |
| # Add validators to models | |
| User.validate_email = validate_email | |
| User.validate_username = validate_username | |
| Product.validate_inventory = validate_inventory | |
| Product.validate_price = validate_price |