Example #1
0
def prepare_program(program, data):
    """ This function adds custom stuff to save_instance to facilitate making programs happen.
    """

    #   Permissions format:
    perms = []
    modules = []

    perms += [('Student/All', None, data['student_reg_start'],
               data['student_reg_end'])]  #it is recursive
    perms += [('Student/Catalog', None, data['student_reg_start'], None)]
    perms += [('Student/Profile', None, data['student_reg_start'], None)]
    perms += [('Teacher/All', None, data['teacher_reg_start'],
               data['teacher_reg_end'])]
    perms += [('Teacher/Classes/View', None, data['teacher_reg_start'], None)]
    perms += [('Teacher/MainPage', None, data['teacher_reg_start'], None)]
    perms += [('Teacher/Profile', None, data['teacher_reg_start'], None)]

    #   Grant onsite bit (for all times) if an onsite user is available.
    if ESPUser.onsite_user():
        perms += [('Onsite', ESPUser.onsite_user(), None, None)]

    modules += [(str(ProgramModule.objects.get(id=i)), i)
                for i in data['program_modules']]

    return perms, modules
Example #2
0
        def _value(self):
            user = ESPUser(self.user)
            node = self.node

            edit_verb = GetNode(EDIT_VERB_STRING)

            if not self.category:
                self.category = nav_category(node, section)

            if user:
                has_edit_bits = user.isAdministrator()
            else:
                has_edit_bits = False

            navbars = list(self.category.get_navbars().order_by('sort_rank'))
            navbar_context = [{
                'entry': x,
                'has_bits': has_edit_bits
            } for x in navbars]

            # add program entries
            navbar_context = list(
                qsd_tree_program(navbar_context, node, section, user))

            context = {
                'node': node,
                'has_edit_bits': has_edit_bits,
                'qsdTree': navbar_context,
                'section': section
            }

            return context
    def paynow_cybersource(self, request, tl, one, two, module, extra, prog):
        if self.have_paid():
            raise ESPError(
                False
            ), "You've already paid for this program; you can't pay again!"

        # Force users to pay for non-optional stuffs
        user = ESPUser(request.user)

        #   Default line item types
        li_types = self.program.getLineItemTypes(user)

        invoice = Document.get_invoice(user,
                                       self.program_anchor_cached(parent=True),
                                       li_types,
                                       dont_duplicate=True)
        context = {}
        context['module'] = self
        context['one'] = one
        context['two'] = two
        context['tl'] = tl
        context['user'] = user
        context['itemizedcosts'] = invoice.get_items()

        try:
            context['itemizedcosttotal'] = invoice.cost()
        except EmptyTransactionException:
            context['itemizedcosttotal'] = 0

        context['financial_aid'] = user.hasFinancialAid(prog.anchor)
        context['invoice'] = invoice

        return render_to_response(self.baseDir() + 'cardpay.html', request,
                                  (prog, tl), context)
Example #4
0
    def testGradeChange(self):
        # Create the admin user
        adminUser, c1 = ESPUser.objects.get_or_create(username='******')
        adminUser.set_password('password')
        adminUser.makeAdmin()
        # Create the student user
        studentUser, c2 = ESPUser.objects.get_or_create(username='******')
        # Make it a student
        studentUser.makeRole("Student")
        # Give it a starting grade
        student_studentinfo = StudentInfo(user=studentUser, graduation_year=ESPUser.YOGFromGrade(9))
        student_studentinfo.save()
        student_regprofile = RegistrationProfile(user=studentUser, student_info=student_studentinfo, most_recent_profile=True)
        student_regprofile.save()
        # Check that the grade starts at 9
        self.assertTrue(studentUser.getGrade() == 9)

        # Login the admin
        self.assertTrue(self.client.login(username="******", password="******"))

        testGrade = 11
        curYear = ESPUser.current_schoolyear()
        gradYear = curYear + (12 - testGrade)
        self.client.get("/manage/userview?username=student&graduation_year="+str(gradYear))
        self.assertTrue(studentUser.getGrade() == testGrade, "Grades don't match: %s %s" % (studentUser.getGrade(), testGrade))

        # Clean up
        if (c1):
            adminUser.delete()
        if (c2):
            studentUser.delete()
Example #5
0
    def view_app(self, request, tl, one, two, module, extra, prog):
        scrmi = prog.getModuleExtension('StudentClassRegModuleInfo')
        reg_nodes = scrmi.reg_verbs()
        
        try:
            cls = ClassSubject.objects.get(id = extra)
            section = cls.default_section()
        except ClassSubject.DoesNotExist:
            raise ESPError(False), 'Cannot find class.'
        
        student = request.GET.get('student',None)
        if not student:
            student = request.POST.get('student','')

        try:
            student = ESPUser(User.objects.get(id = student))
        except ESPUser.DoesNotExist:
            raise ESPError(False), 'Cannot find student, %s' % student

        if student.userbit_set.filter(qsc__parent=cls.anchor, verb__in=reg_nodes).count() == 0:
            raise ESPError(False), 'Student not a student of this class.'
        
        try:
            student.app = student.studentapplication_set.get(program = self.program)
        except:
            student.app = None
            assert False, student.studentapplication_set.all()[0].__dict__
            raise ESPError(False), 'Error: Student did not apply. Student is automatically rejected.'
        
        return render_to_response(self.baseDir()+'app_popup.html', request, (prog, tl), {'class': cls, 'student': student})
Example #6
0
 def teacherhandout(self,
                    request,
                    tl,
                    one,
                    two,
                    module,
                    extra,
                    prog,
                    template_file='teacherschedules.html'):
     #   Use the template defined in ProgramPrintables
     from esp.program.modules.handlers import ProgramPrintables
     context = {'module': self}
     pmos = ProgramModuleObj.objects.filter(
         program=prog, module__handler__icontains='printables')
     if pmos.count() == 1:
         pmo = ProgramPrintables(pmos[0])
         teacher = ESPUser(request.user)
         scheditems = []
         for cls in teacher.getTaughtClasses().filter(
                 parent_program=self.program):
             if cls.isAccepted():
                 for section in cls.sections.all():
                     scheditems.append({
                         'name': teacher.name(),
                         'teacher': teacher,
                         'cls': section
                     })
         scheditems.sort()
         context['scheditems'] = scheditems
         return render_to_response(pmo.baseDir() + template_file, request,
                                   context)
     else:
         raise ESPError(
             False
         ), 'No printables module resolved, so this document cannot be generated.  Consult the webmasters.'
Example #7
0
    def testGradeChange(self):
        # Create the admin user
        adminUser, c1 = ESPUser.objects.get_or_create(username='******')
        adminUser.set_password('password')
        make_user_admin(adminUser)
        # Create the student user
        studentUser, c2 = ESPUser.objects.get_or_create(username='******')
        # Make it a student
        role_bit, created = UserBit.objects.get_or_create(user=studentUser, qsc=GetNode('Q'), verb=GetNode('V/Flags/UserRole/Student'), recursive=False)
        # Give it a starting grade
        student_studentinfo = StudentInfo(user=studentUser, graduation_year=ESPUser.YOGFromGrade(9))
        student_studentinfo.save()
        student_regprofile = RegistrationProfile(user=studentUser, student_info=student_studentinfo, most_recent_profile=True)
        student_regprofile.save()
        # Check that the grade starts at 9
        self.failUnless(studentUser.getGrade() == 9)

        # Login the admin
        self.failUnless(self.client.login(username="******", password="******"))

        testGrade = 11
        curYear = ESPUser.current_schoolyear()
        gradYear = curYear + (12 - testGrade)
        self.client.get("/manage/userview?username=student&graduation_year="+str(gradYear))
        self.failUnless(studentUser.getGrade() == testGrade, "Grades don't match: %s %s" % (studentUser.getGrade(), testGrade))

        # Clean up
        if (c1):
            adminUser.delete()
        if (c2):
            studentUser.delete()
 def rapidcheckin(self, request, tl, one, two, module, extra, prog):
     context = {}
     if request.method == 'POST':
         #   Handle submission of student
         form = OnSiteRapidCheckinForm(request.POST)
         if form.is_valid():
             student = ESPUser(form.cleaned_data['user'])
             #   Check that this is a student user who is not also teaching (e.g. an admin)
             if student.isStudent() and student not in self.program.teachers()['class_approved']:
                 recs = Record.objects.filter(user=student, event="attended", program=prog)
                 if not recs.exists():
                     rec, created = Record.objects.get_or_create(user=student, event="attended", program=prog)
                 context['message'] = '%s %s marked as attended.' % (student.first_name, student.last_name)
                 if request.is_ajax():
                     return self.ajax_status(request, tl, one, two, module, extra, prog, context)
             else:
                 context['message'] = '%s %s is not a student and has not been checked in' % (student.first_name, student.last_name)
                 if request.is_ajax():
                     return self.ajax_status(request, tl, one, two, module, extra, prog, context)
     else:
         form = OnSiteRapidCheckinForm()
     
     context['module'] = self
     context['form'] = form
     return render_to_response(self.baseDir()+'ajaxcheckin.html', request, context)
Example #9
0
def schoolyear(request):
    path_parts = request.path.lstrip('/').split('/')
    if len(path_parts) > 3:
        program_url = '/'.join(path_parts[1:3])
        if Program.objects.filter(url=program_url).count() == 1:
            program = Program.objects.get(url=program_url)
            return {'schoolyear': ESPUser.program_schoolyear(program)}
    return {'schoolyear': ESPUser.current_schoolyear()}
def schoolyear(request):
    path_parts = request.path.lstrip('/').split('/')
    if len(path_parts) > 3:
        program_url = '/'.join(path_parts[1:3])
        if Program.objects.filter(url=program_url).count() == 1:
            program = Program.objects.get(url=program_url)
            return {'schoolyear': ESPUser.program_schoolyear(program)}
    return {'schoolyear': ESPUser.current_schoolyear()}
Example #11
0
def myesp_switchback(request, module):
	user = request.user
	user = ESPUser(user)
	user.updateOnsite(request)

	if not user.other_user:
		raise ESPError(False), 'You were not another user!'

	return HttpResponseRedirect(user.switch_back(request))
Example #12
0
def survey_review_single(request, tl, program, instance):
    """ View a single survey response. """
    try:
        prog = Program.by_prog_inst(program, instance)
    except Program.DoesNotExist:
        #raise Http404
        raise ESPError(), "Can't find the program %s/%s" % (program, instance)

    user = ESPUser(request.user)

    survey_response = None
    ints = request.REQUEST.items()
    if len(ints) == 1:
        srs = SurveyResponse.objects.filter(id=ints[0][0])
        if len(srs) == 1:
            survey_response = srs[0]
    if survey_response is None:
        raise ESPError(
            False
        ), 'Ideally this page should give you some way to pick an individual response. For now I guess you should go back to <a href="review">reviewing the whole survey</a>.'

    if tl == 'manage' and user.isAdmin(prog):
        answers = survey_response.answers.order_by('content_type', 'object_id',
                                                   'question')
        classes_only = False
        other_responses = None
    elif tl == 'teach':
        subject_ct = ContentType.objects.get(app_label="program",
                                             model="classsubject")
        section_ct = ContentType.objects.get(app_label="program",
                                             model="classsection")
        class_ids = [x["id"] for x in user.getTaughtClasses().values('id')]
        section_ids = [x["id"] for x in user.getTaughtSections().values('id')]
        answers = survey_response.answers.filter(
            content_type__in=[subject_ct, section_ct],
            object_id__in=(class_ids + section_ids)).order_by(
                'content_type', 'object_id', 'question')
        classes_only = True
        other_responses = SurveyResponse.objects.filter(
            answers__content_type=subject_ct,
            answers__object_id__in=class_ids).order_by('id').distinct()
    else:
        raise ESPError(
            False
        ), 'You need to be a teacher or administrator of this program to review survey responses.'

    context = {
        'user': user,
        'program': prog,
        'response': survey_response,
        'answers': answers,
        'classes_only': classes_only,
        'other_responses': other_responses
    }

    return render_to_response('survey/review_single.html', request, context)
