Skip to content
Permalink
Browse files

[FIX] purchase: real time average multicurrency valuation

Do a PO in a foreign currency
Invoice it in the same foreign currency
Validate the invoice

Before this commit, The account move of the invoice
contained a price difference line
which is wrong, since the price has not changed in any ways

After this commit, the move has only two lines
one in the stock input, one in the payable

Also, the case where the price does change
due to a change in currency rate is handled

OPW 1955315
  • Loading branch information...
kebeclibre committed Mar 27, 2019
1 parent fa42ceb commit 2a656bb9ff559692b8e5e448691bbadf85008bb9
@@ -157,10 +157,12 @@ def _anglo_saxon_purchase_move_lines(self, i_line, res):
# calculate and write down the possible price difference between invoice price and product price
for line in res:
if line.get('invl_id', 0) == i_line.id and reference_account_id == line['account_id']:
# Do not forward port in >= saas-11.3. PR #32616 takes care of it
# Standard price is in company currency
valuation_price_unit = i_line.product_id.uom_id._compute_price(i_line.product_id.standard_price, i_line.uom_id)
currency_valuation_price_unit = company_currency
if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id:
#for average/fifo/lifo costing method, fetch real cost price from incomming moves
valuation_price_unit = i_line.purchase_line_id.product_uom._compute_price(i_line.purchase_line_id.price_unit, i_line.uom_id)
stock_move_obj = self.env['stock.move']
valuation_stock_move = stock_move_obj.search([
('purchase_line_id', '=', i_line.purchase_line_id.id),
@@ -177,11 +179,30 @@ def _anglo_saxon_purchase_move_lines(self, i_line, res):
for val_stock_move in valuation_stock_move:
valuation_price_unit_total += abs(val_stock_move.price_unit) * val_stock_move.product_qty
valuation_total_qty += val_stock_move.product_qty

# in Stock Move, price unit is in company_currency
valuation_price_unit = valuation_price_unit_total / valuation_total_qty
valuation_price_unit = i_line.product_id.uom_id._compute_price(valuation_price_unit, i_line.uom_id)
if inv.currency_id.id != company_currency.id:
valuation_price_unit = company_currency.with_context(date=inv.date_invoice).compute(valuation_price_unit, inv.currency_id, round=False)
if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
else:
# PO unit price might be in another currency
valuation_price_unit = i_line.purchase_line_id.product_uom._compute_price(i_line.purchase_line_id.price_unit, i_line.uom_id)
currency_valuation_price_unit = i_line.purchase_line_id.order_id.currency_id

# Put the valuation price unit in the invoice currency
if inv.currency_id != currency_valuation_price_unit:
valuation_price_unit = (
currency_valuation_price_unit
.with_context(date=inv.date_invoice)
.compute(valuation_price_unit, inv.currency_id, round=False)
)

# Valuation price unit and i_line.price_unit in invoice currency
# A safe assumption is that line['price_unit'] and i_line.price_unit both in the currency of the invoice, foreign or not
if (
acc and
float_compare(line['price_unit'], i_line.price_unit, precision_rounding=i_line.currency_id.rounding) == 0 and
float_compare(valuation_price_unit, i_line.price_unit, precision_rounding=i_line.currency_id.rounding) != 0
):
# price with discount and without tax included
price_unit = i_line.price_unit * (1 - (i_line.discount or 0.0) / 100.0)
tax_ids = []
@@ -194,6 +215,7 @@ def _anglo_saxon_purchase_move_lines(self, i_line, res):
for child in tax.children_tax_ids:
if child.type_tax_use != 'none':
tax_ids.append((4, child.id, None))

price_before = line.get('price', 0.0)
line.update({'price': inv.currency_id.round(valuation_price_unit * line['quantity'])})
diff_res.append({
@@ -705,7 +705,7 @@ def _get_stock_move_price_unit(self):
if line.product_uom.id != line.product_id.uom_id.id:
price_unit *= line.product_uom.factor / line.product_id.uom_id.factor
if order.currency_id != order.company_id.currency_id:
price_unit = order.currency_id.compute(price_unit, order.company_id.currency_id, round=False)
price_unit = order.currency_id.with_context(date=order.date_approve).compute(price_unit, order.company_id.currency_id, round=False)
return price_unit

@api.multi
@@ -725,7 +725,7 @@ def _prepare_stock_moves(self, picking):
'name': self.name or '',
'product_id': self.product_id.id,
'product_uom': self.product_uom.id,
'date': self.order_id.date_order,
'date': self.order_id.date_approve,
'date_expected': self.date_planned,
'location_id': self.order_id.partner_id.property_stock_supplier.id,
'location_dest_id': self.order_id._get_destination_location(),
@@ -46,7 +46,7 @@ def _get_price_unit(self):
if line.product_uom.id != line.product_id.uom_id.id:
price_unit *= line.product_uom.factor / line.product_id.uom_id.factor
if order.currency_id != order.company_id.currency_id:
price_unit = order.currency_id.compute(price_unit, order.company_id.currency_id, round=False)
price_unit = order.currency_id.with_context(date=self.date or order.date_approve).compute(price_unit, order.company_id.currency_id, round=False)
return price_unit
return super(StockMove, self)._get_price_unit()

Oops, something went wrong.

0 comments on commit 2a656bb

Please sign in to comment.
You can’t perform that action at this time.