[REF] stock_account
- value move lines created when the move is done - when reducing done out move, increase latest in move in order to not lose the returned quantity in the fifo chain
This commit is contained in:
@@ -52,6 +52,16 @@ class StockLocation(models.Model):
|
||||
|
||||
class StockMoveLine(models.Model):
|
||||
_inherit = 'stock.move.line'
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(StockMoveLine, self).create(vals)
|
||||
move = res.move_id
|
||||
if move.state == 'done':
|
||||
correction_value = move._run_valuation(res.qty_done)
|
||||
if move.product_id.valuation == 'real_time' and (move._is_in() or move._is_out()):
|
||||
move.with_context(force_valuation_amount=correction_value)._account_entry_move()
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
@@ -66,23 +76,37 @@ class StockMoveLine(models.Model):
|
||||
# more/less units are available, update `remaining_value` and
|
||||
# `remaining_qty` on the linked stock move.
|
||||
move_vals = {'remaining_qty': move_id.remaining_qty + qty_difference}
|
||||
new_remaining_value = 0
|
||||
if move_id.product_id.cost_method in ['standard', 'average']:
|
||||
correction_value = qty_difference * move_id.product_id.standard_price
|
||||
move_vals['value'] = move_id.value - correction_value
|
||||
move_vals.pop('remaining_qty')
|
||||
else:
|
||||
# FIFO handling
|
||||
if move_id._is_in():
|
||||
correction_value = qty_difference * move_id.price_unit
|
||||
new_remaining_value = move_id.remaining_value + correction_value
|
||||
elif move_id._is_out() and qty_difference > 0:
|
||||
# send more, run fifo again
|
||||
correction_value = self.env['stock.move']._run_fifo(move_id, quantity=qty_difference)
|
||||
new_remaining_value = move_id.remaining_value + correction_value
|
||||
move_vals.pop('remaining_qty')
|
||||
elif move_id._is_out() and qty_difference < 0:
|
||||
# return, value at last fifo price
|
||||
correction_value = qty_difference * move_id.product_id.standard_price
|
||||
remaining_value = move_id.remaining_value + correction_value
|
||||
# fake return, find the last receipt and augment its qties
|
||||
candidates_receipt = self.env['stock.move'].search(move_id._get_in_domain(), order='date, id desc', limit=1)
|
||||
if candidates_receipt:
|
||||
candidates_receipt.write({
|
||||
'remaining_qty': candidates_receipt.remaining_qty + -qty_difference,
|
||||
'remaining_value': candidates_receipt.remaining_value + (-qty_difference * candidates_receipt.price_unit),
|
||||
})
|
||||
correction_value = qty_difference * candidates_receipt.price_unit
|
||||
else:
|
||||
correction_value = qty_difference * move_id.product_id.standard_price
|
||||
move_vals.pop('remaining_qty')
|
||||
if move_id._is_out():
|
||||
move_vals['remaining_value'] = remaining_value if remaining_value < 0 else 0
|
||||
move_vals['remaining_value'] = new_remaining_value if new_remaining_value < 0 else 0
|
||||
else:
|
||||
move_vals['remaining_value'] = remaining_value
|
||||
move_vals['remaining_value'] = new_remaining_value
|
||||
move_id.write(move_vals)
|
||||
|
||||
if move_id.product_id.valuation == 'real_time':
|
||||
@@ -201,52 +225,57 @@ class StockMove(models.Model):
|
||||
# last out and a correction entry will be made once `_fifo_vacuum` is called.
|
||||
if qty_to_take_on_candidates == 0:
|
||||
move.write({
|
||||
'value': -tmp_value, # outgoing move are valued negatively
|
||||
'value': -tmp_value if not quantity else move.value or -tmp_value, # outgoing move are valued negatively
|
||||
'price_unit': -tmp_value / move.product_qty,
|
||||
})
|
||||
elif qty_to_take_on_candidates > 0:
|
||||
last_fifo_price = new_standard_price or move.product_id.standard_price
|
||||
negative_stock_value = last_fifo_price * -qty_to_take_on_candidates
|
||||
vals = {
|
||||
'remaining_qty': -qty_to_take_on_candidates,
|
||||
'remaining_value': negative_stock_value,
|
||||
'remaining_qty': move.remaining_qty + -qty_to_take_on_candidates,
|
||||
'remaining_value': move.remaining_value + negative_stock_value,
|
||||
'value': -tmp_value + negative_stock_value,
|
||||
'price_unit': (-tmp_value + negative_stock_value) / move.product_qty,
|
||||
'price_unit': (-tmp_value + negative_stock_value) / (move.product_qty or quantity),
|
||||
}
|
||||
move.write(vals)
|
||||
return tmp_value
|
||||
|
||||
def _run_valuation(self, quantity=None):
|
||||
self.ensure_one()
|
||||
if self._is_in():
|
||||
if self.product_id.cost_method in ['fifo', 'average']:
|
||||
price_unit = self.price_unit or self._get_price_unit()
|
||||
value = price_unit * (quantity or self.product_qty)
|
||||
vals = {
|
||||
'price_unit': price_unit,
|
||||
'value': value if quantity is None or not self.value else self.value,
|
||||
'remaining_value': value if quantity is None else self.remaining_value + value,
|
||||
}
|
||||
if self.product_id.cost_method == 'fifo':
|
||||
vals['remaining_qty'] = self.product_qty if quantity is None else self.remaining_qty + quantity
|
||||
self.write(vals)
|
||||
else: # standard
|
||||
value = self.product_id.standard_price * (quantity or self.product_qty)
|
||||
self.write({
|
||||
'price_unit': self.product_id.standard_price,
|
||||
'value': value if quantity is None or not self.value else self.value,
|
||||
})
|
||||
elif self._is_out():
|
||||
if self.product_id.cost_method == 'fifo':
|
||||
self.env['stock.move']._run_fifo(self, quantity=quantity)
|
||||
elif self.product_id.cost_method in ['standard', 'average']:
|
||||
curr_rounding = self.company_id.currency_id.rounding
|
||||
value = -float_round(self.product_id.standard_price * (self.product_qty if quantity is None else quantity), precision_rounding=curr_rounding)
|
||||
self.write({
|
||||
'value': value if quantity is None else self.value + value,
|
||||
'price_unit': value / self.product_qty,
|
||||
})
|
||||
|
||||
def _action_done(self):
|
||||
self.product_price_update_before_done()
|
||||
res = super(StockMove, self)._action_done()
|
||||
for move in res:
|
||||
if move._is_in():
|
||||
if move.product_id.cost_method in ['fifo', 'average']:
|
||||
price_unit = move.price_unit or move._get_price_unit()
|
||||
value = price_unit * move.product_qty
|
||||
vals = {
|
||||
'price_unit': price_unit,
|
||||
'value': value,
|
||||
'remaining_value': value,
|
||||
}
|
||||
if move.product_id.cost_method == 'fifo':
|
||||
vals['remaining_qty'] = move.product_qty
|
||||
move.write(vals)
|
||||
else: # standard
|
||||
move.write({
|
||||
'price_unit': move.product_id.standard_price,
|
||||
'value': move.product_id.standard_price * move.product_qty,
|
||||
})
|
||||
elif move._is_out():
|
||||
if move.product_id.cost_method == 'fifo':
|
||||
self.env['stock.move']._run_fifo(move)
|
||||
elif move.product_id.cost_method in ['standard', 'average']:
|
||||
curr_rounding = move.company_id.currency_id.rounding
|
||||
value = -float_round(move.product_id.standard_price * move.product_qty, precision_rounding=curr_rounding)
|
||||
move.write({
|
||||
'value': value,
|
||||
'price_unit': value / move.product_qty,
|
||||
})
|
||||
move._run_valuation()
|
||||
for move in res.filtered(lambda m: m.product_id.valuation == 'real_time' and (m._is_in() or m._is_out())):
|
||||
move._account_entry_move()
|
||||
return res
|
||||
|
||||
@@ -10,14 +10,21 @@ class TestStockValuation(TransactionCase):
|
||||
self.stock_location = self.env.ref('stock.stock_location_stock')
|
||||
self.customer_location = self.env.ref('stock.stock_location_customers')
|
||||
self.supplier_location = self.env.ref('stock.stock_location_suppliers')
|
||||
self.partner = self.env['res.partner'].create({'name': 'xxx'})
|
||||
self.uom_unit = self.env.ref('product.product_uom_unit')
|
||||
self.product1 = self.env['product.product'].create({
|
||||
'name': 'Product A',
|
||||
'type': 'product',
|
||||
'categ_id': self.env.ref('product.product_category_all').id,
|
||||
})
|
||||
self.product2 = self.env['product.product'].create({
|
||||
'name': 'Product B',
|
||||
'type': 'product',
|
||||
'categ_id': self.env.ref('product.product_category_all').id,
|
||||
})
|
||||
|
||||
self.product1.product_tmpl_id.valuation = 'real_time'
|
||||
self.product2.product_tmpl_id.valuation = 'real_time'
|
||||
Account = self.env['account.account']
|
||||
self.stock_input_account = Account.create({
|
||||
'name': 'Stock Input',
|
||||
@@ -54,19 +61,16 @@ class TestStockValuation(TransactionCase):
|
||||
|
||||
def _get_stock_input_move_lines(self):
|
||||
return self.env['account.move.line'].search([
|
||||
('product_id', '=', self.product1.id),
|
||||
('account_id', '=', self.stock_input_account.id),
|
||||
], order='date, id')
|
||||
|
||||
def _get_stock_output_move_lines(self):
|
||||
return self.env['account.move.line'].search([
|
||||
('product_id', '=', self.product1.id),
|
||||
('account_id', '=', self.stock_output_account.id),
|
||||
], order='date, id')
|
||||
|
||||
def _get_stock_valuation_move_lines(self):
|
||||
return self.env['account.move.line'].search([
|
||||
('product_id', '=', self.product1.id),
|
||||
('account_id', '=', self.stock_valuation_account.id),
|
||||
], order='date, id')
|
||||
|
||||
@@ -1480,6 +1484,272 @@ class TestStockValuation(TransactionCase):
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('debit')), 310)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
|
||||
|
||||
def test_fifo_add_move_in_done_picking_1(self):
|
||||
self.product1.product_tmpl_id.cost_method = 'fifo'
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Receive 10@10
|
||||
# ---------------------------------------------------------------------
|
||||
receipt = self.env['stock.picking'].create({
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'partner_id': self.partner.id,
|
||||
'picking_type_id': self.env.ref('stock.picking_type_in').id,
|
||||
})
|
||||
|
||||
move1 = self.env['stock.move'].create({
|
||||
'picking_id': receipt.id,
|
||||
'name': '10 in',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': self.product1.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 10.0,
|
||||
'price_unit': 10,
|
||||
'move_line_ids': [(0, 0, {
|
||||
'product_id': self.product1.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'qty_done': 10.0,
|
||||
})]
|
||||
})
|
||||
move1._action_confirm()
|
||||
move1._action_done()
|
||||
|
||||
# stock values for move1
|
||||
self.assertEqual(move1.value, 100.0)
|
||||
self.assertEqual(move1.remaining_qty, 10.0)
|
||||
self.assertEqual(move1.price_unit, 10.0)
|
||||
self.assertEqual(move1.remaining_value, 100.0)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Add a stock move, receive 10@20 of another product
|
||||
# ---------------------------------------------------------------------
|
||||
self.product2.product_tmpl_id.cost_method = 'fifo'
|
||||
self.product2.standard_price = 20
|
||||
move2 = self.env['stock.move'].create({
|
||||
'picking_id': receipt.id,
|
||||
'name': '10 in',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': self.product2.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 10.0,
|
||||
'state': 'done', # simulate default_get override
|
||||
'move_line_ids': [(0, 0, {
|
||||
'product_id': self.product2.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'qty_done': 10.0,
|
||||
})]
|
||||
})
|
||||
self.assertEqual(move2.value, 200.0)
|
||||
self.assertEqual(move2.remaining_qty, 10.0)
|
||||
self.assertEqual(move2.price_unit, 20.0)
|
||||
self.assertEqual(move2.remaining_value, 200.0)
|
||||
|
||||
self.assertEqual(self.product1.qty_available, 10)
|
||||
self.assertEqual(self.product1.stock_value, 100)
|
||||
self.assertEqual(self.product2.qty_available, 10)
|
||||
self.assertEqual(self.product2.stock_value, 200)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Edit the previous stock move, receive 11
|
||||
# ---------------------------------------------------------------------
|
||||
move2.quantity_done = 11
|
||||
|
||||
self.assertEqual(move2.value, 200.0)
|
||||
self.assertEqual(move2.remaining_qty, 11.0)
|
||||
self.assertEqual(move2.price_unit, 20.0)
|
||||
self.assertEqual(move2.remaining_value, 220.0)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Send 11 product 2
|
||||
# ---------------------------------------------------------------------
|
||||
delivery = self.env['stock.picking'].create({
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'partner_id': self.partner.id,
|
||||
'picking_type_id': self.env.ref('stock.picking_type_out').id,
|
||||
})
|
||||
move3 = self.env['stock.move'].create({
|
||||
'picking_id': delivery.id,
|
||||
'name': '11 out',
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'product_id': self.product2.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 11.0,
|
||||
'move_line_ids': [(0, 0, {
|
||||
'product_id': self.product2.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'qty_done': 11.0,
|
||||
})]
|
||||
})
|
||||
|
||||
move3._action_confirm()
|
||||
move3._action_done()
|
||||
|
||||
self.assertEqual(move3.value, -220.0)
|
||||
self.assertEqual(move3.remaining_qty, 0.0)
|
||||
self.assertEqual(move3.price_unit, -20.0)
|
||||
self.assertEqual(move3.remaining_value, 0.0)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Add one move of product 2
|
||||
# ---------------------------------------------------------------------
|
||||
move4 = self.env['stock.move'].create({
|
||||
'picking_id': delivery.id,
|
||||
'name': '1 out',
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'product_id': self.product2.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
'state': 'done', # simulate default_get override
|
||||
'move_line_ids': [(0, 0, {
|
||||
'product_id': self.product2.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'qty_done': 1.0,
|
||||
})]
|
||||
})
|
||||
self.assertEqual(move4.value, -20.0)
|
||||
self.assertEqual(move4.remaining_qty, -1.0)
|
||||
self.assertEqual(move4.price_unit, -20.0)
|
||||
self.assertEqual(move4.remaining_value, -20.0)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# edit the created move, add 1
|
||||
# ---------------------------------------------------------------------
|
||||
move4.quantity_done = 2
|
||||
|
||||
self.assertEqual(move4.value, -20.0)
|
||||
self.assertEqual(move4.remaining_qty, -2.0)
|
||||
self.assertEqual(move4.price_unit, -20.0)
|
||||
self.assertEqual(move4.remaining_value, -40.0)
|
||||
|
||||
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('debit')), 0)
|
||||
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('credit')), 320) # 10*10 + 11*20
|
||||
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 320)
|
||||
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 260)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('debit')), 260)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
|
||||
|
||||
self.env['stock.move']._run_fifo_vacuum()
|
||||
|
||||
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('debit')), 0)
|
||||
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('credit')), 320) # 10*10 + 11*20
|
||||
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 320)
|
||||
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 260)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('debit')), 260)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# receive 2 products 2 @ 30
|
||||
# ---------------------------------------------------------------------
|
||||
move1 = self.env['stock.move'].create({
|
||||
'picking_id': receipt.id,
|
||||
'name': '10 in',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': self.product2.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 2.0,
|
||||
'price_unit': 30,
|
||||
'move_line_ids': [(0, 0, {
|
||||
'product_id': self.product2.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'qty_done': 2.0,
|
||||
})]
|
||||
})
|
||||
move1._action_confirm()
|
||||
move1._action_done()
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# run vacuum
|
||||
# ---------------------------------------------------------------------
|
||||
self.env['stock.move']._run_fifo_vacuum()
|
||||
|
||||
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('debit')), 0)
|
||||
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('credit')), 380) # 10*10 + 11*20
|
||||
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 380)
|
||||
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 280) # 260/
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('debit')), 280)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
|
||||
|
||||
self.assertEqual(self.product2.qty_available, 0)
|
||||
self.assertEqual(self.product2.stock_value, 0)
|
||||
self.assertEqual(move4.remaining_value, 0)
|
||||
|
||||
def test_fifo_add_moveline_in_done_move_1(self):
|
||||
self.product1.product_tmpl_id.cost_method = 'fifo'
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Receive 10@10
|
||||
# ---------------------------------------------------------------------
|
||||
move1 = self.env['stock.move'].create({
|
||||
'name': '10 in',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': self.product1.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 10.0,
|
||||
'price_unit': 10,
|
||||
'move_line_ids': [(0, 0, {
|
||||
'product_id': self.product1.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'qty_done': 10.0,
|
||||
})]
|
||||
})
|
||||
move1._action_confirm()
|
||||
move1._action_done()
|
||||
|
||||
# stock values for move1
|
||||
self.assertEqual(move1.value, 100.0)
|
||||
self.assertEqual(move1.remaining_qty, 10.0)
|
||||
self.assertEqual(move1.price_unit, 10.0)
|
||||
self.assertEqual(move1.remaining_value, 100.0)
|
||||
|
||||
self.assertEqual(len(move1.account_move_ids), 1)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Add a new move line to receive 10 more
|
||||
# ---------------------------------------------------------------------
|
||||
self.assertEqual(len(move1.move_line_ids), 1)
|
||||
self.env['stock.move.line'].with_context(debug=True).create({
|
||||
'move_id': move1.id,
|
||||
'product_id': move1.product_id.id,
|
||||
'qty_done': 10,
|
||||
'product_uom_id': move1.product_uom.id,
|
||||
'location_id': move1.location_id.id,
|
||||
'location_dest_id': move1.location_dest_id.id,
|
||||
})
|
||||
self.assertEqual(move1.value, 100.0)
|
||||
self.assertEqual(move1.remaining_qty, 20.0)
|
||||
self.assertEqual(move1.price_unit, 10.0)
|
||||
self.assertEqual(move1.remaining_value, 200.0)
|
||||
|
||||
self.assertEqual(len(move1.account_move_ids), 2)
|
||||
|
||||
self.assertEqual(self.product1.qty_available, 20)
|
||||
self.assertEqual(self.product1.stock_value, 200)
|
||||
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('debit')), 0)
|
||||
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('credit')), 200)
|
||||
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 200)
|
||||
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 0)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('debit')), 0)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
|
||||
|
||||
def test_fifo_edit_done_move1(self):
|
||||
""" Check that incrementing the done quantity will correctly re-run a fifo lookup.
|
||||
"""
|
||||
@@ -1649,6 +1919,94 @@ class TestStockValuation(TransactionCase):
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('debit')), 148)
|
||||
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
|
||||
|
||||
def test_fifo_edit_done_move2(self):
|
||||
self.product1.product_tmpl_id.cost_method = 'fifo'
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Receive 10@10
|
||||
# ---------------------------------------------------------------------
|
||||
move1 = self.env['stock.move'].create({
|
||||
'name': 'receive 10@10',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': self.product1.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 10.0,
|
||||
'price_unit': 10,
|
||||
'move_line_ids': [(0, 0, {
|
||||
'product_id': self.product1.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'qty_done': 10.0,
|
||||
})]
|
||||
})
|
||||
move1._action_confirm()
|
||||
move1._action_done()
|
||||
|
||||
# stock values for move1
|
||||
self.assertEqual(move1.value, 100.0)
|
||||
self.assertEqual(move1.remaining_qty, 10.0)
|
||||
self.assertEqual(move1.price_unit, 10.0)
|
||||
self.assertEqual(move1.remaining_value, 100.0)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Send 10
|
||||
# ---------------------------------------------------------------------
|
||||
move2 = self.env['stock.move'].create({
|
||||
'name': '12 out (2 negative)',
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'product_id': self.product1.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 10.0,
|
||||
'price_unit': 0,
|
||||
'move_line_ids': [(0, 0, {
|
||||
'product_id': self.product1.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'qty_done': 10.0,
|
||||
})]
|
||||
})
|
||||
move2._action_confirm()
|
||||
move2._action_done()
|
||||
|
||||
# stock values for move2
|
||||
self.assertEqual(move2.value, -100.0)
|
||||
self.assertEqual(move2.remaining_qty, 0.0)
|
||||
self.assertEqual(move2.remaining_value, 0.0)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Actually, send 8 in the last move
|
||||
# ---------------------------------------------------------------------
|
||||
move2.quantity_done = 8
|
||||
|
||||
self.assertEqual(move2.value, -100.0)
|
||||
self.assertEqual(move2.remaining_qty, 0.0)
|
||||
self.assertEqual(move2.remaining_value, 0.0)
|
||||
|
||||
self.assertEqual(move1.remaining_qty, 2.0)
|
||||
self.assertEqual(move1.remaining_value, 20.0)
|
||||
|
||||
self.product1.qty_available = 2
|
||||
self.product1.stock_value = 20
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Actually, send 10 in the last move
|
||||
# ---------------------------------------------------------------------
|
||||
move2.with_context(debug=True).quantity_done = 10
|
||||
|
||||
self.assertEqual(move2.value, -100.0)
|
||||
self.assertEqual(move2.remaining_qty, 0.0)
|
||||
self.assertEqual(move2.remaining_value, 0.0)
|
||||
|
||||
self.assertEqual(move1.remaining_qty, 0.0)
|
||||
self.assertEqual(move1.remaining_value, 0.0)
|
||||
|
||||
self.product1.qty_available = 2
|
||||
self.product1.stock_value = 20
|
||||
|
||||
def test_average_perpetual_1(self):
|
||||
# http://accountingexplained.com/financial/inventories/avco-method
|
||||
self.product1.product_tmpl_id.cost_method = 'average'
|
||||
|
||||
Reference in New Issue
Block a user