<gh_stars>0
from datetime import datetime
from decimal import Decimal
from unittest import mock

import pytest
from django_countries.fields import Country
from pytz import UTC

from pretix.base.models import InvoiceAddress, Order, OrderPosition
from pretix.base.models.orders import OrderFee


@pytest.fixture
def variations(item):
    v = list()
    v.append(item.variations.create(value="ChildA1", default_price='12.00'))
    v.append(item.variations.create(value="ChildA2", default_price='13.00'))
    return v


@pytest.fixture
def variations2(item2):
    v = list()
    v.append(item2.variations.create(value="ChildB1", default_price='12.00'))
    v.append(item2.variations.create(value="ChildB2", default_price='13.00'))
    return v


@pytest.fixture
def order(event, item, taxrule):
    testtime = datetime(2017, 12, 1, 10, 0, 0, tzinfo=UTC)

    with mock.patch('django.utils.timezone.now') as mock_now:
        mock_now.return_value = testtime
        o = Order.objects.create(
            code='FOO', event=event, email='<EMAIL>',
            status=Order.STATUS_PENDING, secret="k24fiuwvu8kxz3y1",
            datetime=datetime(2017, 12, 1, 10, 0, 0, tzinfo=UTC),
            expires=datetime(2017, 12, 10, 10, 0, 0, tzinfo=UTC),
            total=23, locale='en'
        )
        o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'),
                      tax_value=Decimal('0.05'), tax_rule=taxrule)
        InvoiceAddress.objects.create(order=o, company="Sample company", country=Country('NZ'))
        return o


@pytest.fixture
def order_position(item, order, subevent, taxrule, variations):
    op = OrderPosition.objects.create(
        order=order,
        item=item,
        subevent=subevent,
        variation=variations[0],
        tax_rule=taxrule,
        tax_rate=taxrule.rate,
        tax_value=Decimal("3"),
        price=Decimal("23"),
        attendee_name_parts={'full_name': "Peter"},
        secret="z3fsn8jyufm5kpk768q69gkbyr5f4h6w"
    )
    return op


TEST_SUBEVENT_RES = {
    'active': False,
    'event': 'dummy',
    'presale_start': None,
    'date_to': None,
    'date_admission': None,
    'name': {'en': 'Foobar'},
    'date_from': '2017-12-27T10:00:00Z',
    'presale_end': None,
    'id': 1,
    'variation_price_overrides': [],
    'location': None,
    'is_public': True,
    'item_price_overrides': [],
    'meta_data': {'type': 'Workshop'}
}


@pytest.fixture
def item(event):
    return event.items.create(name="Budget Ticket", default_price=23)


@pytest.fixture
def item2(event2):
    return event2.items.create(name="Another Ticket", default_price=23)


@pytest.mark.django_db
def test_subevent_list(token_client, organizer, event, subevent):
    res = dict(TEST_SUBEVENT_RES)
    res["id"] = subevent.pk
    resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug))
    assert resp.status_code == 200
    assert [res] == resp.data['results']
    resp = token_client.get('/api/v1/organizers/{}/subevents/'.format(organizer.slug))
    assert resp.status_code == 200
    assert [res] == resp.data['results']

    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?active=false'.format(organizer.slug, event.slug))
    assert [res] == resp.data['results']
    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?active=true'.format(organizer.slug, event.slug))
    assert [] == resp.data['results']

    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?event__live=false'.format(organizer.slug, event.slug))
    assert [res] == resp.data['results']
    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?event__live=true'.format(organizer.slug, event.slug))
    assert [] == resp.data['results']

    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?ends_after=2017-12-27T09:59:59Z'.format(organizer.slug, event.slug))
    assert [res] == resp.data['results']
    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?ends_after=2017-12-27T10:01:01Z'.format(organizer.slug, event.slug))
    assert [] == resp.data['results']


@pytest.mark.django_db
def test_subevent_get(token_client, organizer, event, subevent):
    res = dict(TEST_SUBEVENT_RES)
    res["id"] = subevent.pk
    resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
                                                                                   subevent.pk))
    assert resp.status_code == 200
    assert res == resp.data


