vkk.workhours.contributor.views

This submodule contains all of the class based views of this module.

  1"""
  2This submodule contains all of the class based views of this module.
  3"""
  4
  5from django.views.generic import RedirectView, FormView, ListView, TemplateView
  6from django.utils import timezone
  7from django.db.models import Sum, Q
  8from django.http import Http404
  9from django.urls import reverse
 10from django.shortcuts import get_object_or_404, redirect
 11from django.forms import Form, modelform_factory
 12from vkk.generic.views import CustomSuccessView
 13from vkk.generic.mixins import OnSuccessMixin
 14from vkk.workhours.models import Period, WorkHours, PeriodClosure, ProjectAssignment, WorkHoursCorrection
 15from vkk.workhours.forms import PeriodSelectForm
 16from .forms import WorkhourCalendarForm
 17from .mixins import ContributorRequiredMixin, ContributorPeriodSelectorMixin
 18
 19
 20class PeriodRedirect(ContributorRequiredMixin, RedirectView):
 21    """
 22    Redirects a contributor to a period.
 23    """
 24
 25    def get_redirect_url(self, *args, **kwargs):
 26        """
 27        Returns an URL to redirect to.
 28        """
 29        # Catches Period Selection from GET
 30        if 'period' in self.request.GET:
 31            now = timezone.now()
 32            query_set = Period.objects.filter(
 33                Q(dead_line__gte=now) |
 34                Q(workhours__project_assignment__pk=self.kwargs['assignment_pk']) |
 35                Q(periodclosure__project_assignment__pk=self.kwargs['assignment_pk'])
 36            ).distinct()
 37            form = PeriodSelectForm(query_set, data=self.request.GET)
 38            if form.is_valid():
 39                period = form.cleaned_data.get("period")
 40            else:
 41                raise Http404()
 42        # Catches Period no given
 43        elif 'period_pk' not in kwargs:
 44            period = Period.objects.latest(create=True)
 45        # Looks up Period
 46        else:
 47            period = get_object_or_404(Period, pk=kwargs['period_pk'])
 48
 49        return reverse(
 50            'vkk:workhours:contributor:calendar',
 51            args=[kwargs['assignment_pk'], period.pk]
 52        )
 53
 54
 55class WorkhoursView(ContributorRequiredMixin, ContributorPeriodSelectorMixin, FormView):
 56    """
 57    Displays a calendar for entering work hours.
 58    """
 59    form_class = WorkhourCalendarForm
 60    template_name = 'vkk/workhours/contributor/workhours.html'
 61
 62    def get_context_data(self, **kwargs):
 63        """
 64        Returns a dictionary of context data used in the template layer.
 65        """
 66        context = super().get_context_data(**kwargs)
 67        context["project"] = ProjectAssignment.objects.select_related('project').get(
 68            pk=self.kwargs['assignment_pk']
 69        ).project
 70        return context
 71
 72    def dispatch(self, request, *args, **kwargs):
 73        """
 74        Dispatches an incoming request according to its method.
 75        """
 76        period = Period.objects.filter(
 77            pk=self.kwargs['period_pk'],
 78            dead_line__lt=timezone.now()
 79        )
 80        if period.exists():
 81            return redirect('vkk:workhours:contributor:summary', **self.kwargs)
 82
 83        closure = PeriodClosure.objects.filter(
 84            project_assignment__pk=self.kwargs['assignment_pk'],
 85            period__pk=self.kwargs['period_pk']
 86        )
 87        if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager):
 88            return redirect('vkk:workhours:contributor:summary', **self.kwargs)
 89        return super().dispatch(request, *args, **kwargs)
 90
 91    def get_form_kwargs(self):
 92        """
 93        Returns the key word arguments used for constructing
 94         the associated `WorkhourCalendarForm` instance.
 95        """
 96        kwargs = super().get_form_kwargs()
 97        kwargs.update({
 98            'period_pk': self.kwargs['period_pk'],
 99            'assignment_pk': self.kwargs['assignment_pk'],
100        })
101        return kwargs
102
103    def get_success_url(self):
104        """
105        Returns an URL to redirect to after a successfully action.
106        """
107        return reverse(
108            'vkk:workhours:contributor:summary',
109            args=[
110                self.kwargs['assignment_pk'],
111                self.kwargs['period_pk']
112            ]
113        )
114
115    def form_valid(self, form):
116        """
117        A method, which is called, if the associated
118         `WorkhourCalendarForm` instance is valid.
119        """
120        form.save()
121        return super().form_valid(form)
122
123
124class SummaryView(ContributorRequiredMixin, ContributorPeriodSelectorMixin, ListView):
125    """
126    A class based view providing a summary of `WorkHours` for a given period.
127    """
128    model = WorkHours
129    template_name = 'vkk/workhours/contributor/summary.html'
130
131    def get_queryset(self):
132        """
133        Returns a query set of `WorkHours`, associated with the given
134         primary keys of an `ProjectAssignment` and `Period`.
135        """
136        query_set = super().get_queryset()
137        query_set = query_set.filter(
138            project_assignment__pk=self.kwargs['assignment_pk'],
139            period__pk=self.kwargs['period_pk']
140        )
141        return query_set.order_by('day')
142
143    def get_context_data(self, **kwargs):
144        """
145        Returns a dictionary of context data used in the template layer.
146        """
147        context = super().get_context_data(**kwargs)
148        query_set = context["object_list"]
149
150        correction = WorkHoursCorrection.objects.filter(
151            project_assignment__pk=self.kwargs['assignment_pk'],
152            period__pk=self.kwargs['period_pk']
153        )
154        context["correction"] = correction
155
156        context.update(query_set.aggregate(Sum('hours')))
157        if context["hours__sum"] is None:
158            context["hours__sum"] = 0
159        if correction.exists():
160            context["hours__sum"] += correction[0].ammount
161
162        context["fields"] = ['day', 'hours']
163
164        closure = PeriodClosure.objects.filter(
165            project_assignment__pk=self.kwargs['assignment_pk'],
166            period__pk=self.kwargs['period_pk']
167        )
168        if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager):
169            context['closure'] = True
170        else:
171            context['closure'] = False
172
173        context['project'] = ProjectAssignment.objects.select_related('project').get(
174            pk=self.kwargs['assignment_pk']
175        ).project
176
177        return context
178
179
180class ClosureView(ContributorRequiredMixin, OnSuccessMixin, FormView):
181    """
182    A class based view offering functionality to lock a given `Period` for a
183     `ProjectAssignment`.
184    """
185    template_name = 'vkk/workhours/contributor/closure.html'
186    form_class = Form
187    on_success = 'closure_success'
188
189    def post(self, request, *args, **kwargs):
190        """
191        Method which is called in case a POST request is dispatched.
192        """
193        form = self.get_form()
194        model_form = modelform_factory(
195            model=PeriodClosure,
196            fields='__all__',
197        )(
198            data={
199                'period': self.kwargs['period_pk'],
200                'project_assignment': self.kwargs['assignment_pk'],
201                'is_closed_contributor': True,
202            },
203        )
204        if form.is_valid and model_form.is_valid:
205            model_form.save()
206            return self.form_valid(form)
207        else:
208            return self.handle_no_permission()
209
210
211class ClosureSuccessView(ContributorRequiredMixin, CustomSuccessView):
212    """
213    A class based view meant to offer a confirmation to a successful locking
214     of a `Period`.
215    """
216    template_name = 'vkk/workhours/contributor/closure_success.html'
217    model = PeriodClosure
218    on_success = 'summary'
class PeriodRedirect(vkk.workhours.contributor.mixins.ContributorRequiredMixin, django.views.generic.base.RedirectView):
21class PeriodRedirect(ContributorRequiredMixin, RedirectView):
22    """
23    Redirects a contributor to a period.
24    """
25
26    def get_redirect_url(self, *args, **kwargs):
27        """
28        Returns an URL to redirect to.
29        """
30        # Catches Period Selection from GET
31        if 'period' in self.request.GET:
32            now = timezone.now()
33            query_set = Period.objects.filter(
34                Q(dead_line__gte=now) |
35                Q(workhours__project_assignment__pk=self.kwargs['assignment_pk']) |
36                Q(periodclosure__project_assignment__pk=self.kwargs['assignment_pk'])
37            ).distinct()
38            form = PeriodSelectForm(query_set, data=self.request.GET)
39            if form.is_valid():
40                period = form.cleaned_data.get("period")
41            else:
42                raise Http404()
43        # Catches Period no given
44        elif 'period_pk' not in kwargs:
45            period = Period.objects.latest(create=True)
46        # Looks up Period
47        else:
48            period = get_object_or_404(Period, pk=kwargs['period_pk'])
49
50        return reverse(
51            'vkk:workhours:contributor:calendar',
52            args=[kwargs['assignment_pk'], period.pk]
53        )

