vkk.workhours.accounting.projects.project.views

This submodule contains class based views.

  1"""
  2This submodule contains class based views.
  3"""
  4
  5from django.utils.translation import gettext_lazy as _
  6from django.core.exceptions import ValidationError
  7from django.forms import modelform_factory, Form
  8from django.urls import reverse
  9from django.shortcuts import get_object_or_404
 10from django.views.generic import RedirectView, FormView, TemplateView
 11from vkk.generic.forms import CustomDateInput
 12from vkk.generic.mixins import OnSuccessMixin
 13from vkk.generic.views import CustomSuccessView
 14from vkk.users.models import User
 15from vkk.workhours.models import ProjectManager, ProjectAssignment, Project, Period, PeriodClosure, WorkHours, WorkHoursCorrection
 16from vkk.workhours.mixins import PeriodSelectorMixin
 17from vkk.workhours.forms import WorkhourSheetForm, PeriodSelectForm
 18from vkk.workhours.accounting.mixins import AccountantRequiredMixin
 19from vkk.workhours.accounting.views import AccountingDetailView, AccountingFilterView, AccountingCreateView, AccountingUpdateView, AccountingDeleteView
 20from vkk.workhours.accounting.projects.project.forms import ContributorDeleteForm
 21
 22
 23class AccountingProjectOverView(AccountingDetailView):
 24    """
 25    A class based `View` providing  an overview over the given project.
 26    """
 27    model = Project
 28    slug_field = 'invoice_number'
 29    slug_url_kwarg = 'invoice_number'
 30    template_name = 'vkk/workhours/accounting/projects/project/details.html'
 31    fields = ['name', 'invoice_number',
 32              'department', 'contractor', 'start', 'end']
 33
 34    def get_context_data(self, **kwargs):
 35        """
 36        Returns additional context data as an dictionary. This is used for rendering the page.
 37        """
 38        context = super().get_context_data(**kwargs)
 39        context["managers"] = ProjectManager.objects.filter(
 40            project__invoice_number=self.kwargs['invoice_number']
 41        ).prefetch_related('manager').order_by('manager__last_name', 'manager__first_name')
 42        context["contributors"] = ProjectAssignment.objects.filter(
 43            project__invoice_number=self.kwargs['invoice_number']
 44        ).prefetch_related('contributor').order_by('contributor__last_name', 'contributor__first_name')
 45        return context
 46
 47
 48class AccountingProjectUserFilterView(AccountingFilterView):
 49    """
 50    A class based `View` providing utilities for selecting a `User` which
 51    is to be assigned to the given project.
 52    """
 53    model = User
 54    fields = ['last_name', 'first_name', 'email']
 55    action_options = None
 56    to_exclude = None
 57
 58    def get(self, request, *args, invoice_number=None, **kwargs):
 59        """
 60        Handler for GET requests.
 61        """
 62        return super().get(request, *args, **kwargs)
 63
 64    def get_queryset(self):
 65        """
 66        Returns a query set of `Users` which are not assigned to the given Project.
 67        """
 68        kwarg = {self.to_exclude: self.kwargs['invoice_number']}
 69        return super().get_queryset().exclude(**kwarg)
 70
 71
 72class AccountingProjectUpdateView(AccountingUpdateView):
 73    """
 74    A class based `UpdateView` for updating the given project.
 75    """
 76    model = Project
 77    form_class = modelform_factory(
 78        model=Project,
 79        fields=['invoice_number', 'name', 'department',
 80                'contractor', 'start', 'end'],
 81        widgets={'start': CustomDateInput, 'end': CustomDateInput}
 82    )
 83    drop_key = None
 84    slug_field = 'invoice_number'
 85    slug_url_kwarg = 'invoice_number'
 86
 87    def form_valid(self, form):
 88        """
 89        Saves any changes to the associated `Project`.
 90        """
 91        self.kwarg_override = {'invoice_number': form.instance.invoice_number}
 92        return super().form_valid(form)
 93
 94
 95class AccountingManagerCreateView(AccountingCreateView):
 96    """
 97    A class based `CreateView` providing utilities for creating new `ProjectManager`s.
 98    """
 99    model = ProjectManager
