vkk.workhours.contributor.forms

A collection of Forms for contributors.

  1"""
  2A collection of `Form`s for contributors.
  3"""
  4
  5import datetime
  6from django import forms
  7from vkk.workhours.models import WorkHours, Period, ProjectAssignment
  8from vkk.workhours.forms import date_iterator
  9
 10
 11class WorkhourCalendarForm(forms.Form):
 12    """
 13    A form for entering work hours resembling a calender.
 14    """
 15    class Media:
 16        """
 17        An inner class containing meta information for styling.
 18        """
 19        css = {'all': ('styles/calendar.css',)}
 20
 21    template_name_calendar = 'vkk/workhours/contributor/calendar.html'
 22
 23    def __init__(self, *args, period_pk=None, assignment_pk=None, **kwargs):
 24        """
 25        Constructs an `WorkhourCalendarForm` instance using the given primary
 26         keys of an `Period` and `ProjectAssignment`.
 27        """
 28        super().__init__(*args, **kwargs)
 29        self._project_assignment = ProjectAssignment.objects.get(
 30            pk=assignment_pk
 31        )
 32
 33        # create fields
 34        self._period = Period.objects.get(pk=period_pk)
 35        today = datetime.date.today()
 36        field_class = WorkHours.hours.field.formfield
 37
 38        for date in date_iterator(self._period.start, self._period.end):
 39            is_disabled = date > today or self._project_assignment.project.start > date \
 40                or self._project_assignment.project.end < date
 41            field = field_class(
 42                min_value=0,
 43                max_value=24,
 44                required=False,
 45                label=date.day,
 46                label_suffix='',
 47                disabled=is_disabled
 48            )
 49            self.fields[date.isoformat()] = field
 50
 51        # provide initial data
 52        workhours = WorkHours.objects.filter(
 53            period__pk=period_pk,
 54            project_assignment__pk=assignment_pk
 55        )
 56        for entry in workhours:
 57            field = self.fields.get(entry.day.isoformat())
 58            if field is not None:
 59                field.initial = entry.hours
 60
 61    def _get_date_calendar_structure(self):
 62        """
 63        Private method used for structuring some data for rendering the form.
 64        """
 65        dates = date_iterator(self._period.start, self._period.end)
 66
 67        # subdevision into months
 68        months = []
 69        month_number = -1
 70        for date in dates:
 71            if date.month != month_number:
 72                months += [[]]
 73                month_number = date.month
 74            months[-1] += [date]
 75
 76        # subdevision into weeks
 77        weeks = []
 78        for month in months:
 79            weeks += [[]]
 80            week_day = 7
 81            for date in month:
 82                if date.weekday() < week_day:
 83                    weeks[-1] += [[]]
 84                weeks[-1][-1] += [date]
 85                week_day = date.weekday()
 86
 87        return weeks
 88
 89    def _get_field_calendar_structure(self):
 90        """
 91        Private method used for structuring some data for rendering the form.
 92        """
 93        calendar = self._get_date_calendar_structure()
 94        return [[(
 95            [(day, self[day.isoformat()]) for day in week]
 96        ) for week in month] for month in calendar]
 97
 98    def as_calendar(self):
 99        """
100        Renders the form resembling a calender.
101        """
102        context = super().get_context()
103        context.update({'fields_more': self._get_field_calendar_structure()})
104        return self.render(
105            template_name=self.template_name_calendar,
106            context=context
107        )
108
109    def save(self):
110        """
111        Tries to create, modify or delete all changes.
112        """
113        if self.is_valid() and self.has_changed():
114            add = []
115            delete = []
116            for field_name in self.changed_data:
117                initial = self.fields[field_name].initial
118                value = self.cleaned_data.get(field_name)
119                if value is None or value == 0.0:
120                    delete.append(
121                        datetime.date.fromisoformat(field_name)
122                    )
123                elif initial is None:
124                    add.append(WorkHours(
125                        project_assignment=self._project_assignment,
126                        period=self._period,
127                        day=datetime.date.fromisoformat(field_name),
128                        hours=value
129                    ))
130                else:
131                    WorkHours.objects.filter(
132                        project_assignment=self._project_assignment,
133                        period=self._period,
134                        day=datetime.date.fromisoformat(field_name),
135                    ).update(hours=value)
136            WorkHours.objects.filter(
137                project_assignment=self._project_assignment,
138                period=self._period,
139                day__in=delete
140            ).delete()
141            WorkHours.objects.bulk_create(add)
class WorkhourCalendarForm(django.forms.forms.Form):
 12class WorkhourCalendarForm(forms.Form):
 13    """
 14    A form for entering work hours resembling a calender.
 15    """
 16    class Media:
 17        """
 18        An inner class containing meta information for styling.
 19        """
 20        css = {'all': ('styles/calendar.css',)}
 21
 22    template_name_calendar = 'vkk/workhours/contributor/calendar.html'
 23
 24    def __init__(self, *args, period_pk=None, assignment_pk=None, **kwargs):
 25        """
 26        Constructs an `WorkhourCalendarForm` instance using the given primary
 27         keys of an `Period` and `ProjectAssignment`.
 28        """
 29        super().__init__(*args, **kwargs)
 30        self._project_assignment = ProjectAssignment.objects.get(
 31            pk=assignment_pk
 32        )
 33
 34        # create fields
 35        self._period = Period.objects.get(pk=period_pk)
 36        today = datetime.date.today()
 37        field_class = WorkHours.hours.field.formfield
 38
 39        for date in date_iterator(self._period.start, self._period.end):
 40            is_disabled = date > today or self._project_assignment.project.start > date \
 41                or self._project_assignment.project.end < date
 42            field = field_class(
 43                min_value=0,
 44                max_value=24,
 45                required=False,
 46                label=date.day,
 47                label_suffix='',
 48                disabled=is_disabled
 49            )
 50            self.fields[date.isoformat()] = field
 51
 52        # provide initial data
 53        workhours = WorkHours.objects.filter(
 54            period__pk=period_pk,
 55            project_assignment__pk=assignment_pk
 56        )
 57        for entry in workhours:
 58            field = self.fields.get(entry.day.isoformat())
 59            if field is not None:
 60                field.initial = entry.hours
 61
 62    def _get_date_calendar_structure(self):
 63        """
 64        Private method used for structuring some data for rendering the form.
 65        """
 66        dates = date_iterator(self._period.start, self._period.end)
 67
 68        # subdevision into months
 69        months = []
 70        month_number = -1
 71        for date in dates:
 72            if date.month != month_number:
 73                months += [[]]
 74                month_number = date.month
 75            months[-1] += [date]
 76
 77        # subdevision into weeks
 78        weeks = []
 79        for month in months:
 80            weeks += [[]]
 81            week_day = 7
 82            for date in month:
 83                if date.weekday() < week_day:
 84                    weeks[-1] += [[]]
 85                weeks[-1][-1] += [date]
 86                week_day = date.weekday()
 87
 88        return weeks
 89
 90    def _get_field_calendar_structure(self):
 91        """
 92        Private method used for structuring some data for rendering the form.
 93        """
 94        calendar = self._get_date_calendar_structure()
 95        return [[(
 96            [(day, self[day.isoformat()]) for day in week]
 97        ) for week in month] for month in calendar]
 98
 99    def as_calendar(self):
