vkk.workhours.accounting.projects.project.export.receipts.views
1import json 2import csv 3import datetime 4from django.utils.translation import gettext_lazy as _ 5from django.http import JsonResponse, HttpResponse 6from django.views.generic import FormView 7from django.shortcuts import get_object_or_404 8from vkk.workhours.accounting.mixins import AccountantRequiredMixin 9from vkk.workhours.accounting.views import ( 10 AccountingListView, AccountingCreateView 11) 12from vkk.workhours.models import Receipt, Project 13from .forms import ReceiptForm, ReceiptTemplateSelectForm 14 15 16class ReceiptListView(AccountingListView): 17 model = Receipt 18 fields = ['create_time', 'start', 'end'] 19 ordering = ['create_time'] 20 action_options = { 21 'details': _('Details'), 22 'delete': _('Delete'), 23 'receipt_download': _('Download'), 24 } 25 26 def get_queryset(self): 27 return super().get_queryset().filter( 28 project__invoice_number=self.kwargs['invoice_number'], 29 ) 30 31 32class ReceiptCreateView(AccountingCreateView): 33 model = Receipt 34 form_class = ReceiptForm 35 36 def post(self, request, *args, **kwargs): 37 if request.content_type == 'application/json': 38 return self.post_json(request, *args, **kwargs) 39 else: 40 return super().post(request, *args, **kwargs) 41 42 def post_json(self, request, *args, **kwargs): 43 kwargs = self.get_form_kwargs() 44 kwargs.update({ 45 "data": json.loads(request.body), 46 }) 47 form = self.get_form_class()(**kwargs) 48 49 if form.is_valid(): 50 return JsonResponse(form.to_data_dict()) 51 else: 52 return JsonResponse( 53 {'errors': form.errors} 54 ) 55 56 def get_form_kwargs(self): 57 kwargs = super().get_form_kwargs() 58 project = Project.objects.get( 59 invoice_number=self.kwargs['invoice_number'] 60 ) 61 kwargs.update({ 62 "project": project, 63 }) 64 return kwargs 65 66 67class ReceiptTemplateSelectionView(FormView, AccountantRequiredMixin): 68 form_class = ReceiptTemplateSelectForm 69 template_name = "vkk/workhours/accounting/projects/project/export/receipt_select.html" 70 71 def form_valid(self, form): 72 receipt_template = form.cleaned_data.get("receipt_template") 73 receipt = get_object_or_404(Receipt, pk=self.kwargs["pk"]) 74 return self.csv_response(receipt, receipt_template) 75 76 def csv_response(self, receipt, receipt_template): 77 response = HttpResponse( 78 content_type='text/csv', 79 headers={ 80 'Content-Disposition': f'attachment; filename="{ receipt.id }.csv"'}, 81 ) 82 83 # init writer for creating csv 84 writer = csv.writer(response, delimiter=';') 85 86 # retrieving data for creating the receipt in csv format 87 template_data = receipt_template.data 88 data = json.loads(receipt.data) 89 90 # retrieving keys and writing header row 91 keys = [list(column.keys())[0] for column in template_data] 92 writer.writerow([str(key) for key in keys]) 93 94 # getting columns and reorganize them to rows 95 table_template = zip(*(column.get(key) 96 for column, key in zip(template_data, keys))) 97 98 # here be conversion 99 table = [ 100 [ 101 _data_cell_calculation(cell, receipt, data) for cell in row 102 ] for row in table_template 103 ] 104 105 # writing data to csv 106 writer.writerows(table) 107 108 return response 109 110 111def _data_cell_calculation(template, receipt, data): 112 """This functions retrieves the required data point according to the template""" 113 method = template.get("method") 114 if method is None: 115 return "" 116 elif method == "FIXED": 117 return template.get("value") 118 elif method == "GENERATED": 119 value = template.get("value") 120 args = value.split(" ") 121 out = [] 122 for arg in args: 123 lookup = None 124 parts = arg.split(".") 125 if parts[0] == "data": 126 lookup = data 127 elif hasattr(receipt, parts[0]): 128 lookup = getattr(receipt, parts[0]) 129 if lookup is not None: 130 for part in parts[1:]: 131 if isinstance(lookup, dict): 132 lookup = lookup.get(part) 133 elif hasattr(lookup, part): 134 lookup = getattr(lookup, part) 135 if lookup is None: 136 break 137 if lookup is not None: 138 out.append(str(_format(lookup))) 139 else: 140 out.append(str(arg)) 141 return " ".join(out) 142 else: 143 return "" 144 145 146def _format(value): 147 if isinstance(value, datetime.date): 148 return value.strftime("%d.%m.%Y") 149 elif isinstance(value, str): 150 return 0 if value == "0.00" else value 151 elif isinstance(value, bool): 152 return _("Ja") if value else _("Nein") 153 else: 154 return value
17class ReceiptListView(AccountingListView): 18 model = Receipt 19 fields = ['create_time', 'start', 'end'] 20 ordering = ['create_time'] 21 action_options = { 22 'details': _('Details'), 23 'delete': _('Delete'), 24 'receipt_download': _('Download'), 25 } 26 27 def get_queryset(self): 28 return super().get_queryset().filter( 29 project__invoice_number=self.kwargs['invoice_number'], 30 )
Verify that the current user has accountant rights.
def
get_queryset(self):
27 def get_queryset(self): 28 return super().get_queryset().filter( 29 project__invoice_number=self.kwargs['invoice_number'], 30 )
Return the list of items for this view.
The return value must be an iterable and may be an instance of
QuerySet
in which case QuerySet
specific behavior will be enabled.
Inherited Members
- django.views.generic.base.View
- View
- view_is_async
- as_view
- setup
- http_method_not_allowed
- options
- django.contrib.auth.mixins.AccessMixin
- get_login_url
- get_permission_denied_message
- get_redirect_field_name
- handle_no_permission
- django.views.generic.list.MultipleObjectTemplateResponseMixin
- get_template_names
- django.views.generic.base.TemplateResponseMixin
- render_to_response
- django.views.generic.list.BaseListView
- get
- django.views.generic.list.MultipleObjectMixin
- get_ordering
- paginate_queryset
- get_paginate_by
- get_paginator
- get_paginate_orphans
- get_allow_empty
- get_context_object_name
- get_context_data
33class ReceiptCreateView(AccountingCreateView): 34 model = Receipt 35 form_class = ReceiptForm 36 37 def post(self, request, *args, **kwargs): 38 if request.content_type == 'application/json': 39 return self.post_json(request, *args, **kwargs) 40 else: 41 return super().post(request, *args, **kwargs) 42 43 def post_json(self, request, *args, **kwargs): 44 kwargs = self.get_form_kwargs() 45 kwargs.update({ 46 "data": json.loads(request.body), 47 }) 48 form = self.get_form_class()(**kwargs) 49 50 if form.is_valid(): 51 return JsonResponse(form.to_data_dict()) 52 else: 53 return JsonResponse( 54 {'errors': form.errors} 55 ) 56 57 def get_form_kwargs(self): 58 kwargs = super().get_form_kwargs() 59 project = Project.objects.get( 60 invoice_number=self.kwargs['invoice_number'] 61 ) 62 kwargs.update({ 63 "project": project, 64 }) 65 return kwargs
Verify that the current user has accountant rights.
def
post(self, request, *args, **kwargs):
37 def post(self, request, *args, **kwargs): 38 if request.content_type == 'application/json': 39 return self.post_json(request, *args, **kwargs) 40 else: 41 return super().post(request, *args, **kwargs)
Handle POST requests: instantiate a form instance with the passed POST variables and then check if it's valid.
def
post_json(self, request, *args, **kwargs):
43 def post_json(self, request, *args, **kwargs): 44 kwargs = self.get_form_kwargs() 45 kwargs.update({ 46 "data": json.loads(request.body), 47 }) 48 form = self.get_form_class()(**kwargs) 49 50 if form.is_valid(): 51 return JsonResponse(form.to_data_dict()) 52 else: 53 return JsonResponse( 54 {'errors': form.errors} 55 )
def
get_form_kwargs(self):
57 def get_form_kwargs(self): 58 kwargs = super().get_form_kwargs() 59 project = Project.objects.get( 60 invoice_number=self.kwargs['invoice_number'] 61 ) 62 kwargs.update({ 63 "project": project, 64 }) 65 return kwargs
Return the keyword arguments for instantiating the form.
Inherited Members
- django.views.generic.base.View
- View
- view_is_async
- as_view
- setup
- http_method_not_allowed
- options
- django.contrib.auth.mixins.AccessMixin
- get_login_url
- get_permission_denied_message
- get_redirect_field_name
- handle_no_permission
- django.views.generic.detail.SingleObjectTemplateResponseMixin
- get_template_names
- django.views.generic.base.TemplateResponseMixin
- render_to_response
- django.views.generic.edit.BaseCreateView
- get
- django.views.generic.edit.ModelFormMixin
- get_form_class
- form_valid
- django.views.generic.edit.FormMixin
- get_initial
- get_prefix
- get_form
- form_invalid
- get_context_data
- django.views.generic.detail.SingleObjectMixin
- get_object
- get_queryset
- get_slug_field
- get_context_object_name
- django.views.generic.edit.ProcessFormView
- put
class
ReceiptTemplateSelectionView(django.views.generic.edit.FormView, vkk.workhours.accounting.mixins.AccountantRequiredMixin):
68class ReceiptTemplateSelectionView(FormView, AccountantRequiredMixin): 69 form_class = ReceiptTemplateSelectForm 70 template_name = "vkk/workhours/accounting/projects/project/export/receipt_select.html" 71 72 def form_valid(self, form): 73 receipt_template = form.cleaned_data.get("receipt_template") 74 receipt = get_object_or_404(Receipt, pk=self.kwargs["pk"]) 75 return self.csv_response(receipt, receipt_template) 76 77 def csv_response(self, receipt, receipt_template): 78 response = HttpResponse( 79 content_type='text/csv', 80 headers={ 81 'Content-Disposition': f'attachment; filename="{ receipt.id }.csv"'}, 82 ) 83 84 # init writer for creating csv 85 writer = csv.writer(response, delimiter=';') 86 87 # retrieving data for creating the receipt in csv format 88 template_data = receipt_template.data 89 data = json.loads(receipt.data) 90 91 # retrieving keys and writing header row 92 keys = [list(column.keys())[0] for column in template_data] 93 writer.writerow([str(key) for key in keys]) 94 95 # getting columns and reorganize them to rows 96 table_template = zip(*(column.get(key) 97 for column, key in zip(template_data, keys))) 98 99 # here be conversion 100 table = [ 101 [ 102 _data_cell_calculation(cell, receipt, data) for cell in row 103 ] for row in table_template 104 ] 105 106 # writing data to csv 107 writer.writerows(table) 108 109 return response
A view for displaying a form and rendering a template response.
def
form_valid(self, form):
72 def form_valid(self, form): 73 receipt_template = form.cleaned_data.get("receipt_template") 74 receipt = get_object_or_404(Receipt, pk=self.kwargs["pk"]) 75 return self.csv_response(receipt, receipt_template)
If the form is valid, redirect to the supplied URL.
def
csv_response(self, receipt, receipt_template):
77 def csv_response(self, receipt, receipt_template): 78 response = HttpResponse( 79 content_type='text/csv', 80 headers={ 81 'Content-Disposition': f'attachment; filename="{ receipt.id }.csv"'}, 82 ) 83 84 # init writer for creating csv 85 writer = csv.writer(response, delimiter=';') 86 87 # retrieving data for creating the receipt in csv format 88 template_data = receipt_template.data 89 data = json.loads(receipt.data) 90 91 # retrieving keys and writing header row 92 keys = [list(column.keys())[0] for column in template_data] 93 writer.writerow([str(key) for key in keys]) 94 95 # getting columns and reorganize them to rows 96 table_template = zip(*(column.get(key) 97 for column, key in zip(template_data, keys))) 98 99 # here be conversion 100 table = [ 101 [ 102 _data_cell_calculation(cell, receipt, data) for cell in row 103 ] for row in table_template 104 ] 105 106 # writing data to csv 107 writer.writerows(table) 108 109 return response
Inherited Members
- django.views.generic.base.View
- View
- view_is_async
- as_view
- setup
- dispatch
- http_method_not_allowed
- options
- django.views.generic.base.TemplateResponseMixin
- render_to_response
- get_template_names
- django.views.generic.edit.FormMixin
- get_initial
- get_prefix
- get_form_class
- get_form
- get_form_kwargs
- get_success_url
- form_invalid
- get_context_data
- django.views.generic.edit.ProcessFormView
- get
- post
- put
- django.contrib.auth.mixins.AccessMixin
- get_login_url
- get_permission_denied_message
- get_redirect_field_name
- handle_no_permission