From ef463b845d1738a6067c786bf410f5109d832a5c Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 23 May 2024 20:31:53 +0930 Subject: [PATCH] feat(core): Add manufacturers !10 #12 --- app/core/migrations/0005_manufacturer.py | 32 +++++ app/core/models/manufacturer.py | 43 ++++++ app/settings/templates/settings/home.html.j2 | 8 +- .../templates/settings/manufacturers.html.j2 | 43 ++++++ .../test_manufacturer_access_organization.py | 19 +++ .../test_manufacturer_core_history.py | 31 ++++ .../test_manufacturer_permission.py | 32 +++++ .../test_manufacturer_permission_api.py | 32 +++++ app/settings/urls.py | 7 +- app/settings/views/manufacturer.py | 132 ++++++++++++++++++ docs/projects/django-template/core/index.md | 19 +++ 11 files changed, 395 insertions(+), 3 deletions(-) create mode 100644 app/core/migrations/0005_manufacturer.py create mode 100644 app/core/models/manufacturer.py create mode 100644 app/settings/templates/settings/manufacturers.html.j2 create mode 100644 app/settings/tests/manufacturer/test_manufacturer_access_organization.py create mode 100644 app/settings/tests/manufacturer/test_manufacturer_core_history.py create mode 100644 app/settings/tests/manufacturer/test_manufacturer_permission.py create mode 100644 app/settings/tests/manufacturer/test_manufacturer_permission_api.py create mode 100644 app/settings/views/manufacturer.py create mode 100644 docs/projects/django-template/core/index.md diff --git a/app/core/migrations/0005_manufacturer.py b/app/core/migrations/0005_manufacturer.py new file mode 100644 index 00000000..64a5ed12 --- /dev/null +++ b/app/core/migrations/0005_manufacturer.py @@ -0,0 +1,32 @@ +# Generated by Django 5.0.6 on 2024-05-23 10:58 + +import access.fields +import django.db.models.deletion +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('access', '0002_alter_team_organization'), + ('core', '0004_notes_is_null'), + ] + + operations = [ + migrations.CreateModel( + name='Manufacturer', + fields=[ + ('is_global', models.BooleanField(default=False)), + ('id', models.AutoField(primary_key=True, serialize=False, unique=True)), + ('created', access.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False)), + ('modified', access.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False)), + ('name', models.CharField(max_length=50, unique=True)), + ('slug', access.fields.AutoSlugField()), + ('organization', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization')), + ], + options={ + 'ordering': ['name'], + }, + ), + ] diff --git a/app/core/models/manufacturer.py b/app/core/models/manufacturer.py new file mode 100644 index 00000000..f651def1 --- /dev/null +++ b/app/core/models/manufacturer.py @@ -0,0 +1,43 @@ +from django.contrib.auth.models import User +from django.db import models + +from access.fields import * +from access.models import TenancyObject + +from core.mixin.history_save import SaveHistory + +class ManufacturerCommonFields(models.Model): + + class Meta: + abstract = True + + id = models.AutoField( + primary_key=True, + unique=True, + blank=False + ) + + created = AutoCreatedField() + + modified = AutoCreatedField() + + + +class Manufacturer(TenancyObject, ManufacturerCommonFields, SaveHistory): + + + class Meta: + + ordering = [ + 'name' + ] + + + name = models.CharField( + blank = False, + max_length = 50, + unique = True, + ) + + + slug = AutoSlugField() diff --git a/app/settings/templates/settings/home.html.j2 b/app/settings/templates/settings/home.html.j2 index 94ead697..70320777 100644 --- a/app/settings/templates/settings/home.html.j2 +++ b/app/settings/templates/settings/home.html.j2 @@ -32,13 +32,17 @@ div#content article h3 {
+ diff --git a/app/settings/templates/settings/manufacturers.html.j2 b/app/settings/templates/settings/manufacturers.html.j2 new file mode 100644 index 00000000..50bb3861 --- /dev/null +++ b/app/settings/templates/settings/manufacturers.html.j2 @@ -0,0 +1,43 @@ +{% extends 'base.html.j2' %} + + +{% block content_header_icon %}{% endblock %} + +{% block body %} + + + + + + + + + + {% for item in list %} + + + + + + {% endfor %} + +
NameOrganization 
{{ item.name }}{% if item.is_global %}Global{% else %}{{ item.organization }}{% endif %}Delete
+ + +{% endblock %} \ No newline at end of file diff --git a/app/settings/tests/manufacturer/test_manufacturer_access_organization.py b/app/settings/tests/manufacturer/test_manufacturer_access_organization.py new file mode 100644 index 00000000..1394d20d --- /dev/null +++ b/app/settings/tests/manufacturer/test_manufacturer_access_organization.py @@ -0,0 +1,19 @@ + +from django.test import TestCase, Client + +import pytest +import unittest +import requests + + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_create_has_organization(): + """ Devices must be assigned an organization """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_edit_has_organization(): + """ Devices must be assigned an organization """ + pass diff --git a/app/settings/tests/manufacturer/test_manufacturer_core_history.py b/app/settings/tests/manufacturer/test_manufacturer_core_history.py new file mode 100644 index 00000000..2914bf99 --- /dev/null +++ b/app/settings/tests/manufacturer/test_manufacturer_core_history.py @@ -0,0 +1,31 @@ + +from django.test import TestCase, Client + +import pytest +import unittest +import requests + + + +@pytest.mark.skip(reason="to be written") +def test_history_auth_view(): + """ User requires Permission view_history """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_history_manufacturer_create(): + """ History row must be added to history table on create """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_history_manufacturer_update(): + """ History row must be added to history table on updatej """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_history_manufacturer_delete(): + """ History row must be added to history table on delete """ + pass diff --git a/app/settings/tests/manufacturer/test_manufacturer_permission.py b/app/settings/tests/manufacturer/test_manufacturer_permission.py new file mode 100644 index 00000000..f9ab7366 --- /dev/null +++ b/app/settings/tests/manufacturer/test_manufacturer_permission.py @@ -0,0 +1,32 @@ +# from django.conf import settings +# from django.shortcuts import reverse +from django.test import TestCase, Client + +import pytest +import unittest +import requests + + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_auth_view(): + """ Check correct permission for view """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_auth_add(): + """ Check correct permission for add """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_auth_change(): + """ Check correct permission for change """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_auth_delete(): + """ Check correct permission for delete """ + pass diff --git a/app/settings/tests/manufacturer/test_manufacturer_permission_api.py b/app/settings/tests/manufacturer/test_manufacturer_permission_api.py new file mode 100644 index 00000000..a7dbd55e --- /dev/null +++ b/app/settings/tests/manufacturer/test_manufacturer_permission_api.py @@ -0,0 +1,32 @@ +# from django.conf import settings +# from django.shortcuts import reverse +from django.test import TestCase, Client + +import pytest +import unittest +import requests + + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_auth_view_api(): + """ Check correct permission for view """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_auth_add_api(): + """ Check correct permission for add """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_auth_change_api(): + """ Check correct permission for change """ + pass + + +@pytest.mark.skip(reason="to be written") +def test_manufacturer_auth_delete_api(): + """ Check correct permission for delete """ + pass diff --git a/app/settings/urls.py b/app/settings/urls.py index 265d13d8..1c5aa55e 100644 --- a/app/settings/urls.py +++ b/app/settings/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from .views import home, device_types, software_categories +from .views import home, device_types, manufacturer, software_categories from itam.views import device_type, software_category @@ -19,4 +19,9 @@ urlpatterns = [ path("software_category/add/", software_category.Add.as_view(), name="_software_category_add"), path("software_category//delete", software_category.Delete.as_view(), name="_software_category_delete"), + path("manufacturers", manufacturer.Index.as_view(), name="_manufacturers"), + path("manufacturer/", manufacturer.View.as_view(), name="_manufacturer_view"), + path("manufacturer/add/", manufacturer.Add.as_view(), name="_manufacturer_add"), + path("manufacturer//delete", manufacturer.Delete.as_view(), name="_manufacturer_delete"), + ] diff --git a/app/settings/views/manufacturer.py b/app/settings/views/manufacturer.py new file mode 100644 index 00000000..fdca9776 --- /dev/null +++ b/app/settings/views/manufacturer.py @@ -0,0 +1,132 @@ +from django.contrib.auth.mixins import PermissionRequiredMixin +from django.db.models import Q +from django.views import generic + + +from access.mixin import OrganizationPermission +from core.models.manufacturer import Manufacturer + + + +class Index(PermissionRequiredMixin, OrganizationPermission, generic.ListView): + + context_object_name = "list" + + model = Manufacturer + + paginate_by = 10 + + permission_required = 'itam.view_devicetype' + + template_name = 'settings/manufacturers.html.j2' + + + def get_queryset(self): + + if self.request.user.is_superuser: + + return self.model.objects.filter().order_by('name') + + else: + + return self.model.objects.filter(Q(organization__in=self.user_organizations()) | Q(is_global = True)).order_by('name') + + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context['content_title'] = 'Manufacturers' + + return context + + + + +class View(OrganizationPermission, generic.UpdateView): + + context_object_name = "manufacturer" + + fields = [ + "name", + 'slug', + 'id', + 'organization', + 'is_global', + ] + + model = Manufacturer + + permission_required = [ + 'itam.view_manufacturer' + ] + + template_name = 'form.html.j2' + + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context['model_pk'] = self.kwargs['pk'] + context['model_name'] = self.model._meta.verbose_name.replace(' ', '') + + context['content_title'] = self.object.name + + return context + + def get_success_url(self, **kwargs): + + return f"/settings/manufacturer/{self.kwargs['pk']}" + + + +class Add(PermissionRequiredMixin, OrganizationPermission, generic.CreateView): + + fields = [ + 'name', + 'organization', + 'is_global' + ] + + model = Manufacturer + + permission_required = [ + 'access.add_manufacturere', + ] + + template_name = 'form.html.j2' + + + def get_success_url(self, **kwargs): + + return f"/settings/manufacturers" + + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context['content_title'] = 'Add Manufacturer' + + return context + + +class Delete(PermissionRequiredMixin, OrganizationPermission, generic.DeleteView): + + model = Manufacturer + + permission_required = [ + 'access.delete_manufacturer', + ] + + + def get_success_url(self, **kwargs): + + return f"/settings/manufacturers" + + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context['content_title'] = 'Delete ' + self.object.name + + return context + diff --git a/docs/projects/django-template/core/index.md b/docs/projects/django-template/core/index.md new file mode 100644 index 00000000..d97a89d1 --- /dev/null +++ b/docs/projects/django-template/core/index.md @@ -0,0 +1,19 @@ +--- +title: Core Module +description: No Fuss Computings Django ITSM Core module +date: 2024-05-15 +template: project.html +about: https://gitlab.com/nofusscomputing/infrastructure/configuration-management/django_app +--- + +The core module contains items that are relevant across multiple modules. + + +## Features + +- Manufacturers + + +## Manufacturers + +A manufacturer is an entity that creates an item. Within the IT world a manufacturer can also be known as a publisher, this is in the case of software.