100        """
101        Renders the form resembling a calender.
102        """
103        context = super().get_context()
104        context.update({'fields_more': self._get_field_calendar_structure()})
105        return self.render(
106            template_name=self.template_name_calendar,
107            context=context
108        )
109
110    def save(self):
111        """
112        Tries to create, modify or delete all changes.
113        """
114        if self.is_valid() and self.has_changed():
115            add = []
116            delete = []
117            for field_name in self.changed_data:
118                initial = self.fields[field_name].initial
119                value = self.cleaned_data.get(field_name)
120                if value is None or value == 0.0:
121                    delete.append(
122                        datetime.date.fromisoformat(field_name)
123                    )
124                elif initial is None:
125                    add.append(WorkHours(
126                        project_assignment=self._project_assignment,
127                        period=self._period,
128                        day=datetime.date.fromisoformat(field_name),
129                        hours=value
130                    ))
131                else:
132                    WorkHours.objects.filter(
133                        project_assignment=self._project_assignment,
134                        period=self._period,
135                        day=datetime.date.fromisoformat(field_name),
136                    ).update(hours=value)
137            WorkHours.objects.filter(
138                project_assignment=self._project_assignment,
139                period=self._period,
140                day__in=delete
141            ).delete()
142            WorkHours.objects.bulk_create(add)

