04/07 updated password reset, ticket templates, and satisfaction survey
This commit is contained in:
+55
-2
@@ -10,10 +10,11 @@ from app import db
|
||||
from app.models import (Ticket, Comment, Attachment, Notification,
|
||||
TicketStatus, TicketPriority, TicketCategory,
|
||||
User, UserRole, KnowledgeBase, TicketLink, CannedResponse,
|
||||
KBFeedback)
|
||||
KBFeedback, TicketTemplate, TicketSatisfaction)
|
||||
from app.services.notification_service import (
|
||||
notify_new_ticket, notify_status_change,
|
||||
notify_comment_added, notify_assignment,
|
||||
send_satisfaction_survey,
|
||||
)
|
||||
from app.services.log_service import log_action, log_ticket_history
|
||||
from app.services.sla_service import clear_sla_notification
|
||||
@@ -187,8 +188,12 @@ def create_ticket():
|
||||
flash(f'Ticket {ticket.ticket_number} created successfully!', 'success')
|
||||
return redirect(url_for('tickets.ticket_detail', ticket_id=ticket.id))
|
||||
|
||||
templates = TicketTemplate.query.filter_by(is_active=True).order_by(
|
||||
TicketTemplate.sort_order, TicketTemplate.name
|
||||
).all()
|
||||
return render_template('tickets/create.html',
|
||||
categories=_categories(), priorities=_priorities())
|
||||
categories=_categories(), priorities=_priorities(),
|
||||
templates=templates)
|
||||
|
||||
|
||||
# ─── Create Ticket on Behalf of Employee (IT Staff Only) ─────────────────────
|
||||
@@ -530,6 +535,8 @@ def update_ticket(ticket_id):
|
||||
|
||||
if new_status != old_status:
|
||||
notify_status_change(ticket, old_status, current_user)
|
||||
if new_status == TicketStatus.RESOLVED:
|
||||
send_satisfaction_survey(ticket)
|
||||
|
||||
flash('Ticket updated successfully.', 'success')
|
||||
return redirect(url_for('tickets.ticket_detail', ticket_id=ticket.id))
|
||||
@@ -917,6 +924,52 @@ def kb_feedback(article_id):
|
||||
})
|
||||
|
||||
|
||||
# ─── Ticket Survey ────────────────────────────────────────────────────────────
|
||||
|
||||
@tickets_bp.route('/survey/<token>', methods=['GET', 'POST'])
|
||||
def ticket_survey(token):
|
||||
"""Public survey endpoint — no login required.
|
||||
|
||||
The employee clicks a star in the resolution email which hits this route
|
||||
with ?rating=N. A GET with rating pre-selects the star; POST submits
|
||||
the full form (rating + optional comment).
|
||||
"""
|
||||
survey = TicketSatisfaction.query.filter_by(survey_token=token).first()
|
||||
if not survey:
|
||||
return render_template('tickets/survey_invalid.html'), 404
|
||||
|
||||
if survey.submitted:
|
||||
return render_template('tickets/survey_done.html', survey=survey)
|
||||
|
||||
# Star-click from email: rating is in query string → auto-submit
|
||||
quick_rating = request.args.get('rating', type=int)
|
||||
|
||||
if request.method == 'POST' or quick_rating:
|
||||
rating = quick_rating or request.form.get('rating', type=int)
|
||||
comment = request.form.get('comment', '').strip()
|
||||
|
||||
if not rating or not (1 <= rating <= 5):
|
||||
flash('Please select a rating between 1 and 5 stars.', 'danger')
|
||||
return render_template('tickets/survey.html', survey=survey)
|
||||
|
||||
survey.rating = rating
|
||||
survey.comment = comment or None
|
||||
survey.submitted_at = datetime.utcnow()
|
||||
log_action(
|
||||
survey.user_id, 'survey_submit', 'ticket', survey.ticket_id,
|
||||
f'rating={rating}'
|
||||
)
|
||||
db.session.commit()
|
||||
logger.info(
|
||||
f'[SURVEY SUBMIT] ticket_id={survey.ticket_id} '
|
||||
f'user_id={survey.user_id} rating={rating}'
|
||||
)
|
||||
return render_template('tickets/survey_done.html', survey=survey)
|
||||
|
||||
return render_template('tickets/survey.html', survey=survey,
|
||||
quick_rating=quick_rating)
|
||||
|
||||
|
||||
# ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||
|
||||
def _sla_due_date(priority: str) -> 'datetime':
|
||||
|
||||
Reference in New Issue
Block a user