feat: removing the demographics application stage 2 (#35186)

* removing the application folder
* removing references in all other files

FIXES: APER-3560
This commit is contained in:
Deborah Kaplan
2024-07-26 11:13:35 -04:00
committed by GitHub
parent e9e4a3d041
commit 089b34a6bf
24 changed files with 6 additions and 316 deletions

View File

@@ -18,7 +18,7 @@ jobs:
- module-name: lms-2
path: "--django-settings-module=lms.envs.test lms/djangoapps/gating/ lms/djangoapps/grades/ lms/djangoapps/instructor/ lms/djangoapps/instructor_analytics/ lms/djangoapps/discussion/ lms/djangoapps/edxnotes/ lms/djangoapps/email_marketing/ lms/djangoapps/experiments/ lms/djangoapps/instructor_task/ lms/djangoapps/learner_dashboard/ lms/djangoapps/learner_home/ lms/djangoapps/lms_initialization/ lms/djangoapps/lms_xblock/ lms/djangoapps/lti_provider/ lms/djangoapps/mailing/ lms/djangoapps/mobile_api/ lms/djangoapps/monitoring/ lms/djangoapps/ora_staff_grader/ lms/djangoapps/program_enrollments/ lms/djangoapps/rss_proxy lms/djangoapps/static_template_view/ lms/djangoapps/staticbook/ lms/djangoapps/support/ lms/djangoapps/survey/ lms/djangoapps/teams/ lms/djangoapps/tests/ lms/djangoapps/user_tours/ lms/djangoapps/verify_student/ lms/djangoapps/mfe_config_api/ lms/envs/ lms/lib/ lms/tests.py"
- module-name: openedx-1
path: "--django-settings-module=lms.envs.test openedx/core/types/ openedx/core/djangoapps/ace_common/ openedx/core/djangoapps/agreements/ openedx/core/djangoapps/api_admin/ openedx/core/djangoapps/auth_exchange/ openedx/core/djangoapps/bookmarks/ openedx/core/djangoapps/cache_toolbox/ openedx/core/djangoapps/catalog/ openedx/core/djangoapps/ccxcon/ openedx/core/djangoapps/commerce/ openedx/core/djangoapps/common_initialization/ openedx/core/djangoapps/common_views/ openedx/core/djangoapps/config_model_utils/ openedx/core/djangoapps/content/ openedx/core/djangoapps/content_libraries/ openedx/core/djangoapps/content_staging/ openedx/core/djangoapps/contentserver/ openedx/core/djangoapps/cookie_metadata/ openedx/core/djangoapps/cors_csrf/ openedx/core/djangoapps/course_apps/ openedx/core/djangoapps/course_date_signals/ openedx/core/djangoapps/course_groups/ openedx/core/djangoapps/courseware_api/ openedx/core/djangoapps/crawlers/ openedx/core/djangoapps/credentials/ openedx/core/djangoapps/credit/ openedx/core/djangoapps/dark_lang/ openedx/core/djangoapps/debug/ openedx/core/djangoapps/demographics/ openedx/core/djangoapps/discussions/ openedx/core/djangoapps/django_comment_common/ openedx/core/djangoapps/embargo/ openedx/core/djangoapps/enrollments/ openedx/core/djangoapps/external_user_ids/ openedx/core/djangoapps/zendesk_proxy/ openedx/core/djangolib/ openedx/core/lib/ openedx/core/tests/ openedx/core/djangoapps/course_live/"
path: "--django-settings-module=lms.envs.test openedx/core/types/ openedx/core/djangoapps/ace_common/ openedx/core/djangoapps/agreements/ openedx/core/djangoapps/api_admin/ openedx/core/djangoapps/auth_exchange/ openedx/core/djangoapps/bookmarks/ openedx/core/djangoapps/cache_toolbox/ openedx/core/djangoapps/catalog/ openedx/core/djangoapps/ccxcon/ openedx/core/djangoapps/commerce/ openedx/core/djangoapps/common_initialization/ openedx/core/djangoapps/common_views/ openedx/core/djangoapps/config_model_utils/ openedx/core/djangoapps/content/ openedx/core/djangoapps/content_libraries/ openedx/core/djangoapps/content_staging/ openedx/core/djangoapps/contentserver/ openedx/core/djangoapps/cookie_metadata/ openedx/core/djangoapps/cors_csrf/ openedx/core/djangoapps/course_apps/ openedx/core/djangoapps/course_date_signals/ openedx/core/djangoapps/course_groups/ openedx/core/djangoapps/courseware_api/ openedx/core/djangoapps/crawlers/ openedx/core/djangoapps/credentials/ openedx/core/djangoapps/credit/ openedx/core/djangoapps/dark_lang/ openedx/core/djangoapps/debug/ openedx/core/djangoapps/discussions/ openedx/core/djangoapps/django_comment_common/ openedx/core/djangoapps/embargo/ openedx/core/djangoapps/enrollments/ openedx/core/djangoapps/external_user_ids/ openedx/core/djangoapps/zendesk_proxy/ openedx/core/djangolib/ openedx/core/lib/ openedx/core/tests/ openedx/core/djangoapps/course_live/"
- module-name: openedx-2
path: "--django-settings-module=lms.envs.test openedx/core/djangoapps/geoinfo/ openedx/core/djangoapps/header_control/ openedx/core/djangoapps/heartbeat/ openedx/core/djangoapps/lang_pref/ openedx/core/djangoapps/models/ openedx/core/djangoapps/monkey_patch/ openedx/core/djangoapps/oauth_dispatch/ openedx/core/djangoapps/olx_rest_api/ openedx/core/djangoapps/password_policy/ openedx/core/djangoapps/plugin_api/ openedx/core/djangoapps/plugins/ openedx/core/djangoapps/profile_images/ openedx/core/djangoapps/programs/ openedx/core/djangoapps/safe_sessions/ openedx/core/djangoapps/schedules/ openedx/core/djangoapps/service_status/ openedx/core/djangoapps/session_inactivity_timeout/ openedx/core/djangoapps/signals/ openedx/core/djangoapps/site_configuration/ openedx/core/djangoapps/system_wide_roles/ openedx/core/djangoapps/theming/ openedx/core/djangoapps/user_api/ openedx/core/djangoapps/user_authn/ openedx/core/djangoapps/util/ openedx/core/djangoapps/verified_track_content/ openedx/core/djangoapps/video_config/ openedx/core/djangoapps/video_pipeline/ openedx/core/djangoapps/waffle_utils/ openedx/core/djangoapps/xblock/ openedx/core/djangoapps/xmodule_django/ openedx/core/tests/ openedx/features/ openedx/testing/ openedx/tests/ openedx/core/djangoapps/learner_pathway/ openedx/core/djangoapps/notifications/ openedx/core/djangoapps/staticfiles/ openedx/core/djangoapps/content_tagging/"
- module-name: common

View File

@@ -106,7 +106,6 @@
"openedx/core/djangoapps/course_live/",
"openedx/core/djangoapps/dark_lang/",
"openedx/core/djangoapps/debug/",
"openedx/core/djangoapps/demographics/",
"openedx/core/djangoapps/discussions/",
"openedx/core/djangoapps/django_comment_common/",
"openedx/core/djangoapps/embargo/",
@@ -187,7 +186,6 @@
"openedx/core/djangoapps/credit/",
"openedx/core/djangoapps/dark_lang/",
"openedx/core/djangoapps/debug/",
"openedx/core/djangoapps/demographics/",
"openedx/core/djangoapps/discussions/",
"openedx/core/djangoapps/django_comment_common/",
"openedx/core/djangoapps/embargo/",

View File

@@ -3350,9 +3350,6 @@ INSTALLED_APPS = [
# Management of external user ids
'openedx.core.djangoapps.external_user_ids',
# Provides api for Demographics support
'openedx.core.djangoapps.demographics',
# Management of per-user schedules
'openedx.core.djangoapps.schedules',

View File

@@ -129,9 +129,6 @@ urlpatterns = [
),
),
# Demographics API RESTful endpoints
path('api/demographics/', include('openedx.core.djangoapps.demographics.rest_api.urls')),
# Courseware search endpoints
path('search/', include('search.urls')),

View File

@@ -1,19 +0,0 @@
Status: Active
Responsibilities
================
The Demographics app is an application to support the Demographics feature set
and IDA. It serves as the access point for demographics related status.
Direction: Decompose
===============
This app may be removed in the future as the Demographics feature set expands
to a larger set of users. It is not recommended that new features are added
here at this time.
Glossary
========
IDA: Independently Deployable Application
More Documentation
==================

View File

@@ -1,3 +0,0 @@
"""
Django admin page for demographics
"""

View File

@@ -1,25 +0,0 @@
"""
Python API for Demographics Status
"""
from openedx.core.djangoapps.programs.api import is_user_enrolled_in_program_type
from openedx.features.enterprise_support.utils import is_enterprise_learner
def show_user_demographics(user, enrollments=None, entitlements=None):
"""
Check if the user should be shown demographics collection fields. Currently limited
to MicroBachlors Programs' learners who aren't part of an enterprise.
"""
is_user_in_microbachelors_program = is_user_enrolled_in_program_type(
user, "microbachelors", enrollments=enrollments, entitlements=entitlements
)
return is_user_in_microbachelors_program and not is_enterprise_learner(user)
def show_call_to_action_for_user(user):
"""
Utility method to determine if a user should be shown the Demographics call to
action.
"""
return False

View File

@@ -1,22 +0,0 @@
Django Application to Support Demographics Features
---------------------------------------------------
Status
======
Accepted
Context
=======
To support demographics features and the IDA we need to be able to access the
current state of a User from the LMS (i.e. Program Enrollments, Enterprise status).
Decisions
=========
* To meet this need we are creating the Demographics Django Application in the
Open edX core. This application will contain utilities and APIs that will support
the Demographics feature set until they are replaced with other more general APIs
or no longer needed.

View File

@@ -1,55 +0,0 @@
# Generated by Django 2.2.14 on 2020-07-23 19:25
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import model_utils.fields
import simple_history.models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='UserDemographics',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('show_call_to_action', models.BooleanField(default=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'user demographic',
'verbose_name_plural': 'user demographic',
},
),
migrations.CreateModel(
name='HistoricalUserDemographics',
fields=[
('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')),
('show_call_to_action', models.BooleanField(default=True)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField()),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('user', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical user demographic',
'get_latest_by': 'history_date',
'ordering': ('-history_date', '-history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]

View File

@@ -1,48 +0,0 @@
import logging
from django.conf import settings
from django.db import migrations, models
log = logging.getLogger(__name__)
def _clean_duplicate_entries(apps, schema_editor):
"""
This method finds all the duplicate user entries in the UserDemographics model
and then removes all duplicate entries except for the most recently modified one.
"""
demographics_model = apps.get_model('demographics', 'UserDemographics')
# Retrieve a list of all users that have more than one entry.
duplicate_users = (
demographics_model.objects.values(
'user'
).annotate(models.Count('id')).values('user').order_by().filter(id__count__gt=1)
)
# Get a QuerySet of all the UserDemographics instances for the duplicates
# sorted by user and modified in descending order.
user_demographic_dupes = demographics_model.objects.filter(user__in=duplicate_users).order_by('user', '-modified')
# Go through the QuerySet and only keep the most recent instance.
existing_user_ids = set()
for demographic in user_demographic_dupes:
if demographic.user_id in existing_user_ids:
log.info('UserDemographics {user} -- {modified}'.format(
user=demographic.user_id, modified=demographic.modified
))
demographic.delete()
else:
log.info('UserDemographics Duplicate User Delete {user} -- {modified}'.format(
user=demographic.user_id, modified=demographic.modified
))
existing_user_ids.add(demographic.user_id)
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('demographics', '0001_initial'),
]
operations = [
migrations.RunPython(_clean_duplicate_entries, migrations.RunPython.noop),
]

View File

@@ -1,20 +0,0 @@
# Generated by Django 2.2.15 on 2020-08-27 19:49
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('demographics', '0002_clean_duplicate_entries'),
]
operations = [
migrations.AlterField(
model_name='userdemographics',
name='user',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View File

@@ -1,17 +0,0 @@
# Generated by Django 3.2.20 on 2023-08-08 09:44
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('demographics', '0003_auto_20200827_1949'),
]
operations = [
migrations.AlterModelOptions(
name='historicaluserdemographics',
options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical user demographic', 'verbose_name_plural': 'historical user demographic'},
),
]

View File

@@ -1,23 +0,0 @@
# Generated by Django 4.2.14 on 2024-07-25 15:19
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('demographics', '0004_alter_historicaluserdemographics_options'),
]
operations = [
migrations.RemoveField(
model_name='userdemographics',
name='user',
),
migrations.DeleteModel(
name='HistoricalUserDemographics',
),
migrations.DeleteModel(
name='UserDemographics',
),
]

View File

@@ -1,3 +0,0 @@
"""
Demographics models
"""

View File

@@ -1,12 +0,0 @@
"""
Demographics API URLs.
"""
from django.urls import path, include
from .v1 import urls as v1_urls
app_name = 'openedx.core.djangoapps.demographics'
urlpatterns = [
path('v1/', include(v1_urls))
]

View File

@@ -1,12 +0,0 @@
"""
URL Routes for this app.
"""
from django.urls import path
from .views import DemographicsStatusView
urlpatterns = [
path('demographics/status/', DemographicsStatusView.as_view(),
name='demographics_status'
),
]

View File

@@ -1,36 +0,0 @@
# lint-amnesty, pylint: disable=missing-module-docstring
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from openedx.core.djangoapps.demographics.api.status import show_call_to_action_for_user, show_user_demographics
class DemographicsStatusView(APIView):
"""
Demographics display status for the User.
The API will return whether or not to display the Demographics UI based on
the User's status in the Platform
"""
permission_classes = (permissions.IsAuthenticated,)
def _response_context(self, user, user_demographics=None):
"""
Determine whether the user should be shown demographics collection fields and the demographics call to action.
"""
if user_demographics:
show_call_to_action = user_demographics.show_call_to_action
else:
show_call_to_action = show_call_to_action_for_user(user)
return {"display": show_user_demographics(user), "show_call_to_action": show_call_to_action}
def get(self, request):
"""
GET /api/user/v1/accounts/demographics/status
This is a Web API to determine the status of demographics related features
"""
user = request.user
return Response(self._response_context(user))

View File

@@ -10,11 +10,9 @@ base_urls:
lms: http://localhost:18000/
ecommerce: http://localhost:18130/
credentials: http://localhost:18150/
demographics: http://localhost:18360/
retirement_pipeline:
- ['RETIRING_CREDENTIALS', 'CREDENTIALS_COMPLETE', 'CREDENTIALS', 'retire_learner']
- ['RETIRING_ECOM', 'ECOM_COMPLETE', 'ECOMMERCE', 'retire_learner']
- ['RETIRING_DEMOGRAPHICS', 'DEMOGRAPHICS_COMPLETE', 'DEMOGRAPHICS', 'retire_learner']
- ['RETIRING_LICENSE_MANAGER', 'LICENSE_MANAGER_COMPLETE', 'LICENSE_MANAGER', 'retire_learner']
- ['RETIRING_FORUMS', 'FORUMS_COMPLETE', 'LMS', 'retirement_retire_forum']
- ['RETIRING_EMAIL_LISTS', 'EMAIL_LISTS_COMPLETE', 'LMS', 'retirement_retire_mailings']

View File

@@ -18,7 +18,7 @@ import yaml
from six import text_type
from scripts.user_retirement.utils.edx_api import LmsApi # pylint: disable=wrong-import-position
from scripts.user_retirement.utils.edx_api import CredentialsApi, DemographicsApi, EcommerceApi, LicenseManagerApi
from scripts.user_retirement.utils.edx_api import CredentialsApi, EcommerceApi, LicenseManagerApi
from scripts.user_retirement.utils.thirdparty_apis.amplitude_api import \
AmplitudeApi # pylint: disable=wrong-import-position
from scripts.user_retirement.utils.thirdparty_apis.braze_api import BrazeApi # pylint: disable=wrong-import-position
@@ -143,17 +143,16 @@ def _setup_lms_api_or_exit(fail_func, fail_code, config):
def _setup_all_apis_or_exit(fail_func, fail_code, config):
"""
Performs setup of EdxRestClientApi instances for LMS, E-Commerce, Credentials, and
Demographics, as well as fetching the learner's record from LMS and validating that
it is in a state to work on. Returns the learner dict and their current stage in the
retirement flow.
Performs setup of EdxRestClientApi instances for LMS, E-Commerce, and Credentials,
as well as fetching the learner's record from LMS and validating that it is
in a state to work on. Returns the learner dict and their current stage in
the retirement flow.
"""
try:
lms_base_url = config['base_urls']['lms']
ecommerce_base_url = config['base_urls'].get('ecommerce', None)
credentials_base_url = config['base_urls'].get('credentials', None)
segment_base_url = config['base_urls'].get('segment', None)
demographics_base_url = config['base_urls'].get('demographics', None)
license_manager_base_url = config['base_urls'].get('license_manager', None)
client_id = config['client_id']
client_secret = config['client_secret']
@@ -181,7 +180,6 @@ def _setup_all_apis_or_exit(fail_func, fail_code, config):
('CREDENTIALS', credentials_base_url),
('SEGMENT', segment_base_url),
('HUBSPOT', hubspot_api_key),
('DEMOGRAPHICS', demographics_base_url)
):
if state[2] == service and service_url is None:
fail_func(fail_code, 'Service URL is not configured, but required for state {}'.format(state))
@@ -223,9 +221,6 @@ def _setup_all_apis_or_exit(fail_func, fail_code, config):
if credentials_base_url:
config['CREDENTIALS'] = CredentialsApi(lms_base_url, credentials_base_url, client_id, client_secret)
if demographics_base_url:
config['DEMOGRAPHICS'] = DemographicsApi(lms_base_url, demographics_base_url, client_id, client_secret)
if license_manager_base_url:
config['LICENSE_MANAGER'] = LicenseManagerApi(
lms_base_url,