netbox-contract 2.2.4__tar.gz → 2.2.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.
Files changed (73) hide show
  1. {netbox_contract-2.2.4/src/netbox_contract.egg-info → netbox_contract-2.2.6}/PKG-INFO +4 -3
  2. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/README.md +3 -2
  3. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/pyproject.toml +1 -1
  4. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/__init__.py +2 -1
  5. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/api/serializers.py +13 -53
  6. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/api/views.py +2 -0
  7. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/filtersets.py +47 -4
  8. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/forms.py +22 -4
  9. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/tables.py +3 -1
  10. {netbox_contract-2.2.4 → netbox_contract-2.2.6/src/netbox_contract.egg-info}/PKG-INFO +4 -3
  11. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/LICENSE +0 -0
  12. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/MANIFEST.in +0 -0
  13. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/setup.cfg +0 -0
  14. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/setup.py +0 -0
  15. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/api/__init__.py +0 -0
  16. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/api/urls.py +0 -0
  17. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/constants.py +0 -0
  18. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0001_initial.py +0 -0
  19. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0002_alter_contract_circuit_and_more.py +0 -0
  20. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0003_alter_contract_custom_field_data_and_more.py +0 -0
  21. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0004_contract_currency_invoice_currency.py +0 -0
  22. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0005_contract_accounting_dimensions_and_more.py +0 -0
  23. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0006_alter_contract_circuit.py +0 -0
  24. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0007_invoice_date.py +0 -0
  25. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0008_invoice_comments.py +0 -0
  26. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0009_contract_external_reference.py +0 -0
  27. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0010_invoice_contracts.py +0 -0
  28. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0011_auto_20230122_2112.py +0 -0
  29. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0012_remove_invoice_contract.py +0 -0
  30. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0013_contract_documents_invoice_documents.py +0 -0
  31. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0014_contract_end_date.py +0 -0
  32. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0015_contractassignement.py +0 -0
  33. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0016_contract_parent.py +0 -0
  34. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0017_alter_contract_accounting_dimensions.py +0 -0
  35. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0018_contract_external_partie_object_id_and_more.py +0 -0
  36. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0019_auto_20230924_1813.py +0 -0
  37. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0020_alter_contract_external_partie.py +0 -0
  38. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0021_alter_contract_external_partie.py +0 -0
  39. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0022_alter_contract_internal_partie_alter_contract_parent.py +0 -0
  40. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0023_rename_contractassignement_contractassignment_and_more.py +0 -0
  41. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0024_remove_contract_external_partie.py +0 -0
  42. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0025_remove_contract_circuit_and_more.py +0 -0
  43. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0026_auto_20240421_1550.py +0 -0
  44. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0027_invoiceline.py +0 -0
  45. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0028_invoiceline_accounting_dimensions.py +0 -0
  46. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0029_remove_invoiceline_accounting_dimensions_and_more.py +0 -0
  47. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0030_alter_invoiceline_accounting_dimensions.py +0 -0
  48. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0031_contract_invoice_template_invoice_template.py +0 -0
  49. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0032_alter_invoice_period_end_alter_invoice_period_start_and_more.py +0 -0
  50. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0033_remove_contract_invoice_template.py +0 -0
  51. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0034_contract_yrc_alter_contract_mrc.py +0 -0
  52. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0035_accountingdimension_status_and_more.py +0 -0
  53. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/0036_alter_invoiceline_accounting_dimensions.py +0 -0
  54. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/migrations/__init__.py +0 -0
  55. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/models.py +0 -0
  56. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/navigation.py +0 -0
  57. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/search.py +0 -0
  58. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/template_content.py +0 -0
  59. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/templates/contract_assignments_bottom.html +0 -0
  60. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/templates/contract_list_bottom.html +0 -0
  61. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/templates/netbox_contract/accountingdimension.html +0 -0
  62. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/templates/netbox_contract/contract.html +0 -0
  63. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/templates/netbox_contract/contractassignment.html +0 -0
  64. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/templates/netbox_contract/invoice.html +0 -0
  65. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/templates/netbox_contract/invoiceline.html +0 -0
  66. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/templates/netbox_contract/serviceprovider.html +0 -0
  67. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/urls.py +0 -0
  68. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract/views.py +0 -0
  69. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract.egg-info/SOURCES.txt +0 -0
  70. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract.egg-info/dependency_links.txt +0 -0
  71. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract.egg-info/not-zip-safe +0 -0
  72. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract.egg-info/requires.txt +0 -0
  73. {netbox_contract-2.2.4 → netbox_contract-2.2.6}/src/netbox_contract.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-contract
