From 40f6174e92b4c29bcf7916daa2712f4f55fc8aa3 Mon Sep 17 00:00:00 2001 From: openclaw Date: Sat, 11 Apr 2026 03:58:47 +0000 Subject: [PATCH] Add app/services/stock_service.py --- app/services/stock_service.py | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 app/services/stock_service.py diff --git a/app/services/stock_service.py b/app/services/stock_service.py new file mode 100644 index 0000000..bd34d0a --- /dev/null +++ b/app/services/stock_service.py @@ -0,0 +1,54 @@ +from sqlalchemy.orm import Session +from app.models.product import Product +from app.models.stock_movement import StockMovement, MovementType +from app.schemas.stock_movement import StockMoveRequest + + +def register_movement(db: Session, data: StockMoveRequest) -> tuple[StockMovement | None, str]: + prod = db.query(Product).filter(Product.id == data.product_id).first() + if not prod: + return None, "Producto no encontrado" + + movement_type = MovementType(data.type) + + # Validate stock for OUT movements + if movement_type == MovementType.OUT and prod.current_stock < data.quantity: + return None, "Stock insuficiente" + + # Update product stock + if movement_type == MovementType.IN: + prod.current_stock += data.quantity + elif movement_type == MovementType.OUT: + prod.current_stock -= data.quantity + else: # ADJUST + prod.current_stock = data.quantity + + # Record movement + movement = StockMovement( + product_id=data.product_id, + type=movement_type, + quantity=data.quantity, + reason=data.reason, + ) + db.add(movement) + db.commit() + db.refresh(movement) + return movement, "" + + +def get_product_history(db: Session, product_id: str): + return db.query(StockMovement).filter(StockMovement.product_id == product_id).all() + + +def get_stock_summary(db: Session): + products = db.query(Product).all() + return [ + { + "product_id": p.id, + "product_name": p.name, + "current_stock": p.current_stock, + "min_stock": p.min_stock, + "is_low_stock": p.current_stock < p.min_stock, + } + for p in products + ]