Redirects a contributor to a period.

def get_redirect_url(self, *args, **kwargs):
26    def get_redirect_url(self, *args, **kwargs):
27        """
28        Returns an URL to redirect to.
29        """
30        # Catches Period Selection from GET
31        if 'period' in self.request.GET:
32            now = timezone.now()
33            query_set = Period.objects.filter(
34                Q(dead_line__gte=now) |
35                Q(workhours__project_assignment__pk=self.kwargs['assignment_pk']) |
36                Q(periodclosure__project_assignment__pk=self.kwargs['assignment_pk'])
37            ).distinct()
38            form = PeriodSelectForm(query_set, data=self.request.GET)
39            if form.is_valid():
40                period = form.cleaned_data.get("period")
41            else:
42                raise Http404()
43        # Catches Period no given
44        elif 'period_pk' not in kwargs:
45            period = Period.objects.latest(create=True)
46        # Looks up Period
47        else:
48            period = get_object_or_404(Period, pk=kwargs['period_pk'])
49
50        return reverse(
51            'vkk:workhours:contributor:calendar',
52            args=[kwargs['assignment_pk'], period.pk]
53        )

Returns an URL to redirect to.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
vkk.workhours.contributor.mixins.ContributorRequiredMixin
dispatch
django.contrib.auth.mixins.AccessMixin
login_url
permission_denied_message
raise_exception
redirect_field_name
get_login_url
get_permission_denied_message
get_redirect_field_name
handle_no_permission
django.views.generic.base.RedirectView
permanent
url
pattern_name
query_string
get
head
post
options
delete
put
patch
 56class WorkhoursView(ContributorRequiredMixin, ContributorPeriodSelectorMixin, FormView):
 57    """
 58    Displays a calendar for entering work hours.
 59    """
 60    form_class = WorkhourCalendarForm
 61    template_name = 'vkk/workhours/contributor/workhours.html'
 62
 63    def get_context_data(self, **kwargs):
 64        """
 65        Returns a dictionary of context data used in the template layer.
 66        """
 67        context = super().get_context_data(**kwargs)
 68        context["project"] = ProjectAssignment.objects.select_related('project').get(
 69            pk=self.kwargs['assignment_pk']
 70        ).project
 71        return context
 72
 73    def dispatch(self, request, *args, **kwargs):
 74        """
 75        Dispatches an incoming request according to its method.
 76        """
 77        period = Period.objects.filter(
 78            pk=self.kwargs['period_pk'],
 79            dead_line__lt=timezone.now()
 80        )
 81        if period.exists():
 82            return redirect('vkk:workhours:contributor:summary', **self.kwargs)
 83
 84        closure = PeriodClosure.objects.filter(
 85            project_assignment__pk=self.kwargs['assignment_pk'],
 86            period__pk=self.kwargs['period_pk']
 87        )
 88        if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager):
 89            return redirect('vkk:workhours:contributor:summary', **self.kwargs)
 90        return super().dispatch(request, *args, **kwargs)
 91
 92    def get_form_kwargs(self):
 93        """
 94        Returns the key word arguments used for constructing
 95         the associated `WorkhourCalendarForm` instance.
 96        """
 97        kwargs = super().get_form_kwargs()
 98        kwargs.update({
 99            'period_pk': self.kwargs['period_pk'],
100            'assignment_pk': self.kwargs['assignment_pk'],
101        })
102        return kwargs
103
104    def get_success_url(self):
105        """
106        Returns an URL to redirect to after a successfully action.
107        """
108        return reverse(
109            'vkk:workhours:contributor:summary',
110            args=[
111                self.kwargs['assignment_pk'],
112                self.kwargs['period_pk']
113            ]
114        )
115
116    def form_valid(self, form):
117        """
118        A method, which is called, if the associated
119         `WorkhourCalendarForm` instance is valid.
120        """
121        form.save()
122        return super().form_valid(form)

