From f49b9b8d0382fc286b22e88dab7d974a15bf9797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= Date: Tue, 17 Jan 2023 17:33:41 +0100 Subject: [PATCH 1/4] invoicing: move line listing in journal view (#73514) --- .../lingo/invoicing/manager_pool_detail.html | 73 +----------- .../lingo/invoicing/manager_pool_journal.html | 88 +++++++++++++++ lingo/invoicing/urls.py | 5 + lingo/invoicing/views.py | 30 ++++- tests/invoicing/manager/test_campaign.py | 106 +++++++++++++++++- 5 files changed, 231 insertions(+), 71 deletions(-) create mode 100644 lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html b/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html index e7077be..5427631 100644 --- a/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html +++ b/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html @@ -13,76 +13,13 @@ {% if pool.error_count %}{{ pool.error_count }}{% endif %} {{ pool.created_at|date:"DATETIME_FORMAT" }} - {% if pool.draft and pool.status != 'registered' and pool.status != 'running' %} - + + {% trans "Journal" %} + {% if pool.draft and pool.status != 'registered' and pool.status != 'running' %} {% trans "Delete" %} - - {% endif %} + {% endif %} + {% endblock %} {% block content %} - {% if pool.status == 'failed' %} -
-

{% trans "Error while running pool." %}

- {% if pool.exception %}
{{ pool.exception }}
{% endif %} -
- {% endif %} - - - - - - - - - - - - - - - - - - {% for line in lines %} - - - - - - - - - - - - - - - - - {% endfor %} - -
{% trans "PK" %}{% trans "Invoice PK" %}{% trans "Label" %}{% trans "Slug" %}{% trans "Quantity" %}{% trans "Unit amount" %}{% trans "Total amount" %}{% trans "User" %}{% trans "Payer" %}{% trans "Status" %}
{{ line.pk }}{{ line.invoice_id|default:'' }}{{ line.label }}{{ line.slug }}{{ line.quantity }}{{ line.unit_amount }}{{ line.total_amount }}{{ line.user_external_id }}{{ line.payer_external_id }} - {{ line.get_status_display }} - {% if line.status != 'success' %}({{ line.get_error_display }}){% endif %} - {% if line.from_injected_line_id %}({% trans "Injected" %}){% endif %} - {% trans "see details" %}
-
{{ line.pricing_data|pprint }}
-
- {% endblock %} diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html b/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html new file mode 100644 index 0000000..d9369cd --- /dev/null +++ b/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html @@ -0,0 +1,88 @@ +{% extends "lingo/invoicing/manager_pool_detail.html" %} +{% load i18n %} + +{% block breadcrumb %} + {{ block.super }} + {% trans "Journal" %} +{% endblock %} + +{% block appbar %} +

+ {% if pool.success_count %}{{ pool.success_count }}{% endif %} + {% if pool.warning_count %}{{ pool.warning_count }}{% endif %} + {% if pool.error_count %}{{ pool.error_count }}{% endif %} + {{ pool.created_at|date:"DATETIME_FORMAT" }} +

+ {% if pool.draft and pool.status != 'registered' and pool.status != 'running' %} + + {% trans "Delete" %} + + {% endif %} +{% endblock %} + +{% block content %} + {% if pool.status == 'failed' %} +
+

{% trans "Error while running pool." %}

+ {% if pool.exception %}
{{ pool.exception }}
{% endif %} +
+ {% endif %} + + + + + + + + + + + + + + + + + + {% for line in lines %} + + + + + + + + + + + + + + + + + {% endfor %} + +
{% trans "PK" %}{% trans "Invoice PK" %}{% trans "Label" %}{% trans "Slug" %}{% trans "Quantity" %}{% trans "Unit amount" %}{% trans "Total amount" %}{% trans "User" %}{% trans "Payer" %}{% trans "Status" %}
{{ line.pk }}{{ line.invoice_id|default:'' }}{{ line.label }}{{ line.slug }}{{ line.quantity }}{{ line.unit_amount }}{{ line.total_amount }}{{ line.user_external_id }}{{ line.payer_external_id }} + {{ line.get_status_display }} + {% if line.status != 'success' %}({{ line.get_error_display }}){% endif %} + {% if line.from_injected_line_id %}({% trans "Injected" %}){% endif %} + {% trans "see details" %}
+
{{ line.pricing_data|pprint }}
+
+ +{% endblock %} diff --git a/lingo/invoicing/urls.py b/lingo/invoicing/urls.py index 31c19de..342cbd3 100644 --- a/lingo/invoicing/urls.py +++ b/lingo/invoicing/urls.py @@ -74,6 +74,11 @@ urlpatterns = [ views.pool_detail, name='lingo-manager-invoicing-pool-detail', ), + path( + 'campaign//pool//journal/', + views.pool_journal, + name='lingo-manager-invoicing-pool-journal', + ), path( 'campaign//pool//delete/', views.pool_delete, diff --git a/lingo/invoicing/views.py b/lingo/invoicing/views.py index d2b9660..10b6ad1 100644 --- a/lingo/invoicing/views.py +++ b/lingo/invoicing/views.py @@ -297,6 +297,34 @@ class PoolDetailView(DetailView): model = Pool pk_url_kwarg = 'pool_pk' + def dispatch(self, request, *args, **kwargs): + self.campaign = get_object_or_404(Campaign, pk=kwargs['pk']) + return super().dispatch(request, *args, **kwargs) + + def get_queryset(self): + return self.campaign.pool_set.all() + + def get_context_data(self, **kwargs): + kwargs['object'] = self.campaign + kwargs['pool'] = self.object + line_model = InvoiceLine + if self.object.draft: + line_model = DraftInvoiceLine + all_lines = line_model.objects.filter(pool=self.object) + self.object.error_count = len([line for line in all_lines if line.status == 'error']) + self.object.warning_count = len([line for line in all_lines if line.status == 'warning']) + self.object.success_count = len([line for line in all_lines if line.status == 'success']) + return super().get_context_data(**kwargs) + + +pool_detail = PoolDetailView.as_view() + + +class PoolJournalView(DetailView): + template_name = 'lingo/invoicing/manager_pool_journal.html' + model = Pool + pk_url_kwarg = 'pool_pk' + def dispatch(self, request, *args, **kwargs): self.campaign = get_object_or_404(Campaign, pk=kwargs['pk']) return super().dispatch(request, *args, **kwargs) @@ -317,7 +345,7 @@ class PoolDetailView(DetailView): return super().get_context_data(**kwargs) -pool_detail = PoolDetailView.as_view() +pool_journal = PoolJournalView.as_view() class PoolAddView(FormView): diff --git a/tests/invoicing/manager/test_campaign.py b/tests/invoicing/manager/test_campaign.py index 70ab537..ea57d0c 100644 --- a/tests/invoicing/manager/test_campaign.py +++ b/tests/invoicing/manager/test_campaign.py @@ -441,7 +441,109 @@ def test_detail_pool(app, admin_user): assert 'tag-error' not in resp -def test_detail_pool_lines(app, admin_user): +def test_journal_pool(app, admin_user): + campaign = Campaign.objects.create( + date_start=datetime.date(2022, 9, 1), + date_end=datetime.date(2022, 10, 1), + date_issue=datetime.date(2022, 10, 31), + ) + campaign2 = Campaign.objects.create( + date_start=datetime.date(2022, 10, 1), + date_end=datetime.date(2022, 11, 1), + date_issue=datetime.date(2022, 11, 30), + ) + pool = Pool.objects.create( + campaign=campaign, + draft=True, + status='completed', + ) + + app = login(app) + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) + assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) in resp + + app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (0, pool.pk), status=404) + app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign2.pk, pool.pk), status=404) + app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, 0), status=404) + + pool.draft = False + pool.save() + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) + assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) not in resp + + pool.draft = True + pool.status = 'registered' + pool.save() + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) + assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) not in resp + + pool.status = 'running' + pool.save() + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) + assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) not in resp + + pool.status = 'failed' + pool.save() + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) + assert '/manage/invoicing/campaign/%s/pool/%s/delete/' % (campaign.pk, pool.pk) in resp + + line = DraftInvoiceLine.objects.create( + quantity=1, + unit_amount=1, + total_amount=1, + status='success', + pool=pool, + ) + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) + assert '1' 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 '1' 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 '1' in resp + assert 'tag-error' not in resp + line.delete() + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) + assert 'tag-success' not in resp + assert 'tag-warning' not in resp + assert 'tag-error' not in resp + + pool.draft = False + pool.save() + line = InvoiceLine.objects.create( + quantity=1, + unit_amount=1, + total_amount=1, + status='success', + pool=pool, + ) + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) + assert '1' 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 '1' 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 '1' in resp + assert 'tag-error' not in resp + + +def test_journal_pool_lines(app, admin_user): campaign = Campaign.objects.create( date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1), @@ -510,7 +612,7 @@ def test_detail_pool_lines(app, admin_user): return (' '.join([v.strip() for v in value.split('\n')])).strip() app = login(app) - resp = app.get('/manage/invoicing/campaign/%s/pool/%s/' % (campaign.pk, pool.pk)) + resp = app.get('/manage/invoicing/campaign/%s/pool/%s/journal/' % (campaign.pk, pool.pk)) assert format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[0].pk).text()) == 'Success' assert ( resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[0].pk).text().strip() -- 2.39.2 From 9f85afd377db060a797e76cb37eacb24c6bbe4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= Date: Thu, 19 Jan 2023 11:58:46 +0100 Subject: [PATCH 2/4] invoicing: add user_name on lines (#73514) --- lingo/invoicing/migrations/0009_user_name.py | 23 ++++++++++ lingo/invoicing/models.py | 7 ++- .../lingo/invoicing/manager_pool_journal.html | 2 +- lingo/invoicing/utils.py | 22 ++++++--- tests/invoicing/test_invoice_generation.py | 45 ++++++++++++++++--- 5 files changed, 80 insertions(+), 19 deletions(-) create mode 100644 lingo/invoicing/migrations/0009_user_name.py diff --git a/lingo/invoicing/migrations/0009_user_name.py b/lingo/invoicing/migrations/0009_user_name.py new file mode 100644 index 0000000..1a53209 --- /dev/null +++ b/lingo/invoicing/migrations/0009_user_name.py @@ -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, + ), + ] diff --git a/lingo/invoicing/models.py b/lingo/invoicing/models.py index 04b131f..a7c8e28 100644 --- a/lingo/invoicing/models.py +++ b/lingo/invoicing/models.py @@ -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: @@ -215,6 +213,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) diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html b/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html index d9369cd..afe049c 100644 --- a/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html +++ b/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html @@ -53,7 +53,7 @@ {{ line.quantity }} {{ line.unit_amount }} {{ line.total_amount }} - {{ line.user_external_id }} + {{ line.user_name }} ({{ line.user_external_id }}) {{ line.payer_external_id }} {{ line.get_status_display }} diff --git a/lingo/invoicing/utils.py b/lingo/invoicing/utils.py index f8ee024..17590fc 100644 --- a/lingo/invoicing/utils.py +++ b/lingo/invoicing/utils.py @@ -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()] -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: @@ -110,6 +114,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool 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, @@ -127,6 +132,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool 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, @@ -162,7 +168,8 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, pool 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 +182,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 +193,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 diff --git a/tests/invoicing/test_invoice_generation.py b/tests/invoicing/test_invoice_generation.py index 4426b8f..ff3c5e7 100644 --- a/tests/invoicing/test_invoice_generation.py +++ b/tests/invoicing/test_invoice_generation.py @@ -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, ) @@ -351,6 +363,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 +377,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 +447,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 == [ @@ -499,6 +514,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s 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', @@ -518,6 +534,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s 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', @@ -537,6 +554,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s 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', @@ -556,6 +574,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s 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', @@ -575,6 +594,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s 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 == {} @@ -589,6 +609,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s 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 +673,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 +699,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 +724,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 +737,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,6 +813,7 @@ 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 @@ -800,6 +826,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data 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', @@ -818,6 +845,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data 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', @@ -836,6 +864,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data 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', @@ -888,7 +917,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 +927,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 +935,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 +1049,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 @@ -1232,7 +1263,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, ) ] -- 2.39.2 From 49ebe18ee568041d45397b8633b7378cddd22f15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= Date: Thu, 19 Jan 2023 14:41:39 +0100 Subject: [PATCH 3/4] invoicing: display invoices and their lines on pool detail page (#73514) --- .../lingo/invoicing/manager_pool_detail.html | 15 +++ lingo/invoicing/views.py | 5 + tests/invoicing/manager/test_campaign.py | 107 ++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html b/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html index 5427631..cd07c7e 100644 --- a/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html +++ b/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html @@ -22,4 +22,19 @@ {% endblock %} {% block content %} +
+ {% for line in lines %} + {% ifchanged line.invoice_id %} + {% if not forloop.first %}{% endif %} +

+ {% blocktrans with number=line.invoice_id payer=line.invoice.payer amount=line.invoice.total_amount %}Invoice #{{ number }} addressed to {{ payer }}, amount {{ amount }}€{% endblocktrans %} +

+
    + {% endifchanged %} +
  • + #{{ line.pk }} {{ line.user_name }} - {{ line.label }} ({{ line.total_amount }}) +
  • + {% if forloop.last %}
{% endif %} + {% endfor %} +
{% endblock %} diff --git a/lingo/invoicing/views.py b/lingo/invoicing/views.py index 10b6ad1..4cd3efd 100644 --- a/lingo/invoicing/views.py +++ b/lingo/invoicing/views.py @@ -314,6 +314,11 @@ class PoolDetailView(DetailView): 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) diff --git a/tests/invoicing/manager/test_campaign.py b/tests/invoicing/manager/test_campaign.py index ea57d0c..917b826 100644 --- a/tests/invoicing/manager/test_campaign.py +++ b/tests/invoicing/manager/test_campaign.py @@ -441,6 +441,113 @@ def test_detail_pool(app, admin_user): assert 'tag-error' not in resp +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( + 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( + 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( + 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( + 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( + 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 - Label 11 (1.00)' % line11.pk + ) + assert ( + resp.pyquery('ul[data-invoice-id="%s"] li:nth-child(2)' % invoice1.pk).text() + == '#%s User1 Name1 - Label 13 (3.00)' % line13.pk + ) + assert ( + resp.pyquery('ul[data-invoice-id="%s"] li:nth-child(3)' % invoice1.pk).text() + == '#%s User2 Name2 - 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 - Label 21 (1.00)' % line21.pk + ) + + def test_journal_pool(app, admin_user): campaign = Campaign.objects.create( date_start=datetime.date(2022, 9, 1), -- 2.39.2 From cfa59aa4d18b208336972d72e8a7d5ab79e8ca09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= Date: Thu, 19 Jan 2023 15:31:14 +0100 Subject: [PATCH 4/4] invoicing: add event_date in line models (#73514) --- lingo/invoicing/migrations/0010_event_date.py | 25 +++++++++ lingo/invoicing/models.py | 1 + .../lingo/invoicing/manager_pool_detail.html | 2 +- .../lingo/invoicing/manager_pool_journal.html | 13 +++-- lingo/invoicing/utils.py | 3 ++ tests/invoicing/manager/test_campaign.py | 51 ++++++++++++------- tests/invoicing/test_invoice_generation.py | 24 +++++++++ tests/invoicing/test_models.py | 3 ++ 8 files changed, 100 insertions(+), 22 deletions(-) create mode 100644 lingo/invoicing/migrations/0010_event_date.py diff --git a/lingo/invoicing/migrations/0010_event_date.py b/lingo/invoicing/migrations/0010_event_date.py new file mode 100644 index 0000000..9c4efe6 --- /dev/null +++ b/lingo/invoicing/migrations/0010_event_date.py @@ -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, + ), + ] diff --git a/lingo/invoicing/models.py b/lingo/invoicing/models.py index a7c8e28..e75c5d4 100644 --- a/lingo/invoicing/models.py +++ b/lingo/invoicing/models.py @@ -206,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() diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html b/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html index cd07c7e..1bb74ca 100644 --- a/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html +++ b/lingo/invoicing/templates/lingo/invoicing/manager_pool_detail.html @@ -32,7 +32,7 @@
    {% endifchanged %}
  • - #{{ line.pk }} {{ line.user_name }} - {{ line.label }} ({{ line.total_amount }}) + #{{ line.pk }} {{ line.user_name }} - {{ line.event_date|date:"d/m/Y" }} - {{ line.label }} ({{ line.total_amount }})
  • {% if forloop.last %}
{% endif %} {% endfor %} diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html b/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html index afe049c..173d988 100644 --- a/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html +++ b/lingo/invoicing/templates/lingo/invoicing/manager_pool_journal.html @@ -32,8 +32,7 @@ {% trans "PK" %} {% trans "Invoice PK" %} - {% trans "Label" %} - {% trans "Slug" %} + {% trans "Event" %} {% trans "Quantity" %} {% trans "Unit amount" %} {% trans "Total amount" %} @@ -48,8 +47,11 @@ {{ line.pk }} {{ line.invoice_id|default:'' }} - {{ line.label }} - {{ line.slug }} + + {{ line.event_date|date:"d/m/Y" }} - {{ line.label }} +
+ ({{ line.slug }}) + {{ line.quantity }} {{ line.unit_amount }} {{ line.total_amount }} @@ -64,7 +66,10 @@ + {% trans "Pricing data:" %}
{{ line.pricing_data|pprint }}
+ {% trans "Event:" %} +
{{ line.event|pprint }}
{% endfor %} diff --git a/lingo/invoicing/utils.py b/lingo/invoicing/utils.py index 17590fc..862bbcd 100644 --- a/lingo/invoicing/utils.py +++ b/lingo/invoicing/utils.py @@ -108,6 +108,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, user } lines.append( DraftInvoiceLine( + event_date=event_date, slug=event_slug, label=serialized_event['label'], quantity=0, @@ -126,6 +127,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, user # XXX log all context ! lines.append( DraftInvoiceLine( + event_date=event_date, slug=event_slug, label=serialized_event['label'], quantity=1, @@ -163,6 +165,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, user 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, diff --git a/tests/invoicing/manager/test_campaign.py b/tests/invoicing/manager/test_campaign.py index 917b826..c453d64 100644 --- a/tests/invoicing/manager/test_campaign.py +++ b/tests/invoicing/manager/test_campaign.py @@ -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, @@ -461,6 +466,7 @@ def test_detail_pool_invoices(app, admin_user): ) line11 = DraftInvoiceLine.objects.create( + event_date=datetime.date(2022, 9, 1), invoice=invoice1, quantity=1, unit_amount=1, @@ -472,6 +478,7 @@ def test_detail_pool_invoices(app, admin_user): user_name='User1 Name1', ) line12 = DraftInvoiceLine.objects.create( + event_date=datetime.date(2022, 9, 2), invoice=invoice1, quantity=1, unit_amount=2, @@ -483,6 +490,7 @@ def test_detail_pool_invoices(app, admin_user): user_name='User2 Name2', ) line13 = DraftInvoiceLine.objects.create( + event_date=datetime.date(2022, 9, 3), invoice=invoice1, quantity=1, unit_amount=3, @@ -495,6 +503,7 @@ def test_detail_pool_invoices(app, admin_user): ) orphan_line = DraftInvoiceLine.objects.create( + event_date=datetime.date(2022, 9, 1), quantity=1, unit_amount=42, total_amount=42, @@ -506,6 +515,7 @@ def test_detail_pool_invoices(app, admin_user): ) line21 = DraftInvoiceLine.objects.create( + event_date=datetime.date(2022, 9, 1), invoice=invoice2, quantity=1, unit_amount=1, @@ -527,15 +537,15 @@ def test_detail_pool_invoices(app, admin_user): 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 - Label 11 (1.00)' % line11.pk + == '#%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 - Label 13 (3.00)' % line13.pk + == '#%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 - Label 12 (2.00)' % line12.pk + == '#%s User2 Name2 - 02/09/2022 - Label 12 (2.00)' % line12.pk ) assert ( resp.pyquery('h3[data-invoice-id="%s"]' % invoice2.pk).text() @@ -544,7 +554,7 @@ def test_detail_pool_invoices(app, admin_user): 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 - Label 21 (1.00)' % line21.pk + == '#%s User1 Name1 - 01/09/2022 - Label 21 (1.00)' % line21.pk ) @@ -595,6 +605,7 @@ def test_journal_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, @@ -626,6 +637,7 @@ def test_journal_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, @@ -666,6 +678,7 @@ def test_journal_pool_lines(app, admin_user): lines = [ DraftInvoiceLine.objects.create( + event_date=datetime.date(2022, 9, 1), invoice=invoice, quantity=1, unit_amount=1, @@ -673,6 +686,7 @@ def test_journal_pool_lines(app, admin_user): status='success', pool=pool, pricing_data={'foo': 'bar'}, + event={'event': 'foobar'}, ) ] errors = [ @@ -702,6 +716,7 @@ def test_journal_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, @@ -712,6 +727,7 @@ def test_journal_pool_lines(app, admin_user): 'error': error, 'error_details': error_details, }, + event={'event': 'foobar'}, ) ) @@ -723,7 +739,7 @@ def test_journal_pool_lines(app, admin_user): 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()) @@ -731,7 +747,7 @@ def test_journal_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()) @@ -739,7 +755,7 @@ def test_journal_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()) @@ -747,7 +763,7 @@ def test_journal_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()) @@ -755,7 +771,7 @@ def test_journal_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()) @@ -763,7 +779,7 @@ def test_journal_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()) @@ -771,7 +787,7 @@ def test_journal_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()) @@ -779,7 +795,7 @@ def test_journal_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()) @@ -787,7 +803,7 @@ def test_journal_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()) @@ -795,7 +811,7 @@ def test_journal_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()) @@ -803,7 +819,7 @@ def test_journal_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()) @@ -811,7 +827,7 @@ def test_journal_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()) @@ -819,7 +835,7 @@ def test_journal_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'}" ) @@ -842,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, diff --git a/tests/invoicing/test_invoice_generation.py b/tests/invoicing/test_invoice_generation.py index ff3c5e7..cf1cf23 100644 --- a/tests/invoicing/test_invoice_generation.py +++ b/tests/invoicing/test_invoice_generation.py @@ -279,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, @@ -331,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, @@ -350,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, @@ -508,6 +511,7 @@ 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 @@ -528,6 +532,7 @@ 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 @@ -548,6 +553,7 @@ 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 @@ -568,6 +574,7 @@ 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 @@ -588,6 +595,7 @@ 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 @@ -603,6 +611,7 @@ 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 @@ -820,6 +829,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data 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 @@ -839,6 +849,7 @@ 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 @@ -858,6 +869,7 @@ 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 @@ -893,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, @@ -1075,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, @@ -1085,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, @@ -1095,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, @@ -1105,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, @@ -1115,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, @@ -1125,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, @@ -1135,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, @@ -1145,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, @@ -1166,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, diff --git a/tests/invoicing/test_models.py b/tests/invoicing/test_models.py index 7790a31..eebc827 100644 --- a/tests/invoicing/test_models.py +++ b/tests/invoicing/test_models.py @@ -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, -- 2.39.2