def global_stuff(request):
    try:
        header_image = Configuration.objects.get_or_create(name="Header Logo")[0].file.url
    except:
        header_image = None
    school_name = Configuration.get_or_default('School Name', default="Unnamed School")
    school_color = Configuration.get_or_default('School Color', default="").value
    google_analytics_code = Configuration.get_or_default('Google Analytics').value
    
    # Only show messages if user just logged in
    user_messages = None
    if not request.session.get('has_seen_message', False) and request.user.is_authenticated():
        today = datetime.date.today()
        if request.user.groups.filter(name='students'):
            user_messages = MessageToStudent.objects.filter(start_date__lte=today, end_date__gte=today)
        if request.user.groups.filter(name='company') and 'work_study' in settings.INSTALLED_APPS:
            from work_study.models import MessageToSupervisor
            user_messages = MessageToSupervisor.objects.filter(start_date__lte=today, end_date__gte=today)
        request.session['has_seen_message'] = True

    return {
        "header_image": header_image,
        "school_name": school_name,
        "settings": settings,
        "school_color": school_color,
        'user_messages':user_messages,
        'google_analytics_code': google_analytics_code,
    }
Exemple #2
0
def get_active_class_config():
    if Configuration.get_or_default("Only Active Classes in Schedule", None).value == "True" \
    or Configuration.get_or_default("Only Active Classes in Schedule", None).value == "true" \
    or Configuration.get_or_default("Only Active Classes in Schedule", None).value == "T":
        return "True"
    else:
        return "False"
    def get_appy_context(self):
        context = super(SisReport, self).get_appy_context()
        context['date'] = datetime.date.today()
        students = context['objects']
        template = self.report_context.get('template')
        if template:
            self.date_end = self.report_context['date_end']

            # backwards compatibility for templates
            context['date_of_report'] = self.date_end
            context['school_year'] = self.report_context['school_year']
            context['school_name'] = Configuration.get_or_default(name="School Name")

            if template.transcript:
                self.pass_score = float(Configuration.get_or_default("Passing Grade", '70').value)
                self.pass_letters = Configuration.get_or_default("Letter Passing Grade", 'A,B,C,P').value
                for student in students:
                    self.get_student_transcript_data(student)
            if template.benchmark_report_card and \
                'benchmark_grade' in settings.INSTALLED_APPS:
                from benchmark_grade.report import get_benchmark_report_card_data
                get_benchmark_report_card_data(self.report_context, context, students)
            elif template.report_card:
                self.blank_grade = struct()
                self.blank_grade.comment = ""
                school_year = SchoolYear.objects.filter(start_date__lte=self.report_context['date_end']
                        ).order_by('-start_date').first()
                context['year'] = school_year
                self.marking_periods = MarkingPeriod.objects.filter(
                    school_year=school_year, show_reports=True)
                context['marking_periods'] = self.marking_periods.order_by('start_date')
                for student in students:
                    self.get_student_report_card_data(student)
            if template.general_student:
                cal = Calendar()
                schedule_days = self.report_context.get('schedule_days', None)
                marking_periods = MarkingPeriod.objects.filter(start_date__gte=self.report_context['date_end'],
                    end_date__lte=self.report_context['date_end']).order_by('start_date')
                if not marking_periods.count():
                    marking_periods = MarkingPeriod.objects.filter(start_date__gte=self.report_context['date_begin']).order_by('start_date')
                current_mp = marking_periods[0]
                for student in students:
                    if current_mp:
                        student.schedule_days, student.periods = cal.build_schedule(student, current_mp,
                            schedule_days=schedule_days)
                    #student.discipline_records = student.studentdiscipline_set.filter(date__gte=begin_end_dates[0],
                    #    date__lte=begin_end_dates[1])
                    #for d in student.discipline_records:
                    #    d.date = d.date.strftime('%b %d, %Y')

        context['students'] = students
        return context
Exemple #4
0
 def get_email(self):
     """ Returns email address using various configurable methods """
     email_method = Configuration.get_or_default(
         "How to obtain student email",
         default="append",
         help_text="append, user, or student.").value
     if email_method == "append":
         email_end = Configuration.get_or_default("email", default="@change.me").value
         return '%s%s' % (self.student.username, email_end)
     elif email_method == "user":
         if User.objects.filter(username=self.student.username):
             return User.objects.filter(username=self.student.username)[0].email
         return None
     return self.alt_email
    def get_report(self, report_view, context):
        marking_periods = report_view.report.report_context['marking_periods']
        # anticipate str(student.year)
        students = Student.objects.select_related('year__name').filter(
            courseenrollment__course__marking_period__in=marking_periods
        ).distinct()
        titles = ['']
        departments = Department.objects.filter(course__courseenrollment__user__is_active=True).distinct()

        for department in departments:
            titles += [str(department)]
        titles += ['Total', '', 'Username', 'Year','GPA', '', 'Failed courses']

        passing_grade = float(Configuration.get_or_default('Passing Grade','70').value)

        data = []
        iy=2
        for student in students:
            row = [str(student)]
            ix = 1 # letter A
            # query the database once per student, not once per student per department
            # anticipate calling str() on grade.course and grade.marking_period
            student.failed_grades = student.grade_set.select_related(
                'course__department_id',
                'course__fullname',
                'marking_period__name',
            ).filter(
                override_final=False,
                grade__lt=passing_grade,
                marking_period__in=marking_periods
            ).distinct()
            department_counts = {}
            end_of_row = []
            for grade in student.failed_grades:
                # every failing grade gets dumped out at the end of the row
                end_of_row += [
                    str(grade.course),
                    str(grade.marking_period),
                    str(grade.grade)
                ]
                # add one to the failed grade count for this department
                department_counts[grade.course.department_id] = department_counts.get(
                    grade.course.department_id, 0) + 1
            for department in departments:
                row += [department_counts.get(department.pk, 0)]
                ix += 1
            row += [
                '=sum(b{0}:{1}{0})'.format(str(iy),get_column_letter(ix)),
                '',
                student.username,
                str(student.year),
                student.gpa,
                '',
                ]
            row += end_of_row
            data += [row]
            iy += 1

        return report_view.list_to_xlsx_response(data, 'fail_report', header=titles)
