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.

Inventory in Sistema MRP lives in the Inventory table (see Data Models). Each record ties a warehouse to a material and optionally to a budget (project). The principal warehouse drives all stock reservation and dispatch logic; the obra warehouses accumulate stock only through receipts.

Adding stock to the principal warehouse

Use inventory_service.add_stock() to add units to the principal warehouse:
def add_stock(db: Session, warehouse_id, material_id, qty, user_id,
              budget_id=None, budget_name=None):
When budget_id is provided, a separate Inventory record is created (or updated) for that project. This means the same material can appear as multiple cards in the UI — one per project — giving per-project stock visibility. When budget_id is None, the stock lands in the project-less record. add_stock() also writes a Movement(movement_type="IN", reference_type="manual") to the movements log. In the Inventario Principal page, the optional Descontar de presupuesto selector lets you tie the stock addition to an active project; the estimated cost (qty × unit_price) is deducted from the selected budget automatically.
Every call to add_stock() ends with reprocess_requirements(db). This scans all pending and partial requirements owned by the same client and calls reserve_stock() for any items still in pending status. Requirements that become fully reserved are returned in the result list and surfaced as info messages in the UI.

Stock invariant

For every principal-warehouse Inventory record:
available = stock - reserved
FieldMeaning
stockTotal physical units on hand
reservedUnits committed to pending requirements
availableUnits free for new requirements or manual removal
reserve_stock() checks total_available >= requested_qty across all active records for the material before incrementing reserved. It does not call db.commit() — the caller (e.g. create_requirement) commits after processing all items in the requirement.
def reserve_stock(db: Session, warehouse_id, material_id, qty):
    # Checks available = stock - reserved across all active budget records (FIFO)
    # Returns True on success, False if insufficient stock
    # Does NOT commit — caller must commit

Removing stock manually

remove_stock() decrements stock across active inventory records using FIFO order (by Inventory.id):
def remove_stock(db: Session, warehouse_id, material_id, qty, user_id):
    # Returns True on success, False if total stock < qty
    # Writes a Movement(movement_type="OUT", reference_type="manual")
Note that remove_stock() distributes the reduction across all active budget records in id order. It does not check reserved — it is the operator’s responsibility to only remove truly available stock.

Frozen inventory

An Inventory record becomes frozen (is_active = False) when the project it was linked to is deleted. Frozen records do not appear in the active inventory view and cannot be reserved for new requirements. The Stock Congelado section on the Inventario page lists these records. Two recovery actions are available:
  • Redirigir a proyecto — calls redirect_frozen_inventory(db, inventory_id, new_budget_id) to reassign the record to an active project and set is_active = True.
  • Liberar sin proyecto — calls unfreeze_inventory(db, inventory_id) to set budget_id = None and is_active = True, making the stock available without a project association.
Frozen records cannot be reserved or dispatched. If a requirement is created and the only stock for a material is frozen, the corresponding RequirementItem will be set to pending. Resolve frozen records before expecting automatic reservation to succeed.

Build docs developers (and LLMs) love