Skip to content

Commit

Permalink
ubccr#294: Allocation change flow complete
Browse files Browse the repository at this point in the history
  • Loading branch information
brisco17 committed Oct 29, 2021
1 parent 0944bd6 commit 751f4c6
Show file tree
Hide file tree
Showing 17 changed files with 1,168 additions and 225 deletions.
19 changes: 19 additions & 0 deletions 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 @@ -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', )

65 changes: 49 additions & 16 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 Down Expand Up @@ -96,22 +97,6 @@ class AllocationRemoveUserForm(forms.Form):
email = forms.EmailField(max_length=100, required=False, disabled=True)
selected = forms.BooleanField(initial=False, required=False)

class AllocationAttributeChangeForm(forms.Form):
username = forms.CharField(max_length=150, disabled=True)
first_name = forms.CharField(max_length=30, required=False, disabled=True)
last_name = forms.CharField(max_length=150, required=False, disabled=True)
# attribute = forms.ModelChoiceField(queryset=None, empty_label=None)
# change = forms.CharField(widget=forms.Textarea)
# justification = forms.CharField(widget=forms.Textarea)
# allocation_account = forms.ChoiceField(required=False)

# def __init__(self, pk, *args, **kwargs):
# super().__init__(*args, **kwargs)
# allocation_obj = get_object_or_404(Allocation, pk=pk)

# self.fields['change'].help_text = '<br/>Desired change for this attribute.'
# self.fields['justification'].help_text = '<br/>Justification for requesting this allocation.'


class AllocationAttributeDeleteForm(forms.Form):
pk = forms.IntegerField(required=False, disabled=True)
Expand Down Expand Up @@ -190,3 +175,51 @@ 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 AllocationChangeForm(forms.Form):
EXTENSION_CHOICES = [
(0, "----"), (30, "30 days"), (60, "60 days"), (90, "90 days")
]
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,
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
10 changes: 0 additions & 10 deletions coldfront/core/allocation/migrations/0003_auto_20191018_1049.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,4 @@ class Migration(migrations.Migration):
name='is_locked',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='allocation',
name='is_changeable',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='historicalallocation',
name='is_changeable',
field=models.BooleanField(default=False),
),
]
125 changes: 125 additions & 0 deletions coldfront/core/allocation/migrations/0004_auto_20211029_0412.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Generated by Django 2.2.18 on 2021-10-29 08:12

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='historicalallocation',
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,
},
),
]
42 changes: 38 additions & 4 deletions coldfront/core/allocation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,19 +240,19 @@ def clean(self):

if expected_value_type == "Int" and not isinstance(literal_eval(self.value), int):
raise ValidationError(
'Invalid Value "%s". Value must be an integer.' % (self.value))
'Invalid Value "%s" for "%s". Value must be an integer.' % (self.value, self.allocation_attribute_type.name))
elif expected_value_type == "Float" and not (isinstance(literal_eval(self.value), float) or isinstance(literal_eval(self.value), int)):
raise ValidationError(
'Invalid Value "%s". Value must be a float.' % (self.value))
'Invalid Value "%s" for "%s". Value must be a float.' % (self.value, self.allocation_attribute_type.name))
elif expected_value_type == "Yes/No" and self.value not in ["Yes", "No"]:
raise ValidationError(
'Invalid Value "%s". Allowed inputs are "Yes" or "No".' % (self.value))
'Invalid Value "%s" for "%s". Allowed inputs are "Yes" or "No".' % (self.value, self.allocation_attribute_type.name))
elif expected_value_type == "Date":
try:
datetime.datetime.strptime(self.value.strip(), "%Y-%m-%d")
except ValueError:
raise ValidationError(
'Invalid Value "%s". Date must be in format YYYY-MM-DD' % (self.value))
'Invalid Value "%s" for "%s". Date must be in format YYYY-MM-DD' % (self.value, self.allocation_attribute_type.name))

def __str__(self):
return '%s' % (self.allocation_attribute_type.name)
Expand Down Expand Up @@ -304,3 +304,37 @@ def __str__(self):

class Meta:
ordering = ['name', ]


class AllocationChangeStatusChoice(TimeStampedModel):
name = models.CharField(max_length=64)

def __str__(self):
return self.name

class Meta:
ordering = ['name', ]


class AllocationChangeRequest(TimeStampedModel):
allocation = models.ForeignKey(Allocation, on_delete=models.CASCADE,)
status = models.ForeignKey(
AllocationChangeStatusChoice, on_delete=models.CASCADE, verbose_name='Status')
end_date_extension = models.IntegerField(blank=True, null=True)
justification = models.TextField()
notes = models.CharField(max_length=512, blank=True, null=True)
history = HistoricalRecords()

def __str__(self):
return "%s (%s)" % (self.get_parent_resource.name, self.allocation.project.pi)


class AllocationAttributeChangeRequest(TimeStampedModel):
allocation_change_request = models.ForeignKey(AllocationChangeRequest, on_delete=models.CASCADE)
allocation_attribute = models.ForeignKey(AllocationAttribute, on_delete=models.CASCADE)
new_value = models.CharField(max_length=128)
history = HistoricalRecords()

def __str__(self):
return '%s' % (self.allocation_attribute.allocation_attribute_type.name)

This file was deleted.

Loading

0 comments on commit 751f4c6

Please sign in to comment.