
- Created FastAPI application with SQLite database - Implemented models for inventory items, categories, suppliers, and transactions - Added authentication system with JWT tokens - Implemented CRUD operations for all models - Set up Alembic for database migrations - Added comprehensive API documentation - Configured Ruff for code linting
125 lines
3.9 KiB
Python
125 lines
3.9 KiB
Python
from datetime import datetime
|
|
from typing import List
|
|
|
|
from sqlalchemy import and_
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.crud.base import CRUDBase
|
|
from app.models.item import Item
|
|
from app.models.transaction import Transaction, TransactionType
|
|
from app.schemas.transaction import TransactionCreate, TransactionUpdate
|
|
|
|
|
|
class CRUDTransaction(CRUDBase[Transaction, TransactionCreate, TransactionUpdate]):
|
|
"""
|
|
CRUD operations for Transaction model.
|
|
"""
|
|
def create_with_item_update(
|
|
self, db: Session, *, obj_in: TransactionCreate, user_id: int
|
|
) -> Transaction:
|
|
"""
|
|
Create a transaction and update the associated item's quantity.
|
|
"""
|
|
# Get the item to update its quantity
|
|
item = db.query(Item).filter(Item.id == obj_in.item_id).first()
|
|
if not item:
|
|
raise ValueError(f"Item with ID {obj_in.item_id} not found")
|
|
|
|
# Calculate the total price
|
|
total_price = obj_in.quantity * obj_in.unit_price
|
|
|
|
# Create transaction object
|
|
db_obj = Transaction(
|
|
item_id=obj_in.item_id,
|
|
user_id=user_id,
|
|
quantity=obj_in.quantity,
|
|
transaction_type=obj_in.transaction_type,
|
|
unit_price=obj_in.unit_price,
|
|
total_price=total_price,
|
|
reference=obj_in.reference,
|
|
notes=obj_in.notes,
|
|
timestamp=datetime.utcnow()
|
|
)
|
|
|
|
# Update the item quantity based on transaction type
|
|
if obj_in.transaction_type == TransactionType.STOCK_IN:
|
|
item.quantity += obj_in.quantity
|
|
elif obj_in.transaction_type == TransactionType.STOCK_OUT:
|
|
if item.quantity < obj_in.quantity:
|
|
raise ValueError(f"Insufficient stock. Available: {item.quantity}, Requested: {obj_in.quantity}")
|
|
item.quantity -= obj_in.quantity
|
|
|
|
# Save to database
|
|
db.add(db_obj)
|
|
db.add(item)
|
|
db.commit()
|
|
db.refresh(db_obj)
|
|
return db_obj
|
|
|
|
def get_by_item(
|
|
self, db: Session, *, item_id: int, skip: int = 0, limit: int = 100
|
|
) -> List[Transaction]:
|
|
"""
|
|
Get transactions for a specific item.
|
|
"""
|
|
return (
|
|
db.query(Transaction)
|
|
.filter(Transaction.item_id == item_id)
|
|
.order_by(Transaction.timestamp.desc())
|
|
.offset(skip)
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
|
|
def get_by_user(
|
|
self, db: Session, *, user_id: int, skip: int = 0, limit: int = 100
|
|
) -> List[Transaction]:
|
|
"""
|
|
Get transactions performed by a specific user.
|
|
"""
|
|
return (
|
|
db.query(Transaction)
|
|
.filter(Transaction.user_id == user_id)
|
|
.order_by(Transaction.timestamp.desc())
|
|
.offset(skip)
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
|
|
def get_by_date_range(
|
|
self, db: Session, *, start_date: datetime, end_date: datetime,
|
|
skip: int = 0, limit: int = 100
|
|
) -> List[Transaction]:
|
|
"""
|
|
Get transactions within a date range.
|
|
"""
|
|
return (
|
|
db.query(Transaction)
|
|
.filter(and_(
|
|
Transaction.timestamp >= start_date,
|
|
Transaction.timestamp <= end_date
|
|
))
|
|
.order_by(Transaction.timestamp.desc())
|
|
.offset(skip)
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
|
|
def get_by_type(
|
|
self, db: Session, *, transaction_type: TransactionType,
|
|
skip: int = 0, limit: int = 100
|
|
) -> List[Transaction]:
|
|
"""
|
|
Get transactions by type (stock in or stock out).
|
|
"""
|
|
return (
|
|
db.query(Transaction)
|
|
.filter(Transaction.transaction_type == transaction_type)
|
|
.order_by(Transaction.timestamp.desc())
|
|
.offset(skip)
|
|
.limit(limit)
|
|
.all()
|
|
)
|
|
|
|
|
|
transaction = CRUDTransaction(Transaction) |