Skip to content

Commit

Permalink
Merge pull request #330 from brisco17/#294-change-allocation-attributes
Browse files Browse the repository at this point in the history
Allocation Change Flow
  • Loading branch information
aebruno authored Dec 22, 2021
2 parents f282f4e + 526f9d9 commit c490acd
Show file tree
Hide file tree
Showing 18 changed files with 1,658 additions and 12 deletions.
2 changes: 2 additions & 0 deletions coldfront/config/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#------------------------------------------------------------------------------
# Allocation related
#------------------------------------------------------------------------------
ALLOCATION_ENABLE_CHANGE_REQUESTS_BY_DEFAULT = ENV.bool('ALLOCATION_ENABLE_CHANGE_REQUESTS', default=True)
ALLOCATION_CHANGE_REQUEST_EXTENSION_DAYS = ENV.list('ALLOCATION_CHANGE_REQUEST_EXTENSION_DAYS', cast=int, default=[30, 60, 90])
ALLOCATION_ENABLE_ALLOCATION_RENEWAL = ENV.bool('ALLOCATION_ENABLE_ALLOCATION_RENEWAL', default=True)
ALLOCATION_FUNCS_ON_EXPIRE = ['coldfront.core.allocation.utils.test_allocation_function', ]

Expand Down
21 changes: 20 additions & 1 deletion coldfront/core/allocation/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
AllocationAttribute,
AllocationAttributeType,
AllocationAttributeUsage,
AllocationChangeRequest,
AllocationAttributeChangeRequest,
AllocationStatusChoice,
AllocationChangeStatusChoice,
AllocationUser,
AllocationUserNote,
AllocationUserStatusChoice,
Expand Down Expand Up @@ -53,7 +56,7 @@ class AllocationAdmin(SimpleHistoryAdmin):
readonly_fields_change = (
'project', 'justification', 'created', 'modified',)
fields_change = ('project', 'resources', 'quantity', 'justification',
'status', 'start_date', 'end_date', 'description', 'created', 'modified', 'is_locked')
'status', 'start_date', 'end_date', 'description', 'created', 'modified', 'is_locked', 'is_changeable')
list_display = ('pk', 'project_title', 'project_pi', 'resource', 'quantity',
'justification', 'start_date', 'end_date', 'status', 'created', 'modified', )
inlines = [AllocationUserInline,
Expand Down Expand Up @@ -343,3 +346,19 @@ def project_pi(self, obj):
@admin.register(AllocationAccount)
class AllocationAccountAdmin(SimpleHistoryAdmin):
list_display = ('name', 'user', )


@admin.register(AllocationChangeStatusChoice)
class AllocationChangeStatusChoiceAdmin(admin.ModelAdmin):
list_display = ('name', )


@admin.register(AllocationChangeRequest)
class AllocationChangeRequestAdmin(admin.ModelAdmin):
list_display = ('pk', 'allocation', 'status', 'end_date_extension', 'justification', 'notes', )


@admin.register(AllocationAttributeChangeRequest)
class AllocationChangeStatusChoiceAdmin(admin.ModelAdmin):
list_display = ('pk', 'allocation_change_request', 'allocation_attribute', 'new_value', )

76 changes: 76 additions & 0 deletions coldfront/core/allocation/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from coldfront.core.allocation.models import (Allocation, AllocationAccount,
AllocationAttributeType,
AllocationAttribute,
AllocationStatusChoice)
from coldfront.core.allocation.utils import get_user_resources
from coldfront.core.project.models import Project
Expand All @@ -11,6 +12,8 @@

ALLOCATION_ACCOUNT_ENABLED = import_from_settings(
'ALLOCATION_ACCOUNT_ENABLED', False)
ALLOCATION_CHANGE_REQUEST_EXTENSION_DAYS = import_from_settings(
'ALLOCATION_CHANGE_REQUEST_EXTENSION_DAYS', [])


class AllocationForm(forms.Form):
Expand Down Expand Up @@ -64,6 +67,7 @@ class AllocationUpdateForm(forms.Form):
description = forms.CharField(max_length=512,
label='Description',
required=False)
is_changeable = forms.BooleanField(required=False)

def clean(self):
cleaned_data = super().clean()
Expand Down Expand Up @@ -174,3 +178,75 @@ class AllocationAccountForm(forms.ModelForm):
class Meta:
model = AllocationAccount
fields = ['name', ]


class AllocationAttributeChangeForm(forms.Form):
pk = forms.IntegerField(required=False, disabled=True)
name = forms.CharField(max_length=150, required=False, disabled=True)
value = forms.CharField(max_length=150, required=False, disabled=True)
new_value = forms.CharField(max_length=150, required=False, disabled=False)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['pk'].widget = forms.HiddenInput()

def clean(self):
cleaned_data = super().clean()

if cleaned_data.get('new_value') != "":
allocation_attribute = AllocationAttribute.objects.get(pk=cleaned_data.get('pk'))
allocation_attribute.value = cleaned_data.get('new_value')
allocation_attribute.clean()


class AllocationAttributeUpdateForm(forms.Form):
change_pk = forms.IntegerField(required=False, disabled=True)
attribute_pk = forms.IntegerField(required=False, disabled=True)
name = forms.CharField(max_length=150, required=False, disabled=True)
value = forms.CharField(max_length=150, required=False, disabled=True)
new_value = forms.CharField(max_length=150, required=False, disabled=False)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['change_pk'].widget = forms.HiddenInput()
self.fields['attribute_pk'].widget = forms.HiddenInput()

def clean(self):
cleaned_data = super().clean()
allocation_attribute = AllocationAttribute.objects.get(pk=cleaned_data.get('attribute_pk'))

allocation_attribute.value = cleaned_data.get('new_value')
allocation_attribute.clean()


class AllocationChangeForm(forms.Form):
EXTENSION_CHOICES = [
(0, "No Extension")
]
for choice in ALLOCATION_CHANGE_REQUEST_EXTENSION_DAYS:
EXTENSION_CHOICES.append((choice, "{} days".format(choice)))

end_date_extension = forms.TypedChoiceField(
label='Request End Date Extension',
choices = EXTENSION_CHOICES,
coerce=int,
required=False,
empty_value=0,)
justification = forms.CharField(
label='Justification for Changes',
widget=forms.Textarea,
required=False,
help_text='Justification for requesting this allocation change request.')

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)


