From f118a777d30b90e47c98ced537040fd753dcd12f Mon Sep 17 00:00:00 2001 From: metatroncubeswdev Date: Mon, 31 Aug 2026 15:25:50 -0400 Subject: [PATCH] Complete workplace ticket interactions --- .../mcs_corporate_website/controllers/main.py | 56 ++++++++++++ .../models/support_ticket.py | 4 + .../static/src/scss/corporate_website.scss | 91 +++++++++++++++++++ .../views/support_ticket_views.xml | 2 + .../views/workplace_templates.xml | 6 +- 5 files changed, 156 insertions(+), 3 deletions(-) diff --git a/addons/mcs_corporate_website/controllers/main.py b/addons/mcs_corporate_website/controllers/main.py index 7867c53..4c63428 100644 --- a/addons/mcs_corporate_website/controllers/main.py +++ b/addons/mcs_corporate_website/controllers/main.py @@ -1,3 +1,5 @@ +import base64 + from odoo import fields, http from odoo.http import request @@ -86,6 +88,7 @@ class McsCorporateWebsite(http.Controller): "status_key": ticket.state, "customer": ticket.partner_id.name or ticket.customer_name, "assigned_team": dict(ticket._fields["service_area"].selection).get(ticket.service_area), + "assigned_agent": ticket.user_id.name or "", "created": ticket.create_date, "updated": ticket.write_date, "updated_label": fields.Datetime.to_string(ticket.write_date) if ticket.write_date else "", @@ -286,6 +289,41 @@ class McsCorporateWebsite(http.Controller): messages = ticket.message_ids.sorted(lambda item: item.date) return self._workplace_render("mcs_corporate_website.workplace_ticket_detail", {"ticket": ticket, "messages": messages}) + @http.route(["/workplace/tickets//reply"], type="http", auth="user", website=True, methods=["POST"]) + def workplace_ticket_reply(self, ticket_id, **post): + role = self._role() + ticket = request.env["mcs.support.ticket"].sudo().search(self._ticket_domain(role) + [("id", "=", ticket_id)], limit=1) + if not ticket: + return request.not_found() + body = (post.get("reply") or "").strip() + attachments = self._attach_uploaded_files(ticket) + if body or attachments: + ticket.message_post( + body=body or "Attachment added.", + attachment_ids=attachments.ids, + message_type="comment", + subtype_xmlid="mail.mt_comment", + ) + return request.redirect("/workplace/tickets/%s" % ticket.id) + + @http.route(["/workplace/tickets//close"], type="http", auth="user", website=True, methods=["POST"]) + def workplace_ticket_close(self, ticket_id, **post): + role = self._role() + ticket = request.env["mcs.support.ticket"].sudo().search(self._ticket_domain(role) + [("id", "=", ticket_id)], limit=1) + if not ticket: + return request.not_found() + ticket.action_close() + return request.redirect("/workplace/tickets/%s" % ticket.id) + + @http.route(["/workplace/tickets//reopen"], type="http", auth="user", website=True, methods=["POST"]) + def workplace_ticket_reopen(self, ticket_id, **post): + role = self._role() + ticket = request.env["mcs.support.ticket"].sudo().search(self._ticket_domain(role) + [("id", "=", ticket_id)], limit=1) + if not ticket: + return request.not_found() + ticket.action_reopen() + return request.redirect("/workplace/tickets/%s" % ticket.id) + @http.route(["/workplace/knowledge"], type="http", auth="user", website=True) def workplace_knowledge(self, **kwargs): return self._workplace_render("mcs_corporate_website.workplace_knowledge", {"articles": self._knowledge(self._role())}) @@ -311,8 +349,26 @@ class McsCorporateWebsite(http.Controller): "description": (post.get("description") or "").strip(), } ) + self._attach_uploaded_files(ticket) return request.redirect("/support/thanks/%s" % ticket.access_token) + def _attach_uploaded_files(self, ticket): + Attachment = request.env["ir.attachment"].sudo() + attachments = Attachment.browse() + for upload in request.httprequest.files.getlist("attachments"): + if not upload or not upload.filename: + continue + attachments |= Attachment.create( + { + "name": upload.filename, + "datas": base64.b64encode(upload.stream.read()), + "res_model": "mcs.support.ticket", + "res_id": ticket.id, + "mimetype": upload.mimetype, + } + ) + return attachments + @http.route(["/support/thanks/"], type="http", auth="public", website=True) def support_thanks(self, token, **kwargs): ticket = request.env["mcs.support.ticket"].sudo().search([("access_token", "=", token)], limit=1) diff --git a/addons/mcs_corporate_website/models/support_ticket.py b/addons/mcs_corporate_website/models/support_ticket.py index c1c7469..3140446 100644 --- a/addons/mcs_corporate_website/models/support_ticket.py +++ b/addons/mcs_corporate_website/models/support_ticket.py @@ -15,6 +15,7 @@ class McsSupportTicket(models.Model): customer_email = fields.Char(required=True) customer_phone = fields.Char() partner_id = fields.Many2one("res.partner", string="Customer", tracking=True) + user_id = fields.Many2one("res.users", string="Assigned Agent", tracking=True) company_id = fields.Many2one( "res.company", default=lambda self: self.env.company, @@ -95,3 +96,6 @@ class McsSupportTicket(models.Model): def action_close(self): self.write({"state": "closed"}) + + def action_reopen(self): + self.write({"state": "in_progress"}) diff --git a/addons/mcs_corporate_website/static/src/scss/corporate_website.scss b/addons/mcs_corporate_website/static/src/scss/corporate_website.scss index 21e81c8..cf501f6 100644 --- a/addons/mcs_corporate_website/static/src/scss/corporate_website.scss +++ b/addons/mcs_corporate_website/static/src/scss/corporate_website.scss @@ -671,6 +671,11 @@ box-shadow: 0 10px 24px rgba(28, 78, 216, 0.2); } +.mcs-wp-btn--secondary { + background: #334155; + box-shadow: none; +} + .mcs-table-wrap { width: 100%; overflow-x: auto; @@ -796,6 +801,18 @@ } } +.mcs-upload { + border: 1px dashed #B8C1D1; + border-radius: 14px; + padding: 16px; + background: #F8FAFC; + + span { + color: var(--text-secondary); + font-weight: 700; + } +} + .mcs-search { width: min(420px, 100%); border: 1px solid var(--border); @@ -803,6 +820,80 @@ padding: 12px 14px; } +body:has(form[action="/web/login"]) { + background: #F6F7F9; + + #wrapwrap { + min-height: 100vh; + background: + linear-gradient(90deg, #101114 0%, #101114 48%, #F6F7F9 48%, #F6F7F9 100%); + } + + main { + min-height: calc(100vh - 76px); + display: grid; + place-items: center; + padding: 48px 24px; + } + + main::before { + content: "Your workplace. Connected.\\A Attendance, support and collaboration in one place."; + white-space: pre-line; + position: fixed; + left: 8vw; + top: 38vh; + max-width: 440px; + color: #fff; + font-size: 3.1rem; + line-height: 1.05; + font-weight: 820; + letter-spacing: 0; + } + + form[action="/web/login"] { + width: min(430px, 100%); + margin-left: 42vw; + padding: 34px; + border: 1px solid #E6E8EC; + border-radius: 14px; + background: #fff; + box-shadow: 0 24px 70px rgba(17, 24, 39, 0.14); + + .form-control { + min-height: 46px; + border-radius: 10px; + } + + .btn-primary { + width: 100%; + min-height: 46px; + border-radius: 10px; + background: #1C4ED8; + border-color: #1C4ED8; + font-weight: 800; + } + } +} + +@media (max-width: 991.98px) { + body:has(form[action="/web/login"]) { + #wrapwrap { + background: #F6F7F9; + } + + main::before { + position: static; + color: #17181B; + font-size: 2.2rem; + margin-bottom: 22px; + } + + form[action="/web/login"] { + margin-left: 0; + } + } +} + .mcs-timeline { display: grid; gap: 12px; diff --git a/addons/mcs_corporate_website/views/support_ticket_views.xml b/addons/mcs_corporate_website/views/support_ticket_views.xml index 3395732..540c2da 100644 --- a/addons/mcs_corporate_website/views/support_ticket_views.xml +++ b/addons/mcs_corporate_website/views/support_ticket_views.xml @@ -39,6 +39,7 @@ + @@ -66,6 +67,7 @@ + diff --git a/addons/mcs_corporate_website/views/workplace_templates.xml b/addons/mcs_corporate_website/views/workplace_templates.xml index 4df6593..c4565d5 100644 --- a/addons/mcs_corporate_website/views/workplace_templates.xml +++ b/addons/mcs_corporate_website/views/workplace_templates.xml @@ -196,7 +196,7 @@