@pytest.mark.django_db
def test_subevent_create(token_client, organizer, event, subevent, meta_prop, item):
    resp = token_client.post(
        '/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
        {
            "name": {
                "de": "Demo Subevent 2020 Test",
                "en": "Demo Subevent 2020 Test"
            },
            "active": False,
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-28T10:00:00Z",
            "date_admission": None,
            "presale_start": None,
            "presale_end": None,
            "location": None,
            "item_price_overrides": [],
            "variation_price_overrides": [],
            "meta_data": {
                "type": "Workshop"
            },
        },
        format='json'
    )
    assert resp.status_code == 201
    assert not subevent.active
    assert subevent.meta_values.filter(
        property__name=meta_prop.name, value="Workshop"
    ).exists()

    resp = token_client.post(
        '/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
        {
            "name": {
                "de": "Demo Subevent 2020 Test",
                "en": "Demo Subevent 2020 Test"
            },
            "active": False,
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-28T10:00:00Z",
            "date_admission": None,
            "presale_start": None,
            "presale_end": None,
            "location": None,
            "item_price_overrides": [],
            "variation_price_overrides": [],
            "meta_data": {
                "foo": "bar"
            },
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"meta_data":["Meta data property \'foo\' does not exist."]}'

    resp = token_client.post(
        '/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
        {
            "name": {
                "de": "Demo Subevent 2020 Test",
                "en": "Demo Subevent 2020 Test"
            },
            "active": False,
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-28T10:00:00Z",
            "date_admission": None,
            "presale_start": None,
            "presale_end": None,
            "location": None,
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": "23.42"
                }
            ],
            "variation_price_overrides": [],
            "meta_data": {
                "type": "Workshop"
            },
        },
        format='json'
    )
    assert resp.status_code == 201
    assert item.default_price == Decimal('23.00')
    assert event.subevents.get(id=resp.data['id']).item_price_overrides[item.pk] == Decimal('23.42')

    resp = token_client.post(
        '/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
        {
            "name": {
                "de": "Demo Subevent 2020 Test",
                "en": "Demo Subevent 2020 Test"
            },
            "active": False,
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-28T10:00:00Z",
            "date_admission": None,
            "presale_start": None,
            "presale_end": None,
            "location": None,
            "item_price_overrides": [
                {
                    "item": 555,
                    "price": "23.42"
                }
            ],
            "variation_price_overrides": [],
            "meta_data": {
                "type": "Workshop"
            },
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"item_price_overrides":[{"item":["Invalid pk \\"555\\" - object does not exist."]}]}'


@pytest.mark.django_db
def test_subevent_update(token_client, organizer, event, subevent, item, item2, meta_prop, variations, variations2):
    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "date_from": "2018-12-27T10:00:00Z",
            "date_to": "2018-12-28T10:00:00Z",
        },
        format='json'
    )
    assert resp.status_code == 200
    subevent = event.subevents.get(id=subevent.id)
    assert subevent.date_from == datetime(2018, 12, 27, 10, 0, tzinfo=UTC)
    assert subevent.date_to == datetime(2018, 12, 28, 10, 0, tzinfo=UTC)

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-26T10:00:00Z"
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"non_field_errors":["The event cannot end before it starts."]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "presale_start": "2017-12-27T10:00:00Z",
            "presale_end": "2017-12-26T10:00:00Z"
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"non_field_errors":["The event\'s presale cannot end before it starts."]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "meta_data": {
                meta_prop.name: "Conference"
            }
        },
        format='json'
    )
    assert resp.status_code == 200
    assert organizer.events.get(slug=event.slug).subevents.get(id=resp.data['id']).meta_values.filter(
        property__name=meta_prop.name, value="Conference"
    ).exists()

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "meta_data": {
            }
        },
        format='json'
    )
    assert resp.status_code == 200
    assert not subevent.meta_values.filter(
        property__name=meta_prop.name
    ).exists()

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "meta_data": {
                "test": "test"
            }
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"meta_data":["Meta data property \'test\' does not exist."]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert subevent.items.get(id=item.pk).default_price == Decimal('23.00')
    assert subevent.item_price_overrides[item.pk] == Decimal('99.99')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": "88.88"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('88.88')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": None
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": "12.34"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('12.34')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": 123,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"item_price_overrides":[{"item":["Invalid pk \\"123\\" - object does not exist."]}]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item2.id,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"non_field_errors":["One or more items do not belong to this event."]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations[0].pk,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert subevent.variations.get(id=variations[0].pk).default_price == Decimal('12.00')
    assert subevent.var_price_overrides[variations[0].pk] == Decimal('99.99')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations[0].pk,
                    "price": "88.88"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('88.88')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations[0].pk,
                    "price": None
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations[0].pk,
                    "price": "12.34"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('12.34')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": 123,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"variation_price_overrides":[{"variation":["Invalid pk \\"123\\" - object does not exist."]}]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations2[0].pk,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"non_field_errors":["One or more variations do not belong to this event."]}'


