bemade-addons/fsm_visit_confirmation/controllers/main.py
2025-02-26 14:52:17 -05:00

149 lines
5.4 KiB
Python

# -*- coding: utf-8 -*-
import logging
import werkzeug
from odoo import http
from odoo.http import request
from odoo.tools.translate import _
from odoo.tools.misc import get_lang
from odoo.addons.portal.controllers.portal import CustomerPortal
from odoo.exceptions import AccessError, MissingError
_logger = logging.getLogger(__name__)
class CustomerPortalExtended(CustomerPortal):
"""Extend the customer portal controller to handle FSM visit confirmations."""
@http.route("/my/task/<int:task_id>", type="http", auth="public", website=True)
def portal_my_task(self, task_id, access_token=None, **kw):
"""Override to allow access with token for public users."""
try:
task_sudo = self._document_check_access(
"project.task", task_id, access_token
)
except (AccessError, MissingError):
return request.redirect("/my")
# Pass the task to the original method
return super(CustomerPortalExtended, self).portal_my_task(
task_id, access_token=access_token, **kw
)
@http.route(
"/my/fsm_confirmation/<string:token>/<string:action>",
type="http",
auth="public",
website=True,
)
def fsm_confirmation_action(self, token, action, **kwargs):
"""Custom landing page for FSM visit confirmations.
Args:
token: The access token for the task
action: Either 'approve' or 'change'
"""
if action not in ("approve", "change"):
raise werkzeug.exceptions.BadRequest(_("Invalid action"))
# Get the task using the token
task_sudo = self._get_task_by_token(token)
if not task_sudo:
return self._render_error_page(_("Task not found or invalid token"))
# If it's an approval, update the task state directly
if action == "approve":
try:
# Update task state to approved
task_sudo.sudo().write({"state": "03_approved"})
# Add a message to the chatter
task_sudo.sudo().message_post(
body=_("Visit approved by customer"),
message_type="comment",
subtype_xmlid="mail.mt_note",
)
# Always redirect to the task portal page with success message
return request.redirect(
"/my/task/%s?visit_confirmation_status=approved&access_token=%s"
% (task_sudo.id, token)
)
except Exception as e:
_logger.exception("Error approving task: %s", e)
return self._render_error_page(str(e))
# For change requests, redirect to the task portal page with change request form
return request.redirect(
"/my/task/%s?visit_confirmation_status=change&token=%s&access_token=%s"
% (task_sudo.id, token, token)
)
@http.route(
"/my/fsm_confirmation/submit_change",
type="http",
auth="public",
methods=["post"],
website=True,
csrf=True,
)
def fsm_confirmation_submit_change(self, **kwargs):
"""Handle the submission of change request form."""
token = kwargs.get("token")
feedback = kwargs.get("feedback", "")
if not token or not feedback:
return request.redirect("/my")
# Get the task using the token
task_sudo = self._get_task_by_token(token)
if not task_sudo:
return self._render_error_page(_("Task not found or invalid token"))
try:
# Update task state to changes requested
task_sudo.sudo().write({"state": "02_changes_requested"})
# Add the feedback as a message to the chatter
task_sudo.sudo().message_post(
body=_("Changes requested by customer: %s") % feedback,
message_type="comment",
subtype_xmlid="mail.mt_comment",
)
# Always redirect to the task portal page with success message
return request.redirect(
"/my/task/%s?visit_confirmation_status=change_submitted&access_token=%s"
% (task_sudo.id, token)
)
except Exception as e:
_logger.exception("Error submitting change request: %s", e)
return self._render_error_page(str(e))
def _get_task_by_token(self, token):
"""Get a task by its access token."""
# First try to find the task directly by token
task = request.env["project.task"].sudo().search([("access_token", "=", token)], limit=1)
if task:
return task
# If not found, try to find it through the rating token
# This is for backward compatibility with existing tokens in emails
rating = request.env["rating.rating"].sudo().search([("access_token", "=", token)], limit=1)
if rating and rating.res_model == "project.task":
task = request.env["project.task"].sudo().browse(rating.res_id)
if task.exists():
return task
return None
def _render_error_page(self, error_message):
"""Render an error page."""
return request.render(
"http_routing.http_error",
{
"status_code": "400",
"status_message": error_message,
},
)