New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[IMP] De-normalizing sale.order to add applicable rate on the sale.order #25089
Conversation
@odony added rate on sale.order to speed up sale report. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides the runbot errors, I would have expected to add denormalized subtotals/totals fields, similarly to what is done in invoices, rather than just the rate.
It does seem cheaper to only store the rate, though, so perhaps @qdp-odoo could help us and explain why it was considered better to include the full amounts for invoices?
I added only the rate because :
|
a26d62d
to
59aeb05
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Smalls changes required, and some questions.
Otherwise, I totally agree with the principe ;)
addons/sale/models/sale.py
Outdated
@api.depends('pricelist_id', 'date_order', 'company_id') | ||
def _compute_rate(self): | ||
for order in self: | ||
order.currency_rate = order.currency_id._get_rates(order.company_id, order.date_order).get(order.currency_id.id, 1.0) if order.currency_id else 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if order.currency_id
seems useless since the currency_id
field is required.
addons/sale/models/sale.py
Outdated
@@ -157,7 +163,8 @@ def _compute_tax_id(self): | |||
amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all', track_visibility='onchange') | |||
amount_tax = fields.Monetary(string='Taxes', store=True, readonly=True, compute='_amount_all') | |||
amount_total = fields.Monetary(string='Total', store=True, readonly=True, compute='_amount_all', track_visibility='always') | |||
|
|||
currency_rate = fields.Float(digits=(12, 6), default=1.0, help='The rate of the currency to the currency of rate 1 applicable at the date of the order', store=True, readonly=True, compute='_compute_rate') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not important: order the kwargs; string, compute, store, digits, readonly and help.
Not sur sure the default value is important as this is a computed field.
@@ -37,10 +36,10 @@ def _so(self): | |||
so.user_id AS user_id, | |||
pt.categ_id AS categ_id, | |||
so.company_id AS company_id, | |||
sol.price_total / COALESCE(cr.rate, 1.0) AS price_total, | |||
sol.price_total / CASE COALESCE(so.currency_rate, 0) WHEN 0 THEN 1.0 ELSE so.currency_rate END AS price_total, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the so.currency_rate is NULL, then the coalesce will return 0 so we enter the WHEN and take the THEN value. Isn't it simpler to use COALESCE(so.currency_rate, 1.0)
directly, or did I miss something ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(same for the other SQL report ;) )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jem-odoo if currency_rate is equal to 0, I would like to avoid a 0 division. I can change the COALESCE with 1.0, but the case currency_rate=0 will still be possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed ! COALESCE take the first not NULL value, and not the one not evaluated to False. My bad ^^"
59aeb05
to
19fcec6
Compare
@jem-odoo Other changes done |
addons/sale/models/sale.py
Outdated
@api.depends('pricelist_id', 'date_order', 'company_id') | ||
def _compute_rate(self): | ||
for order in self: | ||
order.currency_rate = order.currency_id._get_rates(order.company_id, order.date_order).get(order.currency_id.id, 1.0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a pretty common use case where the rate is agreed between parts.
Example:
- In México the rate in a sale order is agreed at the date of the closing date.
- In Costa Rica the rate is at the moment of the payment.
- In Canada/EEUU relationships the Rate can be set once per year instead per transactions.
- In overinflationary countries the rate can be set at the moment of payment.
If you make this field Record = True and make possible to use such field able to be set (with an inverse) this will help A LOT, and almost effortless.
Feature:
By default this logic is perfect, but order by order this can be set manually or using any other logic with a simple write.
The only thing you need to do is allow the readonly=False and set the inverse to allow securelly write it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @jem-odoo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This commit aims to improve the performance, and unfortunately not changing the existing feature. Since we are near the release what you asked can not be done, but I transfert your request on the Product Owner Team ;)
@odony about the fact that we store all the different amounts in the accounting: that's only code legacy. It has been done that way and nobody never challenged it before... but I suppose it'sit's okay since we want to be able to order invoices by these computed totals, and use them easily in the invoice analysis view... |
19fcec6
to
0f26642
Compare
2ea5a28
to
6e55e97
Compare
Impacted modules: sale, sale_margin, sale_timesheet, pos_sale This speed up a lot reports like sale.report when multiple currencies with multiple rates are used, even with few currencies and few rates. Using `_select_companies_rates` in SQL view bring lots of JOINs, which slow down the view generation. This commit adds a computed stored field containing the currency rate at the order date to speed up report generation (database schema denormalisation). This commit also use this new column on sale.report extensions and on the project.profitability.report in sale_timesheet module. Since a4d6bff, the pos.report is included in the sale.report. So, the same change had to be applied on the pos.order model. Task #1877418 Closes odoo#25089
6e55e97
to
32c1e08
Compare
Impacted modules: sale, sale_margin, sale_timesheet, pos_sale This speed up a lot reports like sale.report when multiple currencies with multiple rates are used, even with few currencies and few rates. Using `_select_companies_rates` in SQL view bring lots of JOINs, which slow down the view generation. This commit adds a computed stored field containing the currency rate at the order date to speed up report generation (database schema denormalisation). This commit also use this new column on sale.report extensions and on the project.profitability.report in sale_timesheet module. Since a4d6bff, the pos.report is included in the sale.report. So, the same change had to be applied on the pos.order model. Task #1877418 Closes #25089
Merged at e8f01b9 |
This speed up a lot reports like sale.report when multiple currencies with multiple rates are used, even with few currencies and few rates.
Description of the issue/feature this PR addresses:
Current behavior before PR:
Desired behavior after PR is merged:
--
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr