Source code for finances.forms

__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"

import datetime

from django import forms
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

from dal import autocomplete
from dateutil.rrule import rrule, MONTHLY

from organizations.models import Organization
from scipost.fields import UserModelChoiceField

from .models import Subsidy, SubsidyAttachment, WorkLog


[docs]class SubsidyForm(forms.ModelForm): organization = forms.ModelChoiceField( queryset=Organization.objects.all(), widget=autocomplete.ModelSelect2( url="/organizations/organization-autocomplete", attrs={"data-html": True} ), )
[docs] class Meta: model = Subsidy fields = [ "organization", "subsidy_type", "description", "amount", "amount_publicly_shown", "status", "date", "date_until", "renewable", "renewal_of", ]
[docs]class SubsidyAttachmentForm(forms.ModelForm):
[docs] class Meta: model = SubsidyAttachment fields = ( "subsidy", "attachment", "name", "publicly_visible", )
############# # Work logs # #############
[docs]class WorkLogForm(forms.ModelForm): 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)
[docs] class Meta: model = WorkLog fields = ( "comments", "log_type", "duration", ) widgets = { "comments": forms.Textarea(attrs={"rows": 4}), "duration": forms.TextInput(attrs={"placeholder": "HH:MM:SS"}), }
[docs]class LogsFilterForm(forms.Form): """ Filter work logs given the requested date range and users. """ employee = UserModelChoiceField( queryset=get_user_model().objects.filter(work_logs__isnull=False).distinct(), required=False, empty_label="Show all", ) start = forms.DateField(required=True, widget=forms.SelectDateWidget()) end = forms.DateField(required=True, widget=forms.SelectDateWidget()) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) today = timezone.now().date() self.initial["start"] = today.today() self.initial["end"] = today.today()
[docs] def clean(self): if self.is_valid(): self.cleaned_data["months"] = [ dt for dt in rrule( MONTHLY, dtstart=self.cleaned_data["start"], until=self.cleaned_data["end"], ) ] return self.cleaned_data
[docs] def get_months(self): if self.is_valid(): return self.cleaned_data.get("months", []) return []
[docs] 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
[docs] def filter_per_month(self): """Filter work logs and return in per-month 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: # If logs exists for given filters output.append( { "logs": [], "user": user, } ) 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"] ) return output