Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 42 additions & 31 deletions enterprise_access/apps/provisioning/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.shortcuts import render
from django.urls import reverse
from django.utils import timezone
from django.utils.safestring import mark_safe
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from djangoql.admin import DjangoQLSearchMixin

Expand Down Expand Up @@ -41,7 +41,7 @@ class ProvisionNewCustomerWorkflowAdmin(DjangoQLSearchMixin, admin.ModelAdmin):
'create_admin_users_step_link',
'create_catalog_step_link',
'create_customer_agreement_step_link',
'create_subscription_plan_step_link',
'create_trial_subscription_plan_step_link',
'enterprise_customer_admin_link',
'subscription_plan_link',
)
Expand All @@ -56,10 +56,11 @@ def create_customer_step_link(self, obj):
step_record = obj.get_create_customer_step()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreatecustomerstep_change", args=(step_record.pk,)),
step_record.pk,
))
)

@admin.display(
description='Create Admin Users Step'
Expand All @@ -71,10 +72,11 @@ def create_admin_users_step_link(self, obj):
step_record = obj.get_create_enterprise_admin_users_step()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreateenterpriseadminusersstep_change", args=(step_record.pk,)),
step_record.pk,
))
)

@admin.display(
description='Create Catalog Step'
Expand All @@ -86,10 +88,11 @@ def create_catalog_step_link(self, obj):
step_record = obj.get_create_catalog_step()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreatecatalogstep_change", args=(step_record.pk,)),
step_record.pk,
))
)

@admin.display(
description='Create Customer Agreement Step'
Expand All @@ -101,25 +104,27 @@ def create_customer_agreement_step_link(self, obj):
step_record = obj.get_create_customer_agreement_step()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreatecustomeragreementstep_change", args=(step_record.pk,)),
step_record.pk,
))
)

@admin.display(
description='Create Subscription Plan Step'
description='Create Trial Subscription Plan Step'
)
def create_subscription_plan_step_link(self, obj):
def create_trial_subscription_plan_step_link(self, obj):
"""
Returns a link to the subscription plan creation step admin page for this workflow.
"""
step_record = obj.get_create_subscription_plan_step()
step_record = obj.get_create_trial_subscription_plan_step()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
reverse("admin:provisioning_getcreatesubscriptionplanstep_change", args=(step_record.pk,)),
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreatetrialsubscriptionplanstep_change", args=(step_record.pk,)),
step_record.pk,
))
)

@admin.display(
description='Enterprise Customer Record (LMS)'
Expand All @@ -131,7 +136,7 @@ def enterprise_customer_admin_link(self, obj):
step_record = obj.get_create_customer_step()
customer_uuid = step_record.output_object.uuid
url = f'{settings.LMS_URL}/admin/enterprise/enterprisecustomer/{customer_uuid}/change/'
return mark_safe(f'<a href="{url}">{url}</a>')
return format_html('<a href="{}">{}</a>', url, url)
Comment on lines 136 to +139

@admin.display(
description='Subscription Plan Record (License Manager)'
Expand All @@ -140,10 +145,10 @@ def subscription_plan_link(self, obj):
"""
Link to the EnterpriseCustomer Admin record in the LMS service.
"""
Comment on lines 145 to 147
step_record = obj.get_create_subscription_plan_step()
step_record = obj.get_create_trial_subscription_plan_step()
plan_uuid = step_record.output_object.uuid
url = f'{settings.LICENSE_MANAGER_URL}/admin/subscriptions/subscriptionplan/{plan_uuid}/change/'
return mark_safe(f'<a href="{url}">{url}</a>')
return format_html('<a href="{}">{}</a>', url, url)


class ProvisionWorkflowStepAdminBase(admin.ModelAdmin):
Expand Down Expand Up @@ -179,10 +184,11 @@ def workflow_record_link(self, obj):
workflow_record = obj.get_workflow_record()
if not workflow_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_provisionnewcustomerworkflow_change", args=(workflow_record.pk,)),
workflow_record.pk,
))
)

@admin.action(description='Re-process the input for this step')
def process_input(self, request, queryset):
Expand Down Expand Up @@ -218,10 +224,11 @@ def preceding_step_link(self, obj):
step_record = obj.get_preceding_step_record()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreatecustomerstep_change", args=(step_record.pk,)),
step_record.pk,
))
)


@admin.register(models.GetCreateCatalogStep)
Expand All @@ -242,10 +249,11 @@ def preceding_step_link(self, obj):
step_record = obj.get_preceding_step_record()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreateenterpriseadminusersstep_change", args=(step_record.pk,)),
step_record.pk,
))
)


@admin.register(models.AssociateAcademyStep)
Expand All @@ -266,10 +274,11 @@ def preceding_step_link(self, obj):
step_record = obj.get_preceding_step_record()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreatecatalogstep_change", args=(step_record.pk,)),
step_record.pk,
))
)


@admin.register(models.GetCreateCustomerAgreementStep)
Expand All @@ -293,10 +302,11 @@ def preceding_step_link(self, obj):
admin_change_url = "admin:provisioning_associateacademystep_change"
if isinstance(step_record, models.GetCreateCatalogStep):
admin_change_url = "admin:provisioning_getcreatecatalogstep_change"
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse(admin_change_url, args=(step_record.pk,)),
step_record.pk,
))
)


