diff --git a/doc/api/resources/categories.rst b/doc/api/resources/categories.rst index 22fb45675..5645e3c17 100644 --- a/doc/api/resources/categories.rst +++ b/doc/api/resources/categories.rst @@ -14,6 +14,7 @@ Field Type Description ===================================== ========================== ======================================================= id integer Internal ID of the category name multi-lingual string The category's visible name +internal_name string An optional name that is only used in the backend description multi-lingual string A public description (might include markdown, can be ``null``) position integer An integer, used for sorting the categories @@ -26,6 +27,10 @@ is_addon boolean If ``True``, it The operations POST, PATCH, PUT and DELETE have been added. +.. versionchanged:: 1.16 + + The field ``internal_name`` has been added. + Endpoints --------- @@ -58,6 +63,7 @@ Endpoints { "id": 1, "name": {"en": "Tickets"}, + "internal_name": "", "description": {"en": "Tickets are what you need to get in."}, "position": 1, "is_addon": false @@ -99,6 +105,7 @@ Endpoints { "id": 1, "name": {"en": "Tickets"}, + "internal_name": "", "description": {"en": "Tickets are what you need to get in."}, "position": 1, "is_addon": false @@ -126,6 +133,7 @@ Endpoints { "name": {"en": "Tickets"}, + "internal_name": "", "description": {"en": "Tickets are what you need to get in."}, "position": 1, "is_addon": false @@ -142,6 +150,7 @@ Endpoints { "id": 1, "name": {"en": "Tickets"}, + "internal_name": "", "description": {"en": "Tickets are what you need to get in."}, "position": 1, "is_addon": false @@ -187,6 +196,7 @@ Endpoints { "id": 1, "name": {"en": "Tickets"}, + "internal_name": "", "description": {"en": "Tickets are what you need to get in."}, "position": 1, "is_addon": true diff --git a/doc/api/resources/items.rst b/doc/api/resources/items.rst index 6e81db49b..87a7af3c3 100644 --- a/doc/api/resources/items.rst +++ b/doc/api/resources/items.rst @@ -14,6 +14,7 @@ Field Type Description ===================================== ========================== ======================================================= id integer Internal ID of the item name multi-lingual string The item's visible name +internal_name string An optional name that is only used in the backend default_price money (string) The item price that is applied if the price is not overwritten by variations or other options. category integer The ID of the category this item belongs to @@ -88,6 +89,10 @@ addons list of objects Definition of a The write operations ``POST``, ``PATCH``, ``PUT``, and ``DELETE`` have been added. The attribute ``price_included`` has been added to ``addons``. +.. versionchanged:: 1.16 + + The field ``internal_name`` has been added. + Notes ----- Please note that an item either always has variations or never has. Once created with variations the item can never @@ -129,6 +134,7 @@ Endpoints { "id": 1, "name": {"en": "Standard ticket"}, + "internal_name": "", "default_price": "23.00", "category": null, "active": true, @@ -211,6 +217,7 @@ Endpoints { "id": 1, "name": {"en": "Standard ticket"}, + "internal_name": "", "default_price": "23.00", "category": null, "active": true, @@ -274,6 +281,7 @@ Endpoints { "id": 1, "name": {"en": "Standard ticket"}, + "internal_name": "", "default_price": "23.00", "category": null, "active": true, @@ -324,6 +332,7 @@ Endpoints { "id": 1, "name": {"en": "Standard ticket"}, + "internal_name": "", "default_price": "23.00", "category": null, "active": true, @@ -406,6 +415,7 @@ Endpoints { "id": 1, "name": {"en": "Ticket"}, + "internal_name": "", "default_price": "25.00", "category": null, "active": true, diff --git a/src/pretix/api/serializers/item.py b/src/pretix/api/serializers/item.py index 9378fcff9..965fddc1d 100644 --- a/src/pretix/api/serializers/item.py +++ b/src/pretix/api/serializers/item.py @@ -74,7 +74,7 @@ class ItemSerializer(I18nAwareModelSerializer): class Meta: model = Item - fields = ('id', 'category', 'name', 'active', 'description', + fields = ('id', 'category', 'name', 'internal_name', 'active', 'description', 'default_price', 'free_price', 'tax_rate', 'tax_rule', 'admission', 'position', 'picture', 'available_from', 'available_until', 'require_voucher', 'hide_without_voucher', 'allow_cancel', @@ -129,7 +129,7 @@ class ItemCategorySerializer(I18nAwareModelSerializer): class Meta: model = ItemCategory - fields = ('id', 'name', 'description', 'position', 'is_addon') + fields = ('id', 'name', 'internal_name', 'description', 'position', 'is_addon') class QuestionOptionSerializer(I18nAwareModelSerializer): diff --git a/src/pretix/base/exporters/json.py b/src/pretix/base/exporters/json.py index 92dc87b00..c7623b65d 100644 --- a/src/pretix/base/exporters/json.py +++ b/src/pretix/base/exporters/json.py @@ -24,13 +24,15 @@ class JSONExporter(BaseExporter): 'categories': [ { 'id': category.id, - 'name': str(category.name) + 'name': str(category.name), + 'internal_name': category.internal_name } for category in self.event.categories.all() ], 'items': [ { 'id': item.id, 'name': str(item.name), + 'internal_name': str(item.internal_name), 'category': item.category_id, 'price': item.default_price, 'tax_rate': item.tax_rule.rate if item.tax_rule else Decimal('0.00'), diff --git a/src/pretix/base/migrations/0090_auto_20180509_0917.py b/src/pretix/base/migrations/0090_auto_20180509_0917.py new file mode 100644 index 000000000..c11a954e2 --- /dev/null +++ b/src/pretix/base/migrations/0090_auto_20180509_0917.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.11 on 2018-05-09 09:17 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('pretixbase', '0089_auto_20180315_1322'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='internal_name', + field=models.CharField(blank=True, + help_text='If you set this, this will be used instead of the public name in the ' + 'backend.', + max_length=255, null=True, verbose_name='Internal name'), + ), + migrations.AddField( + model_name='itemcategory', + name='internal_name', + field=models.CharField(blank=True, + help_text='If you set this, this will be used instead of the public name in the backend.', + max_length=255, null=True, verbose_name='Internal name'), + ), + ] diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py index 3ddceeec4..409967d42 100644 --- a/src/pretix/base/models/items.py +++ b/src/pretix/base/models/items.py @@ -43,6 +43,11 @@ class ItemCategory(LoggedModel): max_length=255, verbose_name=_("Category name"), ) + internal_name = models.CharField( + verbose_name=_("Internal name"), + help_text=_("If you set this, this will be used instead of the public name in the backend."), + blank=True, null=True, max_length=255 + ) description = I18nTextField( blank=True, verbose_name=_("Category description") ) @@ -63,9 +68,10 @@ class ItemCategory(LoggedModel): ordering = ('position', 'id') def __str__(self): + name = self.internal_name or self.name if self.is_addon: - return _('{category} (Add-On products)').format(category=str(self.name)) - return str(self.name) + return _('{category} (Add-On products)').format(category=str(name)) + return str(name) def delete(self, *args, **kwargs): super().delete(*args, **kwargs) @@ -205,6 +211,11 @@ class Item(LoggedModel): max_length=255, verbose_name=_("Item name"), ) + internal_name = models.CharField( + verbose_name=_("Internal name"), + help_text=_("If you set this, this will be used instead of the public name in the backend."), + blank=True, null=True, max_length=255 + ) active = models.BooleanField( default=True, verbose_name=_("Active"), @@ -309,7 +320,7 @@ class Item(LoggedModel): ordering = ("category__position", "category", "position") def __str__(self): - return str(self.name) + return str(self.internal_name or self.name) def save(self, *args, **kwargs): super().save(*args, **kwargs) diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py index 71d082956..b07022899 100644 --- a/src/pretix/base/pdf.py +++ b/src/pretix/base/pdf.py @@ -46,7 +46,7 @@ DEFAULT_VARIABLES = OrderedDict(( ("item", { "label": _("Product name"), "editor_sample": _("Sample product"), - "evaluate": lambda orderposition, order, event: str(orderposition.item) + "evaluate": lambda orderposition, order, event: str(orderposition.item.name) }), ("variation", { "label": _("Variation name"), @@ -62,8 +62,8 @@ DEFAULT_VARIABLES = OrderedDict(( "label": _("Product name and variation"), "editor_sample": _("Sample product – sample variation"), "evaluate": lambda orderposition, order, event: ( - '{} - {}'.format(orderposition.item, orderposition.variation) - if orderposition.variation else str(orderposition.item) + '{} - {}'.format(orderposition.item.name, orderposition.variation) + if orderposition.variation else str(orderposition.item.name) ) }), ("item_category", { diff --git a/src/pretix/base/services/stats.py b/src/pretix/base/services/stats.py index 18841fa2d..6ef671bc3 100644 --- a/src/pretix/base/services/stats.py +++ b/src/pretix/base/services/stats.py @@ -10,10 +10,6 @@ from pretix.base.models.orders import OrderFee from pretix.base.signals import order_fee_type_name -class DummyObject: - pass - - class Dontsum: def __init__(self, value: Any): self.value = value @@ -158,8 +154,7 @@ def order_overview(event: Event, subevent: SubEvent=None) -> Tuple[List[Tuple[It c[0].num_paid = tuplesum(item.num_paid for item in c[1]) # Payment fees - payment_cat_obj = DummyObject() - payment_cat_obj.name = _('Fees') + payment_cat_obj = _('Fees') payment_items = [] if not subevent: @@ -198,9 +193,8 @@ def order_overview(event: Event, subevent: SubEvent=None) -> Tuple[List[Tuple[It names = dict(OrderFee.FEE_TYPES) for pprov, total in sorted(num_total.items(), key=lambda i: i[0]): - ppobj = DummyObject() if pprov[0] == OrderFee.FEE_TYPE_PAYMENT: - ppobj.name = '{} - {}'.format(names[pprov[0]], provider_names.get(pprov[1], pprov[1])) + ppobj = '{} - {}'.format(names[pprov[0]], provider_names.get(pprov[1], pprov[1])) else: name = pprov[1] for r, resp in order_fee_type_name.send(sender=event, fee_type=pprov[0], internal_type=pprov[1]): @@ -208,7 +202,7 @@ def order_overview(event: Event, subevent: SubEvent=None) -> Tuple[List[Tuple[It name = resp break - ppobj.name = '{} - {}'.format(names[pprov[0]], name) + ppobj = '{} - {}'.format(names[pprov[0]], name) ppobj.provider = pprov[1] ppobj.has_variations = False ppobj.num_total = total diff --git a/src/pretix/control/forms/item.py b/src/pretix/control/forms/item.py index ba4b6354a..59a2406e4 100644 --- a/src/pretix/control/forms/item.py +++ b/src/pretix/control/forms/item.py @@ -27,6 +27,7 @@ class CategoryForm(I18nModelForm): localized_fields = '__all__' fields = [ 'name', + 'internal_name', 'description', 'is_addon' ] @@ -90,9 +91,9 @@ class QuotaForm(I18nModelForm): for item in items: if len(item.variations.all()) > 0: for v in item.variations.all(): - choices.append(('{}-{}'.format(item.pk, v.pk), '{} – {}'.format(item.name, v.value))) + choices.append(('{}-{}'.format(item.pk, v.pk), '{} – {}'.format(item, v.value))) else: - choices.append(('{}'.format(item.pk), item.name)) + choices.append(('{}'.format(item.pk), str(item))) self.fields['itemvars'] = forms.MultipleChoiceField( label=_('Products'), @@ -282,6 +283,7 @@ class ItemCreateForm(I18nModelForm): localized_fields = '__all__' fields = [ 'name', + 'internal_name', 'category', 'admission', 'default_price', @@ -308,6 +310,7 @@ class ItemUpdateForm(I18nModelForm): fields = [ 'category', 'name', + 'internal_name', 'active', 'admission', 'description', diff --git a/src/pretix/control/forms/orders.py b/src/pretix/control/forms/orders.py index 0cb8ad394..e1d5f3072 100644 --- a/src/pretix/control/forms/orders.py +++ b/src/pretix/control/forms/orders.py @@ -144,7 +144,7 @@ class OrderPositionAddForm(forms.Form): choices = [] for i in order.event.items.prefetch_related('variations').all(): - pname = str(i.name) + pname = str(i) if not i.is_available(): pname += ' ({})'.format(_('inactive')) variations = list(i.variations.all()) @@ -243,7 +243,7 @@ class OrderPositionChangeForm(forms.Form): choices = [] for i in instance.order.event.items.prefetch_related('variations').all(): - pname = str(i.name) + pname = str(i) if not i.is_available(): pname += ' ({})'.format(_('inactive')) variations = list(i.variations.all()) diff --git a/src/pretix/control/forms/subevents.py b/src/pretix/control/forms/subevents.py index 935d7fcd3..219b2a670 100644 --- a/src/pretix/control/forms/subevents.py +++ b/src/pretix/control/forms/subevents.py @@ -102,7 +102,7 @@ class SubEventItemForm(SubEventItemOrVariationFormMixin, forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['price'].widget.attrs['placeholder'] = money_filter(self.item.default_price, self.item.event.currency, hide_currency=True) - self.fields['price'].label = str(self.item.name) + self.fields['price'].label = str(self.item) class Meta: model = SubEventItem @@ -116,7 +116,7 @@ class SubEventItemVariationForm(SubEventItemOrVariationFormMixin, forms.ModelFor def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['price'].widget.attrs['placeholder'] = money_filter(self.variation.price, self.item.event.currency, hide_currency=True) - self.fields['price'].label = '{} – {}'.format(str(self.item.name), self.variation.value) + self.fields['price'].label = '{} – {}'.format(str(self.item), self.variation.value) class Meta: model = SubEventItem diff --git a/src/pretix/control/forms/vouchers.py b/src/pretix/control/forms/vouchers.py index e4684c1ab..55a4b34dc 100644 --- a/src/pretix/control/forms/vouchers.py +++ b/src/pretix/control/forms/vouchers.py @@ -86,13 +86,13 @@ class VoucherForm(I18nModelForm): itemid, varid = iv.split('-') i = self.instance.event.items.get(pk=itemid) v = i.variations.get(pk=varid) - choices.append(('%d-%d' % (i.pk, v.pk), '%s – %s' % (i.name, v.value))) + choices.append(('%d-%d' % (i.pk, v.pk), '%s – %s' % (str(i), v.value))) elif iv: i = self.instance.event.items.get(pk=iv) if i.variations.exists(): - choices.append((str(i.pk), _('{product} – Any variation').format(product=i.name))) + choices.append((str(i.pk), _('{product} – Any variation').format(product=i))) else: - choices.append((str(i.pk), str(i.name))) + choices.append((str(i.pk), str(i))) self.fields['itemvar'].choices = choices self.fields['itemvar'].widget = Select2ItemVarQuota( diff --git a/src/pretix/control/templates/pretixcontrol/checkin/index.html b/src/pretix/control/templates/pretixcontrol/checkin/index.html index 614f4bf38..032b1c07d 100644 --- a/src/pretix/control/templates/pretixcontrol/checkin/index.html +++ b/src/pretix/control/templates/pretixcontrol/checkin/index.html @@ -90,7 +90,7 @@ {% trans "unpaid" %} {% endif %} - {{ e.item.name }}{% if e.variation %} – {{ e.variation }}{% endif %} + {{ e.item }}{% if e.variation %} – {{ e.variation }}{% endif %} {{ e.order.email }} {% if e.addon_to %} diff --git a/src/pretix/control/templates/pretixcontrol/event/base.html b/src/pretix/control/templates/pretixcontrol/event/base.html index c778f8bcd..5bc7965e3 100644 --- a/src/pretix/control/templates/pretixcontrol/event/base.html +++ b/src/pretix/control/templates/pretixcontrol/event/base.html @@ -42,7 +42,7 @@