Ejemplo n.º 1
0
def clean_course_id(model_form, is_required=True):
    """
    Cleans and validates a course_id for use with a Django ModelForm.

    Arguments:
        model_form (form.ModelForm): The form that has a course_id.
        is_required (Boolean): Default True. When True, validates that the
            course_id is not empty.  In all cases, when course_id is supplied,
            validates that it is a valid course.

    Returns:
        (CourseKey) The cleaned and validated course_id as a CourseKey.

    NOTE: Use this method in model forms instead of a custom "clean_course_id" method!

    """
    cleaned_id = model_form.cleaned_data["course_id"]

    if not cleaned_id and not is_required:
        return None

    try:
        course_key = CourseKey.from_string(cleaned_id)
    except InvalidKeyError:
        msg = u'Course id invalid. Entered course id was: "{0}".'.format(cleaned_id)
        raise forms.ValidationError(msg)

    if not modulestore().has_course(course_key):
        msg = u'Course not found. Entered course id was: "{0}".'.format(text_type(course_key))
        raise forms.ValidationError(msg)

    return course_key
Ejemplo n.º 2
0
def _get_thread_and_context(request, thread_id, retrieve_kwargs=None):
    """
    Retrieve the given thread and build a serializer context for it, returning
    both. This function also enforces access control for the thread (checking
    both the user's access to the course and to the thread's cohort if
    applicable). Raises Http404 if the thread does not exist or the user cannot
    access it.
    """
    retrieve_kwargs = retrieve_kwargs or {}
    try:
        if "mark_as_read" not in retrieve_kwargs:
            retrieve_kwargs["mark_as_read"] = False
        cc_thread = Thread(id=thread_id).retrieve(**retrieve_kwargs)
        course_key = CourseKey.from_string(cc_thread["course_id"])
        course = _get_course_or_404(course_key, request.user)
        context = get_context(course, request, cc_thread)
        if (
                not context["is_requester_privileged"] and
                cc_thread["group_id"] and
                is_commentable_cohorted(course.id, cc_thread["commentable_id"])
        ):
            requester_cohort = get_cohort_id(request.user, course.id)
            if requester_cohort is not None and cc_thread["group_id"] != requester_cohort:
                raise Http404
        return cc_thread, context
    except CommentClientRequestError:
        # params are validated at a higher level, so the only possible request
        # error is if the thread doesn't exist
        raise Http404
def look_up_registration_code(request, course_id):
    """
    Look for the registration_code in the database.
    and check if it is still valid, allowed to redeem or not.
    """
    course_key = CourseKey.from_string(course_id)
    code = request.GET.get('registration_code')
    course = get_course_by_id(course_key, depth=0)
    try:
        registration_code = CourseRegistrationCode.objects.get(code=code)
    except CourseRegistrationCode.DoesNotExist:
        return JsonResponse({
            'is_registration_code_exists': False,
            'is_registration_code_valid': False,
            'is_registration_code_redeemed': False,
            'message': _(u'The enrollment code ({code}) was not found for the {course_name} course.').format(
                code=code, course_name=course.display_name
            )
        }, status=400)  # status code 200: OK by default

    reg_code_already_redeemed = RegistrationCodeRedemption.is_registration_code_redeemed(code)

    registration_code_detail_url = reverse('registration_code_details', kwargs={'course_id': unicode(course_id)})

    return JsonResponse({
        'is_registration_code_exists': True,
        'is_registration_code_valid': registration_code.is_valid,
        'is_registration_code_redeemed': reg_code_already_redeemed,
        'registration_code_detail_url': registration_code_detail_url
    })  # status code 200: OK by default
