mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Allow build orders to be deleted via the API (#3155)
This commit is contained in:
parent
403655e3d2
commit
a816c14b95
@ -1,8 +1,10 @@
|
||||
"""JSON API for the Build app."""
|
||||
|
||||
from django.urls import include, re_path
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import filters, generics
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from django_filters import rest_framework as rest_filters
|
||||
@ -198,12 +200,24 @@ class BuildList(APIDownloadMixin, generics.ListCreateAPIView):
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
|
||||
class BuildDetail(generics.RetrieveUpdateAPIView):
|
||||
class BuildDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""API endpoint for detail view of a Build object."""
|
||||
|
||||
queryset = Build.objects.all()
|
||||
serializer_class = build.serializers.BuildSerializer
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
"""Only allow deletion of a BuildOrder if the build status is CANCELLED"""
|
||||
|
||||
build = self.get_object()
|
||||
|
||||
if build.status != BuildStatus.CANCELLED:
|
||||
raise ValidationError({
|
||||
"non_field_errors": [_("Build must be cancelled before it can be deleted")]
|
||||
})
|
||||
|
||||
return super().destroy(request, *args, **kwargs)
|
||||
|
||||
|
||||
class BuildUnallocate(generics.CreateAPIView):
|
||||
"""API endpoint for unallocating stock items from a build order.
|
||||
|
@ -249,9 +249,11 @@ src="{% static 'img/blank_image.png' %}"
|
||||
{% endif %}
|
||||
|
||||
$("#build-delete").on('click', function() {
|
||||
launchModalForm(
|
||||
"{% url 'build-delete' build.id %}",
|
||||
constructForm(
|
||||
'{% url "api-build-detail" build.pk %}',
|
||||
{
|
||||
method: 'DELETE',
|
||||
title: '{% trans "Delete Build Order" %}',
|
||||
redirect: "{% url 'build-index' %}",
|
||||
}
|
||||
);
|
||||
|
@ -1,7 +0,0 @@
|
||||
{% extends "modal_delete_form.html" %}
|
||||
{% load i18n %}
|
||||
{% block pre_form_content %}
|
||||
|
||||
{% trans "Are you sure you want to delete this build?" %}
|
||||
|
||||
{% endblock %}
|
@ -90,7 +90,7 @@ class BuildAPITest(InvenTreeAPITestCase):
|
||||
# Required roles to access Build API endpoints
|
||||
roles = [
|
||||
'build.change',
|
||||
'build.add'
|
||||
'build.add',
|
||||
]
|
||||
|
||||
|
||||
@ -268,6 +268,39 @@ class BuildTest(BuildAPITest):
|
||||
|
||||
self.assertEqual(bo.status, BuildStatus.CANCELLED)
|
||||
|
||||
def test_delete(self):
|
||||
"""Test that we can delete a BuildOrder via the API"""
|
||||
|
||||
bo = Build.objects.get(pk=1)
|
||||
|
||||
url = reverse('api-build-detail', kwargs={'pk': bo.pk})
|
||||
|
||||
# At first we do not have the required permissions
|
||||
self.delete(
|
||||
url,
|
||||
expected_code=403,
|
||||
)
|
||||
|
||||
self.assignRole('build.delete')
|
||||
|
||||
# As build is currently not 'cancelled', it cannot be deleted
|
||||
self.delete(
|
||||
url,
|
||||
expected_code=400,
|
||||
)
|
||||
|
||||
bo.status = BuildStatus.CANCELLED
|
||||
bo.save()
|
||||
|
||||
# Now, we should be able to delete
|
||||
self.delete(
|
||||
url,
|
||||
expected_code=204,
|
||||
)
|
||||
|
||||
with self.assertRaises(Build.DoesNotExist):
|
||||
Build.objects.get(pk=1)
|
||||
|
||||
def test_create_delete_output(self):
|
||||
"""Test that we can create and delete build outputs via the API."""
|
||||
bo = Build.objects.get(pk=1)
|
||||
|
@ -4,15 +4,12 @@ from django.urls import include, re_path
|
||||
|
||||
from . import views
|
||||
|
||||
build_detail_urls = [
|
||||
re_path(r'^delete/', views.BuildDelete.as_view(), name='build-delete'),
|
||||
|
||||
re_path(r'^.*$', views.BuildDetail.as_view(), name='build-detail'),
|
||||
]
|
||||
|
||||
build_urls = [
|
||||
|
||||
re_path(r'^(?P<pk>\d+)/', include(build_detail_urls)),
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^.*$', views.BuildDetail.as_view(), name='build-detail'),
|
||||
])),
|
||||
|
||||
re_path(r'.*$', views.BuildIndex.as_view(), name='build-index'),
|
||||
]
|
||||
|
@ -1,11 +1,9 @@
|
||||
"""Django views for interacting with Build objects."""
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import DetailView, ListView
|
||||
|
||||
from .models import Build
|
||||
|
||||
from InvenTree.views import AjaxDeleteView
|
||||
from InvenTree.views import InvenTreeRoleMixin
|
||||
from InvenTree.status_codes import BuildStatus
|
||||
|
||||
@ -49,11 +47,3 @@ class BuildDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView):
|
||||
ctx['has_untracked_bom_items'] = build.has_untracked_bom_items()
|
||||
|
||||
return ctx
|
||||
|
||||
|
||||
class BuildDelete(AjaxDeleteView):
|
||||
"""View to delete a build."""
|
||||
|
||||
model = Build
|
||||
ajax_template_name = 'build/delete_build.html'
|
||||
ajax_form_title = _('Delete Build Order')
|
||||
|
Loading…
Reference in New Issue
Block a user