[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:
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user