diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index 756ea92174..61338838e8 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -144,17 +144,6 @@ REPORTS_DATA = ( } ) -# ddt data for test cases involving executive summary report -EXECUTIVE_SUMMARY_DATA = ( - { - 'report_type': 'executive summary', - 'task_type': 'exec_summary_report', - 'instructor_api_endpoint': 'get_exec_summary_report', - 'task_api_endpoint': 'lms.djangoapps.instructor_task.api.submit_executive_summary_report', - 'extra_instructor_api_kwargs': {} - }, -) - INSTRUCTOR_GET_ENDPOINTS = set([ 'get_anon_ids', @@ -167,7 +156,6 @@ INSTRUCTOR_POST_ENDPOINTS = set([ 'change_due_date', 'export_ora2_data', 'get_enrollment_report', - 'get_exec_summary_report', 'get_grading_config', 'get_problem_responses', 'get_proctored_exam_results', @@ -445,7 +433,6 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest ('get_students_features', {}), ('get_enrollment_report', {}), ('get_students_who_may_enroll', {}), - ('get_exec_summary_report', {}), ('get_proctored_exam_results', {}), ('get_problem_responses', {}), ('export_ora2_data', {}), @@ -2875,50 +2862,6 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment response = self.client.post(url, {}) self.assertContains(response, success_status) - @ddt.data(*EXECUTIVE_SUMMARY_DATA) - @ddt.unpack - def test_executive_summary_report_success( - self, - report_type, - task_type, - instructor_api_endpoint, - task_api_endpoint, - extra_instructor_api_kwargs - ): # pylint: disable=unused-argument - kwargs = {'course_id': text_type(self.course.id)} - kwargs.update(extra_instructor_api_kwargs) - url = reverse(instructor_api_endpoint, kwargs=kwargs) - - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - with patch(task_api_endpoint): - response = self.client.post(url, {}) - success_status = u"The {report_type} report is being created." \ - " To view the status of the report, see Pending" \ - " Tasks below".format(report_type=report_type) - self.assertContains(response, success_status) - - @ddt.data(*EXECUTIVE_SUMMARY_DATA) - @ddt.unpack - def test_executive_summary_report_already_running( - self, - report_type, - task_type, - instructor_api_endpoint, - task_api_endpoint, - extra_instructor_api_kwargs - ): - kwargs = {'course_id': text_type(self.course.id)} - kwargs.update(extra_instructor_api_kwargs) - url = reverse(instructor_api_endpoint, kwargs=kwargs) - - CourseFinanceAdminRole(self.course.id).add_users(self.instructor) - already_running_status = generate_already_running_error_message(task_type) - with patch(task_api_endpoint) as mock: - mock.side_effect = AlreadyRunningError(already_running_status) - response = self.client.post(url, {}) - - self.assertContains(response, already_running_status, status_code=400) - def test_get_ora2_responses_success(self): url = reverse('export_ora2_data', kwargs={'course_id': text_type(self.course.id)}) diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index 369e06d2a2..a41170a675 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -39,7 +39,7 @@ from rest_framework import status from rest_framework.permissions import IsAuthenticated, IsAdminUser from rest_framework.response import Response from rest_framework.views import APIView -from six import StringIO, text_type +from six import text_type from six.moves import map, range from submissions import api as sub_api # installed from the edx-submissions repository @@ -1362,25 +1362,6 @@ def get_enrollment_report(request, course_id): return JsonResponse({"status": success_status}) -@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_exec_summary_report(request, course_id): - """ - get the executive summary report for the particular course. - """ - course_key = CourseKey.from_string(course_id) - report_type = _('executive summary') - task_api.submit_executive_summary_report(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 d8df317da9..f19c76a656 100644 --- a/lms/djangoapps/instructor/views/api_urls.py +++ b/lms/djangoapps/instructor/views/api_urls.py @@ -52,7 +52,6 @@ urlpatterns = [ # Reports.. url(r'^get_enrollment_report$', api.get_enrollment_report, name='get_enrollment_report'), - url(r'^get_exec_summary_report$', api.get_exec_summary_report, name='get_exec_summary_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 4259f7e24a..c0b63a9b09 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -318,7 +318,6 @@ def _section_e_commerce(course, access, paid_mode, coupons_enabled, reports_enab '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)}), - 'exec_summary_report_url': reverse('get_exec_summary_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)} diff --git a/lms/djangoapps/instructor_task/api.py b/lms/djangoapps/instructor_task/api.py index bbef2c2f8c..d0c68445a2 100644 --- a/lms/djangoapps/instructor_task/api.py +++ b/lms/djangoapps/instructor_task/api.py @@ -35,7 +35,6 @@ from lms.djangoapps.instructor_task.tasks import ( course_survey_report_csv, delete_problem_state, enrollment_report_features_csv, - exec_summary_report_csv, export_ora2_data, generate_certificates, override_problem_score, @@ -406,20 +405,6 @@ def submit_calculate_may_enroll_csv(request, course_key, features): return submit_task(request, task_type, task_class, course_key, task_input, task_key) -def submit_executive_summary_report(request, course_key): - """ - Submits a task to generate a HTML File containing the executive summary report. - - Raises AlreadyRunningError if HTML File is already being updated. - """ - task_type = 'exec_summary_report' - task_class = exec_summary_report_csv - task_input = {} - task_key = "" - - return submit_task(request, task_type, task_class, course_key, task_input, task_key) - - def submit_course_survey_report(request, course_key): """ Submits a task to generate a HTML File containing the executive summary report. diff --git a/lms/djangoapps/instructor_task/api_helper.py b/lms/djangoapps/instructor_task/api_helper.py index 0ea0a43e5b..0b46c5ad7f 100644 --- a/lms/djangoapps/instructor_task/api_helper.py +++ b/lms/djangoapps/instructor_task/api_helper.py @@ -110,7 +110,6 @@ def generate_already_running_error_message(task_type): 'profile_info_csv': _('enrolled learner profile'), 'may_enroll_info_csv': _('enrollment'), 'detailed_enrollment_report': _('detailed enrollment'), - 'exec_summary_report': _('executive summary'), 'course_survey_report': _('survey'), 'proctored_exam_results_report': _('proctored exam results'), 'export_ora2_data': _('ORA data'), diff --git a/lms/djangoapps/instructor_task/tasks.py b/lms/djangoapps/instructor_task/tasks.py index ae697a1c7e..7c0340eaca 100644 --- a/lms/djangoapps/instructor_task/tasks.py +++ b/lms/djangoapps/instructor_task/tasks.py @@ -33,7 +33,6 @@ 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_exec_summary_report, upload_may_enroll_csv, upload_students_csv ) @@ -230,18 +229,6 @@ def enrollment_report_features_csv(entry_id, xmodule_instance_args): return run_main_task(entry_id, task_fn, action_name) -@task(base=BaseInstructorTask) -def exec_summary_report_csv(entry_id, xmodule_instance_args): - """ - Compute executive summary report for a course and upload the - Html generated report to an S3 bucket for download. - """ - # Translators: This is a past-tense verb that is inserted into task progress messages as {action}. - action_name = 'generating_exec_summary_report' - task_fn = partial(upload_exec_summary_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 58dbdda50a..ddcd33e6e8 100644 --- a/lms/djangoapps/instructor_task/tasks_helper/enrollments.py +++ b/lms/djangoapps/instructor_task/tasks_helper/enrollments.py @@ -18,15 +18,6 @@ from lms.djangoapps.instructor.paidcourse_enrollment_report import PaidCourseEnr 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 -from shoppingcart.models import ( - CouponRedemption, - CourseRegCodeItem, - CourseRegistrationCode, - Invoice, - InvoiceTransaction, - PaidCourseRegistration, - RegistrationCodeRedemption -) from student.models import CourseAccessRole, CourseEnrollment from util.file import course_filename_prefix_generator @@ -221,175 +212,3 @@ def upload_students_csv(_xmodule_instance_args, _entry_id, course_id, task_input upload_csv_to_report_store(rows, 'student_profile_info', course_id, start_date) return task_progress.update_task_state(extra_meta=current_step) - - -def get_executive_report(course_id): - """ - Returns dict containing information about the course executive summary. - """ - single_purchase_total = PaidCourseRegistration.get_total_amount_of_purchased_item(course_id) - bulk_purchase_total = CourseRegCodeItem.get_total_amount_of_purchased_item(course_id) - paid_invoices_total = InvoiceTransaction.get_total_amount_of_paid_course_invoices(course_id) - gross_paid_revenue = single_purchase_total + bulk_purchase_total + paid_invoices_total - - all_invoices_total = Invoice.get_invoice_total_amount_for_course(course_id) - gross_pending_revenue = all_invoices_total - float(paid_invoices_total) - - gross_revenue = float(gross_paid_revenue) + float(gross_pending_revenue) - - refunded_self_purchased_seats = PaidCourseRegistration.get_self_purchased_seat_count( - course_id, status='refunded' - ) - refunded_bulk_purchased_seats = CourseRegCodeItem.get_bulk_purchased_seat_count( - course_id, status='refunded' - ) - total_seats_refunded = refunded_self_purchased_seats + refunded_bulk_purchased_seats - - self_purchased_refunds = PaidCourseRegistration.get_total_amount_of_purchased_item( - course_id, - status='refunded' - ) - bulk_purchase_refunds = CourseRegCodeItem.get_total_amount_of_purchased_item(course_id, status='refunded') - total_amount_refunded = self_purchased_refunds + bulk_purchase_refunds - - top_discounted_codes = CouponRedemption.get_top_discount_codes_used(course_id) - total_coupon_codes_purchases = CouponRedemption.get_total_coupon_code_purchases(course_id) - - bulk_purchased_codes = CourseRegistrationCode.order_generated_registration_codes(course_id) - - unused_registration_codes = 0 - for registration_code in bulk_purchased_codes: - if not RegistrationCodeRedemption.is_registration_code_redeemed(registration_code.code): - unused_registration_codes += 1 - - self_purchased_seat_count = PaidCourseRegistration.get_self_purchased_seat_count(course_id) - bulk_purchased_seat_count = CourseRegCodeItem.get_bulk_purchased_seat_count(course_id) - total_invoiced_seats = CourseRegistrationCode.invoice_generated_registration_codes(course_id).count() - - total_seats = self_purchased_seat_count + bulk_purchased_seat_count + total_invoiced_seats - - self_purchases_percentage = 0.0 - bulk_purchases_percentage = 0.0 - invoice_purchases_percentage = 0.0 - avg_price_paid = 0.0 - - if total_seats != 0: - self_purchases_percentage = (float(self_purchased_seat_count) / float(total_seats)) * 100 - bulk_purchases_percentage = (float(bulk_purchased_seat_count) / float(total_seats)) * 100 - invoice_purchases_percentage = (float(total_invoiced_seats) / float(total_seats)) * 100 - avg_price_paid = gross_revenue / total_seats - - course = get_course_by_id(course_id, depth=0) - currency = settings.PAID_COURSE_REGISTRATION_CURRENCY[1] - - return { - 'display_name': course.display_name, - 'start_date': course.start.strftime("%Y-%m-%d") if course.start is not None else 'N/A', - 'end_date': course.end.strftime("%Y-%m-%d") if course.end is not None else 'N/A', - 'total_seats': total_seats, - 'currency': currency, - 'gross_revenue': float(gross_revenue), - 'gross_paid_revenue': float(gross_paid_revenue), - 'gross_pending_revenue': gross_pending_revenue, - 'total_seats_refunded': total_seats_refunded, - 'total_amount_refunded': float(total_amount_refunded), - 'average_paid_price': float(avg_price_paid), - 'discount_codes_data': top_discounted_codes, - 'total_seats_using_discount_codes': total_coupon_codes_purchases, - 'total_self_purchase_seats': self_purchased_seat_count, - 'total_bulk_purchase_seats': bulk_purchased_seat_count, - 'total_invoiced_seats': total_invoiced_seats, - 'unused_bulk_purchase_code_count': unused_registration_codes, - 'self_purchases_percentage': self_purchases_percentage, - 'bulk_purchases_percentage': bulk_purchases_percentage, - 'invoice_purchases_percentage': invoice_purchases_percentage, - } - - -def upload_exec_summary_report(_xmodule_instance_args, _entry_id, course_id, _task_input, action_name): - """ - For a given `course_id`, generate a html report containing information, - which provides a snapshot of how the course is doing. - """ - start_time = time() - report_generation_date = datetime.now(UTC) - status_interval = 100 - - enrolled_users = CourseEnrollment.objects.users_enrolled_in(course_id) - true_enrollment_count = 0 - for user in enrolled_users: - if not user.is_staff and not CourseAccessRole.objects.filter( - user=user, course_id=course_id, role__in=FILTERED_OUT_ROLES - ).exists(): - true_enrollment_count += 1 - - task_progress = TaskProgress(action_name, true_enrollment_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) - current_step = {'step': 'Gathering executive summary report information'} - - TASK_LOG.info( - u'%s, Task type: %s, Current step: %s, generating executive summary report', - task_info_string, - action_name, - current_step - ) - - if task_progress.attempted % status_interval == 0: - task_progress.update_task_state(extra_meta=current_step) - task_progress.attempted += 1 - - # get the course executive summary report information. - data_dict = get_executive_report(course_id) - data_dict.update( - { - 'total_enrollments': true_enrollment_count, - 'report_generation_date': report_generation_date.strftime("%Y-%m-%d"), - } - ) - - # By this point, we've got the data that we need to generate html report. - current_step = {'step': 'Uploading executive summary report HTML file'} - 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_exec_summary_to_store(data_dict, 'executive_report', course_id, report_generation_date) - task_progress.succeeded += 1 - # One last update before we close out... - TASK_LOG.info(u'%s, Task type: %s, Finalizing executive summary report task', task_info_string, action_name) - return task_progress.update_task_state(extra_meta=current_step) - - -def _upload_exec_summary_to_store(data_dict, report_name, course_id, generated_at, config_name='FINANCIAL_REPORTS'): - """ - Upload Executive Summary Html file using ReportStore. - - Arguments: - data_dict: containing executive report data. - report_name: Name of the resulting Html File. - course_id: ID of the course - """ - report_store = ReportStore.from_config(config_name) - - # Use the data dict and html template to generate the output buffer - output_buffer = StringIO(render_to_string("instructor/instructor_dashboard_2/executive_summary.html", data_dict)) - - report_store.store( - course_id, - u"{course_prefix}_{report_name}_{timestamp_str}.html".format( - course_prefix=course_filename_prefix_generator(course_id), - report_name=report_name, - timestamp_str=generated_at.strftime("%Y-%m-%d-%H%M") - ), - output_buffer, - ) - tracker_emit(report_name) diff --git a/lms/djangoapps/instructor_task/tests/test_api.py b/lms/djangoapps/instructor_task/tests/test_api.py index 269b72ca02..47b8103e71 100644 --- a/lms/djangoapps/instructor_task/tests/test_api.py +++ b/lms/djangoapps/instructor_task/tests/test_api.py @@ -27,7 +27,6 @@ from lms.djangoapps.instructor_task.api import ( submit_delete_entrance_exam_state_for_student, submit_delete_problem_state_for_all_students, submit_detailed_enrollment_features_csv, - submit_executive_summary_report, submit_export_ora2_data, submit_override_score, submit_rescore_entrance_exam_for_student, @@ -257,12 +256,6 @@ class InstructorTaskCourseSubmitTest(TestReportMixin, InstructorTaskCourseTestCa self.course.id) self._test_resubmission(api_call) - def test_submit_executive_summary_report(self): - api_call = lambda: submit_executive_summary_report( - 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 7cbfd0271e..e26b2249c8 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py @@ -44,7 +44,6 @@ from lms.djangoapps.instructor_analytics.basic import UNAVAILABLE, list_problem_ 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_exec_summary_report, upload_may_enroll_csv, upload_students_csv ) @@ -1030,49 +1029,6 @@ class TestProblemReportCohortedContent(TestReportMixin, ContentGroupTestCase, In self.verify_rows_in_csv(expected_grades) -@ddt.ddt -class TestExecutiveSummaryReport(TestReportMixin, InstructorTaskCourseTestCase): - """ - Tests that Executive Summary report generation works. - """ - def setUp(self): - super(TestExecutiveSummaryReport, self).setUp() - self.course = CourseFactory.create() - CourseModeFactory.create( - course_id=self.course.id, - min_price=50, - mode_slug=CourseMode.DEFAULT_SHOPPINGCART_MODE_SLUG - ) - - self.instructor = InstructorFactory(course_key=self.course.id) - self.student1 = UserFactory() - self.student2 = UserFactory() - - def test_successfully_generate_executive_summary_report(self): - """ - Test that successfully generates the executive summary report. - """ - task_input = {'features': []} - with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): - result = upload_exec_summary_report( - None, None, self.course.id, - task_input, 'generating executive summary report' - ) - ReportStore.from_config(config_name='FINANCIAL_REPORTS') - self.assertDictContainsSubset({'attempted': 1, 'succeeded': 1, 'failed': 0}, result) - - def _verify_html_file_report(self, report_store, expected_data): - """ - Verify grade report data. - """ - report_html_filename = report_store.links_for(self.course.id)[0][0] - report_path = report_store.path_to(self.course.id, report_html_filename) - with report_store.storage.open(report_path) as html_file: - html_file_data = html_file.read().decode('utf-8') - for data in expected_data: - self.assertIn(data, html_file_data) - - @ddt.ddt class TestCourseSurveyReport(TestReportMixin, InstructorTaskCourseTestCase): """ diff --git a/lms/templates/instructor/instructor_dashboard_2/e-commerce.html b/lms/templates/instructor/instructor_dashboard_2/e-commerce.html deleted file mode 100644 index c75ae595ef..0000000000 --- a/lms/templates/instructor/instructor_dashboard_2/e-commerce.html +++ /dev/null @@ -1,691 +0,0 @@ -<%page args="section_data" expression_filter="h"/> -<%! -from django.utils.translation import ugettext as _ -from datetime import datetime, timedelta -from openedx.core.djangolib.js_utils import js_escaped_string -from openedx.core.djangolib.markup import HTML, Text -import pytz -%> -<%include file="add_coupon_modal.html" args="section_data=section_data" /> -<%include file="edit_coupon_modal.html" args="section_data=section_data" /> -<%include file="set_course_mode_price_modal.html" args="section_data=section_data" /> -<%include file="generate_registarion_codes_modal.html" args="section_data=section_data" /> -<%include file="invalidate_registration_code_modal.html" args="section_data=section_data" /> -
-
-
- %if not section_data['is_ecommerce_course']: -
-

