From 5c5d383aa0e76771b809f4c4cebc8e2c73f5d187 Mon Sep 17 00:00:00 2001 From: Eugene Dyudyunov Date: Mon, 2 May 2022 17:41:08 +0300 Subject: [PATCH] refactor: remove VerifiedTrackCohortedCourse feature --- .../instructor/views/instructor_dashboard.py | 8 +- .../groups/models/verified_track_settings.js | 12 - lms/static/js/groups/views/cohorts.js | 31 +- .../groups/views/cohorts_dashboard_factory.js | 1 - .../verified_track_settings_notification.js | 76 ----- .../js/spec/groups/views/cohorts_spec.js | 100 +------ .../cohort-form.underscore | 16 +- .../cohort_management.html | 1 - lms/urls.py | 8 - .../verified_track_content/admin.py | 23 -- .../verified_track_content/forms.py | 54 ---- .../management/__init__.py | 0 .../management/commands/__init__.py | 0 .../swap_from_auto_track_cohort_pilot.py | 283 ------------------ .../migrations/0001_initial.py | 19 -- ...rackcohortedcourse_verified_cohort_name.py | 16 - ...0003_migrateverifiedtrackcohortssetting.py | 27 -- .../migrations/__init__.py | 0 .../verified_track_content/models.py | 185 ------------ .../partition_scheme.py | 21 -- .../verified_track_content/tasks.py | 63 ---- .../verified_track_content/views.py | 39 --- 22 files changed, 16 insertions(+), 967 deletions(-) delete mode 100644 lms/static/js/groups/models/verified_track_settings.js delete mode 100644 lms/static/js/groups/views/verified_track_settings_notification.js delete mode 100644 openedx/core/djangoapps/verified_track_content/admin.py delete mode 100644 openedx/core/djangoapps/verified_track_content/forms.py delete mode 100644 openedx/core/djangoapps/verified_track_content/management/__init__.py delete mode 100644 openedx/core/djangoapps/verified_track_content/management/commands/__init__.py delete mode 100644 openedx/core/djangoapps/verified_track_content/management/commands/swap_from_auto_track_cohort_pilot.py delete mode 100644 openedx/core/djangoapps/verified_track_content/migrations/0001_initial.py delete mode 100644 openedx/core/djangoapps/verified_track_content/migrations/0002_verifiedtrackcohortedcourse_verified_cohort_name.py delete mode 100644 openedx/core/djangoapps/verified_track_content/migrations/0003_migrateverifiedtrackcohortssetting.py delete mode 100644 openedx/core/djangoapps/verified_track_content/migrations/__init__.py delete mode 100644 openedx/core/djangoapps/verified_track_content/models.py delete mode 100644 openedx/core/djangoapps/verified_track_content/tasks.py delete mode 100644 openedx/core/djangoapps/verified_track_content/views.py diff --git a/lms/djangoapps/instructor/views/instructor_dashboard.py b/lms/djangoapps/instructor/views/instructor_dashboard.py index ffc2a752d9..4625402f6e 100644 --- a/lms/djangoapps/instructor/views/instructor_dashboard.py +++ b/lms/djangoapps/instructor/views/instructor_dashboard.py @@ -60,7 +60,6 @@ from openedx.core.djangoapps.discussions.utils import available_division_schemes from openedx.core.djangoapps.django_comment_common.models import FORUM_ROLE_ADMINISTRATOR, CourseDiscussionSettings from openedx.core.djangoapps.plugins.constants import ProjectType from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.verified_track_content.models import VerifiedTrackCohortedCourse from openedx.core.djangolib.markup import HTML, Text from openedx.core.lib.courses import get_course_by_id from openedx.core.lib.url_utils import quote_slashes @@ -508,9 +507,6 @@ def _section_cohort_management(course, access): ), 'cohorts_url': reverse('cohorts', kwargs={'course_key_string': str(course_key)}), 'upload_cohorts_csv_url': reverse('add_users_to_cohorts', kwargs={'course_id': str(course_key)}), - 'verified_track_cohorting_url': reverse( - 'verified_track_cohorting', kwargs={'course_key_string': str(course_key)} - ), } return section_data @@ -679,9 +675,7 @@ def _section_send_email(course, access): cohorts = [] if is_course_cohorted(course_key): cohorts = get_course_cohorts(course) - course_modes = [] - if not VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(course_key): - course_modes = CourseMode.modes_for_course(course_key, include_expired=True, only_selectable=False) + course_modes = CourseMode.modes_for_course(course_key, include_expired=True, only_selectable=False) email_editor = fragment.content section_data = { 'section_key': 'send_email', diff --git a/lms/static/js/groups/models/verified_track_settings.js b/lms/static/js/groups/models/verified_track_settings.js deleted file mode 100644 index 68a584bd6a..0000000000 --- a/lms/static/js/groups/models/verified_track_settings.js +++ /dev/null @@ -1,12 +0,0 @@ -(function(define) { - 'use strict'; - define(['backbone'], function(Backbone) { - var VerifiedTrackSettingsModel = Backbone.Model.extend({ - defaults: { - enabled: false, - verified_cohort_name: '' - } - }); - return VerifiedTrackSettingsModel; - }); -}).call(this, define || RequireJS.define); diff --git a/lms/static/js/groups/views/cohorts.js b/lms/static/js/groups/views/cohorts.js index f5df88f5dd..279540690e 100644 --- a/lms/static/js/groups/views/cohorts.js +++ b/lms/static/js/groups/views/cohorts.js @@ -1,19 +1,16 @@ (function(define) { 'use strict'; define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/models/cohort', - 'js/groups/models/verified_track_settings', 'js/groups/views/cohort_editor', 'js/groups/views/cohort_form', 'js/groups/views/course_cohort_settings_notification', - 'js/groups/views/verified_track_settings_notification', 'edx-ui-toolkit/js/utils/html-utils', 'js/views/base_dashboard_view', 'js/views/file_uploader', 'js/models/notification', 'js/views/notification', 'string_utils'], function($, _, Backbone, gettext, CohortModel, - VerifiedTrackSettingsModel, - CohortEditorView, CohortFormView, - CourseCohortSettingsNotificationView, - VerifiedTrackSettingsNotificationView, HtmlUtils, BaseDashboardView) { + CohortEditorView, CohortFormView, + CourseCohortSettingsNotificationView, + HtmlUtils, BaseDashboardView) { var hiddenClass = 'hidden', disabledClass = 'is-disabled', enableCohortsSelector = '.cohorts-state'; @@ -52,19 +49,6 @@ cohortsEnabled: this.cohortSettings.get('is_cohorted') })); this.onSync(); - // Don't create this view until the first render is called, as at that point the - // various other models whose state is required to properly view the notification - // will have completed their fetch operations. - if (!this.verifiedTrackSettingsNotificationView) { - var verifiedTrackSettingsModel = new VerifiedTrackSettingsModel(); - verifiedTrackSettingsModel.url = this.context.verifiedTrackCohortingUrl; - verifiedTrackSettingsModel.fetch({ - success: _.bind(this.renderVerifiedTrackSettingsNotificationView, this) - }); - this.verifiedTrackSettingsNotificationView = new VerifiedTrackSettingsNotificationView({ - model: verifiedTrackSettingsModel - }); - } return this; }, @@ -83,14 +67,6 @@ cohortStateMessageNotificationView.render(); }, - renderVerifiedTrackSettingsNotificationView: function() { - if (this.verifiedTrackSettingsNotificationView) { - this.verifiedTrackSettingsNotificationView.validateSettings( - this.getCohortsEnabled(), this.model.models, this.$(enableCohortsSelector) - ); - } - }, - onSync: function(model, response, options) { var selectedCohort = this.lastSelectedCohortId && this.model.get(this.lastSelectedCohortId), hasCohorts = this.model.length > 0, @@ -124,7 +100,6 @@ actionIconClass: 'fa-plus' }); } - this.renderVerifiedTrackSettingsNotificationView(); }, getSelectedCohort: function() { diff --git a/lms/static/js/groups/views/cohorts_dashboard_factory.js b/lms/static/js/groups/views/cohorts_dashboard_factory.js index 02e0a73b07..99c628a9e6 100644 --- a/lms/static/js/groups/views/cohorts_dashboard_factory.js +++ b/lms/static/js/groups/views/cohorts_dashboard_factory.js @@ -26,7 +26,6 @@ cohortSettings: courseCohortSettings, context: { uploadCohortsCsvUrl: $cohortManagementElement.data('upload_cohorts_csv_url'), - verifiedTrackCohortingUrl: $cohortManagementElement.data('verified_track_cohorting_url'), studioGroupConfigurationsUrl: studioGroupConfigurationsUrl, isCcxEnabled: $cohortManagementElement.data('is_ccx_enabled') } diff --git a/lms/static/js/groups/views/verified_track_settings_notification.js b/lms/static/js/groups/views/verified_track_settings_notification.js deleted file mode 100644 index 2dc4e97cac..0000000000 --- a/lms/static/js/groups/views/verified_track_settings_notification.js +++ /dev/null @@ -1,76 +0,0 @@ -(function(define) { - 'use strict'; - define(['jquery', 'underscore', 'backbone', 'gettext', 'edx-ui-toolkit/js/utils/string-utils', - 'js/models/notification', 'js/views/notification'], - function($, _, Backbone, gettext, StringUtils) { - /* global NotificationModel, NotificationView */ - - var VerifiedTrackSettingsNotificationView = Backbone.View.extend({ - - render: function() { - // All rendering is done in validateSettings, which must be called with some additional information. - return this; - }, - - validateSettings: function(isCohorted, cohortCollection, enableCohortsCheckbox) { - if (this.model.get('enabled')) { - var verifiedCohortName = this.model.get('verified_cohort_name'); - if (isCohorted) { - var verifiedCohortExists = false; - $.each(cohortCollection, function(_, cohort) { - if (cohort.get('assignment_type') === 'manual' && - cohort.get('name') === verifiedCohortName) { - verifiedCohortExists = true; - cohort.disableEditingName = true; - } else { - cohort.disableEditingName = false; - } - } - ); - if (verifiedCohortExists) { - this.showNotification({ - type: 'confirmation', - title: StringUtils.interpolate( - gettext("This course uses automatic cohorting for verified track learners. You cannot disable cohorts, and you cannot rename the manual cohort named '{verifiedCohortName}'. To change the configuration for verified track cohorts, contact your edX partner manager."), // eslint-disable-line max-len - {verifiedCohortName: verifiedCohortName} - ) - }); - } else { - this.showNotification({ - type: 'error', - title: StringUtils.interpolate( - gettext("This course has automatic cohorting enabled for verified track learners, but the required cohort does not exist. You must create a manually-assigned cohort named '{verifiedCohortName}' for the feature to work."), // eslint-disable-line max-len - {verifiedCohortName: verifiedCohortName} - ) - }); - } - enableCohortsCheckbox.prop('disabled', true); - } else { - this.showNotification({ - type: 'error', - title: gettext('This course has automatic cohorting enabled for verified track learners, but cohorts are disabled. You must enable cohorts for the feature to work.') // eslint-disable-line max-len - }); - enableCohortsCheckbox.prop('disabled', false); - } - } - }, - - showNotification: function(options) { - if (this.notification) { - this.notification.remove(); - } - this.notification = new NotificationView({ - model: new NotificationModel(options) - }); - - // It's ugly to reach outside to the cohort-management div, but we want this notification - // message to always be visible (as opposed to using the transient notification area defined - // by cohorts.js). - $('.cohort-management').before(this.notification.$el); - - this.notification.render(); - } - }); - return VerifiedTrackSettingsNotificationView; - }); -}).call(this, define || RequireJS.define); diff --git a/lms/static/js/spec/groups/views/cohorts_spec.js b/lms/static/js/spec/groups/views/cohorts_spec.js index fa76052daa..709930814b 100644 --- a/lms/static/js/spec/groups/views/cohorts_spec.js +++ b/lms/static/js/spec/groups/views/cohorts_spec.js @@ -15,13 +15,13 @@ define(['backbone', 'jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers dogLoversInitialCount = 456, unknownUserMessage, invalidEmailMessage, createMockCohort, createMockCohorts, createMockContentGroups, - createMockCohortSettingsJson, createMockVerifiedTrackCohortsJson, flushVerifiedTrackCohortRequests, + createMockCohortSettingsJson, createCohortsView, cohortsView, requests, respondToRefresh, verifyMessage, verifyNoMessage, - verifyDetailedMessage, verifyHeader, verifyVerifiedTrackMessage, verifyVerifiedTrackUIUpdates, + verifyDetailedMessage, verifyHeader, expectCohortAddRequest, getAddModal, selectContentGroup, clearContentGroup, saveFormAndExpectErrors, createMockCohortSettings, MOCK_COHORTED_USER_PARTITION_ID, MOCK_UPLOAD_COHORTS_CSV_URL, MOCK_STUDIO_ADVANCED_SETTINGS_URL, MOCK_STUDIO_GROUP_CONFIGURATIONS_URL, - MOCK_VERIFIED_TRACK_COHORTING_URL, MOCK_MANUAL_ASSIGNMENT, MOCK_RANDOM_ASSIGNMENT; + MOCK_MANUAL_ASSIGNMENT, MOCK_RANDOM_ASSIGNMENT; MOCK_MANUAL_ASSIGNMENT = 'manual'; MOCK_RANDOM_ASSIGNMENT = 'random'; @@ -29,7 +29,6 @@ define(['backbone', 'jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers MOCK_UPLOAD_COHORTS_CSV_URL = 'http://upload-csv-file-url/'; MOCK_STUDIO_ADVANCED_SETTINGS_URL = 'http://studio/settings/advanced'; MOCK_STUDIO_GROUP_CONFIGURATIONS_URL = 'http://studio/group_configurations'; - MOCK_VERIFIED_TRACK_COHORTING_URL = 'http://courses/foo/verified_track_content/settings'; createMockCohort = function(name, id, userCount, groupId, userPartitionId, assignmentType) { return { @@ -75,17 +74,6 @@ define(['backbone', 'jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers ); }; - createMockVerifiedTrackCohortsJson = function(enabled) { - if (enabled) { - return { - enabled: true, - verified_cohort_name: 'Verified Track' - }; - } else { - return {enabled: false}; - } - }; - createCohortsView = function(test, options) { var cohortsJson, cohorts, contentGroups, cohortSettings; options = options || {}; @@ -105,7 +93,6 @@ define(['backbone', 'jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers uploadCohortsCsvUrl: MOCK_UPLOAD_COHORTS_CSV_URL, studioAdvancedSettingsUrl: MOCK_STUDIO_ADVANCED_SETTINGS_URL, studioGroupConfigurationsUrl: MOCK_STUDIO_GROUP_CONFIGURATIONS_URL, - verifiedTrackCohortingUrl: MOCK_VERIFIED_TRACK_COHORTING_URL } }); @@ -114,20 +101,6 @@ define(['backbone', 'jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers cohortsView.$('.cohort-select').val(options.selectCohort.toString()).change(); } - flushVerifiedTrackCohortRequests(options.enableVerifiedTrackCohorting); - }; - - // Flush out all requests to get verified track cohort information. - // The order relative to other requests is not important to encode, - // and for pre-existing test cases, we don't care about these additional requests. - flushVerifiedTrackCohortRequests = function(enableVerifiedTrackCohorting) { - for (var i = requests.length - 1; i >= 0; i--) { - if (requests[i].url === MOCK_VERIFIED_TRACK_COHORTING_URL) { - AjaxHelpers.respondWithJson( - requests, createMockVerifiedTrackCohortsJson(enableVerifiedTrackCohorting), i - ); - } - } }; respondToRefresh = function(catCount, dogCount) { @@ -181,26 +154,6 @@ define(['backbone', 'jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers expect(cohortsView.$('.message').length).toBe(0); }; - verifyVerifiedTrackMessage = function(type, expectedText) { - if (type) { - expect($('.message').length).toBe(1); - expect($('.message-' + type).length).toBe(1); - expect($('.message-title').text()).toContain(expectedText); - } else { - expect($('.message').length).toBe(0); - } - }; - - verifyVerifiedTrackUIUpdates = function(enableCohortsCheckbox, disableCohortNameField) { - expect(cohortsView.$('.cohorts-state').prop('disabled')).toBe(enableCohortsCheckbox); - // Select settings tab - if (disableCohortNameField !== undefined) { - cohortsView.$('.cohort-select').val('1').change(); - cohortsView.$('.tab-settings a').click(); - expect(cohortsView.$('.cohort-name').prop('readonly')).toBe(disableCohortNameField); - } - }; - verifyDetailedMessage = function(expectedTitle, expectedMessageType, expectedDetails, expectedAction) { var numDetails = cohortsView.$('.summary-items').children().length; verifyMessage(expectedTitle, expectedMessageType, expectedAction, true); @@ -341,53 +294,6 @@ define(['backbone', 'jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers }); }); - describe('Verified Track Cohorting Settings View', function() { - it('displays no message if the feature is disabled', function() { - createCohortsView(this); - verifyVerifiedTrackMessage(false); - verifyVerifiedTrackUIUpdates(false, false); - }); - - it('displays a confirmation if the feature is enabled and a verified track cohort exists', function() { - var cohortName = 'Verified Track'; - createCohortsView(this, { - cohorts: [ - { - id: 1, - name: cohortName, - assignment_type: MOCK_MANUAL_ASSIGNMENT, - group_id: 111, - user_partition_id: MOCK_COHORTED_USER_PARTITION_ID - } - ], - enableVerifiedTrackCohorting: true - }); - verifyVerifiedTrackMessage( - 'confirmation', 'automatic cohorting for verified track learners. You cannot disable cohorts' - ); - verifyVerifiedTrackUIUpdates(true, true); - }); - - it('displays an error if no verified track cohort exists', function() { - createCohortsView(this, {enableVerifiedTrackCohorting: true}); - verifyVerifiedTrackMessage( - 'error', 'cohorting enabled for verified track learners, but the required cohort does not exist' - ); - verifyVerifiedTrackUIUpdates(true, false); - }); - - it('displays an error if cohorting is disabled', function() { - createCohortsView(this, { - cohortSettings: createMockCohortSettings(false), - enableVerifiedTrackCohorting: true - }); - verifyVerifiedTrackMessage( - 'error', 'automatic cohorting enabled for verified track learners, but cohorts are disabled' - ); - verifyVerifiedTrackUIUpdates(false); - }); - }); - describe('Course Cohort Settings', function() { it('can enable and disable cohorting', function() { createCohortsView(this, {cohortSettings: createMockCohortSettings(false)}); diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore b/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore index 9321e29f15..4b8d762980 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore +++ b/lms/templates/instructor/instructor_dashboard_2/cohort-form.underscore @@ -24,13 +24,15 @@ <%- gettext('Cohort Name') %> * <%- gettext('(Required Field)')%> - - " - <% } %> - id="cohort-name" placeholder="<%- placeholder_value %>" required="required" type="text"> +
<% if (isDefaultCohort) { %> diff --git a/lms/templates/instructor/instructor_dashboard_2/cohort_management.html b/lms/templates/instructor/instructor_dashboard_2/cohort_management.html index bcdb171c3f..c7d6a67e8c 100644 --- a/lms/templates/instructor/instructor_dashboard_2/cohort_management.html +++ b/lms/templates/instructor/instructor_dashboard_2/cohort_management.html @@ -13,7 +13,6 @@ from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_ data-cohorts_url="${section_data['cohorts_url']}" data-upload_cohorts_csv_url="${section_data['upload_cohorts_csv_url']}" data-course_cohort_settings_url="${section_data['course_cohort_settings_url']}" - data-verified_track_cohorting_url="${section_data['verified_track_cohorting_url']}" data-is_ccx_enabled="${'true' if section_data['ccx_is_enabled'] else 'false'}" > diff --git a/lms/urls.py b/lms/urls.py index 21fb97fba4..e629d85c68 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -49,7 +49,6 @@ from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.user_authn.views.login import redirect_to_lms_login -from openedx.core.djangoapps.verified_track_content import views as verified_track_content_views from openedx.features.enterprise_support.api import enterprise_enabled from common.djangoapps.student import views as student_views from common.djangoapps.util import views as util_views @@ -607,13 +606,6 @@ urlpatterns += [ discussion_views.discussion_topics, name='discussion_topics', ), - re_path( - r'^courses/{}/verified_track_content/settings'.format( - settings.COURSE_KEY_PATTERN, - ), - verified_track_content_views.cohorting_settings, - name='verified_track_cohorting', - ), # LTI endpoints listing re_path( diff --git a/openedx/core/djangoapps/verified_track_content/admin.py b/openedx/core/djangoapps/verified_track_content/admin.py deleted file mode 100644 index 65b124defc..0000000000 --- a/openedx/core/djangoapps/verified_track_content/admin.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -Django admin page for verified track configuration -""" - - -from django.contrib import admin - -from openedx.core.djangoapps.verified_track_content.forms import VerifiedTrackCourseForm -from openedx.core.djangoapps.verified_track_content.models import ( - MigrateVerifiedTrackCohortsSetting, - VerifiedTrackCohortedCourse -) - - -@admin.register(VerifiedTrackCohortedCourse) -class VerifiedTrackCohortedCourseAdmin(admin.ModelAdmin): - """Admin for enabling verified track cohorting. """ - form = VerifiedTrackCourseForm - - -@admin.register(MigrateVerifiedTrackCohortsSetting) -class MigrateVerifiedTrackCohortsSettingAdmin(admin.ModelAdmin): - """Admin for configuring migration settings of verified track cohorting""" diff --git a/openedx/core/djangoapps/verified_track_content/forms.py b/openedx/core/djangoapps/verified_track_content/forms.py deleted file mode 100644 index f5f287f3a0..0000000000 --- a/openedx/core/djangoapps/verified_track_content/forms.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Forms for configuring courses for verified track cohorting -""" - - -from django import forms -from django.utils.translation import gettext as _ -from opaque_keys import InvalidKeyError -from opaque_keys.edx.keys import CourseKey - -from openedx.core.djangoapps.verified_track_content.models import VerifiedTrackCohortedCourse -from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order - - -class VerifiedTrackCourseForm(forms.ModelForm): - """Validate course keys for the VerifiedTrackCohortedCourse model - - The default behavior in Django admin is to: - * Save course keys for courses that do not exist. - * Return a 500 response if the course key format is invalid. - - Using this form ensures that we display a user-friendly - error message instead. - - """ - class Meta: - model = VerifiedTrackCohortedCourse - fields = '__all__' - - def clean_course_key(self): - """Validate the course key. - - Checks that the key format is valid and that - the course exists. If not, displays an error message. - - Arguments: - field_name (str): The name of the field to validate. - - Returns: - CourseKey - - """ - cleaned_id = self.cleaned_data['course_key'] - error_msg = _('COURSE NOT FOUND. Please check that the course ID is valid.') - - try: - course_key = CourseKey.from_string(cleaned_id) - except InvalidKeyError: - raise forms.ValidationError(error_msg) # lint-amnesty, pylint: disable=raise-missing-from - - if not modulestore().has_course(course_key): - raise forms.ValidationError(error_msg) - - return course_key diff --git a/openedx/core/djangoapps/verified_track_content/management/__init__.py b/openedx/core/djangoapps/verified_track_content/management/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/openedx/core/djangoapps/verified_track_content/management/commands/__init__.py b/openedx/core/djangoapps/verified_track_content/management/commands/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/openedx/core/djangoapps/verified_track_content/management/commands/swap_from_auto_track_cohort_pilot.py b/openedx/core/djangoapps/verified_track_content/management/commands/swap_from_auto_track_cohort_pilot.py deleted file mode 100644 index cef6a85aa4..0000000000 --- a/openedx/core/djangoapps/verified_track_content/management/commands/swap_from_auto_track_cohort_pilot.py +++ /dev/null @@ -1,283 +0,0 @@ -"""Management command to migrate a course's xblock's group_access from Verified Track Cohorts to Enrollment Tracks""" - - -from textwrap import dedent - -from django.conf import settings -from django.core.management.base import BaseCommand, CommandError - -from cms.djangoapps.contentstore.course_group_config import GroupConfiguration -from common.djangoapps.course_modes.models import CourseMode -from openedx.core.djangoapps.course_groups.cohorts import CourseCohort -from openedx.core.djangoapps.course_groups.models import CourseUserGroup, CourseUserGroupPartitionGroup -from openedx.core.djangoapps.verified_track_content.models import ( - MigrateVerifiedTrackCohortsSetting, - VerifiedTrackCohortedCourse -) -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.partitions.partitions_service import PartitionService # lint-amnesty, pylint: disable=wrong-import-order - - -class Command(BaseCommand): - """ - Migrates a course's xblock's group_access from Verified Track Cohorts to Enrollment Tracks - """ - help = dedent(__doc__).strip() - - def handle(self, *args, **options): # lint-amnesty, pylint: disable=too-many-statements - - errors = [] - - module_store = modulestore() - - print("Starting Swap from Auto Track Cohort Pilot command") - - verified_track_cohorts_setting = self._latest_settings() - - if not verified_track_cohorts_setting: - raise CommandError("No MigrateVerifiedTrackCohortsSetting found") - - if not verified_track_cohorts_setting.enabled: - raise CommandError("No enabled MigrateVerifiedTrackCohortsSetting found") - - old_course_key = verified_track_cohorts_setting.old_course_key - rerun_course_key = verified_track_cohorts_setting.rerun_course_key - audit_cohort_names = verified_track_cohorts_setting.get_audit_cohort_names() - - # Verify that the MigrateVerifiedTrackCohortsSetting has all required fields - if not old_course_key: - raise CommandError("No old_course_key set for MigrateVerifiedTrackCohortsSetting with ID: '%s'" - % verified_track_cohorts_setting.id) - - if not rerun_course_key: - raise CommandError("No rerun_course_key set for MigrateVerifiedTrackCohortsSetting with ID: '%s'" - % verified_track_cohorts_setting.id) - - if not audit_cohort_names: - raise CommandError("No audit_cohort_names set for MigrateVerifiedTrackCohortsSetting with ID: '%s'" - % verified_track_cohorts_setting.id) - - print("Running for MigrateVerifiedTrackCohortsSetting with old_course_key='%s' and rerun_course_key='%s'" % - (verified_track_cohorts_setting.old_course_key, verified_track_cohorts_setting.rerun_course_key)) - - # Get the CourseUserGroup IDs for the audit course names from the old course - audit_course_user_group_ids = CourseUserGroup.objects.filter( - name__in=audit_cohort_names, - course_id=old_course_key, - group_type=CourseUserGroup.COHORT, - ).values_list('id', flat=True) - - if not audit_course_user_group_ids: - raise CommandError( - "No Audit CourseUserGroup found for course_id='%s' with group_type='%s' for names='%s'" - % (old_course_key, CourseUserGroup.COHORT, audit_cohort_names) - ) - - # Get all of the audit CourseCohorts from the above IDs that are RANDOM - random_audit_course_user_group_ids = CourseCohort.objects.filter( - course_user_group_id__in=audit_course_user_group_ids, - assignment_type=CourseCohort.RANDOM - ).values_list('course_user_group_id', flat=True) - - if not random_audit_course_user_group_ids: - raise CommandError( - "No Audit CourseCohorts found for course_user_group_ids='%s' with assignment_type='%s" - % (audit_course_user_group_ids, CourseCohort.RANDOM) - ) - - # Get the CourseUserGroupPartitionGroup for the above IDs, these contain the partition IDs and group IDs - # that are set for group_access inside of modulestore - random_audit_course_user_group_partition_groups = list(CourseUserGroupPartitionGroup.objects.filter( - course_user_group_id__in=random_audit_course_user_group_ids - )) - - if not random_audit_course_user_group_partition_groups: - raise CommandError( - "No Audit CourseUserGroupPartitionGroup found for course_user_group_ids='%s'" - % random_audit_course_user_group_ids - ) - - # Get the single VerifiedTrackCohortedCourse for the old course - try: - verified_track_cohorted_course = VerifiedTrackCohortedCourse.objects.get(course_key=old_course_key) - except VerifiedTrackCohortedCourse.DoesNotExist: - raise CommandError("No VerifiedTrackCohortedCourse found for course: '%s'" % old_course_key) # lint-amnesty, pylint: disable=raise-missing-from - - if not verified_track_cohorted_course.enabled: - raise CommandError("VerifiedTrackCohortedCourse not enabled for course: '%s'" % old_course_key) - - # Get the single CourseUserGroupPartitionGroup for the verified_track - # based on the verified_track name for the old course - try: - verified_course_user_group = CourseUserGroup.objects.get( - course_id=old_course_key, - group_type=CourseUserGroup.COHORT, - name=verified_track_cohorted_course.verified_cohort_name - ) - except CourseUserGroup.DoesNotExist: - raise CommandError( # lint-amnesty, pylint: disable=raise-missing-from - "No Verified CourseUserGroup found for course_id='%s' with group_type='%s' for names='%s'" - % (old_course_key, CourseUserGroup.COHORT, verified_track_cohorted_course.verified_cohort_name) - ) - - try: - verified_course_user_group_partition_group = CourseUserGroupPartitionGroup.objects.get( - course_user_group_id=verified_course_user_group.id - ) - except CourseUserGroupPartitionGroup.DoesNotExist: - raise CommandError( # lint-amnesty, pylint: disable=raise-missing-from - "No Verified CourseUserGroupPartitionGroup found for course_user_group_ids='%s'" - % random_audit_course_user_group_ids - ) - - # Verify the enrollment track CourseModes exist for the new course - try: - CourseMode.objects.get( - course_id=rerun_course_key, - mode_slug=CourseMode.AUDIT - ) - except CourseMode.DoesNotExist: - raise CommandError("Audit CourseMode is not defined for course: '%s'" % rerun_course_key) # lint-amnesty, pylint: disable=raise-missing-from - - try: - CourseMode.objects.get( - course_id=rerun_course_key, - mode_slug=CourseMode.VERIFIED - ) - except CourseMode.DoesNotExist: - raise CommandError("Verified CourseMode is not defined for course: '%s'" % rerun_course_key) # lint-amnesty, pylint: disable=raise-missing-from - - items = module_store.get_items(rerun_course_key) - if not items: - raise CommandError("Items for Course with key '%s' not found." % rerun_course_key) - - items_to_update = [] - - all_cohorted_track_group_ids = set() - for audit_course_user_group_partition_group in random_audit_course_user_group_partition_groups: - all_cohorted_track_group_ids.add(audit_course_user_group_partition_group.group_id) - all_cohorted_track_group_ids.add(verified_course_user_group_partition_group.group_id) - - for item in items: - # Verify that there exists group access for this xblock, otherwise skip these checks - if item.group_access: - set_audit_enrollment_track = False - set_verified_enrollment_track = False - - # Check the partition and group IDs for the audit course groups, if they exist in - # the xblock's access settings then set the audit track flag to true - for audit_course_user_group_partition_group in random_audit_course_user_group_partition_groups: - audit_partition_group_access = item.group_access.get( - audit_course_user_group_partition_group.partition_id, - None - ) - if (audit_partition_group_access - and audit_course_user_group_partition_group.group_id in audit_partition_group_access): - print("Queueing XBlock at location: '%s' for Audit Content Group update " % item.location) - set_audit_enrollment_track = True - - # Check the partition and group IDs for the verified course group, if it exists in - # the xblock's access settings then set the verified track flag to true - verified_partition_group_access = item.group_access.get( - verified_course_user_group_partition_group.partition_id, - None - ) - if verified_partition_group_access: - non_verified_track_access_groups = (set(verified_partition_group_access) - - all_cohorted_track_group_ids) - # If the item has group_access that is not the - # verified or audit group IDs then raise an error - # This only needs to be checked for this partition_group once - if non_verified_track_access_groups: - errors.append( - "Non audit/verified cohorted content group set for xblock, location '%s' with IDs '%s'" - % (item.location, non_verified_track_access_groups) - ) - if verified_course_user_group_partition_group.group_id in verified_partition_group_access: - print("Queueing XBlock at location: '%s' for Verified Content Group update " % item.location) - set_verified_enrollment_track = True - - # Add the enrollment track ids to a group access array - enrollment_track_group_access = [] - if set_audit_enrollment_track: - enrollment_track_group_access.append(settings.COURSE_ENROLLMENT_MODES['audit']['id']) - if set_verified_enrollment_track: - enrollment_track_group_access.append(settings.COURSE_ENROLLMENT_MODES['verified']['id']) - - # If there are no errors, and either the audit track, or verified - # track needed an update, set the access, update and publish - if set_verified_enrollment_track or set_audit_enrollment_track: - # Sets whether or not an xblock has changes - has_changes = module_store.has_changes(item) - - # Check that the xblock does not have changes and add it to be updated, otherwise add an error - if not has_changes: - item.group_access = {ENROLLMENT_TRACK_PARTITION_ID: enrollment_track_group_access} - items_to_update.append(item) - else: - errors.append("XBlock '%s' with location '%s' needs access changes, but is a draft" - % (item.display_name, item.location)) - - partitions_to_delete = random_audit_course_user_group_partition_groups - partitions_to_delete.append(verified_course_user_group_partition_group) - - # If there are no errors iterate over and update all of the items that had the access changed - if not errors: - for item in items_to_update: - module_store.update_item(item, ModuleStoreEnum.UserID.mgmt_command) - module_store.publish(item.location, ModuleStoreEnum.UserID.mgmt_command) - print("Updated and published XBlock at location: '%s'" % item.location) - - # Check if we should delete any partition groups if there are no errors. - # If there are errors, none of the xblock items will have been updated, - # so this section will throw errors for each partition in use - if partitions_to_delete and not errors: # lint-amnesty, pylint: disable=too-many-nested-blocks - partition_service = PartitionService(rerun_course_key) - course = partition_service.get_course() - for partition_to_delete in partitions_to_delete: - # Get the user partition, and the index of that partition in the course - partition = partition_service.get_user_partition(partition_to_delete.partition_id) - if partition: - partition_index = course.user_partitions.index(partition) - group_id = int(partition_to_delete.group_id) - - # Sanity check to verify that all of the groups being deleted are empty, - # since they should have been converted to use enrollment tracks instead. - # Taken from contentstore/views/course.py.remove_content_or_experiment_group - usages = GroupConfiguration.get_partitions_usage_info(module_store, course) - used = group_id in usages[partition.id] - if used: - errors.append("Content group '%s' is in use and cannot be deleted." - % partition_to_delete.group_id) - - # If there are not errors, proceed to update the course and user_partitions - if not errors: - # Remove the groups that match the group ID of the partition to be deleted - # Else if there are no match groups left, remove the user partition - matching_groups = [group for group in partition.groups if group.id == group_id] - if matching_groups: - group_index = partition.groups.index(matching_groups[0]) - partition.groups.pop(group_index) - # Update the course user partition with the updated groups - if partition.groups: - course.user_partitions[partition_index] = partition - else: - course.user_partitions.pop(partition_index) - module_store.update_item(course, ModuleStoreEnum.UserID.mgmt_command) - - # If there are any errors, join them together and raise the CommandError - if errors: - raise CommandError( - ("Error for MigrateVerifiedTrackCohortsSetting with ID='%s'\n" % verified_track_cohorts_setting.id) + - "\t\n".join(errors) - ) - - print("Finished for MigrateVerifiedTrackCohortsSetting with ID='%s" % verified_track_cohorts_setting.id) - - def _latest_settings(self): - """ - Return the latest version of the MigrateVerifiedTrackCohortsSetting - """ - return MigrateVerifiedTrackCohortsSetting.current() diff --git a/openedx/core/djangoapps/verified_track_content/migrations/0001_initial.py b/openedx/core/djangoapps/verified_track_content/migrations/0001_initial.py deleted file mode 100644 index ec851e0273..0000000000 --- a/openedx/core/djangoapps/verified_track_content/migrations/0001_initial.py +++ /dev/null @@ -1,19 +0,0 @@ -from django.db import migrations, models -from opaque_keys.edx.django.models import CourseKeyField - - -class Migration(migrations.Migration): - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='VerifiedTrackCohortedCourse', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('course_key', CourseKeyField(help_text='The course key for the course we would like to be auto-cohorted.', unique=True, max_length=255, db_index=True)), - ('enabled', models.BooleanField()), - ], - ), - ] diff --git a/openedx/core/djangoapps/verified_track_content/migrations/0002_verifiedtrackcohortedcourse_verified_cohort_name.py b/openedx/core/djangoapps/verified_track_content/migrations/0002_verifiedtrackcohortedcourse_verified_cohort_name.py deleted file mode 100644 index 296cce508d..0000000000 --- a/openedx/core/djangoapps/verified_track_content/migrations/0002_verifiedtrackcohortedcourse_verified_cohort_name.py +++ /dev/null @@ -1,16 +0,0 @@ -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('verified_track_content', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='verifiedtrackcohortedcourse', - name='verified_cohort_name', - field=models.CharField(default='Verified Learners', max_length=100), - ), - ] diff --git a/openedx/core/djangoapps/verified_track_content/migrations/0003_migrateverifiedtrackcohortssetting.py b/openedx/core/djangoapps/verified_track_content/migrations/0003_migrateverifiedtrackcohortssetting.py deleted file mode 100644 index 4a219c378a..0000000000 --- a/openedx/core/djangoapps/verified_track_content/migrations/0003_migrateverifiedtrackcohortssetting.py +++ /dev/null @@ -1,27 +0,0 @@ -from django.db import migrations, models -import django.db.models.deletion -from django.conf import settings -from opaque_keys.edx.django.models import CourseKeyField - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('verified_track_content', '0002_verifiedtrackcohortedcourse_verified_cohort_name'), - ] - - operations = [ - migrations.CreateModel( - name='MigrateVerifiedTrackCohortsSetting', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')), - ('enabled', models.BooleanField(default=False, verbose_name='Enabled')), - ('old_course_key', CourseKeyField(help_text='Course key for which to migrate verified track cohorts from', max_length=255)), - ('rerun_course_key', CourseKeyField(help_text='Course key for which to migrate verified track cohorts to enrollment tracks to', max_length=255)), - ('audit_cohort_names', models.TextField(help_text='Comma-separated list of audit cohort names')), - ('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')), - ], - ), - ] diff --git a/openedx/core/djangoapps/verified_track_content/migrations/__init__.py b/openedx/core/djangoapps/verified_track_content/migrations/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/openedx/core/djangoapps/verified_track_content/models.py b/openedx/core/djangoapps/verified_track_content/models.py deleted file mode 100644 index 3d1101fc6b..0000000000 --- a/openedx/core/djangoapps/verified_track_content/models.py +++ /dev/null @@ -1,185 +0,0 @@ -""" -Models for verified track selections. -""" - - -import logging - -from config_models.models import ConfigurationModel -from django.db import models -from django.db.models.signals import post_save, pre_save -from django.dispatch import receiver - -from django.utils.translation import gettext_lazy -from edx_django_utils.cache import RequestCache -from opaque_keys.edx.django.models import CourseKeyField - -from openedx.core.djangoapps.course_groups.cohorts import ( - CourseCohort, - get_course_cohorts, - get_random_cohort, - is_course_cohorted -) -from openedx.core.djangoapps.verified_track_content.tasks import sync_cohort_with_mode -from openedx.core.lib.cache_utils import request_cached -from openedx.core.lib.courses import get_course_by_id -from common.djangoapps.student.models import CourseEnrollment - -log = logging.getLogger(__name__) - -DEFAULT_VERIFIED_COHORT_NAME = "Verified Learners" - - -@receiver(post_save, sender=CourseEnrollment) -def move_to_verified_cohort(sender, instance, **kwargs): # pylint: disable=unused-argument - """ - If the learner has changed modes, update assigned cohort iff the course is using - the Automatic Verified Track Cohorting MVP feature. - """ - course_key = instance.course_id - verified_cohort_enabled = VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(course_key) - verified_cohort_name = VerifiedTrackCohortedCourse.verified_cohort_name_for_course(course_key) - - if verified_cohort_enabled and (instance.mode != instance._old_mode): # pylint: disable=protected-access - if not is_course_cohorted(course_key): - log.error("Automatic verified cohorting enabled for course '%s', but course is not cohorted.", course_key) - else: - course = get_course_by_id(course_key) - existing_manual_cohorts = get_course_cohorts(course, assignment_type=CourseCohort.MANUAL) - if any(cohort.name == verified_cohort_name for cohort in existing_manual_cohorts): - # Get a random cohort to use as the default cohort (for audit learners). - # Note that calling this method will create a "Default Group" random cohort if no random - # cohort yet exist. - random_cohort = get_random_cohort(course_key) - args = { - 'course_id': str(course_key), - 'user_id': instance.user.id, - 'verified_cohort_name': verified_cohort_name, - 'default_cohort_name': random_cohort.name - } - log.info( - "Queuing automatic cohorting for user '%s' in course '%s' " - "due to change in enrollment mode from '%s' to '%s'.", - instance.user.id, course_key, instance._old_mode, instance.mode # pylint: disable=protected-access - ) - - # Do the update with a 3-second delay in hopes that the CourseEnrollment transaction has been - # completed before the celery task runs. We want a reasonably short delay in case the learner - # immediately goes to the courseware. - sync_cohort_with_mode.apply_async(kwargs=args, countdown=3) - - # In case the transaction actually was not committed before the celery task runs, - # run it again after 5 minutes. If the first completed successfully, this task will be a no-op. - sync_cohort_with_mode.apply_async(kwargs=args, countdown=300) - else: - log.error( - "Automatic verified cohorting enabled for course '%s', " - "but verified cohort named '%s' does not exist.", - course_key, - verified_cohort_name, - ) - - -@receiver(pre_save, sender=CourseEnrollment) -def pre_save_callback(sender, instance, **kwargs): # pylint: disable=unused-argument - """ - Extend to store previous mode. - """ - try: - old_instance = sender.objects.get(pk=instance.pk) - instance._old_mode = old_instance.mode # pylint: disable=protected-access - except CourseEnrollment.DoesNotExist: - instance._old_mode = None # pylint: disable=protected-access - - -class VerifiedTrackCohortedCourse(models.Model): - """ - Tracks which courses have verified track auto-cohorting enabled. - - .. no_pii: - """ - course_key = CourseKeyField( - max_length=255, db_index=True, unique=True, - help_text=gettext_lazy("The course key for the course we would like to be auto-cohorted.") - ) - - verified_cohort_name = models.CharField(max_length=100, default=DEFAULT_VERIFIED_COHORT_NAME) - - enabled = models.BooleanField() - - CACHE_NAMESPACE = "verified_track_content.VerifiedTrackCohortedCourse.cache." - - def __str__(self): - return f"Course: {str(self.course_key)}, enabled: {self.enabled}" - - @classmethod - def verified_cohort_name_for_course(cls, course_key): - """ - Returns the given cohort name for the specific course. - - Args: - course_key (CourseKey): a course key representing the course we want the verified cohort name for - - Returns: - The cohort name if the course key has one associated to it. None otherwise. - - """ - try: - config = cls.objects.get(course_key=course_key) - return config.verified_cohort_name - except cls.DoesNotExist: - return None - - @classmethod - @request_cached(namespace=CACHE_NAMESPACE) - def is_verified_track_cohort_enabled(cls, course_key): - """ - Checks whether or not verified track cohort is enabled for the given course. - - Args: - course_key (CourseKey): a course key representing the course we want to check - - Returns: - True if the course has verified track cohorts is enabled - False if not - """ - try: - return cls.objects.get(course_key=course_key).enabled - except cls.DoesNotExist: - return False - - -@receiver(models.signals.post_save, sender=VerifiedTrackCohortedCourse) -@receiver(models.signals.post_delete, sender=VerifiedTrackCohortedCourse) -def invalidate_verified_track_cache(sender, **kwargs): # pylint: disable=unused-argument - """Invalidate the cache of VerifiedTrackCohortedCourse. """ - RequestCache(namespace=VerifiedTrackCohortedCourse.CACHE_NAMESPACE).clear() - - -class MigrateVerifiedTrackCohortsSetting(ConfigurationModel): - """ - Configuration for the swap_from_auto_track_cohorts management command. - - .. no_pii: - """ - class Meta: - app_label = "verified_track_content" - - old_course_key = CourseKeyField( - max_length=255, - blank=False, - help_text="Course key for which to migrate verified track cohorts from" - ) - rerun_course_key = CourseKeyField( - max_length=255, - blank=False, - help_text="Course key for which to migrate verified track cohorts to enrollment tracks to" - ) - audit_cohort_names = models.TextField( - help_text="Comma-separated list of audit cohort names" - ) - - @classmethod - def get_audit_cohort_names(cls): - """Get the list of audit cohort names for the course""" - return [cohort_name for cohort_name in cls.current().audit_cohort_names.split(",") if cohort_name] diff --git a/openedx/core/djangoapps/verified_track_content/partition_scheme.py b/openedx/core/djangoapps/verified_track_content/partition_scheme.py index 2f96370d5e..e0472ce10e 100644 --- a/openedx/core/djangoapps/verified_track_content/partition_scheme.py +++ b/openedx/core/djangoapps/verified_track_content/partition_scheme.py @@ -14,7 +14,6 @@ from lms.djangoapps.courseware.masquerade import ( get_masquerading_user_group, is_masquerading_as_specific_student ) -from openedx.core.djangoapps.verified_track_content.models import VerifiedTrackCohortedCourse from common.djangoapps.student.models import CourseEnrollment from xmodule.partitions.partitions import Group, UserPartition # lint-amnesty, pylint: disable=wrong-import-order @@ -38,15 +37,9 @@ class EnrollmentTrackUserPartition(UserPartition): Return the groups (based on CourseModes) for the course associated with this EnrollmentTrackUserPartition instance. Note that only groups based on selectable CourseModes are returned (which means that Credit will never be returned). - - If a course is using the Verified Track Cohorting pilot feature, this method - returns an empty array regardless of registered CourseModes. """ course_key = CourseKey.from_string(self.parameters["course_id"]) - if is_course_using_cohort_instead(course_key): - return [] - return [ Group(ENROLLMENT_GROUP_IDS[mode.slug]["id"], str(mode.name)) for mode in CourseMode.modes_for_course(course_key, include_expired=True) @@ -66,13 +59,7 @@ class EnrollmentTrackPartitionScheme: Returns the Group from the specified user partition to which the user is assigned, via enrollment mode. If a user is in a Credit mode, the Verified or Professional mode for the course is returned instead. - - If a course is using the Verified Track Cohorting pilot feature, this method - returns None regardless of the user's enrollment mode. """ - if is_course_using_cohort_instead(course_key): - return None - # First, check if we have to deal with masquerading. # If the current user is masquerading as a specific student, use the # same logic as normal to return that student's group. If the current @@ -124,11 +111,3 @@ class EnrollmentTrackPartitionScheme: parameters, active ) - - -def is_course_using_cohort_instead(course_key): - """ - Returns whether the given course_context is using verified-track cohorts - and therefore shouldn't use a track-based partition. - """ - return VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(course_key) diff --git a/openedx/core/djangoapps/verified_track_content/tasks.py b/openedx/core/djangoapps/verified_track_content/tasks.py deleted file mode 100644 index cc54407f57..0000000000 --- a/openedx/core/djangoapps/verified_track_content/tasks.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Celery task for Automatic Verifed Track Cohorting MVP feature. -""" - - -from celery import shared_task -from celery.utils.log import get_task_logger -from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user -from edx_django_utils.monitoring import set_code_owner_attribute -from opaque_keys.edx.keys import CourseKey - -from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort, get_cohort, get_cohort_by_name -from common.djangoapps.student.models import CourseEnrollment, CourseMode - -LOGGER = get_task_logger(__name__) - - -@shared_task(bind=True, default_retry_delay=60, max_retries=2) -@set_code_owner_attribute -def sync_cohort_with_mode(self, course_id, user_id, verified_cohort_name, default_cohort_name): - """ - If the learner's mode does not match their assigned cohort, move the learner into the correct cohort. - It is assumed that this task is only initiated for courses that are using the - Automatic Verified Track Cohorting MVP feature. It is also assumed that before - initiating this task, verification has been done to ensure that the course is - cohorted and has an appropriately named "verified" cohort. - """ - course_key = CourseKey.from_string(course_id) - user = User.objects.get(id=user_id) - try: - enrollment = CourseEnrollment.get_enrollment(user, course_key) - # Note that this will enroll the user in the default cohort on initial enrollment. - # That's good because it will force creation of the default cohort if necessary. - current_cohort = get_cohort(user, course_key) - - verified_cohort = get_cohort_by_name(course_key, verified_cohort_name) - - acceptable_modes = {CourseMode.VERIFIED, CourseMode.CREDIT_MODE} - if enrollment.mode in acceptable_modes and (current_cohort.id != verified_cohort.id): - LOGGER.info( - "MOVING_TO_VERIFIED: Moving user '%s' to the verified cohort '%s' for course '%s'", - user.id, verified_cohort.name, course_id - ) - add_user_to_cohort(verified_cohort, user.username) - elif enrollment.mode not in acceptable_modes and current_cohort.id == verified_cohort.id: - default_cohort = get_cohort_by_name(course_key, default_cohort_name) - LOGGER.info( - "MOVING_TO_DEFAULT: Moving user '%s' to the default cohort '%s' for course '%s'", - user.id, default_cohort.name, course_id - ) - add_user_to_cohort(default_cohort, user.username) - else: - LOGGER.info( - "NO_ACTION_NECESSARY: No action necessary for user '%s' in course '%s' and enrollment mode '%s'. " - "The user is already in cohort '%s'.", - user.id, course_id, enrollment.mode, current_cohort.name - ) - except Exception as exc: - LOGGER.warning( - "SYNC_COHORT_WITH_MODE_RETRY: Exception encountered for course '%s' and user '%s': %s", - course_id, user.id, str(exc) - ) - raise self.retry(exc=exc) diff --git a/openedx/core/djangoapps/verified_track_content/views.py b/openedx/core/djangoapps/verified_track_content/views.py deleted file mode 100644 index 20d7196d87..0000000000 --- a/openedx/core/djangoapps/verified_track_content/views.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -View methods for verified track content. -""" - - -from django.contrib.auth.decorators import login_required -from opaque_keys.edx.keys import CourseKey - -from lms.djangoapps.courseware.courses import get_course_with_access -from openedx.core.djangoapps.verified_track_content.models import VerifiedTrackCohortedCourse -from common.djangoapps.util.json_request import JsonResponse, expect_json - - -@expect_json -@login_required -def cohorting_settings(request, course_key_string): - """ - The handler for verified track cohorting requests. - This will raise 404 if user is not staff. - - Returns a JSON representation of whether or not the course has verified track cohorting enabled. - The "verified_cohort_name" field will only be present if "enabled" is True. - - Example: - >>> example = { - >>> "enabled": True, - >>> "verified_cohort_name" : "Micromasters" - >>> } - """ - course_key = CourseKey.from_string(course_key_string) - get_course_with_access(request.user, 'staff', course_key) - - settings = {} - verified_track_cohort_enabled = VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(course_key) - settings['enabled'] = verified_track_cohort_enabled - if verified_track_cohort_enabled: - settings['verified_cohort_name'] = VerifiedTrackCohortedCourse.verified_cohort_name_for_course(course_key) - - return JsonResponse(settings)