Exemple #6
0
 def build_schedule(self, student, marking_period, include_asp=False, schedule_days=None):
     """
     Returns days ['Monday', 'Tuesday'...] and periods
     """
     periods = Period.objects.filter(course__courseenrollment__user=student, course__marking_period=marking_period).order_by('start_time').distinct()
     course_meets = CourseMeet.objects.filter(course__courseenrollment__user=student, course__marking_period=marking_period).distinct()
     
     if schedule_days is None:
         day_list = CourseMeet.day_choice
     else:
         # super ugly
         day_choices = dict(CourseMeet.day_choice)
         day_list = []
         for schedule_day in schedule_days:
             day_list.append((schedule_day, day_choices[schedule_day]))
     days = []
     arr_days = []
     for day in day_list:
         if course_meets.filter(day=day[0]).count():
             days.append(day[1])
             arr_days.append(day)
             
     only_active = Configuration.get_or_default("Only Active Classes in Schedule", "False").value in \
         ['T', 'True', '1', 't', 'true']
     hide_meetingless = Configuration.get_or_default('Hide Empty Periods in Schedule').value in \
         ['T', 'True', '1', 't', 'true']
     
     useful_periods = []
     for period in periods:
         has_meeting = False
         period.days = []
         for day in arr_days:
             if  only_active:
                 course = course_meets.filter(day=day[0], period=period, course__active=True)
             else:
                 course = course_meets.filter(day=day[0], period=period)
             if course.count():
                 period.days.append(course[0])
                 has_meeting = True
             else:
                 period.days.append(None)
         if has_meeting or not hide_meetingless:
             useful_periods.append(period)
     return days, useful_periods
Exemple #7
0
def get_start_date_default():
    """ Return default date for report. It should be X work days ago. """
    work_days = (0,1,2,3,4) # python day of weeks mon-fri
    # Traverse back these many days
    days_back = int(Configuration.get_or_default('Discipline Merit Default Days', default=14).value)
    default_date = datetime.date.today()
    while days_back > 0:
        while not default_date.weekday() in work_days:
            default_date = default_date - datetime.timedelta(days=1)
        default_date = default_date - datetime.timedelta(days=1)
        days_back -= 1
    return default_date
Exemple #8
0
def global_stuff(request):
    try:
        header_image = Configuration.objects.get_or_create(
            name="Header Logo")[0].file.url
    except:
        header_image = None
    school_name = Configuration.get_or_default('School Name',
                                               default="Unnamed School")
    school_color = Configuration.get_or_default('School Color',
                                                default="").value
    google_analytics_code = Configuration.get_or_default(
        'Google Analytics').value

    # Only show messages if user just logged in
    user_messages = None
    if not request.session.get('has_seen_message',
                               False) and request.user.is_authenticated():
        today = datetime.date.today()
        if request.user.groups.filter(name='students'):
            user_messages = MessageToStudent.objects.filter(
                start_date__lte=today, end_date__gte=today)
        if request.user.groups.filter(
                name='company') and 'work_study' in settings.INSTALLED_APPS:
            from work_study.models import MessageToSupervisor
            user_messages = MessageToSupervisor.objects.filter(
                start_date__lte=today, end_date__gte=today)
        request.session['has_seen_message'] = True

    return {
        "header_image": header_image,
        "school_name": school_name,
        "settings": settings,
        "school_color": school_color,
        'user_messages': user_messages,
        'google_analytics_code': google_analytics_code,
    }
Exemple #9
0
    def save(self, creating_worker=False, *args, **kwargs):
        # self.cache_cohorts()
        if self.is_active == False and (Configuration.get_or_default("Clear Placement for Inactive Students","False").value == "True" \
        or Configuration.get_or_default("Clear Placement for Inactive Students","False").value == "true" \
        or Configuration.get_or_default("Clear Placement for Inactive Students","False").value == "T"):
            try:
                self.studentworker.placement = None
            except: pass
        # Check year
        self.determine_year()

        super(Student, self).save(*args, **kwargs)

        # Create student worker if the app is installed.
        # https://code.djangoproject.com/ticket/7623
        if 'work_study' in settings.INSTALLED_APPS:
            if not creating_worker and not hasattr(self, 'studentworker'):
                from work_study.models import StudentWorker
                worker = StudentWorker(user_ptr_id=self.user_ptr_id)
                worker.__dict__.update(self.__dict__)
                worker.save(creating_worker=True)

        group, gcreated = Group.objects.get_or_create(name="students")
        self.user_ptr.groups.add(group)
Exemple #10
0
    def save(self, *args, **kwargs):
        email = False
        emailStu = False

        if not self.supervisor_key or self.supervisor_key == "":
            # Use previous key if one exists
            if self.id:
                ts = TimeSheet.objects.get(id=self.id)
                self.supervisor_key = ts.supervisor_key
            else:
                self.genKey()
                email = True

        # set hours
        hours = self.time_lunch.hour - self.time_in.hour
        mins = self.time_lunch.minute - self.time_in.minute
        hours += self.time_out.hour - self.time_lunch_return.hour
        mins += self.time_out.minute - self.time_lunch_return.minute
        hours += mins/Decimal(60)
        self.hours = hours

        # set pay rates
        if self.for_pay and not self.school_pay_rate and not self.student_pay_rate:
            try:
                self.school_pay_rate = self.student.school_pay_rate
                self.student_pay_rate = self.student.student_pay_rate
            except:
                print >> sys.stderr, "warning: pay rate for company not set. "

        # set payment net sum
        if self.school_pay_rate:
            self.school_net = self.hours * self.school_pay_rate
        if self.student_pay_rate:
            self.student_net = self.hours * self.student_pay_rate

        super(TimeSheet, self).save(*args, **kwargs)

        self.student = StudentWorker.objects.get(id=self.student.id) # refresh data for p contact
        if email and self.student.primary_contact:
            try:
                sendTo = self.student.primary_contact.email
                subject = "Time Sheet for " + str(self.student)
                msg = "Hello " + unicode(self.student.primary_contact.fname) + ",\nPlease click on the link below to approve the time sheet.\n" + \
                    get_base_url() + "/work_study/approve?key=" + str(self.supervisor_key)
                from_addr = Configuration.get_or_default("From Email Address", "*****@*****.**").value
                send_mail(subject, msg, from_addr, [sendTo])
            except:
                print >> sys.stderr, "Unable to send e-mail to supervisor! %s" % (self,)
