Skip to content

Commit

Permalink
Merge pull request #104 from mlebreuil/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
mlebreuil authored Dec 15, 2023
2 parents 55debce + d43f451 commit d91fb35
Show file tree
Hide file tree
Showing 44 changed files with 1,343 additions and 651 deletions.
9 changes: 9 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[flake8]
max-line-length = 120
extend-ignore = W504,E501
exclude =
.git,
__pycache__,
build,
dist
max-complexity = 10
18 changes: 18 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: double-quote-string-fixer
- repo: https://github.com/ambv/black
rev: 23.11.0
hooks:
- id: black
language_version: python3.10
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,18 @@ Customize the location of the plugin's menu:
# configuration.py
PLUGINS_CONFIG = {
'netbox_contract': {
'top_level_menu': True
'top_level_menu': True,
'default_accounting_dimensions':{
"account": "",
"project": "",
"cost center": ""
}
}
}

```

Customize the internal partie field.
Customize fields choices.
Internal partie reference the legal entity of your organization that is a partie to the contract.

```python
Expand Down Expand Up @@ -117,3 +122,15 @@ Add support for Netbox 3.5 which become the minimum version supported to accomod
* [#85](https://github.com/mlebreuil/netbox-contract/issues/85) Fix missing fields contract and invoice import and export forms.

#### version 2.0.8
* [#91](https://github.com/mlebreuil/netbox-contract/issues/91) Replace deprecated ( in netbox version 3.6) MultipleChoiceField.
* [48](https://github.com/mlebreuil/netbox-contract/issues/48) Allow other plugin to inject visual in contract and invoice forms.
* [89] (https://github.com/mlebreuil/netbox-contract/issues/89) Add contract assignement to virtual machines.

#### version 2.0.9
* [42](https://github.com/mlebreuil/netbox-contract/issues/42) Allow the selection of either providers or Service providers as contract third partie.
* Removed all reference to the direct assignement of circuits to contracts
* [88](https://github.com/mlebreuil/netbox-contract/issues/88) Add a placeholder value to the accounting dimensions jsonfield. This placeholder vale con be configured as part of the PLUGINS_CONFIG parameter in the configuration.py file (see above)
* [89](https://github.com/mlebreuil/netbox-contract/issues/89) add the posibility to link contracts to sites and virtual machines.
* [99](https://github.com/mlebreuil/netbox-contract/issues/99) list child contracts in on the parent view.


13 changes: 9 additions & 4 deletions contract_migration.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.contenttypes.models import ContentType
from netbox_contract.models import ContractAssignement, Contract
from django.core.exceptions import ObjectDoesNotExist

from netbox_contract.models import Contract, ContractAssignement

for contract in Contract.objects.all():
circuits = contract.circuit.all()
for circuit in circuits:
try :
try:
circuit_type = ContentType.objects.get_for_model(circuit).id
assignement = ContractAssignement.objects.get(content_type=circuit_type, object_id= circuit.id, contract__id=contract.id)
assignement = ContractAssignement.objects.get(
content_type=circuit_type,
object_id=circuit.id,
contract__id=contract.id,
)
except ObjectDoesNotExist:
assignement = ContractAssignement(content_object=circuit, contract=contract)
assignement.save()
16 changes: 8 additions & 8 deletions netbox-configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
# PostgreSQL database configuration. See the Django documentation for a complete list of available parameters:
# https://docs.djangoproject.com/en/stable/ref/settings/#databases
DATABASE = {
'NAME': 'netbox', # Database name
'USER': 'netbox', # PostgreSQL username
'PASSWORD': 'J5brHrAXFLQSif0K', # PostgreSQL password
'HOST': 'db', # Database server
'PORT': '', # Database port (leave blank for default)
'CONN_MAX_AGE': 300, # Max database connection age
'NAME': 'netbox', # Database name
'USER': 'netbox', # PostgreSQL username
'PASSWORD': 'J5brHrAXFLQSif0K', # PostgreSQL password
'HOST': 'db', # Database server
'PORT': '', # Database port (leave blank for default)
'CONN_MAX_AGE': 300, # Max database connection age
}

# Redis database settings. Redis is used for caching and for queuing background tasks such as webhook events. A separate
Expand Down Expand Up @@ -50,7 +50,7 @@
# Set this to True to skip TLS certificate verification
# This can expose the connection to attacks, be careful
# 'INSECURE_SKIP_TLS_VERIFY': False,
}
},
}

# This key is used for secure generation of random numbers and strings. It must never be exposed outside of this file.
Expand Down Expand Up @@ -103,7 +103,7 @@
# on a production system.
DEBUG = True

DEVELOPER=True
DEVELOPER = True

# Email settings
EMAIL = {
Expand Down
10 changes: 8 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "netbox-contract"
version = "2.0.8"
version = "2.0.9"
authors = [
{ name="Marc Lebreuil", email="[email protected]" },
]
Expand Down Expand Up @@ -30,4 +30,10 @@ zip-safe = false
[tool.setuptools.packages.find]
where = ["src"]
include = ["*"]
namespaces = false
namespaces = false

[tool.black]
skip-string-normalization = true

[tool.isort]
profile = "black"
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from setuptools import find_packages, setup
from setuptools import setup

setup()
setup()
11 changes: 9 additions & 2 deletions src/netbox_contract/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
from extras.plugins import PluginConfig


class ContractsConfig(PluginConfig):
name = 'netbox_contract'
verbose_name = 'Netbox contract'
description = 'Contract management plugin for Netbox'
version = '2.0.8'
version = '2.0.9'
author = 'Marc Lebreuil'
author_email = '[email protected]'
base_url = 'contracts'
min_version = "3.5.0"
min_version = '3.5.0'
required_settings = []
default_settings = {
'top_level_menu': False,
'default_accounting_dimensions': {
'account': '',
'project': '',
'cost center': '',
},
}


config = ContractsConfig
101 changes: 79 additions & 22 deletions src/netbox_contract/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from drf_yasg.utils import swagger_serializer_method
from rest_framework import serializers
from django.contrib.auth.models import ContentType
from tenancy.api.nested_serializers import NestedTenantSerializer
from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer
from drf_yasg.utils import swagger_serializer_method
from netbox.api.fields import ContentTypeField
from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer
from netbox.constants import NESTED_SERIALIZER_PREFIX
from rest_framework import serializers
from tenancy.api.nested_serializers import NestedTenantSerializer
from utilities.api import get_serializer_for_model
from ..models import Contract, Invoice, ServiceProvider, ContractAssignement

from ..models import Contract, ContractAssignement, Invoice, ServiceProvider


class NestedServiceProviderSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
Expand All @@ -17,6 +19,7 @@ class Meta:
model = ServiceProvider
fields = ('id', 'url', 'display', 'name')


class NestedContractSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='plugins-api:netbox_contract-api:contract-detail'
Expand All @@ -26,6 +29,7 @@ class Meta:
model = Contract
fields = ('id', 'url', 'display', 'name')


class NestedInvoiceSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='plugins-api:netbox_contract-api:invoice-detail'
Expand All @@ -35,33 +39,56 @@ class Meta:
model = Invoice
fields = ('id', 'url', 'display', 'number')


class NestedContractAssignementSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='plugins-api:netbox_contract-api:ContractAssignement-detail'
)

class Meta:
model = ContractAssignement
fields = ('id', 'url', 'display','contract','content_object')
fields = ('id', 'url', 'display', 'contract', 'content_object')


class ContractSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='plugins-api:netbox_contract-api:contract-detail'
)
#circuit= NestedCircuitSerializer(many=True, required=False)
# circuit= NestedCircuitSerializer(many=True, required=False)
external_partie = NestedServiceProviderSerializer(many=False)
parent = NestedContractSerializer(many=False, required=False)
tenant= NestedTenantSerializer(many=False, required=False)
tenant = NestedTenantSerializer(many=False, required=False)

class Meta:
model = Contract
fields = (
'id', 'url','display', 'name', 'external_partie','external_reference', 'internal_partie',
'tenant','status','start_date','end_date','initial_term','renewal_term',
'currency','accounting_dimensions','mrc','nrc','invoice_frequency','comments',
'parent','tags', 'custom_fields', 'created', 'last_updated',
'id',
'url',
'display',
'name',
'external_partie',
'external_reference',
'internal_partie',
'tenant',
'status',
'start_date',
'end_date',
'initial_term',
'renewal_term',
'currency',
'accounting_dimensions',
'mrc',
'nrc',
'invoice_frequency',
'comments',
'parent',
'tags',
'custom_fields',
'created',
'last_updated',
)


class InvoiceSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='plugins-api:netbox_contract-api:invoice-detail'
Expand All @@ -71,12 +98,25 @@ class InvoiceSerializer(NetBoxModelSerializer):
class Meta:
model = Invoice
fields = (
'id', 'url', 'display', 'number', 'date', 'contracts',
'period_start','period_end','currency','accounting_dimensions',
'amount','comments',
'tags', 'custom_fields', 'created','last_updated',
'id',
'url',
'display',
'number',
'date',
'contracts',
'period_start',
'period_end',
'currency',
'accounting_dimensions',
'amount',
'comments',
'tags',
'custom_fields',
'created',
'last_updated',
)


class ServiceProviderSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='plugins-api:netbox_contract-api:serviceprovider-detail'
Expand All @@ -85,27 +125,44 @@ class ServiceProviderSerializer(NetBoxModelSerializer):
class Meta:
model = ServiceProvider
fields = (
'id', 'url', 'display', 'name', 'portal_url', 'tags', 'custom_fields', 'created',
'id',
'url',
'display',
'name',
'portal_url',
'tags',
'custom_fields',
'created',
'last_updated',
)


class ContractAssignementSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='plugins-api:netbox_contract-api:contractassignement-detail')
content_type = ContentTypeField(
queryset=ContentType.objects.all()
url = serializers.HyperlinkedIdentityField(
view_name='plugins-api:netbox_contract-api:contractassignement-detail'
)
content_type = ContentTypeField(queryset=ContentType.objects.all())
content_object = serializers.SerializerMethodField(read_only=True)
contract = NestedContractSerializer()

class Meta:
model = ContractAssignement
fields = [
'id', 'url', 'display', 'content_type', 'object_id', 'content_object', 'contract', 'created',
'id',
'url',
'display',
'content_type',
'object_id',
'content_object',
'contract',
'created',
'last_updated',
]

@swagger_serializer_method(serializer_or_field=serializers.JSONField)
def get_content_object(self, instance):
serializer = get_serializer_for_model(instance.content_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX)
serializer = get_serializer_for_model(
instance.content_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX
)
context = {'request': self.context['request']}
return serializer(instance.content_object, context=context).data
1 change: 1 addition & 0 deletions src/netbox_contract/api/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from netbox.api.routers import NetBoxRouter

from . import views

app_name = 'netbox_contract'
Expand Down
Loading

0 comments on commit d91fb35

Please sign in to comment.