from django.shortcuts import render, redirect from django.http import HttpResponse from django.utils.encoding import smart_str # 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.views.generic import TemplateView,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 from dispatch.forms import AddPaperworkForm from django.contrib.auth.models import User from django.contrib.auth.mixins import UserPassesTestMixin # from django.http import HttpResponseRedirect from datetime import datetime, timedelta from django.utils import formats from dateutil import rrule import re, os def home(request): return redirect(reverse('load_list')) def get_week_dates(date=None): week_dates = {} if date == None: date = formats.date_format(datetime.now(), "SHORT_DATE_FORMAT") dt = datetime.strptime(date, '%m/%d/%Y') weekday = dt.weekday() if weekday == 6: week_dates['start_date'] = dt else: weekday = weekday + 1 week_dates['start_date'] = dt - timedelta(days=weekday) week_dates['end_date'] = week_dates['start_date'] + timedelta(days=6) week_dates['next_week'] = week_dates['end_date'] + timedelta(days=1) week_dates['previous_week'] = week_dates['start_date'] - timedelta(days=1) return week_dates def split_loads_by_day(loads,start_date,end_date): split_loads = {} for date in rrule.rrule(rrule.DAILY,dtstart=start_date, until=end_date): if date not in split_loads: split_loads[date] = loads.filter(date=date) return split_loads 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'] = 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 def test_func(self): return self.request.user.is_superuser class DriverDetail(UserPassesTestMixin, LoadDateSort): 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) stats = {}; stats['count'], stats['average'], stats['sum'] = (0,0,0) stats['incomplete_loads'] = 0 loads_by_date = context['loads'] 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 if l.amount == 0: stats['incomplete_loads'] += 1 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 DriverUpdate(UserPassesTestMixin, UpdateView): template_name = "dispatch/drivers/edit.html" model = User success_url = reverse_lazy('driver_list') fields = ['username', 'first_name','last_name','email','groups', 'is_active'] 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 # Customer CRUD class CustomerList(ListView): template_name = "dispatch/companies/list.html" model = Customer 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 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 = ['date', 'customer', 'description', 'delivered_to', 'amount'] def get(self,request): if request.user.is_superuser: self.fields.insert(1,'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(FilteredUpdateView): template_name = "dispatch/loads/edit.html" model = Load fields = ['date', 'customer', 'description', 'delivered_to', 'amount'] def get(self,request,pk): if request.user.is_superuser: self.fields.insert(1,'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) 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 # Paperwork Uploads def PaperworkUpload(request, load_id): l = 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 = l pw.save() return redirect(reverse('load_detail', kwargs={'pk': load_id})) else: form = AddPaperworkForm() ctx = { 'form': form, 'load': l } 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' desc = load.description.replace('"', '') response = HttpResponse(fh.read(), content_type='application/force-download') response['Content-Disposition'] = 'attachment; filename="{}"'.format(smart_str(desc + ext)) response['X-Sendfile'] = smart_str(paperwork.document.path) return response except Exception as e: print(e)