Пример #1
0
def create_test_certificate(course, course_key, university):
    """
    Generate the pdf certicate, save it on disk
    """

    if university.certificate_logo:
        logo_path = os.path.join(university.certificate_logo.url, university.certificate_logo.path)
    else:
        logo_path = None

    teachers = get_teachers_list_from_course(course_key)
    certificate_language = Course.get_course_language(unicode(course_key))
    key = make_hashkey(random.random())
    filename = "TEST_attestation_suivi_%s_%s.pdf" % (
        course.id.to_deprecated_string().replace('/', '_'), key
    )

    certificate = CertificateInfo(settings.STUDENT_NAME_FOR_TEST_CERTIFICATE,
                                  course.display_name, university.name, logo_path, filename, teachers,
                                  language=certificate_language
    )

    certificate.generate()

    return certificate
Пример #2
0
    def send_to_grader(self, submission, system):
        """
        Send a given submission to the grader, via the xqueue
        @param submission: The student submission to send to the grader
        @param system: Modulesystem
        @return: Boolean true (not useful right now)
        """

        # Prepare xqueue request
        #------------------------------------------------------------

        xqueue = system.get('xqueue')
        if xqueue is None:
            return False
        qinterface = xqueue['interface']
        qtime = datetime.strftime(datetime.now(), xqueue_interface.dateformat)

        anonymous_student_id = system.anonymous_student_id

        # Generate header
        queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime +
                                                 anonymous_student_id +
                                                 str(len(self.child_history)))

        xheader = xqueue_interface.make_xheader(
            lms_callback_url=xqueue['construct_callback'](),
            lms_key=queuekey,
            queue_name=self.queue_name
        )

        contents = self.payload.copy()

        # Metadata related to the student submission revealed to the external
        # grader
        student_info = {
            'anonymous_student_id': anonymous_student_id,
            'submission_time': qtime,
        }

        # Update contents with student response and student info
        contents.update({
            'student_info': json.dumps(student_info),
            'student_response': submission,
            'max_score': self.max_score(),
        })

        # Submit request. When successful, 'msg' is the prior length of the
        # queue
        qinterface.send_to_queue(
            header=xheader,
            body=json.dumps(contents)
        )

        # State associated with the queueing request
        queuestate = {
            'key': queuekey,
            'time': qtime,
        }
        return True
    def send_to_grader(self, submission, system):
        """
        Send a given submission to the grader, via the xqueue
        @param submission: The student submission to send to the grader
        @param system: Modulesystem
        @return: Boolean true (not useful right now)
        """

        # Prepare xqueue request
        #------------------------------------------------------------

        xqueue = system.get('xqueue')
        if xqueue is None:
            return False
        qinterface = xqueue['interface']
        qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat)

        anonymous_student_id = system.anonymous_student_id

        # Generate header
        queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime +
                                                 anonymous_student_id +
                                                 str(len(self.child_history)))

        xheader = xqueue_interface.make_xheader(
            lms_callback_url=xqueue['construct_callback'](),
            lms_key=queuekey,
            queue_name=self.queue_name
        )

        contents = self.payload.copy()

        # Metadata related to the student submission revealed to the external grader
        student_info = {
            'anonymous_student_id': anonymous_student_id,
            'submission_time': qtime,
        }

        # Update contents with student response and student info
        contents.update({
            'student_info': json.dumps(student_info),
            'student_response': submission,
            'max_score': self.max_score(),
        })

        # Submit request. When successful, 'msg' is the prior length of the queue
        qinterface.send_to_queue(
            header=xheader,
            body=json.dumps(contents)
        )

        # State associated with the queueing request
        queuestate = {
            'key': queuekey,
            'time': qtime,
        }
        return True
    def _generate_cert(self, cert, course, student, grade_contents, template_pdf, generate_pdf):
        """
        Generate a certificate for the student. If `generate_pdf` is True,
        sends a request to XQueue.
        """
        course_id = unicode(course.id)

        key = make_hashkey(random.random())
        cert.key = key
        contents = {
            'action': 'create',
            'username': student.username,
            'course_id': course_id,
            'course_name': course.display_name or course_id,
            'name': cert.name,
            'grade': grade_contents,
            'template_pdf': template_pdf,
        }
        if generate_pdf:
            cert.status = status.generating
        else:
            cert.status = status.downloadable
            cert.verify_uuid = uuid4().hex

        cert.save()
        logging.info(u'certificate generated for user: %s with generate_pdf status: %s',
                     student.username, generate_pdf)

        if generate_pdf:
            try:
                self._send_to_xqueue(contents, key)
            except XQueueAddToQueueError as exc:
                cert.status = ExampleCertificate.STATUS_ERROR
                cert.error_reason = unicode(exc)
                cert.save()
                LOGGER.critical(
                    (
                        u"Could not add certificate task to XQueue.  "
                        u"The course was '%s' and the student was '%s'."
                        u"The certificate task status has been marked as 'error' "
                        u"and can be re-submitted with a management command."
                    ), course_id, student.id
                )
            else:
                LOGGER.info(
                    (
                        u"The certificate status has been set to '%s'.  "
                        u"Sent a certificate grading task to the XQueue "
                        u"with the key '%s'. "
                    ),
                    cert.status,
                    key
                )
        return cert
Пример #5
0
    def _generate_cert(self, cert, course, student, grade_contents, template_pdf, generate_pdf):
        """
        Generate a certificate for the student. If `generate_pdf` is True,
        sends a request to XQueue.
        """
        course_id = unicode(course.id)

        key = make_hashkey(random.random())
        cert.key = key
        contents = {
            'action': 'create',
            'username': student.username,
            'course_id': course_id,
            'course_name': course.display_name or course_id,
            'name': cert.name,
            'grade': grade_contents,
            'template_pdf': template_pdf,
        }
        if generate_pdf:
            cert.status = status.generating
        else:
            cert.status = status.downloadable
            cert.verify_uuid = uuid4().hex

        cert.save()
        logging.info(u'certificate generated for user: %s with generate_pdf status: %s',
                     student.username, generate_pdf)

        if generate_pdf:
            try:
                self._send_to_xqueue(contents, key)
            except XQueueAddToQueueError as exc:
                cert.status = ExampleCertificate.STATUS_ERROR
                cert.error_reason = unicode(exc)
                cert.save()
                LOGGER.critical(
                    (
                        u"Could not add certificate task to XQueue.  "
                        u"The course was '%s' and the student was '%s'."
                        u"The certificate task status has been marked as 'error' "
                        u"and can be re-submitted with a management command."
                    ), course_id, student.id
                )
            else:
                LOGGER.info(
                    (
                        u"The certificate status has been set to '%s'.  "
                        u"Sent a certificate grading task to the XQueue "
                        u"with the key '%s'. "
                    ),
                    cert.status,
                    key
                )
        return cert
