
This API provides endpoints for: - Product and inventory management - Customer management - Order processing - Payment processing with Stripe integration - User authentication generated with BackendIM... (backend.im)
191 lines
6.6 KiB
Python
191 lines
6.6 KiB
Python
from typing import Any, List
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Path, Query
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app import crud, models, schemas
|
|
from app.api import deps
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/", response_model=List[schemas.Order])
|
|
def list_orders(
|
|
db: Session = Depends(deps.get_db),
|
|
skip: int = Query(0, description="Skip first N items"),
|
|
limit: int = Query(100, description="Limit the number of items returned"),
|
|
customer_id: int = Query(None, description="Filter by customer ID"),
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Retrieve orders with optional customer filtering
|
|
"""
|
|
if customer_id:
|
|
# Check permissions if not superuser
|
|
if not crud.user.is_superuser(current_user):
|
|
customer = crud.customer.get(db, id=customer_id)
|
|
if not customer or not customer.user_id or customer.user_id != current_user.id:
|
|
raise HTTPException(
|
|
status_code=403,
|
|
detail="Not enough permissions to access these orders"
|
|
)
|
|
|
|
orders = crud.order.get_by_customer(db, customer_id=customer_id, skip=skip, limit=limit)
|
|
else:
|
|
# Non-superusers can only see their own orders
|
|
if not crud.user.is_superuser(current_user):
|
|
# Find customer associated with current user
|
|
customer = db.query(models.Customer).filter(models.Customer.user_id == current_user.id).first()
|
|
if not customer:
|
|
return []
|
|
orders = crud.order.get_by_customer(db, customer_id=customer.id, skip=skip, limit=limit)
|
|
else:
|
|
orders = crud.order.get_multi(db, skip=skip, limit=limit)
|
|
return orders
|
|
|
|
|
|
@router.post("/", response_model=schemas.Order)
|
|
def create_order(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
order_in: schemas.OrderCreate,
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Create a new order
|
|
"""
|
|
# Verify customer exists
|
|
customer = crud.customer.get(db, id=order_in.customer_id)
|
|
if not customer:
|
|
raise HTTPException(status_code=404, detail="Customer not found")
|
|
|
|
# Check permissions if not superuser
|
|
if not crud.user.is_superuser(current_user):
|
|
if not customer.user_id or customer.user_id != current_user.id:
|
|
raise HTTPException(
|
|
status_code=403,
|
|
detail="Not enough permissions to create order for this customer"
|
|
)
|
|
|
|
# Verify products exist and have enough inventory
|
|
for item in order_in.items:
|
|
product = crud.product.get(db, id=item.product_id)
|
|
if not product:
|
|
raise HTTPException(
|
|
status_code=404,
|
|
detail=f"Product with ID {item.product_id} not found"
|
|
)
|
|
|
|
# Check inventory
|
|
inventory = crud.inventory.get_by_product_id(db, product_id=item.product_id)
|
|
if not inventory or inventory.quantity < item.quantity:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=f"Not enough inventory for product {product.name}"
|
|
)
|
|
|
|
# Create the order
|
|
order = crud.order.create_with_items(db, obj_in=order_in)
|
|
|
|
# Update inventory
|
|
for item in order.items:
|
|
inventory = crud.inventory.get_by_product_id(db, product_id=item.product_id)
|
|
if inventory:
|
|
crud.inventory.update_quantity(
|
|
db, inventory_id=inventory.id, quantity_change=-item.quantity
|
|
)
|
|
|
|
return order
|
|
|
|
|
|
@router.get("/{order_id}", response_model=schemas.Order)
|
|
def get_order(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
order_id: int = Path(..., description="The ID of the order to get"),
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Get a specific order by id
|
|
"""
|
|
order = crud.order.get_with_items(db, order_id=order_id)
|
|
if not order:
|
|
raise HTTPException(status_code=404, detail="Order not found")
|
|
|
|
# Check permissions if not superuser
|
|
if not crud.user.is_superuser(current_user):
|
|
customer = crud.customer.get(db, id=order.customer_id)
|
|
if not customer or not customer.user_id or customer.user_id != current_user.id:
|
|
raise HTTPException(
|
|
status_code=403,
|
|
detail="Not enough permissions to access this order"
|
|
)
|
|
|
|
return order
|
|
|
|
|
|
@router.put("/{order_id}", response_model=schemas.Order)
|
|
def update_order(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
order_id: int = Path(..., description="The ID of the order to update"),
|
|
order_in: schemas.OrderUpdate,
|
|
current_user: models.User = Depends(deps.get_current_active_superuser),
|
|
) -> Any:
|
|
"""
|
|
Update an order's details (admin only)
|
|
"""
|
|
order = crud.order.get(db, id=order_id)
|
|
if not order:
|
|
raise HTTPException(status_code=404, detail="Order not found")
|
|
|
|
order = crud.order.update(db, db_obj=order, obj_in=order_in)
|
|
return order
|
|
|
|
|
|
@router.delete("/{order_id}", response_model=schemas.Order)
|
|
def cancel_order(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
order_id: int = Path(..., description="The ID of the order to cancel"),
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Cancel an order and restore inventory
|
|
"""
|
|
order = crud.order.get_with_items(db, order_id=order_id)
|
|
if not order:
|
|
raise HTTPException(status_code=404, detail="Order not found")
|
|
|
|
# Check permissions if not superuser
|
|
if not crud.user.is_superuser(current_user):
|
|
customer = crud.customer.get(db, id=order.customer_id)
|
|
if not customer or not customer.user_id or customer.user_id != current_user.id:
|
|
raise HTTPException(
|
|
status_code=403,
|
|
detail="Not enough permissions to cancel this order"
|
|
)
|
|
|
|
# Check if order can be canceled
|
|
if order.status not in ["pending", "processing"]:
|
|
raise HTTPException(
|
|
status_code=400,
|
|
detail=f"Cannot cancel order with status {order.status}"
|
|
)
|
|
|
|
# Update order status
|
|
order = crud.order.update(
|
|
db, db_obj=order, obj_in={"status": "cancelled", "payment_status": "refunded"}
|
|
)
|
|
|
|
# Restore inventory
|
|
for item in order.items:
|
|
inventory = crud.inventory.get_by_product_id(db, product_id=item.product_id)
|
|
if inventory:
|
|
crud.inventory.update_quantity(
|
|
db, inventory_id=inventory.id, quantity_change=item.quantity
|
|
)
|
|
|
|
# TODO: Handle Stripe refund if payment was made
|
|
|
|
return order |