0

I am working on a Python script that will import all my existing invoices to an Odoo 12 instance. I am using odoorpc library to simplify RPC calls to my Odoo instance.

I achieved to create an invoice using the API, registering it in "draft" state. Then, I want to "validate" it and update its state into "open". Unfortunately, using the "Validate" button in Odoo UI or calling the action from the RPC API do the same: invoice state is changed to "paid". I don't understand this behavior, since I didn't register any payment (it will be my next goal).

Here is a simplified version of my script that can be used to reproduce the issue :

import odoorpc

import settings
"""settings module contains various constants used
to connect with Odoo on my VPS"""


if __name__ == "__main__":
    odoo = odoorpc.ODOO(settings.ODOO_HOST, port=settings.ODOO_PORT, timeout=10)
    odoo.login(settings.ODOO_DB, settings.ODOO_USER, settings.ODOO_PASSWORD)

    Partner = odoo.env["res.partner"]
    # This partner already exists in DB
    customer = Partner.browse([22])

    Invoice = odoo.env["account.invoice"]
    invoice_id = Invoice.create({
        'partner_id' : customer.id,
        'state': 'draft',
        # This is ID for "Customers Invoices" journal
        'journal_id': 1,
        'account_id': customer.property_account_receivable_id.id,
        # This is ID for default bank account, already registered
        'partner_bank_id': 1,
        'payment_term_id': odoo.env.ref("account.account_payment_term_net").id,
    })

    InvoiceLine = odoo.env["account.invoice.line"]
    InvoiceLine.create({
        "invoice_id": invoice_id,
        "name": "A basic product",
        "quantity": 6,
        "price_unit": 100.0,
        # Not sure about this one:
        "uom_id": 1,
        # No tax
        "invoice_line_tax_ids": [],
        'journal_id': 1,
        'account_id': customer.property_account_receivable_id.id,
    })

    inv = Invoice.browse([invoice_id])
    print("Before validating:", inv.state)

    inv.action_invoice_open()

    inv = Invoice.browse([invoice_id])
    print("After validating:", inv.state)

result:

Before validating: draft
After validating: paid

I think there is something missing or wrong in my invoice creation, but I didn't find what exactly should be modified to have an invoice created the same way it would be from the UI. Can anybody help me to find what's wrong in my script ?

Antwane
  • 20,760
  • 7
  • 51
  • 84
  • Try to trigger the computation of all the total and subtotal and so on fields on the lines and the invoice itself. My guess: without it, everything is on 0 and an invoice with total equal to 0 will be set to paid immediately. – CZoellner Jun 27 '19 at 19:56
  • Your right, I think the total due remains at 0 which put the invoice as paid on validation. But how to trigger the computation of these fields ? I tried to call on_change methods, like `_onchange_invoice_line_ids`, `_onchange_payment_term_date_invoice`, etc. but Odoo forbids to call private method via XML-RPC. – Antwane Jun 27 '19 at 20:05
  • Could you please try out a write on the invoice after creation of the lines? Just write `date_invoice` to `False`. That possibly triggers the recomputation. – CZoellner Jun 27 '19 at 20:18
  • That was a good idea, but unfortunately, it didn't work. Final invoice is still in paid state after a call to `action_invoice_open()` – Antwane Jun 27 '19 at 20:26
  • I think in Line you are missing 'product_id' ? after product_id onchange the compute function will trigger. – Vishnu VaNnErI Jun 29 '19 at 12:49

1 Answers1

1

I found myself a solution. It seems the account_id must be different for invoice and invoice line. To fix the issue, I retrieved the account.journal instance with ID 1 (for "Customers Invoices" journal), then used it to fill invoice line's account_id based on the journal's default_credit_account_id field:

cust_invoices_journal = odoo.env["account.journal"].browse([1])
# [...]
invoice_id = Invoice.create({
    # [...]
    'journal_id': cust_invoices_journal.id,
    'account_id': customer.property_account_receivable_id.id,
    # [...]
})
# [...]
InvoiceLine.create({
    # [...]
    'account_id': cust_invoices_journal.default_credit_account_id.id,
    # [...]
})
Antwane
  • 20,760
  • 7
  • 51
  • 84
  • you saved my life! I was strugling with custom invoice creation via python and finally checking on postgres account_id from account.invoice.line on properly made invoices showed that i had to use account_id = 188 for the account.invoice and account_id = 356 for account.invoice.line but I was using same ID for my custom invoices – Nacho R Jan 10 '22 at 19:29