Commit Graph
778 Commits
Author SHA1 Message Date
william-andre d8d47f9ff8 [REF] accounting v16. Yeeeeaah
TLDR:
* invoices are implemented using computed methods instead of onchange
* the synchronization only happens when switching tabs in the Form view
  to improve perfs.

_______________________________________________________________________

The whole engine of the synchronization of Invoices to the Journal
Entries has been refactored
* by using computed fields instead of onchange functions
* by synchronizing only from invoice to journal entry in `create` and
  `write`
* by saving when switching tabs on the Invoice form, to synchronize
  before showing the values

This comes with numerous advantages:
* no need to call the onchange methods manually
* no need to use the Form emulator to build invoices (i.e. EDI, OCR,
  intercompany, ...)
* the performance for invoices with many lines improves drastically, going
  from 2 minutes to 4 seconds to create an invoice with 500 lines
* the model is more declarative, we can now see how the values are computed
  instead of having the values being copied from various places.
* remove the hack in `onchange` that disabled the recursivity of it,
  which was unexpected and needed to be managed manually in all the
  onchange methods

This means that:
* Some fields need to be exclusively computed on journal entries values
  or invoice values, more specifically the Tax Summary widget.
  It is now
    - computed from entry lines, when opening the view
    - computed from invoice lines when changing those, because the tax lines
      will need to be recomputed anyways, erasing previously set values
    - set with an inverse function when saving; after the sync has been done
* Some possible operations previously possible have been dropped.
  (i.e. look at the removed test test_in_invoice_line_onchange_accounting_fields_1)
  This is because such a behavior was undefined (how is changing the balance going
  to affect the unit price? How is the amount currency going to affect it?)

_______________________________________________________________________

Implementation Details
----------------------

The "dynamic lines", meaning the payment terms and the tax lines are now
only created in the `create` and `write` functions.
In order to reduce code duplication, it has been implemented using
context managers used in both `account.move` and `account.move.line`
These context managers help comparing the values before/after, acting
like a local `onchange`, but getting benefit from the dirty flags from
the `compute` dependences.
This is relying on computed fields on the move (`needed_terms`) and on
the lines (`compute_all_tax`) which contain the values needed for the
related move.
Depending on the needed values and the existing values (`term_key` and
`tax_key`, respectively) the context manager will determine what needs
to be created/updated/deleted.

Some related changes are to produce a `dict` instead of a `str` for the
`tax_totals` (previously `tax_totals_json`) fields, by simplicity to
reduce the complexity of IO, and simplicity of debugging, because the
logic of the field needed to change (cannot be computed at the same time
anymore since it needed the lines to be synced)

By simplicity, and also because it makes more sense, some boolean fields
have been merged into `display_type`:
* `is_rounding_line`
* `exclude_from_invoice_tab`
* `is_anglo_saxon_line`

The `price_unit`, `quantity` and other "invoice fields" are now not set
anymore on lines that are not product lines since it didn't make any
sense to have it.

Performances
------------

You have to keep in mind that a simple `create` didn't compute a lot of
fields, for instance not taxes were set, no payment terms,...
Now it does.

```python
import random
from timeit import timeit
from odoo import Command
domain = [('company_id', 'in', (False, self.env.company.id))]
products = self.env['product.product'].search(domain).ids
partners = self.env['res.partner'].search(domain).ids
taxes = self.env['account.tax'].search(domain).ids
def create(nmove, nline):
    self.env['account.move'].create([
        {
            'move_type': 'out_invoice',
            'partner_id': random.choice(partners),
            'invoice_line_ids': [
                Command.create({
                    'name': f'line{i}',
                    'product_id': random.choice(products),
                    'tax_ids': [Command.set([random.choice(taxes)])],
                })
                for i in range(nline)
            ]
        }
        for j in range(nmove)
    ])
                                                             # After  | Before
print(timeit("create(1, 1)", globals=globals(), number=1))   # 0.11   | 0.09
print(timeit("create(100, 1)", globals=globals(), number=1)) # 2.76   | 2.50
print(timeit("create(500, 1)", globals=globals(), number=1)) # 14.56  | 12.34
print(timeit("create(1, 100)", globals=globals(), number=1)) # 1.03   | 5.52
print(timeit("create(1, 500)", globals=globals(), number=1)) # 3.99   | 125.02
print(timeit("create(50, 50)", globals=globals(), number=1)) # 19.44  | 79.55
```

Another metric that can be used is running the test suite with
`--test-tags=/account` (only `account` installed)
* before: 404s, 267127 queries (366 tests)
* after: 318s, 232125 queries (362 tests)

Why this commit title?
----------------------

Someone told me that this was the perfect way of naming your commits.
c04065abd8

task-2711317

closes odoo/odoo#96134

Related: odoo/upgrade#3715
Related: odoo/enterprise#29758
Signed-off-by: Laurent Smet <las@odoo.com>
2022-08-03 13:44:49 +02:00
Guillaume (guva) 63d44ffd35 [FIX] account: keep statement line note
We keep the statement line note when changing
the partner in reconciliation widget

Steps:

- Create a Bank Statement, a Bank Statement
  Line BSL with a note (field narration)
- Save, edit, change partner on statement
  line and save.
-> The note on BSL is empty

With this commit we allow narration computation
only for sale documents.

opw-2832287

closes odoo/odoo#97125

X-original-commit: 19394d1971259933c5158139c56344c9c35bdaed
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Guillaume Vanleynseele (guva) <guva@odoo.com>
2022-08-01 10:55:47 +02:00
Florian(flg) cf34b1e04a [FIX] account: Remove useless check on bank statement button post.
As we allow editing balances in processing state, we do not want
to check balances before the validation of the bank statement
(only in case of a bank journal).
Commit about editing balances: 03f83eb87da00938b9d2df78651c1e06cf8a6d58
This fix split the _check_balance_end_real_same_as_computed into
2 functions. One to check "bank" bank statement and one to check
"cash" bank statement. It allows to keep the same behavior for
a "cash" bank statement when we post the bank statement, and
having the right behavior for a "bank" bank statement.