${_('Enrollment Codes')}

-
- %if section_data['sales_admin']: - -

${_('Create one or more pre-paid course enrollment codes. Students can use these codes to enroll in the course.')}

- ${_('Create Enrollment Codes')} -

-

${_('Cancel, restore, or mark an enrollment code as unused.')}

- ${_('Change Enrollment Code Status')} -
- %endif -

${_('Download a .csv file of all enrollment codes for this course.')}

-

-

- - - -
-

-

${_('Download a .csv file of all unused enrollment codes for this course.')}

-

-

- - - -
-

-

${_('Download a .csv file of all used enrollment codes for this course.')}

-

-

- - - -
-

- -
-
- %endif - - %if section_data['coupons_enabled']: -
-

${_("Course Price")}

-
- ${_("Course price per seat: ")}${section_data['currency_symbol']}${section_data['course_price']} - %if section_data['access']['finance_admin'] is True: - + ${_('Edit Price')} - %endif - -
-
- %endif - - %if section_data['access']['finance_admin']: -
-

${_("Course Seat Purchases")}

-
- %if section_data['total_amount'] is not None: - ${_("Total Credit Card Purchases: ")}${section_data['currency_symbol']}${section_data['total_amount']} - %endif - -
-

${_("Download a .csv file for all credit card purchases or for all invoices, regardless of status.")}

