lingo/lingo/invoicing/forms.py

131 lines
4.5 KiB
Python

# lingo - payment and billing system
# Copyright (C) 2022 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import django_filters
from django import forms
from django.utils.translation import ugettext_lazy as _
from lingo.invoicing.models import Campaign, DraftInvoiceLine, InvoiceLine, Regie
class CampaignForm(forms.ModelForm):
class Meta:
model = Campaign
fields = ['date_start', 'date_end', 'date_issue', 'injected_lines']
widgets = {
'date_start': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'date_end': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'date_issue': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
}
def clean(self):
cleaned_data = super().clean()
if 'date_start' in cleaned_data and 'date_end' in cleaned_data:
overlapping_qs = Campaign.objects.extra(
where=["(date_start, date_end) OVERLAPS (%s, %s)"],
params=[cleaned_data['date_start'], cleaned_data['date_end']],
)
if self.instance.pk:
overlapping_qs = overlapping_qs.exclude(pk=self.instance.pk)
if overlapping_qs.exists():
self.add_error(None, _('Another campaign overlapping this period already exists.'))
return cleaned_data
def regie_queryset(request):
return Regie.objects.all()
class AbstractLineFilterSet(django_filters.FilterSet):
regie = django_filters.ModelChoiceFilter(
label=_('Regie'),
queryset=regie_queryset,
field_name='invoice__regie',
)
invoice_number = django_filters.CharFilter(
label=_('Invoice number'),
field_name='invoice__formatted_number',
lookup_expr='contains',
)
invoice_id = django_filters.NumberFilter(
label=_('Invoice number'),
)
pk = django_filters.NumberFilter(
label=_('PK'),
)
payer_external_id = django_filters.CharFilter(
label=_('Payer (external ID)'),
)
user_external_id = django_filters.CharFilter(
label=_('User (external ID)'),
)
status = django_filters.ChoiceFilter(
label=_('Status'),
widget=forms.RadioSelect,
empty_label=_('all'),
method='filter_status',
)
def __init__(self, *args, **kwargs):
self.pool = kwargs.pop('pool')
super().__init__(*args, **kwargs)
if self.pool.draft:
del self.filters['invoice_number']
else:
del self.filters['invoice_id']
status_choices = [
('success', _('Success')),
('success_injected', '%s (%s)' % (_('Success'), _('Injected'))),
('warning', _('Warning')),
('error', _('Error')),
]
if not self.pool.draft:
status_choices += [
('error_todo', _('Error (To treat)')),
('error_ignored', _('Error (Ignored)')),
('error_fixed', _('Error (Fixed)')),
]
self.filters['status'].field.choices = status_choices
def filter_status(self, queryset, name, value):
if not value:
return queryset
if value == 'success_injected':
return queryset.filter(status='success', from_injected_line__isnull=False)
if value == 'error_todo':
return queryset.filter(status='error', error_status='')
if value == 'error_ignored':
return queryset.filter(status='error', error_status='ignored')
if value == 'error_fixed':
return queryset.filter(status='error', error_status='fixed')
return queryset.filter(status=value)
class DraftInvoiceLineFilterSet(AbstractLineFilterSet):
class Meta:
model = DraftInvoiceLine
fields = []
class InvoiceLineFilterSet(AbstractLineFilterSet):
class Meta:
model = InvoiceLine
fields = []