invoicing: move line listing in journal view (#73514)

This commit is contained in:
Lauréline Guérin 2023-01-17 17:33:41 +01:00
parent 1fa8ee3027
commit f49b9b8d03
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
5 changed files with 231 additions and 71 deletions

View File

@ -13,76 +13,13 @@
{% if pool.error_count %}<span class="tag tag-error">{{ pool.error_count }}</span>{% endif %}
{{ pool.created_at|date:"DATETIME_FORMAT" }}
</h2>
{% if pool.draft and pool.status != 'registered' and pool.status != 'running' %}
<span class="actions">
<span class="actions">
<a href="{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk %}">{% trans "Journal" %}</a>
{% if pool.draft and pool.status != 'registered' and pool.status != 'running' %}
<a href="{% url 'lingo-manager-invoicing-pool-delete' pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Delete" %}</a>
</span>
{% endif %}
{% endif %}
</span>
{% endblock %}
{% block content %}
{% if pool.status == 'failed' %}
<div class="pk-error">
<p>{% trans "Error while running pool." %}</p>
{% if pool.exception %}<pre>{{ pool.exception }}</pre>{% endif %}
</div>
{% endif %}
<table class="main pools">
<thead>
<tr>
<th>{% trans "PK" %}</th>
<th>{% trans "Invoice PK" %}</th>
<th>{% trans "Label" %}</th>
<th>{% trans "Slug" %}</th>
<th>{% trans "Quantity" %}</th>
<th>{% trans "Unit amount" %}</th>
<th>{% trans "Total amount" %}</th>
<th>{% trans "User" %}</th>
<th>{% trans "Payer" %}</th>
<th>{% trans "Status" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for line in lines %}
<tr data-line-id="{{ line.pk }}">
<td class="line_id">{{ line.pk }}</td>
<td>{{ line.invoice_id|default:'' }}</td>
<td>{{ line.label }}</td>
<td>{{ line.slug }}</td>
<td>{{ line.quantity }}</td>
<td>{{ line.unit_amount }}</td>
<td>{{ line.total_amount }}</td>
<td>{{ line.user_external_id }}</td>
<td>{{ line.payer_external_id }}</td>
<td class="status">
<span class="tag tag-{{ line.status }}">{{ line.get_status_display }}</span>
{% if line.status != 'success' %}({{ line.get_error_display }}){% endif %}
{% if line.from_injected_line_id %}({% trans "Injected" %}){% endif %}
</td>
<td><a class="details-toggle">{% trans "see details" %}</a></td>
</tr>
<tr data-details-for-line-id="{{ line.pk }}" style="display: none">
<td colspan="10">
<pre>{{ line.pricing_data|pprint }}</pre>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
$(function() {
$('a.details-toggle').on('click', function() {
var line_id = $(this).parents('tr').data('line-id');
var $details = $('tr[data-details-for-line-id=' + line_id + ']');
if ($details.is(':visible')) {
$(this).text('{% trans "see details" %}');
$details.hide();
} else {
$(this).text('{% trans "hide details" %}');
$details.show();
}
});
});
</script>
{% endblock %}

View File

@ -0,0 +1,88 @@
{% extends "lingo/invoicing/manager_pool_detail.html" %}
{% load i18n %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk %}">{% trans "Journal" %}</a>
{% endblock %}
{% block appbar %}
<h2 id="pool-title">
{% if pool.success_count %}<span class="tag tag-success">{{ pool.success_count }}</span>{% endif %}
{% if pool.warning_count %}<span class="tag tag-warning">{{ pool.warning_count }}</span>{% endif %}
{% if pool.error_count %}<span class="tag tag-error">{{ pool.error_count }}</span>{% endif %}
{{ pool.created_at|date:"DATETIME_FORMAT" }}
</h2>
{% if pool.draft and pool.status != 'registered' and pool.status != 'running' %}
<span class="actions">
<a href="{% url 'lingo-manager-invoicing-pool-delete' pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Delete" %}</a>
</span>
{% endif %}
{% endblock %}
{% block content %}
{% if pool.status == 'failed' %}
<div class="pk-error">
<p>{% trans "Error while running pool." %}</p>
{% if pool.exception %}<pre>{{ pool.exception }}</pre>{% endif %}
</div>
{% endif %}
<table class="main pools">
<thead>
<tr>
<th>{% trans "PK" %}</th>
<th>{% trans "Invoice PK" %}</th>
<th>{% trans "Label" %}</th>
<th>{% trans "Slug" %}</th>
<th>{% trans "Quantity" %}</th>
<th>{% trans "Unit amount" %}</th>
<th>{% trans "Total amount" %}</th>
<th>{% trans "User" %}</th>
<th>{% trans "Payer" %}</th>
<th>{% trans "Status" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for line in lines %}
<tr data-line-id="{{ line.pk }}">
<td class="line_id">{{ line.pk }}</td>
<td>{{ line.invoice_id|default:'' }}</td>
<td>{{ line.label }}</td>
<td>{{ line.slug }}</td>
<td>{{ line.quantity }}</td>
<td>{{ line.unit_amount }}</td>
<td>{{ line.total_amount }}</td>
<td>{{ line.user_external_id }}</td>
<td>{{ line.payer_external_id }}</td>
<td class="status">
<span class="tag tag-{{ line.status }}">{{ line.get_status_display }}</span>
{% if line.status != 'success' %}({{ line.get_error_display }}){% endif %}
{% if line.from_injected_line_id %}({% trans "Injected" %}){% endif %}
</td>
<td><a class="details-toggle">{% trans "see details" %}</a></td>
</tr>
<tr data-details-for-line-id="{{ line.pk }}" style="display: none">
<td colspan="10">
<pre>{{ line.pricing_data|pprint }}</pre>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
$(function() {
$('a.details-toggle').on('click', function() {
var line_id = $(this).parents('tr').data('line-id');
var $details = $('tr[data-details-for-line-id=' + line_id + ']');
if ($details.is(':visible')) {
$(this).text('{% trans "see details" %}');
$details.hide();
} else {
$(this).text('{% trans "hide details" %}');
$details.show();
}
});
});
</script>
{% endblock %}