Ejemplo n.º 4
0
def add_coupon(request, course_id):
    """
    add coupon in the Coupons Table
    """
    code = request.POST.get('code')

    # check if the code is already in the Coupons Table and active
    try:
        course_id = CourseKey.from_string(course_id)
        coupon = Coupon.objects.get(is_active=True, code=code, course_id=course_id)
    except Coupon.DoesNotExist:
        # check if the coupon code is in the CourseRegistrationCode Table
        course_registration_code = CourseRegistrationCode.objects.filter(code=code)
        if course_registration_code:
            return JsonResponse(
                {'message': _("The code ({code}) that you have tried to define is already in use as a registration code").format(code=code)},
                status=400)  # status code 400: Bad Request

        description = request.POST.get('description')
        course_id = request.POST.get('course_id')
        try:
            discount = int(request.POST.get('discount'))
        except ValueError:
            return JsonResponse({
                'message': _("Please Enter the Integer Value for Coupon Discount")
            }, status=400)  # status code 400: Bad Request

        if discount > 100 or discount < 0:
            return JsonResponse({
                'message': _("Please Enter the Coupon Discount Value Less than or Equal to 100")
            }, status=400)  # status code 400: Bad Request
        expiration_date = None
        if request.POST.get('expiration_date'):
            expiration_date = request.POST.get('expiration_date')
            try:
                expiration_date = datetime.datetime.strptime(expiration_date, "%m/%d/%Y").replace(tzinfo=pytz.UTC) + datetime.timedelta(days=1)
            except ValueError:
                return JsonResponse({
                    'message': _("Please enter the date in this format i-e month/day/year")
                }, status=400)  # status code 400: Bad Request

        coupon = Coupon(
            code=code, description=description,
            course_id=course_id,
            percentage_discount=discount,
            created_by_id=request.user.id,
            expiration_date=expiration_date
        )
        coupon.save()
        return JsonResponse(
            {'message': _("coupon with the coupon code ({code}) added successfully").format(code=code)}
        )

    if coupon:
        return JsonResponse(
            {'message': _("coupon with the coupon code ({code}) already exists for this course").format(code=code)},
            status=400)  # status code 400: Bad Request
Ejemplo n.º 5
0
def create_thread(request, thread_data):
    """
    Create a thread.

    Arguments:

        request: The django request object used for build_absolute_uri and
          determining the requesting user.

        thread_data: The data for the created thread.

    Returns:

        The created thread; see discussion.rest_api.views.ThreadViewSet for more
        detail.
    """
    course_id = thread_data.get("course_id")
    user = request.user
    if not course_id:
        raise ValidationError({"course_id": ["This field is required."]})
    try:
        course_key = CourseKey.from_string(course_id)
        course = _get_course(course_key, user)
    except InvalidKeyError:
        raise ValidationError({"course_id": ["Invalid value."]})  # lint-amnesty, pylint: disable=raise-missing-from

    if not discussion_open_for_user(course, user):
        raise DiscussionBlackOutException

    context = get_context(course, request)
    _check_initializable_thread_fields(thread_data, context)
    discussion_settings = CourseDiscussionSettings.get(course_key)
    if ("group_id" not in thread_data and is_commentable_divided(
            course_key, thread_data.get("topic_id"), discussion_settings)):
        thread_data = thread_data.copy()
        thread_data["group_id"] = get_group_id_for_user(
            user, discussion_settings)
    serializer = ThreadSerializer(data=thread_data, context=context)
    actions_form = ThreadActionsForm(thread_data)
    if not (serializer.is_valid() and actions_form.is_valid()):
        raise ValidationError(
            dict(
                list(serializer.errors.items()) +
                list(actions_form.errors.items())))
    serializer.save()
    cc_thread = serializer.instance
    thread_created.send(sender=None, user=user, post=cc_thread)
    api_thread = serializer.data
    _do_extra_actions(api_thread, cc_thread, list(thread_data.keys()),
                      actions_form, context, request)

    track_thread_created_event(request, course, cc_thread,
                               actions_form.cleaned_data["following"])

    return api_thread