Displays a calendar for entering work hours.

template_name = 'vkk/workhours/contributor/workhours.html'
def get_context_data(self, **kwargs):
63    def get_context_data(self, **kwargs):
64        """
65        Returns a dictionary of context data used in the template layer.
66        """
67        context = super().get_context_data(**kwargs)
68        context["project"] = ProjectAssignment.objects.select_related('project').get(
69            pk=self.kwargs['assignment_pk']
70        ).project
71        return context

Returns a dictionary of context data used in the template layer.

def dispatch(self, request, *args, **kwargs):
73    def dispatch(self, request, *args, **kwargs):
74        """
75        Dispatches an incoming request according to its method.
76        """
77        period = Period.objects.filter(
78            pk=self.kwargs['period_pk'],
79            dead_line__lt=timezone.now()
80        )
81        if period.exists():
82            return redirect('vkk:workhours:contributor:summary', **self.kwargs)
83
84        closure = PeriodClosure.objects.filter(
85            project_assignment__pk=self.kwargs['assignment_pk'],
86            period__pk=self.kwargs['period_pk']
87        )
88        if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager):
89            return redirect('vkk:workhours:contributor:summary', **self.kwargs)
90        return super().dispatch(request, *args, **kwargs)

Dispatches an incoming request according to its method.

