oca-ocb-accounting/odoo-bringout-oca-ocb-stock_account/stock_account/models/account_move_line.py
Ernad Husremovic 768b70e05e 19.0 vanilla
2026-03-09 09:30:07 +01:00

85 lines
3.2 KiB
Python

from odoo import fields, models, api
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
cogs_origin_id = fields.Many2one( # technical field used to keep track in the originating line of the anglo-saxon lines
comodel_name="account.move.line",
copy=False,
index="btree_not_null",
)
def _compute_account_id(self):
super()._compute_account_id()
for line in self:
if not line.move_id.is_purchase_document():
continue
if not line._eligible_for_stock_account():
continue
fiscal_position = line.move_id.fiscal_position_id
accounts = line.with_company(line.company_id).product_id.product_tmpl_id.get_product_accounts(fiscal_pos=fiscal_position)
if line.product_id.valuation == 'real_time' and accounts['stock_valuation']:
line.account_id = accounts['stock_valuation']
@api.onchange('product_id')
def _inverse_product_id(self):
super(AccountMoveLine, self.filtered(lambda l: l.display_type != 'cogs'))._inverse_product_id()
def _eligible_for_stock_account(self):
self.ensure_one()
if not self.product_id.is_storable:
return False
moves = self._get_stock_moves()
return all(not m._is_dropshipped() for m in moves)
def _get_gross_unit_price(self):
if self.product_uom_id.is_zero(self.quantity):
return self.price_unit
if self.discount != 100:
if not any(t.price_include for t in self.tax_ids) and self.discount:
price_unit = self.price_unit * (1 - self.discount / 100)
else:
price_unit = self.price_subtotal / self.quantity
else:
price_unit = self.price_unit
return -price_unit if self.move_id.move_type == 'in_refund' else price_unit
def _get_cogs_value(self):
""" Get the COGS price unit in the product's default unit of measure.
"""
self.ensure_one()
original_line = self.move_id.reversed_entry_id.line_ids.filtered(
lambda l: l.display_type == 'cogs' and l.product_id == self.product_id and
l.product_uom_id == self.product_uom_id and l.price_unit >= 0)
original_line = original_line and original_line[0]
if original_line:
return original_line.price_unit
if not self.product_id or self.product_uom_id.is_zero(self.quantity):
return self.price_unit
cogs_qty = self._get_cogs_qty()
if moves := self._get_stock_moves().filtered(lambda m: m.state == 'done'):
price_unit = moves._get_cogs_price_unit(cogs_qty)
else:
if self.product_id.cost_method in ['standard', 'average']:
price_unit = self.product_id.standard_price
else:
price_unit = self.product_id._run_fifo(cogs_qty) / cogs_qty if cogs_qty else 0
return (price_unit * cogs_qty - self._get_posted_cogs_value()) / self.quantity
def _get_stock_moves(self):
return self.env['stock.move']
def _get_cogs_qty(self):
self.ensure_one()
return self.quantity
def _get_posted_cogs_value(self):
self.ensure_one()
return 0