opw-2835728

closes odoo/odoo#97153

X-original-commit: 2d97efb4c84f647be3eb03f249c52b236bf00d55
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Florian Gilbert (flg) <flg@odoo.com>
2022-07-29 23:09:09 +02:00
aliya 8a455d8519 [IMP] account: make account creation easier
Task 2888204

- Name is automatically split into code and name
- account_type is computed based on the closest parent of the code prefix (and can be changed)
- _onchange_name is needed to split name into code and name when creating from a related model's form

closes odoo/odoo#94171

Signed-off-by: Quentin De Paoli <qdp@odoo.com>
2022-07-14 18:03:47 +02:00
Xavier-Do 2c6e73a6f3 [FIX] account: avoid invisible product_uom_id
For a non well identified reason, the user doesn't have the uom group
to see the field during the test.

this commit adds the group to the user to make it visible during
the test as a simple fix.

closes odoo/odoo#95741

Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
2022-07-11 20:25:17 +02:00
aliya 26b2472f49 [IMP] account: refactor account types
Task: 2856281

- Remove user_type_id, account.account.type model, internal_type
- Add account_type that is a simple selection field
- Move internal_group and include_initial_balance to account.account
- Because of these changes, type_control_ids on account.journal is also removed

closes odoo/odoo#93212

Related: odoo/documentation#2223
Related: odoo/upgrade#3595
Related: odoo/enterprise#28205
Signed-off-by: Cedric Snauwaert <csn@odoo.com>
2022-07-08 19:52:15 +02:00
Denis Ledoux 5ccc32fcf7 [IMP] tests: common.Form, can't write on invisible fields
In the web client, in a real use case, it's not possible
to write on fields which are invisible,
as it's not possible to write on fields which are readonly.

This is a first step in the goal to change the behavior
of the `groups=` attribute in the back-end views,
to remove them for the view instead of making them invisible.

This is mainly to reduce the diff of the revision that will introduce
the mentioned above behavior change.

As nodes with `groups=` will be removed from the view
when the user doesn't have the group, it's no longer possible
to set a value on a field having a `groups=` the user doesn't have
in the `Form` test class, as the field will no longer be at all in the
view.
However, these unit tests shouldn't have been able to set values
on invisible fields in the first place.
This revision therefore aims to correct the unit tests setting value
on fields which were invisible because the user executing the
test was not part of the required group(s) for these fields
to be visible in the view.

closes odoo/odoo#94337

Related: odoo/enterprise#28936
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
2022-07-08 14:33:47 +02:00
william 0f71c64237 [FIX] account: reduce locking on moves
By trying to avoid concurrency issues while assigning the sequence [1],
we are locking too many operations even when not in the process of
assigning a new number.
* when computing `highest_name`, we don't need to lock as this is mostly
  an information on the form that can possibly change anyway while the
  form view is open (without any lock anymore)
* when computing the accounting date, we don't need to lock, the only
  information we want is the format of the sequence (yearly, monthly, no
  reset), which is not likely to change on a same journal.
* when changing the `journal_id`, it is only a helper for encoding, if
  there is a concurrency error it will be shown during the post anyways.
  Also same argument as for `highest_name`

[1] https://github.com/odoo/odoo/commit/ba6ee0b75d66d6f22a592b1b6a7c5158461bec41

closes odoo/odoo#95480

X-original-commit: 809557cdd02fe6581ed573b58158a927aabe0694
Related: odoo/enterprise#29212
Signed-off-by: Olivier Colson (oco) <oco@odoo.com>
Signed-off-by: William André (wan) <wan@odoo.com>
2022-07-07 14:44:25 +02:00
Guillaume (guva) 4805103274 [FIX] account: change journal on draft invoice
Step to reproduce:

- Create a SO, save and confirm it
- Create an invoice, on edit mode, change the journal and click on save

Issue:

- If the invoice is the first one in the current month, a sequence
  number is automatically assigned and an error is displaid.

forwardport of https://github.com/odoo/odoo/commit/b8328e45d526d276b5781da3523a0d5874da64bd

opw-2660571
opw-2879716

closes odoo/odoo#79084

closes odoo/odoo#95386

X-original-commit: 7b296982139518460405fa63eca6774bd82ba7b1
Signed-off-by: William André (wan) <wan@odoo.com>
Signed-off-by: Minet Adrien (admi) <admi@odoo.com>
2022-07-06 13:11:34 +02:00
Raphael ColletandVincent Schippefilt eb67feb590 [FIX] *: cache consistency
In module mail, invalidating 'message_ids' on a mail thread also
invalidates its inverse field 'res_id' on messages.  If you haven't
flushed it before, your cache will be inconsistent, as shown by the test
/mail:TestMailgateway.test_message_process_bounce_records_channel.

In module purchase_stock, add depends on report.stock.quantity.  This
ensures that when the model is queried after changes in other models,
the data on which the SQL view depends is flushed to the database before
querying that model's table.

closes odoo/odoo#66938

Related: odoo/enterprise#16722
Signed-off-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Vincent Schippefilt <vsc@odoo.com>
2022-07-05 11:35:01 +02:00
Victor Feyens 954c85dc96 [FIX] account: tests
It seems most accounting tests relied on the fact that the "accountman"
test user has both the user AND manager groups (but previously, the
manager group was given by the implied group relation "Settings" ->
"account manager")

Part-of: odoo/odoo#91909
2022-06-23 23:48:29 +02:00
Ricardo Gomes Rodrigues (rigr) 17d44d6617 [IMP] account{,fleet,lock}: add quick invoice encoding
This commit:
- adds a fiduciary mode which allows fast encoding of invoices. This is an Accounting setting which must be activated. This fiduciary mode allows one to edit directly the invoice sequence and enter the total amount of the invoice (by creating a single line which contains the base price, the tax amount, and the most frequent account) such that we match this 'quick total amount'.
- adds a new test for this feature
- adds a 'quick edit total amount' in the tax computation which verifies that the 'quick edit total amount' correctly matches sum of the base and the tax (in case of fiduciary mode)
- sorts and filters the accounts suggestions in an invoice line. The most frequent accounts for a particular partner rank higher while filtering on the type of account suggested (this is disabled if the user searches itself for the account)
- selects by default the most frequent account for a particular partner when creating a new invoice line
- adds the option to hide some columns (label & quantity)
- moves the car column after the account column in case the Fleet app is installed

