diff --git a/lms/djangoapps/instructor/enrollment_report.py b/lms/djangoapps/instructor/enrollment_report.py deleted file mode 100644 index 11c92c5a6815bc8840ff92e1e975090bbd636f9a..0000000000000000000000000000000000000000 --- a/lms/djangoapps/instructor/enrollment_report.py +++ /dev/null @@ -1,102 +0,0 @@ -""" -Defines abstract class for the Enrollment Reports. -""" - - -import abc -import collections -import json - -import six -from django.contrib.auth.models import User - -from student.models import UserProfile - - -class AbstractEnrollmentReportProvider(six.with_metaclass(abc.ABCMeta, object)): - """ - Abstract interface for Detailed Enrollment Report Provider - """ - - @abc.abstractmethod - def get_enrollment_info(self, user, course_id): - """ - Returns the User Enrollment information. - """ - raise NotImplementedError() - - @abc.abstractmethod - def get_user_profile(self, user_id): - """ - Returns the UserProfile information. - """ - raise NotImplementedError() - - @abc.abstractmethod - def get_payment_info(self, user, course_id): - """ - Returns the User Payment information. - """ - raise NotImplementedError() - - -class BaseAbstractEnrollmentReportProvider(AbstractEnrollmentReportProvider): - """ - The base abstract class for all Enrollment Reports that can support multiple - backend such as MySQL/Django-ORM. - - # don't allow instantiation of this class, it must be subclassed - """ - def get_user_profile(self, user_id): - """ - Returns the UserProfile information. - """ - user_info = User.objects.select_related('profile').get(id=user_id) - # extended user profile fields are stored in the user_profile meta column - meta = {} - if user_info.profile.meta: - meta = json.loads(user_info.profile.meta) - - user_data = collections.OrderedDict() - user_data['User ID'] = user_info.id - user_data['Username'] = user_info.username - user_data['Email'] = user_info.email - user_data['Full Name'] = user_info.profile.name - user_data['First Name'] = meta.get('first-name', '') - user_data['Last Name'] = meta.get('last-name', '') - user_data['Company Name'] = meta.get('company', '') - user_data['Title'] = meta.get('title', '') - user_data['Language'] = user_info.profile.language - user_data['Country'] = user_info.profile.country - user_data['Year of Birth'] = user_info.profile.year_of_birth - - user_data['Gender'] = None - gender = user_info.profile.gender - for _gender in UserProfile.GENDER_CHOICES: - if gender == _gender[0]: - user_data['Gender'] = _gender[1] - break - - user_data['Level of Education'] = None - level_of_education = user_info.profile.level_of_education - for _loe in UserProfile.LEVEL_OF_EDUCATION_CHOICES: - if level_of_education == _loe[0]: - user_data['Level of Education'] = _loe[1] - - user_data['Mailing Address'] = user_info.profile.mailing_address - user_data['Goals'] = user_info.profile.goals - user_data['City'] = user_info.profile.city - user_data['Country'] = user_info.profile.country - return user_data - - def get_enrollment_info(self, user, course_id): - """ - Returns the User Enrollment information. - """ - raise NotImplementedError() - - def get_payment_info(self, user, course_id): - """ - Returns the User Payment information. - """ - raise NotImplementedError() diff --git a/lms/djangoapps/instructor/paidcourse_enrollment_report.py b/lms/djangoapps/instructor/paidcourse_enrollment_report.py deleted file mode 100644 index 41113be16775ff38c1d188512b90c2a680cb6a09..0000000000000000000000000000000000000000 --- a/lms/djangoapps/instructor/paidcourse_enrollment_report.py +++ /dev/null @@ -1,196 +0,0 @@ -""" -Defines concrete class for cybersource Enrollment Report. - -""" - - -import collections - -from django.conf import settings -from django.utils.translation import ugettext as _ - -from lms.djangoapps.courseware.access import has_access -from lms.djangoapps.courseware.courses import get_course_by_id -from lms.djangoapps.instructor.enrollment_report import BaseAbstractEnrollmentReportProvider -from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from shoppingcart.models import ( - CouponRedemption, - InvoiceTransaction, - OrderItem, - PaidCourseRegistration, - RegistrationCodeRedemption -) -from student.models import CourseEnrollment, ManualEnrollmentAudit - - -class PaidCourseEnrollmentReportProvider(BaseAbstractEnrollmentReportProvider): - """ - The concrete class for all CyberSource Enrollment Reports. - """ - - def get_enrollment_info(self, user, course_id): - """ - Returns the User Enrollment information. - """ - course = get_course_by_id(course_id, depth=0) - is_course_staff = bool(has_access(user, 'staff', course)) - manual_enrollment_reason = 'N/A' - - # check the user enrollment role - if user.is_staff: - platform_name = configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME) - enrollment_role = _(u'{platform_name} Staff').format(platform_name=platform_name) - elif is_course_staff: - enrollment_role = _('Course Staff') - else: - enrollment_role = _('Student') - - course_enrollment = CourseEnrollment.get_enrollment(user=user, course_key=course_id) - - if is_course_staff: - enrollment_source = _('Staff') - else: - # get the registration_code_redemption object if exists - registration_code_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment( - course_enrollment) - # get the paid_course registration item if exists - paid_course_reg_item = PaidCourseRegistration.get_course_item_for_user_enrollment( - user=user, - course_id=course_id, - course_enrollment=course_enrollment - ) - - # from where the user get here - if registration_code_redemption is not None: - enrollment_source = _('Used Registration Code') - elif paid_course_reg_item is not None: - enrollment_source = _('Credit Card - Individual') - else: - manual_enrollment = ManualEnrollmentAudit.get_manual_enrollment(course_enrollment) - if manual_enrollment is not None: - enrollment_source = _( - u'manually enrolled by username: {username}' - ).format(username=manual_enrollment.enrolled_by.username) - - manual_enrollment_reason = manual_enrollment.reason - else: - enrollment_source = _('Manually Enrolled') - - enrollment_date = course_enrollment.created.strftime(u"%B %d, %Y") - currently_enrolled = course_enrollment.is_active - - course_enrollment_data = collections.OrderedDict() - course_enrollment_data['Enrollment Date'] = enrollment_date - course_enrollment_data['Currently Enrolled'] = currently_enrolled - course_enrollment_data['Enrollment Source'] = enrollment_source - course_enrollment_data['Manual (Un)Enrollment Reason'] = manual_enrollment_reason - course_enrollment_data['Enrollment Role'] = enrollment_role - return course_enrollment_data - - def get_payment_info(self, user, course_id): - """ - Returns the User Payment information. - """ - course_enrollment = CourseEnrollment.get_enrollment(user=user, course_key=course_id) - paid_course_reg_item = PaidCourseRegistration.get_course_item_for_user_enrollment( - user=user, - course_id=course_id, - course_enrollment=course_enrollment - ) - payment_data = collections.OrderedDict() - # check if the user made a single self purchase scenario - # for enrollment in the course. - if paid_course_reg_item is not None: - coupon_redemption = CouponRedemption.objects.select_related('coupon').filter( - order_id=paid_course_reg_item.order_id) - coupon_codes = [redemption.coupon.code for redemption in coupon_redemption] - coupon_codes = ", ".join(coupon_codes) - registration_code_used = 'N/A' - - list_price = paid_course_reg_item.get_list_price() - payment_amount = paid_course_reg_item.unit_cost - coupon_codes_used = coupon_codes - payment_status = paid_course_reg_item.status - transaction_reference_number = paid_course_reg_item.order_id - - else: - # check if the user used a registration code for the enrollment. - registration_code_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment( - course_enrollment) - if registration_code_redemption is not None: - registration_code = registration_code_redemption.registration_code - registration_code_used = registration_code.code - if registration_code.invoice_item_id: - list_price, payment_amount, payment_status, transaction_reference_number =\ - self._get_invoice_data(registration_code_redemption) - coupon_codes_used = 'N/A' - - elif registration_code_redemption.registration_code.order_id: - list_price, payment_amount, coupon_codes_used, payment_status, transaction_reference_number = \ - self._get_order_data(registration_code_redemption, course_id) - - else: - # this happens when the registration code is not created via invoice or bulk purchase - # scenario. - list_price = 'N/A' - payment_amount = 'N/A' - coupon_codes_used = 'N/A' - registration_code_used = 'N/A' - payment_status = _('Data Integrity Error') - transaction_reference_number = 'N/A' - else: - list_price = 'N/A' - payment_amount = 'N/A' - coupon_codes_used = 'N/A' - registration_code_used = 'N/A' - payment_status = _('TBD') - transaction_reference_number = 'N/A' - - payment_data['List Price'] = list_price - payment_data['Payment Amount'] = payment_amount - payment_data['Coupon Codes Used'] = coupon_codes_used - payment_data['Registration Code Used'] = registration_code_used - payment_data['Payment Status'] = payment_status - payment_data['Transaction Reference Number'] = transaction_reference_number - return payment_data - - def _get_order_data(self, registration_code_redemption, course_id): - """ - Returns the order data - """ - order_item = OrderItem.objects.get(order=registration_code_redemption.registration_code.order, - courseregcodeitem__course_id=course_id) - coupon_redemption = CouponRedemption.objects.select_related('coupon').filter( - order_id=registration_code_redemption.registration_code.order) - coupon_codes = [redemption.coupon.code for redemption in coupon_redemption] - coupon_codes = ", ".join(coupon_codes) - - list_price = order_item.get_list_price() - payment_amount = order_item.unit_cost - coupon_codes_used = coupon_codes - payment_status = order_item.status - transaction_reference_number = order_item.order_id - return list_price, payment_amount, coupon_codes_used, payment_status, transaction_reference_number - - def _get_invoice_data(self, registration_code_redemption): - """ - Returns the Invoice data - """ - registration_code = registration_code_redemption.registration_code - list_price = registration_code.invoice_item.unit_price - total_amount = registration_code_redemption.registration_code.invoice.total_amount - qty = registration_code_redemption.registration_code.invoice_item.qty - payment_amount = total_amount / qty - invoice_transaction = InvoiceTransaction.get_invoice_transaction( - invoice_id=registration_code_redemption.registration_code.invoice.id) - if invoice_transaction is not None: - # amount greater than 0 is invoice has bee paid - if invoice_transaction.amount > 0: - payment_status = 'Invoice Paid' - else: - # amount less than 0 is invoice has been refunded - payment_status = 'Refunded' - else: - payment_status = 'Invoice Outstanding' - transaction_reference_number = registration_code_redemption.registration_code.invoice_id - return list_price, payment_amount, payment_status, transaction_reference_number diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index 61338838e886905b7eada4e9f1a7ed822747370e..cb76c48e9d05e0b4ee963e98c999a752f4224301 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -118,12 +118,6 @@ REPORTS_DATA = ( 'task_api_endpoint': 'lms.djangoapps.instructor_task.api.submit_calculate_students_features_csv', 'extra_instructor_api_kwargs': {'csv': '/csv'} }, - { - 'report_type': 'detailed enrollment', - 'instructor_api_endpoint': 'get_enrollment_report', - 'task_api_endpoint': 'lms.djangoapps.instructor_task.api.submit_detailed_enrollment_features_csv', - 'extra_instructor_api_kwargs': {} - }, { 'report_type': 'enrollment', 'instructor_api_endpoint': 'get_students_who_may_enroll', @@ -155,7 +149,6 @@ INSTRUCTOR_POST_ENDPOINTS = set([ 'calculate_grades_csv', 'change_due_date', 'export_ora2_data', - 'get_enrollment_report', 'get_grading_config', 'get_problem_responses', 'get_proctored_exam_results', @@ -431,7 +424,6 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest ('list_report_downloads', {}), ('calculate_grades_csv', {}), ('get_students_features', {}), - ('get_enrollment_report', {}), ('get_students_who_may_enroll', {}), ('get_proctored_exam_results', {}), ('get_problem_responses', {}), diff --git a/lms/djangoapps/instructor/tests/test_enrollment_store_provider.py b/lms/djangoapps/instructor/tests/test_enrollment_store_provider.py deleted file mode 100644 index fb565131d434d53b94190e6b6d99d247454c52c1..0000000000000000000000000000000000000000 --- a/lms/djangoapps/instructor/tests/test_enrollment_store_provider.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -Exercises tests on the base_store_provider file -""" - - -from django.test import TestCase - -from lms.djangoapps.instructor.enrollment_report import AbstractEnrollmentReportProvider -from lms.djangoapps.instructor.paidcourse_enrollment_report import PaidCourseEnrollmentReportProvider - - -class BadImplementationAbstractEnrollmentReportProvider(AbstractEnrollmentReportProvider): - """ - Test implementation of EnrollmentProvider to assert that non-implementations of methods - raises the correct methods - """ - - def get_user_profile(self, user_id): - """ - Fake implementation of method which calls base class, which should throw NotImplementedError - """ - super(BadImplementationAbstractEnrollmentReportProvider, self).get_user_profile(user_id) - - def get_enrollment_info(self, user, course_id): - """ - Fake implementation of method which calls base class, which should throw NotImplementedError - """ - super(BadImplementationAbstractEnrollmentReportProvider, self).get_enrollment_info(user, course_id) - - def get_payment_info(self, user, course_id): - """ - Fake implementation of method which calls base class, which should throw NotImplementedError - """ - super(BadImplementationAbstractEnrollmentReportProvider, self).get_payment_info(user, course_id) - - -class TestBaseNotificationDataProvider(TestCase): - """ - Cover the EnrollmentReportProvider class - """ - - def test_cannot_create_instance(self): - """ - EnrollmentReportProvider is an abstract class and we should not be able - to create an instance of it - """ - - with self.assertRaises(TypeError): - # parent of the BaseEnrollmentReportProvider is EnrollmentReportProvider - super(BadImplementationAbstractEnrollmentReportProvider, self) - - def test_get_provider(self): - """ - Makes sure we get an instance of the registered enrollment provider - """ - - provider = PaidCourseEnrollmentReportProvider() - - self.assertIsNotNone(provider) - self.assertTrue(isinstance(provider, PaidCourseEnrollmentReportProvider)) - - def test_base_methods_exceptions(self): - """ - Asserts that all base-methods on the EnrollmentProvider interface will throw - an NotImplementedError - """ - - bad_provider = BadImplementationAbstractEnrollmentReportProvider() - - with self.assertRaises(NotImplementedError): - bad_provider.get_enrollment_info(None, None) - - with self.assertRaises(NotImplementedError): - bad_provider.get_payment_info(None, None) - - with self.assertRaises(NotImplementedError): - bad_provider.get_user_profile(None) diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index c3d64eb744ee4cbe734c1e21f43ff7bcf99a9d8f..3050417dd987ccddcd71c5a9b7d8bb8ef64c83c4 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -1312,25 +1312,6 @@ class CohortCSV(DeveloperErrorViewMixin, APIView): return Response(status=status.HTTP_204_NO_CONTENT) -@transaction.non_atomic_requests -@require_POST -@ensure_csrf_cookie -@cache_control(no_cache=True, no_store=True, must_revalidate=True) -@require_course_permission(permissions.ENROLLMENT_REPORT) -@require_finance_admin -@common_exceptions_400 -def get_enrollment_report(request, course_id): - """ - get the enrollment report for the particular course. - """ - course_key = CourseKey.from_string(course_id) - report_type = _('detailed enrollment') - task_api.submit_detailed_enrollment_features_csv(request, course_key) - success_status = SUCCESS_MESSAGE_TEMPLATE.format(report_type=report_type) - - return JsonResponse({"status": success_status}) - - @transaction.non_atomic_requests @require_POST @ensure_csrf_cookie diff --git a/lms/djangoapps/instructor/views/api_urls.py b/lms/djangoapps/instructor/views/api_urls.py index f19c76a65619ef3aa2c3b19b1b42dfdef993a416..b9f3442c381f4dbfa80e5e9ac3d8578d1f272b73 100644 --- a/lms/djangoapps/instructor/views/api_urls.py +++ b/lms/djangoapps/instructor/views/api_urls.py @@ -51,7 +51,6 @@ urlpatterns = [ url(r'^problem_grade_report$', api.problem_grade_report, name='problem_grade_report'), # Reports.. - url(r'^get_enrollment_report$', api.get_enrollment_report, name='get_enrollment_report'), url(r'^get_course_survey_results$', api.get_course_survey_results, name='get_course_survey_results'), url(r'^export_ora2_data', api.export_ora2_data, name='export_ora2_data'), diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index 227ff16d9b3e0fa991bfbe1f9b035c3f07e0202a..364444ad126c5c05af86c83c63058eb3073d0fc8 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -55,7 +55,6 @@ from openedx.core.djangoapps.verified_track_content.models import VerifiedTrackC from openedx.core.djangolib.markup import HTML, Text from openedx.core.lib.url_utils import quote_slashes from openedx.core.lib.xblock_utils import wrap_xblock -from shoppingcart.models import Coupon, CourseRegCodeItem, PaidCourseRegistration from student.models import CourseEnrollment from student.roles import ( CourseFinanceAdminRole, CourseInstructorRole, @@ -182,10 +181,6 @@ def instructor_dashboard_2(request, course_id): if is_bulk_email_feature_enabled(course_key) and (access['staff'] or access['instructor']): sections.append(_section_send_email(course, access)) - # Gate access to Ecommerce tab - if course_mode_has_price and (access['finance_admin'] or access['sales_admin']): - sections.append(_section_e_commerce(course, access, paid_modes[0], is_white_label, reports_enabled)) - # Gate access to Special Exam tab depending if either timed exams or proctored exams # are enabled in the course @@ -280,74 +275,6 @@ def instructor_dashboard_2(request, course_id): ## section_key will be used as a css attribute, javascript tie-in, and template import filename. ## section_display_name will be used to generate link titles in the nav bar. - -def _section_e_commerce(course, access, paid_mode, coupons_enabled, reports_enabled): - """ Provide data for the corresponding dashboard section """ - course_key = course.id - coupons = Coupon.objects.filter(course_id=course_key).order_by('-is_active') - course_price = paid_mode.min_price - - total_amount = None - if access['finance_admin']: - single_purchase_total = PaidCourseRegistration.get_total_amount_of_purchased_item(course_key) - bulk_purchase_total = CourseRegCodeItem.get_total_amount_of_purchased_item(course_key) - total_amount = single_purchase_total + bulk_purchase_total - - section_data = { - 'section_key': 'e-commerce', - 'section_display_name': _('E-Commerce'), - 'access': access, - 'course_id': six.text_type(course_key), - 'currency_symbol': settings.PAID_COURSE_REGISTRATION_CURRENCY[1], - 'ajax_remove_coupon_url': reverse('remove_coupon', kwargs={'course_id': six.text_type(course_key)}), - 'ajax_get_coupon_info': reverse('get_coupon_info', kwargs={'course_id': six.text_type(course_key)}), - 'get_user_invoice_preference_url': reverse( - 'get_user_invoice_preference', - kwargs={'course_id': six.text_type(course_key)} - ), - 'sale_validation_url': reverse('sale_validation', kwargs={'course_id': six.text_type(course_key)}), - 'ajax_update_coupon': reverse('update_coupon', kwargs={'course_id': six.text_type(course_key)}), - 'ajax_add_coupon': reverse('add_coupon', kwargs={'course_id': six.text_type(course_key)}), - 'instructor_url': reverse('instructor_dashboard', kwargs={'course_id': six.text_type(course_key)}), - 'get_registration_code_csv_url': reverse( - 'get_registration_codes', - kwargs={'course_id': six.text_type(course_key)} - ), - 'generate_registration_code_csv_url': reverse( - 'generate_registration_codes', - kwargs={'course_id': six.text_type(course_key)} - ), - 'active_registration_code_csv_url': reverse( - 'active_registration_codes', - kwargs={'course_id': six.text_type(course_key)} - ), - 'spent_registration_code_csv_url': reverse( - 'spent_registration_codes', - kwargs={'course_id': six.text_type(course_key)} - ), - 'set_course_mode_url': reverse('set_course_mode_price', kwargs={'course_id': six.text_type(course_key)}), - 'download_coupon_codes_url': reverse('get_coupon_codes', kwargs={'course_id': six.text_type(course_key)}), - 'enrollment_report_url': reverse('get_enrollment_report', kwargs={'course_id': six.text_type(course_key)}), - 'list_financial_report_downloads_url': reverse( - 'list_financial_report_downloads', - kwargs={'course_id': six.text_type(course_key)} - ), - 'list_instructor_tasks_url': reverse('list_instructor_tasks', kwargs={'course_id': six.text_type(course_key)}), - 'look_up_registration_code': reverse( - 'look_up_registration_code', - kwargs={'course_id': six.text_type(course_key)} - ), - 'coupons': coupons, - 'sales_admin': access['sales_admin'], - 'coupons_enabled': coupons_enabled, - 'reports_enabled': reports_enabled, - 'course_price': course_price, - 'total_amount': total_amount, - 'is_ecommerce_course': is_ecommerce_course(course_key) - } - return section_data - - def _section_special_exams(course, access): """ Provide data for the corresponding dashboard section """ course_key = six.text_type(course.id) diff --git a/lms/djangoapps/instructor_task/api.py b/lms/djangoapps/instructor_task/api.py index d0c68445a2579b40fe00c705e6ff91c7fad6abe3..5ec1ffcb65f8b1174b4544c02c5438eb6d4b646a 100644 --- a/lms/djangoapps/instructor_task/api.py +++ b/lms/djangoapps/instructor_task/api.py @@ -34,7 +34,6 @@ from lms.djangoapps.instructor_task.tasks import ( cohort_students, course_survey_report_csv, delete_problem_state, - enrollment_report_features_csv, export_ora2_data, generate_certificates, override_problem_score, @@ -376,20 +375,6 @@ def submit_calculate_students_features_csv(request, course_key, features): return submit_task(request, task_type, task_class, course_key, task_input, task_key) -def submit_detailed_enrollment_features_csv(request, course_key): - """ - Submits a task to generate a CSV containing detailed enrollment info. - - Raises AlreadyRunningError if said CSV is already being updated. - """ - task_type = 'detailed_enrollment_report' - task_class = enrollment_report_features_csv - task_input = {} - task_key = "" - - return submit_task(request, task_type, task_class, course_key, task_input, task_key) - - def submit_calculate_may_enroll_csv(request, course_key, features): """ Submits a task to generate a CSV file containing information about diff --git a/lms/djangoapps/instructor_task/tasks.py b/lms/djangoapps/instructor_task/tasks.py index 7c0340eacae3e0edb3954882a70c4bb9df08104a..2e00eabfc9c937070a6a2c793ca93ce87f748089 100644 --- a/lms/djangoapps/instructor_task/tasks.py +++ b/lms/djangoapps/instructor_task/tasks.py @@ -32,7 +32,6 @@ from bulk_email.tasks import perform_delegate_email_batches from lms.djangoapps.instructor_task.tasks_base import BaseInstructorTask from lms.djangoapps.instructor_task.tasks_helper.certs import generate_students_certificates from lms.djangoapps.instructor_task.tasks_helper.enrollments import ( - upload_enrollment_report, upload_may_enroll_csv, upload_students_csv ) @@ -217,18 +216,6 @@ def calculate_students_features_csv(entry_id, xmodule_instance_args): return run_main_task(entry_id, task_fn, action_name) -@task(base=BaseInstructorTask) -def enrollment_report_features_csv(entry_id, xmodule_instance_args): - """ - Compute student profile information for a course and upload the - CSV to an S3 bucket for download. - """ - # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = ugettext_noop('generating_enrollment_report') - task_fn = partial(upload_enrollment_report, xmodule_instance_args) - return run_main_task(entry_id, task_fn, action_name) - - @task(base=BaseInstructorTask) def course_survey_report_csv(entry_id, xmodule_instance_args): """ diff --git a/lms/djangoapps/instructor_task/tasks_helper/enrollments.py b/lms/djangoapps/instructor_task/tasks_helper/enrollments.py index ddcd33e6e8fcd6f6dc774bcc712f29c89d22bb5d..c22db99a8f24ac6b116ff3337d6243afb7263f2d 100644 --- a/lms/djangoapps/instructor_task/tasks_helper/enrollments.py +++ b/lms/djangoapps/instructor_task/tasks_helper/enrollments.py @@ -14,7 +14,6 @@ from six import StringIO from edxmako.shortcuts import render_to_string from lms.djangoapps.courseware.courses import get_course_by_id -from lms.djangoapps.instructor.paidcourse_enrollment_report import PaidCourseEnrollmentReportProvider from lms.djangoapps.instructor_analytics.basic import enrolled_students_features, list_may_enroll from lms.djangoapps.instructor_analytics.csvs import format_dictlist from lms.djangoapps.instructor_task.models import ReportStore @@ -28,127 +27,6 @@ TASK_LOG = logging.getLogger('edx.celery.task') FILTERED_OUT_ROLES = ['staff', 'instructor', 'finance_admin', 'sales_admin'] -def upload_enrollment_report(_xmodule_instance_args, _entry_id, course_id, _task_input, action_name): - """ - For a given `course_id`, generate a CSV file containing profile - information for all students that are enrolled, and store using a - `ReportStore`. - """ - start_time = time() - start_date = datetime.now(UTC) - status_interval = 100 - students_in_course = CourseEnrollment.objects.enrolled_and_dropped_out_users(course_id) - task_progress = TaskProgress(action_name, students_in_course.count(), start_time) - - fmt = u'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}' - task_info_string = fmt.format( - task_id=_xmodule_instance_args.get('task_id') if _xmodule_instance_args is not None else None, - entry_id=_entry_id, - course_id=course_id, - task_input=_task_input - ) - TASK_LOG.info(u'%s, Task type: %s, Starting task execution', task_info_string, action_name) - - # Loop over all our students and build our CSV lists in memory - rows = [] - header = None - current_step = {'step': 'Gathering Profile Information'} - enrollment_report_provider = PaidCourseEnrollmentReportProvider() - total_students = students_in_course.count() - student_counter = 0 - TASK_LOG.info( - u'%s, Task type: %s, Current step: %s, generating detailed enrollment report for total students: %s', - task_info_string, - action_name, - current_step, - total_students - ) - - for student in students_in_course: - # Periodically update task status (this is a cache write) - if task_progress.attempted % status_interval == 0: - task_progress.update_task_state(extra_meta=current_step) - task_progress.attempted += 1 - - # Now add a log entry after certain intervals to get a hint that task is in progress - student_counter += 1 - if student_counter % 100 == 0: - TASK_LOG.info( - u'%s, Task type: %s, Current step: %s, gathering enrollment profile for students in progress: %s/%s', - task_info_string, - action_name, - current_step, - student_counter, - total_students - ) - - user_data = enrollment_report_provider.get_user_profile(student.id) - course_enrollment_data = enrollment_report_provider.get_enrollment_info(student, course_id) - payment_data = enrollment_report_provider.get_payment_info(student, course_id) - - # display name map for the column headers - enrollment_report_headers = { - 'User ID': _('User ID'), - 'Username': _('Username'), - 'Full Name': _('Full Name'), - 'First Name': _('First Name'), - 'Last Name': _('Last Name'), - 'Company Name': _('Company Name'), - 'Title': _('Title'), - 'Language': _('Language'), - 'Year of Birth': _('Year of Birth'), - 'Gender': _('Gender'), - 'Level of Education': _('Level of Education'), - 'Mailing Address': _('Mailing Address'), - 'Goals': _('Goals'), - 'City': _('City'), - 'Country': _('Country'), - 'Enrollment Date': _('Enrollment Date'), - 'Currently Enrolled': _('Currently Enrolled'), - 'Enrollment Source': _('Enrollment Source'), - 'Manual (Un)Enrollment Reason': _('Manual (Un)Enrollment Reason'), - 'Enrollment Role': _('Enrollment Role'), - 'List Price': _('List Price'), - 'Payment Amount': _('Payment Amount'), - 'Coupon Codes Used': _('Coupon Codes Used'), - 'Registration Code Used': _('Registration Code Used'), - 'Payment Status': _('Payment Status'), - 'Transaction Reference Number': _('Transaction Reference Number') - } - - if not header: - header = list(user_data.keys()) + list(course_enrollment_data.keys()) + list(payment_data.keys()) - display_headers = [] - for header_element in header: - # translate header into a localizable display string - display_headers.append(enrollment_report_headers.get(header_element, header_element)) - rows.append(display_headers) - - rows.append(list(user_data.values()) + list(course_enrollment_data.values()) + list(payment_data.values())) - task_progress.succeeded += 1 - - TASK_LOG.info( - u'%s, Task type: %s, Current step: %s, Detailed enrollment report generated for students: %s/%s', - task_info_string, - action_name, - current_step, - student_counter, - total_students - ) - - # By this point, we've got the rows we're going to stuff into our CSV files. - current_step = {'step': 'Uploading CSVs'} - task_progress.update_task_state(extra_meta=current_step) - TASK_LOG.info(u'%s, Task type: %s, Current step: %s', task_info_string, action_name, current_step) - - # Perform the actual upload - upload_csv_to_report_store(rows, 'enrollment_report', course_id, start_date, config_name='FINANCIAL_REPORTS') - - # One last update before we close out... - TASK_LOG.info(u'%s, Task type: %s, Finalizing detailed enrollment task', task_info_string, action_name) - return task_progress.update_task_state(extra_meta=current_step) - - def upload_may_enroll_csv(_xmodule_instance_args, _entry_id, course_id, task_input, action_name): """ For a given `course_id`, generate a CSV file containing diff --git a/lms/djangoapps/instructor_task/tests/test_api.py b/lms/djangoapps/instructor_task/tests/test_api.py index 47b8103e711600ed44d34f63d387b7d8313c1fe9..d0658391d2ac9c7a94860e15a4444014d78b89ee 100644 --- a/lms/djangoapps/instructor_task/tests/test_api.py +++ b/lms/djangoapps/instructor_task/tests/test_api.py @@ -26,7 +26,6 @@ from lms.djangoapps.instructor_task.api import ( submit_course_survey_report, submit_delete_entrance_exam_state_for_student, submit_delete_problem_state_for_all_students, - submit_detailed_enrollment_features_csv, submit_export_ora2_data, submit_override_score, submit_rescore_entrance_exam_for_student, @@ -251,11 +250,6 @@ class InstructorTaskCourseSubmitTest(TestReportMixin, InstructorTaskCourseTestCa ) self._test_resubmission(api_call) - def test_submit_enrollment_report_features_csv(self): - api_call = lambda: submit_detailed_enrollment_features_csv(self.create_task_request(self.instructor), - self.course.id) - self._test_resubmission(api_call) - def test_submit_course_survey_report(self): api_call = lambda: submit_course_survey_report( self.create_task_request(self.instructor), self.course.id diff --git a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py index e26b2249c8fadcba5b7f2b1aab14fecf5e83961f..ba841d879946810a47a25161e5258e31f46eadc2 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py @@ -43,7 +43,6 @@ from lms.djangoapps.grades.transformer import GradesTransformer from lms.djangoapps.instructor_analytics.basic import UNAVAILABLE, list_problem_responses from lms.djangoapps.instructor_task.tasks_helper.certs import generate_students_certificates from lms.djangoapps.instructor_task.tasks_helper.enrollments import ( - upload_enrollment_report, upload_may_enroll_csv, upload_students_csv )