2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-29 20:16:44 +00:00
2022-05-07 22:34:03 +10:00

344 lines
9.5 KiB
Python

"""
Django views for interacting with Stock app
"""
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from datetime import datetime
from django.views.generic import DetailView, ListView
from django.urls import reverse
from django.http import HttpResponseRedirect
from django.utils.translation import gettext_lazy as _
from InvenTree.views import AjaxUpdateView, AjaxDeleteView, AjaxCreateView
from InvenTree.views import QRCodeView
from InvenTree.views import InvenTreeRoleMixin
from InvenTree.forms import ConfirmForm
from InvenTree.helpers import str2bool
from .models import StockItem, StockLocation, StockItemTracking
import common.settings
from . import forms as StockForms
from plugin.views import InvenTreePluginViewMixin
class StockIndex(InvenTreeRoleMixin, InvenTreePluginViewMixin, ListView):
""" StockIndex view loads all StockLocation and StockItem object
"""
model = StockItem
template_name = 'stock/location.html'
context_obect_name = 'locations'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs).copy()
# Return all top-level locations
locations = StockLocation.objects.filter(parent=None)
context['locations'] = locations
context['items'] = StockItem.objects.all()
context['loc_count'] = StockLocation.objects.count()
context['stock_count'] = StockItem.objects.count()
# No 'ownership' checks are necessary for the top-level StockLocation view
context['user_owns_location'] = True
context['location_owner'] = None
context['ownership_enabled'] = common.models.InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
return context
class StockLocationDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView):
"""
Detailed view of a single StockLocation object
"""
context_object_name = 'location'
template_name = 'stock/location.html'
queryset = StockLocation.objects.all()
model = StockLocation
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['ownership_enabled'] = common.models.InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
context['location_owner'] = context['location'].get_location_owner()
context['user_owns_location'] = context['location'].check_ownership(self.request.user)
return context
class StockItemDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView):
"""
Detailed view of a single StockItem object
"""
context_object_name = 'item'
template_name = 'stock/item.html'
queryset = StockItem.objects.all()
model = StockItem
def get_context_data(self, **kwargs):
"""
Add information on the "next" and "previous" StockItem objects,
based on the serial numbers.
"""
data = super().get_context_data(**kwargs)
if self.object.serialized:
data['previous'] = self.object.get_next_serialized_item(reverse=True)
data['next'] = self.object.get_next_serialized_item()
data['ownership_enabled'] = common.models.InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
data['item_owner'] = self.object.get_item_owner()
data['user_owns_item'] = self.object.check_ownership(self.request.user)
return data
def get(self, request, *args, **kwargs):
""" check if item exists else return to stock index """
stock_pk = kwargs.get('pk', None)
if stock_pk:
try:
stock_item = StockItem.objects.get(pk=stock_pk)
except StockItem.DoesNotExist:
stock_item = None
if not stock_item:
return HttpResponseRedirect(reverse('stock-index'))
return super().get(request, *args, **kwargs)
class StockLocationQRCode(QRCodeView):
""" View for displaying a QR code for a StockLocation object """
ajax_form_title = _("Stock Location QR code")
role_required = ['stock_location.view', 'stock.view']
def get_qr_data(self):
""" Generate QR code data for the StockLocation """
try:
loc = StockLocation.objects.get(id=self.pk)
return loc.format_barcode()
except StockLocation.DoesNotExist:
return None
class StockItemReturnToStock(AjaxUpdateView):
"""
View for returning a stock item (which is assigned to a customer) to stock.
"""
model = StockItem
ajax_form_title = _("Return to Stock")
context_object_name = "item"
form_class = StockForms.ReturnStockItemForm
def validate(self, item, form, **kwargs):
location = form.cleaned_data.get('location', None)
if not location:
form.add_error('location', _('Specify a valid location'))
def save(self, item, form, **kwargs):
location = form.cleaned_data.get('location', None)
if location:
item.returnFromCustomer(location, self.request.user)
def get_data(self):
return {
'success': _('Stock item returned from customer')
}
class StockItemDeleteTestData(AjaxUpdateView):
"""
View for deleting all test data
"""
model = StockItem
form_class = ConfirmForm
ajax_form_title = _("Delete All Test Data")
role_required = ['stock.change', 'stock.delete']
def get_form(self):
return ConfirmForm()
def post(self, request, *args, **kwargs):
valid = False
stock_item = StockItem.objects.get(pk=self.kwargs['pk'])
form = self.get_form()
confirm = str2bool(request.POST.get('confirm', False))
if confirm is not True:
form.add_error('confirm', _('Confirm test data deletion'))
form.add_error(None, _('Check the confirmation box'))
else:
stock_item.test_results.all().delete()
valid = True
data = {
'form_valid': valid,
}
return self.renderJsonResponse(request, form, data)
class StockItemQRCode(QRCodeView):
""" View for displaying a QR code for a StockItem object """
ajax_form_title = _("Stock Item QR Code")
role_required = 'stock.view'
def get_qr_data(self):
""" Generate QR code data for the StockItem """
try:
item = StockItem.objects.get(id=self.pk)
return item.format_barcode()
except StockItem.DoesNotExist:
return None
class StockItemConvert(AjaxUpdateView):
"""
View for 'converting' a StockItem to a variant of its current part.
"""
model = StockItem
form_class = StockForms.ConvertStockItemForm
ajax_form_title = _('Convert Stock Item')
ajax_template_name = 'stock/stockitem_convert.html'
context_object_name = 'item'
def get_form(self):
"""
Filter the available parts.
"""
form = super().get_form()
item = self.get_object()
form.fields['part'].queryset = item.part.get_conversion_options()
return form
def save(self, obj, form):
stock_item = self.get_object()
variant = form.cleaned_data.get('part', None)
stock_item.convert_to_variant(variant, user=self.request.user)
return stock_item
class StockLocationDelete(AjaxDeleteView):
"""
View to delete a StockLocation
Presents a deletion confirmation form to the user
"""
model = StockLocation
success_url = '/stock'
ajax_template_name = 'stock/location_delete.html'
context_object_name = 'location'
ajax_form_title = _('Delete Stock Location')
class StockItemDelete(AjaxDeleteView):
"""
View to delete a StockItem
Presents a deletion confirmation form to the user
"""
model = StockItem
success_url = '/stock/'
ajax_template_name = 'stock/item_delete.html'
context_object_name = 'item'
ajax_form_title = _('Delete Stock Item')
class StockItemTrackingDelete(AjaxDeleteView):
"""
View to delete a StockItemTracking object
Presents a deletion confirmation form to the user
"""
model = StockItemTracking
ajax_template_name = 'stock/tracking_delete.html'
ajax_form_title = _('Delete Stock Tracking Entry')
class StockItemTrackingEdit(AjaxUpdateView):
""" View for editing a StockItemTracking object """
model = StockItemTracking
ajax_form_title = _('Edit Stock Tracking Entry')
form_class = StockForms.TrackingEntryForm
class StockItemTrackingCreate(AjaxCreateView):
""" View for creating a new StockItemTracking object.
"""
model = StockItemTracking
ajax_form_title = _("Add Stock Tracking Entry")
form_class = StockForms.TrackingEntryForm
def post(self, request, *args, **kwargs):
self.request = request
self.form = self.get_form()
valid = False
if self.form.is_valid():
stock_id = self.kwargs['pk']
if stock_id:
try:
stock_item = StockItem.objects.get(id=stock_id)
# Save new tracking information
tracking = self.form.save(commit=False)
tracking.item = stock_item
tracking.user = self.request.user
tracking.quantity = stock_item.quantity
tracking.date = datetime.now().date()
tracking.system = False
tracking.save()
valid = True
except (StockItem.DoesNotExist, ValueError):
pass
data = {
'form_valid': valid
}
return self.renderJsonResponse(request, self.form, data=data)