invoicing: set error status on invoice line (#73740) #21
|
@ -76,13 +76,9 @@ class AbstractLineFilterSet(django_filters.FilterSet):
|
|||
)
|
||||
status = django_filters.ChoiceFilter(
|
||||
label=_('Status'),
|
||||
choices=[
|
||||
('success', _('Success')),
|
||||
('warning', _('Warning')),
|
||||
('error', _('Error')),
|
||||
],
|
||||
widget=forms.RadioSelect,
|
||||
empty_label=_('all'),
|
||||
method='filter_status',
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -94,6 +90,30 @@ class AbstractLineFilterSet(django_filters.FilterSet):
|
|||
else:
|
||||
del self.filters['invoice_id']
|
||||
|
||||
status_choices = [
|
||||
('success', _('Success')),
|
||||
('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 == '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:
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('invoicing', '0013_formatted_number'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='invoiceline',
|
||||
name='error_status',
|
||||
field=models.CharField(
|
||||
blank=True, choices=[('ignored', 'Ignored'), ('fixed', 'Fixed')], max_length=10
|
||||
),
|
||||
),
|
||||
]
|
|
@ -258,12 +258,14 @@ class Pool(models.Model):
|
|||
final_line.pk = None
|
||||
final_line.invoice = final_invoice
|
||||
final_line.pool = self
|
||||
final_line.error_status = ''
|
||||
final_line.save()
|
||||
|
||||
for line in draft_pool.draftinvoiceline_set.filter(invoice__isnull=True).order_by('pk'):
|
||||
final_line = copy.deepcopy(line)
|
||||
final_line.__class__ = InvoiceLine
|
||||
final_line.pk = None
|
||||
final_line.error_status = ''
|
||||
final_line.pool = self
|
||||
final_line.save()
|
||||
|
||||
|
@ -427,3 +429,12 @@ class DraftInvoiceLine(AbstractInvoiceLine):
|
|||
class InvoiceLine(AbstractInvoiceLine):
|
||||
invoice = models.ForeignKey(Invoice, on_delete=models.PROTECT, null=True, related_name='lines')
|
||||
from_injected_line = models.ForeignKey(InjectedLine, on_delete=models.PROTECT, null=True)
|
||||
|
||||
error_status = models.CharField(
|
||||
max_length=10,
|
||||
choices=[
|
||||
('ignored', _('Ignored')),
|
||||
('fixed', _('Fixed')),
|
||||
],
|
||||
blank=True,
|
||||
)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
{% load i18n %}
|
||||
<td class="line_id">{{ line.pk }}</td>
|
||||
<td>
|
||||
{% if pool.draft and line.invoice %}
|
||||
TMP-{{ line.invoice_id }}
|
||||
{% elif line.invoice %}
|
||||
{{ line.invoice.formatted_number }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ line.event_date|date:"d/m/Y" }} - {{ line.label }}
|
||||
<br />
|
||||
({{ line.slug }})
|
||||
</td>
|
||||
<td>{{ line.quantity }}</td>
|
||||
<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 class="status">
|
||||
<span class="tag tag-{{ line.status }}">{% spaceless %}
|
||||
{% if line.status == 'error' and line.error_status %}
|
||||
{{ line.get_error_status_display }}
|
||||
{% else %}
|
||||
{{ line.get_status_display }}
|
||||
{% endif %}
|
||||
{% endspaceless %}</span>
|
||||
{% if line.status != 'success' %}
|
||||
({{ line.get_error_display }})
|
||||
{% if line.status == 'error' %}
|
||||
<br />
|
||||
{% if line.error_status %}
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' pk=object.pk pool_pk=pool.pk line_pk=line.pk status='reset' %}">{% trans "reset" %}</a>
|
||||
{% else %}
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' pk=object.pk pool_pk=pool.pk line_pk=line.pk status='ignore' %}">{% trans "ignore" %}</a>
|
||||
-
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' pk=object.pk pool_pk=pool.pk line_pk=line.pk status='fix' %}">{% trans "mark as fixed" %}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if line.from_injected_line_id %}({% trans "Injected" %}){% endif %}
|
||||
</td>
|
||||
<td><a class="details-toggle" href="#">{% trans "see details" %}</a></td>
|
|
@ -57,30 +57,7 @@
|
|||
<tbody>
|
||||
{% for line in lines %}
|
||||
<tr data-line-id="{{ line.pk }}">
|
||||
<td class="line_id">{{ line.pk }}</td>
|
||||
<td>
|
||||
{% if pool.draft and line.invoice %}
|
||||
TMP-{{ line.invoice_id }}
|
||||
{% elif line.invoice %}
|
||||
{{ line.invoice.formatted_number }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ line.event_date|date:"d/m/Y" }} - {{ line.label }}
|
||||
<br />
|
||||
({{ line.slug }})
|
||||
</td>
|
||||
<td>{{ line.quantity }}</td>
|
||||
<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 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>
|
||||
{% include 'lingo/invoicing/manager_line_detail_fragment.html' %}
|
||||
</tr>
|
||||
<tr data-details-for-line-id="{{ line.pk }}" style="display: none">
|
||||
<td colspan="10">
|
||||
|
@ -96,7 +73,8 @@
|
|||
</div>
|
||||
<script>
|
||||
$(function() {
|
||||
$('a.details-toggle').on('click', function() {
|
||||
$(document).on('click', 'a.details-toggle', function(event) {
|
||||
event.preventDefault();
|
||||
var line_id = $(this).parents('tr').data('line-id');
|
||||
var $details = $('tr[data-details-for-line-id=' + line_id + ']');
|
||||
if ($details.is(':visible')) {
|
||||
|
@ -107,6 +85,18 @@
|
|||
$details.show();
|
||||
}
|
||||
});
|
||||
$(document).on('click', 'a.error-status', function(event) {
|
||||
lguerin marked this conversation as resolved
Outdated
|
||||
// avoid reloading the whole page. There is no refresh of counters, it is not so important.
|
||||
event.preventDefault();
|
||||
var $a = $(this);
|
||||
$.ajax({
|
||||
url: $a.attr('href')
|
||||
}).done(function(html) {
|
||||
$a.parents('tr').html(html);
|
||||
}).fail(function() {
|
||||
location.reload();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -89,4 +89,9 @@ urlpatterns = [
|
|||
views.pool_delete,
|
||||
name='lingo-manager-invoicing-pool-delete',
|
||||
),
|
||||
path(
|
||||
'ajax/campaign/<int:pk>/pool/<int:pool_pk>/line/<int:line_pk>/<slug:status>/',
|
||||
views.line_set_error_status,
|
||||
name='lingo-manager-invoicing-line-set-error-status',
|
||||
),
|
||||
]
|
||||
|
|
|
@ -51,6 +51,10 @@ from lingo.invoicing.models import (
|
|||
from lingo.pricing.forms import ImportForm
|
||||
|
||||
|
||||
def is_ajax(request):
|
||||
return request.headers.get('x-requested-with') == 'XMLHttpRequest'
|
||||
|
||||
|
||||
def import_regies(data):
|
||||
results = collections.defaultdict(list)
|
||||
with transaction.atomic():
|
||||
|
@ -223,7 +227,9 @@ class CampaignDetailView(DetailView):
|
|||
draft_lines.filter(status='success').annotate(count=Count('pool')).values('count')
|
||||
)
|
||||
lines = InvoiceLine.objects.filter(pool=OuterRef('pk')).order_by().values('pool')
|
||||
count_error = lines.filter(status='error').annotate(count=Count('pool')).values('count')
|
||||
count_error = (
|
||||
lines.filter(status='error', error_status='').annotate(count=Count('pool')).values('count')
|
||||
)
|
||||
count_warning = lines.filter(status='warning').annotate(count=Count('pool')).values('count')
|
||||
count_success = lines.filter(status='success').annotate(count=Count('pool')).values('count')
|
||||
kwargs['pools'] = self.object.pool_set.annotate(
|
||||
|
@ -311,7 +317,9 @@ class PoolDetailView(DetailView):
|
|||
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.error_count = len(
|
||||
[line for line in all_lines if line.status == 'error' and not getattr(line, 'error_status', '')]
|
||||
)
|
||||
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'])
|
||||
kwargs['lines'] = (
|
||||
|
@ -346,7 +354,9 @@ class PoolJournalView(DetailView):
|
|||
line_model = DraftInvoiceLine
|
||||
filter_model = DraftInvoiceLineFilterSet
|
||||
all_lines = line_model.objects.filter(pool=self.object).order_by('pk').select_related('invoice')
|
||||
self.object.error_count = len([line for line in all_lines if line.status == 'error'])
|
||||
self.object.error_count = len(
|
||||
[line for line in all_lines if line.status == 'error' and not getattr(line, 'error_status', '')]
|
||||
)
|
||||
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'])
|
||||
data = self.request.GET or None
|
||||
|
@ -442,3 +452,46 @@ class PoolDeleteView(DeleteView):
|
|||
|
||||
|
||||
pool_delete = PoolDeleteView.as_view()
|
||||
|
||||
|
||||
class LineSetErrorStatusView(DetailView):
|
||||
model = InvoiceLine
|
||||
pk_url_kwarg = 'line_pk'
|
||||
template_name = 'lingo/invoicing/manager_line_detail_fragment.html'
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
super()
|
||||
.get_queryset()
|
||||
.filter(status='error', pool=self.kwargs['pool_pk'], pool__campaign=self.kwargs['pk'])
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['object'] = self.object.pool.campaign
|
||||
kwargs['pool'] = self.object.pool
|
||||
kwargs['line'] = self.object
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
error_status = kwargs['status']
|
||||
if error_status == 'reset':
|
||||
self.object.error_status = ''
|
||||
elif error_status == 'ignore':
|
||||
self.object.error_status = 'ignored'
|
||||
elif error_status == 'fix':
|
||||
self.object.error_status = 'fixed'
|
||||
else:
|
||||
raise Http404
|
||||
self.object.save()
|
||||
|
||||
if is_ajax(self.request):
|
||||
context = self.get_context_data(object=self.object)
|
||||
return self.render_to_response(context)
|
||||
|
||||
return redirect(
|
||||
reverse('lingo-manager-invoicing-pool-journal', args=[kwargs['pk'], kwargs['pool_pk']])
|
||||
)
|
||||
|
||||
|
||||
line_set_error_status = LineSetErrorStatusView.as_view()
|
||||
|
|
|
@ -173,6 +173,19 @@ def test_detail_campaign(app, admin_user):
|
|||
assert 'tag-success' not in resp
|
||||
assert '<span class="tag tag-warning">1</span>' in resp
|
||||
assert 'tag-error' not in resp
|
||||
line.status = 'error'
|
||||
line.error_status = 'ignored'
|
||||
line.save()
|
||||
resp = app.get('/manage/invoicing/campaign/%s/' % campaign.pk)
|
||||
assert 'tag-success' not in resp
|
||||
assert 'tag-warning' not in resp
|
||||
assert '<span class="tag tag-error">1</span>' not in resp
|
||||
line.error_status = 'fixed'
|
||||
line.save()
|
||||
resp = app.get('/manage/invoicing/campaign/%s/' % campaign.pk)
|
||||
assert 'tag-success' not in resp
|
||||
assert 'tag-warning' not in resp
|
||||
assert '<span class="tag tag-error">1</span>' not in resp
|
||||
|
||||
|
||||
def test_edit_campaign(app, admin_user):
|
||||
|
@ -742,6 +755,19 @@ def test_journal_pool(app, admin_user):
|
|||
assert 'tag-success' not in resp
|
||||
assert '<span class="tag tag-warning">1</span>' in resp
|
||||
assert 'tag-error' not in resp
|
||||
line.status = 'error'
|
||||
line.error_status = 'ignored'
|
||||
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>' not in resp
|
||||
line.error_status = 'fixed'
|
||||
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>' not in resp
|
||||
|
||||
|
||||
@pytest.mark.parametrize('draft', [True, False])
|
||||
|
@ -830,6 +856,11 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
payer_external_id='payer:2',
|
||||
)
|
||||
)
|
||||
if not draft:
|
||||
lines[-1].error_status = 'ignored'
|
||||
lines[-1].save()
|
||||
lines[-2].error_status = 'fixed'
|
||||
lines[-2].save()
|
||||
|
||||
lines.append(
|
||||
line_model.objects.create(
|
||||
|
@ -867,7 +898,7 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[2].pk).text())
|
||||
== 'Error (No matching criteria for category: cat-foo)'
|
||||
== 'Error (No matching criteria for category: cat-foo) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[2].pk).text().strip()
|
||||
|
@ -875,7 +906,7 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[3].pk).text())
|
||||
== 'Error (Multiple default criteria found for category: cat-foo)'
|
||||
== 'Error (Multiple default criteria found for category: cat-foo) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[3].pk).text().strip()
|
||||
|
@ -883,7 +914,7 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[4].pk).text())
|
||||
== 'Error (Impossible to determine a pricing for criterias: qf-1 (category: qf), bar (category: foo))'
|
||||
== 'Error (Impossible to determine a pricing for criterias: qf-1 (category: qf), bar (category: foo)) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[4].pk).text().strip()
|
||||
|
@ -891,7 +922,7 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[5].pk).text())
|
||||
== 'Error (Pricing is not a decimal: foobar)'
|
||||
== 'Error (Pricing is not a decimal: foobar) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[5].pk).text().strip()
|
||||
|
@ -899,7 +930,7 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[6].pk).text())
|
||||
== 'Error (Unknown check status: unknown)'
|
||||
== 'Error (Unknown check status: unknown) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[6].pk).text().strip()
|
||||
|
@ -907,7 +938,7 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[7].pk).text())
|
||||
== 'Error (Event is not checked)'
|
||||
== 'Error (Event is not checked) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[7].pk).text().strip()
|
||||
|
@ -915,7 +946,7 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[8].pk).text())
|
||||
== 'Error (Booking is not checked)'
|
||||
== 'Error (Booking is not checked) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[8].pk).text().strip()
|
||||
|
@ -923,7 +954,7 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[9].pk).text())
|
||||
== 'Error (Multiple booking found)'
|
||||
== 'Error (Multiple booking found) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[9].pk).text().strip()
|
||||
|
@ -931,24 +962,36 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[10].pk).text())
|
||||
== 'Error (Check type error: not found)'
|
||||
== 'Error (Check type error: not found) ignore - mark as fixed'
|
||||
)
|
||||
assert (
|
||||
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[10].pk).text().strip()
|
||||
== "{'error': 'PricingBookingCheckTypeError', 'error_details': {'reason': 'not-found'}} {'event': 'foobar'}"
|
||||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[11].pk).text())
|
||||
== 'Error (Check type error: pricing not configured (group: foo-bar, check type: foo-reason))'
|
||||
)
|
||||
if draft:
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[11].pk).text())
|
||||
== 'Error (Check type error: pricing not configured (group: foo-bar, check type: foo-reason)) ignore - mark as fixed'
|
||||
)
|
||||
else:
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[11].pk).text())
|
||||
== 'Fixed (Check type error: pricing not configured (group: foo-bar, check type: foo-reason)) reset'
|
||||
)
|
||||
assert resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[11].pk).text().strip() == (
|
||||
"{'error': 'PricingBookingCheckTypeError', 'error_details': {'check_type': 'foo-reason', "
|
||||
"'check_type_group': 'foo-bar', 'reason': 'not-configured'}} {'event': 'foobar'}"
|
||||
)
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[12].pk).text())
|
||||
== 'Error (Check type error: wrong kind (group: foo-bar, check type: foo-reason))'
|
||||
)
|
||||
if draft:
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[12].pk).text())
|
||||
== 'Error (Check type error: wrong kind (group: foo-bar, check type: foo-reason)) ignore - mark as fixed'
|
||||
)
|
||||
else:
|
||||
assert (
|
||||
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[12].pk).text())
|
||||
== 'Ignored (Check type error: wrong kind (group: foo-bar, check type: foo-reason)) reset'
|
||||
)
|
||||
assert resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[12].pk).text().strip() == (
|
||||
"{'error': 'PricingBookingCheckTypeError', 'error_details': {'check_type': 'foo-reason', "
|
||||
"'check_type_group': 'foo-bar', 'reason': 'wrong-kind'}} {'event': 'foobar'}"
|
||||
|
@ -1022,6 +1065,22 @@ def test_journal_pool_lines(app, admin_user, draft):
|
|||
params={'status': 'error'},
|
||||
)
|
||||
assert len(resp.pyquery('tr td.status')) == 11
|
||||
if not draft:
|
||||
resp = app.get(
|
||||
'/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk),
|
||||
params={'status': 'error_todo'},
|
||||
)
|
||||
assert len(resp.pyquery('tr td.status')) == 9
|
||||
resp = app.get(
|
||||
'/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk),
|
||||
params={'status': 'error_ignored'},
|
||||
)
|
||||
assert len(resp.pyquery('tr td.status')) == 1
|
||||
resp = app.get(
|
||||
'/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk),
|
||||
params={'status': 'error_fixed'},
|
||||
)
|
||||
assert len(resp.pyquery('tr td.status')) == 1
|
||||
|
||||
|
||||
def test_delete_pool(app, admin_user):
|
||||
|
@ -1080,3 +1139,141 @@ def test_delete_pool(app, admin_user):
|
|||
pool.draft = True
|
||||
pool.save()
|
||||
app.get('/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk))
|
||||
|
||||
|
||||
def test_set_error_status_line(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),
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
status='completed',
|
||||
)
|
||||
line = InvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=1,
|
||||
unit_amount=1,
|
||||
total_amount=1,
|
||||
status='success',
|
||||
pool=pool,
|
||||
)
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/ignore/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/fix/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
app.get(
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, line.pk),
|
||||
status=404,
|
||||
)
|
||||
app.get(
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/ignore/' % (campaign.pk, pool.pk, line.pk),
|
||||
status=404,
|
||||
)
|
||||
app.get(
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/fix/' % (campaign.pk, pool.pk, line.pk),
|
||||
status=404,
|
||||
)
|
||||
|
||||
line.status = 'warning'
|
||||
line.save()
|
||||
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/ignore/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/fix/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
app.get(
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, line.pk),
|
||||
status=404,
|
||||
)
|
||||
app.get(
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/ignore/' % (campaign.pk, pool.pk, line.pk),
|
||||
status=404,
|
||||
)
|
||||
app.get(
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/fix/' % (campaign.pk, pool.pk, line.pk),
|
||||
status=404,
|
||||
)
|
||||
|
||||
line.status = 'error'
|
||||
line.save()
|
||||
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/ignore/' % (campaign.pk, pool.pk, line.pk) in resp
|
||||
)
|
||||
assert '/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/fix/' % (campaign.pk, pool.pk, line.pk) in resp
|
||||
|
||||
line.error_status = 'ignored'
|
||||
line.save()
|
||||
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, line.pk) in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/ignore/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/fix/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
|
||||
line.error_status = 'fixed'
|
||||
line.save()
|
||||
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk))
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, line.pk) in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/ignore/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/fix/' % (campaign.pk, pool.pk, line.pk)
|
||||
not in resp
|
||||
)
|
||||
|
||||
app.get('/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, line.pk))
|
||||
line.refresh_from_db()
|
||||
assert line.error_status == ''
|
||||
|
||||
app.get('/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/ignore/' % (campaign.pk, pool.pk, line.pk))
|
||||
line.refresh_from_db()
|
||||
assert line.error_status == 'ignored'
|
||||
|
||||
app.get('/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/fix/' % (campaign.pk, pool.pk, line.pk))
|
||||
line.refresh_from_db()
|
||||
assert line.error_status == 'fixed'
|
||||
|
||||
app.get('/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (0, pool.pk, line.pk), status=404)
|
||||
app.get(
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, 0, line.pk), status=404
|
||||
)
|
||||
app.get(
|
||||
'/manage/invoicing/ajax/campaign/%s/pool/%s/line/%s/reset/' % (campaign.pk, pool.pk, 0), status=404
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Mini-effort pour faire en sorte de ne pas recharger la page lorsqu'on change une error status.
Les compteurs (en haut de page) ne sont pas refresh, et en fonction des filtres sélectionnés ça peut ne plus être consistant, mais je pense que c'est acceptable.
Je trouve que ce commentaire pourrait trouver sa place dans le code, à cet endroit précis. Juste un « avoid reloading the whole page. There is no refresh of counters, it is not so important. »