[FIX] sale: fix down payment validation for a locked SO

Sale module has setting `Lock Confirmed Sales`, which particularly doesn't allow
order line modification. However, the application does modify special lines for
Down payment: it changes name from `Down Payment: 09 2001 (Draft)` to `Down
Payment`.

Fix it by excluding down payment lines from the constrain.

Also, this commit fixes access error when user doesn't have read access to
`ir.model.fields` model.

STEPS:

* Create user with only BILLING (group) access in accounting App.
* Now Logged in with Admin user
* Create any SO, Confirm, Validate the delivery order.
* Create an invoice with Down payment (%) as 10.
* Now do Logged in with BILLING user
* Open the draft invoice which gets created by SO.
* Confirm the invoice.

opw-3134083

closes odoo/odoo#110788

X-original-commit: b9cd677b7e20579b9fb0d59a2d24ae5d2e11fb72
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Signed-off-by: Ivan Elizaryev (iel) <iel@odoo.com>
This commit is contained in:
Ivan Yelizariev
2023-01-24 10:20:53 +01:00
parent 95ce7a3003
commit 4f35a7ee0b
2 changed files with 36 additions and 5 deletions
+10 -5
View File
@@ -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)
+26
View File
@@ -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