From fdc7e21f259ab70df778fe07f48702e010f3bbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Houz=C3=A9fa=20Abbasbhay?= Date: Tue, 17 Jan 2023 11:35:21 +0100 Subject: [PATCH] [PR #516] [IMP] helpdesk_mgmt: Add "close from portal" opt * Ticket stage: Add a "close from portal" setting. * Portal form: Display ticket close buttons according to that setting. * Default stages: Add a "rejected" closed stage unavailable to portal. In the process: * Add portal close tests. * Protect against invalid target stage request in the controller. --- helpdesk_mgmt/controllers/main.py | 4 +- helpdesk_mgmt/controllers/myaccount.py | 2 +- helpdesk_mgmt/data/helpdesk_data.xml | 12 ++++++ helpdesk_mgmt/models/helpdesk_ticket_stage.py | 11 ++++- helpdesk_mgmt/tests/test_helpdesk_portal.py | 41 +++++++++++++++++++ .../views/helpdesk_ticket_stage_views.xml | 4 ++ 6 files changed, 71 insertions(+), 3 deletions(-) diff --git a/helpdesk_mgmt/controllers/main.py b/helpdesk_mgmt/controllers/main.py index f043bf930d..924d03e3f0 100644 --- a/helpdesk_mgmt/controllers/main.py +++ b/helpdesk_mgmt/controllers/main.py @@ -25,7 +25,9 @@ def support_ticket_close(self, **kw): .sudo() .search([("id", "=", values["ticket_id"])]) ) - ticket.stage_id = values.get("stage_id") + stage = http.request.env["helpdesk.ticket.stage"].browse(values.get("stage_id")) + if stage.close_from_portal: # protect against invalid target stage request + ticket.stage_id = values.get("stage_id") return werkzeug.utils.redirect("/my/ticket/" + str(ticket.id)) diff --git a/helpdesk_mgmt/controllers/myaccount.py b/helpdesk_mgmt/controllers/myaccount.py index c51cc67120..74e0e674c0 100644 --- a/helpdesk_mgmt/controllers/myaccount.py +++ b/helpdesk_mgmt/controllers/myaccount.py @@ -182,7 +182,7 @@ def portal_my_ticket(self, ticket_id, access_token=None, **kw): def _ticket_get_page_view_values(self, ticket, access_token, **kwargs): closed_stages = request.env["helpdesk.ticket.stage"].search( - [("closed", "=", True)] + [("close_from_portal", "=", True)] ) files = ( request.env["ir.attachment"] diff --git a/helpdesk_mgmt/data/helpdesk_data.xml b/helpdesk_mgmt/data/helpdesk_data.xml index 5fc5aad88d..760aa670f2 100644 --- a/helpdesk_mgmt/data/helpdesk_data.xml +++ b/helpdesk_mgmt/data/helpdesk_data.xml @@ -118,6 +118,7 @@ Done False True + True True @@ -127,6 +128,17 @@ Cancelled False True + True + True + + + + + 6 + Rejected + False + True + False True diff --git a/helpdesk_mgmt/models/helpdesk_ticket_stage.py b/helpdesk_mgmt/models/helpdesk_ticket_stage.py index 96255c72f2..2a31fabae5 100644 --- a/helpdesk_mgmt/models/helpdesk_ticket_stage.py +++ b/helpdesk_mgmt/models/helpdesk_ticket_stage.py @@ -1,4 +1,4 @@ -from odoo import fields, models +from odoo import api, fields, models class HelpdeskTicketStage(models.Model): @@ -12,6 +12,10 @@ class HelpdeskTicketStage(models.Model): active = fields.Boolean(default=True) unattended = fields.Boolean(string="Unattended") closed = fields.Boolean(string="Closed") + close_from_portal = fields.Boolean( + help="Display button in portal ticket form to allow closing ticket " + "with this stage as target." + ) mail_template_id = fields.Many2one( comodel_name="mail.template", string="Email Template", @@ -31,3 +35,8 @@ class HelpdeskTicketStage(models.Model): string="Company", default=lambda self: self.env.company, ) + + @api.onchange("closed") + def _onchange_closed(self): + if not self.closed: + self.close_from_portal = False diff --git a/helpdesk_mgmt/tests/test_helpdesk_portal.py b/helpdesk_mgmt/tests/test_helpdesk_portal.py index 4509ec8483..ef7692e478 100644 --- a/helpdesk_mgmt/tests/test_helpdesk_portal.py +++ b/helpdesk_mgmt/tests/test_helpdesk_portal.py @@ -69,6 +69,26 @@ def _submit_ticket(self, files=None, **values): resp = self.url_open("/submitted/ticket", data=data, files=files) self.assertEqual(resp.status_code, 200) + def _count_close_buttons(self, resp) -> int: + """Count close buttons in a form by counting forms with that target.""" + return resp.text.count('action="/ticket/close"') + + def _call_close_ticket(self, ticket, stage): + """Call /ticket/close with the specified target stage, check redirect.""" + resp = self.url_open( + "/ticket/close", + data={ + "csrf_token": http.WebRequest.csrf_token(self), + "stage_id": stage.id, + "ticket_id": ticket.id, + }, + allow_redirects=False, + ) + self.assertEqual(resp.status_code, 302) + self.assertTrue(resp.is_redirect) # http://127.0.0.1:8069/my/ticket/ + self.assertTrue(resp.headers["Location"].endswith(f"/my/ticket/{ticket.id}")) + return resp + @odoo.tests.tagged("post_install", "-at_install") class TestHelpdeskPortal(TestHelpdeskPortalBase): @@ -124,3 +144,24 @@ def test_submit_ticket_with_attachments(self): # check that both files are public (access_token is set) self.assertTrue(attachment_ids[0].access_token) self.assertTrue(attachment_ids[1].access_token) + + def test_close_ticket(self): + """Close a ticket from the portal.""" + self.assertFalse(self.portal_ticket.closed) + self.authenticate("test-portal", "test-portal") + resp = self.url_open(f"/my/ticket/{self.portal_ticket.id}") + self.assertEqual(self._count_close_buttons(resp), 2) # 2 close stages in data/ + stage = self.env.ref("helpdesk_mgmt.helpdesk_ticket_stage_done") + self._call_close_ticket(self.portal_ticket, stage) + self.assertTrue(self.portal_ticket.closed) + self.assertEqual(self.portal_ticket.stage_id, stage) + resp = self.url_open(f"/my/ticket/{self.portal_ticket.id}") + self.assertEqual(self._count_close_buttons(resp), 0) # no close buttons now + + def test_close_ticket_invalid_stage(self): + """Attempt to close a ticket from the portal with an invalid target stage.""" + self.authenticate("test-portal", "test-portal") + stage = self.env.ref("helpdesk_mgmt.helpdesk_ticket_stage_awaiting") + self._call_close_ticket(self.portal_ticket, stage) + self.assertFalse(self.portal_ticket.closed) + self.assertNotEqual(self.portal_ticket.stage_id, stage) diff --git a/helpdesk_mgmt/views/helpdesk_ticket_stage_views.xml b/helpdesk_mgmt/views/helpdesk_ticket_stage_views.xml index aee2ae90ac..b71e9fe981 100644 --- a/helpdesk_mgmt/views/helpdesk_ticket_stage_views.xml +++ b/helpdesk_mgmt/views/helpdesk_ticket_stage_views.xml @@ -49,6 +49,10 @@ +