Exemplo n.º 1
0
async def test_set_password(cli, url, factory: Factory, db_conn, login):
    await factory.create_company()
    await factory.create_user()

    pw_before = await db_conn.fetchval('SELECT password_hash FROM users WHERE id=$1', factory.user_id)

    with pytest.raises(AssertionError):
        await login(password='******')

    data = {
        'password1': 'testing-new-password',
        'password2': 'testing-new-password',
        'token': encrypt_json(cli.app['main_app'], factory.user_id),
    }
    r = await cli.json_post(url('set-password'), data=data, origin_null=True)
    assert r.status == 200, await r.text()
    data = await r.json()
    assert data == {
        'status': 'success',
        'auth_token': RegexStr(r'.+'),
        'user': {
            'id': factory.user_id,
            'first_name': 'Frank',
            'last_name': 'Spencer',
            'email': '*****@*****.**',
            'role': 'admin',
            'status': 'active',
        },
    }
    pw_after = await db_conn.fetchval('SELECT password_hash FROM users WHERE id=$1', factory.user_id)
    assert pw_after != pw_before
    await login(password='******', captcha=True)
Exemplo n.º 2
0
async def test_set_password_mismatch(cli, url, factory: Factory):
    await factory.create_company()
    await factory.create_user()

    data = {
        'password1': 'testing-new-password',
        'password2': 'testing-new-password2',
        'token': encrypt_json(cli.app['main_app'], factory.user_id),
    }
    r = await cli.json_post(url('set-password'), data=data, origin_null=True)
    assert r.status == 400, await r.text()

    data = await r.json()
    assert data == {
        'message': 'Invalid Data',
        'details': [
            {
                'loc': [
                    'password2',
                ],
                'msg': 'passwords do not match',
                'type': 'value_error',
            },
        ],
    }
Exemplo n.º 3
0
async def test_buy_offline_other_admin(cli, url, dummy_server, factory: Factory, login, db_conn):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user()
    await factory.create_event(price=10)

    u2 = await factory.create_user(email='*****@*****.**')
    await login('*****@*****.**')

    res: Reservation = await factory.create_reservation(u2)
    app = cli.app['main_app']

    data = dict(
        booking_token=encrypt_json(app, res.dict()),
        book_action='buy-tickets-offline',
    )
    r = await cli.json_post(url('event-book-tickets'), data=data)
    assert r.status == 200, await r.text()

    assert dummy_server.app['log'] == [
        (
            'email_send_endpoint',
            'Subject: "The Event Name Ticket Confirmation", To: "Frank Spencer <*****@*****.**>"',
        ),
    ]
    assert 0 == await db_conn.fetchval("SELECT COUNT(*) FROM actions WHERE type='book-free-tickets'")
    assert 1 == await db_conn.fetchval("SELECT COUNT(*) FROM actions WHERE type='buy-tickets-offline'")
Exemplo n.º 4
0
def successful_login(user, app, headers_=None):
    auth_session = {
        'user_id': user['id'],
        'user_role': user['role'],
        'last_active': int(time())
    }
    auth_token = encrypt_json(app, auth_session)
    return json_response(status='success',
                         auth_token=auth_token,
                         user=user,
                         headers_=headers_)
Exemplo n.º 5
0
async def test_book_offline(donorfy: DonorfyActor, factory: Factory, dummy_server, cli, url, login):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user(role='host')
    await factory.create_event(price=10)

    await login()

    res = await factory.create_reservation()
    app = cli.app['main_app']

    data = dict(booking_token=encrypt_json(app, res.dict()), book_action='buy-tickets-offline')
    r = await cli.json_post(url('event-book-tickets'), data=data)
    assert r.status == 200, await r.text()
    assert 'POST donorfy_api_root/standard/transactions' not in dummy_server.app['post_data']
Exemplo n.º 6
0
async def test_buy_offline_host(cli, url, factory: Factory, login, db_conn):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user(role='host')
    await factory.create_event(price=10)

    await login()

    res: Reservation = await factory.create_reservation()
    app = cli.app['main_app']

    data = dict(booking_token=encrypt_json(app, res.dict()), book_action='buy-tickets-offline')
    r = await cli.json_post(url('event-book-tickets'), data=data)
    assert r.status == 200, await r.text()
    assert 0 == await db_conn.fetchval("SELECT COUNT(*) FROM actions WHERE type='book-free-tickets'")
    assert 1 == await db_conn.fetchval("SELECT COUNT(*) FROM actions WHERE type='buy-tickets-offline'")
    assert 0 == await db_conn.fetchval("SELECT COUNT(*) FROM actions WHERE type='buy-tickets'")
