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 'ecwsp.work_study' in settings.INSTALLED_APPS:
            from ecwsp.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,
    }
Beispiel #2
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.
     # No other way to do it see:
     # https://code.djangoproject.com/ticket/7623
     if 'ecwsp.work_study' in settings.INSTALLED_APPS:
         if not creating_worker and not hasattr(self, 'studentworker'):
             from ecwsp.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)
Beispiel #3
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"
Beispiel #4
0
 def build_schedule(self, student, marking_period, include_asp=False):
     """
     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()
     
     days = []
     arr_days = []
     for day in CourseMeet.day_choice:
         if course_meets.filter(day=day[0]).count():
             days.append(day[1])
             arr_days.append(day)
             
     for period in periods:
         period.days = []
         for day in arr_days:
             if Configuration.get_or_default("Only Active Classes in Schedule", "False").value == "True" \
             or Configuration.get_or_default("Only Active Classes in Schedule", "False").value == "true" \
             or Configuration.get_or_default("Only Active Classes in Schedule", "False").value == "T":
                 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])
             else:
                 period.days.append(None)
         CourseMeet.objects.filter(course__courseenrollment__user=student, course__marking_period=marking_period, ).distinct()
     return days, periods
Beispiel #5
0
def ajax_get_student_info(request, course_id, student_id):
    student = get_object_or_404(Student, pk=student_id)
    course = get_object_or_404(Course, pk=course_id)

    # TODO: remove TC hard-coding
    try:
        Category.objects.get(name='Standards') # are we in TC land?
        standards_missing = Item.objects.filter(course=course, category__name='Standards', mark__student=student).annotate(best_mark=Max('mark__mark')).filter(best_mark__lt=3)
        if not standards_missing: standards_missing = ('None',)
        lists = ({'heading':'Standards Missing for {}'.format(student), 'items':standards_missing},)
    except Category.DoesNotExist:
        pass_letters = Configuration.get_or_default("Letter Passing Grade").value.split(',')
        pass_number = float(Configuration.get_or_default("Passing Grade").value) / 100 # yay, assumptions
        items_missing = Item.objects.filter(course=course, mark__student=student).annotate(best_mark=Max('mark__normalized_mark')).filter(
            best_mark__lt=pass_number)
        text_missing = []
        for item in items_missing:
            if item.mark_set.get(student=student).letter_grade in pass_letters:
                continue
            text_missing.append(u'{} / {} ({:.0f}%) {}'.format(
                item.best_mark * float(item.points_possible), item.points_possible, item.best_mark * 100, unicode(item)))
        lists = ({'heading':'Items Missing for {}'.format(student), 'items':text_missing},)
    afterword = '<a onclick="open_grade_detail({}, {})">Create report from current view of gradebook (in new tab)</a>'
    afterword = afterword.format(course_id, student_id)

    return render_to_response('sis/generic_list_fragment.html', {
        'lists': lists,
        'afterword': afterword,
    }, RequestContext(request, {}),)
Beispiel #6
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, {}))
Beispiel #7
0
 def is_passing(self, student, date_report=None):
     """ Is student passing course? """
     pass_score = float(Configuration.get_or_default("Passing Grade", "70").value)
     grade = self.get_final_grade(student, date_report=date_report)
     try:
         if grade >= int(pass_score):
             return True
     except:
         pass_letters = Configuration.get_or_default("Letter Passing Grade", "A,B,C,P").value
         if grade in pass_letters.split(","):
             return True
     return False
Beispiel #8
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
Beispiel #9
0
 def get_user_excludes(self):
     # get user-configured exclusions at runtime
     allowed_exclude = set(['marking_period', 'assignment_type', 'benchmark', 'date', 'description'])
     from ecwsp.administration.models import Configuration
     exclude = [x.strip() for x in Configuration.get_or_default('Gradebook hide fields').value.lower().split(',')] 
     exclude = set(exclude).intersection(allowed_exclude)
     return list(exclude)
Beispiel #10
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)
Beispiel #11
0
 def save(self, saved_by_volunteer=False, *args, **kwargs):
     if not self.secret_key or self.secret_key == "":
         self.genKey()
     
     if saved_by_volunteer:
         if not self.volunteer.email_queue:
             self.volunteer.email_queue = ""
         self.volunteer.email_queue += "Added site %s. " % (unicode(self.site))
         self.volunteer.save()
     if self.id:
         old_volunteer = VolunteerSite.objects.get(id=self.id)
         if old_volunteer.site_approval == "Submitted" and self.site_approval == "Accepted":
             try:
                 from django.core.mail import send_mail
                 from_email = Configuration.get_or_default("From Email Address",default="*****@*****.**").value
                 msg = "Hello %s,\nYour site %s has been approved!" % (self.volunteer, self.site)
                 subject = "Site approval"
                 send_to = self.volunteer.student.get_email
                 send_mail(subject, msg, from_email, [send_to])
             except:
                 exc_type, exc_obj, exc_tb = sys.exc_info()
                 fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
                 logging.warning(
                     'Unable to send email to volunteer about site approval! %s' % (self,),
                     exc_info=True,
                     extra={'request': request,'exception':exc_type,'traceback':'%s %s' % (fname,exc_tb.tb_lineno)}
                     )
     super(VolunteerSite, self).save(*args, **kwargs)
Beispiel #12
0
 def add_view(self, request, form_url='', extra_context=None):
     levels = []
     # 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
         levels.append(level)
     my_context = {
         'levels': levels,
         'current_level': None,
         'year': year,
     }
     return super(ApplicantAdmin, self).add_view(request, form_url, extra_context=my_context)
Beispiel #13
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 email student",
             exc_info=True,
             extra={"exception": sys.exc_info()[0], "exception2": sys.exc_info()[1]},
         )
Beispiel #14
0
    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']
            context['date_of_report'] = self.date_end # backwards compatibility for templates
            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 \
                'ecwsp.benchmark_grade' in settings.INSTALLED_APPS:
                from ecwsp.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
    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=3
        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__lte=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)
Beispiel #16
0
 def save(self, *args, **kwargs):
     if not self.id:
         new = True
     else:
         new = False
     super(ReferralForm, self).save(*args, **kwargs)
     if new:
         try:
             subject = 'New counseling referral for %s.' % (self.student,)
             msg = '%s has submitted a counseling referral form for %s. Click this link to view \n%s%s' % \
             (self.referred_by,self.student,settings.BASE_URL,reverse('admin:counseling_referralform_change',args=(self.id,)),)
             from_addr = Configuration.get_or_default("From Email Address", "*****@*****.**").value
             to_addr = Configuration.get_or_default("counseling_referral_notice_email_to", "").value.split(',')
             if to_addr and to_addr != ['']:
                 send_mail(subject, msg, from_addr, to_addr)
         except:
             logging.error('Couldn\'t email counseling referral form', exc_info=True)
Beispiel #17
0
 def update_contacts_from_sugarcrm(self):
     """ Query recently changed contacts in SugarCRM and sync them to django-sis
     """
     modify_date_minutes = int(Configuration.get_or_default("sync sugarcrm minutes",default="30").value)
     modify_date = datetime.datetime.now() - datetime.timedelta(minutes=modify_date_minutes + 1)
     contacts = self.get_recent_sugar_contacts(modify_date)
     for contact in contacts:
         self.set_django_sis_contact(contact)
Beispiel #18
0
 def is_passing(self, student, date_report=None, cache_grade=None, cache_passing=None, cache_letter_passing=None):
     """ Is student passing course? """
     if cache_passing == None:
         pass_score = float(Configuration.get_or_default("Passing Grade", '70').value)
     else:
         pass_score = cache_passing
     if cache_grade:
         grade = cache_grade
     else:
         grade = self.get_final_grade(student, date_report=date_report)
     try:
         if grade >= int(pass_score):
             return True
     except:
         pass_letters = Configuration.get_or_default("Letter Passing Grade", 'A,B,C,P').value
         if grade in pass_letters.split(','):
             return True
     return False
Beispiel #19
0
 def build_schedule(self, student, marking_period, include_asp=False, schedule_days=None):
     """
     Returns days ['Monday', 'Tuesday'...] and periods
     """
     periods = Period.objects.filter(coursesection__courseenrollment__user=student, coursesection__marking_period=marking_period).order_by('start_time').distinct()
     course_meets = CourseMeet.objects.filter(course_section__courseenrollment__user=student, course_section__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_section = course_meets.filter(day=day[0], period=period, course_section__is_active=True)
             else:
                 course_section = course_meets.filter(day=day[0], period=period)
             if course_section.exists():
                 period.days.append(course_section[0])
                 has_meeting = True
             else:
                 period.days.append(None)
         if has_meeting or not hide_meetingless:
             useful_periods.append(period)
     return days, useful_periods
Beispiel #20
0
 def save(self, *args, **kwargs):
     if Faculty.objects.filter(id=self.id).count():
         raise ValidationError('Cannot have someone be a student AND faculty!')
     self.cache_cohorts()
     if self.inactive == True 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)
     user, created = User.objects.get_or_create(username=self.username)
     if created:
         user.password = "******"
         user.save()
     group, gcreated = Group.objects.get_or_create(name="students")
     user.groups.add(group)
Beispiel #21
0
def applicants_to_students(request, year_id):
    """ Copies all applicants marked as ready for export to sis students
    Does not create copies. Once student is in sis he/she cannot be updated
    from applicant data."""
    imp = Importer()
    school_year = SchoolYear.objects.get(id=year_id)
    msg = ""
    if request.POST:
        imp = Importer()
        applicants = Applicant.objects.filter(ready_for_export=True, sis_student=None, school_year=school_year)
        for appl in applicants:
            student = Student(
                first_name=appl.fname,
                mname=appl.mname,
                last_name=appl.lname,
                sex=appl.sex,
                ssn=appl.ssn,
                bday=appl.bday,
                unique_id=appl.unique_id,
                email=appl.email,
                year=appl.year,
                pic=appl.pic,
                family_preferred_language=appl.family_preferred_language,
            )
            if not student.username:
                student.username = imp.gen_username(student.first_name, student.last_name)
            student.save()

            add_worker = Configuration.get_or_default("Admissions to student also makes student worker", "False")
            if add_worker.value == "True":
                student.promote_to_worker()

            appl.sis_student = student
            appl.save()
            for sib in appl.siblings.all():
                student.siblings.add()
            for par in appl.parent_guardians.all():
                student.emergency_contacts.add(par)
            student.save()
            for contact in student.emergency_contacts.filter(primary_contact=True):
                contact.cache_student_addresses()
            msg += "Imported <a href='/admin/sis/student/%s'>%s</a>, %s<br/>" % (
                student.id,
                unicode(student),
                student.username,
            )
        msg += "<br/>Maybe you want to save this list to add students to Active Directory or Google Apps?<br/><br/>"

    num = Applicant.objects.filter(ready_for_export=True, sis_student=None, school_year=school_year).count()
    msg += (
        "There are currently %s applicants marked as ready for export. This is not a reversable process! Note usernames will be generated, you may change them later.<br/>"
        % str(num)
    )
    return render_to_response("admissions/applicants_to_students.html", {"msg": msg}, RequestContext(request, {}))
Beispiel #22
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"
                    + settings.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 email to supervisor! %s" % (self,)
Beispiel #23
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()
Beispiel #24
0
 def email_admissions_new_inquiries():
     """ Email Admissions team about new online inquiries
     """
     from_email = Configuration.get_or_default("From Email Address").value
     to_email = Configuration.get_or_default('admissions_notify_email').value
     subject = "New online inquiries"
     today = datetime.date.today()
     
     new_inquiries = Applicant.objects.filter(date_added=today, from_online_inquiry=True)
     if new_inquiries:
         msg = "The following inquiries were submitted today\n"
         for inquiry in new_inquiries:
             msg += '\n<a href="{0}{1}">{2} {3}</a>\n'.format(
                 settings.BASE_URL,
                 reverse('admin:admissions_applicant_change', args=(inquiry.id,)),
                 inquiry.fname,
                 inquiry.lname)
             if Applicant.objects.filter(fname=inquiry.fname, lname=inquiry.lname).count() > 1:
                 msg += "(May be duplicate)\n"
             
         send_mail(subject, msg, from_email, to_email.split(','))
Beispiel #25
0
def fte_by_day(request):
    fileName = "report_fteByDay.xls"
    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 = xlsReport(names, titles, fileName, heading="FTE by Day of Week")
    report.addSheet(student_company_day_report(), heading="Detail")
    return report.finish()
Beispiel #26
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
Beispiel #27
0
    def email_admissions_new_inquiries():
        """ Email Admissions team about new online inquiries
        """
        from_email = Configuration.get_or_default("From Email Address").value
        to_email = Configuration.get_or_default('admissions_notify_email').value
        if not len(to_email):
            # don't complain if no one wants this report, just quit
            return
        # validate the from address
        try:
            validate_email(from_email)
        except ValidationError:
            logging.warning('email_admissions_new_inquiries failed because of invalid From Email Address "{}"'.format(from_email), exc_info=True)
            return
        # validate the to addresses
        to_email_list = []
        for addr in to_email.split(','):
            try:
                print addr
                validate_email(addr)
                to_email_list.append(addr)
            except ValidationError:
                logging.warning('email_admissions_new_inquiries omitting invalid address "{}" in admissions_notify_email'.format(addr), exc_info=True)

        subject = "New online inquiries"
        today = datetime.date.today()
        
        new_inquiries = Applicant.objects.filter(date_added=today, from_online_inquiry=True)
        if new_inquiries:
            msg = "The following inquiries were submitted today\n"
            for inquiry in new_inquiries:
                msg += '\n<a href="{0}{1}">{2} {3}</a>\n'.format(
                    settings.BASE_URL,
                    reverse('admin:admissions_applicant_change', args=(inquiry.id,)),
                    inquiry.fname,
                    inquiry.lname)
                if Applicant.objects.filter(fname=inquiry.fname, lname=inquiry.lname).count() > 1:
                    msg += "(May be duplicate)\n"
                
            send_mail(subject, msg, from_email, to_email_list)
Beispiel #28
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()
        if date_report:
            cursor.execute("SELECT (SUM(grade * weight) / sum(weight)) 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 AND schedule_markingperiod.end_date <= %s) and (grade is not null or letter_grade is not null ) ORDER BY `grades_grade`.`override_final` DESC limit 1", (self.course_id, self.user_id, date_report) )
        else:
            cursor.execute("SELECT (SUM(grade * weight) / sum(weight)) AS `ave_grade`, `grades_grade`.`id`, `grades_grade`.`override_final` FROM `grades_grade` left join schedule_markingperiod on schedule_markingperiod.id=marking_period_id WHERE (`grades_grade`.`course_id` = %s  AND `grades_grade`.`student_id` = %s ) and (grade is not null or letter_grade is not null ) ORDER BY `grades_grade`.`override_final` DESC limit 1", (self.course_id, self.user_id) )
        (ave_grade, grade_id, override_final) = cursor.fetchone()
        if override_final:
            course_grades = ecwsp.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:
            return ave_grade.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
        
        # 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"]:
                        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
Beispiel #29
0
 def calculate_final_grade(self, student, date_report=None):
     """
     Calculates final grade.
     Note that this should match recalc_ytd_grade in gradesheet.js!
     """
     if 'ecwsp.grades' in settings.INSTALLED_APPS:
         from ecwsp.grades.models import Grade
         
         final = Grade.objects.filter(course=self, override_final=True, student=student)
         if final:
             if not date_report or final[0].course.marking_period.filter(end_date__lte=date_report).count():
                 return final[0].get_grade()
         final = Decimal(0)
         number = 0
         letter_grade = False
         grades =  Grade.objects.filter(student=student, course=self, marking_period__course=self)
         if date_report:
             grades = grades.filter(marking_period__end_date__lte=date_report)
         total_weight = Decimal(0)
         for grade in grades:
             try:
                 final += Decimal(grade.get_grade()) * grade.marking_period.weight
                 number += 1
                 total_weight += grade.marking_period.weight
             # otherwise it's a letter grade.
             except:
                 # 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 * grade.marking_period.weight
                     number += 1
                     letter_grade = True
                     total_weight += grade.marking_period.weight
                 elif grade.get_grade() in ['F', 'M']:
                     number += 1
                     letter_grade = True
                     total_weight += grade.marking_period.weight
         if final is not None and total_weight:
             final /= total_weight
                 
         if number != 0:
             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
Beispiel #30
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()
Beispiel #31
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 'ecwsp.benchmark_grade' in settings.INSTALLED_APPS:
        options += ['O']
    if 'ecwsp.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_import = 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('ecwsp.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, {}),
    )
Beispiel #32
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)
Beispiel #33
0
 def send_email_approval(self):
     """
     Send email to supervisor for approval
     """
     if not self.site_supervisor or not self.site_supervisor.email:
         return None
     try:
         sendTo = self.site_supervisor.email
         subject = "Volunteer hours approval for " + unicode(self.student)
         msg = "Hello " + unicode(self.site_supervisor.name) + ",\nPlease click on the link below to approve the time sheet\n" + \
             settings.BASE_URL + "/volunteer_tracker/approve?key=" + str(self.secret_key)
         from_addr = Configuration.get_or_default(
             "From Email Address", "*****@*****.**").value
         send_mail(subject, msg, from_addr, [sendTo])
     except:
         logging.warning(
             "Unable to send email to volunteer's supervisor! %s" %
             (self, ),
             exc_info=True)
Beispiel #34
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 email CRA"
Beispiel #35
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()
Beispiel #36
0
 def calculate_final_grade(self, student, date_report=None):
     """
     Calculates final grade. Does not take into account overrides.
     Note that this should match recalc_ytd_grade in gradesheet.js!
     """
     if 'ecwsp.grades' in settings.INSTALLED_APPS:
         from ecwsp.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
Beispiel #37
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()
Beispiel #38
0
    def build_schedule(self, student, marking_period, include_asp=False):
        """
        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()

        days = []
        arr_days = []
        for day in CourseMeet.day_choice:
            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

        for period in periods:
            period.days = []
            for day in arr_days:
                if only_active in ['T', 'True', '1', 't', 'true']:
                    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])
                else:
                    period.days.append(None)
            CourseMeet.objects.filter(
                course__courseenrollment__user=student,
                course__marking_period=marking_period,
            ).distinct()
        return days, periods
