from django.shortcuts import render, redirect from django.http import HttpResponse from django.utils.encoding import smart_str from auditlog.models import LogEntry # from django.template import loader from django.core.urlresolvers import reverse # import django.contrib.auth as auth # from django.conf import settings # Create your views here. from django.core.exceptions import ObjectDoesNotExist # TemplateView was unused from django.views.generic import ListView from django.views.generic.detail import DetailView from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.core.urlresolvers import reverse_lazy from dispatch.models import Customer, Load, Paperwork, \ Invoice, UserInvoiceNumber, Identity, Settings from dispatch.forms import AddPaperworkForm, InviteForm from django.contrib.auth import get_user_model from django.contrib.auth.mixins import UserPassesTestMixin # from django.http import HttpResponseRedirect from .misc import get_week_dates, split_loads_by_day, zip_attachments_for_loads, \ get_valid_filename import re, os, tempfile, datetime User = get_user_model() def home(request): return redirect(reverse('load_list')) class LoadDateSort(DetailView): def get_context_data(self, **kwargs): context = super(DetailView, self).get_context_data(**kwargs) week_dates = get_week_dates(self.request.GET.get('date', None)) loads = self.get_object().load_set.filter( date__range=(week_dates['start_date'], week_dates['end_date']) ).prefetch_related('customer') context['loads_nosplit'] = loads.order_by('date') context['loads'] = split_loads_by_day( loads, week_dates['start_date'], week_dates['end_date']) context['week_dates'] = week_dates return context class FilteredListView(ListView): def get_queryset(self): base_qs = super(FilteredListView, self).get_queryset() if not self.request.user.is_superuser: return base_qs.filter(user=self.request.user) return base_qs class FilteredUpdateView(UpdateView): def get_queryset(self): base_qs = super(FilteredUpdateView, self).get_queryset() if not self.request.user.is_superuser: return base_qs.filter(user=self.request.user) return base_qs class FilteredDeleteView(DeleteView): def get_queryset(self): base_qs = super(FilteredDeleteView, self).get_queryset() if not self.request.user.is_superuser: return base_qs.filter(user=self.request.user) return base_qs # Driver CRUD class DriverList(UserPassesTestMixin, ListView): template_name = "dispatch/drivers/list.html" model = User paginate_by = 10 def test_func(self): return self.request.user.is_superuser class DriverDetail(UserPassesTestMixin, DetailView): template_name = "dispatch/drivers/detail.html" model = User def test_func(self): # Seems a little hacky at first but it works! return self.request.user.is_superuser or \ self.get_object().pk is self.request.user.id def get_context_data(self, **kwargs): # Shit gets fucky with super() really fast, but this seems to work context = super(DriverDetail, self).get_context_data(**kwargs) try: context['ident'] = Identity.objects.get(user=self.get_object().pk) except Exception: context['ident'] = None try: context['invoice_number'] = \ UserInvoiceNumber.objects.get(user=self.get_object().pk) except ObjectDoesNotExist: uinv = UserInvoiceNumber(user=self.get_object()) uinv.save() context['invoice_number'] = uinv # A stupid hack to set a default Bill to Identity on first super user # login try: context['default_bill_to'] = Identity.objects.get(pk=\ Settings.objects.get(key='default_bill_to').value) except: if self.request.user.is_superuser: try: print("No default Identity Set") bill_to = self.request.user.identity default = Settings(key='default_bill_to', value=bill_to.pk) default.save() except Exception as e: print(e) print("No identity, you should be redirected") context['default_bill_to'] = None return context class DriverSummary(UserPassesTestMixin, LoadDateSort): template_name = "dispatch/drivers/summary.html" model = User def test_func(self): # Seems a little hacky at first but it works! return self.request.user.is_superuser or \ self.get_object().pk is self.request.user.id def get_context_data(self, **kwargs): # Shit gets fucky with super() really fast, but this seems to work context = super(DriverSummary, self).get_context_data(**kwargs) stats = {} stats['count'], stats['average'], stats['sum'] = (0, 0, 0) context['can_invoice'] = True context['related_invoices'] = Invoice.objects.filter( invoice_date__range=(context['week_dates']['start_date'], context['week_dates']['end_date']), user=self.object) loads_by_date = context['loads'] if len(context['related_invoices']) >= 1: context['can_invoice'] = False for d in loads_by_date: # Iterate over the array for the given date for l in loads_by_date[d]: stats['count'] += 1 stats['sum'] += l.amount # Any load not up to par will break the chain if not l.can_invoice(): context['can_invoice'] = False if stats['sum'] is not 0 and stats['count'] is not 0: stats['average'] = stats['sum']/stats['count'] # Add our stats to the context so we can use it in the template context['stats'] = stats return context class AuditLog(UserPassesTestMixin, ListView): template_name = "dispatch/log/summary.html" model = LogEntry def test_func(self): return self.request.user.is_superuser class DriverUpdate(UserPassesTestMixin, UpdateView): template_name = "dispatch/drivers/edit.html" model = User # fields = ['username', 'first_name','last_name','email','groups'] fields = [] default_fields = ['first_name', 'last_name', 'email'] superuser_fields = ['first_name', 'last_name', 'email', 'is_active', 'is_superuser'] def set_fields(self, user): if user.is_superuser: self.fields = self.superuser_fields else: self.fields = self.default_fields def post(self, request, *args, **kwargs): self.set_fields(request.user) return super(DriverUpdate, self).post(request) def get(self, request, *args, **kwargs): self.set_fields(request.user) return super(DriverUpdate, self).get(request) def get_context_data(self, **kwargs): # Shit gets fucky with super() really fast, but this seems to work context = super(DriverUpdate, self).get_context_data(**kwargs) return context def test_func(self): # Seems a little hacky at first but it works! test = self.request.user.is_superuser or \ self.get_object().pk is self.request.user.id print(test) return test # Customer CRUD class CustomerList(ListView): template_name = "dispatch/companies/list.html" model = Customer paginate_by = 10 class CustomerCreate(UserPassesTestMixin, CreateView): template_name = "dispatch/companies/create.html" model = Customer success_url = reverse_lazy('customer_list') fields = ['name', 'address', 'phone_number', 'email_address'] def test_func(self): return self.request.user.is_superuser class CustomerDetail(LoadDateSort): template_name = "dispatch/companies/detail.html" model = Customer def CustomerDownload(request, pk): customer = Customer.objects.get(pk=pk) week_dates = get_week_dates(request.GET.get('date', None)) loads = customer.load_set.filter( date__range=(week_dates['start_date'], week_dates['end_date'])) basename, fh = zip_attachments_for_loads(loads, customer.name, week_dates['start_date']) response = HttpResponse( fh.read(), content_type='application/force-download') response['Content-Disposition'] = \ 'attachment; filename="{}"'.format(smart_str(basename)) response['X-Sendfile'] = smart_str(fh) print('%r' % response) return response def DriverDownload(request, pk): print(dir(request)) user = User.objects.get(pk=pk) week_dates = get_week_dates(request.GET.get('date', None)) loads = user.load_set.filter( date__range=(week_dates['start_date'], week_dates['end_date'])) basename, fh = zip_attachments_for_loads(loads, user.identity.name, week_dates['start_date']) response = HttpResponse( fh.read(), content_type='application/force-download') response['Content-Disposition'] = \ 'attachment; filename="{}"'.format(smart_str(basename)) response['X-Sendfile'] = smart_str(fh) # print('%r' % response) return response class CustomerUpdate(UserPassesTestMixin, UpdateView): template_name = "dispatch/companies/edit.html" model = Customer success_url = reverse_lazy('customer_list') fields = ['name', 'address', 'phone_number', 'email_address'] def test_func(self): return self.request.user.is_superuser class CustomerDelete(UserPassesTestMixin, DeleteView): template_name = "dispatch/companies/delete.html" model = Customer success_url = reverse_lazy('customer_list') def test_func(self): return self.request.user.is_superuser # Load CRUD class LoadList(FilteredListView): template_name = "dispatch/loads/list.html" model = Load def get_queryset(self): base_qs = super(LoadList, self).get_queryset() wd = get_week_dates(self.request.GET.get('date', None)) return base_qs.filter(date__range=(wd['start_date'], wd['end_date'])) def get_context_data(self, **kwargs): context = super(LoadList, self).get_context_data(**kwargs) wd = get_week_dates(self.request.GET.get('date', None)) context['week_dates'] = wd context['loads'] = split_loads_by_day( self.object_list, wd['start_date'], wd['end_date']) return context class LoadCreate(CreateView): template_name = "dispatch/loads/create.html" model = Load fields = [] default_fields = ['date', 'customer', 'description', 'delivered_to', 'amount'] superuser_fields = ['user', 'date', 'customer', 'description', 'delivered_to', 'amount'] def set_fields(self, user): if user.is_superuser: self.fields = self.superuser_fields else: self.fields = self.default_fields def post(self, request): self.set_fields(request.user) return super(LoadCreate, self).post(request) def get(self, request): self.set_fields(request.user) return super(LoadCreate, self).get(request) def form_valid(self, form): if not self.request.user.is_superuser: load = form.save(commit=False) load.user = self.request.user return super(LoadCreate, self).form_valid(form) class LoadDetail(DetailView): template_name = "dispatch/loads/detail.html" model = Load def get_context_data(self, **kwargs): context = super(LoadDetail, self).get_context_data(**kwargs) context['paperwork_list'] = Paperwork.objects.filter( load=context['object']) return context class LoadUpdate(UserPassesTestMixin, FilteredUpdateView): template_name = "dispatch/loads/edit.html" model = Load fields = [] default_fields = ['date', 'customer', 'description', 'delivered_to', 'amount'] superuser_fields = ['user', 'date', 'customer', 'description', 'delivered_to', 'amount'] def set_fields(self, user): if user.is_superuser: self.fields = self.superuser_fields else: self.fields = self.default_fields def post(self, request, pk): self.set_fields(request.user) return super(LoadUpdate, self).post(request) def get(self, request, pk): self.set_fields(request.user) return super(LoadUpdate, self).get(request) def form_valid(self, form): if not self.request.user.is_superuser: load = form.save(commit=False) load.user = self.request.user return super(LoadUpdate, self).form_valid(form) def test_func(self): return self.request.user.is_superuser or \ self.get_object().user.pk == self.request.user.pk class LoadDelete(UserPassesTestMixin, FilteredDeleteView): template_name = "dispatch/loads/delete.html" model = Load success_url = reverse_lazy('load_list') def test_func(self): return self.request.user.is_superuser def InviteUser(request): if request.method == 'POST': form = InviteForm(request.POST) if form.is_valid(): request.user.send_invite( form.cleaned_data.get('first_name'), form.cleaned_data.get('email_address') ) return redirect(reverse('driver_list')) else: form = InviteForm() ctx = {'form': form} return render(request, 'dispatch/invite_user.html', ctx) # Paperwork Uploads def PaperworkUpload(request, load_id): load = Load.objects.get(pk=load_id) if request.method == 'POST': form = AddPaperworkForm(request.POST, request.FILES) if form.is_valid(): pw = form.save(commit=False) pw.load = load pw.save() return redirect(reverse('load_detail', kwargs={'pk': load_id})) else: form = AddPaperworkForm() ctx = {'form': form, 'load': load} return render(request, 'dispatch/paperwork/add.html', ctx) def PaperworkDelete(request, load_id, pk): # TODO: Someday we should return the errors deleting the file, if any try: p = Paperwork.objects.get(pk=pk) p.delete() except Exception as e: print(e) return redirect(reverse('load_detail', kwargs={'pk': load_id})) # Specifically for downloading with the filename set to the description of the # load def PaperworkDownload(request, load_id, pk): try: load = Load.objects.get(pk=load_id) paperwork = Paperwork.objects.get(pk=pk) if os.path.exists(paperwork.document.path): with open(paperwork.document.path, 'rb') as fh: try: exp = re.compile('\.[^.]*$', re.IGNORECASE) ext = exp.findall(paperwork.document.path) ext = ext[0] except Exception as e: print(e) ext = '.pdf' filename = get_valid_filename(load.description + " - " + \ load.delivered_to + ext) response = HttpResponse( fh.read(), content_type='application/force-download') response['Content-Disposition'] = \ 'attachment; filename="{}"'.format(smart_str(filename)) response['X-Sendfile'] = smart_str(paperwork.document.path) return response except Exception as e: print(e) # User Invoice Numbers class UserInvoiceNumberUpdate(UserPassesTestMixin, UpdateView): template_name = "dispatch/userinvoicenumber/edit.html" model = UserInvoiceNumber fields = [] default_fields = ['number'] superuser_fields = ['number', 'user'] def set_fields(self, user): if user.is_superuser: self.fields = self.superuser_fields else: self.fields = self.default_fields def post(self, request, *args, **kwargs): self.set_fields(request.user) return super(UserInvoiceNumberUpdate, self).post(request) def get(self, request, *args, **kwargs): self.set_fields(request.user) return super(UserInvoiceNumberUpdate, self).get(request) def test_func(self): return self.request.user.is_superuser or \ self.get_object().user.pk is self.request.user.pk # Identity class IdentityDetail(DetailView): template_name = "dispatch/identity/detail.html" model = Identity def SetDefaultIdentity(request, user_id, pk): if request.user.is_superuser: ident = Identity.objects.get(pk=pk) ident.set_default() return redirect(reverse('driver_details', kwargs={'pk': user_id})) # class IdentityCreate(CreateView, UserPassesTestMixin): class IdentityCreate(UserPassesTestMixin, CreateView): template_name = "dispatch/identity/create.html" model = Identity fields = [] default_fields = ['name', 'address', 'city', 'state', 'zip_code'] superuser_fields = ['user', 'name', 'address', 'city', 'state', 'zip_code'] def set_fields(self, user): if user.is_superuser: self.fields = self.superuser_fields else: self.fields = self.default_fields def post(self, request, *args, **kwargs): self.set_fields(request.user) return super(IdentityCreate, self).post(request) def get(self, request, *args, **kwargs): self.set_fields(request.user) return super(IdentityCreate, self).get(request) def get_object(self): user_id = self.kwargs.get('user_id') u = User.objects.get(pk=user_id) return Identity(user=u) def form_valid(self, form): form.instance.user = self.request.user return super(IdentityCreate, self).form_valid(form) def test_func(self): return self.request.user.is_superuser or \ self.get_object().user.pk is self.request.user.pk class IdentityUpdate(UserPassesTestMixin, UpdateView): template_name = "dispatch/identity/edit.html" model = Identity fields = [] default_fields = ['name', 'address', 'city', 'state', 'zip_code'] superuser_fields = ['user', 'name', 'address', 'city', 'state', 'zip_code'] def set_fields(self, user): if user.is_superuser: self.fields = self.superuser_fields else: self.fields = self.default_fields def post(self, request, *args, **kwargs): self.set_fields(request.user) return super(IdentityUpdate, self).post(request) def get(self, request, *args, **kwargs): self.set_fields(request.user) return super(IdentityUpdate, self).get(request) def test_func(self): return self.request.user.is_superuser or \ self.get_object().user.pk is self.request.user.pk # Invoice class InvoiceEdit(UserPassesTestMixin, FilteredUpdateView): template_name = "dispatch/invoice/edit.html" model = Invoice fields = [] default_fields = [] superuser_fields = ['user', 'owner', 'bill_to', 'invoice_id', 'invoice_date', 'due_date', 'paid', 'payment_identifier'] def set_fields(self, user): if user.is_superuser: self.fields = self.superuser_fields else: self.fields = self.default_fields def post(self, request, pk): self.set_fields(request.user) return super(InvoiceEdit, self).post(request) def get(self, request, pk): self.set_fields(request.user) return super(InvoiceEdit, self).get(request) def test_func(self): return self.request.user.is_superuser # or \ # self.get_object().user.pk == self.request.user.pk class InvoiceList(FilteredListView): template_name = "dispatch/invoice/list.html" model = Invoice paginate_by = 10 def get_queryset(self): # TODO: allow for a pagination base_qs = super(InvoiceList, self).get_queryset() # I don't really like this hack, but whatever if self.request.GET.get('paid') == "1": base_qs = base_qs.filter(paid=True) else: # Show the unpaid ones by default base_qs = base_qs.filter(paid=False) # Give me the newest ones first return base_qs.order_by('-pk') class InvoiceDetail(DetailView): template_name = "dispatch/invoice/detail.html" model = Invoice def InvoiceGenerateForDates(request, pk): driver = User.objects.get(pk=pk) # I fucking hate dates and time. What a clusterfuck start_date = request.GET.get('date', datetime.datetime.now()) if isinstance(start_date, str): start_date = datetime.datetime.strptime(start_date, '%m/%d/%Y') due_date = start_date + datetime.timedelta(days=30) wk = get_week_dates(datetime.datetime.strftime(start_date, "%m/%d/%Y")) inv = Invoice(user=driver, invoice_date=start_date, due_date=due_date) inv.setup() inv.save() inv.populate_items(start_date=wk['start_date'], end_date=wk['end_date']) return redirect(reverse('invoice_list')) class InvoiceDelete(UserPassesTestMixin, DeleteView): template_name = "dispatch/invoice/list.html" model = Invoice success_url = reverse_lazy('invoice_list') def test_func(self): return self.request.user.is_superuser or \ self.get_object().user.pk is self.request.user.pk