Hey there,
I'm currently working on a small tweak for the invoices from the account module.
I want to have a button in the button box of the invoice (next to the timesheet button) which points to the sale order from which the invoice was created. So basically like it's added in the sale_timesheet module, which adds a button to the sale order in the single timesheets.
Refs:
sale_timesheet\views\project_task_views.xml Lines 19-35
sale_timesheet\models\project.py Lines 102-111
What I've done until now:
Created a custom module
Created an xml which inherits from the account invoice form and added the button via xpath
Created an python file which inherits from AccountInvoice to add a action_view_so function
The button shows just fine in the view, shows the origin SO with the correct number (used a statinfo widget) but the function is missing the right reference. After some tries, I decided to create an account in the forums and ask directly instead of reading up old threads which doesn't solve my issue so far.
After clicking on the action this is the error message, which refers to my added function:
"res_id": self.origin.order_id.id, AttributeError: 'str' object has no attribute 'order_id'
This is my record in the xml:
<record id="account_invoice_view_sale_order_button" model="ir.ui.view">
<field name="name">account.invoice.form.inherit.sobutton</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box'][last()]" position="inside">
<button type="object" name="action_view_so" class="oe_stat_button" icon="fa-dollar">
<field name="origin" widget="statinfo" string="Sales Order"/>
</button>
</xpath>
</field>
</record>
This is the class extension in the python file:
class AccountInvoice(models.Model):
_inherit = "account.invoice"
@api.multi
def action_view_so(self):
self.ensure_one()
return {
"type": "ir.actions.act_window",
"res_model": "sale.order",
"views": [[False, "form"]],
"res_id": self.origin.order_id.id,
"context": {"create": False, "show_sale": True},
}
So the res_id is not the correct one, but I can't figure out which one would be the correct reference path. I would really appreciate help from your side to point me to the right direction. Many thanks in advance.
EDIT:
Just after a little more research and trial&error, I've solved it for me.
If someone has the same issue or want to achieve the same functionality, the solution was to convert the string value of the sale order, which is located in the origin field of the invoice, to the correct sale order id.
So the action_view_so function from above has to be like this:
@api.multi
def action_view_so(self):
self.ensure_one()
sale_line_ids = self.invoice_line_ids.mapped('sale_line_ids')
if sale_line_ids:
sale_order = sale_line_ids[0].order_id
return {
"type": "ir.actions.act_window",
"res_model": "sale.order",
"views": [[False, "form"]],
"res_id": sale_order.id,
"context": {"create": False, "show_sale": True},
}
Also the thread wasn't yet approved, but just to contribute to the knowledge base I wanted to share the solution.