|
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 |
|
|
0 commit comments