Exemple #1
0
def test_rules_variation(item, position, clist):
    v1 = item.variations.create(value="A")
    v2 = item.variations.create(value="B")
    position.variation = v2
    position.save()
    clist.rules = {
        "inList": [
            {"var": "variation"}, {
                "objectList": [
                    {"lookup": ["variation", str(v1.pk), "Ticket – A"]},
                ]
            }
        ]
    }
    clist.save()
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert not OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
    assert excinfo.value.code == 'rules'
    assert 'Ticket type not allowed' in str(excinfo.value)

    clist.rules = {
        "inList": [
            {"var": "variation"}, {
                "objectList": [
                    {"lookup": ["variation", str(v1.pk), "Ticket – A"]},
                    {"lookup": ["variation", str(v2.pk), "Ticket – B"]},
                ]
            }
        ]
    }
    clist.save()
    assert OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
    perform_checkin(position, clist, {})
Exemple #2
0
def test_rules_product(event, position, clist):
    i2 = event.items.create(name="Ticket", default_price=3, admission=True)
    clist.rules = {
        "inList": [
            {"var": "product"}, {
                "objectList": [
                    {"lookup": ["product", str(i2.pk), "Ticket"]},
                ]
            }
        ]
    }
    clist.save()
    assert not OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'rules'
    assert 'Ticket type not allowed' in str(excinfo.value)

    clist.rules = {
        "inList": [
            {"var": "product"}, {
                "objectList": [
                    {"lookup": ["product", str(i2.pk), "Ticket"]},
                    {"lookup": ["product", str(position.item.pk), "Ticket"]},
                ]
            }
        ]
    }
    clist.save()
    assert OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
    perform_checkin(position, clist, {})
Exemple #3
0
def test_rules_product(event, position, clist):
    i2 = event.items.create(name="Ticket", default_price=3, admission=True)
    clist.rules = {
        "inList": [
            {"var": "product"}, {
                "objectList": [
                    {"lookup": ["product", str(i2.pk), "Ticket"]},
                ]
            }
        ]
    }
    clist.save()
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'rules'

    clist.rules = {
        "inList": [
            {"var": "product"}, {
                "objectList": [
                    {"lookup": ["product", str(i2.pk), "Ticket"]},
                    {"lookup": ["product", str(position.item.pk), "Ticket"]},
                ]
            }
        ]
    }
    clist.save()
    perform_checkin(position, clist, {})
Exemple #4
0
def test_rules_variation(item, position, clist):
    v1 = item.variations.create(value="A")
    v2 = item.variations.create(value="B")
    position.variation = v2
    position.save()
    clist.rules = {
        "inList": [
            {"var": "variation"}, {
                "objectList": [
                    {"lookup": ["variation", str(v1.pk), "Ticket – A"]},
                ]
            }
        ]
    }
    clist.save()
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'rules'

    clist.rules = {
        "inList": [
            {"var": "variation"}, {
                "objectList": [
                    {"lookup": ["variation", str(v1.pk), "Ticket – A"]},
                    {"lookup": ["variation", str(v2.pk), "Ticket – B"]},
                ]
            }
        ]
    }
    clist.save()
    perform_checkin(position, clist, {})
Exemple #5
0
def test_rules_reasoning_prefer_date_over_product(event, position, clist):
    i2 = event.items.create(name="Ticket", default_price=3, admission=True)
    clist.rules = {
        "or": [
            {
                "inList": [
                    {"var": "product"}, {
                        "objectList": [
                            {"lookup": ["product", str(i2.pk), "Ticket"]},
                        ]
                    }
                ]
            },
            {
                "and": [
                    {"isAfter": [{"var": "now"}, {"buildTime": ["custom", "2020-01-02T10:00:00.000Z"]}, None]},
                    {"isBefore": [{"var": "now"}, {"buildTime": ["custom", "2020-01-02T18:00:00.000Z"]}, None]},
                ]
            }
        ]
    }
    clist.save()

    with freeze_time("2020-01-02 20:00:00Z"):
        with pytest.raises(CheckInError) as excinfo:
            perform_checkin(position, clist, {})
        assert excinfo.value.code == 'rules'
        assert 'Only allowed before 19:00' in str(excinfo.value)
def test_position_queries(django_assert_num_queries, position, clist):
    with django_assert_num_queries(
            12 if 'sqlite' in
            settings.DATABASES['default']['ENGINE'] else 11) as captured:
        perform_checkin(position, clist, {})
    if 'sqlite' not in settings.DATABASES['default']['ENGINE']:
        assert any('FOR UPDATE' in s['sql'] for s in captured)