A form for entering work hours resembling a calender.

WorkhourCalendarForm(*args, period_pk=None, assignment_pk=None, **kwargs)
24    def __init__(self, *args, period_pk=None, assignment_pk=None, **kwargs):
25        """
26        Constructs an `WorkhourCalendarForm` instance using the given primary
27         keys of an `Period` and `ProjectAssignment`.
28        """
29        super().__init__(*args, **kwargs)
30        self._project_assignment = ProjectAssignment.objects.get(
31            pk=assignment_pk
32        )
33
34        # create fields
35        self._period = Period.objects.get(pk=period_pk)
36        today = datetime.date.today()
37        field_class = WorkHours.hours.field.formfield
38
39        for date in date_iterator(self._period.start, self._period.end):
40            is_disabled = date > today or self._project_assignment.project.start > date \
41                or self._project_assignment.project.end < date
42            field = field_class(
43                min_value=0,
44                max_value=24,
45                required=False,
46                label=date.day,
47                label_suffix='',
48                disabled=is_disabled
49            )
50            self.fields[date.isoformat()] = field
51
52        # provide initial data
53        workhours = WorkHours.objects.filter(
54            period__pk=period_pk,
55            project_assignment__pk=assignment_pk
56        )
57        for entry in workhours:
58            field = self.fields.get(entry.day.isoformat())
59            if field is not None:
60                field.initial = entry.hours

Constructs an WorkhourCalendarForm instance using the given primary keys of an Period and ProjectAssignment.

template_name_calendar = 'vkk/workhours/contributor/calendar.html'
def as_calendar(self):
 99    def as_calendar(self):
100        """
101        Renders the form resembling a calender.
102        """
103        context = super().get_context()
104        context.update({'fields_more': self._get_field_calendar_structure()})
105        return self.render(
106            template_name=self.template_name_calendar,
107            context=context
108        )

Renders the form resembling a calender.

def save(self):
110    def save(self):
111        """
112        Tries to create, modify or delete all changes.
113        """
114        if self.is_valid() and self.has_changed():
115            add = []
116            delete = []
117            for field_name in self.changed_data:
118                initial = self.fields[field_name].initial
119                value = self.cleaned_data.get(field_name)
120                if value is None or value == 0.0:
121                    delete.append(
122                        datetime.date.fromisoformat(field_name)
123                    )
124                elif initial is None:
125                    add.append(WorkHours(
126                        project_assignment=self._project_assignment,
127                        period=self._period,
128                        day=datetime.date.fromisoformat(field_name),
129                        hours=value
130                    ))
131                else:
132                    WorkHours.objects.filter(
133                        project_assignment=self._project_assignment,
134                        period=self._period,
135                        day=datetime.date.fromisoformat(field_name),
136                    ).update(hours=value)
137            WorkHours.objects.filter(
138                project_assignment=self._project_assignment,
139                period=self._period,
140                day__in=delete
141            ).delete()
142            WorkHours.objects.bulk_create(add)

Tries to create, modify or delete all changes.

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 WorkhourCalendarForm.Media:
16    class Media:
17        """
18        An inner class containing meta information for styling.
19        """
20        css = {'all': ('styles/calendar.css',)}

An inner class containing meta information for styling.

css = {'all': ('styles/calendar.css',)}