Skip to content

Commit

Permalink
rework of subsidy fulfillment model hierarchy
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-sheehan-edx committed Feb 6, 2023
1 parent cec4b16 commit 25ebd3f
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 110 deletions.
17 changes: 9 additions & 8 deletions enterprise/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -866,17 +866,18 @@ def bulk_licensed_enrollments_expiration(self, request):

try:
termination_status = self._terminate_enrollment(enterprise_course_enrollment, course_overview)
LOGGER.info((
"EnterpriseCourseEnrollment record with enterprise license %s "
"unenrolled to status %s."
), enterprise_course_enrollment.licensed_with.license_uuid, termination_status)
license_uuid = enterprise_course_enrollment.license.license_uuid
LOGGER.info(
f"EnterpriseCourseEnrollment record with enterprise license {license_uuid} "
f"unenrolled to status {termination_status}."
)
if termination_status != self.EnrollmentTerminationStatus.COURSE_COMPLETED:
enterprise_course_enrollment.license.revoke()
except EnrollmentModificationException as exc:
LOGGER.error((
"Failed to unenroll EnterpriseCourseEnrollment record for enterprise license %s. "
"error message %s."
), enterprise_course_enrollment.licensed_with.license_uuid, str(exc))
LOGGER.error(
f"Failed to unenroll EnterpriseCourseEnrollment record for enterprise license "
f"{enterprise_course_enrollment.license.license_uuid}. error message {str(exc)}."
)
any_failures = True

status_code = status.HTTP_200_OK if not any_failures else status.HTTP_422_UNPROCESSABLE_ENTITY
Expand Down
6 changes: 3 additions & 3 deletions enterprise/management/commands/revert_enrollment_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,15 @@ def revert_enrollment_objects(self, options):
for ecu in ecus:
eces = EnterpriseCourseEnrollment.objects.filter(
enterprise_customer_user=ecu,
licensed_with__is_revoked=True,
licensed_with__modified__gte=time_to_revert_to,
enterprise_licensedenterprisecourseenrollment_enrollment_related__is_revoked=True,
enterprise_licensedenterprisecourseenrollment_enrollment_related__modified__gte=time_to_revert_to,
)

for enrollment in eces:
student_course_enrollment = enrollment.course_enrollment
student_course_enrollment.history.as_of(time_to_revert_to).save()

licensed_enrollment = enrollment.licensed_with
licensed_enrollment = enrollment.enterprise_licensedenterprisecourseenrollment_enrollment_related
licensed_enrollment.history.as_of(time_to_revert_to).save()

enrollment.history.as_of(time_to_revert_to).save()
Expand Down
103 changes: 103 additions & 0 deletions enterprise/migrations/0167_auto_20230206_1532.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Generated by Django 3.2.16 on 2023-02-06 15:32

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
import uuid


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('enterprise', '0166_auto_20221209_0819'),
]