Ejemplo n.º 6
0
def create_thread(request, thread_data):
    """
    Create a thread.

    Arguments:

        request: The django request object used for build_absolute_uri and
          determining the requesting user.

        thread_data: The data for the created thread.

    Returns:

        The created thread; see discussion_api.views.ThreadViewSet for more
        detail.
    """
    course_id = thread_data.get("course_id")
    user = request.user
    if not course_id:
        raise ValidationError({"course_id": ["This field is required."]})
    try:
        course_key = CourseKey.from_string(course_id)
        course = _get_course_or_404(course_key, user)
    except (Http404, InvalidKeyError):
        raise ValidationError({"course_id": ["Invalid value."]})

    context = get_context(course, request)
    _check_initializable_thread_fields(thread_data, context)
    if (
            "group_id" not in thread_data and
            is_commentable_cohorted(course_key, thread_data.get("topic_id"))
    ):
        thread_data = thread_data.copy()
        thread_data["group_id"] = get_cohort_id(user, course_key)
    serializer = ThreadSerializer(data=thread_data, context=context)
    actions_form = ThreadActionsForm(thread_data)
    if not (serializer.is_valid() and actions_form.is_valid()):
        raise ValidationError(dict(serializer.errors.items() + actions_form.errors.items()))
    serializer.save()
    cc_thread = serializer.object
    thread_created.send(sender=None, user=user, post=cc_thread)
    api_thread = serializer.data
    _do_extra_actions(api_thread, cc_thread, thread_data.keys(), actions_form, context)

    track_forum_event(
        request,
        THREAD_CREATED_EVENT_NAME,
        course,
        cc_thread,
        get_thread_created_event_data(cc_thread, followed=actions_form.cleaned_data["following"])
    )

    return api_thread
Ejemplo n.º 7
0
 def _create_library(self, org="org", library="lib", display_name="Test Library"):
     """
     Helper method used to create a library. Uses the REST API.
     """
     response = self.client.ajax_post(
         LIBRARY_REST_URL, {"org": org, "library": library, "display_name": display_name}
     )
     self.assertEqual(response.status_code, 200)
     lib_info = parse_json(response)
     lib_key = CourseKey.from_string(lib_info["library_key"])
     self.assertIsInstance(lib_key, LibraryLocator)
     return lib_key
 def _create_library(self, org="org", library="lib", display_name="Test Library"):
     """
     Helper method used to create a library. Uses the REST API.
     """
     response = self.client.ajax_post(LIBRARY_REST_URL, {
         'org': org,
         'library': library,
         'display_name': display_name,
     })
     self.assertEqual(response.status_code, 200)
     lib_info = parse_json(response)
     lib_key = CourseKey.from_string(lib_info['library_key'])
     self.assertIsInstance(lib_key, LibraryLocator)
     return lib_key
Ejemplo n.º 9
0
def get_filename_safe_course_id(course_id, replacement_char='_'):
    """
    Create a representation of a course_id that can be used safely in a filepath.
    """
    try:
        course_key = CourseKey.from_string(course_id)
        filename = unicode(replacement_char).join([course_key.org, course_key.course, course_key.run])
    except InvalidKeyError:
        # If the course_id doesn't parse, we will still return a value here.
        filename = course_id

    # The safest characters are A-Z, a-z, 0-9, <underscore>, <period> and <hyphen>.
    # We represent the first four with \w.
    # TODO: Once we support courses with unicode characters, we will need to revisit this.
    return re.sub(r'[^\w\.\-]', unicode(replacement_char), filename)
