-
-
Notifications
You must be signed in to change notification settings - Fork 17
Closes #85 - Extend support contract assignments to modules #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Generated by Django 5.0.9 on 2025-03-13 16:40 | ||
|
|
||
| import django.db.models.deletion | ||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('dcim', '0190_nested_modules'), | ||
| ('netbox_lifecycle', '0014_rename_last_contract_date_and_more'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AlterModelOptions( | ||
| name='supportcontractassignment', | ||
| options={'ordering': ['contract', 'device', 'license', 'module']}, | ||
| ), | ||
| migrations.AddField( | ||
| model_name='supportcontractassignment', | ||
| name='module', | ||
| field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='contracts', to='dcim.module'), | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,7 @@ | |
| from django.urls import reverse | ||
| from django.utils.translation import gettext as _ | ||
|
|
||
| from dcim.choices import DeviceStatusChoices | ||
| from dcim.choices import DeviceStatusChoices, ModuleStatusChoices | ||
| from netbox.models import PrimaryModel | ||
|
|
||
|
|
||
|
|
@@ -138,6 +138,13 @@ class SupportContractAssignment(PrimaryModel): | |
| blank=True, | ||
| related_name='contracts', | ||
| ) | ||
| module = models.ForeignKey( | ||
| to='dcim.Module', | ||
| on_delete=models.SET_NULL, | ||
| null=True, | ||
| blank=True, | ||
| related_name='contracts', | ||
| ) | ||
| end = models.DateField( | ||
| null=True, | ||
| blank=True, | ||
|
|
@@ -153,16 +160,20 @@ class SupportContractAssignment(PrimaryModel): | |
| 'netbox_lifecycle.SupportSKU', | ||
| 'netbox_lifecycle.License', | ||
| 'dcim.Device', | ||
| 'dcim.Module', | ||
| ) | ||
|
|
||
| class Meta: | ||
| ordering = ['contract', 'device', 'license'] | ||
| ordering = ['contract', 'device', 'license', 'module'] | ||
| constraints = () | ||
|
|
||
| def __str__(self): | ||
| if self.license and self.device: | ||
| return f'{self.device} ({self.license}): {self.contract.contract_id}' | ||
| return f'{self.device}: {self.contract.contract_id}' | ||
| if self.device: | ||
| return f'{self.device}: {self.contract.contract_id}' | ||
| if self.module: | ||
| return f'{self.module}: {self.contract.contract_id}' | ||
|
|
||
| def get_absolute_url(self): | ||
| return reverse('plugins:netbox_lifecycle:supportcontractassignment', args=[self.pk]) | ||
|
|
@@ -178,16 +189,28 @@ def get_device_status_color(self): | |
| return | ||
| return DeviceStatusChoices.colors.get(self.device.status) | ||
|
|
||
| def get_module_status_color(self): | ||
| if self.module is None: | ||
| return | ||
| return ModuleStatusChoices.colors.get(self.module.status) | ||
|
|
||
| def clean(self): | ||
| if self.device and self.license and SupportContractAssignment.objects.filter( | ||
| if self.module: | ||
| if self.license or self.device: | ||
| raise ValidationError('Assigning a Module excludes the assigment of a Device or License') | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if I agree with this. I think selecting a device or license (or both) would be valid depending on the circumstances. A module is always going to be in a device, and when removing from a device in NetBox it is deleted. I think a more reasonable check would be to ensure that this is unique across all 3 fields. In addition, you would want to add unique checks for: device, module where license is None |
||
| elif SupportContractAssignment.objects.filter( | ||
| contract=self.contract, module=self.module | ||
| ).exclude(pk=self.pk).count() > 0: | ||
| raise ValidationError('Module must be unique') | ||
| elif self.device and self.license and not self.module and SupportContractAssignment.objects.filter( | ||
| contract=self.contract, device=self.device, license=self.license, sku=self.sku | ||
| ).exclude(pk=self.pk).count() > 0: | ||
| raise ValidationError('Device or License must be unique') | ||
| elif self.device and not self.license and SupportContractAssignment.objects.filter( | ||
| elif self.device and not self.license and not self.module and SupportContractAssignment.objects.filter( | ||
| contract=self.contract, device=self.device, license=self.license | ||
| ).exclude(pk=self.pk).count() > 0: | ||
| raise ValidationError('Device must be unique') | ||
| elif not self.device and self.license and SupportContractAssignment.objects.filter( | ||
| elif not self.device and self.license and not self.module and SupportContractAssignment.objects.filter( | ||
| contract=self.contract, device=self.device, license=self.license | ||
| ).exclude(pk=self.pk).count() > 0: | ||
| raise ValidationError('License must be unique') | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment in the model and adjust accordingly