Skip to main content
The stock_return_request module enables the management of stock returns from any location, allowing returns to suppliers, customers, or internal locations by reverting corresponding pickings.

Overview

Module Name: stock_return_request
Version: 18.0.1.0.1
License: AGPL-3
Dependencies: stock
Author: Tecnativa, OCA
Category: Stock
This module provides a comprehensive system for managing stock returns to suppliers, customers, or internal locations by creating reverse pickings that revert previous transfers.

Key Features

Return Management

  • Return stock to suppliers (purchase returns)
  • Return stock to customers (customer returns)
  • Return stock to internal locations
  • Reverse corresponding pickings automatically
  • Track returnable quantities

Returnable Quantity Tracking

  • New field qty_returnable on stock moves
  • Automatically computed based on move history
  • Considers already returned quantities
  • Prevents over-returning

Flexible Return Creation

  • Create returns from multiple sources
  • Select specific products and quantities
  • Suggest returnable products automatically
  • Group returns by partner or location

Return Reporting

  • Print return documentation
  • Track return history
  • Analyze return patterns
  • Report generation for returns

Installation

Heavy Installation: The installation computes qty_returnable for all existing stock moves, which can be time-consuming for large databases.
1

Backup Database

Create a database backup before installation.
2

Install During Low Activity

Schedule installation during off-peak hours due to computation time.
3

Install Module

Navigate to Apps, search for “Stock Return Request”, and click Install.
4

Wait for Completion

The installation hook computes returnable quantities for existing moves. This may take time.

Configuration

No specific configuration required. The module works out of the box.

Optional Configuration

Configure return reasons (optional):
Inventory > Configuration > Return Reasons
└── Create reasons like:
    ├── Defective Product
    ├── Wrong Product Shipped
    ├── Customer Mistake
    └── Excess Inventory

Usage

Creating a Return Request

1

Navigate to Returns

Go to Inventory > Operations > Return Request and click Create.
2

Select Return Type

Choose the type of return:
  • To Supplier: Returning to a supplier
  • To Customer: Returning to a customer (rare)
  • Internal: Internal location return
3

Select Partner/Location

Depending on return type:
  • Supplier Returns: Select supplier
  • Customer Returns: Select customer
  • Internal Returns: Select location
4

Add Return Lines

Add products to return:
  • Click Add a line
  • Select product
  • Enter quantity to return
  • Verify quantity is within returnable amount
  • Add return reason (optional)
5

Or Use Suggestion Wizard

Click Suggest Products to automatically:
  • List returnable products from selected partner
  • Show returnable quantities
  • Quick-add products to return
6

Confirm Return

Click Confirm to create return picking.
7

Process Return

Process the created picking:
  • Validate quantities
  • Mark as done
  • Products returned to stock

Returning to Supplier

Scenario: Defective products received from supplier.
1

Create Return Request

Go to Inventory > Operations > Return Request.
2

Configure

  • Return Type: To Supplier
  • Supplier: Select the vendor
  • Reason: Defective Product
3

Add Products

Add the defective products and quantities.
4

Confirm

Confirm to create outgoing picking to supplier.
5

Ship Products

Process the picking to ship products back.

Returning to Customer

Scenario: Return product delivered to wrong customer.
1

Create Return Request

Create new return request.
2

Configure

  • Return Type: To Customer
  • Customer: Select the customer
  • Reason: Wrong Delivery
3

Add Products

Add products to return to customer.
4

Process

Confirm and process delivery back to customer.

Internal Location Returns

Scenario: Return excess stock from production floor to warehouse.
1

Create Return Request

Create new internal return request.
2

Configure

  • Return Type: Internal
  • From Location: Production floor
  • To Location: Main warehouse
3

Add Products

Add products to return.
4

Process Transfer

Confirm and process internal transfer.

Using Suggest Return Wizard

Quickly create returns from previous deliveries:
1

Open Return Request

Create new return request and select partner.
2

Click Suggest Products

Click Suggest Products button.
3

Review Suggestions

Wizard shows:
  • All products delivered to/from partner
  • Returnable quantity for each product
  • Original delivery reference
4

Select Products

Check products to include in return.
5

Adjust Quantities

Modify quantities if not returning full amount.
6

Add to Return

Click Add to Return to populate return lines.

Data Models

Stock Return Request (stock.return.request)

