Skip to content

Commit

Permalink
feat: adds a LicenseTransferJob model and admin
Browse files Browse the repository at this point in the history
Also installs django-autocomplete-light for help to support
advanced admin autocomplete field filtering, and therefore
runs make upgrade to pull in some other new package versions.
  • Loading branch information
iloveagent57 committed Oct 23, 2023
1 parent 9335ec3 commit 25c78c4
Show file tree
Hide file tree
Showing 18 changed files with 503 additions and 82 deletions.
54 changes: 54 additions & 0 deletions license_manager/apps/subscriptions/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
from license_manager.apps.subscriptions.exceptions import CustomerAgreementError
from license_manager.apps.subscriptions.forms import (
CustomerAgreementAdminForm,
LicenseTransferJobAdminForm,
ProductForm,
SubscriptionPlanForm,
SubscriptionPlanRenewalForm,
)
from license_manager.apps.subscriptions.models import (
CustomerAgreement,
License,
LicenseTransferJob,
Notification,
PlanType,
Product,
Expand Down Expand Up @@ -657,3 +659,55 @@ class NotificationAdmin(admin.ModelAdmin):

def has_change_permission(self, request, obj=None):
return False


@admin.register(LicenseTransferJob)
class LicenseTransferJobAdmin(admin.ModelAdmin):
form = LicenseTransferJobAdminForm

list_display = (
'id',
'customer_agreement',
'old_subscription_plan',
'new_subscription_plan',
'completed_at',
'is_dry_run',
)

list_filter = (
'is_dry_run',
)

search_fields = (
'customer_agreement__enterprise_customer_uuid__startswith',
'customer_agreement__enterprise_customer_slug__startswith',
'customer_agreement__enterprise_customer_name__startswith',
'old_subscription_plan',
'new_subscription_plan',
)

sortable_by = (
'id',
'completed_at',
'is_dry_run',
'customer_agreement',
)

readonly_fields = (
'completed_at',
'dry_run_results',
)

actions = ['process_transfer_jobs']

def get_queryset(self, request):
return super().get_queryset(request).select_related(
'customer_agreement',
'old_subscription_plan',
'new_subscription_plan',
)

@admin.action(description="Process selected license transfer jobs")
def process_transfer_jobs(self, request, queryset):
for transfer_job in queryset:
transfer_job.process()
41 changes: 41 additions & 0 deletions license_manager/apps/subscriptions/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import logging

from dal import autocomplete
from django import forms
from django.conf import settings
from django.utils.translation import gettext as _
Expand All @@ -22,6 +23,7 @@
)
from license_manager.apps.subscriptions.models import (
CustomerAgreement,
LicenseTransferJob,
Product,
SubscriptionPlan,
SubscriptionPlanRenewal,
Expand Down Expand Up @@ -401,3 +403,42 @@ def is_valid(self):
return False

return True


class LicenseTransferJobAdminForm(forms.ModelForm):
class Meta:
model = LicenseTransferJob
fields = '__all__'
# Use django-autocomplete-light to filter the available
# subscription_plan choices to only those related to
# the selected customer agreement. Works for both
# records that don't yet exist (on transfer job creation)
# and for modification of existing transfer job records.
# See urls_admin.py for the view that does this filtering,
# and see static/filtered_subscription_admin.js for
# the jQuery code that clears subscription plan selections
# when the selected customer agreement is changed.
widgets = {
'old_subscription_plan': autocomplete.ModelSelect2(
url='filtered_subscription_plan_admin',
# forward the customer_agreement field's value
# into our custom autocomplete field in urls_admin.py
forward=['customer_agreement'],
),
'new_subscription_plan': autocomplete.ModelSelect2(
url='filtered_subscription_plan_admin',
# forward the customer_agreement field's value
# into our custom autocomplete field in urls_admin.py
forward=['customer_agreement'],
),
}

readonly_fields = (
'completed_at',
'dry_run_results',
)

class Media:
js = (
'filtered_subscription_admin.js',
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Generated by Django 4.2.6 on 2023-10-23 15:30

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):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('subscriptions', '0061_auto_20230927_1119'),
]

operations = [
migrations.CreateModel(
name='LicenseTransferJob',
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')),
('completed_at', models.DateTimeField(blank=True, help_text='The time at which the job was successfully processed.', null=True)),
('notes', models.TextField(blank=True, help_text='Say something about why the licenses are being transferred.', null=True)),
('is_dry_run', models.BooleanField(default=False)),
('delimiter', models.CharField(choices=[('newline', 'Newline character'), ('comma', 'Comma character'), ('pipe', 'Pipe character')], default='newline', max_length=8)),
('license_uuids_raw', models.TextField(help_text='Delimitted list of license_uuids to transfer')),
('dry_run_results', models.TextField(blank=True, help_text='Raw results of what licenses would have changed if this was not a dry run', null=True)),
('customer_agreement', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='license_transfer_jobs', to='subscriptions.customeragreement')),
('new_subscription_plan', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='license_transfer_jobs_new', to='subscriptions.subscriptionplan')),
('old_subscription_plan', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='license_transfer_jobs_old', to='subscriptions.subscriptionplan')),
],
options={
'verbose_name': 'License Transfer Job',
'verbose_name_plural': 'License Transfer Jobs',
},
),
migrations.CreateModel(
name='HistoricalLicenseTransferJob',
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')),
('completed_at', models.DateTimeField(blank=True, help_text='The time at which the job was successfully processed.', null=True)),
('notes', models.TextField(blank=True, help_text='Say something about why the licenses are being transferred.', null=True)),
('is_dry_run', models.BooleanField(default=False)),
('delimiter', models.CharField(choices=[('newline', 'Newline character'), ('comma', 'Comma character'), ('pipe', 'Pipe character')], default='newline', max_length=8)),
('license_uuids_raw', models.TextField(help_text='Delimitted list of license_uuids to transfer')),
('dry_run_results', models.TextField(blank=True, help_text='Raw results of what licenses would have changed if this was not a dry run', null=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)),
('customer_agreement', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='subscriptions.customeragreement')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('new_subscription_plan', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='subscriptions.subscriptionplan')),
('old_subscription_plan', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='subscriptions.subscriptionplan')),
],
options={
'verbose_name': 'historical License Transfer Job',
'verbose_name_plural': 'historical License Transfer Jobs',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]
Loading

0 comments on commit 25c78c4

Please sign in to comment.