Facturation: afficher les informations du payeur, pouvoir filtrer dessus (#75054) #32

Merged
lguerin merged 2 commits from wip/75054-invoicing-payer-info into main 2023-03-17 09:12:36 +01:00
7 changed files with 231 additions and 10 deletions

View File

@ -61,10 +61,32 @@ class AbstractInvoiceFilterSet(django_filters.FilterSet):
payer_external_id = django_filters.CharFilter(
label=_('Payer (external ID)'),
)
payer_first_name = django_filters.CharFilter(
label=_('Payer first name'),
lookup_expr='icontains',
)
payer_last_name = django_filters.CharFilter(
label=_('Payer last name'),
lookup_expr='icontains',
)
payer_demat = django_filters.BooleanFilter(
label=_('Payer demat'),
)
payer_direct_debit = django_filters.BooleanFilter(
label=_('Payer direct debit'),
)
user_external_id = django_filters.CharFilter(
label=_('User (external ID)'),
method='filter_user_external_id',
)
user_first_name = django_filters.CharFilter(
label=_('User first name'),
method='filter_user_first_name',
)
user_last_name = django_filters.CharFilter(
label=_('User last name'),
method='filter_user_last_name',
)
def __init__(self, *args, **kwargs):
self.pool = kwargs.pop('pool')
@ -84,6 +106,24 @@ class AbstractInvoiceFilterSet(django_filters.FilterSet):
lines = line_model.objects.filter(user_external_id=value).values('invoice')
return queryset.filter(pk__in=lines)
def filter_user_first_name(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_first_name__icontains=value).values('invoice')
return queryset.filter(pk__in=lines)
def filter_user_last_name(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_last_name__icontains=value).values('invoice')
return queryset.filter(pk__in=lines)
class DraftInvoiceFilterSet(AbstractInvoiceFilterSet):
class Meta:
@ -114,9 +154,31 @@ class AbstractLineFilterSet(django_filters.FilterSet):
payer_external_id = django_filters.CharFilter(
label=_('Payer (external ID)'),
)
payer_first_name = django_filters.CharFilter(
label=_('Payer first name'),
lookup_expr='icontains',
)
payer_last_name = django_filters.CharFilter(
label=_('Payer last name'),
lookup_expr='icontains',
)
payer_demat = django_filters.BooleanFilter(
label=_('Payer demat'),
)
payer_direct_debit = django_filters.BooleanFilter(
label=_('Payer direct debit'),
)
user_external_id = django_filters.CharFilter(
label=_('User (external ID)'),
)
user_first_name = django_filters.CharFilter(
label=_('User first name'),
lookup_expr='icontains',
)
user_last_name = django_filters.CharFilter(
label=_('User last name'),
lookup_expr='icontains',
)
status = django_filters.ChoiceFilter(
label=_('Status'),
widget=forms.RadioSelect,

View File

@ -303,6 +303,11 @@ class AbstractInvoice(models.Model):
class Meta:
abstract = True
@property
Review

Vraiment un détail, mais j’aurais mis une @property pour être raccord à celle déjà définie pour le nom d’utilisateur (AbstractInvoiceLine.user_name).

Vraiment un détail, mais j’aurais mis une `@property` pour être raccord à celle déjà définie pour le nom d’utilisateur (`AbstractInvoiceLine.user_name`).
Review

fait, merci :)

fait, merci :)
def payer_name(self):
payer_name = '%s %s' % (self.payer_first_name, self.payer_last_name)
return payer_name.strip()
class DraftInvoice(AbstractInvoice):
pass
@ -392,6 +397,11 @@ class AbstractInvoiceLine(models.Model):
user_name = '%s %s' % (self.user_first_name, self.user_last_name)
return user_name.strip()
@property
def payer_name(self):
payer_name = '%s %s' % (self.payer_first_name, self.payer_last_name)
return payer_name.strip()
def get_error_display(self):
if self.status == 'success':
return

View File

@ -16,7 +16,13 @@
<td>{{ line.unit_amount }}</td>
<td>{{ line.total_amount }}</td>
<td>{{ line.user_name }} ({{ line.user_external_id }})</td>
<td>{{ line.payer_external_id }}</td>
<td>
{{ line.payer_name }} ({{ line.payer_external_id }})
<br />
{% blocktrans with payer_demat=line.payer_demat|yesno %}demat: {{ payer_demat }}{% endblocktrans %}
<br />
{% blocktrans with payer_direct_debit=line.payer_direct_debit|yesno %}direct debit: {{ payer_direct_debit }}{% endblocktrans %}
</td>
<td class="status">
<span class="meta meta-{{ line.status }}">{% spaceless %}
{% if line.status == 'error' and line.error_status %}

View File