Beispiel #39
0
class SchoolYear(models.Model):
    name = models.CharField(max_length=255, unique=True)
    start_date = models.DateField(validators=settings.DATE_VALIDATORS)
    end_date = models.DateField(validators=settings.DATE_VALIDATORS)
    grad_date = models.DateField(blank=True,
                                 null=True,
                                 validators=settings.DATE_VALIDATORS)
    active_year = models.BooleanField(
        help_text="DANGER!! This is the current school year. There can only be one and setting this will remove it from other years. " \
                  "If you want to change the active year you almost certainly want to click Admin, Change School Year.")
    benchmark_grade = models.BooleanField(
        default=lambda: str(
            Configuration.get_or_default("Benchmark-based grading", "False").
            value).lower() == "true",
        help_text=
        "Causes additional information to appear on transcripts. The configuration option \"Benchmark-based grading\" sets the default for this field."
    )

    class Meta:
        ordering = ('-start_date', )

    def __unicode__(self):
        return self.name

    def get_number_days(self, date=date.today()):
        """ Returns number of active school days in this year, based on
        each marking period of the year.
        date: Defaults to today, date to count towards. Used to get days up to a certain date"""
        mps = self.markingperiod_set.filter(
            show_reports=True).order_by('start_date')
        day = 0
        for mp in mps:
            day += mp.get_number_days(date)
        return day

    def save(self, *args, **kwargs):
        super(SchoolYear, self).save(*args, **kwargs)
        if self.active_year:
            all = SchoolYear.objects.exclude(id=self.id).update(
                active_year=False)