def test_rules_reasoning_prefer_number_over_date(event, position, clist):
    clist.rules = {
        "and": [{
            "isAfter": [{
                "var": "now"
            }, {
                "buildTime": ["custom", "2020-01-02T10:00:00.000Z"]
            }, None]
        }, {
            "isBefore": [{
                "var": "now"
            }, {
                "buildTime": ["custom", "2020-01-02T18:00:00.000Z"]
            }, None]
        }, {
            ">": [{
                "var": "entries_today"
            }, 3]
        }]
    }
    clist.save()

    with freeze_time("2020-01-01 20:00:00Z"):
        with pytest.raises(CheckInError) as excinfo:
            perform_checkin(position, clist, {})
        assert excinfo.value.code == 'rules'
        assert 'Minimum number of entries today exceeded' in str(excinfo.value)
Exemple #8
0
def test_multi_entry_repeat_nonce(position, clist):
    clist.allow_multiple_entries = True
    clist.save()
    perform_checkin(position, clist, {}, nonce='foo')
    perform_checkin(position, clist, {}, nonce='foo')

    assert position.checkins.count() == 1
Exemple #9
0
def test_rules_time_isafter_no_tolerance(event, position, clist):
    # Ticket is valid only after admission time
    event.settings.timezone = 'Europe/Berlin'
    event.date_from = event.timezone.localize(datetime(2020, 1, 1, 12, 0, 0))
    # also tests that date_admission falls back to date_from
    event.save()
    clist.rules = {
        "isAfter": [{
            "var": "now"
        }, {
            "buildTime": ["date_admission"]
        }]
    }
    clist.save()
    with freeze_time("2020-01-01 10:51:00"):
        assert not OrderPosition.objects.filter(
            SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
        with pytest.raises(CheckInError) as excinfo:
            perform_checkin(position, clist, {})
        assert excinfo.value.code == 'rules'

    with freeze_time("2020-01-01 11:01:00"):
        assert OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules),
                                            pk=position.pk).exists()
        perform_checkin(position, clist, {})
Exemple #10
0
def test_unpaid_ignore_without_include_pendung(position, clist):
    o = position.order
    o.status = Order.STATUS_PENDING
    o.save()
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'unpaid'
Exemple #11
0
def test_checkin_all_subevents(position, clist, event):
    event.has_subevents = True
    event.save()
    se1 = event.subevents.create(name="Foo", date_from=event.date_from)
    position.subevent = se1
    position.save()
    perform_checkin(position, clist, {})
Exemple #12
0
def test_unpaid_include_pending_ignore(position, clist):
    o = position.order
    o.status = Order.STATUS_PENDING
    o.save()
    clist.include_pending = True
    clist.save()
    perform_checkin(position, clist, {}, ignore_unpaid=True)
Exemple #13
0
def test_multi_entry(position, clist):
    clist.allow_multiple_entries = True
    clist.save()
    perform_checkin(position, clist, {})
    perform_checkin(position, clist, {})

    assert position.checkins.count() == 2
Exemple #14
0
def test_rules_time_isbefore_with_tolerance(event, position, clist):
    # Ticket is valid until 10 minutes after end time
    event.settings.timezone = 'Europe/Berlin'
    event.date_to = event.timezone.localize(datetime(2020, 1, 1, 12, 0, 0))
    event.save()
    clist.rules = {
        "isBefore": [{
            "var": "now"
        }, {
            "buildTime": ["date_to"]
        }, 10]
    }
    clist.save()
    with freeze_time("2020-01-01 11:11:00"):
        assert not OrderPosition.objects.filter(
            SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
        with pytest.raises(CheckInError) as excinfo:
            perform_checkin(position, clist, {})
        assert excinfo.value.code == 'rules'
        assert 'Only allowed before 12:10' in str(excinfo.value)

    with freeze_time("2020-01-01 11:09:00"):
        assert OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules),
                                            pk=position.pk).exists()
        perform_checkin(position, clist, {})