Example #13
0
    def prepare_context(self, program, target_path=None):
        context = {}
        context['program'] = program
        context['user_types'] = ESPUser.getTypes()
        category_lists = {}
        list_descriptions = program.getListDescriptions()

        #   Add in program-specific lists for most common user types
        for user_type, list_func in zip(Program.USER_TYPES_WITH_LIST_FUNCS,
                                        Program.USER_TYPE_LIST_FUNCS):
            raw_lists = getattr(program, list_func)(True)
            category_lists[user_type] = [{
                'name': key,
                'list': raw_lists[key],
                'description': list_descriptions[key]
            } for key in raw_lists]
            for item in category_lists[user_type]:
                if item['name'] in UserSearchController.preferred_lists:
                    item['preferred'] = True

        #   Add in global lists for each user type
        for user_type in ESPUser.getTypes():
            key = user_type.lower() + 's'
            if user_type not in category_lists:
                category_lists[user_type] = []
            category_lists[user_type].insert(
                0, {
                    'name': 'all_%s' % user_type,
                    'list': ESPUser.getAllOfType(user_type),
                    'description': 'All %s in the database' % key,
                    'preferred': True,
                    'all_flag': True
                })

        #   Add in mailing list accounts
        category_lists['emaillist'] = [{
            'name': 'all_emaillist',
            'list': Q(password='******'),
            'description': 'Everyone signed up for the mailing list',
            'preferred': True
        }]

        context['lists'] = category_lists
        context['all_list_names'] = []
        for category in category_lists:
            for item in category_lists[category]:
                context['all_list_names'].append(item['name'])

        if target_path is None:
            target_path = '/manage/%s/commpanel' % program.getUrlBase()
        context['action_path'] = target_path
        context['groups'] = Group.objects.all()

        return context
Example #14
0
def user_registration_validate(request):    
    """Handle the account creation logic when the form is submitted

This function is overloaded to handle either one or two phase reg"""

    if not Tag.getBooleanTag("ask_about_duplicate_accounts",default=False):
        form = SinglePhaseUserRegForm(request.POST)
    else:
        form = UserRegForm(request.POST)

    if form.is_valid():         
        try:
            #there is an email-only account with that email address to upgrade
            user = ESPUser.objects.get(email=form.cleaned_data['email'],
                                       password = '******')
        except ESPUser.DoesNotExist:
            try:
                #there is an inactive account with that username
                user = ESPUser.objects.filter(
                    username = form.cleaned_data['username'],
                    is_active = False).latest('date_joined')

            except ESPUser.DoesNotExist:
                user = ESPUser(email = form.cleaned_data['email'])

        user.username   = form.cleaned_data['username']
        user.last_name  = form.cleaned_data['last_name']
        user.first_name = form.cleaned_data['first_name']
        user.set_password(form.cleaned_data['password'])
            
        #   Append key to password and disable until activation if desired
        if Tag.getBooleanTag('require_email_validation', default=False):
            userkey = random.randint(0,2**31 - 1)
            user.password += "_%d" % userkey
            user.is_active = False

        user.save()
        ESPUser_Profile.objects.get_or_create(user = user)

        user.groups.add(Group.objects.get(name=form.cleaned_data['initial_role']))

        if not Tag.getBooleanTag('require_email_validation', default=False):
            user = authenticate(username=form.cleaned_data['username'],
                                    password=form.cleaned_data['password'])
                
            login(request, user)
            return HttpResponseRedirect('/myesp/profile/')
        else:
            send_activation_email(user,userkey)
            return render_to_response('registration/account_created_activation_required.html', request,
                                      {'user': user, 'site': Site.objects.get_current()})
    else:
        return render_to_response('registration/newuser.html',
                                  request, {'form':form})
Example #15
0
def preview_miniblog(request, section=None):
    """this function will return the last n miniblog entries from preview_miniblog """
    # last update: Axiak

    if request.user != None:
        curUser = ESPUser(request.user)

    else:
        curUser = ESPUser(AnonymousUser())

    return curUser.getMiniBlogEntries()
Example #16
0
def prepare_program(program, data):
    """ This function adds custom stuff to save_instance to facilitate making programs happen.
    """

    #   Datatrees format: each item is a tuple of (node URI, friendly name)
    datatrees = []
    #   Userbits format: each item is a tuple of (QSC URI, user ID, startdate, enddate)
    userbits = []
    modules = []

    # Fetch/create the program node
    program_node_name = program.anchor.get_uri() + '/' + data['term']

    # Create the DataTree branches
    for sub_node in ProgramTemplate:
        datatrees += [(program_node_name + sub_node, '')]

    userbits += [('V/Flags/Public', None, data['publish_start'], data['publish_end'])]
    
    userbits += [('V/Deadline/Registration/Student', None, data['student_reg_start'], data['student_reg_end'])]
    #userbits += [('V/Deadline/Registration/Student/Applications', None, data['student_reg_start'], data['student_reg_end'])]
    userbits += [('V/Deadline/Registration/Student/Catalog', None, data['student_reg_start'], None)]
    #userbits += [('V/Deadline/Registration/Student/Classes', None, data['student_reg_start'], data['student_reg_end'])]
    #userbits += [('V/Deadline/Registration/Student/Classes/OneClass', None, data['student_reg_start'], data['student_reg_end'])]
    #userbits += [('V/Deadline/Registration/Student/Confirm', None, data['student_reg_start'], data['publish_end'])]
    #userbits += [('V/Deadline/Registration/Student/ExtraCosts', None, data['student_reg_start'], data['student_reg_end'])]
    #userbits += [('V/Deadline/Registration/Student/MainPage', None, data['student_reg_start'], data['publish_end'])]
    #userbits += [('V/Deadline/Registration/Student/Payment', None, data['student_reg_start'], data['publish_end'])]
    
    userbits += [('V/Deadline/Registration/Teacher', None, data['teacher_reg_start'], data['teacher_reg_end'])]
    #userbits += [('V/Deadline/Registration/Teacher/Catalog', None, data['teacher_reg_start'], None)]
    #userbits += [('V/Deadline/Registration/Teacher/Classes', None, data['teacher_reg_start'], data['teacher_reg_end'])]
    userbits += [('V/Deadline/Registration/Teacher/Classes/View', None, data['teacher_reg_start'], None)]
    userbits += [('V/Deadline/Registration/Teacher/MainPage', None, data['teacher_reg_start'], None)]
    userbits += [('V/Deadline/Registration/Teacher/Profile', None, data['teacher_reg_start'], None)]
    
    #   Grant onsite bit (for all times) if an onsite user is available.
    if ESPUser.onsite_user():
        userbits += [('V/Registration/OnSite', ESPUser.onsite_user(), None, None)]
    
    for director in data['admins']:
        userbits += [('V/Administer', ESPUser.objects.get(id=int(director)), None, None)]
        
    json_module = ProgramModule.objects.get(handler=u'JSONDataModule')  # get the JSON Data Module
    # If the JSON Data Module isn't already in the list of selected
    # program modules, add it. The JSON Data Module is a dependency for
    # many commonly-used modules, so it is important that it be enbabled
    # by default for all new programs.
    if json_module.id not in data['program_modules']:
        data['program_modules'].append(json_module.id)
    modules += [(str(ProgramModule.objects.get(id=i)), i) for i in data['program_modules']]
       
    return datatrees, userbits, modules
Example #17
0
    def _checkAdmin(moduleObj, request, *args, **kwargs):
        if not_logged_in(request):
            return HttpResponseRedirect('%s?%s=%s' % (LOGIN_URL, REDIRECT_FIELD_NAME, quote(request.get_full_path())))

        if not request.user.isOnsite(moduleObj.program) and not request.user.isAdmin(moduleObj.program):
            user = request.user
            user = ESPUser(user)
            user.updateOnsite(request)
            ouser = user.get_old(request)
            if not user.other_user or (not ouser.isOnsite(moduleObj.program) and not ouser.isAdmin(moduleObj.program)):
                return render_to_response('errors/program/notonsite.html', request, (moduleObj.program, 'onsite'), {})
        return method(moduleObj, request, *args, **kwargs)
Example #18
0
def login_checked(request, *args, **kwargs):
    if request.user.is_authenticated():
        #   Set response cookies in case of repeat login
        reply = HttpMetaRedirect('/')
        reply._new_user = request.user
        reply.no_set_cookies = False
        return reply

    reply = login(request, *args, **kwargs)

    # Check for user forwarders
    if request.user.is_authenticated():
        old_username = request.user.username
        user, forwarded = UserForwarder.follow(ESPUser(request.user))
        if forwarded:
            auth_logout(request)
            auth_login(request, user)
            # Try to display a friendly error message
            next_uri = reply.get('Location', '').strip()
            if next_uri:
                context = {
                    'request': request,
                    'old_username': old_username,
                    'next_uri': next_uri,
                    'next_title': next_uri,
                }
                if next_uri == '/':
                    context['next_title'] = 'the home page'
                return render_to_response('users/login_duplicate_warning.html',
                                          request,
                                          request.get_node('Q/Web/myesp'),
                                          context)

    mask_locations = ['/', '/myesp/signout/', '/admin/logout/']
    if reply.get('Location', '') in mask_locations:
        # We're getting redirected to somewhere undesirable.
        # Let's try to do something smarter.
        request.user = ESPUser(request.user)
        if request.user.isTeacher():
            reply = HttpMetaRedirect("/teach/index.html")
        else:
            reply = HttpMetaRedirect("/learn/index.html")
    elif reply.status_code == 302:
        #   Even if the redirect was going to a reasonable place, we need to
        #   turn it into a 200 META redirect in order to set the cookies properly.
        request.user = ESPUser(request.user)
        reply = HttpMetaRedirect(reply.get('Location', ''))

    #   Stick the user in the response in order to set cookies if necessary
    reply._new_user = request.user
    reply.no_set_cookies = False

    return reply
Example #19
0
    def process(self, processoverride=False):
        """ Process this request...if it's an email, create all the necessary email requests. """

        # if we already processed, return
        if self.processed and not processoverride:
            return

        # there's no real thing for this...yet
        if not self.email_all:
            return

        # this is for thread-safeness...
        self.processed = True
        self.save()

        # figure out who we're sending from...
        if self.sender is not None and len(self.sender.strip()) > 0:
            send_from = self.sender
        else:
            if self.creator is not None:
                send_from = '%s <%s>' % (ESPUser(
                    self.creator).name(), self.creator.email)
            else:
                send_from = 'ESP Web Site <*****@*****.**>'

        users = self.recipients.getList(ESPUser)
        try:
            users = users.distinct()
        except:
            pass

        # go through each user and parse the text...then create the proper
        # emailrequest and textofemail object
        for user in users:
            user = ESPUser(user)
            newemailrequest = EmailRequest(target=user, msgreq=self)

            newtxt = TextOfEmail(
                send_to='%s <%s>' % (user.name(), user.email),
                send_from=send_from,
                subject=self.parseSmartText(self.subject, user),
                msgtext=self.parseSmartText(self.msgtext, user),
                sent=None)

            newtxt.save()

            newemailrequest.textofemail = newtxt

            newemailrequest.save()

        print 'Prepared e-mails to send for message request %d: %s' % (
            self.id, self.subject)