def generate_fun_certificate(student,
                             course_id,
                             course_display_name, course,
                             teachers,
                             organization_display_name, organization_logo,
                             certificate_base_filename, ignore_grades, new_grade, fail_flag):
    """Generates a certificate for one student and one course."""

    profile = UserProfile.objects.get(user=student)
    student_name = unicode(profile.name).encode('utf-8')
    # grade the student
    cert, _created = GeneratedCertificate.objects.get_or_create(
        user=student, course_id=course_id
    )
    request.user = student
    grade = grades.grade(student, request, course)
    cert.grade = grade['percent']
    cert.user = student
    cert.course_id = course_id
    cert.name = profile.name
    fail = False

    if ignore_grades:
        cert.grade = 1
    elif new_grade:
        fail = fail_flag
        cert.grade = new_grade
    elif grade['grade'] is None:
        ## edx grading
        fail = True

    if fail:
        cert.status = status.notpassing
    else:
        key = make_hashkey(random.random())
        cert.key = key
        certificate_filename = certificate_base_filename + key + ".pdf"
        certificate_language = Course.get_course_language(unicode(course_id))
        info = CertificateInfo(
            student_name, course_display_name,
            organization_display_name, organization_logo,
            certificate_filename, teachers, language=certificate_language
        )
        info.generate()

        cert.status = status.downloadable
        cert.download_url = settings.CERTIFICATE_BASE_URL + certificate_filename
    cert.save()
    return cert.status
Пример #7
0
def generate_fun_certificate(student, course_id, course_display_name, course, teachers, organization_display_name, organization_logo, certificate_base_filename,ignore_grades, new_grade):
    """Generates a certificate for one student and one course."""

    profile = UserProfile.objects.get(user=student)
    student_name = unicode(profile.name).encode('utf-8')
    # grade the student
    cert, created = GeneratedCertificate.objects.get_or_create(
        user=student, course_id=course_id)

    request.user = student
    grade = grades.grade(student, request, course)
    cert.grade = grade['percent']
    cert.user = student
    cert.course_id = course_id
    cert.name = profile.name

    if ignore_grades:
      grade['grade'] = 'A'
      grade['percent'] = 100.0

    if new_grade:
        grade['grade'] = 'A'
        cert.grade = new_grade
        cert.save()

    if grade['grade'] is None:
        cert.status = status.notpassing
    else:
        key = make_hashkey(random.random())
        cert.key = key
        info = CertificateInfo()
        info.full_name = student_name
        info.course_name = course_display_name
        info.teachers = teachers
        info.organization = organization_display_name
        info.organization_logo = organization_logo
        certificate_filename = certificate_base_filename + key + ".pdf";

        info.pdf_file_name = os.path.join(
            settings.CERTIFICATES_DIRECTORY, certificate_filename)
        if info.generate():
            cert.status = status.downloadable
            cert.download_url = settings.CERTIFICATE_BASE_URL + certificate_filename
        else:
            cert.status = status.error
            cert.error_reason = "Error while generating PDF file"
    cert.save()
    return cert.status
Пример #8
0
def _generate_certificate(user, course_id):
    """
    Generate a certificate for this user, in this course run.
    """
    profile = UserProfile.objects.get(user=user)
    profile_name = profile.name

    course = modulestore().get_course(course_id, depth=0)
    course_grade = CourseGradeFactory().read(user, course)
    enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(user, course_id)
    key = make_hashkey(random.random())
    uuid = uuid4().hex

    cert, created = GeneratedCertificate.objects.update_or_create(
        user=user,
        course_id=course_id,
        defaults={
            'user': user,
            'course_id': course_id,
            'mode': enrollment_mode,
            'name': profile_name,
            'status': CertificateStatuses.downloadable,
            'grade': course_grade.percent,
            'download_url': '',
            'key': key,
            'verify_uuid': uuid
        }
    )

    if created:
        created_msg = 'Certificate was created.'
    else:
        created_msg = 'Certificate already existed and was updated.'
    log.info(
        'Generated certificate with status {status} for {user} : {course}. {created_msg}'.format(
            status=cert.status,
            user=cert.user.id,
            course=cert.course_id,
            created_msg=created_msg
        ))
    return cert
Пример #9
0
def _generate_cert(cert, course, student, grade_contents, template_pdf):
        """
        Generate a certificate for the student. If `generate_pdf` is True,
        sends a request to XQueue.
        """
        course_id = unicode(course.id)

        key = make_hashkey(random.random())
        cert.key = key
        contents = {
            'action': 'create',
            'username': student.username,
            'course_id': course_id,
            'course_name': course.display_name or course_id,
            'name': cert.name,
            'grade': grade_contents,
            'template_pdf': template_pdf,
        }
        cert.status = CertificateStatuses.downloadable
        cert.verify_uuid = uuid4().hex

        cert.save()
	return cert
Пример #10
0
    def add_cert(self, student, course_id, course=None):
        """

        Arguments:
          student - User.object
          course_id - courseenrollment.course_id (string)

        Request a new certificate for a student.
        Will change the certificate status to 'generating'.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'


        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status

        """

        VALID_STATUSES = [status.generating,
                          status.unavailable, status.deleted, status.error,
                          status.notpassing]

        cert_status = certificate_status_for_student(
            student, course_id)['status']

        if cert_status in VALID_STATUSES:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = courses.get_course_by_id(course_id)
            profile = UserProfile.objects.get(user=student)

            cert, created = GeneratedCertificate.objects.get_or_create(
                user=student, course_id=course_id)

            grade = grades.grade(student, self.request, course)
            is_whitelisted = self.whitelist.filter(
                user=student, course_id=course_id, whitelist=True).exists()

            if is_whitelisted or grade['grade'] is not None:

                key = make_hashkey(random.random())

                cert.grade = grade['percent']
                cert.user = student
                cert.course_id = course_id
                cert.key = key
                cert.name = profile.name

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue
                if self.restricted.filter(user=student).exists():
                    cert.status = status.restricted
                else:
                    contents = {
                        'action': 'create',
                        'username': student.username,
                        'course_id': course_id,
                        'name': profile.name,
                    }
                    cert.status = status.generating
                    self._send_to_xqueue(contents, key)
                cert.save()
            else:
                cert_status = status.notpassing
                cert.grade = grade['percent']
                cert.status = cert_status
                cert.user = student
                cert.course_id = course_id
                cert.name = profile.name
                cert.save()

        return cert_status