Exemple #15
0
def test_rules_isafter_subevent(position, clist, event):
    event.has_subevents = True
    event.save()
    event.settings.timezone = 'Europe/Berlin'
    se1 = event.subevents.create(name="Foo",
                                 date_from=event.timezone.localize(
                                     datetime(2020, 2, 1, 12, 0, 0)))
    position.subevent = se1
    position.save()
    clist.rules = {
        "isAfter": [{
            "var": "now"
        }, {
            "buildTime": ["date_admission"]
        }]
    }
    clist.save()
    with freeze_time("2020-02-01 10:51:00"):
        assert not OrderPosition.objects.filter(
            SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
        with pytest.raises(CheckInError) as excinfo:
            perform_checkin(position, clist, {})
        assert excinfo.value.code == 'rules'

    with freeze_time("2020-02-01 11:01:00"):
        assert OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules),
                                            pk=position.pk).exists()
        perform_checkin(position, clist, {})
Exemple #16
0
def test_auto_check_out_only_if_checked_in_before_exit_all_at(event, position, clist):
    clist.exit_all_at = event.timezone.localize(datetime(2020, 1, 2, 3, 0))
    clist.save()
    with freeze_time("2020-01-02 04:05:00+01:00"):
        perform_checkin(position, clist, {})

    process_exit_all(sender=None)
    assert position.checkins.count() == 1
Exemple #17
0
def test_checkin_invalid_product(position, clist):
    clist.all_products = False
    clist.save()
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'product'
    clist.limit_products.add(position.item)
    perform_checkin(position, clist, {})
Exemple #18
0
def test_single_entry(position, clist):
    perform_checkin(position, clist, {})

    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'already_redeemed'

    assert position.checkins.count() == 1
Exemple #19
0
    def redeem(self, *args, **kwargs):
        force = bool(self.request.data.get('force', False))
        ignore_unpaid = bool(self.request.data.get('ignore_unpaid', False))
        nonce = self.request.data.get('nonce')
        op = self.get_object(ignore_status=True)

        if 'datetime' in self.request.data:
            dt = DateTimeField().to_internal_value(self.request.data.get('datetime'))
        else:
            dt = now()

        given_answers = {}
        if 'answers' in self.request.data:
            aws = self.request.data.get('answers')
            for q in op.item.questions.filter(ask_during_checkin=True):
                if str(q.pk) in aws:
                    try:
                        given_answers[q] = q.clean_answer(aws[str(q.pk)])
                    except ValidationError:
                        pass

        try:
            perform_checkin(
                op=op,
                clist=self.checkinlist,
                given_answers=given_answers,
                force=force,
                ignore_unpaid=ignore_unpaid,
                nonce=nonce,
                datetime=dt,
                questions_supported=self.request.data.get('questions_supported', True),
                canceled_supported=self.request.data.get('canceled_supported', False),
                user=self.request.user,
                auth=self.request.auth,
            )
        except RequiredQuestionsError as e:
            return Response({
                'status': 'incomplete',
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data,
                'questions': [
                    QuestionSerializer(q).data for q in e.questions
                ]
            }, status=400)
        except CheckInError as e:
            return Response({
                'status': 'error',
                'reason': e.code,
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
            }, status=400)
        else:
            return Response({
                'status': 'ok',
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
            }, status=201)
Exemple #20
0
def test_required_online_question_missing(event, position, clist):
    q = event.questions.create(
        question="Quo vadis?",
        type="S",
        required=True,
        ask_during_checkin=False,
    )
    q.items.add(position.item)
    perform_checkin(position, clist, {}, questions_supported=True)
Exemple #21
0
    def redeem(self, *args, **kwargs):
        force = bool(self.request.data.get('force', False))
        ignore_unpaid = bool(self.request.data.get('ignore_unpaid', False))
        nonce = self.request.data.get('nonce')
        op = self.get_object(ignore_status=True)

        if 'datetime' in self.request.data:
            dt = DateTimeField().to_internal_value(self.request.data.get('datetime'))
        else:
            dt = now()

        given_answers = {}
        if 'answers' in self.request.data:
            aws = self.request.data.get('answers')
            for q in op.item.questions.filter(ask_during_checkin=True):
                if str(q.pk) in aws:
                    try:
                        given_answers[q] = q.clean_answer(aws[str(q.pk)])
                    except ValidationError:
                        pass

        try:
            perform_checkin(
                op=op,
                clist=self.checkinlist,
                given_answers=given_answers,
                force=force,
                ignore_unpaid=ignore_unpaid,
                nonce=nonce,
                datetime=dt,
                questions_supported=self.request.data.get('questions_supported', True),
                user=self.request.user,
                auth=self.request.auth,
            )
        except RequiredQuestionsError as e:
            return Response({
                'status': 'incomplete',
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data,
                'questions': [
                    QuestionSerializer(q).data for q in e.questions
                ]
            }, status=400)
        except CheckInError as e:
            return Response({
                'status': 'error',
                'reason': e.code,
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
            }, status=400)
        else:
            return Response({
                'status': 'ok',
                'require_attention': op.item.checkin_attention or op.order.checkin_attention,
                'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
            }, status=201)
