API Schemas#
This page documents all Pydantic schemas used for request validation and response serialization.
Common Schemas#
MessageResponse:
{"message": "Resource deleted successfully"}
ErrorResponse:
{"detail": "Resource not found"}
PaginatedResponse:
{
"items": [],
"total": 42,
"page": 1,
"per_page": 20,
"total_pages": 3
}
Category Schemas#
CategoryCreate / CategoryUpdate:
class CategoryCreate(BaseModel):
name: str # Required, unique
description: str | None = None
display_order: int = 0
CategoryResponse:
class CategoryResponse(BaseModel):
id: int
name: str
description: str | None
display_order: int
is_active: bool
item_count: int # Number of items in this category
created_at: datetime
updated_at: datetime
Item Schemas#
ItemCreate / ItemUpdate:
class ItemCreate(BaseModel):
name: str # Required
description: str | None = None
price: float # Required, > 0
category_id: int # Required, FK to categories
stock_qty: int = -1 # -1 = unlimited
is_available: bool = True
ItemResponse:
class ItemResponse(BaseModel):
id: int
name: str
description: str | None
price: float
stock_qty: int
is_available: bool
category: CategoryResponse | None
created_at: datetime
updated_at: datetime
Addon Schemas#
AddonCreate / AddonUpdate:
class AddonCreate(BaseModel):
name: str
price: float # >= 0
is_available: bool = True
AddonResponse:
class AddonResponse(BaseModel):
id: int
name: str
price: float
is_available: bool
created_at: datetime
updated_at: datetime
Customer Schemas#
CustomerCreate / CustomerUpdate:
class CustomerCreate(BaseModel):
name: str
phone: str | None = None
email: str | None = None # Valid email format
CustomerResponse:
class CustomerResponse(BaseModel):
id: int
name: str
phone: str | None
email: str | None
total_orders: int
total_spent: float
created_at: datetime
updated_at: datetime
Order Schemas#
OrderItemCreate (nested within OrderCreate):
class OrderItemCreate(BaseModel):
item_id: int
quantity: int = 1 # >= 1
addon_ids: list[int] = []
OrderCreate:
class OrderCreate(BaseModel):
customer_id: int | None = None
payment_method: str = "cash" # cash | card | mobile
discount_id: int | None = None
notes: str | None = None
items: list[OrderItemCreate] # At least 1 item required
OrderStatusUpdate:
class OrderStatusUpdate(BaseModel):
status: str # pending → preparing → ready → completed | cancelled
OrderResponse:
class OrderResponse(BaseModel):
id: int
order_number: str # Format: PHI-YYYYMMDD-XXXX
status: str
payment_method: str
subtotal: float
tax_amount: float
discount_amount: float
total: float
notes: str | None
customer: CustomerResponse | None
discount: DiscountResponse | None
items: list[OrderItemResponse]
created_at: datetime
updated_at: datetime
Discount Schemas#
DiscountCreate / DiscountUpdate:
class DiscountCreate(BaseModel):
name: str
type: str # "percentage" or "flat"
value: float # > 0
is_active: bool = True
DiscountResponse:
class DiscountResponse(BaseModel):
id: int
name: str
type: str
value: float
is_active: bool
created_at: datetime
updated_at: datetime
Shift Schemas#
ShiftOpen:
class ShiftOpen(BaseModel):
opening_cash: float = 0.0
notes: str | None = None
ShiftClose:
class ShiftClose(BaseModel):
closing_cash: float
notes: str | None = None
ShiftResponse:
class ShiftResponse(BaseModel):
id: int
opened_at: datetime
closed_at: datetime | None
opening_cash: float
closing_cash: float | None
status: str # "open" or "closed"
notes: str | None
created_at: datetime
updated_at: datetime
Expense Schemas#
ExpenseCreate / ExpenseUpdate:
class ExpenseCreate(BaseModel):
category: str # supplies, wages, utilities, etc.
description: str
amount: float # > 0
shift_id: int | None = None
ExpenseResponse:
class ExpenseResponse(BaseModel):
id: int
category: str
description: str
amount: float
date: datetime
shift_id: int | None
created_at: datetime
updated_at: datetime
Dashboard Schemas#
DashboardSummary:
class DashboardSummary(BaseModel):
total_revenue: float
total_orders: int
completed_orders: int
cancelled_orders: int
average_order_value: float
total_customers: int
new_customers: int
total_items_sold: int
revenue_change_pct: float # % change vs previous period
total_tax_collected: float
total_discounts_given: float
busiest_hour: int | None # 0-23
TopItem:
class TopItem(BaseModel):
item_id: int
item_name: str
category_name: str
total_quantity: int
total_revenue: float
OrderTrend:
class OrderTrend(BaseModel):
date: str
order_count: int
revenue: float
ProfitLoss:
class ProfitLoss(BaseModel):
total_revenue: float
total_expenses: float
net_profit: float
profit_margin_pct: float
expense_breakdown: list[ExpenseBreakdownItem]