Search code examples
python-3.xodooodoo-11

Unexpected behaviour of inverse_name in Odoo 11


You know about inverse_name parameter, available for One2many fields. It just tells Odoo which is the mandatory Many2one field in the related comodel to know the records to show.

In standard module account, in account.invoice model, there is a Many2one field named move_id. It is related to account.move model and its purpose is to show the journal entry generated for the invoice when this one is validated.

The only thing I want to do is to show in journal entries form (account.move) the invoice (account.invoice) whose validation has generated that journal entry. So it looked easy for me, I have just created the other part of the relationship in account.move model:

invoice_ids = fields.One2many(
    comodel_name='account.invoice',
    inverse_name='move_id',
    string='Invoices whose validation generated this journal entry',
)

The logical between account.invoice and account.move should be 1:1, but for this case I can use 1:N since the One2many is just informative and readonly for users. So this one seemed to work OK, I was able to see the invoice in the journal entry, but after a while I realised that I had destroyed the workflow with that code.

This is what happens now, I describe it with examples:

  1. I create and validate the invoice SALE/INV/00001.

  2. The validation generates the journal entry 2019/00001. I can see this journal entry in the invoice form, and I can see the invoice in the journal entry form (in the One2many I have created). Right.

  3. I pay the invoice, and here is where everything breaks down. The payment generates the journal entry 2019/00002, which is OK, but now, in the invoice SALE/INV/00001, I see this journal entry instead of 2019/00001, which is wrong, and if I go to the form of the journal entry 2019/00001, the One2many field I have created to show the related invoice is empty, whereas the one in the journal entry generated by the payment shows SALE/INV/00001, when it should be empty.

I expected journal entry's invoice_ids field to show only the invoices whose validation generated that journal entry, since move_id in invoices only shows the journal entries generated by validations.

To correct this I have replaced the One2many invoice_ids by the Many2one invoice_id in journal entry, and I fill this in automatically in account.move ORM create method. But this solution does not link old records in the database, and I still do not understand the behaviour of the code described above.

So, does anyone have an explanation for that? I would like to know why inverse_name behaves like that.


Solution

  • After wasting a lot of time filling in the core with log messages, I found my unfortunate problem.

    When you pay an invoice through the standard method (clicking on the Register Payment button), a pop-up of the account.payment model is opened. This model has already a field named invoice_ids, and Odoo is using the context of the action which opens the pop-up to fill it in automatically with the current invoice:

    <field name="context">{'default_invoice_ids': [(4, active_id, None)]}</field>
    

    When the payment is accepted, a call to account.move create method is done to generate the payment journal entry. The problem is that the context of the action still remains in that call, which means that Odoo thinks that I want to fill in my custom field invoice_ids of account.move with that value (which is always the active id, the invoice we keep opened)... and that is not the truth.

    I guess that is very bad luck.

    Finally I fixed it just modifying the technical name of my One2many field to avoid Odoo to be confused:

    validated_invoice_ids = fields.One2many(
        comodel_name='account.invoice',
        inverse_name='move_id',
        string='Invoices whose validation generated this journal entry',
    )