@pytest.mark.django_db
def test_subevent_detail(token_client, organizer, event, subevent):
    res = dict(TEST_SUBEVENT_RES)
    res["id"] = subevent.pk
    resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
                                                                                   subevent.pk))
    assert resp.status_code == 200
    assert res == resp.data


@pytest.mark.django_db
def test_subevent_delete(token_client, organizer, event, subevent):
    resp = token_client.delete('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
                                                                                      subevent.pk))
    assert resp.status_code == 204
    assert not event.subevents.filter(pk=subevent.id).exists()


@pytest.mark.django_db
def test_subevent_with_order_position_not_delete(token_client, organizer, event, subevent, item, order_position):
    resp = token_client.delete('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
                                                                                      subevent.pk))
    assert resp.status_code == 403
    assert resp.content.decode() == '{"detail":"The sub-event can not be deleted as it has already been used in ' \
                                    'orders. Please set \'active\' to false instead to hide it from users."}'
    assert event.subevents.filter(pk=subevent.id).exists()

from datetime import datetime
from decimal import Decimal
from unittest import mock

import pytest
from django_countries.fields import Country
from pytz import UTC

from pretix.base.models import InvoiceAddress, Order, OrderPosition
from pretix.base.models.orders import OrderFee


@pytest.fixture
def variations(item):
    v = list()
    v.append(item.variations.create(value="ChildA1", default_price='12.00'))
    v.append(item.variations.create(value="ChildA2", default_price='13.00'))
    return v


@pytest.fixture
def variations2(item2):
    v = list()
    v.append(item2.variations.create(value="ChildB1", default_price='12.00'))
    v.append(item2.variations.create(value="ChildB2", default_price='13.00'))
    return v


@pytest.fixture
def order(event, item, taxrule):
    testtime = datetime(2017, 12, 1, 10, 0, 0, tzinfo=UTC)

    with mock.patch('django.utils.timezone.now') as mock_now:
        mock_now.return_value = testtime
        o = Order.objects.create(
            code='FOO', event=event, email='<EMAIL>',
            status=Order.STATUS_PENDING, secret="k24fiuwvu8kxz3y1",
            datetime=datetime(2017, 12, 1, 10, 0, 0, tzinfo=UTC),
            expires=datetime(2017, 12, 10, 10, 0, 0, tzinfo=UTC),
            total=23, locale='en'
        )
        o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'),
                      tax_value=Decimal('0.05'), tax_rule=taxrule)
        InvoiceAddress.objects.create(order=o, company="Sample company", country=Country('NZ'))
        return o


@pytest.fixture
def order_position(item, order, subevent, taxrule, variations):
    op = OrderPosition.objects.create(
        order=order,
        item=item,
        subevent=subevent,
        variation=variations[0],
        tax_rule=taxrule,
        tax_rate=taxrule.rate,
        tax_value=Decimal("3"),
        price=Decimal("23"),
        attendee_name_parts={'full_name': "Peter"},
        secret="z3fsn8jyufm5kpk768q69gkbyr5f4h6w"
    )
    return op


TEST_SUBEVENT_RES = {
    'active': False,
    'event': 'dummy',
    'presale_start': None,
    'date_to': None,
    'date_admission': None,
    'name': {'en': 'Foobar'},
    'date_from': '2017-12-27T10:00:00Z',
    'presale_end': None,
    'id': 1,
    'variation_price_overrides': [],
    'location': None,
    'is_public': True,
    'item_price_overrides': [],
    'meta_data': {'type': 'Workshop'}
}