100    form_class = modelform_factory(
101        model=ProjectManager,
102        fields=['start', 'end', 'is_proxy'],
103        widgets={'start': CustomDateInput, 'end': CustomDateInput}
104    )
105    on_success = 'add_manager_success'
106    drop_key = 'pk'
107
108    def form_valid(self, form):
109        """
110        Attempts to save the newly created `ProjectManager` to the database.
111        """
112        form.instance.manager = User.objects.get(pk=self.kwargs['pk'])
113        form.instance.project = Project.objects.get(
114            invoice_number=self.kwargs['invoice_number'])
115        try:
116            form.instance.full_clean()
117        except ValidationError as err:
118            form.add_error(None, err)
119            return self.form_invalid(form)
120        return super().form_valid(form)
121
122
123class AccountingContributorCreateView(AccountingCreateView):
124    """
125    A class based `CreateView` providing utilities for creating new `ProjectAssignment`s.
126    """
127    model = ProjectAssignment
128    fields = ['salary_level']
129    on_success = 'add_contributor_success'
130    drop_key = 'pk'
131
132    def form_valid(self, form):
133        """
134        Attempts to save the newly created `ProjectAssignment` to the database.
135        """
136        form.instance.contributor = User.objects.get(pk=self.kwargs['pk'])
137        form.instance.project = Project.objects.get(
138            invoice_number=self.kwargs['invoice_number'])
139        try:
140            form.instance.full_clean()
141        except ValidationError as err:
142            form.add_error(None, err)
143            return self.form_invalid(form)
144        return super().form_valid(form)
145
146
147class AccountingContributorDeleteView(AccountingDeleteView):
148    """
149    A class based `DeleteView` providing utilities for deleting `ProjectAssignment`s.
150    """
151    model = ProjectAssignment
152    form_class = ContributorDeleteForm
153    on_success = 'delete_contributor_success'
154    drop_key = 'pk'
155
156    def get_form_kwargs(self):
157        """Return the keyword arguments for instantiating the form."""
158        kwargs = super().get_form_kwargs()
159        kwargs['id'] = self.kwargs['pk']
160        return kwargs
161
162class AccountingManagerDeleteView(AccountingDeleteView):
163    """
164    A class based `DeleteView` providing utilities for deleting `ProjectManager`s.
165    """
166    model = ProjectManager
167    on_success = 'delete_manager_success'
168    drop_key = 'pk'
169
170
171class AccountingWorkhourSheetSelectionView(AccountantRequiredMixin, PeriodSelectorMixin, RedirectView):
172    """
173    A class based `View` for selecting a `Period` for a work hour sheet.
174    """
175    def get_redirect_url(self, *args, **kwargs):
176        """
177        Returns an URL to redirect to based on the given period.
178        """
179        # Catches Period Selection from GET
180        if 'period' in self.request.GET:
181            query_set = Period.objects.all()
182            form = PeriodSelectForm(query_set, data=self.request.GET)
183            if form.is_valid():
184                period = form.cleaned_data.get("period")
185            else:
186                raise Http404()
187        # Catches Period no given
188        elif 'period_pk' not in kwargs:
189            period = Period.objects.latest(create=True)
190        # Looks up Period
191        else:
192            period = get_object_or_404(Period, pk=kwargs['period_pk'])
193
194        return reverse(
195            'vkk:workhours:accounting:projects:project:workhours_sheet',
196            args=[kwargs['invoice_number'], period.pk]
197        )
198
199
200class AccountingWorkhourSheetView(AccountantRequiredMixin, PeriodSelectorMixin, FormView):
201    """
202    A class based `View` providing a work hours sheet for a given project and period.
203    """
204    form_class = WorkhourSheetForm
205    template_name = 'vkk/workhours/accounting/projects/project/workhours_sheet.html'
206    period_select_namespace = 'vkk:workhours:accounting:projects:project:workhours_sheet_selection'
207
208    def get_form_kwargs(self):
209        """
210        Returns a dictionary of keyword arguments for instatiating the associated form.
211        """
212        kwargs = super().get_form_kwargs()
213        self.assignments = ProjectAssignment.objects.filter(
214            project__invoice_number=self.kwargs['invoice_number']
215        ).order_by('contributor__last_name', 'contributor__first_name')
216        kwargs.update({
217            'period_pk': self.kwargs['period_pk'],
218            'assignments': self.assignments,
219            'closure_lock': False,
220            'invoice_number': self.kwargs['invoice_number'],
221        })
222        return kwargs
223
224    def get_success_url(self):
225        """
226        Returns a URL to redirect to after a successful action.
227        """
228        return reverse(
229            'vkk:workhours:accounting:projects:project:workhours_sheet_success',
230            args=[
231                self.kwargs['invoice_number'],
232                self.kwargs['period_pk']
233            ]
234        )
235
236    def get_context_data(self, **kwargs):
237        """
238        Returns additional context data as an dictionary. This is used for rendering the page.
239        """
240        context = super().get_context_data(**kwargs)
241        manager_closed_count = self.assignments.filter(
242            periodclosure__period=self.kwargs['period_pk'],
243            periodclosure__is_closed_manager=True
244        ).count()
245        assignment_count = self.assignments.count()
246        if manager_closed_count == assignment_count:
247            context['closed'] = True
248        else:
249            context['closed'] = False
250        context['saveable'] = True
251
252        context['project'] = get_object_or_404(
253            Project, invoice_number=self.kwargs['invoice_number'])
254        return context
255
256    def form_valid(self, form):
257        """
258        Saves all changes to work hours to the database.
259        """
260        form.save()
261        return super().form_valid(form)
262
263
264class AccountingPeriodClosureView(AccountantRequiredMixin, OnSuccessMixin, FormView):
265    """
266    A class based `View` providing utilities to close the period for new entries 
267    for all contributors of the given project.
268    """
269    template_name = 'vkk/workhours/contributor/closure.html'
270    form_class = Form
271    on_success = 'period_closure_success'
272
273    def post(self, request, *args, **kwargs):
274        """
275        Handler for POST rquests.
276        """
277        form = self.get_form()
278        if form.is_valid():
279            self.close_period()
280            return self.form_valid(form)
281        else:
282            return self.form_invalid(form)
283
284    def close_period(self):
285        """
286        Closes the period for all contributors to a project for a given period.
287        """
288        assignments = ProjectAssignment.objects.filter(
289            project__invoice_number=self.kwargs['invoice_number'],
290        )
291        period = get_object_or_404(Period, pk=self.kwargs['period_pk'])
292        closing = [
293            PeriodClosure(
294                period=period,
295                project_assignment=assignment,
296                is_closed_contributor=True,
297                is_closed_manager=True
298            ) for assignment in assignments
299        ]
300        PeriodClosure.objects.bulk_create(
301            closing,
302            update_conflicts=True,
303            update_fields=['is_closed_contributor', 'is_closed_manager'],
304            unique_fields=['project_assignment', 'period']
305        )
306
307
308class AccountingPeriodClosureSuccessView(AccountantRequiredMixin, CustomSuccessView):
309    """
310    A class based `View` providing utilities for displaying a successfull closing of a period
311    for all contributors to a given project.
312    """
313    template_name = 'vkk/workhours/contributor/closure_success.html'
314    model = PeriodClosure
315    on_success = 'workhours_sheet'
316
317
318# Export
319
320class AccountingExportView(AccountantRequiredMixin, FormView):
321    """
322    A class based `View` providing an overview over all possible actions associated with the
323    export of project related data.
324    """
325    template_name = 'vkk/workhours/accounting/projects/project/export.html'
class AccountingProjectOverView(vkk.workhours.accounting.views.AccountingDetailView):
24class AccountingProjectOverView(AccountingDetailView):
25    """
26    A class based `View` providing  an overview over the given project.
27    """
28    model = Project
29    slug_field = 'invoice_number'
30    slug_url_kwarg = 'invoice_number'
31    template_name = 'vkk/workhours/accounting/projects/project/details.html'
32    fields = ['name', 'invoice_number',
33              'department', 'contractor', 'start', 'end']
34
35    def get_context_data(self, **kwargs):
36        """
37        Returns additional context data as an dictionary. This is used for rendering the page.
38        """
39        context = super().get_context_data(**kwargs)
40        context["managers"] = ProjectManager.objects.filter(
41            project__invoice_number=self.kwargs['invoice_number']
42        ).prefetch_related('manager').order_by('manager__last_name', 'manager__first_name')
43        context["contributors"] = ProjectAssignment.objects.filter(
44            project__invoice_number=self.kwargs['invoice_number']
45        ).prefetch_related('contributor').order_by('contributor__last_name', 'contributor__first_name')
46        return context

