From fe3e84085fc9446fb2b745d99df341de980a92c0 Mon Sep 17 00:00:00 2001 From: Ivan Yelizariev Date: Tue, 27 Apr 2021 12:48:34 +0000 Subject: [PATCH] [FIX] point_of_sale: speed up reading computed session fields Context * postgres 12.5 * Odoo 14 DB Stats * pos.payment: 645 K * pos.order by company: 379 K, 1 K, 973 K, 19 K total_payments_amount ===================== Result: 0.02 sec vs 33.6 sec POS Session Stats: * pos.order: 27 K * pos.payment: 39 K BEFORE 22 33.467 0.123 (number of queries, query time, rest time) AFTER read_group refactoring: 4 3.952 0.006 AFTER read_group + session_id index 4 2.770 0.009 AFTER read_group + session_id index + store company_id 4 0.009 0.006 _compute_cash_balance ===================== Result: 0.1 sec vs 9.2 sec POS Session Stats: * pos.order: 59 K * pos.payment: 82 K BEFORE 399 1.695 7.587 AFTER 21 0.123 0.016 _compute_picking_count ====================== Result: 0.7 sec vs 3.5 sec POS Session stats * pos.order: 107 K * stock.picking: 60 K BEFORE 126 1.007 2.452 AFTER 5 0.723 0.011 --- opw-2514640 closes odoo/odoo#73444 X-original-commit: 68bed01a73505870fb4fa41ae9cd8471d055b27f Signed-off-by: pimodoo --- addons/point_of_sale/models/pos_payment.py | 4 ++-- addons/point_of_sale/models/pos_session.py | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/addons/point_of_sale/models/pos_payment.py b/addons/point_of_sale/models/pos_payment.py index 3fe006c0749..fe43e07df08 100644 --- a/addons/point_of_sale/models/pos_payment.py +++ b/addons/point_of_sale/models/pos_payment.py @@ -23,8 +23,8 @@ class PosPayment(models.Model): currency_id = fields.Many2one('res.currency', string='Currency', related='pos_order_id.currency_id') currency_rate = fields.Float(string='Conversion Rate', related='pos_order_id.currency_rate', help='Conversion rate from company currency to order currency.') partner_id = fields.Many2one('res.partner', string='Customer', related='pos_order_id.partner_id') - session_id = fields.Many2one('pos.session', string='Session', related='pos_order_id.session_id', store=True) - company_id = fields.Many2one('res.company', string='Company', related='pos_order_id.company_id') + session_id = fields.Many2one('pos.session', string='Session', related='pos_order_id.session_id', store=True, index=True) + company_id = fields.Many2one('res.company', string='Company', related='pos_order_id.company_id') # TODO: add store=True in master card_type = fields.Char('Type of card used') cardholder_name = fields.Char('Cardholder Name') transaction_id = fields.Char('Payment Transaction ID') diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py index af1b7ba1fa8..12c25c1da79 100644 --- a/addons/point_of_sale/models/pos_session.py +++ b/addons/point_of_sale/models/pos_session.py @@ -110,7 +110,10 @@ class PosSession(models.Model): for session in self: cash_payment_method = session.payment_method_ids.filtered('is_cash_count')[:1] if cash_payment_method: - total_cash_payment = sum(session.order_ids.mapped('payment_ids').filtered(lambda payment: payment.payment_method_id == cash_payment_method).mapped('amount')) + total_cash_payment = 0.0 + result = self.env['pos.payment'].read_group([('session_id', '=', self.id), ('payment_method_id', '=', cash_payment_method.id)], ['amount'], ['session_id']) + if result: + total_cash_payment = result[0]['amount'] session.cash_register_total_entry_encoding = session.cash_register_id.total_entry_encoding + ( 0.0 if session.state == 'closed' else total_cash_payment ) @@ -123,8 +126,10 @@ class PosSession(models.Model): @api.depends('order_ids.payment_ids.amount') def _compute_total_payments_amount(self): + result = self.env['pos.payment'].read_group([('session_id', 'in', self.ids)], ['amount'], ['session_id']) + session_amount_map = dict((data['session_id'][0], data['amount']) for data in result) for session in self: - session.total_payments_amount = sum(session.order_ids.mapped('payment_ids.amount')) + session.total_payments_amount = session_amount_map.get(session.id) or 0 def _compute_order_count(self): orders_data = self.env['pos.order'].read_group([('session_id', 'in', self.ids)], ['session_id'], ['session_id']) @@ -135,8 +140,8 @@ class PosSession(models.Model): @api.depends('picking_ids', 'picking_ids.state') def _compute_picking_count(self): for session in self: - session.picking_count = len(session.picking_ids.ids) - session.failed_pickings = bool(session.picking_ids.filtered(lambda p: p.state != 'done')) + session.picking_count = self.env['stock.picking'].search_count([('pos_session_id', '=', session.id)]) + session.failed_pickings = bool(self.env['stock.picking'].search([('pos_session_id', '=', session.id), ('state', '!=', 'done')], limit=1)) def action_stock_picking(self): self.ensure_one()