listing des factures et de leurs lignes (#73514) #17
|
@ -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,
|
||||
),
|
||||
]
|
|
@ -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,
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
|
|
@ -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">
|
||||
<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 %}
|
||||
</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>
|
||||
<div>
|
||||
{% 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>
|
||||
{% ifchanged line.invoice_id %}
|
||||
{% if not forloop.first %}</ul>{% endif %}
|
||||
<h3 data-invoice-id="{{ line.invoice_id }}">
|
||||
lguerin marked this conversation as resolved
Outdated
|
||||
{% 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 %}
|
||||
Ghost
commented
|date:"SHORT_DATE_FORMAT" pour anticiper les ventes de lingo aux US. |date:"SHORT_DATE_FORMAT" pour anticiper les ventes de lingo aux US.
lguerin
commented
SHORT_DATE_FORMAT = 'j N Y' 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 %}
|
||||
</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>
|
||||
{% endblock %}
|
||||
|
|
|
@ -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 %}
|
|
@ -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,
|
||||
|
|
|
@ -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
Ghost
commented
micro détail, ici j'aurais juste fait
(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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
]
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue
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