From 75191f8ac44103163dbcaa5cf16f67365d5b2127 Mon Sep 17 00:00:00 2001 From: William Henrotin Date: Tue, 24 Mar 2020 12:18:03 +0000 Subject: [PATCH] [FIX] purchase: ensure all vendor bills are gathered from purchase order The 'vendor bills' stat button on purchase order, once clicked, will have a specific behavior depending on the invoice count : 0 : open a new invoice with pre filled fields (not saved yet) 1 : open the form view of the invoice 2+: open the list view of the invoices. Before this commit, the invoice count was computed with an environment on the current user. That means a record rule could make the invoice count lower than the real count and so give an unwanted behavior. Ex: create a new invoice even if there is already one created because the user cannot see the other people's invoices. After this commit, the action_view_invoice with make an explicit read() in database to fill the cache with all the purchase order's invoices and make sure the count is the real one. Task : 2206969 closes odoo/odoo#48274 X-original-commit: e3101d92187946b2bd539e05956e4e83cd9c9097 Signed-off-by: Simon Lejeune (sle) --- addons/purchase/models/purchase.py | 4 +++ addons/purchase/tests/test_access_rights.py | 39 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py index 3fe6f3389f6..545f928b327 100644 --- a/addons/purchase/models/purchase.py +++ b/addons/purchase/models/purchase.py @@ -416,6 +416,10 @@ class PurchaseOrder(models.Model): 'default_company_id': self.company_id.id, 'default_purchase_id': self.id, } + # Invoice_ids may be filtered depending on the user. To ensure we get all + # invoices related to the purchase order, we read them in sudo to fill the + # cache. + self.sudo()._read(['invoice_ids']) # choose the view_mode accordingly if len(self.invoice_ids) > 1 and not create_bill: result['domain'] = "[('id', 'in', " + str(self.invoice_ids.ids) + ")]" diff --git a/addons/purchase/tests/test_access_rights.py b/addons/purchase/tests/test_access_rights.py index dc6fa486c48..af431a9c71c 100644 --- a/addons/purchase/tests/test_access_rights.py +++ b/addons/purchase/tests/test_access_rights.py @@ -95,3 +95,42 @@ class TestPurchaseInvoice(SavepointCase): purchase_order_user1 = purchase_order_user1.save() vendor_bill_user1 = Form(vendor_bill_user2.with_user(self.purchase_user)) vendor_bill_user1 = vendor_bill_user1.save() + + def test_read_purchase_order_2(self): + """ Check that a 2 purchase users with open the vendor bill the same + way even with a 'own documents only' record rule. """ + + # edit the account.move record rule for purchase user in order to ensure + # a user can only see his own invoices + rule = self.env.ref('purchase.purchase_user_account_move_rule') + rule.domain_force = "['&', ('move_type', 'in', ('in_invoice', 'in_refund', 'in_receipt')), ('invoice_user_id', '=', user.id)]" + + # create a purchase and make a vendor bill from it as purchase user 2 + purchase_user_2 = self.purchase_user.copy({ + 'name': 'Purchase user 2', + 'login': 'purchaseUser2', + 'email': 'pu2@odoo.com', + }) + + purchase_order_form = Form(self.env['purchase.order'].with_user(purchase_user_2)) + purchase_order_form.partner_id = self.vendor + with purchase_order_form.order_line.new() as line: + line.name = self.product.name + line.product_id = self.product + line.product_qty = 4 + line.price_unit = 5 + + purchase_order_user2 = purchase_order_form.save() + action = purchase_order_user2.with_user(purchase_user_2).action_view_invoice() + invoice_form = Form(self.env['account.move'].with_user(purchase_user_2).with_context(action['context'])) + vendor_bill_user2 = invoice_form.save() + + # check user 1 cannot read the invoice + with self.assertRaises(AccessError): + Form(vendor_bill_user2.with_user(self.purchase_user)) + + # Check that calling 'action_view_invoice' return the same action despite the record rule + action_user_1 = purchase_order_user2.with_user(self.purchase_user).action_view_invoice() + purchase_order_user2.invalidate_cache() + action_user_2 = purchase_order_user2.with_user(purchase_user_2).action_view_invoice() + self.assertEqual(action_user_1, action_user_2)