Skip to content

Commit

Permalink
[PR OCA#516] [IMP] helpdesk_mgmt: Add "close from portal" opt
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
houzefa-abba authored and PicchiSeba committed Oct 14, 2024
1 parent 99b3b92 commit fdc7e21
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 3 deletions.
4 changes: 3 additions & 1 deletion helpdesk_mgmt/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
2 changes: 1 addition & 1 deletion helpdesk_mgmt/controllers/myaccount.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
12 changes: 12 additions & 0 deletions helpdesk_mgmt/data/helpdesk_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
<field name="name">Done</field>
<field name="unattended">False</field>
<field name="closed">True</field>
<field name="close_from_portal">True</field>
<field name="fold">True</field>
<field name="mail_template_id" ref="helpdesk_mgmt.closed_ticket_template" />
<field name="company_id" />
Expand All @@ -127,6 +128,17 @@
<field name="name">Cancelled</field>
<field name="unattended">False</field>
<field name="closed">True</field>
<field name="close_from_portal">True</field>
<field name="fold">True</field>
<field name="mail_template_id" ref="helpdesk_mgmt.closed_ticket_template" />
<field name="company_id" />
</record>
<record id="helpdesk_ticket_stage_rejected" model="helpdesk.ticket.stage">
<field name="sequence">6</field>
<field name="name">Rejected</field>
<field name="unattended">False</field>
<field name="closed">True</field>
<field name="close_from_portal">False</field>
<field name="fold">True</field>
<field name="mail_template_id" ref="helpdesk_mgmt.closed_ticket_template" />
<field name="company_id" />
Expand Down
11 changes: 10 additions & 1 deletion helpdesk_mgmt/models/helpdesk_ticket_stage.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from odoo import fields, models
from odoo import api, fields, models


class HelpdeskTicketStage(models.Model):
Expand All @@ -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",
Expand All @@ -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
41 changes: 41 additions & 0 deletions helpdesk_mgmt/tests/test_helpdesk_portal.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/<ticket-id>
self.assertTrue(resp.headers["Location"].endswith(f"/my/ticket/{ticket.id}"))
return resp


@odoo.tests.tagged("post_install", "-at_install")
class TestHelpdeskPortal(TestHelpdeskPortalBase):
Expand Down Expand Up @@ -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)
4 changes: 4 additions & 0 deletions helpdesk_mgmt/views/helpdesk_ticket_stage_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
<field name="fold" />
<field name="active" invisible="1" />
<field name="closed" />
<field
name="close_from_portal"
attrs="{'invisible': [('closed', '=', False)]}"
/>
<field name="unattended" />
</group>
</group>
Expand Down

0 comments on commit fdc7e21

Please sign in to comment.