Skip to content

Commit

Permalink
Merge pull request #122 from mlebreuil/develop
Browse files Browse the repository at this point in the history
v2.0.11
  • Loading branch information
mlebreuil authored Mar 29, 2024
2 parents 067e310 + 8bb83f4 commit f8a8e30
Show file tree
Hide file tree
Showing 14 changed files with 123 additions and 84 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ PLUGINS = [
]
```

Customize the location of the plugin's menu:
### Customize the plugin

The following configurationitems can be set:

```python
# configuration.py
Expand All @@ -42,13 +43,23 @@ PLUGINS_CONFIG = {
"account": "",
"project": "",
"cost center": ""
}
},
'mandatory_contract_fields': ['accounting_dimensions'],
'hidden_contract_fields': [],
'mandatory_invoice_fields': ['accounting_dimensions'],
'hidden_invoice_fields': [],
}
}

```

Customize fields choices.
* top_level_menu : If "Contracts" appears under the "Plugins" menu item or on its own
* default_accounting_dimensions: The accounting dimensions which will appear in the field' background when empty.
* mandatory_contract_fields, mandatory_invoice_fields: Fields which are not required by default and can be set as such. The list of fields is at the bottom of the contract import form.
* hidden_contract_fields, hidden_invoice_fields: List of fields to be hidden. Fields should not be required to be hidden.

### Customize the plugin fields choices

Internal partie reference the legal entity of your organization that is a partie to the contract.

```python
Expand Down Expand Up @@ -135,4 +146,9 @@ Add support for Netbox 3.5 which become the minimum version supported to accomod
#### version 2.0.10
* [107](https://github.com/mlebreuil/netbox-contract/issues/107) Add the contacts tab to the service provider detail view.
* [111](https://github.com/mlebreuil/netbox-contract/issues/111) Correct assignment spelling.
#### version 2.0.11
* [115](https://github.com/mlebreuil/netbox-contract/issues/115) API correction for contract external partie
* [117](https://github.com/mlebreuil/netbox-contract/issues/117) Tenant and accounting dimensions optional
* [119](https://github.com/mlebreuil/netbox-contract/issues/119) Add a Yearly recuring cost, read only, calculated field for contract
* [15](https://github.com/mlebreuil/netbox-contract/issues/105) AQuick serach limited to active contracts

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "netbox-contract"
version = "2.0.10"
version = "2.0.11"
authors = [
{ name="Marc Lebreuil", email="[email protected]" },
]
Expand Down
6 changes: 5 additions & 1 deletion src/netbox_contract/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class ContractsConfig(PluginConfig):
name = 'netbox_contract'
verbose_name = 'Netbox contract'
description = 'Contract management plugin for Netbox'
version = '2.0.10'
version = '2.0.11'
author = 'Marc Lebreuil'
author_email = '[email protected]'
base_url = 'contracts'
Expand All @@ -18,6 +18,10 @@ class ContractsConfig(PluginConfig):
'project': '',
'cost center': '',
},
'mandatory_contract_fields': [],
'hidden_contract_fields': [],
'mandatory_invoice_fields': [],
'hidden_invoice_fields': [],
}


Expand Down
19 changes: 16 additions & 3 deletions src/netbox_contract/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ class ContractSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='plugins-api:netbox_contract-api:contract-detail'
)
# circuit= NestedCircuitSerializer(many=True, required=False)
external_partie = NestedServiceProviderSerializer(many=False)
yrc = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
parent = NestedContractSerializer(many=False, required=False)
tenant = NestedTenantSerializer(many=False, required=False)
external_partie_object_type = ContentTypeField(queryset=ContentType.objects.all())
external_partie_object = serializers.SerializerMethodField(read_only=True)

class Meta:
model = Contract
Expand All @@ -66,7 +67,9 @@ class Meta:
'url',
'display',
'name',
'external_partie',
'external_partie_object_type',
'external_partie_object_id',
'external_partie_object',
'external_reference',
'internal_partie',
'tenant',
Expand All @@ -78,6 +81,7 @@ class Meta:
'currency',
'accounting_dimensions',
'mrc',
'yrc',
'nrc',
'invoice_frequency',
'comments',
Expand All @@ -88,6 +92,15 @@ class Meta:
'last_updated',
)

@swagger_serializer_method(serializer_or_field=serializers.JSONField)
def get_external_partie_object(self, instance):
serializer = get_serializer_for_model(
instance.external_partie_object_type.model_class(),
prefix=NESTED_SERIALIZER_PREFIX,
)
context = {'request': self.context['request']}
return serializer(instance.external_partie_object, context=context).data


class InvoiceSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(
Expand Down
5 changes: 4 additions & 1 deletion src/netbox_contract/api/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.db.models import F
from netbox.api.viewsets import NetBoxModelViewSet

from .. import filtersets, models
Expand All @@ -10,7 +11,9 @@


class ContractViewSet(NetBoxModelViewSet):
queryset = models.Contract.objects.prefetch_related('parent', 'circuit', 'tags')
queryset = models.Contract.objects.prefetch_related(
'parent', 'circuit', 'tags'
).annotate(yrc=F('mrc') * 12)
serializer_class = ContractSerializer


Expand Down
1 change: 1 addition & 0 deletions src/netbox_contract/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def search(self, queryset, name, value):
Q(name__icontains=value)
| Q(external_reference__icontains=value)
| Q(comments__icontains=value)
| Q(status__iexact='Active')
)


Expand Down
26 changes: 24 additions & 2 deletions src/netbox_contract/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ class ContractForm(NetBoxModelForm):
widget=HTMXSelect(),
)
external_partie_object = forms.ModelChoiceField(queryset=None)
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all())
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
parent = DynamicModelChoiceField(queryset=Contract.objects.all(), required=False)
accounting_dimensions = Dimensions()
accounting_dimensions = Dimensions(required=False)

