SciPost Code Repository

Skip to content
Snippets Groups Projects
forms.py 4.33 KiB
Newer Older
__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
Jorran de Wit's avatar
Jorran de Wit committed
import datetime
Jorran de Wit's avatar
Jorran de Wit committed
from django import forms
Jorran de Wit's avatar
Jorran de Wit committed
from django.contrib.auth import get_user_model
from django.utils.dates import MONTHS
from django.db.models import Sum
from django.utils import timezone
Jorran de Wit's avatar
Jorran de Wit committed

from ajax_select.fields import AutoCompleteSelectField
Jorran de Wit's avatar
Jorran de Wit committed
from dateutil.rrule import rrule, MONTHLY
Jorran de Wit's avatar
Jorran de Wit committed
from common.forms import MonthYearWidget
from scipost.fields import UserModelChoiceField

from .models import Subsidy, WorkLog
class SubsidyForm(forms.ModelForm):
    organization = AutoCompleteSelectField('organization_lookup')

    class Meta:
        model = Subsidy
        fields = ['organization', 'subsidy_type', 'description',
                  'amount', 'amount_publicly_shown', 'status',
                  'date', 'date_until']
Jorran de Wit's avatar
Jorran de Wit committed
class WorkLogForm(forms.ModelForm):
Jorran de Wit's avatar
Jorran de Wit committed
    def __init__(self, *args, **kwargs):
        self.types = kwargs.pop('log_types', False)
        super().__init__(*args, **kwargs)
        if self.types:
            self.fields['log_type'] = forms.ChoiceField(choices=self.types)

Jorran de Wit's avatar
Jorran de Wit committed
    class Meta:
        model = WorkLog
        fields = (
            'comments',
Jorran de Wit's avatar
Jorran de Wit committed
            'log_type',
Jorran de Wit's avatar
Jorran de Wit committed
            'duration',
        )
        widgets = {
            'comments': forms.Textarea(attrs={'rows': 4}),
            'duration': forms.TextInput(attrs={'placeholder': 'HH:MM:SS'})
        }
Jorran de Wit's avatar
Jorran de Wit committed


Jorran de Wit's avatar
Jorran de Wit committed
class LogsFilter(forms.Form):
    """
    Filter work logs given the requested date range and users.
    """

    employee = UserModelChoiceField(
Jorran de Wit's avatar
Jorran de Wit committed
        queryset=get_user_model().objects.filter(work_logs__isnull=False).distinct(),
Jorran de Wit's avatar
Jorran de Wit committed
        required=False, empty_label='Show all')
Jorran de Wit's avatar
Jorran de Wit committed
    start = forms.DateField(widget=MonthYearWidget(required=True), required=True)  # Month
    end = forms.DateField(widget=MonthYearWidget(required=True, end=True), required=True)  # Month
Jorran de Wit's avatar
Jorran de Wit committed

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
Jorran de Wit's avatar
Jorran de Wit committed
        today = timezone.now().date()
        self.initial['start'] = today.today()
        self.initial['end'] = today.today()
Jorran de Wit's avatar
Jorran de Wit committed

Jorran de Wit's avatar
Jorran de Wit committed
    def clean(self):
        data = super().clean()

        data['months'] = [dt for dt in rrule(MONTHLY, dtstart=data['start'], until=data['end'])]
        return data

    def get_months(self):
        return self.cleaned_data['months']

    def filter(self):
        """Filter work logs and return in user-grouped format."""
        output = []
        if self.is_valid():
            if self.cleaned_data['employee']:
                user_qs = get_user_model().objects.filter(id=self.cleaned_data['employee'].id)
            else:
                user_qs = get_user_model().objects.filter(work_logs__isnull=False)
            user_qs = user_qs.filter(
                work_logs__work_date__gte=self.cleaned_data['start'],
                work_logs__work_date__lte=self.cleaned_data['end']).distinct()

            output = []
            for user in user_qs:
                logs = user.work_logs.filter(
                    work_date__gte=self.cleaned_data['start'],
                    work_date__lte=self.cleaned_data['end']).distinct()

                output.append({
                    'logs': logs,
                    'duration': logs.aggregate(total=Sum('duration')),
                    'user': user,
                })
        return output

Jorran de Wit's avatar
Jorran de Wit committed
    def filter_per_month(self):
        """Filter work logs and return in per-month format."""
Jorran de Wit's avatar
Jorran de Wit committed
        output = []
        if self.is_valid():
            if self.cleaned_data['employee']:
Jorran de Wit's avatar
Jorran de Wit committed
                user_qs = get_user_model().objects.filter(id=self.cleaned_data['employee'].id)
            else:
                user_qs = get_user_model().objects.filter(work_logs__isnull=False)
            user_qs = user_qs.filter(
                work_logs__work_date__gte=self.cleaned_data['start'],
                work_logs__work_date__lte=self.cleaned_data['end']).distinct()

            output = []
            for user in user_qs:
Jorran de Wit's avatar
Jorran de Wit committed
                # If logs exists for given filters
                output.append({
Jorran de Wit's avatar
Jorran de Wit committed
                    'logs': [],
Jorran de Wit's avatar
Jorran de Wit committed
                    'user': user,
                })
Jorran de Wit's avatar
Jorran de Wit committed
                for dt in self.get_months():
                    output[-1]['logs'].append(
                        user.work_logs.filter(
                            work_date__year=dt.year, work_date__month=dt.month).aggregate(total=Sum('duration'))['total'])
Jorran de Wit's avatar
Jorran de Wit committed
        return output