Skip to content
Permalink
Browse files

Final

  • Loading branch information...
kebeclibre committed Apr 10, 2019
1 parent adf2180 commit 8363c7d87dbd7e8a7f3416a5a6a1269ad889bf9a
Showing with 37 additions and 57 deletions.
  1. +12 −25 addons/purchase/models/account_invoice.py
  2. +25 −32 addons/purchase/tests/test_stockvaluation.py
@@ -159,6 +159,7 @@ def _anglo_saxon_purchase_move_lines(self, i_line, res):
if line.get('invl_id', 0) == i_line.id and reference_account_id == line['account_id']:
# 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
stock_move_obj = self.env['stock.move']
@@ -178,35 +179,28 @@ def _anglo_saxon_purchase_move_lines(self, i_line, res):
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
# 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)
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)
# The PO, hence the price unit, can be in another currency
# convert it to company currency
order_id = i_line.purchase_line_id.order_id
if order_id.currency_id != order_id.company_id.currency_id:
valuation_price_unit = (
order_id.currency_id
.with_context(date=i_line.purchase_line_id.order_id.date_approve)
.compute(valuation_price_unit, order_id.company_id.currency_id, round=False)
)
currency_valuation_price_unit = i_line.purchase_line_id.order_id.currency_id

line_price_unit_company_currency = i_line.price_unit
if inv.currency_id.id != company_currency.id:
line_price_unit_company_currency = (
inv.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(line_price_unit_company_currency, company_currency, round=False)
.compute(valuation_price_unit, inv.currency_id, round=False)
)

# Valuation price unit and line_price_unit_company_currency in Company Currency
# line['price_unit'] and i_line.price_unit both in the currency of the invoice, foreign or not
# 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, line_price_unit_company_currency, precision_rounding=company_currency.rounding) != 0
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)
@@ -221,13 +215,6 @@ def _anglo_saxon_purchase_move_lines(self, i_line, res):
if child.type_tax_use != 'none':
tax_ids.append((4, child.id, None))

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)
)