Main model for return requests:
class StockReturnRequest(models.Model):
    _name = 'stock.return.request'
    _description = 'Stock Return Request'
    
    name = fields.Char(          # Return reference
        string='Reference',
        required=True,
        default='/',
    )
    
    partner_id = fields.Many2one(  # Partner (supplier/customer)
        'res.partner',
        string='Partner'
    )
    
    return_type = fields.Selection([
        ('supplier', 'To Supplier'),
        ('customer', 'To Customer'),
        ('internal', 'Internal'),
    ], string='Return Type',
       required=True)
    
    state = fields.Selection([
        ('draft', 'Draft'),
        ('confirmed', 'Confirmed'),
        ('done', 'Done'),
        ('cancel', 'Cancelled'),
    ], default='draft')
    
    line_ids = fields.One2many(    # Return lines
        'stock.return.request.line',
        'return_id',
        string='Products to Return'
    )
    
    picking_ids = fields.One2many( # Generated pickings
        'stock.picking',
        'return_request_id',
        string='Return Pickings'
    )

Stock Return Request Line (stock.return.request.line)

Return request line items:
class StockReturnRequestLine(models.Model):
    _name = 'stock.return.request.line'
    
    return_id = fields.Many2one(   # Parent return request
        'stock.return.request'
    )
    
    product_id = fields.Many2one(  # Product to return
        'product.product',
        required=True
    )
    
    product_qty = fields.Float(    # Quantity to return
        string='Quantity',
        required=True
    )
    
    product_uom_id = fields.Many2one(  # Unit of measure
        'uom.uom'
    )
    
    qty_returnable = fields.Float( # Max returnable qty
        compute='_compute_qty_returnable'
    )
    
    move_id = fields.Many2one(     # Original stock move
        'stock.move',
        string='Original Move'
    )
    
    reason = fields.Text(          # Return reason
        string='Reason'
    )

Stock Move (Extended)

Adds returnable quantity tracking:
class StockMove(models.Model):
    _inherit = 'stock.move'
    
    qty_returnable = fields.Float(
        string='Returnable Quantity',
        compute='_compute_qty_returnable',
        store=True,
        help='Quantity that can still be returned'
    )
    
    @api.depends('product_uom_qty', 'returned_move_ids')
    def _compute_qty_returnable(self):
        for move in self:
            # Calculate: original qty - already returned qty
            returned_qty = sum(
                move.returned_move_ids.mapped('product_uom_qty')
            )
            move.qty_returnable = move.product_uom_qty - returned_qty

Views and Menus

Inventory
├── Operations
│   ├── Return Request
│   │   ├── All Returns
│   │   ├── Supplier Returns
│   │   ├── Customer Returns
│   │   └── Internal Returns
└── Reporting
    └── Return Analysis

Available Views

  • Tree View: List of return requests
  • Form View: Detailed return form with lines
  • Pivot View: Return analysis and reporting
  • Graph View: Return trends and statistics

Wizards

Suggest Return Request Wizard

Model: suggest.return.request Automatically suggests products that can be returned:
class SuggestReturnRequest(models.TransientModel):
    _name = 'suggest.return.request'
    
    return_id = fields.Many2one(     # Target return request
        'stock.return.request'
    )
    
    line_ids = fields.One2many(      # Suggested products
        'suggest.return.request.line',
        'wizard_id'
    )
    
    def action_suggest(self):
        """Find returnable products for selected partner"""
        # Query stock moves from/to partner
        # Calculate returnable quantities
        # Create wizard lines
        
    def action_add_to_return(self):
        """Add selected products to return request"""
        # Create return request lines
        # From selected wizard lines

Reports

Stock Return Report

Template: stock_return_report.xml Printable return document includes:
  • Return request reference
  • Partner information
  • Return type and reason
  • List of products with quantities
  • Original delivery references
  • Return authorization details

Return Analysis Report

Analyze return patterns:
  • Returns by partner
  • Returns by product
  • Return reasons breakdown
  • Return value analysis
  • Trends over time

Use Cases

Defective Product Returns

Scenario: Quality control finds defective products from supplier.
1

Quality Issue Identified

QC team identifies defective batch.
2

Create Return

Create return request to supplier with reason “Defective”.
3

Add Products

Add defective products with quantities.
4

Get Authorization

Contact supplier for return authorization (RMA).
5

Process Return

Confirm return and ship products back.
6

Track Refund

Link return to vendor credit or refund.

Customer Returns Processing

Scenario: Customer returns products (RMA process).
1

Customer Requests Return

