mirror of
https://github.com/bringout/oca-ocb-accounting.git
synced 2026-04-25 03:42:07 +02:00
172 lines
7.5 KiB
Python
172 lines
7.5 KiB
Python
from odoo import fields, models
|
|
from odoo.tools import float_is_zero
|
|
|
|
|
|
class AccountMove(models.Model):
|
|
_inherit = 'account.move'
|
|
|
|
stock_move_ids = fields.One2many('stock.move', 'account_move_id', string='Stock Move')
|
|
|
|
# -------------------------------------------------------------------------
|
|
# OVERRIDE METHODS
|
|
# -------------------------------------------------------------------------
|
|
|
|
def _get_lines_onchange_currency(self):
|
|
# OVERRIDE
|
|
return self.line_ids.filtered(lambda l: l.display_type != 'cogs')
|
|
|
|
def copy_data(self, default=None):
|
|
# Don't keep anglo-saxon lines when copying a journal entry.
|
|
vals_list = super().copy_data(default=default)
|
|
|
|
if not self.env.context.get('move_reverse_cancel'):
|
|
for vals in vals_list:
|
|
if 'line_ids' in vals:
|
|
vals['line_ids'] = [line_vals for line_vals in vals['line_ids']
|
|
if line_vals[0] != 0 or line_vals[2].get('display_type') != 'cogs']
|
|
return vals_list
|
|
|
|
def _post(self, soft=True):
|
|
# OVERRIDE
|
|
|
|
# Don't change anything on moves used to cancel another ones.
|
|
if self.env.context.get('move_reverse_cancel'):
|
|
return super()._post(soft)
|
|
|
|
# Create additional COGS lines for customer invoices.
|
|
self.env['account.move.line'].create(self._stock_account_prepare_realtime_out_lines_vals())
|
|
|
|
# Post entries.
|
|
res = super()._post(soft)
|
|
|
|
self.line_ids._get_stock_moves().filtered(lambda m: m.is_in or m.is_dropship)._set_value()
|
|
|
|
return res
|
|
|
|
def button_draft(self):
|
|
res = super().button_draft()
|
|
|
|
# Unlink the COGS lines generated during the 'post' method.
|
|
with self.env.protecting(self.env['account.move']._get_protected_vals({}, self)):
|
|
self.mapped('line_ids').filtered(lambda line: line.display_type == 'cogs').unlink()
|
|
return res
|
|
|
|
def button_cancel(self):
|
|
# OVERRIDE
|
|
res = super().button_cancel()
|
|
|
|
# Unlink the COGS lines generated during the 'post' method.
|
|
# In most cases it shouldn't be necessary since they should be unlinked with 'button_draft'.
|
|
# However, since it can be called in RPC, better be safe.
|
|
self.mapped('line_ids').filtered(lambda line: line.display_type == 'cogs').unlink()
|
|
return res
|
|
|
|
# -------------------------------------------------------------------------
|
|
# COGS METHODS
|
|
# -------------------------------------------------------------------------
|
|
|
|
def _stock_account_prepare_realtime_out_lines_vals(self):
|
|
''' Prepare values used to create the journal items (account.move.line) corresponding to the Cost of Good Sold
|
|
lines (COGS) for customer invoices.
|
|
|
|
Example:
|
|
|
|
Buy a product having a cost of 9 being a storable product and having a perpetual valuation in FIFO.
|
|
Sell this product at a price of 10. The customer invoice's journal entries looks like:
|
|
|
|
Account | Debit | Credit
|
|
---------------------------------------------------------------
|
|
200000 Product Sales | | 10.0
|
|
---------------------------------------------------------------
|
|
101200 Account Receivable | 10.0 |
|
|
---------------------------------------------------------------
|
|
|
|
This method computes values used to make two additional journal items:
|
|
|
|
---------------------------------------------------------------
|
|
500000 COGS (stock variation) | 9.0 |
|
|
---------------------------------------------------------------
|
|
110100 Stock Account | | 9.0
|
|
---------------------------------------------------------------
|
|
|
|
Note: COGS are only generated for customer invoices except refund made to cancel an invoice.
|
|
|
|
:return: A list of Python dictionary to be passed to env['account.move.line'].create.
|
|
'''
|
|
lines_vals_list = []
|
|
|
|
price_unit_prec = self.env['decimal.precision'].precision_get('Product Price')
|
|
for move in self:
|
|
|
|
# Make the loop multi-company safe when accessing models like product.product
|
|
move = move.with_company(move.company_id)
|
|
|
|
if not move.is_sale_document(include_receipts=True):
|
|
continue
|
|
|
|
anglo_saxon_price_ctx = move._get_anglo_saxon_price_ctx()
|
|
|
|
for line in move.invoice_line_ids:
|
|
# Filter out lines being not eligible for COGS.
|
|
if not line._eligible_for_stock_account() or line.product_id.valuation != 'real_time':
|
|
continue
|
|
# Retrieve accounts needed to generate the COGS.
|
|
accounts = line.product_id.product_tmpl_id.get_product_accounts(fiscal_pos=move.fiscal_position_id)
|
|
stock_account = accounts['stock_valuation']
|
|
credit_expense_account = accounts['expense'] or move.journal_id.default_account_id
|
|
if not stock_account or not credit_expense_account:
|
|
continue
|
|
|
|
# Compute accounting fields.
|
|
sign = -1 if move.move_type == 'out_refund' else 1
|
|
price_unit = line.with_context(anglo_saxon_price_ctx)._get_cogs_value()
|
|
amount_currency = sign * line.product_uom_id._compute_quantity(line.quantity, line.product_id.uom_id) * price_unit
|
|
|
|
if move.currency_id.is_zero(amount_currency) or float_is_zero(price_unit, precision_digits=price_unit_prec):
|
|
continue
|
|
|
|
# Add interim account line.
|
|
lines_vals_list.append({
|
|
'name': line.name[:64] if line.name else '',
|
|
'move_id': move.id,
|
|
'partner_id': move.commercial_partner_id.id,
|
|
'product_id': line.product_id.id,
|
|
'product_uom_id': line.product_uom_id.id,
|
|
'quantity': line.quantity,
|
|
'price_unit': price_unit,
|
|
'amount_currency': -amount_currency,
|
|
'account_id': stock_account.id,
|
|
'display_type': 'cogs',
|
|
'tax_ids': [],
|
|
'cogs_origin_id': line.id,
|
|
})
|
|
|
|
# Add expense account line.
|
|
lines_vals_list.append({
|
|
'name': line.name[:64] if line.name else '',
|
|
'move_id': move.id,
|
|
'partner_id': move.commercial_partner_id.id,
|
|
'product_id': line.product_id.id,
|
|
'product_uom_id': line.product_uom_id.id,
|
|
'quantity': line.quantity,
|
|
'price_unit': -price_unit,
|
|
'amount_currency': amount_currency,
|
|
'account_id': credit_expense_account.id,
|
|
'analytic_distribution': line.analytic_distribution,
|
|
'display_type': 'cogs',
|
|
'tax_ids': [],
|
|
'cogs_origin_id': line.id,
|
|
})
|
|
return lines_vals_list
|
|
|
|
def _get_anglo_saxon_price_ctx(self):
|
|
""" To be overriden in modules overriding _get_cogs_value
|
|
to optimize computations that only depend on account.move and not account.move.line
|
|
"""
|
|
return self.env.context
|
|
|
|
def _get_related_stock_moves(self):
|
|
return self.env['stock.move']
|
|
|
|
def _get_invoiced_lot_values(self):
|
|
return []
|