netbox-contract 2.3.1__tar.gz → 2.3.2__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.3.1 → netbox_contract-2.3.2}/CONTRIBUTING.md +17 -13
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/MANIFEST.in +2 -2
- {netbox_contract-2.3.1/src/netbox_contract.egg-info → netbox_contract-2.3.2}/PKG-INFO +7 -7
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/README.md +6 -6
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/__init__.py +1 -1
- netbox_contract-2.3.2/netbox_contract/constants.py +13 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/forms.py +38 -11
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0019_auto_20230924_1813.py +1 -1
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0026_auto_20240421_1550.py +1 -1
- netbox_contract-2.3.2/netbox_contract/migrations/0040_alter_contract_currency_alter_invoice_currency_and_more.py +28 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/models.py +14 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/tables.py +11 -3
- netbox_contract-2.3.2/netbox_contract/tests/custom.py +18 -0
- netbox_contract-2.3.2/netbox_contract/tests/test_views.py +449 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/urls.py +16 -6
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/views.py +20 -6
- {netbox_contract-2.3.1 → netbox_contract-2.3.2/netbox_contract.egg-info}/PKG-INFO +7 -7
- netbox_contract-2.3.2/netbox_contract.egg-info/SOURCES.txt +84 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/pyproject.toml +8 -19
- netbox_contract-2.3.1/src/netbox_contract/constants.py +0 -6
- netbox_contract-2.3.1/src/netbox_contract.egg-info/SOURCES.txt +0 -83
- netbox_contract-2.3.1/src/netbox_contract.egg-info/not-zip-safe +0 -1
- netbox_contract-2.3.1/tests/test_netbox_contract.py +0 -5
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/LICENSE +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/docs/img/accounting_dimensions.png +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/docs/img/contract.png +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/docs/img/contract_linked_objects.png +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/docs/img/invoice.png +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/docs/img/invoice_line.png +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/docs/img/invoice_linked_objects.png +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/api/__init__.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/api/serializers.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/api/urls.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/api/views.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/filtersets.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0001_initial.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0002_alter_contract_circuit_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0003_alter_contract_custom_field_data_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0004_contract_currency_invoice_currency.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0005_contract_accounting_dimensions_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0006_alter_contract_circuit.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0007_invoice_date.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0008_invoice_comments.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0009_contract_external_reference.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0010_invoice_contracts.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0011_auto_20230122_2112.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0012_remove_invoice_contract.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0013_contract_documents_invoice_documents.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0014_contract_end_date.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0015_contractassignement.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0016_contract_parent.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0017_alter_contract_accounting_dimensions.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0018_contract_external_partie_object_id_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0020_alter_contract_external_partie.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0021_alter_contract_external_partie.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0022_alter_contract_internal_partie_alter_contract_parent.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0023_rename_contractassignement_contractassignment_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0024_remove_contract_external_partie.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0025_remove_contract_circuit_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0027_invoiceline.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0028_invoiceline_accounting_dimensions.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0029_remove_invoiceline_accounting_dimensions_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0030_alter_invoiceline_accounting_dimensions.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0031_contract_invoice_template_invoice_template.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0032_alter_invoice_period_end_alter_invoice_period_start_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0033_remove_contract_invoice_template.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0034_contract_yrc_alter_contract_mrc.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0035_accountingdimension_status_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0036_alter_invoiceline_accounting_dimensions.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0037_contract_notice_period_alter_contract_currency_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0038_alter_accountingdimension_options_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/0039_alter_accountingdimension_status_and_more.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/migrations/__init__.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/navigation.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/search.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/template_content.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/templates/contract_assignments_bottom.html +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/templates/contract_list_bottom.html +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/templates/netbox_contract/accountingdimension.html +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/templates/netbox_contract/contract.html +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/templates/netbox_contract/contractassignment.html +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/templates/netbox_contract/invoice.html +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/templates/netbox_contract/invoiceline.html +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract/templates/netbox_contract/serviceprovider.html +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2/netbox_contract}/tests/__init__.py +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract.egg-info/dependency_links.txt +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract.egg-info/requires.txt +0 -0
- {netbox_contract-2.3.1/src → netbox_contract-2.3.2}/netbox_contract.egg-info/top_level.txt +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/setup.cfg +0 -0
- {netbox_contract-2.3.1 → netbox_contract-2.3.2}/setup.py +0 -0
|
@@ -20,20 +20,18 @@ and "help wanted" is open to whoever wants to implement it.
|
|
|
20
20
|
|
|
21
21
|
## Coding conventions
|
|
22
22
|
|
|
23
|
-
Netbox [Style Guide](https://docs
|
|
24
|
-
Django [Coding style](https://docs.djangoproject.com/en/
|
|
23
|
+
Netbox [Style Guide](https://netboxlabs.com/docs/netbox/en/stable/development/style-guide/)
|
|
24
|
+
Django [Coding style](https://docs.djangoproject.com/en/stable/internals/contributing/writing-code/coding-style/)
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
All files will be formated using the [black](https://black.readthedocs.io/en/stable/) auto-formatter.
|
|
28
|
-
Configuration is stored in pyproject.toml
|
|
26
|
+
## linting
|
|
29
27
|
|
|
30
|
-
[
|
|
28
|
+
The [ruff](https://docs.astral.sh/ruff/) linter is used to enforce code style. A [pre-commit hook](./getting-started.md#3-enable-pre-commit-hooks) which runs this automatically is included with NetBox. To invoke `ruff` manually, run:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
python3 -m pip install ruff
|
|
32
|
+
ruff check netbox_contract/
|
|
33
|
+
```
|
|
31
34
|
|
|
32
|
-
Linting and PEP8 style enforcement will be done with [Flake8](https://flake8.pycqa.org/en/latest/) which is a wrapper arround:
|
|
33
|
-
- PyFlakes
|
|
34
|
-
- pycodestyle
|
|
35
|
-
- Ned Batchelder’s McCabe script
|
|
36
|
-
Configuration is maintained in the .flake8 file (no support for pyproject.toml)
|
|
37
35
|
|
|
38
36
|
The pre-commit Python framework is used to simplify the managment of pre-commit hooks.
|
|
39
37
|
Config is stored in .pre-commit-config.yaml
|
|
@@ -100,7 +98,13 @@ Make sure taht at the Netbox installtion step you follow the "Option B: Clone th
|
|
|
100
98
|
|
|
101
99
|
Connect to the name or IP of the server (as defined in ALLOWED_HOSTS) on port 8000; for example, http://127.0.0.1:8000/.
|
|
102
100
|
|
|
103
|
-
9.
|
|
101
|
+
9. Run unittest
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
$ python3 netbox/netbox/manage.py test netbox_contract
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
10. Commit your changes and push your branch to GitHub:
|
|
104
108
|
|
|
105
109
|
```
|
|
106
110
|
$ git add .
|
|
@@ -108,7 +112,7 @@ Make sure taht at the Netbox installtion step you follow the "Option B: Clone th
|
|
|
108
112
|
$ git push origin name-of-your-bugfix-or-feature
|
|
109
113
|
```
|
|
110
114
|
|
|
111
|
-
|
|
115
|
+
1. Submit a pull request through the GitHub website.
|
|
112
116
|
|
|
113
117
|
## Model changes
|
|
114
118
|
|
|
@@ -9,5 +9,5 @@ recursive-exclude * *.py[co]
|
|
|
9
9
|
recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
graft
|
|
13
|
-
graft
|
|
12
|
+
graft netbox_contract/templates
|
|
13
|
+
graft netbox_contract/templates/netbox_contract
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: netbox-contract
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.2
|
|
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
|
|
@@ -14,7 +14,7 @@ License-File: LICENSE
|
|
|
14
14
|
Requires-Dist: python-dateutil
|
|
15
15
|
Requires-Dist: drf_yasg
|
|
16
16
|
|
|
17
|
-
# Contract
|
|
17
|
+
# Contract plugin
|
|
18
18
|
|
|
19
19
|
NetBox plugin to manage contracts.
|
|
20
20
|
|
|
@@ -24,11 +24,11 @@ NetBox plugin to manage contracts.
|
|
|
24
24
|
|
|
25
25
|
## Features
|
|
26
26
|
|
|
27
|
-
The
|
|
27
|
+
The plugin adds contracts and invoices model to NetBox.
|
|
28
28
|
It allows to link contract with objects.
|
|
29
29
|
And link invoice templates and invoices with contracts.
|
|
30
30
|
Invoice lines can be linked to each invoice / invoice template.
|
|
31
|
-
|
|
31
|
+
Accounting dimensions can be linked with invoice lines.
|
|
32
32
|
|
|
33
33
|
## Compatibility
|
|
34
34
|
|
|
@@ -54,7 +54,7 @@ $ python3 -m pip install netbox-contract
|
|
|
54
54
|
|
|
55
55
|
### Configure NetBox
|
|
56
56
|
|
|
57
|
-
Finally, we need to configure NetBox to enable our new plugin.
|
|
57
|
+
Finally, we need to configure NetBox to enable our new plugin. In the NetBox installation directory, open `netbox/netbox/configuration.py` and locate the `PLUGINS` parameter; it should be an empty list. (If it's not yet defined, go ahead and create it.) Add the name of our plugin to this list:
|
|
58
58
|
|
|
59
59
|
```python
|
|
60
60
|
# configuration.py
|
|
@@ -65,7 +65,7 @@ PLUGINS = [
|
|
|
65
65
|
|
|
66
66
|
### Customize the plugin
|
|
67
67
|
|
|
68
|
-
The following
|
|
68
|
+
The following configuration items can be set:
|
|
69
69
|
|
|
70
70
|
```python
|
|
71
71
|
# configuration.py
|
|
@@ -100,7 +100,7 @@ FIELD_CHOICES = {
|
|
|
100
100
|
('entity2', 'Entity 2', 'yellow'),
|
|
101
101
|
),
|
|
102
102
|
'netbox_contract.Contract.currency': (
|
|
103
|
-
('usd', 'USD'),
|
|
103
|
+
('usd', 'USD'), # 1st position is the default currency
|
|
104
104
|
('eur', 'EUR'),
|
|
105
105
|
('chf', 'CHF'),
|
|
106
106
|
('pln', 'PLN'),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Contract
|
|
1
|
+
# Contract plugin
|
|
2
2
|
|
|
3
3
|
NetBox plugin to manage contracts.
|
|
4
4
|
|
|
@@ -8,11 +8,11 @@ NetBox plugin to manage contracts.
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
The
|
|
11
|
+
The plugin adds contracts and invoices model to NetBox.
|
|
12
12
|
It allows to link contract with objects.
|
|
13
13
|
And link invoice templates and invoices with contracts.
|
|
14
14
|
Invoice lines can be linked to each invoice / invoice template.
|
|
15
|
-
|
|
15
|
+
Accounting dimensions can be linked with invoice lines.
|
|
16
16
|
|
|
17
17
|
## Compatibility
|
|
18
18
|
|
|
@@ -38,7 +38,7 @@ $ python3 -m pip install netbox-contract
|
|
|
38
38
|
|
|
39
39
|
### Configure NetBox
|
|
40
40
|
|
|
41
|
-
Finally, we need to configure NetBox to enable our new plugin.
|
|
41
|
+
Finally, we need to configure NetBox to enable our new plugin. In the NetBox installation directory, open `netbox/netbox/configuration.py` and locate the `PLUGINS` parameter; it should be an empty list. (If it's not yet defined, go ahead and create it.) Add the name of our plugin to this list:
|
|
42
42
|
|
|
43
43
|
```python
|
|
44
44
|
# configuration.py
|
|
@@ -49,7 +49,7 @@ PLUGINS = [
|
|
|
49
49
|
|
|
50
50
|
### Customize the plugin
|
|
51
51
|
|
|
52
|
-
The following
|
|
52
|
+
The following configuration items can be set:
|
|
53
53
|
|
|
54
54
|
```python
|
|
55
55
|
# configuration.py
|
|
@@ -84,7 +84,7 @@ FIELD_CHOICES = {
|
|
|
84
84
|
('entity2', 'Entity 2', 'yellow'),
|
|
85
85
|
),
|
|
86
86
|
'netbox_contract.Contract.currency': (
|
|
87
|
-
('usd', 'USD'),
|
|
87
|
+
('usd', 'USD'), # 1st position is the default currency
|
|
88
88
|
('eur', 'EUR'),
|
|
89
89
|
('chf', 'CHF'),
|
|
90
90
|
('pln', 'PLN'),
|
|
@@ -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.3.
|
|
8
|
+
version = '2.3.2'
|
|
9
9
|
author = 'Marc Lebreuil'
|
|
10
10
|
author_email = 'marc@famillelebreuil.net'
|
|
11
11
|
base_url = 'contracts'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from django.db.models import Q
|
|
2
|
+
|
|
3
|
+
SERVICE_PROVIDER_MODELS = Q(
|
|
4
|
+
Q(app_label='circuits', model__in=('provider',))
|
|
5
|
+
| Q(app_label='netbox_contract', model__in=('serviceprovider',))
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
ASSIGNEMENT_MODELS = Q(
|
|
9
|
+
Q(app_label='circuits', model__in=('circuit',))
|
|
10
|
+
| Q(app_label='dcim', model__in=('site',))
|
|
11
|
+
| Q(app_label='dcim', model__in=('device',))
|
|
12
|
+
| Q(app_label='virtualization', model__in=('virtualmachine',))
|
|
13
|
+
)
|
|
@@ -10,6 +10,7 @@ from netbox.forms import (
|
|
|
10
10
|
NetBoxModelImportForm,
|
|
11
11
|
)
|
|
12
12
|
from tenancy.models import Tenant
|
|
13
|
+
from tenancy.forms import TenancyFilterForm
|
|
13
14
|
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES
|
|
14
15
|
from utilities.forms.fields import (
|
|
15
16
|
CommentField,
|
|
@@ -25,7 +26,7 @@ from utilities.forms.fields import (
|
|
|
25
26
|
)
|
|
26
27
|
from utilities.forms.widgets import DatePicker, HTMXSelect
|
|
27
28
|
|
|
28
|
-
from .constants import SERVICE_PROVIDER_MODELS
|
|
29
|
+
from .constants import SERVICE_PROVIDER_MODELS, ASSIGNEMENT_MODELS
|
|
29
30
|
from .models import (
|
|
30
31
|
AccountingDimension,
|
|
31
32
|
AccountingDimensionStatusChoices,
|
|
@@ -134,10 +135,9 @@ class ContractForm(NetBoxModelForm):
|
|
|
134
135
|
raise ValidationError('you should set monthly OR yearly recuring costs not both')
|
|
135
136
|
|
|
136
137
|
|
|
137
|
-
class ContractFilterForm(NetBoxModelFilterSetForm):
|
|
138
|
+
class ContractFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|
138
139
|
model = Contract
|
|
139
140
|
|
|
140
|
-
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False, selector=True, label=_('Tenant'))
|
|
141
141
|
external_reference = forms.CharField(required=False, label=_('External reference'))
|
|
142
142
|
internal_partie = forms.ChoiceField(choices=InternalEntityChoices, required=False, label=_('Internal partie'))
|
|
143
143
|
status = forms.ChoiceField(choices=StatusChoices, required=False, label=_('Status'))
|
|
@@ -353,7 +353,7 @@ class InvoiceFilterForm(NetBoxModelFilterSetForm):
|
|
|
353
353
|
|
|
354
354
|
|
|
355
355
|
class InvoiceCSVForm(NetBoxModelImportForm):
|
|
356
|
-
contracts =
|
|
356
|
+
contracts = CSVModelMultipleChoiceField(
|
|
357
357
|
queryset=Contract.objects.all(),
|
|
358
358
|
to_field_name='name',
|
|
359
359
|
help_text='Related Contracts',
|
|
@@ -378,7 +378,7 @@ class InvoiceCSVForm(NetBoxModelImportForm):
|
|
|
378
378
|
|
|
379
379
|
|
|
380
380
|
class InvoiceBulkEditForm(NetBoxModelBulkEditForm):
|
|
381
|
-
number = forms.CharField(max_length=100, required=
|
|
381
|
+
number = forms.CharField(max_length=100, required=False, label=_('Number'))
|
|
382
382
|
template = forms.BooleanField(
|
|
383
383
|
required=False,
|
|
384
384
|
label=_('Template'),
|
|
@@ -453,7 +453,7 @@ class ServiceProviderCSVForm(NetBoxModelImportForm):
|
|
|
453
453
|
|
|
454
454
|
|
|
455
455
|
class ServiceProviderBulkEditForm(NetBoxModelBulkEditForm):
|
|
456
|
-
name = forms.CharField(max_length=100, required=
|
|
456
|
+
name = forms.CharField(max_length=100, required=False, label=_('Name'))
|
|
457
457
|
comments = CommentField(label=_('Comments'))
|
|
458
458
|
nullable_fields = ('comments',)
|
|
459
459
|
model = ServiceProvider
|
|
@@ -463,21 +463,32 @@ class ServiceProviderBulkEditForm(NetBoxModelBulkEditForm):
|
|
|
463
463
|
|
|
464
464
|
|
|
465
465
|
class ContractAssignmentForm(NetBoxModelForm):
|
|
466
|
-
|
|
466
|
+
|
|
467
|
+
content_type = ContentTypeChoiceField(
|
|
468
|
+
queryset=ContentType.objects.all(),
|
|
469
|
+
limit_choices_to=ASSIGNEMENT_MODELS,
|
|
470
|
+
label=_('object type'),
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
contract = DynamicModelChoiceField(
|
|
474
|
+
queryset=Contract.objects.all(),
|
|
475
|
+
selector=True,
|
|
476
|
+
label=_('Contract'))
|
|
467
477
|
|
|
468
478
|
class Meta:
|
|
469
479
|
model = ContractAssignment
|
|
470
480
|
fields = ['content_type', 'object_id', 'contract', 'tags']
|
|
471
|
-
widgets = {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}
|
|
481
|
+
# widgets = {
|
|
482
|
+
# 'content_type': forms.HiddenInput(),
|
|
483
|
+
# 'object_id': forms.HiddenInput(),
|
|
484
|
+
# }
|
|
475
485
|
|
|
476
486
|
|
|
477
487
|
class ContractAssignmentFilterForm(NetBoxModelFilterSetForm):
|
|
478
488
|
model = ContractAssignment
|
|
479
489
|
contract = DynamicModelChoiceField(
|
|
480
490
|
queryset=Contract.objects.all(),
|
|
491
|
+
required=False,
|
|
481
492
|
selector=True,
|
|
482
493
|
label=_('Contract'),
|
|
483
494
|
)
|
|
@@ -486,6 +497,7 @@ class ContractAssignmentFilterForm(NetBoxModelFilterSetForm):
|
|
|
486
497
|
class ContractAssignmentImportForm(NetBoxModelImportForm):
|
|
487
498
|
content_type = CSVContentTypeField(
|
|
488
499
|
queryset=ContentType.objects.all(),
|
|
500
|
+
limit_choices_to=ASSIGNEMENT_MODELS,
|
|
489
501
|
help_text='Content Type in the form <app>.<model>',
|
|
490
502
|
label=_('Content type'),
|
|
491
503
|
)
|
|
@@ -500,6 +512,16 @@ class ContractAssignmentImportForm(NetBoxModelImportForm):
|
|
|
500
512
|
fields = ['content_type', 'object_id', 'contract', 'tags']
|
|
501
513
|
|
|
502
514
|
|
|
515
|
+
class ContractAssignmentBulkEditForm(NetBoxModelBulkEditForm):
|
|
516
|
+
contract = DynamicModelChoiceField(
|
|
517
|
+
queryset=Contract.objects.all(),
|
|
518
|
+
required=False,
|
|
519
|
+
selector=True,
|
|
520
|
+
label=_('Contract'),
|
|
521
|
+
)
|
|
522
|
+
model = ContractAssignment
|
|
523
|
+
|
|
524
|
+
|
|
503
525
|
# InvoiceLine
|
|
504
526
|
|
|
505
527
|
|
|
@@ -578,6 +600,7 @@ class InvoiceLineImportForm(NetBoxModelImportForm):
|
|
|
578
600
|
accounting_dimensions = CSVModelMultipleChoiceField(
|
|
579
601
|
queryset=AccountingDimension.objects.all(),
|
|
580
602
|
to_field_name='id',
|
|
603
|
+
required=False,
|
|
581
604
|
help_text='accounting dimension id',
|
|
582
605
|
label=_('Accounting dimensions'),
|
|
583
606
|
)
|
|
@@ -602,6 +625,8 @@ class InvoiceLineBulkEditForm(NetBoxModelBulkEditForm):
|
|
|
602
625
|
selector=True,
|
|
603
626
|
label=_('Accounting dimensions'),
|
|
604
627
|
)
|
|
628
|
+
comments = CommentField(label=_('Comments'))
|
|
629
|
+
nullable_fields = ('comments',)
|
|
605
630
|
model = InvoiceLine
|
|
606
631
|
|
|
607
632
|
|
|
@@ -649,4 +674,6 @@ class AccountingDimensionImportForm(NetBoxModelImportForm):
|
|
|
649
674
|
class AccountingDimensionBulkEditForm(NetBoxModelBulkEditForm):
|
|
650
675
|
name = forms.CharField(max_length=20, required=False, label=_('Name'))
|
|
651
676
|
value = forms.CharField(max_length=20, required=False, label=_('Value'))
|
|
677
|
+
comments = CommentField(label=_('Comments'))
|
|
678
|
+
nullable_fields = ('comments',)
|
|
652
679
|
model = AccountingDimension
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Generated by Django 5.1.5 on 2025-02-23 09:21
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("netbox_contract", "0039_alter_accountingdimension_status_and_more"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="contract",
|
|
15
|
+
name="currency",
|
|
16
|
+
field=models.CharField(default="usd", max_length=3),
|
|
17
|
+
),
|
|
18
|
+
migrations.AlterField(
|
|
19
|
+
model_name="invoice",
|
|
20
|
+
name="currency",
|
|
21
|
+
field=models.CharField(default="usd", max_length=3),
|
|
22
|
+
),
|
|
23
|
+
migrations.AlterField(
|
|
24
|
+
model_name="invoiceline",
|
|
25
|
+
name="currency",
|
|
26
|
+
field=models.CharField(default="usd", max_length=3),
|
|
27
|
+
),
|
|
28
|
+
]
|
|
@@ -9,6 +9,8 @@ from django.utils.translation import gettext_lazy as _
|
|
|
9
9
|
from netbox.models import NetBoxModel
|
|
10
10
|
from netbox.models.features import ContactsMixin
|
|
11
11
|
from utilities.choices import ChoiceSet
|
|
12
|
+
from dcim.choices import DeviceStatusChoices, SiteStatusChoices
|
|
13
|
+
from virtualization.choices import VirtualMachineStatusChoices
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class StatusChoices(ChoiceSet):
|
|
@@ -135,6 +137,18 @@ class ContractAssignment(NetBoxModel):
|
|
|
135
137
|
def get_absolute_url(self):
|
|
136
138
|
return reverse('plugins:netbox_contract:contractassignment', args=[self.pk])
|
|
137
139
|
|
|
140
|
+
def get_contract__status_color(self):
|
|
141
|
+
return StatusChoices.colors.get(self.contract.status)
|
|
142
|
+
|
|
143
|
+
def get_content_object__status_color(self):
|
|
144
|
+
STATUS_MAPPING = {
|
|
145
|
+
'virtualmachine': VirtualMachineStatusChoices.colors,
|
|
146
|
+
'device': DeviceStatusChoices.colors,
|
|
147
|
+
'site': SiteStatusChoices.colors,
|
|
148
|
+
}
|
|
149
|
+
status_colors = STATUS_MAPPING.get(self.content_type.model, StatusChoices.colors)
|
|
150
|
+
return status_colors.get(self.content_object.status)
|
|
151
|
+
|
|
138
152
|
|
|
139
153
|
class Contract(NetBoxModel):
|
|
140
154
|
name = models.CharField(max_length=100, verbose_name=_('name'))
|
|
@@ -12,16 +12,18 @@ from .models import (
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class ContractAssignmentListTable(NetBoxTable):
|
|
15
|
+
id = tables.Column(linkify=True)
|
|
15
16
|
content_type = columns.ContentTypeColumn(verbose_name='Object Type')
|
|
16
17
|
content_object = tables.Column(linkify=True, orderable=False)
|
|
17
18
|
contract = tables.Column(linkify=True)
|
|
18
19
|
actions = columns.ActionsColumn(actions=('edit', 'delete'))
|
|
19
20
|
contract__external_partie_object = tables.Column(linkify=True)
|
|
21
|
+
tags = columns.TagColumn(url_name='plugins:netbox_contract:contractassignment_list')
|
|
20
22
|
|
|
21
23
|
class Meta(NetBoxTable.Meta):
|
|
22
24
|
model = ContractAssignment
|
|
23
25
|
fields = (
|
|
24
|
-
'
|
|
26
|
+
'id',
|
|
25
27
|
'content_type',
|
|
26
28
|
'content_object',
|
|
27
29
|
'contract',
|
|
@@ -30,7 +32,7 @@ class ContractAssignmentListTable(NetBoxTable):
|
|
|
30
32
|
'actions',
|
|
31
33
|
)
|
|
32
34
|
default_columns = (
|
|
33
|
-
'
|
|
35
|
+
'id',
|
|
34
36
|
'content_type',
|
|
35
37
|
'content_object',
|
|
36
38
|
'contract',
|
|
@@ -108,6 +110,7 @@ class ContractListTable(NetBoxTable):
|
|
|
108
110
|
status = columns.ChoiceFieldColumn(
|
|
109
111
|
verbose_name=('Status'),
|
|
110
112
|
)
|
|
113
|
+
tags = columns.TagColumn(url_name='plugins:netbox_contract:contract_list')
|
|
111
114
|
|
|
112
115
|
class Meta(NetBoxTable.Meta):
|
|
113
116
|
model = Contract
|
|
@@ -171,6 +174,7 @@ class ContractListBottomTable(NetBoxTable):
|
|
|
171
174
|
class InvoiceListTable(NetBoxTable):
|
|
172
175
|
contracts = tables.ManyToManyColumn(linkify=True)
|
|
173
176
|
number = tables.Column(linkify=True)
|
|
177
|
+
tags = columns.TagColumn(url_name='plugins:netbox_contract:invoiceline_list')
|
|
174
178
|
|
|
175
179
|
class Meta(NetBoxTable.Meta):
|
|
176
180
|
model = Invoice
|
|
@@ -200,6 +204,7 @@ class InvoiceListTable(NetBoxTable):
|
|
|
200
204
|
|
|
201
205
|
class ServiceProviderListTable(NetBoxTable):
|
|
202
206
|
name = tables.Column(linkify=True)
|
|
207
|
+
tags = columns.TagColumn(url_name='plugins:netbox_contract:serviceprovider_list')
|
|
203
208
|
|
|
204
209
|
class Meta(NetBoxTable.Meta):
|
|
205
210
|
model = ServiceProvider
|
|
@@ -209,7 +214,8 @@ class ServiceProviderListTable(NetBoxTable):
|
|
|
209
214
|
|
|
210
215
|
class InvoiceLineListTable(NetBoxTable):
|
|
211
216
|
invoice = tables.Column(linkify=True)
|
|
212
|
-
accounting_dimensions = tables.ManyToManyColumn(
|
|
217
|
+
accounting_dimensions = tables.ManyToManyColumn(linkify_item=True, filter=lambda qs: qs.order_by('name'))
|
|
218
|
+
tags = columns.TagColumn(url_name='plugins:netbox_contract:invoiceline_list')
|
|
213
219
|
|
|
214
220
|
class Meta(NetBoxTable.Meta):
|
|
215
221
|
model = InvoiceLine
|
|
@@ -232,9 +238,11 @@ class InvoiceLineListTable(NetBoxTable):
|
|
|
232
238
|
|
|
233
239
|
|
|
234
240
|
class AccountingDimensionListTable(NetBoxTable):
|
|
241
|
+
name = tables.Column(linkify=True)
|
|
235
242
|
status = columns.ChoiceFieldColumn(
|
|
236
243
|
verbose_name=('Status'),
|
|
237
244
|
)
|
|
245
|
+
tags = columns.TagColumn(url_name='plugins:netbox_contract:accountingdimension_list')
|
|
238
246
|
|
|
239
247
|
class Meta(NetBoxTable.Meta):
|
|
240
248
|
model = AccountingDimension
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from django.urls import reverse
|
|
2
|
+
from utilities.testing.api import APITestCase as NetBoxAPITestCase
|
|
3
|
+
from utilities.testing.views import ModelViewTestCase as NetBoxModelViewTestCase
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ModelViewTestCase(NetBoxModelViewTestCase):
|
|
7
|
+
def _get_base_url(self):
|
|
8
|
+
return f'plugins:{self.model._meta.app_label}:{self.model._meta.model_name}_{{}}'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class APITestCase(NetBoxAPITestCase):
|
|
12
|
+
def _get_detail_url(self, instance):
|
|
13
|
+
viewname = f'plugins-api:{self._get_view_namespace()}:{instance._meta.model_name}-detail'
|
|
14
|
+
return reverse(viewname, kwargs={'pk': instance.pk})
|
|
15
|
+
|
|
16
|
+
def _get_list_url(self):
|
|
17
|
+
viewname = f'plugins-api:{self._get_view_namespace()}:{self.model._meta.model_name}-list'
|
|
18
|
+
return reverse(viewname)
|