Пример #11
0
    def add_cert(self, student, course_id, course=None, forced_grade=None, template_file=None, title="None"):
        """
        Request a new certificate for a student.

        Arguments:
          student   - User.object
          course_id - courseenrollment.course_id (CourseKey)
          forced_grade - a string indicating a grade parameter to pass with
                         the certificate request. If this is given, grading
                         will be skipped.

        Will change the certificate status to 'generating'.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will be made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'

        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status
        """

        VALID_STATUSES = [status.generating, status.unavailable, status.deleted, status.error, status.notpassing]

        cert_status = certificate_status_for_student(student, course_id)["status"]

        new_status = cert_status

        if cert_status in VALID_STATUSES:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = courses.get_course_by_id(course_id)
            profile = UserProfile.objects.get(user=student)
            profile_name = profile.name

            # Needed
            self.request.user = student
            self.request.session = {}

            course_name = course.display_name or course_id.to_deprecated_string()
            is_whitelisted = self.whitelist.filter(user=student, course_id=course_id, whitelist=True).exists()
            grade = grades.grade(student, self.request, course)
            enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(student, course_id)
            mode_is_verified = enrollment_mode == GeneratedCertificate.MODES.verified
            user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(student)
            user_is_reverified = SoftwareSecurePhotoVerification.user_is_reverified_for_all(course_id, student)
            cert_mode = enrollment_mode
            if mode_is_verified and user_is_verified and user_is_reverified:
                template_pdf = "certificate-template-{id.org}-{id.course}-verified.pdf".format(id=course_id)
            elif mode_is_verified and not (user_is_verified and user_is_reverified):
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id)
                cert_mode = GeneratedCertificate.MODES.honor
            else:
                # honor code and audit students
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id)
            if forced_grade:
                grade["grade"] = forced_grade

            cert, __ = GeneratedCertificate.objects.get_or_create(user=student, course_id=course_id)

            cert.mode = cert_mode
            cert.user = student
            cert.grade = grade["percent"]
            cert.course_id = course_id
            cert.name = profile_name
            # Strip HTML from grade range label
            grade_contents = grade.get("grade", None)
            try:
                grade_contents = lxml.html.fromstring(grade_contents).text_content()
            except (TypeError, XMLSyntaxError, ParserError) as e:
                #   Despite blowing up the xml parser, bad values here are fine
                grade_contents = None

            if is_whitelisted or grade_contents is not None:

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue

                if self.restricted.filter(user=student).exists():
                    new_status = status.restricted
                    cert.status = new_status
                    cert.save()
                else:
                    key = make_hashkey(random.random())
                    cert.key = key
                    contents = {
                        "action": "create",
                        "username": student.username,
                        "course_id": course_id.to_deprecated_string(),
                        "course_name": course_name,
                        "name": profile_name,
                        "grade": grade_contents,
                        "template_pdf": template_pdf,
                    }
                    if template_file:
                        contents["template_pdf"] = template_file
                    new_status = status.generating
                    cert.status = new_status
                    cert.save()
                    self._send_to_xqueue(contents, key)
            else:
                cert_status = status.notpassing
                cert.status = cert_status
                cert.save()

        return new_status
Пример #12
0
    def send_to_grader(self, submission, system):
        """
        Send a given submission to the grader, via the xqueue
        @param submission: The student submission to send to the grader
        @param system: Modulesystem
        @return: Boolean true (not useful right now)
        """

        # Prepare xqueue request
        #------------------------------------------------------------

        xqueue = system.get('xqueue')
        if xqueue is None:
            return False
        qinterface = xqueue['interface']
        qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat)

        anonymous_student_id = system.anonymous_student_id

        # Generate header
        queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime +
                                                 anonymous_student_id +
                                                 str(len(self.child_history)))

        xheader = xqueue_interface.make_xheader(
            lms_callback_url=xqueue['construct_callback'](),
            lms_key=queuekey,
            queue_name=self.queue_name
        )

        contents = self.payload.copy()

        # Metadata related to the student submission revealed to the external grader
        student_info = {
            'anonymous_student_id': anonymous_student_id,
            'submission_time': qtime,
        }

        # Update contents with student response and student info
        contents.update({
            'student_info': json.dumps(student_info),
            'student_response': submission,
            'max_score': self.max_score(),
        })

        # Submit request. When successful, 'msg' is the prior length of the queue
        error, error_message = qinterface.send_to_queue(
            header=xheader,
            body=json.dumps(contents)
        )

        # State associated with the queueing request
        queuestate = {
            'key': queuekey,
            'time': qtime,
        }
        _ = self.system.service(self, "i18n").ugettext
        success = True
        message = _("Successfully saved your submission.")
        if error:
            success = False
            # Translators: the `grader` refers to the grading service open response problems
            # are sent to, either to be machine-graded, peer-graded, or instructor-graded.
            message = _('Unable to submit your submission to the grader. Please try again later.')
            log.error("Unable to submit to grader. location: {0}, error_message: {1}".format(
                self.location_string, error_message
            ))

        return (success, message)