Example #20
0
def viewResponse(request, form_id):
    """
    Viewing response data
    """
    if request.user.is_authenticated and (ESPUser(request.user).isTeacher()
                                          or ESPUser(
                                              request.user).isAdministrator()):
        try:
            form_id = int(form_id)
        except ValueError:
            raise Http404
        form = Form.objects.get(id=form_id)
        return render_to_response('customforms/view_results.html',
                                  {'form': form})
    else:
        return HttpResponseRedirect('/')
Example #21
0
    def printschedules(self, request, tl, one, two, module, extra, prog):
        " A link to print a schedule. "
        if not request.GET.has_key('sure') and not request.GET.has_key('gen_img'):
            printers = Printer.objects.all().values_list('name', flat=True)

            return render_to_response(self.baseDir()+'instructions.html',
                                    request, {'printers': printers})

        if request.GET.has_key('sure'):
            return render_to_response(self.baseDir()+'studentschedulesrenderer.html',
                            request, {})

        requests = PrintRequest.objects.filter(time_executed__isnull=True)
        if extra and Printer.objects.filter(name=extra).exists():
            requests = requests.filter(printer__name=extra)

        for req in requests:
            req.time_executed = datetime.now()
            req.save()

        # get students
        old_students = set([ ESPUser(req.user) for req in requests ])

        if len(old_students) > 0:
            response = ProgramPrintables.get_student_schedules(request, list(old_students), prog, onsite=True)       
        # set the refresh rate
        #response['Refresh'] = '2'
            return response
        else:
            # No response if no users
            return HttpResponse('')
Example #22
0
    def process(self, user, user_match):
        try:
            user = ESPUser.objects.get(username__iexact = user)
        except ESPUser.DoesNotExist:
            return

        user = ESPUser(user)

        # DIRTY HACK to allow mailing aliases to still work for local Mailman messages
        if user.isTeacher() or self.message['List-Id']:
            del(self.message['to'])
            self.message['to'] = user.email
            self.direct_send = True
            self.send = True

        return
Example #23
0
def userview(request):
    """ Render a template displaying all the information about the specified user """
    try:
        user = ESPUser.objects.get(username=request.GET['username'])
    except:
        raise ESPError(False), "Sorry, can't find anyone with that username."

    teacherbio = TeacherBio.getLastBio(user)
    if not teacherbio.picture:
        teacherbio.picture = 'images/not-available.jpg'
    
    from esp.users.forms.user_profile import StudentInfoForm
    
    if 'graduation_year' in request.GET:
        student_info = user.getLastProfile().student_info
        student_info.graduation_year = int(request.GET['graduation_year'])
        student_info.save()
    
    change_grade_form = StudentInfoForm(user=user)
    if 'disabled' in change_grade_form.fields['graduation_year'].widget.attrs:
        del change_grade_form.fields['graduation_year'].widget.attrs['disabled']
    change_grade_form.fields['graduation_year'].initial = ESPUser.YOGFromGrade(user.getGrade())
    change_grade_form.fields['graduation_year'].choices = filter(lambda choice: bool(choice[0]), change_grade_form.fields['graduation_year'].choices)
    
    context = {
        'user': user,
        'taught_classes' : user.getTaughtClasses().order_by('parent_program', 'id'),
        'enrolled_classes' : user.getEnrolledSections().order_by('parent_class__parent_program', 'id'),
        'taken_classes' : user.getSections().order_by('parent_class__parent_program', 'id'),
        'teacherbio': teacherbio,
        'domain': settings.SITE_INFO[1],
        'change_grade_form': change_grade_form,
    }
    return render_to_response("users/userview.html", request, context )
Example #24
0
    def gen_perm(tup):
        new_perm = Permission(permission_type=tup[0], program=prog)

        if tup[2]:
            new_perm.start_date = tup[2]
        if tup[3]:
            new_perm.end_date = tup[3]

        if tup[1] is not None:
            new_perm.user = tup[1]
            new_perm.save()
            return
        elif tup[1] is None and tup[0].startswith("Student"):
            new_perm.role = Group.objects.get(name="Student")
            new_perm.save()
            return
        elif tup[1] is None and tup[0].startswith("Teacher"):
            new_perm.role = Group.objects.get(name="Teacher")
            new_perm.save()
            return

        #It's not for a specific user and not a teacher or student deadline
        for x in ESPUser.getTypes():
            newnew_perm = Permission(permission_type=new_perm.permission_type,
                                     role=Group.objects.get(name=x),
                                     start_date=new_perm.start_date,
                                     end_date=new_perm.end_date,
                                     program=prog)
            newnew_perm.save()
Example #25
0
def hasPerm(user, form):
    """
    Checks if this user qualifies to view this form
    """
    if (not form.anonymous
            or form.perms != "") and not user.is_authenticated():
        return False, "You need to be logged in to view this form."
    if form.perms == "":
        return True, ""
    else:
        perms_list = form.perms.strip(',').split(',')
        main_perm = perms_list[0]
        prog_id = ""
        sub_perms = None
        if len(perms_list) > 1:
            prog_id = perms_list[1]
            if len(perms_list) > 2:
                sub_perms = perms_list[2:]
        Qlist = []
        Qlist.append(ESPUser.getAllOfType(
            main_perm))  # Check -> what to do with students?
        if sub_perms:
            if prog_id != "":
                prog = Program.objects.get(pk=int(prog_id))
                all_Qs = prog.getLists(QObjects=True)
                for perm in sub_perms:
                    Qlist.append(all_Qs[perm]['list'])
        if ESPUser.objects.filter(id=user.id).filter(*Qlist).exists():
            return True, ""
        else:
            return False, "You are not permitted to view this form."
Example #26
0
    def students_status(self, request, tl, one, two, module, extra, prog):
        resp = HttpResponse(mimetype='application/json')
        grade_query = """
SELECT (12 + %d - "users_studentinfo"."graduation_year")
FROM "users_studentinfo", "program_registrationprofile"
WHERE
    "program_registrationprofile"."most_recent_profile" = true
AND	"program_registrationprofile"."student_info_id" = "users_studentinfo"."id"
AND	"users_studentinfo"."user_id" = "auth_user"."id"
ORDER BY program_registrationprofile.id DESC
LIMIT 1
        """ % ESPUser.current_schoolyear()
        #   Try to ensure we don't miss anyone
        students_dict = self.program.students(QObjects=True)
        student_types = [
            'student_profile'
        ]  #   You could add more list names here, but it would get very slow.
        students_Q = Q()
        for student_type in student_types:
            students_Q = students_Q | students_dict[student_type]
        students = ESPUser.objects.filter(students_Q).distinct()
        data = students.extra({
            'grade': grade_query
        }).values_list('id', 'last_name', 'first_name', 'grade').distinct()
        simplejson.dump(list(data), resp)
        return resp
    def __init__(self, *args, **kwargs):
        #   Set up the default form
        super(UserRegForm, self).__init__(*args, **kwargs)

        #   Adjust initial_role choices
        role_choices = [(item[0], item[1]['label']) for item in ESPUser.getAllUserTypes()]
        self.fields['initial_role'].choices = [('', 'Pick one...')] + role_choices
Example #28
0
    def testMorph(self):
        class scratchCls(object):
            pass

        class scratchDict(dict):
            def cycle_key(self):
                pass

            def flush(self):
                for i in self.keys():
                    del self[i]

        # Make up a fake request object
        # This definitely doesn't meet the spec of the real request object;
        # if tests fail as a result in the future, it'll need to be fixed.
        request = scratchCls()

        request.backend = 'django.contrib.auth.backends.ModelBackend'
        request.user = None
        request.session = scratchDict()

        # Create a couple users and a userbit
        self.user, created = ESPUser.objects.get_or_create(
            username='******')
        self.userbit = UserBit.objects.get_or_create(
            user=self.user, verb=GetNode('V/Administer'), qsc=GetNode('Q'))

        self.basic_user, created = ESPUser.objects.get_or_create(
            username='******')
        self.userbit = UserBit.objects.get_or_create(
            user=self.basic_user,
            verb=GetNode('V/Flags/UserRole/Student'),
            qsc=GetNode('Q'))

        self.user.backend = request.backend
        self.basic_user.backend = request.backend

        login(request, self.user)
        self.assertEqual(request.user, self.user,
                         "Failed to log in as '%s'" % self.user)

        request.user.switch_to_user(request, self.basic_user, None, None)
        self.assertEqual(request.user, self.basic_user,
                         "Failed to morph into '%s'" % self.basic_user)

        request.user.switch_back(request)
        self.assertEqual(request.user, self.user,
                         "Failed to morph back into '%s'" % self.user)

        blocked_illegal_morph = True
        try:
            ESPUser(request.user).switch_to_user(request, self.basic_user,
                                                 None, None)
            self.assertEqual(request.user, self.basic_user,
                             "Failed to morph into '%s'" % self.basic_user)
        except ESPError():
            blocked_illegal_morph = True

        self.assertTrue(blocked_illegal_morph,
                        "User '%s' was allowed to morph into an admin!")
Example #29
0
    def gen_perm(tup):
        new_perm=Permission(permission_type=tup[0], program=prog)

        if tup[2]:
            new_perm.start_date = tup[2]
        if tup[3]:
            new_perm.end_date = tup[3]

        if tup[1] is not None:
            new_perm.user=tup[1]
            new_perm.save()
            return
        elif tup[1] is None and tup[0].startswith("Student"):
            new_perm.role=Group.objects.get(name="Student")
            new_perm.save()
            return
        elif tup[1] is None and tup[0].startswith("Teacher"):
            new_perm.role=Group.objects.get(name="Teacher")
            new_perm.save()
            return

        #It's not for a specific user and not a teacher or student deadline
        for x in ESPUser.getTypes():
            newnew_perm=Permission(permission_type=new_perm.permission_type, role=Group.objects.get(name=x), start_date=new_perm.start_date, end_date=new_perm.end_date, program=prog)
            newnew_perm.save()
    def payonline(self, request, tl, one, two, module, extra, prog):

        user = ESPUser(request.user)

        iac = IndividualAccountingController(self.program, request.user)
        context = {}
        context['module'] = self
        context['one'] = one
        context['two'] = two
        context['tl'] = tl
        context['user'] = user
        context['invoice_id'] = iac.get_id()
        context['identifier'] = iac.get_identifier()
        payment_type = iac.default_payments_lineitemtype()
        sibling_type = iac.default_siblingdiscount_lineitemtype()
        grant_type = iac.default_finaid_lineitemtype()
        context['itemizedcosts'] = iac.get_transfers().exclude(
            line_item__in=[payment_type, sibling_type, grant_type]).order_by(
                '-line_item__required')
        context['itemizedcosttotal'] = iac.amount_due()
        context['subtotal'] = iac.amount_requested()
        context['financial_aid'] = iac.amount_finaid()
        context['sibling_discount'] = iac.amount_siblingdiscount()
        context['amount_paid'] = iac.amount_paid()

        if 'HTTP_HOST' in request.META:
            context['hostname'] = request.META['HTTP_HOST']
        else:
            context['hostname'] = Site.objects.get_current().domain
        context['institution'] = settings.INSTITUTION_NAME
        context['storename'] = self.store_id
        context['support_email'] = settings.DEFAULT_EMAIL_ADDRESSES['support']

        return render_to_response(self.baseDir() + 'cardpay.html', request,
                                  context)
    def paynow_cybersource(self, request, tl, one, two, module, extra, prog):

        # Force users to pay for non-optional stuffs
        user = ESPUser(request.user)

        iac = IndividualAccountingController(self.program, request.user)
        context = {}
        context['module'] = self
        context['one'] = one
        context['two'] = two
        context['tl'] = tl
        context['user'] = user
        context['invoice_id'] = iac.get_id()
        context['identifier'] = iac.get_identifier()
        payment_type = iac.default_payments_lineitemtype()
        sibling_type = iac.default_siblingdiscount_lineitemtype()
        grant_type = iac.default_finaid_lineitemtype()
        context['itemizedcosts'] = iac.get_transfers().exclude(
            line_item__in=[payment_type, sibling_type, grant_type]).order_by(
                '-line_item__required')
        context['itemizedcosttotal'] = iac.amount_due()
        context['subtotal'] = iac.amount_requested()
        context['financial_aid'] = iac.amount_finaid()
        context['sibling_discount'] = iac.amount_siblingdiscount()
        context['amount_paid'] = iac.amount_paid()

        return render_to_response(self.baseDir() + 'cardpay.html', request,
                                  context)
