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.
Backup Database
Create a database backup before installation.
Install During Low Activity
Schedule installation during off-peak hours due to computation time.
Install Module
Navigate to Apps , search for “Stock Return Request”, and click Install .
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
Navigate to Returns
Go to Inventory > Operations > Return Request and click Create .
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
Select Partner/Location
Depending on return type:
Supplier Returns : Select supplier
Customer Returns : Select customer
Internal Returns : Select location
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)
Or Use Suggestion Wizard
Click Suggest Products to automatically:
List returnable products from selected partner
Show returnable quantities
Quick-add products to return
Confirm Return
Click Confirm to create return picking.
Process Return
Process the created picking:
Validate quantities
Mark as done
Products returned to stock
Returning to Supplier
Scenario : Defective products received from supplier.
Create Return Request
Go to Inventory > Operations > Return Request .
Configure
Return Type : To Supplier
Supplier : Select the vendor
Reason : Defective Product
Add Products
Add the defective products and quantities.
Confirm
Confirm to create outgoing picking to supplier.
Ship Products
Process the picking to ship products back.
Returning to Customer
Scenario : Return product delivered to wrong customer.
Create Return Request
Create new return request.
Configure
Return Type : To Customer
Customer : Select the customer
Reason : Wrong Delivery
Add Products
Add products to return to customer.
Process
Confirm and process delivery back to customer.
Internal Location Returns
Scenario : Return excess stock from production floor to warehouse.
Create Return Request
Create new internal return request.
Configure
Return Type : Internal
From Location : Production floor
To Location : Main warehouse
Add Products
Add products to return.
Process Transfer
Confirm and process internal transfer.
Using Suggest Return Wizard
Quickly create returns from previous deliveries:
Open Return Request
Create new return request and select partner.
Click Suggest Products
Click Suggest Products button.
Review Suggestions
Wizard shows:
All products delivered to/from partner
Returnable quantity for each product
Original delivery reference
Select Products
Check products to include in return.
Adjust Quantities
Modify quantities if not returning full amount.
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.
Quality Issue Identified
QC team identifies defective batch.
Create Return
Create return request to supplier with reason “Defective”.
Add Products
Add defective products with quantities.
Get Authorization
Contact supplier for return authorization (RMA).
Process Return
Confirm return and ship products back.
Track Refund
Link return to vendor credit or refund.
Customer Returns Processing
Scenario : Customer returns products (RMA process).
Customer Requests Return
Customer contacts support for return.
Issue RMA
Create return request with RMA number.
Customer Ships
Customer ships products back.
Receive Return
Process incoming return picking.
Inspect Products
QC inspects returned products.
Process Refund
Issue credit note or refund to customer.
Excess Inventory Returns
Scenario : Return excess inventory from workstation to warehouse.
Identify Excess
Workstation has excess materials.
Create Internal Return
Create internal return request.
Transfer Products
Move products from workstation to warehouse.
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:
Calculate equivalent quantity in default UoM
Create return with calculated quantity
Manually note the original UoM in return reason/notes
Troubleshooting
Cannot Return Quantity
Problem : System prevents returning desired quantity.
Solutions :
Check qty_returnable on original move
Verify products were actually received/delivered
Check if partial returns already made
Ensure move is in done state
Verify no other pending returns for same move
No Returnable Products in Suggestion
Problem : Suggest wizard shows no products.
Solutions :
Verify partner has completed deliveries/receipts
Check if all quantities already returned
Ensure moves are in done state
Review move history for selected partner
Return Picking Not Created
Problem : Confirming return doesn’t create picking.
Solutions :
Verify return lines have quantities
Check warehouse configuration
Review picking types exist for return type
Check logs for errors
Wrong Returnable Quantity
Problem : qty_returnable shows unexpected value.
Solutions :
Check original move quantity
Review previous return history
Verify returned moves linked correctly
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