def get_form_kwargs(self):
 92    def get_form_kwargs(self):
 93        """
 94        Returns the key word arguments used for constructing
 95         the associated `WorkhourCalendarForm` instance.
 96        """
 97        kwargs = super().get_form_kwargs()
 98        kwargs.update({
 99            'period_pk': self.kwargs['period_pk'],
100            'assignment_pk': self.kwargs['assignment_pk'],
101        })
102        return kwargs

Returns the key word arguments used for constructing the associated WorkhourCalendarForm instance.

def get_success_url(self):
104    def get_success_url(self):
105        """
106        Returns an URL to redirect to after a successfully action.
107        """
108        return reverse(
109            'vkk:workhours:contributor:summary',
110            args=[
111                self.kwargs['assignment_pk'],
112                self.kwargs['period_pk']
113            ]
114        )

Returns an URL to redirect to after a successfully action.

def form_valid(self, form):
116    def form_valid(self, form):
117        """
118        A method, which is called, if the associated
119         `WorkhourCalendarForm` instance is valid.
120        """
121        form.save()
122        return super().form_valid(form)

A method, which is called, if the associated WorkhourCalendarForm instance is valid.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
django.contrib.auth.mixins.AccessMixin
login_url
permission_denied_message
raise_exception
redirect_field_name
get_login_url
get_permission_denied_message
get_redirect_field_name
handle_no_permission
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
get_template_names
django.views.generic.edit.FormMixin
initial
success_url
prefix
get_initial
get_prefix
get_form_class
get_form
form_invalid
django.views.generic.base.ContextMixin
extra_context
django.views.generic.edit.ProcessFormView
get
post
put
125class SummaryView(ContributorRequiredMixin, ContributorPeriodSelectorMixin, ListView):
126    """
127    A class based view providing a summary of `WorkHours` for a given period.
128    """
129    model = WorkHours
130    template_name = 'vkk/workhours/contributor/summary.html'
131
132    def get_queryset(self):
133        """
134        Returns a query set of `WorkHours`, associated with the given
135         primary keys of an `ProjectAssignment` and `Period`.
136        """
137        query_set = super().get_queryset()
138        query_set = query_set.filter(
139            project_assignment__pk=self.kwargs['assignment_pk'],
140            period__pk=self.kwargs['period_pk']
141        )
142        return query_set.order_by('day')
143
144    def get_context_data(self, **kwargs):
145        """
146        Returns a dictionary of context data used in the template layer.
147        """
148        context = super().get_context_data(**kwargs)
149        query_set = context["object_list"]
150
151        correction = WorkHoursCorrection.objects.filter(
152            project_assignment__pk=self.kwargs['assignment_pk'],
153            period__pk=self.kwargs['period_pk']
154        )
155        context["correction"] = correction
156
157        context.update(query_set.aggregate(Sum('hours')))
158        if context["hours__sum"] is None:
159            context["hours__sum"] = 0
160        if correction.exists():
161            context["hours__sum"] += correction[0].ammount
162
163        context["fields"] = ['day', 'hours']
164
165        closure = PeriodClosure.objects.filter(
166            project_assignment__pk=self.kwargs['assignment_pk'],
167            period__pk=self.kwargs['period_pk']
168        )
169        if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager):
170            context['closure'] = True
171        else:
172            context['closure'] = False
173
174        context['project'] = ProjectAssignment.objects.select_related('project').get(
175            pk=self.kwargs['assignment_pk']
176        ).project
177
178        return context

