2025-06-02 11:37:11 +00:00

138 lines
4.1 KiB
Python

from typing import Any, Dict, List, Optional, Tuple, Union
from sqlalchemy.orm import Session
from app.models.inventory import Inventory
from app.models.product import Product
from app.models.warehouse import Warehouse
from app.schemas.inventory import InventoryCreate, InventoryUpdate
def get(db: Session, inventory_id: int) -> Optional[Inventory]:
return db.query(Inventory).filter(Inventory.id == inventory_id).first()
def get_by_product_and_warehouse(
db: Session, *, product_id: int, warehouse_id: int
) -> Optional[Inventory]:
return (
db.query(Inventory)
.filter(Inventory.product_id == product_id, Inventory.warehouse_id == warehouse_id)
.first()
)
def get_multi(
db: Session, *, skip: int = 0, limit: int = 100, warehouse_id: Optional[int] = None
) -> List[Inventory]:
query = db.query(Inventory)
if warehouse_id:
query = query.filter(Inventory.warehouse_id == warehouse_id)
return query.offset(skip).limit(limit).all()
def create(db: Session, *, obj_in: InventoryCreate) -> Inventory:
# Check if inventory already exists for this product/warehouse combination
existing = get_by_product_and_warehouse(
db, product_id=obj_in.product_id, warehouse_id=obj_in.warehouse_id
)
if existing:
# Update quantity instead of creating new
existing.quantity += obj_in.quantity
db.add(existing)
db.commit()
db.refresh(existing)
return existing
# Create new inventory record
db_obj = Inventory(
product_id=obj_in.product_id,
warehouse_id=obj_in.warehouse_id,
quantity=obj_in.quantity,
location=obj_in.location,
min_stock_level=obj_in.min_stock_level,
max_stock_level=obj_in.max_stock_level,
)
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
def update(
db: Session, *, db_obj: Inventory, obj_in: Union[InventoryUpdate, Dict[str, Any]]
) -> Inventory:
if isinstance(obj_in, dict):
update_data = obj_in
else:
update_data = obj_in.dict(exclude_unset=True)
for field in update_data:
setattr(db_obj, field, update_data[field])
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
def remove(db: Session, *, inventory_id: int) -> Inventory:
obj = db.query(Inventory).get(inventory_id)
db.delete(obj)
db.commit()
return obj
def get_with_details(db: Session, inventory_id: int) -> Optional[Tuple[Inventory, str, str]]:
"""Get inventory with product and warehouse names"""
result = (
db.query(Inventory, Product.name, Warehouse.name)
.join(Product)
.join(Warehouse)
.filter(Inventory.id == inventory_id)
.first()
)
if result:
inventory, product_name, warehouse_name = result
return inventory, product_name, warehouse_name
return None
def get_multi_with_details(
db: Session, *, skip: int = 0, limit: int = 100, warehouse_id: Optional[int] = None
) -> List[Tuple[Inventory, str, str]]:
"""Get multiple inventory items with product and warehouse names"""
query = (
db.query(Inventory, Product.name, Warehouse.name)
.join(Product)
.join(Warehouse)
)
if warehouse_id:
query = query.filter(Inventory.warehouse_id == warehouse_id)
return query.offset(skip).limit(limit).all()
def update_quantity(
db: Session, *, inventory_id: int, quantity_change: int
) -> Optional[Inventory]:
"""Update inventory quantity by adding the quantity_change (can be negative)"""
inventory = get(db, inventory_id)
if not inventory:
return None
inventory.quantity += quantity_change
if inventory.quantity < 0:
inventory.quantity = 0
db.add(inventory)
db.commit()
db.refresh(inventory)
return inventory
def get_low_stock_items(db: Session, *, limit: int = 100) -> List[Inventory]:
"""Get inventory items where quantity is below min_stock_level"""
return (
db.query(Inventory)
.filter(Inventory.quantity < Inventory.min_stock_level)
.limit(limit)
.all()
)