3
- Version: 2.2.4
3
+ Version: 2.2.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
@@ -62,10 +62,11 @@ PLUGINS_CONFIG = {
62
62
  "project": "",
63
63
  "cost center": ""
64
64
  },
65
- 'mandatory_contract_fields': ['accounting_dimensions'],
65
+ 'mandatory_contract_fields': [],
66
66
  'hidden_contract_fields': [],
67
- 'mandatory_invoice_fields': ['accounting_dimensions'],
67
+ 'mandatory_invoice_fields': [],
68
68
  'hidden_invoice_fields': [],
69
+ 'mandatory_dimensions': [],
69
70
  }
70
71
  }
71
72
 
@@ -46,10 +46,11 @@ PLUGINS_CONFIG = {
46
46
  "project": "",
47
47
  "cost center": ""
48
48
  },
49
- 'mandatory_contract_fields': ['accounting_dimensions'],
49
+ 'mandatory_contract_fields': [],
50
50
  'hidden_contract_fields': [],
51
- 'mandatory_invoice_fields': ['accounting_dimensions'],
51
+ 'mandatory_invoice_fields': [],
52
52
  'hidden_invoice_fields': [],
53
+ 'mandatory_dimensions': [],
53
54
  }
54
55
  }
55
56
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "netbox-contract"
3
- version = "2.2.4"
3
+ version = "2.2.6"
4
4
  authors = [
5
5
  { name="Marc Lebreuil", email="marc@famillelebreuil.net" },
6
6
  ]
@@ -5,7 +5,7 @@ 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.2.4'
8
+ version = '2.2.6'
9
9
  author = 'Marc Lebreuil'
10
10
  author_email = 'marc@famillelebreuil.net'
11
11
  base_url = 'contracts'
@@ -22,6 +22,7 @@ class ContractsConfig(PluginConfig):
22
22
  'hidden_contract_fields': [],
23
23
  'mandatory_invoice_fields': [],
24
24
  'hidden_invoice_fields': [],
25
+ 'mandatory_dimensions': [],
25
26
  }
26
27
 
27
28
 
@@ -3,9 +3,8 @@ from django.core.exceptions import ObjectDoesNotExist
3
3
  from drf_yasg.utils import swagger_serializer_method
4
4
  from netbox.api.fields import ContentTypeField, SerializedPKRelatedField
5
5
  from netbox.api.serializers import NetBoxModelSerializer, WritableNestedSerializer
6
- from netbox.constants import NESTED_SERIALIZER_PREFIX
7
6
  from rest_framework import serializers
8
- from tenancy.api.nested_serializers import NestedTenantSerializer
7
+ from tenancy.api.serializers_.tenants import TenantSerializer
9
8
  from utilities.api import get_serializer_for_model
10
9
 