price_before = line.get('price', 0.0)
line.update({'price': inv.currency_id.round(valuation_price_unit * line['quantity'])})
diff_res.append({
@@ -501,7 +501,8 @@ def test_realtime_anglo_saxon_valuation_multicurrency_different_dates(self):
"""
The PO and invoice are in the same foreign currency.
The PO is invoiced at a later date than its creation.
This should create a price difference entry.
This should create a price difference entry for standard cost method
Not for average cost method though, since the PO and invoice have the same currency
"""
company = self.env.user.company_id
company.anglo_saxon_accounting = True
@@ -626,7 +627,7 @@ def _today(*args, **kwargs):
p.stop()

move_lines = inv.move_id.line_ids
self.assertEqual(len(move_lines), 5)
self.assertEqual(len(move_lines), 4)

# PAYABLE CHECK
payable_line = move_lines.filtered(lambda l: l.account_id.internal_type == 'payable')
@@ -635,28 +636,19 @@ def _today(*args, **kwargs):

# PRODUCTS CHECKS

# EXCHANGE DIFFERENCE (average)
# NO EXCHANGE DIFFERENCE (average)
# We ordered for a value of 100 EUR
# But by the time we are invoiced for it
# the foreign currency appreciated from 1.5 to 2.0
# We still have to pay 100 EUR, which now values at 50 USD
product_lines = move_lines.filtered(lambda l: l.product_id == self.product1)

# Stock-wise, we have been invoiced 100 EUR
# which in the past valued at 100 * 1/1.5 = 66.66 USD
# However, those 66.66 USD now have a value of 133.33 EUR
# Stock-wise, we have been invoiced 100 EUR, and we ordered 100 EUR
# there is no price difference
# However, 100 EUR should be converted at the time of the invoice
stock_line = product_lines.filtered(lambda l: l.account_id == self.stock_input_account)
self.assertEqual(stock_line.amount_currency, 133.33)
self.assertAlmostEqual(stock_line.balance, 66.67)

# Since we are invoiced for only 100 EUR
# with a value of 50 USD
# The stock "gained" 33.33 EUR in value
# in this case all due to the currency appreciation
# which have a today value of 16.67 USD
price_diff_line = product_lines.filtered(lambda l: l.account_id == self.price_diff_account)
self.assertEqual(price_diff_line.amount_currency, -33.33)
self.assertAlmostEqual(price_diff_line.balance, -16.67)
self.assertEqual(stock_line.amount_currency, 100.00)
self.assertAlmostEqual(stock_line.balance, 50.00)

# PRICE DIFFERENCE (STANDARD)
# We ordered a product that should have cost 60 USD (120 EUR)
@@ -671,10 +663,11 @@ def _today(*args, **kwargs):
self.assertEqual(price_diff_line.amount_currency, -50.00)
self.assertAlmostEqual(price_diff_line.balance, -25.00)

def test_fifo_realtime_anglo_saxon_valuation_multicurrency_different_dates(self):
def test_average_realtime_with_delivery_anglo_saxon_valuation_multicurrency_different_dates(self):
"""
The PO and invoice are in the same foreign currency.
The PO is invoiced at a later date than its creation.
The delivery occurs in between PO validation and invoicing
The invoice is created at an even different date
This should create a price difference entry.
"""
company = self.env.user.company_id
@@ -684,12 +677,12 @@ def test_fifo_realtime_anglo_saxon_valuation_multicurrency_different_dates(self)
date_delivery = '2019-01-08'
date_invoice = '2019-01-16'

product_fifo = self.product1.product_tmpl_id.copy({
product_avg = self.product1.product_tmpl_id.copy({
'valuation': 'real_time',
'invoice_policy': 'order',
'purchase_method': 'purchase',
'cost_method': 'fifo',
'name': 'FIFO',
'cost_method': 'average',
'name': 'AVG',
'standard_price': 60,
'property_account_creditor_price_difference': self.price_diff_account.id
}).product_variant_id
@@ -746,22 +739,22 @@ def _now(*args, **kwargs):
'partner_id': self.partner_id.id,
'order_line': [
(0, 0, {
'name': product_fifo.name,
'product_id': product_fifo.id,
'name': product_avg.name,
'product_id': product_avg.id,
'product_qty': 1.0,
'product_uom': product_fifo.uom_po_id.id,
'product_uom': product_avg.uom_po_id.id,
'price_unit': 30.0,
'date_planned': date_po,
})
],
})
po.button_confirm()

line_product_fifo = po.order_line.filtered(lambda l: l.product_id == product_fifo)
line_product_avg = po.order_line.filtered(lambda l: l.product_id == product_avg)

picking = po.picking_ids
(picking.move_lines
.filtered(lambda l: l.purchase_line_id == line_product_fifo)
.filtered(lambda l: l.purchase_line_id == line_product_avg)
.write({'quantity_done': 1.0}))

picking.button_validate()
@@ -774,12 +767,12 @@ def _now(*args, **kwargs):
'partner_id': self.partner_id.id,
'invoice_line_ids': [
(0, 0, {
'name': product_fifo.name,
'name': product_avg.name,
'price_subtotal': 30.0,
'price_unit': 30.0,
'product_id': product_fifo.id,
'product_id': product_avg.id,
'purchase_id': po.id,
'purchase_line_id': line_product_fifo.id,
'purchase_line_id': line_product_avg.id,
'quantity': 1.0,
'account_id': self.stock_input_account.id,
})
@@ -801,12 +794,12 @@ def _now(*args, **kwargs):

# PRODUCTS CHECKS

# DELIVERY DIFFERENCE (FIFO)
# DELIVERY DIFFERENCE (AVERAGE)
# We ordered a product at 30 EUR valued at 20 USD
# We received it when the exchange rate has appreciated
# So, the actualized 20 USD are now 20*1.5/0.7 = 42.857 USD
# At invoice time, it amounts to 85.71 EUR
product_lines = move_lines.filtered(lambda l: l.product_id == product_fifo)
product_lines = move_lines.filtered(lambda l: l.product_id == product_avg)

# The value of the stock is then 42.86 USD
stock_line = product_lines.filtered(lambda l: l.account_id == self.stock_input_account)

0 comments on commit 8363c7d

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