diff --git a/app/routes/support.py b/app/routes/support.py index 26955b1..994e4e0 100644 --- a/app/routes/support.py +++ b/app/routes/support.py @@ -1,13 +1,11 @@ import os import logging -import threading from flask import (Blueprint, render_template, redirect, url_for, flash, request, current_app, jsonify, abort) from flask_login import login_required, current_user -from flask_mail import Message -from app import db, mail +from app import db from app.models.support import SupportTicket, SupportTicketReply from app.models.user import User from app.models.facility import Facility @@ -15,6 +13,7 @@ from app.utils.decorators import supervisor_required from app.utils.scope import get_customer_scope from app.utils.audit import log_action, ACTION_CREATE, ACTION_UPDATE from app.utils.time_utils import now_eastern +from app.utils.notifications import notify bp = Blueprint('support', __name__, url_prefix='/support') logger = logging.getLogger(__name__) @@ -167,54 +166,28 @@ def submit_ticket(): def _notify_admins_new_ticket(ticket): - """Send email notification to all active admin users in a background thread.""" + """Create in-app notifications and send emails to all active admin users.""" admins = User.query.filter_by(role='admin', active=True).all() if not admins: return - base_url = current_app.config.get('APP_BASE_URL', '').rstrip('/') - ticket_url = f'{base_url}{url_for("support.admin_ticket_detail", ticket_id=ticket.id)}' - facility_label = ticket.facility.name if ticket.facility else 'N/A' customer_label = ticket.customer.display_name if ticket.customer else 'Unknown' + facility_label = ticket.facility.name if ticket.facility else 'N/A' + link = url_for('support.admin_ticket_detail', ticket_id=ticket.id) + title = f'New support ticket #{ticket.id} from {customer_label}' + body = (f'Subject: {ticket.subject}\n' + f'Facility: {facility_label}\n\n' + f'{ticket.body[:300]}{"…" if len(ticket.body) > 300 else ""}') - subject_line = f'[JQC Support] New ticket #{ticket.id}: {ticket.subject}' - html_body = f"""\ - - - -

New Support Ticket #{ticket.id}

-

From: {customer_label}

-

Facility: {facility_label}

-

Subject: {ticket.subject}

-
-

{ticket.body}

-
-

- - View & Reply - -

-

JQC Support System — automated notification.

- -""" - - def _send(): - try: - with current_app.app_context(): - for admin in admins: - msg = Message( - subject = subject_line, - recipients = [admin.email], - html = html_body, - sender = current_app.config.get('MAIL_DEFAULT_SENDER'), - ) - mail.send(msg) - except Exception as exc: - logger.error('SUPPORT | email notification failed: %s', exc) - - threading.Thread(target=_send, daemon=True).start() + for admin in admins: + notify( + recipient = admin, + title = title, + body = body, + link = link, + send_email = True, + ) + db.session.commit() # ── Admin: ticket list ──────────────────────────────────────────────────────── @@ -293,46 +266,21 @@ def admin_ticket_detail(ticket_id): def _notify_customer_reply(ticket, reply): - """Email the customer when an admin replies to their ticket.""" - if not ticket.customer or not ticket.customer.email: + """Create an in-app notification and send an email to the customer.""" + if not ticket.customer: return - base_url = current_app.config.get('APP_BASE_URL', '').rstrip('/') - chat_url = f'{base_url}{url_for("support.chat")}' admin_name = reply.author.display_name if reply.author else 'Support Team' + title = f'Reply to your support request #{ticket.id}' + body = (f'{admin_name} replied to your ticket "{ticket.subject}":\n\n' + f'{reply.body[:400]}{"…" if len(reply.body) > 400 else ""}') + link = url_for('support.chat') - html_body = f"""\ - - - -

Reply to Your Support Request

-

Hi {ticket.customer.display_name},

-

{admin_name} replied to your support ticket - #{ticket.id}: {ticket.subject}:

-
{reply.body}
-

- - View Support Chat - -

-

JQC Support System — automated notification.

- -""" - - def _send(): - try: - with current_app.app_context(): - msg = Message( - subject = f'[JQC Support] Reply to #{ticket.id}: {ticket.subject}', - recipients = [ticket.customer.email], - html = html_body, - sender = current_app.config.get('MAIL_DEFAULT_SENDER'), - ) - mail.send(msg) - except Exception as exc: - logger.error('SUPPORT | customer reply email failed: %s', exc) - - threading.Thread(target=_send, daemon=True).start() + notify( + recipient = ticket.customer, + title = title, + body = body, + link = link, + send_email = True, + ) + db.session.commit()