@pytest.fixture
def item(event):
    return event.items.create(name="Budget Ticket", default_price=23)


@pytest.fixture
def item2(event2):
    return event2.items.create(name="Another Ticket", default_price=23)


@pytest.mark.django_db
def test_subevent_list(token_client, organizer, event, subevent):
    res = dict(TEST_SUBEVENT_RES)
    res["id"] = subevent.pk
    resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug))
    assert resp.status_code == 200
    assert [res] == resp.data['results']
    resp = token_client.get('/api/v1/organizers/{}/subevents/'.format(organizer.slug))
    assert resp.status_code == 200
    assert [res] == resp.data['results']

    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?active=false'.format(organizer.slug, event.slug))
    assert [res] == resp.data['results']
    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?active=true'.format(organizer.slug, event.slug))
    assert [] == resp.data['results']

    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?event__live=false'.format(organizer.slug, event.slug))
    assert [res] == resp.data['results']
    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?event__live=true'.format(organizer.slug, event.slug))
    assert [] == resp.data['results']

    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?ends_after=2017-12-27T09:59:59Z'.format(organizer.slug, event.slug))
    assert [res] == resp.data['results']
    resp = token_client.get(
        '/api/v1/organizers/{}/events/{}/subevents/?ends_after=2017-12-27T10:01:01Z'.format(organizer.slug, event.slug))
    assert [] == resp.data['results']


@pytest.mark.django_db
def test_subevent_get(token_client, organizer, event, subevent):
    res = dict(TEST_SUBEVENT_RES)
    res["id"] = subevent.pk
    resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
                                                                                   subevent.pk))
    assert resp.status_code == 200
    assert res == resp.data


