vkk.workhours.accounting.projects.project.export.receipts.views
This submodule contains class based views.
1""" 2This submodule contains class based views. 3""" 4 5import json 6import csv 7import datetime 8from django.utils.translation import gettext_lazy as _ 9from django.http import JsonResponse, HttpResponse 10from django.views.generic import FormView 11from django.shortcuts import get_object_or_404 12from vkk.workhours.accounting.mixins import AccountantRequiredMixin 13from vkk.workhours.accounting.views import ( 14 AccountingListView, AccountingCreateView 15) 16from vkk.workhours.models import Receipt, Project 17from .forms import ReceiptForm, ReceiptTemplateSelectForm 18 19 20class ReceiptListView(AccountingListView): 21 """ 22 A class based `ListView` providing utilities for listing `Receipt`s. 23 """ 24 model = Receipt 25 fields = ['create_time', 'start', 'end'] 26 ordering = ['create_time'] 27 action_options = { 28 'details': _('Details'), 29 'delete': _('Delete'), 30 'receipt_download': _('Download'), 31 } 32 33 def get_queryset(self): 34 """ 35 Returns a query set of `Receipt`s for a given project. 36 """ 37 return super().get_queryset().filter( 38 project__invoice_number=self.kwargs['invoice_number'], 39 ) 40 41 42class ReceiptCreateView(AccountingCreateView): 43 """ 44 A class based `CreateView` providing utilities for creating `Receipt`s. 45 """ 46 model = Receipt 47 form_class = ReceiptForm 48 49 def post(self, request, *args, **kwargs): 50 """ 51 Handler for POST requests. 52 """ 53 if request.content_type == 'application/json': 54 return self.post_json(request, *args, **kwargs) 55 else: 56 return super().post(request, *args, **kwargs) 57 58 def post_json(self, request, *args, **kwargs): 59 """ 60 Handler for POST requests with content type `'application/json'`. 61 """ 62 kwargs = self.get_form_kwargs() 63 kwargs.update({ 64 "data": json.loads(request.body), 65 }) 66 form = self.get_form_class()(**kwargs) 67 68 if form.is_valid(): 69 return JsonResponse(form.to_data_dict()) 70 else: 71 return JsonResponse( 72 {'errors': form.errors} 73 ) 74 75 def get_form_kwargs(self): 76 """ 77 Returns a dictionary of keywords for instanciating the associated form. 78 """ 79 kwargs = super().get_form_kwargs() 80 project = Project.objects.get( 81 invoice_number=self.kwargs['invoice_number'] 82 ) 83 kwargs.update({ 84 "project": project, 85 }) 86 return kwargs 87 88 89class ReceiptTemplateSelectionView(FormView, AccountantRequiredMixin): 90 """ 91 A class based `View` providing utilities for selecting a template for a receipt and export 92 in shape of a `.csv` file. 93 """ 94 form_class = ReceiptTemplateSelectForm 95 template_name = "vkk/workhours/accounting/projects/project/export/receipt_select.html" 96 97 def form_valid(self, form): 98 """ 99 Returns a CSV-Response based on the given receipt and receipt template from the form. 100 """ 101 receipt_template = form.cleaned_data.get("receipt_template") 102 receipt = get_object_or_404(Receipt, pk=self.kwargs["pk"]) 103 return self.csv_response(receipt, receipt_template) 104 105 def csv_response(self, receipt, receipt_template): 106 """ 107 Returns a CSV-Response based on the given receipt and receipt template. 108 """ 109 response = HttpResponse( 110 content_type='text/csv', 111 headers={ 112 'Content-Disposition': f'attachment; filename="{ receipt.id }.csv"'}, 113 ) 114 115 # init writer for creating csv 116 writer = csv.writer(response, delimiter=';') 117 118 # retrieving data for creating the receipt in csv format 119 template_data = receipt_template.data 120 data = json.loads(receipt.data) 121 122 # retrieving keys and writing header row 123 keys = [list(column.keys())[0] for column in template_data] 124 writer.writerow([str(key) for key in keys]) 125 126 # getting columns and reorganize them to rows 127 table_template = zip(*(column.get(key) 128 for column, key in zip(template_data, keys))) 129 130 # here be conversion 131 table = [ 132 [ 133 _data_cell_calculation(cell, receipt, data) for cell in row 134 ] for row in table_template 135 ] 136 137 # writing data to csv 138 writer.writerows(table) 139 140 return response 141 142 143def _data_cell_calculation(template, receipt, data): 144 """This functions retrieves the required data point according to the template""" 145 method = template.get("method") 146 if method is None: 147 return "" 148 elif method == "FIXED": 149 return template.get("value") 150 elif method == "GENERATED": 151 value = template.get("value") 152 args = value.split(" ") 153 out = [] 154 for arg in args: 155 lookup = None 156 parts = arg.split(".") 157 if parts[0] == "data": 158 lookup = data 159 elif hasattr(receipt, parts[0]): 160 lookup = getattr(receipt, parts[0]) 161 if lookup is not None: 162 for part in parts[1:]: 163 if isinstance(lookup, dict): 164 lookup = lookup.get(part) 165 elif hasattr(lookup, part): 166 lookup = getattr(lookup, part) 167 if lookup is None: 168 break 169 if lookup is not None: 170 out.append(str(_format(lookup))) 171 else: 172 out.append(str(arg)) 173 return " ".join(out) 174 else: 175 return "" 176 177 178def _format(value): 179 if isinstance(value, datetime.date): 180 return value.strftime("%d.%m.%Y") 181 elif isinstance(value, str): 182 return 0 if value == "0.00" else value 183 elif isinstance(value, bool): 184 return _("Ja") if value else _("Nein") 185 else: 186 return value
21class ReceiptListView(AccountingListView): 22 """ 23 A class based `ListView` providing utilities for listing `Receipt`s. 24 """ 25 model = Receipt 26 fields = ['create_time', 'start', 'end'] 27 ordering = ['create_time'] 28 action_options = { 29 'details': _('Details'), 30 'delete': _('Delete'), 31 'receipt_download': _('Download'), 32 } 33 34 def get_queryset(self): 35 """ 36 Returns a query set of `Receipt`s for a given project. 37 """ 38 return super().get_queryset().filter( 39 project__invoice_number=self.kwargs['invoice_number'], 40 )
A class based ListView
providing utilities for listing Receipt
s.
model =
<class 'vkk.workhours.models.Receipt'>
def
get_queryset(self):
34 def get_queryset(self): 35 """ 36 Returns a query set of `Receipt`s for a given project. 37 """ 38 return super().get_queryset().filter( 39 project__invoice_number=self.kwargs['invoice_number'], 40 )
Returns a query set of Receipt
s for a given project.
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.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_orphans
- context_object_name
- paginator_class
- page_kwarg
- get_ordering
- paginate_queryset
- get_paginate_by
- get_paginator
- get_paginate_orphans
- get_allow_empty
- get_context_object_name
- get_context_data
- django.views.generic.base.ContextMixin
- extra_context
43class ReceiptCreateView(AccountingCreateView): 44 """ 45 A class based `CreateView` providing utilities for creating `Receipt`s. 46 """ 47 model = Receipt 48 form_class = ReceiptForm 49 50 def post(self, request, *args, **kwargs): 51 """ 52 Handler for POST requests. 53 """ 54 if request.content_type == 'application/json': 55 return self.post_json(request, *args, **kwargs) 56 else: 57 return super().post(request, *args, **kwargs) 58 59 def post_json(self, request, *args, **kwargs): 60 """ 61 Handler for POST requests with content type `'application/json'`. 62 """ 63 kwargs = self.get_form_kwargs() 64 kwargs.update({ 65 "data": json.loads(request.body), 66 }) 67 form = self.get_form_class()(**kwargs) 68 69 if form.is_valid(): 70 return JsonResponse(form.to_data_dict()) 71 else: 72 return JsonResponse( 73 {'errors': form.errors} 74 ) 75 76 def get_form_kwargs(self): 77 """ 78 Returns a dictionary of keywords for instanciating the associated form. 79 """ 80 kwargs = super().get_form_kwargs() 81 project = Project.objects.get( 82 invoice_number=self.kwargs['invoice_number'] 83 ) 84 kwargs.update({ 85 "project": project, 86 }) 87 return kwargs
A class based CreateView
providing utilities for creating Receipt
s.
model =
<class 'vkk.workhours.models.Receipt'>
form_class =
<class 'vkk.workhours.accounting.projects.project.export.receipts.forms.ReceiptForm'>
def
post(self, request, *args, **kwargs):
50 def post(self, request, *args, **kwargs): 51 """ 52 Handler for POST requests. 53 """ 54 if request.content_type == 'application/json': 55 return self.post_json(request, *args, **kwargs) 56 else: 57 return super().post(request, *args, **kwargs)
Handler for POST requests.
def
post_json(self, request, *args, **kwargs):
59 def post_json(self, request, *args, **kwargs): 60 """ 61 Handler for POST requests with content type `'application/json'`. 62 """ 63 kwargs = self.get_form_kwargs() 64 kwargs.update({ 65 "data": json.loads(request.body), 66 }) 67 form = self.get_form_class()(**kwargs) 68 69 if form.is_valid(): 70 return JsonResponse(form.to_data_dict()) 71 else: 72 return JsonResponse( 73 {'errors': form.errors} 74 )
Handler for POST requests with content type 'application/json'
.
def
get_form_kwargs(self):
76 def get_form_kwargs(self): 77 """ 78 Returns a dictionary of keywords for instanciating the associated form. 79 """ 80 kwargs = super().get_form_kwargs() 81 project = Project.objects.get( 82 invoice_number=self.kwargs['invoice_number'] 83 ) 84 kwargs.update({ 85 "project": project, 86 }) 87 return kwargs
Returns a dictionary of keywords for instanciating the associated form.
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.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
- django.views.generic.edit.ModelFormMixin
- fields
- get_form_class
- form_valid
- 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
ReceiptTemplateSelectionView(django.views.generic.edit.FormView, vkk.workhours.accounting.mixins.AccountantRequiredMixin):
90class ReceiptTemplateSelectionView(FormView, AccountantRequiredMixin): 91 """ 92 A class based `View` providing utilities for selecting a template for a receipt and export 93 in shape of a `.csv` file. 94 """ 95 form_class = ReceiptTemplateSelectForm 96 template_name = "vkk/workhours/accounting/projects/project/export/receipt_select.html" 97 98 def form_valid(self, form): 99 """ 100 Returns a CSV-Response based on the given receipt and receipt template from the form. 101 """ 102 receipt_template = form.cleaned_data.get("receipt_template") 103 receipt = get_object_or_404(Receipt, pk=self.kwargs["pk"]) 104 return self.csv_response(receipt, receipt_template) 105 106 def csv_response(self, receipt, receipt_template): 107 """ 108 Returns a CSV-Response based on the given receipt and receipt template. 109 """ 110 response = HttpResponse( 111 content_type='text/csv', 112 headers={ 113 'Content-Disposition': f'attachment; filename="{ receipt.id }.csv"'}, 114 ) 115 116 # init writer for creating csv 117 writer = csv.writer(response, delimiter=';') 118 119 # retrieving data for creating the receipt in csv format 120 template_data = receipt_template.data 121 data = json.loads(receipt.data) 122 123 # retrieving keys and writing header row 124 keys = [list(column.keys())[0] for column in template_data] 125 writer.writerow([str(key) for key in keys]) 126 127 # getting columns and reorganize them to rows 128 table_template = zip(*(column.get(key) 129 for column, key in zip(template_data, keys))) 130 131 # here be conversion 132 table = [ 133 [ 134 _data_cell_calculation(cell, receipt, data) for cell in row 135 ] for row in table_template 136 ] 137 138 # writing data to csv 139 writer.writerows(table) 140 141 return response
A class based View
providing utilities for selecting a template for a receipt and export
in shape of a .csv
file.
form_class =
<class 'vkk.workhours.accounting.projects.project.export.receipts.forms.ReceiptTemplateSelectForm'>
def
form_valid(self, form):
98 def form_valid(self, form): 99 """ 100 Returns a CSV-Response based on the given receipt and receipt template from the form. 101 """ 102 receipt_template = form.cleaned_data.get("receipt_template") 103 receipt = get_object_or_404(Receipt, pk=self.kwargs["pk"]) 104 return self.csv_response(receipt, receipt_template)
Returns a CSV-Response based on the given receipt and receipt template from the form.
def
csv_response(self, receipt, receipt_template):
106 def csv_response(self, receipt, receipt_template): 107 """ 108 Returns a CSV-Response based on the given receipt and receipt template. 109 """ 110 response = HttpResponse( 111 content_type='text/csv', 112 headers={ 113 'Content-Disposition': f'attachment; filename="{ receipt.id }.csv"'}, 114 ) 115 116 # init writer for creating csv 117 writer = csv.writer(response, delimiter=';') 118 119 # retrieving data for creating the receipt in csv format 120 template_data = receipt_template.data 121 data = json.loads(receipt.data) 122 123 # retrieving keys and writing header row 124 keys = [list(column.keys())[0] for column in template_data] 125 writer.writerow([str(key) for key in keys]) 126 127 # getting columns and reorganize them to rows 128 table_template = zip(*(column.get(key) 129 for column, key in zip(template_data, keys))) 130 131 # here be conversion 132 table = [ 133 [ 134 _data_cell_calculation(cell, receipt, data) for cell in row 135 ] for row in table_template 136 ] 137 138 # writing data to csv 139 writer.writerows(table) 140 141 return response
Returns a CSV-Response based on the given receipt and receipt template.
Inherited Members
- django.views.generic.base.View
- View
- http_method_names
- view_is_async
- as_view
- setup
- dispatch
- http_method_not_allowed
- options
- 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
- get_success_url
- form_invalid
- get_context_data
- django.views.generic.base.ContextMixin
- extra_context
- django.views.generic.edit.ProcessFormView
- get
- post
- put
- 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