- - -
-
-
-

${_("To cancel or resubmit an invoice, enter the invoice number below.")}

- - - - - - -
-
- %endif - %if section_data['reports_enabled']: -
-

${_("Reports")}

-
- -
-

${_("Create a .csv file that contains enrollment information for your course.")}

- -
-
-
-
-
- -
-

${_("Create an HTML file that contains an executive summary for this course.")}

- -
-
-
-
-
-
-

${_("Available Reports")}

-

${_("The following reports are available for download. Reports are not deleted. A link to every report remains available on this page, identified by the date and time (in UTC) that the report was generated.")}

- - ## Translators: a table of URL links to report files appears after this sentence. -

- ${Text(_("{strong_start}Note{strong_end}: To help protect learner data, links to these reports that you save outside of this page or that you send or receive in email expire after five minutes.")).format( - strong_start=HTML(""), - strong_end=HTML(""), - )} -


- -
-
- - %if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'): -
-
-

${_("Pending Tasks")}

-
-

${_("The status for any active tasks appears in a table below.")}

-
-
-
-
-
- %endif -
-
- %endif - %if section_data['coupons_enabled'] and not section_data['is_ecommerce_course']: -
-

${_("Coupon Code List")}

-
- - ${_("Download a .csv file of all coupon codes for this course.")} - - - - ${_("Coupon Codes")} + ${_("Add Coupon Code")} -
-
- %if len(section_data['coupons']): - - - - - - - - - - - - - %for coupon in section_data['coupons']: - <% current_date = datetime.now(pytz.UTC) %> - <% coupon_expiry_date = coupon.expiration_date %> - %if coupon.is_active == False: - - %elif coupon_expiry_date is not None and current_date >= coupon_expiry_date: - - %else: - - %endif - - - - - - - - %endfor - -
${_("Coupon Code")}${_("Description")}${_("Expiration Date")}${_("Coupon (%)")}${_("Number Redeemed")}${_("Actions")}
${_('{code}').format(code=coupon.code)}${_('{description}').format(description=coupon.description)} - ${coupon.display_expiry_date} - ${_('{discount}').format(discount=coupon.percentage_discount)}${ coupon.couponredemption_set.filter(order__status='purchased').count() }[x]${_('Edit')}
- - %endif -
-
-
-
- %endif - -
-
- diff --git a/lms/templates/instructor/instructor_dashboard_2/executive_summary.html b/lms/templates/instructor/instructor_dashboard_2/executive_summary.html deleted file mode 100644 index 16563054c2..0000000000 --- a/lms/templates/instructor/instructor_dashboard_2/executive_summary.html +++ /dev/null @@ -1,140 +0,0 @@ -<%page expression_filter="h"/> -<%! from django.utils.translation import ugettext as _ %> - - - - -Executive Summary - - - - - - - - - - - - - - -

