Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ElthonJohan/Sistema-MRP/llms.txt

Use this file to discover all available pages before exploring further.

The inventory service is the lowest-level component of the MRP stock layer. All other services—requirement, dispatch, and receipt—delegate stock mutations to these functions. Each inventory record is scoped to a (warehouse, material, budget) triple, so materials purchased under different projects appear as distinct cards. The reserve_stock function is intentionally non-committing: the caller accumulates all reservations for a requirement and issues a single db.commit() at the end.

add_stock

add_stock(db, warehouse_id, material_id, qty, user_id, budget_id=None, budget_name=None) -> list
Increments stock on the inventory record that matches (warehouse_id, material_id, budget_id), creating the record if it does not yet exist. Writes a Movement(type="IN", reference_type="manual"), commits, then calls reprocess_requirements to satisfy any pending demand automatically.
db
Session
required
SQLAlchemy session. The caller opens and owns the session; this function commits internally.
warehouse_id
int
required
ID of the principal warehouse receiving the stock.
material_id
int
required
ID of the material being added.
qty
int
required
Units to add. Must be a positive integer.
user_id
int
required
ID of the user performing the operation, recorded in the movement log.
budget_id
int
Project ID. When provided, the stock is recorded under a project-scoped inventory card. When None, stock goes to the project-free card.
budget_name
str
Display name for the project. Used only when a new inventory record is created. Ignored if the record already exists.
return
list
List of Requirement ORM objects whose items all transitioned from pending to reserved as a result of the new stock. Empty when no requirements were newly satisfiable.
from database import SessionLocal
from services.inventory_service import add_stock

db = SessionLocal()
try:
    newly_fulfilled = add_stock(
        db,
        warehouse_id=1,
        material_id=5,
        qty=100,
        user_id=3,
        budget_id=7,
        budget_name="Obra Centro Comercial",
    )
    print(f"{len(newly_fulfilled)} requirement(s) fully reserved after this receipt")
finally:
    db.close()

remove_stock

remove_stock(db, warehouse_id, material_id, qty, user_id) -> bool
Decrements stock across all active inventory records for the given (warehouse, material) pair using FIFO order (lowest id first). Returns False without modifying anything when total on-hand stock is less than qty. Writes a Movement(type="OUT", reference_type="manual") on success.
db
Session
required
Active SQLAlchemy session.
warehouse_id
int
required
Warehouse to remove stock from.
material_id
int
required
Material to reduce.
qty
int
required
Units to remove.
user_id
int
required
Recorded in the movement log.
return
bool
True when the removal succeeded; False when there is insufficient total stock.
from services.inventory_service import remove_stock

ok = remove_stock(db, warehouse_id=1, material_id=5, qty=20, user_id=3)
if not ok:
    print("Insufficient stock — removal aborted")

reserve_stock

reserve_stock(db, warehouse_id, material_id, qty) -> bool
Increments Inventory.reserved across all active records for the material using FIFO order. Only succeeds when sum(stock - reserved) >= qty across all records.
This function does not call db.commit(). The caller is responsible for committing after all items in a requirement have been processed. This preserves atomicity: if a later item fails, the whole batch can be rolled back.
db
Session
required
Active SQLAlchemy session. Must be committed by the caller.
warehouse_id
int
required
Principal warehouse to reserve from.
material_id
int
required
Material to reserve.
qty
int
required
Units to reserve.
return
bool
True when the reservation was applied in-memory; False when available stock is insufficient.
from services.inventory_service import reserve_stock

# Reserve two materials — commit only after both succeed
ok1 = reserve_stock(db, warehouse_id=1, material_id=5, qty=10)
ok2 = reserve_stock(db, warehouse_id=1, material_id=8, qty=3)

if ok1 and ok2:
    db.commit()   # caller commits here
else:
    db.rollback()

release_reservation

release_reservation(db, warehouse_id, material_id, qty) -> None
Decrements Inventory.reserved across active records in FIFO order and commits. Called by cancel_requirement when a requirement is cancelled to return the reserved stock to available.
db
Session
required
Active SQLAlchemy session. This function commits internally.
warehouse_id
int
required
Warehouse holding the reservation.
material_id
int
required
Material whose reservation is being released.
qty
int
required
Units to release.
from services.inventory_service import release_reservation

release_reservation(db, warehouse_id=1, material_id=5, qty=10)
# db is already committed after this call

get_or_create_inventory

get_or_create_inventory(db, warehouse_id, material_id, budget_id=None, budget_name=None) -> Inventory
Returns the existing inventory record matching (warehouse_id, material_id, budget_id), or creates a new one with stock=0, reserved=0 when none exists. When budget_id is None, queries for a record where budget_id IS NULL.
db
Session
required
Active SQLAlchemy session.
warehouse_id
int
required
Target warehouse.
material_id
int
required
Target material.
budget_id
int
Project scope. Pass None for project-free records.
budget_name
str
Used only when a new record is inserted. Has no effect when the record already exists.
return
Inventory
The ORM Inventory instance, either fetched or freshly created and committed.
from services.inventory_service import get_or_create_inventory

inv = get_or_create_inventory(db, warehouse_id=2, material_id=5, budget_id=7)
print(f"Stock: {inv.stock}, Reserved: {inv.reserved}")

delete_inventory_record

delete_inventory_record(db, inventory_id, owner_id=None) -> bool
Deletes an inventory record and writes a DeletedInventory snapshot capturing the record’s last known values (stock, total_value, unit_price, warehouse/material names). The snapshot has status="pending" so it can be reviewed or resolved later. Returns False when the record does not exist.
db
Session
required
Active SQLAlchemy session. Commits internally.
inventory_id
int
required
ID of the inventory record to delete.
owner_id
int
Client user ID stored in the DeletedInventory snapshot for filtering. Pass None when not applicable.
return
bool
True when the record was found and deleted; False otherwise.
from services.inventory_service import delete_inventory_record

deleted = delete_inventory_record(db, inventory_id=42, owner_id=3)
if not deleted:
    print("Record not found")

redirect_frozen_inventory

redirect_frozen_inventory(db, inventory_id, new_budget_id) -> bool
Reassigns a frozen (inactive) inventory record to a different project and sets is_active=True. Used after a project is deleted to move leftover stock to a replacement project. Returns False when the inventory record does not exist, is already active, or new_budget_id does not match any budget.
db
Session
required
Active SQLAlchemy session. Commits internally.
inventory_id
int
required
ID of the frozen inventory record.
new_budget_id
int
required
ID of the destination project.
return
bool
True on success; False when the record or budget is not found.
from services.inventory_service import redirect_frozen_inventory

ok = redirect_frozen_inventory(db, inventory_id=15, new_budget_id=9)
if not ok:
    print("Frozen record or target budget not found")

unfreeze_inventory

unfreeze_inventory(db, inventory_id) -> bool
Reactivates a frozen inventory record without linking it to any project (budget_id=None, budget_name=None). Returns False when the record does not exist or is already active.
db
Session
required
Active SQLAlchemy session. Commits internally.
inventory_id
int
required
ID of the frozen inventory record to reactivate.
return
bool
True when the record was unfrozen; False otherwise.
from services.inventory_service import unfreeze_inventory

ok = unfreeze_inventory(db, inventory_id=15)
if not ok:
    print("Record not found or already active")

Build docs developers (and LLMs) love