Exemple #22
0
def test_checkin_canceled_position(position, clist):
    position.canceled = True
    position.save()
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'unpaid'
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {}, canceled_supported=True)
    assert excinfo.value.code == 'canceled'
    assert position.checkins.count() == 0
Exemple #23
0
def test_question_filled_previously(event, position, clist):
    q = event.questions.create(
        question="Quo vadis?",
        type="S",
        required=True,
        ask_during_checkin=True,
    )
    q.items.add(position.item)
    position.answers.create(question=q, answer='Foo')
    perform_checkin(position, clist, {}, questions_supported=True)
Exemple #24
0
    def post(self, request, **kwargs):
        secret = request.POST.get('secret', '!INVALID!')
        force = request.POST.get('force', 'false') in ('true', 'True')
        ignore_unpaid = request.POST.get('ignore_unpaid', 'false') in ('true', 'True')
        nonce = request.POST.get('nonce')
        response = {
            'version': API_VERSION
        }

        if 'datetime' in request.POST:
            dt = dateutil.parser.parse(request.POST.get('datetime'))
        else:
            dt = now()

        try:
            op = OrderPosition.objects.get(order__event=self.event, secret=secret, subevent=self.subevent)
        except OrderPosition.DoesNotExist:
            response['status'] = 'error'
            response['reason'] = 'unknown_ticket'
        else:
            given_answers = {}
            for q in op.item.questions.filter(ask_during_checkin=True):
                if 'answer_{}'.format(q.pk) in request.POST:
                    try:
                        given_answers[q] = q.clean_answer(request.POST.get('answer_{}'.format(q.pk)))
                    except ValidationError:
                        pass

            try:
                if not self.config.all_items and op.item_id not in [i.pk for i in self.config.items.all()]:
                    raise CheckInError('', 'product')
                perform_checkin(
                    op=op,
                    clist=self.config.list,
                    given_answers=given_answers,
                    force=force,
                    ignore_unpaid=ignore_unpaid,
                    nonce=nonce,
                    datetime=dt,
                    questions_supported=bool(request.POST.get('questions_supported'))
                )
            except RequiredQuestionsError as e:
                response['status'] = 'incomplete'
                response['questions'] = [serialize_question(q) for q in e.questions]
            except CheckInError as e:
                response['status'] = 'error'
                response['reason'] = e.code
            else:
                response['status'] = 'ok'

            response['data'] = serialize_op(op, redeemed=op.order.status == Order.STATUS_PAID or force,
                                            clist=self.config.list)

        return JsonResponse(response)
Exemple #25
0
    def post(self, request, **kwargs):
        secret = request.POST.get('secret', '!INVALID!')
        force = request.POST.get('force', 'false') in ('true', 'True')
        ignore_unpaid = request.POST.get('ignore_unpaid', 'false') in ('true', 'True')
        nonce = request.POST.get('nonce')
        response = {
            'version': API_VERSION
        }

        if 'datetime' in request.POST:
            dt = dateutil.parser.parse(request.POST.get('datetime'))
        else:
            dt = now()

        try:
            op = OrderPosition.objects.get(order__event=self.event, secret=secret, subevent=self.subevent)
        except OrderPosition.DoesNotExist:
            response['status'] = 'error'
            response['reason'] = 'unknown_ticket'
        else:
            given_answers = {}
            for q in op.item.questions.filter(ask_during_checkin=True):
                if 'answer_{}'.format(q.pk) in request.POST:
                    try:
                        given_answers[q] = q.clean_answer(request.POST.get('answer_{}'.format(q.pk)))
                    except ValidationError:
                        pass

            try:
                if not self.config.all_items and op.item_id not in [i.pk for i in self.config.items.all()]:
                    raise CheckInError('', 'product')
                perform_checkin(
                    op=op,
                    clist=self.config.list,
                    given_answers=given_answers,
                    force=force,
                    ignore_unpaid=ignore_unpaid,
                    nonce=nonce,
                    datetime=dt,
                    questions_supported=bool(request.POST.get('questions_supported'))
                )
            except RequiredQuestionsError as e:
                response['status'] = 'incomplete'
                response['questions'] = [serialize_question(q) for q in e.questions]
            except CheckInError as e:
                response['status'] = 'error'
                response['reason'] = e.code
            else:
                response['status'] = 'ok'

            response['data'] = serialize_op(op, redeemed=op.order.status == Order.STATUS_PAID or force,
                                            clist=self.config.list)

        return JsonResponse(response)
