Button access not working on 6.0

I have a problem with the “Post” button not showing up on the account.invoice form after upgrading to version 6.0. I have setup my server with a res.group that allows user to post a invoice even though they are not in the account.group_account. The XML definition that does this is as follows:

<record model="res.group" id="group_out_invoice_only">
       <field name="name">Customer Invoices</field>
</record>

<record model="ir.model.button-res.group" id="invoice_post_button_group_out_invoice_only">
      <field name="button" ref="account_invoice.invoice_post_button"/>
      <field name="group" ref="group_out_invoice_only"/>
</record>

In Tryton previous versions, the button Post appears when the user is added to the Customer Invoices group, but not anymore in version 6.0. Anyone has any idea why this is happening?

The access rights on the button are only disabling the button but not hide it. So it should not be an access right issue.
But the button is invisible if the invoice is not in draft or validated state or posted with a move.

What you mention is what I understand too as the expected behavior, however this is not what is happening in reality which is why I need help. Can you help me verify if you can reproduce this problem? I am attaching the complete XML definition that enables all the access needed to open the customer invoice form without account.group_account. I used trytond-admin to updated the DB but I still have the Post button hidden even with the invoice in draft or validated state. The user must be added into this new group called Customer Invoices defined below.

<!-- Enable menu -->
    <record model="res.group" id="group_out_invoice_only">
        <field name="name">Customer Invoices</field>
    </record>
    <record model="ir.ui.menu-res.group" id="menu_account_group_out_invoice_only">
      <field name="menu" ref="account.menu_account"/>
      <field name="group" ref="group_out_invoice_only"/>
    </record>
    <record model="ir.ui.menu-res.group" id="menu_account_invoice_group_out_invoice_only">
      <field name="menu" ref="account_invoice.menu_invoices"/>
      <field name="group" ref="group_out_invoice_only"/>
    </record>
    <record model="ir.ui.menu-res.group" id="menu_account_invoice_out_group_out_invoice_only">
      <field name="menu" ref="account_invoice.menu_invoice_out_form"/>
      <field name="group" ref="group_out_invoice_only"/>
    </record>
<!-- Access to the minimum models -->
   <record model="ir.model.access" id="access_account_group_out_invoice_only">
      <field name="model" search="[('model', '=', 'account.account')]"/>
      <field name="group" ref="group_out_invoice_only"/>
      <field name="perm_read" eval="True"/>
      <field name="perm_write" eval="False"/>
      <field name="perm_create" eval="False"/>
      <field name="perm_delete" eval="False"/>
    </record>
    <record model="ir.model.access" id="access_account_tax_group_out_invoice_only">
      <field name="model" search="[('model', '=', 'account.tax')]"/>
      <field name="group" ref="group_out_invoice_only"/>
      <field name="perm_read" eval="True"/>
      <field name="perm_write" eval="False"/>
      <field name="perm_create" eval="False"/>
      <field name="perm_delete" eval="False"/>
    </record>
    <record model="ir.model.access" id="access_account_type_group_out_invoice_only">
      <field name="model" search="[('model', '=', 'account.account.type')]"/>
      <field name="group" ref="group_out_invoice_only"/>
      <field name="perm_read" eval="True"/>
      <field name="perm_write" eval="False"/>
      <field name="perm_create" eval="False"/>
      <field name="perm_delete" eval="False"/>
    </record>
    <record model="ir.model.access" id="access_account_invoice_group_out_invoice_only">
      <field name="model" search="[('model', '=', 'account.invoice')]"/>
      <field name="group" ref="group_out_invoice_only"/>
      <field name="perm_read" eval="True"/>
      <field name="perm_write" eval="True"/>
      <field name="perm_create" eval="True"/>
      <field name="perm_delete" eval="False"/>
    </record>
    <record model="ir.model.access" id="access_account_invoice_line_group_out_invoice_only">
      <field name="model" search="[('model', '=', 'account.invoice.line')]"/>
      <field name="group" ref="group_out_invoice_only"/>
      <field name="perm_read" eval="True"/>
      <field name="perm_write" eval="True"/>
      <field name="perm_create" eval="True"/>
      <field name="perm_delete" eval="False"/>
    </record>
    <record model="ir.model.access" id="access_account_invoice_line_tax_group_out_invoice_only">
      <field name="model" search="[('model', '=', 'account.invoice.line-account.tax')]"/>
      <field name="group" ref="group_out_invoice_only"/>
      <field name="perm_read" eval="True"/>
      <field name="perm_write" eval="True"/>
      <field name="perm_create" eval="True"/>
      <field name="perm_delete" eval="False"/>
    </record>
    <record model="ir.model.access" id="access_account_invoice_tax_group_out_invoice_only">
      <field name="model" search="[('model', '=', 'account.invoice.tax')]"/>
      <field name="group" ref="group_out_invoice_only"/>
      <field name="perm_read" eval="True"/>
      <field name="perm_write" eval="True"/>
      <field name="perm_create" eval="True"/>
      <field name="perm_delete" eval="False"/>
    </record>