Task-id: 2857253

Community PR: odoo#91938
Enterprise PR: odoo/enterprise#27605

Part-of: odoo/odoo#91938
2022-06-20 18:56:09 +02:00
Laurent Smet e2178ba796 [REV] account: 0% tax not in tax report due
This reverts commit 65b5ec4ad65f798b1d647978b5b42a49e760139a.

closes odoo/odoo#93717

X-original-commit: 09eb1b725e2f8b86dc671d0f77503e49d106d14c
Signed-off-by: Olivier Colson (oco) <oco@odoo.com>
Signed-off-by: Laurent Smet <las@odoo.com>
2022-06-20 11:14:55 +02:00
John Laterre (jol) 61e2df4084 [FIX] account_move: allow journal's default accounts with type_control_ids
Fixes a bug introduced by this commit : https://github.com/odoo/odoo/commit/aba9ef6a27eca5f70ab7be87a929846988710048

The problem was that once the type_control_ids were activated,
it would always raise an error due to the journal's default_account_id.

This issue was raised by a community member in this PR : https://github.com/odoo/odoo/pull/92390

A test is also included to prevent having the same issue in the future.

closes odoo/odoo#93495

X-original-commit: f08b98397114cf7c912a85e4f75868426ceaeccb
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: John Laterre (jol) <jol@odoo.com>
2022-06-15 12:23:18 +02:00
aliya 9d2875492b [FIX] account: fix payment widget (exchange difference)
Task 2843455

When an exchange difference is linked to a payment, not an invoice,
it is not displayed in the payment widget even though an exchange
difference move is created and matched with the invoice.
Exchange difference should be displayed when it's linked to the payment as well.

closes odoo/odoo#92069

Signed-off-by: Laurent Smet <las@odoo.com>
2022-06-15 11:09:49 +02:00
Andrea Grazioso (agr-odoo) 1318cdc321 [FIX] account: missing base line in CABA entry for tax group
Have Tax A and Tax B both configured with tax exigibility based on
payment
Have a Tax G set as group of taxes with A and B as childs
Make an invoice with Tax G on a line
Register a payment
The CABA entry will be generated without base line

This occur because the system checks for the base line tax exigility,
but the exibigility of a group of taxes is fixed to 'on_invoice' so we
need to check the value on the childs

opw-2858656

closes odoo/odoo#93131

X-original-commit: 766802c345aaae0d9d01ec17685e9742f27526e0
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Grazioso Andrea (agr) <agr@odoo.com>
2022-06-08 19:00:03 +02:00
Stanislas Gueniffey 564af98969 [IMP] account_move: recurring entries
Recurring entries are created using the 'auto_post' selection field
- 'no' for regular entries
- 'at_date' for non-recurring auto-posted entries
- 'monthly', 'quarterly', 'yearly' for recurring auto-posted entries

Auto-posted entries can also be posted manually.
For recurring entries, the next one is  created upon posting.

See : odoo/enterprise#27798
See : odoo/upgrade#3543

closes odoo/odoo#92348

Task: 2855545
Signed-off-by: William André (wan) <wan@odoo.com>
2022-06-07 12:11:29 +02:00
Laurent Smet 080d41a341 [REF] account_accountant: Refactor the bank reconciliation widget
- Refactor the bank reconciliation widget to use more standards views and have a side-by-side kanban/widget views instead.
- Make sure the bank reconciliation widget is doing the same thing as the "reconcile" method on account.bank.statement.line. Then, what you see on the view is exactly what you get on the corresponding journal entry.
- Since the "reconcile" method is gone, clean the matching rules since it's now called only for one statement line at a time. Also, move the auto_validate feature into a CRON to avoid performance issues when opening the widget.

closes odoo/odoo#91448

Task: 2555114
Related: odoo/enterprise#27360
Related: odoo/upgrade#3555
Signed-off-by: William André (wan) <wan@odoo.com>
2022-06-07 10:16:14 +02:00
aliya 4fa0d275ad [IMP] account: change date for calculating the currency exchange
Currently, the currency conversion rate used is based on the accounting date on invoices and bills.
According to partner feedback and the official documentation we should use the exchange rate on the invoice/bill date.
Moves that are not invoices or bills should still use the accounting date.

closes odoo/odoo#87984

Task: 2807136
Signed-off-by: Quentin De Paoli <qdp@odoo.com>
2022-06-02 23:21:52 +02:00
Merlin (megu) ed586dfc68 [FIX] account: prevent draft entry for reconciled statement
Journal entries of a bank statement can be reset to draft even if the
bank statement has been validated

Steps to reproduce:
1. Install Accounting
2. Go to Accounting dashboard, click on the 3 dots of Bank and go to
View > Statements
3. Create a new statement with a transaction of 100, correctly set the
ending balance, save and post
4. Click on reconcile then validate the reconciliation
5. Go back to the statement and validate it
6. Open the journal entry of the statement
7. You can reset it to draft but you shouldn't be able to

Solution:
Prevent the user from resetting a journal entry to draft if the
statement has been confirmed

opw-2827117

closes odoo/odoo#92713

X-original-commit: 5622bc103e063d62f75625ca413a06aa7395d654
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Guillaume Merlin (megu) <megu@odoo.com>
2022-06-02 08:57:56 +02:00
Julien Castiaux da8def8e41 [IMP] core, web: Delegate delivery of static files
Rationnals
----------

