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
closesodoo/odoo#96134
Related: odoo/upgrade#3715
Related: odoo/enterprise#29758
Signed-off-by: Laurent Smet <las@odoo.com>
Before when reporting in the sale module in a multi-company
environment currencies where not converted to a unique currency
before mathematical operations (sum, avg, ...).
Now before mathematical operations currencies are converted to
the currency of the company currently selected.
Task - 2696759
closesodoo/odoo#83550
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Finetuning of #85774Fixes#86174closesodoo/odoo#86260
X-original-commit: 6fff9ac8b4f86469c11e404442f928c2b6616e2b
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
For now the sale margin is incorrectly computed in group by
opw-2767397
closesodoo/odoo#86016
X-original-commit: 9c2915ad9bd5bf1d6eacf8f3a4e14bcd1d4af9f7
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Signed-off-by: Achraf <abz@odoo.com>
* remove unused delay column (there was no field using the value server
side)
* remove unused joins in the FROM part of the table definition (join on
pricelists)
* fix broken inheritance API
pos_sale inheritance adds a null value for fields not available added in
sub modules (website, invoice_status, ...). But this was only working
because the default value of the fields parameter of the _query method
was overridden to a dict in all overrides, filling the record while
climbing the inheritance chain.
This was clearly too magic, using information provided higher in the
inheritance chain, assuming you were calling the super before generating
the pos part of the query.
This commit cleans the methods and API of the model, providing clean
hooks and reducing the mess of values given in overrides of _query.
closesodoo/odoo#85125
Related: odoo/enterprise#24626
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
* Split python file by classes
* Remove empty ir.model.access.csv file
* Correct name for views file
* Use setUpClass instead of setUp to avoid multiple setups during tests
Part-of: odoo/odoo#85001
Prior to this commit, the cost of a service product was computed based
on its standard_price.
With this commit, the product cost is computed based on the timesheet
amounts linked to the sale order, if the sale order has a delivering
method of type timesheet.
PR : #70527
See odoo/upgrade#2616
task-2458135
A new field on tax groups makes it now possible for this group to be displayed under a subtotal label. If not set, this defaults instead to "Untaxed Amount", keeping the traditional behavior. This is intended for withholding taxes, which can now be implemented with negative taxes and a tax group with this field set.
To do that, this commit entirely refactors the way amount_by_group worked, and replaces it with a more complete json field called tax_totals_json. It also streamlines the way taxe totals are displayed on invoices, PO and SO and makes it so that a common code is called instead of copy-pasting the same block 3 times as before.
[IMP] purchase: always display tax totals by groups on purchases orders
Before, tax totals on purchase.order's form were not shown by group, and were instead all aggregated in a single "Taxes" category. The same went for the pdf export. The portal view, though, did show the totals by group. We now display the tax groups in the same way all the time.
closesodoo/odoo#74138
Task: 2457374
Related: odoo/enterprise#19802
Related: odoo/upgrade#2670
Signed-off-by: Quentin De Paoli (qdp) <qdp@openerp.com>
The license is missing in most enterprise manifest so
the decision was taken to make it explicit in all cases.
When not defined, a warning will be triggered starting from
14.0 when falling back on the default LGPL-3.
closesodoo/odoo#74245
Related: odoo/design-themes#48
Related: odoo/enterprise#19862
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
- Create a service product with cost 0
- Create a sales quotation
- Add the service product, change the cost to a positive quantity
- Save and Confirm.
Purchase Price (cost) will be reset to 0
opw-2481564
closesodoo/odoo#70036
X-original-commit: 8a8ff03f6111f377bcd9c2b0f584c450b82a4182
Signed-off-by: agr-odoo <agr-odoo@users.noreply.github.com>
Steps to reproduce the bug:
- Activate Margins in Sales > Settings
- Go to the pivot view of quotations
- In Measures, click Margin (%)
Bug:
Margin percentages are aggregated by computing the sum of the margin sub-percentages instead of using the data of the aggregated row (i.e. agg. margin / agg. total).
Explanation:
This is one of the flaws of the pivot view. The best way to solve this would be to create a custom aggregation in PostgreSQL.
This commit is just hiding the measure for now.
opw:2349896
closesodoo/odoo#60354
X-original-commit: 1e3fc6894b13d51a3f6327653afbf8d5a316a21d
Signed-off-by: backspac <backspac@users.noreply.github.com>
When installing sale_margin, the computed fields will be computed on existing
sale.order and sale.order.line in database. On huge databases, the computation
may take a lot of time, depending on the configuration (multi-company, multi-currency, ...)
The current commit improves the computation of the purchase_price
(recently changed to a computed field), by avoiding unnecessary currency
conversions when possible (one less query to get the conversion rates).
In a multi-currency database where the products have no cost defined
(standard_price field), the sale_margin installation takes up to 50% less time.
closesodoo/odoo#52338
X-original-commit: 3c9841d1aa4fc5b10012c8239a31d6e7f8676fc0
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Installing sale_margin module on a db with a lot of sale.order was impossible.
This commit significantly improves performances.
Went from many hours (forecasted) to 15 minutes on a db with 300k orders
For sale.order:
- Duplicating logic between edit mode and non edit mode
- Edit mode logic stays the same as before
- Non edit mode uses read_group to speed up the computation
X-original-commit: 9f1ea7427cdb6984f175f5111e4c9a4c5f013af2
And use "Margin (%)" for the recently added margin_percent field
computing the margin in % and not in money.
closesodoo/odoo#43130
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Onchanges can be triggered after computes and therefore, we could have a line with an uom
but without product, leading to a conversion from "no uom" to the order line uom, which isn't
accepted.
closesodoo/odoo#42691
X-original-commit: 1bc9963cfc19a4bc5896a647423f81274936db00
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
New field to express the profitability percentage of a Sales Order (/SO line).
task-2033253
closesodoo/odoo#39926
Signed-off-by: Damien Bouvy (dbo) <dbo@odoo.com>
Without demo data, for the odoo-master transifex project
closesodoo/odoo#41935
X-original-commit: dab7670b73506fb3a835695ee3bd735e0c5e5c2b
Related: odoo/enterprise#7287
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Since the purchase_price is now computed, it may be triggered before an
uom is set on the product line (onchanges may happen after computes).
closesodoo/odoo#41808
X-original-commit: 9ebbdd24752a0ff1c1057fc533074555810ffa39
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Followup of a425695e
The terms were back in 12.0
Courtesy of Juan José Scarafía
closesodoo/odoo#41624
X-original-commit: 85d0c7001a997748d7691205bbb8d066597591a5
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
When creating sale order lines from the matrix (sale_product_matrix),
the purchase_price weren't computed
No cleaner change has been found to ensure the cost is computed.
Triggering all onchanges from the server side is quite tricky and dirty
to do...
closesodoo/odoo#40986
X-original-commit: 5c15b1310729129e390b455b0d1e0ac367f8dd69
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
This commit removes some groups that are now useless since their
only purpose was to allow the user to hide or show some fields
depending on its value, but those fields are optional now.
Task-1902765
closesodoo/odoo#31944
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
The goal is to be coherent with the user property.
Actually, company_id and company_ids on the environment are no fields.
Calling env.company_id returns a browse record, not an id.
* account, hr_contract, hr_expense, point_of_sale, sale_margin,
website_sale_delivery, website_sale_wishlist
digits only works on Float fields, on Monetary fields it has no
effect:
- The column_type of a monetary field is always numeric
- It is not applied in `convert_to_column()` or `convert_to_cache()`
- It is not part of `description_attrs`, so it will not be included in
the output of `fields_get()`
closesodoo/odoo#35336
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Since previous commit moved decimal_precision module's feature into base,
use the new syntax for fields declaration
Remove the imports to the removed module
Remove the module from dependency in manifest
sed -i "s|digits=dp.get_precision('\([A-Z a-z]*\)')|digits='\1'|" **.py
sed -i "/from odoo.tools import decimal_precision as dp/d" **py