Beispiel #40
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 email student',
                         exc_info=True,
                         extra={
                             'exception': sys.exc_info()[0],
                             'exception2': sys.exc_info()[1],
                         })
Beispiel #41
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)
Beispiel #42
0
def handle():
    """ Emails subscribed volunteer managers daily site submissions
    """
    volunteers = Volunteer.objects.filter(email_queue__isnull=False).exclude(email_queue="")
    if volunteers:
        from_email = Configuration.objects.get_or_create(name="From Email Address")[0].value
        to_emails = Configuration.get_or_default("Volunteer Track Manager Emails", default="").value
        msg = "Student(s): \n"
        subject = "SWORD daily volunteer changes"

        for volunteer in volunteers:
            msg += "%s - %s\n\n" % (volunteer, volunteer.email_queue)

        to_emails = to_emails.split(',')
        sane_to_emails = []
        for email in to_emails:
            if email and email != " ":
                sane_to_emails.append(email.strip())
        send_mail(subject, msg, from_email, sane_to_emails)

        for volunteer in volunteers:
            volunteer.email_queue = ""
            volunteer.save()
Beispiel #43
0
    def save(self, saved_by_volunteer=False, *args, **kwargs):
        if not self.secret_key or self.secret_key == "":
            self.genKey()

        if saved_by_volunteer:
            if not self.volunteer.email_queue:
                self.volunteer.email_queue = ""
            self.volunteer.email_queue += "Added Site %s. " % (unicode(
                self.site))
            self.volunteer.save()
        if self.id:
            old_volunteer = VolunteerSite.objects.get(id=self.id)
            if old_volunteer.site_approval == "Submitted" and self.site_approval == "Accepted":
                try:
                    from django.core.mail import send_mail
                    from_email = Configuration.get_or_default(
                        "From Email Address",
                        default="*****@*****.**").value
                    msg = "Hello %s,\nYour site %s has been approved!" % (
                        self.volunteer, self.site)
                    subject = "Site approval"
                    send_to = self.volunteer.student.get_email
                    send_mail(subject, msg, from_email, [send_to])
                except:
                    exc_type, exc_obj, exc_tb = sys.exc_info()
                    fname = os.path.split(
                        exc_tb.tb_frame.f_code.co_filename)[1]
                    logging.warning(
                        'Unable to send email to volunteer about site approval! %s'
                        % (self, ),
                        exc_info=True,
                        extra={
                            'request': request,
                            'exception': exc_type,
                            'traceback': '%s %s' % (fname, exc_tb.tb_lineno)
                        })
        super(VolunteerSite, self).save(*args, **kwargs)
