From e8538cd5345027fe8e53f1e090b9c3fc89e1ca6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Sat, 14 Aug 2021 00:25:19 +0200 Subject: [PATCH] Implement Storage navigation and other helpful stuff --- shimatta_kenkyusho/api/serializers.py | 3 + shimatta_kenkyusho/api/views.py | 14 +++++ shimatta_kenkyusho/parts/models.py | 18 ++++-- shimatta_kenkyusho/parts/views.py | 27 +++++++- shimatta_kenkyusho/templates/base.html | 2 +- .../templates/parts/stocks-detail.html | 63 +++++++++++++++---- .../templates/parts/stocks.html | 36 +++++++++++ 7 files changed, 145 insertions(+), 18 deletions(-) diff --git a/shimatta_kenkyusho/api/serializers.py b/shimatta_kenkyusho/api/serializers.py index 3d22f2a..aa1ceef 100644 --- a/shimatta_kenkyusho/api/serializers.py +++ b/shimatta_kenkyusho/api/serializers.py @@ -50,3 +50,6 @@ class DistributorSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = parts_models.Distributor fields = '__all__' + +class StockIncrementDecrementSerializer(serializers.Serializer): + increment = serializers.IntegerField() diff --git a/shimatta_kenkyusho/api/views.py b/shimatta_kenkyusho/api/views.py index 202f41b..fa37ad2 100644 --- a/shimatta_kenkyusho/api/views.py +++ b/shimatta_kenkyusho/api/views.py @@ -15,6 +15,7 @@ from django.utils import timezone from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.authtoken.models import Token from rest_framework.throttling import AnonRateThrottle +from rest_framework.decorators import action # Create your views here. class UserViewSet(viewsets.ReadOnlyModelViewSet): @@ -48,6 +49,19 @@ class PartsStockViewSet(viewsets.ModelViewSet): serializer_class = StockSerializer permission_classes = [permissions.DjangoModelPermissions] + @action(detail=True, methods=['patch'], name="change-stock-count") + def update_stock(self, request, pk=None): + stock = self.get_object() + serializer = StockIncrementDecrementSerializer(data=request.data) + if serializer.is_valid(): + increment = serializer.data['increment'] + if stock.atomic_increment(increment): + return Response({'status': 'Stock updated', 'update_value': increment}) + else: + return Response({'status': 'Stock not updated. Would be negative'}, status=status.HTTP_400_BAD_REQUEST) + else: + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + class PartsPackageViewSet(viewsets.ModelViewSet): queryset = parts_models.Package.objects.all() serializer_class = PackageSerializer diff --git a/shimatta_kenkyusho/parts/models.py b/shimatta_kenkyusho/parts/models.py index f855d0c..0c317b4 100644 --- a/shimatta_kenkyusho/parts/models.py +++ b/shimatta_kenkyusho/parts/models.py @@ -89,7 +89,10 @@ class Storage(models.Model): def get_total_stock_amount(self): stocks = Stock.objects.filter(storage=self) - return stocks.aggregate(Sum('amount'))['amount__sum'] + sum = stocks.aggregate(Sum('amount'))['amount__sum'] + if sum is None: + sum = 0 + return sum def save(self, *args, **kwargs): self.validate_unique() @@ -216,9 +219,16 @@ class Stock(models.Model): def __str__(self): return str(self.component) + ' @ ' + str(self.amount) + ' in ' + str( self.storage) - - def get_under_watermark(): - return Stock.objects.filter(amount__lt = F('watermark')) + + @staticmethod + def get_under_watermark(user_filter = None, invert: bool = False): + query = Stock.objects.filter(amount__lt = F('watermark')) + if user_filter is not None: + if invert: + query = query.exclude(storage__responsible=user_filter) + else: + query = query.filter(storage__responsible=user_filter) + return query class DistributorNum(models.Model): class Meta: diff --git a/shimatta_kenkyusho/parts/views.py b/shimatta_kenkyusho/parts/views.py index 00ec9b6..8531d82 100644 --- a/shimatta_kenkyusho/parts/views.py +++ b/shimatta_kenkyusho/parts/views.py @@ -10,6 +10,7 @@ from django.views.generic import TemplateView, DetailView from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from .models import Storage, Stock from .qr_parser import QrCodeValidator +from django.core.paginator import Paginator class QrSearchForm(forms.Form): my_qr_validator = QrCodeValidator() @@ -101,11 +102,25 @@ class StockView(LoginRequiredMixin, BaseTemplateMixin, TemplateView): template_name = 'parts/stocks.html' base_title = 'Stocks' navbar_selected = 'Stocks' + default_pagination_size = 25 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - context['low_stocks'] = Stock.get_under_watermark() - context['storages'] = Storage.objects.filter(parent_storage=None) + + storage_page = self.request.GET.get('storage_page') + if storage_page is None: + storage_page = 1 + low_stock_page = self.request.GET.get('low_stock_page') + if low_stock_page is None: + low_stock_page = 1 + + storage_paginator = Paginator(Storage.objects.filter(parent_storage=None), self.default_pagination_size) + low_stock_paginator = Paginator(Stock.get_under_watermark(), + self.default_pagination_size) + + context['low_stocks'] = low_stock_paginator.get_page(low_stock_page) + context['storages'] = storage_paginator.get_page(storage_page) + return context class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView): @@ -114,6 +129,7 @@ class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView): pk_url_kwarg = 'uuid' base_title = '' navbar_selected = 'Stocks' + default_pagination_size = 8 def get_breadcrumbs(self): crumbs = self.object.get_path_components() @@ -125,4 +141,11 @@ class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView): self.base_title = 'Stocks / ' + self.object.name context = super().get_context_data(**kwargs) context['breadcrumbs'] = self.get_breadcrumbs() + + storage_page = self.request.GET.get('storage_page') + if storage_page is None: + storage_page = 1 + storage_paginator = Paginator(Storage.objects.filter(parent_storage=self.object), self.default_pagination_size) + + context['storages'] = storage_paginator.get_page(storage_page) return context diff --git a/shimatta_kenkyusho/templates/base.html b/shimatta_kenkyusho/templates/base.html index a4b7996..41c54c8 100644 --- a/shimatta_kenkyusho/templates/base.html +++ b/shimatta_kenkyusho/templates/base.html @@ -25,7 +25,7 @@ {% endfor %} {% if base.navbar.has_user %} -
+ {% csrf_token %}
diff --git a/shimatta_kenkyusho/templates/parts/stocks-detail.html b/shimatta_kenkyusho/templates/parts/stocks-detail.html index 310236e..5f55aab 100644 --- a/shimatta_kenkyusho/templates/parts/stocks-detail.html +++ b/shimatta_kenkyusho/templates/parts/stocks-detail.html @@ -2,18 +2,59 @@ {% load qr_code %} {% block content %}
- + -

Stocks in {{object.get_full_path }}

-{% qr_from_text object.get_qr_code size="m" image_format="svg" %} +
+
+ {% qr_from_text object.get_qr_code size="m" image_format="svg" %} +
+
+ {% if object.parent_storage %} +

Sub-Storages Parent Storage

+ {% else %} +

Sub-Storages Stock Overview

+ {% endif %} + + +
+
{% endblock content %} \ No newline at end of file diff --git a/shimatta_kenkyusho/templates/parts/stocks.html b/shimatta_kenkyusho/templates/parts/stocks.html index 03842b4..dbb9f3d 100644 --- a/shimatta_kenkyusho/templates/parts/stocks.html +++ b/shimatta_kenkyusho/templates/parts/stocks.html @@ -31,6 +31,24 @@ {% endfor %} +

Storages

@@ -47,6 +65,24 @@ {% endfor %}
+