diff --git a/README.md b/README.md
index 5236b02..91485ac 100644
--- a/README.md
+++ b/README.md
@@ -92,3 +92,10 @@ Add support for Netbox 3.5 which become the minimum version supported to accomod
* [#65](https://github.com/mlebreuil/netbox-contract/issues/65) Add end date to contact import form.
* Removed the possibility of add or modify circuits to contracts. The field becomes read only and will be removed in next major release.
* Make accounting dimensions optional.
+
+#### version 2.0.5
+
+* [#75](https://github.com/mlebreuil/netbox-contract/issues/74) Fix contract assignement for service providers.
+* [#73](https://github.com/mlebreuil/netbox-contract/issues/73) Add comment field to contract import form
+* [#72](https://github.com/mlebreuil/netbox-contract/issues/72) Add fields to the contract assignement bottom tables
+* Remove the 'add' actions from the contract assignment list view
diff --git a/pyproject.toml b/pyproject.toml
index 5618c1d..1002cdd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "netbox-contract"
-version = "2.0.4"
+version = "2.0.5"
authors = [
{ name="Marc Lebreuil", email="marc@famillelebreuil.net" },
]
diff --git a/src/netbox_contract/__init__.py b/src/netbox_contract/__init__.py
index 66d3d74..7a48b9a 100644
--- a/src/netbox_contract/__init__.py
+++ b/src/netbox_contract/__init__.py
@@ -4,7 +4,7 @@ class ContractsConfig(PluginConfig):
name = 'netbox_contract'
verbose_name = 'Netbox contract'
description = 'Contract management plugin for Netbox'
- version = '2.0.4'
+ version = '2.0.5'
author = 'Marc Lebreuil'
author_email = 'marc@famillelebreuil.net'
base_url = 'contracts'
diff --git a/src/netbox_contract/forms.py b/src/netbox_contract/forms.py
index 594f0e9..656ade0 100644
--- a/src/netbox_contract/forms.py
+++ b/src/netbox_contract/forms.py
@@ -2,7 +2,7 @@
from django.contrib.contenttypes.models import ContentType
import django_filters
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelBulkEditForm, NetBoxModelImportForm
-from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, MultipleChoiceField, CSVModelChoiceField, SlugField, CSVContentTypeField
+from utilities.forms.fields import CommentField, CSVChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, MultipleChoiceField, CSVModelChoiceField, SlugField, CSVContentTypeField
from utilities.forms.widgets import DatePicker
from extras.filters import TagFilter
from circuits.models import Circuit
@@ -98,6 +98,10 @@ class ContractCSVForm(NetBoxModelImportForm):
help_text='Tenant name',
required=False
)
+ status = CSVChoiceField(
+ choices=StatusChoices,
+ help_text='Contract status'
+ )
parent = CSVModelChoiceField(
queryset=Contract.objects.all(),
to_field_name='name',
@@ -108,9 +112,9 @@ class ContractCSVForm(NetBoxModelImportForm):
class Meta:
model = Contract
fields = [
- 'name', 'external_partie', 'internal_partie','tenant', 'status',
+ 'name', 'external_partie', 'internal_partie', 'external_reference','tenant', 'status',
'start_date', 'end_date','initial_term', 'renewal_term', 'mrc', 'nrc',
- 'invoice_frequency', 'parent'
+ 'invoice_frequency', 'documents', 'comments', 'parent'
]
class ContractBulkEditForm(NetBoxModelBulkEditForm):
diff --git a/src/netbox_contract/tables.py b/src/netbox_contract/tables.py
index 397f1c9..dd66b42 100644
--- a/src/netbox_contract/tables.py
+++ b/src/netbox_contract/tables.py
@@ -34,8 +34,10 @@ class ContractAssignementObjectTable(NetBoxTable):
class Meta(NetBoxTable.Meta):
model = ContractAssignement
- fields = ('pk','contract','contract__external_partie','contract__status', 'actions')
- default_columns = ('pk', 'contract','contract__external_partie','contract__status')
+ fields = ('pk','contract','contract__external_partie','contract__status','contract__start_date',
+ 'contract__end_date','contract__mrc','contract__nrc', 'actions')
+ default_columns = ('pk', 'contract','contract__external_partie','contract__status','contract__start_date',
+ 'contract__end_date','contract__mrc','contract__nrc',)
class ContractAssignementContractTable(NetBoxTable):
content_type = columns.ContentTypeColumn(
@@ -43,16 +45,20 @@ class ContractAssignementContractTable(NetBoxTable):
)
content_object = tables.Column(
linkify=True,
+ verbose_name='Object',
orderable=False
)
+ content_object__status = tables.Column(
+ verbose_name='Status'
+ )
actions = columns.ActionsColumn(
actions=('edit', 'delete')
)
class Meta(NetBoxTable.Meta):
model = ContractAssignement
- fields = ('pk', 'content_type', 'content_object','actions')
- default_columns = ('pk', 'content_type', 'content_object')
+ fields = ('pk', 'content_type', 'content_object','content_object__status','actions')
+ default_columns = ('pk', 'content_type', 'content_object','content_object__status')
class ContractListTable(NetBoxTable):
diff --git a/src/netbox_contract/templates/contact_assignements_bottom.html b/src/netbox_contract/templates/contact_assignements_bottom.html
new file mode 100644
index 0000000..6c3047b
--- /dev/null
+++ b/src/netbox_contract/templates/contact_assignements_bottom.html
@@ -0,0 +1,63 @@
+{% load helpers %}
+
+
+
+
+ {% with contacts=object.contacts.all %}
+ {% if contacts.exists %}
+
+
+ Name |
+ Role |
+ Priority |
+ Phone |
+ Email |
+ |
+
+ {% for contact in contacts %}
+
+ {{ contact.contact|linkify }} |
+ {{ contact.role|placeholder }} |
+ {{ contact.get_priority_display|placeholder }} |
+
+ {% if contact.contact.phone %}
+ {{ contact.contact.phone }}
+ {% else %}
+ {{ ''|placeholder }}
+ {% endif %}
+ |
+
+ {% if contact.contact.email %}
+ {{ contact.contact.email }}
+ {% else %}
+ {{ ''|placeholder }}
+ {% endif %}
+ |
+
+ {% if perms.tenancy.change_contactassignment %}
+
+
+
+ {% endif %}
+ {% if perms.tenancy.delete_contactassignment %}
+
+
+
+ {% endif %}
+ |
+
+ {% endfor %}
+
+ {% else %}
+
None
+ {% endif %}
+ {% endwith %}
+
+ {% if perms.tenancy.add_contactassignment %}
+
+ {% endif %}
+
\ No newline at end of file
diff --git a/src/netbox_contract/templates/netbox_contract/serviceprovider.html b/src/netbox_contract/templates/netbox_contract/serviceprovider.html
index 3e44489..bbab8dd 100644
--- a/src/netbox_contract/templates/netbox_contract/serviceprovider.html
+++ b/src/netbox_contract/templates/netbox_contract/serviceprovider.html
@@ -31,7 +31,7 @@
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/comments.html' %}
{% include 'inc/panels/tags.html' %}
- {% include 'inc/panels/contacts.html' %}
+ {% include 'contact_assignements_bottom.html' %}
{% endblock content %}
\ No newline at end of file
diff --git a/src/netbox_contract/views.py b/src/netbox_contract/views.py
index 05f6fc5..3c63017 100644
--- a/src/netbox_contract/views.py
+++ b/src/netbox_contract/views.py
@@ -4,59 +4,63 @@
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import render, get_object_or_404
from netbox.views import generic
+from tenancy.views import ObjectContactsView
from netbox.views.generic.utils import get_prerequisite_model
from utilities.utils import count_related, normalize_querydict
from utilities.forms import restrict_form_fields
+from utilities.views import ViewTab, register_model_view
from circuits.models import Circuit
-from . import forms, models, tables, filtersets
+from .models import ServiceProvider, ContractAssignement, Contract, Invoice
+from . import forms, tables, filtersets
# ServiceProvider views
class ServiceProviderView(generic.ObjectView):
- queryset = models.ServiceProvider.objects.all()
+ queryset = ServiceProvider.objects.all()
class ServiceProviderListView(generic.ObjectListView):
- queryset = models.ServiceProvider.objects.all()
+ queryset = ServiceProvider.objects.all()
table = tables.ServiceProviderListTable
filterset = filtersets.ServiceProviderFilterSet
filterset_form = forms.ServiceProviderFilterSetForm
class ServiceProviderEditView(generic.ObjectEditView):
- queryset = models.ServiceProvider.objects.all()
+ queryset = ServiceProvider.objects.all()
form = forms.ServiceProviderForm
class ServiceProviderDeleteView(generic.ObjectDeleteView):
- queryset = models.ServiceProvider.objects.all()
+ queryset = ServiceProvider.objects.all()
class ServiceProviderBulkImportView(generic.BulkImportView):
- queryset = models.ServiceProvider.objects.all()
+ queryset = ServiceProvider.objects.all()
model_form = forms.ServiceProviderCSVForm
table = tables.ServiceProviderListTable
class ServiceProviderBulkEditView(generic.BulkEditView):
- queryset = models.ServiceProvider.objects.annotate()
+ queryset = ServiceProvider.objects.annotate()
filterset = filtersets.ServiceProviderFilterSet
table = tables.ServiceProviderListTable
form = forms.ServiceProviderBulkEditForm
class ServiceProviderBulkDeleteView(generic.BulkDeleteView):
- queryset = models.ServiceProvider.objects.annotate()
+ queryset = ServiceProvider.objects.annotate()
filterset = filtersets.ServiceProviderFilterSet
table = tables.ServiceProviderListTable
# Contract assignement view
class ContractAssignementView(generic.ObjectView):
- queryset = models.ContractAssignement.objects.all()
+ queryset = ContractAssignement.objects.all()
class ContractAssignementListView(generic.ObjectListView):
- queryset = models.ContractAssignement.objects.all()
+ queryset = ContractAssignement.objects.all()
table = tables.ContractAssignementListTable
filterset = filtersets.ContractAssignementFilterSet
filterset_form = forms.ContractAssignementFilterSetForm
+ actions = ['import', 'export', ]
class ContractAssignementEditView(generic.ObjectEditView):
- queryset = models.ContractAssignement.objects.all()
+ queryset = ContractAssignement.objects.all()
form = forms.ContractAssignementForm
def alter_object(self, instance, request, args, kwargs):
@@ -73,17 +77,17 @@ def get_extra_addanother_params(self, request):
}
class ContractAssignementDeleteView(generic.ObjectDeleteView):
- queryset = models.ContractAssignement.objects.all()
+ queryset = ContractAssignement.objects.all()
class ContractAssignementBulkImportView(generic.BulkImportView):
- queryset = models.ContractAssignement.objects.all()
+ queryset = ContractAssignement.objects.all()
model_form = forms.ContractAssignementImportForm
table = tables.ContractAssignementListTable
# Contract views
class ContractView(generic.ObjectView):
- queryset = models.Contract.objects.all()
+ queryset = Contract.objects.all()
def get_extra_context(self, request, instance):
invoices_table = tables.InvoiceListTable(instance.invoices.all())
@@ -100,25 +104,25 @@ def get_extra_context(self, request, instance):
}
class ContractListView(generic.ObjectListView):
- queryset = models.Contract.objects.all()
+ queryset = Contract.objects.all()
table = tables.ContractListTable
filterset = filtersets.ContractFilterSet
filterset_form = forms.ContractFilterSetForm
class ContractEditView(generic.ObjectEditView):
- queryset = models.Contract.objects.all()
+ queryset = Contract.objects.all()
form = forms.ContractForm
class ContractDeleteView(generic.ObjectDeleteView):
- queryset = models.Contract.objects.all()
+ queryset = Contract.objects.all()
class ContractBulkImportView(generic.BulkImportView):
- queryset = models.Contract.objects.all()
+ queryset = Contract.objects.all()
model_form = forms.ContractCSVForm
table = tables.ContractListTable
class ContractBulkEditView(generic.BulkEditView):
- queryset = models.Contract.objects.annotate(
+ queryset = Contract.objects.annotate(
count_circuits=count_related(Circuit, 'contracts')
)
filterset = filtersets.ContractFilterSet
@@ -126,7 +130,7 @@ class ContractBulkEditView(generic.BulkEditView):
form = forms.ContractBulkEditForm
class ContractBulkDeleteView(generic.BulkDeleteView):
- queryset = models.Contract.objects.annotate(
+ queryset = Contract.objects.annotate(
count_circuits=count_related(Circuit, 'contracts')
)
filterset = filtersets.ContractFilterSet
@@ -135,7 +139,7 @@ class ContractBulkDeleteView(generic.BulkDeleteView):
# Invoice views
class InvoiceView(generic.ObjectView):
- queryset = models.Invoice.objects.all()
+ queryset = Invoice.objects.all()
def get_extra_context(self, request, instance):
contracts_table = tables.ContractListTable(instance.contracts.all())
@@ -146,13 +150,13 @@ def get_extra_context(self, request, instance):
}
class InvoiceListView(generic.ObjectListView):
- queryset = models.Invoice.objects.all()
+ queryset = Invoice.objects.all()
table = tables.InvoiceListTable
filterset = filtersets.InvoiceFilterSet
filterset_form = forms.InvoiceFilterSetForm
class InvoiceEditView(generic.ObjectEditView):
- queryset = models.Invoice.objects.all()
+ queryset = Invoice.objects.all()
form = forms.InvoiceForm
def get(self, request, *args, **kwargs):
@@ -171,7 +175,7 @@ def get(self, request, *args, **kwargs):
initial_data = normalize_querydict(request.GET)
initial_data['date'] = date.today()
if 'contracts' in initial_data.keys():
- contract = models.Contract.objects.get(pk=initial_data['contracts'])
+ contract = Contract.objects.get(pk=initial_data['contracts'])
try:
last_invoice = contract.invoices.latest('period_end')
@@ -206,20 +210,20 @@ def get(self, request, *args, **kwargs):
})
class InvoiceDeleteView(generic.ObjectDeleteView):
- queryset = models.Invoice.objects.all()
+ queryset = Invoice.objects.all()
class InvoiceBulkImportView(generic.BulkImportView):
- queryset = models.Invoice.objects.all()
+ queryset = Invoice.objects.all()
model_form = forms.InvoiceCSVForm
table = tables.InvoiceListTable
class InvoiceBulkEditView(generic.BulkEditView):
- queryset = models.Invoice.objects.all()
+ queryset = Invoice.objects.all()
filterset = filtersets.InvoiceFilterSet
table = tables.InvoiceListTable
form = forms.InvoiceBulkEditForm
class InvoiceBulkDeleteView(generic.BulkDeleteView):
- queryset = models.Invoice.objects.all()
+ queryset = Invoice.objects.all()
filterset = filtersets.InvoiceFilterSet
table = tables.InvoiceListTable