vkk.workhours.contributor.views
1from django.views.generic import RedirectView, FormView, ListView, TemplateView 2from django.utils import timezone 3from django.db.models import Sum, Q 4from django.http import Http404 5from django.urls import reverse 6from django.shortcuts import get_object_or_404, redirect 7from django.forms import Form, modelform_factory 8from vkk.generic.views import CustomSuccessView 9from vkk.generic.mixins import OnSuccessMixin 10from vkk.workhours.models import Period, WorkHours, PeriodClosure, ProjectAssignment, WorkHoursCorrection 11from vkk.workhours.forms import PeriodSelectForm 12from .forms import WorkhourCalendarForm 13from .mixins import ContributorRequiredMixin, ContributorPeriodSelectorMixin 14 15 16class PeriodRedirect(ContributorRequiredMixin, RedirectView): 17 """ Redirects a contributor to a period.""" 18 19 def get_redirect_url(self, *args, **kwargs): 20 # Catches Period Selection from GET 21 if 'period' in self.request.GET: 22 now = timezone.now() 23 query_set = Period.objects.filter( 24 Q(dead_line__gte=now) | 25 Q(workhours__project_assignment__pk=self.kwargs['assignment_pk']) | 26 Q(periodclosure__project_assignment__pk=self.kwargs['assignment_pk']) 27 ).distinct() 28 form = PeriodSelectForm(query_set, data=self.request.GET) 29 if form.is_valid(): 30 period = form.cleaned_data.get("period") 31 else: 32 raise Http404() 33 # Catches Period no given 34 elif 'period_pk' not in kwargs: 35 period = Period.objects.latest(create=True) 36 # Looks up Period 37 else: 38 period = get_object_or_404(Period, pk=kwargs['period_pk']) 39 40 return reverse( 41 'vkk:workhours:contributor:calendar', 42 args=[kwargs['assignment_pk'], period.pk] 43 ) 44 45 46class WorkhoursView(ContributorRequiredMixin, ContributorPeriodSelectorMixin, FormView): 47 """Displays a calendar for entering work hours.""" 48 form_class = WorkhourCalendarForm 49 template_name = 'vkk/workhours/contributor/workhours.html' 50 51 def get_context_data(self, **kwargs): 52 context = super().get_context_data(**kwargs) 53 context["project"] = ProjectAssignment.objects.select_related('project').get( 54 pk=self.kwargs['assignment_pk'] 55 ).project 56 return context 57 58 def dispatch(self, request, *args, **kwargs): 59 period = Period.objects.filter( 60 pk=self.kwargs['period_pk'], 61 dead_line__lt=timezone.now() 62 ) 63 if period.exists(): 64 return redirect('vkk:workhours:contributor:summary', **self.kwargs) 65 66 closure = PeriodClosure.objects.filter( 67 project_assignment__pk=self.kwargs['assignment_pk'], 68 period__pk=self.kwargs['period_pk'] 69 ) 70 if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager): 71 return redirect('vkk:workhours:contributor:summary', **self.kwargs) 72 return super().dispatch(request, *args, **kwargs) 73 74 def get_form_kwargs(self): 75 kwargs = super().get_form_kwargs() 76 kwargs.update({ 77 'period_pk': self.kwargs['period_pk'], 78 'assignment_pk': self.kwargs['assignment_pk'], 79 }) 80 return kwargs 81 82 def get_success_url(self): 83 return reverse( 84 'vkk:workhours:contributor:summary', 85 args=[ 86 self.kwargs['assignment_pk'], 87 self.kwargs['period_pk'] 88 ] 89 ) 90 91 def form_valid(self, form): 92 form.save() 93 return super().form_valid(form) 94 95 96class SummaryView(ContributorRequiredMixin, ContributorPeriodSelectorMixin, ListView): 97 model = WorkHours 98 template_name = 'vkk/workhours/contributor/summary.html' 99 100 def get_queryset(self): 101 query_set = super().get_queryset() 102 query_set = query_set.filter( 103 project_assignment__pk=self.kwargs['assignment_pk'], 104 period__pk=self.kwargs['period_pk'] 105 ) 106 return query_set.order_by('day') 107 108 def get_context_data(self, **kwargs): 109 context = super().get_context_data(**kwargs) 110 query_set = context["object_list"] 111 112 correction = WorkHoursCorrection.objects.filter( 113 project_assignment__pk=self.kwargs['assignment_pk'], 114 period__pk=self.kwargs['period_pk'] 115 ) 116 context["correction"] = correction 117 118 context.update(query_set.aggregate(Sum('hours'))) 119 if context["hours__sum"] is None: 120 context["hours__sum"] = 0 121 if correction.exists(): 122 context["hours__sum"] += correction[0].ammount 123 124 context["fields"] = ['day', 'hours'] 125 126 closure = PeriodClosure.objects.filter( 127 project_assignment__pk=self.kwargs['assignment_pk'], 128 period__pk=self.kwargs['period_pk'] 129 ) 130 if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager): 131 context['closure'] = True 132 else: 133 context['closure'] = False 134 135 context['project'] = ProjectAssignment.objects.select_related('project').get( 136 pk=self.kwargs['assignment_pk'] 137 ).project 138 139 return context 140 141 142class ClosureView(ContributorRequiredMixin, OnSuccessMixin, FormView): 143 template_name = 'vkk/workhours/contributor/closure.html' 144 form_class = Form 145 on_success = 'closure_success' 146 147 def post(self, request, *args, **kwargs): 148 form = self.get_form() 149 model_form = modelform_factory( 150 model=PeriodClosure, 151 fields='__all__', 152 )( 153 data={ 154 'period': self.kwargs['period_pk'], 155 'project_assignment': self.kwargs['assignment_pk'], 156 'is_closed_contributor': True, 157 }, 158 ) 159 if form.is_valid and model_form.is_valid: 160 model_form.save() 161 return self.form_valid(form) 162 else: 163 return self.handle_no_permission() 164 165 166class ClosureSuccessView(ContributorRequiredMixin, CustomSuccessView): 167 template_name = 'vkk/workhours/contributor/closure_success.html' 168 model = PeriodClosure 169 on_success = 'summary'
17class PeriodRedirect(ContributorRequiredMixin, RedirectView): 18 """ Redirects a contributor to a period.""" 19 20 def get_redirect_url(self, *args, **kwargs): 21 # Catches Period Selection from GET 22 if 'period' in self.request.GET: 23 now = timezone.now() 24 query_set = Period.objects.filter( 25 Q(dead_line__gte=now) | 26 Q(workhours__project_assignment__pk=self.kwargs['assignment_pk']) | 27 Q(periodclosure__project_assignment__pk=self.kwargs['assignment_pk']) 28 ).distinct() 29 form = PeriodSelectForm(query_set, data=self.request.GET) 30 if form.is_valid(): 31 period = form.cleaned_data.get("period") 32 else: 33 raise Http404() 34 # Catches Period no given 35 elif 'period_pk' not in kwargs: 36 period = Period.objects.latest(create=True) 37 # Looks up Period 38 else: 39 period = get_object_or_404(Period, pk=kwargs['period_pk']) 40 41 return reverse( 42 'vkk:workhours:contributor:calendar', 43 args=[kwargs['assignment_pk'], period.pk] 44 )
Redirects a contributor to a period.
20 def get_redirect_url(self, *args, **kwargs): 21 # Catches Period Selection from GET 22 if 'period' in self.request.GET: 23 now = timezone.now() 24 query_set = Period.objects.filter( 25 Q(dead_line__gte=now) | 26 Q(workhours__project_assignment__pk=self.kwargs['assignment_pk']) | 27 Q(periodclosure__project_assignment__pk=self.kwargs['assignment_pk']) 28 ).distinct() 29 form = PeriodSelectForm(query_set, data=self.request.GET) 30 if form.is_valid(): 31 period = form.cleaned_data.get("period") 32 else: 33 raise Http404() 34 # Catches Period no given 35 elif 'period_pk' not in kwargs: 36 period = Period.objects.latest(create=True) 37 # Looks up Period 38 else: 39 period = get_object_or_404(Period, pk=kwargs['period_pk']) 40 41 return reverse( 42 'vkk:workhours:contributor:calendar', 43 args=[kwargs['assignment_pk'], period.pk] 44 )
Return the URL redirect to. Keyword arguments from the URL pattern match generating the redirect request are provided as kwargs to this method.
Inherited Members
- django.views.generic.base.View
- View
- view_is_async
- as_view
- setup
- http_method_not_allowed
- django.contrib.auth.mixins.AccessMixin
- get_login_url
- get_permission_denied_message
- get_redirect_field_name
- handle_no_permission
- django.views.generic.base.RedirectView
- get
- head
- post
- options
- delete
- put
- patch
47class WorkhoursView(ContributorRequiredMixin, ContributorPeriodSelectorMixin, FormView): 48 """Displays a calendar for entering work hours.""" 49 form_class = WorkhourCalendarForm 50 template_name = 'vkk/workhours/contributor/workhours.html' 51 52 def get_context_data(self, **kwargs): 53 context = super().get_context_data(**kwargs) 54 context["project"] = ProjectAssignment.objects.select_related('project').get( 55 pk=self.kwargs['assignment_pk'] 56 ).project 57 return context 58 59 def dispatch(self, request, *args, **kwargs): 60 period = Period.objects.filter( 61 pk=self.kwargs['period_pk'], 62 dead_line__lt=timezone.now() 63 ) 64 if period.exists(): 65 return redirect('vkk:workhours:contributor:summary', **self.kwargs) 66 67 closure = PeriodClosure.objects.filter( 68 project_assignment__pk=self.kwargs['assignment_pk'], 69 period__pk=self.kwargs['period_pk'] 70 ) 71 if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager): 72 return redirect('vkk:workhours:contributor:summary', **self.kwargs) 73 return super().dispatch(request, *args, **kwargs) 74 75 def get_form_kwargs(self): 76 kwargs = super().get_form_kwargs() 77 kwargs.update({ 78 'period_pk': self.kwargs['period_pk'], 79 'assignment_pk': self.kwargs['assignment_pk'], 80 }) 81 return kwargs 82 83 def get_success_url(self): 84 return reverse( 85 'vkk:workhours:contributor:summary', 86 args=[ 87 self.kwargs['assignment_pk'], 88 self.kwargs['period_pk'] 89 ] 90 ) 91 92 def form_valid(self, form): 93 form.save() 94 return super().form_valid(form)
Displays a calendar for entering work hours.
52 def get_context_data(self, **kwargs): 53 context = super().get_context_data(**kwargs) 54 context["project"] = ProjectAssignment.objects.select_related('project').get( 55 pk=self.kwargs['assignment_pk'] 56 ).project 57 return context
Insert the form into the context dict.
59 def dispatch(self, request, *args, **kwargs): 60 period = Period.objects.filter( 61 pk=self.kwargs['period_pk'], 62 dead_line__lt=timezone.now() 63 ) 64 if period.exists(): 65 return redirect('vkk:workhours:contributor:summary', **self.kwargs) 66 67 closure = PeriodClosure.objects.filter( 68 project_assignment__pk=self.kwargs['assignment_pk'], 69 period__pk=self.kwargs['period_pk'] 70 ) 71 if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager): 72 return redirect('vkk:workhours:contributor:summary', **self.kwargs) 73 return super().dispatch(request, *args, **kwargs)
75 def get_form_kwargs(self): 76 kwargs = super().get_form_kwargs() 77 kwargs.update({ 78 'period_pk': self.kwargs['period_pk'], 79 'assignment_pk': self.kwargs['assignment_pk'], 80 }) 81 return kwargs
Return the keyword arguments for instantiating the form.
83 def get_success_url(self): 84 return reverse( 85 'vkk:workhours:contributor:summary', 86 args=[ 87 self.kwargs['assignment_pk'], 88 self.kwargs['period_pk'] 89 ] 90 )
Return the URL to redirect to after processing a valid form.
Inherited Members
- django.views.generic.base.View
- View
- view_is_async
- as_view
- setup
- http_method_not_allowed
- options
- django.contrib.auth.mixins.AccessMixin
- get_login_url
- get_permission_denied_message
- get_redirect_field_name
- handle_no_permission
- django.views.generic.base.TemplateResponseMixin
- render_to_response
- get_template_names
- django.views.generic.edit.FormMixin
- get_initial
- get_prefix
- get_form_class
- get_form
- form_invalid
- django.views.generic.edit.ProcessFormView
- get
- post
- put
97class SummaryView(ContributorRequiredMixin, ContributorPeriodSelectorMixin, ListView): 98 model = WorkHours 99 template_name = 'vkk/workhours/contributor/summary.html' 100 101 def get_queryset(self): 102 query_set = super().get_queryset() 103 query_set = query_set.filter( 104 project_assignment__pk=self.kwargs['assignment_pk'], 105 period__pk=self.kwargs['period_pk'] 106 ) 107 return query_set.order_by('day') 108 109 def get_context_data(self, **kwargs): 110 context = super().get_context_data(**kwargs) 111 query_set = context["object_list"] 112 113 correction = WorkHoursCorrection.objects.filter( 114 project_assignment__pk=self.kwargs['assignment_pk'], 115 period__pk=self.kwargs['period_pk'] 116 ) 117 context["correction"] = correction 118 119 context.update(query_set.aggregate(Sum('hours'))) 120 if context["hours__sum"] is None: 121 context["hours__sum"] = 0 122 if correction.exists(): 123 context["hours__sum"] += correction[0].ammount 124 125 context["fields"] = ['day', 'hours'] 126 127 closure = PeriodClosure.objects.filter( 128 project_assignment__pk=self.kwargs['assignment_pk'], 129 period__pk=self.kwargs['period_pk'] 130 ) 131 if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager): 132 context['closure'] = True 133 else: 134 context['closure'] = False 135 136 context['project'] = ProjectAssignment.objects.select_related('project').get( 137 pk=self.kwargs['assignment_pk'] 138 ).project 139 140 return context
Verify that the current user is a contributor to the given project.
101 def get_queryset(self): 102 query_set = super().get_queryset() 103 query_set = query_set.filter( 104 project_assignment__pk=self.kwargs['assignment_pk'], 105 period__pk=self.kwargs['period_pk'] 106 ) 107 return query_set.order_by('day')
Return the list of items for this view.
The return value must be an iterable and may be an instance of
QuerySet
in which case QuerySet
specific behavior will be enabled.
109 def get_context_data(self, **kwargs): 110 context = super().get_context_data(**kwargs) 111 query_set = context["object_list"] 112 113 correction = WorkHoursCorrection.objects.filter( 114 project_assignment__pk=self.kwargs['assignment_pk'], 115 period__pk=self.kwargs['period_pk'] 116 ) 117 context["correction"] = correction 118 119 context.update(query_set.aggregate(Sum('hours'))) 120 if context["hours__sum"] is None: 121 context["hours__sum"] = 0 122 if correction.exists(): 123 context["hours__sum"] += correction[0].ammount 124 125 context["fields"] = ['day', 'hours'] 126 127 closure = PeriodClosure.objects.filter( 128 project_assignment__pk=self.kwargs['assignment_pk'], 129 period__pk=self.kwargs['period_pk'] 130 ) 131 if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager): 132 context['closure'] = True 133 else: 134 context['closure'] = False 135 136 context['project'] = ProjectAssignment.objects.select_related('project').get( 137 pk=self.kwargs['assignment_pk'] 138 ).project 139 140 return context
Get the context for this view.
Inherited Members
- django.views.generic.base.View
- View
- view_is_async
- as_view
- setup
- http_method_not_allowed
- options
- django.contrib.auth.mixins.AccessMixin
- get_login_url
- get_permission_denied_message
- get_redirect_field_name
- handle_no_permission
- django.views.generic.list.MultipleObjectTemplateResponseMixin
- get_template_names
- django.views.generic.base.TemplateResponseMixin
- render_to_response
- django.views.generic.list.BaseListView
- get
- django.views.generic.list.MultipleObjectMixin
- get_ordering
- paginate_queryset
- get_paginate_by
- get_paginator
- get_paginate_orphans
- get_allow_empty
- get_context_object_name
143class ClosureView(ContributorRequiredMixin, OnSuccessMixin, FormView): 144 template_name = 'vkk/workhours/contributor/closure.html' 145 form_class = Form 146 on_success = 'closure_success' 147 148 def post(self, request, *args, **kwargs): 149 form = self.get_form() 150 model_form = modelform_factory( 151 model=PeriodClosure, 152 fields='__all__', 153 )( 154 data={ 155 'period': self.kwargs['period_pk'], 156 'project_assignment': self.kwargs['assignment_pk'], 157 'is_closed_contributor': True, 158 }, 159 ) 160 if form.is_valid and model_form.is_valid: 161 model_form.save() 162 return self.form_valid(form) 163 else: 164 return self.handle_no_permission()
Verify that the current user is a contributor to the given project.
148 def post(self, request, *args, **kwargs): 149 form = self.get_form() 150 model_form = modelform_factory( 151 model=PeriodClosure, 152 fields='__all__', 153 )( 154 data={ 155 'period': self.kwargs['period_pk'], 156 'project_assignment': self.kwargs['assignment_pk'], 157 'is_closed_contributor': True, 158 }, 159 ) 160 if form.is_valid and model_form.is_valid: 161 model_form.save() 162 return self.form_valid(form) 163 else: 164 return self.handle_no_permission()
Handle POST requests: instantiate a form instance with the passed POST variables and then check if it's valid.
Inherited Members
- django.views.generic.base.View
- View
- view_is_async
- as_view
- setup
- http_method_not_allowed
- options
- django.contrib.auth.mixins.AccessMixin
- get_login_url
- get_permission_denied_message
- get_redirect_field_name
- handle_no_permission
- django.views.generic.base.TemplateResponseMixin
- render_to_response
- get_template_names
- django.views.generic.edit.FormMixin
- get_initial
- get_prefix
- get_form_class
- get_form
- get_form_kwargs
- form_valid
- form_invalid
- get_context_data
- django.views.generic.edit.ProcessFormView
- get
- put
167class ClosureSuccessView(ContributorRequiredMixin, CustomSuccessView): 168 template_name = 'vkk/workhours/contributor/closure_success.html' 169 model = PeriodClosure 170 on_success = 'summary'
Verify that the current user is a contributor to the given project.
Inherited Members
- django.views.generic.base.View
- View
- view_is_async
- as_view
- setup
- http_method_not_allowed
- options
- django.contrib.auth.mixins.AccessMixin
- get_login_url
- get_permission_denied_message
- get_redirect_field_name
- handle_no_permission
- django.views.generic.base.TemplateView
- get
- django.views.generic.base.TemplateResponseMixin
- render_to_response
- get_template_names
- django.views.generic.base.ContextMixin
- get_context_data