Example #32
0
    def testGradeChange(self):
        # Create the admin user
        adminUser, c1 = ESPUser.objects.get_or_create(username='******')
        adminUser.set_password('password')
        adminUser.makeAdmin()
        # Create the student user
        studentUser, c2 = ESPUser.objects.get_or_create(username='******')
        # Make it a student
        studentUser.makeRole("Student")
        # Give it a starting grade
        student_studentinfo = StudentInfo(user=studentUser, graduation_year=ESPUser.YOGFromGrade(9))
        student_studentinfo.save()
        student_regprofile = RegistrationProfile(user=studentUser, student_info=student_studentinfo, most_recent_profile=True)
        student_regprofile.save()
        # Check that the grade starts at 9
        self.assertTrue(studentUser.getGrade() == 9)

        # Login the admin
        self.assertTrue(self.client.login(username="******", password="******"))

        testGrade = 11
        curYear = ESPUser.current_schoolyear()
        gradYear = curYear + (12 - testGrade)
        self.client.get("/manage/userview?username=student&graduation_year="+str(gradYear))
        self.assertTrue(studentUser.getGrade() == testGrade, "Grades don't match: %s %s" % (studentUser.getGrade(), testGrade))

        # Clean up
        if (c1):
            adminUser.delete()
        if (c2):
            studentUser.delete()
Example #33
0
def hasPerm(user, form):
    """
    Checks if this user qualifies to view this form
    """
    if (not form.anonymous or form.perms!="") and not user.is_authenticated():
        return False, "You need to be logged in to view this form."
    if form.perms == "":
        return True, ""
    else:
        perms_list = form.perms.strip(',').split(',')
        main_perm = perms_list[0]
        prog_id = ""
        sub_perms = None
        if len(perms_list)>1:
            prog_id = perms_list[1]
            if len(perms_list)>2:
                sub_perms = perms_list[2:]
        Qlist = []
        Qlist.append(ESPUser.getAllOfType(main_perm))  # Check -> what to do with students?
        if sub_perms:
            if prog_id != "":
                prog = Program.objects.get(pk=int(prog_id))
                all_Qs = prog.getLists(QObjects=True)
                for perm in sub_perms:
                    Qlist.append(all_Qs[perm]['list'])
        if ESPUser.objects.filter(id=user.id).filter(*Qlist).exists():
            return True, ""
        else:
            return False, "You are not permitted to view this form."
Example #34
0
def idebug_hook(request, context):

    if not hasattr(request, 'idebug') or not request.idebug:
        return

    # Exit quickly if we're not logged in and no GET flag was given
    logged_in = hasattr(request, 'user') and hasattr(
        request, 'session') and request.user.is_authenticated()
    has_idebug = 'idebug' in request.GET
    if not logged_in and not has_idebug:
        return

    is_admin = logged_in and ESPUser(request.user).isAdministrator()

    idebug_pw = request.GET['idebug'] if has_idebug else ''
    show = False

    if 'idebug' in request.session:
        show = request.session['idebug']

    if is_admin and has_idebug and idebug_pw == '':
        show = True

    if is_admin and has_idebug and (idebug_pw in ('1', 'on', 'yes', 'True')):
        show = True
        request.session['idebug'] = True

    if idebug_pw in ('0', 'off', 'no', 'False'):
        show = False
        request.session['idebug'] = False

    if hasattr(settings,
               'IDEBUG_PASSWORD') and len(settings.IDEBUG_PASSWORD) > 4:
        if idebug_pw == settings.IDEBUG_PASSWORD:
            show = True

    if not show:
        return

    idebug_data = list()

    # Add the query info first, so we don't capture queries performed during context dump
    for q in connection.queries:
        idebug_data.append(('QUERY', '(%ss) %s' % (q['time'], q['sql'])))

    # Add in cache info
    if hasattr(cache, 'queries'):
        for q in cache.queries:
            idebug_data.append(
                ('CACHE',
                 '%s(\'%s\') = \'%s\'' % (q['method'], q['key'], q['value'])))

    # Loop through the context and dump the contents intelligently
    for subdict in context:
        for k, v in subdict.iteritems():
            idebug_data.append((k, debug_print(k, v)))

    context['idebug'] = idebug_data
    return
Example #35
0
    def save(self):
        #   Reset user's offers
        if self.cleaned_data['user']:
            user = ESPUser.objects.get(id=self.cleaned_data['user'])
            user.volunteeroffer_set.all().delete()

        if self.cleaned_data.get('clear_requests', False):
            #   They want to cancel all shifts - don't do anything further.
            return []

        #   Create user if one doesn't already exist, otherwise associate a user.
        #   Note that this will create a new user account if they enter an e-mail
        #   address different from the one on file.
        if not self.cleaned_data['user']:
            user_data = {
                'first_name': self.cleaned_data['name'].split()[0],
                'last_name': ' '.join(self.cleaned_data['name'].split()[1:]),
                'email': self.cleaned_data['email'],
            }
            existing_users = ESPUser.objects.filter(
                **user_data).order_by('-id')
            if existing_users.exists():
                #   Arbitrarily pick the most recent account
                #   This is not too important, we just need a link to an e-mail address.
                user = existing_users[0]
            else:
                auto_username = ESPUser.get_unused_username(
                    user_data['first_name'], user_data['last_name'])
                user = ESPUser.objects.create_user(auto_username,
                                                   user_data['email'])
                user.__dict__.update(user_data)
                user.save()

        #   Record this user account as a volunteer
        user.makeVolunteer()

        #   Remove offers with the same exact contact info
        VolunteerOffer.objects.filter(email=self.cleaned_data['email'],
                                      phone=self.cleaned_data['phone'],
                                      name=self.cleaned_data['name']).delete()

        offer_list = []
        for req in self.cleaned_data['requests']:
            o = VolunteerOffer()
            o.user_id = user.id
            o.email = self.cleaned_data['email']
            o.phone = self.cleaned_data['phone']
            o.name = self.cleaned_data['name']
            o.confirmed = self.cleaned_data['confirm']
            if 'shirt_size' in self.cleaned_data:
                o.shirt_size = self.cleaned_data['shirt_size']
            if 'shirt_type' in self.cleaned_data:
                o.shirt_type = self.cleaned_data['shirt_type']
            if 'comments' in self.cleaned_data:
                o.comments = self.cleaned_data['comments']
            o.request_id = req
            o.save()
            offer_list.append(o)
        return offer_list
    def studentDesc(self):
        #   Label these heading nicely like the user registration form
        role_choices = ESPUser.getAllUserTypes()
        role_dict = {}
        for item in role_choices:
            role_dict[item[0]] = item[1]

        return {'classreg': """Students who signed up for at least one class""",
                'enrolled': """Students who are enrolled in at least one class"""}
    def save(self):
        #   Reset user's offers
        if self.cleaned_data['user']:
            user = ESPUser.objects.get(id=self.cleaned_data['user'])
            user.volunteeroffer_set.all().delete()

        if self.cleaned_data.get('clear_requests', False):
            #   They want to cancel all shifts - don't do anything further.
            return []

        #   Create user if one doesn't already exist, otherwise associate a user.
        #   Note that this will create a new user account if they enter an e-mail
        #   address different from the one on file.
        if not self.cleaned_data['user']:
            user_data = {'first_name': self.cleaned_data['name'].split()[0],
                         'last_name': ' '.join(self.cleaned_data['name'].split()[1:]),
                         'email': self.cleaned_data['email'],
                        }
            existing_users = ESPUser.objects.filter(**user_data).order_by('-id')
            if existing_users.exists():
                #   Arbitrarily pick the most recent account
                #   This is not too important, we just need a link to an e-mail address.
                user = existing_users[0]
            else:
                auto_username = ESPUser.get_unused_username(user_data['first_name'], user_data['last_name'])
                user = ESPUser.objects.create_user(auto_username, user_data['email'])
                user.__dict__.update(user_data)
                user.save()

        #   Record this user account as a volunteer
        user.makeVolunteer()

        #   Remove offers with the same exact contact info
        VolunteerOffer.objects.filter(email=self.cleaned_data['email'], phone=self.cleaned_data['phone'], name=self.cleaned_data['name']).delete()

        offer_list = []
        for req in self.cleaned_data['requests']:
            o = VolunteerOffer()
            o.user_id = user.id
            o.email = self.cleaned_data['email']
            o.phone = self.cleaned_data['phone']
            o.name = self.cleaned_data['name']
            o.confirmed = self.cleaned_data['confirm']
            if 'shirt_size' in self.cleaned_data:
                o.shirt_size = self.cleaned_data['shirt_size']
            if 'shirt_type' in self.cleaned_data:
                o.shirt_type = self.cleaned_data['shirt_type']
            if 'comments' in self.cleaned_data:
                o.comments = self.cleaned_data['comments']
            o.request_id = req
            o.save()
            offer_list.append(o)
        return offer_list
Example #38
0
def prepare_program(program, data):
    """ This function adds custom stuff to save_instance to facilitate making programs happen.
    """

    #   Permissions format:
    perms = []
    modules = []

    perms += [('Student/All', None, data['student_reg_start'], data['student_reg_end'])] #it is recursive
    perms += [('Student/Catalog', None, data['student_reg_start'], None)]
    perms += [('Student/Profile', None, data['student_reg_start'], None)]
    perms += [('Teacher/All', None, data['teacher_reg_start'], data['teacher_reg_end'])]
    perms += [('Teacher/Classes/View', None, data['teacher_reg_start'], None)]
    perms += [('Teacher/MainPage', None, data['teacher_reg_start'], None)]
    perms += [('Teacher/Profile', None, data['teacher_reg_start'], None)]

    #   Grant onsite bit (for all times) if an onsite user is available.
    if ESPUser.onsite_user():
        perms += [('Onsite', ESPUser.onsite_user(), None, None)]

    modules += [(str(ProgramModule.objects.get(id=i)), i) for i in data['program_modules']]

    return perms, modules