11
10
  from ..models import (
@@ -18,22 +17,12 @@ from ..models import (
18
17
  )
19
18
 
20
19
 
21
- class NestedServiceProviderSerializer(WritableNestedSerializer):
22
- url = serializers.HyperlinkedIdentityField(
23
- view_name='plugins-api:netbox_contract-api:serviceprovider-detail'
24
- )
25
-
26
- class Meta:
27
- model = ServiceProvider
28
- fields = ('id', 'url', 'display', 'name')
29
-
30
-
31
20
  class NestedContractSerializer(WritableNestedSerializer):
32
21
  url = serializers.HyperlinkedIdentityField(
33
22
  view_name='plugins-api:netbox_contract-api:contract-detail'
34
23
  )
35
24
  yrc = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
36
- tenant = NestedTenantSerializer(many=False, required=False)
25
+ tenant = TenantSerializer(nested=True, required=False, allow_null=True)
37
26
  external_partie_object_type = ContentTypeField(queryset=ContentType.objects.all())
38
27
  external_partie_object = serializers.SerializerMethodField(read_only=True)
39
28
 
@@ -67,11 +56,12 @@ class NestedContractSerializer(WritableNestedSerializer):
67
56
  @swagger_serializer_method(serializer_or_field=serializers.JSONField)
68
57
  def get_external_partie_object(self, instance):
69
58
  serializer = get_serializer_for_model(
70
- instance.external_partie_object_type.model_class(),
71
- prefix=NESTED_SERIALIZER_PREFIX,
59
+ instance.external_partie_object_type.model_class()
72
60
  )
73
61
  context = {'request': self.context['request']}
74
- return serializer(instance.external_partie_object, context=context).data
62
+ return serializer(
63
+ instance.external_partie_object, nested=True, context=context
64
+ ).data
75
65
 
76
66
 
77
67
  class NestedInvoiceSerializer(WritableNestedSerializer):
@@ -85,35 +75,6 @@ class NestedInvoiceSerializer(WritableNestedSerializer):
85
75
  brief_fields = ('id', 'url', 'display', 'number')
86
76
 
87
77
 
88
- class NestedContractAssignmentSerializer(WritableNestedSerializer):
89
- url = serializers.HyperlinkedIdentityField(
90
- view_name='plugins-api:netbox_contract-api:contractassignment-detail'
91
- )
92
-
93
- class Meta:
94
- model = ContractAssignment
95
- fields = ('id', 'url', 'display', 'contract', 'content_object')
96
- brief_fields = ('id', 'url', 'display', 'contract', 'content_object')
97
-
98
-
99
- class NestedInvoicelineSerializer(WritableNestedSerializer):
100
- url = serializers.HyperlinkedIdentityField(
101
- view_name='plugins-api:netbox_contract-api:invoiceline-detail'
102
- )
103
-
104
- class Meta:
105
- model = InvoiceLine
106
- fields = ('id', 'url', 'display', 'invoice', 'accounting_dimensions', 'amount')
107
- brief_fields = (
108
- 'id',
109
- 'url',
110
- 'display',
111
- 'invoice',
112
- 'accounting_dimensions',
113
- 'amount',
114
- )
115
-
116
-
117
78
  class NestedAccountingDimensionSerializer(WritableNestedSerializer):
118
79
  url = serializers.HyperlinkedIdentityField(
119
80
  view_name='plugins-api:netbox_contract-api:accountingdimension-detail'
@@ -131,7 +92,7 @@ class ContractSerializer(NetBoxModelSerializer):
131
92
  )
132
93
  yrc = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
133
94
  parent = NestedContractSerializer(many=False, required=False)
134
- tenant = NestedTenantSerializer(many=False, required=False)
95
+ tenant = TenantSerializer(nested=True, required=False, allow_null=True)
135
96
  external_partie_object_type = ContentTypeField(queryset=ContentType.objects.all())
136
97
  external_partie_object = serializers.SerializerMethodField(read_only=True)
137
98
 
@@ -195,11 +156,12 @@ class ContractSerializer(NetBoxModelSerializer):
195
156
  @swagger_serializer_method(serializer_or_field=serializers.JSONField)
196
157
  def get_external_partie_object(self, instance):
197
158
  serializer = get_serializer_for_model(
198
- instance.external_partie_object_type.model_class(),
199
- prefix=NESTED_SERIALIZER_PREFIX,
159
+ instance.external_partie_object_type.model_class()
200
160
  )
201
161
  context = {'request': self.context['request']}
202
- return serializer(instance.external_partie_object, context=context).data
162
+ return serializer(
163
+ instance.external_partie_object, nested=True, context=context
164
+ ).data
203
165
 
204
166
 
205
167
  class InvoiceSerializer(NetBoxModelSerializer):
@@ -363,11 +325,9 @@ class ContractAssignmentSerializer(NetBoxModelSerializer):
363
325
 
364
326
  @swagger_serializer_method(serializer_or_field=serializers.JSONField)
365
327
  def get_content_object(self, instance):
366
- serializer = get_serializer_for_model(
367
- instance.content_type.model_class(), prefix=NESTED_SERIALIZER_PREFIX
368
- )
328
+ serializer = get_serializer_for_model(instance.content_type.model_class())
369
329
  context = {'request': self.context['request']}
370
- return serializer(instance.content_object, context=context).data
330
+ return serializer(instance.content_object, nested=True, context=context).data
371
331
 
372
332
 
373
333
  class InvoiceLineSerializer(NetBoxModelSerializer):
@@ -21,6 +21,7 @@ class ContractViewSet(NetBoxModelViewSet):
21
21
  )
22
22
  )
23
23
  serializer_class = ContractSerializer
24
+ filterset_class = filtersets.ContractFilterSet
24
25
 
25
26
 
26
27
  class InvoiceViewSet(NetBoxModelViewSet):
@@ -44,6 +45,7 @@ class InvoiceLineViewSet(NetBoxModelViewSet):
44
45
  'invoice', 'accounting_dimensions', 'tags'
45
46
  )
46
47
  serializer_class = InvoiceLineSerializer
48
+ filterset_class = filtersets.InvoiceLineFilterSet
47
49
 
48
50
 
49
51
  class AccountingDimensionViewSet(NetBoxModelViewSet):
@@ -1,20 +1,42 @@
1
+ import django_filters
1
2
  from django.db.models import Q
