lingo/tests/api/test_pricing.py

830 lines
26 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'))
Agenda.objects.create(label='Foo')
pricing = Pricing.objects.create(label='Foo bar')
AgendaPricing.objects.create(
label='Foo',
pricing=pricing,
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=10, day=1),
flat_fee_schedule=True,
)
# missing slots, agenda, agenda_pricing
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'] == {
'non_field_errors': ['Either "slots", "agenda" or "agenda_pricing" parameter is required.']
}
# missing start_date
resp = app.get(
'/api/pricing/compute/',
params={'agenda': 'foo', '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']['start_date'] == ['This field is required when using "agenda" parameter.']
resp = app.get(
'/api/pricing/compute/',
params={'agenda_pricing': 'foo', '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']['start_date'] == [
'This field is required when using "agenda_pricing" parameter.'
]
params = [
{'slots': 'foo@foo'},
{'agenda': 'foo', 'start_date': '2021-09-01'},
{'agenda_pricing': 'foo', 'start_date': '2021-09-01'},
]
for param in params:
# missing user_external_id
_param = param.copy()
_param.update({'adult_external_id': 'adult:1'})
resp = app.get(
'/api/pricing/compute/',
params=_param,
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
_param = param.copy()
_param.update({'user_external_id': 'user:1'})
resp = app.get(
'/api/pricing/compute/',
params=_param,
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']
def test_pricing_compute_agenda(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
# unknown agenda
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'agenda',
'start_date': '2021-09-01',
'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']['agenda'] == ['Unknown agenda: agenda']
def test_pricing_compute_agenda_pricing(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
def test():
resp = app.get(
'/api/pricing/compute/',
params={
'agenda_pricing': 'baz',
'start_date': '2021-09-01',
'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']['agenda_pricing'] == ['Unknown pricing: baz']
# unknown agenda_pricing
test()
# bad dates
pricing = Pricing.objects.create(label='Foo bar')
agenda_pricing = AgendaPricing.objects.create(
label='Baz',
pricing=pricing,
date_start=datetime.date(year=2021, month=8, day=1),
date_end=datetime.date(year=2021, month=9, day=1),
flat_fee_schedule=True,
subscription_required=False,
)
test()
agenda_pricing.date_start = datetime.date(year=2021, month=9, day=3)
agenda_pricing.date_end = datetime.date(year=2021, month=10, day=1)
agenda_pricing.save()
test()
# wrong flat_fee_schedule value
agenda_pricing.flat_fee_schedule = False
agenda_pricing.save()
test()
# wrong subscription_required value
agenda_pricing.flat_fee_schedule = True
agenda_pricing.subscription_required = True
agenda_pricing.save()
test()
@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_for_event(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',
},
]
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),
flat_fee_schedule=True, # wrong config
)
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',
'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
agenda_pricing.flat_fee_schedule = False
agenda_pricing.save()
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'}},
]
@mock.patch('lingo.api.serializers.get_subscriptions')
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data')
def test_pricing_compute_for_flat_fee_schedule_with_subscription(
mock_pricing_data, mock_subscriptions, app, user
):
agenda = Agenda.objects.create(label='Foo bar')
pricing = Pricing.objects.create(label='Foo bar')
agenda_pricing = AgendaPricing.objects.create(
label='Foo bar pricing',
pricing=pricing,
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=10, day=1),
flat_fee_schedule=True,
subscription_required=True,
)
agenda_pricing.agendas.add(agenda)
app.authorization = ('Basic', ('john.doe', 'password'))
# no subscription
mock_subscriptions.return_value = []
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-01',
'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 agenda foo-bar']
assert mock_subscriptions.call_args_list == [mock.call('foo-bar', '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-10-01',
'date_end': '2021-11-01',
},
]
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-02',
'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 agenda foo-bar']
assert mock_subscriptions.call_args_list == [mock.call('foo-bar', 'user:1')]
# no agenda_pricing found
agenda_pricing.delete()
agenda_pricing = AgendaPricing.objects.create(
pricing=pricing,
# bad dates
date_start=datetime.date(year=2021, month=8, day=1),
date_end=datetime.date(year=2021, month=9, day=1),
)
agenda_pricing.agendas.add(agenda)
agenda_pricing = AgendaPricing.objects.create(
pricing=pricing,
# bad dates
date_start=datetime.date(year=2021, month=9, day=3),
date_end=datetime.date(year=2021, month=10, day=1),
)
agenda_pricing.agendas.add(agenda)
mock_subscriptions.return_value = [
{
'date_start': '2021-08-01',
'date_end': '2021-09-01',
},
{
'date_start': '2021-09-02',
'date_end': '2021-09-03',
},
{
'date_start': '2021-10-01',
'date_end': '2021-11-01',
},
]
mock_pricing_data.return_value = {'foo': 'bar'}
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-02',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == {
'agenda': 'foo-bar',
'error': 'No agenda pricing found for agenda foo-bar',
}
agenda_pricing.delete()
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),
flat_fee_schedule=False, # wrong config
subscription_required=True,
)
agenda_pricing.agendas.add(agenda)
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-02',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == {
'agenda': 'foo-bar',
'error': 'No agenda pricing found for agenda foo-bar',
}
agenda_pricing.flat_fee_schedule = True
agenda_pricing.subscription_required = False # wrong config
agenda_pricing.save()
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-02',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == {
'agenda': 'foo-bar',
'error': 'No agenda pricing found for agenda foo-bar',
}
# ok
agenda_pricing.subscription_required = True
agenda_pricing.save()
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-02',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == {'agenda': 'foo-bar', 'pricing_data': {'foo': 'bar'}}
assert mock_pricing_data.call_args_list == [
mock.call(
request=mock.ANY,
pricing_date=datetime.date(2021, 9, 1),
subscription={'date_start': '2021-09-02', 'date_end': '2021-09-03'},
user_external_id='user:1',
adult_external_id='adult:1',
),
]
# get_pricing_data with error
mock_pricing_data.side_effect = PricingError(details={'foo': 'error'})
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-02',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == {
'agenda': 'foo-bar',
'error': 'PricingError',
'error_details': {'foo': 'error'},
}
# check with billing dates
mock_pricing_data.return_value = {'foo': 'bar'}
agenda_pricing.billingdates.create(
date_start=datetime.date(2021, 9, 1),
label='Foo 1',
)
agenda_pricing.billingdates.create(
date_start=datetime.date(2021, 9, 15),
label='Foo 2',
)
mock_subscriptions.return_value = [
{
'date_start': '2021-09-01',
'date_end': '2021-09-15',
},
]
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-16',
'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 agenda foo-bar']
mock_subscriptions.return_value = [
{
'date_start': '2021-09-15',
'date_end': '2021-09-16',
},
]
mock_pricing_data.reset_mock()
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-16',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert mock_pricing_data.call_args_list == [
mock.call(
request=mock.ANY,
pricing_date=datetime.date(2021, 9, 15),
subscription={'date_start': '2021-09-15', 'date_end': '2021-09-16'},
user_external_id='user:1',
adult_external_id='adult:1',
),
]
mock_subscriptions.return_value = [
{
'date_start': '2021-09-30',
'date_end': '2021-10-01',
},
]
mock_pricing_data.reset_mock()
resp = app.get(
'/api/pricing/compute/',
params={
'agenda': 'foo-bar',
'start_date': '2021-09-16',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert mock_pricing_data.call_args_list == [
mock.call(
request=mock.ANY,
pricing_date=datetime.date(2021, 9, 15),
subscription={'date_start': '2021-09-30', 'date_end': '2021-10-01'},
user_external_id='user:1',
adult_external_id='adult:1',
),
]
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data')
def test_pricing_compute_for_flat_fee_schedule_without_subscription(mock_pricing_data, app, user):
pricing = Pricing.objects.create(label='Foo bar')
agenda_pricing = AgendaPricing.objects.create(
label='Foo bar pricing',
pricing=pricing,
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=10, day=1),
flat_fee_schedule=True,
subscription_required=False,
)
app.authorization = ('Basic', ('john.doe', 'password'))
mock_pricing_data.return_value = {'foo': 'bar'}
resp = app.get(
'/api/pricing/compute/',
params={
'agenda_pricing': 'foo-bar-pricing',
'start_date': '2021-09-02',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == {'agenda_pricing': 'foo-bar-pricing', 'pricing_data': {'foo': 'bar'}}
assert mock_pricing_data.call_args_list == [
mock.call(
request=mock.ANY,
pricing_date=datetime.date(2021, 9, 1),
subscription=None,
user_external_id='user:1',
adult_external_id='adult:1',
),
]
# get_pricing_data with error
mock_pricing_data.side_effect = PricingError(details={'foo': 'error'})
resp = app.get(
'/api/pricing/compute/',
params={
'agenda_pricing': 'foo-bar-pricing',
'start_date': '2021-09-02',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == {
'agenda_pricing': 'foo-bar-pricing',
'error': 'PricingError',
'error_details': {'foo': 'error'},
}
# check with billing dates
mock_pricing_data.return_value = {'foo': 'bar'}
agenda_pricing.billingdates.create(
date_start=datetime.date(2021, 9, 1),
label='Foo 1',
)
agenda_pricing.billingdates.create(
date_start=datetime.date(2021, 9, 15),
label='Foo 2',
)
mock_pricing_data.reset_mock()
resp = app.get(
'/api/pricing/compute/',
params={
'agenda_pricing': 'foo-bar-pricing',
'start_date': '2021-09-16',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert mock_pricing_data.call_args_list == [
mock.call(
request=mock.ANY,
pricing_date=datetime.date(2021, 9, 15),
subscription=None,
user_external_id='user:1',
adult_external_id='adult:1',
),
]