Example #39
0
def bio(request, tl, last = '', first = '', usernum = 0, username = ''):
    """ Displays a teacher bio """

    try:
        if username != '':
            founduser = ESPUser.objects.get(username=username)
            old_url = (tl != 'teach')
        else:
            founduser = ESPUser.getUserFromNum(first, last, usernum)
            old_url = True
    except:
        return bio_not_found(request)

    return bio_user(request, founduser, old_url)
    def prepare_context(self, program, target_path=None):
        context = {}
        context['program'] = program
        context['user_types'] = ESPUser.getTypes()
        category_lists = {}
        list_descriptions = program.getListDescriptions()

        #   Add in program-specific lists for most common user types
        for user_type, list_func in zip(Program.USER_TYPES_WITH_LIST_FUNCS, Program.USER_TYPE_LIST_FUNCS):
            raw_lists = getattr(program, list_func)(True)
            category_lists[user_type] = [{'name': key, 'list': raw_lists[key], 'description': list_descriptions[key]} for key in raw_lists]
            for item in category_lists[user_type]:
                if item['name'] in UserSearchController.preferred_lists:
                    item['preferred'] = True

        #   Add in global lists for each user type
        for user_type in ESPUser.getTypes():
            key = user_type.lower() + 's'
            if user_type not in category_lists:
                category_lists[user_type] = []
            category_lists[user_type].insert(0, {'name': 'all_%s' % user_type, 'list': ESPUser.getAllOfType(user_type), 'description': 'All %s in the database' % key, 'preferred': True, 'all_flag': True})

        #   Add in mailing list accounts
        category_lists['emaillist'] = [{'name': 'all_emaillist', 'list': Q(password = '******'), 'description': 'Everyone signed up for the mailing list', 'preferred': True}]

        context['lists'] = category_lists
        context['all_list_names'] = []
        for category in category_lists:
            for item in category_lists[category]:
                context['all_list_names'].append(item['name'])

        if target_path is None:
            target_path = '/manage/%s/commpanel' % program.getUrlBase()
        context['action_path'] = target_path

        return context
    def schedule_students(self, request, tl, one, two, module, extra, prog):
        """ Redirect to student registration, having morphed into the desired
        student. """

        user, found = search_for_user(request, ESPUser.getAllOfType('Student', False))
        if not found:
            return user

        request.user.switch_to_user(request,
                                 user,
                                 self.getCoreURL(tl),
                                 'OnSite Registration!',
                                 True)

        return HttpResponseRedirect('/learn/%s/studentreg' % self.program.getUrlBase())
Example #42
0
def bio_edit(request, tl='', last='', first='', usernum=0, progid = None, username=''):
    """ Edits a teacher bio, given user and program identification information """

    old_url = False
    try:
        if tl == '':
            founduser = request.user
        else:
            if username != '':
                founduser = ESPUser.objects.get(username=username)
                old_url = (tl != 'teach')
            else:
                founduser = ESPUser.getUserFromNum(first, last, usernum)
                old_url = True
    except:
        return bio_not_found(request)

    foundprogram = get_from_id(progid, Program, 'program', False)

    return bio_edit_user_program(request, founduser, foundprogram,
                                 old_url=old_url)
    def query_from_criteria(self, user_type, criteria):

        """ Get the "base list" consisting of all the users of a specific type. """
        if user_type.lower() == 'any':
            Q_base = Q()
        else:
            if user_type not in ESPUser.getTypes():
                raise ESPError('user_type must be one of '+str(ESPUser.getTypes()))
            Q_base = ESPUser.getAllOfType(user_type, True)

        Q_include = Q()
        Q_exclude = Q()

        """ Apply the specified criteria to filter the list of users. """
        if criteria.get('userid', '').strip():

            ##  Select users based on their IDs only
            userid = []
            for digit in criteria['userid'].split(','):
                try:
                    userid.append(int(digit))
                except:
                    raise ESPError('User id invalid, please enter a number or comma-separated list of numbers.', log=False)

            if 'userid__not' in criteria:
                Q_exclude &= Q(id__in = userid)
            else:
                Q_include &= Q(id__in = userid)
            self.updated = True

        else:

            ##  Select users based on all other criteria that was entered
            for field in ['username','last_name','first_name', 'email']:
                if criteria.get(field, '').strip():
                    #   Check that it's a valid regular expression
                    try:
                        rc = re.compile(criteria[field])
                    except:
                        raise ESPError('Invalid search expression, please check your syntax: %s' % criteria[field], log=False)
                    filter_dict = {'%s__iregex' % field: criteria[field]}
                    if '%s__not' % field in criteria:
                        Q_exclude &= Q(**filter_dict)
                    else:
                        Q_include &= Q(**filter_dict)
                    self.updated = True

            if 'zipcode' in criteria and 'zipdistance' in criteria and \
                len(criteria['zipcode'].strip()) > 0 and len(criteria['zipdistance'].strip()) > 0:
                try:
                    zipc = ZipCode.objects.get(zip_code = criteria['zipcode'])
                except:
                    raise ESPError('Zip code not found.  This may be because you didn\'t enter a valid US zipcode.  Tried: "%s"' % criteria['zipcode'], log=False)
                zipcodes = zipc.close_zipcodes(criteria['zipdistance'])
                # Excludes zipcodes within a certain radius, giving an annulus; can fail to exclude people who used to live outside the radius.
                # This may have something to do with the Q_include line below taking more than just the most recent profile. -ageng, 2008-01-15
                if criteria.get('zipdistance_exclude', '').strip():
                    zipcodes_exclude = zipc.close_zipcodes(criteria['zipdistance_exclude'])
                    zipcodes = [ zipcode for zipcode in zipcodes if zipcode not in zipcodes_exclude ]
                if len(zipcodes) > 0:
                    Q_include &= Q(registrationprofile__contact_user__address_zip__in = zipcodes, registrationprofile__most_recent_profile=True)
                    self.updated = True

            if criteria.get('states', '').strip():
                state_codes = criteria['states'].strip().upper().split(',')
                if 'states__not' in criteria:
                    Q_exclude &= Q(registrationprofile__contact_user__address_state__in = state_codes, registrationprofile__most_recent_profile=True)
                else:
                    Q_include &= Q(registrationprofile__contact_user__address_state__in = state_codes, registrationprofile__most_recent_profile=True)
                self.updated = True

            if 'grade_min' in criteria:
                yog = ESPUser.YOGFromGrade(criteria['grade_min'])
                if yog != 0:
                    Q_include &= Q(registrationprofile__student_info__graduation_year__lte = yog, registrationprofile__most_recent_profile=True)
                    self.updated = True

            if 'grade_max' in criteria:
                yog = ESPUser.YOGFromGrade(criteria['grade_max'])
                if yog != 0:
                    Q_include &= Q(registrationprofile__student_info__graduation_year__gte = yog, registrationprofile__most_recent_profile=True)
                    self.updated = True

            if 'school' in criteria:
                school = criteria['school']
                if school:
                    Q_include &= (Q(studentinfo__school__icontains=school) | Q(studentinfo__k12school__name__icontains=school))
                    self.updated = True

            #   Filter by graduation years if specifically looking for teachers.
            possible_gradyears = range(1920, 2020)
            if criteria.get('gradyear_min', '').strip():
                try:
                    gradyear_min = int(criteria['gradyear_min'])
                except:
                    raise ESPError('Please enter a 4-digit integer for graduation year limits.', log=False)
                possible_gradyears = filter(lambda x: x >= gradyear_min, possible_gradyears)
            if criteria.get('gradyear_max', '').strip():
                try:
                    gradyear_max = int(criteria['gradyear_max'])
                except:
                    raise ESPError('Please enter a 4-digit integer for graduation year limits.', log=False)
                possible_gradyears = filter(lambda x: x <= gradyear_max, possible_gradyears)
            if criteria.get('gradyear_min', None) or criteria.get('gradyear_max', None):
                Q_include &= Q(registrationprofile__teacher_info__graduation_year__in = map(str, possible_gradyears), registrationprofile__most_recent_profile=True)
                self.updated = True

        return Q_base & (Q_include & ~Q_exclude)
