Automated Action 609e7fb237 Implement retail management and payment API with FastAPI
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)
2025-05-12 12:00:19 +00:00

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