[FIX] Currency and UoM issues for accounting entries

bzr revid: jco@openerp.com-20130503095635-laak8y0vs6y7wuwt
This commit is contained in:
Josse Colpaert
2013-05-03 11:56:35 +02:00
parent dac1cb78be
commit 3a94db4412
5 changed files with 99 additions and 23 deletions
+2 -3
View File
@@ -2263,7 +2263,7 @@ class stock_move(osv.osv):
#I use
if move.product_id.cost_method != 'standard' and move.price_unit:
reference_amount = qty * move.price_unit
reference_amount = move.product_qty * move.price_unit #Using move.price_qty instead of qty to have correct amount
reference_currency_id = move.price_currency_id.id or reference_currency_id
# Otherwise we default to the company's valuation price type, considering that the values of the
@@ -2331,7 +2331,6 @@ class stock_move(osv.osv):
account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_dest, acc_valuation, reference_amount, reference_currency_id, context))]
else:
account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_src, acc_valuation, reference_amount, reference_currency_id, context))]
move_obj = self.pool.get('account.move')
for j_id, move_lines in account_moves:
move_obj.create(cr, uid,
@@ -2436,7 +2435,7 @@ class stock_move(osv.osv):
# fix credit line:
credit_line_vals['credit'] = cur_obj.compute(cr, uid, reference_currency_id, src_main_currency_id, reference_amount, context=context)
if (not src_acct.currency_id) or src_acct.currency_id.id == reference_currency_id:
credit_line_vals.update(currency_id=reference_currency_id, amount_currency=reference_amount)
credit_line_vals.update(currency_id=reference_currency_id, amount_currency=-reference_amount)
if reference_currency_id != dest_main_currency_id:
# fix debit line:
debit_line_vals['debit'] = cur_obj.compute(cr, uid, reference_currency_id, dest_main_currency_id, reference_amount, context=context)
+1 -1
View File
@@ -75,7 +75,7 @@ class stock_partial_move(osv.osv_memory):
'prodlot_id': move.prodlot_id.id,
}
moves_ids.append(move_id)
if (move.move_id.picking_id.type == 'in') and (move.product_id.cost_method == 'average'):
if (move.move_id.picking_id.type == 'in') and (move.product_id.cost_method != 'standard'):
partial_data['move%s' % (move_id)].update(product_price=move.cost,
product_currency=move.currency.id)
self.pool.get('stock.move').do_partial(cr, uid, moves_ids, partial_data, context=context)
+2 -2
View File
@@ -151,7 +151,7 @@ class stock_partial_picking(osv.osv_memory):
'location_id' : move.location_id.id,
'location_dest_id' : move.location_dest_id.id,
}
if move.picking_id.type == 'in' and move.product_id.cost_method == 'average':
if move.picking_id.type == 'in' and move.product_id.cost_method != 'standard':
partial_move.update(update_cost=True, **self._product_cost_for_average_update(cr, uid, move))
return partial_move
@@ -208,7 +208,7 @@ class stock_partial_picking(osv.osv_memory):
'product_uom': wizard_line.product_uom.id,
'prodlot_id': wizard_line.prodlot_id.id,
}
if (picking_type == 'in') and (wizard_line.product_id.cost_method == 'average'):
if (picking_type == 'in') and (wizard_line.product_id.cost_method != 'standard'):
partial_data['move%s' % (wizard_line.move_id.id)].update(product_price=wizard_line.cost,
product_currency=wizard_line.currency.id)
stock_picking.do_partial(cr, uid, [partial.picking_id.id], partial_data, context=context)
+16 -11
View File
@@ -40,7 +40,8 @@ class product_product (osv.osv):
def get_stock_matchings_fifolifo(self, cr, uid, ids, qty, fifo, product_uom_id = False, currency_id = False, context=None):
'''
This method returns a list of tuples for which the stock moves are working fifo/lifo
This method returns a list of tuples for which the stock moves are working fifo/lifo:
(move_in_id, qty in uom of move out, price (converted to move out), qty in uom of move in
This should be called for only one product at a time
UoMs and currencies from the corresponding moves are converted towards that given in the params
'''
@@ -64,33 +65,34 @@ class product_product (osv.osv):
currency_id = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id.id
if fifo:
move_ids = move_obj.search(cr, uid, [('company_id','=', company_id), ('qty_remaining', '>', 0), ('state', '=', 'done'),
move_in_ids = move_obj.search(cr, uid, [('company_id','=', company_id), ('qty_remaining', '>', 0), ('state', '=', 'done'),
('type', '=', 'in'), ('product_id', '=', product.id)],
order = 'date', context=context)
else:
move_ids = move_obj.search(cr, uid, [('company_id','=', company_id), ('qty_remaining', '>', 0), ('state', '=', 'done'),
move_in_ids = move_obj.search(cr, uid, [('company_id','=', company_id), ('qty_remaining', '>', 0), ('state', '=', 'done'),
('type', '=', 'in'), ('product_id', '=', product.id)],
order = 'date desc', context=context)
tuples = []
qty_to_go = qty
for move in move_obj.browse(cr, uid, move_ids, context=context):
for move in move_obj.browse(cr, uid, move_in_ids, context=context):
#Convert to UoM of product each time
uom_from = move.product_uom.id
qty_from = move.product_qty
product_qty = uom_obj._compute_qty(cr, uid, uom_from, qty_from, product_uom_id)
#Convert currency from in move currency id to out move currency
if move.price_currency_id and (move.price_currency_id.id != currency_id):
new_price = currency_obj.compute(cr, uid, move.price_currency_id, currency_id,
if move.price_currency_id and (move.price_currency_id.id != currency_id):
new_price = currency_obj.compute(cr, uid, move.price_currency_id.id, currency_id,
move.price_unit)
else:
new_price = move.price_unit
new_price = uom_obj._compute_price(cr, uid, uom_from, new_price,
product_uom_id)
if qty_to_go - product_qty >= 0:
tuples.append((move.id, product_qty, new_price),)
tuples.append((move.id, product_qty, new_price, qty_from),)
qty_to_go -= product_qty
else:
tuples.append((move.id, qty_to_go, new_price),)
tuples.append((move.id, qty_to_go, new_price, qty_from * qty_to_go / product_qty),)
break
return tuples
@@ -154,10 +156,11 @@ class stock_move(osv.osv):
match_id = matching_obj.create(cr, uid, matchvals, context=context)
move_in = self.browse(cr, uid, match[0], context=context)
#Reduce remaining quantity
self.write(cr, uid, match[0], { 'qty_remaining': move_in.qty_remaining - match[1]}, context=context)
self.write(cr, uid, match[0], { 'qty_remaining': move_in.qty_remaining - match[3]}, context=context)
price_amount += match[1] * match[2]
amount += match[1]
self.write(cr, uid, move.id, {'price_unit': price_amount / amount}, context=context)
#This price has to be put as the new standard price for the product, but needs to be converted to product UoM and currency
#convert uom of qty
uom_id = product.uom_id.id
@@ -174,8 +177,10 @@ class stock_move(osv.osv):
product_obj.write(cr, uid, product.id, {'standard_price': new_price / product_qty}, context=ctx)
# When the move is products returned to supplier or return products from customer
# then the price should be the price from the original move
if move.move_returned_from and cost_method in ['fifo', 'lifo']:
self.write(cr, uid, move.id, {'price_unit': move.move_returned_from.price_unit}, context=context)
elif cost_method in ['fifo', 'lifo']: #if move.move_returned_from and cost_method in ['fifo', 'lifo']:
self.write(cr, uid, [move.id],
{'price_unit': product_price,
'price_currency_id': product_currency})
return True
class stock_move_matching(osv.osv):
+78 -6
View File
@@ -11,13 +11,13 @@
uom_id: product.product_uom_kgm
uom_po_id: product.product_uom_kgm
procure_method: make_to_stock
valuation: real_time
cost_method: fifo
valuation: real_time
property_stock_account_input: account.o_expense
property_stock_account_output: account.o_income
description: FIFO Ice Cream can be mass-produced and thus is widely available in developed parts of the world. Ice cream can be purchased in large cartons (vats and squrounds) from supermarkets and grocery stores, in smaller quantities from ice cream shops, convenience stores, and milk bars, and in individual servings from small carts or vans at public events.
-
I create a draft Purchase Order for first in move for 10 pieces at 60 euro
I create a draft Purchase Order for first in move for 10 kg at 60 euro
-
!record {model: purchase.order, id: purchase_order_fifo1}:
partner_id: base.res_partner_3
@@ -30,7 +30,7 @@
price_unit: 50.0
name: 'FIFO Ice Cream'
-
I create a draft Purchase Order for second shipment for 30 pieces at 80 euro
I create a draft Purchase Order for second shipment for 30 kg at 80 euro
-
!record {model: purchase.order, id: purchase_order_fifo2}:
partner_id: base.res_partner_3
@@ -103,9 +103,9 @@
!python {model: stock.partial.picking}: |
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_fifo_shipment")], 'default_type':'out'})
self.do_partial(cr, uid, [partial_id])
-
-
Check 2 stock move matchings were created
-
-
!python {model: stock.picking}: |
assert len(self.browse(cr, uid, ref("outgoing_fifo_shipment")).move_lines[0].matching_ids_out) == 2, 'Should have created 2 matchings'
-
@@ -146,4 +146,76 @@
Check product price changed to 80.0
-
!python {model: product.product}: |
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 80.0
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 80.0
-
Create new pricelist in usd
-
!record {model: product.pricelist, id: supplier_pricelist_usd}:
name: Supplier Pricelist
type: purchase
currency_id: base.USD
version_id:
- name: v1.0
items_id:
- name: 20% Discount given by my supplier
sequence: 1
price_min_margin: 2
price_max_margin: 5
product_id: product_fifo_icecream
base: -2
-
Purchase order in usd
-
I create a draft Purchase Order for 30000 g at 0.150 USD
-
!record {model: purchase.order, id: purchase_order_fifo_usd}:
partner_id: base.res_partner_3
location_id: stock.stock_location_stock
pricelist_id: supplier_pricelist_usd
order_line:
- product_id: product_fifo_icecream
product_qty: 30000
product_uom: product.product_uom_gram
price_unit: 0.150
name: 'FIFO Ice Cream'
-
I confirm the first purchase order
-
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_usd}
-
Process the reception of purchase order with usd
-
!python {model: stock.partial.picking}: |
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo_usd")).picking_ids
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_partial(cr, uid, [partial_id])
-
We create delivery order of 49500 gram
-
!record {model: stock.picking, id: outgoing_fifo_shipment_cur}:
type: out
-
Picking needs movement from stock
-
!record {model: stock.move, id: outgoing_shipment_fifo_icecream_cur}:
picking_id: outgoing_fifo_shipment_cur
product_id: product_fifo_icecream
product_uom: product.product_uom_gram
product_qty: 49500
type: out
-
Process the delivery of the outgoing shipment
-
!python {model: stock.partial.picking}: |
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_fifo_shipment_cur")], 'default_type':'out'})
self.do_partial(cr, uid, [partial_id])
-
Print price
-
!python {model: product.product}: |
print self.browse(cr, uid, ref("product_fifo_icecream")).standard_price
print self.browse(cr, uid, ref("product_fifo_icecream")).qty_available
list = self.pool.get("stock.move.matching").search(cr, uid, [])
for move in self.pool.get("stock.move.matching").browse(cr, uid, list):
print move.price_unit
print move.qty