A class based view providing a summary of WorkHours for a given period.

model = <class 'vkk.workhours.models.WorkHours'>
template_name = 'vkk/workhours/contributor/summary.html'
def get_queryset(self):
132    def get_queryset(self):
133        """
134        Returns a query set of `WorkHours`, associated with the given
135         primary keys of an `ProjectAssignment` and `Period`.
136        """
137        query_set = super().get_queryset()
138        query_set = query_set.filter(
139            project_assignment__pk=self.kwargs['assignment_pk'],
140            period__pk=self.kwargs['period_pk']
141        )
142        return query_set.order_by('day')

Returns a query set of WorkHours, associated with the given primary keys of an ProjectAssignment and Period.

def get_context_data(self, **kwargs):
144    def get_context_data(self, **kwargs):
145        """
146        Returns a dictionary of context data used in the template layer.
147        """
148        context = super().get_context_data(**kwargs)
149        query_set = context["object_list"]
150
151        correction = WorkHoursCorrection.objects.filter(
152            project_assignment__pk=self.kwargs['assignment_pk'],
153            period__pk=self.kwargs['period_pk']
154        )
155        context["correction"] = correction
156
157        context.update(query_set.aggregate(Sum('hours')))
158        if context["hours__sum"] is None:
159            context["hours__sum"] = 0
160        if correction.exists():
161            context["hours__sum"] += correction[0].ammount
162
163        context["fields"] = ['day', 'hours']
164
165        closure = PeriodClosure.objects.filter(
166            project_assignment__pk=self.kwargs['assignment_pk'],
167            period__pk=self.kwargs['period_pk']
168        )
169        if closure.exists() and (closure[0].is_closed_contributor or closure[0].is_closed_manager):
170            context['closure'] = True
171        else:
172            context['closure'] = False
173
174        context['project'] = ProjectAssignment.objects.select_related('project').get(
175            pk=self.kwargs['assignment_pk']
176        ).project
177
178        return context

