vkk.workhours.allprojects.forms

A collection of Forms 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.

media

Return all media required to render the widgets on this form.

declared_fields = {}
base_fields = {}
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
hidden_fields
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.

custom_template = 'vkk/workhours/allprojects/assignee_form.html'
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                            )
media

Return all media required to render the widgets on this form.

declared_fields = {}
base_fields = {}
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
hidden_fields
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.

css = {'all': ('styles/assignee_form.css',)}
js = ('scripts/assignee.js',)
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.

assignee
period
manager
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            )
media

Return all media required to render the widgets on this form.

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
hidden_fields
visible_fields
get_initial_for_field
django.forms.utils.RenderableFormMixin
as_p
as_table
as_ul
as_div
django.forms.utils.RenderableMixin
render