Filtrer les factures (#73918) #25

Merged
lguerin merged 2 commits from wip/73918-invoicing-invoice-filtering into main 2023-02-07 15:17:33 +01:00
5 changed files with 160 additions and 18 deletions

View File

@ -19,7 +19,7 @@ import django_filters
from django import forms
from django.utils.translation import ugettext_lazy as _
from lingo.invoicing.models import Campaign, DraftInvoiceLine, InvoiceLine, Regie
from lingo.invoicing.models import Campaign, DraftInvoice, DraftInvoiceLine, Invoice, InvoiceLine, Regie
class CampaignForm(forms.ModelForm):
@ -51,17 +51,74 @@ def regie_queryset(request):
return Regie.objects.all()
class AbstractInvoiceFilterSet(django_filters.FilterSet):
regie = django_filters.ModelChoiceFilter(
label=_('Regie'),
queryset=regie_queryset,
)
# for Invoice
lguerin marked this conversation as resolved Outdated
Outdated
Review

peut-être un commentaire ici qui explique que number et pk ne seront jamais affichés ensemble, que number est pour les vraies factures et pk pour les brouillons ?

peut-être un commentaire ici qui explique que number et pk ne seront jamais affichés ensemble, que number est pour les vraies factures et pk pour les brouillons ?

commentaires ajoutés

commentaires ajoutés
number = django_filters.CharFilter(
label=_('Invoice number'),
field_name='formatted_number',
lookup_expr='contains',
)
# for DraftInvoice
pk = django_filters.NumberFilter(
label=_('Invoice number'),
)
payer_external_id = django_filters.CharFilter(
label=_('Payer (external ID)'),
field_name='payer',
)
user_external_id = django_filters.CharFilter(
label=_('User (external ID)'),
method='filter_user_external_id',
)
def __init__(self, *args, **kwargs):
self.pool = kwargs.pop('pool')
super().__init__(*args, **kwargs)
if self.pool.draft:
del self.filters['number']
else:
del self.filters['pk']
def filter_user_external_id(self, queryset, name, value):
if not value:
return queryset
line_model = InvoiceLine
if self.pool.draft:
line_model = DraftInvoiceLine
lines = line_model.objects.filter(user_external_id=value).values('invoice')
return queryset.filter(pk__in=lines)
class DraftInvoiceFilterSet(AbstractInvoiceFilterSet):
class Meta:
model = DraftInvoice
fields = []
class InvoiceFilterSet(AbstractInvoiceFilterSet):
class Meta:
model = Invoice
fields = []
class AbstractLineFilterSet(django_filters.FilterSet):
regie = django_filters.ModelChoiceFilter(
label=_('Regie'),
queryset=regie_queryset,
field_name='invoice__regie',
)
# for InvoiceLine
invoice_number = django_filters.CharFilter(
label=_('Invoice number'),
field_name='invoice__formatted_number',
lookup_expr='contains',
)
# for DraftInvoiceLine
invoice_id = django_filters.NumberFilter(
label=_('Invoice number'),
)

View File

@ -1,7 +1,8 @@
{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk as journal_url %}
{% for line in object_list %}
<li class="line" data-invoice-id="{{ line.invoice_id }}">
<a href="{{ journal_url }}?pk={{ line.pk }}">#{{ line.pk }}</a>
<a href="{{ journal_url }}?user_external_id={{ line.user_external_id }}">{{ line.user_name }}</a>
<a href="{{ journal_url }}?user_external_id={{ line.user_external_id }}">{{ line.user_name }} ({{ line.user_external_id }})</a>
- {{ line.event_date|date:"d/m/Y" }} - {{ line.label }} ({{ line.total_amount }})
</li>
{% endfor %}

View File

@ -25,7 +25,27 @@
{% endblock %}
{% block content %}
{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk as journal_url %}
<div class="section">
<div>
<form class="invoice-filters">
<fieldset class="gadjo-foldable gadjo-folded" id="filters">
<legend class="gadjo-foldable-widget">{% trans "Invoice Filtering" %}</legend>
<div class="gadjo-folding">
{{ filterset.form.as_p }}
</div>
</fieldset>
<script>
$(function() {
$('form.invoice-filters input,select').on('change',
function() {
$(this).parents('form').submit();
});
});
</script>
</form>
</div>
</div>
{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk as journal_url %}
<div>
<ul class="objects-list">
{% for invoice in object_list %}

View File

@ -39,7 +39,13 @@ from django.views.generic import (
)
from lingo.agendas.models import Agenda
from lingo.invoicing.forms import CampaignForm, DraftInvoiceLineFilterSet, InvoiceLineFilterSet
from lingo.invoicing.forms import (
CampaignForm,
DraftInvoiceFilterSet,
DraftInvoiceLineFilterSet,
InvoiceFilterSet,
InvoiceLineFilterSet,
)
from lingo.invoicing.models import (
Campaign,
DraftInvoice,
@ -313,13 +319,21 @@ class PoolDetailView(ListView):
def get_queryset(self):
invoice_model = Invoice
filter_model = InvoiceFilterSet
if self.object.draft:
invoice_model = DraftInvoice
return invoice_model.objects.filter(pool=self.object)
filter_model = DraftInvoiceFilterSet
data = self.request.GET or None
self.filterset = filter_model(
data=data, queryset=invoice_model.objects.filter(pool=self.object), pool=self.object
)
return self.filterset.qs
def get_context_data(self, **kwargs):
kwargs['object'] = self.campaign
kwargs['pool'] = self.object
kwargs['filterset'] = self.filterset
line_model = InvoiceLine
line_values = ['status', 'error_status']
if self.object.draft:
@ -461,16 +475,21 @@ class InvoiceLineListView(ListView):
template_name = 'lingo/invoicing/manager_invoice_lines.html'
def dispatch(self, request, *args, **kwargs):
pool = get_object_or_404(Pool, pk=kwargs['pool_pk'], campaign_id=kwargs['pk'])
self.pool = get_object_or_404(Pool, pk=kwargs['pool_pk'], campaign_id=kwargs['pk'])
invoice_model = Invoice
if pool.draft:
if self.pool.draft:
invoice_model = DraftInvoice
self.invoice = get_object_or_404(invoice_model, pk=kwargs['invoice_pk'], pool=pool)
self.invoice = get_object_or_404(invoice_model, pk=kwargs['invoice_pk'], pool=self.pool)
return super().dispatch(request, *args, **kwargs)
def get_queryset(self):
return self.invoice.lines.all().order_by('user_external_id', 'event_date', 'pk')
def get_context_data(self, **kwargs):
kwargs['object'] = self.pool.campaign
kwargs['pool'] = self.pool
return super().get_context_data(**kwargs)
invoice_line_list = InvoiceLineListView.as_view()

View File

@ -540,12 +540,13 @@ def test_detail_pool_invoices(app, admin_user, draft):
draft=draft,
status='completed',
)
regie = Regie.objects.create(label='Foo')
regie1 = Regie.objects.create(label='Foo1')
regie2 = Regie.objects.create(label='Foo1')
invoice1 = invoice_model.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=pool, payer='payer:1'
date_issue=datetime.date.today(), regie=regie1, pool=pool, payer='payer:1'
)
invoice2 = invoice_model.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=pool, payer='payer:2'
date_issue=datetime.date.today(), regie=regie2, pool=pool, payer='payer:2'
)
if not draft:
invoice1.set_number()
@ -627,7 +628,7 @@ def test_detail_pool_invoices(app, admin_user, draft):
assert resp.pyquery(
'li[data-invoice-id="%s"]' % invoice1.pk
).text() == 'Invoice F%02s-%s-0000001 addressed to payer:1, amount 6.00€' % (
regie.pk,
regie1.pk,
invoice1.created_at.strftime('%y-%m'),
)
lines_url = resp.pyquery('li[data-invoice-id="%s"]' % invoice1.pk).attr('data-invoice-lines-url')
@ -640,15 +641,15 @@ def test_detail_pool_invoices(app, admin_user, draft):
assert len(lines_resp.pyquery('li')) == 3
assert (
lines_resp.pyquery('li:nth-child(1)').text()
== '#%s User1 Name1 - 01/09/2022 - Label 11 (1.00)' % line11.pk
== '#%s User1 Name1 (user:1) - 01/09/2022 - Label 11 (1.00)' % line11.pk
)
assert (
lines_resp.pyquery('li:nth-child(2)').text()
== '#%s User1 Name1 - 03/09/2022 - Label 13 (3.00)' % line13.pk
== '#%s User1 Name1 (user:1) - 03/09/2022 - Label 13 (3.00)' % line13.pk
)
assert (
lines_resp.pyquery('li:nth-child(3)').text()
== '#%s User2 Name2 - 02/09/2022 - Label 12 (2.00)' % line12.pk
== '#%s User2 Name2 (user:2) - 02/09/2022 - Label 12 (2.00)' % line12.pk
)
if draft:
assert (
@ -658,8 +659,8 @@ def test_detail_pool_invoices(app, admin_user, draft):
else:
assert resp.pyquery(
'li[data-invoice-id="%s"]' % invoice2.pk
).text() == 'Invoice F%02d-%s-0000002 addressed to payer:2, amount 1.00€' % (
regie.pk,
).text() == 'Invoice F%02d-%s-0000001 addressed to payer:2, amount 1.00€' % (
regie2.pk,
invoice2.created_at.strftime('%y-%m'),
)
lines_url = resp.pyquery('li[data-invoice-id="%s"]' % invoice2.pk).attr('data-invoice-lines-url')
@ -672,9 +673,53 @@ def test_detail_pool_invoices(app, admin_user, draft):
assert len(lines_resp.pyquery('li')) == 1
assert (
lines_resp.pyquery('li:nth-child(1)').text()
== '#%s User1 Name1 - 01/09/2022 - Label 21 (1.00)' % line21.pk
== '#%s User1 Name1 (user:1) - 01/09/2022 - Label 21 (1.00)' % line21.pk
)
# test filters
resp = app.get(
'/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk),
params={'regie': regie1.pk},
)
assert len(resp.pyquery('li.invoice')) == 1
if draft:
resp = app.get(
'/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk),
params={'pk': invoice1.pk},
)
assert len(resp.pyquery('li.invoice')) == 1
else:
resp = app.get(
'/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk),
params={'number': invoice1.formatted_number},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk),
params={'number': invoice1.created_at.strftime('%y-%m')},
)
assert len(resp.pyquery('li.invoice')) == 2
resp = app.get(
'/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk),
params={'payer_external_id': 'payer:1'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk),
params={'payer_external_id': 'payer:2'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk),
params={'user_external_id': 'user:1'},
)
assert len(resp.pyquery('li.invoice')) == 2
resp = app.get(
'/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk),
params={'user_external_id': 'user:2'},
)
assert len(resp.pyquery('li.invoice')) == 1
def test_journal_pool(app, admin_user):
campaign = Campaign.objects.create(