A class based View providing an overview over the given project.

model = <class 'vkk.workhours.models.Project'>
slug_field = 'invoice_number'
slug_url_kwarg = 'invoice_number'
template_name = 'vkk/workhours/accounting/projects/project/details.html'
fields = ['name', 'invoice_number', 'department', 'contractor', 'start', 'end']
def get_context_data(self, **kwargs):
35    def get_context_data(self, **kwargs):
36        """
37        Returns additional context data as an dictionary. This is used for rendering the page.
38        """
39        context = super().get_context_data(**kwargs)
40        context["managers"] = ProjectManager.objects.filter(
41            project__invoice_number=self.kwargs['invoice_number']
42        ).prefetch_related('manager').order_by('manager__last_name', 'manager__first_name')
43        context["contributors"] = ProjectAssignment.objects.filter(
44            project__invoice_number=self.kwargs['invoice_number']
45        ).prefetch_related('contributor').order_by('contributor__last_name', 'contributor__first_name')
46        return context

Returns additional context data as an dictionary. This is used for rendering the page.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.views.CustomDetailView
action_options
django.views.generic.detail.SingleObjectTemplateResponseMixin
template_name_field
template_name_suffix
get_template_names
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
django.views.generic.detail.BaseDetailView
get
django.views.generic.detail.SingleObjectMixin
queryset
context_object_name
pk_url_kwarg
query_pk_and_slug
get_object
get_queryset
get_slug_field
get_context_object_name
django.views.generic.base.ContextMixin
extra_context
class AccountingProjectUserFilterView(vkk.workhours.accounting.views.AccountingFilterView):
49class AccountingProjectUserFilterView(AccountingFilterView):
50    """
51    A class based `View` providing utilities for selecting a `User` which
52    is to be assigned to the given project.
53    """
54    model = User
55    fields = ['last_name', 'first_name', 'email']
56    action_options = None
57    to_exclude = None
58
59    def get(self, request, *args, invoice_number=None, **kwargs):
60        """
61        Handler for GET requests.
62        """
63        return super().get(request, *args, **kwargs)
64
65    def get_queryset(self):
66        """
67        Returns a query set of `Users` which are not assigned to the given Project.
68        """
69        kwarg = {self.to_exclude: self.kwargs['invoice_number']}
70        return super().get_queryset().exclude(**kwarg)

