ODOO 11技术问询:订单行含任务/服务时隐藏Invoice Order按钮
Hey there! Absolutely, you can pull this off in Odoo 11 using either Python (for custom, flexible logic) or XML (direct view-based conditional visibility). Let's break both approaches down for you:
Method 1: Python + XML (Recommended for Most Cases)
This approach uses a computed field to check if any order line has a service or task, then ties that field to the button's visibility in the view.
Step 1: Add the Computed Field in Python
In your custom module's models folder, create or update the sale order inheritance file:
from odoo import models, fields, api class SaleOrder(models.Model): _inherit = 'sale.order' has_service_task = fields.Boolean( string="Has Service/Task Line", compute='_compute_has_service_task', store=False, # No need to store since it's dynamic readonly=True ) @api.depends('order_line') def _compute_has_service_task(self): for order in self: # Adjust this condition to match your exact business rule # Example 1: Check if any line has a service-type product # has_service = any(line.product_id.type == 'service' for line in order.order_line) # Example 2: Check if any line is linked to a task (e.g., via task_id) # has_task = any(line.task_id for line in order.order_line) # Combine both if needed: order.has_service_task = any( line.product_id.type == 'service' or line.task_id for line in order.order_line )
Step 2: Update the View to Hide the Button
In your custom module's views folder, add an inheritance view for the sale order form:
<odoo> <record id="sale_order_form_inherit_hide_invoice_button" model="ir.ui.view"> <field name="name">sale.order.form.inherit.hide.invoice.button</field> <field name="model">sale.order</field> <field name="inherit_id" ref="sale.view_order_form"/> <field name="arch" type="xml"> <!-- Target the "Invoice Order" button by its action name --> <xpath expr="//button[@name='action_invoice_create']" position="attributes"> <!-- Hide the button when has_service_task is True --> <attribute name="attrs">{'invisible': [('has_service_task', '=', True)]}</attribute> </xpath> </field> </record> </odoo>
Method 2: Pure XML (Simpler for Basic Conditions)
If your condition is straightforward (like checking for service-type products), you can skip the Python field and directly use a domain in the view's attrs:
<odoo> <record id="sale_order_form_inherit_hide_invoice_button_xml" model="ir.ui.view"> <field name="name">sale.order.form.inherit.hide.invoice.button.xml</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_invoice_create']" position="attributes"> <!-- Hide if any order line has a service product --> <attribute name="attrs"> {'invisible': [('order_line', '!=', False), ('order_line.product_id.type', '=', 'service')]} </attribute> </xpath> </field> </record> </odoo>
Note: This method works for simple one-line conditions but is less flexible for complex logic (like combining multiple checks for tasks and services).
Quick Tips
- Double-check the button's
nameattribute in your Odoo 11 instance (it'saction_invoice_createfor the default "Invoice Order" button) - Adjust the condition logic to match your exact definition of "has task/service" (e.g., if tasks are linked via a custom field instead of
task_id, update that part) - Remember to update your module's
__manifest__.pyto include the new model and view files, then upgrade the module to apply changes.
Let me know if you need help tweaking the logic to fit your specific workflow!
内容的提问来源于stack exchange,提问作者Nabil Taleb