Web servers can serve some resources (e.g. static files) right away
without any interaction with the web application. The network model of
most web servers makes them capable of handling thousands of
simultaneous requests when it comes to intensive IO operations such as
streaming data from a file. The network model of Odoo is different: it
is capable of a lot of processing power but can only serve a handful of
requests at a time, i.e. Odoo (with some help from postgres) is
optimized for CPU operations, not IO.

Some users don't configure their web server, they use a basic
configuration that relay all requests to Odoo. The result is that many
Odoo HTTP Workers can be busy streaming static files instead of
processing other requests. This can lead to a worker starvation, i.e.
all workers are busy streaming files and cannot process new requests.

X-Sendfile
----------

In this work, we add the support for the [X-Sendfile] header family,
they are multiples http headers that can be used by the web application
to communicate with the web server in order to delegate the delivery of
files stored on the file system. Odoo still receives the request but it
does no more stream the file content from within its HTTP worker,
instead it skips the response body altogether and sets the `X-Sendfile`
special header with the path of the file on the filesystem. The web
server intercepts that special header, open the file and stream it.

Using those headers, we can use the best of both the web application and
the web server. The web application is still responsible to locate the
resource and verify the access rights, the web server is still
responsible of streaming the content.

Using X-Sendfile is opt-in via the `--x-sendfile` CLI flag. We set both
`X-Sendfile` (apache) and `X-Accel-Redirect` (nginx). If you are using
apache, make sure `mod_xsendfile` is enabled. If you are using NGINX
you have to add the following location block:

    location /web/filestore {  # custom path, hardcoded within Odoo
        # Prevent access from the outside world, i.e. makes this
        # route only accessible via X-Accel. MANDATORY!!!
        internal;

        # Give access to the filestore using this server's
        # permissions. Odoo is in charge of verifying the access
        # rights.
        alias /path/to/odoo/data-dir/filestore;
    }

The Odoo [deployment documentation] has been updated accordingly.

[X-Sendfile]: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/
[deployment documentation]: https://www.odoo.com/documentation/master/administration/install/deploy.html#serving-static-files-and-attachments

Changes to the API
------------------

To benefit most from X-Sendfile, all APIs related to streaming content
over HTTP has to be adapted. They are: (1) `request._serve_static`,
(2) `ir.http._serve_fallback`, (3) `/web/content` and (4) `/web/image`.

Each used it own way to deliver content: (1) `_serve_static` was using
`send_file` (flask's send_file that as been vendored with odoo 10
years ago and not maintenained since then), (2) _serve_fallback was
handcrafting a `werkzeug.wrappers.Response`, (3) /web/content-image were
using the "binary server" `ir.http.binary_content` API.

I has been decided to remove all 3 APIs and to merge the code inside of
the new `http.Stream` object and the `ir.binary` helper model.

A Stream wraps what is going to be sent to the browser, it can be a path
to a file on the locale filesystem, a blob of raw data or an URL to an
external resource. The Stream also holds various metadata that are
mainly used for caching. The preferred way to create a Stream is via one
of its three factories so that all the metadata are set. The factories
are: `from_path`, `from_attachment` and `from_binary_field`. A stream
instance exposes a single method `get_response()` used to create the
corresponding HTTP response object out of the stream.

Inside of `ir.http` were a few methods that were not related to the http
routing and formed what was called the "binary server". All those
methods have been removed and the feature have been refactored inside of
the new `ir.binary` model. The removed methods are:

- `_xmlid_to_obj`
- `_get_record_and_check`
- `_binary_ir_attachment_redirect_content`
- `_binary_record_content`
- `_binary_set_headers`
- `binary_content`
- `_response_by_status`
- `_get_content_common`
- `_content_image`
- `_content_image_get_response`
- `_placeholder_image_get_response`

The new `ir.binary` abstract model exposes the following utilities:

**`_find_record`**

Find an attachment or a record with a binary-field out of an xmlid or
out of a pair record-model/record-id. Check the access rights and the
access token.

**`_get_stream_from`**

Create a Stream from an attachment or a record with a binary-field.

**`_get_image_stream_from`**

Same as `_get_stream_from` but adapted for images. It sets a sensible
ETag on the stream and has image resizing support.

**`_placeholder`**

Get the image placeholder blob.

Testing
-------

It is possible to test the web server configuration using the
`test_http` module. Install the module then run the unittest using the
`webserver` test-tag. By default it attempts to connect to a web-server
running on `http://localhost:80`, you can change this URL by setting the
`WEB_SERVER_URL` environment variable.

    odoo-bin -i test_http --stop-after-init
    WEB_SERVER_URL='http://localhost:80' odoo-bin --test-tags webserver --stop-after-init

closes odoo/odoo#88134

Task: 2801675
Related: odoo/documentation#2083
Related: odoo/enterprise#26191
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-06-01 02:53:59 +02:00
Raphael Collet 6cf8db906f [REF] *: adapt code to new flush API
closes odoo/odoo#87527

Related: odoo/upgrade#3497
Related: odoo/enterprise#26939
Signed-off-by: Raphael Collet <rco@odoo.com>
2022-05-25 18:00:47 +02:00
Pierre Masereel adddc30732 [REVERT] account: unbalanced entry with price_unit 0
This fix will try to write a new amount value on the tax when an
invoice is created from POS, that will raise a user error preventing the
creation of the order.

This reverts commit 2b9592cb0ecef235d708ed7810d0613ccd946124

OPW-2855694

closes odoo/odoo#91719

X-original-commit: d3cce0e3ae13859954d6907a3cb16fb0e1a95f86
Signed-off-by: Masereel Pierre <pim@odoo.com>
2022-05-19 12:28:27 +02:00
Laurent Smet d849155c14 [FIX] account: Fix the register payment wizard in multi-currencies
- Create an invoice of 1200 MXN = 300 USD
- Register a payment, select USD at a date at which 1200 MXN = 400 USD
=> The amount is incorrect, a difference is computed but it should be zero.

closes odoo/odoo#91634

