diff --git a/addons/sale/models/sale_order_line.py b/addons/sale/models/sale_order_line.py index b1d6c2fd2ff..cf8bef41355 100644 --- a/addons/sale/models/sale_order_line.py +++ b/addons/sale/models/sale_order_line.py @@ -973,13 +973,18 @@ class SaleOrderLine(models.Model): protected_fields = self._get_protected_fields() if 'done' in self.mapped('state') and any(f in values.keys() for f in protected_fields): protected_fields_modified = list(set(protected_fields) & set(values.keys())) - fields = self.env['ir.model.fields'].search([ + + if 'name' in protected_fields_modified and all(self.mapped('is_downpayment')): + protected_fields_modified.remove('name') + + fields = self.env['ir.model.fields'].sudo().search([ ('name', 'in', protected_fields_modified), ('model', '=', self._name) ]) - raise UserError( - _('It is forbidden to modify the following fields in a locked order:\n%s') - % '\n'.join(fields.mapped('field_description')) - ) + if fields: + raise UserError( + _('It is forbidden to modify the following fields in a locked order:\n%s') + % '\n'.join(fields.mapped('field_description')) + ) result = super().write(values) diff --git a/addons/sale/tests/test_sale_to_invoice.py b/addons/sale/tests/test_sale_to_invoice.py index 7fd395c334a..4313db875aa 100644 --- a/addons/sale/tests/test_sale_to_invoice.py +++ b/addons/sale/tests/test_sale_to_invoice.py @@ -129,6 +129,32 @@ class TestSaleToInvoice(TestSaleCommon): self.assertEqual(len(invoice.invoice_line_ids.filtered(lambda l: l.display_type == 'line_section' and l.name == "Down Payments")), 1, 'A single section for downpayments should be present') self.assertEqual(invoice.amount_total, self.sale_order.amount_total - sum(downpayment_line.mapped('price_unit')), 'Downpayment should be applied') + def test_downpayment_validation(self): + """ Test invoice for downpayment and check it can be validated + """ + # Lock the sale orders when confirmed + self.env.user.groups_id += self.env.ref('sale.group_auto_done_setting') + + # Confirm the SO + self.sale_order.action_confirm() + self._check_order_search(self.sale_order, [('invoice_ids', '=', False)], self.sale_order) + # Let's do an invoice for a deposit of 10% + downpayment = self.env['sale.advance.payment.inv'].with_context(self.context).create({ + 'advance_payment_method': 'percentage', + 'amount': 10, + 'deposit_account_id': self.company_data['default_account_revenue'].id + }) + downpayment.create_invoices() + self._check_order_search(self.sale_order, [('invoice_ids', '=', False)], self.env['sale.order']) + + # Update delivered quantity of SO lines + self.sol_serv_deliver.write({'qty_delivered': 4.0}) + self.sol_prod_deliver.write({'qty_delivered': 2.0}) + + # Validate invoice + self.sale_order.invoice_ids.action_post() + + def test_downpayment_percentage_tax_icl(self): """ Test invoice with a percentage downpayment and an included tax Check the total amount of invoice is correct and equal to a respective sale order's total amount