from django.shortcuts import render, redirect from django.urls import reverse from django.contrib.auth import logout, login from django.contrib.auth.forms import AuthenticationForm as AuthForm from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth import update_session_auth_hash import django.forms as forms from django.views.generic import TemplateView, DetailView from django.contrib.auth.mixins import LoginRequiredMixin from ..models import Storage, Stock, Component, Distributor, Manufacturer, Package, ComponentParameter, DistributorNum from django.core.paginator import Paginator from django.core.exceptions import ValidationError from django.db import IntegrityError from django.db.models import ProtectedError from ..forms import * from .component_import import import_components_from_csv from django.db.models import Q from django.db.models.functions import Lower from django.forms import formset_factory from django.http import HttpResponse import uuid 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(): sub_name = f.cleaned_data['storage_name'] 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 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) update_watermark_error = None 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)