X-original-commit: d88f630dcb7f98a45c9efe7f2439a8732832c77c
Signed-off-by: Quentin De Paoli <qdp@odoo.com>
2022-05-18 16:04:49 +02:00
Abdelouahab (abla) 1a84399314 [FIX] account : fixing type of journal_id
the `write` method from `AccountMove` class and its children
expect `journal_id` in `vals` to be an `int` and not an `account.journal`.

linked PR : https://github.com/odoo/enterprise/pull/26515

opw-2794392

closes odoo/odoo#91422

X-original-commit: 69ea8b2389e62a415b70edbd109333b1a1a03e8e
Related: odoo/enterprise#27349
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
Signed-off-by: abla001 <abla@odoo.com>
2022-05-16 10:10:03 +02:00
Pouya Malekinejad 9a34a6add3 [IMP] account_invoice: prevent erasing of a tax line entry if there is a tax related to it in the invoice
This is actually checking if for each tax of each line of invoice in the move, there exist a tax entry.
This will prevent the users from accidentally or dully erasing tax lines which includes 0% taxes.
If the users delete the line containing tax, it will be added again the same way as the counterpart line
for an invoice line is being added.

Also, fixes the following:
Recalculating all invoices if a single invoice in a batch has a line with `recompute_tax_line` set should not be allowed.
Deleting a tax account entry of a posted move should not be allowed.

task ID:2834679

closes odoo/odoo#91414

Pr: #90834
X-original-commit: 5f39f8c1533502be52ea9d3ef114430b5b8cd9a6
Signed-off-by: William André (wan) <wan@odoo.com>
2022-05-15 22:38:54 +02:00
Guillaume (guva) 25d2665582 [FIX] account: unbalanced entry with price_unit 0
Steps to reproduce:

- Create invoice for a prudict at price X > 0
- Change the price to 0 before saving
- Then save it
-> Error : Cannot create unbalanced journal entry

This bug was introduced in 14.0 with this commit fe7d56dc32c71e04b54de9dbd756a48942a832f4
With this commit, we use an ugly condition to catch the
specific case of a tax with price included and amount type division
to avoid changing the price unit if the line balance is zero.

opw-2822635

closes odoo/odoo#91059

X-original-commit: 2b9592cb0ecef235d708ed7810d0613ccd946124
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Guillaume Vanleynseele <guva@odoo.com>
2022-05-12 02:00:03 +02:00
Pouya Malekinejad 4cc4037726 [FIX] account: Tax grids stay when removing a tax from invoice line
Currently, when the user removes a tax from an invoice line (tax_ids), the tax grid stays on the account move lines,
after this commit, when the tax is deleted in invoice line, the related tax_tags are removed from `aml.tax_tag_ids` which is the correct behavior

task ID:2843666

closes odoo/odoo#90950

Pr: #90836
X-original-commit: 27b3d3412b347ef7fb62626d5087eaf34621395a
Signed-off-by: Laurent Smet <las@odoo.com>
2022-05-11 11:28:55 +02:00
Merlin (megu) 339cdffb68 [FIX] account: use company name or id as suffix for journal alias name
Loading the demo data of Accounting app when only Japanese language is
installed will raise an error because there is a non-unique alias_name

Steps to reproduce:
1. - Run odoo with parameters `-d [db_name] --without-demo all
--load-language ja_JP -i l10n_jp,account_accountant` (you can also
install those apps using the UI but only Japanese should be installed
so it will be in Japanese)
   - Or create a trial database on odoo.com with Accounting installed,
using Japan as country and Japanese as language
2. Activate debug mode and go to Settings, scroll to the bottom and load
the demo data (`デモデータをロード`, last link in 'Developer Tools')
3. A validation error is thrown

Solution:
When building the alias name, if the name of the journal is not in
ascii, use the journal's code or type followed by the company's name. If
the company's name is not ascii, use the company id as suffix

Problem:
When a journal with non-ascii characters in its name is created, its
alias name fallbacks to the journal's code. In the demo data, two
journals have the same code. It will try to create the second journal
with the same alias name, violating the unicity check in
`_clean_and_check_unique`.

opw-2831638

closes odoo/odoo#90969

X-original-commit: 91d26b32250a74684dacad8350ac4452fa082384
Signed-off-by: William André (wan) <wan@odoo.com>
Signed-off-by: Guillaume Merlin (megu) <megu@odoo.com>
2022-05-10 14:16:59 +02:00
Guillaume (guva) d00fdb9310 [FIX] account: reconciliation on reversed move
With this commit, we make sure that all lines are fully reconciled when
reversing a move.

Steps to reproduce:

- Create a Journal Entry, with eg a line with 300$ debit/credit and two others
lines to make the journal entry fully balanced
- Then reverse the move
-> Only one line is marked as fully reconciled, the other one is marked
as partially reconciled.

This is because each line was passed in the reconcile method with
all the counterpart lines, even those which didn't belong to it.
Therefore, all the firsts lines was marked as partially reconciled
until the last one, which passed with the only counterpart line
left.

With this commit, we group the lines and counterpart lines by account,
and reconcile them.

opw-2810392

closes odoo/odoo#90928

X-original-commit: 0a03d029f93f6c0f31f6617c00943aa2dfcd937b
Signed-off-by: William André (wan) <wan@odoo.com>
Signed-off-by: Guillaume Vanleynseele <guva@odoo.com>
2022-05-09 19:56:50 +02:00
Camille Spiritus c9ce81c253 [FIX] account: allow batch payment for different clients
Description of the bug :
Registering a payment for two confirmed bills/invoices from different partners would result in a stack trace.

Steps to reproduce :
Create a bill from a specific partner and confirm it.
Create another from another partner, confirm it.
From the list view, select both those documents, click Register Payment.
The StackTrace appears.

FIX :
handled the case by setting the payment_difference field to 0.0 if the wizard contains multiple payment batches.
Modified some tests to detect this behaviour in the future.

closes odoo/odoo#89757

X-original-commit: def467e82b12c5ec7284ed9c966bb13ab3a77298
Signed-off-by: Laurent Smet <las@odoo.com>
2022-05-03 13:30:54 +02:00
Nicolas (vin) f34d863257 [FIX] account,*: Ensure tests using TestInvoicingCommon runs
Add a check in 'AccountTestInvoicingCommon' to ensure that all
tests using it are run in post_install.
These tests cannot be run at install, thus they would be ignored
and wouldn't run on the Runbot.

