Merge pull request #862 from nofusscomputing/refactor-switch-model-inheritence

This commit is contained in:
Jon
2025-07-13 21:36:52 +09:30
committed by GitHub
65 changed files with 1408 additions and 778 deletions

View File

@ -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",
),
]

View File

@ -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",),
),
]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}

View 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

View 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 )

View File

@ -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' )

View File

@ -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,
): ):

View File

@ -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'

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ),
}) })

View File

@ -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,

View File

@ -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",),
),
]

View File

@ -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",
),
]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}

View 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

View 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 )

View File

@ -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

View File

@ -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'

View File

@ -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,
): ):

View File

@ -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,
): ):

View File

@ -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'

View File

@ -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

View File

@ -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,
): ):

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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',

View File

@ -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']
} }

View File

@ -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,

View File

@ -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'

View File

@ -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);

View File

@ -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",),
),
]

View File

@ -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

View File

@ -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,

View 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

View 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 )

View File

@ -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

View File

@ -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,

View File

@ -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,
): ):

View File

@ -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,
): ):

View File

@ -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,

View File

@ -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

View File

@ -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,
): ):

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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
View 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()

View 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()

View File

@ -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
View 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()

View File

@ -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>` |

View File

@ -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.",