mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Refactor "uninstall stock item" form to use the API
This commit is contained in:
parent
5cf30a850d
commit
adbcd68fe8
@ -92,13 +92,8 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
return self.serializer_class(*args, **kwargs)
|
return self.serializer_class(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class StockItemSerialize(generics.CreateAPIView):
|
class StockItemContextMixin:
|
||||||
"""
|
""" Mixin class for adding StockItem object to serializer context """
|
||||||
API endpoint for serializing a stock item
|
|
||||||
"""
|
|
||||||
|
|
||||||
queryset = StockItem.objects.none()
|
|
||||||
serializer_class = StockSerializers.SerializeStockItemSerializer
|
|
||||||
|
|
||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
|
|
||||||
@ -112,8 +107,16 @@ class StockItemSerialize(generics.CreateAPIView):
|
|||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
class StockItemSerialize(StockItemContextMixin, generics.CreateAPIView):
|
||||||
|
"""
|
||||||
|
API endpoint for serializing a stock item
|
||||||
|
"""
|
||||||
|
|
||||||
class StockItemInstall(generics.CreateAPIView):
|
queryset = StockItem.objects.none()
|
||||||
|
serializer_class = StockSerializers.SerializeStockItemSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class StockItemInstall(StockItemContextMixin, generics.CreateAPIView):
|
||||||
"""
|
"""
|
||||||
API endpoint for installing a particular stock item into this stock item.
|
API endpoint for installing a particular stock item into this stock item.
|
||||||
|
|
||||||
@ -125,17 +128,14 @@ class StockItemInstall(generics.CreateAPIView):
|
|||||||
queryset = StockItem.objects.none()
|
queryset = StockItem.objects.none()
|
||||||
serializer_class = StockSerializers.InstallStockItemSerializer
|
serializer_class = StockSerializers.InstallStockItemSerializer
|
||||||
|
|
||||||
def get_serializer_context(self):
|
|
||||||
|
|
||||||
context = super().get_serializer_context()
|
class StockItemUninstall(StockItemContextMixin, generics.CreateAPIView):
|
||||||
context['request'] = self.request
|
"""
|
||||||
|
API endpoint for removing (uninstalling) items from this item
|
||||||
|
"""
|
||||||
|
|
||||||
try:
|
queryset = StockItem.objects.none()
|
||||||
context['item'] = StockItem.objects.get(pk=self.kwargs.get('pk', None))
|
serializer_class = StockSerializers.UninstallStockItemSerializer
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class StockAdjustView(generics.CreateAPIView):
|
class StockAdjustView(generics.CreateAPIView):
|
||||||
@ -1421,6 +1421,7 @@ stock_api_urls = [
|
|||||||
re_path(r'^(?P<pk>\d+)/', include([
|
re_path(r'^(?P<pk>\d+)/', include([
|
||||||
re_path(r'^serialize/', StockItemSerialize.as_view(), name='api-stock-item-serialize'),
|
re_path(r'^serialize/', StockItemSerialize.as_view(), name='api-stock-item-serialize'),
|
||||||
re_path(r'^install/', StockItemInstall.as_view(), name='api-stock-item-install'),
|
re_path(r'^install/', StockItemInstall.as_view(), name='api-stock-item-install'),
|
||||||
|
re_path(r'^uninstall/', StockItemUninstall.as_view(), name='api-stock-item-uninstall'),
|
||||||
re_path(r'^.*$', StockDetail.as_view(), name='api-stock-detail'),
|
re_path(r'^.*$', StockDetail.as_view(), name='api-stock-detail'),
|
||||||
])),
|
])),
|
||||||
|
|
||||||
|
@ -1142,7 +1142,7 @@ class StockItem(MPTTModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def uninstallIntoLocation(self, location, user, notes):
|
def uninstall_into_location(self, location, user, notes):
|
||||||
"""
|
"""
|
||||||
Uninstall this stock item from another item, into a location.
|
Uninstall this stock item from another item, into a location.
|
||||||
|
|
||||||
|
@ -448,6 +448,48 @@ class InstallStockItemSerializer(serializers.Serializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UninstallStockItemSerializer(serializers.Serializer):
|
||||||
|
"""
|
||||||
|
API serializers for uninstalling an installed item from a stock item
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
fields = [
|
||||||
|
'location',
|
||||||
|
'note',
|
||||||
|
]
|
||||||
|
|
||||||
|
location = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=StockLocation.objects.all(),
|
||||||
|
many=False, required=True, allow_null=False,
|
||||||
|
label=_('Location'),
|
||||||
|
help_text=_('Destination location for uninstalled item')
|
||||||
|
)
|
||||||
|
|
||||||
|
note = serializers.CharField(
|
||||||
|
label=_('Notes'),
|
||||||
|
help_text=_('Add transaction note (optional)'),
|
||||||
|
required=False, allow_blank=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
|
||||||
|
item = self.context['item']
|
||||||
|
|
||||||
|
data = self.validated_data
|
||||||
|
request = self.context['request']
|
||||||
|
|
||||||
|
location = data['location']
|
||||||
|
|
||||||
|
note = data.get('note', '')
|
||||||
|
|
||||||
|
item.uninstall_into_location(
|
||||||
|
location,
|
||||||
|
request.user,
|
||||||
|
note
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LocationTreeSerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
class LocationTreeSerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
||||||
"""
|
"""
|
||||||
Serializer for a simple tree view
|
Serializer for a simple tree view
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
{% extends "modal_delete_form.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block pre_form_content %}
|
|
||||||
{% trans "Are you sure you want to delete this attachment?" %}
|
|
||||||
<br>
|
|
||||||
{% endblock %}
|
|
@ -159,9 +159,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='panel-content'>
|
<div class='panel-content'>
|
||||||
<div class='btn-group'>
|
<div id='installed-table-toolbar'>
|
||||||
|
<div class='btn-group' role='group'>
|
||||||
|
{% include "filter_list.html" with id='installed-items' %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class='table table-striped table-condensed' id='installed-table'></table>
|
<table class='table table-striped table-condensed' id='installed-table' data-toolbar='#installed-table-toolbar'></table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -207,28 +210,6 @@
|
|||||||
quantity: {{ item.quantity|unlocalize }},
|
quantity: {{ item.quantity|unlocalize }},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
$('#multi-item-uninstall').click(function() {
|
|
||||||
|
|
||||||
var selections = $('#installed-table').bootstrapTable('getSelections');
|
|
||||||
|
|
||||||
var items = [];
|
|
||||||
|
|
||||||
selections.forEach(function(item) {
|
|
||||||
items.push(item.pk);
|
|
||||||
});
|
|
||||||
|
|
||||||
launchModalForm(
|
|
||||||
"{% url 'stock-item-uninstall' %}",
|
|
||||||
{
|
|
||||||
data: {
|
|
||||||
'items[]': items,
|
|
||||||
},
|
|
||||||
reload: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
onPanelLoad('notes', function() {
|
onPanelLoad('notes', function() {
|
||||||
setupNotesField(
|
setupNotesField(
|
||||||
|
@ -445,12 +445,9 @@ $('#stock-install-in').click(function() {
|
|||||||
|
|
||||||
$('#stock-uninstall').click(function() {
|
$('#stock-uninstall').click(function() {
|
||||||
|
|
||||||
launchModalForm(
|
uninstallStockItem(
|
||||||
"{% url 'stock-item-uninstall' %}",
|
{{ item.pk }},
|
||||||
{
|
{
|
||||||
data: {
|
|
||||||
'items[]': [{{ item.pk }}],
|
|
||||||
},
|
|
||||||
reload: true,
|
reload: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
{% extends "modal_form.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% load inventree_extras %}
|
|
||||||
|
|
||||||
{% block pre_form_content %}
|
|
||||||
|
|
||||||
<div class='alert alert-block alert-success'>
|
|
||||||
{% trans "The following stock items will be uninstalled" %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class='list-group'>
|
|
||||||
{% for item in stock_items %}
|
|
||||||
<li class='list-group-item'>
|
|
||||||
{% include "hover_image.html" with image=item.part.image hover=False %}
|
|
||||||
{{ item }}
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block form_data %}
|
|
||||||
|
|
||||||
{% for item in stock_items %}
|
|
||||||
<input type='hidden' name='stock-item-{{ item.pk }}' value='{{ item.pk }}'/>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -43,8 +43,6 @@ stock_urls = [
|
|||||||
# Stock location
|
# Stock location
|
||||||
re_path(r'^location/', include(location_urls)),
|
re_path(r'^location/', include(location_urls)),
|
||||||
|
|
||||||
re_path(r'^item/uninstall/', views.StockItemUninstall.as_view(), name='stock-item-uninstall'),
|
|
||||||
|
|
||||||
re_path(r'^track/', include(stock_tracking_urls)),
|
re_path(r'^track/', include(stock_tracking_urls)),
|
||||||
|
|
||||||
# Individual stock items
|
# Individual stock items
|
||||||
|
@ -5,38 +5,23 @@ Django views for interacting with Stock app
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
|
||||||
from django.views.generic.edit import FormMixin
|
|
||||||
from django.views.generic import DetailView, ListView
|
from django.views.generic import DetailView, ListView
|
||||||
from django.forms.models import model_to_dict
|
|
||||||
from django.forms import HiddenInput
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from django.contrib.auth.models import Group
|
|
||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from moneyed import CURRENCIES
|
|
||||||
|
|
||||||
from InvenTree.views import AjaxUpdateView, AjaxDeleteView, AjaxCreateView
|
from InvenTree.views import AjaxUpdateView, AjaxDeleteView, AjaxCreateView
|
||||||
from InvenTree.views import QRCodeView
|
from InvenTree.views import QRCodeView
|
||||||
from InvenTree.views import InvenTreeRoleMixin
|
from InvenTree.views import InvenTreeRoleMixin
|
||||||
from InvenTree.forms import ConfirmForm
|
from InvenTree.forms import ConfirmForm
|
||||||
|
|
||||||
from InvenTree.helpers import str2bool
|
from InvenTree.helpers import str2bool
|
||||||
from InvenTree.helpers import extract_serial_numbers
|
|
||||||
|
|
||||||
from decimal import Decimal, InvalidOperation
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
|
|
||||||
from company.models import SupplierPart
|
|
||||||
from part.models import Part
|
|
||||||
from .models import StockItem, StockLocation, StockItemTracking
|
from .models import StockItem, StockLocation, StockItemTracking
|
||||||
|
|
||||||
import common.settings
|
import common.settings
|
||||||
from common.models import InvenTreeSetting
|
|
||||||
from users.models import Owner
|
|
||||||
|
|
||||||
from . import forms as StockForms
|
from . import forms as StockForms
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ function renderStockItem(name, data, parameters={}, options={}) {
|
|||||||
|
|
||||||
var part_detail = '';
|
var part_detail = '';
|
||||||
|
|
||||||
if (render_part_detail) {
|
if (render_part_detail && data.part_detail) {
|
||||||
part_detail = `<img src='${image}' class='select2-thumbnail'><span>${data.part_detail.full_name}</span> - `;
|
part_detail = `<img src='${image}' class='select2-thumbnail'><span>${data.part_detail.full_name}</span> - `;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
stockItemFields,
|
stockItemFields,
|
||||||
stockLocationFields,
|
stockLocationFields,
|
||||||
stockStatusCodes,
|
stockStatusCodes,
|
||||||
|
uninstallStockItem,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -2630,13 +2631,10 @@ function loadInstalledInTable(table, options) {
|
|||||||
table.find('.button-uninstall').click(function() {
|
table.find('.button-uninstall').click(function() {
|
||||||
var pk = $(this).attr('pk');
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
launchModalForm(
|
uninstallStockItem(
|
||||||
'{% url "stock-item-uninstall" %}',
|
pk,
|
||||||
{
|
{
|
||||||
data: {
|
onSuccess: function(response) {
|
||||||
'items[]': pk,
|
|
||||||
},
|
|
||||||
success: function() {
|
|
||||||
table.bootstrapTable('refresh');
|
table.bootstrapTable('refresh');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2647,6 +2645,43 @@ function loadInstalledInTable(table, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Launch a dialog to uninstall a stock item from another stock item
|
||||||
|
*/
|
||||||
|
function uninstallStockItem(installed_item_id, options={}) {
|
||||||
|
|
||||||
|
constructForm(
|
||||||
|
`/api/stock/${installed_item_id}/uninstall/`,
|
||||||
|
{
|
||||||
|
confirm: true,
|
||||||
|
method: 'POST',
|
||||||
|
title: '{% trans "Uninstall Stock Item" %}',
|
||||||
|
fields: {
|
||||||
|
location: {
|
||||||
|
icon: 'fa-sitemap',
|
||||||
|
},
|
||||||
|
note: {},
|
||||||
|
},
|
||||||
|
preFormContent: function(opts) {
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
if (installed_item_id == null) {
|
||||||
|
html += `
|
||||||
|
<div class='alert alert-block alert-info'>
|
||||||
|
{% trans "Select stock item to uninstall" %}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
onSuccess: function(response) {
|
||||||
|
handleFormSuccess(response, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Launch a dialog to install a stock item into another stock item
|
* Launch a dialog to install a stock item into another stock item
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user