listing des factures et de leurs lignes (#73514) #17

Merged
lguerin merged 4 commits from wip/73514-invoicing-invoice-listing into main 2023-01-27 16:01:47 +01:00
11 changed files with 528 additions and 102 deletions

View File

@ -0,0 +1,23 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('invoicing', '0008_injected_line'),
]
operations = [
migrations.AddField(
model_name='draftinvoiceline',
name='user_name',
field=models.CharField(default='', max_length=250),
preserve_default=False,
),
migrations.AddField(
model_name='invoiceline',
name='user_name',
field=models.CharField(default='', max_length=250),
preserve_default=False,
),
]

View File

@ -0,0 +1,25 @@
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('invoicing', '0009_user_name'),
]
operations = [
migrations.AddField(
model_name='draftinvoiceline',
name='event_date',
field=models.DateField(default=datetime.date.today),
preserve_default=False,
),
migrations.AddField(
model_name='invoiceline',
name='event_date',
field=models.DateField(default=datetime.date.today),
preserve_default=False,
),
]

View File

@ -152,11 +152,9 @@ class Pool(models.Model):
# get agendas with pricing corresponding to the period
agendas = utils.get_agendas(pool=self)
# get subscribed users for each agenda, for the period
user_external_ids = utils.get_users_from_subscriptions(agendas=agendas, pool=self)
users = utils.get_users_from_subscriptions(agendas=agendas, pool=self)
# get invoice lines for all subscribed users, for each agenda in the corresponding period
lines = utils.get_all_invoice_lines(
agendas=agendas, user_external_ids=user_external_ids, pool=self
)
lines = utils.get_all_invoice_lines(agendas=agendas, users=users, pool=self)
# and generate invoices
utils.generate_invoices_from_lines(agendas=agendas, all_lines=lines, pool=self)
except (RegieNotConfigured, ChronoError) as e:
@ -208,6 +206,7 @@ class InjectedLine(models.Model):
class AbstractInvoiceLine(models.Model):
event_date = models.DateField()
slug = models.SlugField(max_length=250)
label = models.CharField(max_length=260)
quantity = models.FloatField()
@ -215,6 +214,7 @@ class AbstractInvoiceLine(models.Model):
total_amount = models.DecimalField(max_digits=9, decimal_places=2)
user_external_id = models.CharField(max_length=250)
user_name = models.CharField(max_length=250)
payer_external_id = models.CharField(max_length=250)
event = JSONField(default=dict)
pricing_data = JSONField(default=dict, encoder=DjangoJSONEncoder)

View File

