
This commit includes: - Project structure setup with FastAPI - Database models with SQLAlchemy (users, products, categories, orders) - SQLite database configuration - Alembic migration scripts - API endpoints for authentication, users, products, categories, and orders - JWT authentication - Comprehensive documentation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
107 lines
3.4 KiB
Python
107 lines
3.4 KiB
Python
from typing import List, Optional, Dict, Any, Union
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.crud.base import CRUDBase
|
|
from app.models.order import Order, OrderItem, OrderStatus
|
|
from app.schemas.order import OrderCreate, OrderUpdate, OrderItemCreate, OrderItemUpdate
|
|
from app.models.product import Product
|
|
|
|
|
|
class CRUDOrderItem(CRUDBase[OrderItem, OrderItemCreate, OrderItemUpdate]):
|
|
def create_with_order(
|
|
self, db: Session, *, obj_in: OrderItemCreate, order_id: int
|
|
) -> OrderItem:
|
|
# Get product to get current price if not provided
|
|
product = db.query(Product).filter(Product.id == obj_in.product_id).first()
|
|
if not product:
|
|
raise ValueError(f"Product with id {obj_in.product_id} not found")
|
|
|
|
# Check if stock is available
|
|
if product.stock < obj_in.quantity:
|
|
raise ValueError(f"Not enough stock for product {product.name}")
|
|
|
|
# Create order item
|
|
db_obj = OrderItem(
|
|
order_id=order_id,
|
|
product_id=obj_in.product_id,
|
|
quantity=obj_in.quantity,
|
|
price=obj_in.price if obj_in.price else product.price,
|
|
)
|
|
|
|
# Update product stock
|
|
product.stock -= obj_in.quantity
|
|
|
|
db.add(db_obj)
|
|
db.add(product)
|
|
db.commit()
|
|
db.refresh(db_obj)
|
|
return db_obj
|
|
|
|
|
|
order_item = CRUDOrderItem(OrderItem)
|
|
|
|
|
|
class CRUDOrder(CRUDBase[Order, OrderCreate, OrderUpdate]):
|
|
def get_by_user(
|
|
self, db: Session, *, user_id: int, skip: int = 0, limit: int = 100
|
|
) -> List[Order]:
|
|
return (
|
|
db.query(Order)
|
|
.filter(Order.user_id == user_id)
|
|
.offset(skip)
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
|
|
def get_by_status(
|
|
self, db: Session, *, status: OrderStatus, skip: int = 0, limit: int = 100
|
|
) -> List[Order]:
|
|
return (
|
|
db.query(Order)
|
|
.filter(Order.status == status)
|
|
.offset(skip)
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
|
|
def create(self, db: Session, *, obj_in: OrderCreate) -> Order:
|
|
# Calculate total amount from items
|
|
total_amount = 0
|
|
for item in obj_in.items:
|
|
product = db.query(Product).filter(Product.id == item.product_id).first()
|
|
if not product:
|
|
raise ValueError(f"Product with id {item.product_id} not found")
|
|
if product.stock < item.quantity:
|
|
raise ValueError(f"Not enough stock for product {product.name}")
|
|
price = item.price if item.price else product.price
|
|
total_amount += price * item.quantity
|
|
|
|
# Create order
|
|
db_obj = Order(
|
|
user_id=obj_in.user_id,
|
|
status=OrderStatus.PENDING,
|
|
total_amount=total_amount,
|
|
shipping_address=obj_in.shipping_address,
|
|
)
|
|
db.add(db_obj)
|
|
db.commit()
|
|
db.refresh(db_obj)
|
|
|
|
# Create order items
|
|
for item in obj_in.items:
|
|
order_item.create_with_order(db=db, obj_in=item, order_id=db_obj.id)
|
|
|
|
db.refresh(db_obj)
|
|
return db_obj
|
|
|
|
def update_status(
|
|
self, db: Session, *, db_obj: Order, status: OrderStatus
|
|
) -> Order:
|
|
db_obj.status = status
|
|
db.add(db_obj)
|
|
db.commit()
|
|
db.refresh(db_obj)
|
|
return db_obj
|
|
|
|
|
|
order = CRUDOrder(Order) |