Admin-Desk / app /db /schemas.py
Fred808's picture
Update app/db/schemas.py
639b015 verified
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
@validator('end_time')
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
@validator('reminder_minutes')
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
@validator('reminder_minutes')
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
@validator('recurrence_pattern')
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
@validator('recurrence_end_date')
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
@validator('recurrence_pattern')
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
@validates('email')
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
@validates('username')
def validate_username(self, key, username):
if len(username) < 3:
raise ValueError('Username must be at least 3 characters long')
return username
@validates('inventory_count')
def validate_inventory(self, key, count):
if count < 0:
raise ValueError('Inventory count cannot be negative')
return count
@validates('price')
def validate_price(self, key, price):
if price < 0:
raise ValueError('Price cannot be negative')
return price
# Event listeners for automatic timestamps
@event.listens_for(Product, 'before_insert')
def set_created_at(mapper, connection, target):
target.created_at = datetime.utcnow()
target.updated_at = datetime.utcnow()
@event.listens_for(Product, 'before_update')
def set_updated_at(mapper, connection, target):
target.updated_at = datetime.utcnow()
@event.listens_for(Order, 'before_insert')
def set_order_created_at(mapper, connection, target):
target.created_at = datetime.utcnow()
target.updated_at = datetime.utcnow()
@event.listens_for(Order, 'before_update')
def set_order_updated_at(mapper, connection, target):
target.updated_at = datetime.utcnow()
@event.listens_for(Event, 'before_insert')
def set_event_created_at(mapper, connection, target):
target.created_at = datetime.utcnow()
target.updated_at = datetime.utcnow()
@event.listens_for(Event, 'before_update')
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