def test_disabled_university_id_redirect(self): disabled_course = CourseFactory.create(enable_university_id=False) CourseEnrollment.get_or_create_enrollment(self.user, disabled_course.id) set_course_cohort_settings(disabled_course.id, is_cohorted=True) student_form_url = reverse('edraak_university:id', args=[unicode(disabled_course.id)]) course_root_url = reverse('course_root', args=[unicode(disabled_course.id)]) res = self.client.get(student_form_url) self.assertRedirects(res, course_root_url)
def get(self, request, course_id): """ display this view """ course_id = CourseKey.from_string(course_id) course = modulestore().get_course(course_id) if course is None: raise Http404 course_enrollment = CourseEnrollment.get_or_create_enrollment( request.user, course_id) course_enrollment.update_enrollment(mode="verified") course_enrollment.emit_event( EVENT_NAME_USER_ENTERED_MIDCOURSE_REVERIFY_VIEW) context = { "user_full_name": request.user.profile.name, "error": False, "course_id": course_id.to_deprecated_string(), "course_name": course.display_name_with_default, "course_org": course.display_org_with_default, "course_num": course.display_number_with_default, "reverify": True, } return render_to_response( "verify_student/midcourse_photo_reverification.html", context)
def post(self, request, course_id): """ submits the reverification to SoftwareSecure """ try: now = datetime.datetime.now(UTC) course_id = CourseKey.from_string(course_id) window = MidcourseReverificationWindow.get_window(course_id, now) if window is None: raise WindowExpiredException attempt = SoftwareSecurePhotoVerification(user=request.user, window=window) b64_face_image = request.POST["face_image"].split(",")[1] attempt.upload_face_image(b64_face_image.decode("base64")) attempt.fetch_photo_id_image() attempt.mark_ready() attempt.save() attempt.submit() course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, course_id) course_enrollment.update_enrollment(mode="verified") course_enrollment.emit_event(EVENT_NAME_USER_SUBMITTED_MIDCOURSE_REVERIFY) return HttpResponseRedirect(reverse("verify_student_midcourse_reverification_confirmation")) except WindowExpiredException: log.exception( "User {} attempted to re-verify, but the window expired before the attempt".format(request.user.id) ) return HttpResponseRedirect(reverse("verify_student_reverification_window_expired")) except Exception: log.exception("Could not submit verification attempt for user {}".format(request.user.id)) context = {"user_full_name": request.user.profile.name, "error": True} return render_to_response("verify_student/midcourse_photo_reverification.html", context)
def save(self, *args, **kwargs): course_enrollment = super(CourseEnrollmentForm, self).save(commit=False) user = self.cleaned_data['user'] course_overview = self.cleaned_data['course'] enrollment = CourseEnrollment.get_or_create_enrollment(user, course_overview.id) course_enrollment.id = enrollment.id course_enrollment.created = enrollment.created return course_enrollment
def add_to_order(cls, order, course_id, cost, mode, currency='usd'): """ Add a CertificateItem to an order Returns the CertificateItem object after saving `order` - an order that this item should be added to, generally the cart order `course_id` - the course that we would like to purchase as a CertificateItem `cost` - the amount the user will be paying for this CertificateItem `mode` - the course mode that this certificate is going to be issued for This item also creates a new enrollment if none exists for this user and this course. Example Usage: cart = Order.get_cart_for_user(user) CertificateItem.add_to_order(cart, 'edX/Test101/2013_Fall', 30, 'verified') """ super(CertificateItem, cls).add_to_order(order, course_id, cost, currency=currency) course_enrollment = CourseEnrollment.get_or_create_enrollment( order.user, course_id) # do some validation on the enrollment mode valid_modes = CourseMode.modes_for_course_dict(course_id) if mode in valid_modes: mode_info = valid_modes[mode] else: raise InvalidCartItem( _("Mode {mode} does not exist for {course_id}").format( mode=mode, course_id=course_id)) item, _created = cls.objects.get_or_create( order=order, user=order.user, course_id=course_id, course_enrollment=course_enrollment, mode=mode, ) item.status = order.status item.qty = 1 item.unit_cost = cost course_name = modulestore().get_course(course_id).display_name # Translators: In this particular case, mode_name refers to a # particular mode (i.e. Honor Code Certificate, Verified Certificate, etc) # by which a user could enroll in the given course. item.line_desc = _("{mode_name} for course {course}").format( mode_name=mode_info.name, course=course_name) item.currency = currency order.currency = currency order.save() item.save() return item
def test_midcourse_reverify_dash(self): url = reverse('verify_student_midcourse_reverify_dash') response = self.client.get(url) # not enrolled in any courses self.assertEquals(response.status_code, 200) enrollment = CourseEnrollment.get_or_create_enrollment(self.user, self.course_key) enrollment.update_enrollment(mode="verified", is_active=True) MidcourseReverificationWindowFactory(course_id=self.course_key) response = self.client.get(url) # enrolled in a verified course, and the window is open self.assertEquals(response.status_code, 200)
def test_midcourse_reverify_dash(self): url = reverse('verify_student_midcourse_reverify_dash') response = self.client.get(url) # not enrolled in any courses self.assertEquals(response.status_code, 200) enrollment = CourseEnrollment.get_or_create_enrollment(self.user, self.course_id) enrollment.update_enrollment(mode="verified", is_active=True) MidcourseReverificationWindowFactory(course_id=self.course_id) response = self.client.get(url) # enrolled in a verified course, and the window is open self.assertEquals(response.status_code, 200)
def create_course_reference_data(course): """ Populates DB with test data """ course_key = course.id user = UserFactory() group = GroupFactory() CourseGroupRelationship(course_id=course_key, group=group).save() StudentGradebook( user=user, course_id=course_key, grade=0.9, proforma_grade=0.91, progress_summary='test', grade_summary='test', grading_policy='test', ).save() CourseEnrollment.get_or_create_enrollment(user, course_key) CourseAccessRole(user=user, course_id=course_key, org='test', role='TA').save() handouts_usage_key = course_key.make_usage_key('course_info', 'handouts') StudentModule(student=user, course_id=course_key, module_state_key=handouts_usage_key).save() CourseAggregatedMetaData(id=course_key, total_assessments=10, total_modules=20).save() structure_json = '{"test": true}' course_structure, created = CourseStructure.objects.get_or_create( course_id=course_key, defaults={'structure_json': structure_json}) if not created: course_structure.structure_json = structure_json course_structure.save() CourseOverview.get_from_id(course_key)
def add_to_order(cls, order, course_id, cost, mode, currency='usd'): """ Add a CertificateItem to an order Returns the CertificateItem object after saving `order` - an order that this item should be added to, generally the cart order `course_id` - the course that we would like to purchase as a CertificateItem `cost` - the amount the user will be paying for this CertificateItem `mode` - the course mode that this certificate is going to be issued for This item also creates a new enrollment if none exists for this user and this course. Example Usage: cart = Order.get_cart_for_user(user) CertificateItem.add_to_order(cart, 'edX/Test101/2013_Fall', 30, 'verified') """ super(CertificateItem, cls).add_to_order(order, course_id, cost, currency=currency) course_enrollment = CourseEnrollment.get_or_create_enrollment(order.user, course_id) # do some validation on the enrollment mode valid_modes = CourseMode.modes_for_course_dict(course_id) if mode in valid_modes: mode_info = valid_modes[mode] else: raise InvalidCartItem(_("Mode {mode} does not exist for {course_id}").format(mode=mode, course_id=course_id)) item, _created = cls.objects.get_or_create( order=order, user=order.user, course_id=course_id, course_enrollment=course_enrollment, mode=mode, ) item.status = order.status item.qty = 1 item.unit_cost = cost course_name = modulestore().get_course(course_id).display_name # Translators: In this particular case, mode_name refers to a # particular mode (i.e. Honor Code Certificate, Verified Certificate, etc) # by which a user could enroll in the given course. item.line_desc = _("{mode_name} for course {course}").format( mode_name=mode_info.name, course=course_name ) item.currency = currency order.currency = currency order.save() item.save() return item
def test_show_receipt_success_with_upgrade(self): reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_id) cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_id, self.cost, 'honor') self.cart.purchase(first='FirstNameTesting123', street1='StreetTesting123') self.login_user() # When we come from the upgrade flow, we'll have a session variable showing that s = self.client.session s['attempting_upgrade'] = True s.save() self.mock_tracker.emit.reset_mock() # pylint: disable=maybe-no-member resp = self.client.get( reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) # Once they've upgraded, they're no longer *attempting* to upgrade attempting_upgrade = self.client.session.get('attempting_upgrade', False) self.assertFalse(attempting_upgrade) self.assertEqual(resp.status_code, 200) self.assertIn('FirstNameTesting123', resp.content) self.assertIn('80.00', resp.content) ((template, context), _) = render_mock.call_args # When we come from the upgrade flow, we get these context variables self.assertEqual(template, 'shoppingcart/receipt.html') self.assertEqual(context['order'], self.cart) self.assertIn(reg_item, context['order_items']) self.assertIn(cert_item, context['order_items']) self.assertFalse(context['any_refunds']) course_enrollment = CourseEnrollment.get_or_create_enrollment( self.user, self.course_id) course_enrollment.emit_event('edx.course.enrollment.upgrade.succeeded') self.mock_tracker.emit.assert_any_call( # pylint: disable=maybe-no-member 'edx.course.enrollment.upgrade.succeeded', { 'user_id': course_enrollment.user.id, 'course_id': course_enrollment.course_id, 'mode': course_enrollment.mode } )
def test_get_or_create_integrity_error(self): """Verify that get_or_create_enrollment handles IntegrityError.""" CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id) with patch.object(CourseEnrollment.objects, "get_or_create") as mock_get_or_create: mock_get_or_create.side_effect = IntegrityError enrollment = CourseEnrollment.get_or_create_enrollment( self.user, self.course.id) self.assertEqual(enrollment.user, self.user) self.assertEqual(enrollment.course.id, self.course.id)
def test_get_or_create_integrity_error(self): """Verify that get_or_create_enrollment handles IntegrityError.""" CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id) with patch.object(CourseEnrollment.objects, "get_or_create") as mock_get_or_create: mock_get_or_create.side_effect = IntegrityError enrollment = CourseEnrollment.get_or_create_enrollment( self.user, self.course.id ) self.assertEqual(enrollment.user, self.user) self.assertEqual(enrollment.course.id, self.course.id)
def fetch_reverify_banner_info(request, course_key): """ Fetches needed context variable to display reverification banner in courseware """ reverifications = defaultdict(list) user = request.user if not user.id: return reverifications enrollment = CourseEnrollment.get_or_create_enrollment(request.user, course_key) course = modulestore().get_course(course_key) info = single_course_reverification_info(user, course, enrollment) if info: reverifications[info.status].append(info) return reverifications
def clean(self): """ clean form """ user, course_id = self.cleaned_data.get('user'), self.cleaned_data.get('course_id') if user and course_id: self.cleaned_data['enrollment'] = enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id) if enrollment.refundable(): raise forms.ValidationError(_("Course {course_id} not past the refund window.").format(course_id=course_id)) try: self.cleaned_data['cert'] = enrollment.certificateitem_set.filter(mode='verified', status='purchased')[0] except IndexError: raise forms.ValidationError(_("No order found for {user} in course {course_id}").format(user=user, course_id=course_id)) return self.cleaned_data
def show_receipt(request, ordernum): """ Displays a receipt for a particular order. 404 if order is not yet purchased or request.user != order.user """ try: order = Order.objects.get(id=ordernum) except Order.DoesNotExist: raise Http404('Order not found!') if order.user != request.user or order.status != 'purchased': raise Http404('Order not found!') order_items = OrderItem.objects.filter(order=order).select_subclasses() any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() # only show billed to information on receipt if we have any # note, SaferPay does not capture Bill To information show_billed_to_info = order.bill_to_cardtype or order.bill_to_ccnum or \ order.bill_to_first or order.bill_to_last or \ order.bill_to_street1 or order.bill_to_street2 or \ order.bill_to_city or order.bill_to_state or order.bill_to_postalcode or \ order.bill_to_country # we want to have the ability to override the default receipt page when # there is only one item in the order context = { 'order': order, 'order_items': order_items, 'any_refunds': any_refunds, 'instructions': instructions, 'show_billed_to_info': show_billed_to_info, } if order_items.count() == 1: receipt_template = order_items[0].single_item_receipt_template context.update(order_items[0].single_item_receipt_context) # Only orders where order_items.count() == 1 might be attempting to upgrade attempting_upgrade = request.session.get('attempting_upgrade', False) if attempting_upgrade: course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id) course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED) request.session['attempting_upgrade'] = False return render_to_response(receipt_template, context)
def test_show_receipt_success_with_upgrade(self): reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_id) cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_id, self.cost, 'honor') self.cart.purchase(first='FirstNameTesting123', street1='StreetTesting123') self.login_user() # When we come from the upgrade flow, we'll have a session variable showing that s = self.client.session s['attempting_upgrade'] = True s.save() self.mock_server_track.reset_mock() resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id])) # Once they've upgraded, they're no longer *attempting* to upgrade attempting_upgrade = self.client.session.get('attempting_upgrade', False) self.assertFalse(attempting_upgrade) self.assertEqual(resp.status_code, 200) self.assertIn('FirstNameTesting123', resp.content) self.assertIn('80.00', resp.content) ((template, context), _) = render_mock.call_args # When we come from the upgrade flow, we get these context variables self.assertEqual(template, 'shoppingcart/receipt.html') self.assertEqual(context['order'], self.cart) self.assertIn(reg_item, context['order_items']) self.assertIn(cert_item, context['order_items']) self.assertFalse(context['any_refunds']) course_enrollment = CourseEnrollment.get_or_create_enrollment(self.user, self.course_id) course_enrollment.emit_event('edx.course.enrollment.upgrade.succeeded') self.mock_server_track.assert_any_call( None, 'edx.course.enrollment.upgrade.succeeded', { 'user_id': course_enrollment.user.id, 'course_id': course_enrollment.course_id, 'mode': course_enrollment.mode } )
def post(self, request, course_id): """ submits the reverification to SoftwareSecure """ try: now = datetime.datetime.now(UTC) course_id = SlashSeparatedCourseKey.from_deprecated_string( course_id) window = MidcourseReverificationWindow.get_window(course_id, now) if window is None: raise WindowExpiredException attempt = SoftwareSecurePhotoVerification(user=request.user, window=window) b64_face_image = request.POST['face_image'].split(",")[1] attempt.upload_face_image(b64_face_image.decode('base64')) attempt.fetch_photo_id_image() attempt.mark_ready() attempt.save() attempt.submit() course_enrollment = CourseEnrollment.get_or_create_enrollment( request.user, course_id) course_enrollment.update_enrollment(mode="verified") course_enrollment.emit_event( EVENT_NAME_USER_SUBMITTED_MIDCOURSE_REVERIFY) return HttpResponseRedirect( reverse( 'verify_student_midcourse_reverification_confirmation')) except WindowExpiredException: log.exception( "User {} attempted to re-verify, but the window expired before the attempt" .format(request.user.id)) return HttpResponseRedirect( reverse('verify_student_reverification_window_expired')) except Exception: log.exception( "Could not submit verification attempt for user {}".format( request.user.id)) context = { "user_full_name": request.user.profile.name, "error": True, } return render_to_response( "verify_student/midcourse_photo_reverification.html", context)
def test_mode_change_after_refund_seat(self, course_modes, new_mode): """ Test if a course seat is refunded student is enrolled into default course mode unless no default mode available. """ course_id = CourseLocator('test_org', 'test_course_number', 'test_run') CourseMode.objects.all().delete() for course_mode in course_modes: CourseModeFactory.create( course_id=course_id, mode_slug=course_mode, mode_display_name=course_mode, ) httpretty.register_uri(httpretty.POST, settings.ECOMMERCE_API_URL + 'refunds/', status=201, body='[1]', content_type='application/json') httpretty.register_uri(httpretty.PUT, settings.ECOMMERCE_API_URL + 'refunds/1/process/', status=200, body=json.dumps({ "id": 9, "created": "2017-12-21T18:23:49.468298Z", "modified": "2017-12-21T18:24:02.741426Z", "total_credit_excl_tax": "100.00", "currency": "USD", "status": "Complete", "order": 15, "user": 5 }), content_type='application/json') enrollment = CourseEnrollment.enroll(self.user, course_id, mode=course_modes[0]) refund_success = refund_seat(enrollment, True) enrollment = CourseEnrollment.get_or_create_enrollment( self.user, course_id) assert refund_success self.assertEqual(enrollment.mode, new_mode)
def test_mode_change_after_refund_seat(self, course_modes, new_mode): """ Test if a course seat is refunded student is enrolled into default course mode unless no default mode available. """ course_id = CourseLocator('test_org', 'test_course_number', 'test_run') CourseMode.objects.all().delete() for course_mode in course_modes: CourseModeFactory.create( course_id=course_id, mode_slug=course_mode, mode_display_name=course_mode, ) httpretty.register_uri( httpretty.POST, settings.ECOMMERCE_API_URL + 'refunds/', status=201, body='[1]', content_type='application/json' ) httpretty.register_uri( httpretty.PUT, settings.ECOMMERCE_API_URL + 'refunds/1/process/', status=200, body=json.dumps({ "id": 9, "created": "2017-12-21T18:23:49.468298Z", "modified": "2017-12-21T18:24:02.741426Z", "total_credit_excl_tax": "100.00", "currency": "USD", "status": "Complete", "order": 15, "user": 5 }), content_type='application/json' ) enrollment = CourseEnrollment.enroll(self.user, course_id, mode=course_modes[0]) refund_success = refund_seat(enrollment, True) enrollment = CourseEnrollment.get_or_create_enrollment(self.user, course_id) assert refund_success self.assertEqual(enrollment.mode, new_mode)
def test_show_receipt_success_with_upgrade(self): reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_id) cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_id, self.cost, "honor") self.cart.purchase(first="FirstNameTesting123", street1="StreetTesting123") self.login_user() # When we come from the upgrade flow, we'll have a session variable showing that s = self.client.session s["attempting_upgrade"] = True s.save() self.mock_tracker.emit.reset_mock() # pylint: disable=maybe-no-member resp = self.client.get(reverse("shoppingcart.views.show_receipt", args=[self.cart.id])) # Once they've upgraded, they're no longer *attempting* to upgrade attempting_upgrade = self.client.session.get("attempting_upgrade", False) self.assertFalse(attempting_upgrade) self.assertEqual(resp.status_code, 200) self.assertIn("FirstNameTesting123", resp.content) self.assertIn("80.00", resp.content) ((template, context), _) = render_mock.call_args # When we come from the upgrade flow, we get these context variables self.assertEqual(template, "shoppingcart/receipt.html") self.assertEqual(context["order"], self.cart) self.assertIn(reg_item, context["order_items"]) self.assertIn(cert_item, context["order_items"]) self.assertFalse(context["any_refunds"]) course_enrollment = CourseEnrollment.get_or_create_enrollment(self.user, self.course_id) course_enrollment.emit_event("edx.course.enrollment.upgrade.succeeded") self.mock_tracker.emit.assert_any_call( # pylint: disable=maybe-no-member "edx.course.enrollment.upgrade.succeeded", { "user_id": course_enrollment.user.id, "course_id": course_enrollment.course_id, "mode": course_enrollment.mode, }, )
def get_course_enrollment(self, course_key, user): """ If student is not enrolled in course enroll the student in free mode """ course_enrollment = CourseEnrollment.get_enrollment(user, course_key) # If student is not enrolled in course enroll the student in free mode if not course_enrollment: # try to create a enroll user in default course enrollment mode in case of # professional it will break because of no default course mode. try: course_enrollment = CourseEnrollment.get_or_create_enrollment( user=user, course_key=course_key) except Exception: # pylint: disable=broad-except # In case if no free mode is available. course_enrollment = None return course_enrollment
def get(self, request, course_id): """ display this view """ course = course_from_id(course_id) course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, course_id) course_enrollment.update_enrollment(mode="verified") course_enrollment.emit_event(EVENT_NAME_USER_ENTERED_MIDCOURSE_REVERIFY_VIEW) context = { "user_full_name": request.user.profile.name, "error": False, "course_id": course_id, "course_name": course.display_name_with_default, "course_org": course.display_org_with_default, "course_num": course.display_number_with_default, "reverify": True, } return render_to_response("verify_student/midcourse_photo_reverification.html", context)
def clean(self): """ clean form """ user, course_id = self.cleaned_data.get('user'), self.cleaned_data.get('course_id') if user and course_id: self.cleaned_data['enrollment'] = enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id) if enrollment.refundable(): msg = _("Course {course_id} not past the refund window.").format(course_id=course_id) raise forms.ValidationError(msg) try: self.cleaned_data['cert'] = enrollment.certificateitem_set.filter( mode='verified', status='purchased' )[0] except IndexError: msg = _("No order found for {user} in course {course_id}").format(user=user, course_id=course_id) raise forms.ValidationError(msg) return self.cleaned_data
def test_admin_model_form_update(self): """ Test CourseEnrollmentAdminForm update. """ enrollment = CourseEnrollment.get_or_create_enrollment( self.user, self.course.id) count = CourseEnrollment.objects.count() form = CourseEnrollmentForm( { 'user': self.user.id, 'course': six.text_type(self.course.id), 'is_active': False, 'mode': 'audit' }, instance=enrollment) self.assertTrue(form.is_valid()) course_enrollment = form.save() self.assertEqual(count, CourseEnrollment.objects.count()) self.assertFalse(course_enrollment.is_active) self.assertEqual(enrollment.id, course_enrollment.id)
def show_receipt(request, ordernum): """ Displays a receipt for a particular order. 404 if order is not yet purchased or request.user != order.user """ try: order = Order.objects.get(id=ordernum) except Order.DoesNotExist: raise Http404('Order not found!') if order.user != request.user or order.status != 'purchased': raise Http404('Order not found!') order_items = OrderItem.objects.filter(order=order).select_subclasses() any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() # we want to have the ability to override the default receipt page when # there is only one item in the order context = { 'order': order, 'order_items': order_items, 'any_refunds': any_refunds, 'instructions': instructions, } if order_items.count() == 1: receipt_template = order_items[0].single_item_receipt_template context.update(order_items[0].single_item_receipt_context) # Only orders where order_items.count() == 1 might be attempting to upgrade attempting_upgrade = request.session.get('attempting_upgrade', False) if attempting_upgrade: course_enrollment = CourseEnrollment.get_or_create_enrollment( request.user, order_items[0].course_id) course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED) request.session['attempting_upgrade'] = False return render_to_response(receipt_template, context)
def test_activation(self): user = User.objects.create(username="******", email="*****@*****.**") course_id = "edX/Test101/2013" self.assertFalse(CourseEnrollment.is_enrolled(user, course_id)) # Creating an enrollment doesn't actually enroll a student # (calling CourseEnrollment.enroll() would have) enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id) self.assertFalse(CourseEnrollment.is_enrolled(user, course_id)) self.assert_no_events_were_emitted() # Until you explicitly activate it enrollment.activate() self.assertTrue(CourseEnrollment.is_enrolled(user, course_id)) self.assert_enrollment_event_was_emitted(user, course_id) # Activating something that's already active does nothing enrollment.activate() self.assertTrue(CourseEnrollment.is_enrolled(user, course_id)) self.assert_no_events_were_emitted() # Now deactive enrollment.deactivate() self.assertFalse(CourseEnrollment.is_enrolled(user, course_id)) self.assert_unenrollment_event_was_emitted(user, course_id) # Deactivating something that's already inactive does nothing enrollment.deactivate() self.assertFalse(CourseEnrollment.is_enrolled(user, course_id)) self.assert_no_events_were_emitted() # A deactivated enrollment should be activated if enroll() is called # for that user/course_id combination CourseEnrollment.enroll(user, course_id) self.assertTrue(CourseEnrollment.is_enrolled(user, course_id)) self.assert_enrollment_event_was_emitted(user, course_id)
def test_activation(self): user = User.objects.create(username="******", email="*****@*****.**") course_id = SlashSeparatedCourseKey("edX", "Test101", "2013") self.assertFalse(CourseEnrollment.is_enrolled(user, course_id)) # Creating an enrollment doesn't actually enroll a student # (calling CourseEnrollment.enroll() would have) enrollment = CourseEnrollment.get_or_create_enrollment(user, course_id) self.assertFalse(CourseEnrollment.is_enrolled(user, course_id)) self.assert_no_events_were_emitted() # Until you explicitly activate it enrollment.activate() self.assertTrue(CourseEnrollment.is_enrolled(user, course_id)) self.assert_enrollment_event_was_emitted(user, course_id) # Activating something that's already active does nothing enrollment.activate() self.assertTrue(CourseEnrollment.is_enrolled(user, course_id)) self.assert_no_events_were_emitted() # Now deactive enrollment.deactivate() self.assertFalse(CourseEnrollment.is_enrolled(user, course_id)) self.assert_unenrollment_event_was_emitted(user, course_id) # Deactivating something that's already inactive does nothing enrollment.deactivate() self.assertFalse(CourseEnrollment.is_enrolled(user, course_id)) self.assert_no_events_were_emitted() # A deactivated enrollment should be activated if enroll() is called # for that user/course_id combination CourseEnrollment.enroll(user, course_id) self.assertTrue(CourseEnrollment.is_enrolled(user, course_id)) self.assert_enrollment_event_was_emitted(user, course_id)
def results_callback(request): """ Software Secure will call this callback to tell us whether a user is verified to be who they said they are. """ body = request.body try: body_dict = json.loads(body) except ValueError: log.exception( "Invalid JSON received from Software Secure:\n\n{}\n".format(body)) return HttpResponseBadRequest( "Invalid JSON. Received:\n\n{}".format(body)) if not isinstance(body_dict, dict): log.error( "Reply from Software Secure is not a dict:\n\n{}\n".format(body)) return HttpResponseBadRequest( "JSON should be dict. Received:\n\n{}".format(body)) headers = { "Authorization": request.META.get("HTTP_AUTHORIZATION", ""), "Date": request.META.get("HTTP_DATE", "") } sig_valid = ssencrypt.has_valid_signature( "POST", headers, body_dict, settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"], settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"]) _response, access_key_and_sig = headers["Authorization"].split(" ") access_key = access_key_and_sig.split(":")[0] # This is what we should be doing... #if not sig_valid: # return HttpResponseBadRequest("Signature is invalid") # This is what we're doing until we can figure out why we disagree on sigs if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"][ "API_ACCESS_KEY"]: return HttpResponseBadRequest("Access key invalid") receipt_id = body_dict.get("EdX-ID") result = body_dict.get("Result") reason = body_dict.get("Reason", "") error_code = body_dict.get("MessageType", "") try: attempt = SoftwareSecurePhotoVerification.objects.get( receipt_id=receipt_id) except SoftwareSecurePhotoVerification.DoesNotExist: log.error( "Software Secure posted back for receipt_id {}, but not found". format(receipt_id)) return HttpResponseBadRequest("edX ID {} not found".format(receipt_id)) if result == "PASS": log.debug("Approving verification for {}".format(receipt_id)) attempt.approve() elif result == "FAIL": log.debug("Denying verification for {}".format(receipt_id)) attempt.deny(json.dumps(reason), error_code=error_code) elif result == "SYSTEM FAIL": log.debug("System failure for {} -- resetting to must_retry".format( receipt_id)) attempt.system_error(json.dumps(reason), error_code=error_code) log.error("Software Secure callback attempt for %s failed: %s", receipt_id, reason) else: log.error("Software Secure returned unknown result {}".format(result)) return HttpResponseBadRequest( "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL". format(result)) # If this is a reverification, log an event if attempt.window: course_id = attempt.window.course_id course_enrollment = CourseEnrollment.get_or_create_enrollment( attempt.user, course_id) course_enrollment.emit_event( EVENT_NAME_USER_REVERIFICATION_REVIEWED_BY_SOFTWARESECURE) return HttpResponse("OK!")
def show_receipt(request, ordernum): """ Displays a receipt for a particular order. 404 if order is not yet purchased or request.user != order.user """ try: order = Order.objects.get(id=ordernum) except Order.DoesNotExist: raise Http404('Order not found!') if order.user != request.user or order.status != 'purchased': raise Http404('Order not found!') order_items = OrderItem.objects.filter(order=order).select_subclasses() shoppingcart_items = [] course_names_list = [] for order_item in order_items: course_key = getattr(order_item, 'course_id') if course_key: course = get_course_by_id(course_key, depth=0) shoppingcart_items.append((order_item, course)) course_names_list.append(course.display_name) appended_course_names = ", ".join(course_names_list) any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() order_type = getattr(order, 'order_type') # Only orders where order_items.count() == 1 might be attempting to upgrade attempting_upgrade = request.session.get('attempting_upgrade', False) if attempting_upgrade: course_enrollment = CourseEnrollment.get_or_create_enrollment( request.user, order_items[0].course_id) course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED) request.session['attempting_upgrade'] = False recipient_list = [] registration_codes = None total_registration_codes = None recipient_list.append(getattr(order.user, 'email')) if order_type == OrderTypes.BUSINESS: registration_codes = CourseRegistrationCode.objects.filter(order=order) total_registration_codes = registration_codes.count() if order.company_contact_email: recipient_list.append(order.company_contact_email) if order.recipient_email: recipient_list.append(order.recipient_email) appended_recipient_emails = ", ".join(recipient_list) context = { 'order': order, 'shoppingcart_items': shoppingcart_items, 'any_refunds': any_refunds, 'instructions': instructions, 'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME), 'order_type': order_type, 'appended_course_names': appended_course_names, 'appended_recipient_emails': appended_recipient_emails, 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], 'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0], 'total_registration_codes': total_registration_codes, 'registration_codes': registration_codes, 'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"), } # we want to have the ability to override the default receipt page when # there is only one item in the order if order_items.count() == 1: receipt_template = order_items[0].single_item_receipt_template context.update(order_items[0].single_item_receipt_context) return render_to_response(receipt_template, context)
def _show_receipt_html(request, order): """Render the receipt page as HTML. Arguments: request (HttpRequest): The request for the receipt. order (Order): The order model to display. Returns: HttpResponse """ order_items = OrderItem.objects.filter(order=order).select_subclasses() shoppingcart_items = [] course_names_list = [] for order_item in order_items: course_key = getattr(order_item, 'course_id') if course_key: course = get_course_by_id(course_key, depth=0) shoppingcart_items.append((order_item, course)) course_names_list.append(course.display_name) appended_course_names = ", ".join(course_names_list) any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() order_type = getattr(order, 'order_type') # Only orders where order_items.count() == 1 might be attempting to upgrade attempting_upgrade = request.session.get('attempting_upgrade', False) if attempting_upgrade: course_enrollment = CourseEnrollment.get_or_create_enrollment( request.user, order_items[0].course_id) course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED) request.session['attempting_upgrade'] = False recipient_list = [] total_registration_codes = None reg_code_info_list = [] recipient_list.append(getattr(order.user, 'email')) if order_type == OrderTypes.BUSINESS: if order.company_contact_email: recipient_list.append(order.company_contact_email) if order.recipient_email: recipient_list.append(order.recipient_email) for __, course in shoppingcart_items: course_registration_codes = CourseRegistrationCode.objects.filter( order=order, course_id=course.id) total_registration_codes = course_registration_codes.count() for course_registration_code in course_registration_codes: reg_code_info_list.append({ 'course_name': course.display_name, 'redemption_url': reverse('register_code_redemption', args=[course_registration_code.code]), 'code': course_registration_code.code, 'is_redeemed': RegistrationCodeRedemption.objects.filter( registration_code=course_registration_code).exists(), }) appended_recipient_emails = ", ".join(recipient_list) context = { 'order': order, 'shoppingcart_items': shoppingcart_items, 'any_refunds': any_refunds, 'instructions': instructions, 'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME), 'order_type': order_type, 'appended_course_names': appended_course_names, 'appended_recipient_emails': appended_recipient_emails, 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], 'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0], 'total_registration_codes': total_registration_codes, 'reg_code_info_list': reg_code_info_list, 'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"), } # we want to have the ability to override the default receipt page when # there is only one item in the order if order_items.count() == 1: receipt_template = order_items[0].single_item_receipt_template context.update(order_items[0].single_item_receipt_context) return render_to_response(receipt_template, context)
def handle(self, *args, **options): """ Main handler for the command.""" file_path = options['csv_file_path'] if not path.isfile(file_path): raise CommandError("File not found.") with open(file_path) as csv_file: course_key = None user = None file_reader = csv.DictReader(csv_file) headers = file_reader.fieldnames if not ('course_id' in headers and 'mode' in headers and 'user' in headers): raise CommandError('Invalid input CSV file.') for row in file_reader: try: course_key = CourseKey.from_string(row['course_id']) except InvalidKeyError: logger.warning('Invalid or non-existent course id [{}]'.format(row['course_id'])) try: user = User.objects.get(username=row['user']) except: logger.warning('Invalid or non-existent user [{}]'.format(row['user'])) if course_key and user: try: course_enrollment = CourseEnrollment.get_enrollment(user, course_key) # If student is not enrolled in course enroll the student in free mode if not course_enrollment: # try to create a enroll user in default course enrollment mode in case of # professional it will break because of no default course mode. try: course_enrollment = CourseEnrollment.get_or_create_enrollment(user=user, course_key=course_key) except Exception: # pylint: disable=broad-except # In case if no free mode is available. course_enrollment = None if course_enrollment: # if student already had a enrollment and its mode is same as the provided one if course_enrollment.mode == row['mode']: logger.info("Student [%s] is already enrolled in Course [%s] in mode [%s].", user.username, course_key, course_enrollment.mode) # set the enrollment to active if its not already active. if not course_enrollment.is_active: course_enrollment.update_enrollment(is_active=True) else: # if student enrollment exists update it to new mode. with transaction.atomic(): course_enrollment.update_enrollment( mode=row['mode'], is_active=True, skip_refund=True ) course_enrollment.save() if row['mode'] == 'credit': enrollment_attrs = [{ 'namespace': 'credit', 'name': 'provider_id', 'value': course_key.org, }] CourseEnrollmentAttribute.add_enrollment_attr(enrollment=course_enrollment, data_list=enrollment_attrs) else: # if student enrollment do not exists directly enroll in new mode. CourseEnrollment.enroll(user=user, course_key=course_key, mode=row['mode']) except Exception as e: logger.info("Unable to update student [%s] course [%s] enrollment to mode [%s] " "because of Exception [%s]", row['user'], row['course_id'], row['mode'], repr(e))
def results_callback(request): """ Software Secure will call this callback to tell us whether a user is verified to be who they said they are. """ body = request.body try: body_dict = json.loads(body) except ValueError: log.exception("Invalid JSON received from Software Secure:\n\n{}\n".format(body)) return HttpResponseBadRequest("Invalid JSON. Received:\n\n{}".format(body)) if not isinstance(body_dict, dict): log.error("Reply from Software Secure is not a dict:\n\n{}\n".format(body)) return HttpResponseBadRequest("JSON should be dict. Received:\n\n{}".format(body)) headers = { "Authorization": request.META.get("HTTP_AUTHORIZATION", ""), "Date": request.META.get("HTTP_DATE", "") } sig_valid = ssencrypt.has_valid_signature( "POST", headers, body_dict, settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"], settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_SECRET_KEY"] ) _response, access_key_and_sig = headers["Authorization"].split(" ") access_key = access_key_and_sig.split(":")[0] # This is what we should be doing... #if not sig_valid: # return HttpResponseBadRequest("Signature is invalid") # This is what we're doing until we can figure out why we disagree on sigs if access_key != settings.VERIFY_STUDENT["SOFTWARE_SECURE"]["API_ACCESS_KEY"]: return HttpResponseBadRequest("Access key invalid") receipt_id = body_dict.get("EdX-ID") result = body_dict.get("Result") reason = body_dict.get("Reason", "") error_code = body_dict.get("MessageType", "") try: attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=receipt_id) except SoftwareSecurePhotoVerification.DoesNotExist: log.error("Software Secure posted back for receipt_id {}, but not found".format(receipt_id)) return HttpResponseBadRequest("edX ID {} not found".format(receipt_id)) if result == "PASS": log.debug("Approving verification for {}".format(receipt_id)) attempt.approve() elif result == "FAIL": log.debug("Denying verification for {}".format(receipt_id)) attempt.deny(json.dumps(reason), error_code=error_code) elif result == "SYSTEM FAIL": log.debug("System failure for {} -- resetting to must_retry".format(receipt_id)) attempt.system_error(json.dumps(reason), error_code=error_code) log.error("Software Secure callback attempt for %s failed: %s", receipt_id, reason) else: log.error("Software Secure returned unknown result {}".format(result)) return HttpResponseBadRequest( "Result {} not understood. Known results: PASS, FAIL, SYSTEM FAIL".format(result) ) # If this is a reverification, log an event if attempt.window: course_id = attempt.window.course_id course_enrollment = CourseEnrollment.get_or_create_enrollment(attempt.user, course_id) course_enrollment.emit_event(EVENT_NAME_USER_REVERIFICATION_REVIEWED_BY_SOFTWARESECURE) return HttpResponse("OK!")
def _show_receipt_html(request, order): """Render the receipt page as HTML. Arguments: request (HttpRequest): The request for the receipt. order (Order): The order model to display. Returns: HttpResponse """ order_items = OrderItem.objects.filter(order=order).select_subclasses() shoppingcart_items = [] course_names_list = [] for order_item in order_items: course_key = getattr(order_item, 'course_id') if course_key: course = get_course_by_id(course_key, depth=0) shoppingcart_items.append((order_item, course)) course_names_list.append(course.display_name) appended_course_names = ", ".join(course_names_list) any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() order_type = getattr(order, 'order_type') # Only orders where order_items.count() == 1 might be attempting to upgrade attempting_upgrade = request.session.get('attempting_upgrade', False) if attempting_upgrade: course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id) course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED) request.session['attempting_upgrade'] = False recipient_list = [] total_registration_codes = None reg_code_info_list = [] recipient_list.append(getattr(order.user, 'email')) if order_type == OrderTypes.BUSINESS: if order.company_contact_email: recipient_list.append(order.company_contact_email) if order.recipient_email: recipient_list.append(order.recipient_email) for __, course in shoppingcart_items: course_registration_codes = CourseRegistrationCode.objects.filter(order=order, course_id=course.id) total_registration_codes = course_registration_codes.count() for course_registration_code in course_registration_codes: reg_code_info_list.append({ 'course_name': course.display_name, 'redemption_url': reverse('register_code_redemption', args=[course_registration_code.code]), 'code': course_registration_code.code, 'is_redeemed': RegistrationCodeRedemption.objects.filter( registration_code=course_registration_code).exists(), }) appended_recipient_emails = ", ".join(recipient_list) context = { 'order': order, 'shoppingcart_items': shoppingcart_items, 'any_refunds': any_refunds, 'instructions': instructions, 'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME), 'order_type': order_type, 'appended_course_names': appended_course_names, 'appended_recipient_emails': appended_recipient_emails, 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], 'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0], 'total_registration_codes': total_registration_codes, 'reg_code_info_list': reg_code_info_list, 'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"), } # We want to have the ability to override the default receipt page when # there is only one item in the order. if order_items.count() == 1: receipt_template = order_items[0].single_item_receipt_template context.update(order_items[0].single_item_receipt_context) # Ideally, the shoppingcart app would own the receipt view. However, # as a result of changes made to the payment and verification flows as # part of an A/B test, the verify_student app owns it instead. This is # left over, and will be made more general in the future. if receipt_template == 'shoppingcart/verified_cert_receipt.html': url = reverse( 'verify_student_payment_confirmation', kwargs={'course_id': unicode(order_items[0].course_id)} ) # Add a query string param for the order ID # This allows the view to query for the receipt information later. url += '?payment-order-num={order_num}'.format( order_num=order_items[0].order.id ) return HttpResponseRedirect(url) return render_to_response(receipt_template, context)
def _show_receipt_html(request, order): """Render the receipt page as HTML. Arguments: request (HttpRequest): The request for the receipt. order (Order): The order model to display. Returns: HttpResponse """ order_items = OrderItem.objects.filter(order=order).select_subclasses() shoppingcart_items = [] course_names_list = [] for order_item in order_items: course_key = getattr(order_item, 'course_id') if course_key: course = get_course_by_id(course_key, depth=0) shoppingcart_items.append((order_item, course)) course_names_list.append(course.display_name) appended_course_names = ", ".join(course_names_list) any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() order_type = getattr(order, 'order_type') # Only orders where order_items.count() == 1 might be attempting to upgrade attempting_upgrade = request.session.get('attempting_upgrade', False) if attempting_upgrade: course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id) course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED) request.session['attempting_upgrade'] = False recipient_list = [] total_registration_codes = None reg_code_info_list = [] recipient_list.append(getattr(order.user, 'email')) if order_type == OrderTypes.BUSINESS: if order.company_contact_email: recipient_list.append(order.company_contact_email) if order.recipient_email: recipient_list.append(order.recipient_email) for __, course in shoppingcart_items: course_registration_codes = CourseRegistrationCode.objects.filter(order=order, course_id=course.id) total_registration_codes = course_registration_codes.count() for course_registration_code in course_registration_codes: reg_code_info_list.append({ 'course_name': course.display_name, 'redemption_url': reverse('register_code_redemption', args=[course_registration_code.code]), 'code': course_registration_code.code, 'is_redeemed': RegistrationCodeRedemption.objects.filter( registration_code=course_registration_code).exists(), }) appended_recipient_emails = ", ".join(recipient_list) context = { 'order': order, 'shoppingcart_items': shoppingcart_items, 'any_refunds': any_refunds, 'instructions': instructions, 'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME), 'order_type': order_type, 'appended_course_names': appended_course_names, 'appended_recipient_emails': appended_recipient_emails, 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], 'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0], 'total_registration_codes': total_registration_codes, 'reg_code_info_list': reg_code_info_list, 'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"), } # we want to have the ability to override the default receipt page when # there is only one item in the order if order_items.count() == 1: receipt_template = order_items[0].single_item_receipt_template context.update(order_items[0].single_item_receipt_context) return render_to_response(receipt_template, context)
def show_receipt(request, ordernum): """ Displays a receipt for a particular order. 404 if order is not yet purchased or request.user != order.user """ try: order = Order.objects.get(id=ordernum) except Order.DoesNotExist: raise Http404('Order not found!') if order.user != request.user or order.status != 'purchased': raise Http404('Order not found!') order_items = OrderItem.objects.filter(order=order).select_subclasses() shoppingcart_items = [] course_names_list = [] for order_item in order_items: course_key = getattr(order_item, 'course_id') if course_key: course = get_course_by_id(course_key, depth=0) shoppingcart_items.append((order_item, course)) course_names_list.append(course.display_name) appended_course_names = ", ".join(course_names_list) any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() order_type = getattr(order, 'order_type') # Only orders where order_items.count() == 1 might be attempting to upgrade attempting_upgrade = request.session.get('attempting_upgrade', False) if attempting_upgrade: course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id) course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED) request.session['attempting_upgrade'] = False recipient_list = [] registration_codes = None total_registration_codes = None recipient_list.append(getattr(order.user, 'email')) if order_type == OrderTypes.BUSINESS: registration_codes = CourseRegistrationCode.objects.filter(order=order) total_registration_codes = registration_codes.count() if order.company_contact_email: recipient_list.append(order.company_contact_email) if order.recipient_email: recipient_list.append(order.recipient_email) appended_recipient_emails = ", ".join(recipient_list) context = { 'order': order, 'shoppingcart_items': shoppingcart_items, 'any_refunds': any_refunds, 'instructions': instructions, 'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME), 'order_type': order_type, 'appended_course_names': appended_course_names, 'appended_recipient_emails': appended_recipient_emails, 'total_registration_codes': total_registration_codes, 'registration_codes': registration_codes, 'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"), } # we want to have the ability to override the default receipt page when # there is only one item in the order if order_items.count() == 1: receipt_template = order_items[0].single_item_receipt_template context.update(order_items[0].single_item_receipt_context) return render_to_response(receipt_template, context)
def _show_receipt_html(request, order): """Render the receipt page as HTML. Arguments: request (HttpRequest): The request for the receipt. order (Order): The order model to display. Returns: HttpResponse """ order_items = OrderItem.objects.filter(order=order).select_subclasses() shoppingcart_items = [] course_names_list = [] for order_item in order_items: course_key = getattr(order_item, 'course_id') if course_key: course = get_course_by_id(course_key, depth=0) shoppingcart_items.append((order_item, course)) course_names_list.append(course.display_name) appended_course_names = ", ".join(course_names_list) any_refunds = any(i.status == "refunded" for i in order_items) receipt_template = 'shoppingcart/receipt.html' __, instructions = order.generate_receipt_instructions() order_type = getattr(order, 'order_type') # Only orders where order_items.count() == 1 might be attempting to upgrade attempting_upgrade = request.session.get('attempting_upgrade', False) if attempting_upgrade: course_enrollment = CourseEnrollment.get_or_create_enrollment(request.user, order_items[0].course_id) course_enrollment.emit_event(EVENT_NAME_USER_UPGRADED) request.session['attempting_upgrade'] = False recipient_list = [] total_registration_codes = None reg_code_info_list = [] recipient_list.append(getattr(order.user, 'email')) if order_type == OrderTypes.BUSINESS: if order.company_contact_email: recipient_list.append(order.company_contact_email) if order.recipient_email: recipient_list.append(order.recipient_email) for __, course in shoppingcart_items: course_registration_codes = CourseRegistrationCode.objects.filter(order=order, course_id=course.id) total_registration_codes = course_registration_codes.count() for course_registration_code in course_registration_codes: reg_code_info_list.append({ 'course_name': course.display_name, 'redemption_url': reverse('register_code_redemption', args=[course_registration_code.code]), 'code': course_registration_code.code, 'is_redeemed': RegistrationCodeRedemption.objects.filter( registration_code=course_registration_code).exists(), }) appended_recipient_emails = ", ".join(recipient_list) context = { 'order': order, 'shoppingcart_items': shoppingcart_items, 'any_refunds': any_refunds, 'instructions': instructions, 'site_name': microsite.get_value('SITE_NAME', settings.SITE_NAME), 'order_type': order_type, 'appended_course_names': appended_course_names, 'appended_recipient_emails': appended_recipient_emails, 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], 'currency': settings.PAID_COURSE_REGISTRATION_CURRENCY[0], 'total_registration_codes': total_registration_codes, 'reg_code_info_list': reg_code_info_list, 'order_purchase_date': order.purchase_time.strftime("%B %d, %Y"), } # we want to have the ability to override the default receipt page when # there is only one item in the order if order_items.count() == 1: receipt_template = order_items[0].single_item_receipt_template context.update(order_items[0].single_item_receipt_context) # TODO (ECOM-188): Once the A/B test of separate verified / payment flow # completes, implement this in a more general way. For now, # we simply redirect to the new receipt page (in verify_student). if settings.FEATURES.get('SEPARATE_VERIFICATION_FROM_PAYMENT') and request.session.get('separate-verified', False): if receipt_template == 'shoppingcart/verified_cert_receipt.html': url = reverse( 'verify_student_payment_confirmation', kwargs={'course_id': unicode(order_items[0].course_id)} ) # Add a query string param for the order ID # This allows the view to query for the receipt information later. url += '?payment-order-num={order_num}'.format( order_num=order_items[0].id ) return HttpResponseRedirect(url) return render_to_response(receipt_template, context)
def course_enrollment(self, create, extracted, **kwargs): CourseEnrollment.get_or_create_enrollment( course_key=self.course_key, user=self.user, )