import logging from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Sum from django.shortcuts import render, redirect from django.urls import reverse_lazy from django.utils import timezone from django.utils.decorators import method_decorator from django.views import generic from django.views.generic import UpdateView from rest_framework import viewsets from billard.models import LocationData, Location, Client, Accounting from billard.serializers import LocationDataSerializer, ClientUpdateLastSeenSerializer from .forms import UserInformationUpdateForm from .tables import LocationTable, LocationAccountingTable log = logging.getLogger(__name__) class LocationIndexView(LoginRequiredMixin, generic.ListView): template_name = 'billard/location_index.html' context_object_name = 'location_list' def get_queryset(self): """Return the last five published questions.""" return Location.objects.filter(users__id=self.request.user.id).order_by('code') def get_context_data(self, *, object_list=None, **kwargs): context = super().get_context_data(object_list=object_list, **kwargs) table = LocationTable(self.get_queryset()) user = self.request.user if user.has_perm('billard.change_accounting'): table = LocationAccountingTable(self.get_queryset()) context['table'] = table return context class LocationDetailView(LoginRequiredMixin, generic.DetailView): model = Location template_name = 'billard/location_detail.html' def dispatch(self, request, *args, **kwargs): if request.is_ajax(): context = { 'location': self.get_object(), } return render(request, template_name='billard/location_detail_ajax.html', context=context) result = super(LocationDetailView, self).dispatch(request, *args, **kwargs) result.context_data['pk'] = self.kwargs['pk'] return result @method_decorator(login_required, name='dispatch') class AccountingView(generic.ListView): template_name = 'billard/accounting.html' context_object_name = 'accounting' def get_queryset(self): return Accounting.objects.filter(billed=False).filter(desk__client__location_id=self.kwargs['pk']) \ .exclude(time_to__isnull=True).order_by('time_from') def dispatch(self, request, *args, **kwargs): result = super(AccountingView, self).dispatch(request, *args, **kwargs) acc_sum = self.get_queryset().aggregate(Sum('prize')) if acc_sum['prize__sum'] is None: result.context_data['acc_sum'] = 0 else: result.context_data['acc_sum'] = acc_sum['prize__sum'] result.context_data['acc_ids'] = [acc.id for acc in self.get_queryset().all()] result.context_data['location'] = Location.objects.get(pk=self.kwargs['pk']) return result @login_required @permission_required('billard.change_accounting') def accounting_confirm(request, pk): if request.method == 'POST': if 'accountings' in request.POST: acc_ids = request.POST.getlist('list_acc_id') if len(acc_ids) > 0: Accounting.objects.filter(id__in=acc_ids).update( billed=True, account_user=request.user.username, account_tst=timezone.now(), ) resp = redirect('billard:accounting_detail', pk=pk) return resp @login_required def account_modal_view(request, loc_pk): try: uuids = Client.objects.filter(report_user=request.user).values_list('uuid') accounts = Accounting.objects.filter(reporter_uuid__in=uuids) # TODO: support multiple account objects except Client.DoesNotExist: accounts = None context = { 'accounts': accounts, 'loc_pk': loc_pk, 'pks': ','.join([str(account.pk) for account in accounts]), } return render(request, 'billard/accountmodal.html', context=context) @login_required def account_modal_confirm_view(request, loc_pk, pks): for pk in pks.split(','): account = Accounting.objects.get(pk=pk) account.reporter_uuid = None account.save() return redirect('billard:location_detail', pk=loc_pk) class LocationDataViewSet(viewsets.ModelViewSet): queryset = LocationData.objects.all() serializer_class = LocationDataSerializer class ClientUpdateLastSeenViewSet(viewsets.ModelViewSet): queryset = LocationData.objects.all() serializer_class = ClientUpdateLastSeenSerializer @method_decorator(login_required, name='dispatch') class UserUpdateView(UpdateView): form_class = UserInformationUpdateForm template_name = 'registration/my_account.html' success_url = reverse_lazy('billard:my_account') def get_object(self): return self.request.user