Automated Action 5935f302dc Create Small Business Inventory Management System with FastAPI and SQLite
- Set up project structure and FastAPI application
- Create database models with SQLAlchemy
- Implement authentication with JWT
- Add CRUD operations for products, inventory, categories
- Implement purchase order and sales functionality
- Create reporting endpoints
- Set up Alembic for database migrations
- Add comprehensive documentation in README.md
2025-05-16 08:53:15 +00:00

185 lines
5.6 KiB
Python

from typing import Any, List, Optional
from decimal import Decimal
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from app.api.deps import get_db, get_current_active_user, get_current_admin_user
from app.crud.crud_purchase_order import purchase_order
from app.crud.crud_product import product
from app.models.user import User as UserModel
from app.schemas.purchase_order import PurchaseOrder, PurchaseOrderCreate, PurchaseOrderUpdate
router = APIRouter()
@router.get("/", response_model=List[PurchaseOrder])
def read_purchase_orders(
db: Session = Depends(get_db),
skip: int = 0,
limit: int = 100,
status: Optional[str] = None,
current_user: UserModel = Depends(get_current_active_user),
) -> Any:
"""
Retrieve purchase orders with their items.
Filter by status if provided.
"""
orders = purchase_order.get_multi_with_items(db, skip=skip, limit=limit)
# Apply status filter
if status:
orders = [order for order in orders if order.status == status]
# Calculate total amount for each order
for order in orders:
order.total_amount = purchase_order.get_total_amount(db, id=order.id)
return orders
@router.post("/", response_model=PurchaseOrder)
def create_purchase_order(
*,
db: Session = Depends(get_db),
order_in: PurchaseOrderCreate,
current_user: UserModel = Depends(get_current_active_user),
) -> Any:
"""
Create new purchase order with items.
"""
# Verify all products exist
for item in order_in.items:
prod = product.get(db, id=item.product_id)
if not prod:
raise HTTPException(
status_code=404,
detail=f"Product with id {item.product_id} not found"
)
# Create purchase order with items
new_order = purchase_order.create_with_items(
db, obj_in=order_in, user_id=current_user.id
)
# Calculate total amount
new_order.total_amount = purchase_order.get_total_amount(db, id=new_order.id)
return new_order
@router.get("/{id}", response_model=PurchaseOrder)
def read_purchase_order(
*,
db: Session = Depends(get_db),
id: int,
current_user: UserModel = Depends(get_current_active_user),
) -> Any:
"""
Get purchase order by ID with its items.
"""
order = purchase_order.get_with_items(db, id=id)
if not order:
raise HTTPException(status_code=404, detail="Purchase order not found")
# Calculate total amount
order.total_amount = purchase_order.get_total_amount(db, id=order.id)
return order
@router.put("/{id}", response_model=PurchaseOrder)
def update_purchase_order(
*,
db: Session = Depends(get_db),
id: int,
order_in: PurchaseOrderUpdate,
current_user: UserModel = Depends(get_current_active_user),
) -> Any:
"""
Update a purchase order (but not its items).
Can only update pending orders.
"""
order = purchase_order.get(db, id=id)
if not order:
raise HTTPException(status_code=404, detail="Purchase order not found")
# Only allow updates to pending orders
if order.status != "pending":
raise HTTPException(
status_code=400,
detail=f"Cannot update purchase order with status {order.status}. Only pending orders can be updated."
)
updated_order = purchase_order.update(db, db_obj=order, obj_in=order_in)
# Get full order with items for response
result = purchase_order.get_with_items(db, id=updated_order.id)
# Calculate total amount
result.total_amount = purchase_order.get_total_amount(db, id=result.id)
return result
@router.post("/{id}/receive", response_model=PurchaseOrder)
def receive_purchase_order(
*,
db: Session = Depends(get_db),
id: int,
current_user: UserModel = Depends(get_current_active_user),
) -> Any:
"""
Mark a purchase order as received and update inventory.
"""
order = purchase_order.get(db, id=id)
if not order:
raise HTTPException(status_code=404, detail="Purchase order not found")
# Only allow receiving pending orders
if order.status != "pending":
raise HTTPException(
status_code=400,
detail=f"Cannot receive purchase order with status {order.status}. Only pending orders can be received."
)
# Update status and inventory
received_order = purchase_order.receive_order(db, id=id)
# Calculate total amount
received_order.total_amount = purchase_order.get_total_amount(db, id=received_order.id)
return received_order
@router.post("/{id}/cancel", response_model=PurchaseOrder)
def cancel_purchase_order(
*,
db: Session = Depends(get_db),
id: int,
current_user: UserModel = Depends(get_current_active_user),
) -> Any:
"""
Cancel a purchase order.
"""
order = purchase_order.get(db, id=id)
if not order:
raise HTTPException(status_code=404, detail="Purchase order not found")
# Only allow cancelling pending orders
if order.status != "pending":
raise HTTPException(
status_code=400,
detail=f"Cannot cancel purchase order with status {order.status}. Only pending orders can be cancelled."
)
# Update status
cancelled_order = purchase_order.cancel_order(db, id=id)
# Get full order with items for response
result = purchase_order.get_with_items(db, id=cancelled_order.id)
# Calculate total amount
result.total_amount = purchase_order.get_total_amount(db, id=result.id)
return result