Exemplo n.º 7
0
async def test_book_free_with_price(cli, url, factory: Factory):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user()
    await factory.create_event(price=10)

    res: Reservation = await factory.create_reservation()
    app = cli.app['main_app']

    data = dict(booking_token=encrypt_json(app, res.dict()), book_action='book-free-tickets')
    r = await cli.json_post(url('event-book-tickets'), data=data)
    assert r.status == 400, await r.text()

    data = await r.json()
    assert data == {
        'message': 'booking not free',
    }
Exemplo n.º 8
0
async def test_cancel_reservation(cli, url, db_conn, factory: Factory):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user()
    await factory.create_event(price=12.5)

    res = await factory.create_reservation()

    assert 1 == await db_conn.fetchval('SELECT COUNT(*) FROM tickets')
    assert 1 == await db_conn.fetchval('SELECT tickets_taken FROM events')

    booking_token = encrypt_json(cli.app['main_app'], res.dict())
    r = await cli.json_post(url('event-cancel-reservation'), data={'booking_token': booking_token})
    assert r.status == 200, await r.text()

    assert 0 == await db_conn.fetchval('SELECT COUNT(*) FROM tickets')
    assert 0 == await db_conn.fetchval('SELECT tickets_taken FROM events')
Exemplo n.º 9
0
async def test_set_password_reuse_token(cli, url, factory: Factory):
    await factory.create_company()
    await factory.create_user()

    data = {
        'password1': 'testing-new-password',
        'password2': 'testing-new-password',
        'token': encrypt_json(cli.app['main_app'], factory.user_id),
    }
    r = await cli.json_post(url('set-password'), data=data, origin_null=True)
    assert r.status == 200, await r.text()

    r = await cli.json_post(url('set-password'), data=data, origin_null=True)
    assert r.status == 470, await r.text()
    data = await r.json()
    assert data == {
        'message': 'This password reset link has already been used.',
    }
Exemplo n.º 10
0
async def test_book_free_no_fee(donorfy: DonorfyActor, factory: Factory,
                                dummy_server, cli, url, login):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user(role='host')
    await factory.create_event(price=10)

    await login()

    res = await factory.create_reservation()
    app = cli.app['main_app']

    data = dict(
        booking_token=encrypt_json(app, res.dict()),
        book_action='buy-tickets-offline',
    )
    r = await cli.json_post(url('event-book-tickets'), data=data)
    assert r.status == 200, await r.text()
    trans_data = dummy_server.app['post_data'][
        'POST donorfy_api_root/standard/transactions']
    assert len(trans_data) == 1
    assert trans_data[0] == {
        'ExistingConstituentId': '123456',
        'Channel': 'nosht-supper-clubs',
        'Currency': 'gbp',
        'Campaign': 'supper-clubs:the-event-name',
        'PaymentMethod': 'Offline Payment',
        'Product': 'Event Ticket(s)',
        'Fund': 'Unrestricted General',
        'Department': '220 Ticket Sales',
        'BankAccount': 'Unrestricted Account',
        'DatePaid': CloseToNow(),
        'Amount': 10.0,
        'ProcessingCostsAmount': 0,
        'Quantity': 1,
        'Acknowledgement': 'supper-clubs-thanks',
        'AcknowledgementText': RegexStr('Ticket ID: .*'),
        'Reference': 'Events.HUF:supper-clubs the-event-name',
        'AddGiftAidDeclaration': False,
        'GiftAidClaimed': False,
    }
