Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
NAME = "Base Salary Update"
IS_EXCLUSIVE = True
TO_HTML_TEMPLATE = """
{% extends "faculty/event_base.html" %}{% load event_display %}{% load humanize %}{% block dl %}
<dt>Rank & Step</dt><dd>{{ handler|get_display:"rank" }}, step {{ handler|get_display:"step" }}</dd>
<dt>Base salary</dt><dd>${{ handler|get_display:"base_salary"|floatformat:2|intcomma}}</dd>
<dt>Market Differential</dt><dd>${{ handler|get_display:"add_salary"|floatformat:2|intcomma }}</dd>
<dt>Add pay</dt><dd>${{ handler|get_display:"add_pay"|floatformat:2|intcomma }}</dd>
<dt>Total</dt><dd>${{ total|floatformat:2|intcomma }}</dd>
{% endblock %}
"""
class EntryForm(BaseEntryForm):
rank = forms.ChoiceField(choices=RANK_CHOICES, required=True)
step = forms.DecimalField(max_digits=4, decimal_places=2,
help_text="Current salary step")
base_salary = fields.AddSalaryField(help_text="Base annual salary for this rank + step.")
add_salary = fields.AddSalaryField(label="Market Differential")
add_pay = fields.AddPayField()
def post_init(self):
# find the last-known rank as a default
if self.person:
from faculty.models import CareerEvent
event = CareerEvent.objects.filter(person=self.person, event_type='SALARY').effective_now().last()
if event:
self.fields['rank'].initial = event.config['rank']
"""
Get the fellowship choices from EventConfig in these units, or superunits of them.
"""
from faculty.models import EventConfig
superunits = [u.super_units() for u in units] + [units]
superunits = set(u for sublist in superunits for u in sublist) # flatten list of lists
ecs = EventConfig.objects.filter(unit__in=superunits,
event_type=FellowshipEventHandler.EVENT_TYPE)
choices = itertools.chain(*[ec.config.get('fellowships', []) for ec in ecs])
if only_active:
choices = ((short,int) for short,int,status in choices if status == 'ACTIVE')
else:
choices = ((short,int) for short,int,status in choices)
return choices
class EntryForm(BaseEntryForm):
position = forms.ChoiceField(required=True, choices=[])
add_salary = AddSalaryField(required=False)
add_pay = AddPayField(required=False)
teaching_credit = TeachingCreditField(required=False)
def post_init(self):
# set the allowed position choices from the config from allowed units
choices = FellowshipEventHandler.get_fellowship_choices(self.units, only_active=True)
self.fields['position'].choices = choices
def clean(self):
data = self.cleaned_data
if 'unit' not in data:
raise forms.ValidationError("Couldn't check unit for fellowship ownership.")
choices = FellowshipEventHandler.get_fellowship_choices([data['unit']], only_active=True)
return 'Committee member: {}'.format(ctte)
class ResearchMembershipHandler(CareerEventHandlerBase):
EVENT_TYPE = 'LABMEMB'
NAME = 'Research Group / Lab Membership'
TO_HTML_TEMPLATE = '''
{% extends 'faculty/event_base.html' %}{% load event_display %}{% block dl %}
<dt>Lab Name</dt><dd>{{ handler|get_config:'lab_name' }}</dd>
<dt>Location</dt><dd>{{ handler|get_config:'location' }}</dd>
{% endblock %}
'''
class EntryForm(BaseEntryForm):
LOCATION_TYPES = Choices(
('SFU', 'Internal SFU'),
('ACADEMIC', 'Other Academic'),
('EXTERNAL', 'External'),
)
lab_name = forms.CharField(label='Research Group / Lab Name', max_length=255)
location = forms.ChoiceField(choices=LOCATION_TYPES)
SEARCH_RULES = {
'lab_name': search.StringSearchRule,
'location': search.ChoiceSearchRule,
}
SEARCH_RESULT_FIELDS = [
'lab_name',
class NormalTeachingLoadHandler(CareerEventHandlerBase, TeachingCareerEvent):
EVENT_TYPE = 'NORM_TEACH'
NAME = 'Normal Teaching Load'
IS_EXCLUSIVE = True
SEMESTER_BIAS = True
TO_HTML_TEMPLATE = """
{% extends "faculty/event_base.html" %}{% load event_display %}{% block dl %}
<dt>Required Load</dt><dd>{{ handler|get_display:'load' }} course{{ handler|get_display:'load'|pluralize }} per year</dd>
{% endblock %}
"""
class EntryForm(BaseEntryForm):
load = AnnualTeachingCreditField(label='Teaching Load', help_text=mark_safe('Expected teaching load per year. May be a fraction like 5/2.'))
SEARCH_RULES = {
'load': search.ComparableSearchRule,
}
SEARCH_RESULT_FIELDS = [
'load',
]
def short_summary(self):
load = self.get_config('load', 0)
return "Teaching load: {}/year".format(load*3)
def get_load_display(self):
# display as an annual value, while storing as semesterly
return str(self.get_config('load', 0)*3)
class ExternalAffiliationHandler(CareerEventHandlerBase):
EVENT_TYPE = 'EXTERN_AFF'
NAME = 'External Affiliation'
TO_HTML_TEMPLATE = '''
{% extends 'faculty/event_base.html' %}{% load event_display %}{% block dl %}
<dt>Organization Name</dt><dd>{{ handler|get_display:'org_name' }}</dd>
<dt>Organization Type</dt><dd>{{ handler|get_display:'org_type'}}</dd>
<dt>Organization Class</dt><dd>{{ handler|get_display:'org_class'}}</dd>
<dt>Is Research Institute / Centre?</dt><dd>{{ handler|get_display:'is_research'|yesno }}</dd>
<dt>Is Adjunct?</dt><dd>{{ handler|get_display:'is_adjunct'|yesno }}</dd>
{% endblock %}
'''
class EntryForm(BaseEntryForm):
ORG_TYPES = Choices(
('SFU', 'Internal SFU'),
('ACADEMIC', 'Academic'),
('PRIVATE', 'Private Sector'),
)
ORG_CLASSES = Choices(
('EXTERN_COMP', 'External Company'),
('NO_PROFIT', 'Not-For-Profit Institution'),
)
org_name = forms.CharField(label='Organization Name', max_length=255)
org_type = forms.ChoiceField(label='Organization Type', choices=ORG_TYPES)
org_class = forms.ChoiceField(label='Organization Classification', choices=ORG_CLASSES)
is_research = forms.BooleanField(label='Research Institute/Centre?', required=False)
is_adjunct = forms.BooleanField(label='Adjunct?', required=False)
if cls.SEMESTER_PINNED:
cls.EntryForm.base_fields['start_date'] = SemesterToDateField(start=True)
cls.EntryForm.base_fields['end_date'] = SemesterToDateField(start=False,
required=False)
else:
# NOTE: We don't allow IS_INSTANT to work with SEMESTER_PINNED
# If IS_INSTANT, get rid of the 'end_date' field from EntryForm
if cls.IS_INSTANT and 'end_date' in cls.EntryForm.base_fields:
del cls.EntryForm.base_fields['end_date']
# Figure out what fields are required by the Handler subclass
cls.BASE_FIELDS = collections.OrderedDict()
cls.CONFIG_FIELDS = collections.OrderedDict()
for name, field in cls.EntryForm.base_fields.iteritems():
if name in BaseEntryForm.base_fields:
cls.BASE_FIELDS[name] = field
else:
cls.CONFIG_FIELDS[name] = field
# Instantiate each of the SearchRules
cls.SEARCH_RULE_INSTANCES = collections.OrderedDict()
for name in cls.CONFIG_FIELDS:
if name in cls.SEARCH_RULES:
field = cls.CONFIG_FIELDS[name]
cls.SEARCH_RULE_INSTANCES[name] = cls.SEARCH_RULES[name](name, field, cls)
def __init__(self, editor, units, *args, **kwargs):
handler = kwargs.pop('handler', None)
self.person = kwargs.pop('person', None)
self.editor = editor
self.units = units
super(BaseEntryForm, self).__init__(*args, **kwargs)
self.fields['unit'].queryset = Unit.objects.filter(id__in=(u.id for u in units))
self.fields['unit'].choices = [(unicode(u.id), unicode(u)) for u in units]
# Load initial data from the handler instance if possible
if handler:
self.initial['start_date'] = handler.event.start_date
self.initial['end_date'] = handler.event.end_date
self.initial['unit'] = handler.event.unit
self.initial['comments'] = handler.event.comments
# Load any handler specific field values
for name in handler.CONFIG_FIELDS:
self.initial[name] = handler.get_config(name, None)
# force the comments field to the bottom
class AdminPositionEventHandler(CareerEventHandlerBase, TeachingCareerEvent):
"""
Given admin position
"""
EVENT_TYPE = 'ADMINPOS'
NAME = 'Admin Position'
TO_HTML_TEMPLATE = """
{% extends "faculty/event_base.html" %}{% load event_display %}{% block dl %}
<dt>Position</dt><dd>{{ handler|get_display:'position' }}</dd>
<dt>Teaching Credit</dt><dd>{{ handler|get_display:'teaching_credit' }}</dd>
{% endblock %}
"""
class EntryForm(BaseEntryForm):
POSITIONS = Choices(
('UGRAD_DIRECTOR', 'Undergrad Program Director'),
('GRAD_DIRECTOR', 'Graduate Program Director'),
('DDP_DIRECTOR', 'Dual-Degree Program Director'),
('ASSOC_DIRECTOR', 'Associate Director/Chair'),
('DIRECTOR', 'School Director/Chair'),
('ASSOC_DEAN', 'Associate Dean'),
('DEAN', 'Dean'),
('OTHER', 'Other Admin Position'),
)
position = forms.ChoiceField(required=True, choices=POSITIONS)
teaching_credit = TeachingCreditField(required=False, initial=None)
SEARCH_RULES = {
def set_status(self, editor):
"""
Set status appropriate to the editor. Override this method
if the status checking becomes more complex for an event type.
"""
if self.can_approve(editor):
self.event.status = 'A'
self.save(editor)
else:
self.event.status = 'NA'
self.save(editor)
# Stuff relating to forms
class EntryForm(BaseEntryForm):
pass
def load(self, form):
"""
Given a valid form, load its data into the handler.
"""
try:
self.event.unit = form.cleaned_data['unit']
self.event.start_date = form.cleaned_data['start_date']
except KeyError:
pass
self.event.end_date = form.cleaned_data.get('end_date', None)
self.event.comments = form.cleaned_data.get('comments', None)
# XXX: Event status is set based on the editor,
# This is set in handler method 'set_status'
{{ handler|get_display:"institution2" }}, {{ handler|get_display:"location2" }}{% endif %}
{% if handler|get_config:"degree3" != 'unknown' and handler|get_config:"degree3" != '' %}<br>
<dd>{{ handler|get_display:"degree3" }}, {{ handler|get_display:"year3" }},
{{ handler|get_display:"institution3" }}, {{ handler|get_display:"location3" }}{% endif %}
{% endif %}
{% if handler|get_config:"teaching_semester_credits" != 'unknown' and handler|get_config:"teaching_semester_credits" != ''%}
</dd><dt>Teaching Semester Credits</dt><dd>{{ handler|get_config:"teaching_semester_credits" }}</dd>
{% endif %}
{% endblock %}
"""
PDFS = {'yellow1': 'Yellow Form for Tenure Track',
'yellow2': 'Yellow Form for Limited Term'}
class EntryForm(BaseEntryForm):
LEAVING_CHOICES = Choices(
('HERE', '\u2014'), # hasn't left yet
('RETI', 'Retired'),
('END', 'Limited-term contract ended'),
('UNIV', 'Left: job at another University'),
('PRIV', 'Left: private-sector job'),
('GONE', 'Left: employment status unknown'),
('FIRE', 'Dismissal'),
('DIED', 'Deceased'),
('OTHR', 'Other/Unknown'),
)
position_number = forms.CharField(initial='', required=False, widget=forms.TextInput(attrs={'size': '6'}))
spousal_hire = forms.BooleanField(initial=False, required=False)
leaving_reason = forms.ChoiceField(initial='HERE', choices=LEAVING_CHOICES)