Ejemplo n.º 10
0
def create_thread(request, thread_data):
    """
    Create a thread.

    Arguments:

        request: The django request object used for build_absolute_uri and
          determining the requesting user.

        thread_data: The data for the created thread.

    Returns:

        The created thread; see discussion.rest_api.views.ThreadViewSet for more
        detail.
    """
    course_id = thread_data.get("course_id")
    user = request.user
    if not course_id:
        raise ValidationError({"course_id": ["This field is required."]})
    try:
        course_key = CourseKey.from_string(course_id)
        course = _get_course(course_key, user)
    except InvalidKeyError:
        raise ValidationError({"course_id": ["Invalid value."]})

    context = get_context(course, request)
    _check_initializable_thread_fields(thread_data, context)
    discussion_settings = get_course_discussion_settings(course_key)
    if (
            "group_id" not in thread_data and
            is_commentable_divided(course_key, thread_data.get("topic_id"), discussion_settings)
    ):
        thread_data = thread_data.copy()
        thread_data["group_id"] = get_group_id_for_user(user, discussion_settings)
    serializer = ThreadSerializer(data=thread_data, context=context)
    actions_form = ThreadActionsForm(thread_data)
    if not (serializer.is_valid() and actions_form.is_valid()):
        raise ValidationError(dict(list(serializer.errors.items()) + list(actions_form.errors.items())))
    serializer.save()
    cc_thread = serializer.instance
    thread_created.send(sender=None, user=user, post=cc_thread)
    api_thread = serializer.data
    _do_extra_actions(api_thread, cc_thread, list(thread_data.keys()), actions_form, context, request)

    track_thread_created_event(request, course, cc_thread, actions_form.cleaned_data["following"])

    return api_thread
Ejemplo n.º 11
0
    def setUp(self):
        super().setUp()
        self.user = UserFactory()

        self.course1 = CourseOverviewFactory()
        self.course2 = CourseOverviewFactory(
            id=CourseKey.from_string('{}a'.format(self.course1.id)))

        self.eligible_cert = GeneratedCertificateFactory.create(
            status=CertificateStatuses.downloadable,
            user=self.user,
            course_id=self.course1.id)
        self.ineligible_cert = GeneratedCertificateFactory.create(
            status=CertificateStatuses.audit_passing,
            user=self.user,
            course_id=self.course2.id)
Ejemplo n.º 12
0
def get_filename_safe_course_id(course_id, replacement_char='_'):
    """
    Create a representation of a course_id that can be used safely in a filepath.
    """
    try:
        course_key = CourseKey.from_string(course_id)
        filename = unicode(replacement_char).join(
            [course_key.org, course_key.course, course_key.run])
    except InvalidKeyError:
        # If the course_id doesn't parse, we will still return a value here.
        filename = course_id

    # The safest characters are A-Z, a-z, 0-9, <underscore>, <period> and <hyphen>.
    # We represent the first four with \w.
    # TODO: Once we support courses with unicode characters, we will need to revisit this.
    return re.sub(r'[^\w\.\-]', unicode(replacement_char), filename)
