173 lines
4.9 KiB
Python
173 lines
4.9 KiB
Python
from typing import Any, List
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
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 read_user_orders(
|
|
db: Session = Depends(deps.get_db),
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Retrieve current user's orders.
|
|
"""
|
|
orders = crud.order.get_orders_by_user(
|
|
db, user_id=current_user.id, 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.
|
|
"""
|
|
# Validate order items
|
|
if not order_in.items or len(order_in.items) == 0:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Order must contain at least one item",
|
|
)
|
|
|
|
# Check if products exist and are in stock
|
|
for item in order_in.items:
|
|
product = crud.product.get(db, id=item.product_id)
|
|
if not product or not product.is_active:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Product with id {item.product_id} not found or inactive",
|
|
)
|
|
|
|
if product.stock < item.quantity:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail=f"Not enough stock for product {product.name}. Available: {product.stock}",
|
|
)
|
|
|
|
# Create order
|
|
order = crud.order.create_with_items(
|
|
db, obj_in=order_in, user_id=current_user.id
|
|
)
|
|
|
|
# Update product stock
|
|
for item in order.items:
|
|
product = crud.product.get(db, id=item.product_id)
|
|
product.stock -= item.quantity
|
|
db.add(product)
|
|
|
|
# Clear user's cart
|
|
cart = crud.cart.get_by_user_id(db, user_id=current_user.id)
|
|
if cart:
|
|
crud.cart_item.clear_cart(db, cart_id=cart.id)
|
|
|
|
db.commit()
|
|
|
|
return order
|
|
|
|
|
|
@router.get("/{order_id}", response_model=schemas.Order)
|
|
def read_order(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
order_id: int,
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> Any:
|
|
"""
|
|
Get order by ID.
|
|
"""
|
|
order = crud.order.get_order_with_items(db, order_id=order_id)
|
|
if not order:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Order not found",
|
|
)
|
|
|
|
# Check if user is authorized to access this order
|
|
if order.user_id != current_user.id and not current_user.is_admin:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Not enough permissions",
|
|
)
|
|
|
|
return order
|
|
|
|
|
|
@router.put("/{order_id}", response_model=schemas.Order)
|
|
def update_order_status(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
order_id: int,
|
|
order_in: schemas.OrderUpdate,
|
|
current_user: models.User = Depends(deps.get_current_admin_user),
|
|
) -> Any:
|
|
"""
|
|
Update order status (admin only).
|
|
"""
|
|
order = crud.order.get(db, id=order_id)
|
|
if not order:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Order not found",
|
|
)
|
|
|
|
order = crud.order.update(db, db_obj=order, obj_in=order_in)
|
|
return order
|
|
|
|
|
|
@router.delete("/{order_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None)
|
|
def cancel_order(
|
|
*,
|
|
db: Session = Depends(deps.get_db),
|
|
order_id: int,
|
|
current_user: models.User = Depends(deps.get_current_active_user),
|
|
) -> None:
|
|
"""
|
|
Cancel an order. Only allowed for pending orders.
|
|
"""
|
|
order = crud.order.get_order_with_items(db, order_id=order_id)
|
|
if not order:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Order not found",
|
|
)
|
|
|
|
# Check if user is authorized to cancel this order
|
|
if order.user_id != current_user.id and not current_user.is_admin:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Not enough permissions",
|
|
)
|
|
|
|
# Check if order can be cancelled
|
|
if order.status != models.OrderStatus.PENDING:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Only pending orders can be cancelled",
|
|
)
|
|
|
|
# Update order status to cancelled
|
|
order.status = models.OrderStatus.CANCELLED
|
|
|
|
# Restore product stock
|
|
for item in order.items:
|
|
product = crud.product.get(db, id=item.product_id)
|
|
if product:
|
|
product.stock += item.quantity
|
|
db.add(product)
|
|
|
|
db.add(order)
|
|
db.commit()
|