X-original-commit: 659ee179e1beed962026e3abac1bda322c2ac964
[FIX] account,*: Ensure tests using TestInvoicingCommon runs

Add a check in 'AccountTestInvoicingCommon' to ensure that all
tests using it are run in post_install.
These tests cannot be run at install, thus they would be ignored
and wouldn't run on the Runbot.

closes odoo/odoo#90242

X-original-commit: ec36b403edda3fbe3b5bd5f30f31ef6bad680967
Related: odoo/enterprise#26791
Signed-off-by: Florian Gilbert <flg@odoo.com>
Signed-off-by: William André (wan) <wan@odoo.com>
2022-05-02 18:48:52 +02:00
Laurent Smet 49d3e8e68d [FIX] account: Fix reconciliation rounding issue
Steps to reproduce:
- Create an invoice: select a product; set the price to 23.00$; change the currency to €; confirm the invoice.
- Create a receiving payment from the same customer: select the $ currency and put 100$
- Go back to the invoice and select the payment/reconcile the invoice and the payment.

Issue:
The payment is partial with 0.01€ to be paid.

Cause:
(conversion rate: 1.5289$/1€)

1) When the currency is changed or the price assigned, we convert the price EXCL. and then we convert the tax amount.

https://github.com/odoo/odoo/blob/582b43bdf46c485be8219e1cbeb60dbed033f1e7/addons/account/models/account_move.py#L3953-L3954

In our example:
- price EXCL.: 23€ * 1.5289 = 35.1647$
    price._convert() -> 35.16$
- Tax amount: 3.45€ * 1.5289 = 5.274705$
    tax_amount._convert() -> 5.27$
Real Sum = 40,439405$
Sum returned after convertion = 40.43$ != 40.44$

2) To compute what is left to be paid, we use the converted amount and convert it back to the currency of the invoice. Double conversion, double mistake.

https://github.com/odoo/odoo/blob/582b43bdf46c485be8219e1cbeb60dbed033f1e7/addons/account/models/account_move.py#L4873-L4878

In our example:

3) We convert back the 40.43$ to know the residual:
- 40.43$ / 1.5289 = 26.443848519€ => rounded = 26.44€ != 26.45

We then compute the `debit_amount_residual_currency` (26.45€) by substracting from it the `min_debit_amount_residual_currency`(26.44€).

https://github.com/odoo/odoo/blob/582b43bdf46c485be8219e1cbeb60dbed033f1e7/addons/account/models/account_move.py#L4886-L4887

Which lefts us with a `debit_amount_residual_currency` 0.01€ (0.0099999..801).
https://github.com/odoo/odoo/blob/582b43bdf46c485be8219e1cbeb60dbed033f1e7/addons/account/models/account_move.py#L1421-L1437

Ticket: 2765223
X-original-commit: ce1d64cdcf160e596dba97b29f970a8b9d87b348
Part-of: odoo/odoo#88265
2022-04-19 09:47:41 +02:00
Laurent Smet 5883f0a84c [IMP] account: foreign currency reconciliation (Exchange diff entries on partials)
* Previously, when reconciling  journal items in multi-currencies, the exchange difference entry was created only on the full reconciliation. It will now be created directly at each partial to ensure the ratio between amount_residual_currency and amount_residual is always kept identical.
* Also when reconciling two lines, one with a foreign currency and one expressed in company currency, the reconciliation is now made based on the foreign currency.

==== RATIONALE ====

This patch allows to fix the following use cases (among others)
1) When everything is expressed in foreign currency, the reconciliation is made in that currency:

Suppose EUR is the foreign currency and USD is the company currency. Reconciling:
L1: 120 EUR 60 USD (rate 2:1)
L2: 240 EUR 80 USD (rate 3:1)

..leads to a partial of 120 EUR and min(80, 60) = 60 USD

After the reconciliation, L1 is fully matched but L2 is still open with 120 EUR but only 20 USD.
This is the first problem is the current reconciliation because L2 is supposed to have a rate 3:1 so the residual amount should be 120 / 3 = 40 USD.
Since the rate is no longer consistent on L2, the user will probably close the reconciliation by using another line in EUR or will close manually the reconciliation with 20 USD but without any additional exchange difference journal items explaining where this unconsistency comes from.

2) When the current lines are mixing multiple currencies, the reconciliation is made using the company's currency.

In some countries like Mexico, Ethiopia or Costa Rica, the customer is free to pay an invoice using the company's currency instead of the foreign one.
So, suppose USD is the foreign currency and MXN is the company currency.
The invoice is expressed by:
L1: 120 USD 60 MXN (rate 2:1)
If the customer is paying at a date in which the rate is 3:1, he is free to pay
either L2: 120 USD 40 MXN (rate 3:1), either L2: 40 MXN.
In the second case, he is expecting the invoice to be fully paid because its paiement is equivalent to 120 USD at the payment date.

In Odoo, the second case led to an open balance of 20 MXN and the invoice was not completely paid.
Even this situation could be easily fixed by a manual write-off, this makes the Mexican payment EDI very complicated to fullfil correctly because the government is expecting a complete matching between the invoice and the payment.
When the customer is paying multiple invoices or the invoices are paid using multiple payments, the currently generated mexican EDI file in Odoo was wrong.

==== REFERENCES ====

Original idea suggested by hbto@vauxoo.com. Thanks for the contribution and patience of the many persons having, at some point, helped on that.

github issue: https://github.com/odoo/odoo/issues/37469

closes odoo/odoo#84201

Task: 2669371
Related: odoo/enterprise#24268
Signed-off-by: Quentin De Paoli <qdp@odoo.com>
2022-04-06 16:45:41 +02:00
Ivan Yelizariev d795f364f1 [FIX] account: invalidate moves cache after lines invalidation
This patch solves memory problem on exporting `account.move.line` records:
while export method invalidate cache for `account.move.line`, it keeps cache for
`account.move`, which may lead to memory error.

