| 
						
						
							
								
							
						
						
					 | 
					@ -19,7 +19,11 @@ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					#    If not, see <http://www.gnu.org/licenses/>. | 
					 | 
					 | 
					#    If not, see <http://www.gnu.org/licenses/>. | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					# | 
					 | 
					 | 
					# | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					################################################################################ | 
					 | 
					 | 
					################################################################################ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					from odoo import fields, models | 
					 | 
					 | 
					from odoo import fields, models, _ | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					from odoo.tools.float_utils import float_is_zero | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					from collections import defaultdict | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					from odoo.exceptions import UserError | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					class StockLandedCost(models.Model): | 
					 | 
					 | 
					class StockLandedCost(models.Model): | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -52,6 +56,38 @@ class StockLandedCost(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                    'once, it will hide the button and make' | 
					 | 
					 | 
					                                    'once, it will hide the button and make' | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                    'it invisible.') | 
					 | 
					 | 
					                                    'it invisible.') | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    def calculate_avco_price(self): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        for cost in self: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            cost = cost.with_company(cost.company_id) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            cost_to_add_byproduct = defaultdict(lambda: 0.0) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            for line in cost.valuation_adjustment_lines.filtered(lambda line: line.move_id): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                remaining_qty = sum(line.move_id.stock_valuation_layer_ids.mapped('remaining_qty')) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                # Prorate the value at what's still in stock | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                move_qty = line.move_id.product_uom._compute_quantity(line.move_id.quantity, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                                                      line.move_id.product_id.uom_id) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                cost_to_add = (remaining_qty / move_qty) * line.additional_landed_cost | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                # Update the AVCO/FIFO | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                product = line.move_id.product_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                if product.cost_method in ['average', 'fifo']: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    cost_to_add_byproduct[product] -= cost_to_add | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                # Products with manual inventory valuation are ignored because they do not need to create journal entries. | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                if product.valuation != "real_time": | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    continue | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                # `remaining_qty` is negative if the move is out and delivered proudcts that were not | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                # in stock. | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                qty_out = 0 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                # batch standard price computation avoid recompute quantity_svl at each iteration | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                products = self.env['product.product'].browse(p.id for p in cost_to_add_byproduct.keys()).with_company( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    cost.company_id) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                for product in products:  # iterate on recordset to prefetch efficiently quantity_svl | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    if not float_is_zero(product.quantity_svl, precision_rounding=product.uom_id.rounding): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                        product.sudo().with_context(disable_auto_svl=True).standard_price += cost_to_add_byproduct[ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                                                                                 product] / product.quantity_svl | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    def action_landed_cost_cancel(self): | 
					 | 
					 | 
					    def action_landed_cost_cancel(self): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        """Cancels the landed cost record by deleting its associated | 
					 | 
					 | 
					        """Cancels the landed cost record by deleting its associated | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        accounting entries, stock valuation, and changes state to 'cancelled'. | 
					 | 
					 | 
					        accounting entries, stock valuation, and changes state to 'cancelled'. | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -64,18 +100,8 @@ class StockLandedCost(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    lambda line: line.move_id): | 
					 | 
					 | 
					                    lambda line: line.move_id): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                product = line.move_id.product_id | 
					 | 
					 | 
					                product = line.move_id.product_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if product.cost_method == 'average': | 
					 | 
					 | 
					                if product.cost_method == 'average': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    original_price = product.standard_price | 
					 | 
					 | 
					                    self.calculate_avco_price() | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    new_price = product.standard_price - line.additional_landed_cost | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                    product.write({'standard_price': new_price}) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    stock_valuation_layer = self.env['stock.valuation.layer'] \ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        .search([('product_id', '=', product.id), | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                 ('description', '=', f'Product value manually ' | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                                      f'modified (from {original_price} to {new_price})')], | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                limit=1) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if stock_valuation_layer: | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.account_move_id.button_draft() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.account_move_id.sudo().unlink() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.sudo().unlink() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if rec.account_move_id: | 
					 | 
					 | 
					            if rec.account_move_id: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                account_id = rec.account_move_id | 
					 | 
					 | 
					                account_id = rec.account_move_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                account_move_ids = account_id.line_ids | 
					 | 
					 | 
					                account_move_ids = account_id.line_ids | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -102,18 +128,8 @@ class StockLandedCost(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    lambda line: line.move_id): | 
					 | 
					 | 
					                    lambda line: line.move_id): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                product = line.move_id.product_id | 
					 | 
					 | 
					                product = line.move_id.product_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if product.cost_method == 'average': | 
					 | 
					 | 
					                if product.cost_method == 'average': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    original_price = product.standard_price | 
					 | 
					 | 
					                    self.calculate_avco_price() | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    new_price = product.standard_price - line.additional_landed_cost | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                    product.write({'standard_price': new_price}) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    stock_valuation_layer = self.env['stock.valuation.layer'] \ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        .search([('product_id', '=', product.id), | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                 ('description', '=', f'Product value manually ' | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                                      f'modified (from {original_price} to {new_price})')], | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                limit=1) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if stock_valuation_layer: | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.account_move_id.button_draft() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.account_move_id.sudo().unlink() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.sudo().unlink() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if rec.account_move_id: | 
					 | 
					 | 
					            if rec.account_move_id: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                account_id = rec.account_move_id | 
					 | 
					 | 
					                account_id = rec.account_move_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                account_move_ids = account_id.line_ids | 
					 | 
					 | 
					                account_move_ids = account_id.line_ids | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -140,18 +156,7 @@ class StockLandedCost(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    lambda line: line.move_id): | 
					 | 
					 | 
					                    lambda line: line.move_id): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                product = line.move_id.product_id | 
					 | 
					 | 
					                product = line.move_id.product_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if product.cost_method == 'average': | 
					 | 
					 | 
					                if product.cost_method == 'average': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    original_price = product.standard_price | 
					 | 
					 | 
					                    self.calculate_avco_price() | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                    new_price = product.standard_price - line.additional_landed_cost | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    product.write({'standard_price': new_price}) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    stock_valuation_layer = self.env['stock.valuation.layer'] \ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        .search([('product_id', '=', product.id), | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                 ('description', '=', f'Product value manually ' | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                                      f'modified (from {original_price} to {new_price})')], | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                limit=1) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if stock_valuation_layer: | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.account_move_id.button_draft() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.account_move_id.sudo().unlink() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.sudo().unlink() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            if rec.account_move_id: | 
					 | 
					 | 
					            if rec.account_move_id: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                account_id = rec.account_move_id | 
					 | 
					 | 
					                account_id = rec.account_move_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                account_move_ids = account_id.line_ids | 
					 | 
					 | 
					                account_move_ids = account_id.line_ids | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -167,6 +172,7 @@ class StockLandedCost(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            rec.write({'state': 'cancel'}) | 
					 | 
					 | 
					            rec.write({'state': 'cancel'}) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            rec.unlink() | 
					 | 
					 | 
					            rec.unlink() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    def action_landed_cost_cancel_form(self): | 
					 | 
					 | 
					    def action_landed_cost_cancel_form(self): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        """Cancels the landed cost record and deletes its associated | 
					 | 
					 | 
					        """Cancels the landed cost record and deletes its associated | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        accounting entries and stock valuation. It also creates two entries | 
					 | 
					 | 
					        accounting entries and stock valuation. It also creates two entries | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -188,18 +194,8 @@ class StockLandedCost(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    lambda line: line.move_id): | 
					 | 
					 | 
					                    lambda line: line.move_id): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                product = line.move_id.product_id | 
					 | 
					 | 
					                product = line.move_id.product_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if product.cost_method == 'average': | 
					 | 
					 | 
					                if product.cost_method == 'average': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    original_price = product.standard_price | 
					 | 
					 | 
					                    self.calculate_avco_price() | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    new_price = product.standard_price - line.additional_landed_cost | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					                    product.write({'standard_price': new_price}) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    stock_valuation_layer = self.env['stock.valuation.layer'] \ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        .search([('product_id', '=', product.id), | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                 ('description', '=', f'Product value manually ' | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                                      f'modified (from {original_price} to {new_price})')], | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                limit=1) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if stock_valuation_layer: | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.account_move_id.button_draft() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.account_move_id.sudo().unlink() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        stock_valuation_layer.sudo().unlink() | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					        if self.account_move_id: | 
					 | 
					 | 
					        if self.account_move_id: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            account_id = self.account_move_id | 
					 | 
					 | 
					            account_id = self.account_move_id | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            account_move_ids = account_id.line_ids | 
					 | 
					 | 
					            account_move_ids = account_id.line_ids | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -212,6 +208,7 @@ class StockLandedCost(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self.valuation_adjustment_lines.unlink() | 
					 | 
					 | 
					            self.valuation_adjustment_lines.unlink() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if self.stock_valuation_layer_ids: | 
					 | 
					 | 
					        if self.stock_valuation_layer_ids: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            self.sudo().stock_valuation_layer_ids.unlink() | 
					 | 
					 | 
					            self.sudo().stock_valuation_layer_ids.unlink() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        landed_mode = self.env['ir.config_parameter'].sudo().get_param( | 
					 | 
					 | 
					        landed_mode = self.env['ir.config_parameter'].sudo().get_param( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            'cancel_landed_cost_odoo.land_cost_cancel_modes') | 
					 | 
					 | 
					            'cancel_landed_cost_odoo.land_cost_cancel_modes') | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        if landed_mode == 'cancel': | 
					 | 
					 | 
					        if landed_mode == 'cancel': | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					
  |