| 
						
						
							
								
							
						
						
					 | 
					@ -60,14 +60,11 @@ class AccountInvoice(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            total = 0.0 | 
					 | 
					 | 
					            total = 0.0 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            total_currency = 0.0 | 
					 | 
					 | 
					            total_currency = 0.0 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            currencies = set() | 
					 | 
					 | 
					            currencies = set() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            for line in move.line_ids: | 
					 | 
					 | 
					            for line in move.line_ids: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if line.currency_id: | 
					 | 
					 | 
					                if line.currency_id: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    currencies.add(line.currency_id) | 
					 | 
					 | 
					                    currencies.add(line.currency_id) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                if move.is_invoice(include_receipts=True): | 
					 | 
					 | 
					                if move.is_invoice(include_receipts=True): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    # === Invoices === | 
					 | 
					 | 
					                    # === Invoices === | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    if not line.exclude_from_invoice_tab: | 
					 | 
					 | 
					                    if not line.exclude_from_invoice_tab: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        # Untaxed amount. | 
					 | 
					 | 
					                        # Untaxed amount. | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        total_untaxed += line.balance | 
					 | 
					 | 
					                        total_untaxed += line.balance | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -80,7 +77,8 @@ class AccountInvoice(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        total_tax_currency += line.amount_currency | 
					 | 
					 | 
					                        total_tax_currency += line.amount_currency | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        total += line.balance | 
					 | 
					 | 
					                        total += line.balance | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        total_currency += line.amount_currency | 
					 | 
					 | 
					                        total_currency += line.amount_currency | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    elif line.account_id.user_type_id.type in ('receivable', 'payable'): | 
					 | 
					 | 
					                    elif line.account_id.user_type_id.type in ( | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                            'receivable', 'payable'): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        # Residual amount. | 
					 | 
					 | 
					                        # Residual amount. | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        total_to_pay += line.balance | 
					 | 
					 | 
					                        total_to_pay += line.balance | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        total_residual += line.amount_residual | 
					 | 
					 | 
					                        total_residual += line.amount_residual | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -96,51 +94,67 @@ class AccountInvoice(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            else: | 
					 | 
					 | 
					            else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                sign = -1 | 
					 | 
					 | 
					                sign = -1 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            if move.discount_type == 'percent': | 
					 | 
					 | 
					            if move.discount_type == 'percent': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                move.amount_discount = sum((line.quantity * line.price_unit * line.discount) / 100 for line in move.invoice_line_ids) | 
					 | 
					 | 
					                move.amount_discount = sum( | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    (line.quantity * line.price_unit * line.discount) / 100 for | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    line in move.invoice_line_ids) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            else: | 
					 | 
					 | 
					            else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                move.amount_discount = move.discount_rate | 
					 | 
					 | 
					                move.amount_discount = move.discount_rate | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            move.amount_untaxed = sign * (total_untaxed_currency if len(currencies) == 1 else total_untaxed) | 
					 | 
					 | 
					            move.amount_untaxed = sign * (total_untaxed_currency if len( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            move.amount_tax = sign * (total_tax_currency if len(currencies) == 1 else total_tax) | 
					 | 
					 | 
					                currencies) == 1 else total_untaxed) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            move.amount_total = sign * (total_currency if len(currencies) == 1 else total) | 
					 | 
					 | 
					            move.amount_tax = sign * ( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            move.amount_residual = -sign * (total_residual_currency if len(currencies) == 1 else total_residual) | 
					 | 
					 | 
					                total_tax_currency if len(currencies) == 1 else total_tax) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            move.amount_total = sign * ( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                total_currency if len(currencies) == 1 else total) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            move.amount_residual = -sign * (total_residual_currency if len( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                currencies) == 1 else total_residual) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            move.amount_untaxed_signed = -total_untaxed | 
					 | 
					 | 
					            move.amount_untaxed_signed = -total_untaxed | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            move.amount_tax_signed = -total_tax | 
					 | 
					 | 
					            move.amount_tax_signed = -total_tax | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					            move.amount_total_signed = abs(total) if move.move_type == 'entry' else -total | 
					 | 
					 | 
					            move.amount_total_signed = abs( | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                total) if move.move_type == 'entry' else -total | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            move.amount_residual_signed = total_residual | 
					 | 
					 | 
					            move.amount_residual_signed = total_residual | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
					            currency = len( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            currency = len(currencies) == 1 and currencies.pop() or move.company_id.currency_id | 
					 | 
					 | 
					                currencies) == 1 and currencies.pop() or move.company_id.currency_id | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					            # Compute 'payment_state'. | 
					 | 
					 | 
					            # Compute 'payment_state'. | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            new_pmt_state = 'not_paid' if move.move_type != 'entry' else False | 
					 | 
					 | 
					            new_pmt_state = 'not_paid' if move.move_type != 'entry' else False | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
					            if move.is_invoice( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            if move.is_invoice(include_receipts=True) and move.state == 'posted': | 
					 | 
					 | 
					                    include_receipts=True) and move.state == 'posted': | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                if currency.is_zero(move.amount_residual): | 
					 | 
					 | 
					                if currency.is_zero(move.amount_residual): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    if all(payment.is_matched for payment in move._get_reconciled_payments()): | 
					 | 
					 | 
					                    if all(payment.is_matched for payment in | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                           move._get_reconciled_payments()): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        new_pmt_state = 'paid' | 
					 | 
					 | 
					                        new_pmt_state = 'paid' | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    else: | 
					 | 
					 | 
					                    else: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                        new_pmt_state = move._get_invoice_in_payment_state() | 
					 | 
					 | 
					                        new_pmt_state = move._get_invoice_in_payment_state() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                elif currency.compare_amounts(total_to_pay, total_residual) != 0: | 
					 | 
					 | 
					                elif currency.compare_amounts(total_to_pay, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                              total_residual) != 0: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    new_pmt_state = 'partial' | 
					 | 
					 | 
					                    new_pmt_state = 'partial' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
					            if new_pmt_state == 'paid' and move.move_type in ( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					            if new_pmt_state == 'paid' and move.move_type in ('in_invoice', 'out_invoice', 'entry'): | 
					 | 
					 | 
					                    'in_invoice', 'out_invoice', 'entry'): | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					                reverse_type = move.move_type == 'in_invoice' and 'in_refund' or move.move_type == 'out_invoice' and 'out_refund' or 'entry' | 
					 | 
					 | 
					                reverse_type = move.move_type == 'in_invoice' and 'in_refund' or move.move_type == 'out_invoice' and 'out_refund' or 'entry' | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                reverse_moves = self.env['account.move'].search( | 
					 | 
					 | 
					                reverse_moves = self.env['account.move'].search( | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                    [('reversed_entry_id', '=', move.id), ('state', '=', 'posted'), ('move_type', '=', reverse_type)]) | 
					 | 
					 | 
					                    [('reversed_entry_id', '=', move.id), | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
					                     ('state', '=', 'posted'), | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                     ('move_type', '=', reverse_type)]) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                # We only set 'reversed' state in cas of 1 to 1 full reconciliation with a reverse entry; otherwise, we use the regular 'paid' state | 
					 | 
					 | 
					                # We only set 'reversed' state in cas of 1 to 1 full reconciliation with a reverse entry; otherwise, we use the regular 'paid' state | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                reverse_moves_full_recs = reverse_moves.mapped('line_ids.full_reconcile_id') | 
					 | 
					 | 
					                reverse_moves_full_recs = reverse_moves.mapped( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                if reverse_moves_full_recs.mapped('reconciled_line_ids.move_id').filtered(lambda x: x not in ( | 
					 | 
					 | 
					                    'line_ids.full_reconcile_id') | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                        reverse_moves + reverse_moves_full_recs.mapped('exchange_move_id'))) == move: | 
					 | 
					 | 
					                if reverse_moves_full_recs.mapped( | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                        'reconciled_line_ids.move_id').filtered( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                    lambda x: x not in ( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                            reverse_moves + reverse_moves_full_recs.mapped( | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                        'exchange_move_id'))) == move: | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    new_pmt_state = 'reversed' | 
					 | 
					 | 
					                    new_pmt_state = 'reversed' | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            move.payment_state = new_pmt_state | 
					 | 
					 | 
					            move.payment_state = new_pmt_state | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    discount_type = fields.Selection([('percent', 'Percentage'), ('amount', 'Amount')], string='Discount Type', | 
					 | 
					 | 
					    discount_type = fields.Selection( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					                                     readonly=True, states={'draft': [('readonly', False)]}, default='percent') | 
					 | 
					 | 
					        [('percent', 'Percentage'), ('amount', 'Amount')], | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					    discount_rate = fields.Float('Discount Amount', digits=(16, 2), readonly=True, | 
					 | 
					 | 
					        string='Discount Type', | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        readonly=True, states={'draft': [('readonly', False)]}, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        default='percent') | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    discount_rate = fields.Float('Discount Amount', digits=(16, 2), | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                 readonly=True, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                 states={'draft': [('readonly', False)]}) | 
					 | 
					 | 
					                                 states={'draft': [('readonly', False)]}) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    amount_discount = fields.Monetary(string='Discount', store=True, readonly=True, compute='_compute_amount', | 
					 | 
					 | 
					    amount_discount = fields.Monetary(string='Discount', store=True, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                                      readonly=True, compute='_compute_amount', | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                                      track_visibility='always') | 
					 | 
					 | 
					                                      track_visibility='always') | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    @api.onchange('discount_type', 'discount_rate', 'invoice_line_ids') | 
					 | 
					 | 
					    @api.onchange('discount_type', 'discount_rate', 'invoice_line_ids') | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -163,7 +177,6 @@ class AccountInvoice(models.Model): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                    line._onchange_price_subtotal() | 
					 | 
					 | 
					                    line._onchange_price_subtotal() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            inv._compute_invoice_taxes_by_group() | 
					 | 
					 | 
					            inv._compute_invoice_taxes_by_group() | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    # | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    def button_dummy(self): | 
					 | 
					 | 
					    def button_dummy(self): | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					        self.supply_rate() | 
					 | 
					 | 
					        self.supply_rate() | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					
  |