A class based View providing utilities for selecting a User which is to be assigned to the given project.

model = <class 'vkk.users.models.User'>
fields = ['last_name', 'first_name', 'email']
action_options = None
to_exclude = None
def get(self, request, *args, invoice_number=None, **kwargs):
59    def get(self, request, *args, invoice_number=None, **kwargs):
60        """
61        Handler for GET requests.
62        """
63        return super().get(request, *args, **kwargs)

Handler for GET requests.

def get_queryset(self):
65    def get_queryset(self):
66        """
67        Returns a query set of `Users` which are not assigned to the given Project.
68        """
69        kwarg = {self.to_exclude: self.kwargs['invoice_number']}
70        return super().get_queryset().exclude(**kwarg)

Returns a query set of Users which are not assigned to the given Project.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.views.CustomFilterView
template_name
filter_fields
get_filter_fields
get_filter
get_context_data
vkk.generic.views.CustomListView
keys
paginate_by
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.MultipleObjectMixin
allow_empty
queryset
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 AccountingProjectUpdateView(vkk.workhours.accounting.views.AccountingUpdateView):
73class AccountingProjectUpdateView(AccountingUpdateView):
74    """
75    A class based `UpdateView` for updating the given project.
76    """
77    model = Project
78    form_class = modelform_factory(
79        model=Project,
80        fields=['invoice_number', 'name', 'department',
81                'contractor', 'start', 'end'],
82        widgets={'start': CustomDateInput, 'end': CustomDateInput}
83    )
84    drop_key = None
85    slug_field = 'invoice_number'
86    slug_url_kwarg = 'invoice_number'
87
88    def form_valid(self, form):
89        """
90        Saves any changes to the associated `Project`.
91        """
92        self.kwarg_override = {'invoice_number': form.instance.invoice_number}
93        return super().form_valid(form)

A class based UpdateView for updating the given project.

model = <class 'vkk.workhours.models.Project'>
form_class = <class 'django.forms.widgets.ProjectForm'>
drop_key = None
slug_field = 'invoice_number'
slug_url_kwarg = 'invoice_number'
def form_valid(self, form):
88    def form_valid(self, form):
89        """
90        Saves any changes to the associated `Project`.
91        """
92        self.kwarg_override = {'invoice_number': form.instance.invoice_number}
93        return super().form_valid(form)

Saves any changes to the associated Project.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.views.CustomUpdateView
on_success
template_name
vkk.generic.mixins.OnSuccessMixin
kwarg_override
get_success_url
django.views.generic.edit.UpdateView
template_name_suffix
django.views.generic.detail.SingleObjectTemplateResponseMixin
template_name_field
get_template_names
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
django.views.generic.edit.BaseUpdateView
get
post
django.views.generic.edit.ModelFormMixin
fields
get_form_class
get_form_kwargs
django.views.generic.edit.FormMixin
initial
success_url
prefix
get_initial
get_prefix
get_form
form_invalid
get_context_data
django.views.generic.detail.SingleObjectMixin
queryset
context_object_name
pk_url_kwarg
query_pk_and_slug
get_object
get_queryset
get_slug_field
get_context_object_name
django.views.generic.base.ContextMixin
extra_context
django.views.generic.edit.ProcessFormView
put
class AccountingManagerCreateView(vkk.workhours.accounting.views.AccountingCreateView):
 96class AccountingManagerCreateView(AccountingCreateView):
 97    """
 98    A class based `CreateView` providing utilities for creating new `ProjectManager`s.
 99    """
100    model = ProjectManager
101    form_class = modelform_factory(
102        model=ProjectManager,
103        fields=['start', 'end', 'is_proxy'],
104        widgets={'start': CustomDateInput, 'end': CustomDateInput}
105    )
106    on_success = 'add_manager_success'
107    drop_key = 'pk'
108
109    def form_valid(self, form):
110        """
111        Attempts to save the newly created `ProjectManager` to the database.
112        """
113        form.instance.manager = User.objects.get(pk=self.kwargs['pk'])
114        form.instance.project = Project.objects.get(
115            invoice_number=self.kwargs['invoice_number'])
116        try:
117            form.instance.full_clean()
118        except ValidationError as err:
119            form.add_error(None, err)
120            return self.form_invalid(form)
121        return super().form_valid(form)

A class based CreateView providing utilities for creating new ProjectManagers.

