aboutsummaryrefslogtreecommitdiffstats
path: root/ctrack/caf
diff options
context:
space:
mode:
authorMatthew Lemon <matt@matthewlemon.com>2020-09-02 12:04:19 +0100
committerMatthew Lemon <matt@matthewlemon.com>2020-09-02 12:04:19 +0100
commitedd91cb77191b386af95dfaca0b2706c7ee143b9 (patch)
treeb94edf8e069911d0aea4e1acfc23a72a180cb2cf /ctrack/caf
parent15c89a78c097dc00ad7b8ca3314581ed3b058187 (diff)
parentc406d3da83d20d65c2fc4da7d5d4d5db0f6ad115 (diff)
Merge branch 'db_rewrite' into master
Diffstat (limited to 'ctrack/caf')
-rw-r--r--ctrack/caf/admin.py47
-rw-r--r--ctrack/caf/forms.py38
-rw-r--r--ctrack/caf/managers.py12
-rw-r--r--ctrack/caf/migrations/0001_initial.py66
-rw-r--r--ctrack/caf/migrations/0002_auto_20200403_1407.py58
-rw-r--r--ctrack/caf/migrations/0002_caf_systems.py18
-rw-r--r--ctrack/caf/migrations/0003_auto_20200424_1924.py18
-rw-r--r--ctrack/caf/migrations/0004_auto_20200813_0953.py31
-rw-r--r--ctrack/caf/migrations/0005_applicablesystem_oes_categorisation.py18
-rw-r--r--ctrack/caf/migrations/0006_auto_20200813_1125.py22
-rw-r--r--ctrack/caf/migrations/0007_auto_20200814_1230.py23
-rw-r--r--ctrack/caf/migrations/0008_auto_20200814_1318.py23
-rw-r--r--ctrack/caf/models.py66
-rw-r--r--ctrack/caf/templates/caf/applicablesystem_detail.html39
-rw-r--r--ctrack/caf/templates/caf/caf_detail.html2
-rw-r--r--ctrack/caf/tests/factories.py3
-rw-r--r--ctrack/caf/views.py16
17 files changed, 196 insertions, 304 deletions
diff --git a/ctrack/caf/admin.py b/ctrack/caf/admin.py
index f19e8f4..5513781 100644
--- a/ctrack/caf/admin.py
+++ b/ctrack/caf/admin.py
@@ -1,31 +1,56 @@
from django.contrib import admin
-from .models import CAF, FileStore, DocumentFile, Grading, ApplicableSystem
+from .models import (
+ CAF,
+ FileStore,
+ DocumentFile,
+ Grading,
+ ApplicableSystem,
+ EssentialService,
+)
+
+
+def get_system_org(obj):
+ es = obj.essentialservice_set.first() # just get the first if there are many
+ return es.organisation.name
+
+
+get_system_org.short_description = "Organisation"
+
+
+class EssentialServiceAdmin(admin.ModelAdmin):
+ model = EssentialService
class ApplicableSystemListAdmin(admin.ModelAdmin):
model = ApplicableSystem
- list_display = ["name", "organisation", "caf"]
+ list_display = ["name", get_system_org, "function"]
-class ApplicableSystemAdmin(admin.StackedInline):
- model = ApplicableSystem
- max_num = 3
- extra = 1
+# FIXME
+# class ApplicableSystemAdmin(admin.StackedInline):
+# model = ApplicableSystem
+# max_num = 3
+# extra = 1
-def get_caf_name(obj):
- ass = ApplicableSystem.objects.filter(caf=obj).first()
- return f"{ass.organisation.name}_v{obj.version}"
+# FIXME - NOT NEEDED
+# def get_caf_name(obj):
+# ass = ApplicableSystem.objects.filter(caf=obj).first()
+# return f"{ass.organisation.name}_v{obj.version}"
+# FIXME
class CAFAdmin(admin.ModelAdmin):
model = CAF
- inlines = [ApplicableSystemAdmin]
- list_display = [get_caf_name, "quality_grading", "confidence_grading", "file"]
+ # inlines = [ApplicableSystemAdmin]
+
+
+# list_display = ["quality_grading", "confidence_grading", "file"]
admin.site.register(CAF, CAFAdmin)
+admin.site.register(EssentialService, EssentialServiceAdmin)
admin.site.register(FileStore)
admin.site.register(DocumentFile)
admin.site.register(Grading)
diff --git a/ctrack/caf/forms.py b/ctrack/caf/forms.py
index 7367ccd..8e3d8ee 100644
--- a/ctrack/caf/forms.py
+++ b/ctrack/caf/forms.py
@@ -12,12 +12,13 @@ from django import forms
from django.forms import inlineformset_factory
from django.urls import reverse
-from ctrack.caf.models import CAF, ApplicableSystem
+from ctrack.caf.models import CAF, ApplicableSystem, EssentialService
from ctrack.organisations.models import Organisation
-CAFCreateInlineFormset = inlineformset_factory(
- CAF, ApplicableSystem, fields=("name", "organisation"), extra=2
-)
+# TODO - Replace this to get inlineformet working
+# CAFCreateInlineFormset = inlineformset_factory(
+# CAF, ApplicableSystem, fields=("name", "organisation"), extra=2
+# )
class ApplicableSystemCreateFromCafForm(forms.Form):
@@ -77,13 +78,14 @@ class ApplicableSystemCreateFromCafForm(forms.Form):
class ApplicableSystemCreateFromOrgForm(forms.Form):
name = forms.CharField(max_length=255)
function = forms.CharField(widget=forms.Textarea)
- organisation = forms.ModelChoiceField(queryset=Organisation.objects.all())
- caf = forms.ModelChoiceField(queryset=CAF.objects.all())
- essential_service = forms.CharField(
- widget=forms.Textarea,
- max_length=255,
- help_text="Description of the essential service which the system suppports.",
- )
+ # organisation = forms.ModelChoiceField(queryset=Organisation.objects.all())
+ # caf = forms.ModelChoiceField(queryset=CAF.objects.all())
+ # essential_service = forms.CharField(
+ # widget=forms.Textarea,
+ # max_length=255,
+ # help_text="Description of the essential service which the system suppports.",
+ # )
+ essential_service = forms.ModelChoiceField(queryset=EssentialService.objects.all())
dft_categorisation = forms.ChoiceField(
choices=ApplicableSystem.SYSTEM_CATEGORISATION,
help_text="Refer to documentation for description of these criteria",
@@ -93,16 +95,19 @@ class ApplicableSystemCreateFromOrgForm(forms.Form):
help_text="Categorisation based on OES' own internal prioritisation process.",
)
- def __init__(self, org_id, slug, org_name, org_cafs, *args, **kwargs):
+ def __init__(self, org_id, slug, org_name, *args, **kwargs):
super().__init__(*args, **kwargs)
cancel_redirect = reverse("organisations:detail", args=[slug])
# we need to create the choices we can use for the CAF dropdown in the form
- self.fields["caf"].queryset = CAF.objects.filter(
- pk__in=[caf.pk for caf in org_cafs]
- )
- self.fields["caf"].label = "CAF"
+ # self.fields["caf"].queryset = CAF.objects.filter(
+ # pk__in=[caf.pk for caf in org_cafs]
+ # )
+ # self.fields["caf"].label = "CAF"
self.fields["dft_categorisation"].label = "DfT Categorisation"
self.fields["oes_categorisation"].label = "OES Categorisation"
+ self.fields["essential_service"].queryset = EssentialService.objects.filter(
+ pk=org_id
+ )
self.helper = FormHelper(self)
self.helper.layout = Layout(
Fieldset(
@@ -113,7 +118,6 @@ class ApplicableSystemCreateFromOrgForm(forms.Form):
"dft_categorisation",
"oes_categorisation",
Hidden("organisation", org_id),
- "caf",
),
ButtonHolder(
Submit("submit", "Submit", css_class="btn-primary"),
diff --git a/ctrack/caf/managers.py b/ctrack/caf/managers.py
index cba8c83..4d8c134 100644
--- a/ctrack/caf/managers.py
+++ b/ctrack/caf/managers.py
@@ -1,8 +1,8 @@
from django.db import connection
from django.db import models
-import ctrack.caf.models # to deal with circular import
-from ctrack.organisations.models import Organisation, Person
+import ctrack.caf.models as caf_models # to deal with circular import
+import ctrack.organisations.models as org_models
class ApplicableSystemManager(models.Manager):
@@ -16,14 +16,16 @@ class ApplicableSystemManager(models.Manager):
Using Custom Managers Django docs for an example.
"""
with connection.cursor() as cursor:
- cursor.execute("""
+ cursor.execute(
+ """
SELECT a.id, a.name, o.id, c.id, sm.id, p.id, o.name
FROM caf_applicablesystem a, organisations_organisation o, organisations_person p, caf_caf c, organisations_submode sm
WHERE a.organisation_id = o.id AND a.caf_id = c.id AND p.organisation_id = o.id AND o.submode_id = sm.id AND p.primary_nis_contact = True;
- """)
+ """
+ )
result_list = []
for row in cursor.fetchall():
- org = Organisation.objects.get(pk=row[2])
+ org = org_models.Organisation.objects.get(pk=row[3])
caf = ctrack.caf.models.CAF.objects.get(pk=row[3])
ass = self.model(id=row[0], name=row[1], organisation=org, caf=caf)
ass.nis_contact = Person.objects.get(pk=row[5])
diff --git a/ctrack/caf/migrations/0001_initial.py b/ctrack/caf/migrations/0001_initial.py
index 5e184df..ca65af6 100644
--- a/ctrack/caf/migrations/0001_initial.py
+++ b/ctrack/caf/migrations/0001_initial.py
@@ -1,6 +1,8 @@
-# Generated by Django 2.2.9 on 2020-04-03 14:07
+# Generated by Django 2.2.12 on 2020-08-27 09:40
+import ctrack.caf.models
from django.db import migrations, models
+import django.db.models.deletion
class Migration(migrations.Migration):
@@ -8,6 +10,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
+ ('organisations', '0001_initial'),
]
operations = [
@@ -15,49 +18,68 @@ class Migration(migrations.Migration):
name='ApplicableSystem',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('name', models.CharField(max_length=256)),
- ('description', models.TextField(max_length=1000)),
+ ('name', models.CharField(help_text='System name assigned by OES', max_length=256)),
+ ('function', models.TextField(blank=True, help_text='How the system is relevant to delivering or supporting the essential service', max_length=1000, null=True)),
+ ('dft_categorisation', models.CharField(choices=[('CR', 'Critical'), ('IM', 'Important (Legacy use only)')], default='CR', help_text='Refer to documentation for description of these criteria', max_length=2, verbose_name='DfT Categorisation')),
+ ('oes_categorisation', models.CharField(default='NA', help_text="Categorisation based on OES' own internal prioritisation process.", max_length=255, verbose_name='OES Categorisation')),
],
options={
- 'verbose_name': 'Applicable System',
+ 'verbose_name': 'NIS System',
},
),
migrations.CreateModel(
- name='CAF',
+ name='Grading',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('version', models.CharField(blank=True, max_length=10, null=True)),
- ('triage_review_date', models.DateField(blank=True, null=True)),
- ('comments', models.TextField(max_length=1000)),
+ ('descriptor', models.CharField(help_text='Q1, C1, etc', max_length=2)),
+ ('description', models.TextField(max_length=250)),
+ ('type', models.CharField(choices=[('CONFIDENCE', 'Confidence'), ('QUALITY', 'Quality'), ('MISC', 'Misc')], help_text='Type of grading', max_length=20)),
],
- options={
- 'verbose_name': 'CAF',
- },
),
migrations.CreateModel(
- name='DocumentFile',
+ name='FileStore',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('name', models.CharField(max_length=255)),
- ('type', models.IntegerField(choices=[(1, 'Excel'), (2, 'Word'), (3, 'PDF'), (4, 'Hard Copy')], default=1)),
+ ('descriptor', models.CharField(max_length=100)),
+ ('virtual_location', models.CharField(help_text='USB, Rosa, email, etc', max_length=100)),
+ ('physical_location', models.CharField(blank=True, help_text='Cupboard, room, building, etc', max_length=100)),
+ ('physical_location_organisation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='organisations.Organisation')),
],
),
migrations.CreateModel(
- name='FileStore',
+ name='EssentialService',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('descriptor', models.CharField(max_length=100)),
- ('virtual_location', models.CharField(help_text='USB, Rosa, email, etc', max_length=100)),
- ('physical_location', models.CharField(blank=True, help_text='Cupboard, room, building, etc', max_length=100)),
+ ('name', models.CharField(max_length=256)),
+ ('description', models.CharField(max_length=512)),
+ ('organisation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='organisations.Organisation')),
+ ('systems', models.ManyToManyField(to='caf.ApplicableSystem')),
],
),
migrations.CreateModel(
- name='Grading',
+ name='DocumentFile',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('descriptor', models.CharField(help_text='Q1, C1, etc', max_length=2)),
- ('description', models.TextField(max_length=250)),
- ('type', models.CharField(choices=[('CONFIDENCE', 'Confidence'), ('QUALITY', 'Quality'), ('MISC', 'Misc')], help_text='Type of grading', max_length=20)),
+ ('name', models.CharField(max_length=255)),
+ ('type', models.IntegerField(choices=[(1, 'Excel'), (2, 'Word'), (3, 'PDF'), (4, 'Hard Copy')], default=1)),
+ ('file_store_location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='caf.FileStore')),
],
),
+ migrations.CreateModel(
+ name='CAF',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('version', models.CharField(blank=True, max_length=10, null=True)),
+ ('triage_review_date', models.DateField(blank=True, null=True)),
+ ('comments', models.TextField(max_length=1000)),
+ ('confidence_grading', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='confidence_grading', to='caf.Grading')),
+ ('file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='caf.DocumentFile')),
+ ('organisation', models.ForeignKey(on_delete=models.SET(ctrack.caf.models.CAF.get_sentinel_org), to='organisations.Organisation')),
+ ('quality_grading', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='quality_grading', to='caf.Grading')),
+ ('triage_review_inspector', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='organisations.Person')),
+ ],
+ options={
+ 'verbose_name': 'CAF',
+ },
+ ),
]
diff --git a/ctrack/caf/migrations/0002_auto_20200403_1407.py b/ctrack/caf/migrations/0002_auto_20200403_1407.py
deleted file mode 100644
index e5963d5..0000000
--- a/ctrack/caf/migrations/0002_auto_20200403_1407.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Generated by Django 2.2.9 on 2020-04-03 14:07
-
-import ctrack.caf.models
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- initial = True
-
- dependencies = [
- ('caf', '0001_initial'),
- ('organisations', '0001_initial'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='filestore',
- name='physical_location_organisation',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='organisations.Organisation'),
- ),
- migrations.AddField(
- model_name='documentfile',
- name='file_store_location',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='caf.FileStore'),
- ),
- migrations.AddField(
- model_name='caf',
- name='confidence_grading',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='confidence_grading', to='caf.Grading'),
- ),
- migrations.AddField(
- model_name='caf',
- name='file',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='caf.DocumentFile'),
- ),
- migrations.AddField(
- model_name='caf',
- name='quality_grading',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='quality_grading', to='caf.Grading'),
- ),
- migrations.AddField(
- model_name='caf',
- name='triage_review_inspector',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='organisations.Person'),
- ),
- migrations.AddField(
- model_name='applicablesystem',
- name='caf',
- field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='applicable_systems', to='caf.CAF'),
- ),
- migrations.AddField(
- model_name='applicablesystem',
- name='organisation',
- field=models.ForeignKey(on_delete=models.SET(ctrack.caf.models.ApplicableSystem.get_sentinel_org), to='organisations.Organisation'),
- ),
- ]
diff --git a/ctrack/caf/migrations/0002_caf_systems.py b/ctrack/caf/migrations/0002_caf_systems.py
new file mode 100644
index 0000000..9e0f76a
--- /dev/null
+++ b/ctrack/caf/migrations/0002_caf_systems.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.2.12 on 2020-08-27 12:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('caf', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='caf',
+ name='systems',
+ field=models.ManyToManyField(to='caf.ApplicableSystem'),
+ ),
+ ]
diff --git a/ctrack/caf/migrations/0003_auto_20200424_1924.py b/ctrack/caf/migrations/0003_auto_20200424_1924.py
deleted file mode 100644
index 34613c6..0000000
--- a/ctrack/caf/migrations/0003_auto_20200424_1924.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 2.2.9 on 2020-04-24 19:24
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('caf', '0002_auto_20200403_1407'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='applicablesystem',
- name='description',
- field=models.TextField(blank=True, max_length=1000, null=True),
- ),
- ]
diff --git a/ctrack/caf/migrations/0004_auto_20200813_0953.py b/ctrack/caf/migrations/0004_auto_20200813_0953.py
deleted file mode 100644
index ad1ca96..0000000
--- a/ctrack/caf/migrations/0004_auto_20200813_0953.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Generated by Django 2.2.12 on 2020-08-13 09:53
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('caf', '0003_auto_20200424_1924'),
- ]
-
- operations = [
- migrations.AlterModelOptions(
- name='applicablesystem',
- options={'verbose_name': 'NIS System'},
- ),
- migrations.RemoveField(
- model_name='applicablesystem',
- name='description',
- ),
- migrations.AddField(
- model_name='applicablesystem',
- name='function',
- field=models.TextField(blank=True, help_text='How the system is relevant to delivering or supporting the essential service', max_length=1000, null=True),
- ),
- migrations.AlterField(
- model_name='applicablesystem',
- name='name',
- field=models.CharField(help_text='System name assigned by OES', max_length=256),
- ),
- ]
diff --git a/ctrack/caf/migrations/0005_applicablesystem_oes_categorisation.py b/ctrack/caf/migrations/0005_applicablesystem_oes_categorisation.py
deleted file mode 100644
index dc8c928..0000000
--- a/ctrack/caf/migrations/0005_applicablesystem_oes_categorisation.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 2.2.12 on 2020-08-13 11:17
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('caf', '0004_auto_20200813_0953'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='applicablesystem',
- name='oes_categorisation',
- field=models.CharField(choices=[('CR', 'Critical'), ('IM', 'Important')], default='CR', max_length=2),
- ),
- ]
diff --git a/ctrack/caf/migrations/0006_auto_20200813_1125.py b/ctrack/caf/migrations/0006_auto_20200813_1125.py
deleted file mode 100644
index 1e97dff..0000000
--- a/ctrack/caf/migrations/0006_auto_20200813_1125.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Generated by Django 2.2.12 on 2020-08-13 11:25
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('caf', '0005_applicablesystem_oes_categorisation'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='applicablesystem',
- name='oes_categorisation',
- ),
- migrations.AddField(
- model_name='applicablesystem',
- name='dft_categorisation',
- field=models.CharField(choices=[('CR', 'Critical'), ('IM', 'Important')], default='CR', help_text='Refer to documentation for description of these criteria', max_length=2, verbose_name='DfT Categorisation'),
- ),
- ]
diff --git a/ctrack/caf/migrations/0007_auto_20200814_1230.py b/ctrack/caf/migrations/0007_auto_20200814_1230.py
deleted file mode 100644
index 68a12bd..0000000
--- a/ctrack/caf/migrations/0007_auto_20200814_1230.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Generated by Django 2.2.12 on 2020-08-14 12:30
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('caf', '0006_auto_20200813_1125'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='applicablesystem',
- name='oes_categorisation',
- field=models.CharField(default='', help_text="Categorisation based on OES' own internal prioritisation process.", max_length=255, verbose_name='OES Categorisation'),
- ),
- migrations.AlterField(
- model_name='applicablesystem',
- name='dft_categorisation',
- field=models.CharField(choices=[('CR', 'Critical'), ('IM', 'Important (Legacy use only)')], default='CR', help_text='Refer to documentation for description of these criteria', max_length=2, verbose_name='DfT Categorisation'),
- ),
- ]
diff --git a/ctrack/caf/migrations/0008_auto_20200814_1318.py b/ctrack/caf/migrations/0008_auto_20200814_1318.py
deleted file mode 100644
index 90f188f..0000000
--- a/ctrack/caf/migrations/0008_auto_20200814_1318.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Generated by Django 2.2.12 on 2020-08-14 13:18
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('caf', '0007_auto_20200814_1230'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='applicablesystem',
- name='essential_service',
- field=models.CharField(default='NA', help_text='Name of the essential service which the system suppports.', max_length=255, verbose_name='Essential Service'),
- ),
- migrations.AlterField(
- model_name='applicablesystem',
- name='oes_categorisation',
- field=models.CharField(default='NA', help_text="Categorisation based on OES' own internal prioritisation process.", max_length=255, verbose_name='OES Categorisation'),
- ),
- ]
diff --git a/ctrack/caf/models.py b/ctrack/caf/models.py
index 27220bc..5fd586f 100644
--- a/ctrack/caf/models.py
+++ b/ctrack/caf/models.py
@@ -45,13 +45,6 @@ class DocumentFile(models.Model):
class ApplicableSystem(models.Model):
- CRITICAL = "CR"
- IMPORTANT = "IM"
- SYSTEM_CATEGORISATION = (
- (CRITICAL, "Critical"),
- (IMPORTANT, "Important (Legacy use only)"),
- )
-
def get_sentinel_org():
"""
We need this so that we can ensure models.SET() is applied with a callable
@@ -60,6 +53,13 @@ class ApplicableSystem(models.Model):
"""
return Organisation.objects.get_or_create(name="DELETED ORGANISATION")[0]
+ CRITICAL = "CR"
+ IMPORTANT = "IM"
+ SYSTEM_CATEGORISATION = (
+ (CRITICAL, "Critical"),
+ (IMPORTANT, "Important (Legacy use only)"),
+ )
+
name = models.CharField(max_length=256, help_text="System name assigned by OES")
function = models.TextField(
max_length=1000,
@@ -68,22 +68,6 @@ class ApplicableSystem(models.Model):
help_text="How the system is relevant to delivering or supporting the "
"essential service",
)
- organisation = models.ForeignKey(
- Organisation, on_delete=models.SET(get_sentinel_org)
- )
- caf = models.ForeignKey(
- "CAF",
- on_delete=models.CASCADE,
- blank=True,
- null=True,
- related_name="applicable_systems",
- )
- essential_service = models.CharField(
- max_length=255,
- default="NA",
- verbose_name="Essential Service",
- help_text="Description of the essential service which the system suppports.",
- )
dft_categorisation = models.CharField(
max_length=2,
choices=SYSTEM_CATEGORISATION,
@@ -105,12 +89,20 @@ class ApplicableSystem(models.Model):
return self.organisation.person_set.filter(primary_nis_contact=True)
def __str__(self):
- return f"{self.organisation.name} | {self.name}"
+ return self.name
objects = ApplicableSystemManager()
class CAF(models.Model):
+ def get_sentinel_org():
+ """
+ We need this so that we can ensure models.SET() is applied with a callable
+ to handle when Users are deleted from the system, preventing the Organisation
+ objects related to them being deleted also.
+ """
+ return Organisation.objects.get_or_create(name="DELETED ORGANISATION")[0]
+
quality_grading = models.ForeignKey(
Grading,
on_delete=models.CASCADE,
@@ -129,10 +121,14 @@ class CAF(models.Model):
DocumentFile, on_delete=models.CASCADE, blank=True, null=True
)
version = models.CharField(max_length=10, blank=True, null=True)
+ organisation = models.ForeignKey(
+ Organisation, on_delete=models.SET(get_sentinel_org)
+ )
triage_review_date = models.DateField(blank=True, null=True)
triage_review_inspector = models.ForeignKey(
Person, on_delete=models.CASCADE, blank=True, null=True
)
+ systems = models.ManyToManyField(ApplicableSystem)
comments = models.TextField(max_length=1000)
class Meta:
@@ -147,14 +143,24 @@ class CAF(models.Model):
"""
return ApplicableSystem.objects.filter(caf=self)
- def organisation(self):
- first_ass = ApplicableSystem.objects.filter(caf=self).first()
- return first_ass.organisation
+ # FIXME remove once we know we don't need it
+ # def organisation(self):
+ # first_ass = ApplicableSystem.objects.filter(caf=self).first()
+ # return first_ass.organisation
def sub_mode(self):
- return self.organisation().submode
+ return self.organisation.submode
def __str__(self):
# Get the organisation and applicable system
- ass = ApplicableSystem.objects.filter(caf=self).first()
- return f"CAF | {ass.organisation.name}_v{self.version}"
+ return f"CAF | {self.organisation.name}_v{self.version}"
+
+
+class EssentialService(models.Model):
+ name = models.CharField(max_length=256)
+ description = models.CharField(max_length=512)
+ organisation = models.ForeignKey(Organisation, on_delete=models.CASCADE)
+ systems = models.ManyToManyField(ApplicableSystem)
+
+ def __str__(self):
+ return self.name
diff --git a/ctrack/caf/templates/caf/applicablesystem_detail.html b/ctrack/caf/templates/caf/applicablesystem_detail.html
index 9e12043..b8467b0 100644
--- a/ctrack/caf/templates/caf/applicablesystem_detail.html
+++ b/ctrack/caf/templates/caf/applicablesystem_detail.html
@@ -5,24 +5,31 @@
{% block title %}{{ object.name }}{% endblock %}
{% block content %}
- <div class="container mt-3">
- <div class="row">
- <div class="col-sm-12 pl-0 my-2">
+ <div class="container mt-3">
<div class="row">
- <h4>{{ object.name }}</h4>
+ <div class="col-sm-12 pl-0 my-2">
+ <div class="row">
+ <h4>{{ object.name }}</h4>
+ </div>
+ <div class="row">
+ <h5>{{ object.caf.organisation }}</h5>
+ </div>
+ <div class="row">
+ <h5>Function</h5>
+ </div>
+ <div class="row">
+ <p>{{ object.function }}</p>
+ <p>Supports Essential Services:</p>
+ </div>
+ <div class="row">
+ <ul>
+ {% for s in object.essentialservice_set.all %}
+ <li>{{ s.name }}</li>
+ {% endfor %}
+ </ul>
+ </div>
+ </div>
</div>
- <div class="row">
- <h5>{{ object.caf.organisation }}</h5>
- </div>
- <div class="row">
- <h6>Function</h6>
- </div>
- <div class="row">
- <p>{{ object.function }}</p>
- <p>Contained within CAF: <a href="{% url "caf:detail" object.caf.pk %}">{{ object.caf }}</a></p>
- </div>
- </div>
</div>
- </div>
{% endblock %}
diff --git a/ctrack/caf/templates/caf/caf_detail.html b/ctrack/caf/templates/caf/caf_detail.html
index fc2fcfd..fdd939e 100644
--- a/ctrack/caf/templates/caf/caf_detail.html
+++ b/ctrack/caf/templates/caf/caf_detail.html
@@ -72,7 +72,7 @@
<tr>
<td><a href="{% url "caf:ass_detail" system.id %}">{{ system.name }}</a></td>
<td>{{ system.function }}<br>
- <a href="{% url "caf:detail" system.caf.pk %}" class="small">
+ <a href="{% url "caf:detail" system.pk %}" class="small">
{{ system.caf }}
</a> <span class="text-muted"> | <a href="#" class="small">Edit System</a></span>
</td>
diff --git a/ctrack/caf/tests/factories.py b/ctrack/caf/tests/factories.py
index 3c62307..7aaf716 100644
--- a/ctrack/caf/tests/factories.py
+++ b/ctrack/caf/tests/factories.py
@@ -10,6 +10,7 @@ from ctrack.organisations.tests.factories import OrganisationFactory, PersonFact
class CAFFactory(factory.DjangoModelFactory):
quality_grading = factory.SubFactory("ctrack.caf.tests.factories.GradingFactory")
confidence_grading = factory.SubFactory("ctrack.caf.tests.factories.GradingFactory")
+ organisation = factory.SubFactory("ctrack.organisations.tests.OrganisationFactory")
file = None
version = Faker("bothify", text="??##", letters="ABCD")
triage_review_date = Faker("date_object")
@@ -29,8 +30,6 @@ class ApplicableSystemFactory(factory.DjangoModelFactory):
function = Faker(
"paragraph", nb_sentences=4, variable_nb_sentences=True, ext_word_list=None
)
- organisation = factory.SubFactory(OrganisationFactory)
- caf = factory.SubFactory("ctrack.caf.tests.factories.CAFFactory")
dft_categorisation = "CR"
class Meta:
diff --git a/ctrack/caf/views.py b/ctrack/caf/views.py
index 258774e..480e305 100644
--- a/ctrack/caf/views.py
+++ b/ctrack/caf/views.py
@@ -36,8 +36,8 @@ def caf_detail_view(request, pk):
context = {
"object": caf,
"assessments_and_scores": _scrs,
- "organisation": ApplicableSystem.objects.filter(caf=caf).first().organisation,
- "systems": caf.applicable_systems.all(),
+ "organisation": caf.organisation,
+ "systems": caf.systems.all(),
}
return render(request, "caf/caf_detail.html", context)
@@ -107,20 +107,22 @@ class ApplicableSystemCreateFromOrg(
ass = ApplicableSystem.objects.create(
name=form.cleaned_data["name"],
function=form.cleaned_data["function"],
- organisation=form.cleaned_data["organisation"],
- caf=form.cleaned_data["caf"],
+ # organisation=form.cleaned_data["organisation"],
+ # caf=form.cleaned_data["caf"],
)
+ es = form.cleaned_data["essential_service"]
+ es.systems.add(ass)
return super().form_valid(form)
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
org = Organisation.objects.get(slug=self.kwargs["slug"])
- asses = org.applicablesystem_set.all()
- org_cafs = {ass.caf for ass in asses}
+ asses = org.applicable_systems()
+ # org_cafs = org.caf_set.all()
kwargs["org_id"] = org.id
kwargs["slug"] = org.slug
kwargs["org_name"] = org.name
- kwargs["org_cafs"] = list(org_cafs)
+ # kwargs["org_cafs"] = list(org_cafs)
return kwargs
def get_success_url(self):