1438 lines
49 KiB
Python
1438 lines
49 KiB
Python
import datetime
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
from django.core.management import CommandError, call_command
|
|
from django.db import connection
|
|
from django.test.utils import CaptureQueriesContext
|
|
|
|
from lingo.agendas.chrono import ChronoError
|
|
from lingo.agendas.models import Agenda
|
|
from lingo.invoicing import utils
|
|
from lingo.invoicing.models import Campaign, DraftInvoice, DraftInvoiceLine, Pool, Regie
|
|
from lingo.pricing.models import AgendaPricing, Criteria, CriteriaCategory, Pricing, PricingError
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
def test_get_agendas():
|
|
agenda1 = Agenda.objects.create(label='Agenda 1')
|
|
agenda2 = Agenda.objects.create(label='Agenda 2')
|
|
agenda3 = Agenda.objects.create(label='Agenda 3')
|
|
Agenda.objects.create(label='Agenda 4')
|
|
pricing = Pricing.objects.create(label='Foo bar 1')
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
# no agenda pricing defined
|
|
assert list(utils.get_agendas(pool=pool)) == []
|
|
|
|
# agenda pricing, but for flat_fee_schedule
|
|
agenda_pricing = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2022, month=9, day=1),
|
|
date_end=datetime.date(year=2022, month=10, day=1),
|
|
flat_fee_schedule=True, # wrong config
|
|
)
|
|
agenda_pricing.agendas.add(agenda1)
|
|
assert list(utils.get_agendas(pool=pool)) == []
|
|
|
|
# create some agenda pricing
|
|
agenda_pricing1 = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2021, month=9, day=1),
|
|
date_end=datetime.date(year=2021, month=10, day=1),
|
|
)
|
|
agenda_pricing2 = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2022, month=9, day=1),
|
|
date_end=datetime.date(year=2022, month=10, day=1),
|
|
)
|
|
assert list(utils.get_agendas(pool=pool)) == []
|
|
|
|
# link agendas to agenda pricing
|
|
agenda_pricing1.agendas.add(agenda1, agenda2)
|
|
agenda_pricing2.agendas.add(agenda3)
|
|
|
|
assert list(utils.get_agendas(pool=pool)) == [agenda3]
|
|
campaign.date_start = datetime.date(2021, 9, 1)
|
|
campaign.date_end = datetime.date(2021, 10, 1)
|
|
campaign.save()
|
|
assert list(utils.get_agendas(pool=pool)) == [agenda1, agenda2]
|
|
campaign.date_start = datetime.date(2022, 8, 31)
|
|
campaign.date_end = datetime.date(2022, 9, 1)
|
|
campaign.save()
|
|
assert list(utils.get_agendas(pool=pool)) == []
|
|
campaign.date_start = datetime.date(2022, 9, 1)
|
|
campaign.date_end = datetime.date(2022, 9, 2)
|
|
campaign.save()
|
|
assert list(utils.get_agendas(pool=pool)) == [agenda3]
|
|
campaign.date_start = datetime.date(2022, 9, 30)
|
|
campaign.date_end = datetime.date(2022, 10, 1)
|
|
campaign.save()
|
|
assert list(utils.get_agendas(pool=pool)) == [agenda3]
|
|
campaign.date_start = datetime.date(2022, 10, 1)
|
|
campaign.date_end = datetime.date(2022, 10, 2)
|
|
campaign.save()
|
|
assert list(utils.get_agendas(pool=pool)) == []
|
|
campaign.date_start = datetime.date(2021, 9, 15)
|
|
campaign.date_end = datetime.date(2022, 9, 15)
|
|
campaign.save()
|
|
assert list(utils.get_agendas(pool=pool)) == [agenda1, agenda2, agenda3]
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_subscriptions')
|
|
def test_get_all_subscriptions_error(mock_subscriptions):
|
|
agenda = Agenda.objects.create(label='Agenda')
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
mock_subscriptions.side_effect = ChronoError('foo baz')
|
|
with pytest.raises(ChronoError):
|
|
utils.get_all_subscriptions(agendas=[agenda], pool=pool)
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_subscriptions')
|
|
def test_get_all_subscriptions(mock_subscriptions):
|
|
agenda1 = Agenda.objects.create(label='Agenda 1')
|
|
agenda2 = Agenda.objects.create(label='Agenda 2')
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
# no agendas
|
|
assert utils.get_all_subscriptions(agendas=[], pool=pool) == {}
|
|
assert mock_subscriptions.call_args_list == []
|
|
|
|
# no subscriptions
|
|
mock_subscriptions.return_value = []
|
|
assert utils.get_all_subscriptions(agendas=[agenda1, agenda2], pool=pool) == {}
|
|
assert mock_subscriptions.call_args_list == [
|
|
mock.call(
|
|
agenda_slug='agenda-1', date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1)
|
|
),
|
|
mock.call(
|
|
agenda_slug='agenda-2', date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1)
|
|
),
|
|
]
|
|
mock_subscriptions.reset_mock()
|
|
|
|
# with subscriptions
|
|
mock_subscriptions.side_effect = [
|
|
[
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-08-01',
|
|
'date_end': '2022-09-02',
|
|
},
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-02',
|
|
'date_end': '2022-09-03',
|
|
},
|
|
{
|
|
'user_external_id': 'user:2',
|
|
'date_start': '2022-09-02',
|
|
'date_end': '2022-09-03',
|
|
},
|
|
],
|
|
[
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-08-01',
|
|
'date_end': '2022-10-01',
|
|
},
|
|
],
|
|
]
|
|
assert utils.get_all_subscriptions(agendas=[agenda1, agenda2], pool=pool) == {
|
|
'user:1': {
|
|
'agenda-1': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-08-01',
|
|
'date_end': '2022-09-02',
|
|
},
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-02',
|
|
'date_end': '2022-09-03',
|
|
},
|
|
],
|
|
'agenda-2': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-08-01',
|
|
'date_end': '2022-10-01',
|
|
},
|
|
],
|
|
},
|
|
'user:2': {
|
|
'agenda-1': [
|
|
{
|
|
'user_external_id': 'user:2',
|
|
'date_start': '2022-09-02',
|
|
'date_end': '2022-09-03',
|
|
},
|
|
],
|
|
},
|
|
}
|
|
assert mock_subscriptions.call_args_list == [
|
|
mock.call(
|
|
agenda_slug='agenda-1', date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1)
|
|
),
|
|
mock.call(
|
|
agenda_slug='agenda-2', date_start=datetime.date(2022, 9, 1), date_end=datetime.date(2022, 10, 1)
|
|
),
|
|
]
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_check_status')
|
|
def test_get_invoice_lines_for_user_check_status_error(mock_status):
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
mock_status.side_effect = ChronoError('foo baz')
|
|
with pytest.raises(ChronoError):
|
|
utils.get_invoice_lines_for_user(
|
|
agendas=['foo'],
|
|
agendas_pricings=[],
|
|
user_external_id='user:1',
|
|
subscriptions={'foo': 'bar'},
|
|
pool=pool,
|
|
)
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_check_status')
|
|
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data_for_event')
|
|
def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_status):
|
|
agenda1 = Agenda.objects.create(label='Agenda 1')
|
|
agenda2 = Agenda.objects.create(label='Agenda 2')
|
|
pricing = Pricing.objects.create(label='Foo bar 1')
|
|
agenda_pricing = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2022, month=9, day=1),
|
|
date_end=datetime.date(year=2022, month=10, day=1),
|
|
)
|
|
agenda_pricing.agendas.add(agenda1, agenda2)
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
# no agendas
|
|
assert (
|
|
utils.get_invoice_lines_for_user(
|
|
agendas=[],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda-1': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-10-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
== []
|
|
)
|
|
assert mock_status.call_args_list == []
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
|
|
# no subscriptions
|
|
assert (
|
|
utils.get_invoice_lines_for_user(
|
|
agendas=[agenda1, agenda2],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={},
|
|
pool=pool,
|
|
)
|
|
== []
|
|
)
|
|
assert mock_status.call_args_list == []
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
|
|
# no status
|
|
mock_status.return_value = []
|
|
assert (
|
|
utils.get_invoice_lines_for_user(
|
|
agendas=[agenda1, agenda2],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda-1': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-10-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
== []
|
|
)
|
|
assert mock_status.call_args_list == [
|
|
mock.call(
|
|
agenda_slugs=['agenda-1'],
|
|
user_external_id='user:1',
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
)
|
|
]
|
|
mock_status.reset_mock()
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
|
|
# agenda and subscriptions not matching
|
|
mock_status.return_value = [
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
}
|
|
}
|
|
]
|
|
assert (
|
|
utils.get_invoice_lines_for_user(
|
|
agendas=[agenda1, agenda2],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'unknown': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-10-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
== []
|
|
)
|
|
assert mock_status.call_args_list == [
|
|
mock.call(
|
|
agenda_slugs=['unknown'],
|
|
user_external_id='user:1',
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
)
|
|
]
|
|
mock_status.reset_mock()
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
|
|
# correct data
|
|
mock_pricing_data_event.side_effect = [
|
|
{'foo1': 'bar1', 'pricing': 1},
|
|
{'foo2': 'bar2', 'pricing': 2},
|
|
{'foo3': 'bar3', 'pricing': 3},
|
|
{'foo4': 'bar4', 'pricing': 4},
|
|
]
|
|
mock_status.return_value = [
|
|
# many events for agenda-1
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event-1',
|
|
'label': 'Event 1',
|
|
},
|
|
'check_status': {'foo': 'bar1'},
|
|
'booking': {'foo': 'baz1'},
|
|
},
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-09-02T12:00:00+02:00',
|
|
'slug': 'event-2',
|
|
'label': 'Event 2',
|
|
},
|
|
'check_status': {'foo': 'bar2'},
|
|
'booking': {'foo': 'baz2'},
|
|
},
|
|
# and for agenda-2
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-2',
|
|
'start_datetime': '2022-09-01T13:00:00+02:00',
|
|
'slug': 'eveeent-1',
|
|
'label': 'Eveeent 1',
|
|
},
|
|
'check_status': {'foo': 'barrr1'},
|
|
'booking': {'foo': 'bazzz1'},
|
|
},
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-2',
|
|
'start_datetime': '2022-09-02T13:00:00+02:00',
|
|
'slug': 'eveeent-2',
|
|
'label': 'Eveeent 2',
|
|
},
|
|
'check_status': {'foo': 'barrr2'},
|
|
'booking': {'foo': 'bazzz2'},
|
|
},
|
|
]
|
|
lines = utils.get_invoice_lines_for_user(
|
|
agendas=[agenda1, agenda2],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
# matching dates
|
|
'agenda-1': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-10-01',
|
|
},
|
|
],
|
|
'agenda-2': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-10-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
assert mock_pricing_data_event.call_args_list == [
|
|
mock.call(
|
|
request=mock.ANY,
|
|
agenda=agenda1,
|
|
event={
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event-1',
|
|
'label': 'Event 1',
|
|
},
|
|
subscription={'user_external_id': 'user:1', 'date_start': '2022-09-01', 'date_end': '2022-10-01'},
|
|
check_status={'foo': 'bar1'},
|
|
booking={'foo': 'baz1'},
|
|
user_external_id='user:1',
|
|
adult_external_id='user:1',
|
|
),
|
|
mock.call(
|
|
request=mock.ANY,
|
|
agenda=agenda1,
|
|
event={
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-09-02T12:00:00+02:00',
|
|
'slug': 'event-2',
|
|
'label': 'Event 2',
|
|
},
|
|
subscription={'user_external_id': 'user:1', 'date_start': '2022-09-01', 'date_end': '2022-10-01'},
|
|
check_status={'foo': 'bar2'},
|
|
booking={'foo': 'baz2'},
|
|
user_external_id='user:1',
|
|
adult_external_id='user:1',
|
|
),
|
|
mock.call(
|
|
request=mock.ANY,
|
|
agenda=agenda2,
|
|
event={
|
|
'agenda': 'agenda-2',
|
|
'start_datetime': '2022-09-01T13:00:00+02:00',
|
|
'slug': 'eveeent-1',
|
|
'label': 'Eveeent 1',
|
|
},
|
|
subscription={'user_external_id': 'user:1', 'date_start': '2022-09-01', 'date_end': '2022-10-01'},
|
|
check_status={'foo': 'barrr1'},
|
|
booking={'foo': 'bazzz1'},
|
|
user_external_id='user:1',
|
|
adult_external_id='user:1',
|
|
),
|
|
mock.call(
|
|
request=mock.ANY,
|
|
agenda=agenda2,
|
|
event={
|
|
'agenda': 'agenda-2',
|
|
'start_datetime': '2022-09-02T13:00:00+02:00',
|
|
'slug': 'eveeent-2',
|
|
'label': 'Eveeent 2',
|
|
},
|
|
subscription={'user_external_id': 'user:1', 'date_start': '2022-09-01', 'date_end': '2022-10-01'},
|
|
check_status={'foo': 'barrr2'},
|
|
booking={'foo': 'bazzz2'},
|
|
user_external_id='user:1',
|
|
adult_external_id='user:1',
|
|
),
|
|
]
|
|
assert len(lines) == 4
|
|
line1, line2, line3, line4 = lines
|
|
assert isinstance(line1, DraftInvoiceLine)
|
|
assert line1.invoice is None
|
|
assert line1.slug == 'agenda-1@event-1'
|
|
assert line1.label == 'Event 1'
|
|
assert line1.quantity == 1
|
|
assert line1.unit_amount == 1
|
|
assert line1.total_amount == 1
|
|
assert line1.user_external_id == 'user:1'
|
|
assert line1.payer_external_id == 'user:1'
|
|
assert line1.event == {
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event-1',
|
|
'label': 'Event 1',
|
|
}
|
|
assert line1.pricing_data == {'foo1': 'bar1', 'pricing': 1}
|
|
assert line1.status == 'success'
|
|
assert line1.pool == pool
|
|
assert isinstance(line2, DraftInvoiceLine)
|
|
assert line2.invoice is None
|
|
assert line2.slug == 'agenda-1@event-2'
|
|
assert line2.label == 'Event 2'
|
|
assert line2.quantity == 1
|
|
assert line2.unit_amount == 2
|
|
assert line2.total_amount == 2
|
|
assert line2.user_external_id == 'user:1'
|
|
assert line2.payer_external_id == 'user:1'
|
|
assert line2.event == {
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-09-02T12:00:00+02:00',
|
|
'slug': 'event-2',
|
|
'label': 'Event 2',
|
|
}
|
|
assert line2.pricing_data == {'foo2': 'bar2', 'pricing': 2}
|
|
assert line2.status == 'success'
|
|
assert line2.pool == pool
|
|
assert isinstance(line3, DraftInvoiceLine)
|
|
assert line3.invoice is None
|
|
assert line3.slug == 'agenda-2@eveeent-1'
|
|
assert line3.label == 'Eveeent 1'
|
|
assert line3.quantity == 1
|
|
assert line3.unit_amount == 3
|
|
assert line3.total_amount == 3
|
|
assert line3.user_external_id == 'user:1'
|
|
assert line3.payer_external_id == 'user:1'
|
|
assert line3.event == {
|
|
'agenda': 'agenda-2',
|
|
'start_datetime': '2022-09-01T13:00:00+02:00',
|
|
'slug': 'eveeent-1',
|
|
'label': 'Eveeent 1',
|
|
}
|
|
assert line3.pricing_data == {'foo3': 'bar3', 'pricing': 3}
|
|
assert line3.status == 'success'
|
|
assert line3.pool == pool
|
|
assert isinstance(line4, DraftInvoiceLine)
|
|
assert line4.invoice is None
|
|
assert line4.slug == 'agenda-2@eveeent-2'
|
|
assert line4.label == 'Eveeent 2'
|
|
assert line4.quantity == 1
|
|
assert line4.unit_amount == 4
|
|
assert line4.total_amount == 4
|
|
assert line4.user_external_id == 'user:1'
|
|
assert line4.payer_external_id == 'user:1'
|
|
assert line4.event == {
|
|
'agenda': 'agenda-2',
|
|
'start_datetime': '2022-09-02T13:00:00+02:00',
|
|
'slug': 'eveeent-2',
|
|
'label': 'Eveeent 2',
|
|
}
|
|
assert line4.pricing_data == {'foo4': 'bar4', 'pricing': 4}
|
|
assert line4.status == 'success'
|
|
assert line4.pool == pool
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_check_status')
|
|
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data_for_event')
|
|
def test_get_invoice_lines_for_user_check_status_subscriptions_dates(mock_pricing_data_event, mock_status):
|
|
agenda = Agenda.objects.create(label='Agenda')
|
|
pricing = Pricing.objects.create(label='Foo bar')
|
|
agenda_pricing = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2022, month=9, day=1),
|
|
date_end=datetime.date(year=2022, month=10, day=1),
|
|
)
|
|
agenda_pricing.agendas.add(agenda)
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
mock_pricing_data_event.return_value = {'foo': 'bar', 'pricing': 42}
|
|
mock_status.return_value = [
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
]
|
|
|
|
assert (
|
|
utils.get_invoice_lines_for_user(
|
|
agendas=[agenda],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
# event is outside the period
|
|
'date_start': '2022-08-31',
|
|
'date_end': '2022-09-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
== []
|
|
)
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
|
|
assert (
|
|
utils.get_invoice_lines_for_user(
|
|
agendas=[agenda],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
# event is outside the period
|
|
'date_start': '2022-09-02',
|
|
'date_end': '2022-09-03',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
== []
|
|
)
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
|
|
lines = utils.get_invoice_lines_for_user(
|
|
agendas=[agenda],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
# event is outside the period
|
|
'date_start': '2022-08-31',
|
|
'date_end': '2022-09-01',
|
|
},
|
|
{
|
|
'user_external_id': 'user:1',
|
|
# bingo !
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-09-02',
|
|
},
|
|
{
|
|
'user_external_id': 'user:1',
|
|
# event is outside the period
|
|
'date_start': '2022-09-02',
|
|
'date_end': '2022-09-03',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
assert len(lines) == 1
|
|
assert mock_pricing_data_event.call_args_list == [
|
|
mock.call(
|
|
request=mock.ANY,
|
|
agenda=agenda,
|
|
event={
|
|
'agenda': 'agenda',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
subscription={'user_external_id': 'user:1', 'date_start': '2022-09-01', 'date_end': '2022-09-02'},
|
|
check_status={'foo': 'bar'},
|
|
booking={'foo': 'baz'},
|
|
user_external_id='user:1',
|
|
adult_external_id='user:1',
|
|
)
|
|
]
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_check_status')
|
|
def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_status):
|
|
agenda = Agenda.objects.create(label='Agenda')
|
|
pricing = Pricing.objects.create(label='Foo bar')
|
|
agenda_pricing1 = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2022, month=9, day=1),
|
|
date_end=datetime.date(year=2022, month=10, day=1),
|
|
)
|
|
agenda_pricing1.agendas.add(agenda)
|
|
agenda_pricing2 = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2022, month=10, day=1),
|
|
date_end=datetime.date(year=2022, month=11, day=1),
|
|
flat_fee_schedule=True,
|
|
)
|
|
agenda_pricing2.agendas.add(agenda)
|
|
agenda_pricing3 = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2022, month=10, day=1),
|
|
date_end=datetime.date(year=2022, month=11, day=1),
|
|
)
|
|
agenda_pricing3.agendas.add(agenda)
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 1, 1),
|
|
date_end=datetime.date(2023, 1, 1),
|
|
date_issue=datetime.date(2023, 1, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
pricing_data_event_patch = mock.patch.object(AgendaPricing, 'get_pricing_data_for_event', autospec=True)
|
|
|
|
# check agenda pricing of september is used
|
|
for event_date in ['2022-09-01T12:00:00+02:00', '2022-09-30T12:00:00+02:00']:
|
|
mock_status.return_value = [
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda',
|
|
'start_datetime': event_date,
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
]
|
|
with pricing_data_event_patch as mock_pricing_data_event:
|
|
mock_pricing_data_event.return_value = {'foo': 'bar', 'pricing': 42}
|
|
lines = utils.get_invoice_lines_for_user(
|
|
agendas=[agenda],
|
|
agendas_pricings=AgendaPricing.objects.all(),
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-01-01',
|
|
'date_end': '2023-01-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
assert len(lines) == 1
|
|
assert mock_pricing_data_event.call_args_list[0][0][0] == agenda_pricing1
|
|
|
|
# check agenda pricing of october is used
|
|
for event_date in ['2022-10-01T12:00:00+02:00', '2022-10-31T12:00:00+02:00']:
|
|
mock_status.return_value = [
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda',
|
|
'start_datetime': event_date,
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
]
|
|
with pricing_data_event_patch as mock_pricing_data_event:
|
|
mock_pricing_data_event.return_value = {'foo': 'bar', 'pricing': 42}
|
|
lines = utils.get_invoice_lines_for_user(
|
|
agendas=[agenda],
|
|
agendas_pricings=AgendaPricing.objects.all(),
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-01-01',
|
|
'date_end': '2023-01-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
assert len(lines) == 1
|
|
assert mock_pricing_data_event.call_args_list[0][0][0] == agenda_pricing3
|
|
|
|
# no matching agenda pricing
|
|
for event_date in ['2022-08-31T12:00:00+02:00', '2022-11-01T12:00:00+02:00']:
|
|
mock_status.return_value = [
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda',
|
|
'start_datetime': event_date,
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
]
|
|
with pricing_data_event_patch as mock_pricing_data_event:
|
|
lines = utils.get_invoice_lines_for_user(
|
|
agendas=[agenda],
|
|
agendas_pricings=AgendaPricing.objects.all(),
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-01-01',
|
|
'date_end': '2023-01-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
assert len(lines) == 0
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_check_status')
|
|
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data_for_event')
|
|
def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data_event, mock_status):
|
|
agenda = Agenda.objects.create(label='Agenda')
|
|
pricing = Pricing.objects.create(label='Foo bar')
|
|
agenda_pricing = AgendaPricing.objects.create(
|
|
pricing=pricing,
|
|
date_start=datetime.date(year=2022, month=9, day=1),
|
|
date_end=datetime.date(year=2022, month=10, day=1),
|
|
)
|
|
agenda_pricing.agendas.add(agenda)
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
mock_pricing_data_event.side_effect = [
|
|
{'foo1': 'bar1', 'pricing': 1},
|
|
PricingError(),
|
|
{'foo3': 'bar3', 'pricing': 3},
|
|
]
|
|
mock_status.return_value = [
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event-1',
|
|
'label': 'Event 1',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda',
|
|
'start_datetime': '2022-09-02T12:00:00+02:00',
|
|
'slug': 'event-2',
|
|
'label': 'Event 2',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda',
|
|
'start_datetime': '2022-09-03T12:00:00+02:00',
|
|
'slug': 'event-3',
|
|
'label': 'Event 3',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
]
|
|
lines = utils.get_invoice_lines_for_user(
|
|
agendas=[agenda],
|
|
agendas_pricings=[agenda_pricing],
|
|
user_external_id='user:1',
|
|
subscriptions={
|
|
'agenda': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-10-01',
|
|
},
|
|
],
|
|
},
|
|
pool=pool,
|
|
)
|
|
assert len(lines) == 3
|
|
line1, line2, line3 = lines
|
|
assert isinstance(line1, DraftInvoiceLine)
|
|
assert line1.invoice is None
|
|
assert line1.slug == 'agenda@event-1'
|
|
assert line1.label == 'Event 1'
|
|
assert line1.quantity == 1
|
|
assert line1.unit_amount == 1
|
|
assert line1.total_amount == 1
|
|
assert line1.user_external_id == 'user:1'
|
|
assert line1.payer_external_id == 'user:1'
|
|
assert line1.event == {
|
|
'agenda': 'agenda',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event-1',
|
|
'label': 'Event 1',
|
|
}
|
|
assert line1.pricing_data == {'foo1': 'bar1', 'pricing': 1}
|
|
assert line1.status == 'success'
|
|
assert line1.pool == pool
|
|
assert isinstance(line2, DraftInvoiceLine)
|
|
assert line2.invoice is None
|
|
assert line2.slug == 'agenda@event-2'
|
|
assert line2.label == 'Event 2'
|
|
assert line2.quantity == 0
|
|
assert line2.unit_amount == 0
|
|
assert line2.total_amount == 0
|
|
assert line2.user_external_id == 'user:1'
|
|
assert line2.payer_external_id == 'user:1'
|
|
assert line2.event == {
|
|
'agenda': 'agenda',
|
|
'start_datetime': '2022-09-02T12:00:00+02:00',
|
|
'slug': 'event-2',
|
|
'label': 'Event 2',
|
|
}
|
|
assert line2.pricing_data == {'error': {}}
|
|
assert line2.status == 'error'
|
|
assert line2.pool == pool
|
|
assert isinstance(line3, DraftInvoiceLine)
|
|
assert line3.invoice is None
|
|
assert line3.slug == 'agenda@event-3'
|
|
assert line3.label == 'Event 3'
|
|
assert line3.quantity == 1
|
|
assert line3.unit_amount == 3
|
|
assert line3.total_amount == 3
|
|
assert line3.user_external_id == 'user:1'
|
|
assert line3.payer_external_id == 'user:1'
|
|
assert line3.event == {
|
|
'agenda': 'agenda',
|
|
'start_datetime': '2022-09-03T12:00:00+02:00',
|
|
'slug': 'event-3',
|
|
'label': 'Event 3',
|
|
}
|
|
assert line3.pricing_data == {'foo3': 'bar3', 'pricing': 3}
|
|
assert line3.status == 'success'
|
|
assert line3.pool == pool
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_invoice_lines_for_user')
|
|
def test_get_all_invoice_lines(mock_user_lines):
|
|
agenda1 = Agenda.objects.create(label='Agenda 1')
|
|
agenda2 = Agenda.objects.create(label='Agenda 2')
|
|
Agenda.objects.create(label='Agenda 3')
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
line1 = DraftInvoiceLine.objects.create(
|
|
quantity=0,
|
|
unit_amount=0,
|
|
total_amount=0,
|
|
pool=pool,
|
|
)
|
|
line2 = DraftInvoiceLine.objects.create(
|
|
quantity=0,
|
|
unit_amount=0,
|
|
total_amount=0,
|
|
pool=pool,
|
|
)
|
|
line3 = DraftInvoiceLine.objects.create(
|
|
quantity=0,
|
|
unit_amount=0,
|
|
total_amount=0,
|
|
pool=pool,
|
|
)
|
|
|
|
mock_user_lines.side_effect = [[line1, line2], [line3]]
|
|
|
|
# no subscriptions
|
|
assert (
|
|
utils.get_all_invoice_lines(
|
|
agendas=[agenda1, agenda2],
|
|
subscriptions={},
|
|
pool=pool,
|
|
)
|
|
== []
|
|
)
|
|
assert mock_user_lines.call_args_list == []
|
|
|
|
# with subscriptions
|
|
assert utils.get_all_invoice_lines(
|
|
agendas=[agenda1, agenda2],
|
|
subscriptions={
|
|
'user:1': {'foo': 'bar1'},
|
|
'user:2': {'foo': 'bar2'},
|
|
},
|
|
pool=pool,
|
|
) == [line1, line2, line3]
|
|
assert mock_user_lines.call_args_list == [
|
|
mock.call(
|
|
agendas=[agenda1, agenda2],
|
|
agendas_pricings=mock.ANY,
|
|
user_external_id='user:1',
|
|
subscriptions={'foo': 'bar1'},
|
|
pool=pool,
|
|
),
|
|
mock.call(
|
|
agendas=[agenda1, agenda2],
|
|
agendas_pricings=mock.ANY,
|
|
user_external_id='user:2',
|
|
subscriptions={'foo': 'bar2'},
|
|
pool=pool,
|
|
),
|
|
]
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_check_status')
|
|
def test_get_all_invoice_lines_queryset(mock_status):
|
|
# don't mock get_pricing_data_for_event to check all querysets
|
|
category1 = CriteriaCategory.objects.create(label='Foo1', slug='foo1')
|
|
criteria1 = Criteria.objects.create(label='Bar1', slug='bar1', condition='True', category=category1)
|
|
category2 = CriteriaCategory.objects.create(label='Foo2', slug='foo2')
|
|
criteria2 = Criteria.objects.create(label='Bar2', slug='bar2', condition='True', category=category2)
|
|
|
|
pricing1 = Pricing.objects.create(label='Foo bar 1')
|
|
pricing1.criterias.add(criteria1, criteria2)
|
|
pricing1.categories.add(category1, through_defaults={'order': 1})
|
|
pricing1.categories.add(category2, through_defaults={'order': 2})
|
|
pricing2 = Pricing.objects.create(label='Foo bar 2')
|
|
pricing2.criterias.add(criteria1, criteria2)
|
|
pricing2.categories.add(category1, through_defaults={'order': 1})
|
|
pricing2.categories.add(category2, through_defaults={'order': 2})
|
|
|
|
agenda1 = Agenda.objects.create(label='Agenda 1')
|
|
agenda_pricing11 = AgendaPricing.objects.create(
|
|
pricing=pricing1,
|
|
date_start=datetime.date(year=2022, month=9, day=1),
|
|
date_end=datetime.date(year=2022, month=10, day=1),
|
|
)
|
|
agenda_pricing11.agendas.add(agenda1)
|
|
agenda_pricing12 = AgendaPricing.objects.create(
|
|
pricing=pricing1,
|
|
date_start=datetime.date(year=2022, month=10, day=1),
|
|
date_end=datetime.date(year=2022, month=11, day=1),
|
|
)
|
|
agenda_pricing12.agendas.add(agenda1)
|
|
|
|
agenda2 = Agenda.objects.create(label='Agenda 2')
|
|
agenda_pricing21 = AgendaPricing.objects.create(
|
|
pricing=pricing2,
|
|
date_start=datetime.date(year=2022, month=9, day=1),
|
|
date_end=datetime.date(year=2022, month=10, day=1),
|
|
)
|
|
agenda_pricing21.agendas.add(agenda2)
|
|
agenda_pricing22 = AgendaPricing.objects.create(
|
|
pricing=pricing2,
|
|
date_start=datetime.date(year=2022, month=10, day=1),
|
|
date_end=datetime.date(year=2022, month=11, day=1),
|
|
)
|
|
agenda_pricing22.agendas.add(agenda2)
|
|
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 11, 1),
|
|
date_issue=datetime.date(2022, 11, 30),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
mock_status.return_value = [
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-1',
|
|
'start_datetime': '2022-10-01T12:00:00+02:00',
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-2',
|
|
'start_datetime': '2022-09-01T12:00:00+02:00',
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
{
|
|
'event': {
|
|
'agenda': 'agenda-2',
|
|
'start_datetime': '2022-10-01T12:00:00+02:00',
|
|
'slug': 'event',
|
|
'label': 'Event',
|
|
},
|
|
'check_status': {'foo': 'bar'},
|
|
'booking': {'foo': 'baz'},
|
|
},
|
|
]
|
|
|
|
with CaptureQueriesContext(connection) as ctx:
|
|
lines = utils.get_all_invoice_lines(
|
|
agendas=[agenda1, agenda2],
|
|
subscriptions={
|
|
'user:1': {
|
|
'agenda-1': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-11-01',
|
|
},
|
|
],
|
|
'agenda-2': [
|
|
{
|
|
'user_external_id': 'user:1',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-11-01',
|
|
},
|
|
],
|
|
},
|
|
'user:2': {
|
|
'agenda-1': [
|
|
{
|
|
'user_external_id': 'user:2',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-11-01',
|
|
},
|
|
],
|
|
'agenda-2': [
|
|
{
|
|
'user_external_id': 'user:2',
|
|
'date_start': '2022-09-01',
|
|
'date_end': '2022-11-01',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
pool=pool,
|
|
)
|
|
assert lines
|
|
assert len(ctx.captured_queries) == 7
|
|
|
|
|
|
def test_generate_invoices_from_lines():
|
|
regie1 = Regie.objects.create(label='Regie 1')
|
|
regie2 = Regie.objects.create(label='Regie 2')
|
|
agenda1 = Agenda.objects.create(label='Agenda 1', regie=regie1)
|
|
agenda2 = Agenda.objects.create(label='Agenda 2', regie=regie2)
|
|
agenda3 = Agenda.objects.create(label='Agenda 3', regie=regie1)
|
|
agenda4 = Agenda.objects.create(label='Agenda 4') # regie not configured
|
|
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
|
|
line_error = DraftInvoiceLine.objects.create(
|
|
event={'agenda': 'agenda-1'},
|
|
quantity=0,
|
|
unit_amount=0,
|
|
total_amount=0,
|
|
user_external_id='user:1',
|
|
payer_external_id='user:1',
|
|
status='error',
|
|
pool=pool,
|
|
)
|
|
line1 = DraftInvoiceLine.objects.create(
|
|
event={'agenda': 'agenda-1'},
|
|
quantity=1,
|
|
unit_amount=1,
|
|
total_amount=1,
|
|
user_external_id='user:1',
|
|
payer_external_id='user:1',
|
|
status='success',
|
|
pool=pool,
|
|
)
|
|
line2 = DraftInvoiceLine.objects.create(
|
|
event={'agenda': 'agenda-1'},
|
|
quantity=1,
|
|
unit_amount=2,
|
|
total_amount=2,
|
|
user_external_id='user:1',
|
|
payer_external_id='user:1',
|
|
status='success',
|
|
pool=pool,
|
|
)
|
|
line3 = DraftInvoiceLine.objects.create(
|
|
event={'agenda': 'agenda-2'},
|
|
quantity=1,
|
|
unit_amount=3,
|
|
total_amount=3,
|
|
user_external_id='user:1',
|
|
payer_external_id='user:1',
|
|
status='success',
|
|
pool=pool,
|
|
)
|
|
line4 = DraftInvoiceLine.objects.create(
|
|
event={'agenda': 'agenda-2'},
|
|
quantity=1,
|
|
unit_amount=4,
|
|
total_amount=4,
|
|
user_external_id='user:1',
|
|
payer_external_id='user:2',
|
|
status='success',
|
|
pool=pool,
|
|
)
|
|
line5 = DraftInvoiceLine.objects.create(
|
|
event={'agenda': 'agenda-3'},
|
|
quantity=1,
|
|
unit_amount=5,
|
|
total_amount=5,
|
|
user_external_id='user:2',
|
|
payer_external_id='user:1',
|
|
status='success',
|
|
pool=pool,
|
|
)
|
|
DraftInvoiceLine.objects.create( # not used for generation
|
|
event={'agenda': 'agenda-3'},
|
|
quantity=1,
|
|
unit_amount=5,
|
|
total_amount=5,
|
|
user_external_id='user:2',
|
|
payer_external_id='user:1',
|
|
status='success',
|
|
pool=pool,
|
|
)
|
|
line6 = DraftInvoiceLine.objects.create(
|
|
event={'agenda': 'agenda-4'}, # regie not configured
|
|
quantity=1,
|
|
unit_amount=6,
|
|
total_amount=6,
|
|
user_external_id='user:1',
|
|
payer_external_id='user:1',
|
|
status='success',
|
|
pool=pool,
|
|
)
|
|
|
|
invoices = utils.generate_invoices_from_lines(
|
|
agendas=[],
|
|
all_lines=[line_error, line1, line2, line3, line4, line5, line6],
|
|
pool=pool,
|
|
)
|
|
assert len(invoices) == 0
|
|
|
|
invoices = utils.generate_invoices_from_lines(
|
|
agendas=[agenda1, agenda2, agenda3, agenda4],
|
|
all_lines=[line_error, line1, line2, line3, line4, line5, line6],
|
|
pool=pool,
|
|
)
|
|
assert len(invoices) == 3
|
|
invoice1, invoice2, invoice3 = invoices
|
|
# refresh total_amount field (triggered)
|
|
invoice1.refresh_from_db()
|
|
invoice2.refresh_from_db()
|
|
invoice3.refresh_from_db()
|
|
assert isinstance(invoice1, DraftInvoice)
|
|
assert invoice1.label == 'Invoice from 2022-09-01 to 2022-09-30'
|
|
assert invoice1.total_amount == 8
|
|
assert invoice1.date_issue == datetime.date(2022, 10, 31)
|
|
assert invoice1.regie == regie1
|
|
assert invoice1.payer == 'user:1'
|
|
assert invoice1.pool == pool
|
|
assert list(invoice1.lines.order_by('pk')) == [line1, line2, line5]
|
|
assert isinstance(invoice2, DraftInvoice)
|
|
assert invoice2.label == 'Invoice from 2022-09-01 to 2022-09-30'
|
|
assert invoice2.total_amount == 3
|
|
assert invoice2.date_issue == datetime.date(2022, 10, 31)
|
|
assert invoice2.regie == regie2
|
|
assert invoice2.payer == 'user:1'
|
|
assert invoice2.pool == pool
|
|
assert list(invoice2.lines.order_by('pk')) == [line3]
|
|
assert isinstance(invoice3, DraftInvoice)
|
|
assert invoice3.label == 'Invoice from 2022-09-01 to 2022-09-30'
|
|
assert invoice3.total_amount == 4
|
|
assert invoice3.date_issue == datetime.date(2022, 10, 31)
|
|
assert invoice3.regie == regie2
|
|
assert invoice3.payer == 'user:2'
|
|
assert invoice3.pool == pool
|
|
assert list(invoice3.lines.order_by('pk')) == [line4]
|
|
|
|
|
|
@mock.patch('lingo.invoicing.utils.get_agendas')
|
|
@mock.patch('lingo.invoicing.utils.get_all_subscriptions')
|
|
@mock.patch('lingo.invoicing.utils.get_all_invoice_lines')
|
|
@mock.patch('lingo.invoicing.utils.generate_invoices_from_lines')
|
|
def test_generate_invoices(mock_generate, mock_lines, mock_subscriptions, mock_agendas):
|
|
agenda1 = Agenda.objects.create(label='Agenda 1')
|
|
agenda2 = Agenda.objects.create(label='Agenda 2')
|
|
Agenda.objects.create(label='Agenda 3')
|
|
campaign = Campaign.objects.create(
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_issue=datetime.date(2022, 10, 31),
|
|
)
|
|
|
|
mock_agendas.return_value = [agenda1, agenda2]
|
|
mock_subscriptions.return_value = {'foo': 'bar'}
|
|
mock_lines.return_value = ['foo', 'bar']
|
|
|
|
# check only calls between functions
|
|
utils.generate_invoices(campaign=campaign, draft=True)
|
|
pool = Pool.objects.latest('pk')
|
|
assert pool.campaign == campaign
|
|
assert pool.draft is True
|
|
assert mock_agendas.call_args_list == [mock.call(pool=pool)]
|
|
assert mock_subscriptions.call_args_list == [
|
|
mock.call(
|
|
agendas=[agenda1, agenda2],
|
|
pool=pool,
|
|
)
|
|
]
|
|
assert mock_lines.call_args_list == [
|
|
mock.call(
|
|
agendas=[agenda1, agenda2],
|
|
subscriptions={'foo': 'bar'},
|
|
pool=pool,
|
|
)
|
|
]
|
|
assert mock_generate.call_args_list == [
|
|
mock.call(
|
|
agendas=[agenda1, agenda2],
|
|
all_lines=['foo', 'bar'],
|
|
pool=pool,
|
|
)
|
|
]
|
|
|
|
|
|
def test_generate_invoices_cmd():
|
|
with mock.patch(
|
|
'lingo.invoicing.management.commands.generate_invoices.generate_invoices'
|
|
) as mock_generate:
|
|
with pytest.raises(CommandError) as excinfo:
|
|
call_command('generate_invoices')
|
|
assert '%s' % excinfo.value == 'Error: the following arguments are required: date_start, date_end'
|
|
assert mock_generate.call_args_list == []
|
|
|
|
with pytest.raises(CommandError) as excinfo:
|
|
call_command('generate_invoices', 'bad-value', '2022-10-01')
|
|
assert '%s' % excinfo.value == 'Bad value "bad-value" for date_start'
|
|
assert mock_generate.call_args_list == []
|
|
|
|
with pytest.raises(CommandError) as excinfo:
|
|
call_command('generate_invoices', '2022-09-01', 'bad-value')
|
|
assert '%s' % excinfo.value == 'Bad value "bad-value" for date_end'
|
|
assert mock_generate.call_args_list == []
|
|
|
|
with pytest.raises(CommandError) as excinfo:
|
|
call_command('generate_invoices', '2022-09-01', '2022-10-01', '--date-issue=bad-value')
|
|
assert '%s' % excinfo.value == 'Bad value "bad-value" for date_issue'
|
|
assert mock_generate.call_args_list == []
|
|
|
|
assert Campaign.objects.count() == 0
|
|
call_command('generate_invoices', '2022-09-01', '2022-10-01')
|
|
assert Campaign.objects.count() == 1
|
|
campaign = Campaign.objects.latest('pk')
|
|
assert campaign.date_start == datetime.date(2022, 9, 1)
|
|
assert campaign.date_end == datetime.date(2022, 10, 1)
|
|
assert campaign.date_issue == campaign.date_end
|
|
assert mock_generate.call_args_list == [mock.call(campaign=campaign, draft=False)]
|
|
mock_generate.reset_mock()
|
|
|
|
# again
|
|
call_command('generate_invoices', '2022-09-01', '2022-10-01')
|
|
assert Campaign.objects.count() == 1
|
|
assert mock_generate.call_args_list == [mock.call(campaign=campaign, draft=False)]
|
|
mock_generate.reset_mock()
|
|
call_command('generate_invoices', '2022-09-01', '2022-10-01', '--draft')
|
|
assert Campaign.objects.count() == 1
|
|
assert mock_generate.call_args_list == [mock.call(campaign=campaign, draft=True)]
|
|
mock_generate.reset_mock()
|
|
|
|
# with overlapping
|
|
with pytest.raises(CommandError) as excinfo:
|
|
call_command('generate_invoices', '2022-08-31', '2022-09-02')
|
|
assert '%s' % excinfo.value == 'Overlapping campaigns already exist'
|
|
assert mock_generate.call_args_list == []
|
|
with pytest.raises(CommandError) as excinfo:
|
|
call_command('generate_invoices', '2022-09-30', '2022-10-02')
|
|
assert '%s' % excinfo.value == 'Overlapping campaigns already exist'
|
|
assert mock_generate.call_args_list == []
|
|
|
|
# no overlapping
|
|
call_command('generate_invoices', '2022-08-01', '2022-09-01', '--date-issue=2022-10-31')
|
|
assert Campaign.objects.count() == 2
|
|
campaign = Campaign.objects.latest('pk')
|
|
assert mock_generate.call_args_list == [mock.call(campaign=campaign, draft=False)]
|
|
assert campaign.date_start == datetime.date(2022, 8, 1)
|
|
assert campaign.date_end == datetime.date(2022, 9, 1)
|
|
assert campaign.date_issue == datetime.date(2022, 10, 31)
|
|
mock_generate.reset_mock()
|
|
call_command('generate_invoices', '2022-10-01', '2022-11-01')
|
|
assert Campaign.objects.count() == 3
|
|
campaign = Campaign.objects.latest('pk')
|
|
assert mock_generate.call_args_list == [mock.call(campaign=campaign, draft=False)]
|
|
assert campaign.date_start == datetime.date(2022, 10, 1)
|
|
assert campaign.date_end == datetime.date(2022, 11, 1)
|
|
assert campaign.date_issue == campaign.date_end
|