
- Set up FastAPI application structure - Create database models for User, Product, Cart, CartItem, Order, and OrderItem - Set up Alembic for database migrations - Create Pydantic schemas for request/response models - Implement API endpoints for products, cart operations, and checkout process - Add health endpoint - Update README with project details and documentation
131 lines
3.7 KiB
Python
131 lines
3.7 KiB
Python
from typing import Optional, List
|
|
from datetime import datetime
|
|
from decimal import Decimal
|
|
from pydantic import Field
|
|
|
|
from app.models.order import OrderStatus, PaymentMethod
|
|
from app.schemas.base import BaseSchema, TimestampSchema
|
|
from app.schemas.product import Product
|
|
|
|
|
|
class OrderItemBase(BaseSchema):
|
|
"""Base schema for OrderItem data."""
|
|
product_id: int
|
|
quantity: int = Field(..., gt=0)
|
|
unit_price: Decimal = Field(..., ge=0, decimal_places=2)
|
|
|
|
|
|
class OrderItemCreate(OrderItemBase):
|
|
"""Schema for creating a new order item."""
|
|
pass
|
|
|
|
|
|
class OrderItemInDBBase(OrderItemBase, TimestampSchema):
|
|
"""Base schema for OrderItem in DB (with ID)."""
|
|
id: int
|
|
order_id: int
|
|
|
|
|
|
class OrderItemInDB(OrderItemInDBBase):
|
|
"""Schema for OrderItem in DB."""
|
|
pass
|
|
|
|
|
|
class OrderItemWithProduct(OrderItemInDBBase):
|
|
"""Schema for OrderItem with Product details."""
|
|
product: Product
|
|
|
|
@property
|
|
def subtotal(self) -> Decimal:
|
|
"""Calculate the subtotal for this order item."""
|
|
return self.unit_price * self.quantity
|
|
|
|
|
|
class OrderBase(BaseSchema):
|
|
"""Base schema for Order data."""
|
|
user_id: int
|
|
status: OrderStatus = OrderStatus.PENDING
|
|
total_amount: Decimal = Field(..., ge=0, decimal_places=2)
|
|
shipping_address: str
|
|
payment_method: PaymentMethod
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class OrderCreate(BaseSchema):
|
|
"""Schema for creating a new order."""
|
|
cart_id: int
|
|
shipping_address: str
|
|
payment_method: PaymentMethod
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class OrderUpdate(BaseSchema):
|
|
"""Schema for updating an order."""
|
|
status: Optional[OrderStatus] = None
|
|
tracking_number: Optional[str] = None
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class OrderInDBBase(OrderBase, TimestampSchema):
|
|
"""Base schema for Order in DB (with ID)."""
|
|
id: int
|
|
tracking_number: Optional[str] = None
|
|
payment_id: Optional[str] = None
|
|
paid_at: Optional[datetime] = None
|
|
|
|
|
|
class OrderInDB(OrderInDBBase):
|
|
"""Schema for Order in DB."""
|
|
pass
|
|
|
|
|
|
class Order(OrderInDBBase):
|
|
"""Schema for Order response with items."""
|
|
items: List[OrderItemWithProduct] = []
|
|
|
|
model_config = {
|
|
"json_schema_extra": {
|
|
"examples": [
|
|
{
|
|
"id": 1,
|
|
"user_id": 1,
|
|
"status": "pending",
|
|
"total_amount": "39.98",
|
|
"shipping_address": "123 Main St, City, Country",
|
|
"tracking_number": None,
|
|
"payment_method": "credit_card",
|
|
"payment_id": None,
|
|
"paid_at": None,
|
|
"notes": "Please deliver during business hours",
|
|
"created_at": "2023-07-24T12:00:00",
|
|
"updated_at": "2023-07-24T12:00:00",
|
|
"items": [
|
|
{
|
|
"id": 1,
|
|
"order_id": 1,
|
|
"product_id": 1,
|
|
"quantity": 2,
|
|
"unit_price": "19.99",
|
|
"product": {
|
|
"id": 1,
|
|
"name": "Product 1",
|
|
"description": "Description of product 1",
|
|
"price": "19.99",
|
|
"sku": "PROD1",
|
|
"stock_quantity": 100,
|
|
"is_active": True
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
|
|
class OrderResponse(BaseSchema):
|
|
"""Schema for response after creating an order."""
|
|
order_id: int
|
|
message: str
|
|
status: str
|
|
total_amount: Decimal |