Exemplo n.º 11
0
async def test_buy_offline_other_not_admin(cli, url, dummy_server, factory: Factory, login, db_conn):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user()
    await factory.create_event(price=10)

    u2 = await factory.create_user(email='*****@*****.**', role='host')
    await login('*****@*****.**')

    res: Reservation = await factory.create_reservation(u2)
    app = cli.app['main_app']

    data = dict(booking_token=encrypt_json(app, res.dict()), book_action='buy-tickets-offline')
    r = await cli.json_post(url('event-book-tickets'), data=data)
    assert r.status == 400, await r.text()
    assert {'message': 'to buy tickets offline you must be the host or an admin'} == await r.json()

    assert dummy_server.app['log'] == []
    assert 0 == await db_conn.fetchval("SELECT COUNT(*) FROM actions WHERE type='book-free-tickets'")
    assert 0 == await db_conn.fetchval("SELECT COUNT(*) FROM actions WHERE type='buy-tickets-offline'")
    assert 0 == await db_conn.fetchval("SELECT COUNT(*) FROM actions WHERE type='buy-tickets'")
Exemplo n.º 12
0
async def test_waiting_list_book_free(cli, url, login, factory: Factory, db_conn):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user()
    await factory.create_event(price=None, status='published')

    await login()

    assert await db_conn.fetchval('select count(*) from waiting_list') == 0

    r = await cli.json_post(url('event-waiting-list-add', id=factory.event_id))
    assert r.status == 200, await r.text()

    assert await db_conn.fetchval('select count(*) from waiting_list') == 1

    res: Reservation = await factory.create_reservation()
    app = cli.app['main_app']

    data = dict(booking_token=encrypt_json(app, res.dict()), book_action='book-free-tickets')
    r = await cli.json_post(url('event-book-tickets'), data=data)
    assert r.status == 200, await r.text()

    assert await db_conn.fetchval('select count(*) from waiting_list') == 0
Exemplo n.º 13
0
async def test_stripe_existing_customer_card(cli, db_conn, stripe_factory: Factory):
    await stripe_factory.create_company(stripe_public_key=stripe_public_key, stripe_secret_key=stripe_secret_key)
    await stripe_factory.create_cat()
    await stripe_factory.create_user()
    await stripe_factory.create_event(ticket_limit=10)

    res: Reservation = await stripe_factory.create_reservation()
    app = cli.app['main_app']

    customers = await stripe_request(app, BasicAuth(stripe_secret_key), 'get', 'customers?limit=1')
    customer = customers['data'][0]
    customer_id = customer['id']
    await db_conn.execute('UPDATE users SET stripe_customer_id=$1 WHERE id=$2', customer_id, stripe_factory.user_id)

    m = StripePayModel(
        stripe_token='tok_visa',
        stripe_client_ip='0.0.0.0',
        stripe_card_ref='{last4}-{exp_year}-{exp_month}'.format(**customer['sources']['data'][0]),
        booking_token=encrypt_json(app, res.dict()),
    )

    await stripe_pay(m, stripe_factory.company_id, stripe_factory.user_id, app, db_conn)

    new_customer_id = await db_conn.fetchval('SELECT stripe_customer_id FROM users WHERE id=$1', stripe_factory.user_id)
    assert new_customer_id == customer_id

    extra = await db_conn.fetchval("SELECT extra FROM actions WHERE type='buy-tickets'")

    extra = json.loads(extra)
    assert extra == {
        'new_card': False,
        'new_customer': False,
        'charge_id': RegexStr('ch_.+'),
        'card_expiry': RegexStr('\d+/\d+'),
        'card_last4': '4242',
    }