Пример #13
0
    def message_post(self, data, system):
        """
        Handles a student message post (a reaction to the grade they received from an open ended grader type)
        Returns a boolean success/fail and an error message
        """

        event_info = dict()
        event_info['problem_id'] = self.location_string
        event_info['student_id'] = system.anonymous_student_id
        event_info['survey_responses'] = data
        _ = self.system.service(self, "i18n").ugettext

        survey_responses = event_info['survey_responses']
        for tag in ['feedback', 'submission_id', 'grader_id', 'score']:
            if tag not in survey_responses:
                # This is a student_facing_error
                return {
                    'success': False,
                    # Translators: 'tag' is one of 'feedback', 'submission_id',
                    # 'grader_id', or 'score'. They are categories that a student
                    # responds to when filling out a post-assessment survey
                    # of his or her grade from an openended problem.
                    'msg': _("Could not find needed tag {tag_name} in the "
                             "survey responses. Please try submitting "
                             "again.").format(tag_name=tag)
                }
        try:
            submission_id = int(survey_responses['submission_id'])
            grader_id = int(survey_responses['grader_id'])
            feedback = str(survey_responses['feedback'].encode('ascii', 'ignore'))
            score = int(survey_responses['score'])
        except:
            # This is a dev_facing_error
            error_message = (
                "Could not parse submission id, grader id, "
                "or feedback from message_post ajax call.  "
                "Here is the message data: {0}".format(survey_responses)
            )
            log.exception(error_message)
            # This is a student_facing_error
            return {
                'success': False,
                'msg': _(
                    "There was an error saving your feedback. Please "
                    "contact course staff."
                )
            }

        xqueue = system.get('xqueue')
        if xqueue is None:
            return {'success': False, 'msg': _("Couldn't submit feedback.")}
        qinterface = xqueue['interface']
        qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat)
        anonymous_student_id = system.anonymous_student_id
        queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime +
                                                 anonymous_student_id +
                                                 str(len(self.child_history)))

        xheader = xqueue_interface.make_xheader(
            lms_callback_url=xqueue['construct_callback'](),
            lms_key=queuekey,
            queue_name=self.message_queue_name
        )

        student_info = {
            'anonymous_student_id': anonymous_student_id,
            'submission_time': qtime,
        }
        contents = {
            'feedback': feedback,
            'submission_id': submission_id,
            'grader_id': grader_id,
            'score': score,
            'student_info': json.dumps(student_info),
        }

        error, error_message = qinterface.send_to_queue(
            header=xheader,
            body=json.dumps(contents)
        )

        # Convert error to a success value
        success = True
        message = _("Successfully saved your feedback.")
        if error:
            success = False
            message = _("Unable to save your feedback. Please try again later.")
            log.error("Unable to send feedback to grader. location: {0}, error_message: {1}".format(
                self.location_string, error_message
            ))
        else:
            self.child_state = self.DONE

        # This is a student_facing_message
        return {'success': success, 'msg': message}
Пример #14
0
    def add_cert(self, student, course_id, course=None):
        """

        Arguments:
          student - User.object
          course_id - courseenrollment.course_id (string)

        Request a new certificate for a student.
        Will change the certificate status to 'generating'.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'

        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status

        """

        VALID_STATUSES = [status.generating,
                          status.unavailable,
                          status.deleted,
                          status.error,
                          status.notpassing]

        cert_status = certificate_status_for_student(student, course_id)['status']

        new_status = cert_status

        if cert_status in VALID_STATUSES:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = courses.get_course_by_id(course_id)
            profile = UserProfile.objects.get(user=student)

            # Needed
            self.request.user = student
            self.request.session = {}

            grade = grades.grade(student, self.request, course)
            is_whitelisted = self.whitelist.filter(
                user=student, course_id=course_id, whitelist=True).exists()
            enrollment_mode = CourseEnrollment.enrollment_mode_for_user(student, course_id)
            mode_is_verified = (enrollment_mode == GeneratedCertificate.MODES.verified)
            user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(student)
            user_is_reverified = SoftwareSecurePhotoVerification.user_is_reverified_for_all(course_id, student)
            org = course_id.split('/')[0]
            course_num = course_id.split('/')[1]
            cert_mode = enrollment_mode
            if (mode_is_verified and user_is_verified and user_is_reverified):
                template_pdf = "certificate-template-{0}-{1}-verified.pdf".format(
                    org, course_num)
            elif (mode_is_verified and not (user_is_verified and user_is_reverified)):
                template_pdf = "certificate-template-{0}-{1}.pdf".format(
                    org, course_num)
                cert_mode = GeneratedCertificate.MODES.honor
            else:
                # honor code and audit students
                template_pdf = "certificate-template-{0}-{1}.pdf".format(
                    org, course_num)

            cert, created = GeneratedCertificate.objects.get_or_create(
                user=student, course_id=course_id)

            cert.mode = cert_mode
            cert.user = student
            cert.grade = grade['percent']
            cert.course_id = course_id
            cert.name = profile.name

            if is_whitelisted or grade['grade'] is not None:

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue

                if self.restricted.filter(user=student).exists():
                    new_status = status.restricted
                    cert.status = new_status
                    cert.save()
                else:
                    key = make_hashkey(random.random())
                    cert.key = key
                    contents = {
                        'action': 'create',
                        'username': student.username,
                        'course_id': course_id,
                        'name': profile.name,
                        'grade': grade['grade'],
                        'template_pdf': template_pdf,
                    }
                    new_status = status.generating
                    cert.status = new_status
                    cert.save()
                    self._send_to_xqueue(contents, key)
            else:
                new_status = status.notpassing
                cert.status = new_status
                cert.save()

        return new_status
