From e50f762aa92db2076125f02e524cce01d7b10c6c Mon Sep 17 00:00:00 2001 From: Alvaro Fuentes Date: Tue, 6 Jun 2023 12:30:59 +0000 Subject: [PATCH] [FIX] point_of_sale: fix memory error When there are too many (millions) of POS order lines associated to opened POS sessions we get too many taxes, most are duplicated. This causes a MemorryError. Example queries from a real DB: ``` > select count(distinct r.account_tax_id) from pos_order_line l join pos_order o on o.id = l.order_id join pos_session s on s.id = o.session_id join account_tax_pos_order_line_rel r on r.pos_order_ line_id = l.id where s.state != 'closed' +-------+ | count | |-------| | 24 | +-------+ > select count(r.account_tax_id) from pos_order_line l join pos_order o on o.id = l.order_id join pos_session s on s.id = o.session_id join account_tax_pos_order_line_rel r on r.pos_order_line_id = l.id where s.state != 'closed' +---------+ | count | |---------| | 2504539 | +---------+ ``` opw-3295467 closes odoo/odoo#124990 X-original-commit: b5870af0fd74118d96cbd130f3b319e2319d82f8 Signed-off-by: Christophe Simonis (chs) --- addons/point_of_sale/models/account_tax.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/addons/point_of_sale/models/account_tax.py b/addons/point_of_sale/models/account_tax.py index 3cd0d4841a9..d5dd8cb6843 100644 --- a/addons/point_of_sale/models/account_tax.py +++ b/addons/point_of_sale/models/account_tax.py @@ -2,23 +2,27 @@ from odoo import _, api, models from odoo.exceptions import UserError +from odoo.tools import split_every class AccountTax(models.Model): _inherit = 'account.tax' def write(self, vals): - forbidden_fields = set([ + forbidden_fields = { 'amount_type', 'amount', 'type_tax_use', 'tax_group_id', 'price_include', 'include_base_amount', 'is_base_affected', - ]) + } if forbidden_fields & set(vals.keys()): - open_lines = self.env['pos.order.line'].sudo().search([ + lines = self.env['pos.order.line'].sudo().search([ ('order_id.session_id.state', '!=', 'closed') ]) - if not set(self.ids).isdisjoint(open_lines.tax_ids.ids): - raise UserError(_( - 'It is forbidden to modify a tax used in a POS order not posted. ' - 'You must close the POS sessions before modifying the tax.' - )) + self_ids = set(self.ids) + for lines_chunk in map(self.env['pos.order.line'].browse, split_every(100000, lines.ids)): + if any(tid in self_ids for ts in lines_chunk.read(['tax_ids']) for tid in ts['tax_ids']): + raise UserError(_( + 'It is forbidden to modify a tax used in a POS order not posted. ' + 'You must close the POS sessions before modifying the tax.' + )) + lines_chunk.invalidate_recordset(['tax_ids']) return super(AccountTax, self).write(vals)