Exemplo n.º 14
0
    async def execute(self, m: Model):  # noqa: C901 (ignore complexity)
        event_id = int(self.request.match_info['id'])
        ticket_count = len(m.tickets)

        if ticket_count > self.settings.max_tickets:
            raise JsonErrors.HTTPBadRequest(
                message='Too many tickets reserved')

        user_id = self.session['user_id']

        status, external_ticket_url, event_name, cover_costs_percentage = await self.conn.fetchrow(
            """
            SELECT e.status, e.external_ticket_url, e.name, c.cover_costs_percentage
            FROM events AS e
            JOIN categories c on e.category = c.id
            WHERE c.company=$1 AND e.id=$2
            """, self.request['company_id'], event_id)

        if status != 'published':
            raise JsonErrors.HTTPBadRequest(message='Event not published')

        if external_ticket_url is not None:
            raise JsonErrors.HTTPBadRequest(
                message='Cannot reserve ticket for an externally ticketed event'
            )

        r = await self.conn.fetchrow(
            'SELECT price FROM ticket_types WHERE event=$1 AND id=$2',
            event_id, m.ticket_type)
        if not r:
            raise JsonErrors.HTTPBadRequest(message='Ticket type not found')
        item_price, *_ = r

        if self.settings.ticket_reservation_precheck:  # should only be false during CheckViolationError tests
            tickets_remaining = await self.conn.fetchval(
                'SELECT check_tickets_remaining($1, $2)', event_id,
                self.settings.ticket_ttl)
            if tickets_remaining is not None and ticket_count > tickets_remaining:
                raise JsonErrors.HTTP470(
                    message=f'only {tickets_remaining} tickets remaining',
                    tickets_remaining=tickets_remaining)

        total_price, item_extra_donated = None, None
        if item_price:
            total_price = item_price * ticket_count
            if cover_costs_percentage and m.tickets[0].cover_costs:
                item_extra_donated = item_price * cover_costs_percentage / 100
                total_price += item_extra_donated * ticket_count

        try:
            async with self.conn.transaction():
                update_user_preferences = await self.create_users(m.tickets)

                action_id = await record_action_id(self.request,
                                                   user_id,
                                                   ActionTypes.reserve_tickets,
                                                   event_id=event_id)
                ticket_values = [
                    Values(
                        email=t.email and t.email.lower(),
                        first_name=t.first_name,
                        last_name=t.last_name,
                        extra_info=t.extra_info or None,
                    ) for t in m.tickets
                ]

                await self.conn.execute_b(
                    """
                    WITH v (email, first_name, last_name, extra_info) AS (VALUES :values)
                    INSERT INTO tickets (event, reserve_action, ticket_type, price, extra_donated, user_id,
                      first_name, last_name, extra_info)
                    SELECT :event, :reserve_action, :ticket_type, :price, :extra_donated, u.id,
                      v.first_name, v.last_name, v.extra_info FROM v
                    LEFT JOIN users AS u ON v.email=u.email AND u.company=:company_id
                    """,
                    event=event_id,
                    reserve_action=action_id,
                    ticket_type=m.ticket_type,
                    price=item_price,
                    extra_donated=item_extra_donated,
                    company_id=self.request['company_id'],
                    values=MultipleValues(*ticket_values),
                )
                await self.conn.execute(
                    'SELECT check_tickets_remaining($1, $2)', event_id,
                    self.settings.ticket_ttl)
        except CheckViolationError as exc:
            if exc.constraint_name != 'ticket_limit_check':  # pragma: no branch
                raise  # pragma: no cover
            logger.warning('CheckViolationError: %s', exc)
            raise JsonErrors.HTTPBadRequest(
                message='insufficient tickets remaining')

        res = Reservation(
            user_id=user_id,
            action_id=action_id,
            price_cent=total_price and int(total_price * 100),
            event_id=event_id,
            ticket_count=ticket_count,
            event_name=event_name,
        )
        if total_price:
            client_secret = await stripe_buy_intent(res,
                                                    self.request['company_id'],
                                                    self.app, self.conn)
        else:
            client_secret = None
        if update_user_preferences:
            # has to happen after the transactions is finished
            await self.app['donorfy_actor'].update_user(
                self.request['session']['user_id'], update_user=False)
        return {
            'booking_token':
            encrypt_json(self.app, res.dict()),
            'action_id':
            action_id,
            'ticket_count':
            ticket_count,
            'item_price':
            item_price and float(item_price),
            'extra_donated':
            item_extra_donated and float(item_extra_donated * ticket_count),
            'total_price':
            total_price and float(total_price),
            'timeout':
            int(time()) + self.settings.ticket_ttl - 30,
            'client_secret':
            client_secret,
        }
