diff --git a/app/vkk/workhours/accounting/projects/project/export/__init__.py b/app/vkk/workhours/accounting/projects/project/export/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d397b2042836752356ca764f47fb51d290cc092b 100644 --- a/app/vkk/workhours/accounting/projects/project/export/__init__.py +++ b/app/vkk/workhours/accounting/projects/project/export/__init__.py @@ -0,0 +1,5 @@ +""" +This module contains the utilities associated with the export of a project data. + +This module's substructure closely resembles the path substructure of the website. +""" \ No newline at end of file diff --git a/app/vkk/workhours/accounting/projects/project/export/funded_staff/__init__.py b/app/vkk/workhours/accounting/projects/project/export/funded_staff/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9dadd36ecb74fcb4608fc6bad517d83ed228aea4 100644 --- a/app/vkk/workhours/accounting/projects/project/export/funded_staff/__init__.py +++ b/app/vkk/workhours/accounting/projects/project/export/funded_staff/__init__.py @@ -0,0 +1,3 @@ +""" +This module contains the utilities associated with the administration of project funded staff. +""" \ No newline at end of file diff --git a/app/vkk/workhours/accounting/projects/project/export/funded_staff/forms.py b/app/vkk/workhours/accounting/projects/project/export/funded_staff/forms.py index 8e59ad8afb6a2dc67d5ebdd7bb2383f0f99669e7..7139d8c3be30b4cf2f54ac2840c6332d8d0781b6 100644 --- a/app/vkk/workhours/accounting/projects/project/export/funded_staff/forms.py +++ b/app/vkk/workhours/accounting/projects/project/export/funded_staff/forms.py @@ -1,3 +1,7 @@ +""" +A collection of forms used in this module. +""" + from django import forms from vkk.workhours.models import ( ProjectFundedStaff, ProjectFundedStaffDate, SalaryLevel, @@ -6,6 +10,9 @@ from vkk.workhours.models import ( from vkk.workhours.forms import CustomDateInput class ProjectFundedStaffForm(forms.ModelForm): + """ + A class based `ModelForm` providing utilities for administrating `ProjectFundedStaff`. + """ class Meta: model = ProjectFundedStaffDate fields = ['date'] @@ -14,6 +21,9 @@ class ProjectFundedStaffForm(forms.ModelForm): } def __init__(self, *args, invoice_number=None, **kwargs): + """ + Initializes and returns an object of this class. An invoice_number of a project must be provided. + """ super().__init__(*args, **kwargs) self._invoice_number = invoice_number @@ -37,6 +47,10 @@ class ProjectFundedStaffForm(forms.ModelForm): ].initial = project_funded_staff_instance.hours def save(self, commit=True): + """ + Tries to save and return the `ProjectFundedStaffDate` instance of this class and + all associated instances of `ProjectFundedStaff` to the database. + """ if self.instance.pk is None: self.instance.project = Project.objects.get(invoice_number=self._invoice_number) # save instance diff --git a/app/vkk/workhours/accounting/projects/project/export/funded_staff/urls.py b/app/vkk/workhours/accounting/projects/project/export/funded_staff/urls.py index 1c85f2558fe2665c242084c9a51ef2851620c108..9c57a10c84f0cc4de32d37a5f2063c6794576ee4 100644 --- a/app/vkk/workhours/accounting/projects/project/export/funded_staff/urls.py +++ b/app/vkk/workhours/accounting/projects/project/export/funded_staff/urls.py @@ -1,3 +1,7 @@ +""" +This submodule contains the routing configuration. +""" + from django.urls import include, path from django.utils.translation import gettext_lazy as _ from vkk.models import ProjectFundedStaffDate diff --git a/app/vkk/workhours/accounting/projects/project/export/funded_staff/views.py b/app/vkk/workhours/accounting/projects/project/export/funded_staff/views.py index 222e25cc04f960c07fdba2f8ceb9d8fefd80467f..bb03bc672eb24ab52e95574824cdca136cfe54c3 100644 --- a/app/vkk/workhours/accounting/projects/project/export/funded_staff/views.py +++ b/app/vkk/workhours/accounting/projects/project/export/funded_staff/views.py @@ -1,3 +1,7 @@ +""" +This submodule contains class based views. +""" + from vkk.workhours.accounting.views import ( AccountingCreateView, AccountingListView ) @@ -5,20 +9,32 @@ from vkk.workhours.models import ProjectFundedStaffDate, ProjectFundedStaff from .forms import ProjectFundedStaffForm class ProjectFundedStaffListView(AccountingListView): + """ + A class based `View` providing utilities for listing `ProjectFundedStaff`. + """ model = ProjectFundedStaffDate fields = ['date'] ordering = ['date'] def get_queryset(self): + """ + Returns a query set of `ProjectFundedStaffDate` for the given project. + """ return super().get_queryset().filter( project__invoice_number=self.kwargs['invoice_number'], ) class ProjectFundedStaffCreateView(AccountingCreateView): + """ + A class based `View` providing utilities for creating `ProjectFundedStaff`. + """ model = ProjectFundedStaffDate form_class = ProjectFundedStaffForm def get_form_kwargs(self): + """ + Returns a dictionary of keyword arguments used for instanciating the associated form. + """ kwargs = super().get_form_kwargs() kwargs.update({ 'invoice_number' : self.kwargs['invoice_number'], diff --git a/app/vkk/workhours/accounting/projects/project/export/receipts/__init__.py b/app/vkk/workhours/accounting/projects/project/export/receipts/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..19fa3ab15c4a812f3ca88c7e04aaeff749295fda 100644 --- a/app/vkk/workhours/accounting/projects/project/export/receipts/__init__.py +++ b/app/vkk/workhours/accounting/projects/project/export/receipts/__init__.py @@ -0,0 +1,3 @@ +""" +This module contains the utilities associated with the generating of receipts. +""" \ No newline at end of file diff --git a/app/vkk/workhours/accounting/projects/project/export/receipts/forms.py b/app/vkk/workhours/accounting/projects/project/export/receipts/forms.py index 78a6b0c86b08768a346236f05b65469e2786c94c..813887c748b816b1780a9899dee0167ba8930ac9 100644 --- a/app/vkk/workhours/accounting/projects/project/export/receipts/forms.py +++ b/app/vkk/workhours/accounting/projects/project/export/receipts/forms.py @@ -1,3 +1,7 @@ +""" +A collection of forms used in this module. +""" + from django import forms from decimal import Decimal from django.db.models import Sum, F @@ -9,6 +13,10 @@ from vkk.generic.forms import CustomDateInput class ReceiptForm(forms.ModelForm): + """ + A `Form` sublcass for generating a receipt. This mimics the papaer receipts + used previously. + """ class Meta: model = models.Receipt fields = ['start', 'end', 'receipt_number', 'buper'] @@ -21,6 +29,9 @@ class ReceiptForm(forms.ModelForm): js = ('scripts/receipts.js',) def __init__(self, *args, project=None, **kwargs): + """ + Initializes and returns a new object of this class. A `Project` instance must be provided. + """ super().__init__(*args, **kwargs) self.project = project self.department = self.project.department @@ -35,6 +46,9 @@ class ReceiptForm(forms.ModelForm): self.data_dict = None def set_and_clean_general_costs(self, start, end): + """ + Sets and cleans data associated to `GeneralCosts`. + """ if models.GeneralCosts.objects.filter(start__gt=start, start__lte=end,).exists(): raise ValidationError( _('General cost records are ambiguous.'), @@ -51,6 +65,9 @@ class ReceiptForm(forms.ModelForm): ) def set_and_clean_department_costs(self, start, end): + """ + Sets and cleans data associated to `DepartmentCosts`. + """ if models.DepartmentCosts.objects.filter( department=self.department, start__date__gt=start, @@ -72,6 +89,9 @@ class ReceiptForm(forms.ModelForm): ) def set_and_clean_project_funded_staff(self, start, end): + """ + Sets and cleans data associated to `ProjectFundedStaff`. + """ if models.ProjectFundedStaffDate.objects.filter( project=self.project, date__gt=start, @@ -95,6 +115,9 @@ class ReceiptForm(forms.ModelForm): ) def set_and_clean_salary_level(self, start, end): + """ + Sets and cleans data associated to `SalaryLevelCosts`. + """ if models.SalaryLevelDate.objects.filter( date__gt=start, date__lte=end, @@ -118,6 +141,9 @@ class ReceiptForm(forms.ModelForm): ) def check_peroid_overlap(self, start, end): + """ + Checks whether the given start and end dates overlap with only one period. + """ # check for matching period if not models.Period.objects.filter(start=start, end=end).exists(): raise ValidationError( @@ -126,6 +152,9 @@ class ReceiptForm(forms.ModelForm): ) def check_closed_periods(self, start, end): + """ + Checks whether the period has been closed. + """ assignments_not_closed = models.ProjectAssignment.objects.filter( project=self.project ).exclude( @@ -141,6 +170,9 @@ class ReceiptForm(forms.ModelForm): ) def set_and_clean_workhours(self, start, end): + """ + Sets and cleans work hours. (Summed) + """ if self.salary_costs is not None: # Specify constraints for aggregations agg1 = self.salary_costs.filter( @@ -178,6 +210,9 @@ class ReceiptForm(forms.ModelForm): self.salary_costs_annotated2 = agg2 def clean(self): + """ + Cleans the associated data of this object and returns it as a dictionary. + """ start = self.cleaned_data.get('start') end = self.cleaned_data.get('end') if start is not None and end is not None: @@ -191,6 +226,9 @@ class ReceiptForm(forms.ModelForm): return self.cleaned_data def save(self, commit=True): + """ + Tries to save the data associated with this form as a receipt. + """ self.instance.project = self.project self.instance.data = self.to_json() return super().save(commit) @@ -297,6 +335,9 @@ class ReceiptForm(forms.ModelForm): } def to_data_dict(self): + """ + Returns the data associated with this form as a dictionary. + """ self.data_dict = self._project_dict() \ | self._department_dict() \ | self._general_costs_dict() \ @@ -322,10 +363,17 @@ class ReceiptForm(forms.ModelForm): return self.data_dict def to_json(self): + """ + Encodes and returns the data associated with this form in JSON. + """ return CostumJSONEncoder().encode(self.to_data_dict()) class CostumJSONEncoder(DjangoJSONEncoder): + """ + A costum JSON encoder which rounds numbers after to decimal places and uses + commas instead of points. + """ def default(self, o): if isinstance(o, Decimal): return str(round(o, 2)).replace(".", ",") @@ -334,6 +382,9 @@ class CostumJSONEncoder(DjangoJSONEncoder): class ReceiptTemplateSelectForm(forms.Form): + """ + A `Form` subclass for selecting a specific receipt template. + """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) queryset = models.ReceiptTemplate.objects.all().order_by('-start') diff --git a/app/vkk/workhours/accounting/projects/project/export/receipts/urls.py b/app/vkk/workhours/accounting/projects/project/export/receipts/urls.py index 3cf163158f4f44ffc8041ab2d28b062ab723c6c1..a114852de2508292cea4795087d19204fbeaf096 100644 --- a/app/vkk/workhours/accounting/projects/project/export/receipts/urls.py +++ b/app/vkk/workhours/accounting/projects/project/export/receipts/urls.py @@ -1,3 +1,7 @@ +""" +This submodule contains the routing configuration. +""" + from django.urls import include, path from django.utils.translation import gettext_lazy as _ from vkk.models import Receipt diff --git a/app/vkk/workhours/accounting/projects/project/export/receipts/views.py b/app/vkk/workhours/accounting/projects/project/export/receipts/views.py index af1c1e34152d696d1237b4110340bfa373348ad8..c845d35aa6c0830ab978ea84cc58ccd02ffe1dc3 100644 --- a/app/vkk/workhours/accounting/projects/project/export/receipts/views.py +++ b/app/vkk/workhours/accounting/projects/project/export/receipts/views.py @@ -1,3 +1,7 @@ +""" +This submodule contains class based views. +""" + import json import csv import datetime @@ -14,6 +18,9 @@ from .forms import ReceiptForm, ReceiptTemplateSelectForm class ReceiptListView(AccountingListView): + """ + A class based `ListView` providing utilities for listing `Receipt`s. + """ model = Receipt fields = ['create_time', 'start', 'end'] ordering = ['create_time'] @@ -24,22 +31,34 @@ class ReceiptListView(AccountingListView): } def get_queryset(self): + """ + Returns a query set of `Receipt`s for a given project. + """ return super().get_queryset().filter( project__invoice_number=self.kwargs['invoice_number'], ) class ReceiptCreateView(AccountingCreateView): + """ + A class based `CreateView` providing utilities for creating `Receipt`s. + """ model = Receipt form_class = ReceiptForm def post(self, request, *args, **kwargs): + """ + Handler for POST requests. + """ if request.content_type == 'application/json': return self.post_json(request, *args, **kwargs) else: return super().post(request, *args, **kwargs) def post_json(self, request, *args, **kwargs): + """ + Handler for POST requests with content type `'application/json'`. + """ kwargs = self.get_form_kwargs() kwargs.update({ "data": json.loads(request.body), @@ -54,6 +73,9 @@ class ReceiptCreateView(AccountingCreateView): ) def get_form_kwargs(self): + """ + Returns a dictionary of keywords for instanciating the associated form. + """ kwargs = super().get_form_kwargs() project = Project.objects.get( invoice_number=self.kwargs['invoice_number'] @@ -65,15 +87,25 @@ class ReceiptCreateView(AccountingCreateView): class ReceiptTemplateSelectionView(FormView, AccountantRequiredMixin): + """ + A class based `View` providing utilities for selecting a template for a receipt and export + in shape of a `.csv` file. + """ form_class = ReceiptTemplateSelectForm template_name = "vkk/workhours/accounting/projects/project/export/receipt_select.html" def form_valid(self, form): + """ + Returns a CSV-Response based on the given receipt and receipt template from the form. + """ receipt_template = form.cleaned_data.get("receipt_template") receipt = get_object_or_404(Receipt, pk=self.kwargs["pk"]) return self.csv_response(receipt, receipt_template) def csv_response(self, receipt, receipt_template): + """ + Returns a CSV-Response based on the given receipt and receipt template. + """ response = HttpResponse( content_type='text/csv', headers={ diff --git a/app/vkk/workhours/accounting/projects/project/export/urls.py b/app/vkk/workhours/accounting/projects/project/export/urls.py index f8b63a0fe67669c0180084e45f451627ad38360b..f5eadf4136218d8f0ecaff59777c46477b8d16bc 100644 --- a/app/vkk/workhours/accounting/projects/project/export/urls.py +++ b/app/vkk/workhours/accounting/projects/project/export/urls.py @@ -1,3 +1,7 @@ +""" +This submodule contains the routing configuration. +""" + from django.urls import include, path from django.utils.translation import gettext_lazy as _ from vkk.workhours.accounting.views import AccountingOverView