# Copyright 2017 Akretion (http://www.akretion.com) # Copyright 2020 Camptocamp SA # Mourad EL HADJ MIMOUNE # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). from datetime import datetime from odoo.exceptions import ValidationError from odoo.tests.common import TransactionCase from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT class TestPurchaseException(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() # Useful models cls.PurchaseOrder = cls.env["purchase.order"] cls.PurchaseOrderLine = cls.env["purchase.order.line"] cls.partner_id = cls.env.ref("base.res_partner_1") cls.product_id_1 = cls.env.ref("product.product_product_6") cls.product_id_2 = cls.env.ref("product.product_product_7") cls.product_id_3 = cls.env.ref("product.product_product_7") cls.date_planned = datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT) cls.purchase_exception_confirm = cls.env["purchase.exception.confirm"] cls.exception_noemail = cls.env.ref("purchase_exception.po_excep_no_email") cls.exception_qtycheck = cls.env.ref("purchase_exception.pol_excep_qty_check") cls.po_vals = { "partner_id": cls.partner_id.id, "order_line": [ ( 0, 0, { "name": cls.product_id_1.name, "product_id": cls.product_id_1.id, "product_qty": 5.0, "product_uom": cls.product_id_1.uom_po_id.id, "price_unit": 500.0, "date_planned": cls.date_planned, }, ), ( 0, 0, { "name": cls.product_id_2.name, "product_id": cls.product_id_2.id, "product_qty": 5.0, "product_uom": cls.product_id_2.uom_po_id.id, "price_unit": 250.0, "date_planned": cls.date_planned, }, ), ], } cls.po_vals2 = { "partner_id": cls.partner_id.id, "order_line": [ ( 0, 0, { "name": cls.product_id_3.name, "product_id": cls.product_id_3.id, "product_qty": -1.0, "product_uom": cls.product_id_3.uom_po_id.id, "price_unit": 20.0, "date_planned": cls.date_planned, }, ), ], } def test_purchase_order_exception(self): self.exception_noemail.active = True self.exception_qtycheck.active = True self.partner_id.email = False self.po = self.PurchaseOrder.create(self.po_vals.copy()) # confirm quotation self.po.button_confirm() self.assertEqual(self.po.state, "draft") # test all draft po self.po2 = self.PurchaseOrder.create(self.po_vals.copy()) self.PurchaseOrder.test_all_draft_orders() self.assertEqual(self.po2.state, "draft") # Set ignore_exception flag (Done after ignore is selected at wizard) self.po.ignore_exception = True self.po.button_confirm() self.assertEqual(self.po.state, "purchase") # Add a order line to test after PO is confirmed field_onchange = self.PurchaseOrder._onchange_spec() self.assertEqual(field_onchange.get("order_line"), "1") self.po3New = self.PurchaseOrder.new(self.po_vals.copy()) self.po3New.ignore_exception = True self.po3New.state = "purchase" self.po.write( { "order_line": [ ( 0, 0, { "name": self.product_id_3.name, "product_id": self.product_id_3.id, "product_qty": 2, "product_uom": self.product_id_3.uom_id.id, "price_unit": 30, "date_planned": self.date_planned, }, ) ] } ) # Set ignore exception True (Done manually by user) self.po.ignore_exception = True self.po.button_cancel() self.po.button_draft() self.assertEqual(self.po.state, "draft") self.assertTrue(not self.po.ignore_exception) self.po.button_confirm() self.assertTrue(self.po.state, "to approve") # Simulation the opening of the wizard purchase_exception_confirm and # set ignore_exception to True po_except_confirm = self.purchase_exception_confirm.with_context( active_id=self.po.id, active_ids=[self.po.id], active_model=self.po._name, ).create({"ignore": True}) po_except_confirm.action_confirm() def test_exception_qtycheck(self): # No allow ignoring exceptions if the "is_blocking" field is checked self.exception_qtycheck.active = True self.exception_qtycheck.is_blocking = True self.po = self.PurchaseOrder.create(self.po_vals2.copy()) po_except_confirm = self.purchase_exception_confirm.with_context( **{ "active_id": self.po.id, "active_ids": [self.po.id], "active_model": self.po._name, } ).create({"ignore": True}) po_except_confirm.exception_ids = self.exception_qtycheck po_except_confirm.action_confirm() def test_exception_no_validation_for_unlock(self): self.partner_id.email = False po = self.PurchaseOrder.create(self.po_vals.copy()) po.button_confirm() self.assertEqual(po.state, "purchase") po.button_done() self.assertEqual(po.state, "done") exception = self.env.ref("purchase_exception.po_excep_no_email") exception.active = True with self.assertRaises(ValidationError): po.write({"state": "purchase"}) po.button_unlock() self.assertEqual(po.state, "purchase")