Merge pull request #862 from nofusscomputing/refactor-switch-model-inheritence
This commit is contained in:
@ -0,0 +1,56 @@
|
|||||||
|
# Generated by Django 5.1.10 on 2025-07-12 07:20
|
||||||
|
|
||||||
|
import access.models.tenancy_abstract
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("access", "0019_companyaudithistory_companycenturionmodelnote"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="role",
|
||||||
|
name="id",
|
||||||
|
field=models.AutoField(
|
||||||
|
help_text="ID of the item",
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
unique=True,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="role",
|
||||||
|
name="model_notes",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Tid bits of information",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Notes",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="role",
|
||||||
|
name="organization",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
help_text="Tenant this belongs to",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="+",
|
||||||
|
to="access.tenant",
|
||||||
|
validators=[
|
||||||
|
access.models.tenancy_abstract.TenancyAbstractModel.validatate_organization_exists
|
||||||
|
],
|
||||||
|
verbose_name="Tenant",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name="RoleHistory",
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name="RoleNotes",
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,81 @@
|
|||||||
|
# Generated by Django 5.1.10 on 2025-07-12 08:50
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("access", "0020_remove_rolenotes_model_and_more"),
|
||||||
|
("core", "0033_alter_ticketcommentcategory_parent_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="RoleAuditHistory",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"centurionaudit_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="core.centurionaudit",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model",
|
||||||
|
models.ForeignKey(
|
||||||
|
help_text="Model this history belongs to",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="audit_history",
|
||||||
|
to="access.role",
|
||||||
|
verbose_name="Model",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Role History",
|
||||||
|
"verbose_name_plural": "Role Histories",
|
||||||
|
"db_table": "access_role_audithistory",
|
||||||
|
"managed": True,
|
||||||
|
},
|
||||||
|
bases=("core.centurionaudit",),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="RoleCenturionModelNote",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"centurionmodelnote_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="core.centurionmodelnote",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model",
|
||||||
|
models.ForeignKey(
|
||||||
|
help_text="Model this note belongs to",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="+",
|
||||||
|
to="access.role",
|
||||||
|
verbose_name="Model",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Role Note",
|
||||||
|
"verbose_name_plural": "Role Notes",
|
||||||
|
"db_table": "access_role_centurionmodelnote",
|
||||||
|
"managed": True,
|
||||||
|
},
|
||||||
|
bases=("core.centurionmodelnote",),
|
||||||
|
),
|
||||||
|
]
|
@ -1,5 +1,3 @@
|
|||||||
from .organization_history import OrganizationHistory # pylint: disable=W0611:unused-import
|
from .organization_history import OrganizationHistory # pylint: disable=W0611:unused-import
|
||||||
from .role_history import RoleHistory # pylint: disable=W0611:unused-import
|
|
||||||
|
|
||||||
from .organization_notes import OrganizationNotes # pylint: disable=W0611:unused-import
|
from .organization_notes import OrganizationNotes # pylint: disable=W0611:unused-import
|
||||||
from .role_notes import RoleNotes # pylint: disable=W0611:unused-import
|
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from access.fields import AutoCreatedField, AutoLastModifiedField
|
from access.fields import AutoLastModifiedField
|
||||||
from access.models.tenancy import TenancyObject
|
|
||||||
|
from core.models.centurion import CenturionModel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Role(
|
class Role(
|
||||||
TenancyObject
|
CenturionModel
|
||||||
):
|
):
|
||||||
|
|
||||||
|
documentation = ''
|
||||||
|
|
||||||
|
model_tag = 'role'
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
||||||
@ -28,14 +33,6 @@ class Role(
|
|||||||
verbose_name_plural = 'Roles'
|
verbose_name_plural = 'Roles'
|
||||||
|
|
||||||
|
|
||||||
id = models.AutoField(
|
|
||||||
blank=False,
|
|
||||||
help_text = 'Primary key of the entry',
|
|
||||||
primary_key=True,
|
|
||||||
unique=True,
|
|
||||||
verbose_name = 'ID'
|
|
||||||
)
|
|
||||||
|
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
blank = False,
|
blank = False,
|
||||||
help_text = 'Name of this role',
|
help_text = 'Name of this role',
|
||||||
@ -53,12 +50,8 @@ class Role(
|
|||||||
verbose_name = 'Permissions'
|
verbose_name = 'Permissions'
|
||||||
)
|
)
|
||||||
|
|
||||||
created = AutoCreatedField()
|
|
||||||
|
|
||||||
modified = AutoLastModifiedField()
|
modified = AutoLastModifiedField()
|
||||||
|
|
||||||
is_global = None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
@ -66,8 +59,6 @@ class Role(
|
|||||||
return str( self.organization ) + ' / ' + self.name
|
return str( self.organization ) + ' / ' + self.name
|
||||||
|
|
||||||
|
|
||||||
documentation = ''
|
|
||||||
|
|
||||||
page_layout: dict = [
|
page_layout: dict = [
|
||||||
{
|
{
|
||||||
"name": "Details",
|
"name": "Details",
|
||||||
@ -156,19 +147,3 @@ class Role(
|
|||||||
return self._permissions_int
|
return self._permissions_int
|
||||||
|
|
||||||
return self._permissions_int
|
return self._permissions_int
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def save_history(self, before: dict, after: dict) -> bool:
|
|
||||||
|
|
||||||
from access.models.role_history import RoleHistory
|
|
||||||
|
|
||||||
history = super().save_history(
|
|
||||||
before = before,
|
|
||||||
after = after,
|
|
||||||
history_model = RoleHistory
|
|
||||||
)
|
|
||||||
|
|
||||||
return history
|
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
from core.models.model_history import ModelHistory
|
|
||||||
|
|
||||||
from access.models.role import Role
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RoleHistory(
|
|
||||||
ModelHistory
|
|
||||||
):
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
|
|
||||||
db_table = 'access_role_history'
|
|
||||||
|
|
||||||
ordering = ModelHistory._meta.ordering
|
|
||||||
|
|
||||||
verbose_name = 'Role History'
|
|
||||||
|
|
||||||
verbose_name_plural = 'Role History'
|
|
||||||
|
|
||||||
|
|
||||||
model = models.ForeignKey(
|
|
||||||
Role,
|
|
||||||
blank = False,
|
|
||||||
help_text = 'Model this note belongs to',
|
|
||||||
null = False,
|
|
||||||
on_delete = models.CASCADE,
|
|
||||||
related_name = 'history',
|
|
||||||
verbose_name = 'Model',
|
|
||||||
)
|
|
||||||
|
|
||||||
table_fields: list = []
|
|
||||||
|
|
||||||
page_layout: dict = []
|
|
||||||
|
|
||||||
|
|
||||||
def get_object(self):
|
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def get_serialized_model(self, serializer_context):
|
|
||||||
|
|
||||||
model = None
|
|
||||||
|
|
||||||
from access.serializers.role import BaseSerializer
|
|
||||||
|
|
||||||
model = BaseSerializer(self.model, context = serializer_context)
|
|
||||||
|
|
||||||
return model
|
|
@ -1,45 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
from access.models.role import Role
|
|
||||||
|
|
||||||
from core.models.model_notes import ModelNotes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RoleNotes(
|
|
||||||
ModelNotes
|
|
||||||
):
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
|
|
||||||
db_table = 'access_role_notes'
|
|
||||||
|
|
||||||
ordering = ModelNotes._meta.ordering
|
|
||||||
|
|
||||||
verbose_name = 'Role Note'
|
|
||||||
|
|
||||||
verbose_name_plural = 'Role Notes'
|
|
||||||
|
|
||||||
|
|
||||||
model = models.ForeignKey(
|
|
||||||
Role,
|
|
||||||
blank = False,
|
|
||||||
help_text = 'Model this note belongs to',
|
|
||||||
null = False,
|
|
||||||
on_delete = models.CASCADE,
|
|
||||||
related_name = 'notes',
|
|
||||||
verbose_name = 'Model',
|
|
||||||
)
|
|
||||||
|
|
||||||
table_fields: list = []
|
|
||||||
|
|
||||||
page_layout: dict = []
|
|
||||||
|
|
||||||
|
|
||||||
def get_url_kwargs(self) -> dict:
|
|
||||||
|
|
||||||
return {
|
|
||||||
'model_id': self.model.pk,
|
|
||||||
'pk': self.pk
|
|
||||||
}
|
|
56
app/access/serializers/centurionaudit_role.py
Normal file
56
app/access/serializers/centurionaudit_role.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from drf_spectacular.utils import extend_schema_serializer
|
||||||
|
|
||||||
|
from api.serializers import common
|
||||||
|
|
||||||
|
from centurion.models.meta import RoleAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
|
||||||
|
|
||||||
|
from core.serializers.centurionaudit import (
|
||||||
|
BaseSerializer,
|
||||||
|
ViewSerializer as AuditHistoryViewSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'RoleAuditHistoryModelSerializer')
|
||||||
|
class ModelSerializer(
|
||||||
|
common.CommonModelSerializer,
|
||||||
|
BaseSerializer
|
||||||
|
):
|
||||||
|
"""Git Group Audit History Base Model"""
|
||||||
|
|
||||||
|
|
||||||
|
_urls = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = RoleAuditHistory
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'organization',
|
||||||
|
'display_name',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'before',
|
||||||
|
'after',
|
||||||
|
'action',
|
||||||
|
'user',
|
||||||
|
'created',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'RoleAuditHistoryViewSerializer')
|
||||||
|
class ViewSerializer(
|
||||||
|
ModelSerializer,
|
||||||
|
AuditHistoryViewSerializer,
|
||||||
|
):
|
||||||
|
"""Git Group Audit History Base View Model"""
|
||||||
|
pass
|
87
app/access/serializers/centurionmodelnote_role.py
Normal file
87
app/access/serializers/centurionmodelnote_role.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from drf_spectacular.utils import extend_schema_serializer
|
||||||
|
|
||||||
|
from access.serializers.organization import (TenantBaseSerializer)
|
||||||
|
|
||||||
|
from centurion.models.meta import RoleCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
|
||||||
|
|
||||||
|
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
|
||||||
|
BaseSerializer,
|
||||||
|
ModelSerializer as BaseModelModelSerializer,
|
||||||
|
ViewSerializer as BaseModelViewSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'RoleModelNoteModelSerializer')
|
||||||
|
class ModelSerializer(
|
||||||
|
BaseModelModelSerializer,
|
||||||
|
):
|
||||||
|
|
||||||
|
|
||||||
|
_urls = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
|
def get_url(self, item) -> dict:
|
||||||
|
|
||||||
|
return {
|
||||||
|
'_self': item.get_url( request = self._context['view'].request ),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = RoleCenturionModelNote
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'organization',
|
||||||
|
'display_name',
|
||||||
|
'body',
|
||||||
|
'created_by',
|
||||||
|
'modified_by',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'organization',
|
||||||
|
'created_by',
|
||||||
|
'modified_by',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
|
||||||
|
is_valid = False
|
||||||
|
|
||||||
|
note_model = self.Meta.model.model.field.related_model
|
||||||
|
|
||||||
|
attrs['model'] = note_model.objects.get(
|
||||||
|
id = int( self.context['view'].kwargs['model_id'] )
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
is_valid = super().validate(attrs)
|
||||||
|
|
||||||
|
return is_valid
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'RoleModelNoteViewSerializer')
|
||||||
|
class ViewSerializer(
|
||||||
|
ModelSerializer,
|
||||||
|
BaseModelViewSerializer,
|
||||||
|
):
|
||||||
|
|
||||||
|
organization = TenantBaseSerializer( many = False, read_only = True )
|
@ -0,0 +1,44 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from django.test import Client
|
||||||
|
|
||||||
|
|
||||||
|
class AdditionalTestCases:
|
||||||
|
|
||||||
|
|
||||||
|
def test_permission_add(self, model_instance, api_request_permissions,
|
||||||
|
model_kwargs, kwargs_api_create
|
||||||
|
):
|
||||||
|
""" Check correct permission for add
|
||||||
|
|
||||||
|
Attempt to add as user with permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
client = Client()
|
||||||
|
|
||||||
|
client.force_login( api_request_permissions['user']['add'] )
|
||||||
|
|
||||||
|
the_model = model_instance( kwargs_create = model_kwargs )
|
||||||
|
|
||||||
|
url = the_model.get_url( many = True )
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
path = url,
|
||||||
|
data = kwargs_api_create,
|
||||||
|
content_type = 'application/json'
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200, response.content
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_returned_data_from_user_and_global_organizations_only(
|
||||||
|
self
|
||||||
|
):
|
||||||
|
"""Check items returned
|
||||||
|
|
||||||
|
Items returned from the query Must be from the users organization and
|
||||||
|
global ONLY!
|
||||||
|
"""
|
||||||
|
|
||||||
|
pytest.mark.xfail( reason = 'model is not for global use' )
|
@ -10,6 +10,8 @@ from access.serializers.role import Role, ModelSerializer
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_role
|
||||||
|
@pytest.mark.module_role
|
||||||
class ValidationSerializer(
|
class ValidationSerializer(
|
||||||
TestCase,
|
TestCase,
|
||||||
):
|
):
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import django
|
import django
|
||||||
|
import pytest
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
@ -20,6 +22,8 @@ User = django.contrib.auth.get_user_model()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_role
|
||||||
|
@pytest.mark.module_role
|
||||||
class ViewSetBase:
|
class ViewSetBase:
|
||||||
|
|
||||||
add_data: dict = None
|
add_data: dict = None
|
||||||
@ -238,7 +242,7 @@ class RolePermissionsAPITest(
|
|||||||
|
|
||||||
url_view_kwargs: dict = {}
|
url_view_kwargs: dict = {}
|
||||||
|
|
||||||
url_name = '_api_v2_role'
|
url_name = '_api_role'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -260,7 +264,7 @@ class RoleViewSetTest(
|
|||||||
|
|
||||||
url_view_kwargs: dict = {}
|
url_view_kwargs: dict = {}
|
||||||
|
|
||||||
url_name = '_api_v2_role'
|
url_name = '_api_role'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -283,4 +287,4 @@ class RoleMetadataTest(
|
|||||||
|
|
||||||
url_view_kwargs: dict = {}
|
url_view_kwargs: dict = {}
|
||||||
|
|
||||||
url_name = '_api_v2_role'
|
url_name = '_api_role'
|
||||||
|
19
app/access/tests/unit/role/conftest.py
Normal file
19
app/access/tests/unit/role/conftest.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture( scope = 'class')
|
||||||
|
def model(model_role):
|
||||||
|
|
||||||
|
yield model_role
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture( scope = 'class', autouse = True)
|
||||||
|
def model_kwargs(request, kwargs_role):
|
||||||
|
|
||||||
|
request.cls.kwargs_create_item = kwargs_role.copy()
|
||||||
|
|
||||||
|
yield kwargs_role.copy()
|
||||||
|
|
||||||
|
if hasattr(request.cls, 'kwargs_create_item'):
|
||||||
|
del request.cls.kwargs_create_item
|
@ -1,3 +1,4 @@
|
|||||||
|
import pytest
|
||||||
import django
|
import django
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
@ -18,6 +19,7 @@ User = django.contrib.auth.get_user_model()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_role
|
||||||
class APITestCases(
|
class APITestCases(
|
||||||
APITenancyObject,
|
APITenancyObject,
|
||||||
):
|
):
|
||||||
@ -154,6 +156,7 @@ class APITestCases(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_role
|
||||||
class RoleAPITest(
|
class RoleAPITest(
|
||||||
APITestCases,
|
APITestCases,
|
||||||
TestCase,
|
TestCase,
|
||||||
@ -163,7 +166,7 @@ class RoleAPITest(
|
|||||||
|
|
||||||
model = Role
|
model = Role
|
||||||
|
|
||||||
url_ns_name = '_api_v2_role'
|
url_ns_name = '_api_role'
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -1,30 +1,70 @@
|
|||||||
from django.test import TestCase
|
import pytest
|
||||||
|
|
||||||
from access.models.role import Role
|
from django.db import models
|
||||||
|
|
||||||
from centurion.tests.unit.test_unit_models import (
|
|
||||||
TenancyObjectInheritedCases
|
from core.tests.unit.centurion_abstract.test_unit_centurion_abstract_model import (
|
||||||
|
CenturionAbstractModelInheritedCases
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_role
|
||||||
class RoleModelTestCases(
|
class RoleModelTestCases(
|
||||||
TenancyObjectInheritedCases,
|
CenturionAbstractModelInheritedCases
|
||||||
):
|
):
|
||||||
|
|
||||||
model = None
|
|
||||||
|
|
||||||
kwargs_item_create: dict = None
|
@property
|
||||||
|
def parameterized_class_attributes(self):
|
||||||
|
|
||||||
|
return {
|
||||||
|
'model_tag': {
|
||||||
|
'type': str,
|
||||||
|
'value': 'role'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parameterized_model_fields(self):
|
||||||
|
|
||||||
class RoleModelTest(
|
return {
|
||||||
RoleModelTestCases,
|
'name': {
|
||||||
TestCase,
|
'blank': False,
|
||||||
):
|
'default': models.fields.NOT_PROVIDED,
|
||||||
|
'field_type': models.CharField,
|
||||||
model = Role
|
'max_length': 30,
|
||||||
|
'null': False,
|
||||||
kwargs_item_create: dict = {
|
'unique': False,
|
||||||
'name': 'a role'
|
},
|
||||||
|
'permissions': {
|
||||||
|
'blank': True,
|
||||||
|
'default': models.fields.NOT_PROVIDED,
|
||||||
|
'field_type': models.ManyToManyField,
|
||||||
|
'null': False,
|
||||||
|
'unique': False,
|
||||||
|
},
|
||||||
|
'modified': {
|
||||||
|
'blank': False,
|
||||||
|
'default': models.fields.NOT_PROVIDED,
|
||||||
|
'field_type': models.DateTimeField,
|
||||||
|
'null': False,
|
||||||
|
'unique': False,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RoleModelInheritedCases(
|
||||||
|
RoleModelTestCases,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_role
|
||||||
|
class RoleModelPyTest(
|
||||||
|
RoleModelTestCases,
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
@ -20,6 +20,8 @@ import pytest
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_role
|
||||||
|
@pytest.mark.module_role
|
||||||
@pytest.mark.skip( reason = 'figure out how to isolate so entirety of unit tests can run without this test failing' )
|
@pytest.mark.skip( reason = 'figure out how to isolate so entirety of unit tests can run without this test failing' )
|
||||||
# @pytest.mark.forked
|
# @pytest.mark.forked
|
||||||
# @pytest.mark.django_db
|
# @pytest.mark.django_db
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
|
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
@ -9,6 +11,7 @@ from api.tests.unit.test_unit_common_viewset import ModelViewSetInheritedCases
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_role
|
||||||
class ViewsetTestCases(
|
class ViewsetTestCases(
|
||||||
ModelViewSetInheritedCases,
|
ModelViewSetInheritedCases,
|
||||||
):
|
):
|
||||||
@ -44,6 +47,7 @@ class ViewsetTestCases(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_role
|
||||||
class RoleViewsetTest(
|
class RoleViewsetTest(
|
||||||
ViewsetTestCases,
|
ViewsetTestCases,
|
||||||
TestCase,
|
TestCase,
|
||||||
@ -51,6 +55,6 @@ class RoleViewsetTest(
|
|||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
|
||||||
route_name = 'v2:_api_v2_role'
|
route_name = 'v2:_api_role'
|
||||||
|
|
||||||
viewset = ViewSet
|
viewset = ViewSet
|
||||||
|
@ -82,12 +82,7 @@ router.register(
|
|||||||
|
|
||||||
router.register(
|
router.register(
|
||||||
prefix = 'role', viewset = role.ViewSet,
|
prefix = 'role', viewset = role.ViewSet,
|
||||||
feature_flag = '2025-00003', basename = '_api_v2_role'
|
feature_flag = '2025-00003', basename = '_api_role'
|
||||||
)
|
)
|
||||||
|
|
||||||
# router.register(
|
|
||||||
# prefix = 'role/(?P<model_id>[0-9]+)/notes', viewset = role_notes.ViewSet,
|
|
||||||
# feature_flag = '2025-00003', basename = '_api_v2_role_note'
|
|
||||||
# )
|
|
||||||
|
|
||||||
urlpatterns = router.urls
|
urlpatterns = router.urls
|
||||||
|
@ -37,7 +37,7 @@ class Index(IndexViewset):
|
|||||||
if self.request.feature_flag['2025-00003']:
|
if self.request.feature_flag['2025-00003']:
|
||||||
|
|
||||||
response.update({
|
response.update({
|
||||||
"role": reverse( 'v2:_api_v2_role-list', request=request ),
|
"role": reverse( 'v2:_api_role-list', request=request ),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiResponse
|
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiResponse
|
||||||
|
|
||||||
# THis import only exists so that the migrations can be created
|
|
||||||
from access.models.role_history import RoleHistory # pylint: disable=W0611:unused-import
|
|
||||||
from access.serializers.role import (
|
from access.serializers.role import (
|
||||||
Role,
|
Role,
|
||||||
ModelSerializer,
|
ModelSerializer,
|
||||||
|
@ -0,0 +1,118 @@
|
|||||||
|
# Generated by Django 5.1.10 on 2025-07-10 09:10
|
||||||
|
|
||||||
|
import access.models.tenancy_abstract
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("access", "0019_companyaudithistory_companycenturionmodelnote"),
|
||||||
|
("accounting", "0001_initial"),
|
||||||
|
("core", "0033_alter_ticketcommentcategory_parent_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="assetbase",
|
||||||
|
name="id",
|
||||||
|
field=models.AutoField(
|
||||||
|
help_text="ID of the item",
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
unique=True,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="assetbase",
|
||||||
|
name="model_notes",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Tid bits of information",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Notes",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="assetbase",
|
||||||
|
name="organization",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
help_text="Tenant this belongs to",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="+",
|
||||||
|
to="access.tenant",
|
||||||
|
validators=[
|
||||||
|
access.models.tenancy_abstract.TenancyAbstractModel.validatate_organization_exists
|
||||||
|
],
|
||||||
|
verbose_name="Tenant",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="AssetBaseAuditHistory",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"centurionaudit_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="core.centurionaudit",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model",
|
||||||
|
models.ForeignKey(
|
||||||
|
help_text="Model this history belongs to",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="audit_history",
|
||||||
|
to="accounting.assetbase",
|
||||||
|
verbose_name="Model",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Asset History",
|
||||||
|
"verbose_name_plural": "Asset Histories",
|
||||||
|
"db_table": "accounting_assetbase_audithistory",
|
||||||
|
"managed": True,
|
||||||
|
},
|
||||||
|
bases=("core.centurionaudit",),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="AssetBaseCenturionModelNote",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"centurionmodelnote_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="core.centurionmodelnote",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model",
|
||||||
|
models.ForeignKey(
|
||||||
|
help_text="Model this note belongs to",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="+",
|
||||||
|
to="accounting.assetbase",
|
||||||
|
verbose_name="Model",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Asset Note",
|
||||||
|
"verbose_name_plural": "Asset Notes",
|
||||||
|
"db_table": "accounting_assetbase_centurionmodelnote",
|
||||||
|
"managed": True,
|
||||||
|
},
|
||||||
|
bases=("core.centurionmodelnote",),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 5.1.10 on 2025-07-10 09:31
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("accounting", "0002_alter_assetbase_id_alter_assetbase_model_notes_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name="AssetBaseHistory",
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name="AssetBaseNotes",
|
||||||
|
),
|
||||||
|
]
|
@ -1,5 +0,0 @@
|
|||||||
from .asset_base_history import AssetBaseHistory # pylint: disable=W0611:unused-import
|
|
||||||
|
|
||||||
from .asset_base_history import AssetBaseHistory # pylint: disable=W0611:unused-import
|
|
||||||
|
|
||||||
from .asset_base_notes import AssetBaseNotes # pylint: disable=W0611:unused-import
|
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from rest_framework.reverse import reverse
|
from access.fields import AutoLastModifiedField
|
||||||
|
|
||||||
from access.fields import AutoCreatedField, AutoLastModifiedField
|
from core.models.centurion import CenturionModel
|
||||||
from access.models.tenancy import TenancyObject
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AssetBase(
|
class AssetBase(
|
||||||
TenancyObject,
|
CenturionModel,
|
||||||
):
|
):
|
||||||
"""Asset Base Model
|
"""Asset Base Model
|
||||||
|
|
||||||
@ -21,6 +20,10 @@ class AssetBase(
|
|||||||
|
|
||||||
app_namespace = 'accounting'
|
app_namespace = 'accounting'
|
||||||
|
|
||||||
|
model_tag = 'asset'
|
||||||
|
|
||||||
|
url_model_name = 'asset'
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _base_model(self):
|
def _base_model(self):
|
||||||
@ -50,18 +53,6 @@ class AssetBase(
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
is_global = None
|
|
||||||
|
|
||||||
|
|
||||||
id = models.AutoField(
|
|
||||||
blank = False,
|
|
||||||
help_text = 'Ticket ID Number',
|
|
||||||
primary_key = True,
|
|
||||||
unique = True,
|
|
||||||
verbose_name = 'Number',
|
|
||||||
)
|
|
||||||
|
|
||||||
asset_number = models.CharField(
|
asset_number = models.CharField(
|
||||||
blank = True,
|
blank = True,
|
||||||
help_text = 'Number or tag to use to track this asset',
|
help_text = 'Number or tag to use to track this asset',
|
||||||
@ -96,14 +87,11 @@ class AssetBase(
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Status
|
# Status
|
||||||
|
|
||||||
# model (manufacturer / model)
|
# model (manufacturer / model)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def get_model_type(self):
|
def get_model_type(self):
|
||||||
"""Fetch the Ticket Type
|
"""Fetch the Ticket Type
|
||||||
@ -137,7 +125,7 @@ class AssetBase(
|
|||||||
|
|
||||||
if(
|
if(
|
||||||
( isinstance(model, AssetBase) or issubclass(model, AssetBase) )
|
( isinstance(model, AssetBase) or issubclass(model, AssetBase) )
|
||||||
and AssetBase._meta.sub_model_type != 'asset'
|
# and AssetBase._meta.sub_model_type != 'asset'
|
||||||
|
|
||||||
):
|
):
|
||||||
|
|
||||||
@ -159,12 +147,6 @@ class AssetBase(
|
|||||||
verbose_name = 'Asset Type',
|
verbose_name = 'Asset Type',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
created = AutoCreatedField(
|
|
||||||
editable = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
modified = AutoLastModifiedField()
|
modified = AutoLastModifiedField()
|
||||||
|
|
||||||
|
|
||||||
@ -237,6 +219,26 @@ class AssetBase(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def clean_fields(self, exclude = None):
|
||||||
|
|
||||||
|
related_model = self.get_related_model()
|
||||||
|
|
||||||
|
if related_model is None:
|
||||||
|
|
||||||
|
related_model = self
|
||||||
|
|
||||||
|
if (
|
||||||
|
self.asset_type != str(related_model._meta.sub_model_type).lower().replace(' ', '_')
|
||||||
|
and str(related_model._meta.sub_model_type).lower().replace(' ', '_') != 'asset'
|
||||||
|
):
|
||||||
|
|
||||||
|
self.asset_type = str(related_model._meta.sub_model_type).lower().replace(' ', '_')
|
||||||
|
|
||||||
|
|
||||||
|
super().clean_fields(exclude = exclude)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_related_field_name(self) -> str:
|
def get_related_field_name(self) -> str:
|
||||||
|
|
||||||
meta = getattr(self, '_meta')
|
meta = getattr(self, '_meta')
|
||||||
@ -260,6 +262,7 @@ class AssetBase(
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_related_model(self):
|
def get_related_model(self):
|
||||||
"""Recursive model Fetch
|
"""Recursive model Fetch
|
||||||
|
|
||||||
@ -292,74 +295,3 @@ class AssetBase(
|
|||||||
|
|
||||||
|
|
||||||
return related_model
|
return related_model
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_url( self, request = None ) -> str:
|
|
||||||
|
|
||||||
kwargs = self.get_url_kwargs()
|
|
||||||
|
|
||||||
url_path_name = '_api_v2_asset_sub'
|
|
||||||
|
|
||||||
if self._meta.sub_model_type == 'asset':
|
|
||||||
|
|
||||||
url_path_name = '_api_v2_asset'
|
|
||||||
|
|
||||||
if request:
|
|
||||||
|
|
||||||
return reverse(f"v2:accounting:{url_path_name}-detail", request=request, kwargs = kwargs )
|
|
||||||
|
|
||||||
return reverse(f"v2:accounting:{url_path_name}-detail", kwargs = kwargs )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_url_kwargs(self) -> dict:
|
|
||||||
|
|
||||||
kwargs = {
|
|
||||||
'asset_model': self.asset_type,
|
|
||||||
}
|
|
||||||
|
|
||||||
if self._meta.sub_model_type == 'asset':
|
|
||||||
|
|
||||||
kwargs = {}
|
|
||||||
|
|
||||||
|
|
||||||
if self.id:
|
|
||||||
|
|
||||||
kwargs.update({
|
|
||||||
'pk': self.id
|
|
||||||
})
|
|
||||||
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
|
||||||
|
|
||||||
related_model = self.get_related_model()
|
|
||||||
|
|
||||||
if related_model is None:
|
|
||||||
|
|
||||||
related_model = self
|
|
||||||
|
|
||||||
if self.asset_type != str(related_model._meta.sub_model_type).lower().replace(' ', '_'):
|
|
||||||
|
|
||||||
self.asset_type = str(related_model._meta.sub_model_type).lower().replace(' ', '_')
|
|
||||||
|
|
||||||
super().save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def save_history(self, before: dict, after: dict) -> bool:
|
|
||||||
|
|
||||||
from accounting.models.asset_base_history import AssetBaseHistory
|
|
||||||
|
|
||||||
history = super().save_history(
|
|
||||||
before = before,
|
|
||||||
after = after,
|
|
||||||
history_model = AssetBaseHistory
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
return history
|
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
from accounting.models.asset_base import AssetBase
|
|
||||||
|
|
||||||
from core.models.model_history import ModelHistory
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AssetBaseHistory(
|
|
||||||
ModelHistory
|
|
||||||
):
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
|
|
||||||
db_table = 'accounting_assetbase_history'
|
|
||||||
|
|
||||||
ordering = ModelHistory._meta.ordering
|
|
||||||
|
|
||||||
verbose_name = 'Asset History'
|
|
||||||
|
|
||||||
verbose_name_plural = 'Asset History'
|
|
||||||
|
|
||||||
|
|
||||||
model = models.ForeignKey(
|
|
||||||
AssetBase,
|
|
||||||
blank = False,
|
|
||||||
help_text = 'Model this note belongs to',
|
|
||||||
null = False,
|
|
||||||
on_delete = models.CASCADE,
|
|
||||||
related_name = 'history',
|
|
||||||
verbose_name = 'Model',
|
|
||||||
)
|
|
||||||
|
|
||||||
table_fields: list = []
|
|
||||||
|
|
||||||
page_layout: dict = []
|
|
||||||
|
|
||||||
|
|
||||||
def get_object(self):
|
|
||||||
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
def get_serialized_model(self, serializer_context):
|
|
||||||
|
|
||||||
model = None
|
|
||||||
|
|
||||||
from accounting.serializers.asset import BaseSerializer
|
|
||||||
|
|
||||||
model = BaseSerializer(self.model, context = serializer_context)
|
|
||||||
|
|
||||||
return model
|
|
@ -1,47 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
from accounting.models.asset_base import AssetBase
|
|
||||||
|
|
||||||
from core.models.model_notes import ModelNotes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AssetBaseNotes(
|
|
||||||
ModelNotes
|
|
||||||
):
|
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
|
|
||||||
db_table = 'accounting_assetbase_notes'
|
|
||||||
|
|
||||||
ordering = ModelNotes._meta.ordering
|
|
||||||
|
|
||||||
verbose_name = 'Asset Note'
|
|
||||||
|
|
||||||
verbose_name_plural = 'Asset Notes'
|
|
||||||
|
|
||||||
|
|
||||||
model = models.ForeignKey(
|
|
||||||
AssetBase,
|
|
||||||
blank = False,
|
|
||||||
help_text = 'Model this note belongs to',
|
|
||||||
null = False,
|
|
||||||
on_delete = models.CASCADE,
|
|
||||||
related_name = 'notes',
|
|
||||||
verbose_name = 'Model',
|
|
||||||
)
|
|
||||||
|
|
||||||
app_namespace = 'accounting'
|
|
||||||
|
|
||||||
table_fields: list = []
|
|
||||||
|
|
||||||
page_layout: dict = []
|
|
||||||
|
|
||||||
|
|
||||||
def get_url_kwargs(self) -> dict:
|
|
||||||
|
|
||||||
return {
|
|
||||||
'model_id': self.model.pk,
|
|
||||||
'pk': self.pk
|
|
||||||
}
|
|
56
app/accounting/serializers/centurionaudit_assetbase.py
Normal file
56
app/accounting/serializers/centurionaudit_assetbase.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from drf_spectacular.utils import extend_schema_serializer
|
||||||
|
|
||||||
|
from api.serializers import common
|
||||||
|
|
||||||
|
from centurion.models.meta import AssetBaseAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
|
||||||
|
|
||||||
|
from core.serializers.centurionaudit import (
|
||||||
|
BaseSerializer,
|
||||||
|
ViewSerializer as AuditHistoryViewSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'AssetBaseAuditHistoryModelSerializer')
|
||||||
|
class ModelSerializer(
|
||||||
|
common.CommonModelSerializer,
|
||||||
|
BaseSerializer
|
||||||
|
):
|
||||||
|
"""Git Group Audit History Base Model"""
|
||||||
|
|
||||||
|
|
||||||
|
_urls = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = AssetBaseAuditHistory
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'organization',
|
||||||
|
'display_name',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'before',
|
||||||
|
'after',
|
||||||
|
'action',
|
||||||
|
'user',
|
||||||
|
'created',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'AssetBaseAuditHistoryViewSerializer')
|
||||||
|
class ViewSerializer(
|
||||||
|
ModelSerializer,
|
||||||
|
AuditHistoryViewSerializer,
|
||||||
|
):
|
||||||
|
"""Git Group Audit History Base View Model"""
|
||||||
|
pass
|
87
app/accounting/serializers/centurionmodelnote_assetbase.py
Normal file
87
app/accounting/serializers/centurionmodelnote_assetbase.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from drf_spectacular.utils import extend_schema_serializer
|
||||||
|
|
||||||
|
from access.serializers.organization import (TenantBaseSerializer)
|
||||||
|
|
||||||
|
from centurion.models.meta import AssetBaseCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
|
||||||
|
|
||||||
|
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
|
||||||
|
BaseSerializer,
|
||||||
|
ModelSerializer as BaseModelModelSerializer,
|
||||||
|
ViewSerializer as BaseModelViewSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'AssetBaseModelNoteModelSerializer')
|
||||||
|
class ModelSerializer(
|
||||||
|
BaseModelModelSerializer,
|
||||||
|
):
|
||||||
|
|
||||||
|
|
||||||
|
_urls = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
|
def get_url(self, item) -> dict:
|
||||||
|
|
||||||
|
return {
|
||||||
|
'_self': item.get_url( request = self._context['view'].request ),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = AssetBaseCenturionModelNote
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'organization',
|
||||||
|
'display_name',
|
||||||
|
'body',
|
||||||
|
'created_by',
|
||||||
|
'modified_by',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'organization',
|
||||||
|
'created_by',
|
||||||
|
'modified_by',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
|
||||||
|
is_valid = False
|
||||||
|
|
||||||
|
note_model = self.Meta.model.model.field.related_model
|
||||||
|
|
||||||
|
attrs['model'] = note_model.objects.get(
|
||||||
|
id = int( self.context['view'].kwargs['model_id'] )
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
is_valid = super().validate(attrs)
|
||||||
|
|
||||||
|
return is_valid
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'AssetBaseModelNoteViewSerializer')
|
||||||
|
class ViewSerializer(
|
||||||
|
ModelSerializer,
|
||||||
|
BaseModelViewSerializer,
|
||||||
|
):
|
||||||
|
|
||||||
|
organization = TenantBaseSerializer( many = False, read_only = True )
|
@ -18,7 +18,7 @@ def model(request):
|
|||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def create_serializer():
|
def create_serializer():
|
||||||
|
|
||||||
from accounting.serializers.asset import ModelSerializer
|
from accounting.serializers.assetbase import ModelSerializer
|
||||||
|
|
||||||
|
|
||||||
yield ModelSerializer
|
yield ModelSerializer
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import django
|
import django
|
||||||
|
import pytest
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
@ -15,6 +17,7 @@ User = django.contrib.auth.get_user_model()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_assetbase
|
||||||
class MetadataTestCases(
|
class MetadataTestCases(
|
||||||
MetadataAttributesFunctional,
|
MetadataAttributesFunctional,
|
||||||
):
|
):
|
||||||
@ -234,7 +237,7 @@ class AssetBaseMetadataInheritedCases(
|
|||||||
|
|
||||||
kwargs_create_item_diff_org: dict = {}
|
kwargs_create_item_diff_org: dict = {}
|
||||||
|
|
||||||
url_name = 'accounting:_api_v2_asset_sub'
|
url_name = 'accounting:_api_asset_sub'
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -251,21 +254,22 @@ class AssetBaseMetadataInheritedCases(
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.url_kwargs = {
|
self.url_kwargs = {
|
||||||
'asset_model': self.model._meta.sub_model_type
|
'model_name': self.model._meta.model_name
|
||||||
}
|
}
|
||||||
|
|
||||||
self.url_view_kwargs = {
|
self.url_view_kwargs = {
|
||||||
'asset_model': self.model._meta.sub_model_type
|
'model_name': self.model._meta.model_name
|
||||||
}
|
}
|
||||||
|
|
||||||
super().setUpTestData()
|
super().setUpTestData()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class AssetBaseMetadataTest(
|
class AssetBaseMetadataTest(
|
||||||
MetadataTestCases,
|
MetadataTestCases,
|
||||||
TestCase,
|
TestCase,
|
||||||
|
|
||||||
):
|
):
|
||||||
|
|
||||||
url_name = 'accounting:_api_v2_asset'
|
url_name = 'accounting:_api_asset'
|
||||||
|
@ -6,6 +6,7 @@ from api.tests.functional.test_functional_api_permissions import (
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_assetbase
|
||||||
class PermissionsAPITestCases(
|
class PermissionsAPITestCases(
|
||||||
APIPermissionsInheritedCases,
|
APIPermissionsInheritedCases,
|
||||||
):
|
):
|
||||||
@ -36,7 +37,7 @@ class PermissionsAPITestCases(
|
|||||||
|
|
||||||
url_kwargs: dict = {}
|
url_kwargs: dict = {}
|
||||||
|
|
||||||
url_name = 'accounting:_api_v2_asset'
|
url_name = 'accounting:_api_asset'
|
||||||
|
|
||||||
url_view_kwargs: dict = {}
|
url_view_kwargs: dict = {}
|
||||||
|
|
||||||
@ -65,18 +66,18 @@ class AssetBasePermissionsAPIInheritedCases(
|
|||||||
|
|
||||||
kwargs_create_item_diff_org: dict = None
|
kwargs_create_item_diff_org: dict = None
|
||||||
|
|
||||||
url_name = 'accounting:_api_v2_asset_sub'
|
url_name = 'accounting:_api_asset_sub'
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='class')
|
@pytest.fixture(scope='class')
|
||||||
def inherited_var_setup(self, request):
|
def inherited_var_setup(self, request):
|
||||||
|
|
||||||
request.cls.url_kwargs.update({
|
request.cls.url_kwargs.update({
|
||||||
'asset_model': self.model._meta.sub_model_type
|
'model_name': self.model._meta.model_name
|
||||||
})
|
})
|
||||||
|
|
||||||
request.cls.url_view_kwargs.update({
|
request.cls.url_view_kwargs.update({
|
||||||
'asset_model': self.model._meta.sub_model_type
|
'model_name': self.model._meta.model_name
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -94,6 +95,8 @@ class AssetBasePermissionsAPIInheritedCases(
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class AssetBasePermissionsAPIPyTest(
|
class AssetBasePermissionsAPIPyTest(
|
||||||
PermissionsAPITestCases,
|
PermissionsAPITestCases,
|
||||||
):
|
):
|
||||||
|
@ -27,6 +27,7 @@ class MockView:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_assetbase
|
||||||
class AssetBaseSerializerTestCases:
|
class AssetBaseSerializerTestCases:
|
||||||
|
|
||||||
|
|
||||||
@ -188,6 +189,7 @@ class AssetBaseSerializerInheritedCases(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class AssetBaseSerializerPyTest(
|
class AssetBaseSerializerPyTest(
|
||||||
AssetBaseSerializerTestCases,
|
AssetBaseSerializerTestCases,
|
||||||
):
|
):
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import django
|
import django
|
||||||
|
import pytest
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
@ -15,6 +17,7 @@ User = django.contrib.auth.get_user_model()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_assetbase
|
||||||
class ViewSetBase:
|
class ViewSetBase:
|
||||||
|
|
||||||
add_data: dict = {
|
add_data: dict = {
|
||||||
@ -237,7 +240,7 @@ class AssetBaseViewSetInheritedCases(
|
|||||||
|
|
||||||
model = None
|
model = None
|
||||||
|
|
||||||
url_name = 'accounting:_api_v2_asset_sub'
|
url_name = 'accounting:_api_asset_sub'
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -254,20 +257,21 @@ class AssetBaseViewSetInheritedCases(
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.url_kwargs = {
|
self.url_kwargs = {
|
||||||
'asset_model': self.model._meta.sub_model_type
|
'model_name': self.model._meta.model_name
|
||||||
}
|
}
|
||||||
|
|
||||||
self.url_view_kwargs = {
|
self.url_view_kwargs = {
|
||||||
'asset_model': self.model._meta.sub_model_type
|
'model_name': self.model._meta.model_name
|
||||||
}
|
}
|
||||||
|
|
||||||
super().setUpTestData()
|
super().setUpTestData()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class AssetBaseViewSetTest(
|
class AssetBaseViewSetTest(
|
||||||
ViewSetTestCases,
|
ViewSetTestCases,
|
||||||
TestCase,
|
TestCase,
|
||||||
):
|
):
|
||||||
|
|
||||||
url_name = 'accounting:_api_v2_asset'
|
url_name = 'accounting:_api_asset'
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from accounting.models.asset_base import AssetBase
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture( scope = 'class')
|
@pytest.fixture( scope = 'class')
|
||||||
def model(request):
|
def model(model_assetbase):
|
||||||
|
|
||||||
request.cls.model = AssetBase
|
yield model_assetbase
|
||||||
|
|
||||||
yield request.cls.model
|
|
||||||
|
|
||||||
del request.cls.model
|
@pytest.fixture( scope = 'class', autouse = True)
|
||||||
|
def model_kwargs(request, kwargs_assetbase):
|
||||||
|
|
||||||
|
request.cls.kwargs_create_item = kwargs_assetbase.copy()
|
||||||
|
|
||||||
|
yield kwargs_assetbase.copy()
|
||||||
|
|
||||||
|
if hasattr(request.cls, 'kwargs_create_item'):
|
||||||
|
try:
|
||||||
|
del request.cls.kwargs_create_item
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
@ -8,6 +8,7 @@ from api.tests.functional.test_functional_api_fields import (
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_assetbase
|
||||||
class AssetBaseAPITestCases(
|
class AssetBaseAPITestCases(
|
||||||
APIFieldsInheritedCases,
|
APIFieldsInheritedCases,
|
||||||
):
|
):
|
||||||
@ -23,7 +24,7 @@ class AssetBaseAPITestCases(
|
|||||||
if model != self.base_model:
|
if model != self.base_model:
|
||||||
|
|
||||||
request.cls.url_view_kwargs.update({
|
request.cls.url_view_kwargs.update({
|
||||||
'asset_model': model._meta.sub_model_type,
|
'model_name': model._meta.model_name,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ class AssetBaseAPITestCases(
|
|||||||
'serial_number': '65756756756',
|
'serial_number': '65756756756',
|
||||||
}
|
}
|
||||||
|
|
||||||
url_ns_name = 'accounting:_api_v2_asset'
|
url_ns_name = 'accounting:_api_asset'
|
||||||
"""Url namespace (optional, if not required) and url name"""
|
"""Url namespace (optional, if not required) and url name"""
|
||||||
|
|
||||||
|
|
||||||
@ -68,10 +69,11 @@ class AssetBaseAPIInheritedCases(
|
|||||||
|
|
||||||
model = None
|
model = None
|
||||||
|
|
||||||
url_ns_name = 'accounting:_api_v2_asset_sub'
|
url_ns_name = 'accounting:_api_asset_sub'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class AssetBaseAPIPyTest(
|
class AssetBaseAPIPyTest(
|
||||||
AssetBaseAPITestCases,
|
AssetBaseAPITestCases,
|
||||||
):
|
):
|
||||||
|
@ -4,204 +4,96 @@ from django.db import models
|
|||||||
|
|
||||||
from accounting.models.asset_base import AssetBase
|
from accounting.models.asset_base import AssetBase
|
||||||
|
|
||||||
from centurion.tests.unit.test_unit_models import (
|
from core.tests.unit.centurion_abstract.test_unit_centurion_abstract_model import (
|
||||||
PyTestTenancyObjectInheritedCases,
|
CenturionAbstractModelInheritedCases
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_assetbase
|
||||||
class AssetBaseModelTestCases(
|
class AssetBaseModelTestCases(
|
||||||
PyTestTenancyObjectInheritedCases,
|
CenturionAbstractModelInheritedCases
|
||||||
):
|
):
|
||||||
|
|
||||||
base_model = AssetBase
|
|
||||||
|
|
||||||
kwargs_create_item: dict = {
|
@property
|
||||||
'asset_number': 'a12s432',
|
def parameterized_class_attributes(self):
|
||||||
'serial_number': 'abbcccdddd',
|
|
||||||
}
|
|
||||||
|
|
||||||
sub_model_type = 'asset'
|
return {
|
||||||
"""Sub Model Type
|
'app_namespace': {
|
||||||
|
'type': str,
|
||||||
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
|
'value': 'accounting'
|
||||||
"""
|
},
|
||||||
|
'model_tag': {
|
||||||
|
'type': str,
|
||||||
parameterized_fields: dict = {
|
'value': 'asset'
|
||||||
"asset_number": {
|
},
|
||||||
'field_type': models.fields.CharField,
|
'url_model_name': {
|
||||||
'field_parameter_default_exists': False,
|
'type': str,
|
||||||
'field_parameter_verbose_name_type': str,
|
'value': 'asset'
|
||||||
},
|
},
|
||||||
"serial_number": {
|
|
||||||
'field_type': models.fields.CharField,
|
|
||||||
'field_parameter_default_exists': False,
|
|
||||||
'field_parameter_verbose_name_type': str,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parameterized_model_fields(self):
|
||||||
|
|
||||||
|
return {
|
||||||
|
'asset_number': {
|
||||||
|
'blank': True,
|
||||||
|
'default': models.fields.NOT_PROVIDED,
|
||||||
|
'field_type': models.CharField,
|
||||||
|
'max_length': 30,
|
||||||
|
'null': True,
|
||||||
|
'unique': True,
|
||||||
|
},
|
||||||
|
'serial_number': {
|
||||||
|
'blank': True,
|
||||||
|
'default': models.fields.NOT_PROVIDED,
|
||||||
|
'field_type': models.CharField,
|
||||||
|
'max_length': 30,
|
||||||
|
'null': True,
|
||||||
|
'unique': True,
|
||||||
|
},
|
||||||
|
'asset_type': {
|
||||||
|
'blank': True,
|
||||||
|
'default': 'asset',
|
||||||
|
'field_type': models.CharField,
|
||||||
|
'max_length': 30,
|
||||||
|
'null': False,
|
||||||
|
'unique': False,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_class_inherits_assetbase(self, model):
|
||||||
@pytest.fixture( scope = 'class')
|
|
||||||
def setup_model(self,
|
|
||||||
request,
|
|
||||||
model,
|
|
||||||
django_db_blocker,
|
|
||||||
organization_one,
|
|
||||||
organization_two
|
|
||||||
):
|
|
||||||
|
|
||||||
with django_db_blocker.unblock():
|
|
||||||
|
|
||||||
request.cls.organization = organization_one
|
|
||||||
|
|
||||||
request.cls.different_organization = organization_two
|
|
||||||
|
|
||||||
kwargs_create_item = {}
|
|
||||||
|
|
||||||
for base in reversed(request.cls.__mro__):
|
|
||||||
|
|
||||||
if hasattr(base, 'kwargs_create_item'):
|
|
||||||
|
|
||||||
if base.kwargs_create_item is None:
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
kwargs_create_item.update(**base.kwargs_create_item)
|
|
||||||
|
|
||||||
|
|
||||||
if len(kwargs_create_item) > 0:
|
|
||||||
|
|
||||||
request.cls.kwargs_create_item = kwargs_create_item
|
|
||||||
|
|
||||||
|
|
||||||
if 'organization' not in request.cls.kwargs_create_item:
|
|
||||||
|
|
||||||
request.cls.kwargs_create_item.update({
|
|
||||||
'organization': request.cls.organization
|
|
||||||
})
|
|
||||||
|
|
||||||
yield
|
|
||||||
|
|
||||||
with django_db_blocker.unblock():
|
|
||||||
|
|
||||||
del request.cls.kwargs_create_item
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture( scope = 'class', autouse = True)
|
|
||||||
def class_setup(self,
|
|
||||||
setup_model,
|
|
||||||
create_model,
|
|
||||||
):
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_class_inherits_assetbase(self):
|
|
||||||
""" Class inheritence
|
""" Class inheritence
|
||||||
|
|
||||||
TenancyObject must inherit SaveHistory
|
TenancyObject must inherit SaveHistory
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert issubclass(self.model, AssetBase)
|
assert issubclass(model, AssetBase)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_type_app_namespace(self):
|
|
||||||
"""Attribute Type
|
|
||||||
|
|
||||||
app_namespace is of type str
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert type(self.model.app_namespace) is str
|
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_value_app_namespace(self):
|
|
||||||
"""Attribute Type
|
|
||||||
|
|
||||||
app_namespace has been set, override this test case with the value
|
|
||||||
of attribute `app_namespace`
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.model.app_namespace == 'accounting'
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_is_property_get_model_type(self):
|
|
||||||
"""Function test
|
|
||||||
|
|
||||||
Confirm function `get_model_type` is a property
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert type(self.model.get_model_type) is property
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_value_get_model_type(self):
|
|
||||||
"""Function test
|
|
||||||
|
|
||||||
Confirm function `get_model_type` returns None for base model
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.item.get_model_type is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_value_get_related_model(self):
|
|
||||||
"""Function test
|
|
||||||
|
|
||||||
Confirm function `get_related_model` is of the sub-model type
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert type(self.item.get_related_model()) == self.model
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_value_get_url(self):
|
|
||||||
|
|
||||||
assert self.item.get_url() == '/api/v2/accounting/asset/' + str(self.item.id)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AssetBaseModelInheritedCases(
|
class AssetBaseModelInheritedCases(
|
||||||
AssetBaseModelTestCases,
|
AssetBaseModelTestCases,
|
||||||
):
|
):
|
||||||
"""Sub-Ticket Test Cases
|
|
||||||
|
|
||||||
Test Cases for Ticket models that inherit from model AssetBase
|
|
||||||
"""
|
|
||||||
|
|
||||||
kwargs_create_item: dict = {}
|
|
||||||
|
|
||||||
model = None
|
|
||||||
|
|
||||||
|
|
||||||
sub_model_type = None
|
def test_method_get_url_kwargs(self, mocker, model_instance, settings):
|
||||||
"""Ticket Sub Model Type
|
|
||||||
|
|
||||||
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
|
url = model_instance.get_url_kwargs()
|
||||||
"""
|
|
||||||
|
|
||||||
|
assert model_instance.get_url_kwargs() == {
|
||||||
def test_function_value_get_model_type(self):
|
'model_name': model_instance._meta.model_name,
|
||||||
"""Function test
|
'pk': model_instance.id
|
||||||
|
}
|
||||||
Confirm function `get_model_type` does not have a value of None
|
|
||||||
value should be equaul to Meta.sub_model_type
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.item.get_model_type == self.item._meta.sub_model_type
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class AssetBaseModelPyTest(
|
class AssetBaseModelPyTest(
|
||||||
AssetBaseModelTestCases,
|
AssetBaseModelTestCases,
|
||||||
):
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
def test_function_value_get_related_model(self):
|
|
||||||
"""Function test
|
|
||||||
|
|
||||||
Confirm function `get_related_model` is None for base model
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.item.get_related_model() is None
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
|
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
@ -11,8 +13,13 @@ from accounting.viewsets.asset import (
|
|||||||
|
|
||||||
from api.tests.unit.test_unit_common_viewset import SubModelViewSetInheritedCases
|
from api.tests.unit.test_unit_common_viewset import SubModelViewSetInheritedCases
|
||||||
|
|
||||||
|
from centurion.tests.abstract.mock_view import MockRequest
|
||||||
|
|
||||||
|
from settings.models.app_settings import AppSettings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_assetbase
|
||||||
class AssetBaseViewsetTestCases(
|
class AssetBaseViewsetTestCases(
|
||||||
SubModelViewSetInheritedCases,
|
SubModelViewSetInheritedCases,
|
||||||
):
|
):
|
||||||
@ -43,7 +50,7 @@ class AssetBaseViewsetTestCases(
|
|||||||
if self.model is not AssetBase:
|
if self.model is not AssetBase:
|
||||||
|
|
||||||
self.kwargs = {
|
self.kwargs = {
|
||||||
'asset_model': self.model._meta.sub_model_type
|
'model_name': self.model._meta.sub_model_type
|
||||||
}
|
}
|
||||||
|
|
||||||
self.viewset.kwargs = self.kwargs
|
self.viewset.kwargs = self.kwargs
|
||||||
@ -60,6 +67,8 @@ class AssetBaseViewsetTestCases(
|
|||||||
|
|
||||||
self.http_options_response_list = client.options(url)
|
self.http_options_response_list = client.options(url)
|
||||||
|
|
||||||
|
a = 'a'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_view_attr_value_model_kwarg(self):
|
def test_view_attr_value_model_kwarg(self):
|
||||||
@ -70,7 +79,30 @@ class AssetBaseViewsetTestCases(
|
|||||||
|
|
||||||
view_set = self.viewset()
|
view_set = self.viewset()
|
||||||
|
|
||||||
assert view_set.model_kwarg == 'asset_model'
|
assert view_set.model_kwarg == 'model_name'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_view_attr_model_value(self):
|
||||||
|
"""Attribute Test
|
||||||
|
|
||||||
|
Attribute `model` must return the correct sub-model
|
||||||
|
"""
|
||||||
|
|
||||||
|
view_set = self.viewset()
|
||||||
|
|
||||||
|
|
||||||
|
app_settings = AppSettings.objects.select_related('global_organization').get(
|
||||||
|
owner_organization = None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
view_set.request = MockRequest(
|
||||||
|
user = self.view_user,
|
||||||
|
app_settings = app_settings,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert view_set.model == self.model
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -85,10 +117,11 @@ class AssetBaseViewsetInheritedCases(
|
|||||||
model: str = None
|
model: str = None
|
||||||
"""name of the model to test"""
|
"""name of the model to test"""
|
||||||
|
|
||||||
route_name = 'v2:accounting:_api_v2_asset_sub'
|
route_name = 'v2:accounting:_api_asset_sub'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class AssetBaseViewsetTest(
|
class AssetBaseViewsetTest(
|
||||||
AssetBaseViewsetTestCases,
|
AssetBaseViewsetTestCases,
|
||||||
TestCase,
|
TestCase,
|
||||||
@ -96,6 +129,6 @@ class AssetBaseViewsetTest(
|
|||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
|
||||||
route_name = 'v2:accounting:_api_v2_asset'
|
route_name = 'v2:accounting:_api_asset'
|
||||||
|
|
||||||
viewset = NoDocsViewSet
|
viewset = NoDocsViewSet
|
||||||
|
@ -33,7 +33,7 @@ for model in apps.get_models():
|
|||||||
if model._meta.sub_model_type == 'asset':
|
if model._meta.sub_model_type == 'asset':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
asset_type_names += model._meta.sub_model_type + '|'
|
asset_type_names += model._meta.model_name + '|'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ asset_type_names = str(asset_type_names)[:-1]
|
|||||||
if not asset_type_names:
|
if not asset_type_names:
|
||||||
asset_type_names = 'none'
|
asset_type_names = 'none'
|
||||||
|
|
||||||
router.register(f'asset/(?P<asset_model>[{asset_type_names}]+)?', asset.ViewSet, feature_flag = '2025-00004', basename='_api_v2_asset_sub')
|
router.register(f'asset/(?P<model_name>[{asset_type_names}]+)?', asset.ViewSet, feature_flag = '2025-00004', basename='_api_asset_sub')
|
||||||
router.register('asset', asset.NoDocsViewSet, feature_flag = '2025-00004', basename='_api_v2_asset')
|
router.register('asset', asset.NoDocsViewSet, feature_flag = '2025-00004', basename='_api_asset')
|
||||||
|
|
||||||
urlpatterns = router.urls
|
urlpatterns = router.urls
|
||||||
|
@ -12,7 +12,7 @@ from drf_spectacular.utils import (
|
|||||||
|
|
||||||
from accounting.models.asset_base import AssetBase
|
from accounting.models.asset_base import AssetBase
|
||||||
|
|
||||||
from api.viewsets.common import SubModelViewSet
|
from api.viewsets.common import SubModelViewSet_ReWrite
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
|
|||||||
|
|
||||||
if issubclass(model, AssetBase):
|
if issubclass(model, AssetBase):
|
||||||
|
|
||||||
serializer_name = 'asset'
|
serializer_name = 'assetbase'
|
||||||
|
|
||||||
if(
|
if(
|
||||||
model._meta.model_name == 'assetbase'
|
model._meta.model_name == 'assetbase'
|
||||||
@ -34,7 +34,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
serializer_name += '_' + model._meta.sub_model_type
|
serializer_name += '_' + model._meta.model_name
|
||||||
|
|
||||||
serializer_module = importlib.import_module(
|
serializer_module = importlib.import_module(
|
||||||
model._meta.app_label + '.serializers.' + str(
|
model._meta.app_label + '.serializers.' + str(
|
||||||
@ -56,7 +56,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
|
|||||||
description='.',
|
description='.',
|
||||||
parameters = [
|
parameters = [
|
||||||
OpenApiParameter(
|
OpenApiParameter(
|
||||||
name = 'asset_model',
|
name = 'model_name',
|
||||||
description = 'Enter the asset type. This is the name of the asset sub-model.',
|
description = 'Enter the asset type. This is the name of the asset sub-model.',
|
||||||
location = OpenApiParameter.PATH,
|
location = OpenApiParameter.PATH,
|
||||||
type = str,
|
type = str,
|
||||||
@ -97,7 +97,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
|
|||||||
description = '.',
|
description = '.',
|
||||||
parameters =[
|
parameters =[
|
||||||
OpenApiParameter(
|
OpenApiParameter(
|
||||||
name = 'asset_model',
|
name = 'model_name',
|
||||||
description = 'Enter the asset type. This is the name of the asset sub-model.',
|
description = 'Enter the asset type. This is the name of the asset sub-model.',
|
||||||
location = OpenApiParameter.PATH,
|
location = OpenApiParameter.PATH,
|
||||||
type = str,
|
type = str,
|
||||||
@ -121,7 +121,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
|
|||||||
description='.',
|
description='.',
|
||||||
parameters = [
|
parameters = [
|
||||||
OpenApiParameter(
|
OpenApiParameter(
|
||||||
name = 'asset_model',
|
name = 'model_name',
|
||||||
description = 'Enter the asset model. This is the name of the asset sub-model.',
|
description = 'Enter the asset model. This is the name of the asset sub-model.',
|
||||||
location = OpenApiParameter.PATH,
|
location = OpenApiParameter.PATH,
|
||||||
type = str,
|
type = str,
|
||||||
@ -153,7 +153,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
|
|||||||
description='.',
|
description='.',
|
||||||
parameters = [
|
parameters = [
|
||||||
OpenApiParameter(
|
OpenApiParameter(
|
||||||
name = 'asset_model',
|
name = 'model_name',
|
||||||
description = 'Enter the asset model. This is the name of the Asset sub-model.',
|
description = 'Enter the asset model. This is the name of the Asset sub-model.',
|
||||||
location = OpenApiParameter.PATH,
|
location = OpenApiParameter.PATH,
|
||||||
type = str,
|
type = str,
|
||||||
@ -214,7 +214,7 @@ def spectacular_request_serializers( serializer_type = 'Model'):
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
class ViewSet( SubModelViewSet ):
|
class ViewSet( SubModelViewSet_ReWrite ):
|
||||||
|
|
||||||
_has_purge: bool = False
|
_has_purge: bool = False
|
||||||
"""User Permission
|
"""User Permission
|
||||||
@ -232,7 +232,7 @@ class ViewSet( SubModelViewSet ):
|
|||||||
# 'is_deleted'
|
# 'is_deleted'
|
||||||
]
|
]
|
||||||
|
|
||||||
model_kwarg = 'asset_model'
|
model_kwarg = 'model_name'
|
||||||
|
|
||||||
search_fields = [
|
search_fields = [
|
||||||
'asset_number',
|
'asset_number',
|
||||||
|
@ -638,7 +638,7 @@ class ReactUIMetadata(OverRideJSONAPIMetadata):
|
|||||||
'view_itamassetbase': {
|
'view_itamassetbase': {
|
||||||
"display_name": "IT Assets",
|
"display_name": "IT Assets",
|
||||||
"name": "itasset",
|
"name": "itasset",
|
||||||
"link": "/itam/it_asset"
|
"link": "/itam/itamassetbase"
|
||||||
},
|
},
|
||||||
**nav['itam']['pages']
|
**nav['itam']['pages']
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ class APIFieldsTestCases:
|
|||||||
|
|
||||||
view_team.permissions.set([view_permissions])
|
view_team.permissions.set([view_permissions])
|
||||||
|
|
||||||
request.cls.view_user = User.objects.create_user(username="cafs_test_user_view" + str(random_str), password="password")
|
request.cls.view_user = User.objects.create_user(username="cafs_test_user_view" + str(random_str), password="password", is_superuser = True)
|
||||||
|
|
||||||
team_user = TeamUsers.objects.create(
|
team_user = TeamUsers.objects.create(
|
||||||
team = view_team,
|
team = view_team,
|
||||||
|
@ -8,7 +8,8 @@ from django.utils.module_loading import import_string
|
|||||||
# Note: Only included so that it can be picked up.
|
# Note: Only included so that it can be picked up.
|
||||||
# in future when model referenced, this include statement may be repoved.
|
# in future when model referenced, this include statement may be repoved.
|
||||||
from access.models.company_base import Company # pylint: disable=W0611:unused-import
|
from access.models.company_base import Company # pylint: disable=W0611:unused-import
|
||||||
|
from access.models.role import Role # pylint: disable=W0611:unused-import
|
||||||
|
## EoF Include block
|
||||||
|
|
||||||
|
|
||||||
module_path = f'centurion.models.meta'
|
module_path = f'centurion.models.meta'
|
||||||
|
@ -76,10 +76,7 @@ CREATE TABLE IF NOT EXISTS "assistance_knowledge_base_history" ("modelhistory_pt
|
|||||||
CREATE TABLE IF NOT EXISTS "access_team_history" ("modelhistory_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_history" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_team" ("group_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "access_team_history" ("modelhistory_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_history" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_team" ("group_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "core_ticketcategory_notes" ("modelnotes_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_notes" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "core_ticketcategory" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "core_ticketcategory_notes" ("modelnotes_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_notes" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "core_ticketcategory" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "core_ticketcommentcategory_notes" ("modelnotes_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_notes" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "core_ticketcommentcategory" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "core_ticketcommentcategory_notes" ("modelnotes_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_notes" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "core_ticketcommentcategory" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "access_role" ("model_notes" text NULL, "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(30) NOT NULL, "created" datetime NOT NULL, "modified" datetime NOT NULL, "organization_id" integer NOT NULL REFERENCES "access_tenant" ("id") DEFERRABLE INITIALLY DEFERRED);
|
|
||||||
CREATE TABLE IF NOT EXISTS "access_role_permissions" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "role_id" integer NOT NULL REFERENCES "access_role" ("id") DEFERRABLE INITIALLY DEFERRED, "permission_id" integer NOT NULL REFERENCES "auth_permission" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "access_role_permissions" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "role_id" integer NOT NULL REFERENCES "access_role" ("id") DEFERRABLE INITIALLY DEFERRED, "permission_id" integer NOT NULL REFERENCES "auth_permission" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "access_role_history" ("modelhistory_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_history" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_role" ("id") DEFERRABLE INITIALLY DEFERRED);
|
|
||||||
CREATE TABLE IF NOT EXISTS "access_role_notes" ("modelnotes_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_notes" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_role" ("id") DEFERRABLE INITIALLY DEFERRED);
|
|
||||||
CREATE TABLE IF NOT EXISTS "access_contact" ("person_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "access_person" ("entity_ptr_id") DEFERRABLE INITIALLY DEFERRED, "directory" bool NOT NULL, "email" varchar(254) NOT NULL UNIQUE);
|
CREATE TABLE IF NOT EXISTS "access_contact" ("person_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "access_person" ("entity_ptr_id") DEFERRABLE INITIALLY DEFERRED, "directory" bool NOT NULL, "email" varchar(254) NOT NULL UNIQUE);
|
||||||
CREATE TABLE IF NOT EXISTS "core_ticketbase_assigned_to" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "ticketbase_id" integer NOT NULL REFERENCES "core_ticketbase" ("id") DEFERRABLE INITIALLY DEFERRED, "entity_id" integer NOT NULL REFERENCES "access_entity" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "core_ticketbase_assigned_to" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "ticketbase_id" integer NOT NULL REFERENCES "core_ticketbase" ("id") DEFERRABLE INITIALLY DEFERRED, "entity_id" integer NOT NULL REFERENCES "access_entity" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "core_ticketbase_subscribed_to" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "ticketbase_id" integer NOT NULL REFERENCES "core_ticketbase" ("id") DEFERRABLE INITIALLY DEFERRED, "entity_id" integer NOT NULL REFERENCES "access_entity" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "core_ticketbase_subscribed_to" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "ticketbase_id" integer NOT NULL REFERENCES "core_ticketbase" ("id") DEFERRABLE INITIALLY DEFERRED, "entity_id" integer NOT NULL REFERENCES "access_entity" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
@ -139,9 +136,12 @@ CREATE TABLE IF NOT EXISTS "access_person_audithistory" ("centurionaudit_ptr_id"
|
|||||||
CREATE TABLE IF NOT EXISTS "access_person_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_person" ("entity_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "access_person_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_person" ("entity_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "access_company_audithistory" ("centurionaudit_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_audithistory" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_company" ("entity_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "access_company_audithistory" ("centurionaudit_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_audithistory" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_company" ("entity_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "access_company_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_company" ("entity_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "access_company_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_company" ("entity_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "accounting_assetbase" ("model_notes" text NULL, "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "asset_number" varchar(30) NULL UNIQUE, "serial_number" varchar(30) NULL UNIQUE, "asset_type" varchar(30) NOT NULL, "created" datetime NOT NULL, "modified" datetime NOT NULL, "organization_id" integer NOT NULL REFERENCES "access_tenant" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "access_role" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(30) NOT NULL, "created" datetime NOT NULL, "modified" datetime NOT NULL, "organization_id" integer NOT NULL REFERENCES "access_tenant" ("id") DEFERRABLE INITIALLY DEFERRED, "model_notes" text NULL);
|
||||||
CREATE TABLE IF NOT EXISTS "accounting_assetbase_history" ("modelhistory_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_history" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "accounting_assetbase" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "access_role_audithistory" ("centurionaudit_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_audithistory" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_role" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "accounting_assetbase_notes" ("modelnotes_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_model_notes" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "accounting_assetbase" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "access_role_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "access_role" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
|
CREATE TABLE IF NOT EXISTS "accounting_assetbase" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "asset_number" varchar(30) NULL UNIQUE, "serial_number" varchar(30) NULL UNIQUE, "asset_type" varchar(30) NOT NULL, "created" datetime NOT NULL, "modified" datetime NOT NULL, "organization_id" integer NOT NULL REFERENCES "access_tenant" ("id") DEFERRABLE INITIALLY DEFERRED, "model_notes" text NULL);
|
||||||
|
CREATE TABLE IF NOT EXISTS "accounting_assetbase_audithistory" ("centurionaudit_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_audithistory" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "accounting_assetbase" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
|
CREATE TABLE IF NOT EXISTS "accounting_assetbase_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "accounting_assetbase" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "django_admin_log" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "object_id" text NULL, "object_repr" varchar(200) NOT NULL, "action_flag" smallint unsigned NOT NULL CHECK ("action_flag" >= 0), "change_message" text NOT NULL, "content_type_id" integer NULL REFERENCES "django_content_type" ("id") DEFERRABLE INITIALLY DEFERRED, "user_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED, "action_time" datetime NOT NULL);
|
CREATE TABLE IF NOT EXISTS "django_admin_log" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "object_id" text NULL, "object_repr" varchar(200) NOT NULL, "action_flag" smallint unsigned NOT NULL CHECK ("action_flag" >= 0), "change_message" text NOT NULL, "content_type_id" integer NULL REFERENCES "django_content_type" ("id") DEFERRABLE INITIALLY DEFERRED, "user_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED, "action_time" datetime NOT NULL);
|
||||||
CREATE TABLE IF NOT EXISTS "api_authtoken" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "note" varchar(50) NULL, "token" varchar(64) NOT NULL UNIQUE, "expires" datetime NOT NULL, "created" datetime NOT NULL, "modified" datetime NOT NULL, "user_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "api_authtoken" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "note" varchar(50) NULL, "token" varchar(64) NOT NULL UNIQUE, "expires" datetime NOT NULL, "created" datetime NOT NULL, "modified" datetime NOT NULL, "user_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "itam_itamassetbase" ("assetbase_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "accounting_assetbase" ("id") DEFERRABLE INITIALLY DEFERRED, "itam_type" varchar(30) NOT NULL);
|
CREATE TABLE IF NOT EXISTS "itam_itamassetbase" ("assetbase_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "accounting_assetbase" ("id") DEFERRABLE INITIALLY DEFERRED, "itam_type" varchar(30) NOT NULL);
|
||||||
@ -197,6 +197,8 @@ CREATE TABLE IF NOT EXISTS "itam_softwarecategory_centurionmodelnote" ("centurio
|
|||||||
CREATE TABLE IF NOT EXISTS "itam_softwareversion" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "modified" datetime NOT NULL, "name" varchar(50) NOT NULL, "organization_id" integer NOT NULL REFERENCES "access_tenant" ("id") DEFERRABLE INITIALLY DEFERRED, "software_id" integer NOT NULL REFERENCES "itam_software" ("id") DEFERRABLE INITIALLY DEFERRED, "model_notes" text NULL);
|
CREATE TABLE IF NOT EXISTS "itam_softwareversion" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "modified" datetime NOT NULL, "name" varchar(50) NOT NULL, "organization_id" integer NOT NULL REFERENCES "access_tenant" ("id") DEFERRABLE INITIALLY DEFERRED, "software_id" integer NOT NULL REFERENCES "itam_software" ("id") DEFERRABLE INITIALLY DEFERRED, "model_notes" text NULL);
|
||||||
CREATE TABLE IF NOT EXISTS "itam_softwareversion_audithistory" ("centurionaudit_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_audithistory" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "itam_softwareversion" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "itam_softwareversion_audithistory" ("centurionaudit_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_audithistory" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "itam_softwareversion" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "itam_softwareversion_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "itam_softwareversion" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "itam_softwareversion_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "itam_softwareversion" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
|
CREATE TABLE IF NOT EXISTS "itam_itamassetbase_audithistory" ("centurionaudit_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_audithistory" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "itam_itamassetbase" ("assetbase_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
|
CREATE TABLE IF NOT EXISTS "itam_itamassetbase_centurionmodelnote" ("centurionmodelnote_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "core_centurionmodelnote" ("id") DEFERRABLE INITIALLY DEFERRED, "model_id" integer NOT NULL REFERENCES "itam_itamassetbase" ("assetbase_ptr_id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "itim_cluster_devices" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "cluster_id" integer NOT NULL REFERENCES "itim_cluster" ("id") DEFERRABLE INITIALLY DEFERRED, "device_id" integer NOT NULL REFERENCES "itam_device" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "itim_cluster_devices" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "cluster_id" integer NOT NULL REFERENCES "itim_cluster" ("id") DEFERRABLE INITIALLY DEFERRED, "device_id" integer NOT NULL REFERENCES "itam_device" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "itim_cluster_nodes" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "cluster_id" integer NOT NULL REFERENCES "itim_cluster" ("id") DEFERRABLE INITIALLY DEFERRED, "device_id" integer NOT NULL REFERENCES "itam_device" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "itim_cluster_nodes" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "cluster_id" integer NOT NULL REFERENCES "itim_cluster" ("id") DEFERRABLE INITIALLY DEFERRED, "device_id" integer NOT NULL REFERENCES "itam_device" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
CREATE TABLE IF NOT EXISTS "itim_cluster" ("model_notes" text NULL, "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(50) NOT NULL, "config" text NULL CHECK ((JSON_VALID("config") OR "config" IS NULL)), "created" datetime NOT NULL, "modified" datetime NOT NULL, "organization_id" integer NOT NULL REFERENCES "access_tenant" ("id") DEFERRABLE INITIALLY DEFERRED, "cluster_type_id" integer NULL REFERENCES "itim_clustertype" ("id") DEFERRABLE INITIALLY DEFERRED, "parent_cluster_id" integer NULL REFERENCES "itim_cluster" ("id") DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE IF NOT EXISTS "itim_cluster" ("model_notes" text NULL, "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(50) NOT NULL, "config" text NULL CHECK ((JSON_VALID("config") OR "config" IS NULL)), "created" datetime NOT NULL, "modified" datetime NOT NULL, "organization_id" integer NOT NULL REFERENCES "access_tenant" ("id") DEFERRABLE INITIALLY DEFERRED, "cluster_type_id" integer NULL REFERENCES "itim_clustertype" ("id") DEFERRABLE INITIALLY DEFERRED, "parent_cluster_id" integer NULL REFERENCES "itim_cluster" ("id") DEFERRABLE INITIALLY DEFERRED);
|
||||||
@ -237,9 +239,9 @@ CREATE TABLE IF NOT EXISTS "social_auth_nonce" ("id" integer NOT NULL PRIMARY KE
|
|||||||
CREATE TABLE IF NOT EXISTS "social_auth_usersocialauth" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "provider" varchar(32) NOT NULL, "uid" varchar(255) NOT NULL, "user_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED, "created" datetime NOT NULL, "modified" datetime NOT NULL, "extra_data" text NOT NULL CHECK ((JSON_VALID("extra_data") OR "extra_data" IS NULL)));
|
CREATE TABLE IF NOT EXISTS "social_auth_usersocialauth" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "provider" varchar(32) NOT NULL, "uid" varchar(255) NOT NULL, "user_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED, "created" datetime NOT NULL, "modified" datetime NOT NULL, "extra_data" text NOT NULL CHECK ((JSON_VALID("extra_data") OR "extra_data" IS NULL)));
|
||||||
CREATE TABLE IF NOT EXISTS "social_auth_partial" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "token" varchar(32) NOT NULL, "next_step" smallint unsigned NOT NULL CHECK ("next_step" >= 0), "backend" varchar(32) NOT NULL, "timestamp" datetime NOT NULL, "data" text NOT NULL CHECK ((JSON_VALID("data") OR "data" IS NULL)));
|
CREATE TABLE IF NOT EXISTS "social_auth_partial" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "token" varchar(32) NOT NULL, "next_step" smallint unsigned NOT NULL CHECK ("next_step" >= 0), "backend" varchar(32) NOT NULL, "timestamp" datetime NOT NULL, "data" text NOT NULL CHECK ((JSON_VALID("data") OR "data" IS NULL)));
|
||||||
DELETE FROM sqlite_sequence;
|
DELETE FROM sqlite_sequence;
|
||||||
INSERT INTO sqlite_sequence VALUES('django_migrations',222);
|
INSERT INTO sqlite_sequence VALUES('django_migrations',227);
|
||||||
INSERT INTO sqlite_sequence VALUES('django_content_type',216);
|
INSERT INTO sqlite_sequence VALUES('django_content_type',218);
|
||||||
INSERT INTO sqlite_sequence VALUES('auth_permission',909);
|
INSERT INTO sqlite_sequence VALUES('auth_permission',917);
|
||||||
INSERT INTO sqlite_sequence VALUES('auth_group',0);
|
INSERT INTO sqlite_sequence VALUES('auth_group',0);
|
||||||
INSERT INTO sqlite_sequence VALUES('auth_user',0);
|
INSERT INTO sqlite_sequence VALUES('auth_user',0);
|
||||||
INSERT INTO sqlite_sequence VALUES('core_notes',0);
|
INSERT INTO sqlite_sequence VALUES('core_notes',0);
|
||||||
@ -261,6 +263,8 @@ INSERT INTO sqlite_sequence VALUES('assistance_knowledgebasecategory',0);
|
|||||||
INSERT INTO sqlite_sequence VALUES('assistance_modelknowledgebasearticle',0);
|
INSERT INTO sqlite_sequence VALUES('assistance_modelknowledgebasearticle',0);
|
||||||
INSERT INTO sqlite_sequence VALUES('access_tenant',0);
|
INSERT INTO sqlite_sequence VALUES('access_tenant',0);
|
||||||
INSERT INTO sqlite_sequence VALUES('access_entity',0);
|
INSERT INTO sqlite_sequence VALUES('access_entity',0);
|
||||||
|
INSERT INTO sqlite_sequence VALUES('access_role',0);
|
||||||
|
INSERT INTO sqlite_sequence VALUES('accounting_assetbase',0);
|
||||||
INSERT INTO sqlite_sequence VALUES('django_admin_log',0);
|
INSERT INTO sqlite_sequence VALUES('django_admin_log',0);
|
||||||
INSERT INTO sqlite_sequence VALUES('itam_devicetype',0);
|
INSERT INTO sqlite_sequence VALUES('itam_devicetype',0);
|
||||||
INSERT INTO sqlite_sequence VALUES('config_management_configgrouphosts',0);
|
INSERT INTO sqlite_sequence VALUES('config_management_configgrouphosts',0);
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
# Generated by Django 5.1.10 on 2025-07-10 09:10
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("core", "0033_alter_ticketcommentcategory_parent_and_more"),
|
||||||
|
("itam", "0024_alter_software_organization"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="ITAMAssetBaseAuditHistory",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"centurionaudit_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="core.centurionaudit",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model",
|
||||||
|
models.ForeignKey(
|
||||||
|
help_text="Model this history belongs to",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="+",
|
||||||
|
to="itam.itamassetbase",
|
||||||
|
verbose_name="Model",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "IT Asset History",
|
||||||
|
"verbose_name_plural": "IT Asset Histories",
|
||||||
|
"db_table": "itam_itamassetbase_audithistory",
|
||||||
|
"managed": True,
|
||||||
|
},
|
||||||
|
bases=("core.centurionaudit",),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="ITAMAssetBaseCenturionModelNote",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"centurionmodelnote_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="core.centurionmodelnote",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model",
|
||||||
|
models.ForeignKey(
|
||||||
|
help_text="Model this note belongs to",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="+",
|
||||||
|
to="itam.itamassetbase",
|
||||||
|
verbose_name="Model",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "IT Asset Note",
|
||||||
|
"verbose_name_plural": "IT Asset Notes",
|
||||||
|
"db_table": "itam_itamassetbase_centurionmodelnote",
|
||||||
|
"managed": True,
|
||||||
|
},
|
||||||
|
bases=("core.centurionmodelnote",),
|
||||||
|
),
|
||||||
|
]
|
@ -1,4 +1,5 @@
|
|||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
@ -18,9 +19,13 @@ class ITAMAssetBase(
|
|||||||
**Don't** use this model directly, it should be used via a sub-model.
|
**Don't** use this model directly, it should be used via a sub-model.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_is_submodel = True
|
||||||
|
|
||||||
app_namespace = None
|
app_namespace = None
|
||||||
|
|
||||||
note_basename = 'accounting:_api_v2_asset_note'
|
model_tag = 'it_asset'
|
||||||
|
|
||||||
|
url_model_name = 'itamassetbase'
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -69,7 +74,7 @@ class ITAMAssetBase(
|
|||||||
|
|
||||||
if(
|
if(
|
||||||
( isinstance(model, ITAMAssetBase) or issubclass(model, ITAMAssetBase) )
|
( isinstance(model, ITAMAssetBase) or issubclass(model, ITAMAssetBase) )
|
||||||
and ITAMAssetBase._meta.itam_sub_model_type != 'itam_base'
|
# and ITAMAssetBase._meta.itam_sub_model_type != 'itam_base'
|
||||||
|
|
||||||
):
|
):
|
||||||
|
|
||||||
@ -161,22 +166,7 @@ class ITAMAssetBase(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_url( self, request = None ) -> str:
|
def clean_fields(self, exclude = None):
|
||||||
|
|
||||||
kwargs = self.get_url_kwargs()
|
|
||||||
|
|
||||||
url_path_name = '_api_v2_itam_asset'
|
|
||||||
|
|
||||||
if request:
|
|
||||||
|
|
||||||
return reverse(f"v2:{url_path_name}-detail", request=request, kwargs = kwargs )
|
|
||||||
|
|
||||||
|
|
||||||
return reverse(f"v2:{url_path_name}-detail", kwargs = kwargs )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
|
||||||
|
|
||||||
related_model = self.get_related_model()
|
related_model = self.get_related_model()
|
||||||
|
|
||||||
@ -184,8 +174,56 @@ class ITAMAssetBase(
|
|||||||
|
|
||||||
related_model = self
|
related_model = self
|
||||||
|
|
||||||
if self.itam_type != str(related_model._meta.itam_sub_model_type).lower().replace(' ', '_'):
|
if(
|
||||||
|
self.itam_type != str(related_model._meta.itam_sub_model_type).lower().replace(' ', '_')
|
||||||
|
and str(related_model._meta.sub_model_type).lower().replace(' ', '_') != 'itam_base'
|
||||||
|
):
|
||||||
|
|
||||||
self.itam_type = str(related_model._meta.itam_sub_model_type).lower().replace(' ', '_')
|
self.itam_type = str(related_model._meta.itam_sub_model_type).lower().replace(' ', '_')
|
||||||
|
|
||||||
super().save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
|
|
||||||
|
super().clean_fields(exclude = exclude)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_url(
|
||||||
|
self, relative: bool = False, api_version: int = 2, many = False, request: any = None
|
||||||
|
) -> str:
|
||||||
|
|
||||||
|
namespace = f'v{api_version}'
|
||||||
|
|
||||||
|
if self.get_app_namespace():
|
||||||
|
namespace = namespace + ':' + self.get_app_namespace()
|
||||||
|
|
||||||
|
|
||||||
|
url_basename = f'{namespace}:_api_{self._meta.model_name}'
|
||||||
|
|
||||||
|
if self.url_model_name:
|
||||||
|
|
||||||
|
url_basename = f'{namespace}:_api_{self.url_model_name}'
|
||||||
|
|
||||||
|
if (
|
||||||
|
self._is_submodel
|
||||||
|
and self._meta.sub_model_type != 'it_asset'
|
||||||
|
):
|
||||||
|
|
||||||
|
url_basename += '_sub'
|
||||||
|
|
||||||
|
|
||||||
|
if many:
|
||||||
|
|
||||||
|
url_basename += '-list'
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
url_basename += '-detail'
|
||||||
|
|
||||||
|
|
||||||
|
url = reverse( viewname = url_basename, kwargs = self.get_url_kwargs( many = many ) )
|
||||||
|
|
||||||
|
if not relative:
|
||||||
|
|
||||||
|
url = settings.SITE_URL + url
|
||||||
|
|
||||||
|
|
||||||
|
return url
|
||||||
|
@ -4,7 +4,7 @@ from drf_spectacular.utils import extend_schema_serializer
|
|||||||
|
|
||||||
from access.serializers.organization import TenantBaseSerializer
|
from access.serializers.organization import TenantBaseSerializer
|
||||||
|
|
||||||
from accounting.serializers.asset import (
|
from accounting.serializers.assetbase import (
|
||||||
BaseSerializer,
|
BaseSerializer,
|
||||||
ModelSerializer as AssetBaseModelSerializer,
|
ModelSerializer as AssetBaseModelSerializer,
|
||||||
ViewSerializer as AssetBaseViewSerializer,
|
ViewSerializer as AssetBaseViewSerializer,
|
56
app/itam/serializers/centurionaudit_itamassetbase.py
Normal file
56
app/itam/serializers/centurionaudit_itamassetbase.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from drf_spectacular.utils import extend_schema_serializer
|
||||||
|
|
||||||
|
from api.serializers import common
|
||||||
|
|
||||||
|
from centurion.models.meta import ITAMAssetBaseAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
|
||||||
|
|
||||||
|
from core.serializers.centurionaudit import (
|
||||||
|
BaseSerializer,
|
||||||
|
ViewSerializer as AuditHistoryViewSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'ITAMAssetBaseAuditHistoryModelSerializer')
|
||||||
|
class ModelSerializer(
|
||||||
|
common.CommonModelSerializer,
|
||||||
|
BaseSerializer
|
||||||
|
):
|
||||||
|
"""Git Group Audit History Base Model"""
|
||||||
|
|
||||||
|
|
||||||
|
_urls = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = ITAMAssetBaseAuditHistory
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'organization',
|
||||||
|
'display_name',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'before',
|
||||||
|
'after',
|
||||||
|
'action',
|
||||||
|
'user',
|
||||||
|
'created',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = fields
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'ITAMAssetBaseAuditHistoryViewSerializer')
|
||||||
|
class ViewSerializer(
|
||||||
|
ModelSerializer,
|
||||||
|
AuditHistoryViewSerializer,
|
||||||
|
):
|
||||||
|
"""Git Group Audit History Base View Model"""
|
||||||
|
pass
|
87
app/itam/serializers/centurionmodelnote_itamassetbase.py
Normal file
87
app/itam/serializers/centurionmodelnote_itamassetbase.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from drf_spectacular.utils import extend_schema_serializer
|
||||||
|
|
||||||
|
from access.serializers.organization import (TenantBaseSerializer)
|
||||||
|
|
||||||
|
from centurion.models.meta import ITAMAssetBaseCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
|
||||||
|
|
||||||
|
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
|
||||||
|
BaseSerializer,
|
||||||
|
ModelSerializer as BaseModelModelSerializer,
|
||||||
|
ViewSerializer as BaseModelViewSerializer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'ITAMAssetBaseModelNoteModelSerializer')
|
||||||
|
class ModelSerializer(
|
||||||
|
BaseModelModelSerializer,
|
||||||
|
):
|
||||||
|
|
||||||
|
|
||||||
|
_urls = serializers.SerializerMethodField('get_url')
|
||||||
|
|
||||||
|
def get_url(self, item) -> dict:
|
||||||
|
|
||||||
|
return {
|
||||||
|
'_self': item.get_url( request = self._context['view'].request ),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = ITAMAssetBaseCenturionModelNote
|
||||||
|
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'organization',
|
||||||
|
'display_name',
|
||||||
|
'body',
|
||||||
|
'created_by',
|
||||||
|
'modified_by',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
read_only_fields = [
|
||||||
|
'id',
|
||||||
|
'display_name',
|
||||||
|
'organization',
|
||||||
|
'created_by',
|
||||||
|
'modified_by',
|
||||||
|
'content_type',
|
||||||
|
'model',
|
||||||
|
'created',
|
||||||
|
'modified',
|
||||||
|
'_urls',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
|
||||||
|
is_valid = False
|
||||||
|
|
||||||
|
note_model = self.Meta.model.model.field.related_model
|
||||||
|
|
||||||
|
attrs['model'] = note_model.objects.get(
|
||||||
|
id = int( self.context['view'].kwargs['model_id'] )
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
is_valid = super().validate(attrs)
|
||||||
|
|
||||||
|
return is_valid
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema_serializer(component_name = 'ITAMAssetBaseModelNoteViewSerializer')
|
||||||
|
class ViewSerializer(
|
||||||
|
ModelSerializer,
|
||||||
|
BaseModelViewSerializer,
|
||||||
|
):
|
||||||
|
|
||||||
|
organization = TenantBaseSerializer( many = False, read_only = True )
|
@ -18,7 +18,7 @@ def model(request):
|
|||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def create_serializer():
|
def create_serializer():
|
||||||
|
|
||||||
from itam.serializers.asset_it_asset import ModelSerializer
|
from itam.serializers.assetbase_itamassetbase import ModelSerializer
|
||||||
|
|
||||||
|
|
||||||
yield ModelSerializer
|
yield ModelSerializer
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from accounting.tests.functional.asset_base.test_functional_asset_base_metadata import AssetBaseMetadataInheritedCases
|
from accounting.tests.functional.asset_base.test_functional_asset_base_metadata import AssetBaseMetadataInheritedCases
|
||||||
@ -6,6 +8,7 @@ from itam.models.itam_asset_base import ITAMAssetBase
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_itamassetbase
|
||||||
class MetadataTestCases(
|
class MetadataTestCases(
|
||||||
AssetBaseMetadataInheritedCases,
|
AssetBaseMetadataInheritedCases,
|
||||||
):
|
):
|
||||||
@ -22,7 +25,7 @@ class MetadataTestCases(
|
|||||||
|
|
||||||
url_view_kwargs: dict = {}
|
url_view_kwargs: dict = {}
|
||||||
|
|
||||||
url_name = '_api_v2_itam_asset'
|
url_name = '_api_itamassetbase'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -38,6 +41,7 @@ class ITAMAssetBaseMetadataInheritedCases(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class ITAMAssetBaseMetadataTest(
|
class ITAMAssetBaseMetadataTest(
|
||||||
MetadataTestCases,
|
MetadataTestCases,
|
||||||
TestCase,
|
TestCase,
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from accounting.tests.functional.asset_base.test_functional_asset_base_permission import AssetBasePermissionsAPIInheritedCases
|
from accounting.tests.functional.asset_base.test_functional_asset_base_permission import AssetBasePermissionsAPIInheritedCases
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_itamassetbase
|
||||||
class PermissionsAPITestCases(
|
class PermissionsAPITestCases(
|
||||||
AssetBasePermissionsAPIInheritedCases,
|
AssetBasePermissionsAPIInheritedCases,
|
||||||
):
|
):
|
||||||
@ -17,13 +20,13 @@ class PermissionsAPITestCases(
|
|||||||
kwargs_create_item_diff_org: dict = {}
|
kwargs_create_item_diff_org: dict = {}
|
||||||
|
|
||||||
url_kwargs: dict = {
|
url_kwargs: dict = {
|
||||||
'asset_model': 'it_asset',
|
'model_name': 'itamassetbase',
|
||||||
}
|
}
|
||||||
|
|
||||||
url_name = '_api_v2_itam_asset'
|
url_name = '_api_itamassetbase'
|
||||||
|
|
||||||
url_view_kwargs: dict = {
|
url_view_kwargs: dict = {
|
||||||
'asset_model': 'it_asset',
|
'model_name': 'itamassetbase',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -40,6 +43,7 @@ class ITAMAssetBasePermissionsAPIInheritedCases(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class ITAMAssetBasePermissionsAPIPyTest(
|
class ITAMAssetBasePermissionsAPIPyTest(
|
||||||
PermissionsAPITestCases,
|
PermissionsAPITestCases,
|
||||||
):
|
):
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from accounting.tests.functional.asset_base.test_functional_asset_base_serializer import AssetBaseSerializerInheritedCases
|
from accounting.tests.functional.asset_base.test_functional_asset_base_serializer import AssetBaseSerializerInheritedCases
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ class MockView:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_itamassetbase
|
||||||
class ITAMAssetBaseSerializerTestCases(
|
class ITAMAssetBaseSerializerTestCases(
|
||||||
AssetBaseSerializerInheritedCases
|
AssetBaseSerializerInheritedCases
|
||||||
):
|
):
|
||||||
@ -54,6 +56,7 @@ class ITAMAssetBaseSerializerInheritedCases(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class ITAMAssetBaseSerializerPyTest(
|
class ITAMAssetBaseSerializerPyTest(
|
||||||
ITAMAssetBaseSerializerTestCases,
|
ITAMAssetBaseSerializerTestCases,
|
||||||
):
|
):
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from accounting.tests.functional.asset_base.test_functional_asset_base_viewset import AssetBaseViewSetInheritedCases
|
from accounting.tests.functional.asset_base.test_functional_asset_base_viewset import AssetBaseViewSetInheritedCases
|
||||||
@ -6,6 +8,7 @@ from itam.models.itam_asset_base import ITAMAssetBase
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_itamassetbase
|
||||||
class ViewSetTestCases(
|
class ViewSetTestCases(
|
||||||
AssetBaseViewSetInheritedCases
|
AssetBaseViewSetInheritedCases
|
||||||
):
|
):
|
||||||
@ -21,14 +24,14 @@ class ViewSetTestCases(
|
|||||||
model = ITAMAssetBase
|
model = ITAMAssetBase
|
||||||
|
|
||||||
url_kwargs: dict = {
|
url_kwargs: dict = {
|
||||||
'asset_model': 'it_asset',
|
'model_name': 'itamassetbase',
|
||||||
}
|
}
|
||||||
|
|
||||||
url_view_kwargs: dict = {
|
url_view_kwargs: dict = {
|
||||||
'asset_model': 'it_asset',
|
'model_name': 'itamassetbase',
|
||||||
}
|
}
|
||||||
|
|
||||||
url_name = '_api_v2_itam_asset'
|
url_name = '_api_itamassetbase'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -42,6 +45,7 @@ class ITAMAssetBaseViewSetInheritedCases(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class ITAMAssetBaseViewSetTest(
|
class ITAMAssetBaseViewSetTest(
|
||||||
ViewSetTestCases,
|
ViewSetTestCases,
|
||||||
TestCase,
|
TestCase,
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from itam.models.itam_asset_base import ITAMAssetBase
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture( scope = 'class')
|
@pytest.fixture( scope = 'class')
|
||||||
def model(request):
|
def model(model_itamassetbase):
|
||||||
|
|
||||||
request.cls.model = ITAMAssetBase
|
yield model_itamassetbase
|
||||||
|
|
||||||
yield request.cls.model
|
|
||||||
|
|
||||||
del request.cls.model
|
@pytest.fixture( scope = 'class', autouse = True)
|
||||||
|
def model_kwargs(request, kwargs_itamassetbase):
|
||||||
|
|
||||||
|
request.cls.kwargs_create_item = kwargs_itamassetbase.copy()
|
||||||
|
|
||||||
|
yield kwargs_itamassetbase.copy()
|
||||||
|
|
||||||
|
if hasattr(request.cls, 'kwargs_create_item'):
|
||||||
|
try:
|
||||||
|
del request.cls.kwargs_create_item
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from accounting.tests.unit.asset_base.test_unit_asset_base_api_fields import (
|
from accounting.tests.unit.asset_base.test_unit_asset_base_api_fields import (
|
||||||
AssetBaseAPIInheritedCases
|
AssetBaseAPIInheritedCases
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_itamassetbase
|
||||||
class ITAMAssetBaseAPITestCases(
|
class ITAMAssetBaseAPITestCases(
|
||||||
AssetBaseAPIInheritedCases,
|
AssetBaseAPIInheritedCases,
|
||||||
):
|
):
|
||||||
@ -29,6 +32,7 @@ class ITAMAssetBaseAPIInheritedCases(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class ITAMAssetBaseAPIPyTest(
|
class ITAMAssetBaseAPIPyTest(
|
||||||
ITAMAssetBaseAPITestCases,
|
ITAMAssetBaseAPITestCases,
|
||||||
):
|
):
|
||||||
|
@ -1,177 +1,77 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from accounting.tests.unit.asset_base.test_unit_asset_base_model import AssetBaseModelInheritedCases
|
from accounting.tests.unit.asset_base.test_unit_asset_base_model import (
|
||||||
|
AssetBaseModelInheritedCases,
|
||||||
|
)
|
||||||
|
|
||||||
from itam.models.itam_asset_base import ITAMAssetBase
|
from itam.models.itam_asset_base import ITAMAssetBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ITAMAssetBaseModelTestCases(
|
@pytest.mark.model_itamassetbase
|
||||||
AssetBaseModelInheritedCases,
|
class ITAMAssetModelTestCases(
|
||||||
|
AssetBaseModelInheritedCases
|
||||||
):
|
):
|
||||||
|
|
||||||
kwargs_create_item: dict = {}
|
|
||||||
|
|
||||||
it_asset_base_model = ITAMAssetBase
|
@property
|
||||||
|
def parameterized_class_attributes(self):
|
||||||
|
|
||||||
sub_model_type = 'itam_base'
|
return {
|
||||||
"""Sub Model Type
|
'_is_submodel': {
|
||||||
|
'value': True
|
||||||
sub-models must have this attribute defined in `ModelName.Meta.sub_model_type`
|
},
|
||||||
"""
|
'app_namespace': {
|
||||||
|
'type': type(None),
|
||||||
|
'value': None
|
||||||
|
},
|
||||||
|
'model_tag': {
|
||||||
|
'type': str,
|
||||||
|
'value': 'it_asset'
|
||||||
|
},
|
||||||
|
'url_model_name': {
|
||||||
|
'type': str,
|
||||||
|
'value': 'itamassetbase'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
parameterized_fields: dict = {
|
@property
|
||||||
"itam_type": {
|
def parameterized_model_fields(self):
|
||||||
'field_type': models.fields.CharField,
|
|
||||||
'field_parameter_default_exists': True,
|
return {
|
||||||
'field_parameter_default_value': ITAMAssetBase._meta.itam_sub_model_type,
|
'itam_type': {
|
||||||
'field_parameter_verbose_name_type': str
|
'blank': True,
|
||||||
|
'default': 'itam_base',
|
||||||
|
'field_type': models.CharField,
|
||||||
|
'max_length': 30,
|
||||||
|
'null': False,
|
||||||
|
'unique': False,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_class_inherits_itamassetbase(self, model):
|
||||||
def test_class_inherits_itam_assetbase(self):
|
|
||||||
""" Class inheritence
|
""" Class inheritence
|
||||||
|
|
||||||
TenancyObject must inherit SaveHistory
|
TenancyObject must inherit SaveHistory
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert issubclass(self.model, ITAMAssetBase)
|
assert issubclass(model, ITAMAssetBase)
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_meta_exists_itam_sub_model_type(self):
|
|
||||||
"""Attribute check
|
|
||||||
|
|
||||||
meta.itam_sub_model_type must exist
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert hasattr(self.model()._meta, 'itam_sub_model_type')
|
|
||||||
|
|
||||||
|
|
||||||
def test_sanity_is_it_asset_sub_model(self):
|
|
||||||
"""Sanity Test
|
|
||||||
|
|
||||||
This test ensures that the model being tested `self.model` is a
|
|
||||||
sub-model of `self.it_asset_base_model`.
|
|
||||||
This test is required as the same viewset is used for all sub-models
|
|
||||||
of `ITAMAssetBase`
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert issubclass(self.model, self.it_asset_base_model)
|
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_meta_type_itam_sub_model_type(self):
|
|
||||||
"""Attribute type
|
|
||||||
|
|
||||||
meta.itam_sub_model_type must be of type str
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert type(self.model()._meta.itam_sub_model_type) is str
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_type_app_namespace(self):
|
class ITAMAssetModelInheritedCases(
|
||||||
"""Attribute Type
|
ITAMAssetModelTestCases,
|
||||||
|
|
||||||
app_namespace is of type str
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.model.app_namespace is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_value_app_namespace(self):
|
|
||||||
"""Attribute Type
|
|
||||||
|
|
||||||
app_namespace has been set, override this test case with the value
|
|
||||||
of attribute `app_namespace`
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.model.app_namespace is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_type_note_basename(self):
|
|
||||||
"""Attribute Type
|
|
||||||
|
|
||||||
note_basename is of type str
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert type(self.model.note_basename) is str
|
|
||||||
|
|
||||||
|
|
||||||
def test_attribute_value_note_basename(self):
|
|
||||||
"""Attribute Type
|
|
||||||
|
|
||||||
note_basename has been set, override this test case with the value
|
|
||||||
of attribute `note_basename`
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.model.note_basename == 'accounting:_api_v2_asset_note'
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_is_property_get_itam_model_type(self):
|
|
||||||
"""Function test
|
|
||||||
|
|
||||||
Confirm function `get_itam_model_type` is a property
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert type(self.model.get_itam_model_type) is property
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_value_get_itam_model_type(self):
|
|
||||||
"""Function test
|
|
||||||
|
|
||||||
Confirm function `get_itam_model_type` is a property
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.item.get_itam_model_type is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_value_get_url(self):
|
|
||||||
|
|
||||||
assert self.item.get_url() == '/api/v2/itam/it_asset/' + str(self.item.id)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ITAMAssetBaseModelInheritedCases(
|
|
||||||
ITAMAssetBaseModelTestCases,
|
|
||||||
):
|
):
|
||||||
"""Sub-Ticket Test Cases
|
pass
|
||||||
|
|
||||||
Test Cases for Ticket models that inherit from model AssetBase
|
|
||||||
"""
|
|
||||||
|
|
||||||
kwargs_create_item: dict = {}
|
|
||||||
|
|
||||||
model = None
|
|
||||||
|
|
||||||
|
|
||||||
sub_model_type = None
|
|
||||||
"""Ticket Sub Model Type
|
|
||||||
|
|
||||||
Ticket sub-models must have this attribute defined in `ModelNam.Meta.sub_model_type`
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def test_function_value_not_None_get_itam_model_type(self):
|
|
||||||
"""Function test
|
|
||||||
|
|
||||||
Confirm function `get_itam_model_type` is a property
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.item.get_itam_model_type is not None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ITAMAssetBaseModelPyTest(
|
@pytest.mark.module_accounting
|
||||||
ITAMAssetBaseModelTestCases,
|
class ITAMAssetModelPyTest(
|
||||||
|
ITAMAssetModelTestCases,
|
||||||
):
|
):
|
||||||
|
pass
|
||||||
def test_function_value_get_related_model(self):
|
|
||||||
"""Function test
|
|
||||||
|
|
||||||
Confirm function `get_related_model` is None for base model
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert self.item.get_related_model() is None
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
|
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
@ -22,6 +24,7 @@ from itam.models.itam_asset_base import ITAMAssetBase
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.model_itamassetbase
|
||||||
class ITAMAssetBaseViewsetTestCases(
|
class ITAMAssetBaseViewsetTestCases(
|
||||||
AssetBaseViewsetInheritedCases,
|
AssetBaseViewsetInheritedCases,
|
||||||
):
|
):
|
||||||
@ -41,10 +44,11 @@ class ITAMAssetBaseViewsetInheritedCases(
|
|||||||
model: str = None
|
model: str = None
|
||||||
"""name of the model to test"""
|
"""name of the model to test"""
|
||||||
|
|
||||||
route_name = 'v2:accounting:_api_v2_asset_sub'
|
route_name = 'v2:accounting:_api_asset_sub'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.module_accounting
|
||||||
class ITAMAssetBaseViewsetTest(
|
class ITAMAssetBaseViewsetTest(
|
||||||
ITAMAssetBaseViewsetTestCases,
|
ITAMAssetBaseViewsetTestCases,
|
||||||
TestCase,
|
TestCase,
|
||||||
|
@ -34,8 +34,8 @@ router.register(
|
|||||||
basename = '_api_v2_itam_home'
|
basename = '_api_v2_itam_home'
|
||||||
)
|
)
|
||||||
router.register(
|
router.register(
|
||||||
prefix = '(?P<asset_model>[it_asset]+)', viewset = asset.ViewSet,
|
prefix = '(?P<model_name>[itamassetbase]+)', viewset = asset.ViewSet,
|
||||||
feature_flag = '2025-00007', basename = '_api_v2_itam_asset'
|
feature_flag = '2025-00007', basename = '_api_itamassetbase'
|
||||||
)
|
)
|
||||||
router.register(
|
router.register(
|
||||||
prefix = 'device', viewset = device.ViewSet,
|
prefix = 'device', viewset = device.ViewSet,
|
||||||
|
15
app/tests/fixtures/__init__.py
vendored
15
app/tests/fixtures/__init__.py
vendored
@ -18,6 +18,11 @@ from .model_appsettings import (
|
|||||||
model_appsettings,
|
model_appsettings,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .model_assetbase import (
|
||||||
|
kwargs_assetbase,
|
||||||
|
model_assetbase,
|
||||||
|
)
|
||||||
|
|
||||||
from .model_centurionaudit import (
|
from .model_centurionaudit import (
|
||||||
kwargs_centurionaudit,
|
kwargs_centurionaudit,
|
||||||
model_centurionaudit,
|
model_centurionaudit,
|
||||||
@ -160,6 +165,11 @@ from .model_instance import (
|
|||||||
model_instance
|
model_instance
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .model_itamassetbase import (
|
||||||
|
kwargs_itamassetbase,
|
||||||
|
model_itamassetbase,
|
||||||
|
)
|
||||||
|
|
||||||
from .model_knowledgebase import (
|
from .model_knowledgebase import (
|
||||||
kwargs_knowledgebase,
|
kwargs_knowledgebase,
|
||||||
model_knowledgebase,
|
model_knowledgebase,
|
||||||
@ -223,6 +233,11 @@ from .model_projecttype import (
|
|||||||
model_projecttype,
|
model_projecttype,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .model_role import (
|
||||||
|
kwargs_role,
|
||||||
|
model_role,
|
||||||
|
)
|
||||||
|
|
||||||
from .model_service import (
|
from .model_service import (
|
||||||
kwargs_service,
|
kwargs_service,
|
||||||
model_service,
|
model_service,
|
||||||
|
26
app/tests/fixtures/model_assetbase.py
vendored
Normal file
26
app/tests/fixtures/model_assetbase.py
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import datetime
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from accounting.models.asset_base import AssetBase
|
||||||
|
|
||||||
|
@pytest.fixture( scope = 'class')
|
||||||
|
def model_assetbase():
|
||||||
|
|
||||||
|
yield AssetBase
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture( scope = 'class')
|
||||||
|
def kwargs_assetbase( kwargs_centurionmodel, model_assetbase ):
|
||||||
|
|
||||||
|
random_str = str(datetime.datetime.now(tz=datetime.timezone.utc))
|
||||||
|
random_str = str(random_str).replace(
|
||||||
|
' ', '').replace(':', '').replace('+', '').replace('.', '')
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
**kwargs_centurionmodel.copy(),
|
||||||
|
'asset_number': 'ab_' + random_str,
|
||||||
|
'serial_number': 'ab_' + random_str,
|
||||||
|
# 'asset_type': (model_assetbase._meta.sub_model_type, model_assetbase._meta.verbose_name),
|
||||||
|
}
|
||||||
|
|
||||||
|
yield kwargs.copy()
|
25
app/tests/fixtures/model_itamassetbase.py
vendored
Normal file
25
app/tests/fixtures/model_itamassetbase.py
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import datetime
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from itam.models.itam_asset_base import ITAMAssetBase
|
||||||
|
|
||||||
|
@pytest.fixture( scope = 'class')
|
||||||
|
def model_itamassetbase():
|
||||||
|
|
||||||
|
yield ITAMAssetBase
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture( scope = 'class')
|
||||||
|
def kwargs_itamassetbase( kwargs_assetbase, model_itamassetbase ):
|
||||||
|
|
||||||
|
random_str = str(datetime.datetime.now(tz=datetime.timezone.utc))
|
||||||
|
random_str = str(random_str).replace(
|
||||||
|
' ', '').replace(':', '').replace('+', '').replace('.', '')
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
**kwargs_assetbase.copy(),
|
||||||
|
# 'asset_type': (model_itamassetbase._meta.sub_model_type, model_itamassetbase._meta.verbose_name),
|
||||||
|
'itam_type': "it_asset"
|
||||||
|
}
|
||||||
|
|
||||||
|
yield kwargs.copy()
|
21
app/tests/fixtures/model_kwarg_data.py
vendored
21
app/tests/fixtures/model_kwarg_data.py
vendored
@ -1,5 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError, ObjectDoesNotExist
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
@ -97,9 +97,22 @@ def model_kwarg_data():
|
|||||||
|
|
||||||
if 'unique' in e.error_dict['__all__'][0].code:
|
if 'unique' in e.error_dict['__all__'][0].code:
|
||||||
|
|
||||||
instance = model.objects.get(
|
try:
|
||||||
**kwargs
|
|
||||||
)
|
instance = model.objects.get(
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
except ObjectDoesNotExist as e:
|
||||||
|
|
||||||
|
if 'modified' in kwargs:
|
||||||
|
|
||||||
|
no_modified_in_kwargs = kwargs.copy()
|
||||||
|
del no_modified_in_kwargs['modified']
|
||||||
|
|
||||||
|
instance = model.objects.get(
|
||||||
|
**no_modified_in_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
for field, values in many_field.items():
|
for field, values in many_field.items():
|
||||||
|
29
app/tests/fixtures/model_role.py
vendored
Normal file
29
app/tests/fixtures/model_role.py
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import datetime
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from access.models.role import Role
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture( scope = 'class')
|
||||||
|
def model_role():
|
||||||
|
|
||||||
|
yield Role
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture( scope = 'class')
|
||||||
|
def kwargs_role(
|
||||||
|
kwargs_centurionmodel
|
||||||
|
):
|
||||||
|
|
||||||
|
random_str = str(datetime.datetime.now(tz=datetime.timezone.utc))
|
||||||
|
random_str = str(random_str).replace(
|
||||||
|
' ', '').replace(':', '').replace('-', '').replace('+', '').replace('.', '')
|
||||||
|
|
||||||
|
kwargs = {
|
||||||
|
**kwargs_centurionmodel.copy(),
|
||||||
|
'name': 'r_' + random_str,
|
||||||
|
'modified': '2024-06-03T23:00:00Z',
|
||||||
|
}
|
||||||
|
|
||||||
|
yield kwargs.copy()
|
@ -87,7 +87,7 @@ A Model link is a reference to an item within the database. Supported model link
|
|||||||
| gitrepository| `$git_repository-<id>` |
|
| gitrepository| `$git_repository-<id>` |
|
||||||
| gitgroup| `$git_group-<id>` |
|
| gitgroup| `$git_group-<id>` |
|
||||||
| group| `$-<id>` |
|
| group| `$-<id>` |
|
||||||
| it_asset | `$it_asset-<id>` |
|
| it_asset | `$asset-<id>` or `$it_asset-<id>` |
|
||||||
| knowledgebase| `$kb-<id>` |
|
| knowledgebase| `$kb-<id>` |
|
||||||
| knowledgebasecategory| `$kb_category-<id>` |
|
| knowledgebasecategory| `$kb_category-<id>` |
|
||||||
| manufacturer| `$manufacturer-<id>` |
|
| manufacturer| `$manufacturer-<id>` |
|
||||||
|
@ -1103,6 +1103,7 @@ markers = [
|
|||||||
"meta_models: Selects Meta models",
|
"meta_models: Selects Meta models",
|
||||||
"mixin: Selects all mixin test cases.",
|
"mixin: Selects all mixin test cases.",
|
||||||
"mixin_centurion: Selects all centurion mixin test cases.",
|
"mixin_centurion: Selects all centurion mixin test cases.",
|
||||||
|
"model_assetbase: Selects tests for model Asset Base.",
|
||||||
"model_appsettings: Selects tests for model app settings.",
|
"model_appsettings: Selects tests for model app settings.",
|
||||||
"model_company: Selects test for model Company.",
|
"model_company: Selects test for model Company.",
|
||||||
"model_configgroups: Selects Config Group tests.",
|
"model_configgroups: Selects Config Group tests.",
|
||||||
@ -1124,6 +1125,7 @@ markers = [
|
|||||||
"model_githubrepository: Selects tests for model `github repository`",
|
"model_githubrepository: Selects tests for model `github repository`",
|
||||||
"model_gitlabrepository: Selects tests for model `gitlab repository`",
|
"model_gitlabrepository: Selects tests for model `gitlab repository`",
|
||||||
"model_gitrepository: Selects tests for model `git repository`",
|
"model_gitrepository: Selects tests for model `git repository`",
|
||||||
|
"model_itamassetbase: Selects tests for model ITAM Asset Base.",
|
||||||
"model_knowledgebase: Selects Knowledge base tests.",
|
"model_knowledgebase: Selects Knowledge base tests.",
|
||||||
"model_knowledgebasecategory: Selects Knowledge base category tests.",
|
"model_knowledgebasecategory: Selects Knowledge base category tests.",
|
||||||
"model_manufacturer: Select all manufacturer tests.",
|
"model_manufacturer: Select all manufacturer tests.",
|
||||||
@ -1135,6 +1137,7 @@ markers = [
|
|||||||
"model_projectmilestone: Selects tests for model Project Milestone.",
|
"model_projectmilestone: Selects tests for model Project Milestone.",
|
||||||
"model_projectstate: Selects tests for model Project State.",
|
"model_projectstate: Selects tests for model Project State.",
|
||||||
"model_projecttype: Selects tests for model Project Type.",
|
"model_projecttype: Selects tests for model Project Type.",
|
||||||
|
"model_role: Selects tests for model Role.",
|
||||||
"model_service: Selects tests for model Service.",
|
"model_service: Selects tests for model Service.",
|
||||||
"model_software: Selects tests for model Software.",
|
"model_software: Selects tests for model Software.",
|
||||||
"model_softwarecategory: Selects tests for model Software Category.",
|
"model_softwarecategory: Selects tests for model Software Category.",
|
||||||
|
Reference in New Issue
Block a user