2
3
  from netbox.filtersets import NetBoxModelFilterSet
4
+ from tenancy.filtersets import TenancyFilterSet
3
5
 
4
6
  from .models import (
5
7
  AccountingDimension,
8
+ AccountingDimensionStatusChoices,
6
9
  Contract,
7
10
  ContractAssignment,
11
+ CurrencyChoices,
12
+ InternalEntityChoices,
8
13
  Invoice,
9
14
  InvoiceLine,
10
15
  ServiceProvider,
16
+ StatusChoices,
11
17
  )
12
18
 
13
19
 
14
- class ContractFilterSet(NetBoxModelFilterSet):
20
+ class ContractFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
21
+ status = django_filters.MultipleChoiceFilter(choices=StatusChoices, null_value=None)
22
+ internal_partie = django_filters.MultipleChoiceFilter(
23
+ choices=InternalEntityChoices, null_value=None
24
+ )
25
+ currency = django_filters.MultipleChoiceFilter(
26
+ choices=CurrencyChoices, null_value=None
27
+ )
28
+
15
29
  class Meta:
16
30
  model = Contract
17
- fields = ('id', 'internal_partie', 'status', 'parent')
31
+ fields = (
32
+ 'id',
33
+ 'name',
34
+ 'external_reference',
35
+ 'start_date',
36
+ 'end_date',
37
+ 'initial_term',
38
+ 'parent',
39
+ )
18
40
 
19
41
  def search(self, queryset, name, value):