form_class = <class 'django.forms.widgets.ProjectManagerForm'>
on_success = 'add_manager_success'
drop_key = 'pk'
def form_valid(self, form):
109    def form_valid(self, form):
110        """
111        Attempts to save the newly created `ProjectManager` to the database.
112        """
113        form.instance.manager = User.objects.get(pk=self.kwargs['pk'])
114        form.instance.project = Project.objects.get(
115            invoice_number=self.kwargs['invoice_number'])
116        try:
117            form.instance.full_clean()
118        except ValidationError as err:
119            form.add_error(None, err)
120            return self.form_invalid(form)
121        return super().form_valid(form)

Attempts to save the newly created ProjectManager to the database.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.views.CustomCreateView
template_name
vkk.generic.mixins.OnSuccessMixin
kwarg_override
get_success_url
django.views.generic.edit.CreateView
template_name_suffix
django.views.generic.detail.SingleObjectTemplateResponseMixin
template_name_field
get_template_names
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
django.views.generic.edit.BaseCreateView
get
post
django.views.generic.edit.ModelFormMixin
fields
get_form_class
get_form_kwargs
django.views.generic.edit.FormMixin
initial
success_url
prefix
get_initial
get_prefix
get_form
form_invalid
get_context_data
django.views.generic.detail.SingleObjectMixin
queryset
slug_field
context_object_name
slug_url_kwarg
pk_url_kwarg
query_pk_and_slug
get_object
get_queryset
get_slug_field
get_context_object_name
django.views.generic.base.ContextMixin
extra_context
django.views.generic.edit.ProcessFormView
put
class AccountingContributorCreateView(vkk.workhours.accounting.views.AccountingCreateView):
124class AccountingContributorCreateView(AccountingCreateView):
125    """
126    A class based `CreateView` providing utilities for creating new `ProjectAssignment`s.
127    """
128    model = ProjectAssignment
129    fields = ['salary_level']
130    on_success = 'add_contributor_success'
131    drop_key = 'pk'
132
133    def form_valid(self, form):
134        """
135        Attempts to save the newly created `ProjectAssignment` to the database.
136        """
137        form.instance.contributor = User.objects.get(pk=self.kwargs['pk'])
138        form.instance.project = Project.objects.get(
139            invoice_number=self.kwargs['invoice_number'])
140        try:
141            form.instance.full_clean()
142        except ValidationError as err:
143            form.add_error(None, err)
144            return self.form_invalid(form)
145        return super().form_valid(form)

A class based CreateView providing utilities for creating new ProjectAssignments.

fields = ['salary_level']
on_success = 'add_contributor_success'
drop_key = 'pk'
def form_valid(self, form):
133    def form_valid(self, form):
134        """
135        Attempts to save the newly created `ProjectAssignment` to the database.
136        """
137        form.instance.contributor = User.objects.get(pk=self.kwargs['pk'])
138        form.instance.project = Project.objects.get(
139            invoice_number=self.kwargs['invoice_number'])
140        try:
141            form.instance.full_clean()
142        except ValidationError as err:
143            form.add_error(None, err)
144            return self.form_invalid(form)
145        return super().form_valid(form)

Attempts to save the newly created ProjectAssignment to the database.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.views.CustomCreateView
template_name
vkk.generic.mixins.OnSuccessMixin
kwarg_override
get_success_url
django.views.generic.edit.CreateView
template_name_suffix
django.views.generic.detail.SingleObjectTemplateResponseMixin
template_name_field
get_template_names
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
django.views.generic.edit.BaseCreateView
get
post
django.views.generic.edit.ModelFormMixin
get_form_class
get_form_kwargs
django.views.generic.edit.FormMixin
initial
form_class
success_url
prefix
get_initial
get_prefix
get_form
form_invalid
get_context_data
django.views.generic.detail.SingleObjectMixin
queryset
slug_field
context_object_name
slug_url_kwarg
pk_url_kwarg
query_pk_and_slug
get_object
get_queryset
get_slug_field
get_context_object_name
django.views.generic.base.ContextMixin
extra_context
django.views.generic.edit.ProcessFormView
put
class AccountingContributorDeleteView(vkk.workhours.accounting.views.AccountingDeleteView):
148class AccountingContributorDeleteView(AccountingDeleteView):
149    """
150    A class based `DeleteView` providing utilities for deleting `ProjectAssignment`s.
151    """
152    model = ProjectAssignment
153    form_class = ContributorDeleteForm
154    on_success = 'delete_contributor_success'
155    drop_key = 'pk'
156
157    def get_form_kwargs(self):
158        """Return the keyword arguments for instantiating the form."""
159        kwargs = super().get_form_kwargs()
160        kwargs['id'] = self.kwargs['pk']
161        return kwargs

A class based DeleteView providing utilities for deleting ProjectAssignments.

