How to Transfer Chatter History from Sales to Delivery in Odoo 18: Complete Guide
By Braincuber Team
Published on December 29, 2025
Communication continuity across departments is essential for smooth business operations. In Odoo 18, the Chatter feature serves as a centralized communication hub where teams can log messages, schedule activities, and track important conversations. However, when a sales order transitions into delivery, the warehouse team often misses out on critical context stored in the sales chatter.
This tutorial demonstrates how to transfer chatter history from sales orders to delivery orders in Odoo 18, ensuring your warehouse team has complete visibility into customer requirements, special instructions, and team discussions. We'll walk through both automatic and selective transfer methods with practical code examples.
What You'll Learn:
- Understanding Chatter's role in cross-department communication
- Creating custom buttons to trigger chatter transfer
- Writing Python methods to copy messages between models
- Implementing selective message filtering (notes, activities, emails)
- Best practices for maintaining communication continuity
Understanding Chatter in Odoo 18
Before diving into transferring chatter history, let's understand what makes Odoo's Chatter such a powerful communication tool:
Send Messages
Send emails directly from records to followers with template support
Log Notes
Internal notes visible only to team members for documentation
Schedule Activities
Assign tasks with deadlines visible in activity dashboards
Attachments
Upload and access files related to specific records
Why Transfer Chatter from Sales to Delivery?
Consider this real-world scenario: A customer places an order for office furniture and mentions in the sales order chatter that they need special protective packaging because the delivery location has narrow corridors. Additionally, the sales team logged a note about preferred delivery timing between 2-4 PM.
Without chatter history transfer, the warehouse team processing the delivery order would be completely unaware of these critical instructions. This could lead to:
- Improper packaging causing damage during delivery
- Failed delivery attempts due to timing constraints
- Customer dissatisfaction and potential re-work
- Time wasted switching between sales and delivery records
Implementation Method 1: Complete Chatter Transfer
Let's start by implementing a button-triggered method that transfers all chatter messages from a sales order to its corresponding delivery order.
Step 1: Add Transfer Button to Sales Order Form
First, we need to extend the sales order form view to include a button that triggers the chatter transfer action.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_order_form_inherit_chatter_transfer" model="ir.ui.view">
<field name="name">sale.order.form.chatter.transfer</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='action_draft']" position="after">
<button name="action_transfer_chatter_to_delivery"
string="Transfer Chatter to Delivery"
type="object"
class="btn-primary"
attrs="{'invisible': [('picking_ids', '=', [])]}" />
</xpath>
</field>
</record>
</odoo>
Key Points: The button only appears when delivery orders exist (picking_ids is not empty). This prevents errors when trying to transfer to non-existent deliveries.
Step 2: Implement Python Transfer Method
Now let's write the Python method that handles the actual chatter message transfer:
from odoo import models, api
class SaleOrder(models.Model):
_inherit = 'sale.order'
def action_transfer_chatter_to_delivery(self):
"""
Transfers all chatter messages from sales order to
the first non-cancelled delivery order.
"""
# Fetch all messages from current sales order
sale_messages = self.env["mail.message"].search([
("res_id", "=", self.id),
("model", "=", "sale.order")
], order='create_date asc')
# Get active delivery orders (exclude cancelled)
active_deliveries = self.picking_ids.filtered(
lambda p: p.state != 'cancel'
)
if not active_deliveries:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': 'No Active Deliveries',
'message': 'There are no active delivery orders to transfer chatter to.',
'type': 'warning',
'sticky': False,
}
}
# Transfer to first active delivery
target_delivery = active_deliveries[0]
for message in sale_messages:
message.copy({
"model": "stock.picking",
"res_id": target_delivery.id
})
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': 'Success',
'message': f'{len(sale_messages)} messages transferred to delivery {target_delivery.name}',
'type': 'success',
'sticky': False,
}
}
Implementation Method 2: Selective Message Transfer
In many cases, you don't want to transfer all messages—only specific types like internal notes or logged activities. Here's how to implement selective filtering:
from odoo import models, api
class SaleOrder(models.Model):
_inherit = 'sale.order'
def action_transfer_chatter_notes_only(self):
"""
Transfers only internal notes (Log Note messages) from
sales order to delivery order.
"""
# Fetch all messages from sales order
sale_messages = self.env["mail.message"].search([
("res_id", "=", self.id),
("model", "=", "sale.order")
], order='create_date asc')
# Get active deliveries
active_deliveries = self.picking_ids.filtered(
lambda p: p.state != 'cancel'
)
if not active_deliveries:
return
target_delivery = active_deliveries[0]
# Filter for "Note" subtype messages only
notes_only = sale_messages.filtered(
lambda m: m.subtype_id.name == 'Note'
)
transferred_count = 0
for note in notes_only:
note.copy({
"model": "stock.picking",
"res_id": target_delivery.id
})
transferred_count += 1
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': 'Notes Transferred',
'message': f'{transferred_count} internal notes transferred successfully',
'type': 'success',
}
}
Available Message Subtypes for Filtering
| Subtype Name | Description | Use Case |
|---|---|---|
Note |
Internal log notes | Team instructions, internal context |
Activities |
Scheduled activities | Follow-up tasks, deadlines |
Discussions |
Email discussions | Customer communications |
Testing the Implementation
Let's walk through testing the chatter transfer functionality:
- Create a Sales Order: Navigate to Sales → Orders → Create and add products to create a new quotation.
- Add Chatter Messages: In the sales order chatter, log several notes like "Customer requests eco-friendly packaging" and "Deliver between 10 AM - 12 PM".
- Confirm the Order: Click Confirm to create the sales order and generate delivery orders.
- Transfer Chatter: Click the "Transfer Chatter to Delivery" button on the sales order form.
- Verify Transfer: Open the delivery order by clicking the Delivery smart button and check the chatter section—all messages should now appear there.
Important Note: Messages are copied, not moved. Original messages remain in the sales order chatter for reference.
Advanced: Automatic Transfer on Delivery Creation
Instead of manual button clicks, you can automate chatter transfer when delivery orders are created:
from odoo import models, api
class SaleOrder(models.Model):
_inherit = 'sale.order'
def action_confirm(self):
"""Override order confirmation to auto-transfer chatter"""
result = super(SaleOrder, self).action_confirm()
# Transfer relevant messages to newly created deliveries
self._auto_transfer_chatter_to_deliveries()
return result
def _auto_transfer_chatter_to_deliveries(self):
"""Internal method to auto-transfer important messages"""
# Get all notes and activities
important_messages = self.env["mail.message"].search([
("res_id", "=", self.id),
("model", "=", "sale.order"),
("subtype_id.name", "in", ["Note", "Activities"])
], order='create_date asc')
# Transfer to all active deliveries
for delivery in self.picking_ids.filtered(lambda p: p.state != 'cancel'):
for message in important_messages:
message.copy({
"model": "stock.picking",
"res_id": delivery.id
})
Frequently Asked Questions
Can I transfer chatter to multiple delivery orders?
Yes. Instead of targeting only the first delivery, you can loop through all active deliveries using a for loop in the picking_ids.filtered() result to transfer messages to multiple delivery orders.
Do transferred messages maintain the original timestamp?
Yes. When using the copy() method, Odoo preserves the original create_date, ensuring the chronological order of messages is maintained in the delivery chatter.
Can I filter by message author?
Absolutely. Add author_id to your filter criteria. For example, to only transfer messages from specific users: messages.filtered(lambda m: m.author_id.id in user_ids_list)
Are attachments included when copying messages?
Yes. The copy() method includes associated attachments by default, so files attached to chatter messages will also be available in the delivery order.
How do I prevent duplicate transfers?
Add a custom boolean field like chatter_transferred to the sale.order model and check it before transferring. Set it to True after successful transfer to prevent duplicate operations.
Can this method work for other model transfers?
Yes. This approach can be adapted for any model pair in Odoo 18, such as purchase orders to receipts, projects to tasks, or leads to opportunities. Just change the model names accordingly.
Conclusion
Transferring chatter history from sales to delivery orders in Odoo 18 creates seamless communication continuity across departments. Whether you implement manual transfer buttons or automatic synchronization, your warehouse team will have instant access to critical customer requirements and team discussions without switching between records.
This functionality can significantly reduce communication gaps, minimize errors, and improve customer satisfaction. Start with the basic implementation and gradually expand to selective filtering based on your specific business needs.
Need Help Implementing Chatter Transfer in Odoo 18?
Our Odoo experts can help you customize chatter functionality, automate workflows, and optimize inter-departmental communication across your Odoo instance.
