@ -3,27 +3,33 @@ title: Models
|
||||
description: Centurion ERP Models development documentation
|
||||
date: 2024-07-14
|
||||
template: project.html
|
||||
about: https://gitlab.com/nofusscomputing/infrastructure/configuration-management/centurion_erp
|
||||
about: https://github.com/nofusscomputing/centurion_erp
|
||||
---
|
||||
|
||||
Models within Centurion ERP are how the data is structured within the database. This page contains documentation pertinent to the development of the models for use with Centurion ERP.
|
||||
|
||||
All models within Centurion ERP are what we call a "Tenancy Object." A tenancy object is a model that takes advantage of the multi-tenancy features of Centurion ERP.
|
||||
|
||||
## Creating a Model
|
||||
|
||||
All models are class based models. Due to this fact, most of the work has been done for the models. We have two types of models: normal and sub-model. In most cases to create a model you will only need to declare the fields and any validation.
|
||||
|
||||
When designing or even implementing a model do consider that what is defined within its class must take into account that the model is responsible for ensure that no data is saved to the database wherein it could create an inconsistancy. For ensureing this does not see [Validation](#validation-methods) below.
|
||||
|
||||
|
||||
## Requirements
|
||||
### Requirements
|
||||
|
||||
All models must meet the following requirements:
|
||||
When creating models they must meet the following requirements:
|
||||
|
||||
- inherits from `app.access.models.TenancyObject`
|
||||
- inherits from `core.models.centurion.CenturionModel` or if a submodel `core.models.centurion.CenturionSubModel` and its base model.
|
||||
|
||||
!!! tip
|
||||
There is no requirement to include class [`app.core.mixin.history_save.SaveHistory`](./api/models/core_history_save.md) for inheritence as this class is already included within class `app.access.models.TenancyObject`.
|
||||
- class has the folloing objects defined:
|
||||
|
||||
!!! note
|
||||
If there is a specific use case for the object not to be a tenancy object, this will need to be discussed with a maintainer.
|
||||
- Function `__str__` is defined to return the models name when requested as a string.
|
||||
|
||||
- Attribute `page_layout` is defined with the models UI page layout
|
||||
|
||||
- Attribute `table_fields` is defined with the fields to display by default for viewing the model within a table.
|
||||
|
||||
- class has `__str__` method defined to return that is used to return a default value if no field is specified.
|
||||
|
||||
- Fields are initialized with the following parameters:
|
||||
|
||||
@ -31,13 +37,6 @@ All models must meet the following requirements:
|
||||
|
||||
- `help_text`
|
||||
|
||||
- No `queryset` is to return data that the user has not got access to.
|
||||
|
||||
- Single Field validation is conducted if required.
|
||||
|
||||
!!! danger "Requirement"
|
||||
Multi-field validation, or validation that requires access to multiple fields must be done within the [form class](./forms.md#requirements).
|
||||
|
||||
- contains a `Meta` sub-class with following attributes:
|
||||
|
||||
- `ordering` _Order the results are returned in._
|
||||
@ -46,82 +45,91 @@ All models must meet the following requirements:
|
||||
|
||||
- `verbose_name_plural` _Plural Name of the model_
|
||||
|
||||
- If creating a new model, function `access.functions.permissions.permission_queryset()` has been updated to display the models permission(s)
|
||||
- No `queryset` is to return data that the user has not got access to.
|
||||
|
||||
- Attribute `page_layout` is defined with the models UI page layout
|
||||
|
||||
- Attribute `table_fields` is defined with the fields to display by default for viewing the model within a table.
|
||||
|
||||
- `clean()` method within a model is **only** used to ensure that the data entered into the DB is valid and/or to ensure application wide changes/validation is conducted prior to saving model.
|
||||
|
||||
- Tenancy models must have the ability to have a [knowledge base article](#knowledge-base-article-linking) linked to it.
|
||||
|
||||
- Models must save audit history
|
||||
!!! tip
|
||||
It's a good idea to create the initial model class, then create and add the model tests for that class. This way you can run the tests to ensure that the requirements are met. Of Note, the tests may not cover ALL of the requirements section, due diligence will need to be exercised.
|
||||
|
||||
|
||||
## Creating a Model
|
||||
### Normal (Base) Model
|
||||
|
||||
Within Centurion ERP there are two types of models, they are:
|
||||
This model is nothing special and is the core model type that will be created. If this model is inherited by a sub-model its also referred to as a _"base model."_ Creating one is as simple as simple as declaring the class, inheriting from `core.models.centurion.CenturionModel` then adding your fields and [validation method(s)](#validation-methods).
|
||||
|
||||
- Standard
|
||||
|
||||
- Sub-Model
|
||||
#### Available Base models
|
||||
|
||||
The are already some base models within Centurion ERP that you can use to extend and/or add features to Centurion easier. They are:
|
||||
|
||||
Within Centurion ERP there are some base models that are designed to be used for extending Centurion. They are:
|
||||
|
||||
- [Asset](./accounting/asset.md)
|
||||
|
||||
- [ITAM Asset](./itam/it_asset.md)
|
||||
|
||||
_A sub-model of Asset. Used by the ITAM module_
|
||||
|
||||
- [Entity](./core/entity.md)
|
||||
|
||||
Using a base model reduces the effort required to add a feature. This is such due to how the base model / sub-model has been designed. That is the base model has the core features so you don't need to add them. All that is required for the extension is that you add your fields and test the differences.
|
||||
- Company
|
||||
|
||||
_A sub-model of Entity. All business like entities_
|
||||
|
||||
### Standard Model
|
||||
- Person
|
||||
|
||||
This is your typical model that you would define within any Django Application. This includes Abstract models and precludes multi-table inherited models.
|
||||
_A sub-model of Entity. As the name implies, A person_
|
||||
|
||||
- Contact
|
||||
|
||||
_A sub-model of Person. Contains fields that are common to a contact_
|
||||
|
||||
- [Ticket](./core/ticket.md)
|
||||
|
||||
_All Ticketing Models use this_
|
||||
|
||||
- [Ticket Comment](./core/ticket_comment.md)
|
||||
|
||||
_All Ticket Comment Models use this_
|
||||
|
||||
All sub-models are intended to be extended and contain the core features for ALL models. This aids in extensibility and reduces the work required to add a model.
|
||||
|
||||
!!! tip
|
||||
Core features can be switched on and/or off for the model you are creating. Before doing so though, consider the reasons for doing so and do discuss with a maintainer. This discussion will be required to ensure that you are not unintentially removing a feature that is a **must** for a Centurion ERP model.
|
||||
|
||||
|
||||
### Sub-Model
|
||||
|
||||
This model is known within Django as multi-table inherited models. That is where the base model is a concrete class (not an Abstract model) and the super model inherits from the concrete base model. In this instance both models get their own database tables.
|
||||
A Sub-model specifically inherits from a normal model with the purpose of using the base model fields (the common fields) and if required specifying its own fields. A sub-model provides an additional feature in that the data from the base model can now be based off of the permissions of the sub-model, not the base. THis model inherits from `core.models.centurion.CenturionSubModel` and its base model.
|
||||
|
||||
|
||||
#### Available Sub-Models
|
||||
## Core Features
|
||||
|
||||
We do have some core sub-models available. There intended purpose is to serve as a single place for all items of that type. Available sub-models are:
|
||||
All models must contain the core features, being:
|
||||
|
||||
- [Asset](./accounting/asset.md)
|
||||
- [Audit History](./core/model_history.md)
|
||||
|
||||
- [IT Asset](./itam/it_asset.md)
|
||||
_Every change that occurs to a model is recorded_
|
||||
|
||||
- [Ticket](./core/ticket.md)
|
||||
- [Notes](./core/model_notes.md)
|
||||
|
||||
- [Ticket Comment](./core/ticket_comment.md)
|
||||
_Adds the ability for a user to add comments to a model_
|
||||
|
||||
All sub-models are intended to be extended and contain the core features for ALL models. This aids in extensibility and reduces the work required to add a model.
|
||||
- KB Article linking
|
||||
|
||||
_Enables linking a knowledge base article to a model_
|
||||
|
||||
- Model Tag
|
||||
|
||||
_Enables the possibility within markdown fields to use its [tag](../user/core/markdown.md#model-reference--model-tag) to create a link to the model._
|
||||
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
#### Requirements
|
||||
<!-- markdownlint-restore -->
|
||||
## Validation Methods
|
||||
|
||||
- Must **not** be an abstract class
|
||||
Within All of our models including when they are created via an API serializer, the models [validators](https://docs.djangoproject.com/en/5.1/ref/models/instances/#validating-objects) are called. The models validators are responsible for ensuring that no data goes into the database that may create an inconsistancy.
|
||||
|
||||
- Attribute `sub_model_type` must be specified within the models `Meta` sub-class
|
||||
!!! example
|
||||
You have defined a model that has a user field that must always have a value. This model can be access via the API, in which the user field is auto-populated by object `request.user`. In the same token you have admin commands that uses this model.
|
||||
Now every time you use the admin command to create this model, it will fail validation due to there being no value for the user field. This is where the models validator methods come into play. defining method `clean()` within the model with the logic required to ensure that the user field has value for the user field ensures that the model now when used by the admin command is consistant and meets the intent of the models purpose.
|
||||
|
||||
- File name is `<base model>_<sub_model_type>` where `base model` is the value of `Meta.sub_model_type` or the first model in the chain.
|
||||
|
||||
|
||||
## Checklist
|
||||
|
||||
This section details the additional items that may need to be done when adding a new model:
|
||||
|
||||
- If the model is a primary model, add it to model reference rendering in `app/core/lib/markdown_plugins/model_reference.py` function `tag_html`
|
||||
|
||||
- If the model is a primary model, add it to the model link slash command in `app/core/lib/slash_commands/linked_model.py` function `command_linked_model`
|
||||
|
||||
!!! tip
|
||||
It's a good idea to create the initial model class, then create and add the model tests for that class. This way you can run the tests to ensure that the requirements are met. Of Note, the tests may not cover ALL of the requirements section, due diligence will need to be exercised.
|
||||
Whilst most data that will use a model will be via an API Serializer, which in turn has its own validation. The models Validation is only to serve the purpose of ensuring data consistancy.
|
||||
|
||||
|
||||
## page_layout Attribute
|
||||
@ -203,6 +211,80 @@ table_fields: list = [
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- ToDo
|
||||
|
||||
- Avoid:
|
||||
|
||||
- adding `model.delete()` method
|
||||
|
||||
- adding `model.save()` method
|
||||
|
||||
- Do
|
||||
|
||||
- Add `model.clean()` To set/modify any field values, _if required_
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
- `clean()` method within a model is **only** used to ensure that the data entered into the DB is valid and/or to ensure application wide changes/validation is conducted prior to saving model.
|
||||
|
||||
- Tenancy models must have the ability to have a [knowledge base article](#knowledge-base-article-linking) linked to it.
|
||||
|
||||
- Models must save audit history
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
#### Requirements
|
||||
<!-- markdownlint-restore -->
|
||||
|
||||
- Must **not** be an abstract class
|
||||
|
||||
- Attribute `sub_model_type` must be specified within the models `Meta` sub-class
|
||||
|
||||
- File name is `<base model>_<sub_model_type>` where `base model` is the value of `Meta.sub_model_type` or the first model in the chain.
|
||||
|
||||
|
||||
## Checklist
|
||||
|
||||
This section details the additional items that may need to be done when adding a new model:
|
||||
|
||||
- If the model is a primary model, add it to model reference rendering in `app/core/lib/markdown_plugins/model_reference.py` function `tag_html`
|
||||
|
||||
- If the model is a primary model, add it to the model link slash command in `app/core/lib/slash_commands/linked_model.py` function `command_linked_model`
|
||||
|
||||
|
||||
|
||||
## History
|
||||
|
||||
Adding [History](./core/model_history.md) to a model is automatic. If there is a desire not to have model history it can be disabled by adding attribute `_audit_enabled` to the model class and setting its value to `False.`
|
||||
@ -270,20 +352,3 @@ All Tenancy Models must have the ability to be able to have a knowledge base art
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Docs to clean up
|
||||
|
||||
!!! note
|
||||
The below documentation is still to be developed. As such what is written below may be incorrect.
|
||||
|
||||
for items that have a parent item, modification will need to be made to the mixin by adding the relevant check and setting the relevant keys.
|
||||
|
||||
``` python
|
||||
|
||||
if self._meta.model_name == 'deviceoperatingsystem':
|
||||
|
||||
item_parent_pk = self.device.pk
|
||||
item_parent_class = self.device._meta.model_name
|
||||
|
||||
```
|
||||
|
Reference in New Issue
Block a user