Beispiel #44
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)
Beispiel #45
0
 def get_context_data(self, **kwargs):
     context = super(CourseSectionGrades, self).get_context_data(**kwargs)
     form_class = self.get_form_class()
     form = self.get_form(form_class)
     form.fields['marking_period'].queryset = form.fields[
         'marking_period'].queryset.filter(
             coursesection=context['coursesection'])
     context['form'] = form
     if self.request.user.is_superuser or \
         self.request.user.has_perm('grades.change_own_final_grade') or \
         self.request.user.has_perm('grades.change_grade'):
         context['edit_final'] = True
     else:
         context['edit_final'] = False
     if self.request.user.is_superuser or \
         self.request.user.has_perm('grades.change_own_grade') or \
         self.request.user.has_perm('grades.change_grade'):
         context['edit'] = True
     else:
         context['edit'] = False
     context[
         'letter_grade_required_for_pass'] = Configuration.get_or_default(
             'letter_grade_required_for_pass', '60').value
     return context
    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 = 3
        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__lte=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)
Beispiel #47
0
def get_hours_default():
    return Configuration.get_or_default('Volunteer Track Required Hours',
                                        default=20).value
Beispiel #48
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, {}),
    )
Beispiel #49
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) + \
                        "\n" + 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").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',
                                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 = u"Hello {0},\n".format(student.first_name)
        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],
                    })
