diff --git a/addons/purchase_stock/models/stock_move.py b/addons/purchase_stock/models/stock_move.py index e67617e18c0..2dade39cbbc 100644 --- a/addons/purchase_stock/models/stock_move.py +++ b/addons/purchase_stock/models/stock_move.py @@ -48,8 +48,8 @@ class StockMove(models.Model): if self.state == 'done': received_qty -= self.product_uom._compute_quantity(self.quantity_done, line.product_uom, rounding_method='HALF-UP') if float_compare(line.qty_invoiced, received_qty, precision_rounding=line.product_uom.rounding) > 0: - move_layer = line.move_ids.stock_valuation_layer_ids - invoiced_layer = line.invoice_lines.stock_valuation_layer_ids + move_layer = line.move_ids.sudo().stock_valuation_layer_ids + invoiced_layer = line.sudo().invoice_lines.stock_valuation_layer_ids # value on valuation layer is in company's currency, while value on invoice line is in order's currency receipt_value = 0 if move_layer: @@ -60,7 +60,7 @@ class StockMove(models.Model): l.value, order.currency_id, order.company_id, l.create_date, round=False))) invoiced_value = 0 invoiced_qty = 0 - for invoice_line in line.invoice_lines: + for invoice_line in line.sudo().invoice_lines: if invoice_line.tax_ids: invoiced_value += invoice_line.tax_ids.with_context(round=False).compute_all( invoice_line.price_unit, currency=invoice_line.currency_id, quantity=invoice_line.quantity)['total_void'] diff --git a/addons/purchase_stock/tests/test_average_price.py b/addons/purchase_stock/tests/test_average_price.py index 6295ced532e..27f1301b36e 100644 --- a/addons/purchase_stock/tests/test_average_price.py +++ b/addons/purchase_stock/tests/test_average_price.py @@ -131,3 +131,41 @@ class TestAveragePrice(ValuationReconciliationTestCommon): self.assertEqual(product_cable_management_box.qty_available, 20.5, 'Reception of purchase order in grams leads to wrong quantity in stock') self.assertEqual(round(product_cable_management_box.standard_price, 2), 78.05, 'Standard price as average price of third reception with other UoM incorrect! Got %s instead of 78.05' % (round(product_cable_management_box.standard_price, 2))) + + def test_inventory_user_svl_access(self): + """ Test to check if Inventory/User is able to validate a + transfer when the product has been invoiced already """ + + avco_product = self.env['product.product'].create({ + 'name': 'Average Ice Cream', + 'type': 'product', + 'categ_id': self.stock_account_product_categ.id, + 'purchase_method': 'purchase', + }) + avco_product.categ_id.property_cost_method = 'average' + + purchase_order = self.env['purchase.order'].create({ + 'partner_id': self.partner_a.id, + 'order_line': [(0, 0, { + 'product_id': avco_product.id, + 'product_qty': 1.0, + })] + }) + + purchase_order.button_confirm() + purchase_order.action_create_invoice() + bill = purchase_order.invoice_ids[0] + + bill.invoice_date = time.strftime('%Y-%m-%d') + bill.invoice_line_ids[0].quantity = 1.0 + bill.action_post() + + self.assertEqual(purchase_order.order_line[0].qty_invoiced, 1.0, 'QTY invoiced should have been set to 1 on the purchase order line') + + picking = purchase_order.picking_ids[0] + picking.action_set_quantities_to_reservation() + # clear cash to ensure access rights verification + self.env.invalidate_all() + picking.with_user(self.res_users_stock_user).button_validate() + + self.assertEqual(picking.state, 'done', 'Transfer should be in the DONE state') diff --git a/addons/stock_account/tests/test_anglo_saxon_valuation_reconciliation_common.py b/addons/stock_account/tests/test_anglo_saxon_valuation_reconciliation_common.py index a65a49c5fff..7661df56f65 100644 --- a/addons/stock_account/tests/test_anglo_saxon_valuation_reconciliation_common.py +++ b/addons/stock_account/tests/test_anglo_saxon_valuation_reconciliation_common.py @@ -48,6 +48,13 @@ class ValuationReconciliationTestCommon(AccountTestInvoicingCommon): 'uom_po_id': uom_unit.id, }) + cls.res_users_stock_user = cls.env['res.users'].create({ + 'name': "Inventory User", + 'login': "su", + 'email': "stockuser@yourcompany.com", + 'groups_id': [(6, 0, [cls.env.ref('stock.group_stock_user').id])], + }) + @classmethod def setup_company_data(cls, company_name, chart_template=None, **kwargs): company_data = super().setup_company_data(company_name, chart_template=chart_template, **kwargs)