Customer contacts support for return.
2

Issue RMA

Create return request with RMA number.
3

Customer Ships

Customer ships products back.
4

Receive Return

Process incoming return picking.
5

Inspect Products

QC inspects returned products.
6

Process Refund

Issue credit note or refund to customer.

Excess Inventory Returns

Scenario: Return excess inventory from workstation to warehouse.
1

Identify Excess

Workstation has excess materials.
2

Create Internal Return

Create internal return request.
3

Transfer Products

Move products from workstation to warehouse.
4

Update Inventory

Inventory updated in both locations.

Best Practices

Return Authorization

Get RMA First: Always obtain return authorization (RMA) from supplier before shipping returns.
Document Reasons: Clearly document return reasons for tracking and analysis.

Quantity Verification

Check Returnable Qty: Always verify quantity to return doesn’t exceed returnable amount.
Physical Count: Perform physical count before creating return to ensure accuracy.

Process Management

Standardize Process: Create standard procedures for different return types.
Track Timelines: Set and monitor timelines for return processing.

Quality Control

Inspect Before Return: Inspect products before returning to supplier to verify defect.
Photo Documentation: Take photos of defective products for records.

Known Issues and Roadmap

UoM Limitation: Products are returned in the default product UoM. UoM conversions are not currently implemented.

Workaround for UoM

If you need to return in different UoM:
  1. Calculate equivalent quantity in default UoM
  2. Create return with calculated quantity
  3. Manually note the original UoM in return reason/notes

Troubleshooting

Cannot Return Quantity

Problem: System prevents returning desired quantity. Solutions:
  1. Check qty_returnable on original move
  2. Verify products were actually received/delivered
  3. Check if partial returns already made
  4. Ensure move is in done state
  5. Verify no other pending returns for same move

No Returnable Products in Suggestion

Problem: Suggest wizard shows no products. Solutions:
  1. Verify partner has completed deliveries/receipts
  2. Check if all quantities already returned
  3. Ensure moves are in done state
  4. Review move history for selected partner

Return Picking Not Created

Problem: Confirming return doesn’t create picking. Solutions:
  1. Verify return lines have quantities
  2. Check warehouse configuration
  3. Review picking types exist for return type
  4. Check logs for errors

Wrong Returnable Quantity

Problem: qty_returnable shows unexpected value. Solutions:
  1. Check original move quantity
  2. Review previous return history
  3. Verify returned moves linked correctly
  4. Recalculate returnable quantities:
env['stock.move'].search([])._compute_qty_returnable()

Advanced Features

Custom Return Workflows

Extend return process with custom logic:
class StockReturnRequest(models.Model):
    _inherit = 'stock.return.request'
    
    def action_confirm(self):
        # Custom validation
        for return_request in self:
            if return_request.return_type == 'supplier':
                # Require RMA number for supplier returns
                if not return_request.rma_number:
                    raise UserError("RMA number required for supplier returns.")
        
        return super().action_confirm()

Return Analytics

Query return data for analysis:
# Find most returned products
returns = env['stock.return.request.line'].read_group(
    domain=[('return_id.state', '=', 'done')],
    fields=['product_id', 'product_qty'],
    groupby=['product_id'],
    orderby='product_qty desc',
    limit=10
)

# Returns by supplier
supplier_returns = env['stock.return.request'].search([
    ('return_type', '=', 'supplier'),
    ('state', '=', 'done'),
])

Integration with Quality Module

Link returns with quality checks:
class StockReturnRequest(models.Model):
    _inherit = 'stock.return.request'
    
    quality_check_ids = fields.One2many(
        'quality.check',
        'return_request_id',
        string='Quality Checks'
    )
    
    def action_confirm(self):
        # Create quality check for return inspection
        super().action_confirm()
        for line in self.line_ids:
            self.env['quality.check'].create({
                'product_id': line.product_id.id,
                'return_request_id': self.id,
                'test_type': 'inspection',
            })

Stock Module

Odoo standard stock management

Stock Request Core

Internal stock requests (different from returns)
Stock Return Request is independent from the Stock Request modules - it doesn’t require stock_request to be installed.

Contributors

Developed by:
  • Tecnativa (Primary development)
    • Sergio Teruel
    • Pedro M. Baeza
    • David Vidal
    • César A. Sánchez
    • Carlos Lopez
  • Pro Thai Technology
    • Prapassorn Sornkaew

Build docs developers (and LLMs) love