opw-2764457

closes odoo/odoo#88060

X-original-commit: 80c65498adf05b37d91207e0b59c781c6057f64b
Signed-off-by: Raphael Collet <rco@odoo.com>
2022-04-06 14:32:38 +02:00
wan d4fd9affc7 [FIX] account: clash in resequence
Have 3 moves named 0, 1 and 2
Delete move 1 to make a hole.
Resequence, starting the sequence at 2.

Expected: new names are 2 and 3

Result: an error because 1 is renamed to 2 but 2 still exists, leading
to a (temporary) duplicated name, which is not allowed.

We clear all the names to be resequenced before doing it in order to
avoid that.

closes odoo/odoo#87836

X-original-commit: bf5173f64582e2675f4121122ce26cb57624e08a
Signed-off-by: Quentin De Paoli <qdp@odoo.com>
Signed-off-by: William André (wan) <wan@odoo.com>
2022-04-02 00:54:49 +02:00
Laurent Smet cd6c33575b [IMP] account: Add generic methods to help the taxes computation
Unify taxes computation between 'account', 'sale' and 'purchase' including:
- computation of price_subtotal/price_total.
- computation of business models total (using the json field)

closes odoo/odoo#80231

Task: 2654784
Related: odoo/enterprise#25620
Signed-off-by: Olivier Colson <oco@odoo.com>
2022-03-29 20:20:15 +02:00
Thibault Delavallée 76b8d8f550 [REV] account: remove mail performance tests
Query counter tests related to account composer are actually dependent on
l10n due to extra queries, related to account.move fields and/or COA
specific code. Moreover some COA might skip or delay the sending, leading to
emails not being sent.

Purpose would be to run those tests only with generic_coa. Those tests will
be moved and improved soon, removing it currently to avoid frictions with
L10N builds.

This reverts odoo/odoo@d0e0db3b8e

closes odoo/odoo#86540

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-03-16 23:22:43 +01:00
Thibault Delavallée 11d44b9062 [IMP] account, website_sale: improve docstrings / notes
Purpose is to cleanup some remaining notes in code to better know some cleaning
is long awaited, planned but still not in WIP. Brol is not a recognized word
in the whole world. Also add some query counters explanation as counters are
a bit different depending on accounting, community and enterprise runs.

Part-of: odoo/odoo#86254
2022-03-14 17:28:26 +00:00
Brice bib Bartoletti f4c669d0e4 [FIX] account: price at 0, fixed tax price include
The aim of this commit is to correct the compute_all calculation
when it is dealing with an article with 0.00 price and having a fixed
tax included in it.

In this situation, this means the tax is directly taken as an expense
by the company that offers it to its client.

This also solves the situation in which we have a 100% discount because
discount is applied before calling `compute_all` by changing the
unit_price.

Before this commit:
Creating an invoice with a line having a price at 0 or a 100% discount
and a fixed tax price_include resulted in a really weird behavior: the
company had to reimburse the customer for the amount of the tax.
(what a lucky customer :D )

After this commit:
Customer is sad, he only gets the product for free.
The base is calculated as negative, resulting in a debit amount on the base
income line.
The tax is then counterbalance by it.

The form is displaying a negative untaxed amount, a positive tax and the
total is 0.

closes odoo/odoo#86223

Ticket: 2660808, 2637512
Community-pr: https://github.com/odoo/odoo/pull/85747
X-original-commit: 727d19cb4e012e9a24d94640987ac5ea6f452a2e
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Brice Bartoletti <bib@odoo.com>
2022-03-10 20:00:40 +00:00
Thibault Delavallée d0e0db3b8e [IMP] account: add performance test on account invoice send wizard
Just have some numbers before working on composer onchange removal and see
its impact.

Task-2789182 (Account: Invoice send performance test)
Prepares Task-2088884 (Mail: Composer onchange removal)

closes odoo/odoo#85902

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2022-03-08 16:48:42 +00:00
aliya 631212c895 [FIX] account: fix liquidity journal currency
Currently, if a liquidity journal has a currency set (e.g. Bank) the amount_currency shows lines according to the journal currency, which is correct. However, if the journal currency is the same as the company currency, the amount_currency shows the amount in the foreign currency that is not in fact held in the Bank.
Should be: follow the same logic for liquidity journals that have the same currency as the company (or set company currency by default) and show amount in journal/company currency.

closes odoo/odoo#85975

Task: 2779310
X-original-commit: 2e7a8e8200a4666baad74c9b596208841501c225
Signed-off-by: Laurent Smet <las@odoo.com>
2022-03-08 11:03:43 +00:00
Nicolas (vin) 745ad763a5 [FIX] account: invoice accounting date.
The accounting date and the related warnings were in some cases not
being set properly. This change aims to improve that by displaying
warnings in the view and updating the date on post instead of raising
user errors.
This will mostly affect sell documents.

Task id #2778958

closes odoo/odoo#85744

X-original-commit: 51ddb870d346ff61a6ae36c8c3b545eaca9736cb
Signed-off-by: William André (wan) <wan@odoo.com>
2022-03-03 12:58:01 +00:00
Laurent Smet aa856399db [FIX] account: Fix tax details with negative invoice lines
Before this commit:
Suppose invl1 of 1000.0 with 10.0% and invl2 of -100.0 with the same tax. A tax line of 90.0 is created.
If invl1 is created before invl2, the tax details is computing the tax amounts as:
invl1 tax amount = 1000/900 * 90 = 100 (OK)
invl2 tax amount = 90 - 100 = -10 (OK)
total tax amount = 100 - 10 = 90 (OK)
If invl2 is created before invl2:
invl1 tax amount = 100/900 * 90 = 10 (NOT OK)
invl2 tax amount = 90 - 10 = 80 (NOT OK)
total tax amount = 10 + 80 = 90 (OK)

closes odoo/odoo#85406

