netbox-contract 2.4.4__tar.gz → 2.4.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {netbox_contract-2.4.4/netbox_contract.egg-info → netbox_contract-2.4.6}/PKG-INFO +7 -1
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/README.md +6 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/__init__.py +3 -2
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/api/serializers.py +15 -4
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/forms.py +8 -4
- netbox_contract-2.4.6/netbox_contract/template_content.py +45 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/netbox_contract/contract.html +1 -1
- netbox_contract-2.4.6/netbox_contract/templates/netbox_contract/object_contracts.html +7 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/views.py +65 -1
- {netbox_contract-2.4.4 → netbox_contract-2.4.6/netbox_contract.egg-info}/PKG-INFO +7 -1
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract.egg-info/SOURCES.txt +1 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/pyproject.toml +1 -1
- netbox_contract-2.4.4/netbox_contract/template_content.py +0 -32
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/CONTRIBUTING.md +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/LICENSE +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/MANIFEST.in +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/docs/img/accounting_dimensions.png +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/docs/img/contract.png +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/docs/img/contract_linked_objects.png +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/docs/img/invoice.png +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/docs/img/invoice_line.png +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/docs/img/invoice_linked_objects.png +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/api/__init__.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/api/urls.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/api/views.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/constants.py +1 -1
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/filtersets.py +3 -3
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/locale/en/LC_MESSAGES/django.mo +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/locale/en/LC_MESSAGES/django.po +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/locale/fr/LC_MESSAGES/django.mo +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/locale/fr/LC_MESSAGES/django.po +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0001_initial.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0002_alter_contract_circuit_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0003_alter_contract_custom_field_data_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0004_contract_currency_invoice_currency.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0005_contract_accounting_dimensions_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0006_alter_contract_circuit.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0007_invoice_date.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0008_invoice_comments.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0009_contract_external_reference.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0010_invoice_contracts.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0011_auto_20230122_2112.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0012_remove_invoice_contract.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0013_contract_documents_invoice_documents.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0014_contract_end_date.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0015_contractassignement.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0016_contract_parent.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0017_alter_contract_accounting_dimensions.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0018_contract_external_partie_object_id_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0019_auto_20230924_1813.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0020_alter_contract_external_partie.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0021_alter_contract_external_partie.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0022_alter_contract_internal_partie_alter_contract_parent.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0023_rename_contractassignement_contractassignment_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0024_remove_contract_external_partie.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0025_remove_contract_circuit_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0026_auto_20240421_1550.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0027_invoiceline.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0028_invoiceline_accounting_dimensions.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0029_remove_invoiceline_accounting_dimensions_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0030_alter_invoiceline_accounting_dimensions.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0031_contract_invoice_template_invoice_template.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0032_alter_invoice_period_end_alter_invoice_period_start_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0033_remove_contract_invoice_template.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0034_contract_yrc_alter_contract_mrc.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0035_accountingdimension_status_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0036_alter_invoiceline_accounting_dimensions.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0037_contract_notice_period_alter_contract_currency_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0038_alter_accountingdimension_options_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0039_alter_accountingdimension_status_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0040_alter_contract_currency_alter_invoice_currency_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0041_contracttype_contract_contract_type.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0042_remove_contract_netbox_cont_externa_6343fb_idx_and_more.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0043_invoice_status.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/__init__.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/models.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/navigation.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/search.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/tables.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/contract_assignments_bottom.html +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/contract_list_bottom.html +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/netbox_contract/accountingdimension.html +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/netbox_contract/contractassignment.html +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/netbox_contract/contracttype.html +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/netbox_contract/invoice.html +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/netbox_contract/invoiceline.html +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/netbox_contract/serviceprovider.html +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/urls.py +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract.egg-info/dependency_links.txt +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract.egg-info/requires.txt +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract.egg-info/top_level.txt +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/setup.cfg +0 -0
- {netbox_contract-2.4.4 → netbox_contract-2.4.6}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: netbox-contract
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.6
|
|
4
4
|
Summary: Contract management plugin for Netbox
|
|
5
5
|
Author-email: Marc Lebreuil <marc@famillelebreuil.net>
|
|
6
6
|
Project-URL: Homepage, https://github.com/mlebreuil/netbox-contract
|
|
@@ -49,6 +49,7 @@ Accounting dimensions can be linked with invoice lines.
|
|
|
49
49
|
| 4.2 | 2.3 |
|
|
50
50
|
| 4.3 | 2.4 |
|
|
51
51
|
| 4.4 | 2.4 |
|
|
52
|
+
| 4.5 | 2.4 |
|
|
52
53
|
|
|
53
54
|
## Installing
|
|
54
55
|
|
|
@@ -101,12 +102,17 @@ PLUGINS_CONFIG = {
|
|
|
101
102
|
'ipam.ipaddress',
|
|
102
103
|
'ipam.prefix',
|
|
103
104
|
],
|
|
105
|
+
'contract_assignments_display': 'both', # options: 'tab', 'inline', 'both'
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
```
|
|
108
110
|
|
|
109
111
|
* top_level_menu : If "Contracts" appears under the "Plugins" menu item or on its own
|
|
112
|
+
* contract_assignments_display:
|
|
113
|
+
* `'tab'` - only the Contracts view tab is visible on the related object page.
|
|
114
|
+
* `'inline'` - only the inline contract assignments table is shown in object detail; the Contracts tab is hidden.
|
|
115
|
+
* `'both'` - both tab and inline table are shown (default behavior).
|
|
110
116
|
* default_accounting_dimensions: The accounting dimensions which will appear in the field' background when empty. Note that accounting dimensions are now managed as individual objects. The use of this field is deprecated.
|
|
111
117
|
* 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.
|
|
112
118
|
* hidden_contract_fields, hidden_invoice_fields: List of fields to be hidden. Fields should not be required to be hidden.
|
|
@@ -22,6 +22,7 @@ Accounting dimensions can be linked with invoice lines.
|
|
|
22
22
|
| 4.2 | 2.3 |
|
|
23
23
|
| 4.3 | 2.4 |
|
|
24
24
|
| 4.4 | 2.4 |
|
|
25
|
+
| 4.5 | 2.4 |
|
|
25
26
|
|
|
26
27
|
## Installing
|
|
27
28
|
|
|
@@ -74,12 +75,17 @@ PLUGINS_CONFIG = {
|
|
|
74
75
|
'ipam.ipaddress',
|
|
75
76
|
'ipam.prefix',
|
|
76
77
|
],
|
|
78
|
+
'contract_assignments_display': 'both', # options: 'tab', 'inline', 'both'
|
|
77
79
|
}
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
```
|
|
81
83
|
|
|
82
84
|
* top_level_menu : If "Contracts" appears under the "Plugins" menu item or on its own
|
|
85
|
+
* contract_assignments_display:
|
|
86
|
+
* `'tab'` - only the Contracts view tab is visible on the related object page.
|
|
87
|
+
* `'inline'` - only the inline contract assignments table is shown in object detail; the Contracts tab is hidden.
|
|
88
|
+
* `'both'` - both tab and inline table are shown (default behavior).
|
|
83
89
|
* default_accounting_dimensions: The accounting dimensions which will appear in the field' background when empty. Note that accounting dimensions are now managed as individual objects. The use of this field is deprecated.
|
|
84
90
|
* 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.
|
|
85
91
|
* hidden_contract_fields, hidden_invoice_fields: List of fields to be hidden. Fields should not be required to be hidden.
|
|
@@ -5,11 +5,11 @@ class ContractsConfig(PluginConfig):
|
|
|
5
5
|
name = 'netbox_contract'
|
|
6
6
|
verbose_name = 'Netbox contract'
|
|
7
7
|
description = 'Contract management plugin for Netbox'
|
|
8
|
-
version = '2.4.
|
|
8
|
+
version = '2.4.6'
|
|
9
9
|
author = 'Marc Lebreuil'
|
|
10
10
|
author_email = 'marc@famillelebreuil.net'
|
|
11
11
|
base_url = 'contracts'
|
|
12
|
-
min_version = '4.
|
|
12
|
+
min_version = '4.5.0'
|
|
13
13
|
required_settings = []
|
|
14
14
|
default_settings = {
|
|
15
15
|
'top_level_menu': False,
|
|
@@ -27,6 +27,7 @@ class ContractsConfig(PluginConfig):
|
|
|
27
27
|
'virtualization.virtualmachine',
|
|
28
28
|
'virtualization.cluster',
|
|
29
29
|
],
|
|
30
|
+
'contract_assignments_display': 'both', # options: 'tab', 'inline', 'both'
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
|
|
@@ -46,12 +46,14 @@ class NestedContractSerializer(WritableNestedSerializer):
|
|
|
46
46
|
'end_date',
|
|
47
47
|
'initial_term',
|
|
48
48
|
'renewal_term',
|
|
49
|
+
'notice_period',
|
|
49
50
|
'currency',
|
|
50
51
|
'mrc',
|
|
51
52
|
'yrc',
|
|
52
53
|
'nrc',
|
|
53
54
|
'invoice_frequency',
|
|
54
55
|
'comments',
|
|
56
|
+
'documents',
|
|
55
57
|
)
|
|
56
58
|
|
|
57
59
|
@swagger_serializer_method(serializer_or_field=serializers.JSONField)
|
|
@@ -98,6 +100,7 @@ class ContractTypeSerializer(NetBoxModelSerializer):
|
|
|
98
100
|
'display',
|
|
99
101
|
'name',
|
|
100
102
|
'description',
|
|
103
|
+
'color',
|
|
101
104
|
'tags',
|
|
102
105
|
'custom_fields',
|
|
103
106
|
'created',
|
|
@@ -136,12 +139,14 @@ class ContractSerializer(NetBoxModelSerializer):
|
|
|
136
139
|
'end_date',
|
|
137
140
|
'initial_term',
|
|
138
141
|
'renewal_term',
|
|
142
|
+
'notice_period',
|
|
139
143
|
'currency',
|
|
140
144
|
'mrc',
|
|
141
145
|
'yrc',
|
|
142
146
|
'nrc',
|
|
143
147
|
'invoice_frequency',
|
|
144
148
|
'comments',
|
|
149
|
+
'documents',
|
|
145
150
|
'parent',
|
|
146
151
|
'tags',
|
|
147
152
|
'custom_fields',
|
|
@@ -205,12 +210,14 @@ class InvoiceSerializer(NetBoxModelSerializer):
|
|
|
205
210
|
'number',
|
|
206
211
|
'date',
|
|
207
212
|
'template',
|
|
213
|
+
'status',
|
|
208
214
|
'contracts',
|
|
209
215
|
'period_start',
|
|
210
216
|
'period_end',
|
|
211
217
|
'currency',
|
|
212
218
|
'amount',
|
|
213
219
|
'comments',
|
|
220
|
+
'documents',
|
|
214
221
|
'tags',
|
|
215
222
|
'custom_fields',
|
|
216
223
|
'created',
|
|
@@ -310,13 +317,15 @@ class ServiceProviderSerializer(NetBoxModelSerializer):
|
|
|
310
317
|
'url',
|
|
311
318
|
'display',
|
|
312
319
|
'name',
|
|
320
|
+
'slug',
|
|
313
321
|
'portal_url',
|
|
322
|
+
'comments',
|
|
314
323
|
'tags',
|
|
315
324
|
'custom_fields',
|
|
316
325
|
'created',
|
|
317
326
|
'last_updated',
|
|
318
327
|
)
|
|
319
|
-
brief_fields = ('id', 'url', 'display', 'name')
|
|
328
|
+
brief_fields = ('id', 'url', 'display', 'name', 'slug')
|
|
320
329
|
|
|
321
330
|
|
|
322
331
|
class ContractAssignmentSerializer(NetBoxModelSerializer):
|
|
@@ -337,10 +346,12 @@ class ContractAssignmentSerializer(NetBoxModelSerializer):
|
|
|
337
346
|
'object_id',
|
|
338
347
|
'content_object',
|
|
339
348
|
'contract',
|
|
349
|
+
'tags',
|
|
350
|
+
'custom_fields',
|
|
340
351
|
'created',
|
|
341
352
|
'last_updated',
|
|
342
353
|
)
|
|
343
|
-
brief_fields = ('id', 'url', 'display', 'content_object', 'contract')
|
|
354
|
+
brief_fields = ('id', 'url', 'display', 'content_object', 'contract', 'tags', 'custom_fields')
|
|
344
355
|
|
|
345
356
|
@swagger_serializer_method(serializer_or_field=serializers.JSONField)
|
|
346
357
|
def get_content_object(self, instance):
|
|
@@ -394,8 +405,7 @@ class InvoiceLineSerializer(NetBoxModelSerializer):
|
|
|
394
405
|
for dimension in accounting_dimensions:
|
|
395
406
|
if dimension.name in dimensions_names:
|
|
396
407
|
raise serializers.ValidationError('duplicate accounting dimension')
|
|
397
|
-
|
|
398
|
-
dimensions_names.append(dimension.name)
|
|
408
|
+
dimensions_names.append(dimension.name)
|
|
399
409
|
return data
|
|
400
410
|
|
|
401
411
|
|
|
@@ -412,6 +422,7 @@ class AccountingDimensionSerializer(NetBoxModelSerializer):
|
|
|
412
422
|
'display',
|
|
413
423
|
'name',
|
|
414
424
|
'value',
|
|
425
|
+
'status',
|
|
415
426
|
'comments',
|
|
416
427
|
'tags',
|
|
417
428
|
'custom_fields',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from circuits.models import Provider
|
|
1
2
|
from django import forms
|
|
2
3
|
from django.conf import settings
|
|
3
4
|
from django.contrib.contenttypes.models import ContentType
|
|
@@ -11,7 +12,6 @@ from netbox.forms import (
|
|
|
11
12
|
)
|
|
12
13
|
from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
|
|
13
14
|
from tenancy.models import Tenant
|
|
14
|
-
from circuits.models import Provider
|
|
15
15
|
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, get_field_value
|
|
16
16
|
from utilities.forms.fields import (
|
|
17
17
|
ColorField,
|
|
@@ -40,9 +40,9 @@ from .models import (
|
|
|
40
40
|
InternalEntityChoices,
|
|
41
41
|
Invoice,
|
|
42
42
|
InvoiceLine,
|
|
43
|
+
InvoiceStatusChoices,
|
|
43
44
|
ServiceProvider,
|
|
44
45
|
StatusChoices,
|
|
45
|
-
InvoiceStatusChoices,
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
plugin_settings = settings.PLUGINS_CONFIG['netbox_contract']
|
|
@@ -61,6 +61,11 @@ class ContractForm(NetBoxModelForm):
|
|
|
61
61
|
label=_('External party object type'),
|
|
62
62
|
)
|
|
63
63
|
external_party_object = forms.ModelChoiceField(queryset=None, label=_('External party object'))
|
|
64
|
+
internal_party = internal_party = forms.ChoiceField(
|
|
65
|
+
choices=InternalEntityChoices,
|
|
66
|
+
required=True,
|
|
67
|
+
label=_('Internal party')
|
|
68
|
+
)
|
|
64
69
|
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False, selector=True, label=_('Tenant'))
|
|
65
70
|
parent = DynamicModelChoiceField(
|
|
66
71
|
queryset=Contract.objects.all(),
|
|
@@ -683,8 +688,7 @@ class InvoiceLineForm(NetBoxModelForm):
|
|
|
683
688
|
for dimension in accounting_dimensions:
|
|
684
689
|
if dimension.name in dimensions_names:
|
|
685
690
|
raise ValidationError('duplicate accounting dimension')
|
|
686
|
-
|
|
687
|
-
dimensions_names.append(dimension.name)
|
|
691
|
+
dimensions_names.append(dimension.name)
|
|
688
692
|
|
|
689
693
|
# Make sure mandatory dimensions are present
|
|
690
694
|
mandatory_dimensions = plugin_settings.get('mandatory_dimensions')
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from django.conf import settings
|
|
2
|
+
from django.contrib.contenttypes.models import ContentType
|
|
3
|
+
from netbox.plugins import PluginTemplateExtension
|
|
4
|
+
|
|
5
|
+
from . import tables
|
|
6
|
+
from .constants import ASSIGNEMENT_TYPES
|
|
7
|
+
from .models import ContractAssignment
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ObjectContractAssignments(PluginTemplateExtension):
|
|
11
|
+
models = ASSIGNEMENT_TYPES
|
|
12
|
+
|
|
13
|
+
def full_width_page(self):
|
|
14
|
+
display = settings.PLUGINS_CONFIG.get('netbox_contract', {}).get(
|
|
15
|
+
'contract_assignments_display', 'both'
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# 'tab' means only the contract tab is shown; inline table stays hidden.
|
|
19
|
+
if display == 'tab':
|
|
20
|
+
return ''
|
|
21
|
+
|
|
22
|
+
# 'inline' or 'both' renders inline table; the tab is still built via ObjectChildrenView.
|
|
23
|
+
if display in ('inline', 'both'):
|
|
24
|
+
object = self.context['object']
|
|
25
|
+
object_type = ContentType.objects.get_for_model(object)
|
|
26
|
+
|
|
27
|
+
contract_assignments = ContractAssignment.objects.filter(
|
|
28
|
+
content_type__pk=object_type.id, object_id=object.id
|
|
29
|
+
)
|
|
30
|
+
assignments_table = tables.ContractAssignmentObjectTable(contract_assignments)
|
|
31
|
+
assignments_table.configure(self.context['request'])
|
|
32
|
+
|
|
33
|
+
return self.render(
|
|
34
|
+
'contract_assignments_bottom.html',
|
|
35
|
+
extra_context={
|
|
36
|
+
'assignments_table': assignments_table,
|
|
37
|
+
},
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
return ''
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
template_extensions = [
|
|
44
|
+
ObjectContractAssignments,
|
|
45
|
+
]
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
from datetime import date, timedelta
|
|
2
2
|
|
|
3
3
|
from dateutil.relativedelta import relativedelta
|
|
4
|
+
from django.apps import apps
|
|
4
5
|
from django.conf import settings
|
|
5
6
|
from django.contrib.contenttypes.models import ContentType
|
|
6
7
|
from django.core.exceptions import ObjectDoesNotExist
|
|
7
8
|
from django.db.models import Case, F, When
|
|
8
9
|
from django.db.models.functions import Round
|
|
9
10
|
from django.shortcuts import get_object_or_404, render
|
|
11
|
+
from django.utils.translation import gettext_lazy as _
|
|
12
|
+
from netbox.object_actions import *
|
|
10
13
|
from netbox.views import generic
|
|
11
14
|
from netbox.views.generic.utils import get_prerequisite_model
|
|
12
15
|
from utilities.forms import restrict_form_fields
|
|
13
16
|
from utilities.querydict import normalize_querydict
|
|
14
|
-
from utilities.views import register_model_view
|
|
17
|
+
from utilities.views import ViewTab, get_action_url, register_model_view
|
|
15
18
|
|
|
16
19
|
from . import filtersets, forms, tables
|
|
20
|
+
from .constants import ASSIGNEMENT_TYPES
|
|
17
21
|
from .models import (
|
|
18
22
|
AccountingDimension,
|
|
19
23
|
Contract,
|
|
@@ -182,6 +186,66 @@ class ContractAssignmentBulkDeleteView(generic.BulkDeleteView):
|
|
|
182
186
|
filterset = filtersets.ContractAssignmentFilterSet
|
|
183
187
|
table = tables.ContractAssignmentListTable
|
|
184
188
|
|
|
189
|
+
|
|
190
|
+
class AddContractAssignment(AddObject):
|
|
191
|
+
label = _('Add contract')
|
|
192
|
+
|
|
193
|
+
@classmethod
|
|
194
|
+
def get_url(cls, obj):
|
|
195
|
+
# obj will be the parent object in the custom template (ObjectChildren hook)
|
|
196
|
+
if hasattr(obj, 'pk') and hasattr(obj, '_meta') and obj.pk:
|
|
197
|
+
parent = obj
|
|
198
|
+
parent_ct = ContentType.objects.get_for_model(parent)
|
|
199
|
+
base_url = get_action_url(ContractAssignment, action='add')
|
|
200
|
+
return (
|
|
201
|
+
f"{base_url}?content_type={parent_ct.pk}"
|
|
202
|
+
f"&object_id={parent.pk}&return_url={parent.get_absolute_url()}"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# fallback for a class value (if called as model class)
|
|
206
|
+
return get_action_url(ContractAssignment, action='add')
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class BaseObjectContractAssignmentView(generic.ObjectChildrenView):
|
|
210
|
+
child_model = ContractAssignment
|
|
211
|
+
table = tables.ContractAssignmentObjectTable
|
|
212
|
+
filterset = filtersets.ContractAssignmentFilterSet
|
|
213
|
+
template_name = 'netbox_contract/object_contracts.html'
|
|
214
|
+
actions = (AddContractAssignment, BulkEdit, BulkDelete)
|
|
215
|
+
tab = ViewTab(
|
|
216
|
+
label=_('Contracts'),
|
|
217
|
+
visible=lambda obj: plugin_settings.get('contract_assignments_display', 'both') != 'inline',
|
|
218
|
+
badge=lambda obj: ContractAssignment.objects.filter(
|
|
219
|
+
content_type=ContentType.objects.get_for_model(obj), object_id=obj.id
|
|
220
|
+
).count(),
|
|
221
|
+
permission='contracts.view_contractassignment',
|
|
222
|
+
weight=550,
|
|
223
|
+
hide_if_empty=True,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def get_children(self, request, parent):
|
|
227
|
+
object_type = ContentType.objects.get_for_model(parent)
|
|
228
|
+
contract_assignments = ContractAssignment.objects.filter(
|
|
229
|
+
content_type__pk=object_type.id, object_id=parent.id
|
|
230
|
+
)
|
|
231
|
+
return contract_assignments
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
# Dynamically register the view for all supported models
|
|
235
|
+
for model_string in ASSIGNEMENT_TYPES:
|
|
236
|
+
app_label, model_name = model_string.split('.')
|
|
237
|
+
model = apps.get_model(app_label, model_name)
|
|
238
|
+
|
|
239
|
+
class_name = f"{model_name.title()}ContractAssignmentView"
|
|
240
|
+
attrs = {
|
|
241
|
+
'queryset': model.objects.all(),
|
|
242
|
+
'viewname': f'netbox_contract:{model_name}_contracts',
|
|
243
|
+
}
|
|
244
|
+
view_class = type(class_name, (BaseObjectContractAssignmentView,), attrs)
|
|
245
|
+
|
|
246
|
+
register_model_view(model, 'contracts', path='contracts')(view_class)
|
|
247
|
+
|
|
248
|
+
|
|
185
249
|
# Contract views
|
|
186
250
|
|
|
187
251
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: netbox-contract
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.6
|
|
4
4
|
Summary: Contract management plugin for Netbox
|
|
5
5
|
Author-email: Marc Lebreuil <marc@famillelebreuil.net>
|
|
6
6
|
Project-URL: Homepage, https://github.com/mlebreuil/netbox-contract
|
|
@@ -49,6 +49,7 @@ Accounting dimensions can be linked with invoice lines.
|
|
|
49
49
|
| 4.2 | 2.3 |
|
|
50
50
|
| 4.3 | 2.4 |
|
|
51
51
|
| 4.4 | 2.4 |
|
|
52
|
+
| 4.5 | 2.4 |
|
|
52
53
|
|
|
53
54
|
## Installing
|
|
54
55
|
|
|
@@ -101,12 +102,17 @@ PLUGINS_CONFIG = {
|
|
|
101
102
|
'ipam.ipaddress',
|
|
102
103
|
'ipam.prefix',
|
|
103
104
|
],
|
|
105
|
+
'contract_assignments_display': 'both', # options: 'tab', 'inline', 'both'
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
```
|
|
108
110
|
|
|
109
111
|
* top_level_menu : If "Contracts" appears under the "Plugins" menu item or on its own
|
|
112
|
+
* contract_assignments_display:
|
|
113
|
+
* `'tab'` - only the Contracts view tab is visible on the related object page.
|
|
114
|
+
* `'inline'` - only the inline contract assignments table is shown in object detail; the Contracts tab is hidden.
|
|
115
|
+
* `'both'` - both tab and inline table are shown (default behavior).
|
|
110
116
|
* default_accounting_dimensions: The accounting dimensions which will appear in the field' background when empty. Note that accounting dimensions are now managed as individual objects. The use of this field is deprecated.
|
|
111
117
|
* 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.
|
|
112
118
|
* hidden_contract_fields, hidden_invoice_fields: List of fields to be hidden. Fields should not be required to be hidden.
|
|
@@ -86,4 +86,5 @@ netbox_contract/templates/netbox_contract/contractassignment.html
|
|
|
86
86
|
netbox_contract/templates/netbox_contract/contracttype.html
|
|
87
87
|
netbox_contract/templates/netbox_contract/invoice.html
|
|
88
88
|
netbox_contract/templates/netbox_contract/invoiceline.html
|
|
89
|
+
netbox_contract/templates/netbox_contract/object_contracts.html
|
|
89
90
|
netbox_contract/templates/netbox_contract/serviceprovider.html
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from django.contrib.contenttypes.models import ContentType
|
|
2
|
-
from netbox.plugins import PluginTemplateExtension
|
|
3
|
-
|
|
4
|
-
from . import tables
|
|
5
|
-
from .models import ContractAssignment
|
|
6
|
-
from .constants import ASSIGNEMENT_TYPES
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class ObjectContractAssignments(PluginTemplateExtension):
|
|
10
|
-
models = ASSIGNEMENT_TYPES
|
|
11
|
-
|
|
12
|
-
def full_width_page(self):
|
|
13
|
-
object = self.context['object']
|
|
14
|
-
object_type = ContentType.objects.get_for_model(object)
|
|
15
|
-
|
|
16
|
-
contract_assignments = ContractAssignment.objects.filter(
|
|
17
|
-
content_type__pk=object_type.id, object_id=object.id
|
|
18
|
-
)
|
|
19
|
-
assignments_table = tables.ContractAssignmentObjectTable(contract_assignments)
|
|
20
|
-
assignments_table.configure(self.context['request'])
|
|
21
|
-
|
|
22
|
-
return self.render(
|
|
23
|
-
'contract_assignments_bottom.html',
|
|
24
|
-
extra_context={
|
|
25
|
-
'assignments_table': assignments_table,
|
|
26
|
-
},
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
template_extensions = [
|
|
31
|
-
ObjectContractAssignments,
|
|
32
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import django_filters
|
|
2
|
-
from
|
|
2
|
+
from circuits.models import Provider
|
|
3
3
|
from django.contrib.contenttypes.models import ContentType
|
|
4
|
+
from django.db.models import Q
|
|
4
5
|
from netbox.filtersets import NetBoxModelFilterSet
|
|
5
6
|
from tenancy.filtersets import ContactModelFilterSet, TenancyFilterSet
|
|
6
|
-
from circuits.models import Provider
|
|
7
7
|
|
|
8
8
|
from .models import (
|
|
9
9
|
AccountingDimension,
|
|
@@ -15,9 +15,9 @@ from .models import (
|
|
|
15
15
|
InternalEntityChoices,
|
|
16
16
|
Invoice,
|
|
17
17
|
InvoiceLine,
|
|
18
|
+
InvoiceStatusChoices,
|
|
18
19
|
ServiceProvider,
|
|
19
20
|
StatusChoices,
|
|
20
|
-
InvoiceStatusChoices,
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/locale/en/LC_MESSAGES/django.mo
RENAMED
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/locale/en/LC_MESSAGES/django.po
RENAMED
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/locale/fr/LC_MESSAGES/django.mo
RENAMED
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/locale/fr/LC_MESSAGES/django.po
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0007_invoice_date.py
RENAMED
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0008_invoice_comments.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0010_invoice_contracts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0014_contract_end_date.py
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0016_contract_parent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0027_invoiceline.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/migrations/0043_invoice_status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract/templates/contract_list_bottom.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_contract-2.4.4 → netbox_contract-2.4.6}/netbox_contract.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|