import uuid from django.shortcuts import redirect from django.urls import reverse from django.views.generic import TemplateView, DetailView from django.contrib.auth.mixins import LoginRequiredMixin from django.core.paginator import Paginator from django.core.exceptions import ValidationError from django.db.models import Q from django.db.models.functions import Lower from ..models import Storage, Stock from ..forms import * from .generic_views import BaseTemplateMixin 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) 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) add_stor_form = AddSubStorageForm() add_stor_form.fields['responsible'].initial = self.request.user.id context['add_storage_form'] = add_stor_form return context def handle_add_storage(self, request, **kwargs): f = AddSubStorageForm(data=request.POST) if f.is_valid(): sub_name = f.cleaned_data['storage_name'] try: Storage.objects.create(name=sub_name, responsible=f.cleaned_data['responsible'], is_template=f.cleaned_data['is_template'], template=f.cleaned_data.get('template')) except ValidationError as v_err: f.add_error('storage_name', '. '.join(v_err.messages)) context = self.get_context_data(**kwargs) context['add_storage_form'] = f return self.render_to_response(context) def post(self, request, **kwargs): if 'submit-add-storage' in request.POST: return self.handle_add_storage(request, **kwargs) return super().post(request, **kwargs) class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView): template_name = 'parts/stocks-detail.html' model = Storage pk_url_kwarg = 'uuid' base_title = '' navbar_selected = 'Stocks' default_pagination_size = 8 def get_breadcrumbs(self): crumbs = self.object.get_path_components() # Reverse list and drop the last element of the reversed list crumbs = crumbs[::-1][:-1] return crumbs def search_stock_queryset(self, search): stocks_in_storage = Stock.objects.filter(storage=self.object).order_by(Lower('component__name')) if search is None or search == '': return stocks_in_storage if search.startswith('[comp_uuid]'): search = search.replace('[comp_uuid]', '') # Check if the searhc equals a UUID test_uuid = None try: test_uuid = uuid.UUID(search) except: pass if test_uuid is not None: stocks_in_storage = stocks_in_storage.filter(Q(component__id = test_uuid) | Q(id= test_uuid)) else: stocks_in_storage = stocks_in_storage.filter(Q(component__name__icontains = search) | Q(component__package__name__icontains = search) | Q(component__manufacturer__name__icontains = search)) return stocks_in_storage def get_context_data(self, **kwargs): 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', default=1) storage_paginator = Paginator(Storage.objects.filter(parent_storage=self.object), self.default_pagination_size) stock_search_input = self.request.GET.get('search') componente_stock_page = self.request.GET.get('stock_page', default=1) stock_paginator = Paginator(self.search_stock_queryset(stock_search_input), self.default_pagination_size) context['storages'] = storage_paginator.get_page(storage_page) stocks = stock_paginator.get_page(componente_stock_page) context['stocks'] = stocks context['stock_search'] = stock_search_input add_storage_form = AddSubStorageForm() add_storage_form.fields['responsible'].initial = self.request.user.id context['add_storage_form'] = add_storage_form change_storage_form = ChangeStorageForm() change_storage_form.fields['storage_name'].initial = self.object.name change_storage_form.fields['verbose_name'].initial = self.object.verbose_name change_storage_form.fields['responsible'].initial = self.object.responsible.id change_storage_form.fields['is_template'].initial = self.object.is_template context['change_storage_form'] = change_storage_form context['delete_storage_error'] = None context['add_stock_form'] = AddStockForm() return context def handle_add_storage_post(self, request, **kwargs): f = AddSubStorageForm(data=request.POST) if f.is_valid(): sub_name = f.cleaned_data['storage_name'] try: Storage.objects.create(name=sub_name, verbose_name=f.cleaned_data.get('verbose_name'), parent_storage=self.object, responsible=f.cleaned_data['responsible'], is_template=f.cleaned_data['is_template'], template=f.cleaned_data.get('template')) except ValidationError as v_err: f.add_error('storage_name', '. '.join(v_err.messages)) context = self.get_context_data(**kwargs) context['add_storage_form'] = f return self.render_to_response(context) def handle_change_storage_post(self, request, **kwargs): f = ChangeStorageForm(data=request.POST) if f.is_valid(): try: self.object.name = f.cleaned_data['storage_name'] self.object.verbose_name = f.cleaned_data.get('verbose_name') self.object.responsible = f.cleaned_data['responsible'] self.object.is_template = f.cleaned_data['is_template'] self.object.save() except ValidationError as v_err: f.add_error('storage_name', '. '.join(v_err.messages)) context = self.get_context_data(**kwargs) context['change_storage_form'] = f return self.render_to_response(context) def handle_del_storage_post(self, request, **kwargs): parent = self.object.parent_storage try: self.object.delete() except: context = self.get_context_data(**kwargs) context['delete_storage_errors'] = ['Error deleting Storage '+str(self.object)] return self.render_to_response(context) if parent is None: return redirect('parts-stocks') else: return redirect(reverse('parts-stocks-detail', kwargs={'uuid':parent.id})) def handle_del_stock_post(self, request, **kwargs): del_error = None # TODO: Check error handling. This is clearly not working as intended :P if 'stock_uuid' in request.POST: f = DeleteStockForm(data=request.POST) if f.is_valid(): try: s = Stock.objects.get(id=f.cleaned_data['stock_uuid']) print(s.storage) print(self.object) if s.storage == self.object: s.delete() else: del_error = 'Cannot delete stock from another storage.' except: del_error = 'Could not find requested stock in this storage.' context = self.get_context_data(**kwargs) return self.render_to_response(context) def handle_update_watermark(self, request, **kwargs): edit_form = EditWatermarkForm(data=request.POST) if edit_form.is_valid(): edit_form.save() else: pass # Todo: Handle error context = self.get_context_data(**kwargs) return self.render_to_response(context) def handle_amount_change_post(self, request, increase, **kwargs): edit_form = EditStockAmountForm(data=request.POST) if edit_form.is_valid(): edit_form.save(increase) context = self.get_context_data(**kwargs) return self.render_to_response(context) def handle_add_stock_post(self, request, **kwargs): f = AddStockForm(data=request.POST) error_occured = False if f.is_valid(): try: f.save(self.object) except Exception as ex: f.add_error('', str(ex)) error_occured = True else: error_occured = True context = self.get_context_data(**kwargs) if error_occured: context['add_stock_form'] = f return self.render_to_response(context) def post(self, request, *args, **kwargs): self.object = self.get_object() if 'submit-add-storage' in request.POST: return self.handle_add_storage_post(request, **kwargs) elif 'submit-change-storage' in request.POST: return self.handle_change_storage_post(request, **kwargs) elif 'submit-delete-storage' in request.POST: return self.handle_del_storage_post(request, **kwargs) elif 'submit-delete-stock' in request.POST: return self.handle_del_stock_post(request, **kwargs) elif 'submit-edit-watermark' in request.POST: return self.handle_update_watermark(request, **kwargs) elif 'submit-amount-reduce' in request.POST: return self.handle_amount_change_post(request, False, **kwargs) elif 'submit-amount-increase' in request.POST: return self.handle_amount_change_post(request, True, **kwargs) elif 'submit-add-stock' in request.POST: return self.handle_add_stock_post(request, **kwargs) return super().post(request, *args, **kwargs)