mirror of
https://github.com/pretix/pretix.git
synced 2026-08-27 13:24:41 +00:00
New check-in features (#3022)
This commit is contained in:
@@ -131,6 +131,9 @@ TEST_ORDERPOSITION1_RES = {
|
||||
"country": None,
|
||||
"state": None,
|
||||
"subevent": None,
|
||||
"valid_from": None,
|
||||
"valid_until": None,
|
||||
"blocked": None,
|
||||
"pseudonymization_id": "ABCDEFGHKL",
|
||||
}
|
||||
|
||||
@@ -163,6 +166,9 @@ TEST_ORDERPOSITION2_RES = {
|
||||
"country": None,
|
||||
"state": None,
|
||||
"subevent": None,
|
||||
"valid_from": None,
|
||||
"valid_until": None,
|
||||
"blocked": None,
|
||||
"pseudonymization_id": "BACDEFGHKL",
|
||||
}
|
||||
|
||||
@@ -195,6 +201,9 @@ TEST_ORDERPOSITION3_RES = {
|
||||
"country": None,
|
||||
"state": None,
|
||||
"subevent": None,
|
||||
"valid_from": None,
|
||||
"valid_until": None,
|
||||
"blocked": None,
|
||||
"pseudonymization_id": "FOOBAR12345",
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,9 @@ TEST_ORDERPOSITION1_RES = {
|
||||
"country": None,
|
||||
"state": None,
|
||||
"subevent": None,
|
||||
"valid_from": None,
|
||||
"valid_until": None,
|
||||
"blocked": None,
|
||||
"pseudonymization_id": "ABCDEFGHKL",
|
||||
}
|
||||
|
||||
|
||||
@@ -378,6 +378,7 @@ def test_item_detail_variations(token_client, organizer, event, team, item):
|
||||
"active": True,
|
||||
"description": None,
|
||||
"position": 0,
|
||||
"checkin_attention": False,
|
||||
"require_approval": False,
|
||||
"require_membership": False,
|
||||
"require_membership_hidden": False,
|
||||
@@ -551,6 +552,7 @@ def test_item_create_with_variation(token_client, organizer, event, item, catego
|
||||
},
|
||||
"active": True,
|
||||
"require_approval": True,
|
||||
"checkin_attention": False,
|
||||
"require_membership": False,
|
||||
"require_membership_hidden": False,
|
||||
"require_membership_types": [],
|
||||
@@ -1291,6 +1293,7 @@ TEST_VARIATIONS_RES = {
|
||||
"position": 0,
|
||||
"default_price": None,
|
||||
"price": "23.00",
|
||||
"checkin_attention": False,
|
||||
"require_approval": False,
|
||||
"require_membership": False,
|
||||
"require_membership_hidden": False,
|
||||
@@ -1311,6 +1314,7 @@ TEST_VARIATIONS_UPDATE = {
|
||||
"description": None,
|
||||
"position": 1,
|
||||
"default_price": "20.0",
|
||||
"checkin_attention": False,
|
||||
"require_approval": False,
|
||||
"require_membership": False,
|
||||
"require_membership_hidden": False,
|
||||
|
||||
@@ -255,6 +255,7 @@ def test_order_update_allowed_fields(token_client, organizer, event, order):
|
||||
organizer.slug, event.slug, order.code
|
||||
), format='json', data={
|
||||
'comment': 'Here is a comment',
|
||||
'valid_if_pending': True,
|
||||
'custom_followup_at': '2021-06-12',
|
||||
'checkin_attention': True,
|
||||
'email': 'foo@bar.com',
|
||||
@@ -283,6 +284,7 @@ def test_order_update_allowed_fields(token_client, organizer, event, order):
|
||||
assert order.email == 'foo@bar.com'
|
||||
assert order.phone == '+4962219999'
|
||||
assert order.locale == 'de'
|
||||
assert order.valid_if_pending
|
||||
assert order.invoice_address.company == "This is my company name"
|
||||
assert order.invoice_address.name_cached == "John Doe"
|
||||
assert order.invoice_address.name_parts == {'_legacy': 'John Doe'}
|
||||
@@ -540,6 +542,64 @@ def test_position_regenerate_secrets(token_client, organizer, event, order):
|
||||
assert ps != p.secret
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_position_manage_blocks(token_client, organizer, event, order):
|
||||
with scopes_disabled():
|
||||
p = order.positions.first()
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/{}/add_block/'.format(
|
||||
organizer.slug, event.slug, p.pk,
|
||||
), format='json', data={
|
||||
'name': 'invalid'
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/{}/add_block/'.format(
|
||||
organizer.slug, event.slug, p.pk,
|
||||
), format='json', data={
|
||||
'name': 'admin'
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
p.refresh_from_db()
|
||||
assert p.blocked == ['admin']
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/{}/add_block/'.format(
|
||||
organizer.slug, event.slug, p.pk,
|
||||
), format='json', data={
|
||||
'name': 'api:custom'
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
p.refresh_from_db()
|
||||
assert p.blocked == ['admin', 'api:custom']
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/{}/remove_block/'.format(
|
||||
organizer.slug, event.slug, p.pk,
|
||||
), format='json', data={
|
||||
'name': 'api:custom'
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
p.refresh_from_db()
|
||||
assert p.blocked == ['admin']
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/{}/remove_block/'.format(
|
||||
organizer.slug, event.slug, p.pk,
|
||||
), format='json', data={
|
||||
'name': 'admin'
|
||||
}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
p.refresh_from_db()
|
||||
assert p.blocked is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_order_resend_link(token_client, organizer, event, order):
|
||||
djmail.outbox = []
|
||||
@@ -1614,6 +1674,8 @@ def test_position_add_and_set_info(token_client, organizer, event, order, questi
|
||||
'order': order.code,
|
||||
'item': item.pk,
|
||||
'attendee_name': 'John Doe',
|
||||
'valid_from': '2022-12-12T12:12:12+00:00',
|
||||
'valid_until': '2022-12-12T13:12:12+00:00',
|
||||
'answers': [
|
||||
{
|
||||
'question': question.pk,
|
||||
@@ -1635,6 +1697,27 @@ def test_position_add_and_set_info(token_client, organizer, event, order, questi
|
||||
assert op.positionid == 3
|
||||
assert op.attendee_name == 'John Doe'
|
||||
assert op.answers.count() == 1
|
||||
assert op.valid_from.isoformat() == '2022-12-12T12:12:12+00:00'
|
||||
assert op.valid_until.isoformat() == '2022-12-12T13:12:12+00:00'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_position_update_validity(token_client, organizer, event, order, quota, item, subevent):
|
||||
with scopes_disabled():
|
||||
op = order.positions.get()
|
||||
payload = {
|
||||
'valid_from': '2022-12-12T12:12:12+00:00',
|
||||
'valid_until': '2022-12-12T13:12:12+00:00',
|
||||
}
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/{}/'.format(
|
||||
organizer.slug, event.slug, op.pk
|
||||
), format='json', data=payload
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
op.refresh_from_db()
|
||||
assert op.valid_from.isoformat() == '2022-12-12T12:12:12+00:00'
|
||||
assert op.valid_until.isoformat() == '2022-12-12T13:12:12+00:00'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
||||
@@ -153,6 +153,7 @@ ORDER_CREATE_PAYLOAD = {
|
||||
"phone": "+49622112345",
|
||||
"locale": "en",
|
||||
"sales_channel": "web",
|
||||
"valid_if_pending": True,
|
||||
"fees": [
|
||||
{
|
||||
"fee_type": "payment",
|
||||
@@ -223,6 +224,7 @@ def test_order_create(token_client, organizer, event, item, quota, question):
|
||||
assert o.total == Decimal('23.25')
|
||||
assert o.status == Order.STATUS_PENDING
|
||||
assert o.sales_channel == "web"
|
||||
assert o.valid_if_pending
|
||||
assert not o.testmode
|
||||
|
||||
with scopes_disabled():
|
||||
@@ -295,6 +297,7 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques
|
||||
'datetime': None,
|
||||
'payment_date': None,
|
||||
'payment_provider': None,
|
||||
'valid_if_pending': True,
|
||||
'fees': [
|
||||
{
|
||||
'id': 0,
|
||||
@@ -345,6 +348,9 @@ def test_order_create_simulate(token_client, organizer, event, item, quota, ques
|
||||
'discount': None,
|
||||
'checkins': [],
|
||||
'downloads': [],
|
||||
"valid_from": None,
|
||||
"valid_until": None,
|
||||
"blocked": None,
|
||||
'answers': [
|
||||
{'question': question.pk, 'answer': 'L', 'question_identifier': 'ABC',
|
||||
'options': [opt.pk],
|
||||
@@ -413,13 +419,13 @@ def test_order_create_positionids_addons_simulated(token_client, organizer, even
|
||||
'street': None, 'zipcode': None, 'city': None, 'country': None, 'state': None, 'attendee_email': None,
|
||||
'voucher': None, 'tax_rate': '0.00', 'tax_value': '0.00', 'discount': None,
|
||||
'addon_to': None, 'subevent': None, 'checkins': [], 'downloads': [], 'answers': [], 'tax_rule': None,
|
||||
'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False},
|
||||
'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False, 'valid_from': None, 'valid_until': None, 'blocked': None},
|
||||
{'id': 0, 'order': '', 'positionid': 2, 'item': item.pk, 'variation': None, 'price': '23.00',
|
||||
'attendee_name': 'Peter', 'attendee_name_parts': {'full_name': 'Peter', '_scheme': 'full'}, 'company': None,
|
||||
'street': None, 'zipcode': None, 'city': None, 'country': None, 'state': None, 'attendee_email': None,
|
||||
'voucher': None, 'tax_rate': '0.00', 'tax_value': '0.00', 'discount': None,
|
||||
'addon_to': 1, 'subevent': None, 'checkins': [], 'downloads': [], 'answers': [], 'tax_rule': None,
|
||||
'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False}
|
||||
'pseudonymization_id': 'PREVIEW', 'seat': None, 'canceled': False, 'valid_from': None, 'valid_until': None, 'blocked': None}
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -173,6 +173,9 @@ TEST_ORDERPOSITION_RES = {
|
||||
"city": None,
|
||||
"country": None,
|
||||
"state": None,
|
||||
"valid_from": None,
|
||||
"valid_until": None,
|
||||
"blocked": None,
|
||||
"answers": [
|
||||
{
|
||||
"question": 1,
|
||||
@@ -271,6 +274,7 @@ TEST_ORDER_RES = {
|
||||
"vat_id_validated": True
|
||||
},
|
||||
"require_approval": False,
|
||||
"valid_if_pending": False,
|
||||
"positions": [TEST_ORDERPOSITION_RES],
|
||||
"downloads": [],
|
||||
"payments": TEST_PAYMENTS_RES,
|
||||
@@ -1752,6 +1756,22 @@ def test_revoked_secret_list(token_client, organizer, event):
|
||||
assert [res] == resp.data['results']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_blocked_secret_list(token_client, organizer, event):
|
||||
r = event.blocked_secrets.create(secret="abcd", blocked=True)
|
||||
res = {
|
||||
"id": r.id,
|
||||
"secret": "abcd",
|
||||
"blocked": True,
|
||||
"updated": r.updated.isoformat().replace("+00:00", "Z")
|
||||
}
|
||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/blockedsecrets/'.format(
|
||||
organizer.slug, event.slug,
|
||||
))
|
||||
assert resp.status_code == 200
|
||||
assert [res] == resp.data['results']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_pdf_data(token_client, organizer, event, order, django_assert_max_num_queries):
|
||||
# order detail
|
||||
|
||||
@@ -61,6 +61,8 @@ event_permission_sub_urls = [
|
||||
('patch', 'can_change_event_settings', 'settings/', 200),
|
||||
('get', 'can_view_orders', 'revokedsecrets/', 200),
|
||||
('get', 'can_view_orders', 'revokedsecrets/1/', 404),
|
||||
('get', 'can_view_orders', 'blockedsecrets/', 200),
|
||||
('get', 'can_view_orders', 'blockedsecrets/1/', 404),
|
||||
('get', 'can_view_orders', 'orders/', 200),
|
||||
('get', 'can_view_orders', 'orderpositions/', 200),
|
||||
('delete', 'can_change_orders', 'orderpositions/1/', 404),
|
||||
|
||||
@@ -98,6 +98,42 @@ class EventCancelTests(TestCase):
|
||||
self.order.refresh_from_db()
|
||||
assert self.order.status == Order.STATUS_CANCELED
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_cancel_auto_refund_skip_blocked(self):
|
||||
gc = self.o.issued_gift_cards.create(currency="EUR")
|
||||
p1 = self.order.payments.create(
|
||||
amount=Decimal('46.00'),
|
||||
state=OrderPayment.PAYMENT_STATE_CONFIRMED,
|
||||
provider='giftcard',
|
||||
info='{"gift_card": %d}' % gc.pk
|
||||
)
|
||||
self.order.status = Order.STATUS_PAID
|
||||
self.order.save()
|
||||
|
||||
self.op1.blocked = ["admin"]
|
||||
self.op1.save()
|
||||
|
||||
cancel_event(
|
||||
self.event.pk, subevent=None,
|
||||
auto_refund=True, keep_fee_fixed="0.00", keep_fee_percentage="0.00", keep_fee_per_ticket="",
|
||||
send=True, send_subject="Event canceled", send_message="Event canceled :-(",
|
||||
user=None
|
||||
)
|
||||
|
||||
self.op1.refresh_from_db()
|
||||
assert not self.op1.canceled
|
||||
self.op2.refresh_from_db()
|
||||
assert self.op2.canceled
|
||||
|
||||
r = self.order.refunds.get()
|
||||
assert r.state == OrderRefund.REFUND_STATE_DONE
|
||||
assert r.amount == Decimal('23.00')
|
||||
assert r.source == OrderRefund.REFUND_SOURCE_ADMIN
|
||||
assert r.payment == p1
|
||||
assert self.order.all_logentries().filter(action_type='pretix.event.order.refund.created').exists()
|
||||
assert not self.order.all_logentries().filter(action_type='pretix.event.order.refund.requested').exists()
|
||||
assert gc.value == Decimal('23.00')
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_cancel_auto_refund(self):
|
||||
gc = self.o.issued_gift_cards.create(currency="EUR")
|
||||
@@ -524,6 +560,24 @@ class SubEventCancelTests(TestCase):
|
||||
self.order.refresh_from_db()
|
||||
assert self.order.status == Order.STATUS_CANCELED
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_cancel_skip_blocked(self):
|
||||
self.op2.subevent = self.se1
|
||||
self.op2.blocked = ["admin"]
|
||||
self.op2.save()
|
||||
cancel_event(
|
||||
self.event.pk, subevent=self.se1.pk,
|
||||
auto_refund=True, keep_fee_fixed="0.00", keep_fee_percentage="0.00", keep_fee_per_ticket="",
|
||||
send=True, send_subject="Event canceled", send_message="Event canceled :-(",
|
||||
user=None
|
||||
)
|
||||
self.order.refresh_from_db()
|
||||
assert self.order.status == Order.STATUS_PENDING
|
||||
self.op1.refresh_from_db()
|
||||
assert self.op1.canceled
|
||||
self.op2.refresh_from_db()
|
||||
assert not self.op2.canceled
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_cancel_all_subevents(self):
|
||||
cancel_event(
|
||||
|
||||
@@ -115,6 +115,50 @@ def test_checkin_canceled_position(position, clist):
|
||||
assert position.checkins.count() == 0
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_checkin_blocked_position(position, clist):
|
||||
position.blocked = ["admin"]
|
||||
position.save()
|
||||
with pytest.raises(CheckInError) as excinfo:
|
||||
perform_checkin(position, clist, {})
|
||||
assert excinfo.value.code == 'blocked'
|
||||
assert position.checkins.count() == 0
|
||||
with pytest.raises(CheckInError) as excinfo:
|
||||
perform_checkin(position, clist, {}, type=Checkin.TYPE_EXIT)
|
||||
assert excinfo.value.code == 'blocked'
|
||||
assert position.checkins.count() == 0
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_checkin_valid_from(event, position, clist):
|
||||
position.valid_from = event.timezone.localize(datetime(2020, 1, 1, 12, 0, 0))
|
||||
position.save()
|
||||
with freeze_time("2020-01-01 10:45:00"):
|
||||
with pytest.raises(CheckInError) as excinfo:
|
||||
perform_checkin(position, clist, {})
|
||||
assert excinfo.value.code == 'invalid_time'
|
||||
assert excinfo.value.reason == 'This ticket is only valid after 2020-01-01 12:00.'
|
||||
assert position.checkins.count() == 0
|
||||
|
||||
perform_checkin(position, clist, {}, type=Checkin.TYPE_EXIT)
|
||||
assert position.checkins.count() == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_checkin_valid_until(event, position, clist):
|
||||
position.valid_until = event.timezone.localize(datetime(2020, 1, 1, 9, 0, 0))
|
||||
position.save()
|
||||
with freeze_time("2020-01-01 10:45:00"):
|
||||
with pytest.raises(CheckInError) as excinfo:
|
||||
perform_checkin(position, clist, {})
|
||||
assert excinfo.value.code == 'invalid_time'
|
||||
assert excinfo.value.reason == 'This ticket was only valid before 2020-01-01 09:00.'
|
||||
assert position.checkins.count() == 0
|
||||
|
||||
perform_checkin(position, clist, {}, type=Checkin.TYPE_EXIT)
|
||||
assert position.checkins.count() == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_checkin_invalid_product(position, clist):
|
||||
clist.all_products = False
|
||||
@@ -162,6 +206,30 @@ def test_unpaid(position, clist):
|
||||
assert excinfo.value.code == 'unpaid'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unpaid_but_valid(position, clist):
|
||||
o = position.order
|
||||
o.status = Order.STATUS_PENDING
|
||||
o.valid_if_pending = True
|
||||
o.save()
|
||||
clist.include_pending = False
|
||||
clist.save()
|
||||
perform_checkin(position, clist, {})
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_require_approval(position, clist):
|
||||
o = position.order
|
||||
o.status = Order.STATUS_PENDING
|
||||
o.require_approval = True
|
||||
o.save()
|
||||
clist.include_pending = False
|
||||
clist.save()
|
||||
with pytest.raises(CheckInError) as excinfo:
|
||||
perform_checkin(position, clist, {}, ignore_unpaid=True)
|
||||
assert excinfo.value.code == 'unpaid'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unpaid_include_pending_ignore(position, clist):
|
||||
o = position.order
|
||||
@@ -173,7 +241,7 @@ def test_unpaid_include_pending_ignore(position, clist):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_unpaid_ignore_without_include_pendung(position, clist):
|
||||
def test_unpaid_ignore_without_include_pending(position, clist):
|
||||
o = position.order
|
||||
o.status = Order.STATUS_PENDING
|
||||
o.save()
|
||||
|
||||
@@ -1310,7 +1310,7 @@ class OrderTestCase(BaseQuotaTestCase):
|
||||
assert self.order.user_cancel_allowed
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_can_cancel_checked_in(self):
|
||||
def test_can_not_cancel_checked_in(self):
|
||||
self.order.status = Order.STATUS_PAID
|
||||
self.order.save()
|
||||
self.event.settings.cancel_allow_user = False
|
||||
@@ -1322,6 +1322,17 @@ class OrderTestCase(BaseQuotaTestCase):
|
||||
)
|
||||
assert not self.order.user_cancel_allowed
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_can_not_cancel_blocked(self):
|
||||
self.order.status = Order.STATUS_PAID
|
||||
self.order.save()
|
||||
self.event.settings.cancel_allow_user = False
|
||||
self.event.settings.cancel_allow_user_paid = True
|
||||
assert self.order.user_cancel_allowed
|
||||
self.op1.blocked = ["admin"]
|
||||
self.op1.save()
|
||||
assert not self.order.user_cancel_allowed
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_can_cancel_order_multiple(self):
|
||||
item1 = Item.objects.create(event=self.event, name="Ticket", default_price=23,
|
||||
|
||||
@@ -679,6 +679,19 @@ def test_import_seat(user, event, item):
|
||||
assert not s3.is_available()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_validity(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['valid_until'] = 'csv:J'
|
||||
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
).get()
|
||||
assert OrderPosition.objects.first().valid_until.isoformat() == '2021-06-28T11:00:00+00:00'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_subevent_invalid(user, event, item):
|
||||
|
||||
@@ -44,6 +44,7 @@ from pretix.base.payment import (
|
||||
FreeOrderProvider, GiftCardPayment, PaymentException,
|
||||
)
|
||||
from pretix.base.reldate import RelativeDate, RelativeDateWrapper
|
||||
from pretix.base.secrets import assign_ticket_secret
|
||||
from pretix.base.services.invoices import generate_invoice
|
||||
from pretix.base.services.orders import (
|
||||
OrderChangeManager, OrderError, _create_order, approve_order, cancel_order,
|
||||
@@ -567,6 +568,17 @@ class PaymentReminderTests(TestCase):
|
||||
self.event.settings.mail_days_order_expire_warning = 10
|
||||
send_expiry_warnings(sender=self.event)
|
||||
assert len(djmail.outbox) == 1
|
||||
assert "only guarantee your order" in djmail.outbox[0].body
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_sent_no_expiry(self):
|
||||
self.order.valid_if_pending = True
|
||||
self.order.save()
|
||||
self.event.settings.mail_days_order_expire_warning = 10
|
||||
send_expiry_warnings(sender=self.event)
|
||||
assert len(djmail.outbox) == 1
|
||||
assert "only guarantee your order" not in djmail.outbox[0].body
|
||||
assert "required to pay" in djmail.outbox[0].body
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_sent_not_immediately_after_purchase(self):
|
||||
@@ -2904,6 +2916,62 @@ class OrderChangeManagerTests(TestCase):
|
||||
assert self.op1.used_membership is None
|
||||
assert self.op1.item == self.ticket
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_add_block(self):
|
||||
self.ocm.add_block(self.op1, "admin")
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
assert self.op1.blocked == ["admin"]
|
||||
bs = self.op1.blocked_secrets.get()
|
||||
assert bs.secret == self.op1.secret
|
||||
assert bs.blocked
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_remove_block(self):
|
||||
self.op1.blocked = ["admin"]
|
||||
self.op1.save()
|
||||
bs = self.op1.blocked_secrets.create(event=self.event, secret=self.op1.secret, blocked=True)
|
||||
self.ocm.remove_block(self.op1, "admin")
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
assert self.op1.blocked is None
|
||||
bs.refresh_from_db()
|
||||
assert not bs.blocked
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_set_valid_from(self):
|
||||
old_secret = self.op1.secret
|
||||
dt = make_aware(datetime(2016, 9, 20, 15, 0, 0, 0))
|
||||
self.ocm.change_valid_from(self.op1, dt)
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
assert self.op1.valid_from == dt
|
||||
assert self.op1.secret == old_secret
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_set_valid_until(self):
|
||||
self.event.settings.ticket_secret_generator = "pretix_sig1"
|
||||
assign_ticket_secret(self.event, self.op1, force_invalidate=True, save=True)
|
||||
old_secret = self.op1.secret
|
||||
|
||||
dt = make_aware(datetime(2022, 9, 20, 15, 0, 0, 0))
|
||||
self.ocm.change_valid_until(self.op1, dt)
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
assert self.op1.secret != old_secret
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_unset_valid_from_until(self):
|
||||
self.op1.valid_from = make_aware(datetime(2016, 9, 20, 15, 0, 0, 0))
|
||||
self.op1.valid_until = make_aware(datetime(2016, 9, 20, 15, 0, 0, 0))
|
||||
self.op1.save()
|
||||
self.ocm.change_valid_from(self.op1, None)
|
||||
self.ocm.change_valid_until(self.op1, None)
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
assert self.op1.valid_from is None
|
||||
assert self.op1.valid_until is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_autocheckin(clist_autocheckin, event):
|
||||
|
||||
@@ -302,6 +302,22 @@ def test_sendmail_rule_send_order_pending_excluded(event, order):
|
||||
assert len(djmail.outbox) == 0
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_sendmail_rule_send_order_valid_if_pending(event, order):
|
||||
order.valid_if_pending = True
|
||||
order.status = Order.STATUS_PENDING
|
||||
order.save()
|
||||
djmail.outbox = []
|
||||
|
||||
event.sendmail_rules.create(send_date=dt_now - datetime.timedelta(hours=1), include_pending=False,
|
||||
subject='meow', template='meow meow meow')
|
||||
|
||||
sendmail_run_rules(None)
|
||||
|
||||
assert len(djmail.outbox) == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize('status', [
|
||||
Order.STATUS_EXPIRED,
|
||||
|
||||
@@ -90,12 +90,13 @@ def test_csv_simple(event):
|
||||
})
|
||||
assert clean(content.decode()) == clean(""""Order code","Attendee name","Attendee name: Title","Attendee name:
|
||||
First name","Attendee name: Middle name","Attendee name: Family name","Product","Price","Checked in","Checked out","Automatically
|
||||
checked in","Secret","E-mail","Phone number","Company","Voucher code","Order date","Order time","Requires special attention","Comment","Seat ID","Seat name",
|
||||
"Seat zone","Seat row","Seat number","Address","ZIP code","City","Country","State"
|
||||
checked in","Secret","E-mail","Phone number","Company","Voucher code","Order date","Order time","Requires special attention",
|
||||
"Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Blocked","Valid from","Valid until","Address","ZIP code",
|
||||
"City","Country","State"
|
||||
"FOO","Mr Peter A Jones","Mr","Peter","A","Jones","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytxx",
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
"FOO","Mrs Andrea J Zulu","Mrs","Andrea","J","Zulu","Ticket","13.00","","","No","ggsngqtnmhx74jswjngw3fk8pfwz2a7k",
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
""")
|
||||
|
||||
|
||||
@@ -112,11 +113,12 @@ def test_csv_order_by_name_parts(event): # noqa
|
||||
assert clean(content.decode()) == clean(""""Order code","Attendee name","Attendee name: Title",
|
||||
"Attendee name: First name","Attendee name: Middle name","Attendee name: Family name","Product","Price",
|
||||
"Checked in","Checked out","Automatically checked in","Secret","E-mail","Phone number","Company","Voucher code","Order date","Order time","Requires special
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Address","ZIP code","City","Country","State"
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Blocked","Valid from","Valid until",
|
||||
"Address","ZIP code","City","Country","State"
|
||||
"FOO","Mrs Andrea J Zulu","Mrs","Andrea","J","Zulu","Ticket","13.00","","","No","ggsngqtnmhx74jswjngw3fk8pfwz2a7k",
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
"FOO","Mr Peter A Jones","Mr","Peter","A","Jones","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytxx",
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
""")
|
||||
c = CSVCheckinList(event, organizer=event.organizer)
|
||||
_, _, content = c.render({
|
||||
@@ -129,11 +131,12 @@ def test_csv_order_by_name_parts(event): # noqa
|
||||
assert clean(content.decode()) == clean(""""Order code","Attendee name","Attendee name: Title",
|
||||
"Attendee name: First name","Attendee name: Middle name","Attendee name: Family name","Product","Price",
|
||||
"Checked in","Checked out","Automatically checked in","Secret","E-mail","Phone number","Company","Voucher code","Order date","Order time","Requires special
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Address","ZIP code","City","Country","State"
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Blocked","Valid from","Valid until",
|
||||
"Address","ZIP code","City","Country","State"
|
||||
"FOO","Mr Peter A Jones","Mr","Peter","A","Jones","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytxx",
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
"FOO","Mrs Andrea J Zulu","Mrs","Andrea","J","Zulu","Ticket","13.00","","","No","ggsngqtnmhx74jswjngw3fk8pfwz2a7k",
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
""")
|
||||
|
||||
|
||||
@@ -180,11 +183,12 @@ def test_csv_order_by_inherited_name_parts(event): # noqa
|
||||
assert clean(content.decode()) == clean(""""Order code","Attendee name","Attendee name: Title",
|
||||
"Attendee name: First name","Attendee name: Middle name","Attendee name: Family name","Product","Price",
|
||||
"Checked in","Checked out","Automatically checked in","Secret","E-mail","Phone number","Company","Voucher code","Order date","Order time","Requires special
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Address","ZIP code","City","Country","State"
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Blocked","Valid from","Valid until",
|
||||
"Address","ZIP code","City","Country","State"
|
||||
"BAR","Mr Albert J Zulu","Mr","Albert","J","Zulu","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytyy",
|
||||
"dummy@dummy.test","'+498912345678","BARCORP","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","BARCORP","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
"FOO","Mr Paul A Jones","Mr","Paul","A","Jones","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytxx",
|
||||
"dummy@dummy.test","'+498912345678","FOOCORP","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","FOOCORP","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
""")
|
||||
c = CSVCheckinList(event, organizer=event.organizer)
|
||||
_, _, content = c.render({
|
||||
@@ -197,11 +201,12 @@ def test_csv_order_by_inherited_name_parts(event): # noqa
|
||||
assert clean(content.decode()) == clean(""""Order code","Attendee name","Attendee name: Title",
|
||||
"Attendee name: First name","Attendee name: Middle name","Attendee name: Family name","Product","Price",
|
||||
"Checked in","Checked out","Automatically checked in","Secret","E-mail","Phone number","Company","Voucher code","Order date","Order time","Requires special
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Address","ZIP code","City","Country","State"
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Blocked","Valid from","Valid until",
|
||||
"Address","ZIP code","City","Country","State"
|
||||
"BAR","Mr Albert J Zulu","Mr","Albert","J","Zulu","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytyy",
|
||||
"dummy@dummy.test","'+498912345678","BARCORP","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","BARCORP","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
"FOO","Mr Paul A Jones","Mr","Paul","A","Jones","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytxx",
|
||||
"dummy@dummy.test","'+498912345678","FOOCORP","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","FOOCORP","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
""")
|
||||
c = CSVCheckinList(event, organizer=event.organizer)
|
||||
_, _, content = c.render({
|
||||
@@ -214,9 +219,10 @@ def test_csv_order_by_inherited_name_parts(event): # noqa
|
||||
assert clean(content.decode()) == clean(""""Order code","Attendee name","Attendee name: Title",
|
||||
"Attendee name: First name","Attendee name: Middle name","Attendee name: Family name","Product","Price",
|
||||
"Checked in","Checked out","Automatically checked in","Secret","E-mail","Phone number","Company","Voucher code","Order date","Order time","Requires special
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Address","ZIP code","City","Country","State"
|
||||
attention","Comment","Seat ID","Seat name","Seat zone","Seat row","Seat number","Blocked","Valid from","Valid until",
|
||||
"Address","ZIP code","City","Country","State"
|
||||
"FOO","Mr Paul A Jones","Mr","Paul","A","Jones","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytxx",
|
||||
"dummy@dummy.test","'+498912345678","FOOCORP","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","FOOCORP","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
"BAR","Mr Albert J Zulu","Mr","Albert","J","Zulu","Ticket","23.00","","","No","hutjztuxhkbtwnesv2suqv26k6ttytyy",
|
||||
"dummy@dummy.test","'+498912345678","BARCORP","","2019-02-22","14:00:00","No","","","","","","","","","","",""
|
||||
"dummy@dummy.test","'+498912345678","BARCORP","","2019-02-22","14:00:00","No","","","","","","","","","","","","","",""
|
||||
""")
|
||||
|
||||
Reference in New Issue
Block a user