Пример #15
0
    def add_cert(self, student, course_id, course=None, forced_grade=None, template_file=None,
                 title='None', generate_pdf=True):
        """
        Request a new certificate for a student.

        Arguments:
          student   - User.object
          course_id - courseenrollment.course_id (CourseKey)
          forced_grade - a string indicating a grade parameter to pass with
                         the certificate request. If this is given, grading
                         will be skipped.
          generate_pdf - Boolean should a message be sent in queue to generate certificate PDF

        Will change the certificate status to 'generating' or
        `downloadable` in case of web view certificates.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will be made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'

        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status and newly created certificate instance
        """

        valid_statuses = [
            status.generating,
            status.unavailable,
            status.deleted,
            status.error,
            status.notpassing,
            status.downloadable
        ]

        cert_status = certificate_status_for_student(student, course_id)['status']
        new_status = cert_status
        cert = None

        if cert_status not in valid_statuses:
            LOGGER.warning(
                (
                    u"Cannot create certificate generation task for user %s "
                    u"in the course '%s'; "
                    u"the certificate status '%s' is not one of %s."
                ),
                student.id,
                unicode(course_id),
                cert_status,
                unicode(valid_statuses)
            )
        else:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = modulestore().get_course(course_id, depth=0)
            profile = UserProfile.objects.get(user=student)
            profile_name = profile.name

            # Needed
            self.request.user = student
            self.request.session = {}

            course_name = course.display_name or unicode(course_id)
            is_whitelisted = self.whitelist.filter(user=student, course_id=course_id, whitelist=True).exists()
            grade = grades.grade(student, self.request, course)
            enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(student, course_id)
            mode_is_verified = enrollment_mode in GeneratedCertificate.VERIFIED_CERTS_MODES
            user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(student)
            cert_mode = enrollment_mode

            # For credit mode generate verified certificate
            if cert_mode == CourseMode.CREDIT_MODE:
                cert_mode = CourseMode.VERIFIED

            if mode_is_verified and user_is_verified:
                template_pdf = "certificate-template-{id.org}-{id.course}-verified.pdf".format(id=course_id)
            elif mode_is_verified and not user_is_verified:
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id)
                cert_mode = GeneratedCertificate.MODES.honor
            else:
                # honor code and audit students
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id)
            if forced_grade:
                grade['grade'] = forced_grade

            cert, __ = GeneratedCertificate.objects.get_or_create(user=student, course_id=course_id)

            cert.mode = cert_mode
            cert.user = student
            cert.grade = grade['percent']
            cert.course_id = course_id
            cert.name = profile_name
            cert.download_url = ''
            # Strip HTML from grade range label
            grade_contents = grade.get('grade', None)
            try:
                grade_contents = lxml.html.fromstring(grade_contents).text_content()
            except (TypeError, XMLSyntaxError, ParserError) as exc:
                LOGGER.info(
                    (
                        u"Could not retrieve grade for student %s "
                        u"in the course '%s' "
                        u"because an exception occurred while parsing the "
                        u"grade contents '%s' as HTML. "
                        u"The exception was: '%s'"
                    ),
                    student.id,
                    unicode(course_id),
                    grade_contents,
                    unicode(exc)
                )

                #   Despite blowing up the xml parser, bad values here are fine
                grade_contents = None

            if is_whitelisted or grade_contents is not None:

                if is_whitelisted:
                    LOGGER.info(
                        u"Student %s is whitelisted in '%s'",
                        student.id,
                        unicode(course_id)
                    )

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue

                if self.restricted.filter(user=student).exists():
                    new_status = status.restricted
                    cert.status = new_status
                    cert.save()

                    LOGGER.info(
                        (
                            u"Student %s is in the embargoed country restricted "
                            u"list, so their certificate status has been set to '%s' "
                            u"for the course '%s'. "
                            u"No certificate generation task was sent to the XQueue."
                        ),
                        student.id,
                        new_status,
                        unicode(course_id)
                    )
                else:
                    key = make_hashkey(random.random())
                    cert.key = key
                    contents = {
                        'action': 'create',
                        'username': student.username,
                        'course_id': unicode(course_id),
                        'course_name': course_name,
                        'name': profile_name,
                        'grade': grade_contents,
                        'template_pdf': template_pdf,
                    }
                    if template_file:
                        contents['template_pdf'] = template_file
                    if generate_pdf:
                        new_status = status.generating
                    else:
                        new_status = status.downloadable
                        cert.verify_uuid = uuid4().hex

                    cert.status = new_status
                    cert.save()

                    if generate_pdf:
                        try:
                            self._send_to_xqueue(contents, key)
                        except XQueueAddToQueueError as exc:
                            new_status = ExampleCertificate.STATUS_ERROR
                            cert.status = new_status
                            cert.error_reason = unicode(exc)
                            cert.save()
                            LOGGER.critical(
                                (
                                    u"Could not add certificate task to XQueue.  "
                                    u"The course was '%s' and the student was '%s'."
                                    u"The certificate task status has been marked as 'error' "
                                    u"and can be re-submitted with a management command."
                                ), course_id, student.id
                            )
                        else:
                            LOGGER.info(
                                (
                                    u"The certificate status has been set to '%s'.  "
                                    u"Sent a certificate grading task to the XQueue "
                                    u"with the key '%s'. "
                                ),
                                new_status,
                                key
                            )
            else:
                new_status = status.notpassing
                cert.status = new_status
                cert.save()

                LOGGER.info(
                    (
                        u"Student %s does not have a grade for '%s', "
                        u"so their certificate status has been set to '%s'. "
                        u"No certificate generation task was sent to the XQueue."
                    ),
                    student.id,
                    unicode(course_id),
                    new_status
                )

        return new_status, cert
Пример #16
0
def make_certificate_hash_key():
    return make_hashkey(random.random())
    def message_post(self, data, system):
        """
        Handles a student message post (a reaction to the grade they received from an open ended grader type)
        Returns a boolean success/fail and an error message
        """

        event_info = dict()
        event_info['problem_id'] = self.location_string
        event_info['student_id'] = system.anonymous_student_id
        event_info['survey_responses'] = data

        survey_responses = event_info['survey_responses']
        for tag in ['feedback', 'submission_id', 'grader_id', 'score']:
            if tag not in survey_responses:
                # This is a student_facing_error
                return {'success': False,
                        'msg': "Could not find needed tag {0} in the survey responses.  Please try submitting again.".format(
                            tag)}
        try:
            submission_id = int(survey_responses['submission_id'])
            grader_id = int(survey_responses['grader_id'])
            feedback = str(survey_responses['feedback'].encode('ascii', 'ignore'))
            score = int(survey_responses['score'])
        except:
            # This is a dev_facing_error
            error_message = (
                "Could not parse submission id, grader id, "
                "or feedback from message_post ajax call.  "
                "Here is the message data: {0}".format(survey_responses)
            )
            log.exception(error_message)
            # This is a student_facing_error
            return {'success': False, 'msg': "There was an error saving your feedback.  Please contact course staff."}

        xqueue = system.get('xqueue')
        if xqueue is None:
            return {'success': False, 'msg': "Couldn't submit feedback."}
        qinterface = xqueue['interface']
        qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat)
        anonymous_student_id = system.anonymous_student_id
        queuekey = xqueue_interface.make_hashkey(str(system.seed) + qtime +
                                                 anonymous_student_id +
                                                 str(len(self.child_history)))

        xheader = xqueue_interface.make_xheader(
            lms_callback_url=xqueue['construct_callback'](),
            lms_key=queuekey,
            queue_name=self.message_queue_name
        )

        student_info = {
            'anonymous_student_id': anonymous_student_id,
            'submission_time': qtime,
        }
        contents = {
            'feedback': feedback,
            'submission_id': submission_id,
            'grader_id': grader_id,
            'score': score,
            'student_info': json.dumps(student_info),
        }

        (error, msg) = qinterface.send_to_queue(
            header=xheader,
            body=json.dumps(contents)
        )

        # Convert error to a success value
        success = True
        if error:
            success = False

        self.child_state = self.DONE

        # This is a student_facing_message
        return {'success': success, 'msg': "Successfully submitted your feedback."}
