126 lines
5.4 KiB
Markdown
126 lines
5.4 KiB
Markdown
# account_invoice_default_journal
|
|
|
|
Forces the journal of an invoice from a journal configured on its products.
|
|
|
|
Two company-dependent journal fields are added on the product form, under the
|
|
**Accounting** tab:
|
|
|
|
- `forced_journal_id` ("Forced sale journal", restricted to sale journals), used for
|
|
customer invoices and credit notes (`out_invoice`, `out_refund`).
|
|
- `forced_purchase_journal_id` ("Forced purchase journal", restricted to purchase
|
|
journals), used for vendor bills and refunds (`in_invoice`, `in_refund`).
|
|
|
|
When Odoo looks for the default journal of an invoice
|
|
(`account.move._search_default_journal()`), the journal forced by the invoice lines'
|
|
products takes precedence over the company default. A move belongs to a single journal,
|
|
so a `UserError` is raised if the lines force two different journals — split the
|
|
document into two invoices in that case.
|
|
|
|
Both fields are company-dependent: each company configures its own forced journal on the
|
|
same product.
|
|
|
|
## Installation
|
|
|
|
`account` is the only dependency, and it is part of Odoo core. Use the standard Odoo
|
|
module installation procedure to install `account_invoice_default_journal`.
|
|
|
|
### Required access group
|
|
|
|
Both fields are added inside the **Accounting** tab of the product form, which comes
|
|
from `account.product_template_form_view`. In Odoo 18.0 that tab is restricted to the
|
|
technical group `account.group_account_readonly`, and neither
|
|
`account.group_account_invoice` ("Invoicing") nor `account.group_account_manager`
|
|
("Administrator") implies it — only `account.group_account_user` ("Show Full Accounting
|
|
Features") does. Odoo 16.0 also allowed `account.group_account_invoice` on that tab, so
|
|
the restriction is tighter than it used to be.
|
|
|
|
On an Invoicing-only installation, meaning without the `account_accountant` module,
|
|
there is no standard way to obtain that group: it has to be granted explicitly.
|
|
Otherwise both fields stay invisible even though the module is correctly installed.
|
|
|
|
Upgrading an Odoo 16.0 database: the values of both fields were stored in `ir.property`,
|
|
a model removed in Odoo 17.0. The module ships
|
|
`migrations/18.0.1.0.0/post-migration.py`, which converts them to the new `jsonb`
|
|
storage automatically during the upgrade.
|
|
|
|
## Configuration
|
|
|
|
No configuration is needed. Set the journal on each product that needs one; a product
|
|
with no forced journal does not affect journal selection.
|
|
|
|
## Usage
|
|
|
|
1. Open the product form and go to the **Accounting** tab.
|
|
2. Set **Forced sale journal** and/or **Forced purchase journal**.
|
|
|
|
The forced journal is then applied when Odoo computes the journal of a new invoice,
|
|
which happens only if the invoice is created together with its lines **and** without an
|
|
explicit journal in the creation values. That is the case for invoices generated from
|
|
another document, such as a sale order.
|
|
|
|
It is **not** the case when editing an invoice in the user interface: see the limitation
|
|
below. Read it before relying on this module for manual invoicing.
|
|
|
|
## Known issues / Roadmap
|
|
|
|
### The forced journal is a default, not a constraint
|
|
|
|
The module plugs into `account.move._search_default_journal()`, which supplies a
|
|
**default** value. A default is overridable by design, so the forced journal is only
|
|
honored on one of the three ways an invoice can get its journal:
|
|
|
|
- Created in a single call, with its lines, and no `journal_id` in the creation values:
|
|
the forced journal **is** applied.
|
|
- Created in a single call with an explicit `journal_id` in the creation values: the
|
|
forced journal is **not** applied.
|
|
- Created first, then lines added afterwards: the forced journal is **not** applied.
|
|
|
|
Two independent Odoo behaviors cause the two failing cases:
|
|
|
|
- An explicit value in the creation values short-circuits the computation entirely, so
|
|
the default is never requested. The web client sends `journal_id` because the field is
|
|
present and editable in the invoice form, which puts manual invoicing in this case.
|
|
- `_compute_journal_id` declares
|
|
`@api.depends('move_type', 'origin_payment_id', 'statement_line_id')`. It does not
|
|
depend on `invoice_line_ids`, so adding a product never invalidates the journal. It
|
|
also skips any move whose journal already has a valid type, which is true of the
|
|
company default sale journal.
|
|
|
|
Both behaviors are identical in Odoo 16.0, so this is a limitation of the module's
|
|
design rather than a regression introduced by the 18.0 migration.
|
|
|
|
Lifting it means moving from a default to an actual constraint, by overriding `create`
|
|
and `write`, or by refusing to save a mismatched journal. Both change behavior for
|
|
existing users and neither is implemented.
|
|
|
|
### Other
|
|
|
|
- `_search_default_journal()` calls `super()` first, so a company with no journal of the
|
|
expected type still raises before the forced journal is considered.
|
|
|
|
## Bug Tracker
|
|
|
|
Bugs are tracked on
|
|
[our issues website](https://github.com/elabore-coop/account-tools/issues). In case of
|
|
trouble, please check there if your issue has already been reported. If you spotted it
|
|
first, help us smashing it by providing a detailed and welcomed feedback.
|
|
|
|
## Credits
|
|
|
|
### Contributors
|
|
|
|
- Stéphan SAINLEGER - [Github](https://github.com/stephansainleger)
|
|
- Nicolas JEUDY - [Github](https://github.com/njeudy)
|
|
|
|
### Funders
|
|
|
|
The development of this module has been financially supported by:
|
|
|
|
- [Lokavaluto](https://lokavaluto.fr)
|
|
- [Mycéliandre](https://myceliandre.fr)
|
|
- [Elabore](https://elabore.coop)
|
|
|
|
### Maintainer
|
|
|
|
This module is maintained by Elabore.
|