[IMP] stock_account: create account moves in batch

This commit groups creation and posting of account moves related to
stock valuation in case of automatic valuation product.

Previously, the account move were created one by one and posted right at
the creation. Which can really slow (for instance running
_run_fifo_vaccum with a large amount of remaining quantity layer)

closes odoo/odoo#62700

Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
This commit is contained in:
William Henrotin
2020-12-08 13:40:54 +00:00
parent e95b9c068f
commit 7fa9ec2638
4 changed files with 46 additions and 42 deletions
+6 -5
View File
@@ -362,6 +362,7 @@ class ProductProduct(models.Model):
('stock_move_id', '!=', False),
('company_id', '=', company.id),
], order='create_date, id')
as_svls = []
for svl_to_vacuum in svls_to_vacuum:
domain = [
('company_id', '=', svl_to_vacuum.company_id.id),
@@ -431,13 +432,13 @@ class ProductProduct(models.Model):
if product.cost_method == 'average' and not float_is_zero(product.quantity_svl, precision_rounding=self.uom_id.rounding):
product.sudo().with_context(disable_auto_svl=True).write({'standard_price': product.value_svl / product.quantity_svl})
# Create the account move.
if self.valuation != 'real_time':
continue
vacuum_svl.stock_move_id._account_entry_move(
vacuum_svl.quantity, vacuum_svl.description, vacuum_svl.id, vacuum_svl.value
)
# Create the related expense entry
as_svls.append((vacuum_svl, svl_to_vacuum))
self.env['stock.valuation.layer'].browse(x[0].id for x in as_svls)._validate_accounting_entries()
for vacuum_svl, svl_to_vacuum in as_svls:
self._create_fifo_vacuum_anglo_saxon_expense_entry(vacuum_svl, svl_to_vacuum)
def _create_fifo_vacuum_anglo_saxon_expense_entry(self, vacuum_svl, svl_to_vacuum):
+22 -33
View File
@@ -260,12 +260,7 @@ class StockMove(models.Model):
stock_valuation_layers |= getattr(todo_valued_moves, '_create_%s_svl' % valued_type)()
for svl in stock_valuation_layers:
if not svl.product_id.valuation == 'real_time':
continue
if svl.currency_id.is_zero(svl.value):
continue
svl.stock_move_id._account_entry_move(svl.quantity, svl.description, svl.id, svl.value)
stock_valuation_layers._validate_accounting_entries()
stock_valuation_layers._check_company()
@@ -437,23 +432,20 @@ class StockMove(models.Model):
vals['to_refund'] = self.to_refund
return vals
def _create_account_move_line(self, credit_account_id, debit_account_id, journal_id, qty, description, svl_id, cost):
def _prepare_account_move_vals(self, credit_account_id, debit_account_id, journal_id, qty, description, svl_id, cost):
self.ensure_one()
AccountMove = self.env['account.move'].with_context(default_journal_id=journal_id)
move_lines = self._prepare_account_move_line(qty, cost, credit_account_id, debit_account_id, description)
if move_lines:
date = self._context.get('force_period_date', fields.Date.context_today(self))
new_account_move = AccountMove.sudo().create({
'journal_id': journal_id,
'line_ids': move_lines,
'date': date,
'ref': description,
'stock_move_id': self.id,
'stock_valuation_layer_ids': [(6, None, [svl_id])],
'move_type': 'entry',
})
new_account_move._post()
date = self._context.get('force_period_date', fields.Date.context_today(self))
return {
'journal_id': journal_id,
'line_ids': move_lines,
'date': date,
'ref': description,
'stock_move_id': self.id,
'stock_valuation_layer_ids': [(6, None, [svl_id])],
'move_type': 'entry',
}
def _account_entry_move(self, qty, description, svl_id, cost):
""" Accounting Valuation Entries """
@@ -465,46 +457,43 @@ class StockMove(models.Model):
# if the move isn't owned by the company, we don't make any valuation
return False
location_from = self.location_id
location_to = self.location_dest_id
company_from = self._is_out() and self.mapped('move_line_ids.location_id.company_id') or False
company_to = self._is_in() and self.mapped('move_line_ids.location_dest_id.company_id') or False
journal_id, acc_src, acc_dest, acc_valuation = self._get_accounting_data_for_valuation()
# Create Journal Entry for products arriving in the company; in case of routes making the link between several
# warehouse of the same company, the transit location belongs to this company, so we don't need to create accounting entries
am_vals = []
if self._is_in():
if self._is_returned(valued_type='in'):
self.with_company(company_to)._create_account_move_line(acc_dest, acc_valuation, journal_id, qty, description, svl_id, cost)
am_vals.append(self.with_company(company_to)._prepare_account_move_vals(acc_dest, acc_valuation, journal_id, qty, description, svl_id, cost))
else:
self.with_company(company_to)._create_account_move_line(acc_src, acc_valuation, journal_id, qty, description, svl_id, cost)
am_vals.append(self.with_company(company_to)._prepare_account_move_vals(acc_src, acc_valuation, journal_id, qty, description, svl_id, cost))
# Create Journal Entry for products leaving the company
if self._is_out():
cost = -1 * cost
if self._is_returned(valued_type='out'):
self.with_company(company_from)._create_account_move_line(acc_valuation, acc_src, journal_id, qty, description, svl_id, cost)
am_vals.append(self.with_company(company_from)._prepare_account_move_vals(acc_valuation, acc_src, journal_id, qty, description, svl_id, cost))
else:
self.with_company(company_from)._create_account_move_line(acc_valuation, acc_dest, journal_id, qty, description, svl_id, cost)
am_vals.append(self.with_company(company_from)._prepare_account_move_vals(acc_valuation, acc_dest, journal_id, qty, description, svl_id, cost))
if self.company_id.anglo_saxon_accounting:
# Creates an account entry from stock_input to stock_output on a dropship move. https://github.com/odoo/odoo/issues/12687
if self._is_dropshipped():
if cost > 0:
self.with_company(self.company_id)._create_account_move_line(acc_src, acc_valuation, journal_id, qty, description, svl_id, cost)
am_vals.append(self.with_company(self.company_id)._prepare_account_move_vals(acc_src, acc_valuation, journal_id, qty, description, svl_id, cost))
else:
cost = -1 * cost
self.with_company(self.company_id)._create_account_move_line(acc_valuation, acc_dest, journal_id, qty, description, svl_id, cost)
am_vals.append(self.with_company(self.company_id)._prepare_account_move_vals(acc_valuation, acc_dest, journal_id, qty, description, svl_id, cost))
elif self._is_dropshipped_returned():
if cost > 0:
self.with_company(self.company_id)._create_account_move_line(acc_valuation, acc_src, journal_id, qty, description, svl_id, cost)
am_vals.append(self.with_company(self.company_id)._prepare_account_move_vals(acc_valuation, acc_src, journal_id, qty, description, svl_id, cost))
else:
cost = -1 * cost
self.with_company(self.company_id)._create_account_move_line(acc_dest, acc_valuation, journal_id, qty, description, svl_id, cost)
am_vals.append(self.with_company(self.company_id)._prepare_account_move_vals(acc_dest, acc_valuation, journal_id, qty, description, svl_id, cost))
if self.company_id.anglo_saxon_accounting:
# Eventually reconcile together the invoice and valuation accounting entries on the stock interim accounts
self._get_related_invoices()._stock_account_anglo_saxon_reconcile_valuation(product=self.product_id)
return am_vals
def _get_related_invoices(self): # To be overridden in purchase and sale_stock
""" This method is overrided in both purchase and sale_stock modules to adapt
@@ -56,7 +56,5 @@ class StockMoveLine(models.Model):
elif move._is_dropshipped() and diff < 0 or move._is_dropshipped_returned() and diff > 0:
stock_valuation_layers |= move._create_dropshipped_returned_svl(forced_quantity=abs(diff))
for svl in stock_valuation_layers:
if not svl.product_id.valuation == 'real_time':
continue
svl.stock_move_id._account_entry_move(svl.quantity, svl.description, svl.id, svl.value)
stock_valuation_layers._validate_accounting_entries()
@@ -36,3 +36,19 @@ class StockValuationLayer(models.Model):
self._table, ['product_id', 'remaining_qty', 'stock_move_id', 'company_id', 'create_date']
)
def _validate_accounting_entries(self):
am_vals = []
for svl in self:
if not svl.product_id.valuation == 'real_time':
continue
if svl.currency_id.is_zero(svl.value):
continue
am_vals += svl.stock_move_id._account_entry_move(svl.quantity, svl.description, svl.id, svl.value)
if am_vals:
account_moves = self.env['account.move'].sudo().create(am_vals)
account_moves._post()
if self.company_id.anglo_saxon_accounting:
# Eventually reconcile together the invoice and valuation accounting entries on the stock interim accounts
for svl in self:
svl.stock_move_id._get_related_invoices()._stock_account_anglo_saxon_reconcile_valuation(product=svl.product_id)