@ -41,7 +41,7 @@
<td>{{ line.unit_amount }}</td>
<td>{{ line.total_amount }}</td>
<td>{{ line.user_name }} ({{ line.user_external_id }})</td>
<td>{{ line.payer_external_id }}</td>
<td>{{ line.payer_name}} ({{ line.payer_external_id }})</td>
<td class="status">
<span class="meta meta-{{ line.status }}">{% spaceless %}
{% if line.status == 'error'%}

View File

@ -51,9 +51,9 @@
{% for invoice in object_list %}
<li class="invoice untoggled" data-invoice-id="{{ invoice.pk }}" data-invoice-lines-url="{% url 'lingo-manager-invoicing-invoice-line-list' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk invoice_pk=invoice.pk %}">
{% if pool.draft %}
{% blocktrans with number=invoice.pk payer=invoice.payer_external_id amount=invoice.total_amount %}Invoice <a href="{{ journal_url }}?invoice_id={{ number }}">PROFORMA-{{ number }}</a> addressed to <a href="{{ journal_url }}?payer_external_id={{ payer }}">{{ payer }}</a>, amount {{ amount }}€{% endblocktrans %}
{% blocktrans with number=invoice.pk payer_id=invoice.payer_external_id payer_name=invoice.payer_name payer_demat=invoice.payer_demat|yesno payer_direct_debit=invoice.payer_direct_debit|yesno amount=invoice.total_amount %}Invoice <a href="{{ journal_url }}?invoice_id={{ number }}">PROFORMA-{{ number }}</a> addressed to <a href="{{ journal_url }}?payer_external_id={{ payer_id }}">{{ payer_name }} ({{ payer_id }})</a>, amount {{ amount }}€, demat: {{ payer_demat }}, direct debit: {{ payer_direct_debit }}{% endblocktrans %}
{% else %}
{% blocktrans with invoice_number=invoice.formatted_number payer=invoice.payer_external_id amount=invoice.total_amount number=invoice.number %}Invoice <a href="{{ journal_url }}?invoice_number={{ number }}">{{ invoice_number }}</a> addressed to <a href="{{ journal_url }}?payer_external_id={{ payer }}">{{ payer }}</a>, amount {{ amount }}€{% endblocktrans %}
{% blocktrans with invoice_number=invoice.formatted_number payer_id=invoice.payer_external_id payer_name=invoice.payer_name payer_demat=invoice.payer_demat|yesno payer_direct_debit=invoice.payer_direct_debit|yesno amount=invoice.total_amount number=invoice.number %}Invoice <a href="{{ journal_url }}?invoice_number={{ number }}">{{ invoice_number }}</a> addressed to <a href="{{ journal_url }}?payer_external_id={{ payer_id }}">{{ payer_name }} ({{ payer_id }})</a>, amount {{ amount }}€, demat: {{ payer_demat }}, direct debit: {{ payer_direct_debit }}{% endblocktrans %}
{% endif %}
<span class="togglable"></span>
</li>

View File

@ -635,6 +635,8 @@ class NonInvoicedLineListView(ListView):
'total_amount',
'user_external_id',
'payer_external_id',
'payer_first_name',
'payer_last_name',
'user_first_name',
'user_last_name',
'event',
@ -669,6 +671,9 @@ class NonInvoicedLineListView(ListView):
line['user_name'] = InvoiceLine(
user_first_name=line['user_first_name'], user_last_name=line['user_last_name']
).user_name
line['payer_name'] = InvoiceLine(
payer_first_name=line['payer_first_name'], payer_last_name=line['payer_last_name']
).payer_name
line['error_display'] = InvoiceLine(
status=line['status'], pricing_data=line['pricing_data']
).get_error_display()

View File

