from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from app import crud from app.api import deps from app.models.transaction import TransactionType from app.schemas.transaction import Transaction, TransactionCreate, TransactionUpdate router = APIRouter() @router.get("/", response_model=List[Transaction]) def read_transactions( db: Session = Depends(deps.get_db), skip: int = 0, limit: int = 100, item_id: Optional[int] = None, transaction_type: Optional[TransactionType] = None, current_user: Any = Depends(deps.get_current_active_user), ) -> Any: """ Retrieve transactions. """ if item_id: transactions = crud.transaction.get_by_item(db, item_id=item_id, skip=skip, limit=limit) elif transaction_type: transactions = crud.transaction.get_by_transaction_type( db, transaction_type=transaction_type, skip=skip, limit=limit ) else: transactions = crud.transaction.get_multi(db, skip=skip, limit=limit) return transactions @router.post("/", response_model=Transaction) def create_transaction( *, db: Session = Depends(deps.get_db), transaction_in: TransactionCreate, current_user: Any = Depends(deps.get_current_active_user), ) -> Any: """ Create new transaction. """ # Check if item exists item = crud.item.get(db, id=transaction_in.item_id) if not item: raise HTTPException( status_code=400, detail=f"Item with ID {transaction_in.item_id} does not exist.", ) # Check if there's enough inventory for sales or returns if transaction_in.transaction_type == TransactionType.SALE and item.quantity < transaction_in.quantity: raise HTTPException( status_code=400, detail=f"Not enough inventory for item ID {transaction_in.item_id}. Available: {item.quantity}, Requested: {transaction_in.quantity}", ) # Set the user ID if not provided if not transaction_in.user_id: transaction_in_dict = transaction_in.dict() transaction_in_dict["user_id"] = current_user.id transaction_in = TransactionCreate(**transaction_in_dict) transaction = crud.transaction.create(db, obj_in=transaction_in) return transaction @router.get("/{id}", response_model=Transaction) def read_transaction( *, db: Session = Depends(deps.get_db), id: int, current_user: Any = Depends(deps.get_current_active_user), ) -> Any: """ Get transaction by ID. """ transaction = crud.transaction.get(db, id=id) if not transaction: raise HTTPException(status_code=404, detail="Transaction not found") return transaction @router.put("/{id}", response_model=Transaction) def update_transaction( *, db: Session = Depends(deps.get_db), id: int, transaction_in: TransactionUpdate, current_user: Any = Depends(deps.get_current_active_superuser), ) -> Any: """ Update a transaction. Only superusers can update transactions. """ transaction = crud.transaction.get(db, id=id) if not transaction: raise HTTPException(status_code=404, detail="Transaction not found") # Check if item exists if item_id is provided if transaction_in.item_id and transaction_in.item_id != transaction.item_id: if not crud.item.get(db, id=transaction_in.item_id): raise HTTPException( status_code=400, detail=f"Item with ID {transaction_in.item_id} does not exist.", ) # TODO: Handle inventory adjustments when updating transactions # This is complex and might require reversing the old transaction and applying the new one transaction = crud.transaction.update(db, db_obj=transaction, obj_in=transaction_in) return transaction @router.delete("/{id}", response_model=Transaction) def delete_transaction( *, db: Session = Depends(deps.get_db), id: int, current_user: Any = Depends(deps.get_current_active_superuser), ) -> Any: """ Delete a transaction. Only superusers can delete transactions. """ transaction = crud.transaction.get(db, id=id) if not transaction: raise HTTPException(status_code=404, detail="Transaction not found") # Reverse the inventory impact of this transaction item = crud.item.get(db, id=transaction.item_id) quantity_change = transaction.quantity if transaction.transaction_type in [TransactionType.PURCHASE, TransactionType.ADJUSTMENT]: quantity_change = -quantity_change elif transaction.transaction_type in [TransactionType.SALE, TransactionType.RETURN]: quantity_change = quantity_change # Update item quantity crud.item.update_quantity(db, item_id=transaction.item_id, quantity_change=quantity_change) transaction = crud.transaction.remove(db, id=id) return transaction