Exemple #26
0
def test_rules_scan_number(position, clist):
    # Ticket is valid three times
    clist.allow_multiple_entries = True
    clist.rules = {"<": [{"var": "entries_number"}, 3]}
    clist.save()
    perform_checkin(position, clist, {})
    perform_checkin(position, clist, {})
    perform_checkin(position, clist, {}, type=Checkin.TYPE_EXIT)
    perform_checkin(position, clist, {})
    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'rules'
Exemple #27
0
def test_rules_time_isafter_custom_time(event, position, clist):
    # Ticket is valid starting at a custom time
    event.settings.timezone = 'Europe/Berlin'
    clist.rules = {"isAfter": [{"var": "now"}, {"buildTime": ["custom", "2020-01-01T22:00:00.000Z"]}, None]}
    clist.save()
    with freeze_time("2020-01-01 21:55:00"):
        with pytest.raises(CheckInError) as excinfo:
            perform_checkin(position, clist, {})
        assert excinfo.value.code == 'rules'

    with freeze_time("2020-01-01 22:05:00"):
        perform_checkin(position, clist, {})
Exemple #28
0
def test_question_filled(event, position, clist):
    q = event.questions.create(
        question="Quo vadis?",
        type="S",
        required=True,
        ask_during_checkin=True,
    )
    q.items.add(position.item)
    perform_checkin(position, clist, {q: 'Foo'}, questions_supported=True)
    a = position.answers.get()
    assert a.question == q
    assert a.answer == 'Foo'
Exemple #29
0
def test_optional_question_missing(event, position, clist):
    q = event.questions.create(
        question="Quo vadis?",
        type="S",
        required=False,
        ask_during_checkin=True,
    )
    q.items.add(position.item)
    with pytest.raises(RequiredQuestionsError) as excinfo:
        perform_checkin(position, clist, {}, questions_supported=True)
    assert excinfo.value.code == 'incomplete'
    assert excinfo.value.questions == [q]
Exemple #30
0
def test_checkin_invalid_subevent(position, clist, event):
    event.has_subevents = True
    event.save()
    se1 = event.subevents.create(name="Foo", date_from=event.date_from)
    se2 = event.subevents.create(name="Foo", date_from=event.date_from)
    position.subevent = se1
    position.save()
    clist.subevent = se2
    clist.save()

    with pytest.raises(CheckInError) as excinfo:
        perform_checkin(position, clist, {})
    assert excinfo.value.code == 'product'
Exemple #31
0
def test_rules_time_isafter_custom_datetime(event, position, clist):
    # Ticket is valid starting at a custom time
    event.settings.timezone = 'Europe/Berlin'
    clist.rules = {"isAfter": [{"var": "now"}, {"buildTime": ["custom", "2020-01-01T23:00:00.000+01:00"]}, None]}
    clist.save()
    with freeze_time("2020-01-01 21:55:00+00:00"):
        assert not OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
        with pytest.raises(CheckInError) as excinfo:
            perform_checkin(position, clist, {})
        assert excinfo.value.code == 'rules'

    with freeze_time("2020-01-01 22:05:00+00:00"):
        assert OrderPosition.objects.filter(SQLLogic(clist).apply(clist.rules), pk=position.pk).exists()
        perform_checkin(position, clist, {})
Exemple #32
0
def test_rules_time_isbefore_with_tolerance(event, position, clist):
    # Ticket is valid until 10 minutes after end time
    event.settings.timezone = 'Europe/Berlin'
    event.date_to = event.timezone.localize(datetime(2020, 1, 1, 12, 0, 0))
    event.save()
    clist.rules = {"isBefore": [{"var": "now"}, {"buildTime": ["date_to"]}, 10]}
    clist.save()
    with freeze_time("2020-01-01 11:11:00"):
        with pytest.raises(CheckInError) as excinfo:
            perform_checkin(position, clist, {})
        assert excinfo.value.code == 'rules'

    with freeze_time("2020-01-01 11:09:00"):
        perform_checkin(position, clist, {})