def __init__(self, *args, **kwargs):
initial = kwargs.get('initial', None)
Expand Down Expand Up @@ -103,6 +103,15 @@ def __init__(self, *args, **kwargs):
# 'accounting_dimensions'
# ].widget.attrs['placeholder'] = '{"key": "value"}'

# Initialise fields settings
mandatory_fields = plugin_settings.get('mandatory_contract_fields')
for field in mandatory_fields:
self.fields[field].required = True
hidden_fields = plugin_settings.get('hidden_contract_fields')
for field in hidden_fields:
if not self.fields[field].required:
self.fields[field].widget = forms.HiddenInput()

class Meta:
model = Contract
fields = (
Expand Down Expand Up @@ -138,6 +147,19 @@ class InvoiceForm(NetBoxModelForm):
contracts = DynamicModelMultipleChoiceField(
queryset=Contract.objects.all(), required=False
)
accounting_dimensions = Dimensions(required=False)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

# Initialise fields settings
mandatory_fields = plugin_settings.get('mandatory_invoice_fields')
for field in mandatory_fields:
self.fields[field].required = True
hidden_fields = plugin_settings.get('hidden_invoice_fields')
for field in hidden_fields:
if not self.fields[field].required:
self.fields[field].widget = forms.HiddenInput()

class Meta:
model = Invoice
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.2.10 on 2024-03-29 09:49

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
(
'netbox_contract',
'0023_rename_contractassignement_contractassignment_and_more',
),
]

operations = [
migrations.RemoveField(
model_name='contract',
name='external_partie',
),
]
7 changes: 0 additions & 7 deletions src/netbox_contract/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,6 @@ def get_absolute_url(self):

class Contract(NetBoxModel):
name = models.CharField(max_length=100)
external_partie = models.ForeignKey(
to=ServiceProvider,
on_delete=models.CASCADE,
related_name='contracts',
blank=True,
null=True,
)

