From e7d5622c7e2af9485b2d3194d12efe8ddf69e5c3 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 3 Sep 2013 18:27:57 +0200 Subject: [PATCH] [FIX] purchase: fifo_price.yml bzr revid: qdp-launchpad@openerp.com-20130903162757-p3rquk1uap0qz8qb --- addons/purchase/test/fifo_price.yml | 24 ++++++++++++------------ addons/stock/stock.py | 12 ++++++++---- addons/stock_account/stock_account.py | 25 ++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/addons/purchase/test/fifo_price.yml b/addons/purchase/test/fifo_price.yml index 0424dd3bb89..3c45cd1c9c1 100644 --- a/addons/purchase/test/fifo_price.yml +++ b/addons/purchase/test/fifo_price.yml @@ -88,7 +88,7 @@ picking_id: outgoing_fifo_shipment product_id: product_fifo_icecream product_uom: product.product_uom_kgm - product_qty: 20.0 + product_uom_qty: 20.0 location_id: stock.stock_location_stock location_dest_id: stock.stock_location_customers picking_type_id: stock.picking_type_out @@ -107,7 +107,7 @@ Check product standard price changed to 65.0 (because last outgoing shipment was made of 10 kg at 50€ and 10 kg at 80€) - !python {model: product.product}: | - assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 65.0 + assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 65.0, "Product price not updated accordingly. %s found instead of 65" %(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price,) - Do a delivery of an extra 500 g (delivery order) - @@ -122,7 +122,7 @@ product_uom: product.product_uom_gram location_id: stock.stock_location_stock location_dest_id: stock.stock_location_customers - product_qty: 500.0 + product_uom_qty: 500.0 picking_type_id: stock.picking_type_out - I assign this outgoing shipment @@ -139,7 +139,7 @@ Check product price changed to 80.0 (because last outgoing shipment was made of 0.5 kg at 80€) - !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, "Product price not updated accordingly. %s found instead of 80" %(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price,) - We will temporarily change the currency rate on the sixth of June to have the same results all year - @@ -204,7 +204,7 @@ picking_id: outgoing_fifo_shipment_cur product_id: product_fifo_icecream product_uom: product.product_uom_kgm - product_qty: 49.5 + product_uom_qty: 49.5 location_id: stock.stock_location_stock location_dest_id: stock.stock_location_customers picking_type_id: stock.picking_type_out @@ -223,7 +223,7 @@ Check rounded price is 102 euro (because last outgoing shipment was made of 19.5kg at 80€ and 30kg at $150 (rate=1.2834) - !python {model: product.product}: | - assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == 102, "Price after doing other currency is wrong" + assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == 102, "Product price not updated accordingly. %s found instead of 102 (rounded values)" %(round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price),) - Do a delivery of an extra 10 kg - @@ -236,7 +236,7 @@ picking_id: outgoing_fifo_shipment_ret product_id: product_fifo_icecream product_uom: product.product_uom_kgm - product_qty: 10.0 + product_uom_qty: 10.0 location_id: stock.stock_location_stock location_dest_id: stock.stock_location_customers picking_type_id: stock.picking_type_out @@ -255,7 +255,7 @@ Check rounded price is 150.0 / 1.2834 - !python {model: product.product}: | - assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == round(150.0 / 1.2834) + assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == round(150.0 / 1.2834), "Product price not updated accordingly. %s found instead of %s" %(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price, round(150.0/1.2834)) - Let us create some outs to get negative stock. Create outpicking. We create delivery order of 200 kg, but will pick only 100 kg - @@ -268,7 +268,7 @@ picking_id: outgoing_fifo_shipment_neg product_id: product_fifo_icecream product_uom: product.product_uom_kgm - product_qty: 200.0 + product_uom_qty: 200.0 location_id: stock.stock_location_stock location_dest_id: stock.stock_location_customers picking_type_id: stock.picking_type_out @@ -284,7 +284,7 @@ picking_id: outgoing_fifo_shipment_neg2 product_id: product_fifo_icecream product_uom: product.product_uom_kgm - product_qty: 400.0 + product_uom_qty: 400.0 location_id: stock.stock_location_stock location_dest_id: stock.stock_location_customers picking_type_id: stock.picking_type_out @@ -323,7 +323,7 @@ Assert price on product is still the old price as the out move has not been received fully yet - !python {model: product.product}: | - assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == round(150.0 / 1.2834) + assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == round(150.0 / 1.2834), 'The product price should not have been updated' - Receive purchase order with 60 kg FIFO Ice Cream at 80 euro/kg - @@ -351,4 +351,4 @@ The price of the product should have changed back to 65.0 - !python {model: product.product}: | - assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 65.0 + assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 65.0, "Product price not updated accordingly. %s found instead of 65" %(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price,) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index e6b14143376..99af87ac0d7 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -231,6 +231,7 @@ class stock_quant(osv.osv): result += self._quants_get_lifo(cr, uid, location, product, qty, domain, prefered_order=prefered_order, context=context) else: raise osv.except_osv(_('Error!'), _('Removal strategy %s not implemented.' % (removal_strategy,))) + print 'Quant get result', result return result # @@ -241,7 +242,7 @@ class stock_quant(osv.osv): def _quant_create(self, cr, uid, qty, move, lot_id = False, context=None): # FP Note: TODO: compute the right price according to the move, with currency convert # QTY is normally already converted to main product's UoM - price_unit = move.price_unit + price_unit = self.pool.get('stock.move').get_price_unit(cr, uid, move, context=context) vals = { 'product_id': move.product_id.id, 'location_id': move.location_dest_id.id, @@ -253,7 +254,6 @@ class stock_quant(osv.osv): 'lot_id': lot_id, } - negative_quant_id = False if move.location_id.usage == 'internal': #if we were trying to move something from an internal location and reach here (quant creation), #it means that a negative quant has to be created as well. @@ -262,9 +262,9 @@ class stock_quant(osv.osv): negative_vals['qty'] = -qty negative_vals['cost'] = price_unit negative_quant_id = self.create(cr, uid, negative_vals, context=context) + vals.update({'propagated_from_id': negative_quant_id}) #create the quant - vals.update({'propagated_from_id': negative_quant_id}) quant_id = self.create(cr, uid, vals, context=context) return self.browse(cr, uid, quant_id, context=context) @@ -975,6 +975,10 @@ class stock_move(osv.osv): _order = 'date_expected desc, id' _log_create = False + def get_price_unit(self, cr, uid, move, context=None): + """ Returns the unit price to store on the move """ + return move.price_unit or move.product_id.standard_price + def name_get(self, cr, uid, ids, context=None): res = [] for line in self.browse(cr, uid, ids, context=context): @@ -1497,7 +1501,7 @@ class stock_move(osv.osv): for move in self.browse(cr, uid, ids, context=context): if move.picking_id: pickings.add(move.picking_id.id) - qty = move.product_uom_qty + qty = move.product_qty # for qty, location_id in move_id.prefered_location_ids: # quants = quant_obj.quants_get(cr, uid, move.location_id, move.product_id, qty, context=context) diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py index 659f53adf91..ecb14b1d814 100644 --- a/addons/stock_account/stock_account.py +++ b/addons/stock_account/stock_account.py @@ -70,7 +70,6 @@ class stock_quant(osv.osv): return line.cost * line.qty return super(stock_quant, self)._get_inventory_value(cr, uid, line, prodbrow, context=context) - # FP Note: this is where we should post accounting entries for adjustment def _price_update(self, cr, uid, quant, newprice, context=None): super(stock_quant, self)._price_update(cr, uid, quant, newprice, context=context) @@ -198,4 +197,28 @@ class stock_quant(osv.osv): return move_obj.create(cr, uid, {'journal_id': journal_id, 'line_id': move_lines, 'ref': move.picking_id and move.picking_id.name}, context=context) +class stock_move(osv.osv): + _inherit = "stock.move" + def action_done(self, cr, uid, ids, context=None): + super(stock_move, self).action_done(cr, uid, ids, context=context) + self.product_price_update(cr, uid, ids, context=context) + + def product_price_update(self, cr, uid, ids, context=None): + ''' + This method adapts the price on the product when necessary (if the cost_method is 'real'), so that a return or an inventory loss is made using the last value used for an outgoing valuation. + ''' + product_obj = self.pool.get('product.product') + for move in self.browse(cr, uid, ids, context=context): + if move.product_id.cost_method == 'real' and move.location_dest_id.usage != 'internal': + if any([q.qty <= 0 for q in move.quant_ids]): + #if there is a negative quant, the standard price shouldn't be updated + continue + #get the average price of the move + #Note: here we can't use the quant.cost directly as we may have moved out 2 units (1 unit to 5€ and 1 unit to 7€) and in case of a product return of 1 unit, we can't know which of the 2 cost has to be used (5€ or 7€?). So at that time, thanks to the average valuation price we are storing we will svaluate it at 6€ + average_valuation_price = 0.0 + for q in move.quant_ids: + average_valuation_price += q.qty * q.cost + average_valuation_price = average_valuation_price / move.product_qty + product_obj.write(cr, uid, move.product_id.id, {'standard_price': average_valuation_price}, context=context) + self.write(cr, uid, move.id, {'price_unit': average_valuation_price}, context=context)