Exemple #11
0
def fte_by_day(request):
    cursor = connection.cursor()
    fte = int(
        Configuration.get_or_default(name="Students per FTE"[0],
                                     default=5).value)
    cursor.execute("select day, count(*)/" + str(fte) + \
        " from work_study_studentworker left join work_study_workteam on work_study_workteam.id = "+\
        "work_study_studentworker.placement_id where work_study_workteam.inactive = False group by day;")
    names = cursor.fetchall()
    titles = (["Day", "FTE"])
    report = XlReport(file_name="report_fteByDay")
    report.add_sheet(names,
                     header_row=titles,
                     title="FTE by Day of Week",
                     heading="FTE by Day of Week")
    return report.as_download()
Exemple #12
0
 def emailStudent(self, show_comment=True):
     try:
         sendTo = self.student.get_email
         subject = "Time sheet approved for " + unicode(self.student)
         if show_comment:
             msg = "Hello " + unicode(self.student) + ",\nYour time card for " + self.date.strftime("%x") + " was approved. Your rating was " + unicode(self.performance) + " \nYour supervisor's comment was \"" \
                 + unicode(self.supervisor_comment) + "\""
         else:
             msg = "Hello " + unicode(self.student) + ",\nYour time card for " + self.date.strftime("%x") + " was approved."
         from_addr = Configuration.get_or_default("From Email Address", "*****@*****.**").value
         send_mail(subject, msg, from_addr, [str(sendTo)])
     except:
         logging.warning('Could not e-mail student', exc_info=True, extra={
             'exception': sys.exc_info()[0],
             'exception2': sys.exc_info()[1],
         })
Exemple #13
0
 def save(self, *args, **kwargs):
     super(ClientVisit, self).save(*args, **kwargs)
     if self.notify_mentors:
         try:
             users = User.objects.filter(groups__name='mentor')
             sendTo = []
             for user in users:
                 sendTo.append(user.email)
             subject = "CRA visit at " + unicode(self.company)
             msg = "A CRA report has been entered for " + unicode(
                 self.company) + " on " + unicode(
                     self.date) + ".\n" + unicode(self.notes)
             from_addr = Configuration.get_or_default(
                 "From Email Address", "*****@*****.**").value
             send_mail(subject, msg, from_addr, sendTo)
         except:
             print >> sys.stderr, "warning: could not e-mail mentors"
Exemple #14
0
def select_grade_method(request):
    """ Select a per user preferred grading method
    Forward to previously requested page after
    """
    pref = UserPreference.objects.get_or_create(user=request.user)[0]
    if request.POST and 'choice' in request.POST:
        pref.gradebook_preference = request.POST['choice']
        pref.save()
    options = []
    if 'benchmark_grade' in settings.INSTALLED_APPS:
        options += ['O']
    if 'engrade_sync' in settings.INSTALLED_APPS:
        options += ['E']
    allow_spreadsheet = Configuration.get_or_default(
        'grades_allow_spreadsheet_import').value
    if allow_spreadsheet == 'True':
        options += ['S']
    else:
        allow_spreadsheet = False
    if request.user.has_perm('grades.change_own_grade'
                             ) or request.user.has_pem('grades.change_grade'):
        options += ['M']
        allow_manual = True

    if not pref.gradebook_preference and len(options) == 1:
        pref.gradebook_preference = options[0]
        pref.save()

    if pref.gradebook_preference and (not 'override' in request.GET
                                      or request.POST):
        if 'next' in request.GET:
            next_page = request.GET['next']
            if next_page == "teacher_grade":
                return redirect('grades.views.teacher_grade')

    return render_to_response(
        'grades/select_grade_method.html',
        {
            'request': request,
            'allow_spreadsheet': allow_spreadsheet,
            'allow_manual': allow_manual
        },
        RequestContext(request, {}),
    )
Exemple #15
0
    def change_view(self, request, object_id, extra_context=None):
        levels = []
        applicant = get_object_or_404(Applicant, id=object_id)
        # Attempt to guess next school year
        future_years = SchoolYear.objects.filter(
            start_date__gt=datetime.date.today()).order_by('start_date')
        if future_years:
            override_date = Configuration.get_or_default(
                name="admissions_override_year_start",
                default='',
                help_text="Must be ISO date (ex 2012-10-25) or blank",
            ).value
            if override_date:
                try:
                    override_date = parser.parse(override_date)
                    future_years[0].start_date = override_date
                except:
                    pass
            year = future_years[0]
        else:
            year = None
        for level in AdmissionLevel.objects.all():
            level.checks = []
            level.max = 0
            for check in AdmissionCheck.objects.filter(level=level):
                level.checks.append(check)
                level.max += 1
                if object_id:
                    if check in applicant.checklist.all():
                        check.checked = True
                    else:
                        check.checked = False
            levels.append(level)

        my_context = {
            'levels': levels,
            'current_level': applicant.level,
            'year': year,
        }
        return super(ApplicantAdmin,
                     self).change_view(request,
                                       object_id,
                                       extra_context=my_context)
Exemple #16
0
 def save(self, *args, **kwargs):
     if not self.id: new = True
     else: new = False
     super(StudentInteraction, self).save(*args, **kwargs)
     #email if needed
     if self.student.count() >= 1 and new:
         try:
             stu = self.student.all()[0]
             subject = unicode(self)
             msg = "Hello CRA " + unicode(stu.placement.cra.name.first_name) + ",\n"
             for aStudent in self.student.all():
                 msg += unicode(aStudent.fname) + " " + unicode(aStudent.lname) + ", "
             msg = msg[:-2] + " had a mentor meeting on " + unicode(self.date) + "\n" + unicode(self.comments) + "\n"
             for com in self.preset_comment.all():
                 msg += unicode(com) + "\n"
             from_addr = Configuration.get_or_default("From Email Address", "*****@*****.**").value
             send_mail(subject, msg, from_addr, [unicode(stu.placement.cra.name.email)])
         except:
             print >> sys.stderr, "warning: could not e-mail CRA"
