[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 <pimodoo@users.noreply.github.com>
This commit is contained in:
Ivan Yelizariev
2021-07-08 15:22:34 +00:00
parent 16375995de
commit fe3e84085f
2 changed files with 11 additions and 6 deletions
+2 -2
View File
@@ -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')
+9 -4
View File
@@ -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()