Skip to content
Snippets Groups Projects
Unverified Commit f468cf22 authored by Richard I Reilly's avatar Richard I Reilly Committed by GitHub
Browse files

Merge pull request #20135 from edx/rir/addProgramEnrollments

Add ProgramEnrollment app and model for masters
parents f893f86f 2bf3e662
No related branches found
No related tags found
No related merge requests found
# -*- coding: utf-8 -*-
"""
Admin tool for the Program Enrollments models
"""
from __future__ import unicode_literals
from django.contrib import admin
from lms.djangoapps.program_enrollments.models import ProgramEnrollment
class ProgramEnrollmentAdmin(admin.ModelAdmin):
"""
Admin tool for the ProgramEnrollment model
"""
admin.site.register(ProgramEnrollment, ProgramEnrollmentAdmin)
# -*- coding: utf-8 -*-
"""
ProgramEnrollments Application Configuration
"""
from __future__ import unicode_literals
from django.apps import AppConfig
class ProgramEnrollmentsConfig(AppConfig):
"""
Application configuration for ProgramEnrollment
"""
name = 'lms.djangoapps.program_enrollments'
plugin_app = {
'url_config': {},
}
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-04-09 19:32
from __future__ import unicode_literals
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='HistoricalProgramEnrollment',
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')),
('external_user_key', models.CharField(db_index=True, max_length=255, null=True)),
('program_uuid', models.UUIDField(db_index=True)),
('curriculum_uuid', models.UUIDField(db_index=True)),
('status', models.CharField(choices=[('enrolled', 'enrolled'), ('pending', 'pending'), ('suspended', 'suspended'), ('withdrawn', 'withdrawn')], max_length=9)),
('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={
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
'verbose_name': 'historical program enrollment',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='ProgramEnrollment',
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')),
('external_user_key', models.CharField(db_index=True, max_length=255, null=True)),
('program_uuid', models.UUIDField(db_index=True)),
('curriculum_uuid', models.UUIDField(db_index=True)),
('status', models.CharField(choices=[('enrolled', 'enrolled'), ('pending', 'pending'), ('suspended', 'suspended'), ('withdrawn', 'withdrawn')], max_length=9)),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
# -*- coding: utf-8 -*-
"""
Django model specifications for the Program Enrollments API
"""
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.db import models
from model_utils.models import TimeStampedModel
from simple_history.models import HistoricalRecords
class ProgramEnrollment(TimeStampedModel): # pylint: disable=model-missing-unicode
"""
This is a model for Program Enrollments from the registrar service
.. pii: PII is found in the external key for a program enrollment
.. pii_types: other
.. pii_retirement: local_api
"""
STATUSES = (
('enrolled', 'enrolled'),
('pending', 'pending'),
('suspended', 'suspended'),
('withdrawn', 'withdrawn'),
)
class Meta(object):
app_label = "program_enrollments"
user = models.ForeignKey(
User,
null=True,
blank=True
)
external_user_key = models.CharField(
db_index=True,
max_length=255,
null=True
)
program_uuid = models.UUIDField(db_index=True, null=False)
curriculum_uuid = models.UUIDField(db_index=True, null=False)
status = models.CharField(max_length=9, choices=STATUSES)
historical_records = HistoricalRecords()
@classmethod
def retire_user(cls, user_id):
"""
With the parameter user_id, retire the external_user_key field
Return True if there is data that was retired
Return False if there is no matching data
"""
enrollments = cls.objects.filter(user=user_id)
if not enrollments:
return False
for enrollment in enrollments:
enrollment.historical_records.update(external_user_key=None)
enrollments.update(external_user_key=None)
return True
"""
Unit tests for ProgramEnrollment models.
"""
from __future__ import unicode_literals
from uuid import uuid4
from django.test import TestCase
from lms.djangoapps.program_enrollments.models import ProgramEnrollment
from student.tests.factories import UserFactory
class ProgramEnrollmentModelTests(TestCase):
"""
Tests for the ProgramEnrollment model.
"""
def setUp(self):
"""
Set up the test data used in the specific tests
"""
super(ProgramEnrollmentModelTests, self).setUp()
self.user = UserFactory.create()
self.enrollment = ProgramEnrollment.objects.create(
user=self.user,
external_user_key='abc',
program_uuid=uuid4(),
curriculum_uuid=uuid4(),
status='enrolled'
)
def test_user_retirement(self):
"""
Test that the external_user_key is uccessfully retired for a user's program enrollments and history.
"""
new_status = 'withdrawn'
self.enrollment.status = new_status
self.enrollment.save()
# Ensure that all the records had values for external_user_key
self.assertEquals(self.enrollment.external_user_key, 'abc')
self.assertTrue(self.enrollment.historical_records.all())
for record in self.enrollment.historical_records.all():
self.assertEquals(record.external_user_key, 'abc')
ProgramEnrollment.retire_user(self.user.id)
self.enrollment.refresh_from_db()
# Ensure those values are retired
self.assertEquals(self.enrollment.external_user_key, None)
self.assertTrue(self.enrollment.historical_records.all())
for record in self.enrollment.historical_records.all():
self.assertEquals(record.external_user_key, None)
# -*- coding: utf-8 -*-
"""
ProgramEnrollment Views
"""
from __future__ import unicode_literals
# from django.shortcuts import render
# Create your views here.
......@@ -82,7 +82,8 @@ setup(
"zendesk_proxy = openedx.core.djangoapps.zendesk_proxy.apps:ZendeskProxyConfig",
"instructor = lms.djangoapps.instructor.apps:InstructorConfig",
"password_policy = openedx.core.djangoapps.password_policy.apps:PasswordPolicyConfig",
"user_authn = openedx.core.djangoapps.user_authn.apps:UserAuthnConfig"
"user_authn = openedx.core.djangoapps.user_authn.apps:UserAuthnConfig",
"program_enrollments = lms.djangoapps.program_enrollments.apps:ProgramEnrollmentsConfig",
],
"cms.djangoapp": [
"announcements = openedx.features.announcements.apps:AnnouncementsConfig",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment