lingo/tests/invoicing/manager/test_campaign.py

2984 lines
112 KiB
Python

import copy
import datetime
from unittest import mock
import pytest
from django.utils.formats import date_format
from django.utils.timezone import localtime
from lingo.agendas.chrono import ChronoError
from lingo.agendas.models import Agenda
from lingo.invoicing.models import (
Campaign,
DraftInvoice,
DraftInvoiceLine,
InjectedLine,
Invoice,
InvoiceLine,
InvoicePayment,
Payment,
Pool,
Regie,
)
from tests.utils import login
pytestmark = pytest.mark.django_db
def test_add_campaign(app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda = Agenda.objects.create(label='Foo bar', regie=regie)
Agenda.objects.create(label='Other Foo bar')
other_regie = Regie.objects.create(label='Other Foo')
Campaign.objects.create(
regie=other_regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
app = login(app)
resp = app.get('/manage/')
resp = resp.click('Invoicing')
resp = resp.click(href='/manage/invoicing/regies/')
resp = resp.click(href='/manage/invoicing/regie/%s/' % regie.pk)
resp = resp.click('New campaign')
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2022-09-01'
resp.form['date_end'] = '2022-08-01'
resp.form.get('agendas', 0).value = agenda.pk
assert resp.form['agendas'].options == [(str(agenda.pk), False, 'Foo bar')]
resp = resp.form.submit()
assert resp.context['form'].errors['date_end'] == ['End date must be greater than start date.']
resp.form['date_end'] = '2022-10-01'
resp = resp.form.submit()
campaign = Campaign.objects.latest('pk')
assert resp.location.endswith('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert campaign.regie == regie
assert campaign.label == 'Foo'
assert campaign.date_start == datetime.date(2022, 9, 1)
assert campaign.date_end == datetime.date(2022, 10, 1)
assert campaign.date_publication == campaign.date_end
assert campaign.date_payment_deadline == campaign.date_end
assert campaign.date_issue == campaign.date_end
assert campaign.date_debit == campaign.date_end
assert list(campaign.agendas.all()) == [agenda]
def test_add_campaign_overlapping_date_start(app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda1 = Agenda.objects.create(label='Foo bar 1', regie=regie)
agenda2 = Agenda.objects.create(label='Foo bar 2', regie=regie)
agenda3 = Agenda.objects.create(label='Foo bar 3', regie=regie)
campaign = Campaign.objects.create(
regie=regie,
label='Campaign',
date_start=datetime.date(2022, 9, 15),
date_end=datetime.date(2022, 10, 15),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign.agendas.add(agenda1, agenda2)
def add_agenda(resp):
select = copy.copy(resp.form.fields['agendas'][0])
select.id = 'id_agendas_1'
resp.form.fields['agendas'].append(select)
resp.form.field_order.append(('agendas', select))
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/add/' % regie.pk)
add_agenda(resp)
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2022-10-01'
resp.form['date_end'] = '2022-11-01'
resp.form.get('agendas', 0).value = agenda1.pk
resp.form.get('agendas', 1).value = agenda2.pk
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 1" has already a campaign overlapping this period.',
'Agenda "Foo bar 2" has already a campaign overlapping this period.',
]
# ok, no overlapping
resp.form['date_start'] = '2022-10-15'
resp.form.submit().follow()
new_campaign = Campaign.objects.latest('pk')
assert list(new_campaign.agendas.all()) == [agenda1, agenda2]
resp = app.get('/manage/invoicing/regie/%s/campaign/add/' % regie.pk)
add_agenda(resp)
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2021-10-01'
resp.form['date_end'] = '2022-11-01'
resp.form.get('agendas', 0).value = agenda1.pk
resp.form.get('agendas', 1).value = agenda2.pk
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 1" has already a campaign overlapping this period.',
'Agenda "Foo bar 2" has already a campaign overlapping this period.',
]
resp.form.get('agendas', 0).value = agenda3.pk
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 2" has already a campaign overlapping this period.'
]
resp.form.get('agendas', 1).value = agenda3.pk
# ok
resp.form.submit().follow()
new_campaign = Campaign.objects.latest('pk')
assert list(new_campaign.agendas.all()) == [agenda3]
def test_add_campaign_overlapping_date_end(app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda1 = Agenda.objects.create(label='Foo bar 1', regie=regie)
agenda2 = Agenda.objects.create(label='Foo bar 2', regie=regie)
agenda3 = Agenda.objects.create(label='Foo bar 3', regie=regie)
campaign = Campaign.objects.create(
regie=regie,
label='Campaign',
date_start=datetime.date(2022, 10, 15),
date_end=datetime.date(2022, 11, 15),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign.agendas.add(agenda1, agenda2)
def add_agenda(resp):
select = copy.copy(resp.form.fields['agendas'][0])
select.id = 'id_agendas_1'
resp.form.fields['agendas'].append(select)
resp.form.field_order.append(('agendas', select))
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/add/' % regie.pk)
add_agenda(resp)
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2022-10-01'
resp.form['date_end'] = '2022-11-01'
resp.form.get('agendas', 0).value = agenda1.pk
resp.form.get('agendas', 1).value = agenda2.pk
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 1" has already a campaign overlapping this period.',
'Agenda "Foo bar 2" has already a campaign overlapping this period.',
]
# ok, no overlapping
resp.form['date_end'] = '2022-10-15'
resp.form.submit().follow()
new_campaign = Campaign.objects.latest('pk')
assert list(new_campaign.agendas.all()) == [agenda1, agenda2]
resp = app.get('/manage/invoicing/regie/%s/campaign/add/' % regie.pk)
add_agenda(resp)
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2022-10-01'
resp.form['date_end'] = '2022-11-01'
resp.form.get('agendas', 0).value = agenda1.pk
resp.form.get('agendas', 1).value = agenda2.pk
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 1" has already a campaign overlapping this period.',
'Agenda "Foo bar 2" has already a campaign overlapping this period.',
]
resp.form.get('agendas', 0).value = agenda3.pk
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 2" has already a campaign overlapping this period.'
]
resp.form.get('agendas', 1).value = agenda3.pk
# ok
resp.form.submit().follow()
new_campaign = Campaign.objects.latest('pk')
assert list(new_campaign.agendas.all()) == [agenda3]
def test_detail_campaign(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
pool1 = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
pool2 = Pool.objects.create(
campaign=campaign,
draft=True,
status='registered',
)
app = login(app)
resp = app.get(url='/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool1.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
pool2.status = 'running'
pool2.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool1.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
pool2.status = 'failed'
pool2.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool1.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
pool3 = Pool.objects.create(
campaign=campaign,
draft=False,
status='completed',
)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool1.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool3.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) in resp
assert 'The last pool is invalid, please start a new pool.' not in resp
for status in ['running', 'failed', 'registered']:
pool3.status = status
pool3.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
pool3.status = 'completed'
pool3.draft = True
pool3.save()
campaign.invalid = True
campaign.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool1.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool3.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
assert 'The last pool is invalid, please start a new pool.' in resp
campaign.invalid = False
campaign.finalized = True
campaign.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool1.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool3.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
# orphan line
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
)
line = DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool1,
)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '<span class="meta meta-success">1</span>' in resp
assert 'meta-warning' not in resp
assert 'meta-error' not in resp
line.status = 'error'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' in resp
line.status = 'warning'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert 'meta-success' not in resp
assert '<span class="meta meta-warning">1</span>' in resp
assert 'meta-error' not in resp
line.delete()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert 'meta-error' not in resp
line = InvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool1,
)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert '<span class="meta meta-success">1</span>' in resp
assert 'meta-warning' not in resp
assert 'meta-error' not in resp
line.status = 'error'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' in resp
line.status = 'warning'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert 'meta-success' not in resp
assert '<span class="meta meta-warning">1</span>' in resp
assert 'meta-error' not in resp
line.status = 'error'
line.error_status = 'ignored'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' not in resp
line.error_status = 'fixed'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' not in resp
app.get('/manage/invoicing/regie/%s/campaign/%s/' % (0, campaign.pk), status=404)
def test_edit_campaign(app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda = Agenda.objects.create(label='Foo bar', regie=regie)
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk))
resp.form['label'] = 'Bar'
resp.form['date_start'] = '2022-09-30'
resp.form['date_end'] = '2022-08-01'
resp.form.get('agendas', 0).value = agenda.pk
resp = resp.form.submit()
assert resp.context['form'].errors['date_end'] == ['End date must be greater than start date.']
resp.form['date_end'] = '2022-10-02'
resp = resp.form.submit()
campaign.refresh_from_db()
assert campaign.date_start == datetime.date(2022, 9, 30)
assert campaign.date_end == datetime.date(2022, 10, 2)
assert campaign.invalid is False
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk))
resp = resp.form.submit()
campaign.refresh_from_db()
assert campaign.invalid is True
pool.status = 'failed'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk))
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (0, campaign.pk), status=404)
pool.status = 'registered'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk), status=404)
pool.status = 'running'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk), status=404)
pool.status = 'completed'
pool.draft = False
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk), status=404)
pool.draft = True
pool.save()
campaign.finalized = True
campaign.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk), status=404)
def test_edit_campaign_overlapping_date_start(app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda1 = Agenda.objects.create(label='Foo bar 1', regie=regie)
agenda2 = Agenda.objects.create(label='Foo bar 2', regie=regie)
agenda3 = Agenda.objects.create(label='Foo bar 3', regie=regie)
campaign1 = Campaign.objects.create(
regie=regie,
label='Campaign',
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign1.agendas.add(agenda1, agenda2)
campaign2 = Campaign.objects.create(
regie=regie,
label='Campaign',
date_start=datetime.date(2022, 9, 15),
date_end=datetime.date(2022, 10, 15),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign2.agendas.add(agenda1, agenda2)
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign1.pk))
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 1" has already a campaign overlapping this period.',
'Agenda "Foo bar 2" has already a campaign overlapping this period.',
]
# ok, no overlapping
resp.form['date_start'] = '2022-10-15'
resp.form.submit().follow()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign1.pk))
resp.form['date_start'] = '2021-10-01'
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 1" has already a campaign overlapping this period.',
'Agenda "Foo bar 2" has already a campaign overlapping this period.',
]
resp.form.get('agendas', 0).value = agenda3.pk
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 2" has already a campaign overlapping this period.'
]
resp.form.get('agendas', 1).value = agenda3.pk
# ok
resp.form.submit().follow()
assert list(campaign1.agendas.all()) == [agenda3]
def test_edit_campaign_overlapping_date_end(app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda1 = Agenda.objects.create(label='Foo bar 1', regie=regie)
agenda2 = Agenda.objects.create(label='Foo bar 2', regie=regie)
agenda3 = Agenda.objects.create(label='Foo bar 3', regie=regie)
campaign1 = Campaign.objects.create(
regie=regie,
label='Campaign',
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign1.agendas.add(agenda1, agenda2)
campaign2 = Campaign.objects.create(
regie=regie,
label='Campaign',
date_start=datetime.date(2022, 10, 15),
date_end=datetime.date(2022, 11, 15),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign2.agendas.add(agenda1, agenda2)
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign1.pk))
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 1" has already a campaign overlapping this period.',
'Agenda "Foo bar 2" has already a campaign overlapping this period.',
]
# ok, no overlapping
resp.form['date_end'] = '2022-10-15'
resp.form.submit().follow()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign1.pk))
resp.form['date_end'] = '2022-11-01'
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 1" has already a campaign overlapping this period.',
'Agenda "Foo bar 2" has already a campaign overlapping this period.',
]
resp.form.get('agendas', 0).value = agenda3.pk
resp = resp.form.submit()
assert resp.context['form'].non_field_errors() == [
'Agenda "Foo bar 2" has already a campaign overlapping this period.'
]
resp.form.get('agendas', 1).value = agenda3.pk
# ok
resp.form.submit().follow()
assert list(campaign1.agendas.all()) == [agenda3]
def test_edit_campaign_dates(app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda = Agenda.objects.create(label='Foo bar', regie=regie)
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
campaign.agendas.add(agenda)
pool1 = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
draft_invoice1 = DraftInvoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool1,
)
draft_invoice2 = DraftInvoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
date_debit=campaign.date_debit,
regie=regie,
pool=pool1,
payer_direct_debit=True,
)
pool2 = Pool.objects.create(
campaign=campaign,
draft=False,
status='completed',
)
invoice1 = Invoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool2,
)
invoice2 = Invoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
date_debit=campaign.date_debit,
regie=regie,
pool=pool2,
payer_direct_debit=True,
)
orphan_invoice = Invoice.objects.create(
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
regie=regie,
payer_direct_debit=True,
)
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk))
resp.form['date_publication'] = '2022-10-31'
resp.form['date_payment_deadline'] = '2022-10-30'
resp.form['date_issue'] = '2022-10-29'
resp.form['date_debit'] = '2022-12-15'
resp = resp.form.submit()
assert resp.context['form'].errors == {
'date_payment_deadline': ['Payment deadline must be greater than publication date.']
}
resp.form['date_publication'] = '2022-10-30'
resp.form['date_payment_deadline'] = '2022-10-31'
resp = resp.form.submit()
assert resp.context['form'].errors == {
'date_issue': ['Issue date must be greater than payment deadline.']
}
resp.form['date_publication'] = '2022-10-29'
resp.form['date_payment_deadline'] = '2022-10-30'
resp.form['date_issue'] = '2022-10-31'
resp.form.submit().follow()
campaign.refresh_from_db()
assert campaign.date_publication == datetime.date(2022, 10, 29)
assert campaign.date_payment_deadline == datetime.date(2022, 10, 30)
assert campaign.date_issue == datetime.date(2022, 10, 31)
assert campaign.date_debit == datetime.date(2022, 12, 15)
assert campaign.invalid is False # no impact
draft_invoice1.refresh_from_db()
assert draft_invoice1.date_publication == campaign.date_publication
assert draft_invoice1.date_payment_deadline == campaign.date_payment_deadline
assert draft_invoice1.date_issue == campaign.date_issue
assert draft_invoice1.date_debit is None
draft_invoice2.refresh_from_db()
assert draft_invoice2.date_publication == campaign.date_publication
assert draft_invoice2.date_payment_deadline == campaign.date_payment_deadline
assert draft_invoice2.date_issue == campaign.date_issue
assert draft_invoice2.date_debit == campaign.date_debit
invoice1.refresh_from_db()
assert invoice1.date_publication == campaign.date_publication
assert invoice1.date_payment_deadline == campaign.date_payment_deadline
assert invoice1.date_issue == campaign.date_issue
assert invoice1.date_debit is None
invoice2.refresh_from_db()
assert invoice2.date_publication == campaign.date_publication
assert invoice2.date_payment_deadline == campaign.date_payment_deadline
assert invoice2.date_issue == campaign.date_issue
assert invoice2.date_debit == campaign.date_debit
orphan_invoice.refresh_from_db()
assert orphan_invoice.date_publication == datetime.date(2022, 10, 1)
assert orphan_invoice.date_payment_deadline == datetime.date(2022, 10, 31)
assert orphan_invoice.date_issue == datetime.date(2022, 10, 31)
assert orphan_invoice.date_debit == datetime.date(2022, 11, 15)
app.get('/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk))
app.get('/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (0, campaign.pk), status=404)
campaign.finalized = True
campaign.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk), status=404)
def test_delete_campaign(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk))
resp = resp.form.submit()
assert Campaign.objects.count() == 0
assert resp.location.endswith('/manage/invoicing/regie/%s/#open:campaigns' % regie.pk)
campaign.save()
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
invoice = DraftInvoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
)
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk))
resp = resp.form.submit()
assert Campaign.objects.count() == 0
campaign.save()
pool.status = 'failed'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk))
app.get('/manage/invoicing/regie/%s/campaign/%s/delete/' % (0, campaign.pk), status=404)
pool.status = 'registered'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk), status=404)
pool.status = 'running'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk), status=404)
pool.status = 'completed'
pool.draft = False
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk), status=404)
def test_add_pool(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
invalid=True,
)
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk))
with mock.patch.object(Campaign, 'generate', autospec=True) as mock_generate:
resp = resp.form.submit()
assert resp.location.endswith(
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
)
assert mock_generate.call_args_list == [mock.call(campaign)]
campaign.refresh_from_db()
assert campaign.invalid is False
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='failed',
)
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk))
pool.status = 'completed'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk))
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (0, campaign.pk), status=404)
pool.status = 'registered'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk), status=404)
pool.status = 'running'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk), status=404)
pool.status = 'completed'
pool.draft = False
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk), status=404)
pool.draft = True
pool.save()
campaign.finalized = True
campaign.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk), status=404)
@mock.patch('lingo.invoicing.views.campaign.unlock_events_check')
def test_unlock_check(mock_unlock, app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda = Agenda.objects.create(label='Foo bar', regie=regie)
agenda2 = Agenda.objects.create(label='Foo bar 2', regie=regie)
Agenda.objects.create(label='Foo bar 3', regie=regie)
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
app = login(app)
# no agendas
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk))
resp = resp.form.submit()
assert resp.location.endswith(
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
)
assert mock_unlock.call_args_list == []
campaign.refresh_from_db()
assert campaign.invalid is True
# with agendas
campaign.invalid = False
campaign.save()
campaign.agendas.add(agenda, agenda2)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk))
resp = resp.form.submit()
assert resp.location.endswith(
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
)
assert mock_unlock.call_args_list == [
mock.call(
agenda_slugs=['foo-bar', 'foo-bar-2'],
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
)
]
campaign.refresh_from_db()
assert campaign.invalid is True
# ChronoError
campaign.invalid = False
campaign.save()
mock_unlock.side_effect = ChronoError('foo baz')
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk))
resp = resp.form.submit().follow()
assert 'Fail to unlock events check: foo baz' in resp
campaign.invalid = False
campaign.save()
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='failed',
)
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk))
pool.status = 'completed'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk))
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (0, campaign.pk), status=404)
pool.status = 'registered'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk), status=404)
pool.status = 'running'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk), status=404)
pool.status = 'completed'
pool.draft = False
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk), status=404)
pool.draft = True
pool.save()
campaign.invalid = True
campaign.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk), status=404)
campaign.invalid = False
campaign.finalized = True
campaign.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk), status=404)
@mock.patch('lingo.invoicing.views.campaign.mark_events_invoiced')
def test_finalize(mock_invoiced, app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda = Agenda.objects.create(label='Foo bar', regie=regie)
agenda2 = Agenda.objects.create(label='Foo bar 2', regie=regie)
Agenda.objects.create(label='Foo bar 3', regie=regie)
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=False,
status='completed',
)
app = login(app)
# no agendas
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk))
resp = resp.form.submit()
assert resp.location.endswith(
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
)
assert mock_invoiced.call_args_list == []
campaign.refresh_from_db()
assert campaign.finalized is True
# with agendas
campaign.finalized = False
campaign.save()
campaign.agendas.add(agenda, agenda2)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk))
resp = resp.form.submit()
assert resp.location.endswith(
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
)
assert mock_invoiced.call_args_list == [
mock.call(
agenda_slugs=['foo-bar', 'foo-bar-2'],
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
)
]
campaign.refresh_from_db()
assert campaign.finalized is True
# ChronoError
campaign.finalized = False
campaign.save()
mock_invoiced.side_effect = ChronoError('foo baz')
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk))
resp = resp.form.submit().follow()
assert 'Fail to mark events as invoiced: foo baz' in resp
campaign.refresh_from_db()
assert campaign.finalized is False
pool.status = 'failed'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
pool.status = 'completed'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk))
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (0, campaign.pk), status=404)
pool.status = 'registered'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
pool.status = 'running'
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
pool.status = 'completed'
pool.draft = True
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
pool.draft = False
pool.save()
campaign.invalid = True
campaign.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
campaign.invalid = False
campaign.finalized = True
campaign.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
def test_promote_pool(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
app = login(app)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
)
with mock.patch.object(Pool, 'promote', autospec=True) as mock_promote:
resp = resp.form.submit()
assert resp.location.endswith(
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
)
assert mock_promote.call_args_list == [mock.call(pool)]
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (0, campaign.pk, pool.pk), status=404)
pool.status = 'registered'
pool.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
pool.status = 'running'
pool.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
pool.status = 'failed'
pool.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
pool.status = 'completed'
pool.draft = False
pool.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
pool.draft = True
pool.save()
campaign.invalid = True
campaign.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
campaign.invalid = False
campaign.finalized = True
campaign.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
campaign.finalized = False
campaign.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
)
resp.form.submit()
assert Pool.objects.filter(draft=False).exists()
# not the last
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
def test_detail_pool(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
campaign2 = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk) in resp
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk) in resp
)
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (0, campaign.pk, pool.pk), status=404)
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, 0, pool.pk), status=404)
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign2.pk, pool.pk), status=404)
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, 0), status=404)
pool.draft = False
pool.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk) in resp
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
pool.draft = True
pool.status = 'registered'
pool.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
pool.status = 'running'
pool.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
pool.status = 'failed'
pool.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk) in resp
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
pool.status = 'completed'
pool.save()
campaign.invalid = True
campaign.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk) in resp
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
campaign.invalid = False
campaign.finalized = True
campaign.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
campaign.finalized = False
campaign.save()
pool2 = Pool.objects.create(
campaign=pool.campaign,
status='running',
)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
not in resp
) # not the last
pool2.status = 'completed'
pool2.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk) in resp
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
not in resp
) # not the last
# orphan line
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
)
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/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert '<span class="meta meta-success">1</span>' in resp
assert 'meta-warning' not in resp
assert 'meta-error' not in resp
line.status = 'error'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' in resp
line.status = 'warning'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert 'meta-success' not in resp
assert '<span class="meta meta-warning">1</span>' in resp
assert 'meta-error' not in resp
line.delete()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert 'meta-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/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert '<span class="meta meta-success">1</span>' in resp
assert 'meta-warning' not in resp
assert 'meta-error' not in resp
line.status = 'error'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' in resp
line.status = 'warning'
line.save()
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert 'meta-success' not in resp
assert '<span class="meta meta-warning">1</span>' in resp
assert 'meta-error' not in resp
@pytest.mark.parametrize('draft', [True, False])
def test_detail_pool_invoices(app, admin_user, draft):
invoice_model = DraftInvoice if draft else Invoice
line_model = DraftInvoiceLine if draft else InvoiceLine
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=draft,
status='completed',
)
invoice1 = invoice_model.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:1',
payer_first_name='First1',
payer_last_name='Name1',
payer_demat=True,
payer_direct_debit=False,
)
invoice2 = invoice_model.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:2',
payer_first_name='First2',
payer_last_name='Name2',
payer_demat=False,
payer_direct_debit=True,
)
invoice3 = invoice_model.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:3',
payer_first_name='First3',
payer_last_name='Name3',
payer_demat=False,
payer_direct_debit=True,
)
orphan_invoice = invoice_model.objects.create(
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
regie=regie,
)
if not draft:
invoice1.set_number()
invoice1.save()
invoice2.set_number()
invoice2.save()
invoice3.set_number()
invoice3.save()
orphan_invoice.set_number()
orphan_invoice.save()
line11 = line_model.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_first_name='User1',
user_last_name='Name1',
)
line12 = line_model.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_first_name='User2',
user_last_name='Name2',
)
line13 = line_model.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_first_name='User1',
user_last_name='Name1',
)
if not draft:
payment1 = Payment.objects.create(
regie=regie,
amount=1,
payment_type='cash',
)
invoice_payment1 = InvoicePayment.objects.create(
payment=payment1,
invoice=invoice1,
amount=1,
)
invoice1.refresh_from_db()
assert invoice1.remaining_amount == 5
assert invoice1.paid_amount == 1
orphan_line = line_model.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_first_name='User1',
user_last_name='Name1',
)
line_model.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=42,
total_amount=42,
status='success',
label='Orphan',
user_external_id='user:1',
user_first_name='User1',
user_last_name='Name1',
invoice=orphan_invoice,
)
line21 = line_model.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_first_name='User1',
user_last_name='Name1',
)
if not draft:
payment2 = Payment.objects.create(
regie=regie,
amount=1,
payment_type='cash',
)
invoice_payment2 = InvoicePayment.objects.create(
payment=payment2,
invoice=invoice2,
amount=1,
)
invoice2.refresh_from_db()
assert invoice2.remaining_amount == 0
assert invoice2.paid_amount == 1
line31 = line_model.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice3,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
label='Label 31',
user_external_id='user:1',
user_first_name='User1',
user_last_name='Name1',
)
invoice3.refresh_from_db()
if not draft:
assert invoice3.remaining_amount == 1
assert invoice3.paid_amount == 0
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
assert '#%s' % orphan_line.pk not in resp
if draft:
assert (
resp.pyquery('li[data-invoice-id="%s"]' % invoice1.pk).text()
== 'Invoice TEMPORARY-%s addressed to First1 Name1 (payer:1), amount 6.00€, demat: yes, direct debit: no - download'
% invoice1.pk
)
else:
assert resp.pyquery(
'li[data-invoice-id="%s"]' % invoice1.pk
).text() == 'Partially paid Invoice F%02d-%s-0000001 addressed to First1 Name1 (payer:1), amount 6.00€, demat: yes, direct debit: no - download' % (
regie.pk,
invoice1.created_at.strftime('%y-%m'),
)
lines_url = resp.pyquery('li[data-invoice-id="%s"]' % invoice1.pk).attr('data-invoice-lines-url')
assert lines_url == '/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/invoice/%s/lines/' % (
regie.pk,
campaign.pk,
pool.pk,
invoice1.pk,
)
lines_resp = app.get(lines_url)
if draft:
assert len(lines_resp.pyquery('li')) == 3
else:
assert len(lines_resp.pyquery('li')) == 6
assert (
lines_resp.pyquery('li:nth-child(1)').text()
== '#%s User1 Name1 (user:1) - 01/09/2022 - Label 11 (1.00)' % line11.pk
)
assert (
lines_resp.pyquery('li:nth-child(2)').text()
== '#%s User1 Name1 (user:1) - 03/09/2022 - Label 13 (3.00)' % line13.pk
)
assert (
lines_resp.pyquery('li:nth-child(3)').text()
== '#%s User2 Name2 (user:2) - 02/09/2022 - Label 12 (2.00)' % line12.pk
)
if not draft:
assert lines_resp.pyquery(
'li:nth-child(4)'
).text() == '%s - Payment type: Cash - Amount: 1.00€' % date_format(
localtime(invoice_payment1.created_at), 'DATETIME_FORMAT'
)
assert lines_resp.pyquery('li:nth-child(5)').text() == 'Paid amount: 1.00€'
assert lines_resp.pyquery('li:nth-child(6)').text() == 'Remaining amount: 5.00€'
if draft:
assert (
resp.pyquery('li[data-invoice-id="%s"]' % invoice2.pk).text()
== 'Invoice TEMPORARY-%s addressed to First2 Name2 (payer:2), amount 1.00€, demat: no, direct debit: yes - download'
% invoice2.pk
)
else:
assert resp.pyquery(
'li[data-invoice-id="%s"]' % invoice2.pk
).text() == 'Paid Invoice F%02d-%s-0000002 addressed to First2 Name2 (payer:2), amount 1.00€, demat: no, direct debit: yes - download' % (
regie.pk,
invoice2.created_at.strftime('%y-%m'),
)
lines_url = resp.pyquery('li[data-invoice-id="%s"]' % invoice2.pk).attr('data-invoice-lines-url')
assert lines_url == '/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/invoice/%s/lines/' % (
regie.pk,
campaign.pk,
pool.pk,
invoice2.pk,
)
lines_resp = app.get(lines_url)
if draft:
assert len(lines_resp.pyquery('li')) == 1
else:
assert len(lines_resp.pyquery('li')) == 3
assert (
lines_resp.pyquery('li:nth-child(1)').text()
== '#%s User1 Name1 (user:1) - 01/09/2022 - Label 21 (1.00)' % line21.pk
)
if not draft:
assert lines_resp.pyquery(
'li:nth-child(2)'
).text() == '%s - Payment type: Cash - Amount: 1.00€' % date_format(
localtime(invoice_payment2.created_at), 'DATETIME_FORMAT'
)
assert lines_resp.pyquery('li:nth-child(3)').text() == 'Paid amount: 1.00€'
if draft:
assert (
resp.pyquery('li[data-invoice-id="%s"]' % invoice3.pk).text()
== 'Invoice TEMPORARY-%s addressed to First3 Name3 (payer:3), amount 1.00€, demat: no, direct debit: yes - download'
% invoice3.pk
)
else:
assert resp.pyquery(
'li[data-invoice-id="%s"]' % invoice3.pk
).text() == 'Invoice F%02d-%s-0000003 addressed to First3 Name3 (payer:3), amount 1.00€, demat: no, direct debit: yes - download' % (
regie.pk,
invoice3.created_at.strftime('%y-%m'),
)
lines_url = resp.pyquery('li[data-invoice-id="%s"]' % invoice3.pk).attr('data-invoice-lines-url')
assert lines_url == '/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/invoice/%s/lines/' % (
regie.pk,
campaign.pk,
pool.pk,
invoice3.pk,
)
lines_resp = app.get(lines_url)
if draft:
assert len(lines_resp.pyquery('li')) == 1
else:
assert len(lines_resp.pyquery('li')) == 2
assert (
lines_resp.pyquery('li:nth-child(1)').text()
== '#%s User1 Name1 (user:1) - 01/09/2022 - Label 31 (1.00)' % line31.pk
)
if not draft:
assert lines_resp.pyquery('li:nth-child(2)').text() == 'Remaining amount: 1.00€'
# test filters
if draft:
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'pk': invoice1.pk},
)
assert len(resp.pyquery('li.invoice')) == 1
else:
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'number': invoice1.formatted_number},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'number': invoice1.created_at.strftime('%y-%m')},
)
assert len(resp.pyquery('li.invoice')) == 3
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_external_id': 'payer:1'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_external_id': 'payer:2'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_first_name': 'first'},
)
assert len(resp.pyquery('li.invoice')) == 3
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_first_name': 'first1'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_last_name': 'name'},
)
assert len(resp.pyquery('li.invoice')) == 3
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_last_name': 'name1'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_demat': True},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_direct_debit': True},
)
assert len(resp.pyquery('li.invoice')) == 2
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_external_id': 'user:1'},
)
assert len(resp.pyquery('li.invoice')) == 3
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_external_id': 'user:2'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_first_name': 'user'},
)
assert len(resp.pyquery('li.invoice')) == 3
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_first_name': 'user2'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_last_name': 'name'},
)
assert len(resp.pyquery('li.invoice')) == 3
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'user_last_name': 'name1'},
)
assert len(resp.pyquery('li.invoice')) == 3
if not draft:
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'paid': 'yes'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'paid': 'partially'},
)
assert len(resp.pyquery('li.invoice')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk),
params={'paid': 'no'},
)
assert len(resp.pyquery('li.invoice')) == 1
@pytest.mark.parametrize('draft', [True, False])
def test_invoice_pdf(app, admin_user, draft):
invoice_model = DraftInvoice if draft else Invoice
line_model = DraftInvoiceLine if draft else InvoiceLine
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=draft,
status='completed',
)
invoice = invoice_model.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:1',
payer_first_name='First1',
payer_last_name='Name1',
payer_demat=True,
payer_direct_debit=False,
)
if not draft:
invoice.set_number()
invoice.save()
line_model.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
label='Label 11',
user_external_id='user:1',
user_first_name='User1',
user_last_name='Name1',
)
line_model.objects.create(
event_date=datetime.date(2022, 9, 2),
invoice=invoice,
quantity=1,
unit_amount=2,
total_amount=2,
status='success',
pool=pool,
label='Label 12',
user_external_id='user:2',
user_first_name='User2',
user_last_name='Name2',
)
line_model.objects.create(
event_date=datetime.date(2022, 9, 3),
invoice=invoice,
quantity=1,
unit_amount=3,
total_amount=3,
status='success',
pool=pool,
label='Label 13',
user_external_id='user:1',
user_first_name='User1',
user_last_name='Name1',
)
app = login(app)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/invoice/%s/pdf/?html'
% (regie.pk, campaign.pk, pool.pk, invoice.pk)
)
assert resp.pyquery('address#from').text() == 'Foo'
assert resp.pyquery('address#to').text() == 'First1 Name1'
if draft:
assert resp.pyquery('dl#informations').text() == 'Invoice number\nTEMPORARY-%s\nDate\n%s' % (
invoice.pk,
date_format(localtime(invoice.created_at), 'DATE_FORMAT'),
)
else:
assert resp.pyquery('dl#informations').text() == 'Invoice number\nF%02d-%s-0000001\nDate\n%s' % (
regie.pk,
invoice.created_at.strftime('%y-%m'),
date_format(localtime(invoice.created_at), 'DATE_FORMAT'),
)
assert len(resp.pyquery('table#lines tbody tr')) == 3
assert (
resp.pyquery('table#lines tbody tr:nth-child(1)').text() == 'Label 11\nUser1 Name1\n1.00\n1.0\n1.00'
)
assert (
resp.pyquery('table#lines tbody tr:nth-child(2)').text() == 'Label 13\nUser1 Name1\n3.00\n1.0\n3.00'
)
assert (
resp.pyquery('table#lines tbody tr:nth-child(3)').text() == 'Label 12\nUser2 Name2\n2.00\n1.0\n2.00'
)
assert resp.pyquery('table#total tbody').text() == 'Oct. 31, 2022\n6.00'
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/invoice/%s/pdf/?html'
% (0, campaign.pk, pool.pk, invoice.pk),
status=404,
)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/invoice/%s/pdf/?html'
% (regie.pk, 0, pool.pk, invoice.pk),
status=404,
)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/invoice/%s/pdf/?html'
% (regie.pk, campaign.pk, 0, invoice.pk),
status=404,
)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/invoice/%s/pdf/?html'
% (regie.pk, campaign.pk, pool.pk, 0),
status=404,
)
other_regie = Regie.objects.create(label='Foo')
other_campaign = Campaign.objects.create(
regie=other_regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
other_pool = Pool.objects.create(
campaign=other_campaign,
draft=draft,
status='completed',
)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/invoice/%s/pdf/?html'
% (other_regie.pk, campaign.pk, pool.pk, invoice.pk),
status=404,
)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/invoice/%s/pdf/?html'
% (regie.pk, other_campaign.pk, pool.pk, invoice.pk),
status=404,
)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/invoice/%s/pdf/?html'
% (regie.pk, campaign.pk, other_pool.pk, invoice.pk),
status=404,
)
def test_journal_pool(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
campaign2 = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
app = login(app)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk) in resp
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (0, campaign.pk, pool.pk), status=404)
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, 0, pool.pk), status=404)
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign2.pk, pool.pk),
status=404,
)
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, 0), status=404
)
pool.draft = False
pool.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk) in resp
pool.draft = True
pool.status = 'registered'
pool.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
pool.status = 'running'
pool.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert (
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
not in resp
)
pool.status = 'failed'
pool.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk) in resp
# orphan line
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
)
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/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert '<span class="meta meta-success">1</span>' in resp
assert 'meta-warning' not in resp
assert 'meta-error' not in resp
line.status = 'error'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' in resp
line.status = 'warning'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert 'meta-success' not in resp
assert '<span class="meta meta-warning">1</span>' in resp
assert 'meta-error' not in resp
line.delete()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert 'meta-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/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert '<span class="meta meta-success">1</span>' in resp
assert 'meta-warning' not in resp
assert 'meta-error' not in resp
line.status = 'error'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' in resp
line.status = 'warning'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert 'meta-success' not in resp
assert '<span class="meta meta-warning">1</span>' in resp
assert 'meta-error' not in resp
line.status = 'error'
line.error_status = 'ignored'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' not in resp
line.error_status = 'fixed'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert 'meta-success' not in resp
assert 'meta-warning' not in resp
assert '<span class="meta meta-error">1</span>' not in resp
@pytest.mark.parametrize('draft', [True, False])
def test_journal_pool_lines(app, admin_user, draft):
invoice_model = DraftInvoice if draft else Invoice
line_model = DraftInvoiceLine if draft else InvoiceLine
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=draft,
status='completed',
)
invoice1 = invoice_model.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:1',
)
invoice2 = invoice_model.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:2',
)
orphan_invoice = invoice_model.objects.create(
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
regie=regie,
)
if not draft:
invoice1.set_number()
invoice1.save()
invoice2.set_number()
invoice2.save()
orphan_invoice.set_number()
orphan_invoice.save()
line_model.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=42,
total_amount=42,
status='success',
label='Orphan',
user_external_id='user:1',
user_first_name='User1',
user_last_name='Name1',
invoice=orphan_invoice,
)
lines = [
line_model.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice1,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
pricing_data={'foo': 'bar'},
event={'event': 'foobar'},
user_external_id='user:1',
user_first_name='First1',
user_last_name='Last1',
payer_external_id='payer:1',
payer_first_name='First1',
payer_last_name='Last1',
payer_demat=True,
payer_direct_debit=False,
),
]
errors = [
('AgendaPricingNotFound', {}),
('CriteriaConditionNotFound', {'category': 'cat-foo'}),
('MultipleDefaultCriteriaCondition', {'category': 'cat-foo'}),
('PricingDataError', {'criterias': {'qf': 'qf-1', 'foo': 'bar'}}),
('PricingDataFormatError', {'pricing': 'foobar', 'wanted': 'decimal'}),
('PricingUnknownCheckStatusError', {'status': 'unknown'}),
('PricingEventNotCheckedError', {}),
('PricingBookingNotCheckedError', {}),
('PricingMultipleBookingError', {}),
('PricingBookingCheckTypeError', {'reason': 'not-found'}),
(
'PricingBookingCheckTypeError',
{
'check_type_group': 'foo-bar',
'check_type': 'foo-reason',
'reason': 'not-configured',
},
),
(
'PricingBookingCheckTypeError',
{'check_type_group': 'foo-bar', 'check_type': 'foo-reason', 'reason': 'wrong-kind'},
),
('PayerError', {'reason': 'empty-template'}),
('PayerError', {'reason': 'empty-result'}),
('PayerError', {'reason': 'syntax-error'}),
('PayerError', {'reason': 'variable-error'}),
('PayerDataError', {'key': 'foo', 'reason': 'empty-template'}),
('PayerDataError', {'key': 'foo', 'reason': 'empty-result'}),
('PayerDataError', {'key': 'foo', 'reason': 'syntax-error'}),
('PayerDataError', {'key': 'foo', 'reason': 'variable-error'}),
('PayerDataError', {'key': 'foo', 'reason': 'not-a-boolean'}),
]
for error, error_details in errors:
lines.append(
line_model.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
status='warning' if error == 'AgendaPricingNotFound' else 'error',
pool=pool,
pricing_data={
'error': error,
'error_details': error_details,
},
event={'event': 'foobar'},
user_external_id='user:1',
user_first_name='First1',
user_last_name='Last1',
payer_external_id='payer:2',
payer_first_name='First2',
payer_last_name='Last2',
payer_demat=False,
payer_direct_debit=True,
)
)
if not draft:
lines[-1].error_status = 'ignored'
lines[-1].save()
lines[-2].error_status = 'fixed'
lines[-2].save()
injected_line = InjectedLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
user_external_id='user:2',
payer_external_id='payer:2',
payer_first_name='First2',
payer_last_name='Last2',
payer_demat=False,
payer_direct_debit=True,
regie=regie,
)
lines.append(
line_model.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice2,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
pricing_data={'foo': 'bar'},
event={'event': 'foobar2'},
user_external_id='user:2',
user_first_name='First2',
user_last_name='Last2',
payer_external_id='payer:2',
payer_first_name='First2',
payer_last_name='Last2',
payer_demat=False,
payer_direct_debit=True,
from_injected_line=injected_line,
),
)
def format_status(value):
return (' '.join([v.strip() for v in value.split('\n')])).strip()
if draft:
error_links = ''
else:
error_links = ' ignore - mark as fixed'
app = login(app)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, 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'} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[1].pk).text())
== 'Warning (Agenda pricing not found)'
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[1].pk).text().strip()
== "{'error': 'AgendaPricingNotFound', 'error_details': {}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[2].pk).text())
== 'Error (No matching criteria for category: cat-foo)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[2].pk).text().strip()
== "{'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())
== 'Error (Multiple default criteria found for category: cat-foo)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[3].pk).text().strip()
== "{'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())
== 'Error (Impossible to determine a pricing for criterias: qf-1 (category: qf), bar (category: foo))%s'
% error_links
)
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'}}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[5].pk).text())
== 'Error (Pricing is not a decimal: foobar)%s' % error_links
)
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'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[6].pk).text())
== 'Error (Unknown check status: unknown)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[6].pk).text().strip()
== "{'error': 'PricingUnknownCheckStatusError', 'error_details': {'status': 'unknown'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[7].pk).text())
== 'Error (Event is not checked)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[7].pk).text().strip()
== "{'error': 'PricingEventNotCheckedError', 'error_details': {}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[8].pk).text())
== 'Error (Booking is not checked)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[8].pk).text().strip()
== "{'error': 'PricingBookingNotCheckedError', 'error_details': {}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[9].pk).text())
== 'Error (Multiple booking found)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[9].pk).text().strip()
== "{'error': 'PricingMultipleBookingError', 'error_details': {}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[10].pk).text())
== 'Error (Check type error: not found)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[10].pk).text().strip()
== "{'error': 'PricingBookingCheckTypeError', 'error_details': {'reason': 'not-found'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[11].pk).text())
== 'Error (Check type error: pricing not configured (group: foo-bar, check type: foo-reason))%s'
% error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[11].pk).text().strip()
== "{'error': 'PricingBookingCheckTypeError', 'error_details': {'check_type': 'foo-reason', "
"'check_type_group': 'foo-bar', 'reason': 'not-configured'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[12].pk).text())
== 'Error (Check type error: wrong kind (group: foo-bar, check type: foo-reason))%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[12].pk).text().strip()
== "{'error': 'PricingBookingCheckTypeError', 'error_details': {'check_type': 'foo-reason', "
"'check_type_group': 'foo-bar', 'reason': 'wrong-kind'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[13].pk).text())
== 'Error (Impossible to determine payer: Template is empty)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[13].pk).text().strip()
== "{'error': 'PayerError', 'error_details': {'reason': 'empty-template'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[14].pk).text())
== 'Error (Impossible to determine payer: Result is empty)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[14].pk).text().strip()
== "{'error': 'PayerError', 'error_details': {'reason': 'empty-result'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[15].pk).text())
== 'Error (Impossible to determine payer: Syntax error)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[15].pk).text().strip()
== "{'error': 'PayerError', 'error_details': {'reason': 'syntax-error'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[16].pk).text())
== 'Error (Impossible to determine payer: Variable error)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[16].pk).text().strip()
== "{'error': 'PayerError', 'error_details': {'reason': 'variable-error'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[17].pk).text())
== 'Error (Impossible to get payer foo: Template is empty)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[17].pk).text().strip()
== "{'error': 'PayerDataError', 'error_details': {'key': 'foo', 'reason': 'empty-template'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[18].pk).text())
== 'Error (Impossible to get payer foo: Result is empty)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[18].pk).text().strip()
== "{'error': 'PayerDataError', 'error_details': {'key': 'foo', 'reason': 'empty-result'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[19].pk).text())
== 'Error (Impossible to get payer foo: Syntax error)%s' % error_links
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[19].pk).text().strip()
== "{'error': 'PayerDataError', 'error_details': {'key': 'foo', 'reason': 'syntax-error'}} {'event': 'foobar'}"
)
if draft:
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[20].pk).text())
== 'Error (Impossible to get payer foo: Variable error)%s' % error_links
)
else:
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[20].pk).text())
== 'Fixed (Impossible to get payer foo: Variable error) reset'
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[20].pk).text().strip()
== "{'error': 'PayerDataError', 'error_details': {'key': 'foo', 'reason': 'variable-error'}} {'event': 'foobar'}"
)
if draft:
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[21].pk).text())
== 'Error (Impossible to get payer foo: Result is not a boolean)%s' % error_links
)
else:
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[21].pk).text())
== 'Ignored (Impossible to get payer foo: Result is not a boolean) reset'
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[21].pk).text().strip()
== "{'error': 'PayerDataError', 'error_details': {'key': 'foo', 'reason': 'not-a-boolean'}} {'event': 'foobar'}"
)
assert (
format_status(resp.pyquery('tr[data-line-id="%s"] td.status' % lines[22].pk).text())
== 'Success (Injected)'
)
assert (
resp.pyquery('tr[data-details-for-line-id="%s"] td pre' % lines[22].pk).text().strip()
== "{'foo': 'bar'} {'event': 'foobar2'}"
)
# test filters
if draft:
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'invoice_id': invoice1.pk},
)
assert len(resp.pyquery('tr td.status')) == 1
else:
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'invoice_number': invoice1.formatted_number},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'invoice_number': invoice1.created_at.strftime('%y-%m')},
)
assert len(resp.pyquery('tr td.status')) == 2
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'pk': lines[0].pk},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_external_id': 'payer:1'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_external_id': 'payer:2'},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_first_name': 'first'},
)
assert len(resp.pyquery('tr td.status')) == 23
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_first_name': 'first1'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_last_name': 'last'},
)
assert len(resp.pyquery('tr td.status')) == 23
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_last_name': 'last1'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_demat': True},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'payer_direct_debit': True},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_external_id': 'user:1'},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_external_id': 'user:2'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_first_name': 'first'},
)
assert len(resp.pyquery('tr td.status')) == 23
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_first_name': 'first1'},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_last_name': 'last'},
)
assert len(resp.pyquery('tr td.status')) == 23
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'user_last_name': 'last1'},
)
assert len(resp.pyquery('tr td.status')) == 22
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'status': 'success'},
)
assert len(resp.pyquery('tr td.status')) == 2
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'status': 'success_injected'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'status': 'warning'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'status': 'error'},
)
assert len(resp.pyquery('tr td.status')) == 20
if not draft:
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'status': 'error_todo'},
)
assert len(resp.pyquery('tr td.status')) == 18
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'status': 'error_ignored'},
)
assert len(resp.pyquery('tr td.status')) == 1
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk),
params={'status': 'error_fixed'},
)
assert len(resp.pyquery('tr td.status')) == 1
@pytest.mark.parametrize('draft', [True, False])
def test_journal_pool_lines_link(settings, app, admin_user, draft):
settings.KNOWN_SERVICES = {}
line_model = DraftInvoiceLine if draft else InvoiceLine
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=draft,
status='completed',
)
line = line_model.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
pool=pool,
)
app = login(app)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert 'see agenda' not in resp
assert 'see event' not in resp
line.event = {
'agenda': 'foobar',
}
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert '<a href="/manage/pricing/agenda/foobar/">see agenda</a>' in resp
assert 'see event' not in resp
line.event['slug'] = 'bazbaz'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert '<a href="/manage/pricing/agenda/foobar/">see agenda</a>' in resp
assert 'see event' not in resp
settings.KNOWN_SERVICES['chrono'] = {'default': {'url': 'https://chrono.dev/'}}
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert '<a href="/manage/pricing/agenda/foobar/">see agenda</a>' in resp
assert '<a href="https://chrono.dev/manage/agendas/foobar/events/bazbaz/">see event</a>' in resp
def test_delete_pool(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
campaign2 = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
invoice = DraftInvoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
)
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
)
app = login(app)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
)
resp = resp.form.submit()
assert Pool.objects.count() == 0
assert resp.location.endswith(
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
)
campaign.refresh_from_db()
assert campaign.invalid is True
pool.save()
pool2 = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
campaign.invalid = False
campaign.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
)
resp.form.submit()
assert Pool.objects.count() == 1
campaign.refresh_from_db()
# pool is not the last, don't invalidate the campaign
assert campaign.invalid is False
pool2.delete()
pool.draft = True
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (0, campaign.pk, pool.pk), status=404)
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, 0, pool.pk), status=404)
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign2.pk, pool.pk),
status=404,
)
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, 0), status=404)
pool.status = 'registered'
pool.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
pool.status = 'running'
pool.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
campaign.finalized = True
campaign.save()
app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk),
status=404,
)
campaign.finalized = False
campaign.save()
pool.draft = False
pool.status = 'error'
pool.save()
invoice = Invoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
)
InvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk),
)
resp.form.submit()
assert Pool.objects.count() == 0
campaign.refresh_from_db()
# pool is not draft, don't invalidate the campaign
assert campaign.invalid is False
pool.save()
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk))
def test_set_error_status_line(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_publication=datetime.date(2022, 10, 1),
date_payment_deadline=datetime.date(2022, 10, 31),
date_issue=datetime.date(2022, 10, 31),
date_debit=datetime.date(2022, 11, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=False,
status='completed',
)
line = InvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
quantity=1,
unit_amount=1,
total_amount=1,
status='success',
pool=pool,
)
app = login(app)
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/ignore/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/fix/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, line.pk),
status=404,
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/ignore/'
% (regie.pk, campaign.pk, pool.pk, line.pk),
status=404,
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/fix/'
% (regie.pk, campaign.pk, pool.pk, line.pk),
status=404,
)
line.status = 'warning'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/ignore/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/fix/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, line.pk),
status=404,
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/ignore/'
% (regie.pk, campaign.pk, pool.pk, line.pk),
status=404,
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/fix/'
% (regie.pk, campaign.pk, pool.pk, line.pk),
status=404,
)
line.status = 'error'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/ignore/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/fix/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
in resp
)
line.error_status = 'ignored'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/ignore/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/fix/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
line.error_status = 'fixed'
line.save()
resp = app.get(
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/journal/' % (regie.pk, campaign.pk, pool.pk)
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/ignore/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
assert (
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/fix/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
not in resp
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
)
line.refresh_from_db()
assert line.error_status == ''
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/ignore/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
)
line.refresh_from_db()
assert line.error_status == 'ignored'
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/fix/'
% (regie.pk, campaign.pk, pool.pk, line.pk)
)
line.refresh_from_db()
assert line.error_status == 'fixed'
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (0, campaign.pk, pool.pk, line.pk),
status=404,
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, 0, pool.pk, line.pk),
status=404,
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, 0, line.pk),
status=404,
)
app.get(
'/manage/invoicing/ajax/regie/%s/campaign/%s/pool/%s/line/%s/reset/'
% (regie.pk, campaign.pk, pool.pk, 0),
status=404,
)