[FIX] stock_landed_cost: allow reversing valuation via negative quantity + safer cancel/unlink

- Support negative costs by creating reverse valuation move,
  and undoing the quant computation.
  This may or may not produce the exact reverse effect on
  the quant, as it depends on the rounding of the unit
  cost, which uses decimal precision 'Account'
- Hide 'compute' button when cost is not draft
- Forbid cancel of posted cost
- Forbid deletion of cost if not draft
This commit is contained in:
Olivier Dony 2015-04-08 19:20:24 +02:00
parent 8b95a8424b
commit 15d00bd957
2 changed files with 46 additions and 32 deletions

View File

@ -21,6 +21,7 @@
from openerp.osv import fields, osv
import openerp.addons.decimal_precision as dp
from openerp.exceptions import Warning
from openerp.tools import float_compare
from openerp.tools.translate import _
import product
@ -90,7 +91,7 @@ class stock_landed_cost(osv.osv):
),
'state': fields.selection([('draft', 'Draft'), ('done', 'Posted'), ('cancel', 'Cancelled')], 'State', readonly=True, track_visibility='onchange', copy=False),
'account_move_id': fields.many2one('account.move', 'Journal Entry', readonly=True, copy=False),
'account_journal_id': fields.many2one('account.journal', 'Account Journal', required=True),
'account_journal_id': fields.many2one('account.journal', 'Account Journal', required=True, states={'done': [('readonly', True)]}),
}
_defaults = {
@ -120,41 +121,43 @@ class stock_landed_cost(osv.osv):
Afterwards, for the goods that are already out of stock, we should create the out moves
"""
aml_obj = self.pool.get('account.move.line')
aml_obj.create(cr, uid, {
base_line = {
'name': line.name,
'move_id': move_id,
'product_id': line.product_id.id,
'quantity': line.quantity,
'debit': line.additional_landed_cost,
'account_id': debit_account_id
}, context=context)
aml_obj.create(cr, uid, {
'name': line.name,
'move_id': move_id,
'product_id': line.product_id.id,
'quantity': line.quantity,
'credit': line.additional_landed_cost,
'account_id': credit_account_id
}, context=context)
}
debit_line = dict(base_line, account_id=debit_account_id)
credit_line = dict(base_line, account_id=credit_account_id)
diff = line.additional_landed_cost
if diff > 0:
debit_line['debit'] = diff
credit_line['credit'] = diff
else:
# negative cost, reverse the entry
debit_line['credit'] = -diff
credit_line['debit'] = -diff
aml_obj.create(cr, uid, debit_line, context=context)
aml_obj.create(cr, uid, credit_line, context=context)
#Create account move lines for quants already out of stock
if qty_out > 0:
aml_obj.create(cr, uid, {
'name': line.name + ": " + str(qty_out) + _(' already out'),
'move_id': move_id,
'product_id': line.product_id.id,
'quantity': qty_out,
'credit': line.additional_landed_cost * qty_out / line.quantity,
'account_id': debit_account_id
}, context=context)
aml_obj.create(cr, uid, {
'name': line.name + ": " + str(qty_out) + _(' already out'),
'move_id': move_id,
'product_id': line.product_id.id,
'quantity': qty_out,
'debit': line.additional_landed_cost * qty_out / line.quantity,
'account_id': already_out_account_id
}, context=context)
debit_line = dict(debit_line,
name=(line.name + ": " + str(qty_out) + _(' already out')),
quantity=qty_out)
credit_line = dict(credit_line,
name=(line.name + ": " + str(qty_out) + _(' already out')),
quantity=qty_out)
diff = diff * qty_out / line.quantity
if diff > 0:
debit_line['debit'] = diff
credit_line['credit'] = diff
else:
# negative cost, reverse the entry
debit_line['credit'] = -diff
credit_line['debit'] = -diff
aml_obj.create(cr, uid, debit_line, context=context)
aml_obj.create(cr, uid, credit_line, context=context)
return True
def _create_account_move(self, cr, uid, cost, context=None):
@ -192,6 +195,8 @@ class stock_landed_cost(osv.osv):
quant_obj = self.pool.get('stock.quant')
for cost in self.browse(cr, uid, ids, context=context):
if cost.state != 'draft':
raise Warning(_('Only draft landed costs can be validated'))
if not cost.valuation_adjustment_lines or not self._check_sum(cr, uid, cost, context=context):
raise osv.except_osv(_('Error!'), _('You cannot validate a landed cost which has no valid valuation lines.'))
move_id = self._create_account_move(cr, uid, cost, context=context)
@ -208,6 +213,7 @@ class stock_landed_cost(osv.osv):
else:
quant_dict[quant.id] += diff
for key, value in quant_dict.items():
print value
quant_obj.write(cr, uid, key, {'cost': value}, context=context)
qty_out = 0
for quant in line.move_id.quant_ids:
@ -218,8 +224,16 @@ class stock_landed_cost(osv.osv):
return True
def button_cancel(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
return True
cost = self.browse(cr, uid, ids, context=context)
if cost.state == 'done':
raise Warning(_('Validated landed costs cannot be cancelled, '
'but you could create negative landed costs to reverse them'))
return cost.write({'state': 'cancel'})
def unlink(self, cr, uid, ids, context=None):
# cancel or raise first
self.button_cancel(cr, uid, ids, context)
return super(stock_landed_cost, self).unlink(cr, uid, ids, context=context)
def compute_landed_cost(self, cr, uid, ids, context=None):
line_obj = self.pool.get('stock.valuation.adjustment.lines')

View File

@ -66,7 +66,7 @@
<group>
<separator string="Valuation Adjustments"/>
</group>
<group>
<group states='draft'>
<button name="compute_landed_cost" string="Compute" type="object" class="oe_right"/>
</group>
</group>