Exemple #17
0
def fte_by_ind(request):
    """ FTE by industry
    """
    cursor = connection.cursor()
    fte = int(
        Configuration.get_or_default(name="Students per FTE"[0],
                                     default=5).value)
    cursor.execute("select industry_type, count(*)/" + str(fte) + \
        " from work_study_studentworker left join work_study_workteam on work_study_workteam.id = "+\
        "work_study_studentworker.placement_id where work_study_workteam.inactive = False group by industry_type;")
    names = cursor.fetchall()
    titles = (["Industry", "FTE"])
    report = XlReport(file_name="report_fteByInd")
    report.add_sheet(data=names,
                     header_row=titles,
                     title="Analytics Report",
                     heading="FTE by Industry Type")
    report.add_sheet(data=student_company_day_report(industry_type=True),
                     heading="Detail")
    return report.as_download()
Exemple #18
0
def fte_by_pay(request):
    report = XlReport(file_name="report_fteByPay")
    student_fte = int(Configuration.get_or_default(name="Students per FTE"[0], default=5).value)

    cursor = connection.cursor()
    cursor.execute("select paying, count(*)/" + str(student_fte) + \
                   " from work_study_studentworker left join work_study_workteam on work_study_workteam.id = "+\
        "work_study_studentworker.placement_id where work_study_workteam.inactive = False group by paying;")
    totals = cursor.fetchall()

    cursor = connection.cursor()
    cursor.execute("select team_name, paying, count(*)/" + str(student_fte) + ", funded_by as fte from work_study_studentworker left join work_study_workteam on "+\
        "work_study_workteam.id = work_study_studentworker.placement_id group by team_name order by paying, team_name;")
    company = cursor.fetchall()

    titles = (["Paying?","FTE"])
    report.add_sheet(totals, header_row=titles, title="Totals")
    titles = (["WorkTeam", "Paying?","FTE", "Funded by"])
    report.add_sheet(company, header_row=titles, title="Companies")
    report.add_sheet(student_company_day_report(paying=True), heading="Detail")
    return report.as_download()
Exemple #19
0
    def calculate_final_grade(self, student, date_report=None):
        """Calculates final grade. Does not take into account overrides.
		Note that this should math recalc_ytd_grade in gradesheet.js! """
        from SMS.grades.models import Grade
        final = Decimal(0)
        number = 0
        letter_grade = False
        grades = Grade.objects.filter(student=student, course=self)
        if date_report:
            grades = grades.filter(marking_period__end_date__lte=date_report)
        for grade in grades:
            try:
                final += grade.get_grade()
                number += 1
            # otherwise it's a letter grade.
            except TypeError:
                # I (Incomplete) results in the final grade being I
                if grade.get_grade() == "I":
                    return "I"
                elif grade.get_grade() in ["P", "HP", "LP"]:
                    final += 100
                    number += 1
                    letter_grade = True
                elif grade.get_grade() == 'F':
                    number += 1
                    letter_grade = True

        if number != 0:
            final = final / number
            final = Decimal(final).quantize(Decimal("0.01"), ROUND_HALF_UP)
            if letter_grade == True:
                if final > int(
                        Configuration.get_or_default(
                            'letter_grade_required_for_pass', '60').value):
                    return "P"
                else:
                    return "F"
        else:
            final = None
        return final
Exemple #20
0
def post_save_attendance_handler(sender, instance, **kwargs):
    """ Check for any triggers we should run """
    if True:
        try:
            # Create work study attendance if student's workday is today
            if ('ecwsp.work_study' in settings.INSTALLED_APPS and
                Configuration.get_or_default("attendance_create_work_attendance", "False").value == "True" and
                instance.date == datetime.date.today() and
                instance.status.absent and
                hasattr(instance.student, 'studentworker') and
                instance.student.studentworker and
                datetime.date.today().isoweekday() == instance.student.studentworker.get_day_as_iso_date()
               ):
                from ecwsp.work_study.models import Attendance
                attn, created = Attendance.objects.get_or_create(
                    student=instance.student.studentworker,
                    absence_date = datetime.date.today(),
                )
                if created:
                    attn.sis_attendance = instance
                    attn.save()
        except:
            logging.error('Attendance trigger error', exc_info=True)
Exemple #21
0
    def save(self, *args, **kwargs):
        try:
            previous = StudentWorker.objects.get(id=self.id)
            if previous.placement != self.placement:
                history = CompanyHistory(student = self, placement = previous.placement)
                history.save()
                # set primary contact to None if company has changed and p_contact isn't explicitly set
                if previous.primary_contact == self.primary_contact:
                    self.primary_contact = None
        except:
            pass

        if self.primary_contact and self.placement:
            self.placement.contacts.add(self.primary_contact)

         # set pay rates
        if not self.school_pay_rate and not self.student_pay_rate:
            try:
                self.school_pay_rate = Decimal(Configuration.get_or_default("school pay rate per hour", default="13.00").value)
                self.student_pay_rate = Decimal(Configuration.objects.get("student pay rate per hour", default="9").value)
            except:
                pass
        super(StudentWorker, self).save(*args, **kwargs)
Exemple #22
0
def post_save_attendance_handler(sender, instance, **kwargs):
    """ Check for any triggers we should run """
    if True:
        try:
            # Create work study attendance if student's workday is today
            if ('ecwsp.work_study' in settings.INSTALLED_APPS
                    and Configuration.get_or_default(
                        "attendance_create_work_attendance", "False").value
                    == "True" and instance.date == datetime.date.today()
                    and instance.status.absent
                    and hasattr(instance.student, 'studentworker')
                    and instance.student.studentworker
                    and datetime.date.today().isoweekday()
                    == instance.student.studentworker.get_day_as_iso_date()):
                from ecwsp.work_study.models import Attendance
                attn, created = Attendance.objects.get_or_create(
                    student=instance.student.studentworker,
                    absence_date=datetime.date.today(),
                )
                if created:
                    attn.sis_attendance = instance
                    attn.save()
        except:
            logging.error('Attendance trigger error', exc_info=True)
