Merge pull request #26672 from edx/BOM-2374-entitlements
Run Pyupgrade on entitlement.
This commit is contained in:
@@ -30,7 +30,7 @@ class CourseEntitlementAdmin(admin.ModelAdmin): # lint-amnesty, pylint: disable
|
||||
class CourseEntitlementSupportDetailForm(forms.ModelForm):
|
||||
"""Form for adding entitlement support details, exists mostly for testing purposes"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CourseEntitlementSupportDetailForm, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if self.data.get('unenrolled_run'):
|
||||
try:
|
||||
@@ -44,10 +44,10 @@ class CourseEntitlementSupportDetailForm(forms.ModelForm):
|
||||
try:
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
except InvalidKeyError:
|
||||
raise forms.ValidationError("Cannot make a valid CourseKey from id {}!".format(course_id)) # lint-amnesty, pylint: disable=raise-missing-from
|
||||
raise forms.ValidationError(f"Cannot make a valid CourseKey from id {course_id}!") # lint-amnesty, pylint: disable=raise-missing-from
|
||||
|
||||
if not modulestore().has_course(course_key):
|
||||
raise forms.ValidationError("Cannot find course with id {} in the modulestore".format(course_id))
|
||||
raise forms.ValidationError(f"Cannot find course with id {course_id} in the modulestore")
|
||||
|
||||
return course_key
|
||||
|
||||
@@ -72,7 +72,7 @@ class CourseEntitlementSupportDetailAdmin(admin.ModelAdmin):
|
||||
class CourseEntitlementPolicyForm(forms.ModelForm):
|
||||
""" Form for creating custom course entitlement policies. """
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CourseEntitlementPolicyForm, self).__init__(*args, **kwargs) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['site'].required = False
|
||||
self.fields['mode'].required = False
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import logging
|
||||
from textwrap import dedent
|
||||
|
||||
from django.core.management import BaseCommand
|
||||
from six.moves import range
|
||||
|
||||
from common.djangoapps.entitlements.models import CourseEntitlement
|
||||
from common.djangoapps.entitlements.tasks import expire_old_entitlements
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Test Entitlements models""" # lint-amnesty, pylint: disable=django-not-configured
|
||||
|
||||
|
||||
import mock
|
||||
from unittest import mock
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.test import TestCase
|
||||
from six.moves import range
|
||||
|
||||
from common.djangoapps.entitlements.tests.factories import CourseEntitlementFactory
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=django-not-configured, missing-module-docstring
|
||||
|
||||
|
||||
import uuid
|
||||
|
||||
import django.utils.timezone
|
||||
@@ -26,7 +23,7 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False)),
|
||||
('course_uuid', models.UUIDField()),
|
||||
('expired_at', models.DateTimeField(null=True)),
|
||||
('mode', models.CharField(default=u'audit', max_length=100)),
|
||||
('mode', models.CharField(default='audit', max_length=100)),
|
||||
('order_number', models.CharField(max_length=128, null=True)),
|
||||
('enrollment_course_run', models.ForeignKey(to='student.CourseEnrollment', null=True, on_delete=models.CASCADE)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@@ -17,21 +14,21 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='courseentitlement',
|
||||
name='course_uuid',
|
||||
field=models.UUIDField(help_text=u'UUID for the Course, not the Course Run'),
|
||||
field=models.UUIDField(help_text='UUID for the Course, not the Course Run'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='courseentitlement',
|
||||
name='enrollment_course_run',
|
||||
field=models.ForeignKey(to='student.CourseEnrollment', help_text=u'The current Course enrollment for this entitlement. If NULL the Learner has not enrolled.', null=True, on_delete=models.CASCADE), # lint-amnesty, pylint: disable=line-too-long
|
||||
field=models.ForeignKey(to='student.CourseEnrollment', help_text='The current Course enrollment for this entitlement. If NULL the Learner has not enrolled.', null=True, on_delete=models.CASCADE), # lint-amnesty, pylint: disable=line-too-long
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='courseentitlement',
|
||||
name='expired_at',
|
||||
field=models.DateTimeField(help_text=u'The date that an entitlement expired, if NULL the entitlement has not expired.', null=True), # lint-amnesty, pylint: disable=line-too-long
|
||||
field=models.DateTimeField(help_text='The date that an entitlement expired, if NULL the entitlement has not expired.', null=True), # lint-amnesty, pylint: disable=line-too-long
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='courseentitlement',
|
||||
name='mode',
|
||||
field=models.CharField(help_text=u'The mode of the Course that will be applied on enroll.', max_length=100),
|
||||
field=models.CharField(help_text='The mode of the Course that will be applied on enroll.', max_length=100),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
import datetime
|
||||
|
||||
from django.db import migrations, models
|
||||
@@ -18,21 +15,21 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
name='CourseEntitlementPolicy',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('expiration_period', models.DurationField(default=datetime.timedelta(450), help_text=u'Duration in days from when an entitlement is created until when it is expired.')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('refund_period', models.DurationField(default=datetime.timedelta(60), help_text=u'Duration in days from when an entitlement is created until when it is no longer refundable')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('regain_period', models.DurationField(default=datetime.timedelta(14), help_text=u'Duration in days from when an entitlement is redeemed for a course run until it is no longer able to be regained by a user.')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('expiration_period', models.DurationField(default=datetime.timedelta(450), help_text='Duration in days from when an entitlement is created until when it is expired.')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('refund_period', models.DurationField(default=datetime.timedelta(60), help_text='Duration in days from when an entitlement is created until when it is no longer refundable')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('regain_period', models.DurationField(default=datetime.timedelta(14), help_text='Duration in days from when an entitlement is redeemed for a course run until it is no longer able to be regained by a user.')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('site', models.ForeignKey(to='sites.Site', on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='courseentitlement',
|
||||
name='enrollment_course_run',
|
||||
field=models.ForeignKey(blank=True, to='student.CourseEnrollment', help_text=u'The current Course enrollment for this entitlement. If NULL the Learner has not enrolled.', null=True, on_delete=models.CASCADE), # lint-amnesty, pylint: disable=line-too-long
|
||||
field=models.ForeignKey(blank=True, to='student.CourseEnrollment', help_text='The current Course enrollment for this entitlement. If NULL the Learner has not enrolled.', null=True, on_delete=models.CASCADE), # lint-amnesty, pylint: disable=line-too-long
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='courseentitlement',
|
||||
name='expired_at',
|
||||
field=models.DateTimeField(help_text=u'The date that an entitlement expired, if NULL the entitlement has not expired.', null=True, blank=True), # lint-amnesty, pylint: disable=line-too-long
|
||||
field=models.DateTimeField(help_text='The date that an entitlement expired, if NULL the entitlement has not expired.', null=True, blank=True), # lint-amnesty, pylint: disable=line-too-long
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='courseentitlement',
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
import uuid
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
from django.conf import settings
|
||||
@@ -22,7 +19,7 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('reason', models.CharField(max_length=15, choices=[(u'LEAVE', 'Learner requested leave session for expired entitlement'), (u'CHANGE', 'Learner requested session change for expired entitlement'), (u'LEARNER_NEW', 'Learner requested new entitlement'), (u'COURSE_TEAM_NEW', 'Course team requested entitlement for learnerg'), (u'OTHER', 'Other')])), # lint-amnesty, pylint: disable=line-too-long
|
||||
('reason', models.CharField(max_length=15, choices=[('LEAVE', 'Learner requested leave session for expired entitlement'), ('CHANGE', 'Learner requested session change for expired entitlement'), ('LEARNER_NEW', 'Learner requested new entitlement'), ('COURSE_TEAM_NEW', 'Course team requested entitlement for learnerg'), ('OTHER', 'Other')])), # lint-amnesty, pylint: disable=line-too-long
|
||||
('comments', models.TextField(null=True)),
|
||||
('entitlement', models.ForeignKey(to='entitlements.CourseEntitlement', on_delete=models.CASCADE)),
|
||||
('support_user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@@ -14,7 +11,7 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
migrations.AddField(
|
||||
model_name='courseentitlementsupportdetail',
|
||||
name='action',
|
||||
field=models.CharField(default='CREATE', max_length=15, choices=[(u'REISSUE', u'Re-issue entitlement'), (u'CREATE', u'Create new entitlement')]), # lint-amnesty, pylint: disable=line-too-long
|
||||
field=models.CharField(default='CREATE', max_length=15, choices=[('REISSUE', 'Re-issue entitlement'), ('CREATE', 'Create new entitlement')]), # lint-amnesty, pylint: disable=line-too-long
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
import datetime
|
||||
|
||||
from django.db import migrations, models
|
||||
@@ -16,6 +13,6 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
migrations.AlterField(
|
||||
model_name='courseentitlementpolicy',
|
||||
name='expiration_period',
|
||||
field=models.DurationField(default=datetime.timedelta(730), help_text=u'Duration in days from when an entitlement is created until when it is expired.'), # lint-amnesty, pylint: disable=line-too-long
|
||||
field=models.DurationField(default=datetime.timedelta(730), help_text='Duration in days from when an entitlement is created until when it is expired.'), # lint-amnesty, pylint: disable=line-too-long
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@@ -14,7 +11,7 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
migrations.AddField(
|
||||
model_name='courseentitlementpolicy',
|
||||
name='mode',
|
||||
field=models.CharField(max_length=32, null=True, choices=[(None, u'---------'), (u'verified', u'verified'), (u'professional', u'professional')]), # lint-amnesty, pylint: disable=line-too-long
|
||||
field=models.CharField(max_length=32, null=True, choices=[(None, '---------'), ('verified', 'verified'), ('professional', 'professional')]), # lint-amnesty, pylint: disable=line-too-long
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='courseentitlementpolicy',
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
# Generated by Django 1.11.12 on 2018-04-12 12:00
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
|
||||
|
||||
from datetime import datetime # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from django.db import migrations, models # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
# Generated by Django 1.11.20 on 2019-05-30 21:13
|
||||
|
||||
|
||||
@@ -8,7 +7,7 @@ import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
import simple_history.models
|
||||
import uuid # lint-amnesty, pylint: disable=wrong-import-order
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
@@ -27,9 +26,9 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)),
|
||||
('course_uuid', models.UUIDField(help_text=u'UUID for the Course, not the Course Run')),
|
||||
('expired_at', models.DateTimeField(blank=True, help_text=u'The date that an entitlement expired, if NULL the entitlement has not expired.', null=True)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('mode', models.CharField(help_text=u'The mode of the Course that will be applied on enroll.', max_length=100)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('course_uuid', models.UUIDField(help_text='UUID for the Course, not the Course Run')),
|
||||
('expired_at', models.DateTimeField(blank=True, help_text='The date that an entitlement expired, if NULL the entitlement has not expired.', null=True)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('mode', models.CharField(help_text='The mode of the Course that will be applied on enroll.', max_length=100)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('order_number', models.CharField(max_length=128, null=True)),
|
||||
('refund_locked', models.BooleanField(default=False)),
|
||||
('history_id', models.AutoField(primary_key=True, serialize=False)),
|
||||
@@ -37,7 +36,7 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
('history_change_reason', models.CharField(max_length=100, null=True)),
|
||||
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('_policy', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='entitlements.CourseEntitlementPolicy')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('enrollment_course_run', models.ForeignKey(blank=True, db_constraint=False, help_text=u'The current Course enrollment for this entitlement. If NULL the Learner has not enrolled.', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='student.CourseEnrollment')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('enrollment_course_run', models.ForeignKey(blank=True, db_constraint=False, help_text='The current Course enrollment for this entitlement. If NULL the Learner has not enrolled.', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='student.CourseEnrollment')), # lint-amnesty, pylint: disable=line-too-long
|
||||
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), # lint-amnesty, pylint: disable=line-too-long
|
||||
('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)), # lint-amnesty, pylint: disable=line-too-long
|
||||
],
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
# Generated by Django 1.11.25 on 2019-10-23 15:47
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
# Generated by Django 1.11.26 on 2019-12-17 14:08
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
# Generated by Django 1.11.27 on 2020-01-15 20:22
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*- # lint-amnesty, pylint: disable=missing-module-docstring
|
||||
# Generated by Django 1.11.27 on 2020-01-29 10:33
|
||||
|
||||
|
||||
@@ -24,6 +23,6 @@ class Migration(migrations.Migration): # lint-amnesty, pylint: disable=missing-
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseentitlement',
|
||||
unique_together=set([('course_uuid', 'order_number')]),
|
||||
unique_together={('course_uuid', 'order_number')},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -16,12 +16,12 @@ from simple_history.models import HistoricalRecords
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.entitlements.utils import is_course_run_entitlement_fulfillable
|
||||
from common.djangoapps.student.models import CourseEnrollment, CourseEnrollmentException
|
||||
from common.djangoapps.util.date_utils import strftime_localized
|
||||
from lms.djangoapps.certificates.models import GeneratedCertificate
|
||||
from lms.djangoapps.commerce.utils import refund_entitlement
|
||||
from openedx.core.djangoapps.catalog.utils import get_course_uuid_for_course
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from common.djangoapps.student.models import CourseEnrollment, CourseEnrollmentException
|
||||
from common.djangoapps.util.date_utils import strftime_localized
|
||||
|
||||
log = logging.getLogger("common.entitlements.models")
|
||||
|
||||
@@ -37,23 +37,23 @@ class CourseEntitlementPolicy(models.Model):
|
||||
DEFAULT_EXPIRATION_PERIOD_DAYS = 730
|
||||
DEFAULT_REFUND_PERIOD_DAYS = 60
|
||||
DEFAULT_REGAIN_PERIOD_DAYS = 14
|
||||
MODES = Choices((None, u'---------'), CourseMode.VERIFIED, CourseMode.PROFESSIONAL)
|
||||
MODES = Choices((None, '---------'), CourseMode.VERIFIED, CourseMode.PROFESSIONAL)
|
||||
|
||||
# Use a DurationField to calculate time as it returns a timedelta, useful in performing operations with datetimes
|
||||
expiration_period = models.DurationField(
|
||||
default=timedelta(days=DEFAULT_EXPIRATION_PERIOD_DAYS),
|
||||
help_text=u"Duration in days from when an entitlement is created until when it is expired.",
|
||||
help_text="Duration in days from when an entitlement is created until when it is expired.",
|
||||
null=False
|
||||
)
|
||||
refund_period = models.DurationField(
|
||||
default=timedelta(days=DEFAULT_REFUND_PERIOD_DAYS),
|
||||
help_text=u"Duration in days from when an entitlement is created until when it is no longer refundable",
|
||||
help_text="Duration in days from when an entitlement is created until when it is no longer refundable",
|
||||
null=False
|
||||
)
|
||||
regain_period = models.DurationField(
|
||||
default=timedelta(days=DEFAULT_REGAIN_PERIOD_DAYS),
|
||||
help_text=(u"Duration in days from when an entitlement is redeemed for a course run until "
|
||||
u"it is no longer able to be regained by a user."),
|
||||
help_text=("Duration in days from when an entitlement is redeemed for a course run until "
|
||||
"it is no longer able to be regained by a user."),
|
||||
null=False
|
||||
)
|
||||
site = models.ForeignKey(Site, null=True, on_delete=models.CASCADE)
|
||||
@@ -140,7 +140,7 @@ class CourseEntitlementPolicy(models.Model):
|
||||
and not entitlement.expired_at)
|
||||
|
||||
def __str__(self):
|
||||
return u'Course Entitlement Policy: expiration_period: {}, refund_period: {}, regain_period: {}, mode: {}'\
|
||||
return 'Course Entitlement Policy: expiration_period: {}, refund_period: {}, regain_period: {}, mode: {}'\
|
||||
.format(
|
||||
self.expiration_period,
|
||||
self.refund_period,
|
||||
@@ -157,17 +157,17 @@ class CourseEntitlement(TimeStampedModel):
|
||||
"""
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
||||
uuid = models.UUIDField(default=uuid_tools.uuid4, editable=False, unique=True)
|
||||
course_uuid = models.UUIDField(help_text=u'UUID for the Course, not the Course Run')
|
||||
course_uuid = models.UUIDField(help_text='UUID for the Course, not the Course Run')
|
||||
expired_at = models.DateTimeField(
|
||||
null=True,
|
||||
help_text=u'The date that an entitlement expired, if NULL the entitlement has not expired.',
|
||||
help_text='The date that an entitlement expired, if NULL the entitlement has not expired.',
|
||||
blank=True
|
||||
)
|
||||
mode = models.CharField(max_length=100, help_text=u'The mode of the Course that will be applied on enroll.')
|
||||
mode = models.CharField(max_length=100, help_text='The mode of the Course that will be applied on enroll.')
|
||||
enrollment_course_run = models.ForeignKey(
|
||||
'student.CourseEnrollment',
|
||||
null=True,
|
||||
help_text=u'The current Course enrollment for this entitlement. If NULL the Learner has not enrolled.',
|
||||
help_text='The current Course enrollment for this entitlement. If NULL the Learner has not enrolled.',
|
||||
blank=True,
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
@@ -399,7 +399,7 @@ class CourseEntitlement(TimeStampedModel):
|
||||
mode=entitlement.mode
|
||||
)
|
||||
except CourseEnrollmentException:
|
||||
log.exception(u'Login for Course Entitlement {uuid} failed'.format(uuid=entitlement.uuid))
|
||||
log.exception(f'Login for Course Entitlement {entitlement.uuid} failed')
|
||||
return False
|
||||
|
||||
entitlement.set_enrollment(enrollment)
|
||||
@@ -445,7 +445,7 @@ class CourseEntitlement(TimeStampedModel):
|
||||
if not refund_successful:
|
||||
# This state is achieved in most cases by a failure in the ecommerce service to process the refund.
|
||||
log.warning(
|
||||
u'Entitlement Refund failed for Course Entitlement [%s], alert User',
|
||||
'Entitlement Refund failed for Course Entitlement [%s], alert User',
|
||||
self.uuid
|
||||
)
|
||||
# Force Transaction reset with an Integrity error exception, this will revert all previous transactions
|
||||
@@ -457,7 +457,7 @@ class CourseEntitlement(TimeStampedModel):
|
||||
"""
|
||||
if not self.order_number:
|
||||
self.order_number = None
|
||||
super(CourseEntitlement, self).save(*args, **kwargs)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
@@ -468,24 +468,24 @@ class CourseEntitlementSupportDetail(TimeStampedModel):
|
||||
.. no_pii:
|
||||
"""
|
||||
# Reasons deprecated
|
||||
LEAVE_SESSION = u'LEAVE'
|
||||
CHANGE_SESSION = u'CHANGE'
|
||||
LEARNER_REQUEST_NEW = u'LEARNER_NEW'
|
||||
COURSE_TEAM_REQUEST_NEW = u'COURSE_TEAM_NEW'
|
||||
OTHER = u'OTHER'
|
||||
LEAVE_SESSION = 'LEAVE'
|
||||
CHANGE_SESSION = 'CHANGE'
|
||||
LEARNER_REQUEST_NEW = 'LEARNER_NEW'
|
||||
COURSE_TEAM_REQUEST_NEW = 'COURSE_TEAM_NEW'
|
||||
OTHER = 'OTHER'
|
||||
ENTITLEMENT_SUPPORT_REASONS = (
|
||||
(LEAVE_SESSION, u'Learner requested leave session for expired entitlement'),
|
||||
(CHANGE_SESSION, u'Learner requested session change for expired entitlement'),
|
||||
(LEARNER_REQUEST_NEW, u'Learner requested new entitlement'),
|
||||
(COURSE_TEAM_REQUEST_NEW, u'Course team requested entitlement for learnerg'),
|
||||
(OTHER, u'Other'),
|
||||
(LEAVE_SESSION, 'Learner requested leave session for expired entitlement'),
|
||||
(CHANGE_SESSION, 'Learner requested session change for expired entitlement'),
|
||||
(LEARNER_REQUEST_NEW, 'Learner requested new entitlement'),
|
||||
(COURSE_TEAM_REQUEST_NEW, 'Course team requested entitlement for learnerg'),
|
||||
(OTHER, 'Other'),
|
||||
)
|
||||
|
||||
REISSUE = u'REISSUE'
|
||||
CREATE = u'CREATE'
|
||||
REISSUE = 'REISSUE'
|
||||
CREATE = 'CREATE'
|
||||
ENTITLEMENT_SUPPORT_ACTIONS = (
|
||||
(REISSUE, u'Re-issue entitlement'),
|
||||
(CREATE, u'Create new entitlement'),
|
||||
(REISSUE, 'Re-issue entitlement'),
|
||||
(CREATE, 'Create new entitlement'),
|
||||
)
|
||||
|
||||
entitlement = models.ForeignKey('entitlements.CourseEntitlement', on_delete=models.CASCADE)
|
||||
@@ -509,7 +509,7 @@ class CourseEntitlementSupportDetail(TimeStampedModel):
|
||||
|
||||
def __str__(self):
|
||||
"""Unicode representation of an Entitlement"""
|
||||
return u'Course Entitlement Support Detail: entitlement: {}, support_user: {}, reason: {}'.format(
|
||||
return 'Course Entitlement Support Detail: entitlement: {}, support_user: {}, reason: {}'.format(
|
||||
self.entitlement,
|
||||
self.support_user,
|
||||
self.reason,
|
||||
|
||||
@@ -14,7 +14,7 @@ class CharListFilter(filters.CharFilter):
|
||||
if value not in (None, ''):
|
||||
value = value.split(',')
|
||||
|
||||
return super(CharListFilter, self).filter(qs, value) # lint-amnesty, pylint: disable=super-with-arguments
|
||||
return super().filter(qs, value)
|
||||
|
||||
|
||||
class UUIDListFilter(CharListFilter):
|
||||
@@ -22,7 +22,7 @@ class UUIDListFilter(CharListFilter):
|
||||
|
||||
def __init__(self, field_name='uuid', label=None, widget=None, method=None, lookup_expr='in', required=False,
|
||||
distinct=False, exclude=False, **kwargs):
|
||||
super(UUIDListFilter, self).__init__( # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().__init__(
|
||||
field_name=field_name,
|
||||
label=label,
|
||||
widget=widget,
|
||||
|
||||
@@ -7,23 +7,23 @@ import logging
|
||||
import unittest
|
||||
import uuid
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
from mock import patch
|
||||
from opaque_keys.edx.locator import CourseKey
|
||||
from pytz import UTC
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, UserFactory
|
||||
from lms.djangoapps.courseware.models import DynamicUpgradeDeadlineConfiguration
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
from openedx.core.djangoapps.user_api.models import UserOrgTag
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
@@ -45,7 +45,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
ENTITLEMENTS_DETAILS_PATH = 'entitlements_api:v1:entitlements-detail'
|
||||
|
||||
def setUp(self):
|
||||
super(EntitlementViewSetTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory(is_staff=True)
|
||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||
self.course = CourseFactory()
|
||||
@@ -375,7 +375,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
entitlement_data = self._get_data_set(self.user, str(course_uuid))
|
||||
entitlement_data['email_opt_in'] = True
|
||||
|
||||
org = u'particularly'
|
||||
org = 'particularly'
|
||||
mock_get_owners.return_value = [{'key': org}]
|
||||
|
||||
response = self.client.post(
|
||||
@@ -386,7 +386,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
assert response.status_code == 201
|
||||
|
||||
result_obj = UserOrgTag.objects.get(user=self.user, org=org, key='email-optin')
|
||||
assert result_obj.value == u'True'
|
||||
assert result_obj.value == 'True'
|
||||
|
||||
@patch("common.djangoapps.entitlements.rest_api.v1.views.get_owners_for_course")
|
||||
def test_email_opt_in_multiple_orgs(self, mock_get_owners):
|
||||
@@ -394,8 +394,8 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
entitlement_data = self._get_data_set(self.user, str(course_uuid))
|
||||
entitlement_data['email_opt_in'] = True
|
||||
|
||||
org_1 = u'particularly'
|
||||
org_2 = u'underwood'
|
||||
org_1 = 'particularly'
|
||||
org_2 = 'underwood'
|
||||
mock_get_owners.return_value = [{'key': org_1}, {'key': org_2}]
|
||||
|
||||
response = self.client.post(
|
||||
@@ -406,9 +406,9 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
assert response.status_code == 201
|
||||
|
||||
result_obj = UserOrgTag.objects.get(user=self.user, org=org_1, key='email-optin')
|
||||
assert result_obj.value == u'True'
|
||||
assert result_obj.value == 'True'
|
||||
result_obj = UserOrgTag.objects.get(user=self.user, org=org_2, key='email-optin')
|
||||
assert result_obj.value == u'True'
|
||||
assert result_obj.value == 'True'
|
||||
|
||||
def test_add_entitlement_with_support_detail(self):
|
||||
"""
|
||||
@@ -610,7 +610,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
self.client.login(username=not_staff_user.username, password=TEST_PASSWORD)
|
||||
entitlement_user2 = CourseEntitlementFactory.create_batch(2, user=not_staff_user, created=past_datetime)
|
||||
url = reverse('entitlements_api:v1:entitlements-list')
|
||||
url += '?user={username}'.format(username=not_staff_user.username)
|
||||
url += f'?user={not_staff_user.username}'
|
||||
|
||||
# Set the first entitlement to be at a time that it isn't expired
|
||||
entitlement_user2[0].created = now()
|
||||
@@ -630,7 +630,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
CourseEntitlementFactory.create()
|
||||
entitlement_user2 = CourseEntitlementFactory.create(user=user2)
|
||||
url = reverse('entitlements_api:v1:entitlements-list')
|
||||
url += '?user={username}'.format(username=user2.username)
|
||||
url += f'?user={user2.username}'
|
||||
response = self.client.get(
|
||||
url,
|
||||
content_type='application/json',
|
||||
@@ -816,7 +816,7 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase):
|
||||
ENTITLEMENTS_ENROLLMENT_NAMESPACE = 'entitlements_api:v1:enrollments'
|
||||
|
||||
def setUp(self):
|
||||
super(EntitlementEnrollmentViewSetTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory()
|
||||
UserFactory(username=settings.ECOMMERCE_SERVICE_WORKER_USERNAME, is_staff=True)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ app_name = 'v1'
|
||||
urlpatterns = [
|
||||
url(r'', include(router.urls)),
|
||||
url(
|
||||
r'entitlements/(?P<uuid>{regex})/enrollments$'.format(regex=EntitlementViewSet.ENTITLEMENT_UUID4_REGEX),
|
||||
fr'entitlements/(?P<uuid>{EntitlementViewSet.ENTITLEMENT_UUID4_REGEX})/enrollments$',
|
||||
ENROLLMENTS_VIEW,
|
||||
name='enrollments'
|
||||
)
|
||||
|
||||
@@ -17,16 +17,20 @@ from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.response import Response
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.entitlements.models import ( # lint-amnesty, pylint: disable=line-too-long
|
||||
CourseEntitlement,
|
||||
CourseEntitlementPolicy,
|
||||
CourseEntitlementSupportDetail
|
||||
)
|
||||
from common.djangoapps.entitlements.rest_api.v1.filters import CourseEntitlementFilter
|
||||
from common.djangoapps.entitlements.rest_api.v1.permissions import IsAdminOrSupportOrAuthenticatedReadOnly
|
||||
from common.djangoapps.entitlements.rest_api.v1.serializers import CourseEntitlementSerializer
|
||||
from common.djangoapps.entitlements.models import CourseEntitlement, CourseEntitlementPolicy, CourseEntitlementSupportDetail # lint-amnesty, pylint: disable=line-too-long
|
||||
from common.djangoapps.entitlements.utils import is_course_run_entitlement_fulfillable
|
||||
from common.djangoapps.student.models import AlreadyEnrolledError, CourseEnrollment, CourseEnrollmentException
|
||||
from openedx.core.djangoapps.catalog.utils import get_course_runs_for_course, get_owners_for_course
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.cors_csrf.authentication import SessionAuthenticationCrossDomainCsrf
|
||||
from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in
|
||||
from common.djangoapps.student.models import AlreadyEnrolledError, CourseEnrollment, CourseEnrollmentException
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -273,7 +277,7 @@ class EntitlementViewSet(viewsets.ModelViewSet):
|
||||
entitlement = CourseEntitlement.objects.get(uuid=entitlement_uuid)
|
||||
except CourseEntitlement.DoesNotExist:
|
||||
return HttpResponseBadRequest(
|
||||
u'Could not find entitlement {entitlement_uuid} to update'.format(
|
||||
'Could not find entitlement {entitlement_uuid} to update'.format(
|
||||
entitlement_uuid=entitlement_uuid
|
||||
)
|
||||
)
|
||||
@@ -295,12 +299,12 @@ class EntitlementViewSet(viewsets.ModelViewSet):
|
||||
support_detail['unenrolled_run'] = CourseOverview.objects.get(id=unenrolled_run_course_key)
|
||||
except (InvalidKeyError, CourseOverview.DoesNotExist) as error:
|
||||
return HttpResponseBadRequest(
|
||||
u'Error raised while trying to unenroll user {user} from course run {course_id}: {error}'
|
||||
'Error raised while trying to unenroll user {user} from course run {course_id}: {error}'
|
||||
.format(user=entitlement.user.username, course_id=unenrolled_run_id, error=error)
|
||||
)
|
||||
CourseEntitlementSupportDetail.objects.create(**support_detail)
|
||||
|
||||
return super(EntitlementViewSet, self).partial_update(request, *args, **kwargs) # lint-amnesty, pylint: disable=no-member, super-with-arguments
|
||||
return super().partial_update(request, *args, **kwargs) # lint-amnesty, pylint: disable=no-member, super-with-arguments
|
||||
|
||||
|
||||
class EntitlementEnrollmentViewSet(viewsets.GenericViewSet):
|
||||
@@ -417,7 +421,7 @@ class EntitlementEnrollmentViewSet(viewsets.GenericViewSet):
|
||||
return Response(
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
data={
|
||||
'message': 'Invalid {course_id}'.format(course_id=course_run_id)
|
||||
'message': f'Invalid {course_run_id}'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -8,22 +8,22 @@ from factory.fuzzy import FuzzyChoice, FuzzyText
|
||||
|
||||
from common.djangoapps.course_modes.helpers import CourseMode
|
||||
from common.djangoapps.entitlements.models import CourseEntitlement, CourseEntitlementPolicy
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
|
||||
|
||||
class CourseEntitlementPolicyFactory(factory.django.DjangoModelFactory):
|
||||
"""
|
||||
Factory for a a CourseEntitlementPolicy
|
||||
"""
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = CourseEntitlementPolicy
|
||||
|
||||
site = factory.SubFactory(SiteFactory)
|
||||
|
||||
|
||||
class CourseEntitlementFactory(factory.django.DjangoModelFactory): # lint-amnesty, pylint: disable=missing-class-docstring
|
||||
class Meta(object):
|
||||
class Meta:
|
||||
model = CourseEntitlement
|
||||
|
||||
uuid = factory.LazyFunction(uuid4)
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
|
||||
import unittest
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
from uuid import uuid4
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.utils.timezone import now
|
||||
from mock import patch
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, UserFactory
|
||||
from lms.djangoapps.certificates.api import MODES
|
||||
from lms.djangoapps.certificates.models import CertificateStatuses
|
||||
from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
@@ -33,7 +33,7 @@ class TestCourseEntitlementModelHelpers(ModuleStoreTestCase):
|
||||
Series of tests for the helper methods in the CourseEntitlement Model Class.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TestCourseEntitlementModelHelpers, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.user = UserFactory()
|
||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||
|
||||
@@ -117,7 +117,7 @@ class TestModels(TestCase):
|
||||
"""Test entitlement with policy model functions."""
|
||||
|
||||
def setUp(self):
|
||||
super(TestModels, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
self.course = CourseOverviewFactory.create(
|
||||
start=now()
|
||||
)
|
||||
|
||||
@@ -4,10 +4,10 @@ Test entitlements tasks
|
||||
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from unittest import mock
|
||||
|
||||
import mock
|
||||
import pytz
|
||||
import pytest
|
||||
import pytz
|
||||
from django.test import TestCase
|
||||
|
||||
from common.djangoapps.entitlements import tasks
|
||||
|
||||
@@ -11,8 +11,13 @@ from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
from common.djangoapps.student.tests.factories import ( # lint-amnesty, pylint: disable=line-too-long
|
||||
TEST_PASSWORD,
|
||||
CourseEnrollmentFactory,
|
||||
CourseOverviewFactory,
|
||||
UserFactory
|
||||
)
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from common.djangoapps.student.tests.factories import TEST_PASSWORD, CourseEnrollmentFactory, CourseOverviewFactory, UserFactory # lint-amnesty, pylint: disable=line-too-long
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
|
||||
# Entitlements is not in CMS' INSTALLED_APPS so these imports will error during test collection
|
||||
@@ -28,7 +33,7 @@ class TestCourseRunFulfillableForEntitlement(ModuleStoreTestCase):
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestCourseRunFulfillableForEntitlement, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
super().setUp()
|
||||
|
||||
self.user = UserFactory(is_staff=True)
|
||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||
|
||||
@@ -8,8 +8,8 @@ import logging
|
||||
from django.utils import timezone
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
|
||||
log = logging.getLogger("common.entitlements.utils")
|
||||
|
||||
@@ -36,8 +36,8 @@ def is_course_run_entitlement_fulfillable(
|
||||
try:
|
||||
course_overview = CourseOverview.get_from_id(course_run_key)
|
||||
except CourseOverview.DoesNotExist:
|
||||
log.error((u'There is no CourseOverview entry available for {course_run_id}, '
|
||||
u'course run cannot be applied to entitlement').format(
|
||||
log.error(('There is no CourseOverview entry available for {course_run_id}, '
|
||||
'course run cannot be applied to entitlement').format(
|
||||
course_run_id=str(course_run_key)
|
||||
))
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user