vkk.workhours.allprojects.forms
A collection of Form
s for this module.
1""" 2A collection of `Form`s for this module. 3""" 4 5from django import forms 6from django.db.models import Sum 7from django.utils import timezone 8from vkk.users.models import User 9from vkk.workhours.models import ProjectAssignment, Period, WorkHours, WorkHoursCorrection, PeriodClosure 10from django.utils.translation import gettext_lazy as _ 11 12 13class YearSelectForm(forms.Form): 14 """ 15 A `Form` subclass for selecting a year. 16 """ 17 18 def __init__(self, *args, **kwargs): 19 """ 20 Constructs and returns an instance of this class. 21 """ 22 super().__init__(*args, **kwargs) 23 choices = {(entry['start'].year, entry['start'].year) 24 for entry in Period.objects.all().values('start')} 25 choices = list(choices) 26 choices.sort() 27 self.fields['year'] = forms.ChoiceField( 28 label=_('Year'), 29 choices=choices 30 ) 31 32 33class AssigneeForm(forms.Form): 34 """ 35 A `Form` subclass providing functionality for administrating work hours of a contributor. 36 """ 37 custom_template = 'vkk/workhours/allprojects/assignee_form.html' 38 39 class Media: 40 """ 41 A inner class for meta information. 42 """ 43 css = {'all': ('styles/assignee_form.css',)} 44 js = ('scripts/assignee.js',) 45 46 def __init__(self, *args, assignee=None, manager=None, year=None, **kwargs): 47 """ 48 Constructs and returns an instance of this class. 49 """ 50 super().__init__(*args, **kwargs) 51 self._assignee = assignee 52 self._year = year 53 self._periods = Period.objects.filter( 54 start__year=year, 55 ).order_by('start') 56 self._assignments = ProjectAssignment.objects.filter( 57 contributor=assignee, 58 project__projectmanager__manager=manager, 59 project__projectmanager__end__gte=timezone.now().date() 60 ).select_related("project").order_by('project__invoice_number') 61 62 for assignment in self._assignments: 63 for period in self._periods: 64 workhours = WorkHours.objects.filter( 65 project_assignment=assignment, 66 period=period, 67 ) 68 workhours_correction = WorkHoursCorrection.objects.filter( 69 project_assignment=assignment, 70 period=period, 71 ) 72 73 disabled = timezone.now() > period.dead_line_final 74 if not disabled: 75 closure = PeriodClosure.objects.filter( 76 project_assignment=assignment, 77 period=period 78 ) 79 if closure.exists(): 80 disabled = closure[0].is_closed_manager 81 82 if not disabled: 83 disabled = period.end < assignment.project.start 84 disabled |= period.start > assignment.project.end 85 86 field = forms.DecimalField( 87 required=False, 88 min_value=0, 89 max_digits=5, 90 decimal_places=2, 91 disabled=disabled 92 ) 93 94 initial = workhours.aggregate(Sum('hours'))['hours__sum'] or 0 95 if workhours_correction.exists(): 96 initial += workhours_correction[0].ammount 97 if initial != 0: 98 field.initial = initial 99 100 self.fields[str(assignment.id) + '_' + str(period.id)] = field 101 102 def _get_field_structure(self): 103 return [ 104 ( 105 assignment, 106 [ 107 self[str(assignment.pk) + '_' + str(period.id)] for period in self._periods 108 ] 109 ) for assignment in self._assignments 110 ] 111 112 def as_html(self): 113 context = super().get_context() 114 context.update({ 115 'assignee': self._assignee, 116 'year': self._year, 117 'periods': self._periods, 118 'fields_more': self._get_field_structure() 119 }) 120 return self.render( 121 template_name=self.custom_template, 122 context=context 123 ) 124 125 def save(self): 126 if self.is_valid() and self.has_changed(): 127 for assignment in self._assignments: 128 for period in self._periods: 129 field_name = str(assignment.pk) + '_' + str(period.id) 130 if field_name in self.changed_data: 131 workhours = WorkHours.objects.filter( 132 project_assignment=assignment, 133 period=period, 134 ) 135 value = (self.cleaned_data[field_name] or 0) - ( 136 workhours.aggregate(Sum('hours'))['hours__sum'] or 0) 137 if value == 0: 138 WorkHoursCorrection.objects.filter( 139 project_assignment=assignment, 140 period=period, 141 ).delete() 142 else: 143 WorkHoursCorrection.objects.update_or_create( 144 project_assignment=assignment, 145 period=period, 146 defaults={'ammount': value} 147 ) 148 149 150class AssgineeClosureForm(forms.Form): 151 assignee = forms.ModelChoiceField(queryset=User.objects.all()) 152 period = forms.ModelChoiceField(queryset=Period.objects.all()) 153 manager = forms.ModelChoiceField(queryset=User.objects.all()) 154 155 def save(self): 156 if self.is_valid(): 157 assignee = self.cleaned_data['assignee'] 158 period = self.cleaned_data['period'] 159 manager = self.cleaned_data['manager'] 160 project_assignments = ProjectAssignment.objects.filter( 161 contributor=assignee, 162 project__projectmanager__manager=manager 163 ) 164 165 objs = [PeriodClosure( 166 period=period, 167 project_assignment=project_assignment, 168 is_closed_contributor=True, 169 is_closed_manager=True, 170 ) for project_assignment in project_assignments] 171 172 PeriodClosure.objects.bulk_create( 173 objs=objs, 174 ignore_conflicts=False, 175 update_conflicts=True, 176 update_fields=['is_closed_contributor', 'is_closed_manager'], 177 unique_fields=['period', 'project_assignment'] 178 )
class
YearSelectForm(django.forms.forms.Form):
14class YearSelectForm(forms.Form): 15 """ 16 A `Form` subclass for selecting a year. 17 """ 18 19 def __init__(self, *args, **kwargs): 20 """ 21 Constructs and returns an instance of this class. 22 """ 23 super().__init__(*args, **kwargs) 24 choices = {(entry['start'].year, entry['start'].year) 25 for entry in Period.objects.all().values('start')} 26 choices = list(choices) 27 choices.sort() 28 self.fields['year'] = forms.ChoiceField( 29 label=_('Year'), 30 choices=choices 31 )
A Form
subclass for selecting a year.
YearSelectForm(*args, **kwargs)
19 def __init__(self, *args, **kwargs): 20 """ 21 Constructs and returns an instance of this class. 22 """ 23 super().__init__(*args, **kwargs) 24 choices = {(entry['start'].year, entry['start'].year) 25 for entry in Period.objects.all().values('start')} 26 choices = list(choices) 27 choices.sort() 28 self.fields['year'] = forms.ChoiceField( 29 label=_('Year'), 30 choices=choices 31 )
Constructs and returns an instance of this class.
Inherited Members
- django.forms.forms.BaseForm
- default_renderer
- field_order
- prefix
- use_required_attribute
- template_name_div
- template_name_p
- template_name_table
- template_name_ul
- template_name_label
- is_bound
- data
- files
- auto_id
- initial
- error_class
- label_suffix
- empty_permitted
- fields
- renderer
- order_fields
- errors
- is_valid
- add_prefix
- add_initial_prefix
- template_name
- get_context
- non_field_errors
- add_error
- has_error
- full_clean
- clean
- has_changed
- changed_data
- is_multipart
- visible_fields
- get_initial_for_field
- django.forms.utils.RenderableFormMixin
- as_p
- as_table
- as_ul
- as_div
- django.forms.utils.RenderableMixin
- render
class
AssigneeForm(django.forms.forms.Form):
34class AssigneeForm(forms.Form): 35 """ 36 A `Form` subclass providing functionality for administrating work hours of a contributor. 37 """ 38 custom_template = 'vkk/workhours/allprojects/assignee_form.html' 39 40 class Media: 41 """ 42 A inner class for meta information. 43 """ 44 css = {'all': ('styles/assignee_form.css',)} 45 js = ('scripts/assignee.js',) 46 47 def __init__(self, *args, assignee=None, manager=None, year=None, **kwargs): 48 """ 49 Constructs and returns an instance of this class. 50 """ 51 super().__init__(*args, **kwargs) 52 self._assignee = assignee 53 self._year = year 54 self._periods = Period.objects.filter( 55 start__year=year, 56 ).order_by('start') 57 self._assignments = ProjectAssignment.objects.filter( 58 contributor=assignee, 59 project__projectmanager__manager=manager, 60 project__projectmanager__end__gte=timezone.now().date() 61 ).select_related("project").order_by('project__invoice_number') 62 63 for assignment in self._assignments: 64 for period in self._periods: 65 workhours = WorkHours.objects.filter( 66 project_assignment=assignment, 67 period=period, 68 ) 69 workhours_correction = WorkHoursCorrection.objects.filter( 70 project_assignment=assignment, 71 period=period, 72 ) 73 74 disabled = timezone.now() > period.dead_line_final 75 if not disabled: 76 closure = PeriodClosure.objects.filter( 77 project_assignment=assignment, 78 period=period 79 ) 80 if closure.exists(): 81 disabled = closure[0].is_closed_manager 82 83 if not disabled: 84 disabled = period.end < assignment.project.start 85 disabled |= period.start > assignment.project.end 86 87 field = forms.DecimalField( 88 required=False, 89 min_value=0, 90 max_digits=5, 91 decimal_places=2, 92 disabled=disabled 93 ) 94 95 initial = workhours.aggregate(Sum('hours'))['hours__sum'] or 0 96 if workhours_correction.exists(): 97 initial += workhours_correction[0].ammount 98 if initial != 0: 99 field.initial = initial 100 101 self.fields[str(assignment.id) + '_' + str(period.id)] = field 102 103 def _get_field_structure(self): 104 return [ 105 ( 106 assignment, 107 [ 108 self[str(assignment.pk) + '_' + str(period.id)] for period in self._periods 109 ] 110 ) for assignment in self._assignments 111 ] 112 113 def as_html(self): 114 context = super().get_context() 115 context.update({ 116 'assignee': self._assignee, 117 'year': self._year, 118 'periods': self._periods, 119 'fields_more': self._get_field_structure() 120 }) 121 return self.render( 122 template_name=self.custom_template, 123 context=context 124 ) 125 126 def save(self): 127 if self.is_valid() and self.has_changed(): 128 for assignment in self._assignments: 129 for period in self._periods: 130 field_name = str(assignment.pk) + '_' + str(period.id) 131 if field_name in self.changed_data: 132 workhours = WorkHours.objects.filter( 133 project_assignment=assignment, 134 period=period, 135 ) 136 value = (self.cleaned_data[field_name] or 0) - ( 137 workhours.aggregate(Sum('hours'))['hours__sum'] or 0) 138 if value == 0: 139 WorkHoursCorrection.objects.filter( 140 project_assignment=assignment, 141 period=period, 142 ).delete() 143 else: 144 WorkHoursCorrection.objects.update_or_create( 145 project_assignment=assignment, 146 period=period, 147 defaults={'ammount': value} 148 )
A Form
subclass providing functionality for administrating work hours of a contributor.
AssigneeForm(*args, assignee=None, manager=None, year=None, **kwargs)
47 def __init__(self, *args, assignee=None, manager=None, year=None, **kwargs): 48 """ 49 Constructs and returns an instance of this class. 50 """ 51 super().__init__(*args, **kwargs) 52 self._assignee = assignee 53 self._year = year 54 self._periods = Period.objects.filter( 55 start__year=year, 56 ).order_by('start') 57 self._assignments = ProjectAssignment.objects.filter( 58 contributor=assignee, 59 project__projectmanager__manager=manager, 60 project__projectmanager__end__gte=timezone.now().date() 61 ).select_related("project").order_by('project__invoice_number') 62 63 for assignment in self._assignments: 64 for period in self._periods: 65 workhours = WorkHours.objects.filter( 66 project_assignment=assignment, 67 period=period, 68 ) 69 workhours_correction = WorkHoursCorrection.objects.filter( 70 project_assignment=assignment, 71 period=period, 72 ) 73 74 disabled = timezone.now() > period.dead_line_final 75 if not disabled: 76 closure = PeriodClosure.objects.filter( 77 project_assignment=assignment, 78 period=period 79 ) 80 if closure.exists(): 81 disabled = closure[0].is_closed_manager 82 83 if not disabled: 84 disabled = period.end < assignment.project.start 85 disabled |= period.start > assignment.project.end 86 87 field = forms.DecimalField( 88 required=False, 89 min_value=0, 90 max_digits=5, 91 decimal_places=2, 92 disabled=disabled 93 ) 94 95 initial = workhours.aggregate(Sum('hours'))['hours__sum'] or 0 96 if workhours_correction.exists(): 97 initial += workhours_correction[0].ammount 98 if initial != 0: 99 field.initial = initial 100 101 self.fields[str(assignment.id) + '_' + str(period.id)] = field
Constructs and returns an instance of this class.
def
as_html(self):
113 def as_html(self): 114 context = super().get_context() 115 context.update({ 116 'assignee': self._assignee, 117 'year': self._year, 118 'periods': self._periods, 119 'fields_more': self._get_field_structure() 120 }) 121 return self.render( 122 template_name=self.custom_template, 123 context=context 124 )
def
save(self):
126 def save(self): 127 if self.is_valid() and self.has_changed(): 128 for assignment in self._assignments: 129 for period in self._periods: 130 field_name = str(assignment.pk) + '_' + str(period.id) 131 if field_name in self.changed_data: 132 workhours = WorkHours.objects.filter( 133 project_assignment=assignment, 134 period=period, 135 ) 136 value = (self.cleaned_data[field_name] or 0) - ( 137 workhours.aggregate(Sum('hours'))['hours__sum'] or 0) 138 if value == 0: 139 WorkHoursCorrection.objects.filter( 140 project_assignment=assignment, 141 period=period, 142 ).delete() 143 else: 144 WorkHoursCorrection.objects.update_or_create( 145 project_assignment=assignment, 146 period=period, 147 defaults={'ammount': value} 148 )
Inherited Members
- django.forms.forms.BaseForm
- default_renderer
- field_order
- prefix
- use_required_attribute
- template_name_div
- template_name_p
- template_name_table
- template_name_ul
- template_name_label
- is_bound
- data
- files
- auto_id
- initial
- error_class
- label_suffix
- empty_permitted
- fields
- renderer
- order_fields
- errors
- is_valid
- add_prefix
- add_initial_prefix
- template_name
- get_context
- non_field_errors
- add_error
- has_error
- full_clean
- clean
- has_changed
- changed_data
- is_multipart
- visible_fields
- get_initial_for_field
- django.forms.utils.RenderableFormMixin
- as_p
- as_table
- as_ul
- as_div
- django.forms.utils.RenderableMixin
- render
class
AssigneeForm.Media:
40 class Media: 41 """ 42 A inner class for meta information. 43 """ 44 css = {'all': ('styles/assignee_form.css',)} 45 js = ('scripts/assignee.js',)
A inner class for meta information.
class
AssgineeClosureForm(django.forms.forms.Form):
151class AssgineeClosureForm(forms.Form): 152 assignee = forms.ModelChoiceField(queryset=User.objects.all()) 153 period = forms.ModelChoiceField(queryset=Period.objects.all()) 154 manager = forms.ModelChoiceField(queryset=User.objects.all()) 155 156 def save(self): 157 if self.is_valid(): 158 assignee = self.cleaned_data['assignee'] 159 period = self.cleaned_data['period'] 160 manager = self.cleaned_data['manager'] 161 project_assignments = ProjectAssignment.objects.filter( 162 contributor=assignee, 163 project__projectmanager__manager=manager 164 ) 165 166 objs = [PeriodClosure( 167 period=period, 168 project_assignment=project_assignment, 169 is_closed_contributor=True, 170 is_closed_manager=True, 171 ) for project_assignment in project_assignments] 172 173 PeriodClosure.objects.bulk_create( 174 objs=objs, 175 ignore_conflicts=False, 176 update_conflicts=True, 177 update_fields=['is_closed_contributor', 'is_closed_manager'], 178 unique_fields=['period', 'project_assignment'] 179 )
A collection of Fields, plus their associated data.
def
save(self):
156 def save(self): 157 if self.is_valid(): 158 assignee = self.cleaned_data['assignee'] 159 period = self.cleaned_data['period'] 160 manager = self.cleaned_data['manager'] 161 project_assignments = ProjectAssignment.objects.filter( 162 contributor=assignee, 163 project__projectmanager__manager=manager 164 ) 165 166 objs = [PeriodClosure( 167 period=period, 168 project_assignment=project_assignment, 169 is_closed_contributor=True, 170 is_closed_manager=True, 171 ) for project_assignment in project_assignments] 172 173 PeriodClosure.objects.bulk_create( 174 objs=objs, 175 ignore_conflicts=False, 176 update_conflicts=True, 177 update_fields=['is_closed_contributor', 'is_closed_manager'], 178 unique_fields=['period', 'project_assignment'] 179 )
declared_fields =
{'assignee': <django.forms.models.ModelChoiceField object>, 'period': <django.forms.models.ModelChoiceField object>, 'manager': <django.forms.models.ModelChoiceField object>}
base_fields =
{'assignee': <django.forms.models.ModelChoiceField object>, 'period': <django.forms.models.ModelChoiceField object>, 'manager': <django.forms.models.ModelChoiceField object>}
Inherited Members
- django.forms.forms.BaseForm
- BaseForm
- default_renderer
- field_order
- prefix
- use_required_attribute
- template_name_div
- template_name_p
- template_name_table
- template_name_ul
- template_name_label
- is_bound
- data
- files
- auto_id
- initial
- error_class
- label_suffix
- empty_permitted
- fields
- renderer
- order_fields
- errors
- is_valid
- add_prefix
- add_initial_prefix
- template_name
- get_context
- non_field_errors
- add_error
- has_error
- full_clean
- clean
- has_changed
- changed_data
- is_multipart
- visible_fields
- get_initial_for_field
- django.forms.utils.RenderableFormMixin
- as_p
- as_table
- as_ul
- as_div
- django.forms.utils.RenderableMixin
- render