aboutsummaryrefslogtreecommitdiffstats
path: root/ctrack/organisations
diff options
context:
space:
mode:
authorMatthew Lemon <lemon@matthewlemon.com>2020-05-28 16:12:13 +0100
committerMatthew Lemon <lemon@matthewlemon.com>2020-05-28 16:12:13 +0100
commitacf875c2bca1727306cb70aaa37e6f4595209786 (patch)
tree67390297bcd02b2481f5673629227dfea0884215 /ctrack/organisations
parent4aaa68109434e04d1103710d675efd075b2f744a (diff)
parent520a9deb13f93c689443c0339b1c96a67f0c15a1 (diff)
Merge branch 'stakeholder-profile'
Diffstat (limited to 'ctrack/organisations')
-rw-r--r--ctrack/organisations/admin.py18
-rw-r--r--ctrack/organisations/migrations/0005_auto_20200525_1502.py29
-rw-r--r--ctrack/organisations/models.py25
-rw-r--r--ctrack/organisations/templates/organisations/organisation_detail.html2
-rw-r--r--ctrack/organisations/tests/factories.py4
-rw-r--r--ctrack/organisations/views.py34
6 files changed, 87 insertions, 25 deletions
diff --git a/ctrack/organisations/admin.py b/ctrack/organisations/admin.py
index dbd7239..f85ddad 100644
--- a/ctrack/organisations/admin.py
+++ b/ctrack/organisations/admin.py
@@ -1,6 +1,15 @@
from django.contrib import admin
-from .models import Organisation, Address, AddressType, Person, Role, Mode, Submode
+from .models import (
+ Address,
+ AddressType,
+ Mode,
+ Organisation,
+ Person,
+ Role,
+ Stakeholder,
+ Submode,
+)
# So we can get the organisation name - a reverse lookup
@@ -16,6 +25,10 @@ class AddressTypeAdmin(admin.ModelAdmin):
pass
+class StakeholderAdmin(admin.ModelAdmin):
+ model = Stakeholder
+
+
class AddressInLine(admin.StackedInline):
model = Address
max_num = 3
@@ -24,7 +37,7 @@ class AddressInLine(admin.StackedInline):
class OrganisationAdmin(admin.ModelAdmin):
inlines = [AddressInLine]
- list_display = ("name", "submode", "date_updated", "updated_by")
+ list_display = ("name", "submode", "date_updated")
class PersonAdmin(admin.ModelAdmin):
@@ -58,3 +71,4 @@ admin.site.register(Role, RoleAdmin)
admin.site.register(Person, PersonAdmin)
admin.site.register(Mode, ModeAdmin)
admin.site.register(Submode, SubmodeAdmin)
+admin.site.register(Stakeholder, StakeholderAdmin)
diff --git a/ctrack/organisations/migrations/0005_auto_20200525_1502.py b/ctrack/organisations/migrations/0005_auto_20200525_1502.py
new file mode 100644
index 0000000..921fdbb
--- /dev/null
+++ b/ctrack/organisations/migrations/0005_auto_20200525_1502.py
@@ -0,0 +1,29 @@
+# Generated by Django 3.0.5 on 2020-05-25 15:02
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('organisations', '0004_auto_20200513_1441'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='organisation',
+ name='updated_by',
+ ),
+ migrations.RemoveField(
+ model_name='person',
+ name='updated_by',
+ ),
+ migrations.CreateModel(
+ name='Stakeholder',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='organisations.Person')),
+ ],
+ ),
+ ]
diff --git a/ctrack/organisations/models.py b/ctrack/organisations/models.py
index b11e97b..6a1b4ac 100644
--- a/ctrack/organisations/models.py
+++ b/ctrack/organisations/models.py
@@ -47,7 +47,7 @@ class Person(models.Model):
to handle when Users are deleted from the system, preventing the Person objects
related to them being deleted also.
"""
- return get_user_model().objects.get_or_create(username='DELETED USER')[0]
+ return get_user_model().objects.get_or_create(username="DELETED USER")[0]
primary_nis_contact = models.BooleanField(
default=False, verbose_name="Primary NIS contact"
@@ -65,7 +65,9 @@ class Person(models.Model):
mobile = models.CharField(max_length=20, blank=True)
landline = models.CharField(max_length=20, blank=True)
date_updated = models.DateField(auto_now=True)
- updated_by = models.ForeignKey(get_user_model(), on_delete=models.SET(get_sentinel_user))
+ # updated_by = models.ForeignKey(
+ # get_user_model(), on_delete=models.SET(get_sentinel_user)
+ # )
clearance = models.IntegerField(choices=CLEARANCE_LEVEL, default=1)
clearance_sponsor = models.CharField(max_length=100, blank=True)
clearance_start_date = models.DateField(blank=True, null=True)
@@ -74,7 +76,11 @@ class Person(models.Model):
active = models.BooleanField(default=True)
date_ended = models.DateField(blank=True, null=True)
predecessor = models.ForeignKey(
- "self", blank=True, on_delete=models.CASCADE, related_name="previous_person", null=True
+ "self",
+ blank=True,
+ on_delete=models.CASCADE,
+ related_name="previous_person",
+ null=True,
)
comments = models.TextField(max_length=1000, blank=True)
@@ -116,7 +122,7 @@ class Organisation(models.Model):
to handle when Users are deleted from the system, preventing the Organisations
related to them being deleted also.
"""
- return get_user_model().objects.get_or_create(username='DELETED USER')[0]
+ return get_user_model().objects.get_or_create(username="DELETED USER")[0]
name = models.CharField(max_length=255)
slug = AutoSlugField(populate_from=["name"])
@@ -128,7 +134,9 @@ class Organisation(models.Model):
registered_company_name = models.CharField(max_length=255, blank=True)
registered_company_number = models.CharField(max_length=100, blank=True)
date_updated = models.DateField(auto_now=True)
- updated_by = models.ForeignKey(get_user_model(), on_delete=models.SET(get_sentinel_user))
+ # updated_by = models.ForeignKey(
+ # get_user_model(), on_delete=models.SET(get_sentinel_user)
+ # )
comments = models.TextField(max_length=500, blank=True, null=True)
active = models.BooleanField(default=True)
@@ -166,3 +174,10 @@ class Address(models.Model):
class Meta:
verbose_name_plural = "Addresses"
+
+
+class Stakeholder(models.Model):
+ person = models.ForeignKey(Person, on_delete=models.CASCADE)
+
+ def __str__(self):
+ return f"{self.person.first_name} {self.person.last_name}"
diff --git a/ctrack/organisations/templates/organisations/organisation_detail.html b/ctrack/organisations/templates/organisations/organisation_detail.html
index daec5a9..2479f50 100644
--- a/ctrack/organisations/templates/organisations/organisation_detail.html
+++ b/ctrack/organisations/templates/organisations/organisation_detail.html
@@ -48,7 +48,7 @@
</tr>
<tr>
<td><strong>Updated By:</strong></td>
- <td>{{ object.updated_by }}</td>
+ <td>REMOVED</td>
</tr>
<tr>
<td><strong>Active:</strong></td>
diff --git a/ctrack/organisations/tests/factories.py b/ctrack/organisations/tests/factories.py
index 7acd887..ba2655e 100644
--- a/ctrack/organisations/tests/factories.py
+++ b/ctrack/organisations/tests/factories.py
@@ -33,6 +33,8 @@ def _random_submode():
class UserFactory(DjangoModelFactory):
+ # Better to create this using example in ctrack.users.tests.factories.
+ # Handles password generation correctly.
class Meta:
model = User
@@ -51,7 +53,6 @@ class OrganisationFactory(DjangoModelFactory):
registered_company_name = Faker("company")
registered_company_number = Faker("numerify", text="######")
date_updated = Faker("date_this_year", before_today=True)
- updated_by = SubFactory(UserFactory)
comments = Faker("paragraph", nb_sentences=3)
active = True
@@ -99,7 +100,6 @@ class PersonFactory(DjangoModelFactory):
mobile = Faker("cellphone_number", locale="en_GB")
landline = Faker("phone_number", locale="en_GB")
date_updated = factory.LazyFunction(datetime.now)
- updated_by = SubFactory(UserFactory)
clearance = factory.LazyFunction(lambda: random.randint(1, 6))
clearance_sponsor = Faker("name", locale="en_GB")
clearance_start_date = factory.LazyFunction(datetime.now)
diff --git a/ctrack/organisations/views.py b/ctrack/organisations/views.py
index fe88728..b929de4 100644
--- a/ctrack/organisations/views.py
+++ b/ctrack/organisations/views.py
@@ -1,12 +1,15 @@
-from typing import Any
-from typing import Dict
+from typing import Any, Dict
-from django.contrib.auth.mixins import LoginRequiredMixin
+from django.contrib.auth.mixins import (
+ LoginRequiredMixin,
+ PermissionRequiredMixin,
+ UserPassesTestMixin,
+)
from django.db import transaction
from django.urls import reverse_lazy
-from django.views.generic import DetailView, ListView, CreateView
+from django.views.generic import CreateView, DetailView, ListView
-from .forms import OrganisationCreateForm, AddressInlineFormSet
+from .forms import AddressInlineFormSet, OrganisationCreateForm
from .models import Organisation
@@ -27,19 +30,20 @@ class OrganisationCreate(LoginRequiredMixin, CreateView):
context = self.get_context_data()
addresses = context["addresses"]
with transaction.atomic():
- form.instance.updated_by = self.request.user
+ # form.instance.updated_by = self.request.user REMOVED updated_by
self.object = form.save()
if addresses.is_valid():
addresses.instance = self.object
addresses.save()
return super().form_valid(form)
- def get_success_url(self) -> str:
+ def get_success_url(self):
return reverse_lazy("organisations:detail", kwargs={"slug": self.object.slug})
-class OrganisationListView(LoginRequiredMixin, ListView):
+class OrganisationListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
model = Organisation
+ permission_required = "organisations.view_organisation"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@@ -52,18 +56,18 @@ class OrganisationDetailView(LoginRequiredMixin, DetailView):
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
context = super().get_context_data()
- org = kwargs['object']
+ org = kwargs["object"]
no_addr = org.addresses.count()
if no_addr > 1:
- context['no_addr'] = no_addr
+ context["no_addr"] = no_addr
addr = org.addresses.all()
- context['addr'] = addr
+ context["addr"] = addr
else:
- context['no_addr'] = 1
+ context["no_addr"] = 1
addr = org.addresses.first()
- context['addr'] = addr
+ context["addr"] = addr
people = org.person_set.all()
- context['people'] = people
+ context["people"] = people
applicable_systems = org.applicablesystem_set.all()
- context['applicable_systems'] = applicable_systems
+ context["applicable_systems"] = applicable_systems
return context