From 3d31cdaed40f4ac9b0e8fbbd25b133686c8f4c5d Mon Sep 17 00:00:00 2001 From: Kara Engelhardt Date: Mon, 27 Jul 2026 12:05:35 +0200 Subject: [PATCH] Show correct number of currency placed in widget (Z#23241522) --- src/pretix/presale/views/widget.py | 1 + .../static/pretixpresale/js/widget/widget.js | 27 ++++++++++--------- .../static/pretixpresale/widget/src/api.ts | 1 + .../widget/src/components/Item.vue | 6 ++--- .../widget/src/components/PriceBox.vue | 10 +++---- .../pretixpresale/widget/src/sharedStore.ts | 3 +++ src/tests/presale/test_widget.py | 4 +++ 7 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/pretix/presale/views/widget.py b/src/pretix/presale/views/widget.py index a51af50a4f..e0a28311b5 100644 --- a/src/pretix/presale/views/widget.py +++ b/src/pretix/presale/views/widget.py @@ -795,6 +795,7 @@ class WidgetAPIProductList(EventListMixin, View): 'target_url': eventreverse_absolute(request.event, 'presale:event.index'), 'subevent': self.subevent.pk if self.subevent else None, 'currency': request.event.currency, + 'currency_places': settings.CURRENCY_PLACES.get(request.event.currency, 2), 'display_net_prices': request.event.settings.display_net_prices, 'use_native_spinners': request.event.settings.widget_use_native_spinners, 'show_variations_expanded': request.event.settings.show_variations_expanded, diff --git a/src/pretix/static/pretixpresale/js/widget/widget.js b/src/pretix/static/pretixpresale/js/widget/widget.js index 3529acdd8f..22c44c8edb 100644 --- a/src/pretix/static/pretixpresale/js/widget/widget.js +++ b/src/pretix/static/pretixpresale/js/widget/widget.js @@ -380,16 +380,16 @@ Vue.component('pricebox', { }, display_price: function () { if (this.$root.display_net_prices) { - return floatformat(parseFloat(this.price.net), 2); + return floatformat(this.price.net, this.$root.currency_places); } else { - return floatformat(parseFloat(this.price.gross), 2); + return floatformat(this.price.gross, this.$root.currency_places); } }, display_price_nonlocalized: function () { if (this.$root.display_net_prices) { - return parseFloat(this.price.net).toFixed(2); + return parseFloat(this.price.net).toFixed(this.$root.currency_places); } else { - return parseFloat(this.price.gross).toFixed(2); + return parseFloat(this.price.gross).toFixed(this.$root.currency_places); } }, suggested_price_nonlocalized: function () { @@ -398,9 +398,9 @@ Vue.component('pricebox', { price = this.price; } if (this.$root.display_net_prices) { - return parseFloat(price.net).toFixed(2); + return parseFloat(price.net).toFixed(this.$root.currency_places); } else { - return parseFloat(price.gross).toFixed(2); + return parseFloat(price.gross).toFixed(this.$root.currency_places); } }, original_price_aria_label: function () { @@ -410,7 +410,7 @@ Vue.component('pricebox', { return django.interpolate(strings.new_price, [this.stripHTML(this.priceline)]); }, original_line: function () { - return '' + this.$root.currency + " " + floatformat(parseFloat(this.original_price), 2); + return '' + this.$root.currency + " " + floatformat(this.original_price, this.$root.currency_places); }, priceline: function () { if (this.price.gross === "0.00") { @@ -645,19 +645,19 @@ Vue.component('item', { if (this.item.free_price) { return django.interpolate(strings.price_from, { 'currency': this.$root.currency, - 'price': floatformat(this.item.min_price, 2) + 'price': floatformat(this.item.min_price, this.$root.currency_places) }, true).replace(this.$root.currency, '' + this.$root.currency + ''); } else if (this.item.min_price !== this.item.max_price) { - return '' + this.$root.currency + " " - + floatformat(this.item.min_price, 2) + " – " - + floatformat(this.item.max_price, 2); + return '' + this.$root.currency + " " + + floatformat(this.item.min_price, this.$root.currency_places) + " – " + + floatformat(this.item.max_price, this.$root.currency_places); } else if (this.item.min_price === "0.00" && this.item.max_price === "0.00") { if (this.item.mandatory_priced_addons) { return "\xA0"; // nbsp, because an empty string would cause the HTML element to collapse } return strings.free; } else { - return '' + this.$root.currency + " " + floatformat(this.item.min_price, 2); + return '' + this.$root.currency + " " + floatformat(this.item.min_price, this.$root.currency_places); } }, variationsToggleLabel: function () { @@ -1949,6 +1949,7 @@ var shared_root_methods = { root.location = data.location; root.categories = data.items_by_category; root.currency = data.currency; + root.currency_places = data.currency_places; root.display_net_prices = data.display_net_prices; root.voucher_explanation_text = data.voucher_explanation_text; root.error = data.error; @@ -1983,6 +1984,7 @@ var shared_root_methods = { }, function (error) { root.categories = []; root.currency = ''; + root.currency_places = 2; if (error.status === 429) { root.error = strings['loading_error_429']; root.connection_error = true; @@ -2339,6 +2341,7 @@ var create_widget = function (element, html_id=null) { is_button: false, categories: null, currency: null, + currency_places: 2, name: null, date_range: null, location: null, diff --git a/src/pretix/static/pretixpresale/widget/src/api.ts b/src/pretix/static/pretixpresale/widget/src/api.ts index 23650186c9..cbe0a9e19a 100644 --- a/src/pretix/static/pretixpresale/widget/src/api.ts +++ b/src/pretix/static/pretixpresale/widget/src/api.ts @@ -22,6 +22,7 @@ export interface ProductListResponse { location?: string items_by_category?: Category[] currency?: string + currency_places?: number display_net_prices?: boolean voucher_explanation_text?: string error?: string diff --git a/src/pretix/static/pretixpresale/widget/src/components/Item.vue b/src/pretix/static/pretixpresale/widget/src/components/Item.vue index 260ee6987e..d2c115a576 100644 --- a/src/pretix/static/pretixpresale/widget/src/components/Item.vue +++ b/src/pretix/static/pretixpresale/widget/src/components/Item.vue @@ -72,7 +72,7 @@ const pricerange = computed(() => { STRINGS.price_from, { currency: store.currency, - price: floatformat(props.item.min_price || '0', 2), + price: floatformat(props.item.min_price || '0', store.currency_places), }, true ).replace( @@ -80,14 +80,14 @@ const pricerange = computed(() => { `${store.currency}` ) } else if (props.item.min_price !== props.item.max_price) { - return `${store.currency} ${floatformat(props.item.min_price || '0', 2)} – ${floatformat(props.item.max_price || '0', 2)}` + return `${store.currency} ${floatformat(props.item.min_price || '0', store.currency_places)} – ${floatformat(props.item.max_price || '0', store.currency_places)}` } else if (props.item.min_price === '0.00' && props.item.max_price === '0.00') { if (props.item.mandatory_priced_addons) { return '\xA0' // nbsp, because an empty string would cause the HTML element to collapse } return STRINGS.free } else { - return `${store.currency} ${floatformat(props.item.min_price || '0', 2)}` + return `${store.currency} ${floatformat(props.item.min_price || '0', store.currency_places)}` } }) diff --git a/src/pretix/static/pretixpresale/widget/src/components/PriceBox.vue b/src/pretix/static/pretixpresale/widget/src/components/PriceBox.vue index 3ce01162cb..858c5c9910 100644 --- a/src/pretix/static/pretixpresale/widget/src/components/PriceBox.vue +++ b/src/pretix/static/pretixpresale/widget/src/components/PriceBox.vue @@ -25,9 +25,9 @@ const ariaLabelledby = computed(() => `${store.htmlId}-item-label-${props.itemId const displayPrice = computed(() => { if (store.displayNetPrices) { - return floatformat(parseFloat(props.price.net), 2) + return floatformat(props.price.net, store.currency_places) } - return floatformat(parseFloat(props.price.gross), 2) + return floatformat(props.price.gross, store.currency_places) }) const displayPriceNonlocalized = computed(() => { @@ -40,15 +40,15 @@ const displayPriceNonlocalized = computed(() => { const suggestedPriceNonlocalized = computed(() => { const price = props.suggestedPrice ?? props.price if (store.displayNetPrices) { - return parseFloat(price.net).toFixed(2) + return parseFloat(price.net).toFixed(store.currency_places) } - return parseFloat(price.gross).toFixed(2) + return parseFloat(price.gross).toFixed(store.currency_places) }) // TODO BAD const originalLine = computed(() => { if (!props.originalPrice) return '' - return `${store.currency} ${floatformat(parseFloat(props.originalPrice), 2)}` + return `${store.currency} ${floatformat(props.originalPrice, store.currency_places)}` }) // TODO BAD diff --git a/src/pretix/static/pretixpresale/widget/src/sharedStore.ts b/src/pretix/static/pretixpresale/widget/src/sharedStore.ts index f43398316b..00d36c02f7 100644 --- a/src/pretix/static/pretixpresale/widget/src/sharedStore.ts +++ b/src/pretix/static/pretixpresale/widget/src/sharedStore.ts @@ -71,6 +71,7 @@ export function createWidgetStore (config: { frontpageText: null as string | null, categories: [] as Category[], currency: '', + currency_places: 2, displayNetPrices: false, voucherExplanationText: null as string | null, displayAddToCart: false, @@ -299,6 +300,7 @@ export function createWidgetStore (config: { this.location = data.location ?? null this.categories = data.items_by_category ?? [] this.currency = data.currency ?? '' + this.currency_places = data.currency_places ?? 2 this.displayNetPrices = data.display_net_prices ?? false this.voucherExplanationText = data.voucher_explanation_text ?? null this.error = data.error ?? null @@ -338,6 +340,7 @@ export function createWidgetStore (config: { } catch (e) { this.categories = [] this.currency = '' + this.currency_places = 2 if (e instanceof ApiError && e.status === 429) { this.error = STRINGS.loading_error_429 } else { diff --git a/src/tests/presale/test_widget.py b/src/tests/presale/test_widget.py index 10795cb154..0738326d7f 100644 --- a/src/tests/presale/test_widget.py +++ b/src/tests/presale/test_widget.py @@ -173,6 +173,7 @@ class WidgetCartTest(CartTestMixin, TestCase): "frontpage_text": "", "location": "", "currency": "EUR", + "currency_places": 2, "show_variations_expanded": False, "display_net_prices": False, "use_native_spinners": False, @@ -379,6 +380,7 @@ class WidgetCartTest(CartTestMixin, TestCase): "frontpage_text": "", "location": "", "currency": "EUR", + "currency_places": 2, "show_variations_expanded": False, "display_net_prices": False, "use_native_spinners": False, @@ -439,6 +441,7 @@ class WidgetCartTest(CartTestMixin, TestCase): "frontpage_text": "", "location": "", "currency": "EUR", + "currency_places": 2, "show_variations_expanded": False, "display_net_prices": False, "use_native_spinners": False, @@ -524,6 +527,7 @@ class WidgetCartTest(CartTestMixin, TestCase): "frontpage_text": "", "location": "", "currency": "EUR", + "currency_places": 2, 'poweredby': 'ticketing powered by pretix', "show_variations_expanded": False, "display_net_prices": False,