348 lines
11 KiB
Python
348 lines
11 KiB
Python
import datetime
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
|
|
from lingo.agendas.chrono import ChronoError
|
|
from lingo.agendas.models import Agenda
|
|
from lingo.pricing.models import AgendaPricing, Pricing, PricingError
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
def test_pricing_compute_params(app, user):
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
# missing slots
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={'user_external_id': 'user:1', 'adult_external_id': 'adult:1'},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['slots'] == ['This field is required.']
|
|
|
|
# missing user_external_id
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={'slots': 'foo@foo', 'adult_external_id': 'adult:1'},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['user_external_id'] == ['This field is required.']
|
|
|
|
# missing adult_external_id
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={'slots': 'foo@foo', 'user_external_id': 'user:1'},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['adult_external_id'] == ['This field is required.']
|
|
|
|
|
|
def test_pricing_compute_slots(app, user):
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
# bad slot format
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'event-bar-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['slots'] == ['Invalid format for slot event-bar-slug']
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': '@event-bar-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['slots'] == ['Missing agenda slug in slot @event-bar-slug']
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['slots'] == ['Missing event slug in slot agenda@']
|
|
|
|
# unknown agenda
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug, agenda2@event-bar-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['slots'] == ['Unknown agendas: agenda, agenda2']
|
|
|
|
|
|
@mock.patch('lingo.api.serializers.get_events')
|
|
def test_pricing_compute_events_error(mock_events, app, user):
|
|
Agenda.objects.create(label='Agenda')
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
mock_events.side_effect = ChronoError('foo bar')
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['slots'] == ['foo bar']
|
|
|
|
|
|
@mock.patch('lingo.api.serializers.get_events')
|
|
@mock.patch('lingo.api.serializers.get_subscriptions')
|
|
def test_pricing_compute_subscriptions_error(mock_subscriptions, mock_events, app, user):
|
|
Agenda.objects.create(label='Agenda')
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
mock_events.return_value = [
|
|
{'start_datetime': '2021-09-01T12:00:00+02:00', 'agenda': 'agenda', 'slug': 'event-bar-slug'}
|
|
]
|
|
mock_subscriptions.side_effect = ChronoError('foo baz')
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['user_external_id'] == ['foo baz']
|
|
|
|
|
|
@mock.patch('lingo.api.serializers.get_events')
|
|
@mock.patch('lingo.api.serializers.get_subscriptions')
|
|
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data_for_event')
|
|
def test_pricing_compute(mock_pricing_data_event, mock_subscriptions, mock_events, app, user):
|
|
agenda = Agenda.objects.create(label='Agenda')
|
|
agenda2 = Agenda.objects.create(label='Agenda2')
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
# no subscription
|
|
mock_events.return_value = [
|
|
{'start_datetime': '2021-09-01T12:00:00+02:00', 'agenda': 'agenda', 'slug': 'event-bar-slug'}
|
|
]
|
|
mock_subscriptions.return_value = []
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['user_external_id'] == [
|
|
'No subscription found for event agenda@event-bar-slug'
|
|
]
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
assert mock_subscriptions.call_args_list == [mock.call('agenda', 'user:1')]
|
|
|
|
# no matching subscription
|
|
mock_subscriptions.reset_mock()
|
|
mock_subscriptions.return_value = [
|
|
{
|
|
'date_start': '2021-08-01',
|
|
'date_end': '2021-09-01',
|
|
},
|
|
{
|
|
'date_start': '2021-09-02',
|
|
'date_end': '2021-09-03',
|
|
},
|
|
]
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['user_external_id'] == [
|
|
'No subscription found for event agenda@event-bar-slug'
|
|
]
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
assert mock_subscriptions.call_args_list == [mock.call('agenda', 'user:1')]
|
|
|
|
# no matching subscription
|
|
mock_events.return_value = [
|
|
{'start_datetime': '2021-09-02T12:00:00+02:00', 'agenda': 'agenda', 'slug': 'event-bar-slug'},
|
|
{'start_datetime': '2021-09-01T12:00:00+02:00', 'agenda': 'agenda2', 'slug': 'event-baz-slug'},
|
|
]
|
|
mock_subscriptions.reset_mock()
|
|
mock_subscriptions.return_value = [
|
|
{
|
|
'date_start': '2021-08-01',
|
|
'date_end': '2021-09-01',
|
|
},
|
|
{
|
|
'date_start': '2021-09-02',
|
|
'date_end': '2021-09-03',
|
|
},
|
|
]
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug, agenda2@event-baz-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
status=400,
|
|
)
|
|
assert resp.json['err'] == 1
|
|
assert resp.json['err_desc'] == 'invalid payload'
|
|
assert resp.json['errors']['user_external_id'] == [
|
|
'No subscription found for event agenda2@event-baz-slug'
|
|
]
|
|
assert mock_pricing_data_event.call_args_list == []
|
|
assert mock_subscriptions.call_args_list == [
|
|
mock.call('agenda', 'user:1'),
|
|
mock.call('agenda2', 'user:1'),
|
|
]
|
|
|
|
# no agenda_pricing found
|
|
mock_subscriptions.return_value = [
|
|
{
|
|
'date_start': '2021-08-01',
|
|
'date_end': '2021-09-01',
|
|
},
|
|
{
|
|
'date_start': '2021-09-01',
|
|
'date_end': '2021-09-02',
|
|
},
|
|
{
|
|
'date_start': '2021-09-02',
|
|
'date_end': '2021-09-03',
|
|
},
|
|
]
|
|
mock_pricing_data_event.side_effect = [
|
|
{'foo': 'baz'},
|
|
{'foo': 'bar'},
|
|
]
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug, agenda2@event-baz-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
)
|
|
assert resp.json['data'] == [
|
|
{
|
|
'event': 'agenda2@event-baz-slug',
|
|
'error': 'No agenda pricing found for event agenda2@event-baz-slug',
|
|
},
|
|
{
|
|
'event': 'agenda@event-bar-slug',
|
|
'error': 'No agenda pricing found for event agenda@event-bar-slug',
|
|
},
|
|
]
|
|
|
|
# ok
|
|
pricing = Pricing.objects.create(label='Foo bar')
|
|
agenda_pricing = 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_pricing.agendas.add(agenda, agenda2)
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug, agenda2@event-baz-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
)
|
|
assert resp.json['data'] == [
|
|
{'event': 'agenda2@event-baz-slug', 'pricing_data': {'foo': 'baz'}},
|
|
{'event': 'agenda@event-bar-slug', 'pricing_data': {'foo': 'bar'}},
|
|
]
|
|
assert mock_pricing_data_event.call_args_list == [
|
|
mock.call(
|
|
request=mock.ANY,
|
|
agenda=agenda2,
|
|
event={
|
|
'start_datetime': '2021-09-01T12:00:00+02:00',
|
|
'agenda': 'agenda2',
|
|
'slug': 'event-baz-slug',
|
|
},
|
|
subscription={'date_start': '2021-09-01', 'date_end': '2021-09-02'},
|
|
check_status={'status': 'presence', 'check_type': None},
|
|
booking={},
|
|
user_external_id='user:1',
|
|
adult_external_id='adult:1',
|
|
),
|
|
mock.call(
|
|
request=mock.ANY,
|
|
agenda=agenda,
|
|
event={
|
|
'start_datetime': '2021-09-02T12:00:00+02:00',
|
|
'agenda': 'agenda',
|
|
'slug': 'event-bar-slug',
|
|
},
|
|
subscription={'date_start': '2021-09-02', 'date_end': '2021-09-03'},
|
|
check_status={'status': 'presence', 'check_type': None},
|
|
booking={},
|
|
user_external_id='user:1',
|
|
adult_external_id='adult:1',
|
|
),
|
|
]
|
|
|
|
# get_pricing_data_for_event with error
|
|
mock_pricing_data_event.side_effect = [
|
|
PricingError(details={'foo': 'error'}),
|
|
{'foo': 'bar'},
|
|
]
|
|
resp = app.get(
|
|
'/api/pricing/compute/',
|
|
params={
|
|
'slots': 'agenda@event-bar-slug, agenda2@event-baz-slug',
|
|
'user_external_id': 'user:1',
|
|
'adult_external_id': 'adult:1',
|
|
},
|
|
)
|
|
assert resp.json['data'] == [
|
|
{'event': 'agenda2@event-baz-slug', 'error': {'foo': 'error'}},
|
|
{'event': 'agenda@event-bar-slug', 'pricing_data': {'foo': 'bar'}},
|
|
]
|