external_partie_object_type = models.ForeignKey(
to=ContentType, on_delete=models.CASCADE, blank=True, null=True
Expand Down
4 changes: 3 additions & 1 deletion src/netbox_contract/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ class Meta(NetBoxTable.Meta):

class ContractListTable(NetBoxTable):
name = tables.Column(linkify=True)
external_partie_object = tables.Column(linkify=True)
external_partie_object = tables.Column(verbose_name='External partie', linkify=True)
parent = tables.Column(linkify=True)
yrc = tables.Column(verbose_name='Yerly recuring costs')

class Meta(NetBoxTable.Meta):
model = Contract
Expand All @@ -111,6 +112,7 @@ class Meta(NetBoxTable.Meta):
'currency',
'accounting_dimensions',
'mrc',
'yrc',
'nrc',
'invoice_frequency',
'documents',
Expand Down
63 changes: 0 additions & 63 deletions src/netbox_contract/templates/contact_assignments_bottom.html

This file was deleted.

18 changes: 18 additions & 0 deletions src/netbox_contract/templates/netbox_contract/contract.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,38 +38,54 @@ <h5 class="card-header">Contract</h5>
<th scope="row">Internal partie</th>
<td>{{ object.internal_partie }}</td>
</tr>
{% if not 'tenant' in hidden_fields %}
<tr>
<th scope="row">Tenant</th>
<td>{{ object.tenant }}</td>
</tr>
{% endif %}
{% if not 'start_date' in hidden_fields %}
<tr>
<th scope="row">Start date</th>
<td>{{ object.start_date }}</td>
</tr>
{% endif %}
{% if not 'end_date' in hidden_fields %}
<tr>
<th scope="row">End date</th>
<td>{{ object.end_date }}</td>
</tr>
{% endif %}
{% if not 'initial_term' in hidden_fields %}
<tr>
<th scope="row">Initial term</th>
<td>{{ object.initial_term }}</td>
</tr>
{% endif %}
{% if not 'renewal_term' in hidden_fields %}
<tr>
<th scope="row">Renewal term</th>
<td>{{ object.renewal_term }}</td>
</tr>
{% endif %}
<tr>
<th scope="row">Currency</th>
<td>{{ object.currency }}</td>
</tr>
{% if not 'accounting_dimensions' in hidden_fields %}
<tr>
<th scope="row">Accounting dimensions</th>
<td>{{ object.accounting_dimensions }}</td>
</tr>
{% endif %}
<tr>
<th scope="row">Monthly recuring costs</th>
<td>{{ object.mrc }}</td>
</tr>
<tr>
<th scope="row">Yearly recuring costs</th>
<td>{{ object.yrc }}</td>
</tr>
<tr>
<th scope="row">Non recuring costs</th>
<td>{{ object.nrc }}</td>
Expand All @@ -78,12 +94,14 @@ <h5 class="card-header">Contract</h5>
<th scope="row">Invoice frequency</th>
<td>{{ object.invoice_frequency }}</td>
</tr>
{% if not 'parent' in hidden_fields %}
<tr>
<th scope="row">Parent</th>
<td>
<a href="{{ object.parent.get_absolute_url }}">{{ object.parent.name }}</a>
</td>
</tr>
{% endif %}
{% if object.documents %}
<tr>
<th scope="row">Documents</th>
Expand Down
2 changes: 2 additions & 0 deletions src/netbox_contract/templates/netbox_contract/invoice.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ <h5 class="card-header">Invoices</h5>
<th scope="row">Currency</th>
<td>{{ object.currency }}</td>
</tr>
{% if not 'accounting_dimensions' in hidden_fields %}
<tr>
<th scope="row">Accounting dimensions</th>
<td>{{ object.accounting_dimensions }}</td>
</tr>
{% endif %}
<tr>
<th scope="row">Amount</th>
<td>{{ object.amount }}</td>
Expand Down
Loading

0 comments on commit f8a8e30

Please sign in to comment.