${_("Executive Summary for {display_name}").format(display_name=display_name)}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
${_("Course Start Date")} ${start_date}
${_("Course End Date")} ${end_date}
${_("Report Creation Date")} ${report_generation_date}
${_("Number of Seats")}${total_seats}
${_("Number of Enrollments")}${total_enrollments}
${_("Gross Revenue")}${currency}${"{0:0.2f}".format(gross_revenue)}
${_("Gross Revenue Collected")}${currency}${"{0:0.2f}".format(gross_paid_revenue)}
${_("Gross Revenue Pending")}${currency}${"{0:0.2f}".format(gross_pending_revenue)}
${_("Number of Enrollment Refunds")}${total_seats_refunded}
${_("Amount Refunded")}${currency}${"{0:0.2f}".format(total_amount_refunded)}
${_("Average Price per Seat")}${currency}${"{0:0.2f}".format(average_paid_price)}

${_("Frequently Used Coupon Codes")}

- - - - - -
${_("Number of seats purchased using coupon codes")}${total_seats_using_discount_codes['coupon__count']}
- - - - - - - %for i, discount_code_data in enumerate(discount_codes_data): - - - - - - - %endfor -
${_("Rank")}${_("Coupon Code")}${_("Percent Discount")}${_("Times Used")}
${i+1}${discount_code_data['coupon__code']}${discount_code_data['coupon__percentage_discount']}${discount_code_data['coupon__used_count']}

${_("Bulk and Single Seat Purchases")}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
${_("Number of seats purchased individually")}${total_self_purchase_seats}
${_("Number of seats purchased in bulk")}${total_bulk_purchase_seats}
${_("Number of seats purchased with invoices")}${total_invoiced_seats}
${_("Unused bulk purchase seats (revenue at risk)")}${unused_bulk_purchase_code_count}
${_("Percentage of seats purchased individually")}${"{0:0.2f}".format(self_purchases_percentage)}%
${_("Percentage of seats purchased in bulk")}${"{0:0.2f}".format(bulk_purchases_percentage)}%
${_("Percentage of seats purchased with invoices")}${"{0:0.2f}".format(invoice_purchases_percentage)}%
- -