[FIX] account: compute partner ranks at post() + fixes
closes odoo/odoo#36080 Signed-off-by: Fabien Pinckaers <fpodoo@users.noreply.github.com>
This commit is contained in:
@@ -14,6 +14,7 @@ from itertools import zip_longest
|
||||
import json
|
||||
import re
|
||||
import logging
|
||||
import psycopg2
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -1900,6 +1901,26 @@ class AccountMove(models.Model):
|
||||
# installing Accounting- with bank statements)
|
||||
move.company_id.account_bank_reconciliation_start = move.date
|
||||
|
||||
for move in self:
|
||||
if not move.partner_id: continue
|
||||
if move.type.startswith('out_'):
|
||||
field='customer_rank'
|
||||
elif move.type.startswith('in_'):
|
||||
field='supplier_rank'
|
||||
else:
|
||||
continue
|
||||
try:
|
||||
with self.env.cr.savepoint():
|
||||
self.env.cr.execute("SELECT "+field+" FROM res_partner WHERE ID=%s FOR UPDATE NOWAIT", (move.partner_id.id,))
|
||||
self.env.cr.execute("UPDATE res_partner SET "+field+"="+field+"+1 WHERE ID=%s", (move.partner_id.id,))
|
||||
self.env.cache.remove(move.partner_id, move.partner_id._fields[field])
|
||||
except psycopg2.DatabaseError as e:
|
||||
if e.pgcode == '55P03':
|
||||
_logger.debug('Another transaction already locked partner rows. Cannot update partner ranks.')
|
||||
continue
|
||||
else:
|
||||
raise e
|
||||
|
||||
def action_reverse(self):
|
||||
action = self.env.ref('account.action_view_account_move_reversal').read()[0]
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import time
|
||||
import psycopg2
|
||||
import logging
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
@@ -10,8 +9,6 @@ from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.addons.base.models.res_partner import WARNING_MESSAGE, WARNING_HELP
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class AccountFiscalPosition(models.Model):
|
||||
_name = 'account.fiscal.position'
|
||||
_description = 'Fiscal Position'
|
||||
@@ -439,8 +436,8 @@ class ResPartner(models.Model):
|
||||
invoice_warn_msg = fields.Text('Message for Invoice')
|
||||
# Computed fields to order the partners as suppliers/customers according to the
|
||||
# amount of their generated incoming/outgoing account moves
|
||||
supplier_rank = fields.Integer(compute='_compute_rank', store=True)
|
||||
customer_rank = fields.Integer(compute='_compute_rank', store=True)
|
||||
supplier_rank = fields.Integer(default=0)
|
||||
customer_rank = fields.Integer(default=0)
|
||||
|
||||
def _get_name_search_order_by_fields(self):
|
||||
res = super()._get_name_search_order_by_fields()
|
||||
@@ -456,67 +453,6 @@ class ResPartner(models.Model):
|
||||
order_by_field = order_by_field % field
|
||||
return '%s, %s' % (res, order_by_field % field) if res else order_by_field
|
||||
|
||||
@api.depends('invoice_ids', 'invoice_ids.state')
|
||||
def _compute_rank(self):
|
||||
"""
|
||||
The two field values may not be exact in the database!
|
||||
To avoid any concurrent update failure while writing on the partner,
|
||||
the count is not updated if the lock cannot be directly acquired.
|
||||
The count will eventually be correctly computed, at the next successfull try.
|
||||
"""
|
||||
types_in = ('in_invoice', 'in_refund', 'in_receipt')
|
||||
types_out = ('out_invoice', 'out_refund', 'out_receipt')
|
||||
partner_ids = tuple(self.ids)
|
||||
queries_params = {
|
||||
'supplier_rank': {
|
||||
'partner_id': partner_ids,
|
||||
'move_types': types_in
|
||||
},
|
||||
'customer_rank': {
|
||||
'partner_id': partner_ids,
|
||||
'move_types': types_out
|
||||
},
|
||||
}
|
||||
|
||||
# Update database in case an invoice is just created
|
||||
self.flush()
|
||||
for field, params in queries_params.items():
|
||||
try:
|
||||
with self.env.cr.savepoint():
|
||||
# Check if rows are not locked
|
||||
# Take this opportunity to retrieve the current partner ranks
|
||||
# If a customer has been created from the "Customer" menuitem
|
||||
# his rank should be equal to 1, even if no invoice has been
|
||||
# created for him yet
|
||||
self.env.cr.execute("""
|
||||
SELECT id, COALESCE({}, 0)
|
||||
FROM res_partner
|
||||
WHERE id IN %(partner_id)s
|
||||
FOR UPDATE NOWAIT
|
||||
""".format(field), params, log_exceptions=False)
|
||||
current_counts = dict(self.env.cr.fetchall())
|
||||
# Compute the real ranks, based on the posted
|
||||
# account moves generated from the invoices
|
||||
self.env.cr.execute("""
|
||||
SELECT m.partner_id, COUNT(*) AS move_count
|
||||
FROM account_move AS m
|
||||
WHERE
|
||||
type in %(move_types)s
|
||||
AND state = 'posted'
|
||||
AND partner_id IN %(partner_id)s
|
||||
GROUP BY m.partner_id
|
||||
""", params)
|
||||
counts = dict(self.env.cr.fetchall())
|
||||
# Update all ranks
|
||||
for partner in self:
|
||||
partner[field] = max(counts.get(partner.id, 0), current_counts.get(partner.id, 0))
|
||||
except psycopg2.DatabaseError as e:
|
||||
if e.pgcode == '55P03':
|
||||
_logger.debug('Another transaction already locked partner rows. Cannot update partner ranks now.')
|
||||
continue
|
||||
else:
|
||||
raise e
|
||||
|
||||
def _compute_bank_count(self):
|
||||
bank_data = self.env['res.partner.bank'].read_group([('partner_id', 'in', self.ids)], ['partner_id'], ['partner_id'])
|
||||
mapped_data = dict([(bank['partner_id'][0], bank['partner_id_count']) for bank in bank_data])
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">res.partner</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context">{'search_default_customer': 1,'res_partner_search_mode': 'customer', 'default_is_company': True}</field>
|
||||
<field name="context">{'search_default_customer': 1,'res_partner_search_mode': 'customer', 'default_is_company': True, 'default_customer_rank': 1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a new customer in your address book
|
||||
@@ -237,7 +237,7 @@
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">res.partner</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context">{'search_default_supplier': 1,'res_partner_search_mode': 'supplier', 'default_is_company': True}</field>
|
||||
<field name="context">{'search_default_supplier': 1,'res_partner_search_mode': 'supplier', 'default_is_company': True, 'default_supplier_rank': 1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a new supplier in your address book
|
||||
|
||||
Reference in New Issue
Block a user