Exemple #23
0
    def calculate_grade_real(self, date_report=None, ignore_letter=False):
        """ Calculate the final grade for a course
        ignore_letter can be useful when computing averages
        when you don't care about letter grades
        """
        cursor = connection.cursor()

        # postgres requires a over () to run
        # http://stackoverflow.com/questions/19271646/how-to-make-a-sum-without-group-by
        sql_string = '''
        SELECT ( Sum(grade * weight) {over} / Sum(weight) {over} ) AS ave_grade,
               grades_grade.id,
               grades_grade.override_final
        FROM   grades_grade
               LEFT JOIN schedule_markingperiod
                      ON schedule_markingperiod.id = grades_grade.marking_period_id
        WHERE  ( grades_grade.course_id = %s
                 AND grades_grade.student_id = %s {extra_where} )
               AND ( grade IS NOT NULL
                      OR letter_grade IS NOT NULL )
        ORDER  BY grades_grade.override_final DESC limit 1'''

        if date_report:
            if settings.DATABASES['default'][
                    'ENGINE'] == 'django.db.backends.postgresql_psycopg2':
                cursor.execute(
                    sql_string.format(
                        over='over ()',
                        extra_where=
                        'AND (schedule_markingperiod.end_date <= %s OR override_final = 1)'
                    ), (self.course_id, self.user_id, date_report))
            else:
                cursor.execute(
                    sql_string.format(
                        over='',
                        extra_where=
                        'AND (schedule_markingperiod.end_date <= %s OR grades_grade.override_final = 1)'
                    ), (self.course_id, self.user_id, date_report))

        else:
            if settings.DATABASES['default'][
                    'ENGINE'] == 'django.db.backends.postgresql_psycopg2':
                cursor.execute(
                    sql_string.format(over='over ()', extra_where=''),
                    (self.course_id, self.user_id))
            else:
                cursor.execute(sql_string.format(over='', extra_where=''),
                               (self.course_id, self.user_id))

        result = cursor.fetchone()
        if result:
            (ave_grade, grade_id, override_final) = result
        else:  # No grades at all. The average of no grades is None
            return None

        if override_final:
            course_grades = grades.models.Grade.objects.get(id=grade_id)
            grade = course_grades.get_grade()
            if ignore_letter and not isinstance(grade, (int, Decimal, float)):
                return None
            return grade

        if ave_grade:
            # database math always comes out as a float :(
            return Decimal(ave_grade)

        # about 0.5 s
        # Letter Grade
        if ignore_letter == False:
            final = 0.0
            grades = self.course.grade_set.filter(student=self.user)
            if date_report:
                grades = grades.filter(
                    marking_period__end_date__lte=date_report)
            if grades:
                total_weight = Decimal(0)
                for grade in grades:
                    get_grade = grade.get_grade()
                    if get_grade in ["I", "IN", "YT"]:
                        return get_grade
                    elif get_grade in ["P", "HP", "LP"]:
                        if grade.marking_period:
                            final += float(100 * grade.marking_period.weight)
                            total_weight += grade.marking_period.weight
                    elif get_grade in ['F', 'M']:
                        if grade.marking_period:
                            total_weight += grade.marking_period.weight
                    elif get_grade:
                        final += get_grade
                if total_weight:
                    final /= float(total_weight)
                    final = Decimal(final).quantize(Decimal("0.01"),
                                                    ROUND_HALF_UP)
                    if final > int(
                            Configuration.get_or_default(
                                'letter_grade_required_for_pass').value):
                        return "P"
                    else:
                        return "F"
        return None
Exemple #24
0
class Course(models.Model):
    active = models.BooleanField(
        default=True,
        help_text="Sometimes used in third party integrations such as Moodle.")
    fullname = models.CharField(max_length=255, unique=True)
    shortname = models.CharField(max_length=255)
    #marking_period = models.ManyToManyField(MarkingPeriod, blank=True)
    start_date = models.DateField(validators=settings.DATE_VALIDATORS)
    end_date = models.DateField(validators=settings.DATE_VALIDATORS)
    #periods = models.ManyToManyField(CourseMeet, blank=True)#, through=CourseMeet)
    teacher = models.ForeignKey('profiles.Faculty',
                                blank=True,
                                null=True,
                                related_name="ateacher")
    secondary_teachers = models.ManyToManyField(
        'profiles.Faculty',
        blank=True,
        null=True,
        related_name="secondary_teachers")
    homeroom = models.BooleanField(
        default=False, help_text="Homerooms can be used for attendance")
    graded = models.BooleanField(
        default=True, help_text="Teachers can submit grades for this course")
    enrollments = models.ManyToManyField('auth.User',
                                         through=CourseEnrollment,
                                         blank=True,
                                         null=True)
    description = models.TextField(blank=True)
    credits = models.DecimalField(max_digits=5,
                                  decimal_places=2,
                                  help_text="Credits affect GPA.",
                                  default=lambda: Configuration.get_or_default(
                                      name='Default course credits').value)
    award_credits = models.BooleanField(
        default=True,
        help_text='''When disabled, course will not be included in any student's
        credit totals. However, the number of credits will still be used as a
        weight in GPA calculations.''')
    department = models.ForeignKey(Department, blank=True, null=True)
    level = models.ForeignKey('profiles.GradeLevel', blank=True, null=True)
    last_grade_submission = models.DateTimeField(
        blank=True,
        null=True,
        editable=False,
        validators=settings.DATE_VALIDATORS)

    def __unicode__(self):
        return self.fullname

    def save(self, *args, **kwargs):
        super(Course, self).save(*args, **kwargs)
        # assign teacher in as enrolled user
        try:
            if self.teacher:
                enroll, created = CourseEnrollment.objects.get_or_create(
                    course=self, user=self.teacher, role="teacher")
        except:
            pass

    @staticmethod
    def autocomplete_search_fields():
        return (
            "shortname__icontains",
            "fullname__icontains",
        )

    def grades_link(self):
        link = '<a href="/grades/teacher_grade/upload/%s" class="historylink"> Grades </a>' % (
            self.id, )
        return link

    grades_link.allow_tags = True

    def calculate_final_grade(self, student):
        """ Shim code to calculate final grade WITHOUT cache """
        enrollment = self.courseenrollment_set.get(user=student,
                                                   role="student")
        return enrollment.calculate_grade_real()

    def get_enrolled_students(self):
        return Student.objects.filter(courseenrollment__course=self)

    def copy_instance(self, request):
        changes = (("fullname", self.fullname + " copy"), )
        new = duplicate(self, changes)
        for enroll in self.courseenrollment_set.all():
            new_enrollment = CourseEnrollment(
                course=new,
                user=enroll.user,
                role=enroll.role,
                attendance_note=enroll.attendance_note)
            new_enrollment.save()
            for day in enroll.exclude_days.all():
                new_enrollment.exclude_days.add(day)
        for cm in self.coursemeet_set.all():
            new.coursemeet_set.create(location=cm.location,
                                      day=cm.day,
                                      period=cm.period)
        new.save()
        messages.success(request, 'Copy successful!')

    def number_of_students(self):
        return self.courseenrollment_set.filter(role="student").count()

    number_of_students.short_description = "# of Students"