Пример #18
0
    def add_cert(self,
                 student,
                 course_id,
                 course=None,
                 forced_grade=None,
                 template_file=None,
                 title='None',
                 generate_pdf=True):
        """
        Request a new certificate for a student.

        Arguments:
          student   - User.object
          course_id - courseenrollment.course_id (CourseKey)
          forced_grade - a string indicating a grade parameter to pass with
                         the certificate request. If this is given, grading
                         will be skipped.
          generate_pdf - Boolean should a message be sent in queue to generate certificate PDF

        Will change the certificate status to 'generating' or
        `downloadable` in case of web view certificates.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will be made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'

        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status and newly created certificate instance
        """

        valid_statuses = [
            status.generating, status.unavailable, status.deleted,
            status.error, status.notpassing, status.downloadable
        ]

        cert_status = certificate_status_for_student(student,
                                                     course_id)['status']
        new_status = cert_status
        cert = None

        if cert_status not in valid_statuses:
            LOGGER.warning(
                (u"Cannot create certificate generation task for user %s "
                 u"in the course '%s'; "
                 u"the certificate status '%s' is not one of %s."), student.id,
                unicode(course_id), cert_status, unicode(valid_statuses))
        else:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = modulestore().get_course(course_id, depth=0)
            profile = UserProfile.objects.get(user=student)
            profile_name = profile.name

            # Needed
            self.request.user = student
            self.request.session = {}

            course_name = course.display_name or unicode(course_id)
            is_whitelisted = self.whitelist.filter(user=student,
                                                   course_id=course_id,
                                                   whitelist=True).exists()
            grade = grades.grade(student, self.request, course)
            enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(
                student, course_id)
            mode_is_verified = (
                enrollment_mode == GeneratedCertificate.MODES.verified)
            user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(
                student)
            cert_mode = enrollment_mode
            if mode_is_verified and user_is_verified:
                template_pdf = "certificate-template-{id.org}-{id.course}-verified.pdf".format(
                    id=course_id)
            elif mode_is_verified and not user_is_verified:
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(
                    id=course_id)
                cert_mode = GeneratedCertificate.MODES.honor
            else:
                # honor code and audit students
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(
                    id=course_id)
            if forced_grade:
                grade['grade'] = forced_grade

            cert, __ = GeneratedCertificate.objects.get_or_create(
                user=student, course_id=course_id)

            cert.mode = cert_mode
            cert.user = student
            cert.grade = grade['percent']
            cert.course_id = course_id
            cert.name = profile_name
            cert.download_url = ''
            # Strip HTML from grade range label
            grade_contents = grade.get('grade', None)
            try:
                grade_contents = lxml.html.fromstring(
                    grade_contents).text_content()
            except (TypeError, XMLSyntaxError, ParserError) as exc:
                LOGGER.info(
                    (u"Could not retrieve grade for student %s "
                     u"in the course '%s' "
                     u"because an exception occurred while parsing the "
                     u"grade contents '%s' as HTML. "
                     u"The exception was: '%s'"), student.id,
                    unicode(course_id), grade_contents, unicode(exc))

                #   Despite blowing up the xml parser, bad values here are fine
                grade_contents = None

            if is_whitelisted or grade_contents is not None:

                if is_whitelisted:
                    LOGGER.info(u"Student %s is whitelisted in '%s'",
                                student.id, unicode(course_id))

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue

                if self.restricted.filter(user=student).exists():
                    new_status = status.restricted
                    cert.status = new_status
                    cert.save()

                    LOGGER.info((
                        u"Student %s is in the embargoed country restricted "
                        u"list, so their certificate status has been set to '%s' "
                        u"for the course '%s'. "
                        u"No certificate generation task was sent to the XQueue."
                    ), student.id, new_status, unicode(course_id))
                else:
                    key = make_hashkey(random.random())
                    cert.key = key
                    contents = {
                        'action': 'create',
                        'username': student.username,
                        'course_id': unicode(course_id),
                        'course_name': course_name,
                        'name': profile_name,
                        'grade': grade_contents,
                        'template_pdf': template_pdf,
                    }
                    if template_file:
                        contents['template_pdf'] = template_file
                    if generate_pdf:
                        new_status = status.generating
                    else:
                        new_status = status.downloadable
                        cert.verify_uuid = uuid4().hex

                    cert.status = new_status
                    cert.save()

                    if generate_pdf:
                        try:
                            self._send_to_xqueue(contents, key)
                        except XQueueAddToQueueError as exc:
                            new_status = ExampleCertificate.STATUS_ERROR
                            cert.status = new_status
                            cert.error_reason = unicode(exc)
                            cert.save()
                            LOGGER.critical((
                                u"Could not add certificate task to XQueue.  "
                                u"The course was '%s' and the student was '%s'."
                                u"The certificate task status has been marked as 'error' "
                                u"and can be re-submitted with a management command."
                            ), course_id, student.id)
                        else:
                            LOGGER.info((
                                u"The certificate status has been set to '%s'.  "
                                u"Sent a certificate grading task to the XQueue "
                                u"with the key '%s'. "), new_status, key)
            else:
                new_status = status.notpassing
                cert.status = new_status
                cert.save()

                LOGGER.info((
                    u"Student %s does not have a grade for '%s', "
                    u"so their certificate status has been set to '%s'. "
                    u"No certificate generation task was sent to the XQueue."),
                            student.id, unicode(course_id), new_status)

        return new_status, cert