on_success = 'delete_contributor_success'
drop_key = 'pk'
def get_form_kwargs(self):
157    def get_form_kwargs(self):
158        """Return the keyword arguments for instantiating the form."""
159        kwargs = super().get_form_kwargs()
160        kwargs['id'] = self.kwargs['pk']
161        return kwargs

Return the keyword arguments for instantiating the form.

Inherited Members
django.views.generic.edit.BaseDeleteView
BaseDeleteView
post
form_valid
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.views.CustomDeleteView
template_name
vkk.generic.mixins.OnSuccessMixin
kwarg_override
get_success_url
django.views.generic.edit.DeleteView
template_name_suffix
django.views.generic.detail.SingleObjectTemplateResponseMixin
template_name_field
get_template_names
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
django.views.generic.edit.DeletionMixin
success_url
delete
django.views.generic.edit.FormMixin
initial
prefix
get_initial
get_prefix
get_form_class
get_form
form_invalid
get_context_data
django.views.generic.detail.BaseDetailView
get
django.views.generic.detail.SingleObjectMixin
queryset
slug_field
context_object_name
slug_url_kwarg
pk_url_kwarg
query_pk_and_slug
get_object
get_queryset
get_slug_field
get_context_object_name
django.views.generic.base.ContextMixin
extra_context
django.views.generic.base.View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
class AccountingManagerDeleteView(vkk.workhours.accounting.views.AccountingDeleteView):
163class AccountingManagerDeleteView(AccountingDeleteView):
164    """
165    A class based `DeleteView` providing utilities for deleting `ProjectManager`s.
166    """
167    model = ProjectManager
168    on_success = 'delete_manager_success'
169    drop_key = 'pk'

A class based DeleteView providing utilities for deleting ProjectManagers.

on_success = 'delete_manager_success'
drop_key = 'pk'
Inherited Members
django.views.generic.edit.BaseDeleteView
BaseDeleteView
form_class
post
form_valid
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.views.CustomDeleteView
template_name
vkk.generic.mixins.OnSuccessMixin
kwarg_override
get_success_url
django.views.generic.edit.DeleteView
template_name_suffix
django.views.generic.detail.SingleObjectTemplateResponseMixin
template_name_field
get_template_names
django.views.generic.base.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
django.views.generic.edit.DeletionMixin
success_url
delete
django.views.generic.edit.FormMixin
initial
prefix
get_initial
get_prefix
get_form_class
get_form
get_form_kwargs
form_invalid
get_context_data
django.views.generic.detail.BaseDetailView
get
django.views.generic.detail.SingleObjectMixin
queryset
slug_field
context_object_name
slug_url_kwarg
pk_url_kwarg
query_pk_and_slug
get_object
get_queryset
get_slug_field
get_context_object_name
django.views.generic.base.ContextMixin
extra_context
django.views.generic.base.View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
class AccountingWorkhourSheetSelectionView(vkk.workhours.accounting.mixins.AccountantRequiredMixin, vkk.workhours.mixins.PeriodSelectorMixin, django.views.generic.base.RedirectView):
172class AccountingWorkhourSheetSelectionView(AccountantRequiredMixin, PeriodSelectorMixin, RedirectView):
173    """
174    A class based `View` for selecting a `Period` for a work hour sheet.
175    """
176    def get_redirect_url(self, *args, **kwargs):
177        """
178        Returns an URL to redirect to based on the given period.
179        """
180        # Catches Period Selection from GET
181        if 'period' in self.request.GET:
182            query_set = Period.objects.all()
183            form = PeriodSelectForm(query_set, data=self.request.GET)
184            if form.is_valid():
185                period = form.cleaned_data.get("period")
186            else:
187                raise Http404()
188        # Catches Period no given
189        elif 'period_pk' not in kwargs:
190            period = Period.objects.latest(create=True)
191        # Looks up Period
192        else:
193            period = get_object_or_404(Period, pk=kwargs['period_pk'])
194
195        return reverse(
196            'vkk:workhours:accounting:projects:project:workhours_sheet',
197            args=[kwargs['invoice_number'], period.pk]
198        )

A class based View for selecting a Period for a work hour sheet.

def get_redirect_url(self, *args, **kwargs):
176    def get_redirect_url(self, *args, **kwargs):
177        """
178        Returns an URL to redirect to based on the given period.
179        """
180        # Catches Period Selection from GET
181        if 'period' in self.request.GET:
182            query_set = Period.objects.all()
183            form = PeriodSelectForm(query_set, data=self.request.GET)
184            if form.is_valid():
185                period = form.cleaned_data.get("period")
186            else:
187                raise Http404()
188        # Catches Period no given
189        elif 'period_pk' not in kwargs:
190            period = Period.objects.latest(create=True)
191        # Looks up Period
192        else:
193            period = get_object_or_404(Period, pk=kwargs['period_pk'])
194
195        return reverse(
196            'vkk:workhours:accounting:projects:project:workhours_sheet',
197            args=[kwargs['invoice_number'], period.pk]
198        )

