Skip to content
This repository has been archived by the owner on Sep 7, 2020. It is now read-only.

Autoresolve for "expired" tickets #139

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,30 @@ def seed():
student = User(name=real_name, email=email)
db.session.add(student)
db.session.commit()

delta = datetime.timedelta(minutes=random.randrange(0, 30))
ticket = Ticket(
user=student,
status=TicketStatus.pending,
created=datetime.datetime.utcnow() - delta,
assignment=random.choice(['Hog', 'Scheme']),
description=random.choice(['', 'SyntaxError on Line 5']),
question=random.randrange(1, 6),
location=random.choice(['109 Morgan', '247 Cory']),
)
if i % 2 == 0:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is really necessary. If we do want to keep this, you should create the ticket outside the if and then update the fields for certain values.

ticket = Ticket(
user=student,
status=TicketStatus.pending,
created=datetime.datetime.utcnow() - delta,
assignment=random.choice(['Hog', 'Scheme']),
description=random.choice(['', 'SyntaxError on Line 5']),
question=random.randrange(1, 6),
location=random.choice(['109 Morgan', '247 Cory']),
)
else:
ticket = Ticket(
user=student,
status=TicketStatus.assigned,
created=datetime.datetime.utcnow() - delta,
updated= datetime.datetime.utcnow(),
assignment=random.choice(['Hog', 'Scheme']),
description=random.choice(['', 'SyntaxError on Line 5']),
question=random.randrange(1, 6),
location=random.choice(['109 Morgan', '247 Cory']),
helper_id = 61
)

db.session.add(ticket)
db.session.commit()

Expand Down
4 changes: 2 additions & 2 deletions oh_queue/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def short_name(self):
return first_name.rsplit('@')[0]
return first_name

TicketStatus = enum.Enum('TicketStatus', 'pending assigned resolved deleted')
TicketStatus = enum.Enum('TicketStatus', 'pending assigned resolved deleted autoresolved autodeleted')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think a separate "autoresolved" category is necessary. I don't see any situation where we'd need to be able to distinguish resolved vs autoresolved tickets (and if we really need to, we could always inspect the events)

I'd lean toward the same for autodeleted tickets, but I'm more open to a separate category there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, I'll not add any categories here.


class Ticket(db.Model):
"""Represents an ticket in the queue. A student submits a ticket and receives
Expand Down Expand Up @@ -87,7 +87,7 @@ def by_status(cls, status=None):

TicketEventType = enum.Enum(
'TicketEventType',
'create assign unassign resolve delete describe',
'create assign unassign resolve delete describe autoresolve autodelete',
)

class TicketEvent(db.Model):
Expand Down
49 changes: 47 additions & 2 deletions oh_queue/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,24 @@ def ticket_json(ticket):
}

def emit_event(ticket, event_type):
ticket_event = TicketEvent(
if event_type == TicketEventType.autodelete:
ticket_event = TicketEvent(
event_type=event_type,
ticket=ticket,
user=current_user,
user_id=0 # assuming ids start @ 1, 0 signifies admin/autodelete
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems hacky. I'd prefer to change TicketEvent to allow the user to be nullable (though that would require a migration)

)
elif event_type == TicketEventType.autoresolve:
ticket_event = TicketEvent(
event_type=event_type,
ticket=ticket,
user_id=ticket.helper_id
)
else:
ticket_event = TicketEvent(
event_type=event_type,
ticket=ticket,
user=current_user,
)
db.session.add(ticket_event)
db.session.commit()
socketio.emit('event', {
Expand Down Expand Up @@ -131,6 +144,21 @@ def disconnect():

@socketio.on('refresh')
def refresh(ticket_ids):
""" Cuts out tickets that have elapsed time beyond cuttoff in minutes"""
pending_cutoff = 180
assigned_cutoff = 30

pending_cutoff_time = datetime.datetime.utcnow() - datetime.timedelta(minutes = pending_cutoff)
assigned_cutoff_time = datetime.datetime.utcnow() - datetime.timedelta(minutes = assigned_cutoff)

exp_pending_tickets = Ticket.query.filter(Ticket.created < pending_cutoff_time, Ticket.status == TicketStatus.pending).all()
exp_pending_ticket_ids = [tick.id for tick in exp_pending_tickets]
autodelete(exp_pending_ticket_ids)

exp_assigned_tickets = Ticket.query.filter(Ticket.updated < assigned_cutoff_time, Ticket.status == TicketStatus.assigned).all()
exp_assigned_ticket_ids = [tick.id for tick in exp_assigned_tickets]
autoresolve(exp_assigned_ticket_ids)

tickets = Ticket.query.filter(Ticket.id.in_(ticket_ids)).all()
return {
'tickets': [ticket_json(ticket) for ticket in tickets],
Expand Down Expand Up @@ -204,6 +232,14 @@ def delete(ticket_ids):
emit_event(ticket, TicketEventType.delete)
db.session.commit()

@socketio.on('autodelete')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be triggered on the server-side, so I don't think the socket event listener is necessary.

def autodelete(ticket_ids):
tickets = get_tickets(ticket_ids)
for ticket in tickets:
ticket.status = TicketStatus.autodeleted
emit_event(ticket, TicketEventType.autodelete)
db.session.commit()

@socketio.on('resolve')
@logged_in
def resolve(ticket_ids):
Expand All @@ -216,6 +252,15 @@ def resolve(ticket_ids):
db.session.commit()
return get_next_ticket()

@socketio.on('resolve')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about autodelete above (also, this shouldn't have the same socket event as the existing resolve function.

def autoresolve(ticket_ids):
tickets = get_tickets(ticket_ids)
for ticket in tickets:
ticket.status = TicketStatus.autoresolved
emit_event(ticket, TicketEventType.autoresolve)
db.session.commit()
#return get_next_ticket()

@socketio.on('assign')
@is_staff
def assign(ticket_ids):
Expand Down