@ -627,10 +627,24 @@ def test_detail_pool_invoices(app, admin_user, draft):
status='completed',
)
invoice1 = invoice_model.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=pool, payer_external_id='payer:1'
date_issue=datetime.date.today(),
regie=regie,
pool=pool,
payer_external_id='payer:1',
payer_first_name='First1',
payer_last_name='Name1',
payer_demat=True,
payer_direct_debit=False,
)
invoice2 = invoice_model.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=pool, payer_external_id='payer:2'
date_issue=datetime.date.today(),
regie=regie,
pool=pool,
payer_external_id='payer:2',
payer_first_name='First2',
payer_last_name='Name2',
payer_demat=False,
payer_direct_debit=True,
)
if not draft:
invoice1.set_number()
@ -711,12 +725,13 @@ def test_detail_pool_invoices(app, admin_user, draft):
if draft:
assert (
resp.pyquery('li[data-invoice-id="%s"]' % invoice1.pk).text()
== 'Invoice PROFORMA-%s addressed to payer:1, amount 6.00€' % invoice1.pk
== 'Invoice PROFORMA-%s addressed to First1 Name1 (payer:1), amount 6.00€, demat: yes, direct debit: no'
% invoice1.pk
)
else:
assert resp.pyquery(
'li[data-invoice-id="%s"]' % invoice1.pk
).text() == 'Invoice F%02s-%s-0000001 addressed to payer:1, amount 6.00€' % (
).text() == 'Invoice F%02s-%s-0000001 addressed to First1 Name1 (payer:1), amount 6.00€, demat: yes, direct debit: no' % (
regie.pk,
invoice1.created_at.strftime('%y-%m'),
)
@ -744,12 +759,13 @@ def test_detail_pool_invoices(app, admin_user, draft):
if draft:
assert (
resp.pyquery('li[data-invoice-id="%s"]' % invoice2.pk).text()
== 'Invoice PROFORMA-%s addressed to payer:2, amount 1.00€' % invoice2.pk
== 'Invoice PROFORMA-%s addressed to First2 Name2 (payer:2), amount 1.00€, demat: no, direct debit: yes'
% invoice2.pk
)
else:
assert resp.pyquery(
'li[data-invoice-id="%s"]' % invoice2.pk
).text() == 'Invoice F%02d-%s-0000002 addressed to payer:2, amount 1.00€' % (
).text() == 'Invoice F%02d-%s-0000002 addressed to First2 Name2 (payer:2), amount 1.00€, demat: no, direct debit: yes' % (
regie.pk,
invoice2.created_at.strftime('%y-%m'),
)
@ -795,6 +811,36 @@ def test_detail_pool_invoices(app, admin_user, draft):
params={'payer_external_id': 'payer:2'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_first_name': 'first'},
)
assert len(resp.pyquery('li.invoice')) == 2
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_first_name': 'first1'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_last_name': 'name'},
)
assert len(resp.pyquery('li.invoice')) == 2
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_last_name': 'name1'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_demat': True},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_direct_debit': True},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_external_id': 'user:1'},
@ -805,6 +851,26 @@ def test_detail_pool_invoices(app, admin_user, draft):
params={'user_external_id': 'user:2'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_first_name': 'user'},
)
assert len(resp.pyquery('li.invoice')) == 2
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_first_name': 'user2'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_last_name': 'name'},
)
assert len(resp.pyquery('li.invoice')) == 2
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_last_name': 'name1'},
)
assert len(resp.pyquery('li.invoice')) == 2
def test_journal_pool(app, admin_user):
@ -1011,7 +1077,13 @@ def test_journal_pool_lines(app, admin_user, draft):
pricing_data={'foo': 'bar'},
event={'event': 'foobar'},
user_external_id='user:1',
user_first_name='First1',
user_last_name='Last1',
payer_external_id='payer:1',
payer_first_name='First1',
payer_last_name='Last1',
payer_demat=True,
payer_direct_debit=False,
),
]
errors = [
@ -1062,7 +1134,13 @@ def test_journal_pool_lines(app, admin_user, draft):
},
event={'event': 'foobar'},
user_external_id='user:1',
user_first_name='First1',
user_last_name='Last1',
payer_external_id='payer:2',
payer_first_name='First2',
payer_last_name='Last2',
payer_demat=False,
payer_direct_debit=True,
)
)
if not draft:
@ -1078,6 +1156,10 @@ def test_journal_pool_lines(app, admin_user, draft):
total_amount=1,
user_external_id='user:2',
payer_external_id='payer:2',
payer_first_name='First2',
payer_last_name='Last2',
payer_demat=False,
payer_direct_debit=True,
regie=regie,
)
lines.append(
@ -1092,7 +1174,13 @@ def test_journal_pool_lines(app, admin_user, draft):
pricing_data={'foo': 'bar'},
event={'event': 'foobar2'},
user_external_id='user:2',
user_first_name='First2',
user_last_name='Last2',
payer_external_id='payer:2',
payer_first_name='First2',
payer_last_name='Last2',
payer_demat=False,
payer_direct_debit=True,
from_injected_line=injected_line,
),
)
@ -1340,6 +1428,36 @@ def test_journal_pool_lines(app, admin_user, draft):
params={'payer_external_id': 'payer:2'},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_first_name': 'first'},
)
assert len(resp.pyquery('tr td.status')) == 23
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_first_name': 'first1'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_last_name': 'last'},
)
assert len(resp.pyquery('tr td.status')) == 23
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_last_name': 'last1'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_demat': True},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_direct_debit': True},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_external_id': 'user:1'},
@ -1350,6 +1468,26 @@ def test_journal_pool_lines(app, admin_user, draft):
params={'user_external_id': 'user:2'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_first_name': 'first'},
)
assert len(resp.pyquery('tr td.status')) == 23
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_first_name': 'first1'},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_last_name': 'last'},
)
assert len(resp.pyquery('tr td.status')) == 23
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_last_name': 'last1'},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'status': 'success'},