Returns an URL to redirect to based on the given period.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.workhours.mixins.PeriodSelectorMixin
period_select_namespace
get_context_data
get_select_url
django.views.generic.base.RedirectView
permanent
url
pattern_name
query_string
get
head
post
options
delete
put
patch
class AccountingWorkhourSheetView(vkk.workhours.accounting.mixins.AccountantRequiredMixin, vkk.workhours.mixins.PeriodSelectorMixin, django.views.generic.edit.FormView):
201class AccountingWorkhourSheetView(AccountantRequiredMixin, PeriodSelectorMixin, FormView):
202    """
203    A class based `View` providing a work hours sheet for a given project and period.
204    """
205    form_class = WorkhourSheetForm
206    template_name = 'vkk/workhours/accounting/projects/project/workhours_sheet.html'
207    period_select_namespace = 'vkk:workhours:accounting:projects:project:workhours_sheet_selection'
208
209    def get_form_kwargs(self):
210        """
211        Returns a dictionary of keyword arguments for instatiating the associated form.
212        """
213        kwargs = super().get_form_kwargs()
214        self.assignments = ProjectAssignment.objects.filter(
215            project__invoice_number=self.kwargs['invoice_number']
216        ).order_by('contributor__last_name', 'contributor__first_name')
217        kwargs.update({
218            'period_pk': self.kwargs['period_pk'],
219            'assignments': self.assignments,
220            'closure_lock': False,
221            'invoice_number': self.kwargs['invoice_number'],
222        })
223        return kwargs
224
225    def get_success_url(self):
226        """
227        Returns a URL to redirect to after a successful action.
228        """
229        return reverse(
230            'vkk:workhours:accounting:projects:project:workhours_sheet_success',
231            args=[
232                self.kwargs['invoice_number'],
233                self.kwargs['period_pk']
234            ]
235        )
236
237    def get_context_data(self, **kwargs):
238        """
239        Returns additional context data as an dictionary. This is used for rendering the page.
240        """
241        context = super().get_context_data(**kwargs)
242        manager_closed_count = self.assignments.filter(
243            periodclosure__period=self.kwargs['period_pk'],
244            periodclosure__is_closed_manager=True
245        ).count()
246        assignment_count = self.assignments.count()
247        if manager_closed_count == assignment_count:
248            context['closed'] = True
249        else:
250            context['closed'] = False
251        context['saveable'] = True
252
253        context['project'] = get_object_or_404(
254            Project, invoice_number=self.kwargs['invoice_number'])
255        return context
256
257    def form_valid(self, form):
258        """
259        Saves all changes to work hours to the database.
260        """
261        form.save()
262        return super().form_valid(form)

A class based View providing a work hours sheet for a given project and period.

form_class = <class 'vkk.workhours.forms.WorkhourSheetForm'>
template_name = 'vkk/workhours/accounting/projects/project/workhours_sheet.html'
period_select_namespace = 'vkk:workhours:accounting:projects:project:workhours_sheet_selection'
def get_form_kwargs(self):
209    def get_form_kwargs(self):
210        """
211        Returns a dictionary of keyword arguments for instatiating the associated form.
212        """
213        kwargs = super().get_form_kwargs()
214        self.assignments = ProjectAssignment.objects.filter(
215            project__invoice_number=self.kwargs['invoice_number']
216        ).order_by('contributor__last_name', 'contributor__first_name')
217        kwargs.update({
218            'period_pk': self.kwargs['period_pk'],
219            'assignments': self.assignments,
220            'closure_lock': False,
221            'invoice_number': self.kwargs['invoice_number'],
222        })
223        return kwargs

Returns a dictionary of keyword arguments for instatiating the associated form.

def get_success_url(self):
225    def get_success_url(self):
226        """
227        Returns a URL to redirect to after a successful action.
228        """
229        return reverse(
230            'vkk:workhours:accounting:projects:project:workhours_sheet_success',
231            args=[
232                self.kwargs['invoice_number'],
233                self.kwargs['period_pk']
234            ]
235        )

Returns a URL to redirect to after a successful action.

def get_context_data(self, **kwargs):
237    def get_context_data(self, **kwargs):
238        """
239        Returns additional context data as an dictionary. This is used for rendering the page.
240        """
241        context = super().get_context_data(**kwargs)
242        manager_closed_count = self.assignments.filter(
243            periodclosure__period=self.kwargs['period_pk'],
244            periodclosure__is_closed_manager=True
245        ).count()
246        assignment_count = self.assignments.count()
247        if manager_closed_count == assignment_count:
248            context['closed'] = True
249        else:
250            context['closed'] = False
251        context['saveable'] = True
252
253        context['project'] = get_object_or_404(
254            Project, invoice_number=self.kwargs['invoice_number'])
255        return context

Returns additional context data as an dictionary. This is used for rendering the page.

def form_valid(self, form):
257    def form_valid(self, form):
258        """
259        Saves all changes to work hours to the database.
260        """
261        form.save()
262        return super().form_valid(form)