Returns a dictionary of context data used in the template layer.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.contributor.mixins.ContributorRequiredMixin
dispatch
django.contrib.auth.mixins.AccessMixin
login_url
permission_denied_message
raise_exception
redirect_field_name
get_login_url
get_permission_denied_message
get_redirect_field_name
handle_no_permission
django.views.generic.list.MultipleObjectTemplateResponseMixin
template_name_suffix
get_template_names
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
django.views.generic.list.BaseListView
get
django.views.generic.list.MultipleObjectMixin
allow_empty
queryset
paginate_by
paginate_orphans
context_object_name
paginator_class
page_kwarg
ordering
get_ordering
paginate_queryset
get_paginate_by
get_paginator
get_paginate_orphans
get_allow_empty
get_context_object_name
django.views.generic.base.ContextMixin
extra_context
class ClosureView(vkk.workhours.contributor.mixins.ContributorRequiredMixin, vkk.generic.mixins.OnSuccessMixin, django.views.generic.edit.FormView):
181class ClosureView(ContributorRequiredMixin, OnSuccessMixin, FormView):
182    """
183    A class based view offering functionality to lock a given `Period` for a
184     `ProjectAssignment`.
185    """
186    template_name = 'vkk/workhours/contributor/closure.html'
187    form_class = Form
188    on_success = 'closure_success'
189
190    def post(self, request, *args, **kwargs):
191        """
192        Method which is called in case a POST request is dispatched.
193        """
194        form = self.get_form()
195        model_form = modelform_factory(
196            model=PeriodClosure,
197            fields='__all__',
198        )(
199            data={
200                'period': self.kwargs['period_pk'],
201                'project_assignment': self.kwargs['assignment_pk'],
202                'is_closed_contributor': True,
203            },
204        )
205        if form.is_valid and model_form.is_valid:
206            model_form.save()
207            return self.form_valid(form)
208        else:
209            return self.handle_no_permission()

A class based view offering functionality to lock a given Period for a ProjectAssignment.

template_name = 'vkk/workhours/contributor/closure.html'
form_class = <class 'django.forms.forms.Form'>
on_success = 'closure_success'
def post(self, request, *args, **kwargs):
190    def post(self, request, *args, **kwargs):
191        """
192        Method which is called in case a POST request is dispatched.
193        """
194        form = self.get_form()
195        model_form = modelform_factory(
196            model=PeriodClosure,
197            fields='__all__',
198        )(
199            data={
200                'period': self.kwargs['period_pk'],
201                'project_assignment': self.kwargs['assignment_pk'],
202                'is_closed_contributor': True,
203            },
204        )
205        if form.is_valid and model_form.is_valid:
206            model_form.save()
207            return self.form_valid(form)
208        else:
209            return self.handle_no_permission()

Method which is called in case a POST request is dispatched.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.contributor.mixins.ContributorRequiredMixin
dispatch
django.contrib.auth.mixins.AccessMixin
login_url
permission_denied_message
raise_exception
redirect_field_name
get_login_url
get_permission_denied_message
get_redirect_field_name
handle_no_permission
vkk.generic.mixins.OnSuccessMixin
drop_key
kwarg_override
get_success_url
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
get_template_names
django.views.generic.edit.FormMixin
initial
success_url
prefix
get_initial
get_prefix
get_form_class
get_form
get_form_kwargs
form_valid
form_invalid
get_context_data
django.views.generic.base.ContextMixin
extra_context
django.views.generic.edit.ProcessFormView
get
put
212class ClosureSuccessView(ContributorRequiredMixin, CustomSuccessView):
213    """
214    A class based view meant to offer a confirmation to a successful locking
215     of a `Period`.
216    """
217    template_name = 'vkk/workhours/contributor/closure_success.html'
218    model = PeriodClosure
219    on_success = 'summary'

A class based view meant to offer a confirmation to a successful locking of a Period.

template_name = 'vkk/workhours/contributor/closure_success.html'
on_success = 'summary'
Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.contributor.mixins.ContributorRequiredMixin
dispatch
django.contrib.auth.mixins.AccessMixin
login_url
permission_denied_message
raise_exception
redirect_field_name
get_login_url
get_permission_denied_message
get_redirect_field_name
handle_no_permission
vkk.generic.mixins.OnSuccessMixin
drop_key
kwarg_override
get_success_url
django.views.generic.base.TemplateView
get
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
get_template_names
django.views.generic.base.ContextMixin
extra_context
get_context_data