diff --git a/addons/purchase_stock/tests/test_average_price.py b/addons/purchase_stock/tests/test_average_price.py index f18daec3d1a..0f1e257ccbd 100644 --- a/addons/purchase_stock/tests/test_average_price.py +++ b/addons/purchase_stock/tests/test_average_price.py @@ -24,13 +24,13 @@ class TestAveragePrice(TestPurchase): 'standard_price': 60.0, 'uom_id': self.env.ref('uom.product_uom_kgm').id, 'uom_po_id': self.env.ref('uom.product_uom_kgm').id, - 'cost_method': 'average', - 'valuation': 'real_time', - 'property_stock_account_input': self.ref('purchase.o_expense'), - 'property_stock_account_output': self.ref('purchase.o_income'), 'supplier_taxes_id': [], 'description': 'FIFO Ice Cream', }) + product_cable_management_box.categ_id.property_cost_method = 'average' + product_cable_management_box.categ_id.property_valuation = 'real_time' + product_cable_management_box.categ_id.property_stock_account_input_categ_id = self.ref('purchase.o_expense') + product_cable_management_box.categ_id.property_stock_account_output_categ_id = self.ref('purchase.o_income') # I create a draft Purchase Order for first incoming shipment for 10 pieces at 60€ purchase_order_1 = self.env['purchase.order'].create({ diff --git a/addons/purchase_stock/tests/test_fifo_price.py b/addons/purchase_stock/tests/test_fifo_price.py index f0c923b9c17..bb7c1b2a2b1 100644 --- a/addons/purchase_stock/tests/test_fifo_price.py +++ b/addons/purchase_stock/tests/test_fifo_price.py @@ -23,13 +23,13 @@ class TestFifoPrice(TestPurchase): 'standard_price': 70.0, 'uom_id': self.env.ref('uom.product_uom_kgm').id, 'uom_po_id': self.env.ref('uom.product_uom_kgm').id, - 'cost_method': 'fifo', - 'valuation': 'real_time', - 'property_stock_account_input': self.ref('purchase.o_expense'), - 'property_stock_account_output': self.ref('purchase.o_income'), 'supplier_taxes_id': '[]', 'description': 'FIFO Ice Cream', }) + product_cable_management_box.categ_id.property_cost_method = 'fifo' + product_cable_management_box.categ_id.property_valuation = 'real_time' + product_cable_management_box.categ_id.property_stock_account_input_categ_id = self.ref('purchase.o_expense') + product_cable_management_box.categ_id.property_stock_account_output_categ_id = self.ref('purchase.o_income') # I create a draft Purchase Order for first in move for 10 kg at 50 euro purchase_order_1 = self.env['purchase.order'].create({ @@ -217,13 +217,13 @@ class TestFifoPrice(TestPurchase): 'standard_price': 70.0, 'uom_id': self.env.ref('uom.product_uom_kgm').id, 'uom_po_id': self.env.ref('uom.product_uom_kgm').id, - 'cost_method': 'fifo', - 'valuation': 'real_time', - 'property_stock_account_input': self.ref('purchase.o_expense'), - 'property_stock_account_output': self.ref('purchase.o_income'), 'supplier_taxes_id': '[]', 'description': 'FIFO Ice Cream', }) + product_fifo_negative.categ_id.property_cost_method = 'fifo' + product_fifo_negative.categ_id.property_valuation = 'real_time' + product_fifo_negative.categ_id.property_stock_account_input_categ_id = self.ref('purchase.o_expense') + product_fifo_negative.categ_id.property_stock_account_output_categ_id = self.ref('purchase.o_income') # Create outpicking.create delivery order of 100 kg. outgoing_shipment_neg = self.env['stock.picking'].create({ diff --git a/addons/purchase_stock/tests/test_fifo_returns.py b/addons/purchase_stock/tests/test_fifo_returns.py index 566577f847d..9a2811ac45b 100644 --- a/addons/purchase_stock/tests/test_fifo_returns.py +++ b/addons/purchase_stock/tests/test_fifo_returns.py @@ -22,12 +22,12 @@ class TestFifoReturns(TestPurchase): 'standard_price': 0.0, 'uom_id': self.env.ref('uom.product_uom_kgm').id, 'uom_po_id': self.env.ref('uom.product_uom_kgm').id, - 'cost_method': 'fifo', - 'valuation': 'real_time', - 'property_stock_account_input': self.ref('purchase.o_expense'), - 'property_stock_account_output': self.ref('purchase.o_income'), 'description': 'FIFO Ice Cream', }) + product_fiforet_icecream.categ_id.property_cost_method = 'fifo' + product_fiforet_icecream.categ_id.property_valuation = 'real_time' + product_fiforet_icecream.categ_id.property_stock_account_input_categ_id = self.ref('purchase.o_expense') + product_fiforet_icecream.categ_id.property_stock_account_output_categ_id = self.ref('purchase.o_income') # I create a draft Purchase Order for first in move for 10 kg at 50 euro purchase_order_1 = self.env['purchase.order'].create({ diff --git a/addons/purchase_stock/tests/test_stockvaluation.py b/addons/purchase_stock/tests/test_stockvaluation.py index 336cb7ebd7a..bb92513c0b4 100644 --- a/addons/purchase_stock/tests/test_stockvaluation.py +++ b/addons/purchase_stock/tests/test_stockvaluation.py @@ -53,7 +53,7 @@ class TestStockValuation(TransactionCase): purchase order before validating the receipt, the value of the received goods should be set according to the last unit cost. """ - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'average' po1 = self.env['purchase.order'].create({ 'partner_id': self.partner_id.id, 'order_line': [ @@ -96,7 +96,7 @@ class TestStockValuation(TransactionCase): purchase order and the standard price of the product before validating the receipt, the value of the received goods should be set according to the last standard price. """ - self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard' # set a standard price self.product1.product_tmpl_id.standard_price = 10 @@ -149,7 +149,7 @@ class TestStockValuation(TransactionCase): eur_currency = self.env.ref('base.EUR') - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'average' # default currency is USD, create a purchase order in EUR po1 = self.env['purchase.order'].create({ @@ -212,7 +212,7 @@ class TestStockValuation(TransactionCase): """ Check that the extra move when over processing a receipt is correctly merged back in the original move. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' po1 = self.env['purchase.order'].create({ 'partner_id': self.partner_id.id, 'order_line': [ @@ -246,7 +246,7 @@ class TestStockValuation(TransactionCase): """ Check that the backordered move when under processing a receipt correctly keep the price unit of the original move. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' po1 = self.env['purchase.order'].create({ 'partner_id': self.partner_id.id, 'order_line': [ @@ -321,8 +321,8 @@ class TestStockValuationWithCOA(AccountingTestCase): def test_fifo_anglosaxon_return(self): self.env.user.company_id.anglo_saxon_accounting = True - self.product1.product_tmpl_id.cost_method = 'fifo' - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'delivery' price_diff_account = self.env['account.account'].create({ 'name': 'price diff account', @@ -421,8 +421,8 @@ class TestStockValuationWithCOA(AccountingTestCase): def test_anglosaxon_valuation(self): self.env.user.company_id.anglo_saxon_accounting = True - self.product1.product_tmpl_id.cost_method = 'fifo' - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'delivery' price_diff_account = self.env['account.account'].create({ 'name': 'price diff account', diff --git a/addons/stock_account/data/product_data.xml b/addons/stock_account/data/product_data.xml index f1c3044dced..0d4e5602347 100644 --- a/addons/stock_account/data/product_data.xml +++ b/addons/stock_account/data/product_data.xml @@ -1,18 +1,6 @@ - - property_stock_account_output - - - - - - property_stock_account_input - - - - property_stock_account_output_categ_id diff --git a/addons/stock_account/data/stock_account_data.xml b/addons/stock_account/data/stock_account_data.xml index c71fee32837..45a9d817cde 100644 --- a/addons/stock_account/data/stock_account_data.xml +++ b/addons/stock_account/data/stock_account_data.xml @@ -1,18 +1,6 @@ - - Cost Method Property - - - selection - - - Valuation Property - - - selection - Cost Method Property diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py index c95a3b3cd1f..3ecccb65beb 100644 --- a/addons/stock_account/models/product.py +++ b/addons/stock_account/models/product.py @@ -12,62 +12,11 @@ class ProductTemplate(models.Model): _name = 'product.template' _inherit = 'product.template' - property_valuation = fields.Selection([ - ('manual_periodic', 'Periodic (manual)'), - ('real_time', 'Perpetual (automated)')], string='Inventory Valuation', - company_dependent=True, copy=True, default='manual_periodic', - help="""Manual: The accounting entries to value the inventory are not posted automatically. - Automated: An accounting entry is automatically created to value the inventory when a product enters or leaves the company.""") - valuation = fields.Char(compute='_compute_valuation_type', inverse='_set_valuation_type') - property_cost_method = fields.Selection([ - ('standard', 'Standard Price'), - ('fifo', 'First In First Out (FIFO)'), - ('average', 'Average Cost (AVCO)')], string='Costing Method', - company_dependent=True, copy=True, - help="""Standard Price: The products are valued at their standard cost defined on the product. - Average Cost (AVCO): The products are valued at weighted average cost. - First In First Out (FIFO): The products are valued supposing those that enter the company first will also leave it first.""") - cost_method = fields.Char(compute='_compute_cost_method', inverse='_set_cost_method') - property_stock_account_input = fields.Many2one( - 'account.account', 'Stock Input Account', - company_dependent=True, domain=[('deprecated', '=', False)], - help="When doing real-time inventory valuation, counterpart journal items for all incoming stock moves will be posted in this account, unless " - "there is a specific valuation account set on the source location. When not set on the product, the one from the product category is used.") - property_stock_account_output = fields.Many2one( - 'account.account', 'Stock Output Account', - company_dependent=True, domain=[('deprecated', '=', False)], - help="When doing real-time inventory valuation, counterpart journal items for all outgoing stock moves will be posted in this account, unless " - "there is a specific valuation account set on the destination location. When not set on the product, the one from the product category is used.") - - @api.one - @api.depends('property_valuation', 'categ_id.property_valuation') - def _compute_valuation_type(self): - self.valuation = self.property_valuation or self.categ_id.property_valuation - - @api.one - def _set_valuation_type(self): - return self.write({'property_valuation': self.valuation}) - - @api.one - @api.depends('property_cost_method', 'categ_id.property_cost_method') - def _compute_cost_method(self): - self.cost_method = self.property_cost_method or self.categ_id.property_cost_method + cost_method = fields.Selection(related="categ_id.property_cost_method", readonly=True) + valuation = fields.Selection(related="categ_id.property_valuation", readonly=True) def _is_cost_method_standard(self): - return self.property_cost_method == 'standard' - - @api.one - def _set_cost_method(self): - # When going from FIFO to AVCO or to standard, we update the standard price with the - # average value in stock. - if self.property_cost_method == 'fifo' and self.cost_method in ['average', 'standard']: - # Cannot use the `stock_value` computed field as it's already invalidated when - # entering this method. - valuation = sum([variant._sum_remaining_values()[0] for variant in self.product_variant_ids]) - qty_available = self.with_context(company_owned=True).qty_available - if qty_available: - self.standard_price = valuation / qty_available - return self.write({'property_cost_method': self.cost_method}) + return self.categ_id.property_cost_method == 'standard' @api.multi def _get_product_accounts(self): @@ -77,8 +26,8 @@ class ProductTemplate(models.Model): accounts = super(ProductTemplate, self)._get_product_accounts() res = self._get_asset_accounts() accounts.update({ - 'stock_input': res['stock_input'] or self.property_stock_account_input or self.categ_id.property_stock_account_input_categ_id, - 'stock_output': res['stock_output'] or self.property_stock_account_output or self.categ_id.property_stock_account_output_categ_id, + 'stock_input': res['stock_input'] or self.categ_id.property_stock_account_input_categ_id, + 'stock_output': res['stock_output'] or self.categ_id.property_stock_account_output_categ_id, 'stock_valuation': self.categ_id.property_stock_valuation_account_id or False, }) return accounts @@ -177,7 +126,7 @@ class ProductProduct(models.Model): return sum(moves.mapped('remaining_value')), moves @api.multi - @api.depends('stock_move_ids.product_qty', 'stock_move_ids.state', 'stock_move_ids.remaining_value', 'product_tmpl_id.cost_method', 'product_tmpl_id.standard_price', 'product_tmpl_id.property_valuation', 'product_tmpl_id.categ_id.property_valuation') + @api.depends('stock_move_ids.product_qty', 'stock_move_ids.state', 'stock_move_ids.remaining_value', 'product_tmpl_id.cost_method', 'product_tmpl_id.standard_price', 'product_tmpl_id.categ_id.property_valuation') def _compute_stock_value(self): StockMove = self.env['stock.move'] to_date = self.env.context.get('to_date') @@ -402,6 +351,14 @@ class ProductCategory(models.Model): input_and_output_accounts = category.property_stock_account_input_categ_id | category.property_stock_account_output_categ_id if valuation_account and valuation_account in input_and_output_accounts: raise ValidationError(_('The Stock Input and/or Output accounts cannot be the same than the Stock Valuation account.')) + @api.multi + def write(self, vals): + # When going from FIFO to AVCO or to standard, we update the standard price with the + # average value in stock. + cost_method = vals.get('property_cost_method') + if cost_method and cost_method in ['average', 'standard']: + self._update_standard_price() + return super(ProductCategory, self).write(vals) @api.onchange('property_cost_method') def onchange_property_valuation(self): @@ -414,3 +371,12 @@ class ProductCategory(models.Model): 'message': _("Changing your cost method is an important change that will impact your inventory valuation. Are you sure you want to make that change?"), } } + + def _update_standard_price(self): + updated_categories = self.filtered(lambda x: x.property_cost_method == 'fifo') + templates = self.env['product.template'].search([('categ_id', 'in', updated_categories.ids)]) + for t in templates: + valuation = sum([variant._sum_remaining_values()[0] for variant in t.product_variant_ids]) + qty_available = t.with_context(company_owned=True).qty_available + if qty_available: + t.standard_price = valuation / qty_available diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py index fc10fb468b9..c0d05ebbd0d 100644 --- a/addons/stock_account/models/stock.py +++ b/addons/stock_account/models/stock.py @@ -476,8 +476,6 @@ class StockMove(models.Model): def _run_fifo_vacuum(self): # Call `_fifo_vacuum` on concerned moves fifo_valued_products = self.env['product.product'] - fifo_valued_products |= self.env['product.template'].search([('property_cost_method', '=', 'fifo')]).mapped( - 'product_variant_ids') fifo_valued_categories = self.env['product.category'].search([('property_cost_method', '=', 'fifo')]) fifo_valued_products |= self.env['product.product'].search([('categ_id', 'child_of', fifo_valued_categories.ids)]) moves_to_vacuum = self.env['stock.move'] diff --git a/addons/stock_account/tests/test_stockvaluation.py b/addons/stock_account/tests/test_stockvaluation.py index 39ced676a1a..3720b453635 100644 --- a/addons/stock_account/tests/test_stockvaluation.py +++ b/addons/stock_account/tests/test_stockvaluation.py @@ -29,8 +29,8 @@ class TestStockValuation(TransactionCase): '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' + self.product1.categ_id.property_valuation = 'real_time' + self.product2.categ_id.property_valuation = 'real_time' Account = self.env['account.account'] self.stock_input_account = Account.create({ 'name': 'Stock Input', @@ -113,7 +113,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(price_change_aml.product_id, self.product1) def test_fifo_perpetual_1(self): - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # --------------------------------------------------------------------- # receive 10 units @ 10.00 per unit @@ -779,7 +779,7 @@ class TestStockValuation(TransactionCase): def test_fifo_perpetual_2(self): # http://accountingexplained.com/financial/inventories/fifo-method - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # Beginning Inventory: 68 units @ 15.00 per unit move1 = self.env['stock.move'].create({ @@ -1223,7 +1223,7 @@ class TestStockValuation(TransactionCase): """ Send products that you do not have. Value the first outgoing move to the standard price, receive in multiple times the delivered quantity and run _fifo_vacuum to compensate. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # We expect the user to set manually set a standard price to its products if its first # transfer is sending products that he doesn't have. @@ -1416,7 +1416,7 @@ class TestStockValuation(TransactionCase): price, running the vacuum should not do anything. Receive 2 units at the price the two extra units were sent, check that no accounting entries are created. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # --------------------------------------------------------------------- # Receive 10@10 @@ -1584,7 +1584,7 @@ class TestStockValuation(TransactionCase): """ Receives 10 units, send 10 units, then send more: the extra quantity should be valued at the last fifo price, running the vacuum should not do anything. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # --------------------------------------------------------------------- # Receive 10@10 @@ -1750,7 +1750,7 @@ class TestStockValuation(TransactionCase): IN03 2@30 product2 vacuum """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # --------------------------------------------------------------------- # Receive 10@10 @@ -1791,7 +1791,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # Add a stock move, receive 10@20 of another product # --------------------------------------------------------------------- - self.product2.product_tmpl_id.cost_method = 'fifo' + self.product2.categ_id.property_cost_method = 'fifo' self.product2.standard_price = 20 move2 = self.env['stock.move'].create({ 'picking_id': receipt.id, @@ -1974,7 +1974,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(move4.value, -60) # after correction, the move is valued -(2*30) def test_fifo_add_moveline_in_done_move_1(self): - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # --------------------------------------------------------------------- # Receive 10@10 @@ -2037,7 +2037,7 @@ class TestStockValuation(TransactionCase): def test_fifo_edit_done_move1(self): """ Increase OUT done move while quantities are available. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # --------------------------------------------------------------------- # Receive 10@10 @@ -2216,7 +2216,7 @@ class TestStockValuation(TransactionCase): def test_fifo_edit_done_move2(self): """ Decrease, then increase OUT done move while quantities are available. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # --------------------------------------------------------------------- # Receive 10@10 @@ -2305,7 +2305,7 @@ class TestStockValuation(TransactionCase): def test_average_perpetual_1(self): # http://accountingexplained.com/financial/inventories/avco-method - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' # Beginning Inventory: 60 units @ 15.00 per unit move1 = self.env['stock.move'].create({ @@ -2410,7 +2410,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(move6.value, 0) def test_average_perpetual_2(self): - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' move1 = self.env['stock.move'].create({ 'name': 'Receive 10 units at 10', @@ -2471,7 +2471,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(self.product1.stock_value, 87.5) def test_average_perpetual_3(self): - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' move1 = self.env['stock.move'].create({ 'name': 'Receive 10 units at 10', @@ -2530,7 +2530,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(self.product1.stock_value, -187.5) def test_average_perpetual_4(self): - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' move1 = self.env['stock.move'].create({ 'name': 'Receive 1 unit at 10', @@ -2566,7 +2566,7 @@ class TestStockValuation(TransactionCase): def test_average_perpetual_5(self): ''' Set owner on incoming move => no valuation ''' - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' move1 = self.env['stock.move'].create({ 'name': 'Receive 1 unit at 10', @@ -2590,7 +2590,7 @@ class TestStockValuation(TransactionCase): def test_average_negative_1(self): """ Test edit in the past. Receive 10, send 20, edit the second move to only send 10. """ - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' move1 = self.env['stock.move'].create({ 'name': 'Receive 10 units at 10', @@ -2644,7 +2644,7 @@ class TestStockValuation(TransactionCase): def test_average_negative_2(self): """ Send goods that you don't have in stock and never received any unit. """ - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' # set a standard price self.product1.standard_price = 99 @@ -2667,7 +2667,7 @@ class TestStockValuation(TransactionCase): def test_average_negative_3(self): """ Send goods that you don't have in stock but received and send some units before. """ - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method= 'average' # set a standard price self.product1.standard_price = 99 @@ -2722,7 +2722,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(move3.value, -100.0) # as no move out were done for this product, fallback on latest cost def test_average_negative_4(self): - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' # set a standard price self.product1.standard_price = 99 @@ -2745,7 +2745,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(move1.value, 100.0) def test_average_negative_5(self): - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' # in 10 @ 10 move1 = self.env['stock.move'].create({ @@ -2871,8 +2871,8 @@ class TestStockValuation(TransactionCase): def test_average_manual_1(self): ''' Set owner on incoming move => no valuation ''' - self.product1.product_tmpl_id.cost_method = 'average' - self.product1.product_tmpl_id.valuation = 'manual_periodic' + self.product1.categ_id.property_cost_method = 'average' + self.product1.categ_id.property_valuation = 'manual_periodic' move1 = self.env['stock.move'].create({ 'name': 'Receive 1 unit at 10', @@ -2895,7 +2895,7 @@ class TestStockValuation(TransactionCase): def test_standard_perpetual_1(self): ''' Set owner on incoming move => no valuation ''' - self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.categ_id.property_cost_method = 'standard' move1 = self.env['stock.move'].create({ 'name': 'Receive 1 unit at 10', @@ -2918,8 +2918,8 @@ class TestStockValuation(TransactionCase): def test_standard_manual_1(self): ''' Set owner on incoming move => no valuation ''' - self.product1.product_tmpl_id.cost_method = 'standard' - self.product1.product_tmpl_id.valuation = 'manual_periodic' + self.product1.categ_id.property_cost_method = 'standard' + self.product1.categ_id.property_valuation = 'manual_periodic' move1 = self.env['stock.move'].create({ 'name': 'Receive 1 unit at 10', @@ -2946,7 +2946,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # Use FIFO, make some operations # --------------------------------------------------------------------- - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # receive 10@10 move1 = self.env['stock.move'].create({ @@ -2999,7 +2999,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # Change the production valuation to AVCO # --------------------------------------------------------------------- - self.product1.product_tmpl_id.cost_method = 'average' + self.product1.categ_id.property_cost_method = 'average' # valuation should stay to ~240 self.assertAlmostEqual(self.product1.stock_value, 240, delta=0.03) @@ -3016,7 +3016,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # Use FIFO, make some operations # --------------------------------------------------------------------- - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' # receive 10@10 move1 = self.env['stock.move'].create({ @@ -3069,7 +3069,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # Change the production valuation to AVCO # --------------------------------------------------------------------- - self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.categ_id.property_cost_method = 'standard' # valuation should stay to ~240 self.assertAlmostEqual(self.product1.stock_value, 240, delta=0.03) @@ -3088,7 +3088,7 @@ class TestStockValuation(TransactionCase): quants to a customer, only the one in the internal location should be valued. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' view_location = self.env['stock.location'].create({'name': 'view', 'usage': 'view'}) subloc1 = self.env['stock.location'].create({ @@ -3258,7 +3258,7 @@ class TestStockValuation(TransactionCase): move2._action_done() def test_at_date_standard_1(self): - self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.categ_id.property_cost_method = 'standard' now = Datetime.now() date1 = now - timedelta(days=8) @@ -3452,7 +3452,7 @@ class TestStockValuation(TransactionCase): date wizard are consistent. Afterwards, edit the done quantity of some operations. The valuation at date results should take these changes into account. """ - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' now = Datetime.now() date1 = now - timedelta(days=8) @@ -3579,7 +3579,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # ending: manual valuation # --------------------------------------------------------------------- - self.product1.product_tmpl_id.valuation = 'manual_periodic' + self.product1.categ_id.property_valuation = 'manual_periodic' self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).qty_at_date, 20) self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).stock_value, 200) self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date2)).qty_at_date, 30) @@ -3598,7 +3598,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # ending: perpetual valuation # --------------------------------------------------------------------- - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.categ_id.property_valuation = 'real_time' self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).qty_at_date, 10) self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).stock_value, 100) self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date2)).qty_at_date, 20) @@ -3615,7 +3615,7 @@ class TestStockValuation(TransactionCase): self.assertEqual(self.product1.stock_value, 1375) def test_at_date_fifo_2(self): - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.categ_id.property_cost_method = 'fifo' now = Datetime.now() date1 = now - timedelta(days=8) @@ -3740,7 +3740,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # ending: manual valuation # --------------------------------------------------------------------- - self.product1.product_tmpl_id.valuation = 'manual_periodic' + self.product1.categ_id.property_valuation = 'manual_periodic' self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).qty_at_date, 10) self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).stock_value, 100) self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date2)).qty_at_date, 20) @@ -3759,7 +3759,7 @@ class TestStockValuation(TransactionCase): # --------------------------------------------------------------------- # ending: perpetual valuation # --------------------------------------------------------------------- - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.categ_id.property_valuation = 'real_time' self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).qty_at_date, 10) self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date1)).stock_value, 100) self.assertEqual(self.product1.with_context(to_date=Datetime.to_string(date2)).qty_at_date, 20) diff --git a/addons/stock_account/views/product_views.xml b/addons/stock_account/views/product_views.xml index 237a3862444..5a6326688fd 100644 --- a/addons/stock_account/views/product_views.xml +++ b/addons/stock_account/views/product_views.xml @@ -35,7 +35,6 @@ - - - - - - - - diff --git a/addons/stock_dropshipping/tests/test_lifo_price.py b/addons/stock_dropshipping/tests/test_lifo_price.py index a93c1c1a4e0..358e9168ba3 100644 --- a/addons/stock_dropshipping/tests/test_lifo_price.py +++ b/addons/stock_dropshipping/tests/test_lifo_price.py @@ -40,8 +40,8 @@ class TestLifoPrice(common.TransactionCase): # category (or hand-assign the property_* version which seems...) # product_form.valuation = 'real_time' # product_form.cost_method = 'fifo' - product_form.property_stock_account_input = self.env.ref('stock_dropshipping.o_expense') - product_form.property_stock_account_output = self.env.ref('stock_dropshipping.o_income') + product_form.categ_id.property_stock_account_input_categ_id = self.env.ref('stock_dropshipping.o_expense') + product_form.categ_id.property_stock_account_output_categ_id = self.env.ref('stock_dropshipping.o_income') product_lifo_icecream = product_form.save() # I create a draft Purchase Order for first in move for 10 pieces at 60 euro diff --git a/addons/stock_dropshipping/tests/test_stockvaluation.py b/addons/stock_dropshipping/tests/test_stockvaluation.py index 02a4a834a20..536a188f9c2 100644 --- a/addons/stock_dropshipping/tests/test_stockvaluation.py +++ b/addons/stock_dropshipping/tests/test_stockvaluation.py @@ -108,9 +108,9 @@ class TestStockValuation(AccountingTestCase): # ------------------------------------------------------------------------- def test_dropship_standard_perpetual_continental_ordered(self): self.env.user.company_id.anglo_saxon_accounting = False - self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'order' all_amls = self._dropship_product1() @@ -126,9 +126,9 @@ class TestStockValuation(AccountingTestCase): def test_dropship_standard_perpetual_continental_delivered(self): self.env.user.company_id.anglo_saxon_accounting = False - self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'delivery' all_amls = self._dropship_product1() @@ -144,9 +144,9 @@ class TestStockValuation(AccountingTestCase): def test_dropship_fifo_perpetual_continental_ordered(self): self.env.user.company_id.anglo_saxon_accounting = False - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.proprty_cost_method = 'fifo' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'order' all_amls = self._dropship_product1() @@ -163,9 +163,9 @@ class TestStockValuation(AccountingTestCase): def test_dropship_fifo_perpetual_continental_delivered(self): self.env.user.company_id.anglo_saxon_accounting = False - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'delivery' all_amls = self._dropship_product1() @@ -184,9 +184,9 @@ class TestStockValuation(AccountingTestCase): # ------------------------------------------------------------------------- def test_dropship_standard_perpetual_anglosaxon_ordered(self): self.env.user.company_id.anglo_saxon_accounting = True - self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'order' all_amls = self._dropship_product1() @@ -207,9 +207,9 @@ class TestStockValuation(AccountingTestCase): def test_dropship_standard_perpetual_anglosaxon_delivered(self): self.env.user.company_id.anglo_saxon_accounting = True - self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'delivery' all_amls = self._dropship_product1() @@ -230,9 +230,9 @@ class TestStockValuation(AccountingTestCase): def test_dropship_fifo_perpetual_anglosaxon_ordered(self): self.env.user.company_id.anglo_saxon_accounting = True - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'order' all_amls = self._dropship_product1() @@ -250,9 +250,9 @@ class TestStockValuation(AccountingTestCase): def test_dropship_fifo_perpetual_anglosaxon_delivered(self): self.env.user.company_id.anglo_saxon_accounting = True - self.product1.product_tmpl_id.cost_method = 'fifo' + self.product1.product_tmpl_id.categ_id.property_cost_method = 'fifo' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'delivery' all_amls = self._dropship_product1() @@ -272,7 +272,7 @@ class TestStockValuation(AccountingTestCase): self.env.user.company_id.anglo_saxon_accounting = True self.product1.product_tmpl_id.cost_method = 'standard' self.product1.product_tmpl_id.standard_price = 10 - self.product1.product_tmpl_id.valuation = 'real_time' + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' self.product1.product_tmpl_id.invoice_policy = 'order' all_amls = self._dropship_product1() diff --git a/addons/stock_landed_costs/tests/common.py b/addons/stock_landed_costs/tests/common.py index 56087a3726c..4f30966a930 100644 --- a/addons/stock_landed_costs/tests/common.py +++ b/addons/stock_landed_costs/tests/common.py @@ -47,29 +47,26 @@ class TestStockLandedCostsCommon(AccountingTestCase): self.product_refrigerator = self.Product.create({ 'name': 'Refrigerator', 'type': 'product', - 'cost_method': 'fifo', - 'valuation': 'real_time', 'standard_price': 1.0, 'weight': 10, 'volume': 1, 'categ_id': self.categ_all.id}) + self.product_refrigerator.categ_id.property_cost_method = 'fifo' + self.product_refrigerator.categ_id.property_valuation = 'real_time' self.product_oven = self.Product.create({ 'name': 'Microwave Oven', 'type': 'product', - 'cost_method': 'fifo', - 'valuation': 'real_time', 'standard_price': 1.0, 'weight': 20, 'volume': 1.5, 'categ_id': self.categ_all.id}) + self.product_oven.categ_id.property_cost_method = 'fifo' + self.product_oven.categ_id.property_valuation = 'real_time' # Create service type product 1.Labour 2.Brokerage 3.Transportation 4.Packaging self.landed_cost = self._create_services('Landed Cost') self.brokerage_quantity = self._create_services('Brokerage Cost') self.transportation_weight = self._create_services('Transportation Cost') self.packaging_volume = self._create_services('Packaging Cost') - # Ensure the account properties exists. - self.ensure_account_property('property_stock_account_input') - self.ensure_account_property('property_stock_account_output') def _create_services(self, name): return self.Product.create({ diff --git a/addons/stock_landed_costs/tests/test_stock_landed_costs.py b/addons/stock_landed_costs/tests/test_stock_landed_costs.py index d2b4c70caab..9735d5eb696 100644 --- a/addons/stock_landed_costs/tests/test_stock_landed_costs.py +++ b/addons/stock_landed_costs/tests/test_stock_landed_costs.py @@ -20,23 +20,21 @@ class TestStockLandedCosts(TestStockLandedCostsCommon): # them for real_time valuation and fifo costing method product_landed_cost_1 = self.env['product.product'].create({ 'name': "LC product 1", - 'cost_method': 'fifo', - 'valuation': 'real_time', 'weight': 10, 'volume': 1, - 'property_stock_account_input': self.ref('stock_landed_costs.o_expense'), - 'property_stock_account_output': self.ref('stock_landed_costs.o_income'), }) + product_landed_cost_1.product_tmpl_id.categ_id.property_cost_method = 'fifo' + product_landed_cost_1.product_tmpl_id.categ_id.property_stock_account_input_categ_id = self.ref('stock_landed_costs.o_expense') + product_landed_cost_1.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.ref('stock_landed_costs.o_income') product_landed_cost_2 = self.env['product.product'].create({ 'name': "LC product 2", - 'cost_method': 'fifo', - 'valuation': 'real_time', 'weight': 20, 'volume': 1.5, - 'property_stock_account_input': self.ref('stock_landed_costs.o_expense'), - 'property_stock_account_output': self.ref('stock_landed_costs.o_income'), }) + product_landed_cost_2.product_tmpl_id.categ_id.property_cost_method = 'fifo' + product_landed_cost_2.product_tmpl_id.categ_id.property_stock_account_input_categ_id = self.ref('stock_landed_costs.o_expense') + product_landed_cost_2.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.ref('stock_landed_costs.o_income') picking_default_vals = self.env['stock.picking'].default_get(list(self.env['stock.picking'].fields_get())) diff --git a/addons/stock_landed_costs/tests/test_stock_landed_costs_rounding.py b/addons/stock_landed_costs/tests/test_stock_landed_costs_rounding.py index 2d7b820d512..916debcf046 100644 --- a/addons/stock_landed_costs/tests/test_stock_landed_costs_rounding.py +++ b/addons/stock_landed_costs/tests/test_stock_landed_costs_rounding.py @@ -25,21 +25,20 @@ class TestStockLandedCostsRounding(TestStockLandedCostsCommon): # valuation and real price costing method product_landed_cost_3 = self.env['product.product'].create({ 'name': "LC product 3", - 'cost_method': 'fifo', 'uom_id': product_uom_unit_round_1.id, - 'valuation': 'real_time', - 'property_stock_account_input': self.ref('stock_landed_costs.o_expense'), - 'property_stock_account_output': self.ref('stock_landed_costs.o_income'), }) + product_landed_cost_3.product_tmpl_id.categ_id.property_cost_method = 'fifo' + product_landed_cost_3.product_tmpl_id.categ_id.property_stock_account_input_categ_id = self.ref('stock_landed_costs.o_expense') + product_landed_cost_3.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.ref('stock_landed_costs.o_income') product_landed_cost_4 = self.env['product.product'].create({ 'name': "LC product 4", - 'cost_method': 'fifo', 'uom_id': product_uom_unit_round_1.id, - 'valuation': 'real_time', - 'property_stock_account_input': self.ref('stock_landed_costs.o_expense'), - 'property_stock_account_output': self.ref('stock_landed_costs.o_income'), }) + product_landed_cost_4.product_tmpl_id.categ_id.property_cost_method = 'fifo' + product_landed_cost_4.product_tmpl_id.categ_id.property_valuation = 'real_time' + product_landed_cost_4.product_tmpl_id.categ_id.property_stock_account_input_categ_id = self.ref('stock_landed_costs.o_expense') + product_landed_cost_4.product_tmpl_id.categ_id.property_stock_account_output_categ_id = self.ref('stock_landed_costs.o_income') picking_default_vals = self.env['stock.picking'].default_get(list(self.env['stock.picking'].fields_get()))