X-original-commit: bada85c7621b45970c88548c4d09b88b77c08e8e
Signed-off-by: Olivier Colson <oco@odoo.com>
Signed-off-by: Laurent Smet <las@odoo.com>
2022-02-28 10:14:48 +00:00
Julien Castiaux c0647b5c52 [REF] core: HTTPocalypse (14) changes all addons
This commit is the 14th commit of a comprehensive refactor of our HTTP
framework. See odoo/odoo#78857 for complete historic, discussions and
rationnals.

* `request.uid = x` => `request.update_env(user=x)`.
* `request.context = x` => `request.update_env(context=x)`.
* `request.context = dict(request.context, x=y)`
   => `request.update_context(x=y)`.
* `request.cr = None` => `request.cr.close()`.
* `http.mono_db()` => `request.db`.
* `http.dispatch_rpc()` => `service.dispatch_rpc()`.
* `@service.model.check` => `service.model.retrying()`.
* `request.endpoint`
   => `env['ir.http']._match(request.httprequest.path)[0].endpoint`.
* `request.routing_iteration `=> `removed`.
* `request.jsonrequest` => `request.dispatcher.jsonrequest`.

Note that `request.params` is now set much later in the process. If you
are in a situation where you values from the query string or the
http body you can use `request.get_http_params()`.

Note that using the new `request.future_response`, it is possible to
add headers and cookies on the response object before the response
object is initialized. Please note that headers/cookies saved on
the future response will NOT be injected in case of error.

PR: odoo#78857
Task: 2571224
2022-02-24 13:30:51 +00:00
jbw ff9adda52e [FIX] account: don't map repartition lines on cash basis reversal
To reproduce the issue:
    - create a cash basis tax, with different account and tags for invoice and refund
    - make an customer invoice using this tax, post it, and register a full payment for it
    - unreconcile the payment

=> Two cash basis moves have been generated: one for the initial reconciliation, and another one reverting it when the reconciliation got cancelled.

=> Bug: the reverse move uses the refund repartition, while the original one is using the invoice's one, so they don't sum up to zero. It's wrong: since the reconciliation got cancelled, we want the impact of the invoice on our tax report to be 0 again, just as if it was brand new.

closes odoo/odoo#84727

X-original-commit: b9e94def7dd84a6a02ddb76959400b8d8fbc5025
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Olivier Colson <oco@odoo.com>
2022-02-16 16:57:29 +00:00
jbw df37d3ef91 [REV] account: commit d22cd54
d22cd54 introduced the fact that when doing a full refund of an invoice, the same account was used as on the original invoice, instead of the one on the tax refund repartition lines, though the tags were still the refund ones. This is wrong.

Also, it restored an inconsistent data setup in a test, while the current version was actually correct.

X-original-commit: 031f017a5a696874065cb5873f2fecd5c4b177ed
Part-of: odoo/odoo#84727
2022-02-16 16:57:28 +00:00
Nicolas (vin) d0c3e6cba1 [FIX] account: fix tax line partner assignation
When creating a new invoice by giving it an invoice_line_ids list for
which the last line is a note, the tax line may be created wrongfully
without partner_id, which is totally wrong.

To reproduce :

Create a SO
Set a customer
Insert a product with tax
Insert a note
Deliver the product
Invoice the SO and confirm the invoice
The partner_id is not set on the created tax line

While the issue only arises in 15.0, it brings to light that the partner
is not in the grouping keys while it should, so it will be changed in 13.0+

opw-2750851

closes odoo/odoo#83999

X-original-commit: 2ce994d279126aa0356b86d3fa38b699e9035e54
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Nicolas Viseur <vin@odoo.com>
2022-02-04 17:56:35 +00:00
0b38cc527b [IMP] account: implementation of storno accounting
Storno accounting is the term used to described the process of recording
a reverse action as a negative amount on the same site instead of a
positive amount on the opposite site of the credt/debit.
For instance, when one creates a credit note for an invoice, the values
of debit and credit will be kept in the same column with negative signs
instead of swapping columns like in non-Storno accounting.

It is a business practice commonly used in Eastern European countries.

Countries where Storno accounting is mandatory or considered as best
practice would be :
Czech Republic, Poland, Romania, Russia, Slovakia, Ukraine, Croatia,
Bosnia and Herzegovina, Serbia, Romania, China, Russia, Slovenia

It is available as an option in the settings and is automatically
activated for some countries which use this type of accounting.

otask-2064899

closes odoo/odoo#79581

Related: odoo/upgrade#3212
Signed-off-by: William André (wan) <wan@odoo.com>
Co-authored-by: william-andre <wan@odoo.com>
Co-authored-by: qdp-odoo <qdp@odoo.com>
2022-02-03 15:21:28 +00:00
John Laterre (jol) a8628c5697 [IMP] account: add test for fiscal positions with delivery address
The goal is to test various use cases related to fiscal positions
having a specific delivery address.

The use cases are as follows:

- Case : 1
Billing (VAT/country) : BE/BE
Delivery (VAT/country) : NL/NL
Expected FP : Régime National

- Case : 2
Billing (VAT/country) : NL/NL
Delivery (VAT/country) : BE/BE
Expected FP : Régime National

- Case : 3
Billing (VAT/country) : BE/BE
Delivery (VAT/country) : None/NL
Expected FP : Régime National

- Case : 4
Billing (VAT/country) : NL/NL
Delivery (VAT/country) : NL/NL
Expected FP : Régime Intra-Communautaire

- Case : 5
Billing (VAT/country) : None/NL
Delivery (VAT/country) : None/NL
Expected FP : EU privé

- Case : 6
Billing (VAT/country) : None/US
Delivery (VAT/country) : None/US
Expected FP : Régime Extra-Communautaire

closes odoo/odoo#83714

X-original-commit: e7f112ab658b2254d0663207831f4eabdfcec166
Signed-off-by: Quentin De Paoli <qdp@odoo.com>
Signed-off-by: Laurent Smet <las@odoo.com>
2022-02-01 11:53:05 +00:00