<!-- Limit to customer invoices -->
    <record model="ir.rule.group" id="rule_group_invoice_out_only">
      <field name="name">Access Customer Invoice Only</field>
      <field name="model" search="[('model', '=', 'account.invoice')]"/>
      <field name="global_p" eval="False"/>
      <field name="perm_read" eval="True"/>
      <field name="perm_write" eval="True"/>
      <field name="perm_create" eval="True"/>
      <field name="perm_delete" eval="False"/>
    </record>
    <record model="ir.rule" id="rule_invoice_out_only1">
      <field name="domain" eval="[['type', '=', 'out']]" pyson="1"/>
      <field name="rule_group" ref="rule_group_invoice_out_only"/>
    </record>

<!-- Buttons -->
   <record model="ir.rule.group-res.group" id="rule_group_out_invoice_only-invoice">
      <field name="rule_group" ref="rule_group_invoice_out_only"/>
      <field name="group" ref="group_out_invoice_only"/>
    </record>
    <record model="ir.model.button-res.group" id="invoice_draft_button_group_out_invoice_only">
      <field name="button" ref="account_invoice.invoice_draft_button"/>
      <field name="group" ref="group_out_invoice_only"/>
    </record>
    <record model="ir.model.button-res.group" id="invoice_post_button_group_out_invoice_only">
      <field name="button" ref="account_invoice.invoice_post_button"/>
      <field name="group" ref="group_out_invoice_only"/>
    </record>
    <record model="ir.model.button-res.group" id="invoice_validate_button_group_out_invoice_only">
      <field name="button" ref="account_invoice.invoice_validate_button"/>
      <field name="group" ref="group_out_invoice_only"/>
    </record>

I still haven’t been able to figure out why the Post button remains hidden. I tried comparing the XHR on the model.account.invoice.fields_view_get between the admin user and the limited user. I found that the account.invoice form returned for the limited user does not return the button tag and instead it returns:

<label id="hidden post-0"/>

in the position where I would find the post button definition. The most strange thing is that I can see the Pay button tag present right after, which the limited user does not have access to. So anyone have any clue what is happening?

The complete buttons section is the following:

<group col="-1" colspan="3" id="buttons">
<button name="cancel" icon="tryton-cancel" string="Cancelar" help="Cancelar la factura" confirm="¿Está seguro que quiere cancelar la factura?" states="{"invisible": {"__class__": "Not", "v": {"__class__": "Eval", "v": "allow_cancel", "d": false}}, "depends": ["allow_cancel"], "readonly": true}" type="class"/>
<button name="draft" icon="tryton-back" string="Borrador" help="" confirm="" states="{"invisible": {"__class__": "Or", "s": [{"__class__": "Not", "v": {"__class__": "In", "k": {"__class__": "Eval", "v": "state", "d": ""}, "v": ["cancelled", "validated"]}}, {"__class__": "And", "s": [{"__class__": "Equal", "s1": {"__class__": "Eval", "v": "state", "d": ""}, "s2": "cancelled"}, {"__class__": "Bool", "v": {"__class__": "Eval", "v": "cancel_move", "d": -1}}]}]}, "icon": {"__class__": "If", "c": {"__class__": "Equal", "s1": {"__class__": "Eval", "v": "state", "d": ""}, "s2": "cancelled"}, "t": "tryton-undo", "e": "tryton-back"}, "depends": ["state"]}" type="class"/>
<button name="validate_invoice" icon="tryton-forward" string="Validar" help="También conocida como proforma" confirm="" states="{"pre_validate": ["OR", ["invoice_date", "!=", null], ["type", "!=", "in"]], "invisible": {"__class__": "Not", "v": {"__class__": "Equal", "s1": {"__class__": "Eval", "v": "state", "d": ""}, "s2": "draft"}}, "depends": ["state"]}" type="class"/>
<label id="hidden post-0"/>
<button name="pay" icon="tryton-forward" string="Pagar" help="" confirm="" states="{"invisible": {"__class__": "Not", "v": {"__class__": "Equal", "s1": {"__class__": "Eval", "v": "state", "d": ""}, "s2": "posted"}}, "depends": ["state"], "readonly": true}" type="class"/>
<button name="process" icon="tryton-refresh" string="Procesar" help="" confirm="" states="{"invisible": {"__class__": "Not", "v": {"__class__": "In", "k": {"__class__": "Eval", "v": "state", "d": ""}, "v": ["posted", "paid"]}}, "depends": ["state"], "readonly": true}" type="class"/>
</group>

Nevermind, I figure out. The answers was all along in the ModelView.parse_view function definition, where buttons are removed if any of the fields defined in the depends are not read accessible. In this case, the move field was added into the depends list in version 6.0. And since a limited user doesn’t have read access to the model account.move the Post button is removed and therefore hidden.

Now what I have to do is to figure out how to enable back the Post button without giving too much access to the limited user to the account.move model.

Although I still would like to know what was the reason behind this change in version 6.0 for adding an additional criteria in the “invisible” clause when posted with a move? Wouldn’t it be enough to hide the Post button if the Invoice’s state was not equal to draft or validated, just like in version 5.8?

It is Issue 10054: Batch posting invoices - Tryton issue tracker that adds it.
This is for the batch posting in case the creation of the move fails but the invoice has already the state posted.
I guess we could not depend on move for the button if we set a not null default value to the Eval('move') so user without read access to move can not “re-post” the invoice in case of failure.