@ -13,76 +13,28 @@
{% 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>
<div>
{% for line in lines %}
{% ifchanged line.invoice_id %}
{% if not forloop.first %}</ul>{% endif %}
<h3 data-invoice-id="{{ line.invoice_id }}">
lguerin marked this conversation as resolved Outdated
Outdated
Review

Même si c'est encore draft, peut-être un tout petit poil d'explication, genre

Facture #220 adressée à Prenom Nom, total 233,00 €

parce qu'en première approx j'avais pas compris les « #202 foo:8 (116,00) » sur la copie d'écran

Mais bon, on est vraiment encore en mode draft, tu peux laisser ainsi

Même si c'est encore draft, peut-être un tout petit poil d'explication, genre Facture #220 adressée à Prenom Nom, total 233,00 € parce qu'en première approx j'avais pas compris les « #202 foo:8 (116,00) » sur la copie d'écran Mais bon, on est vraiment encore en mode draft, tu peux laisser ainsi
{% blocktrans with number=line.invoice_id payer=line.invoice.payer amount=line.invoice.total_amount %}Invoice #{{ number }} addressed to {{ payer }}, amount {{ amount }}€{% endblocktrans %}
</h3>
<ul class="objects-list" data-invoice-id="{{ line.invoice_id }}">
{% endifchanged %}
Outdated
Review

|date:"SHORT_DATE_FORMAT" pour anticiper les ventes de lingo aux US.

|date:"SHORT_DATE_FORMAT" pour anticiper les ventes de lingo aux US.

SHORT_DATE_FORMAT = 'j N Y'
Ça n'est pas ce que je veux afficher :)

SHORT_DATE_FORMAT = 'j N Y' Ça n'est pas ce que je veux afficher :)
<li>
#{{ line.pk }} {{ line.user_name }} - {{ line.event_date|date:"d/m/Y" }} - {{ line.label }} ({{ line.total_amount }})
</li>
{% if forloop.last %}</ul>{% endif %}
{% endfor %}
</div>
{% endblock %}

View File

@ -0,0 +1,93 @@
{% 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 "Event" %}</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.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>
</tr>
<tr data-details-for-line-id="{{ line.pk }}" style="display: none">
<td colspan="10">
{% trans "Pricing data:" %}
<pre>{{ line.pricing_data|pprint }}</pre>
{% trans "Event:" %}
<pre>{{ line.event|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

@ -35,7 +35,7 @@ def get_agendas(pool):
def get_users_from_subscriptions(agendas, pool):
user_external_ids = set()
users = {}
for agenda in agendas:
subscriptions = get_subscriptions(
agenda_slug=agenda.slug,
@ -43,11 +43,15 @@ def get_users_from_subscriptions(agendas, pool):
date_end=pool.campaign.date_end,
)
for subscription in subscriptions:
user_external_ids.add(subscription['user_external_id'])
return user_external_ids
user_external_id = subscription['user_external_id']
if user_external_id in users:
continue
user_name = '%s %s' % (subscription['user_first_name'], subscription['user_last_name'])
users[user_external_id] = user_name.strip()[:250] or user_external_id
return [(user_id, user_name) for user_id, user_name in users.items()]
lguerin marked this conversation as resolved Outdated
Outdated
Review

micro détail, ici j'aurais juste fait
...

      users[user_external_id] = user_name.strip()[:250] or user_external_id
 return [(user_id, user_name) for user_id, user_name in users.items()]

(parce que je trouve le return plus clair ainsi sur ce qui est retourné)

micro détail, ici j'aurais juste fait ... users[user_external_id] = user_name.strip()[:250] or user_external_id return [(user_id, user_name) for user_id, user_name in users.items()] (parce que je trouve le return plus clair ainsi sur ce qui est retourné)
def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool):
def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, user_name, pool):
def get_agenda_pricing(agendas_pricings_for_agenda, date_event):
# same logic as AgendaPricing.get_agenda_pricing
for agenda_pricing in agendas_pricings_for_agenda:
@ -104,12 +108,14 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool
}
lines.append(
DraftInvoiceLine(
event_date=event_date,
slug=event_slug,
label=serialized_event['label'],
quantity=0,
unit_amount=0,
total_amount=0,
user_external_id=user_external_id,
user_name=user_name,
payer_external_id=user_external_id, # XXX
event=serialized_event,
pricing_data=pricing_error,
@ -121,12 +127,14 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool
# XXX log all context !
lines.append(
DraftInvoiceLine(
event_date=event_date,
slug=event_slug,
label=serialized_event['label'],
quantity=1,
unit_amount=pricing_data['pricing'],
total_amount=pricing_data['pricing'],
user_external_id=user_external_id,
user_name=user_name,
payer_external_id=user_external_id, # XXX
event=serialized_event,
pricing_data=pricing_data,
@ -157,12 +165,14 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool
for injected_line in injected_lines:
lines.append(
DraftInvoiceLine(
event_date=injected_line.event_date,
slug=injected_line.slug,
label=injected_line.label,
quantity=injected_line.quantity,
unit_amount=injected_line.unit_amount,
total_amount=injected_line.total_amount,
user_external_id=injected_line.user_external_id,
user_external_id=user_external_id,
user_name=user_name,
payer_external_id=injected_line.user_external_id,
status='success',
pool=pool,
@ -175,7 +185,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool
return lines
def get_all_invoice_lines(agendas, user_external_ids, pool):
def get_all_invoice_lines(agendas, users, pool):
agendas_pricings = (
AgendaPricing.objects.filter(flat_fee_schedule=False)
.extra(
@ -186,12 +196,13 @@ def get_all_invoice_lines(agendas, user_external_ids, pool):
)
lines = []
for user_external_id in user_external_ids:
for user_external_id, user_name in users:
# generate lines for each user
lines += get_invoice_lines_for_user(
agendas=agendas,
agendas_pricings=agendas_pricings,
user_external_id=user_external_id,
user_name=user_name,
pool=pool,
)
return lines

View File

@ -297,6 +297,39 @@ 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'])
kwargs['lines'] = (
all_lines.filter(invoice__isnull=False)
.select_related('invoice')
.order_by('invoice__pk', 'user_external_id', 'pk')
)
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 +350,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

@ -120,6 +120,7 @@ def test_detail_campaign(app, admin_user):
assert '/manage/invoicing/campaign/%s/pool/add/' % (campaign.pk) not in resp
line = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
@ -149,6 +150,7 @@ def test_detail_campaign(app, admin_user):
assert 'tag-error' not in resp
line = InvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
@ -264,6 +266,7 @@ def test_delete_campaign(app, admin_user):
regie = Regie.objects.create(label='Foo')
invoice = DraftInvoice.objects.create(date_issue=datetime.date.today(), regie=regie, pool=pool)
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
quantity=1,
unit_amount=1,
@ -386,6 +389,7 @@ def test_detail_pool(app, admin_user):
assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) in resp
line = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
@ -417,6 +421,7 @@ def test_detail_pool(app, admin_user):
pool.draft = False
pool.save()
line = InvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
@ -441,7 +446,223 @@ def test_detail_pool(app, admin_user):
assert 'tag-error' not in resp
def test_detail_pool_lines(app, admin_user):
def test_detail_pool_invoices(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=True,
status='completed',
)
regie = Regie.objects.create(label='Foo')
invoice1 = DraftInvoice.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=pool, payer='payer:1'
)
invoice2 = DraftInvoice.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=pool, payer='payer:2'
)
line11 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice1,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
label='Label 11',
user_external_id='user:1',
user_name='User1 Name1',
)
line12 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 2),
invoice=invoice1,
quantity=1,
unit_amount=2,
total_amount=2,
status='success',
pool=pool,
label='Label 12',
user_external_id='user:2',
user_name='User2 Name2',
)
line13 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 3),
invoice=invoice1,
quantity=1,
unit_amount=3,
total_amount=3,
status='success',
pool=pool,
label='Label 13',
user_external_id='user:1',
user_name='User1 Name1',
)
orphan_line = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=42,
total_amount=42,
status='failed',
pool=pool,
label='Label 14',
user_external_id='user:1',
user_name='User1 Name1',
)
line21 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice2,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
label='Label 21',
user_external_id='user:1',
user_name='User1 Name1',
)
app = login(app)
resp = app.get('/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk))
assert '#%s' % orphan_line.pk not in resp
assert (
resp.pyquery('h3[data-invoice-id="%s"]' % invoice1.pk).text()
== 'Invoice #%s addressed to payer:1, amount 6.00€' % invoice1.pk
)
assert len(resp.pyquery('ul[data-invoice-id="%s"] li' % invoice1.pk)) == 3
assert (
resp.pyquery('ul[data-invoice-id="%s"] li:nth-child(1)' % invoice1.pk).text()
== '#%s User1 Name1 - 01/09/2022 - Label 11 (1.00)' % line11.pk
)
assert (
resp.pyquery('ul[data-invoice-id="%s"] li:nth-child(2)' % invoice1.pk).text()
== '#%s User1 Name1 - 03/09/2022 - Label 13 (3.00)' % line13.pk
)
assert (
resp.pyquery('ul[data-invoice-id="%s"] li:nth-child(3)' % invoice1.pk).text()
== '#%s User2 Name2 - 02/09/2022 - Label 12 (2.00)' % line12.pk
)
assert (
resp.pyquery('h3[data-invoice-id="%s"]' % invoice2.pk).text()
== 'Invoice #%s addressed to payer:2, amount 1.00€' % invoice2.pk
)
assert len(resp.pyquery('ul[data-invoice-id="%s"] li' % invoice2.pk)) == 1
assert (
resp.pyquery('ul[data-invoice-id="%s"] li:nth-child(1)' % invoice2.pk).text()
== '#%s User1 Name1 - 01/09/2022 - Label 21 (1.00)' % line21.pk
)
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(
event_date=datetime.date(2022, 9, 1),
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(
event_date=datetime.date(2022, 9, 1),
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),
@ -457,6 +678,7 @@ def test_detail_pool_lines(app, admin_user):
lines = [
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
quantity=1,
unit_amount=1,
@ -464,6 +686,7 @@ def test_detail_pool_lines(app, admin_user):
status='success',
pool=pool,
pricing_data={'foo': 'bar'},
event={'event': 'foobar'},
)
]
errors = [
@ -493,6 +716,7 @@ def test_detail_pool_lines(app, admin_user):
for error, error_details in errors:
lines.append(
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
quantity=1,
unit_amount=1,
@ -503,6 +727,7 @@ def test_detail_pool_lines(app, admin_user):
'error': error,
'error_details': error_details,
},
event={'event': 'foobar'},
)
)
@ -510,11 +735,11 @@ 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()
== "{'foo': 'bar'}"
== "{'foo': 'bar'} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[1].pk).text())
@ -522,7 +747,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[1].pk).text().strip()
== "{'error': 'AgendaPricingNotFound', 'error_details': {}}"
== "{'error': 'AgendaPricingNotFound', 'error_details': {}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[2].pk).text())
@ -530,7 +755,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[2].pk).text().strip()
== "{'error': 'CriteriaConditionNotFound', 'error_details': {'category': 'cat-foo'}}"
== "{'error': 'CriteriaConditionNotFound', 'error_details': {'category': 'cat-foo'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[3].pk).text())
@ -538,7 +763,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[3].pk).text().strip()
== "{'error': 'MultipleDefaultCriteriaCondition', 'error_details': {'category': 'cat-foo'}}"
== "{'error': 'MultipleDefaultCriteriaCondition', 'error_details': {'category': 'cat-foo'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[4].pk).text())
@ -546,7 +771,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[4].pk).text().strip()
== "{'error': 'PricingDataError', 'error_details': {'criterias': {'foo': 'bar', 'qf': 'qf-1'}}}"
== "{'error': 'PricingDataError', 'error_details': {'criterias': {'foo': 'bar', 'qf': 'qf-1'}}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[5].pk).text())
@ -554,7 +779,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[5].pk).text().strip()
== "{'error': 'PricingDataFormatError', 'error_details': {'pricing': 'foobar', 'wanted': 'decimal'}}"
== "{'error': 'PricingDataFormatError', 'error_details': {'pricing': 'foobar', 'wanted': 'decimal'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[6].pk).text())
@ -562,7 +787,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[6].pk).text().strip()
== "{'error': 'PricingUnknownCheckStatusError', 'error_details': {'status': 'unknown'}}"
== "{'error': 'PricingUnknownCheckStatusError', 'error_details': {'status': 'unknown'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[7].pk).text())
@ -570,7 +795,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[7].pk).text().strip()
== "{'error': 'PricingEventNotCheckedError', 'error_details': {}}"
== "{'error': 'PricingEventNotCheckedError', 'error_details': {}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[8].pk).text())
@ -578,7 +803,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[8].pk).text().strip()
== "{'error': 'PricingBookingNotCheckedError', 'error_details': {}}"
== "{'error': 'PricingBookingNotCheckedError', 'error_details': {}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[9].pk).text())
@ -586,7 +811,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[9].pk).text().strip()
== "{'error': 'PricingMultipleBookingError', 'error_details': {}}"
== "{'error': 'PricingMultipleBookingError', 'error_details': {}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[10].pk).text())
@ -594,7 +819,7 @@ def test_detail_pool_lines(app, admin_user):
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[10].pk).text().strip()
== "{'error': 'PricingBookingCheckTypeError', 'error_details': {'reason': 'not-found'}}"
== "{'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())
@ -602,7 +827,7 @@ def test_detail_pool_lines(app, admin_user):
)
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'}}"
"'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())
@ -610,7 +835,7 @@ def test_detail_pool_lines(app, admin_user):
)
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'}}"
"'check_type_group': 'foo-bar', 'reason': 'wrong-kind'}} {'event': 'foobar'}"
)
@ -633,6 +858,7 @@ def test_delete_pool(app, admin_user):
regie = Regie.objects.create(label='Foo')
invoice = DraftInvoice.objects.create(date_issue=datetime.date.today(), regie=regie, pool=pool)
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
quantity=1,
unit_amount=1,

