TICKET:928 use correct role in session request notification email
- Legacy-Id: 5802
This commit is contained in:
parent
613746fceb
commit
45ec7a97a1
|
@ -15,7 +15,7 @@ from ietf.ietfauth.decorators import has_role
|
|||
from ietf.utils.mail import send_mail
|
||||
from ietf.meeting.models import Meeting, Session, Constraint
|
||||
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.name.models import SessionStatusName, ConstraintName
|
||||
|
||||
from forms import *
|
||||
|
@ -50,7 +50,7 @@ def get_initial_session(sessions):
|
|||
initial = {}
|
||||
# even if there are three sessions requested, the old form has 2 in this field
|
||||
initial['num_session'] = sessions.count() if sessions.count() <= 2 else 2
|
||||
|
||||
|
||||
# accessing these foreign key fields throw errors if they are unset so we
|
||||
# need to catch these
|
||||
initial['length_session1'] = str(sessions[0].requested_duration.seconds)
|
||||
|
@ -65,7 +65,7 @@ def get_initial_session(sessions):
|
|||
initial['conflict3'] = ' '.join([ c.target.acronym for c in conflicts.filter(name__slug='conflic3') ])
|
||||
initial['comments'] = sessions[0].comments
|
||||
return initial
|
||||
|
||||
|
||||
def get_lock_message():
|
||||
'''
|
||||
Returns the message to display to non-secretariat users when the tool is locked.
|
||||
|
@ -84,6 +84,19 @@ def get_meeting():
|
|||
'''
|
||||
return Meeting.objects.filter(type='ietf').order_by('-date')[0]
|
||||
|
||||
def get_requester_text(person,group):
|
||||
'''
|
||||
This function takes a Person object and a Group object and returns the text to use in the
|
||||
session request notification email, ie. Joe Smith, a Chair of the ancp working group
|
||||
'''
|
||||
roles = group.role_set.filter(name__in=('chair','secr'),person=person)
|
||||
if roles:
|
||||
return '%s, a %s of the %s working group' % (person, roles[0].name, group.acronym)
|
||||
if group.parent.role_set.filter(name='ad',person=person):
|
||||
return '%s, a %s Area Director' % (person, group.parent.acronym.upper())
|
||||
if person.role_set.filter(name='secr',group__acronym='secretariat'):
|
||||
return '%s, on behalf of the %s working group' % (person, group.acronym)
|
||||
|
||||
def save_conflicts(group, meeting, conflicts, name):
|
||||
'''
|
||||
This function takes a Group, Meeting a string which is a list of Groups acronyms (conflicts),
|
||||
|
@ -93,7 +106,7 @@ def save_conflicts(group, meeting, conflicts, name):
|
|||
acronyms = conflicts.replace(',',' ').split()
|
||||
for acronym in acronyms:
|
||||
target = Group.objects.get(acronym=acronym)
|
||||
|
||||
|
||||
constraint = Constraint(source=group,
|
||||
target=target,
|
||||
meeting=meeting,
|
||||
|
@ -111,7 +124,7 @@ def send_notification(group,meeting,login,session,action):
|
|||
from_email = ('"IETF Meeting Session Request Tool"','session_request_developers@ietf.org')
|
||||
subject = '%s - New Meeting Session Request for IETF %s' % (group.acronym, meeting.number)
|
||||
template = 'sreq/session_request_notification.txt'
|
||||
|
||||
|
||||
# send email
|
||||
context = {}
|
||||
context['session'] = session
|
||||
|
@ -119,12 +132,13 @@ def send_notification(group,meeting,login,session,action):
|
|||
context['meeting'] = meeting
|
||||
context['login'] = login
|
||||
context['header'] = 'A new'
|
||||
|
||||
context['requester'] = get_requester_text(login,group)
|
||||
|
||||
# update overrides
|
||||
if action == 'update':
|
||||
subject = '%s - Update to a Meeting Session Request for IETF %s' % (group.acronym, meeting.number)
|
||||
context['header'] = 'An update to a'
|
||||
|
||||
|
||||
# if third session requested approval is required
|
||||
# change headers TO=ADs, CC=session-request, submitter and cochairs
|
||||
if session.get('length_session3',None):
|
||||
|
@ -164,11 +178,11 @@ def approve(request, acronym):
|
|||
meeting = get_meeting()
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
session = Session.objects.get(meeting=meeting,group=group,status='apprw')
|
||||
|
||||
|
||||
if has_role(request.user,'Secretariat') or group.parent.role_set.filter(name='ad',person=request.user.get_profile()):
|
||||
session.status = SessionStatusName.objects.get(slug='appr')
|
||||
session.save()
|
||||
|
||||
|
||||
messages.success(request, 'Third session approved')
|
||||
url = reverse('sessions_view', kwargs={'acronym':acronym})
|
||||
return HttpResponseRedirect(url)
|
||||
|
@ -184,27 +198,27 @@ def cancel(request, acronym):
|
|||
This view cancels a session request and sends a notification.
|
||||
To cancel, or withdraw the request set status = deleted.
|
||||
"canceled" status is used by the secretariat.
|
||||
|
||||
|
||||
NOTE: this function can also be called after a session has been
|
||||
scheduled during the period when the session request tool is
|
||||
scheduled during the period when the session request tool is
|
||||
reopened. In this case be sure to clear the timeslot assignment as well.
|
||||
'''
|
||||
meeting = get_meeting()
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
sessions = Session.objects.filter(meeting=meeting,group=group).order_by('id')
|
||||
login = request.user.get_profile()
|
||||
|
||||
|
||||
# delete conflicts
|
||||
Constraint.objects.filter(meeting=meeting,source=group).delete()
|
||||
|
||||
|
||||
# mark sessions as deleted
|
||||
for session in sessions:
|
||||
session.status_id = 'deleted'
|
||||
session.save()
|
||||
|
||||
|
||||
# clear schedule assignments if already scheduled
|
||||
session.scheduledsession_set.all().delete()
|
||||
|
||||
|
||||
# send notifitcation
|
||||
to_email = SESSION_REQUEST_EMAIL
|
||||
cc_list = get_cc_list(group, login)
|
||||
|
@ -214,7 +228,7 @@ def cancel(request, acronym):
|
|||
{'login':login,
|
||||
'group':group,
|
||||
'meeting':meeting}, cc=cc_list)
|
||||
|
||||
|
||||
messages.success(request, 'The %s Session Request has been canceled' % group.acronym)
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
@ -231,23 +245,23 @@ def confirm(request, acronym):
|
|||
meeting = get_meeting()
|
||||
group = get_object_or_404(Group,acronym=acronym)
|
||||
login = request.user.get_profile()
|
||||
|
||||
|
||||
if request.method == 'POST':
|
||||
# clear http session data
|
||||
del request.session['session_form']
|
||||
|
||||
|
||||
button_text = request.POST.get('submit', '')
|
||||
if button_text == 'Cancel':
|
||||
messages.success(request, 'Session Request has been canceled')
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
# delete any existing session records with status = canceled or notmeet
|
||||
Session.objects.filter(group=group,meeting=meeting,status__in=('canceled','notmeet')).delete()
|
||||
|
||||
|
||||
# create new session records
|
||||
count = 0
|
||||
# lenth_session2 and length_session3 fields might be disabled by javascript and so
|
||||
# lenth_session2 and length_session3 fields might be disabled by javascript and so
|
||||
# wouldn't appear in form data
|
||||
for duration in (form.get('length_session1',None),form.get('length_session2',None),form.get('length_session3',None)):
|
||||
count += 1
|
||||
|
@ -262,30 +276,30 @@ def confirm(request, acronym):
|
|||
comments=form['comments'],
|
||||
status=SessionStatusName.objects.get(slug=slug))
|
||||
new_session.save()
|
||||
|
||||
|
||||
# write constraint records
|
||||
save_conflicts(group,meeting,form['conflict1'],'conflict')
|
||||
save_conflicts(group,meeting,form['conflict2'],'conflic2')
|
||||
save_conflicts(group,meeting,form['conflict3'],'conflic3')
|
||||
|
||||
|
||||
# deprecated in new schema
|
||||
# log activity
|
||||
#add_session_activity(group,'New session was requested',meeting,user)
|
||||
|
||||
|
||||
# clear not meeting
|
||||
Session.objects.filter(group=group,meeting=meeting,status='notmeet').delete()
|
||||
|
||||
|
||||
# send notification
|
||||
send_notification(group,meeting,login,form,'new')
|
||||
|
||||
|
||||
status_text = 'IETF Agenda to be scheduled'
|
||||
messages.success(request, 'Your request has been sent to %s' % status_text)
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
# GET logic
|
||||
session_conflicts = session_conflicts_as_string(group, meeting)
|
||||
|
||||
|
||||
return render_to_response('sreq/confirm.html', {
|
||||
'session': form,
|
||||
'group': group,
|
||||
|
@ -294,7 +308,7 @@ def confirm(request, acronym):
|
|||
)
|
||||
|
||||
@check_permissions
|
||||
def edit(request, acronym):
|
||||
def edit(request, acronym):
|
||||
'''
|
||||
This view allows the user to edit details of the session request
|
||||
'''
|
||||
|
@ -305,13 +319,13 @@ def edit(request, acronym):
|
|||
initial = get_initial_session(sessions)
|
||||
session_conflicts = session_conflicts_as_string(group, meeting)
|
||||
login = request.user.get_profile()
|
||||
|
||||
|
||||
if request.method == 'POST':
|
||||
button_text = request.POST.get('submit', '')
|
||||
if button_text == 'Cancel':
|
||||
url = reverse('sessions_view', kwargs={'acronym':acronym})
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
form = SessionForm(request.POST,initial=initial)
|
||||
if form.is_valid():
|
||||
if form.has_changed():
|
||||
|
@ -322,7 +336,7 @@ def edit(request, acronym):
|
|||
session = sessions[0]
|
||||
session.requested_duration = datetime.timedelta(0,int(form.cleaned_data['length_session1']))
|
||||
session.save()
|
||||
|
||||
|
||||
# session 2
|
||||
if 'length_session2' in form.changed_data:
|
||||
length_session2 = form.cleaned_data['length_session2']
|
||||
|
@ -344,7 +358,7 @@ def edit(request, acronym):
|
|||
session = sessions[1]
|
||||
session.requested_duration = duration
|
||||
session.save()
|
||||
|
||||
|
||||
# session 3
|
||||
if 'length_session3' in form.changed_data:
|
||||
length_session3 = form.cleaned_data['length_session3']
|
||||
|
@ -366,8 +380,8 @@ def edit(request, acronym):
|
|||
session = sessions[2]
|
||||
session.requested_duration = duration
|
||||
session.save()
|
||||
|
||||
|
||||
|
||||
|
||||
if 'attendees' in form.changed_data:
|
||||
sessions.update(attendees=form.cleaned_data['attendees'])
|
||||
if 'comments' in form.changed_data:
|
||||
|
@ -381,21 +395,21 @@ def edit(request, acronym):
|
|||
if 'conflict3' in form.changed_data:
|
||||
Constraint.objects.filter(meeting=meeting,source=group,name='conflic3').delete()
|
||||
save_conflicts(group,meeting,form.cleaned_data['conflict3'],'conflic3')
|
||||
|
||||
|
||||
# deprecated
|
||||
# log activity
|
||||
#add_session_activity(group,'Session Request was updated',meeting,user)
|
||||
|
||||
|
||||
# send notification
|
||||
send_notification(group,meeting,login,form.cleaned_data,'update')
|
||||
|
||||
|
||||
messages.success(request, 'Session Request updated')
|
||||
url = reverse('sessions_view', kwargs={'acronym':acronym})
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
else:
|
||||
form = SessionForm(initial=initial)
|
||||
|
||||
|
||||
return render_to_response('sreq/edit.html', {
|
||||
'meeting': meeting,
|
||||
'form': form,
|
||||
|
@ -407,22 +421,22 @@ def edit(request, acronym):
|
|||
def main(request):
|
||||
'''
|
||||
Display list of groups the user has access to.
|
||||
|
||||
|
||||
Template variables
|
||||
form: a select box populated with unscheduled groups
|
||||
meeting: the current meeting
|
||||
scheduled_sessions:
|
||||
scheduled_sessions:
|
||||
'''
|
||||
# check for locked flag
|
||||
is_locked = check_app_locked()
|
||||
|
||||
|
||||
if is_locked and not has_role(request.user,'Secretariat'):
|
||||
message = get_lock_message()
|
||||
return render_to_response('sreq/locked.html', {
|
||||
'message': message},
|
||||
RequestContext(request, {}),
|
||||
)
|
||||
|
||||
|
||||
# TODO this is not currently used in the main template
|
||||
if request.method == 'POST':
|
||||
button_text = request.POST.get('submit', '')
|
||||
|
@ -432,15 +446,15 @@ def main(request):
|
|||
else:
|
||||
redirect_url = reverse('sessions_new', kwargs={'acronym':request.POST['group']})
|
||||
return HttpResponseRedirect(redirect_url)
|
||||
|
||||
|
||||
meeting = get_meeting()
|
||||
scheduled_groups,unscheduled_groups = groups_by_session(request.user, meeting)
|
||||
|
||||
|
||||
# load form select with unscheduled groups
|
||||
choices = zip([ g.pk for g in unscheduled_groups ],
|
||||
[ str(g) for g in unscheduled_groups ])
|
||||
form = GroupSelectForm(choices=choices)
|
||||
|
||||
|
||||
# add session status messages for use in template
|
||||
for group in scheduled_groups:
|
||||
sessions = group.session_set.filter(meeting=meeting)
|
||||
|
@ -448,12 +462,12 @@ def main(request):
|
|||
group.status_message = sessions[0].status
|
||||
else:
|
||||
group.status_message = 'First two sessions: %s, Third session: %s' % (sessions[0].status,sessions[2].status)
|
||||
|
||||
|
||||
# add not meeting indicators for use in template
|
||||
for group in unscheduled_groups:
|
||||
if group.session_set.filter(meeting=meeting,status='notmeet'):
|
||||
group.not_meeting = True
|
||||
|
||||
|
||||
return render_to_response('sreq/main.html', {
|
||||
'is_locked': is_locked,
|
||||
'form': form,
|
||||
|
@ -469,18 +483,18 @@ def new(request, acronym):
|
|||
This view gathers details for a new session request. The user proceeds to confirm()
|
||||
to create the request.
|
||||
'''
|
||||
|
||||
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
meeting = get_meeting()
|
||||
session_conflicts = session_conflicts_as_string(group, meeting)
|
||||
user = request.user
|
||||
|
||||
|
||||
if request.method == 'POST':
|
||||
button_text = request.POST.get('submit', '')
|
||||
if button_text == 'Cancel':
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
form = SessionForm(request.POST)
|
||||
if form.is_valid():
|
||||
# check if request already exists for this group
|
||||
|
@ -488,13 +502,13 @@ def new(request, acronym):
|
|||
messages.warning(request, 'Sessions for working group %s have already been requested once.' % group.acronym)
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
# save in user session
|
||||
request.session['session_form'] = form.data
|
||||
|
||||
|
||||
url = reverse('sessions_confirm',kwargs={'acronym':acronym})
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
# the "previous" querystring causes the form to be returned
|
||||
# pre-populated with data from last meeeting's session request
|
||||
elif request.method == 'GET' and request.GET.has_key('previous'):
|
||||
|
@ -507,10 +521,10 @@ def new(request, acronym):
|
|||
|
||||
initial = get_initial_session(previous_sessions)
|
||||
form = SessionForm(initial=initial)
|
||||
|
||||
|
||||
else:
|
||||
form = SessionForm()
|
||||
|
||||
|
||||
return render_to_response('sreq/new.html', {
|
||||
'meeting': meeting,
|
||||
'form': form,
|
||||
|
@ -530,7 +544,7 @@ def no_session(request, acronym):
|
|||
meeting = get_meeting()
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
login = request.user.get_profile()
|
||||
|
||||
|
||||
# delete canceled record if there is one
|
||||
Session.objects.filter(group=group,meeting=meeting,status='canceled').delete()
|
||||
|
||||
|
@ -539,7 +553,7 @@ def no_session(request, acronym):
|
|||
messages.info(request, 'The group %s is already marked as not meeting' % group.acronym)
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
session = Session(group=group,
|
||||
meeting=meeting,
|
||||
requested=datetime.datetime.now(),
|
||||
|
@ -547,7 +561,7 @@ def no_session(request, acronym):
|
|||
requested_duration=0,
|
||||
status=SessionStatusName.objects.get(slug='notmeet'))
|
||||
session.save()
|
||||
|
||||
|
||||
# send notification
|
||||
to_email = SESSION_REQUEST_EMAIL
|
||||
cc_list = get_cc_list(group, login)
|
||||
|
@ -557,12 +571,12 @@ def no_session(request, acronym):
|
|||
{'login':login,
|
||||
'group':group,
|
||||
'meeting':meeting}, cc=cc_list)
|
||||
|
||||
|
||||
# deprecated?
|
||||
# log activity
|
||||
#text = 'A message was sent to notify not having a session at IETF %d' % meeting.meeting_num
|
||||
#add_session_activity(group,text,meeting,request.person)
|
||||
|
||||
|
||||
# redirect
|
||||
messages.success(request, 'A message was sent to notify not having a session at IETF %s' % meeting.number)
|
||||
url = reverse('sessions')
|
||||
|
@ -574,32 +588,32 @@ def tool_status(request):
|
|||
This view handles locking and unlocking of the tool to the public.
|
||||
'''
|
||||
is_locked = check_app_locked()
|
||||
|
||||
|
||||
if request.method == 'POST':
|
||||
button_text = request.POST.get('submit', '')
|
||||
if button_text == 'Done':
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
form = ToolStatusForm(request.POST)
|
||||
|
||||
|
||||
if button_text == 'Lock':
|
||||
if form.is_valid():
|
||||
f = open(LOCKFILE,'w')
|
||||
f.write(form.cleaned_data['message'])
|
||||
f.close()
|
||||
|
||||
|
||||
messages.success(request, 'Session Request Tool is now Locked')
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
elif button_text == 'Unlock':
|
||||
os.remove(LOCKFILE)
|
||||
|
||||
|
||||
messages.success(request, 'Session Request Tool is now Unlocked')
|
||||
url = reverse('sessions')
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
else:
|
||||
if is_locked:
|
||||
message = get_lock_message()
|
||||
|
@ -607,7 +621,7 @@ def tool_status(request):
|
|||
form = ToolStatusForm(initial=initial)
|
||||
else:
|
||||
form = ToolStatusForm()
|
||||
|
||||
|
||||
return render_to_response('sreq/tool_status.html', {
|
||||
'is_locked': is_locked,
|
||||
'form': form},
|
||||
|
@ -621,12 +635,12 @@ def view(request, acronym):
|
|||
meeting = get_meeting()
|
||||
group = get_object_or_404(Group, acronym=acronym)
|
||||
sessions = Session.objects.filter(~Q(status__in=('canceled','notmeet','deleted')),meeting=meeting,group=group).order_by('id')
|
||||
|
||||
|
||||
# if there are no session requests yet, redirect to new session request page
|
||||
if not sessions:
|
||||
redirect_url = reverse('sessions_new', kwargs={'acronym':acronym})
|
||||
return HttpResponseRedirect(redirect_url)
|
||||
|
||||
|
||||
# TODO simulate activity records
|
||||
activities = [{'act_date':sessions[0].requested.strftime('%b %d, %Y'),
|
||||
'act_time':sessions[0].requested.strftime('%H:%M:%S'),
|
||||
|
@ -637,20 +651,20 @@ def view(request, acronym):
|
|||
'act_time':sessions[0].scheduled.strftime('%H:%M:%S'),
|
||||
'activity':'Session was scheduled',
|
||||
'act_by':'Secretariat'})
|
||||
|
||||
|
||||
# other groups that list this group in their conflicts
|
||||
session_conflicts = session_conflicts_as_string(group, meeting)
|
||||
show_approve_button = False
|
||||
|
||||
|
||||
# if sessions include a 3rd session waiting approval and the user is a secretariat or AD of the group
|
||||
# display approve button
|
||||
if sessions.filter(status='apprw'):
|
||||
if has_role(request.user,'Secretariat') or group.parent.role_set.filter(name='ad',person=request.user.get_profile()):
|
||||
show_approve_button = True
|
||||
|
||||
|
||||
# build session dictionary (like querydict from new session request form) for use in template
|
||||
session = get_initial_session(sessions)
|
||||
|
||||
|
||||
return render_to_response('sreq/view.html', {
|
||||
'session': session,
|
||||
'activities': activities,
|
||||
|
|
|
@ -180,14 +180,11 @@ def doc_detail(request, date, name):
|
|||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
|
||||
# As of Datatracker v4.32, Conflict Review (conflrev) Document Types can
|
||||
# be added to the Telechat agenda. We need to check the document type here
|
||||
# and set the state_type for use later in the view
|
||||
# be added to the Telechat agenda. If Document.type_id == draft use draft-iesg
|
||||
# for state type
|
||||
state_type = doc.type_id
|
||||
if doc.type_id == 'draft':
|
||||
state_type = 'draft-iesg'
|
||||
elif doc.type_id == 'conflrev':
|
||||
state_type = 'conflrev'
|
||||
elif doc.type_id == 'charter':
|
||||
state_type = 'charter'
|
||||
|
||||
started_process = doc.latest_event(type="started_iesg_process")
|
||||
login = request.user.get_profile()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Dear {{ group.parent }} Director(s):
|
||||
|
||||
{{ header }} meeting session request has just been
|
||||
submitted by {{ login }}, a working group chair of {{ group.name }}.
|
||||
submitted by {{ requester }}.
|
||||
The third session requires your approval.
|
||||
|
||||
To approve the session go to the session request view here:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% load ams_filters %}
|
||||
|
||||
A request to cancel a meeting session has just been submitted by {{ login|smart_login }} {{ group.acronym }} working group.
|
||||
A request to cancel a meeting session has just been submitted by {{ requester }}.
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% load ams_filters %}
|
||||
|
||||
{{ header }} meeting session request has just been submitted by {{ login|smart_login }} {{ group.acronym }} working group.
|
||||
{{ header }} meeting session request has just been submitted by {{ requester }}.
|
||||
|
||||
{% include "includes/session_info.txt" %}
|
||||
|
|
Loading…
Reference in a new issue