Saves all changes to work hours to the database.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.workhours.mixins.PeriodSelectorMixin
get_select_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
form_invalid
django.views.generic.base.ContextMixin
extra_context
django.views.generic.edit.ProcessFormView
get
post
put
class AccountingPeriodClosureView(vkk.workhours.accounting.mixins.AccountantRequiredMixin, vkk.generic.mixins.OnSuccessMixin, django.views.generic.edit.FormView):
265class AccountingPeriodClosureView(AccountantRequiredMixin, OnSuccessMixin, FormView):
266    """
267    A class based `View` providing utilities to close the period for new entries 
268    for all contributors of the given project.
269    """
270    template_name = 'vkk/workhours/contributor/closure.html'
271    form_class = Form
272    on_success = 'period_closure_success'
273
274    def post(self, request, *args, **kwargs):
275        """
276        Handler for POST rquests.
277        """
278        form = self.get_form()
279        if form.is_valid():
280            self.close_period()
281            return self.form_valid(form)
282        else:
283            return self.form_invalid(form)
284
285    def close_period(self):
286        """
287        Closes the period for all contributors to a project for a given period.
288        """
289        assignments = ProjectAssignment.objects.filter(
290            project__invoice_number=self.kwargs['invoice_number'],
291        )
292        period = get_object_or_404(Period, pk=self.kwargs['period_pk'])
293        closing = [
294            PeriodClosure(
295                period=period,
296                project_assignment=assignment,
297                is_closed_contributor=True,
298                is_closed_manager=True
299            ) for assignment in assignments
300        ]
301        PeriodClosure.objects.bulk_create(
302            closing,
303            update_conflicts=True,
304            update_fields=['is_closed_contributor', 'is_closed_manager'],
305            unique_fields=['project_assignment', 'period']
306        )

A class based View providing utilities to close the period for new entries for all contributors of the given project.

template_name = 'vkk/workhours/contributor/closure.html'
form_class = <class 'django.forms.forms.Form'>
on_success = 'period_closure_success'
def post(self, request, *args, **kwargs):
274    def post(self, request, *args, **kwargs):
275        """
276        Handler for POST rquests.
277        """
278        form = self.get_form()
279        if form.is_valid():
280            self.close_period()
281            return self.form_valid(form)
282        else:
283            return self.form_invalid(form)

Handler for POST rquests.

def close_period(self):
285    def close_period(self):
286        """
287        Closes the period for all contributors to a project for a given period.
288        """
289        assignments = ProjectAssignment.objects.filter(
290            project__invoice_number=self.kwargs['invoice_number'],
291        )
292        period = get_object_or_404(Period, pk=self.kwargs['period_pk'])
293        closing = [
294            PeriodClosure(
295                period=period,
296                project_assignment=assignment,
297                is_closed_contributor=True,
298                is_closed_manager=True
299            ) for assignment in assignments
300        ]
301        PeriodClosure.objects.bulk_create(
302            closing,
303            update_conflicts=True,
304            update_fields=['is_closed_contributor', 'is_closed_manager'],
305            unique_fields=['project_assignment', 'period']
306        )

Closes the period for all contributors to a project for a given period.

Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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
309class AccountingPeriodClosureSuccessView(AccountantRequiredMixin, CustomSuccessView):
310    """
311    A class based `View` providing utilities for displaying a successfull closing of a period
312    for all contributors to a given project.
313    """
314    template_name = 'vkk/workhours/contributor/closure_success.html'
315    model = PeriodClosure
316    on_success = 'workhours_sheet'

A class based View providing utilities for displaying a successfull closing of a period for all contributors to a given project.

template_name = 'vkk/workhours/contributor/closure_success.html'
on_success = 'workhours_sheet'
Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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
class AccountingExportView(vkk.workhours.accounting.mixins.AccountantRequiredMixin, django.views.generic.edit.FormView):
321class AccountingExportView(AccountantRequiredMixin, FormView):
322    """
323    A class based `View` providing an overview over all possible actions associated with the
324    export of project related data.
325    """
326    template_name = 'vkk/workhours/accounting/projects/project/export.html'

A class based View providing an overview over all possible actions associated with the export of project related data.

template_name = 'vkk/workhours/accounting/projects/project/export.html'
Inherited Members
django.views.generic.base.View
View
http_method_names
view_is_async
as_view
setup
http_method_not_allowed
options
vkk.workhours.accounting.mixins.AccountantRequiredMixin
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.TemplateResponseMixin
template_engine
response_class
content_type
render_to_response
get_template_names
django.views.generic.edit.FormMixin
initial
form_class
success_url
prefix
get_initial
get_prefix
get_form_class
get_form
get_form_kwargs
get_success_url
form_valid
form_invalid
get_context_data
django.views.generic.base.ContextMixin
extra_context
django.views.generic.edit.ProcessFormView
get
post
put