[FIX] Currency and UoM issues for accounting entries
bzr revid: jco@openerp.com-20130503095635-laak8y0vs6y7wuwt
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user