mirror of
https://github.com/pretix/pretix.git
synced 2026-05-04 15:04:03 +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:
@@ -10,7 +10,7 @@ class ItemAssignmentSerializer(I18nAwareModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = TicketLayoutItem
|
||||
fields = ('item',)
|
||||
fields = ('item', 'sales_channel')
|
||||
|
||||
|
||||
class TicketLayoutSerializer(I18nAwareModelSerializer):
|
||||
|
||||
@@ -85,7 +85,13 @@ class AllTicketsPDF(BaseExporter):
|
||||
with language(op.order.locale):
|
||||
buffer = BytesIO()
|
||||
p = o._create_canvas(buffer)
|
||||
layout = o.layout_map.get(op.item_id, o.default_layout)
|
||||
layout = o.layout_map.get(
|
||||
(op.item_id, op.order.sales_channel),
|
||||
o.layout_map.get(
|
||||
(op.item_id, 'web'),
|
||||
o.default_layout
|
||||
)
|
||||
)
|
||||
o._draw_page(layout, p, op, op.order)
|
||||
p.save()
|
||||
outbuffer = o._render_with_background(layout, buffer)
|
||||
|
||||
@@ -19,13 +19,21 @@ class TicketLayoutItemForm(forms.ModelForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
event = kwargs.pop('event')
|
||||
self.sales_channel = kwargs.pop('sales_channel')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['layout'].label = _('PDF ticket layout')
|
||||
self.fields['layout'].empty_label = _('(Event default)')
|
||||
if self.sales_channel.identifier != 'web':
|
||||
self.fields['layout'].label = _('PDF ticket layout for {channel}').format(
|
||||
channel=self.sales_channel.verbose_name
|
||||
)
|
||||
self.fields['layout'].empty_label = _('(Same as above)')
|
||||
else:
|
||||
self.fields['layout'].label = _('PDF ticket layout')
|
||||
self.fields['layout'].empty_label = _('(Event default)')
|
||||
self.fields['layout'].queryset = event.ticket_layouts.all()
|
||||
self.fields['layout'].required = False
|
||||
|
||||
def save(self, commit=True):
|
||||
self.instance.sales_channel = self.sales_channel.identifier
|
||||
if self.cleaned_data['layout'] is None:
|
||||
if self.instance.pk:
|
||||
self.instance.delete()
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 2.1.1 on 2018-11-23 10:59
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0103_auto_20181121_1224'),
|
||||
('ticketoutputpdf', '0006_auto_20181017_0024'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ticketlayoutitem',
|
||||
name='sales_channel',
|
||||
field=models.CharField(default='web', max_length=190),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketlayoutitem',
|
||||
name='item',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketlayout_assignments', to='pretixbase.Item'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='ticketlayoutitem',
|
||||
unique_together={('item', 'layout', 'sales_channel')},
|
||||
),
|
||||
]
|
||||
@@ -66,6 +66,10 @@ class TicketLayout(LoggedModel):
|
||||
|
||||
|
||||
class TicketLayoutItem(models.Model):
|
||||
item = models.OneToOneField('pretixbase.Item', null=True, blank=True, related_name='ticketlayout_assignment',
|
||||
on_delete=models.CASCADE)
|
||||
item = models.ForeignKey('pretixbase.Item', null=True, blank=True, related_name='ticketlayout_assignments',
|
||||
on_delete=models.CASCADE)
|
||||
layout = models.ForeignKey('TicketLayout', on_delete=models.CASCADE, related_name='item_assignments')
|
||||
sales_channel = models.CharField(max_length=190, default='web')
|
||||
|
||||
class Meta:
|
||||
unique_together = (('item', 'layout', 'sales_channel'),)
|
||||
|
||||
@@ -7,6 +7,7 @@ from django.urls import reverse
|
||||
from django.utils.html import escape
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.models import QuestionAnswer
|
||||
from pretix.base.signals import ( # NOQA: legacy import
|
||||
event_copy_data, item_copy_data, layout_text_variables, logentry_display,
|
||||
@@ -61,25 +62,26 @@ def variables_from_questions(sender, *args, **kwargs):
|
||||
|
||||
@receiver(item_forms, dispatch_uid="pretix_ticketoutputpdf_item_forms")
|
||||
def control_item_forms(sender, request, item, **kwargs):
|
||||
try:
|
||||
inst = TicketLayoutItem.objects.get(item=item)
|
||||
except TicketLayoutItem.DoesNotExist:
|
||||
inst = TicketLayoutItem(item=item)
|
||||
return TicketLayoutItemForm(
|
||||
instance=inst,
|
||||
event=sender,
|
||||
data=(request.POST if request.method == "POST" else None),
|
||||
prefix="ticketlayoutitem"
|
||||
)
|
||||
forms = []
|
||||
for k, v in sorted(list(get_all_sales_channels().items()), key=lambda a: (int(a[0] != 'web'), a[0])):
|
||||
try:
|
||||
inst = TicketLayoutItem.objects.get(item=item, sales_channel=k)
|
||||
except TicketLayoutItem.DoesNotExist:
|
||||
inst = TicketLayoutItem(item=item)
|
||||
forms.append(TicketLayoutItemForm(
|
||||
instance=inst,
|
||||
event=sender,
|
||||
sales_channel=v,
|
||||
data=(request.POST if request.method == "POST" else None),
|
||||
prefix="ticketlayoutitem_{}".format(k)
|
||||
))
|
||||
return forms
|
||||
|
||||
|
||||
@receiver(item_copy_data, dispatch_uid="pretix_ticketoutputpdf_item_copy")
|
||||
def copy_item(sender, source, target, **kwargs):
|
||||
try:
|
||||
inst = TicketLayoutItem.objects.get(item=source)
|
||||
TicketLayoutItem.objects.create(item=target, layout=inst.layout)
|
||||
except TicketLayoutItem.DoesNotExist:
|
||||
pass
|
||||
for tli in TicketLayoutItem.objects.filter(item=source):
|
||||
TicketLayoutItem.objects.create(item=target, layout=tli.layout, sales_channel=tli.sales_channel)
|
||||
|
||||
|
||||
@receiver(signal=event_copy_data, dispatch_uid="pretix_ticketoutputpdf_copy_data")
|
||||
@@ -110,7 +112,8 @@ def pdf_event_copy_data_receiver(sender, other, item_map, question_map, **kwargs
|
||||
layout_map[oldid] = bl
|
||||
|
||||
for bi in TicketLayoutItem.objects.filter(item__event=other):
|
||||
TicketLayoutItem.objects.create(item=item_map.get(bi.item_id), layout=layout_map.get(bi.layout_id))
|
||||
TicketLayoutItem.objects.create(item=item_map.get(bi.item_id), layout=layout_map.get(bi.layout_id),
|
||||
sales_channel=bi.sales_channel)
|
||||
return layout_map
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ class PdfTicketOutput(BaseTicketOutput):
|
||||
@cached_property
|
||||
def layout_map(self):
|
||||
return {
|
||||
bi.item_id: bi.layout
|
||||
(bi.item_id, bi.sales_channel): bi.layout
|
||||
for bi in TicketLayoutItem.objects.select_related('layout').filter(item__event=self.event)
|
||||
}
|
||||
|
||||
@@ -68,7 +68,13 @@ class PdfTicketOutput(BaseTicketOutput):
|
||||
|
||||
buffer = BytesIO()
|
||||
p = self._create_canvas(buffer)
|
||||
layout = self.layout_map.get(op.item_id, self.default_layout)
|
||||
layout = self.layout_map.get(
|
||||
(op.item_id, order.sales_channel),
|
||||
self.layout_map.get(
|
||||
(op.item_id, 'web'),
|
||||
self.default_layout
|
||||
)
|
||||
)
|
||||
self._draw_page(layout, p, op, order)
|
||||
p.save()
|
||||
outbuffer = self._render_with_background(layout, buffer)
|
||||
@@ -84,7 +90,13 @@ class PdfTicketOutput(BaseTicketOutput):
|
||||
buffer = BytesIO()
|
||||
p = self._create_canvas(buffer)
|
||||
order = op.order
|
||||
layout = self.layout_map.get(op.item_id, self.default_layout)
|
||||
layout = self.layout_map.get(
|
||||
(op.item_id, order.sales_channel),
|
||||
self.layout_map.get(
|
||||
(op.item_id, 'web'),
|
||||
self.default_layout
|
||||
)
|
||||
)
|
||||
with language(order.locale):
|
||||
self._draw_page(layout, p, op, order)
|
||||
p.save()
|
||||
|
||||
Reference in New Issue
Block a user