[FIX] negative quants fixing
bzr revid: qdp-launchpad@openerp.com-20130923143309-42mo2trr8jy6m5qk
This commit is contained in:
parent
ba60391f07
commit
4bea4bc1f3
|
@ -215,7 +215,10 @@ class stock_quant(osv.osv):
|
|||
# add location_dest_id in parameters (False=use the destination of the move)
|
||||
def quants_move(self, cr, uid, quants, move, context=None):
|
||||
for quant, qty in quants:
|
||||
self.move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
#quant may be a browse record or None
|
||||
quant_record = self.move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
#quant_record is the quant newly created or already split
|
||||
self._quant_reconcile_negative(cr, uid, quant_record, context=context)
|
||||
|
||||
def check_preferred_location(self, cr, uid, move, context=None):
|
||||
return move.location_dest_id
|
||||
|
@ -233,7 +236,6 @@ class stock_quant(osv.osv):
|
|||
'history_ids': [(4, move.id)]
|
||||
})
|
||||
quant.refresh()
|
||||
self._quant_reconcile_negative(cr, uid, quant, context=context)
|
||||
return quant
|
||||
|
||||
def quants_get(self, cr, uid, location, product, qty, domain=None, prefered_order=False, reservedcontext=None, restrict_lot_id=False, restrict_partner_id=False, context=None):
|
||||
|
@ -317,19 +319,28 @@ class stock_quant(osv.osv):
|
|||
move = m
|
||||
return move
|
||||
|
||||
def _reconcile_single_negative_quant(self, cr, uid, to_solve_quant, quant, quant_neg, qty, context=None):
|
||||
move = self._get_latest_move(cr, uid, to_solve_quant, context=context)
|
||||
remaining_solving_quant = self._quant_split(cr, uid, quant, qty, context=context)
|
||||
remaining_to_solve_quant = self._quant_split(cr, uid, to_solve_quant, qty, context=context)
|
||||
remaining_neg_quant = self._quant_split(cr, uid, quant_neg, -qty, context=context)
|
||||
#if the reconciliation was not complete, we need to link together the remaining parts
|
||||
if remaining_to_solve_quant and remaining_neg_quant:
|
||||
self.write(cr, uid, remaining_to_solve_quant.id, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||
#delete the reconciled quants, as it is replaced by the solving quant
|
||||
self.unlink(cr, SUPERUSER_ID, [quant_neg.id, to_solve_quant.id], context=context)
|
||||
#call move_single_quant to ensure recursivity if necessary and do the stock valuation
|
||||
self.move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
return remaining_solving_quant, remaining_to_solve_quant
|
||||
#def _reconcile_single_negative_quant(self, cr, uid, to_solve_quant, quant, quant_neg, qty, context=None):
|
||||
# move = self._get_latest_move(cr, uid, to_solve_quant, context=context)
|
||||
# remaining_solving_quant = self._quant_split(cr, uid, quant, qty, context=context)
|
||||
# remaining_to_solve_quant = self._quant_split(cr, uid, to_solve_quant, qty, context=context)
|
||||
# remaining_neg_quant = self._quant_split(cr, uid, quant_neg, -qty, context=context)
|
||||
# #if the reconciliation was not complete, we need to link together the remaining parts
|
||||
# if remaining_to_solve_quant and remaining_neg_quant:
|
||||
# self.write(cr, uid, remaining_to_solve_quant.id, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||
# #delete the reconciled quants, as it is replaced by the solving quant
|
||||
# if remaining_neg_quant:
|
||||
# otherquant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id)], context=context)
|
||||
# self.write(cr, uid, otherquant_ids, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||
# self.unlink(cr, SUPERUSER_ID, [quant_neg.id, to_solve_quant.id], context=context)
|
||||
# #call move_single_quant to ensure recursivity if necessary and do the stock valuation
|
||||
# self.move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
# return remaining_solving_quant, remaining_to_solve_quant
|
||||
|
||||
def _quants_merge(self, cr, uid, solved_quant_ids, solving_quant, context=None):
|
||||
path = []
|
||||
for move in solving_quant.history_ids:
|
||||
path.append((4, move.id))
|
||||
self.write(cr, uid, solved_quant_ids, {'history_ids': path}, context=context)
|
||||
|
||||
def _quant_reconcile_negative(self, cr, uid, quant, context=None):
|
||||
"""
|
||||
|
@ -344,14 +355,36 @@ class stock_quant(osv.osv):
|
|||
for quant_neg, qty in quants:
|
||||
if not quant_neg:
|
||||
continue
|
||||
to_solve_quant = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id), ('id', '!=', solving_quant.id)], context=context)
|
||||
if not to_solve_quant:
|
||||
to_solve_quant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id)], context=context)
|
||||
if not to_solve_quant_ids:
|
||||
continue
|
||||
to_solve_quant = self.browse(cr, uid, to_solve_quant[0], context=context)
|
||||
solving_quant, dummy = self._reconcile_single_negative_quant(cr, uid, to_solve_quant, solving_quant, quant_neg, qty, context=context)
|
||||
solving_qty = qty
|
||||
solved_quant_ids = []
|
||||
for to_solve_quant in self.browse(cr, uid, to_solve_quant_ids, context=context):
|
||||
if solving_qty <= 0:
|
||||
continue
|
||||
solved_quant_ids.append(to_solve_quant.id)
|
||||
self._quant_split(cr, uid, to_solve_quant, min(solving_qty, to_solve_quant.qty), context=context)
|
||||
solving_qty -= min(solving_qty, to_solve_quant.qty)
|
||||
#merge history (and cost?)
|
||||
self._quants_merge(cr, uid, solved_quant_ids, solving_quant, context=context)
|
||||
remaining_solving_quant = self._quant_split(cr, uid, solving_quant, qty, context=context)
|
||||
remaining_neg_quant = self._quant_split(cr, uid, quant_neg, -qty, context=context)
|
||||
#if the reconciliation was not complete, we need to link together the remaining parts
|
||||
if remaining_neg_quant:
|
||||
remaining_to_solve_quant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id), ('id', 'not in', solved_quant_ids)], context=context)
|
||||
if remaining_to_solve_quant_ids:
|
||||
self.write(cr, uid, remaining_to_solve_quant_ids, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||
#price update + accounting entries adjustments
|
||||
self._price_update(cr, uid, solved_quant_ids, solving_quant.cost, context=context)
|
||||
#delete the reconciled quants, as it is replaced by the solving quant
|
||||
self.unlink(cr, SUPERUSER_ID, [quant_neg.id, solving_quant.id], context=context)
|
||||
solving_quant = remaining_solving_quant
|
||||
|
||||
def _price_update(self, cr, uid, quant, newprice, context=None):
|
||||
self.write(cr, uid, [quant.id], {'cost': newprice}, context=context)
|
||||
#solving_quant, dummy = self._reconcile_single_negative_quant(cr, uid, to_solve_quant, solving_quant, quant_neg, qty, context=context)
|
||||
|
||||
def _price_update(self, cr, uid, ids, newprice, context=None):
|
||||
self.write(cr, uid, ids, {'cost': newprice}, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
#We want to trigger the move with nothing on reserved_quant_ids for the store of the remaining quantity
|
||||
|
|
|
@ -59,27 +59,41 @@ 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)
|
||||
# TODO: generate accounting entries
|
||||
def _price_update(self, cr, uid, quant_ids, newprice, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
ctx = context.copy()
|
||||
for quant in self.browse(cr, uid, quant_ids, context=context):
|
||||
move = self._get_latest_move(cr, uid, quant, context=context)
|
||||
ctx['force_valuation_amount'] = newprice - quant.cost
|
||||
# this is where we post accounting entries for adjustment
|
||||
self._account_entry_move(cr, uid, quant, move, context=ctx)
|
||||
#update the standard price of the product, only if we would have done it if we'd have had enough stock at first, which means
|
||||
#1) the product cost's method is 'real'
|
||||
#2) we just fixed a negative quant caused by an outgoing shipment
|
||||
if not quant.product_id.cost_method == 'real' and quant.location_id.usage != 'internal':
|
||||
self.pool.get('stock.move')._store_average_cost_price(cr, uid, move, context=context)
|
||||
super(stock_quant, self)._price_update(cr, uid, quant_ids, newprice, context=context)
|
||||
|
||||
"""
|
||||
Accounting Valuation Entries
|
||||
|
||||
location_from: can be None if it's a new quant
|
||||
"""
|
||||
def _account_entry_move(self, cr, uid, quant, location_from, location_to, move, context=None):
|
||||
def _account_entry_move(self, cr, uid, quant, move, context=None):
|
||||
location_from = move.location_id
|
||||
location_to = move.location_dest_id
|
||||
if context is None:
|
||||
context = {}
|
||||
if quant.product_id.valuation != 'real_time':
|
||||
return False
|
||||
if quant.lot_id and quant.lot_id.partner_id:
|
||||
if quant.owner_id:
|
||||
#if the quant isn't owned by the company, we don't make any valuation entry
|
||||
return False
|
||||
if quant.qty <= 0 or quant.propagated_from_id:
|
||||
#we don't make any stock valuation for negative quants because we may not know the real cost price.
|
||||
#The valuation will be made at the time of the reconciliation of the negative quant.
|
||||
if quant.qty <= 0:
|
||||
#we don't make any stock valuation for negative quants because the valuation is already made for the counterpart.
|
||||
#At that time the valuation will be made at the product cost price and afterward there will be new accounting entries
|
||||
#to make the adjustments when we know the real cost price.
|
||||
return False
|
||||
company_from = self._location_owner(cr, uid, quant, location_from, context=context)
|
||||
company_to = self._location_owner(cr, uid, quant, location_to, context=context)
|
||||
|
@ -109,11 +123,9 @@ class stock_quant(osv.osv):
|
|||
self._create_account_move_line(cr, uid, quant, move, acc_valuation, acc_dest, journal_id, context=ctx)
|
||||
|
||||
def move_single_quant(self, cr, uid, quant, qty, move, context=None):
|
||||
location_from = quant and quant.location_id or False
|
||||
quant = super(stock_quant, self).move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
quant.refresh()
|
||||
self._account_entry_move(cr, uid, quant, location_from, quant.location_id, move, context=context)
|
||||
return quant
|
||||
quant_record = super(stock_quant, self).move_single_quant(cr, uid, quant, qty, move, context=context)
|
||||
self._account_entry_move(cr, uid, quant_record, move, context=context)
|
||||
return quant_record
|
||||
|
||||
def _get_accounting_data_for_valuation(self, cr, uid, move, context=None):
|
||||
"""
|
||||
|
@ -153,7 +165,12 @@ class stock_quant(osv.osv):
|
|||
Generate the account.move.line values to post to track the stock valuation difference due to the
|
||||
processing of the given quant.
|
||||
"""
|
||||
valuation_amount = quant.product_id.cost_method == 'real' and quant.cost or quant.product_id.standard_price
|
||||
if context is None:
|
||||
context = {}
|
||||
if context.get('force_valuation_amount'):
|
||||
valuation_amount = context.get('force_valuation_amount')
|
||||
else:
|
||||
valuation_amount = quant.product_id.cost_method == 'real' and quant.cost or quant.product_id.standard_price
|
||||
partner_id = (move.picking_id.partner_id and self.pool.get('res.partner')._find_accounting_partner(move.picking_id.partner_id).id) or False
|
||||
debit_line_vals = {
|
||||
'name': move.name,
|
||||
|
@ -187,17 +204,17 @@ class stock_quant(osv.osv):
|
|||
'line_id': move_lines,
|
||||
'ref': move.picking_id and move.picking_id.name}, context=context)
|
||||
|
||||
def _reconcile_single_negative_quant(self, cr, uid, to_solve_quant, quant, quant_neg, qty, context=None):
|
||||
move = self._get_latest_move(cr, uid, to_solve_quant, context=context)
|
||||
quant_neg_position = quant_neg.negative_dest_location_id.usage
|
||||
remaining_solving_quant, remaining_to_solve_quant = super(stock_quant, self)._reconcile_single_negative_quant(cr, uid, to_solve_quant, quant, quant_neg, qty, context=context)
|
||||
#update the standard price of the product, only if we would have done it if we'd have had enough stock at first, which means
|
||||
#1) there isn't any negative quant anymore
|
||||
#2) the product cost's method is 'real'
|
||||
#3) we just fixed a negative quant caused by an outgoing shipment
|
||||
if not remaining_to_solve_quant and move.product_id.cost_method == 'real' and quant_neg_position != 'internal':
|
||||
self.pool.get('stock.move')._store_average_cost_price(cr, uid, move, context=context)
|
||||
return remaining_solving_quant, remaining_to_solve_quant
|
||||
#def _reconcile_single_negative_quant(self, cr, uid, to_solve_quant, quant, quant_neg, qty, context=None):
|
||||
# move = self._get_latest_move(cr, uid, to_solve_quant, context=context)
|
||||
# quant_neg_position = quant_neg.negative_dest_location_id.usage
|
||||
# remaining_solving_quant, remaining_to_solve_quant = super(stock_quant, self)._reconcile_single_negative_quant(cr, uid, to_solve_quant, quant, quant_neg, qty, context=context)
|
||||
# #update the standard price of the product, only if we would have done it if we'd have had enough stock at first, which means
|
||||
# #1) there isn't any negative quant anymore
|
||||
# #2) the product cost's method is 'real'
|
||||
# #3) we just fixed a negative quant caused by an outgoing shipment
|
||||
# if not remaining_to_solve_quant and move.product_id.cost_method == 'real' and quant_neg_position != 'internal':
|
||||
# self.pool.get('stock.move')._store_average_cost_price(cr, uid, move, context=context)
|
||||
# return remaining_solving_quant, remaining_to_solve_quant
|
||||
|
||||
class stock_move(osv.osv):
|
||||
_inherit = "stock.move"
|
||||
|
|
Loading…
Reference in New Issue