@pytest.mark.django_db
def test_subevent_create(token_client, organizer, event, subevent, meta_prop, item):
    resp = token_client.post(
        '/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
        {
            "name": {
                "de": "Demo Subevent 2020 Test",
                "en": "Demo Subevent 2020 Test"
            },
            "active": False,
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-28T10:00:00Z",
            "date_admission": None,
            "presale_start": None,
            "presale_end": None,
            "location": None,
            "item_price_overrides": [],
            "variation_price_overrides": [],
            "meta_data": {
                "type": "Workshop"
            },
        },
        format='json'
    )
    assert resp.status_code == 201
    assert not subevent.active
    assert subevent.meta_values.filter(
        property__name=meta_prop.name, value="Workshop"
    ).exists()

    resp = token_client.post(
        '/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
        {
            "name": {
                "de": "Demo Subevent 2020 Test",
                "en": "Demo Subevent 2020 Test"
            },
            "active": False,
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-28T10:00:00Z",
            "date_admission": None,
            "presale_start": None,
            "presale_end": None,
            "location": None,
            "item_price_overrides": [],
            "variation_price_overrides": [],
            "meta_data": {
                "foo": "bar"
            },
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"meta_data":["Meta data property \'foo\' does not exist."]}'

    resp = token_client.post(
        '/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
        {
            "name": {
                "de": "Demo Subevent 2020 Test",
                "en": "Demo Subevent 2020 Test"
            },
            "active": False,
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-28T10:00:00Z",
            "date_admission": None,
            "presale_start": None,
            "presale_end": None,
            "location": None,
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": "23.42"
                }
            ],
            "variation_price_overrides": [],
            "meta_data": {
                "type": "Workshop"
            },
        },
        format='json'
    )
    assert resp.status_code == 201
    assert item.default_price == Decimal('23.00')
    assert event.subevents.get(id=resp.data['id']).item_price_overrides[item.pk] == Decimal('23.42')

    resp = token_client.post(
        '/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
        {
            "name": {
                "de": "Demo Subevent 2020 Test",
                "en": "Demo Subevent 2020 Test"
            },
            "active": False,
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-28T10:00:00Z",
            "date_admission": None,
            "presale_start": None,
            "presale_end": None,
            "location": None,
            "item_price_overrides": [
                {
                    "item": 555,
                    "price": "23.42"
                }
            ],
            "variation_price_overrides": [],
            "meta_data": {
                "type": "Workshop"
            },
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"item_price_overrides":[{"item":["Invalid pk \\"555\\" - object does not exist."]}]}'


@pytest.mark.django_db
def test_subevent_update(token_client, organizer, event, subevent, item, item2, meta_prop, variations, variations2):
    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "date_from": "2018-12-27T10:00:00Z",
            "date_to": "2018-12-28T10:00:00Z",
        },
        format='json'
    )
    assert resp.status_code == 200
    subevent = event.subevents.get(id=subevent.id)
    assert subevent.date_from == datetime(2018, 12, 27, 10, 0, tzinfo=UTC)
    assert subevent.date_to == datetime(2018, 12, 28, 10, 0, tzinfo=UTC)

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "date_from": "2017-12-27T10:00:00Z",
            "date_to": "2017-12-26T10:00:00Z"
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"non_field_errors":["The event cannot end before it starts."]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "presale_start": "2017-12-27T10:00:00Z",
            "presale_end": "2017-12-26T10:00:00Z"
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"non_field_errors":["The event\'s presale cannot end before it starts."]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "meta_data": {
                meta_prop.name: "Conference"
            }
        },
        format='json'
    )
    assert resp.status_code == 200
    assert organizer.events.get(slug=event.slug).subevents.get(id=resp.data['id']).meta_values.filter(
        property__name=meta_prop.name, value="Conference"
    ).exists()

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "meta_data": {
            }
        },
        format='json'
    )
    assert resp.status_code == 200
    assert not subevent.meta_values.filter(
        property__name=meta_prop.name
    ).exists()

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "meta_data": {
                "test": "test"
            }
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"meta_data":["Meta data property \'test\' does not exist."]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert subevent.items.get(id=item.pk).default_price == Decimal('23.00')
    assert subevent.item_price_overrides[item.pk] == Decimal('99.99')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": "88.88"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('88.88')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": None
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item.pk,
                    "price": "12.34"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('12.34')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": 123,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"item_price_overrides":[{"item":["Invalid pk \\"123\\" - object does not exist."]}]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "item_price_overrides": [
                {
                    "item": item2.id,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"non_field_errors":["One or more items do not belong to this event."]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations[0].pk,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert subevent.variations.get(id=variations[0].pk).default_price == Decimal('12.00')
    assert subevent.var_price_overrides[variations[0].pk] == Decimal('99.99')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations[0].pk,
                    "price": "88.88"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('88.88')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations[0].pk,
                    "price": None
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations[0].pk,
                    "price": "12.34"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('12.34')

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [],
        },
        format='json'
    )
    assert resp.status_code == 200
    assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": 123,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"variation_price_overrides":[{"variation":["Invalid pk \\"123\\" - object does not exist."]}]}'

    resp = token_client.patch(
        '/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
        {
            "variation_price_overrides": [
                {
                    "variation": variations2[0].pk,
                    "price": "99.99"
                }
            ],
        },
        format='json'
    )
    assert resp.status_code == 400
    assert resp.content.decode() == '{"non_field_errors":["One or more variations do not belong to this event."]}'


@pytest.mark.django_db
def test_subevent_detail(token_client, organizer, event, subevent):
    res = dict(TEST_SUBEVENT_RES)
    res["id"] = subevent.pk
    resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
                                                                                   subevent.pk))
    assert resp.status_code == 200
    assert res == resp.data


@pytest.mark.django_db
def test_subevent_delete(token_client, organizer, event, subevent):
    resp = token_client.delete('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
                                                                                      subevent.pk))
    assert resp.status_code == 204
    assert not event.subevents.filter(pk=subevent.id).exists()


@pytest.mark.django_db
def test_subevent_with_order_position_not_delete(token_client, organizer, event, subevent, item, order_position):
    resp = token_client.delete('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
                                                                                      subevent.pk))
    assert resp.status_code == 403
    assert resp.content.decode() == '{"detail":"The sub-event can not be deleted as it has already been used in ' \
                                    'orders. Please set \'active\' to false instead to hide it from users."}'
    assert event.subevents.filter(pk=subevent.id).exists()