View File

@ -130,12 +130,12 @@ def test_get_users_from_subscriptions(mock_subscriptions):
)
# no agendas
assert utils.get_users_from_subscriptions(agendas=[], pool=pool) == set()
assert utils.get_users_from_subscriptions(agendas=[], pool=pool) == []
assert mock_subscriptions.call_args_list == []
# no subscriptions
mock_subscriptions.return_value = []
assert utils.get_users_from_subscriptions(agendas=[agenda1, agenda2], pool=pool) == set()
assert utils.get_users_from_subscriptions(agendas=[agenda1, agenda2], pool=pool) == []
assert mock_subscriptions.call_args_list == [
mock.call(
agenda_slug='agenda-1', date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1)
@ -151,16 +151,22 @@ def test_get_users_from_subscriptions(mock_subscriptions):
[
{
'user_external_id': 'user:1',
'user_first_name': 'User1',
'user_last_name': 'Name1',
'date_start': '2022-08-01',
'date_end': '2022-09-02',
},
{
'user_external_id': 'user:1',
'user_first_name': 'Foo Bar',
'user_last_name': '',
'date_start': '2022-09-02',
'date_end': '2022-09-03',
},
{
'user_external_id': 'user:2',
'user_first_name': '',
'user_last_name': '',
'date_start': '2022-09-02',
'date_end': '2022-09-03',
},
@ -168,12 +174,17 @@ def test_get_users_from_subscriptions(mock_subscriptions):
[
{
'user_external_id': 'user:1',
'user_first_name': 'User1 Name1',
'user_last_name': '',
'date_start': '2022-08-01',
'date_end': '2022-10-01',
},
],
]
assert utils.get_users_from_subscriptions(agendas=[agenda1, agenda2], pool=pool) == {'user:1', 'user:2'}
assert utils.get_users_from_subscriptions(agendas=[agenda1, agenda2], pool=pool) == [
('user:1', 'User1 Name1'),
('user:2', 'user:2'),
]
assert mock_subscriptions.call_args_list == [
mock.call(
agenda_slug='agenda-1', date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1)
@ -202,6 +213,7 @@ def test_get_invoice_lines_for_user_check_status_error(mock_status):
agendas=[agenda],
agendas_pricings=[],
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
)
@ -267,6 +279,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
)
# ok, same campaign
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=0,
unit_amount=0,
total_amount=0,
@ -319,6 +332,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
)
# nok, already invoiced
InvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 15),
quantity=0,
unit_amount=0,
total_amount=0,
@ -338,6 +352,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
)
# nok, other campaign
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 16),
quantity=0,
unit_amount=0,
total_amount=0,
@ -351,6 +366,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
agendas=[],
agendas_pricings=[agenda_pricing],
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
)
== []
@ -364,6 +380,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
agendas=[agenda1, agenda2],
agendas_pricings=[agenda_pricing],
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
)
assert len(lines) == 2 # injected lines
@ -433,6 +450,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
agendas=[agenda1, agenda2],
agendas_pricings=[agenda_pricing],
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
)
assert mock_pricing_data_event.call_args_list == [
@ -493,12 +511,14 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
line1, line2, line3, line4, line5, line6 = lines
assert isinstance(line1, DraftInvoiceLine)
assert line1.invoice is None
assert line1.event_date == datetime.date(2022, 9, 1)
assert line1.slug == 'agenda-1@event-1'
assert line1.label == 'Event 1'
assert line1.quantity == 1
assert line1.unit_amount == 1
assert line1.total_amount == 1
assert line1.user_external_id == 'user:1'
assert line1.user_name == 'User1 Name1'
assert line1.payer_external_id == 'user:1'
assert line1.event == {
'agenda': 'agenda-1',
@ -512,12 +532,14 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
assert line1.from_injected_line is None
assert isinstance(line2, DraftInvoiceLine)
assert line2.invoice is None
assert line2.event_date == datetime.date(2022, 9, 2)
assert line2.slug == 'agenda-1@event-2'
assert line2.label == 'Event 2'
assert line2.quantity == 1
assert line2.unit_amount == 2
assert line2.total_amount == 2
assert line2.user_external_id == 'user:1'
assert line2.user_name == 'User1 Name1'
assert line2.payer_external_id == 'user:1'
assert line2.event == {
'agenda': 'agenda-1',
@ -531,12 +553,14 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
assert line2.from_injected_line is None
assert isinstance(line3, DraftInvoiceLine)
assert line3.invoice is None
assert line3.event_date == datetime.date(2022, 9, 1)
assert line3.slug == 'agenda-2@eveeent-1'
assert line3.label == 'Eveeent 1'
assert line3.quantity == 1
assert line3.unit_amount == 3
assert line3.total_amount == 3
assert line3.user_external_id == 'user:1'
assert line3.user_name == 'User1 Name1'
assert line3.payer_external_id == 'user:1'
assert line3.event == {
'agenda': 'agenda-2',
@ -550,12 +574,14 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
assert line3.from_injected_line is None
assert isinstance(line4, DraftInvoiceLine)
assert line4.invoice is None
assert line4.event_date == datetime.date(2022, 9, 2)
assert line4.slug == 'agenda-2@eveeent-2'
assert line4.label == 'Eveeent 2'
assert line4.quantity == 1
assert line4.unit_amount == 4
assert line4.total_amount == 4
assert line4.user_external_id == 'user:1'
assert line4.user_name == 'User1 Name1'
assert line4.payer_external_id == 'user:1'
assert line4.event == {
'agenda': 'agenda-2',
@ -569,12 +595,14 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
assert line4.from_injected_line is None
assert isinstance(line5, DraftInvoiceLine)
assert line5.invoice is None
assert line5.event_date == injected_line2.event_date
assert line5.slug == 'event-2022-09-01'
assert line5.label == 'Event 2022-09-01'
assert line5.quantity == 2
assert line5.unit_amount == 1.5
assert line5.total_amount == 3
assert line5.user_external_id == 'user:1'
assert line5.user_name == 'User1 Name1'
assert line5.payer_external_id == 'user:1'
assert line5.event == {}
assert line5.pricing_data == {}
@ -583,12 +611,14 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
assert line5.from_injected_line == injected_line2
assert isinstance(line6, DraftInvoiceLine)
assert line6.invoice is None
assert line6.event_date == injected_line4.event_date
assert line6.slug == 'event-2022-09-30'
assert line6.label == 'Event 2022-09-30'
assert line6.quantity == 3
assert line6.unit_amount == 1.5
assert line6.total_amount == 4.5
assert line6.user_external_id == 'user:1'
assert line6.user_name == 'User1 Name1'
assert line6.payer_external_id == 'user:1'
assert line6.event == {}
assert line6.pricing_data == {}
@ -652,6 +682,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
agendas=[agenda],
agendas_pricings=AgendaPricing.objects.all(),
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
)
assert len(lines) == 1
@ -677,6 +708,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
agendas=[agenda],
agendas_pricings=AgendaPricing.objects.all(),
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
)
assert len(lines) == 1
@ -701,6 +733,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
agendas=[agenda],
agendas_pricings=AgendaPricing.objects.all(),
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
)
assert len(lines) == 1
@ -713,6 +746,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
assert line.unit_amount == 0
assert line.total_amount == 0
assert line.user_external_id == 'user:1'
assert line.user_name == 'User1 Name1'
assert line.payer_external_id == 'user:1'
assert line.event == {
'agenda': 'agenda',
@ -788,18 +822,21 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
agendas=[agenda],
agendas_pricings=[agenda_pricing],
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
)
assert len(lines) == 3
line1, line2, line3 = lines
assert isinstance(line1, DraftInvoiceLine)
assert line1.invoice is None
assert line1.event_date == datetime.date(2022, 9, 1)
assert line1.slug == 'agenda@event-1'
assert line1.label == 'Event 1'
assert line1.quantity == 1
assert line1.unit_amount == 1
assert line1.total_amount == 1
assert line1.user_external_id == 'user:1'
assert line1.user_name == 'User1 Name1'
assert line1.payer_external_id == 'user:1'
assert line1.event == {
'agenda': 'agenda',
@ -812,12 +849,14 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
assert line1.pool == pool
assert isinstance(line2, DraftInvoiceLine)
assert line2.invoice is None
assert line2.event_date == datetime.date(2022, 9, 2)
assert line2.slug == 'agenda@event-2'
assert line2.label == 'Event 2'
assert line2.quantity == 0
assert line2.unit_amount == 0
assert line2.total_amount == 0
assert line2.user_external_id == 'user:1'
assert line2.user_name == 'User1 Name1'
assert line2.payer_external_id == 'user:1'
assert line2.event == {
'agenda': 'agenda',
@ -830,12 +869,14 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
assert line2.pool == pool
assert isinstance(line3, DraftInvoiceLine)
assert line3.invoice is None
assert line3.event_date == datetime.date(2022, 9, 3)
assert line3.slug == 'agenda@event-3'
assert line3.label == 'Event 3'
assert line3.quantity == 1
assert line3.unit_amount == 3
assert line3.total_amount == 3
assert line3.user_external_id == 'user:1'
assert line3.user_name == 'User1 Name1'
assert line3.payer_external_id == 'user:1'
assert line3.event == {
'agenda': 'agenda',
@ -864,18 +905,21 @@ def test_get_all_invoice_lines(mock_user_lines):
)
line1 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=0,
unit_amount=0,
total_amount=0,
pool=pool,
)
line2 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=0,
unit_amount=0,
total_amount=0,
pool=pool,
)
line3 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=0,
unit_amount=0,
total_amount=0,
@ -888,7 +932,7 @@ def test_get_all_invoice_lines(mock_user_lines):
assert (
utils.get_all_invoice_lines(
agendas=[agenda1, agenda2],
user_external_ids=[],
users=[],
pool=pool,
)
== []
@ -898,7 +942,7 @@ def test_get_all_invoice_lines(mock_user_lines):
# with subscribed users
assert utils.get_all_invoice_lines(
agendas=[agenda1, agenda2],
user_external_ids=['user:1', 'user:2'],
users=[('user:1', 'User1 Name1'), ('user:2', 'User2 Name2')],
pool=pool,
) == [line1, line2, line3]
assert mock_user_lines.call_args_list == [
@ -906,12 +950,14 @@ def test_get_all_invoice_lines(mock_user_lines):
agendas=[agenda1, agenda2],
agendas_pricings=mock.ANY,
user_external_id='user:1',
user_name='User1 Name1',
pool=pool,
),
mock.call(
agendas=[agenda1, agenda2],
agendas_pricings=mock.ANY,
user_external_id='user:2',
user_name='User2 Name2',
pool=pool,
),
]
@ -1018,7 +1064,7 @@ def test_get_all_invoice_lines_queryset(mock_status):
with CaptureQueriesContext(connection) as ctx:
lines = utils.get_all_invoice_lines(
agendas=[agenda1, agenda2],
user_external_ids=['user:1', 'user:2'],
users=[('user:1', 'User1 Name1'), ('user:2', 'User2 Name2')],
pool=pool,
)
assert lines
@ -1044,6 +1090,7 @@ def test_generate_invoices_from_lines():
)
line_error = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
event={'agenda': 'agenda-1'},
quantity=0,
unit_amount=0,
@ -1054,6 +1101,7 @@ def test_generate_invoices_from_lines():
pool=pool,
)
line1 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
event={'agenda': 'agenda-1'},
quantity=1,
unit_amount=1,
@ -1064,6 +1112,7 @@ def test_generate_invoices_from_lines():
pool=pool,
)
line2 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
event={'agenda': 'agenda-1'},
quantity=1,
unit_amount=2,
@ -1074,6 +1123,7 @@ def test_generate_invoices_from_lines():
pool=pool,
)
line3 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
event={'agenda': 'agenda-2'},
quantity=1,
unit_amount=3,
@ -1084,6 +1134,7 @@ def test_generate_invoices_from_lines():
pool=pool,
)
line4 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
event={'agenda': 'agenda-2'},
quantity=1,
unit_amount=4,
@ -1094,6 +1145,7 @@ def test_generate_invoices_from_lines():
pool=pool,
)
line5 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
event={'agenda': 'agenda-3'},
quantity=1,
unit_amount=5,
@ -1104,6 +1156,7 @@ def test_generate_invoices_from_lines():
pool=pool,
)
DraftInvoiceLine.objects.create( # not used for generation
event_date=datetime.date(2022, 9, 1),
event={'agenda': 'agenda-3'},
quantity=1,
unit_amount=5,
@ -1114,6 +1167,7 @@ def test_generate_invoices_from_lines():
pool=pool,
)
line6 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
event={'agenda': 'agenda-4'}, # regie not configured
quantity=1,
unit_amount=6,
@ -1135,6 +1189,7 @@ def test_generate_invoices_from_lines():
regie=regie1,
)
line7 = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=7,
total_amount=7,
@ -1232,7 +1287,7 @@ def test_generate_invoices(mock_generate, mock_lines, mock_users, mock_agendas):
assert mock_lines.call_args_list == [
mock.call(
agendas=[agenda1, agenda2],
user_external_ids=['foo', 'bar'],
users=['foo', 'bar'],
pool=pool,
)
]

View File

@ -30,6 +30,7 @@ def test_invoice_total_amount(draft):
# line with error status, ignored
line = line_model.objects.create(
event_date=datetime.date.today(),
invoice=invoice, # with invoice
quantity=0,
unit_amount=0,
@ -80,6 +81,7 @@ def test_invoice_total_amount(draft):
# create line with invoice, status success
line2 = line_model.objects.create(
event_date=datetime.date.today(),
invoice=invoice,
quantity=1,
unit_amount=20,
@ -109,6 +111,7 @@ def test_invoice_total_amount(draft):
# create line without invoice, status success
line3 = line_model.objects.create(
event_date=datetime.date.today(),
quantity=1,
unit_amount=20,
total_amount=20,