Beispiel #50
0
def get_default_three():
    return int(
        Configuration.get_or_default('Discipline Merit Level Three',
                                     default=3).value)
Beispiel #51
0
def get_default_two():
    return int(
        Configuration.get_or_default('Discipline Merit Level Two',
                                     default=1).value)
Beispiel #52
0
def get_default_one():
    return int(
        Configuration.get_or_default('Discipline Merit Level One',
                                     default=0).value)
Beispiel #53
0
def get_default_four():
    return int(
        Configuration.get_or_default('Discipline Merit Level Four',
                                     default=5).value)
Beispiel #54
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 ecwsp.sis.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, {}),
    )
Beispiel #55
0
def get_city():
    return Configuration.get_or_default("Default City", "").value
Beispiel #56
0
def get_credits_default():
    return Configuration.get_or_default(name='Default course credits').value
Beispiel #57
0
    def calculate_grade_real(self, date_report=None, ignore_letter=False):
        """ Calculate the final grade for a course section
        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 case when Sum(override_final{postgres_type_cast}) {over} = 1 then -9001 else (Sum(grade * weight) {over} / Sum(weight) {over}) end AS ave_grade
FROM grades_grade
    LEFT JOIN schedule_markingperiod
    ON schedule_markingperiod.id = grades_grade.marking_period_id
WHERE (grades_grade.course_section_id = %s
    AND grades_grade.student_id = %s {extra_where} )
    AND ( grade IS NOT NULL
    OR letter_grade IS NOT NULL )'''

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

        else:
            if settings.DATABASES['default']['ENGINE'] in [
                    'django.db.backends.postgresql_psycopg2',
                    'tenant_schemas.postgresql_backend'
            ]:
                cursor.execute(
                    sql_string.format(postgres_type_cast='::int',
                                      over='over ()',
                                      extra_where=''),
                    (self.course_section_id, self.user_id))
            else:
                cursor.execute(
                    sql_string.format(postgres_type_cast='',
                                      over='',
                                      extra_where=''),
                    (self.course_section_id, self.user_id))

        result = cursor.fetchone()
        if result:
            ave_grade = result[0]
        else:  # No grades at all. The average of no grades is None
            return None

        # -9001 = override. We can't mix text and int in picky postgress.
        if str(ave_grade) == "-9001":
            course_section_grade = Grade.objects.get(
                override_final=True,
                student=self.user,
                course_section=self.course_section)
            grade = course_section_grade.get_grade()
            if ignore_letter and not isinstance(grade, (int, Decimal, float)):
                return None
            return grade

        elif ave_grade:
            return Decimal(ave_grade)

        # about 0.5 s
        # Letter Grade
        if ignore_letter == False:
            final = 0.0
            grades = self.course_section.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:
                        try:
                            final += get_grade
                        except TypeError:
                            return 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
Beispiel #58
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)
Beispiel #59
0
 def get_readonly_fields(self, request, obj=None):
     edit_all = Configuration.get_or_default("Edit all Student Worker Fields", "False")
     if edit_all.value == "True":
         return ['parent_guardian', 'street', 'city', 'state', 'zip', 'parent_email', 'alt_email']
     return super(StudentAdmin, self).get_readonly_fields(request, obj=obj)
Beispiel #60
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 'ecwsp.work_study' in settings.INSTALLED_APPS:

    if settings.SYNC_SUGAR:
        from ecwsp.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