class AllocationChangeNoteForm(forms.Form):
notes = forms.CharField(
max_length=512,
label='Notes',
required=False,
widget=forms.Textarea,
help_text="Leave any feedback about the allocation change request.")

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from coldfront.core.allocation.models import (AttributeType,
AllocationAttributeType,
AllocationStatusChoice,
AllocationChangeStatusChoice,
AllocationUserStatusChoice)


Expand All @@ -20,6 +21,9 @@ def handle(self, *args, **options):
'Renewal Requested', 'Revoked', 'Unpaid',):
AllocationStatusChoice.objects.get_or_create(name=choice)

for choice in ('Pending', 'Approved', 'Denied',):
AllocationChangeStatusChoice.objects.get_or_create(name=choice)

for choice in ('Active', 'Error', 'Removed', ):
AllocationUserStatusChoice.objects.get_or_create(name=choice)

Expand Down
135 changes: 135 additions & 0 deletions coldfront/core/allocation/migrations/0004_auto_20211102_1017.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Generated by Django 2.2.18 on 2021-11-02 14:17

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),
('allocation', '0003_auto_20191018_1049'),
]

operations = [
migrations.CreateModel(
name='AllocationChangeRequest',
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')),
('end_date_extension', models.IntegerField(blank=True, null=True)),
('justification', models.TextField()),
('notes', models.CharField(blank=True, max_length=512, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='AllocationChangeStatusChoice',
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')),
('name', models.CharField(max_length=64)),
],
options={
'ordering': ['name'],
},
),
migrations.AddField(
model_name='allocation',
name='is_changeable',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='allocationattributetype',
name='is_changeable',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='historicalallocation',
name='is_changeable',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='historicalallocationattributetype',
name='is_changeable',
field=models.BooleanField(default=False),
),
migrations.CreateModel(
name='HistoricalAllocationChangeRequest',
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')),
('end_date_extension', models.IntegerField(blank=True, null=True)),
('justification', models.TextField()),
('notes', models.CharField(blank=True, max_length=512, 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)),
('allocation', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='allocation.Allocation')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('status', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='allocation.AllocationChangeStatusChoice', verbose_name='Status')),
],
options={
'verbose_name': 'historical allocation change request',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalAllocationAttributeChangeRequest',
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')),
('new_value', models.CharField(max_length=128)),
('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)),
('allocation_attribute', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='allocation.AllocationAttribute')),
('allocation_change_request', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='allocation.AllocationChangeRequest')),
('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 allocation attribute change request',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.AddField(
model_name='allocationchangerequest',
name='allocation',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='allocation.Allocation'),
),
migrations.AddField(
model_name='allocationchangerequest',
name='status',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='allocation.AllocationChangeStatusChoice', verbose_name='Status'),
),
migrations.CreateModel(
name='AllocationAttributeChangeRequest',
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')),
('new_value', models.CharField(max_length=128)),
('allocation_attribute', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='allocation.AllocationAttribute')),
('allocation_change_request', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='allocation.AllocationChangeRequest')),
],
options={
'abstract': False,
},
),
]
20 changes: 20 additions & 0 deletions coldfront/core/allocation/migrations/0005_auto_20211117_1413.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 2.2.24 on 2021-11-17 19:13

from django.db import migrations


def create_status_choices(apps, schema_editor):
AllocationChangeStatusChoice = apps.get_model('allocation', "AllocationChangeStatusChoice")
for choice in ('Pending', 'Approved', 'Denied',):
AllocationChangeStatusChoice.objects.get_or_create(name=choice)


class Migration(migrations.Migration):

dependencies = [
('allocation', '0004_auto_20211102_1017'),
]

operations = [
migrations.RunPython(create_status_choices),
]
Loading

0 comments on commit c490acd

Please sign in to comment.