[FIX] sale_mrp, stock, stock_account: Decimal Accuracy in Inventory report & Valuation report

Steps to reproduce the bug:

- Go to  Settings > Technical > Decimal Accuracy
- Change Unit of Measure to 4 digits
- Go to Inventory report or Valuation report

Bug:

The decimal accuracy in Valuation report for quantity or reserved quantity was in two digits instead of four digits
The decimal accuracy in Inventory report for qty_at_date was in two digits instead of four digits

PS: In stock move report or stock move line report, the decimal accuracy of quantity fields are in four digits

By default digits of Product Unit of Measure is 3, that's why some test had to be modified

opw:2410981

closes odoo/odoo#82989

X-original-commit: 0cf5c4e8241c46724defc0ea7e0d2c881ec2eeab
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Arnold Moyaux <arm@odoo.com>
This commit is contained in:
Goffin Simon
2022-02-03 09:56:03 +00:00
committed by Arnold Moyaux
parent 088b9c2398
commit e91b00d053
4 changed files with 31 additions and 29 deletions
+7 -7
View File
@@ -254,7 +254,7 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon):
line.product_uom_id = self.uom_unit
with f.bom_line_ids.new() as line:
line.product_id = product_c
line.product_qty = 300.5
line.product_qty = 300.0
line.product_uom_id = self.uom_gm
with f.bom_line_ids.new() as line:
line.product_id = product_d
@@ -313,10 +313,10 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon):
#
# [15 * 400 gm ( 6 kg product C)] = 6 kg product C
#
# Product C 1502.5 gm.
# Product C 1500.0 gm.
# [
# For 2 Dozen product A will consume 300.5 gm product C
# then for 10 Dozen product A will consume 1502.5 gm product C.
# For 2 Dozen product A will consume 300.0 gm product C
# then for 10 Dozen product A will consume 1500.0 gm product C.
# ]
#
# product D 20 Unit.
@@ -370,8 +370,8 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon):
# Check total consume line of product c with gm.
self.assertEqual(len(move), 1, 'Production move lines are not generated proper.')
# Check quantity should be with 1502.5 ( 2 Dozen product A consume 300.5 gm then 10 Dozen (300.5 * (10/2)).
self.assertEqual(move.product_uom_qty, 1502.5, "Wrong product quantity in 'To consume line' of manufacturing order.")
# Check quantity should be with 1500.0 ( 2 Dozen product A consume 300.0 gm then 10 Dozen (300.0 * (10/2)).
self.assertEqual(move.product_uom_qty, 1500.0, "Wrong product quantity in 'To consume line' of manufacturing order.")
# Check state of consume line with product c with and uom gm.
self.assertEqual(move.state, 'confirmed', "Wrong state in 'To consume line' of manufacturing order.")
@@ -446,7 +446,7 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon):
# Create inventory for product C.
# ------------------------------
# Need product C ( 20 kg + 6 kg + 1502.5 gm = 27.5025 kg)
# Need product C ( 20 kg + 6 kg + 1500.0 gm = 27.500 kg)
# -------------------------------------------------------
self.Quant.with_context(inventory_mode=True).create({
+3 -3
View File
@@ -84,16 +84,16 @@ class StockQuant(models.Model):
quantity = fields.Float(
'Quantity',
help='Quantity of products in this quant, in the default unit of measure of the product',
readonly=True)
readonly=True, digits='Product Unit of Measure')
reserved_quantity = fields.Float(
'Reserved Quantity',
default=0.0,
help='Quantity of reserved products in this quant, in the default unit of measure of the product',
readonly=True, required=True)
readonly=True, required=True, digits='Product Unit of Measure')
available_quantity = fields.Float(
'Available Quantity',
help="On hand quantity which hasn't been reserved on a transfer, in the default unit of measure of the product",
compute='_compute_available_quantity')
compute='_compute_available_quantity', digits='Product Unit of Measure')
in_date = fields.Datetime('Incoming Date', readonly=True, required=True, default=fields.Datetime.now)
tracking = fields.Selection(related='product_id.tracking', readonly=True)
on_hand = fields.Boolean('On Hand', store=False, search='_search_on_hand')
+19 -17
View File
@@ -538,8 +538,8 @@ class TestStockFlow(TestStockCommon):
# Check quants and available quantity for product gB
quants = self.StockQuantObj.search([('product_id', '=', self.gB.id), ('location_id', '=', self.stock_location)])
total_qty = [quant.quantity for quant in quants]
self.assertEqual(sum(total_qty), 525.3, 'Expecting 525.3 gram , got %.4f gram on location stock!' % (sum(total_qty)))
self.assertEqual(self.gB.qty_available, 525.3, 'Wrong quantity available (%s found instead of 525.3' % (self.gB.qty_available))
self.assertAlmostEqual(sum(total_qty), 525.3, msg='Expecting 525.3 gram , got %.4f gram on location stock!' % (sum(total_qty)))
self.assertAlmostEqual(self.gB.qty_available, 525.3, msg='Wrong quantity available (%s found instead of 525.3' % (self.gB.qty_available))
# Check quants and available quantity for product kgB
quants = self.StockQuantObj.search([('product_id', '=', self.kgB.id), ('location_id', '=', self.stock_location)])
total_qty = [quant.quantity for quant in quants]
@@ -958,7 +958,7 @@ class TestStockFlow(TestStockCommon):
self.MoveObj.create({
'name': productKG.name,
'product_id': productKG.id,
'product_uom_qty': 2.5,
'product_uom_qty': 25,
'product_uom': self.uom_gm.id,
'picking_id': picking_out.id,
'location_id': self.stock_location,
@@ -966,7 +966,7 @@ class TestStockFlow(TestStockCommon):
picking_out.action_confirm()
picking_out.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', picking_out.id)], limit=1)
pack_opt.write({'reserved_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 5})
res_dict = picking_out.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
res_dict_for_back_order = wizard.process()
@@ -975,7 +975,7 @@ class TestStockFlow(TestStockCommon):
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
total_qty = [quant.quantity for quant in quants]
# Check total quantity stock location.
self.assertEqual(sum(total_qty), 999.9995, 'Expecting 999.9995 kg , got %.4f kg on location stock!' % (sum(total_qty)))
self.assertEqual(sum(total_qty), 999.995, 'Expecting 999.995 kg , got %.4f kg on location stock!' % (sum(total_qty)))
# ---------------------------------
# Check Back order created or not.
@@ -986,11 +986,11 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(len(bo_out_1.move_ids), 1, 'Wrong number of move lines')
moves_KG = self.MoveObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_1.id)], limit=1)
# Check back order created with correct quantity and uom or not.
self.assertEqual(moves_KG.product_uom_qty, 2.0, 'Wrong move quantity (%s found instead of 2.0)' % (moves_KG.product_uom_qty))
self.assertEqual(moves_KG.product_uom_qty, 20, 'Wrong move quantity (%s found instead of 20)' % (moves_KG.product_uom_qty))
self.assertEqual(moves_KG.product_uom.id, self.uom_gm.id, 'Wrong uom in move for product KG.')
bo_out_1.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_1.id)], limit=1)
pack_opt.write({'reserved_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 5})
res_dict = bo_out_1.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
res_dict_for_back_order = wizard.process()
@@ -1000,7 +1000,7 @@ class TestStockFlow(TestStockCommon):
total_qty = [quant.quantity for quant in quants]
# Check total quantity stock location.
self.assertEqual(sum(total_qty), 999.9990, 'Expecting 999.9990 kg , got %.4f kg on location stock!' % (sum(total_qty)))
self.assertEqual(sum(total_qty), 999.990, 'Expecting 999.990 kg , got %.4f kg on location stock!' % (sum(total_qty)))
# Check Back order created or not.
# ---------------------------------
@@ -1010,11 +1010,11 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(len(bo_out_2.move_ids), 1, 'Wrong number of move lines')
# Check back order created with correct move quantity and uom or not.
moves_KG = self.MoveObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_2.id)], limit=1)
self.assertEqual(moves_KG.product_uom_qty, 1.5, 'Wrong move quantity (%s found instead of 1.5)' % (moves_KG.product_uom_qty))
self.assertEqual(moves_KG.product_uom_qty, 15, 'Wrong move quantity (%s found instead of 15)' % (moves_KG.product_uom_qty))
self.assertEqual(moves_KG.product_uom.id, self.uom_gm.id, 'Wrong uom in move for product KG.')
bo_out_2.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_2.id)], limit=1)
pack_opt.write({'reserved_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 5})
res_dict = bo_out_2.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
res_dict_for_back_order = wizard.process()
@@ -1023,7 +1023,7 @@ class TestStockFlow(TestStockCommon):
# Check total quantity stock location of product KG.
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
total_qty = [quant.quantity for quant in quants]
self.assertEqual(sum(total_qty), 999.9985, 'Expecting 999.9985 kg , got %.4f kg on location stock!' % (sum(total_qty)))
self.assertEqual(sum(total_qty), 999.985, 'Expecting 999.985 kg , got %.4f kg on location stock!' % (sum(total_qty)))
# Check Back order created or not.
# ---------------------------------
@@ -1033,17 +1033,19 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(len(bo_out_3.move_ids), 1, 'Wrong number of move lines')
# Check back order created with correct quantity and uom or not.
moves_KG = self.MoveObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_3.id)], limit=1)
self.assertEqual(moves_KG.product_uom_qty, 1, 'Wrong move quantity (%s found instead of 1.0)' % (moves_KG.product_uom_qty))
self.assertEqual(moves_KG.product_uom_qty, 10, 'Wrong move quantity (%s found instead of 10)' % (moves_KG.product_uom_qty))
self.assertEqual(moves_KG.product_uom.id, self.uom_gm.id, 'Wrong uom in move for product KG.')
bo_out_3.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_3.id)], limit=1)
pack_opt.write({'reserved_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 5})
res_dict = bo_out_3.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
res_dict_for_back_order = wizard.process()
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context'])
backorder_wizard.process()
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
total_qty = [quant.quantity for quant in quants]
self.assertEqual(sum(total_qty), 999.9980, 'Expecting 999.9980 kg , got %.4f kg on location stock!' % (sum(total_qty)))
self.assertEqual(sum(total_qty), 999.980, 'Expecting 999.980 kg , got %.4f kg on location stock!' % (sum(total_qty)))
# Check Back order created or not.
# ---------------------------------
@@ -1054,17 +1056,17 @@ class TestStockFlow(TestStockCommon):
self.assertEqual(len(bo_out_4.move_ids), 1, 'Wrong number of move lines')
# Check back order created with correct quantity and uom or not.
moves_KG = self.MoveObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_4.id)], limit=1)
self.assertEqual(moves_KG.product_uom_qty, 0.5, 'Wrong move quantity (%s found instead of 0.5)' % (moves_KG.product_uom_qty))
self.assertEqual(moves_KG.product_uom_qty, 5, 'Wrong move quantity (%s found instead of 5)' % (moves_KG.product_uom_qty))
self.assertEqual(moves_KG.product_uom.id, self.uom_gm.id, 'Wrong uom in move for product KG.')
bo_out_4.action_assign()
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_4.id)], limit=1)
pack_opt.write({'reserved_uom_qty': 0.5})
pack_opt.write({'reserved_uom_qty': 5})
res_dict = bo_out_4.button_validate()
wizard = Form(self.env[(res_dict.get('res_model'))].with_context(res_dict['context'])).save()
wizard.process()
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
total_qty = [quant.quantity for quant in quants]
self.assertAlmostEqual(sum(total_qty), 999.9975, msg='Expecting 999.9975 kg , got %.4f kg on location stock!' % (sum(total_qty)))
self.assertAlmostEqual(sum(total_qty), 999.975, msg='Expecting 999.975 kg , got %.4f kg on location stock!' % (sum(total_qty)))
def test_20_create_inventory_with_packs_and_lots(self):
# --------------------------------------------------------
@@ -17,12 +17,12 @@ class StockValuationLayer(models.Model):
product_id = fields.Many2one('product.product', 'Product', readonly=True, required=True, check_company=True, auto_join=True)
categ_id = fields.Many2one('product.category', related='product_id.categ_id')
product_tmpl_id = fields.Many2one('product.template', related='product_id.product_tmpl_id')
quantity = fields.Float('Quantity', digits=0, help='Quantity', readonly=True)
quantity = fields.Float('Quantity', help='Quantity', readonly=True, digits='Product Unit of Measure')
uom_id = fields.Many2one(related='product_id.uom_id', readonly=True, required=True)
currency_id = fields.Many2one('res.currency', 'Currency', related='company_id.currency_id', readonly=True, required=True)
unit_cost = fields.Monetary('Unit Value', readonly=True)
value = fields.Monetary('Total Value', readonly=True)
remaining_qty = fields.Float(digits=0, readonly=True)
remaining_qty = fields.Float(readonly=True, digits='Product Unit of Measure')
remaining_value = fields.Monetary('Remaining Value', readonly=True)
description = fields.Char('Description', readonly=True)
stock_valuation_layer_id = fields.Many2one('stock.valuation.layer', 'Linked To', readonly=True, check_company=True)