Exemplo n.º 15
0
    async def execute(self, m: Model):
        event_id = int(self.request.match_info['id'])
        ticket_count = len(m.tickets)
        if ticket_count < 1:
            raise JsonErrors.HTTPBadRequest(message='at least one ticket must be purchased')

        status, event_price, event_name = await self.conn.fetchrow(
            """
            SELECT e.status, e.price, e.name
            FROM events AS e
            JOIN categories c on e.category = c.id
            WHERE c.company=$1 AND e.id=$2
            """,
            self.request['company_id'], event_id
        )
        if status != 'published':
            raise JsonErrors.HTTPBadRequest(message='Event not published')

        tickets_remaining = await self.conn.fetchval(
            'SELECT check_tickets_remaining($1, $2)',
            event_id, self.settings.ticket_ttl
        )

        if tickets_remaining is not None and ticket_count > tickets_remaining:
            raise JsonErrors.HTTP470(message=f'only {tickets_remaining} tickets remaining',
                                     tickets_remaining=tickets_remaining)

        # TODO check user isn't already booked

        try:
            async with self.conn.transaction():
                user_lookup = await self.create_users(m.tickets)

                action_id = await record_action_id(self.request, self.session['user_id'], ActionTypes.reserve_tickets)
                await self.conn.execute_b(
                    'INSERT INTO tickets (:values__names) VALUES :values',
                    values=MultipleValues(*[
                        Values(
                            event=event_id,
                            user_id=user_lookup[t.email.lower()] if t.email else None,
                            reserve_action=action_id,
                            extra=to_json_if(t.dict(include={'dietary_req', 'extra_info'})),
                        )
                        for t in m.tickets
                    ])
                )
                await self.conn.execute('SELECT check_tickets_remaining($1, $2)', event_id, self.settings.ticket_ttl)
        except CheckViolationError as e:
            logger.warning('CheckViolationError: %s', e)
            raise JsonErrors.HTTPBadRequest(message='insufficient tickets remaining')

        user = await self.conn.fetchrow(
            """
            SELECT id, full_name(first_name, last_name, email) AS name, email, role
            FROM users
            WHERE id=$1
            """,
            self.session['user_id']
        )
        # TODO needs to work when the event is free
        price_cent = int(event_price * ticket_count * 100)
        res = Reservation(
            user_id=self.session['user_id'],
            action_id=action_id,
            price_cent=price_cent,
            event_id=event_id,
            ticket_count=ticket_count,
            event_name=event_name,
        )
        return {
            'booking_token': encrypt_json(self.app, res.dict()),
            'ticket_count': ticket_count,
            'item_price_cent': int(event_price * 100),
            'total_price_cent': price_cent,
            'user': dict(user),
            'timeout': int(time()) + self.settings.ticket_ttl,
        }
Exemplo n.º 16
0
async def test_stripe_successful(cli, db_conn, stripe_factory: Factory):
    await stripe_factory.create_company(stripe_public_key=stripe_public_key, stripe_secret_key=stripe_secret_key)
    await stripe_factory.create_cat()
    await stripe_factory.create_user()
    await stripe_factory.create_event(ticket_limit=10)

    res: Reservation = await stripe_factory.create_reservation()
    app = cli.app['main_app']

    m = StripePayModel(
        stripe_token='tok_visa',
        stripe_client_ip='0.0.0.0',
        stripe_card_ref='4242-32-01',
        booking_token=encrypt_json(app, res.dict()),
    )
    await db_conn.execute('SELECT check_tickets_remaining($1, 10)', res.event_id)
    customer_id = await db_conn.fetchval('SELECT stripe_customer_id FROM users WHERE id=$1', stripe_factory.user_id)
    assert customer_id is None

    ticket_limit, tickets_taken = await db_conn.fetchrow(
        'SELECT ticket_limit, tickets_taken FROM events where id=$1',
        stripe_factory.event_id
    )
    assert (ticket_limit, tickets_taken) == (10, 1)

    await stripe_pay(m, stripe_factory.company_id, stripe_factory.user_id, app, db_conn)

    customer_id = await db_conn.fetchval('SELECT stripe_customer_id FROM users WHERE id=$1', stripe_factory.user_id)
    assert customer_id is not None
    assert customer_id.startswith('cus_')

    ticket_limit, tickets_taken = await db_conn.fetchrow(
        'SELECT ticket_limit, tickets_taken FROM events where id=$1',
        stripe_factory.event_id
    )
    assert (ticket_limit, tickets_taken) == (10, 1)

    paid_action = await db_conn.fetchrow("SELECT * FROM actions WHERE type='buy-tickets'")

    assert paid_action['company'] == stripe_factory.company_id
    assert paid_action['user_id'] == stripe_factory.user_id
    assert paid_action['ts'] == CloseToNow(delta=10)
    extra = json.loads(paid_action['extra'])
    assert extra == {
        'new_card': True,
        'new_customer': True,
        'charge_id': RegexStr('ch_.+'),
        'card_expiry': RegexStr('\d+/\d+'),
        'card_last4': '4242',
    }

    charge = await stripe_request(app, BasicAuth(stripe_secret_key), 'get', f'charges/{extra["charge_id"]}')
    # debug(d)
    assert charge['amount'] == 10_00
    assert charge['description'] == f'1 tickets for Foobar ({stripe_factory.event_id})'
    assert charge['metadata'] == {
        'event': str(stripe_factory.event_id),
        'tickets_bought': '1',
        'paid_action': str(paid_action['id']),
        'reserve_action': str(res.action_id),
    }
    assert charge['source']['last4'] == '4242'