20
42
  return queryset.filter(
@@ -26,9 +48,22 @@ class ContractFilterSet(NetBoxModelFilterSet):
26
48
 
27
49
 
28
50
  class InvoiceFilterSet(NetBoxModelFilterSet):
51
+ currency = django_filters.MultipleChoiceFilter(
52
+ choices=CurrencyChoices, null_value=None
53
+ )
54
+
29
55
  class Meta:
30
56
  model = Invoice
31
- fields = ('id', 'contracts')
57
+ fields = (
58
+ 'id',
59
+ 'number',
60
+ 'template',
61
+ 'date',
62
+ 'contracts',
63
+ 'period_start',
64
+ 'period_end',
65
+ 'amount',
66
+ )
32
67
 
33
68
  def search(self, queryset, name, value):
34
69
  return queryset.filter(
@@ -55,9 +90,13 @@ class ContractAssignmentFilterSet(NetBoxModelFilterSet):
55
90
 
56
91
 
57
92
  class InvoiceLineFilterSet(NetBoxModelFilterSet):
93
+ currency = django_filters.MultipleChoiceFilter(
94
+ choices=CurrencyChoices, null_value=None
95
+ )
96
+
58
97
  class Meta:
59
98
  model = InvoiceLine
60
- fields = ('id', 'invoice')
99
+ fields = ('id', 'invoice', 'accounting_dimensions')
61
100
 
62
101
  def search(self, queryset, name, value):
63
102
  return queryset.filter(
@@ -66,6 +105,10 @@ class InvoiceLineFilterSet(NetBoxModelFilterSet):
66
105
 
67
106
 
68
107
  class AccountingDimensionFilterSet(NetBoxModelFilterSet):
108
+ status = django_filters.MultipleChoiceFilter(
109
+ choices=AccountingDimensionStatusChoices, null_value=None
110
+ )
111
+
69
112
  class Meta:
70
113
  model = AccountingDimension
71
114
  fields = ('name', 'value')
@@ -2,7 +2,6 @@ from django import forms
2
2
  from django.conf import settings
3
3
  from django.contrib.contenttypes.models import ContentType
4
4
  from django.core.exceptions import ObjectDoesNotExist, ValidationError
5
- from extras.filters import TagFilter
6
5
  from netbox.forms import (
7
6
  NetBoxModelBulkEditForm,
8
7
  NetBoxModelFilterSetForm,
@@ -10,6 +9,7 @@ from netbox.forms import (
10
9
  NetBoxModelImportForm,
11
10
  )
12
11
  from tenancy.models import Tenant
12
+ from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES
13
13
  from utilities.forms.fields import (
14
14
  CommentField,
15
15
  ContentTypeChoiceField,
@@ -21,6 +21,7 @@ from utilities.forms.fields import (
21
21
  DynamicModelMultipleChoiceField,
22
22
  JSONField,
23
23
  SlugField,
24
+ TagFilterField,
24
25
  )
25
26
  from utilities.forms.widgets import DatePicker, HTMXSelect
26
27
 
@@ -161,9 +162,11 @@ class ContractFilterSetForm(NetBoxModelFilterSetForm):
161
162
 
162
163
  tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
163
164
  external_reference = forms.CharField(required=False)
164
- internal_partie = forms.CharField(required=False)
165
+ internal_partie = forms.ChoiceField(choices=InternalEntityChoices, required=False)
165
166
  status = forms.ChoiceField(choices=StatusChoices, required=False)
167
+ currency = forms.ChoiceField(choices=CurrencyChoices, required=False)
166
168
  parent = DynamicModelChoiceField(queryset=Contract.objects.all(), required=False)
169
+ tag = TagFilterField(model)
167
170
 
168
171
 
169
172
  class ContractCSVForm(NetBoxModelImportForm):
@@ -359,9 +362,15 @@ class InvoiceForm(NetBoxModelForm):
359
362
 
360
363
  class InvoiceFilterSetForm(NetBoxModelFilterSetForm):
361
364
  model = Invoice
365
+ number = forms.CharField(required=False)
366
+ template = forms.NullBooleanField(
367
+ required=False, widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES)
368
+ )
369
+ currency = forms.ChoiceField(choices=CurrencyChoices, required=False)
362
370
  contracts = DynamicModelMultipleChoiceField(
363
371
  queryset=Contract.objects.all(), required=False
364
372
  )
373
+ tag = TagFilterField(model)
365
374
 
366
375
 
367
376
  class InvoiceCSVForm(NetBoxModelImportForm):
@@ -425,7 +434,8 @@ class ServiceProviderForm(NetBoxModelForm):
425
434
 
426
435
  class ServiceProviderFilterSetForm(NetBoxModelFilterSetForm):
427
436
  model = ServiceProvider
428
- tag = TagFilter()
437
+ name = forms.CharField(required=False)
438
+ tag = TagFilterField(model)
429
439
 
430
440
 
431
441
  class ServiceProviderCSVForm(NetBoxModelImportForm):
@@ -499,6 +509,12 @@ class InvoiceLineForm(NetBoxModelForm):
499
509
  else:
500
510
  dimensions_names.append(dimension.name)
501
511
 
512
+ # Make sure mandatory dimensions are present
513
+ mandatory_dimensions = plugin_settings.get('mandatory_dimensions')
514
+ for dimension in mandatory_dimensions:
515
+ if dimension not in dimensions_names:
516
+ raise ValidationError(f'dimension {dimension} missing')
517
+
502
518
  class Meta:
503
519
  model = InvoiceLine
504
520
  fields = [
@@ -514,9 +530,11 @@ class InvoiceLineForm(NetBoxModelForm):
514
530
  class InvoiceLineFilterSetForm(NetBoxModelFilterSetForm):
515
531
  model = InvoiceLine
516
532
  invoice = DynamicModelChoiceField(queryset=Invoice.objects.all(), required=False)
517
- accounting_dimensions = DynamicModelChoiceField(
533
+ accounting_dimensions = DynamicModelMultipleChoiceField(
518
534
  queryset=AccountingDimension.objects.all(), required=False
519
535
  )
536
+ currency = forms.ChoiceField(choices=CurrencyChoices, required=False)
537
+ tag = TagFilterField(model)
520
538
 
521
539
 
522
540
  class InvoiceLineImportForm(NetBoxModelImportForm):
@@ -200,7 +200,9 @@ class ServiceProviderListTable(NetBoxTable):
200
200
 
201
201
  class InvoiceLineListTable(NetBoxTable):
202
202
  invoice = tables.Column(linkify=True)
203
- accounting_dimensions = tables.ManyToManyColumn(linkify=True)
203
+ accounting_dimensions = tables.ManyToManyColumn(
204
+ linkify=True, filter=lambda qs: qs.order_by('name')
205
+ )
204
206
 
205
207
  class Meta(NetBoxTable.Meta):
206
208
  model = InvoiceLine
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-contract
3
- Version: 2.2.4
3
+ Version: 2.2.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
@@ -62,10 +62,11 @@ PLUGINS_CONFIG = {
62
62
  "project": "",
63
63
  "cost center": ""
64
64
  },
65
- 'mandatory_contract_fields': ['accounting_dimensions'],
65
+ 'mandatory_contract_fields': [],
66
66
  'hidden_contract_fields': [],
67
- 'mandatory_invoice_fields': ['accounting_dimensions'],
67
+ 'mandatory_invoice_fields': [],
68
68
  'hidden_invoice_fields': [],
69
+ 'mandatory_dimensions': [],
69
70
  }
70
71
  }
71
72
 
File without changes