Пример #19
0
def make_certificate_hash_key():
    return make_hashkey(random.random())
    def message_post(self, data, system):
        """
        Handles a student message post (a reaction to the grade they received from an open ended grader type)
        Returns a boolean success/fail and an error message
        """

        event_info = dict()
        event_info['problem_id'] = self.location_string
        event_info['student_id'] = system.anonymous_student_id
        event_info['survey_responses'] = data
        _ = self.system.service(self, "i18n").ugettext

        survey_responses = event_info['survey_responses']
        for tag in ['feedback', 'submission_id', 'grader_id', 'score']:
            if tag not in survey_responses:
                # This is a student_facing_error
                return {
                    'success':
                    False,
                    # Translators: 'tag' is one of 'feedback', 'submission_id',
                    # 'grader_id', or 'score'. They are categories that a student
                    # responds to when filling out a post-assessment survey
                    # of his or her grade from an openended problem.
                    'msg':
                    _("Could not find needed tag {tag_name} in the "
                      "survey responses. Please try submitting "
                      "again.").format(tag_name=tag)
                }
        try:
            submission_id = int(survey_responses['submission_id'])
            grader_id = int(survey_responses['grader_id'])
            feedback = str(survey_responses['feedback'].encode(
                'ascii', 'ignore'))
            score = int(survey_responses['score'])
        except:
            # This is a dev_facing_error
            error_message = (
                "Could not parse submission id, grader id, "
                "or feedback from message_post ajax call.  "
                "Here is the message data: {0}".format(survey_responses))
            log.exception(error_message)
            # This is a student_facing_error
            return {
                'success':
                False,
                'msg':
                _("There was an error saving your feedback. Please "
                  "contact course staff.")
            }

        xqueue = system.get('xqueue')
        if xqueue is None:
            return {'success': False, 'msg': _("Couldn't submit feedback.")}
        qinterface = xqueue['interface']
        qtime = datetime.strftime(datetime.now(UTC),
                                  xqueue_interface.dateformat)
        anonymous_student_id = system.anonymous_student_id
        queuekey = xqueue_interface.make_hashkey(
            str(system.seed) + qtime + anonymous_student_id +
            str(len(self.child_history)))

        xheader = xqueue_interface.make_xheader(
            lms_callback_url=xqueue['construct_callback'](),
            lms_key=queuekey,
            queue_name=self.message_queue_name)

        student_info = {
            'anonymous_student_id': anonymous_student_id,
            'submission_time': qtime,
        }
        contents = {
            'feedback': feedback,
            'submission_id': submission_id,
            'grader_id': grader_id,
            'score': score,
            'student_info': json.dumps(student_info),
        }

        error, error_message = qinterface.send_to_queue(
            header=xheader, body=json.dumps(contents))

        # Convert error to a success value
        success = True
        message = _("Successfully saved your feedback.")
        if error:
            success = False
            message = _(
                "Unable to save your feedback. Please try again later.")
            log.error(
                "Unable to send feedback to grader. location: {0}, error_message: {1}"
                .format(self.location_string, error_message))
        else:
            self.child_state = self.DONE

        # This is a student_facing_message
        return {'success': success, 'msg': message}
Пример #21
0
    def add_cert(self, student, course_id, course=None, forced_grade=None, template_file=None, title='None'):
        """
        Request a new certificate for a student.

        Arguments:
          student   - User.object
          course_id - courseenrollment.course_id (CourseKey)
          forced_grade - a string indicating a grade parameter to pass with
                         the certificate request. If this is given, grading
                         will be skipped.

        Will change the certificate status to 'generating'.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will be made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'

        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status
        """

        valid_statuses = [
            status.generating,
            status.unavailable,
            status.deleted,
            status.error,
            status.notpassing
        ]

        cert_status = certificate_status_for_student(student, course_id)['status']
        new_status = cert_status

        if cert_status not in valid_statuses:
            LOGGER.warning(
                (
                    u"Cannot create certificate generation task for user %s "
                    u"in the course '%s'; "
                    u"the certificate status '%s' is not one of %s."
                ),
                student.id,
                unicode(course_id),
                cert_status,
                unicode(valid_statuses)
            )
        else:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = courses.get_course_by_id(course_id)
            profile = UserProfile.objects.get(user=student)
            profile_name = profile.name

            # Needed
            self.request.user = student
            self.request.session = {}

            course_name = course.display_name or course_id.to_deprecated_string()
            is_whitelisted = self.whitelist.filter(user=student, course_id=course_id, whitelist=True).exists()
            grade = grades.grade(student, self.request, course)
            enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(student, course_id)
            mode_is_verified = (enrollment_mode == GeneratedCertificate.MODES.verified)
            user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(student)
            user_is_reverified = SoftwareSecurePhotoVerification.user_is_reverified_for_all(course_id, student)
            cert_mode = enrollment_mode
            if (mode_is_verified and user_is_verified and user_is_reverified):
                template_pdf = "certificate-template-{id.org}-{id.course}-verified.pdf".format(id=course_id)
            elif (mode_is_verified and not (user_is_verified and user_is_reverified)):
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id)
                cert_mode = GeneratedCertificate.MODES.honor
            else:
                # honor code and audit students
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(id=course_id)
            if forced_grade:
                grade['grade'] = forced_grade

            cert, __ = GeneratedCertificate.objects.get_or_create(user=student, course_id=course_id)

            cert.mode = cert_mode
            cert.user = student
            cert.grade = grade['percent']
            cert.course_id = course_id
            cert.name = profile_name
            # Strip HTML from grade range label
            grade_contents = grade.get('grade', None)
            try:
                grade_contents = lxml.html.fromstring(grade_contents).text_content()
            except (TypeError, XMLSyntaxError, ParserError) as exc:
                LOGGER.info(
                    (
                        u"Could not retrieve grade for student %s "
                        u"in the course '%s' "
                        u"because an exception occurred while parsing the "
                        u"grade contents '%s' as HTML. "
                        u"The exception was: '%s'"
                    ),
                    student.id,
                    unicode(course_id),
                    grade_contents,
                    unicode(exc)
                )

                #   Despite blowing up the xml parser, bad values here are fine
                grade_contents = None

            if is_whitelisted or grade_contents is not None:

                if is_whitelisted:
                    LOGGER.info(
                        u"Student %s is whitelisted in '%s'",
                        student.id,
                        unicode(course_id)
                    )

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue

                if self.restricted.filter(user=student).exists():
                    new_status = status.restricted
                    cert.status = new_status
                    cert.save()

                    LOGGER.info(
                        (
                            u"Student %s is in the embargoed country restricted "
                            u"list, so their certificate status has been set to '%s' "
                            u"for the course '%s'. "
                            u"No certificate generation task was sent to the XQueue."
                        ),
                        student.id,
                        new_status,
                        unicode(course_id)
                    )
                else:
                    key = make_hashkey(random.random())
                    cert.key = key
                    contents = {
                        'action': 'create',
                        'username': student.username,
                        'course_id': course_id.to_deprecated_string(),
                        'course_name': course_name,
                        'name': profile_name,
                        'grade': grade_contents,
                        'template_pdf': template_pdf,
                    }
                    if template_file:
                        contents['template_pdf'] = template_file
                    new_status = status.generating
                    cert.status = new_status
                    cert.save()
                    self._send_to_xqueue(contents, key)

                    LOGGER.info(
                        (
                            u"The certificate status has been set to '%s'.  "
                            u"Sent a certificate grading task to the XQueue "
                            u"with the key '%s'. "
                        ),
                        key,
                        new_status
                    )
            else:
                cert_status = status.notpassing
                cert.status = cert_status
                cert.save()

                LOGGER.info(
                    (
                        u"Student %s does not have a grade for '%s', "
                        u"so their certificate status has been set to '%s'. "
                        u"No certificate generation task was sent to the XQueue."
                    ),
                    student.id,
                    unicode(course_id),
                    cert_status
                )

        return new_status