View File

@ -74,6 +74,11 @@ urlpatterns = [
views.pool_detail,
name='lingo-manager-invoicing-pool-detail',
),
path(
'campaign/<int:pk>/pool/<int:pool_pk>/journal/',
views.pool_journal,
name='lingo-manager-invoicing-pool-journal',
),
path(
'campaign/<int:pk>/pool/<int:pool_pk>/delete/',
views.pool_delete,

View File

@ -297,6 +297,34 @@ class PoolDetailView(DetailView):
model = Pool
pk_url_kwarg = 'pool_pk'
def dispatch(self, request, *args, **kwargs):
self.campaign = get_object_or_404(Campaign, pk=kwargs['pk'])
return super().dispatch(request, *args, **kwargs)
def get_queryset(self):
return self.campaign.pool_set.all()
def get_context_data(self, **kwargs):
kwargs['object'] = self.campaign
kwargs['pool'] = self.object
line_model = InvoiceLine
if self.object.draft:
line_model = DraftInvoiceLine
all_lines = line_model.objects.filter(pool=self.object)
self.object.error_count = len([line for line in all_lines if line.status == 'error'])
self.object.warning_count = len([line for line in all_lines if line.status == 'warning'])
self.object.success_count = len([line for line in all_lines if line.status == 'success'])
return super().get_context_data(**kwargs)
pool_detail = PoolDetailView.as_view()
class PoolJournalView(DetailView):
template_name = 'lingo/invoicing/manager_pool_journal.html'
model = Pool
pk_url_kwarg = 'pool_pk'
def dispatch(self, request, *args, **kwargs):
self.campaign = get_object_or_404(Campaign, pk=kwargs['pk'])
return super().dispatch(request, *args, **kwargs)
@ -317,7 +345,7 @@ class PoolDetailView(DetailView):
return super().get_context_data(**kwargs)
pool_detail = PoolDetailView.as_view()
pool_journal = PoolJournalView.as_view()
class PoolAddView(FormView):

View File

@ -441,7 +441,109 @@ def test_detail_pool(app, admin_user):
assert 'tag-error' not in resp
def test_detail_pool_lines(app, admin_user):
def test_journal_pool(app, admin_user):
campaign = Campaign.objects.create(
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_issue=datetime.date(2022, 10, 31),
)
campaign2 = Campaign.objects.create(
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_issue=datetime.date(2022, 11, 30),
)
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
app = login(app)
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) in resp
app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (0, pool.pk), status=404)
app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign2.pk, pool.pk), status=404)
app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, 0), status=404)
pool.draft = False
pool.save()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) not in resp
pool.draft = True
pool.status = 'registered'
pool.save()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) not in resp
pool.status = 'running'
pool.save()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) not in resp
pool.status = 'failed'
pool.save()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) in resp
line = DraftInvoiceLine.objects.create(
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
)
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert '<span class="tag tag-success">1</span>' in resp
assert 'tag-warning' not in resp
assert 'tag-error' not in resp
line.status = 'error'
line.save()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert 'tag-success' not in resp
assert 'tag-warning' not in resp
assert '<span class="tag tag-error">1</span>' in resp
line.status = 'warning'
line.save()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert 'tag-success' not in resp
assert '<span class="tag tag-warning">1</span>' in resp
assert 'tag-error' not in resp
line.delete()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert 'tag-success' not in resp
assert 'tag-warning' not in resp
assert 'tag-error' not in resp
pool.draft = False
pool.save()
line = InvoiceLine.objects.create(
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
)
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert '<span class="tag tag-success">1</span>' in resp
assert 'tag-warning' not in resp
assert 'tag-error' not in resp
line.status = 'error'
line.save()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert 'tag-success' not in resp
assert 'tag-warning' not in resp
assert '<span class="tag tag-error">1</span>' in resp
line.status = 'warning'
line.save()
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert 'tag-success' not in resp
assert '<span class="tag tag-warning">1</span>' in resp
assert 'tag-error' not in resp
def test_journal_pool_lines(app, admin_user):
campaign = Campaign.objects.create(
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
@ -510,7 +612,7 @@ def test_detail_pool_lines(app, admin_user):
return (' '.join([v.strip() for v in value.split('\n')])).strip()
app = login(app)
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk))
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
assert format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[0].pk).text()) == 'Success'
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[0].pk).text().strip()