@admin.register(models.GetCreateTrialSubscriptionPlanStep)
Expand All @@ -317,10 +327,11 @@ def preceding_step_link(self, obj):
step_record = obj.get_preceding_step_record()
if not step_record:
return None
return mark_safe('<a href="{}">{}</a>'.format(
return format_html(
'<a href="{}">{}</a>',
reverse("admin:provisioning_getcreatecustomeragreementstep_change", args=(step_record.pk,)),
step_record.pk,
))
)


@admin.register(models.GetCreateSubscriptionPlanRenewalStep)
Expand Down
36 changes: 19 additions & 17 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ amqp==5.3.1
# via kombu
analytics-python==1.4.post1
# via -r requirements/base.in
asgiref==3.11.1
asgiref==3.12.1
# via
# django
# django-cors-headers
Expand All @@ -30,9 +30,9 @@ backoff==1.10.0
# via analytics-python
billiard==4.2.4
# via celery
boto3==1.43.40
boto3==1.43.55
# via snowflake-connector-python
botocore==1.43.40
botocore==1.43.55
# via
# boto3
# s3transfer
Expand All @@ -44,15 +44,15 @@ celery==5.6.3
# -r requirements/base.in
# django-celery-results
# edx-celeryutils
certifi==2026.6.17
certifi==2026.7.22
# via
# requests
# snowflake-connector-python
cffi==2.0.0
cffi==2.1.0
# via
# cryptography
# pynacl
charset-normalizer==3.4.7
charset-normalizer==3.4.9
# via
# requests
# snowflake-connector-python
Expand Down Expand Up @@ -88,7 +88,7 @@ defusedxml==0.7.1
# via
# python3-openid
# social-auth-core
django==5.2.15
django==5.2.16
# via
# -c requirements/common_constraints.txt
# -r requirements/base.in
Expand Down Expand Up @@ -138,7 +138,7 @@ django-crum==0.7.9
# edx-toggles
django-extensions==4.1
# via -r requirements/base.in
django-filter==25.2
django-filter==26.1
# via -r requirements/base.in
django-log-request-id==2.1.2
# via -r requirements/base.in
Expand All @@ -148,7 +148,7 @@ django-model-utils==5.0.0
# edx-rbac
django-object-actions==5.1.2
# via -r requirements/base.in
django-simple-history==3.12.0
django-simple-history==3.13.0
# via -r requirements/base.in
django-waffle==5.0.0
# via
Expand All @@ -173,7 +173,7 @@ dnspython==2.8.0
# via pymongo
drf-jwt==1.19.2
# via edx-drf-extensions
drf-spectacular==0.29.0
drf-spectacular==0.30.0
# via -r requirements/base.in
drf-yasg==1.21.15
# via edx-api-doc-tools
Expand Down Expand Up @@ -226,7 +226,7 @@ fastavro==1.12.2
# -r requirements/base.in
# confluent-kafka
# openedx-events
filelock==3.29.4
filelock==3.32.0
# via snowflake-connector-python
idna==3.18
# via
Expand Down Expand Up @@ -271,7 +271,7 @@ packaging==26.2
# drf-yasg
# kombu
# snowflake-connector-python
platformdirs==4.10.0
platformdirs==4.11.0
# via snowflake-connector-python
ply==3.11
# via djangoql
Expand Down Expand Up @@ -343,7 +343,7 @@ rpds-py==2026.6.3
# referencing
rules==3.5
# via -r requirements/base.in
s3transfer==0.19.0
s3transfer==0.19.2
# via boto3
semantic-version==2.10.0
# via edx-drf-extensions
Expand All @@ -355,14 +355,16 @@ six==1.17.0
# edx-django-release-util
# edx-rbac
# python-dateutil
snowflake-connector-python==4.7.0
snowflake-connector-python==4.7.1
# via -r requirements/base.in
social-auth-app-django==5.9.0
# via
# -c requirements/common_constraints.txt
# -c requirements/constraints.txt
# edx-auth-backends
social-auth-core==4.9.1
# via
# -c requirements/common_constraints.txt
# -c requirements/constraints.txt
# edx-auth-backends
# social-auth-app-django
Expand All @@ -375,11 +377,11 @@ stevedore==5.9.0
# code-annotations
# edx-django-utils
# edx-opaque-keys
stripe==15.3.0
stripe==15.3.1
# via -r requirements/base.in
text-unidecode==1.3
# via python-slugify
tomlkit==0.15.0
tomlkit==0.15.1
# via snowflake-connector-python
typing-extensions==4.16.0
# via
Expand All @@ -390,7 +392,7 @@ typing-extensions==4.16.0
# referencing
# snowflake-connector-python
# stripe
tzdata==2026.2
tzdata==2026.3
# via kombu
tzlocal==5.4.4
# via celery
Expand Down
6 changes: 6 additions & 0 deletions requirements/common_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ Django<6.0
# elastic search changelog: https://www.elastic.co/guide/en/enterprise-search/master/release-notes-7.14.0.html
# See https://github.com/openedx/edx-platform/issues/35126 for more info
elasticsearch<7.14.0

# 2026-07-06: Constrain social-auth-* packages to the latest version compatible with
# edx-drf-extensions<=10.6.0. (Newer versions require a POST instead of a GET.)
# Tracking issue: https://github.com/openedx/edx-drf-extensions/issues/561
social-auth-app-django<6.0.0
social-auth-core<5.0.0
Loading
Loading