mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
Add sales channels (#1103)
- [x] Data model - [x] Enforce constraint - [x] Filter order list - [x] Set channel on created order - [x] Products API - [x] Order API - [x] Tests - [x] Filter reports - [x] Resellers - [ ] deploy plugins - [ ] posbackend - [ ] resellers - [ ] reports - [x] Ticketlayouts - [x] Support in pretixPOS
This commit is contained in:
@@ -212,6 +212,7 @@ TEST_ITEM_RES = {
|
||||
"name": {"en": "Budget Ticket"},
|
||||
"internal_name": None,
|
||||
"default_price": "23.00",
|
||||
"sales_channels": ["web"],
|
||||
"category": None,
|
||||
"active": True,
|
||||
"description": None,
|
||||
@@ -352,6 +353,7 @@ def test_item_create(token_client, organizer, event, item, category, taxrule):
|
||||
"en": "Ticket"
|
||||
},
|
||||
"active": True,
|
||||
"sales_channels": ["web", "pretixpos"],
|
||||
"description": None,
|
||||
"default_price": "23.00",
|
||||
"free_price": False,
|
||||
@@ -373,6 +375,7 @@ def test_item_create(token_client, organizer, event, item, category, taxrule):
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 201
|
||||
assert Item.objects.get(pk=resp.data['id']).sales_channels == ["web", "pretixpos"]
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
||||
@@ -177,6 +177,7 @@ TEST_ORDER_RES = {
|
||||
"datetime": "2017-12-01T10:00:00Z",
|
||||
"expires": "2017-12-10T10:00:00Z",
|
||||
"payment_date": "2017-12-01",
|
||||
"sales_channel": "web",
|
||||
"fees": [
|
||||
{
|
||||
"fee_type": "payment",
|
||||
@@ -1238,6 +1239,7 @@ def test_order_invalid_state_deny(token_client, organizer, event, order):
|
||||
ORDER_CREATE_PAYLOAD = {
|
||||
"email": "dummy@dummy.test",
|
||||
"locale": "en",
|
||||
"sales_channel": "web",
|
||||
"fees": [
|
||||
{
|
||||
"fee_type": "payment",
|
||||
@@ -1297,6 +1299,7 @@ def test_order_create(token_client, organizer, event, item, quota, question):
|
||||
assert o.locale == "en"
|
||||
assert o.total == Decimal('23.25')
|
||||
assert o.status == Order.STATUS_PENDING
|
||||
assert o.sales_channel == "web"
|
||||
|
||||
p = o.payments.first()
|
||||
assert p.provider == "banktransfer"
|
||||
@@ -1337,6 +1340,37 @@ def test_order_create_invoice_address_optional(token_client, organizer, event, i
|
||||
o.invoice_address
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_order_create_sales_channel_optional(token_client, organizer, event, item, quota, question):
|
||||
res = copy.deepcopy(ORDER_CREATE_PAYLOAD)
|
||||
res['positions'][0]['item'] = item.pk
|
||||
res['positions'][0]['answers'][0]['question'] = question.pk
|
||||
del res['sales_channel']
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orders/'.format(
|
||||
organizer.slug, event.slug
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 201
|
||||
o = Order.objects.get(code=resp.data['code'])
|
||||
assert o.sales_channel == "web"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_order_create_sales_channel_invalid(token_client, organizer, event, item, quota, question):
|
||||
res = copy.deepcopy(ORDER_CREATE_PAYLOAD)
|
||||
res['positions'][0]['item'] = item.pk
|
||||
res['positions'][0]['answers'][0]['question'] = question.pk
|
||||
res['sales_channel'] = 'foo'
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/orders/'.format(
|
||||
organizer.slug, event.slug
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'sales_channel': ['Unknown sales channel.']}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_order_create_attendee_name_optional(token_client, organizer, event, item, quota, question):
|
||||
res = copy.deepcopy(ORDER_CREATE_PAYLOAD)
|
||||
|
||||
@@ -304,7 +304,8 @@ class ItemsTest(ItemFormTest):
|
||||
'default_price': '23.00',
|
||||
'tax_rate': '19.00',
|
||||
'active': 'yes',
|
||||
'allow_cancel': 'yes'
|
||||
'allow_cancel': 'yes',
|
||||
'sales_channels': 'web'
|
||||
})
|
||||
self.item1.refresh_from_db()
|
||||
assert self.item1.default_price == Decimal('23.00')
|
||||
@@ -425,6 +426,7 @@ class ItemsTest(ItemFormTest):
|
||||
def test_create_copy(self):
|
||||
q = Question.objects.create(event=self.event1, question="Size", type="N")
|
||||
q.items.add(self.item2)
|
||||
self.item2.sales_channels = ["web", "bar"]
|
||||
|
||||
self.client.post('/control/event/%s/%s/items/add' % (self.orga1.slug, self.event1.slug), {
|
||||
'name_0': 'Intermediate',
|
||||
@@ -443,6 +445,7 @@ class ItemsTest(ItemFormTest):
|
||||
assert i_new.require_voucher == i_old.require_voucher
|
||||
assert i_new.hide_without_voucher == i_old.hide_without_voucher
|
||||
assert i_new.allow_cancel == i_old.allow_cancel
|
||||
assert i_new.sales_channels == i_old.sales_channels
|
||||
assert set(i_new.questions.all()) == set(i_old.questions.all())
|
||||
assert set([str(v.value) for v in i_new.variations.all()]) == set([str(v.value) for v in i_old.variations.all()])
|
||||
|
||||
|
||||
@@ -66,7 +66,8 @@ class BadgeLayoutFormTest(SoupTest):
|
||||
'tax_rate': '19.00',
|
||||
'active': 'yes',
|
||||
'allow_cancel': 'yes',
|
||||
'badgeitem-layout': bl2.pk
|
||||
'badgeitem-layout': bl2.pk,
|
||||
'sales_channels': 'web',
|
||||
})
|
||||
assert BadgeItem.objects.get(item=self.item1, layout=bl2)
|
||||
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item1.id), {
|
||||
@@ -75,6 +76,7 @@ class BadgeLayoutFormTest(SoupTest):
|
||||
'tax_rate': '19.00',
|
||||
'active': 'yes',
|
||||
'allow_cancel': 'yes',
|
||||
'sales_channels': 'web',
|
||||
})
|
||||
assert not BadgeItem.objects.filter(item=self.item1, layout=bl2).exists()
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ RES_LAYOUT = {
|
||||
'id': 1,
|
||||
'name': 'Foo',
|
||||
'default': True,
|
||||
'item_assignments': [{'item': 1}],
|
||||
'item_assignments': [{'item': 1, 'sales_channel': 'web'}],
|
||||
'layout': [{'a': 2}],
|
||||
'background': None
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ class TicketLayoutFormTest(SoupTest):
|
||||
'tax_rate': '19.00',
|
||||
'active': 'yes',
|
||||
'allow_cancel': 'yes',
|
||||
'ticketlayoutitem-layout': bl2.pk
|
||||
'ticketlayoutitem_web-layout': bl2.pk,
|
||||
'sales_channels': 'web',
|
||||
})
|
||||
assert TicketLayoutItem.objects.get(item=self.item1, layout=bl2)
|
||||
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item1.id), {
|
||||
@@ -75,6 +76,7 @@ class TicketLayoutFormTest(SoupTest):
|
||||
'tax_rate': '19.00',
|
||||
'active': 'yes',
|
||||
'allow_cancel': 'yes',
|
||||
'sales_channels': 'web',
|
||||
})
|
||||
assert not TicketLayoutItem.objects.filter(item=self.item1, layout=bl2).exists()
|
||||
|
||||
|
||||
@@ -658,6 +658,22 @@ class CartTest(CartTestMixin, TestCase):
|
||||
self.assertIn('no longer available', doc.select('.alert-danger')[0].text)
|
||||
self.assertFalse(CartPosition.objects.filter(cart_id=self.session_key, event=self.event).exists())
|
||||
|
||||
def test_wrong_sales_channel(self):
|
||||
self.ticket.sales_channels = ['bar']
|
||||
self.ticket.save()
|
||||
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
|
||||
'item_%d' % self.ticket.id: '1',
|
||||
}, follow=True)
|
||||
self.assertEqual(CartPosition.objects.filter(cart_id=self.session_key, event=self.event).count(), 0)
|
||||
|
||||
def test_other_sales_channel(self):
|
||||
self.ticket.sales_channels = ['bar']
|
||||
self.ticket.save()
|
||||
self.client.post('/%s/%s/cart/add' % (self.orga.slug, self.event.slug), {
|
||||
'item_%d' % self.ticket.id: '1',
|
||||
}, follow=True, PRETIX_SALES_CHANNEL='bar')
|
||||
self.assertEqual(CartPosition.objects.filter(cart_id=self.session_key, event=self.event).count(), 1)
|
||||
|
||||
def test_in_time_available(self):
|
||||
self.ticket.available_until = now() + timedelta(days=2)
|
||||
self.ticket.available_from = now() - timedelta(days=2)
|
||||
|
||||
@@ -84,7 +84,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=False)
|
||||
q.items.add(item)
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)).rendered_content
|
||||
self.assertNotIn("Early-bird", html)
|
||||
self.assertNotIn("btn-add-to-cart", html)
|
||||
|
||||
@@ -96,6 +96,16 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
self.assertIn("Early-bird", doc.select("section .product-row")[0].text)
|
||||
self.assertEqual(len(doc.select("#btn-add-to-cart")), 1)
|
||||
|
||||
def test_sales_channel(self):
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=True,
|
||||
sales_channels=['bar'])
|
||||
q.items.add(item)
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)).rendered_content
|
||||
self.assertNotIn("Early-bird", html)
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug), PRETIX_SALES_CHANNEL="bar").rendered_content
|
||||
self.assertIn("Early-bird", html)
|
||||
|
||||
def test_timely_available(self):
|
||||
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=True,
|
||||
@@ -110,7 +120,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=True,
|
||||
available_until=now() - datetime.timedelta(days=2))
|
||||
q.items.add(item)
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)).rendered_content
|
||||
self.assertNotIn("Early-bird", html)
|
||||
|
||||
def test_not_yet_available(self):
|
||||
@@ -118,7 +128,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=True,
|
||||
available_from=now() + datetime.timedelta(days=2))
|
||||
q.items.add(item)
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)).rendered_content
|
||||
self.assertNotIn("Early-bird", html)
|
||||
|
||||
def test_hidden_without_voucher(self):
|
||||
@@ -126,7 +136,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=True,
|
||||
hide_without_voucher=True)
|
||||
q.items.add(item)
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))
|
||||
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)).rendered_content
|
||||
self.assertNotIn("Early-bird", html)
|
||||
|
||||
def test_simple_with_category(self):
|
||||
|
||||
Reference in New Issue
Block a user