Пример #22
0
    def add_cert(self,
                 student,
                 course_id,
                 course=None,
                 forced_grade=None,
                 template_file=None,
                 title='None'):
        """
        Request a new certificate for a student.

        Arguments:
          student   - User.object
          course_id - courseenrollment.course_id (CourseKey)
          forced_grade - a string indicating a grade parameter to pass with
                         the certificate request. If this is given, grading
                         will be skipped.

        Will change the certificate status to 'generating'.

        Certificate must be in the 'unavailable', 'error',
        'deleted' or 'generating' state.

        If a student has a passing grade or is in the whitelist
        table for the course a request will be made for a new cert.

        If a student has allow_certificate set to False in the
        userprofile table the status will change to 'restricted'

        If a student does not have a passing grade the status
        will change to status.notpassing

        Returns the student's status
        """

        VALID_STATUSES = [
            status.generating, status.unavailable, status.deleted,
            status.error, status.notpassing
        ]

        cert_status = certificate_status_for_student(student,
                                                     course_id)['status']

        new_status = cert_status

        if cert_status in VALID_STATUSES:
            # grade the student

            # re-use the course passed in optionally so we don't have to re-fetch everything
            # for every student
            if course is None:
                course = courses.get_course_by_id(course_id)
            profile = UserProfile.objects.get(user=student)
            profile_name = profile.name

            # Needed
            self.request.user = student
            self.request.session = {}

            course_name = course.display_name or course_id.to_deprecated_string(
            )
            is_whitelisted = self.whitelist.filter(user=student,
                                                   course_id=course_id,
                                                   whitelist=True).exists()
            grade = grades.grade(student, self.request, course)
            enrollment_mode, __ = CourseEnrollment.enrollment_mode_for_user(
                student, course_id)
            mode_is_verified = (
                enrollment_mode == GeneratedCertificate.MODES.verified)
            user_is_verified = SoftwareSecurePhotoVerification.user_is_verified(
                student)
            user_is_reverified = SoftwareSecurePhotoVerification.user_is_reverified_for_all(
                course_id, student)
            cert_mode = enrollment_mode
            if (mode_is_verified and user_is_verified and user_is_reverified):
                template_pdf = "certificate-template-{id.org}-{id.course}-verified.pdf".format(
                    id=course_id)
            elif (mode_is_verified
                  and not (user_is_verified and user_is_reverified)):
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(
                    id=course_id)
                cert_mode = GeneratedCertificate.MODES.honor
            else:
                # honor code and audit students
                template_pdf = "certificate-template-{id.org}-{id.course}.pdf".format(
                    id=course_id)
            if forced_grade:
                grade['grade'] = forced_grade

            cert, __ = GeneratedCertificate.objects.get_or_create(
                user=student, course_id=course_id)

            cert.mode = cert_mode
            cert.user = student
            cert.grade = grade['percent']
            cert.course_id = course_id
            cert.name = profile_name
            # Strip HTML from grade range label
            grade_contents = grade.get('grade', None)
            try:
                grade_contents = lxml.html.fromstring(
                    grade_contents).text_content()
            except (TypeError, XMLSyntaxError, ParserError) as e:
                #   Despite blowing up the xml parser, bad values here are fine
                grade_contents = None

            if is_whitelisted or grade_contents is not None:

                # check to see whether the student is on the
                # the embargoed country restricted list
                # otherwise, put a new certificate request
                # on the queue

                if self.restricted.filter(user=student).exists():
                    new_status = status.restricted
                    cert.status = new_status
                    cert.save()
                else:
                    key = make_hashkey(random.random())
                    cert.key = key
                    contents = {
                        'action': 'create',
                        'username': student.username,
                        'course_id': course_id.to_deprecated_string(),
                        'course_name': course_name,
                        'name': profile_name,
                        'grade': grade_contents,
                        'template_pdf': template_pdf,
                    }
                    if template_file:
                        contents['template_pdf'] = template_file
                    new_status = status.generating
                    cert.status = new_status
                    cert.save()
                    self._send_to_xqueue(contents, key)
            else:
                cert_status = status.notpassing
                cert.status = cert_status
                cert.save()

        return new_status
    def send_to_grader(self, submission, system):
        """
        Send a given submission to the grader, via the xqueue
        @param submission: The student submission to send to the grader
        @param system: Modulesystem
        @return: Boolean true (not useful right now)
        """

        # Prepare xqueue request
        #------------------------------------------------------------

        xqueue = system.get('xqueue')
        if xqueue is None:
            return False
        qinterface = xqueue['interface']
        qtime = datetime.strftime(datetime.now(UTC),
                                  xqueue_interface.dateformat)

        anonymous_student_id = system.anonymous_student_id

        # Generate header
        queuekey = xqueue_interface.make_hashkey(
            str(system.seed) + qtime + anonymous_student_id +
            str(len(self.child_history)))

        xheader = xqueue_interface.make_xheader(
            lms_callback_url=xqueue['construct_callback'](),
            lms_key=queuekey,
            queue_name=self.queue_name)

        contents = self.payload.copy()

        # Metadata related to the student submission revealed to the external grader
        student_info = {
            'anonymous_student_id': anonymous_student_id,
            'submission_time': qtime,
        }

        # Update contents with student response and student info
        contents.update({
            'student_info': json.dumps(student_info),
            'student_response': submission,
            'max_score': self.max_score(),
        })

        # Submit request. When successful, 'msg' is the prior length of the queue
        error, error_message = qinterface.send_to_queue(
            header=xheader, body=json.dumps(contents))

        # State associated with the queueing request
        queuestate = {
            'key': queuekey,
            'time': qtime,
        }
        _ = self.system.service(self, "i18n").ugettext
        success = True
        message = _("Successfully saved your submission.")
        if error:
            success = False
            # Translators: the `grader` refers to the grading service open response problems
            # are sent to, either to be machine-graded, peer-graded, or instructor-graded.
            message = _(
                'Unable to submit your submission to the grader. Please try again later.'
            )
            log.error(
                "Unable to submit to grader. location: {0}, error_message: {1}"
                .format(self.location_string, error_message))

        return (success, message)