# -*- coding: utf-8 -*- from odoo.tests.common import TransactionCase from odoo import fields from datetime import timedelta class TestStockBackdate(TransactionCase): def setUp(self): super(TestStockBackdate, self).setUp() # Find a suitable company self.company = self.env.company # Create a product with type 'consu' (Odoo 19 physical product type) category = self.env['product.category'].search([], limit=1) self.product = self.env['product.product'].create({ 'name': 'Test Backdated Product', 'type': 'consu', 'categ_id': category.id, }) # Try to set automated valuation. If accounts are missing, it might raise/warn, so handle it. try: self.product.categ_id.write({ 'property_valuation': 'real_time', 'property_cost_method': 'average', }) except Exception: pass # Fallback to standard valuation if real_time fails due to accounts configuration self.stock_location = self.env['stock.location'].search([('usage', '=', 'internal')], limit=1) def test_scrap_backdate(self): """Test that backdated scrap order works and backdates all valuation/moves""" backdate = fields.Datetime.now() - timedelta(days=5) scrap = self.env['stock.scrap'].create({ 'product_id': self.product.id, 'product_uom_id': self.product.uom_id.id, 'scrap_qty': 5.0, 'location_id': self.stock_location.id, 'date_done': backdate, }) # Verify initial state self.assertEqual(scrap.state, 'draft') self.assertEqual(scrap.date_done, backdate) # Confirm scrap scrap.action_validate() self.assertEqual(scrap.state, 'done') # Verify stock move backdated move = scrap.move_ids self.assertTrue(move, "Stock move should be created for the scrap order") self.assertEqual(move.date, backdate, "Stock move date should match the scrap backdate") # Verify stock move line backdated move_line = move.move_line_ids self.assertTrue(move_line, "Stock move line should be created") self.assertEqual(move_line.date, backdate, "Stock move line date should match the scrap backdate") # Verify product value backdated product_value = self.env['product.value'].search([('move_id', '=', move.id)], limit=1) if product_value: self.assertEqual(product_value.date, backdate, "Product value date should match the scrap backdate") self.assertEqual(product_value.create_date, backdate, "Product value create_date should match the scrap backdate") # Verify account move backdated if exists if move.account_move_id: self.assertEqual(move.account_move_id.date, backdate.date(), "Account move date should match the scrap backdate date") for aml in move.account_move_id.line_ids: self.assertEqual(aml.date, backdate.date(), "Account move line date should match the scrap backdate date") def test_inventory_backdate(self): """Test that backdated inventory adjustment works and backdates all valuation/moves""" backdate = fields.Datetime.now() - timedelta(days=10) # Create backdated inventory adjustment inventory = self.env['stock.inventory.backdate'].create({ 'backdate_datetime': backdate, 'location_id': self.stock_location.id, }) # Add inventory line line = self.env['stock.inventory.backdate.line'].create({ 'inventory_id': inventory.id, 'product_id': self.product.id, 'theoretical_qty': 0.0, 'counted_qty': 50.0, }) self.assertEqual(line.difference_qty, 50.0) # Validate the adjustment inventory.action_validate() self.assertEqual(inventory.state, 'done') # Find created moves move = self.env['stock.move'].search([ ('product_id', '=', self.product.id), ('is_inventory', '=', True), ('origin', '=', inventory.name) ], limit=1) self.assertTrue(move, "Stock move should be created for backdated inventory adjustment") self.assertEqual(move.date, backdate, "Stock move date should match the adjustment backdate") # Verify stock move line backdated move_line = move.move_line_ids self.assertTrue(move_line, "Stock move line should be created") self.assertEqual(move_line.date, backdate, "Stock move line date should match the adjustment backdate") # Verify product value backdated product_value = self.env['product.value'].search([('move_id', '=', move.id)], limit=1) if product_value: self.assertEqual(product_value.date, backdate, "Product value date should match the adjustment backdate") self.assertEqual(product_value.create_date, backdate, "Product value create_date should match the adjustment backdate") # Verify account move backdated if exists if move.account_move_id: self.assertEqual(move.account_move_id.date, backdate.date(), "Account move date should match the adjustment backdate date") for aml in move.account_move_id.line_ids: self.assertEqual(aml.date, backdate.date(), "Account move line date should match the adjustment backdate date")