Exemple #25
0
def get_city():
    return Configuration.get_or_default("Default City", "").value
Exemple #26
0
def grade_comment_length_validator(value):
    max_length = int(
        Configuration.get_or_default('Grade comment length limit').value)
    validator = MaxLengthValidator(max_length)
    return validator(value)
Exemple #27
0
def get_default_benchmark_grade():
    return str(
        Configuration.get_or_default("Benchmark-based grading",
                                     "False").value).lower() == "true"
Exemple #28
0
def get_default_one():
    return int(
        Configuration.get_or_default('Discipline Merit Level One',
                                     default=0).value)
Exemple #29
0
def get_default_two():
    return int(
        Configuration.get_or_default('Discipline Merit Level Two',
                                     default=1).value)
Exemple #30
0
def get_default_three():
    return int(Configuration.get_or_default('Discipline Merit Level Three', default=3).value)
Exemple #31
0
def get_default_four():
    return int(
        Configuration.get_or_default('Discipline Merit Level Four',
                                     default=5).value)
Exemple #32
0
def get_default_four():
    return int(Configuration.get_or_default('Discipline Merit Level Four', default=5).value)
Exemple #33
0
from datetime import date
import logging
from django.conf import settings

from celery.task.schedules import crontab
from celery.decorators import periodic_task
from celery import task

import sys