Example #44
0
def profile_editor(request, prog_input=None, responseuponCompletion = True, role=''):
    """ Display the registration profile page, the page that contains the contact information for a student, as attached to a particular program """

    from esp.users.models import K12School
    from esp.web.views.main import registration_redirect

    if prog_input is None:
        prog = None
    else:
        prog = prog_input

    curUser = request.user
    context = {'logged_in': request.user.is_authenticated() }
    context['user'] = request.user
    context['program'] = prog

    curUser.updateOnsite(request)

    #   Get the profile form from the user's type, although we need to handle
    #   a couple of extra possibilities for the 'role' variable.
    user_types = ESPUser.getAllUserTypes()
    additional_types = [['',  {'label': 'Not specified', 'profile_form': 'UserContactForm'}],
                        ['Administrator', {'label': 'Administrator', 'profile_form': 'UserContactForm'}],
                       ]
    additional_type_labels = [x[0] for x in additional_types]
    #   Handle all-lowercase versions of role being passed in by calling title()
    user_type_labels = [x[0] for x in user_types]
    if role.title() in user_type_labels:
        target_type = user_types[user_type_labels.index(role.title())][1]
    else:
        target_type = additional_types[additional_type_labels.index(role.title())][1]
    mod = __import__('esp.users.forms.user_profile', (), (), target_type['profile_form'])
    FormClass = getattr(mod, target_type['profile_form'])

    context['profiletype'] = role

    if request.method == 'POST' and 'profile_page' in request.POST:
        form = FormClass(curUser, request.POST)

        # Don't suddenly demand an explanation from people who are already student reps
        if curUser.hasRole("StudentRep"):
            if hasattr(form, 'repress_studentrep_expl_error'):
                form.repress_studentrep_expl_error()

        if form.is_valid():
            new_data = form.cleaned_data

            regProf = RegistrationProfile.getLastForProgram(curUser, prog)

            if regProf.id is None:
                old_regProf = RegistrationProfile.getLastProfile(curUser)
            else:
                old_regProf = regProf

            for field_name in ['address_zip','address_city','address_street','address_state']:
                if field_name in new_data and new_data[field_name] != getattr(old_regProf.contact_user,field_name,False):
                    new_data['address_postal'] = ''

            if new_data['address_postal'] == '':
                new_data['address_postal'] = False

            regProf.contact_user = ContactInfo.addOrUpdate(regProf, new_data, regProf.contact_user, '', curUser)
            regProf.contact_emergency = ContactInfo.addOrUpdate(regProf, new_data, regProf.contact_emergency, 'emerg_')

            if new_data.get('dietary_restrictions'):
                regProf.dietary_restrictions = new_data['dietary_restrictions']

            if role == 'student':
                regProf.student_info = StudentInfo.addOrUpdate(curUser, regProf, new_data)
                regProf.contact_guardian = ContactInfo.addOrUpdate(regProf, new_data, regProf.contact_guardian, 'guard_')
            elif role == 'teacher':
                regProf.teacher_info = TeacherInfo.addOrUpdate(curUser, regProf, new_data)
            elif role == 'guardian':
                regProf.guardian_info = GuardianInfo.addOrUpdate(curUser, regProf, new_data)
            elif role == 'educator':
                regProf.educator_info = EducatorInfo.addOrUpdate(curUser, regProf, new_data)
            blah = regProf.__dict__
            regProf.save()

            curUser.first_name = new_data['first_name']
            curUser.last_name  = new_data['last_name']
            curUser.email     = new_data['e_mail']
            curUser.save()
            if responseuponCompletion == True:
                return registration_redirect(request)
            else:
                return True
        else:
            #   Force loading the school back in if possible...
            replacement_data = form.data.copy()
            try:
                replacement_data['k12school'] = form.fields['k12school'].clean(form.data['k12school']).id
            except:
                pass
            form = FormClass(curUser, replacement_data)

    else:
        if prog_input is None:
            regProf = RegistrationProfile.getLastProfile(curUser)
        else:
            regProf = RegistrationProfile.getLastForProgram(curUser, prog)
        if regProf.id is None:
            regProf = RegistrationProfile.getLastProfile(curUser)
        new_data = {}
        if curUser.isStudent():
            new_data['studentrep'] = curUser.groups.filter(name="StudentRep").exists()
        new_data['first_name'] = curUser.first_name
        new_data['last_name']  = curUser.last_name
        new_data['e_mail']     = curUser.email
        new_data = regProf.updateForm(new_data, role)

        if regProf.student_info and regProf.student_info.dob:
            new_data['dob'] = regProf.student_info.dob

        #   Set default values for state fields
        state_fields = ['address_state', 'emerg_address_state']
        state_tag_map = {}
        for field in state_fields:
            state_tag_map[field] = 'local_state'
        form = FormClass(curUser, initial=new_data, tag_map=state_tag_map)

    context['request'] = request
    context['form'] = form
    return render_to_response('users/profile.html', request, context)
    def classchangerequest(self, request, tl, one, two, module, extra, prog):
        timeslots = prog.getTimeSlots()
        sections = prog.sections().filter(status=10, meeting_times__isnull=False).distinct()

        enrollments = {}
        for timeslot in timeslots:
            try:
                enrollments[timeslot] = ClassSubject.objects.get(nest_Q(StudentRegistration.is_valid_qobject(), 'sections__studentregistration'), sections__studentregistration__relationship__name="Enrolled", sections__studentregistration__user=request.user, sections__meeting_times=timeslot, parent_program=prog)
            except ClassSubject.DoesNotExist:
                enrollments[timeslot] = None

        context = {}
        context['timeslots'] = timeslots
        context['enrollments'] = enrollments
        context['user'] = request.user
        if 'success' in request.GET:
            context['success'] = True
        else:
            context['success'] = False

        if request.user.isStudent():
            sections_by_slot = dict([(timeslot,[(section, 1 == StudentRegistration.valid_objects().filter(user=context['user'], section=section, relationship__name="Request").count()) for section in sections if section.get_meeting_times()[0] == timeslot and section.parent_class.grade_min <= request.user.getGrade(prog) <= section.parent_class.grade_max and section.parent_class not in enrollments.values() and ESPUser.getRankInClass(request.user, section.parent_class) in (5,10)]) for timeslot in timeslots])
        else:
            sections_by_slot = dict([(timeslot,[(section, False) for section in sections if section.get_meeting_times()[0] == timeslot]) for timeslot in timeslots])

        fields = {}
        for i, timeslot in enumerate(sections_by_slot.keys()):
            choices = [('0', "I'm happy with my current enrollment.")]
            initial = '0'
            for section in sections_by_slot[timeslot]:
                choices.append((section[0].emailcode(), section[0].emailcode()+": "+section[0].title()))
                if section[1]:
                    initial = section[0].emailcode()
            fields['timeslot_'+str(i+1)] = forms.ChoiceField(label="Timeslot "+str(i+1)+" ("+timeslot.pretty_time()+")", choices=choices, initial=initial)

        form = type('ClassChangeRequestForm', (forms.Form,), fields)
        context['form'] = form()
        if request.method == "POST":
            old_requests = StudentRegistration.valid_objects().filter(user=context['user'], section__parent_class__parent_program=prog, relationship__name="Request")
            for r in old_requests:
                r.expire()
            form = form(request.POST)
            if form.is_valid():
                for value in form.cleaned_data.values():
                    section = None
                    for s in sections:
                        if s.emailcode() == value:
                            section = s
                            break
                    if not section:
                        continue
                    r = StudentRegistration.valid_objects().get_or_create(user=context['user'], section=section, relationship=RegistrationType.objects.get_or_create(name="Request", category="student")[0])[0]
                    r.save()

                return HttpResponseRedirect(request.path.rstrip('/')+'/?success')
        else:
            return render_to_response(self.baseDir() + 'classchangerequest.html', request, context)
    def query_from_postdata(self, program, data):
        """ Get a Q object for the targeted list of users from the POST data submitted
            on the main "comm panel" page
        """

        def get_recipient_type(list_name):
            for user_type in Program.USER_TYPE_LIST_FUNCS:
                raw_lists = getattr(program, user_type)(True)
                if list_name in raw_lists:
                    return user_type

        subquery = None

        if 'base_list' in data and 'recipient_type' in data:
            #   Get the program-specific part of the query (e.g. which list to use)
            if data['recipient_type'] not in ESPUser.getTypes():
                recipient_type = 'any'
                q_program = Q()
            else:
                if data['base_list'].startswith('all'):
                    q_program = Q()
                    recipient_type = data['recipient_type']
                else:
                    program_lists = getattr(program, data['recipient_type'].lower()+'s')(QObjects=True)
                    q_program = program_lists[data['base_list']]
                    """ Some program queries rely on UserBits, and since user types are also stored in
                        UserBits we cannot store both of these in a single Q object.  To compensate, we
                        ignore the user type when performing a program-specific query.  """
                    recipient_type = 'any'

            #   Get the user-specific part of the query (e.g. ID, name, school)
            q_extra = self.query_from_criteria(recipient_type, data)

        ##  Handle "combination list" submissions
        elif 'combo_base_list' in data:
            #   Get an initial query from the supplied base list
            recipient_type, list_name = data['combo_base_list'].split(':')
            if list_name.startswith('all'):
                q_program = Q()
            else:
                q_program = getattr(program, recipient_type.lower()+'s')(QObjects=True)[list_name]

            #   Apply Boolean filters
            #   Base list will be intersected with any lists marked 'AND', and then unioned
            #   with any lists marked 'OR'.
            checkbox_keys = map(lambda x: x[9:], filter(lambda x: x.startswith('checkbox_'), data.keys()))
            and_keys = map(lambda x: x[4:], filter(lambda x: x.startswith('and_'), checkbox_keys))
            or_keys = map(lambda x: x[3:], filter(lambda x: x.startswith('or_'), checkbox_keys))
            not_keys = map(lambda x: x[4:], filter(lambda x: x.startswith('not_'), checkbox_keys))
            #if any keys concern the same field, we will place them into
            #a subquery and count occurrences

            #for the purpose of experimentation simply fix this to the record__event
            #as this could very well have different implications for other fields

            subqry_fieldmap = {'record__event':[]}

            for and_list_name in and_keys:
                user_type = get_recipient_type(and_list_name)

                if user_type:

                    qobject = getattr(program, user_type)(QObjects=True)[and_list_name]

                    if and_list_name in not_keys:
                        q_program = q_program & ~qobject
                    else:
                        qobject_child = qobject.children[1]
                        needs_subquery = False

                        if isinstance(qobject_child, (list, tuple)):
                            field_name, field_value = qobject.children[1]
                            needs_subquery = field_name in subqry_fieldmap

                            if needs_subquery:
                                subqry_fieldmap[field_name].append(field_value)
                        if not needs_subquery:
                            q_program = q_program & qobject

            event_fields = subqry_fieldmap['record__event']

            if event_fields:
                #annotation is needed to initiate group by
                #except that it causes the query to return two columns
                #so we call values at the end of the chain, however,
                #that results in multiple group by fields(causing the query to fail)
                #so, we assign a group by field, to force grouping by user_id
                subquery = (
                              Record
                              .objects
                              .filter(program=program,event__in=event_fields)
                              .annotate(numusers=Count('user__id'))
                              .filter(numusers=len(event_fields))
                              .values_list('user_id',flat=True)
                            )

                subquery.query.group_by = []#leave empty to strip out duplicate group by
                subquery = Q(pk__in=subquery)

            for or_list_name in or_keys:
                user_type = get_recipient_type(or_list_name)
                if user_type:
                    qobject = getattr(program, user_type)(QObjects=True)[or_list_name]
                    if or_list_name not in not_keys:
                        q_program = q_program | qobject
                    else:
                        q_program = q_program | ~qobject

            #   Get the user-specific part of the query (e.g. ID, name, school)
            q_extra = self.query_from_criteria(recipient_type, data)

        qobject = (q_extra & q_program & Q(is_active=True))

        #strip out duplicate clauses
        #   Note: in some cases, the children of the Q object are unhashable.
        #   Keep these separate.
        clauses_hashable = []
        clauses_unhashable = []
        for clause in qobject.children:
            if isinstance(clause, Q) or (isinstance(clause, tuple) and isinstance(clause[1], collections.Hashable)):
                clauses_hashable.append(clause)
            else:
                clauses_unhashable.append(clause)
        qobject.children = list(set(clauses_hashable)) + clauses_unhashable

        if subquery:
            qobject = qobject & subquery
        return qobject
    def __init__(self, user=None, *args, **kwargs):
        from esp.users.models import ESPUser
        super(StudentInfoForm, self).__init__(user, *args, **kwargs)

        self.allow_change_grade_level = Tag.getTag('allow_change_grade_level')

        ## All of these Tags may someday want to be made per-program somehow.
        ## We don't know the current program right now, though...
        show_studentrep_application = Tag.getTag('show_studentrep_application')
        if not show_studentrep_application:
            ## Only enable the Student Rep form optionally.
            del self.fields['studentrep']
        if (not show_studentrep_application) or show_studentrep_application == "no_expl":
            del self.fields['studentrep_expl']

        if not Tag.getTag('show_student_tshirt_size_options'):
            del self.fields['shirt_size']
            del self.fields['shirt_type']
        elif Tag.getTag('studentinfo_shirt_type_selection') == 'False':
            del self.fields['shirt_type']

        if not Tag.getTag('show_student_vegetarianism_options'):
            del self.fields['food_preference']

        #   Allow grade range of students to be customized by a Tag (default is 7-12)
        self.fields['graduation_year'].choices = [('','')]+[(str(ESPUser.YOGFromGrade(x)), str(x)) for x in ESPUser.grade_options()]

        #   Add user's current grade if it is out of range and they have already filled out the profile.
        if user and user.registrationprofile_set.count() > 0:
            user_grade = user.getGrade()
            grade_tup = (str(ESPUser.YOGFromGrade(user_grade)), str(user_grade))
            if grade_tup not in self.fields['graduation_year'].choices:
                self.fields['graduation_year'].choices.insert(0, grade_tup)

        #   Honor several possible Tags for customizing the fields that are displayed.
        if Tag.getTag('show_student_graduation_years_not_grades'):
            current_grad_year = self.ESPUser.current_schoolyear()
            new_choices = []
            for x in self.fields['graduation_year'].choices:
                if len(x[0]) > 0:
                    new_choices.append((str(x[0]), "%s (%sth grade)" % (x[0], x[1])))
                else:
                    new_choices.append(x)
            self.fields['graduation_year'].choices = new_choices

        if not Tag.getBooleanTag('student_profile_gender_field'):
            del self.fields['gender']

        if not Tag.getTag('ask_student_about_transportation_to_program'):
            del self.fields['transportation']

        if not Tag.getTag('allow_change_grade_level'):
            if 'initial' in kwargs:
                initial_data = kwargs['initial']

                # Disable the age and grade fields if they already exist.
                if 'graduation_year' in initial_data and 'dob' in initial_data:
                    self.fields['graduation_year'].widget.attrs['disabled'] = "true"
                    self.fields['graduation_year'].required = False
                    self.fields['dob'].widget.attrs['disabled'] = "true"
                    self.fields['dob'].required = False

        #   Add field asking about medical needs if directed by the Tag
        if Tag.getTag('student_medical_needs'):
            self.fields['medical_needs'].widget = forms.Textarea(attrs={'cols': 40, 'rows': 3})
        else:
            del self.fields['medical_needs']

        #   The unmatched_school field is for students to opt out of selecting a K12School.
        #   If we don't require a K12School to be selected, don't bother showing that field.
        if not Tag.getBooleanTag('require_school_field', default=False):
            del self.fields['unmatched_school']

        self._user = user