operations = [
migrations.CreateModel(
name='EnterpriseCourseEntitlement',
fields=[
('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')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('course_uuid', models.CharField(help_text='The UUID of the course (not course run) in which the learner is entitled.', max_length=255)),
('enterprise_customer_user', models.ForeignKey(help_text='The enterprise learner to which this entitlement is attached.', on_delete=django.db.models.deletion.CASCADE, related_name='enterprise_entitlements', to='enterprise.enterprisecustomeruser')),
],
options={
'ordering': ['created'],
'unique_together': {('enterprise_customer_user', 'course_uuid')},
},
),
migrations.CreateModel(
name='HistoricalEnterpriseCourseEntitlement',
fields=[
('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')),
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False)),
('course_uuid', models.CharField(help_text='The UUID of the course (not course run) in which the learner is entitled.', max_length=255)),
('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)),
('enterprise_customer_user', models.ForeignKey(blank=True, db_constraint=False, help_text='The enterprise learner to which this entitlement is attached.', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='enterprise.enterprisecustomeruser')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical enterprise course entitlement',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='SubsidizedEnterpriseCourseEnrollment',
fields=[
('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')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('fulfillment_type', models.CharField(choices=[('license', 'License'), ('learner_credit', 'Learner Credit'), ('coupon_code', 'Coupon Code')], default='license', help_text="Subsidy fulfillment type, can be one of: ('license', 'learner_credit', 'coupon_code')", max_length=128)),
('is_revoked', models.BooleanField(default=False, help_text="Whether the enterprise subsidy is revoked, e.g., when a user's license is revoked.")),
('transaction_id', models.UUIDField(editable=False)),
('enterprise_course_enrollment', models.OneToOneField(blank=True, help_text='The course enrollment the associated subsidy is for.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='enterprise_subsidizedenterprisecourseenrollment_enrollment_related', to='enterprise.enterprisecourseenrollment')),
('enterprise_course_entitlement', models.OneToOneField(blank=True, help_text='The course entitlement the associated subsidy is for.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='enterprise_subsidizedenterprisecourseenrollment_entitlement_related', to='enterprise.enterprisecourseentitlement')),
],
options={
'abstract': False,
},
),
migrations.RemoveField(
model_name='licensedenterprisecourseenrollment',
name='id',
),
migrations.AddField(
model_name='licensedenterprisecourseenrollment',
name='fulfillment_type',
field=models.CharField(choices=[('license', 'License'), ('learner_credit', 'Learner Credit'), ('coupon_code', 'Coupon Code')], default='license', help_text="Subsidy fulfillment type, can be one of: ('license', 'learner_credit', 'coupon_code')", max_length=128),
),
migrations.AddField(
model_name='licensedenterprisecourseenrollment',
name='uuid',
field=models.UUIDField(null=True, editable=False, serialize=False),
),
migrations.AlterField(
model_name='licensedenterprisecourseenrollment',
name='enterprise_course_enrollment',
field=models.OneToOneField(blank=True, help_text='The course enrollment the associated subsidy is for.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='enterprise_licensedenterprisecourseenrollment_enrollment_related', to='enterprise.enterprisecourseenrollment'),
),
migrations.AlterField(
model_name='licensedenterprisecourseenrollment',
name='is_revoked',
field=models.BooleanField(default=False, help_text="Whether the enterprise subsidy is revoked, e.g., when a user's license is revoked."),
),
migrations.DeleteModel(
name='HistoricalLicensedEnterpriseCourseEnrollment',
),
migrations.AddField(
model_name='licensedenterprisecourseenrollment',
name='enterprise_course_entitlement',
field=models.OneToOneField(blank=True, help_text='The course entitlement the associated subsidy is for.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='enterprise_licensedenterprisecourseenrollment_entitlement_related', to='enterprise.enterprisecourseentitlement'),
),
]

This file was deleted.

22 changes: 22 additions & 0 deletions enterprise/migrations/0168_auto_20230206_1655.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 3.2.16 on 2023-02-06 16:55

from django.db import migrations
import uuid


def gen_uuid(apps, schema_editor):
LicensedEnterpriseCourseEnrollment = apps.get_model('enterprise', 'LicensedEnterpriseCourseEnrollment')
for row in LicensedEnterpriseCourseEnrollment.objects.all():
row.uuid = uuid.uuid4()
row.save(update_fields=['uuid'])


class Migration(migrations.Migration):

dependencies = [
('enterprise', '0167_auto_20230206_1532'),
]

operations = [
migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop),
]
19 changes: 19 additions & 0 deletions enterprise/migrations/0169_auto_20230206_1655.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.16 on 2023-02-06 16:55

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

dependencies = [
('enterprise', '0168_auto_20230206_1655'),
]

operations = [
migrations.AlterField(
model_name='licensedenterprisecourseenrollment',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False),
),
]
Loading

0 comments on commit 25ebd3f

Please sign in to comment.