if 'work_study' in settings.INSTALLED_APPS:

    if settings.SYNC_SUGAR:
        from work_study.sugar_sync import SugarSync
        modify_date_minutes = int(
            Configuration.get_or_default("sync sugarcrm minutes",
                                         default="30").value)

        @periodic_task(run_every=crontab(minute='*/%s' %
                                         (modify_date_minutes, )))
        def update_contacts_from_sugarcrm():
            sugar_sync = SugarSync()
            sugar_sync.update_contacts_from_sugarcrm()

        @task()
        def update_contact_to_sugarcrm(contact):
            sugar_sync = SugarSync()
            sugar_sync.update_contact(contact)

    @periodic_task(run_every=crontab(hour=20, minute=27))
    def email_cra_nightly():
        """ Email CRA nightly time sheet and student interaction information
Exemple #34
0
def grade_comment_length_validator(value):
    max_length = int(Configuration.get_or_default('Grade comment length limit').value)
    validator = MaxLengthValidator(max_length)
    return validator(value)
Exemple #35
0
def teacher_grade_upload(request, id):
    """ This view is for inputing grades. It usually is done by uploading a spreadsheet.
    However it can also be done by manually overriding grades. This requires
    registrar level access. """

    course = Course.objects.get(id=id)

    students = Student.objects.filter(courseenrollment__course=course)
    grades = course.grade_set.all()

    if request.method == 'POST' and 'upload' in request.POST:
        import_form = GradeUpload(request.POST, request.FILES)
        if import_form.is_valid():
            from profiles.importer import Importer
            importer = Importer(request.FILES['file'], request.user)
            error = importer.import_grades(
                course, import_form.cleaned_data['marking_period'])
            if error:
                messages.warning(request, error)
            else:
                course.last_grade_submission = datetime.datetime.now()
                course.save()
    else:
        import_form = GradeUpload()
        import_form.fields['marking_period'].queryset = import_form.fields[
            'marking_period'].queryset.filter(course=course)

    if request.method == 'POST' and 'edit' in request.POST:
        handle_grade_save(request, course)

    marking_periods = course.marking_period.all().order_by('start_date')

    # Ensure grades exists
    for mp in marking_periods:
        for student in students:
            grade, created = Grade.objects.get_or_create(student=student,
                                                         course=course,
                                                         marking_period=mp)

    for student in students:
        student.grades = student.grade_set.filter(course=course,
                                                  override_final=False)
        try:
            student.final = student.grade_set.get(
                course=course, override_final=True).get_grade()
            student.final_override = True
        except Grade.DoesNotExist:
            student.final = course.calculate_final_grade(student)

    if request.user.is_superuser or \
        request.user.has_perm('grades.change_own_final_grade') or \
        request.user.has_perm('grades.change_grade'):
        edit_final = True
    else:
        edit_final = False
    if request.user.is_superuser or \
        request.user.has_perm('grades.change_own_grade') or \
        request.user.has_perm('grades.change_grade'):
        edit = True
    else:
        edit = False

    letter_grade_required_for_pass = Configuration.get_or_default(
        'letter_grade_required_for_pass', '60').value

    return render_to_response(
        'grades/teacher_grade_upload.html',
        {
            'request': request,
            'course': course,
            'marking_periods': marking_periods,
            'students': students,
            'import_form': import_form,
            'edit': edit,
            'edit_final': edit_final,
            'letter_grade_required_for_pass': letter_grade_required_for_pass
        },
        RequestContext(request, {}),
    )
Exemple #36
0
def get_default_one():
    return int(Configuration.get_or_default('Discipline Merit Level One', default=0).value)
Exemple #37
0
def get_default_two():
    return int(Configuration.get_or_default('Discipline Merit Level Two', default=1).value)
Exemple #38
0
def inquiry_form(request):
    """ A place for applicants to inquire for more info
    Places them in the database as an applicant
    Public view can be used by anyone
    """
    css = Configuration.get_or_default('admissions_inquiry_form_css').value
    exclude_years = Configuration.get_or_default('admissions_hide_inquiry_grade').value.split(',')
    valid_years = GradeLevel.objects.all()
    if exclude_years:
        try:
            valid_years = valid_years.exclude(id__in=exclude_years)
        except:
            valid_years = GradeLevel.objects.all()
    if request.POST:
        form = InquiryForm(request.POST)
        if form.is_valid():
            data = form.cleaned_data
            applicant = form.save()
            applicant.from_online_inquiry = True
            if data['ethnicity_other']:
                applicant.ethnicity = EthnicityChoice.objects.get_or_create(name=data['ethnicity_other'])[0]
            if data['language_other']:
                applicant.family_preferred_language = LanguageChoice.objects.get_or_create(name=data['language_other'])[0]
            if data['religion_other']:
                applicant.religion = ReligionChoice.objects.get_or_create(name=data['religion_other'])[0]

            if data['p_lname'] and data['p_fname']:
                ec = EmergencyContact.objects.get_or_create(
                    fname=data['p_fname'],
                    lname=data['p_lname'],
                    relationship_to_student=data['p_relationship_to_child'],
                    street=data['p_address'],
                    city=data['p_city'],
                    state=data['p_state'],
                    zip=data['p_zip'],
                    email=data['p_email'],
                )[0]
                applicant.parent_guardians.add(ec)

                if data['p_home']:
                    EmergencyContactNumber.objects.get_or_create(
                        contact=ec,
                        number=data['p_home'],
                        type="H"
                    )
                if data['p_work']:
                    ec_number = EmergencyContactNumber.objects.get_or_create(
                        contact=ec,
                        number=data['p_work'],
                        ext=data['p_work_ext'],
                        type="W"
                    )
                if data['p_mobile']:
                    ec_number = EmergencyContactNumber.objects.get_or_create(
                        contact=ec,
                        number=data['p_mobile'],
                        type="C"
                    )

            applicant.save()
            log = ContactLog(
                applicant=applicant,
                date=datetime.date.today(),
                note="Sent online inquiry form",
            )
            log.save()
            return HttpResponse('Thank you for submitting an inquiry!')
    else:
        form = InquiryForm()
        form.fields['year'].queryset = valid_years
    return render_to_response('admissions/inquiry_form.html', {
            'form': form,
            'css': css,
        },
        RequestContext(request, {}),
    )
Exemple #39
0
    def email_cra_nightly():
        """ Email CRA nightly time sheet and student interaction information
        """
        from_email = Configuration.objects.get_or_create(
            name="From Email Address")[0].value
        cras = CraContact.objects.filter(email=True)
        for cra in cras:
            msg = "Student(s): "
            subject = "SWORD student interactions"
            interactions = StudentInteraction.objects.filter(
                date__year=date.today().year,
                date__day=date.today().day,
                date__month=date.today().month).filter(
                    student__placement__cras=cra)
            if interactions.count() > 0:
                for interaction in interactions:
                    for student in interaction.student.all():
                        msg += unicode(student) + " "
                    msg += "\n"
                    msg += interaction.comments
                    msg += "\n"
                    for preset in interaction.preset_comment.all():
                        msg += unicode(preset) + "\n"
                    try:
                        send_mail(subject, msg, from_email,
                                  [unicode(cra.name.email)])
                    except:
                        logging.warning('Could not email interactions',
                                        exc_info=True,
                                        extra={
                                            'exception': sys.exc_info()[0],
                                            'exception2': sys.exc_info()[1],
                                        })

        cras = CraContact.objects.filter(email=True).filter(email_all=False)
        for cra in cras:
            msg = ""
            subject = "SWORD comments"
            send = False
            timesheets = TimeSheet.objects.filter(company__cras=cra).filter(
                cra_email_sent=False,
                creation_date__month=date.today().month).order_by(
                    'company__team_name')
            if timesheets.count():
                for timesheet in timesheets:
                    if timesheet.supervisor_comment or timesheet.performance or timesheet.student_accomplishment:
                        send = True
                        if timesheet.show_student_comments:
                            showtxt = "Student was able to view comments"
                        else:
                            showtxt = "Student was not allowed to view comments"
                        msg += unicode(timesheet.student) + ": " + unicode(timesheet.performance) + "\nsupervisor: " + \
                            unicode(timesheet.company) + " - " + unicode(timesheet.student.primary_contact) + "\n" + \
                            unicode(timesheet.supervisor_comment) + "\nstudent: " + unicode(timesheet.student_accomplishment) + \
                            showtxt + "\n"
                        if timesheet.approved:
                            msg += "Timesheet approved by supervisor\n\n"
                        else:
                            msg += "Timesheet not yet approved by supervisor\n\n"

                # Now get students who are present but did not submit a time card
                students = StudentWorker.objects.filter(
                    attendance__absence_date=date.today(),
                    attendance__tardy="P",
                    timesheet__company__cras=cra).exclude(
                        timesheet__date=date.today()).distinct()
                if students:
                    msg += "The following students were present but did not submit time sheets:\n"
                    for student in students:
                        msg += "{0}, ".format(student)
                    msg = msg[:-2]

                try:
                    send_mail(subject, msg, from_email,
                              [unicode(cra.name.email)])
                except:
                    logging.warning('Could not email CRA',
                                    exc_info=True,
                                    extra={
                                        'exception': sys.exc_info()[0],
                                        'exception2': sys.exc_info()[1],
                                    })
        cras = CraContact.objects.filter(email_all=True)
        for cra in cras:
            msg = ""
            subject = "SWORD comments"
            send = False
            timesheets = TimeSheet.objects.filter(
                cra_email_sent=False,
                creation_date__month=date.today().month).order_by(
                    'company__cras', 'company__team_name')
            if timesheets.count() > 0:
                for timesheet in timesheets:
                    if timesheet.supervisor_comment or timesheet.performance or timesheet.student_accomplishment:
                        send = True
                        msg += unicode(timesheet.student) + ": " + unicode(timesheet.performance) + "\nsupervisor: " + \
                            unicode(timesheet.company) + " - " + unicode(timesheet.student.primary_contact) + "\n" + \
                            unicode(timesheet.supervisor_comment) + "\nstudent: " + unicode(timesheet.student_accomplishment) + "\n"
                        if timesheet.approved:
                            msg += "Timesheet approved by supervisor\n\n"
                        else:
                            msg += "Timesheet not yet approved by supervisor\n\n"

                # Now get students who are present but did not submit a time card
                students = StudentWorker.objects.filter(
                    attendance__absence_date=date.today(),
                    attendance__tardy="P").exclude(
                        timesheet__date=date.today())
                if students:
                    msg += "The following students were present but did not submit time sheets:\n"
                    for student in students:
                        msg += smart_unicode(student) + ", "
                    msg = msg[:-2]

                try:
                    send_mail(subject, msg, from_email,
                              [unicode(cra.name.email)])
                except:
                    logging.warning('Could not email CRA all comments',
                                    exc_info=True,
                                    extra={
                                        'exception': sys.exc_info()[0],
                                        'exception2': sys.exc_info()[1],
                                    })

        # Check off time sheets that were processed today (so they aren't processed tomorrow)
        timesheets = TimeSheet.objects.filter(
            creation_date__month=date.today().month, cra_email_sent=False)
        for timesheet in timesheets:
            timesheet.cra_email_sent = True
            timesheet.save()

        # Remind students to submit time sheets
        students = StudentWorker.objects.filter(
            attendance__absence_date=date.today(),
            attendance__tardy="P").exclude(timesheet__date=date.today())
        subject = "Timesheet not submitted"
        for student in students:
            msg = "Hello {0},\n"
            conf_msg = Configuration.get_or_default(
                "work_study message to student missing time sheet",
                default=
                "You did not submit a time card today. Please remember to do so. This is an automated message, please do not reply."
            )
            msg += conf_msg.value
            email = student.get_email
            if email and email[-9:] != "change.me":
                try:
                    send_mail(subject, msg, from_email, [unicode(email)])
                except:
                    logging.warning(
                        'Could not email student about missing time card',
                        exc_info=True,
                        extra={
                            'exception': sys.exc_info()[0],
                            'exception2': sys.exc_info()[1],
                        })
Exemple #40
0
    def calculate_grade_real(self, date_report=None, ignore_letter=False):
        """ Calculate the final grade for a course
        ignore_letter can be useful when computing averages
        when you don't care about letter grades
        """
        cursor = connection.cursor()

        # postgres requires a over () to run
        # http://stackoverflow.com/questions/19271646/how-to-make-a-sum-without-group-by
        sql_string = '''
        SELECT ( Sum(grade * weight) {over} / Sum(weight) {over} ) AS ave_grade,
               grades_grade.id,
               grades_grade.override_final
        FROM   grades_grade
               LEFT JOIN schedule_markingperiod
                      ON schedule_markingperiod.id = grades_grade.marking_period_id
        WHERE  ( grades_grade.course_id = %s
                 AND grades_grade.student_id = %s {extra_where} )
               AND ( grade IS NOT NULL
                      OR letter_grade IS NOT NULL )
        ORDER  BY grades_grade.override_final DESC limit 1'''

        if date_report:
            if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2':
                cursor.execute(sql_string.format(
                    over='over ()', extra_where='AND (schedule_markingperiod.end_date <= %s OR override_final = 1)'),
                               (self.course_id, self.user_id, date_report))
            else:
                cursor.execute(sql_string.format(
                    over='', extra_where='AND (schedule_markingperiod.end_date <= %s OR grades_grade.override_final = 1)'),
                               (self.course_id, self.user_id, date_report))

        else:
            if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2':
                cursor.execute(sql_string.format(
                    over='over ()', extra_where=''),
                               (self.course_id, self.user_id))
            else:
                cursor.execute(sql_string.format(
                    over='', extra_where=''),
                               (self.course_id, self.user_id))

        result = cursor.fetchone()
        if result:
            (ave_grade, grade_id, override_final) = result
        else: # No grades at all. The average of no grades is None
            return None

        if override_final:
            course_grades = grades.models.Grade.objects.get(id=grade_id)
            grade = course_grades.get_grade()
            if ignore_letter and not isinstance(grade, (int, Decimal, float)):
                return None
            return grade

        if ave_grade:
            # database math always comes out as a float :(
            return Decimal(ave_grade)

        # about 0.5 s
        # Letter Grade
        if ignore_letter == False:
            final = 0.0
            grades = self.course.grade_set.filter(student=self.user)
            if date_report:
                grades = grades.filter(marking_period__end_date__lte=date_report)
            if grades:
                total_weight = Decimal(0)
                for grade in grades:
                    get_grade =  grade.get_grade()
                    if get_grade in ["I", "IN", "YT"]:
                        return get_grade
                    elif get_grade in ["P","HP","LP"]:
                        if grade.marking_period:
                            final += float(100 * grade.marking_period.weight)
                            total_weight += grade.marking_period.weight
                    elif get_grade in ['F', 'M']:
                        if grade.marking_period:
                            total_weight += grade.marking_period.weight
                    elif get_grade:
                        final += get_grade
                if total_weight:
                    final /= float(total_weight)
                    final = Decimal(final).quantize(Decimal("0.01"), ROUND_HALF_UP)
                    if final > int(Configuration.get_or_default('letter_grade_required_for_pass').value):
                        return "P"
                    else:
                        return "F"
        return None
Exemple #41
0
def get_default_three():
    return int(
        Configuration.get_or_default('Discipline Merit Level Three',
                                     default=3).value)