diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 34f18f6d6..d3910de3a 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -3890,6 +3890,40 @@ class InventoryItemForm(BootstrapMixin, forms.ModelForm): } +class InventoryItemCreateForm(ComponentForm): + device = forms.ModelChoiceField( + queryset=Device.objects.all(), + widget=forms.HiddenInput() + ) + name_pattern = ExpandableNameField( + label='Name' + ) + manufacturer = forms.ModelChoiceField( + queryset=Manufacturer.objects.all(), + required=False, + widget=APISelect( + api_url="/api/dcim/manufacturers/" + ) + ) + part_id = forms.CharField( + max_length=50, + required=False, + label='Part ID' + ) + serial = forms.CharField( + max_length=50, + required=False, + ) + asset_tag = forms.CharField( + max_length=50, + required=False, + ) + description = forms.CharField( + max_length=100, + required=False + ) + + class InventoryItemCSVForm(forms.ModelForm): device = FlexibleModelChoiceField( queryset=Device.objects.all(), diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index e37569f79..431419a7a 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -1004,7 +1004,7 @@ class InventoryItem(ComponentModel): return self.name def get_absolute_url(self): - return self.device.get_absolute_url() + return reverse('dcim:device_inventory', kwargs={'pk': self.device.pk}) def to_csv(self): return ( diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 803fee30b..5bf8963de 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -1136,10 +1136,11 @@ class InventoryItemTestCase(StandardTestCases.Views): # Disable inapplicable views test_get_object = None - - # TODO test_create_object = None + def test_bulk_create_objects(self): + return self._test_bulk_create_objects(expected_count=3) + @classmethod def setUpTestData(cls): device = create_test_device('Device 1') @@ -1164,6 +1165,18 @@ class InventoryItemTestCase(StandardTestCases.Views): 'tags': 'Alpha,Bravo,Charlie', } + cls.bulk_create_data = { + 'device': device.pk, + 'name_pattern': 'Inventory Item [4-6]', + 'manufacturer': manufacturer.pk, + 'parent': None, + 'discovered': False, + 'part_id': '123456', + 'serial': '123ABC', + 'description': 'An inventory item', + 'tags': 'Alpha,Bravo,Charlie', + } + cls.bulk_edit_data = { 'device': device.pk, 'manufacturer': manufacturer.pk, diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index caf1ccd16..9d70e0415 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -278,13 +278,12 @@ urlpatterns = [ # Inventory items path('inventory-items/', views.InventoryItemListView.as_view(), name='inventoryitem_list'), + path('inventory-items/add/', views.InventoryItemCreateView.as_view(), name='inventoryitem_add'), path('inventory-items/import/', views.InventoryItemBulkImportView.as_view(), name='inventoryitem_import'), path('inventory-items/edit/', views.InventoryItemBulkEditView.as_view(), name='inventoryitem_bulk_edit'), path('inventory-items/delete/', views.InventoryItemBulkDeleteView.as_view(), name='inventoryitem_bulk_delete'), path('inventory-items//edit/', views.InventoryItemEditView.as_view(), name='inventoryitem_edit'), path('inventory-items//delete/', views.InventoryItemDeleteView.as_view(), name='inventoryitem_delete'), - # TODO: Replace below with InventoryItemCreateView - path('devices//inventory-items/add/', views.InventoryItemEditView.as_view(), name='inventoryitem_add'), # Cables path('cables/', views.CableListView.as_view(), name='cable_list'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 6e7018fb5..ee5ea876c 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -2135,13 +2135,13 @@ class InventoryItemEditView(PermissionRequiredMixin, ObjectEditView): model = InventoryItem model_form = forms.InventoryItemForm - def alter_obj(self, obj, request, url_args, url_kwargs): - if 'device' in url_kwargs: - obj.device = get_object_or_404(Device, pk=url_kwargs['device']) - return obj - def get_return_url(self, request, obj): - return reverse('dcim:device_inventory', kwargs={'pk': obj.device.pk}) +class InventoryItemCreateView(PermissionRequiredMixin, ComponentCreateView): + permission_required = 'dcim.add_inventoryitem' + model = InventoryItem + form = forms.InventoryItemCreateForm + model_form = forms.InventoryItemForm + template_name = 'dcim/device_component_add.html' class InventoryItemDeleteView(PermissionRequiredMixin, ObjectDeleteView): diff --git a/netbox/templates/dcim/device_inventory.html b/netbox/templates/dcim/device_inventory.html index 0d50343eb..1a7e5d793 100644 --- a/netbox/templates/dcim/device_inventory.html +++ b/netbox/templates/dcim/device_inventory.html @@ -54,7 +54,7 @@ {% if perms.dcim.add_inventoryitem %}