"""TA entitlement-related user interface implementation.
This module implements the Web user interface for managing TA entitlements.
"""
from operator import attrgetter
from itertools import groupby, islice
from ll.xist.ns import html
from uw.web.html.form import render_select, render_hidden, render_radio
from uw.web.html.format import make_table_format, format_return, format_datetime
from uw.web.wsgi.delegate import delegate_get_post
from uw.web.wsgi.form import use_form_param, parse_form_value
from uw.web.wsgi.function import return_html
from uw.web.wsgi.status import HTTPFound
from uw.local.util.format import format_person
from uw.local.termtools import fromCode, render_term_select
from ....util.identity import use_remote_identity
from .ui import format_units
[docs]def render_entitlements (cursor, unit, term, person, roles, url_prefix=""):
'''Renders the TA Entitlement section
:param term: Object respresenting a uw term.
:param person: A database row representing a particular student.
:param url_prefix:
:return: a list of HTML elements for the TA entitlement section. The
section provides forms for TA scholarship or override entitlements as
well as TA assignment history.
'''
result = [
html.h3 ('Entitlements'),
]
entitlements = cursor.execute_tuples ("select *, ta_student_entitlement_description (tse) as entitlement_description from ta_student_entitlement tse where (unit_code, person_id) = (%(unit_code)s, %(person_id)s) order by entitlement_seq", unit_code=unit.unit_code, person_id=person.person_id)
table_columns = [
('#', attrgetter ('entitlement_seq')),
('Description', format_entitlement_description),
('Units', format_entitlement_units),
('Comment', attrgetter ('entitled_comment')),
('History', lambda r: format_entitlement_time (cursor, r)),
]
if 'TAMAN' in roles:
table_columns.append (('Actions', lambda r: html.a ('Cancel…', href="entitle?entitlement-seq=%d" % r.entitlement_seq) if r.entitled_cancelled is None else None))
table = make_table_format (*table_columns) (entitlements)
total_entitlement = sum (r.entitled_units for r in entitlements if r.entitled_cancelled is None)
table.append (html.tr (
html.th ('Total Entitlement:', colspan=2),
html.td (format_units (total_entitlement)),
html.td (colspan=3),
))
result.append (table)
if 'TAMAN' in roles:
result.append (html.form (
html.p (
'New entitlement:'
),
html.p (
html.label (
render_radio ("type", value="scholarship"),
' Scholarship (starting ',
),
render_term_select ("start-term", islice ((term - 3).countFrom (), 9)),
' for ',
render_select ("term-count", ((i, i) for i in range (2, 10))),
' terms)',
),
html.p (
html.label (
render_radio ("type", value="override"),
' Override',
)
),
html.p (
'Units: ',
html.input (type="text", name="units"),
),
html.p (
' Comment: ',
html.input (type="text", name="comment"),
' ',
),
html.p (
html.input (type="submit", name="!create", value="Create!"),
),
method="post", action=url_prefix
))
assignments = groupby (cursor.execute_tuples ("select * from ta_position_assignment_plus left join ta_eval using (unit_code, term_id, admin_id, job_code, person_id) left join (select * from ta_rating_eval where rating_code = 'OVERALL') as tre using (eval_id) where (unit_code, person_id) = (%(unit_code)s, %(person_id)s) order by term_id, admin_description, job_description", unit_code=unit.unit_code, term_id=term.code (), person_id=person.person_id), key=attrgetter ('term_id'))
table = html.table (
html.tr (
html.th ('Term'),
html.th ('Course'),
html.th ('Job'),
html.th ('Overall Rating'),
html.th ('Evaluation'),
html.th ('Job Units'),
html.th ('Term Units'),
)
)
total_units = 0
for term_id, rows in assignments:
rows = list (rows)
for i, r in enumerate (rows):
tr = html.tr ()
if not i:
tr.append (html.td (fromCode (r.term_id).description (), rowspan=len (rows)))
tr.append (html.td (r.admin_description))
tr.append (html.td (r.job_description))
tr.append (html.td (r.rating if r.rating else None, style="text-align: center;"))
tr.append (html.td (html.a ('View…', href="./eval/%s" % r.eval_id) if r.eval_id else None))
tr.append (html.td (format_units (r.assigned_units)))
if not i:
term_units = sum (rr.assigned_units for rr in rows)
total_units += term_units
tr.append (html.td (format_units (term_units), rowspan=len (rows)))
table.append (tr)
table.append (html.tr (
html.th ('Total Units Assigned:', style="text-align: right;", colspan=5),
html.td (format_units (total_units), colspan=2),
))
result.extend ([
html.h3 ('Assignment History'),
table
])
result.append (html.p (
'Remaining entitlement: ',
format_units (total_entitlement - total_units),
))
return result
@use_form_param
@use_remote_identity
@return_html
def entitlement_get_handler (cursor, unit, term, person, form, remote_identity, roles):
if "entitlement-seq" in form:
result = html.form (html.p (
render_hidden ("entitlement-seq", form.required_field_value ("entitlement-seq")),
html.input (type="submit", name="!cancel", value="Cancel!"),
),
method="post", action="?"
)
return 'Confirm Cancel', result
else:
result = [format_return ('Term', 'Student List', dot='Student')]
result.append (render_entitlements (cursor, unit, term, person, roles))
return 'Student Entitlements for %s, %s (%s)' % (person.surname, person.givennames, person.userid), result
@use_form_param
@use_remote_identity
@return_html
def entitlement_post_handler (cursor, unit, term, person, form, remote_identity, roles):
if not 'TAMAN' in roles:
raise HTTPForbidden ()
if "!create" in form:
# Create an entitlement
etype = form.required_field_value ("type")
if etype == "scholarship":
plan_code = None
start_term = parse_form_value (form.optional_field_value ("start-term"), fromCode)
if start_term is None:
return 'Error: No start term selected', html.p ('Please choose a start term and try again.')
term_count = parse_form_value (form.optional_field_value ("term-count"), int)
if term_count is None:
return 'Error: No term count selected', html.p ('Please choose a term count and try again.')
scholarship_dates = '[%s,%s)' % (start_term.startDate (), (start_term + term_count).startDate ())
elif etype == "override":
plan_code = None
scholarship_dates = None
else:
return 'Error: No entitlement type selected', html.p ('Please choose an entitlement type and try again.')
units = form.optional_field_value ("units")
try:
units = parse_form_value (units, float)
except ValueError as x:
return 'Error: Cannot understand number of units', html.p (
'“%s” does not look like a number of units.' % units
)
if units is None:
return 'Error: No number of units specified', html.p ('Please fill in a number of units and try again.')
comment = form.optional_field_value ("comment")
cursor.callproc_none ("ta_student_entitlement_create", unit.unit_code, person.person_id, plan_code, scholarship_dates, units, comment, remote_identity.person_id)
elif "!cancel" in form:
# Cancel an entitlement
entitlement_seq = form.required_field_value ("entitlement-seq")
cursor.callproc_none ("ta_student_entitlement_cancel", unit.unit_code, person.person_id, entitlement_seq, remote_identity.person_id)
raise HTTPFound (".")
entitlement_handler = delegate_get_post (entitlement_get_handler, entitlement_post_handler)
[docs]def render_entitlement_schedule (cursor, unit_code):
entitlements = cursor.execute_tuples ("select * from ta_plan_entitlement natural join pps_plan where unit_code = %(unit_code)s order by plan_code", unit_code=unit_code)
return make_table_format (
('Plan Code', attrgetter ('plan_code')),
('Plan Transcript Description', attrgetter ('plan_transcript_description')),
('Units', lambda r: format_units (r.entitled_units)),
) (entitlements)