Skip to main content

Overview

The stock.request.allocation model creates the connection between stock requests and stock moves. It tracks the quantity allocated from a request to a specific move, monitors completion status, and helps compute the overall progress of stock requests. Model Name: stock.request.allocation

Fields

Relational Fields

stock_request_id
Many2one
required
Reference to stock.request. The stock request being fulfilled.Properties: ondelete="cascade"
stock_move_id
Many2one
required
Reference to stock.move. The stock move fulfilling (part of) the request.Properties: ondelete="cascade"
company_id
Many2one
Reference to res.company. The company this allocation belongs to.Related: stock_request_id.company_idProperties: readonly=True, store=True
product_id
Many2one
Reference to product.product. The product being allocated.Related: stock_request_id.product_idProperties: readonly=True
product_uom_id
Many2one
Reference to uom.uom. The unit of measure for the product.Related: stock_request_id.product_uom_idProperties: readonly=True

Quantity Fields

requested_product_uom_qty
Float
Quantity of the stock request allocated to the stock move, in the UoM of the Stock Request.This is the quantity that was originally requested from this allocation.
requested_product_qty
Float
Quantity of the stock request allocated to the stock move, in the default UoM of the product.Properties: compute="_compute_requested_product_qty"This is the converted quantity in the product’s base UoM.
allocated_product_qty
Float
Quantity of the stock request allocated to the stock move, in the default UoM of the product.Properties: copy=FalseThis represents the actual quantity that has been allocated/processed.
open_product_qty
Float
Remaining open quantity that hasn’t been fulfilled yet.Properties: compute="_compute_open_product_qty"Calculated as: requested_product_qty - allocated_product_qty (when move is not cancelled or done)

Methods

Compute Methods

_compute_requested_product_qty
method
Converts the requested quantity from the request’s UoM to the product’s default UoM.Depends on:
  • stock_request_id.product_id
  • stock_request_id.product_uom_id
  • requested_product_uom_qty
Behavior:
  • Uses UoM conversion with HALF-UP rounding method
  • Converts from product_uom_id to product_id.uom_id
stock_request/models/stock_request_allocation.py:64
@api.depends(
    "stock_request_id.product_id",
    "stock_request_id.product_uom_id",
    "requested_product_uom_qty",
)
def _compute_requested_product_qty(self):
    for rec in self:
        rec.requested_product_qty = rec.product_uom_id._compute_quantity(
            rec.requested_product_uom_qty,
            rec.product_id.uom_id,
            rounding_method="HALF-UP",
        )
_compute_open_product_qty
method
Calculates the remaining open quantity for this allocation.Depends on:
  • requested_product_qty
  • allocated_product_qty
  • stock_move_id
  • stock_move_id.state
Logic:
  • Returns 0.0 if the stock move is in state cancel or done
  • Otherwise returns requested_product_qty - allocated_product_qty (minimum 0)
stock_request/models/stock_request_allocation.py:77
@api.depends(
    "requested_product_qty",
    "allocated_product_qty",
    "stock_move_id",
    "stock_move_id.state",
)
def _compute_open_product_qty(self):
    for rec in self:
        if rec.stock_move_id.state in ["cancel", "done"]:
            rec.open_product_qty = 0.0
        else:
            rec.open_product_qty = (
                rec.requested_product_qty - rec.allocated_product_qty
            )
            if rec.open_product_qty < 0.0:
                rec.open_product_qty = 0.0

Field Details

Quantity Field Relationships

The allocation model tracks quantities at different stages:

State-Dependent Behavior

The open_product_qty field behaves differently based on the stock move state:
# Move state: 'draft', 'waiting', 'confirmed', 'assigned', 'partially_available'
open_product_qty = requested_product_qty - allocated_product_qty
# Can be > 0 if not fully allocated

Usage in Stock Request Flow

Creation

Allocations are typically created during procurement rule execution:
# In stock.request._prepare_stock_request_allocation()
allocation_vals = {
    'stock_request_id': request.id,
    'stock_move_id': move.id,
    'requested_product_uom_qty': move.product_uom_qty,
}
allocation = env['stock.request.allocation'].create(allocation_vals)

Tracking Progress

The stock request uses allocations to compute its progress:
# From stock.request._compute_qty()
for allocation in request.allocation_ids:
    if allocation.stock_move_id.picking_code == "incoming":
        incoming_qty += allocation.allocated_product_qty
    else:
        other_qty += allocation.allocated_product_qty

done_qty = abs(other_qty - incoming_qty)
open_qty = sum(request.allocation_ids.mapped("open_product_qty"))

Computing Stock Moves

Allocations link to stock moves for viewing:
# From stock.request._compute_move_ids()
move_ids = request.allocation_ids.mapped("stock_move_id")
# Then recursively get all origin moves

Data Model

Cascade Deletion

Both stock_request_id and stock_move_id have ondelete="cascade".This means:
  • Deleting a stock request deletes all its allocations
  • Deleting a stock move deletes all its allocations
Several fields are related to the stock request:
  • company_idstock_request_id.company_id (stored)
  • product_idstock_request_id.product_id
  • product_uom_idstock_request_id.product_uom_id
This provides quick access to commonly needed information without additional queries.

Usage Example

# Find allocations for a stock request
allocations = env['stock.request.allocation'].search([
    ('stock_request_id', '=', request.id)
])

# Check progress
for allocation in allocations:
    print(f"Move: {allocation.stock_move_id.name}")
    print(f"Requested: {allocation.requested_product_qty}")
    print(f"Allocated: {allocation.allocated_product_qty}")
    print(f"Open: {allocation.open_product_qty}")
    print(f"Move state: {allocation.stock_move_id.state}")

# Sum up totals
total_requested = sum(allocations.mapped('requested_product_qty'))
total_allocated = sum(allocations.mapped('allocated_product_qty'))
total_open = sum(allocations.mapped('open_product_qty'))

print(f"Total requested: {total_requested}")
print(f"Total allocated: {total_allocated}")
print(f"Total open: {total_open}")

# Find allocations for a specific move
move_allocations = env['stock.request.allocation'].search([
    ('stock_move_id', '=', move.id)
])

# Get all related stock requests
related_requests = move_allocations.mapped('stock_request_id')

Integration Points

With stock.request

  • Referenced via allocation_ids One2many field
  • Used in _compute_qty() to calculate progress
  • Used in _compute_move_ids() to find related moves
  • Created in _prepare_stock_request_allocation() and _action_use_stock_available()

With stock.move

  • Extended via stock_request_ids computed field (see stock_move.py)
  • Move state changes affect open_product_qty computation
  • Move cancellation sets open quantity to zero

With Procurement

  • Created when procurement rules generate stock moves
  • Links the procurement back to the originating request
  • Enables tracking from request → procurement → move → picking

See Also

Build docs developers (and LLMs) love