Ejemplo n.º 13
0
    def setUp(self):
        super(EligibleCertificateManagerTest, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
        self.user = UserFactory()

        self.course1 = CourseOverviewFactory()
        self.course2 = CourseOverviewFactory(
            id=CourseKey.from_string('{}a'.format(self.course1.id)))

        self.eligible_cert = GeneratedCertificateFactory.create(
            status=CertificateStatuses.downloadable,
            user=self.user,
            course_id=self.course1.id)
        self.ineligible_cert = GeneratedCertificateFactory.create(
            status=CertificateStatuses.audit_passing,
            user=self.user,
            course_id=self.course2.id)
def registration_code_details(request, course_id):
    """
    Post handler to mark the registration code as
        1) valid
        2) invalid
        3) Unredeem.

    """
    course_key = CourseKey.from_string(course_id)
    code = request.POST.get('registration_code')
    action_type = request.POST.get('action_type')
    course = get_course_by_id(course_key, depth=0)
    action_type_messages = {
        'invalidate_registration_code': _('This enrollment code has been canceled. It can no longer be used.'),
        'unredeem_registration_code': _('This enrollment code has been marked as unused.'),
        'validate_registration_code': _('The enrollment code has been restored.')
    }
    try:
        registration_code = CourseRegistrationCode.objects.get(code=code)
    except CourseRegistrationCode.DoesNotExist:
        return JsonResponse({
            'message': _(u'The enrollment code ({code}) was not found for the {course_name} course.').format(
                code=code, course_name=course.display_name
            )}, status=400)

    if action_type == 'invalidate_registration_code':
        registration_code.is_valid = False
        registration_code.save()
        if RegistrationCodeRedemption.is_registration_code_redeemed(code):
            code_redemption = RegistrationCodeRedemption.get_registration_code_redemption(code, course_key)
            delete_redemption_entry(request, code_redemption, course_key)

    if action_type == 'validate_registration_code':
        registration_code.is_valid = True
        registration_code.save()

    if action_type == 'unredeem_registration_code':
        code_redemption = RegistrationCodeRedemption.get_registration_code_redemption(code, course_key)
        if code_redemption is None:
            return JsonResponse({
                'message': _(u'The redemption does not exist against enrollment code ({code}).').format(
                    code=code)}, status=400)

        delete_redemption_entry(request, code_redemption, course_key)

    return JsonResponse({'message': action_type_messages[action_type]})
Ejemplo n.º 15
0
def registration_code_details(request, course_id):
    """
    Post handler to mark the registration code as
        1) valid
        2) invalid
        3) Unredeem.

    """
    course_key = CourseKey.from_string(course_id)
    code = request.POST.get('registration_code')
    action_type = request.POST.get('action_type')
    course = get_course_by_id(course_key, depth=0)
    action_type_messages = {
        'invalidate_registration_code': _('This enrolment code has been canceled. It can no longer be used.'),
        'unredeem_registration_code': _('This enrolment code has been marked as unused.'),
        'validate_registration_code': _('The enrolment code has been restored.')
    }
    try:
        registration_code = CourseRegistrationCode.objects.get(code=code)
    except CourseRegistrationCode.DoesNotExist:
        return JsonResponse({
            'message': _('The enrolment code ({code}) was not found for the {course_name} course.').format(
                code=code, course_name=course.display_name
            )}, status=400)

    if action_type == 'invalidate_registration_code':
        registration_code.is_valid = False
        registration_code.save()
        if RegistrationCodeRedemption.is_registration_code_redeemed(code):
            code_redemption = RegistrationCodeRedemption.get_registration_code_redemption(code, course_key)
            delete_redemption_entry(request, code_redemption, course_key)

    if action_type == 'validate_registration_code':
        registration_code.is_valid = True
        registration_code.save()

    if action_type == 'unredeem_registration_code':
        code_redemption = RegistrationCodeRedemption.get_registration_code_redemption(code, course_key)
        if code_redemption is None:
            return JsonResponse({
                'message': _('The redemption does not exist against enrolment code ({code}).').format(
                    code=code)}, status=400)

        delete_redemption_entry(request, code_redemption, course_key)

    return JsonResponse({'message': action_type_messages[action_type]})
Ejemplo n.º 16
0
    def test_list_libraries(self):
        """
        Test that we can GET /library/ to list all libraries visible to the current user.
        """
        # Create some more libraries
        libraries = [LibraryFactory.create() for _ in range(3)]
        lib_dict = dict([(lib.location.library_key, lib) for lib in libraries])

        response = self.client.get_json(LIBRARY_REST_URL)
        self.assertEqual(response.status_code, 200)
        lib_list = parse_json(response)
        self.assertEqual(len(lib_list), len(libraries))
        for entry in lib_list:
            self.assertIn("library_key", entry)
            self.assertIn("display_name", entry)
            key = CourseKey.from_string(entry["library_key"])
            self.assertIn(key, lib_dict)
            self.assertEqual(entry["display_name"], lib_dict[key].display_name)
            del lib_dict[key]  # To ensure no duplicates are matched
Ejemplo n.º 17
0
    def setUp(self):
        super(EligibleCertificateManagerTest, self).setUp()
        self.user = UserFactory()

        self.course1 = CourseOverviewFactory()
        self.course2 = CourseOverviewFactory(
            id=CourseKey.from_string('{}a'.format(self.course1.id))
        )

        self.eligible_cert = GeneratedCertificateFactory.create(
            status=CertificateStatuses.downloadable,
            user=self.user,
            course_id=self.course1.id
        )
        self.ineligible_cert = GeneratedCertificateFactory.create(
            status=CertificateStatuses.audit_passing,
            user=self.user,
            course_id=self.course2.id
        )
Ejemplo n.º 18
0
    def test_list_libraries(self):
        """
        Test that we can GET /library/ to list all libraries visible to the current user.
        """
        # Create some more libraries
        libraries = [LibraryFactory.create() for _ in range(3)]
        lib_dict = dict([(lib.location.library_key, lib) for lib in libraries])

        response = self.client.get_json(LIBRARY_REST_URL)
        self.assertEqual(response.status_code, 200)
        lib_list = parse_json(response)
        self.assertEqual(len(lib_list), len(libraries))
        for entry in lib_list:
            self.assertIn("library_key", entry)
            self.assertIn("display_name", entry)
            key = CourseKey.from_string(entry["library_key"])
            self.assertIn(key, lib_dict)
            self.assertEqual(entry["display_name"], lib_dict[key].display_name)
            del lib_dict[key]  # To ensure no duplicates are matched
Ejemplo n.º 19
0
def look_up_registration_code(request, course_id):
    """
    Look for the registration_code in the database.
    and check if it is still valid, allowed to redeem or not.
    """
    course_key = CourseKey.from_string(course_id)
    code = request.GET.get('registration_code')
    course = get_course_by_id(course_key, depth=0)
    try:
        registration_code = CourseRegistrationCode.objects.get(code=code)
    except CourseRegistrationCode.DoesNotExist:
        return JsonResponse(
            {
                'is_registration_code_exists':
                False,
                'is_registration_code_valid':
                False,
                'is_registration_code_redeemed':
                False,
                'message':
                _(u'The enrollment code ({code}) was not found for the {course_name} course.'
                  ).format(code=code, course_name=course.display_name)
            },
            status=400)  # status code 200: OK by default

    reg_code_already_redeemed = RegistrationCodeRedemption.is_registration_code_redeemed(
        code)

    registration_code_detail_url = reverse(
        'registration_code_details',
        kwargs={'course_id': six.text_type(course_id)})

    return JsonResponse({
        'is_registration_code_exists':
        True,
        'is_registration_code_valid':
        registration_code.is_valid,
        'is_registration_code_redeemed':
        reg_code_already_redeemed,
        'registration_code_detail_url':
        registration_code_detail_url
    })  # status code 200: OK by default
Ejemplo n.º 20
0
    def test_user_cannot_enroll_in_unknown_course_run_id(
            self, mock_get_course_runs):
        fake_course_str = str(self.course.id) + 'fake'
        fake_course_key = CourseKey.from_string(fake_course_str)
        course_entitlement = CourseEntitlementFactory.create(user=self.user)
        mock_get_course_runs.return_value = self.return_values

        url = reverse(self.ENTITLEMENTS_ENROLLMENT_NAMESPACE,
                      args=[str(course_entitlement.uuid)])

        data = {'course_run_id': str(fake_course_key)}
        response = self.client.post(
            url,
            data=json.dumps(data),
            content_type='application/json',
        )

        expected_message = 'The Course Run ID is not a match for this Course Entitlement.'
        assert response.status_code == 400
        assert response.data['message'] == expected_message  # pylint: disable=no-member
        assert not CourseEnrollment.is_enrolled(self.user, fake_course_key)
Ejemplo n.º 21
0
    def test_user_cannot_enroll_in_unknown_course_run_id(self, mock_get_course_runs):
        fake_course_str = str(self.course.id) + 'fake'
        fake_course_key = CourseKey.from_string(fake_course_str)
        course_entitlement = CourseEntitlementFactory.create(user=self.user, mode=CourseMode.VERIFIED)
        mock_get_course_runs.return_value = self.return_values

        url = reverse(
            self.ENTITLEMENTS_ENROLLMENT_NAMESPACE,
            args=[str(course_entitlement.uuid)]
        )

        data = {
            'course_run_id': str(fake_course_key)
        }
        response = self.client.post(
            url,
            data=json.dumps(data),
            content_type='application/json',
        )

        expected_message = 'The Course Run ID is not a match for this Course Entitlement.'
        assert response.status_code == 400
        assert response.data['message'] == expected_message  # pylint: disable=no-member
        assert not CourseEnrollment.is_enrolled(self.user, fake_course_key)
Ejemplo n.º 22
0
def validate_course_id(course_id):
    """
    Validate course id and return the corresponding CourseKey object.

    Arguments:
        course_id (str): Course identifier

    Raises:
        (forms.ValidationError): if Given course jey is not valid or does not point to an existing course.

    Returns:
        (CourseKey): CourseKey object against the given course identifier.
    """
    try:
        course_key = CourseKey.from_string(course_id)
    except InvalidKeyError:
        msg = u'Course id invalid. Entered course id was: "{0}".'.format(course_id)
        raise forms.ValidationError(msg)

    if not modulestore().has_course(course_key):
        msg = u'Course not found. Entered course id was: "{0}".'.format(text_type(course_key))
        raise forms.ValidationError(msg)

    return course_key
Ejemplo n.º 23
0
def add_coupon(request, course_id):
    """
    add coupon in the Coupons Table
    """
    code = request.POST.get('code')

    # check if the code is already in the Coupons Table and active
    try:
        course_id = CourseKey.from_string(course_id)
        coupon = Coupon.objects.get(is_active=True,
                                    code=code,
                                    course_id=course_id)
    except Coupon.DoesNotExist:
        # check if the coupon code is in the CourseRegistrationCode Table
        course_registration_code = CourseRegistrationCode.objects.filter(
            code=code)
        if course_registration_code:
            return JsonResponse(
                {
                    'message':
                    _(u"The code ({code}) that you have tried to define is already in use as a registration code"
                      ).format(code=code)
                },
                status=400)  # status code 400: Bad Request

        description = request.POST.get('description')
        course_id = request.POST.get('course_id')
        try:
            discount = int(request.POST.get('discount'))
        except ValueError:
            return JsonResponse(
                {
                    'message':
                    _("Please Enter the Integer Value for Coupon Discount")
                },
                status=400)  # status code 400: Bad Request

        if discount > 100 or discount < 0:
            return JsonResponse(
                {
                    'message':
                    _("Please Enter the Coupon Discount Value Less than or Equal to 100"
                      )
                },
                status=400)  # status code 400: Bad Request
        expiration_date = None
        if request.POST.get('expiration_date'):
            expiration_date = request.POST.get('expiration_date')
            try:
                expiration_date = datetime.datetime.strptime(
                    expiration_date, "%m/%d/%Y").replace(
                        tzinfo=pytz.UTC) + datetime.timedelta(days=1)
            except ValueError:
                return JsonResponse(
                    {
                        'message':
                        _("Please enter the date in this format i-e month/day/year"
                          )
                    },
                    status=400)  # status code 400: Bad Request

        coupon = Coupon(code=code,
                        description=description,
                        course_id=course_id,
                        percentage_discount=discount,
                        created_by_id=request.user.id,
                        expiration_date=expiration_date)
        coupon.save()
        return JsonResponse({
            'message':
            _(u"coupon with the coupon code ({code}) added successfully").
            format(code=code)
        })

    if coupon:
        return JsonResponse(
            {
                'message':
                _(u"coupon with the coupon code ({code}) already exists for this course"
                  ).format(code=code)
            },
            status=400)  # status code 400: Bad Request