Compare commits

...
Author SHA1 Message Date
Mira Weller 167105a552 Add hidden_if_item_available_mode to API docs 2025-01-24 09:59:52 +01:00
Mira Weller 899843cacc Fix tests 2025-01-23 15:14:37 +01:00
Mira Weller af3e0bce28 Fix error 2025-01-23 13:05:18 +01:00
Mira Weller a7a5d8e3aa Add migration 2025-01-23 13:03:15 +01:00
Mira Weller c6879f5ed1 Implement hidden_if_item_available_mode option 2025-01-23 12:49:35 +01:00
Mira Weller ccc0fac499 Deduplicate options, use same wording everywhere 2025-01-23 12:48:54 +01:00
Hijiri UmemotoandRaphael Michel dd4bac70be Translations: Update Japanese
Currently translated at 99.8% (5837 of 5844 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ja/

powered by weblate
2025-01-22 18:36:36 +01:00
Johanna KetolaandRaphael Michel 1187757b56 Translations: Update Finnish
Currently translated at 25.3% (1484 of 5844 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fi/

powered by weblate
2025-01-22 18:36:36 +01:00
CVZ-esandRaphael Michel abe5b4ef53 Translations: Update Spanish
Currently translated at 100.0% (5844 of 5844 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2025-01-22 18:36:36 +01:00
CVZ-esandRaphael Michel b1fb391d08 Translations: Update French
Currently translated at 100.0% (5844 of 5844 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2025-01-22 18:36:36 +01:00
Raphael MichelandRaphael Michel a95c6d94ee Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (235 of 235 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de_Informal/

powered by weblate
2025-01-22 18:36:36 +01:00
Raphael MichelandRaphael Michel 4809558343 Translations: Update German
Currently translated at 100.0% (235 of 235 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de/

powered by weblate
2025-01-22 18:36:36 +01:00
Raphael Michel a6d1af01d2 Fix missing language info for nb-NO (default is just nb) (Z#23177041) 2025-01-22 15:57:47 +01:00
Raphael Michel 23e58996bc Invoice preview: Fix missing delivery date 2025-01-22 11:49:20 +01:00
Raphael MichelandRaphael Michel 15e05dae2f Translations: Update German (informal) (de_Informal)
Currently translated at 100.0% (5844 of 5844 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2025-01-21 18:25:40 +01:00
Raphael MichelandRaphael Michel ce40524ae8 Translations: Update German
Currently translated at 100.0% (5844 of 5844 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2025-01-21 18:25:40 +01:00
Raphael MichelandGitHub 46aefc10f3 Order change form: No default fee type, use most generic fee type first (Z#23179634) (#4771) 2025-01-21 17:48:31 +01:00
Raphael Michel 1f49b577f0 Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2025-01-21 17:43:41 +01:00
Hijiri UmemotoandRaphael Michel b3aa405bcc Translations: Update Japanese
Currently translated at 100.0% (5840 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ja/

powered by weblate
2025-01-21 17:42:33 +01:00
HectorandRaphael Michel f29b60b3db Translations: Update Spanish
Currently translated at 100.0% (235 of 235 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/es/

powered by weblate
2025-01-21 17:42:33 +01:00
HectorandRaphael Michel 603e7821cc Translations: Update Spanish
Currently translated at 100.0% (5844 of 5844 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2025-01-21 17:42:33 +01:00
Raphael MichelandGitHub ffdc73e0a3 Show percentage of discount in cart (Z#23176955) (#4719)
* Show percentage of discount in cart (Z#23176955)

* Fix computation
2025-01-21 16:35:15 +01:00
Raphael MichelandGitHub 00b4622afa Address form logic: Respect dependency of VAT ID on is_business (#4713) 2025-01-21 15:05:16 +01:00
Raphael MichelandGitHub 045edc7cec Invoice rendering: Remove transparency from logos (Z#23179391) (#4762)
* Invoice rendering: Remove logos from transparency

* Add comment
2025-01-21 15:03:43 +01:00
Raphael MichelandGitHub 1635118772 Copy ItemVariation.limit_sales_channels when copying items (#4752) 2025-01-21 15:01:28 +01:00
MiraandGitHub 87c987fee5 Only display tax rates with non-zero gross amount (#4760) 2025-01-20 14:49:04 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1267bf8ba8 Update webauthn requirement from ==2.4.* to ==2.5.* (#4766)
Updates the requirements on [webauthn](https://github.com/duo-labs/py_webauthn) to permit the latest version.
- [Release notes](https://github.com/duo-labs/py_webauthn/releases)
- [Changelog](https://github.com/duo-labs/py_webauthn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/duo-labs/py_webauthn/compare/v2.4.0...v2.5.0)

---
updated-dependencies:
- dependency-name: webauthn
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 12:49:03 +01:00
Serge BazanskiandRaphael Michel a8d1ed8ee1 Translations: Update Polish (informal) (pl_Informal)
Currently translated at 13.3% (782 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl_Informal/

powered by weblate
2025-01-20 12:45:01 +01:00
Serge BazanskiandRaphael Michel b7736d5e82 Translations: Update Polish (informal) (pl_Informal)
Currently translated at 12.0% (701 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl_Informal/

powered by weblate
2025-01-20 12:45:01 +01:00
Serge BazanskiandRaphael Michel cfefe5bfc3 Translations: Update Polish (informal) (pl_Informal)
Currently translated at 100.0% (235 of 235 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/pl_Informal/

powered by weblate
2025-01-20 12:45:01 +01:00
Serge BazanskiandRaphael Michel f0f272b304 Translations: Update Polish (informal) (pl_Informal)
Currently translated at 6.8% (398 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl_Informal/

powered by weblate
2025-01-20 12:45:01 +01:00
Wiktor PrzybylskiandRaphael Michel e8b159e6d4 Translations: Update Polish
Currently translated at 98.7% (5769 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2025-01-20 12:45:01 +01:00
Hijiri UmemotoandRaphael Michel b0de6815db Translations: Update Japanese
Currently translated at 100.0% (235 of 235 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/ja/

powered by weblate
2025-01-20 12:45:01 +01:00
Hijiri UmemotoandRaphael Michel 92ceea2680 Translations: Update Japanese
Currently translated at 100.0% (5840 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ja/

powered by weblate
2025-01-20 12:45:01 +01:00
Wiktor PrzybylskiandRaphael Michel c2a9f9f76a Translations: Update Polish
Currently translated at 98.4% (5751 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2025-01-20 12:45:01 +01:00
Wiktor PrzybylskiandRaphael Michel 1e1f0e5d86 Translations: Update Polish
Currently translated at 98.3% (5746 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/pl/

powered by weblate
2025-01-20 12:45:01 +01:00
Richard SchreiberandGitHub 9634907539 [a11y] Remove h1 aria-label in presale 2025-01-20 08:57:21 +01:00
Raphael MichelandRaphael Michel 70dd688ec1 Translations: Add Flemish (West) 2025-01-17 17:49:14 +01:00
Raphael MichelandRaphael Michel 5ad0213195 Translations: Add Albanian 2025-01-17 17:49:14 +01:00
Raphael MichelandRaphael Michel c40cf45179 Translations: Add Faroese 2025-01-17 17:49:14 +01:00
CVZ-esandRaphael Michel a72839fd0e Translations: Update Spanish
Currently translated at 100.0% (5844 of 5844 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/es/

powered by weblate
2025-01-17 17:49:14 +01:00
CVZ-esandRaphael Michel 5071db0a8b Translations: Update French
Currently translated at 100.0% (5840 of 5840 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2025-01-17 17:49:14 +01:00
82 changed files with 148594 additions and 51093 deletions
+13
View File
@@ -69,6 +69,10 @@ hidden_if_available integer **DEPRECATED*
hidden_if_item_available integer The internal ID of a different item, or ``null``. If
set, this item won't be shown publicly as long as this
other item is available.
hidden_if_item_available_mode string If ``hide`` (the default), this item is hidden in the shop
if unavailable due to the ``hidden_if_item_available`` setting.
If ``info``, the item is visible, but can't be purchased,
and a note explaining the unavailability is displayed.
require_voucher boolean If ``true``, this item can only be bought using a
voucher that is specifically assigned to this item.
hide_without_voucher boolean If ``true``, this item is only shown during the voucher
@@ -239,6 +243,10 @@ meta_data object Values set fo
The ``hidden_if_item_available`` attributes has been added, the ``hidden_if_available`` attribute has been
deprecated.
.. versionchanged:: 2025.01
The ``hidden_if_item_available_mode`` attributes has been added.
Notes
-----
@@ -308,6 +316,7 @@ Endpoints
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"hidden_if_item_available_mode": "hide",
"require_voucher": false,
"hide_without_voucher": false,
"allow_cancel": true,
@@ -459,6 +468,7 @@ Endpoints
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"hidden_if_item_available_mode": "hide",
"require_voucher": false,
"hide_without_voucher": false,
"allow_cancel": true,
@@ -589,6 +599,7 @@ Endpoints
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"hidden_if_item_available_mode": "hide",
"require_voucher": false,
"hide_without_voucher": false,
"allow_cancel": true,
@@ -705,6 +716,7 @@ Endpoints
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"hidden_if_item_available_mode": "hide",
"require_voucher": false,
"hide_without_voucher": false,
"allow_cancel": true,
@@ -855,6 +867,7 @@ Endpoints
"available_until_mode": "hide",
"hidden_if_available": null,
"hidden_if_item_available": null,
"hidden_if_item_available_mode": "hide",
"require_voucher": false,
"hide_without_voucher": false,
"generate_tickets": null,
+1 -1
View File
@@ -100,7 +100,7 @@ dependencies = [
"ua-parser==1.0.*",
"vat_moss_forked==2020.3.20.0.11.0",
"vobject==0.9.*",
"webauthn==2.4.*",
"webauthn==2.5.*",
"zeep==4.3.*"
]
+6
View File
@@ -163,6 +163,12 @@ EXTRA_LANG_INFO = {
'name': 'Portuguese',
'name_local': 'Português',
},
'nb-no': {
'bidi': False,
'code': 'nb-no',
'name': 'Norwegian Bokmal',
'name_local': 'norsk (bokmål)',
},
}
django.conf.locale.LANG_INFO.update(EXTRA_LANG_INFO)
+1 -1
View File
@@ -272,7 +272,7 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
'require_voucher', 'hide_without_voucher', 'allow_cancel', 'require_bundling',
'min_per_order', 'max_per_order', 'checkin_attention', 'checkin_text', 'has_variations', 'variations',
'addons', 'bundles', 'original_price', 'require_approval', 'generate_tickets',
'show_quota_left', 'hidden_if_available', 'hidden_if_item_available', 'allow_waitinglist',
'show_quota_left', 'hidden_if_available', 'hidden_if_item_available', 'hidden_if_item_available_mode', 'allow_waitinglist',
'issue_giftcard', 'meta_data',
'require_membership', 'require_membership_types', 'require_membership_hidden', 'grant_membership_type',
'grant_membership_duration_like_event', 'grant_membership_duration_days',
+11
View File
@@ -388,6 +388,15 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
except:
logger.exception("Can not resize image")
pass
try:
# Valid ZUGFeRD invoices must be compliant with PDF/A-3. pretix-zugferd ensures this by passing them
# through ghost script. Unfortunately, if the logo contains transparency, this will still fail.
# I was unable to figure out a way to fix this in GhostScript, so the easy fix is to remove the
# transparency, as our invoices always have a white background anyways.
ir.remove_transparency()
except:
logger.exception("Can not remove transparency from logo")
pass
canvas.drawImage(ir,
self.logo_left,
self.pagesize[1] - self.logo_height - self.logo_top,
@@ -775,6 +784,8 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
for idx, gross in grossvalue_map.items():
rate, name = idx
if rate == 0 and gross == 0:
continue
tax = taxvalue_map[idx]
tdata.append([
Paragraph(self._normalize(localize(rate) + " % " + name), self.stylesheet['Fineprint']),
@@ -0,0 +1,18 @@
# Generated by Django 4.2.16 on 2025-01-23 11:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("pretixbase", "0275_alter_question_valid_number_max_and_more"),
]
operations = [
migrations.AddField(
model_name="item",
name="hidden_if_item_available_mode",
field=models.CharField(default="hide", max_length=16),
),
]
+12 -1
View File
@@ -442,8 +442,12 @@ class Item(LoggedModel):
UNAVAIL_MODE_INFO = "info"
UNAVAIL_MODES = (
(UNAVAIL_MODE_HIDDEN, _("Hide product if unavailable")),
(UNAVAIL_MODE_INFO, _("Show info text if unavailable")),
(UNAVAIL_MODE_INFO, _("Show product with info on why its unavailable")),
)
UNAVAIL_MODE_ICONS = {
UNAVAIL_MODE_HIDDEN: 'eye-slash',
UNAVAIL_MODE_INFO: 'info'
}
MEDIA_POLICY_REUSE = 'reuse'
MEDIA_POLICY_NEW = 'new'
@@ -596,6 +600,11 @@ class Item(LoggedModel):
"be a short period in which both products are visible while all tickets of the referenced "
"product are reserved, but not yet sold.")
)
hidden_if_item_available_mode = models.CharField(
choices=UNAVAIL_MODES,
default=UNAVAIL_MODE_HIDDEN,
max_length=16,
)
require_voucher = models.BooleanField(
verbose_name=_('This product can only be bought using a voucher.'),
default=False,
@@ -885,6 +894,8 @@ class Item(LoggedModel):
return 'available_from'
elif subevent_item and subevent_item.available_until and subevent_item.available_until < now_dt:
return 'available_until'
elif self.hidden_if_item_available and self._dependency_available:
return 'hidden_if_item_available'
else:
return None
+7 -1
View File
@@ -2281,9 +2281,9 @@ class OrderFee(models.Model):
FEE_TYPE_OTHER = "other"
FEE_TYPE_GIFTCARD = "giftcard"
FEE_TYPES = (
(FEE_TYPE_SERVICE, _("Service fee")),
(FEE_TYPE_PAYMENT, _("Payment fee")),
(FEE_TYPE_SHIPPING, _("Shipping fee")),
(FEE_TYPE_SERVICE, _("Service fee")),
(FEE_TYPE_CANCELLATION, _("Cancellation fee")),
(FEE_TYPE_INSURANCE, _("Insurance fee")),
(FEE_TYPE_LATE, _("Late fee")),
@@ -3218,6 +3218,12 @@ class CartPosition(AbstractPosition):
self.tax_code = line_price.code
self.save(update_fields=['line_price_gross', 'tax_rate'])
@property
def discount_percentage(self):
if not self.line_price_gross:
return 0
return (self.line_price_gross - self.price) / self.line_price_gross * 100
@property
def addons_without_bundled(self):
addons = [op for op in self.addons.all() if not op.is_bundled]
+6
View File
@@ -495,12 +495,18 @@ def build_preview_invoice_pdf(event):
invoice=invoice, description=_("Sample product {}").format(i + 1),
gross_value=tax.gross, tax_value=tax.tax,
tax_rate=tax.rate, tax_name=tax.name, tax_code=tax.code,
event_date_from=event.date_from,
event_date_to=event.date_to,
event_location=event.settings.invoice_event_location,
)
else:
for i in range(5):
InvoiceLine.objects.create(
invoice=invoice, description=_("Sample product A"),
gross_value=100, tax_value=0, tax_rate=0, tax_code=None,
event_date_from=event.date_from,
event_date_to=event.date_to,
event_location=event.settings.invoice_event_location,
)
return event.invoice_renderer.generate(invoice)
+13 -16
View File
@@ -476,6 +476,7 @@ class ItemCreateForm(I18nModelForm):
'show_quota_left',
'hidden_if_available',
'hidden_if_item_available',
'hidden_if_item_available_mode',
'require_bundling',
'require_membership',
'grant_membership_type',
@@ -539,6 +540,8 @@ class ItemCreateForm(I18nModelForm):
v.pk = None
v.item = instance
v.save()
if not variation.all_sales_channels:
v.limit_sales_channels.set(variation.limit_sales_channels.all())
for mv in variation.meta_values.all():
mv.pk = None
mv.variation = v
@@ -644,18 +647,12 @@ class ItemUpdateForm(I18nModelForm):
self.fields['available_from_mode'].widget = ButtonGroupRadioSelect(
choices=self.fields['available_from_mode'].choices,
option_icons={
Item.UNAVAIL_MODE_HIDDEN: 'eye-slash',
Item.UNAVAIL_MODE_INFO: 'info'
}
option_icons=Item.UNAVAIL_MODE_ICONS
)
self.fields['available_until_mode'].widget = ButtonGroupRadioSelect(
choices=self.fields['available_until_mode'].choices,
option_icons={
Item.UNAVAIL_MODE_HIDDEN: 'eye-slash',
Item.UNAVAIL_MODE_INFO: 'info'
}
option_icons=Item.UNAVAIL_MODE_ICONS
)
self.fields['hide_without_voucher'].widget = ButtonGroupRadioSelect(
@@ -670,6 +667,11 @@ class ItemUpdateForm(I18nModelForm):
attrs={'data-checkbox-dependency': '#id_require_voucher'}
)
self.fields['hidden_if_item_available_mode'].widget = ButtonGroupRadioSelect(
choices=self.fields['hidden_if_item_available_mode'].choices,
option_icons=Item.UNAVAIL_MODE_ICONS
)
if self.instance.hidden_if_available_id:
self.fields['hidden_if_available'].queryset = self.event.quotas.all()
self.fields['hidden_if_available'].help_text = format_html(
@@ -851,6 +853,7 @@ class ItemUpdateForm(I18nModelForm):
'show_quota_left',
'hidden_if_available',
'hidden_if_item_available',
'hidden_if_item_available_mode',
'issue_giftcard',
'require_membership',
'require_membership_types',
@@ -968,18 +971,12 @@ class ItemVariationForm(I18nModelForm):
self.fields['available_from_mode'].widget = ButtonGroupRadioSelect(
choices=self.fields['available_from_mode'].choices,
option_icons={
Item.UNAVAIL_MODE_HIDDEN: 'eye-slash',
Item.UNAVAIL_MODE_INFO: 'info'
}
option_icons=Item.UNAVAIL_MODE_ICONS
)
self.fields['available_until_mode'].widget = ButtonGroupRadioSelect(
choices=self.fields['available_until_mode'].choices,
option_icons={
Item.UNAVAIL_MODE_HIDDEN: 'eye-slash',
Item.UNAVAIL_MODE_INFO: 'info'
}
option_icons=Item.UNAVAIL_MODE_ICONS
)
self.meta_fields = []
+7 -1
View File
@@ -612,7 +612,13 @@ class OrderFeeChangeForm(forms.Form):
class OrderFeeAddForm(forms.Form):
fee_type = forms.ChoiceField(choices=OrderFee.FEE_TYPES)
fee_type = forms.ChoiceField(
choices=[("", ""), *OrderFee.FEE_TYPES],
help_text=_(
"Note that payment fees have a special semantic and might automatically be changed if the "
"payment method of the order is changed."
)
)
value = forms.DecimalField(
max_digits=13, decimal_places=2,
localize=True,
@@ -172,7 +172,7 @@
{% if form.hidden_if_available %}
{% bootstrap_field form.hidden_if_available layout="control" horizontal_field_class="col-md-7" %}
{% endif %}
{% bootstrap_field form.hidden_if_item_available layout="control" horizontal_field_class="col-md-7" %}
{% bootstrap_field form.hidden_if_item_available visibility_field=form.hidden_if_item_available_mode layout="control_with_visibility" %}
</fieldset>
{% for v in formsets.values %}
<fieldset>
@@ -2,5 +2,5 @@
{% if mode == "hide" %}
<span class="pull-right text-muted unavail-mode-indicator" data-toggle="tooltip" title="{% trans "Hide product if unavailable" %}. {% if f.variation %}{% trans "You can change this option in the variation settings." %}{% else %}{% trans "You can change this option in the product settings." %}{% endif %}"><span class="fa fa-eye-slash"></span></span>
{% else %}
<span class="pull-right text-muted unavail-mode-indicator" data-toggle="tooltip" title="{% trans "Show info text if unavailable" %}. {% if f.variation %}{% trans "You can change this option in the variation settings." %}{% else %}{% trans "You can change this option in the product settings." %}{% endif %}"><span class="fa fa-info-circle"></span></span>
<span class="pull-right text-muted unavail-mode-indicator" data-toggle="tooltip" title="{% trans "Show product with info on why its unavailable" %}. {% if f.variation %}{% trans "You can change this option in the variation settings." %}{% else %}{% trans "You can change this option in the product settings." %}{% endif %}"><span class="fa fa-info-circle"></span></span>
{% endif %}
+6
View File
@@ -39,6 +39,12 @@ class ThumbnailingImageReader(ImageReader):
self._data = None
return width, height
def remove_transparency(self, background_color="WHITE"):
if "A" in self._image.mode:
new_image = Image.new("RGBA", self._image.size, background_color)
new_image.paste(self._image, mask=self._image)
self._image = new_image.convert("RGB")
def _jpeg_fh(self):
# Bypass a reportlab-internal optimization that falls back to the original
# file handle if the file is a JPEG, and therefore does not respect the
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-15 16:46+0000\n"
"PO-Revision-Date: 2024-09-10 07:17+0000\n"
"PO-Revision-Date: 2025-01-22 16:00+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
"de/>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.7\n"
"X-Generator: Weblate 5.9.2\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -777,13 +777,13 @@ msgstr "Preis"
#, javascript-format
msgctxt "widget"
msgid "Original price: %s"
msgstr ""
msgstr "Originalpreis: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:21
#, javascript-format
msgctxt "widget"
msgid "New price: %s"
msgstr ""
msgstr "Neuer Preis: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:22
msgctxt "widget"
@@ -836,7 +836,7 @@ msgstr "ab %(currency)s %(price)s"
#, javascript-format
msgctxt "widget"
msgid "Image of %s"
msgstr ""
msgstr "Bild von %s"
#: pretix/static/pretixpresale/js/widget/widget.js:32
msgctxt "widget"
File diff suppressed because it is too large Load Diff
@@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-15 16:46+0000\n"
"PO-Revision-Date: 2024-09-10 07:17+0000\n"
"PO-Revision-Date: 2025-01-22 16:00+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
"pretix/pretix-js/de_Informal/>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.7\n"
"X-Generator: Weblate 5.9.2\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -776,13 +776,13 @@ msgstr "Preis"
#, javascript-format
msgctxt "widget"
msgid "Original price: %s"
msgstr ""
msgstr "Originalpreis: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:21
#, javascript-format
msgctxt "widget"
msgid "New price: %s"
msgstr ""
msgstr "Neuer Preis: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:22
msgctxt "widget"
@@ -835,7 +835,7 @@ msgstr "ab %(currency)s %(price)s"
#, javascript-format
msgctxt "widget"
msgid "Image of %s"
msgstr ""
msgstr "Bild von %s"
#: pretix/static/pretixpresale/js/widget/widget.js:32
msgctxt "widget"
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-15 16:46+0000\n"
"POT-Creation-Date: 2025-01-21 16:43+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-15 16:46+0000\n"
"PO-Revision-Date: 2025-01-16 10:32+0000\n"
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
"PO-Revision-Date: 2025-01-21 00:00+0000\n"
"Last-Translator: Hector <hector@demandaeventos.es>\n"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/"
"pretix-js/es/>\n"
"Language: es\n"
@@ -775,7 +775,7 @@ msgstr "Precio"
#, javascript-format
msgctxt "widget"
msgid "Original price: %s"
msgstr "Prix initial : %s"
msgstr "Precio original: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:21
#, javascript-format
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+20 -26
View File
@@ -8,10 +8,10 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-15 16:46+0000\n"
"PO-Revision-Date: 2024-12-27 11:45+0000\n"
"PO-Revision-Date: 2025-01-18 18:00+0000\n"
"Last-Translator: Hijiri Umemoto <hijiri@umemoto.org>\n"
"Language-Team: Japanese <https://translate.pretix.eu/projects/pretix/pretix-"
"js/ja/>\n"
"Language-Team: Japanese <https://translate.pretix.eu/projects/pretix/"
"pretix-js/ja/>\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -31,7 +31,7 @@ msgstr "注釈:"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
msgid "PayPal"
msgstr ""
msgstr "PayPal"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
msgid "Venmo"
@@ -60,19 +60,19 @@ msgstr "PayPal後払い"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
msgid "iDEAL"
msgstr ""
msgstr "iDEAL"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
msgid "SEPA Direct Debit"
msgstr ""
msgstr "SEPA Direct Debit"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
msgid "Bancontact"
msgstr ""
msgstr "Bancontact"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
msgid "giropay"
msgstr ""
msgstr "giropay"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
msgid "SOFORT"
@@ -88,7 +88,7 @@ msgstr "MyBank"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
msgid "Przelewy24"
msgstr ""
msgstr "Przelewy24"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
msgid "Verkkopankki"
@@ -124,7 +124,7 @@ msgstr "Boleto"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
msgid "WeChat Pay"
msgstr ""
msgstr "WeChat Pay"
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
msgid "Mercado Pago"
@@ -241,7 +241,7 @@ msgstr "確認済み"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
msgid "Approval pending"
msgstr ""
msgstr "承認保留中"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
msgid "Redeemed"
@@ -297,16 +297,12 @@ msgid "Ticket code revoked/changed"
msgstr "チケットコードのブロック/変更"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
#, fuzzy
#| msgid "Ticket not paid"
msgid "Ticket blocked"
msgstr "チケット未払い"
msgstr "チケットブロック中"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
#, fuzzy
#| msgid "Ticket not paid"
msgid "Ticket not valid at this time"
msgstr "チケット未払い"
msgstr "現時点で無効なチケット"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
msgid "Order canceled"
@@ -314,11 +310,11 @@ msgstr "注文がキャンセルされました"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
msgid "Ticket code is ambiguous on list"
msgstr ""
msgstr "リストのチケットコードは曖昧です"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
msgid "Order not approved"
msgstr ""
msgstr "承認されない注文"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
msgid "Checked-in Tickets"
@@ -455,7 +451,7 @@ msgstr "商品の種類"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
msgid "Gate"
msgstr ""
msgstr "ゲート"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
msgid "Current date and time"
@@ -576,10 +572,8 @@ msgid "Text object (deprecated)"
msgstr "テキストオブジェクト (廃止済)"
#: pretix/static/pretixcontrol/js/ui/editor.js:901
#, fuzzy
#| msgid "Text object"
msgid "Text box"
msgstr "テキストオブジェクト"
msgstr "テキストボックス"
#: pretix/static/pretixcontrol/js/ui/editor.js:903
msgid "Barcode area"
@@ -770,13 +764,13 @@ msgstr "価格"
#, javascript-format
msgctxt "widget"
msgid "Original price: %s"
msgstr ""
msgstr "元の価格: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:21
#, javascript-format
msgctxt "widget"
msgid "New price: %s"
msgstr ""
msgstr "新しい価格: %s"
#: pretix/static/pretixpresale/js/widget/widget.js:22
msgctxt "widget"
@@ -829,7 +823,7 @@ msgstr "%(currency)s %(price)sから"
#, javascript-format
msgctxt "widget"
msgid "Image of %s"
msgstr ""
msgstr "%sのイメージ"
#: pretix/static/pretixpresale/js/widget/widget.js:32
msgctxt "widget"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -82,17 +82,17 @@
{% endif %}
{% if event_logo and event_logo_image_large %}
<a href="{% eventurl event "presale:event.index" cart_namespace=cart_namespace|default_if_none:"" %}"
aria-label="{% trans 'Homepage' %}" title="{% trans 'Homepage' %}">
title="{% trans 'Homepage' %}">
<img src="{{ event_logo|thumb:'1170x5000' }}" alt="{{ event.name }}" class="event-logo" />
</a>
{% elif event_logo %}
<a href="{% eventurl event "presale:event.index" cart_namespace=cart_namespace|default_if_none:"" %}"
aria-label="{% trans 'Homepage' %}" title="{% trans 'Homepage' %}">
title="{% trans 'Homepage' %}">
<img src="{{ event_logo|thumb:'5000x120' }}" alt="{{ event.name }}" class="event-logo" />
</a>
{% else %}
<h1>
<a href="{% eventurl event "presale:event.index" cart_namespace=cart_namespace|default_if_none:"" %}" aria-label="{% trans 'Homepage' %}">{{ event.name }}</a>
<a href="{% eventurl event "presale:event.index" cart_namespace=cart_namespace|default_if_none:"" %}">{{ event.name }}</a>
{% if request.event.settings.show_dates_on_frontpage and not event.has_subevents %}
<small>{{ event.get_date_range_display_as_html }}</small>
{% endif %}
@@ -5,6 +5,10 @@
<div class="col-md-2 col-sm-3 col-xs-6 availability-box unavailable">
<p><small><a href="#voucher">{% trans "Enter a voucher code below to buy this product." %}</a></small></p>
</div>
{% elif item.current_unavailability_reason == 'hidden_if_item_available' %}
<div class="col-md-2 col-sm-3 col-xs-6 availability-box unavailable">
<p><small>{% trans "Not available yet." %}</small></p>
</div>
{% elif item.current_unavailability_reason == 'available_from' or var.current_unavailability_reason == 'available_from' %}
<div class="col-md-2 col-sm-3 col-xs-6 availability-box unavailable">
<p><small>{% trans "Not available yet." %}</small></p>
@@ -268,8 +268,14 @@
{% if line.discount and line.line_price_gross != line.price %}
<span class="text-success discounted" data-toggle="tooltip" title="{% trans "The price of this product was reduced because of an automatic discount." %}">
<br>
<span class="fa fa-percent fa-fw" aria-hidden="true"></span>
{% trans "Discounted" %}
<span class="fa fa-star fa-fw" aria-hidden="true"></span>
{% if line.price < line.line_price_gross %}
{% blocktranslate trimmed with percent=line.discount_percentage|floatformat:0 %}
{{ percent }} % Discount
{% endblocktranslate %}
{% else %}
{% trans "Discounted" %}
{% endif %}
</span>
{% endif %}
</div>
@@ -335,8 +341,14 @@
{% if line.discount and line.line_price_gross != line.price %}
<span class="text-success discounted" data-toggle="tooltip" title="{% trans "The price of this product was reduced because of an automatic discount." %}">
<br>
<span class="fa fa-percent fa-fw" aria-hidden="true"></span>
{% trans "Discounted" %}
<span class="fa fa-star fa-fw" aria-hidden="true"></span>
{% if line.price < line.line_price_gross %}
{% blocktranslate trimmed with percent=line.discount_percentage|floatformat:0 %}
{{ percent }} % Discount
{% endblocktranslate %}
{% else %}
{% trans "Discounted" %}
{% endif %}
</span>
{% endif %}
</div>
+4 -4
View File
@@ -70,7 +70,7 @@ from pretix.base.models import (
)
from pretix.base.models.event import Event, SubEvent
from pretix.base.models.items import (
ItemAddOn, ItemBundle, SubEventItem, SubEventItemVariation,
Item, ItemAddOn, ItemBundle, SubEventItem, SubEventItemVariation,
)
from pretix.base.services.placeholders import PlaceholderContext
from pretix.base.services.quotas import QuotaAvailability
@@ -302,14 +302,14 @@ def get_grouped_items(event, *, channel: SalesChannel, subevent=None, voucher=No
if item.hidden_if_item_available:
if item.hidden_if_item_available.has_variations:
dependency_available = any(
item._dependency_available = any(
var.check_quotas(subevent=subevent, _cache=quota_cache, include_bundled=True)[0] == Quota.AVAILABILITY_OK
for var in item.hidden_if_item_available.available_variations
)
else:
q = item.hidden_if_item_available.check_quotas(subevent=subevent, _cache=quota_cache, include_bundled=True)
dependency_available = q[0] == Quota.AVAILABILITY_OK
if dependency_available:
item._dependency_available = q[0] == Quota.AVAILABILITY_OK
if item._dependency_available and item.hidden_if_item_available_mode == Item.UNAVAIL_MODE_HIDDEN:
item._remove = True
continue
+10 -3
View File
@@ -34,10 +34,17 @@ $(function () {
}
for(var k in dependents) {
const options = data[k],
dependent = dependents[k],
visible = 'visible' in options ? options.visible : true,
required = 'required' in options && options.required && isRequired && visible;
dependent = dependents[k];
let visible = 'visible' in options ? options.visible : true;
if (dependent.is("[data-display-dependency]")) {
const dependency = $(dependent.attr("data-display-dependency"));
visible = visible && (
(dependency.attr("type") === 'checkbox' || dependency.attr("type") === 'radio') ? dependency.prop('checked') : !!dependency.val()
);
}
const required = 'required' in options && options.required && isRequired && visible;
dependent.closest(".form-group").toggle(visible).toggleClass('required', required);
dependent.prop("required", required);
}
@@ -38,6 +38,7 @@ var strings = {
'unavailable_available_from': django.pgettext('widget', 'Not yet available'),
'unavailable_available_until': django.pgettext('widget', 'Not available anymore'),
'unavailable_active': django.pgettext('widget', 'Currently not available'),
'unavailable_hidden_if_item_available': django.pgettext('widget', 'Not yet available'),
'order_min': django.pgettext('widget', 'minimum amount to order: %s'),
'exit': django.pgettext('widget', 'Close ticket shop'),
'loading_error': django.pgettext('widget', 'The ticket shop could not be loaded.'),
+1
View File
@@ -323,6 +323,7 @@ TEST_ITEM_RES = {
"max_per_order": None,
"hidden_if_available": None,
"hidden_if_item_available": None,
"hidden_if_item_available_mode": "hide",
"checkin_attention": False,
"checkin_text": None,
"has_variations": False,
+9 -2
View File
@@ -673,7 +673,12 @@ class ItemsTest(ItemFormTest):
with scopes_disabled():
q = Question.objects.create(event=self.event1, question="Size", type="N")
q.items.add(self.item2)
self.item2.sales_channels = ["web", "bar"]
self.item2.limit_sales_channels.set(self.orga1.sales_channels.filter(identifier__in=["web", "bar"]))
self.item2.all_sales_channels = False
self.item2.save()
self.var2.limit_sales_channels.set(self.orga1.sales_channels.filter(identifier__in=["web"]))
self.var2.all_sales_channels = False
self.var2.save()
prop = self.event1.item_meta_properties.create(name="Foo")
self.item2.meta_values.create(property=prop, value="Bar")
@@ -690,6 +695,7 @@ class ItemsTest(ItemFormTest):
with scopes_disabled():
i_old = Item.objects.get(name__icontains='Business')
i_new = Item.objects.get(name__icontains='Intermediate')
v2_new = i_new.variations.get(value__icontains='Gold')
assert i_new.category == i_old.category
assert i_new.description == i_old.description
assert i_new.active == i_old.active
@@ -698,7 +704,8 @@ 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 set(i_new.limit_sales_channels.all()) == set(i_old.limit_sales_channels.all())
assert set(i_new.limit_sales_channels.values_list("identifier", flat=True)) == {"web", "bar"}
assert set(v2_new.limit_sales_channels.values_list("identifier", flat=True)) == {"web"}
assert i_new.meta_data == i_old.meta_data == {"Foo": "Bar"}
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()])