Example #48
0
 def __init__(self, *args, **kwargs):
     super(OnSiteRegForm, self).__init__(*args, **kwargs)
     self.fields['grade'].choices = (
         [('', '')] + [(x, x) for x in ESPUser.grade_options()])
    def stats(prog):
        # Create a dictionary to assemble the output
        dictOut = { "stats": [] }

        classes = prog.classes().select_related()
        vitals = {'id': 'vitals'}

        class_num_list = []
        class_num_list.append(("Total # of Classes", classes.distinct().count()))
        class_num_list.append(("Total # of Class Sections", prog.sections().select_related().distinct().count()))
        class_num_list.append(("Total # of Lunch Classes", classes.filter(category__category = "Lunch").filter(status=10).distinct().count()))
        class_num_list.append(("Total # of Classes <span style='color: #00C;'>Unreviewed</span>", classes.filter(status=0).distinct().count()))
        class_num_list.append(("Total # of Classes <span style='color: #0C0;'>Accepted</span>", classes.filter(status=10).distinct().count()))
        class_num_list.append(("Total # of Classes <span style='color: #C00;'>Rejected</span>", classes.filter(status=-10).distinct().count()))
        class_num_list.append(("Total # of Classes <span style='color: #990;'>Cancelled</span>", classes.filter(status=-20).distinct().count()))
        for ft in ClassFlagType.get_flag_types(prog):
            class_num_list.append(('Total # of Classes with the "%s" flag' % ft.name, classes.filter(flags__flag_type=ft).distinct().count()))
        vitals['classnum'] = class_num_list

        #   Display pretty labels for teacher and student numbers
        teacher_labels_dict = {}
        for module in prog.getModules():
            teacher_labels_dict.update(module.teacherDesc())
        vitals['teachernum'] = []

        ## Ew, queries in a for loop...
        ## Not much to be done about it, though;
        ## the loop is iterating over a list of independent queries and running each.
        teachers = prog.teachers()
        for key in teachers.keys():
            if key in teacher_labels_dict:
                vitals['teachernum'].append((teacher_labels_dict[key],         ## Unfortunately,
teachers[key].filter(is_active = True).distinct().count()))
            else:
                vitals['teachernum'].append((key, teachers[key].filter(is_active = True).distinct().count()))

        student_labels_dict = {}
        for module in prog.getModules():
            student_labels_dict.update(module.studentDesc())
        vitals['studentnum'] = []

        ## Ew, another set of queries in a for loop...
        ## Same justification, though.
        students = prog.students()
        for key in students.keys():
            if key in student_labels_dict:
                vitals['studentnum'].append((student_labels_dict[key], students[key].filter(is_active = True).distinct().count()))
            else:
                vitals['studentnum'].append((key, students[key].filter(is_active = True).distinct().count()))

        timeslots = prog.getTimeSlots()
        vitals['timeslots'] = []


        shours = 0.0
        chours = 0.0
        crhours = 0.0
        ## Write this as a 'for' loop because PostgreSQL can't do it in
        ## one go without a subquery or duplicated logic, and Django
        ## doesn't have enough power to expose either approach directly.
        ## At least there aren't any queries in the for loop...
        ## (In MySQL, this could I believe be done with a minimally-painful extra() clause.)
        ## Also, since we're iterating over a big data set, use .values()
        ## minimize the number of objects that we're creating.
        ## One dict and two Decimals per row, as opposed to
        ## an Object per field and all kinds of stuff...
        for cls in prog.classes().exclude(category__category='Lunch').annotate(num_sections=Count('sections'), subject_duration=Sum('sections__duration'), subject_students=Sum('sections__enrolled_students')).values('num_sections', 'subject_duration', 'subject_students', 'class_size_max'):
            if cls['subject_duration']:
                chours += float(cls['subject_duration'])
                shours += float(cls['subject_duration']) * (float(cls['class_size_max']) if cls['class_size_max'] else 0)
                crhours += float(cls['subject_duration']) * float(cls['subject_students']) / float(cls['num_sections'])
        vitals["hournum"] = []
        vitals["hournum"].append(("Total # of Class-Hours", chours))
        vitals["hournum"].append(("Total # of Class-Student-Hours (capacity)", shours))
        vitals["hournum"].append(("Total # of Class-Student-Hours (registered)", crhours))


        ## Prefetch enough data that get_meeting_times() and num_students() don't have to hit the db
        curclasses = ClassSection.prefetch_catalog_data(
            ClassSection.objects
            .filter(parent_class__parent_program=prog)
            .select_related('parent_class', 'parent_class__category'))

        ## Is it really faster to do this logic in Python?
        ## It'd be even faster to just write a raw SQL query to do it.
        ## But this is probably good enough.
        timeslot_dict = defaultdict(list)
        timeslot_set = set(timeslots)
        for section in curclasses:
            for timeslot in set.intersection(timeslot_set, section.get_meeting_times()):
                timeslot_dict[timeslot].append(section)

        for timeslot in timeslots:
            curTimeslot = {'slotname': timeslot.short_description}

            curTimeslot['classcount'] = len(timeslot_dict[timeslot])

            def student_count(clslist):
                lst = [0] + [x.num_students() for x in clslist if x.category.category != 'Lunch']
                return reduce(operator.add, lst)

            def student_max_count(clslist):
                lst = [0] + [x.capacity for x in clslist if x.category.category != 'Lunch']
                return reduce(operator.add, lst)

            curTimeslot['studentcount'] = {
                'count': student_count(timeslot_dict[timeslot]),
                'max_count': student_max_count(timeslot_dict[timeslot])
                }

            vitals['timeslots'].append(curTimeslot)

        dictOut["stats"].append(vitals)

        shirt_data = {"id": "shirtnum"};
        adminvitals_shirt = prog.getShirtInfo()
        shirt_data["sizes"] = adminvitals_shirt['shirt_sizes'];
        shirt_data["types"] = adminvitals_shirt['shirt_types'];
        shirt_data["data"] = adminvitals_shirt['shirts'];
        dictOut["stats"].append(shirt_data);

        Q_categories = Q(program=prog)
        crmi = prog.classregmoduleinfo
        if crmi.open_class_registration:
            Q_categories |= Q(pk=prog.open_class_category.pk)
        #   Introduce a separate query to get valid categories, since the single query seemed to introduce duplicates
        program_categories = ClassCategories.objects.filter(Q_categories).distinct().values_list('id', flat=True)
        annotated_categories = ClassCategories.objects.filter(cls__parent_program=prog, cls__status__gte=0).annotate(num_subjects=Count('cls', distinct=True), num_sections=Count('cls__sections'), num_class_hours=Sum('cls__sections__duration')).order_by('-num_subjects').values('id', 'num_sections', 'num_subjects', 'num_class_hours', 'category').distinct()
        #   Convert Decimal values to float for serialization
        for i in range(len(annotated_categories)):
            annotated_categories[i]['num_class_hours'] = float(annotated_categories[i]['num_class_hours'])
        dictOut["stats"].append({"id": "categories", "data": filter(lambda x: x['id'] in program_categories, annotated_categories)})

        ## Calculate the grade data:
        grades = [i for i in range(prog.grade_min, prog.grade_max+1)]
        # We can't perfectly trust most_recent_profile, but it's good enough for stats
        students_grades = students['enrolled'].filter(registrationprofile__most_recent_profile=True)
        students_grades = students_grades.values_list('registrationprofile__student_info__graduation_year')
        students_grades = students_grades.annotate(Count('id', distinct=True))
        grades_dict = {result[0]: result[1] for result in students_grades}
        grades_results = []
        for g in grades:
            year = ESPUser.YOGFromGrade(g, ESPUser.program_schoolyear(prog))
            grade_classes = classes.filter(status__gte=0, grade_min__lte=g, grade_max__gte=g)
            grade_sections = prog.sections().filter(status__gte=0, parent_class__in=grade_classes)
            grades_results.append({'grade': g, 'num_subjects': grade_classes.count(),
                                   'num_sections': grade_sections.count(),
                                   'num_students': grades_dict[year] if year in grades_dict else 0})
        dictOut["stats"].append({"id": "grades", "data": grades_results})

        #   Add SplashInfo statistics if our program has them
        splashinfo_data = {}
        splashinfo_modules = filter(lambda x: isinstance(x, SplashInfoModule), prog.getModules('learn'))
        if len(splashinfo_modules) > 0:
            splashinfo_module = splashinfo_modules[0]
            tag_data = Tag.getProgramTag('splashinfo_choices', prog)
            if tag_data:
                splashinfo_choices = json.loads(tag_data)
            else:
                splashinfo_choices = {'lunchsat': SplashInfoForm.default_choices, 'lunchsun': SplashInfoForm.default_choices}
            for key in splashinfo_choices:
                counts = {}
                for item in splashinfo_choices[key]:
                    filter_kwargs = {'program': prog}
                    filter_kwargs[key] = item[0]
                    counts[item[1]] = SplashInfo.objects.filter(**filter_kwargs).distinct().count()
                splashinfo_data[key] = counts
            splashinfo_data['siblings'] = {
                'yes': SplashInfo.objects.filter(program=prog, siblingdiscount=True).distinct().count(),
                'no':  SplashInfo.objects.filter(program=prog).exclude(siblingdiscount=True).distinct().count()
            }
            dictOut["stats"].append({"id": "splashinfo", "data": splashinfo_data})

        #   Add accounting stats
        pac = ProgramAccountingController(prog)
        (num_payments, total_payment) = pac.payments_summary()
        accounting_data = {
            'num_payments': num_payments,
            # We need to convert to a float in order for json to serialize it.
            # Since we're not doing any computation client-side with these
            # numbers, this doesn't cause accuracy issues.  If the
            # total_payment is None, just coerce it to zero for display
            # purposes.
            'total_payments': float(total_payment or 0),
        }
        dictOut["stats"].append({"id": "accounting", "data": accounting_data})

        return dictOut
    def initialize(self):
        """ Gather all of the information needed to run the lottery assignment.
            This includes:
            -   Students' interest (priority and interested bits)
            -   Class schedules and capacities
            -   Timeslots (incl. lunch periods for each day)
        """

        self.enroll_orig = numpy.zeros((self.num_students, self.num_sections, self.num_timeslots), dtype=numpy.bool)
        self.enroll_final = numpy.zeros((self.num_students, self.num_sections, self.num_timeslots), dtype=numpy.bool)
        self.request = numpy.zeros((self.num_students, self.num_sections, self.num_timeslots), dtype=numpy.bool)
        self.waitlist = [numpy.zeros((self.num_students, self.num_sections, self.num_timeslots), dtype=numpy.bool) for i in range(self.priority_limit+1)]
        self.section_schedules = numpy.zeros((self.num_sections, self.num_timeslots), dtype=numpy.bool)
        self.section_capacities = numpy.zeros((self.num_sections,), dtype=numpy.int32)
        self.section_scores = numpy.zeros((self.num_sections,), dtype=numpy.int32)
        self.same_subject = numpy.zeros((self.num_sections, self.num_sections), dtype=numpy.bool)
        self.section_conflict = numpy.zeros((self.num_sections, self.num_sections), dtype=numpy.bool) # is this a section that takes place in the same timeblock

        #   Get student, section, timeslot IDs and prepare lookup table
        (self.student_ids, self.student_indices) = self.get_ids_and_indices(self.students)
        (self.section_ids, self.section_indices) = self.get_ids_and_indices(self.sections)
        (self.timeslot_ids, self.timeslot_indices) = self.get_ids_and_indices(self.timeslots)
        self.parent_classes = numpy.array(self.sections.values_list('parent_class__id', flat=True))

        self.student_not_checked_in = numpy.zeros((self.num_students,), dtype=numpy.bool)
        self.student_not_checked_in[self.student_indices[self.students_not_checked_in]] = True

        #   Get IDs of timeslots allocated to lunch by day
        #   (note: requires that this is constant across days)
        self.lunch_schedule = numpy.zeros((self.num_timeslots,))
        lunch_timeslots = Event.objects.filter(meeting_times__parent_class__parent_program=self.program, meeting_times__parent_class__category__category='Lunch').order_by('start').distinct()
        #   Note: this code should not be necessary once lunch-constraints branch is merged (provides Program.dates())
        dates = []
        for ts in self.timeslots:
            ts_day = date(ts.start.year, ts.start.month, ts.start.day)
            if ts_day not in dates:
                dates.append(ts_day)
        lunch_by_day = [[] for x in dates]
        ts_count = 0
        for ts in lunch_timeslots:
            d = date(ts.start.year, ts.start.month, ts.start.day)
            lunch_by_day[dates.index(d)].append(ts.id)
            self.lunch_schedule[self.timeslot_indices[ts.id]] = True

        for i in range(len(lunch_by_day)):
            if len(lunch_by_day[i]) > ts_count:
                ts_count = len(lunch_by_day[i])
        self.lunch_timeslots = numpy.zeros((len(lunch_by_day), ts_count), dtype=numpy.int32)
        for i in range(len(lunch_by_day)):
            self.lunch_timeslots[i, :len(lunch_by_day[i])] = numpy.array(lunch_by_day[i])

        #   Populate old enrollment matrix
        enroll_regs = StudentRegistration.objects.filter(self.Q_EN).values_list('user__id', 'section__id', 'section__meeting_times__id').distinct()
        era = numpy.array(enroll_regs, dtype=numpy.uint32)
        try:
            self.enroll_orig[self.student_indices[era[:, 0]], self.section_indices[era[:, 1]], self.timeslot_indices[era[:, 2]]] = True
        except IndexError:
            pass

        self.student_not_checked_in[numpy.transpose(numpy.nonzero(True-self.enroll_orig.any(axis=(1,2))))] = True

        #   Populate old enrollment matrix
        request_regs = StudentRegistration.objects.filter(self.Q_REQ).values_list('user__id', 'section__id', 'section__meeting_times__id').distinct()
        rra = numpy.array(request_regs, dtype=numpy.uint32)
        try:
            self.request[self.student_indices[rra[:, 0]], self.section_indices[rra[:, 1]], self.timeslot_indices[rra[:, 2]]] = True
        except IndexError:
            pass

        #   Populate waitlist matrix
        waitlist_regs = [StudentRegistration.objects.filter(self.Q_WAIT[i]).values_list('user__id', 'section__id', 'section__meeting_times__id').distinct() for i in range(self.priority_limit+1)]
        wra = [numpy.array(waitlist_regs[i], dtype=numpy.uint32) for i in range(self.priority_limit+1)]
        self.waitlist[0][:,:,:] = True
        for i in range(1, self.priority_limit+1):
            try:
                self.waitlist[i][self.student_indices[wra[i][:, 0]], self.section_indices[wra[i][:, 1]], self.timeslot_indices[wra[i][:, 2]]] = True
                self.waitlist[0][self.student_indices[wra[i][:, 0]], self.section_indices[wra[i][:, 1]], self.timeslot_indices[wra[i][:, 2]]] = False
            except IndexError:
                pass

        #   Populate section schedule
        section_times = numpy.array(self.sections.values_list('id', 'meeting_times__id'))
        self.section_schedules[self.section_indices[section_times[:, 0]], self.timeslot_indices[section_times[:, 1]]] = True

        #   Populate section overlap matrix
        for i in range(self.num_sections):
            group_ids = numpy.nonzero(self.parent_classes == self.parent_classes[i])[0]
            self.same_subject[numpy.meshgrid(group_ids, group_ids)] = True

            sec_times = numpy.transpose(numpy.nonzero(self.section_schedules[i, :]))
            for [ts_ind,] in sec_times:
                self.section_conflict[numpy.transpose(numpy.nonzero(self.section_schedules[:, ts_ind])), i] = True
                self.section_conflict[i, numpy.transpose(numpy.nonzero(self.section_schedules[:, ts_ind]))] = True
            self.section_conflict[i, i] = False

        #   Populate section grade limits
        self.section_grade_min = numpy.array(self.sections.values_list('parent_class__grade_min', flat=True), dtype=numpy.uint32)
        self.section_grade_max = numpy.array(self.sections.values_list('parent_class__grade_max', flat=True), dtype=numpy.uint32)

        #   Populate student grades; grade will be assumed to be 0 if not entered on profile
        self.student_grades = numpy.zeros((self.num_students,))
        gradyear_pairs = numpy.array(RegistrationProfile.objects.filter(user__id__in=list(self.student_ids), most_recent_profile=True, student_info__graduation_year__isnull=False).values_list('user__id', 'student_info__graduation_year'), dtype=numpy.uint32)
        self.student_grades[self.student_indices[gradyear_pairs[:, 0]]] = 12 + ESPUser.program_schoolyear(self.program) - gradyear_pairs[:, 1]

        #   Find section capacities (TODO: convert to single query)
        for sec in self.sections:
            sec_ind = self.section_indices[sec.id]
            self.section_capacities[sec_ind] = sec.capacity - sec.num_students()
            self.section_capacities[sec_ind] += numpy.count_nonzero((self.enroll_orig[:, sec_ind, self.section_schedules[sec_ind,:]].any(axis=1) * self.request[:,:,self.section_schedules[sec_ind,:]].any(axis=(1,2)))) # number enrolled but want to switch out
            self.enroll_final[numpy.transpose(numpy.nonzero((self.enroll_orig[:, sec_ind, self.section_schedules[sec_ind,:]].any(axis=1) * (True - self.request[:,:,self.section_schedules[sec_ind,:]].any(axis=(1,2)))))), sec_ind, self.section_schedules[sec_ind,:]] = True
            self.section_scores[sec_ind] = -self.section_capacities[sec_ind]
            self.section_scores[sec_ind] += numpy.count_nonzero(self.request[:, sec_ind, :].any(axis=1)) # number who want to switch in
        self.section_capacities_orig = numpy.copy(self.section_capacities)
        self.section_scores_orig = numpy.copy(self.section_scores)
        self.enroll_final_orig = numpy.copy(self.enroll_final)
        self.clear_assignments()
    def onsite_create(self, request, tl, one, two, module, extra, prog):
        if request.method == 'POST':
            form = OnSiteRegForm(request.POST)

            if form.is_valid():
                new_data = form.cleaned_data
                username = ESPUser.get_unused_username(new_data['first_name'], new_data['last_name'])
                new_user = ESPUser.objects.create_user(username = username,
                                first_name = new_data['first_name'],
                                last_name  = new_data['last_name'],
                                email      = new_data['email'])

                self.student = new_user

                regProf = RegistrationProfile.getLastForProgram(new_user,
                                                                self.program)
                contact_user = ContactInfo(first_name = new_user.first_name,
                                           last_name  = new_user.last_name,
                                           e_mail     = new_user.email,
                                           user       = new_user)
                contact_user.save()
                regProf.contact_user = contact_user

                student_info = StudentInfo(user = new_user, graduation_year = ESPUser.YOGFromGrade(new_data['grade'], ESPUser.program_schoolyear(self.program)))

                try:
                    if isinstance(new_data['k12school'], K12School):
                        student_info.k12school = new_data['k12school']
                    else:
                        if isinstance(new_data['k12school'], int):
                            student_info.k12school = K12School.objects.get(id=int(new_data['k12school']))
                        else:
                            student_info.k12school = K12School.objects.filter(name__icontains=new_data['k12school'])[0]
                except:
                    student_info.k12school = None
                student_info.school = new_data['school'] if not student_info.k12school else student_info.k12school.name

                student_info.save()
                regProf.student_info = student_info

                regProf.save()

                if new_data['paid']:
                    self.createBit('paid')
                    self.updatePaid(True)
                else:
                    self.updatePaid(False)

                self.createBit('Attended')

                if new_data['medical']:
                    self.createBit('Med')

                if new_data['liability']:
                    self.createBit('Liab')

                self.createBit('OnSite')


                new_user.groups.add(Group.objects.get(name="Student"))

                new_user.recoverPassword()

                return render_to_response(self.baseDir()+'reg_success.html', request, {
                    'student': new_user,
                    'retUrl': '/onsite/%s/classchange_grid?student_id=%s' % (self.program.getUrlBase(), new_user.id)
                    })

        else:
            form = OnSiteRegForm()

        return render_to_response(self.baseDir()+'reg_info.html', request, {'form':form})