Exemplo n.º 17
0
async def test_ticket_export(cli, url, login, factory: Factory, db_conn):
    await factory.create_company()
    await factory.create_cat()
    await factory.create_user()
    await factory.create_event(
        price=12.34,
        status='published',
        location_name='Testing Location',
        location_lat=51.5,
        location_lng=-0.5,
        duration=timedelta(hours=2, minutes=45),
    )
    await factory.buy_tickets(await factory.create_reservation())
    await factory.buy_tickets(await factory.create_reservation())

    ticket_id = await db_conn.fetchval(
        'SELECT id FROM tickets ORDER BY id DESC LIMIT 1')
    await db_conn.execute('UPDATE tickets SET user_id=NULL WHERE id=$1',
                          ticket_id)

    admin_user_id = await factory.create_user(email='*****@*****.**',
                                              first_name='Admin',
                                              last_name='Istrator')
    await login(email='*****@*****.**')
    res = await factory.create_reservation(admin_user_id)
    data = dict(booking_token=encrypt_json(cli.app['main_app'], res.dict()),
                book_action='buy-tickets-offline')
    r = await cli.json_post(url('event-book-tickets'), data=data)
    assert r.status == 200, await r.text()

    r = await cli.get(url('export', type='tickets'))
    assert r.status == 200
    text = await r.text()
    data = [dict(r) for r in DictReader(StringIO(text))]
    ticket_type = str(await db_conn.fetchval('SELECT id FROM ticket_types'))
    assert data == [
        {
            'id': RegexStr(r'\d+'),
            'ticket_first_name': '',
            'ticket_last_name': '',
            'status': 'booked',
            'booking_action': 'buy-tickets',
            'price': '12.34',
            'extra_donated': '',
            'created_ts': RegexStr(r'\d{4}.*'),
            'extra_info': '',
            'ticket_type_id': ticket_type,
            'ticket_type_name': 'Standard',
            'event_id': str(factory.event_id),
            'event_slug': 'the-event-name',
            'guest_user_id': str(factory.user_id),
            'guest_first_name': 'Frank',
            'guest_last_name': 'Spencer',
            'buyer_user_id': str(factory.user_id),
            'buyer_first_name': 'Frank',
            'buyer_last_name': 'Spencer',
        },
        {
            'id': RegexStr(r'\d+'),
            'ticket_first_name': '',
            'ticket_last_name': '',
            'status': 'booked',
            'booking_action': 'buy-tickets',
            'price': '12.34',
            'extra_donated': '',
            'created_ts': RegexStr(r'\d{4}.*'),
            'extra_info': '',
            'ticket_type_id': ticket_type,
            'ticket_type_name': 'Standard',
            'event_id': str(factory.event_id),
            'event_slug': 'the-event-name',
            'guest_user_id': '',
            'guest_first_name': '',
            'guest_last_name': '',
            'buyer_user_id': str(factory.user_id),
            'buyer_first_name': 'Frank',
            'buyer_last_name': 'Spencer',
        },
        {
            'id': RegexStr(r'\d+'),
            'ticket_first_name': '',
            'ticket_last_name': '',
            'status': 'booked',
            'booking_action': 'buy-tickets-offline',
            'price': '',
            'extra_donated': '',
            'created_ts': RegexStr(r'\d{4}.*'),
            'extra_info': '',
            'ticket_type_id': ticket_type,
            'ticket_type_name': 'Standard',
            'event_id': str(factory.event_id),
            'event_slug': 'the-event-name',
            'guest_user_id': str(admin_user_id),
            'guest_first_name': 'Admin',
            'guest_last_name': 'Istrator',
            'buyer_user_id': str(admin_user_id),
            'buyer_first_name': 'Admin',
            'buyer_last_name': 'Istrator',
        },
    ]