from django.shortcuts import render, redirect from django.urls import resolve, reverse from django.contrib.auth import logout, login from django.contrib.auth.models import User from django.http import HttpResponse from .navbar import NavBar from django.contrib.auth.forms import AuthenticationForm as AuthForm from django.views import View import django.forms as forms 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 from django.core.exceptions import ValidationError class QrSearchForm(forms.Form): my_qr_validator = QrCodeValidator() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) qr_search = forms.CharField(label='qr_search', validators=[my_qr_validator]) class BaseTemplateMixin(object): navbar_selected = '' base_title = '' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) base_context = { 'navbar': NavBar.get_navbar(self.navbar_selected, self.request.user), 'title': NavBar.get_brand()+' / '+ self.base_title, 'login_active': False, } context['base'] = base_context return context def post(self, request, *args, **kwargs): data = request.POST if 'qr_search' not in data: super().post(request, *args, **kwargs) print('QR',data['qr_search']) f = QrSearchForm(data) if f.is_valid(): return redirect(f.my_qr_validator.get_redirect_url(f.cleaned_data['qr_search'])) return self.get(request) class MainView(BaseTemplateMixin, TemplateView): template_name = 'parts/main.html' navbar_selected = 'Main' base_title = 'Main' def logout_view(request): logout(request) return redirect('parts-main') def login_view(request): base_context = { 'navbar': NavBar.get_navbar('Login', request.user), 'title': NavBar.get_brand()+' / '+'Login', 'login_active': True, } if request.user.is_authenticated: next_param = request.GET.get('next') if next_param is not None: return redirect(next_param) else: return redirect('parts-main') if request.method == 'POST': form = AuthForm(data=request.POST) if form.is_valid(): valid_user = form.get_user() login(request, valid_user) next_param = request.GET.get('next') if next_param is not None: return redirect(next_param) else: return redirect('parts-main') else: form = AuthForm() context = { 'base': base_context, 'form': form, } return render(request, 'parts/login.html', context) # Create your views here. class ComponentView(LoginRequiredMixin, BaseTemplateMixin, TemplateView): template_name = 'parts/components.html' base_title = 'Components' navbar_selected = 'Components' class AddSubStorageForm(forms.Form): storage_name = forms.CharField(label="storage_name", initial='') responsible = forms.CharField(label='responsible_user') 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.username context['add_storage_form'] = add_stor_form return context def handle_add_storage(self, request, **kwargs): return_invalid_form = False f = AddSubStorageForm(data=request.POST) if f.is_valid(): new_storage_name = f.cleaned_data['storage_name'] try: resp_user = User.objects.get(username=f.cleaned_data['responsible']) except Exception as _: resp_user = None f.add_error('responsible', 'Invalid Responsible User') return_invalid_form = True if resp_user is not None: try: Storage.objects.create(name=new_storage_name, responsible=resp_user, parent_storage=None) except ValidationError as verr: return_invalid_form = True f.add_error('storage_name', ' .'.join(verr.messages)) else: return_invalid_form = True context = self.get_context_data(**kwargs) if return_invalid_form: 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 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') 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) add_storage_form = AddSubStorageForm() add_storage_form.fields['responsible'].initial = self.request.user.username context['add_storage_form'] = add_storage_form context['delete_storage_error'] = None 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: user = User.objects.get(username=f.cleaned_data['responsible']) try: Storage.objects.create(name=sub_name, parent_storage=self.object, responsible=user) except ValidationError as v_err: f.add_error('storage_name', '. '.join(v_err.messages)) except: f.add_error('responsible', 'Invalid user') context = self.get_context_data(**kwargs) context['add_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 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-delete-storage' in request.POST: return self.handle_del_storage_post(request, **kwargs) return super().post(request, *args, **kwargs)