Example #52
0
    def process(self):
        """Process this request, creating TextOfEmail and EmailRequest objects.

        It is the caller's responsibility to call this only on unprocessed
        MessageRequests.
        """

        # figure out who we're sending from...
        if self.sender is not None and len(self.sender.strip()) > 0:
            send_from = self.sender
        else:
            if self.creator is not None:
                send_from = '%s <%s>' % (self.creator.name(), self.creator.email)
            else:
                send_from = 'ESP Web Site <*****@*****.**>'

        users = self.recipients.getList(ESPUser).distinct()

        sendto_fn = self.get_sendto_fn_callable(self.sendto_fn_name)

        # go through each user and parse the text...then create the proper
        # emailrequest and textofemail object
        for user in users:
            subject = self.parseSmartText(self.subject, user)
            msgtext = self.parseSmartText(self.msgtext, user)

            # For each user, create an EmailRequest and a TextOfEmail
            # for each address given by the output of the sendto function.
            for address_pair in sendto_fn(user):
                newemailrequest = {'target': user, 'msgreq': self}
                send_to = ESPUser.email_sendto_address(*address_pair)
                newtxt = {
                    'send_to': send_to,
                    'send_from': send_from,
                    'subject': subject,
                    'msgtext': msgtext,
                    'created_at': self.created_at,
                    'defaults': {'sent': None},
                }

                # Use get_or_create so that, if this send_to address is
                # already receiving the exact same email, it doesn't need to
                # get sent a second time.
                # This is useful to de-duplicate announcement emails for
                # people with multiple accounts, or for preventing a user
                # from receiving a duplicate when a message request needs to
                # be resent after a bug prevented it from being received by
                # all recipients the first time.
                newtxt, created = TextOfEmail.objects.get_or_create(**newtxt)
                if not created:
                    logger.warning('Skipped duplicate creation of message to %s for message request %d: %s', send_to, self.id, self.subject)

                newemailrequest['textofemail'] = newtxt

                EmailRequest.objects.get_or_create(**newemailrequest)

        # Mark ourselves processed.  We don't have to worry about the DB
        # falling over between the above writes and this one, because the whole
        # assembly is in a transaction.
        self.processed = True
        self.save()

        logger.info('Prepared e-mails to send for message request %d: %s', self.id, self.subject)