Free price: Allow to suggest a different price than the minimum (#3666)

* Free price: Allow to suggest a different price than the minimum

* Full implementation

* Widget tests

* Add min values to titles
This commit is contained in:
Raphael Michel
2023-10-27 13:36:01 +02:00
committed by GitHub
parent b32249d48b
commit 000c64755d
18 changed files with 205 additions and 23 deletions
+18 -2
View File
@@ -18,6 +18,8 @@ default_price money (string) The price set d
price money (string) The price used for this variation. This is either the
same as ``default_price`` if that value is set or equal
to the item's ``default_price`` (read-only).
free_price_suggestion money (string) A suggested price, used as a default value if
``Item.free_price`` is set (or ``null``).
original_price money (string) An original price, shown for comparison, not used
for price calculations (or ``null``).
active boolean If ``false``, this variation will not be sold or shown.
@@ -53,6 +55,10 @@ meta_data object Values set for
The ``meta_data`` and ``checkin_attention`` attributes have been added.
.. versionchanged:: 2023.9
The ``free_price_suggestion`` attribute has been added.
Endpoints
---------
@@ -103,6 +109,7 @@ Endpoints
"default_price": "223.00",
"price": 223.0,
"original_price": null,
"free_price_suggestion": null,
"meta_data": {}
},
{
@@ -116,10 +123,16 @@ Endpoints
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
"sales_channels": ["web"],
"available_from": null,
"available_until": null,
"hide_without_voucher": false,
"description": {},
"position": 1,
"default_price": null,
"price": 15.0,
"default_price": "223.00",
"price": 223.0,
"original_price": null,
"free_price_suggestion": null,
"meta_data": {}
}
]
@@ -163,6 +176,7 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -231,6 +245,7 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -291,6 +306,7 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": false,
"checkin_attention": false,
"require_approval": false,
+23
View File
@@ -29,6 +29,8 @@ free_price boolean If ``true``,
they buy the product (however, the price can't be set
lower than the price defined by ``default_price`` or
otherwise).
free_price_suggestion money (string) A suggested price, used as a default value if
``free_price`` is set (or ``null``).
tax_rate decimal (string) The VAT rate to be applied for this item (read-only,
set through ``tax_rule``).
tax_rule integer The internal ID of the applied tax rule (or ``null``).
@@ -123,6 +125,8 @@ variations list of objects A list with o
├ price money (string) The price used for this variation. This is either the
same as ``default_price`` if that value is set or equal
to the item's ``default_price``.
├ free_price_suggestion money (string) A suggested price, used as a default value if
``free_price`` is set (or ``null``).
├ original_price money (string) An original price, shown for comparison, not used
for price calculations (or ``null``).
├ active boolean If ``false``, this variation will not be sold or shown.
@@ -196,6 +200,10 @@ meta_data object Values set fo
The ``media_policy`` and ``media_type`` attributes have been added.
.. versionchanged:: 2023.9
The ``free_price_suggestion`` and ``variations[x].free_price_suggestion`` attributes have been added.
Notes
-----
@@ -246,6 +254,7 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
@@ -291,6 +300,7 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -309,6 +319,7 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -377,6 +388,7 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
@@ -422,6 +434,7 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -440,6 +453,7 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -489,6 +503,7 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
@@ -533,6 +548,7 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -551,6 +567,7 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -588,6 +605,7 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
@@ -633,6 +651,7 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -651,6 +670,7 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -719,6 +739,7 @@ Endpoints
"active": true,
"description": null,
"free_price": false,
"free_price_suggestion": null,
"tax_rate": "0.00",
"tax_rule": 1,
"admission": false,
@@ -764,6 +785,7 @@ Endpoints
"default_price": "10.00",
"price": "10.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
@@ -782,6 +804,7 @@ Endpoints
"default_price": null,
"price": "23.00",
"original_price": null,
"free_price_suggestion": null,
"active": true,
"checkin_attention": false,
"require_approval": false,
+4 -4
View File
@@ -59,7 +59,7 @@ class InlineItemVariationSerializer(I18nAwareModelSerializer):
class Meta:
model = ItemVariation
fields = ('id', 'value', 'active', 'description',
'position', 'default_price', 'price', 'original_price', 'require_approval',
'position', 'default_price', 'price', 'original_price', 'free_price_suggestion', 'require_approval',
'require_membership', 'require_membership_types', 'require_membership_hidden',
'checkin_attention', 'available_from', 'available_until',
'sales_channels', 'hide_without_voucher', 'meta_data')
@@ -83,7 +83,7 @@ class ItemVariationSerializer(I18nAwareModelSerializer):
class Meta:
model = ItemVariation
fields = ('id', 'value', 'active', 'description',
'position', 'default_price', 'price', 'original_price', 'require_approval',
'position', 'default_price', 'price', 'original_price', 'free_price_suggestion', 'require_approval',
'require_membership', 'require_membership_types', 'require_membership_hidden',
'checkin_attention', 'available_from', 'available_until',
'sales_channels', 'hide_without_voucher', 'meta_data')
@@ -234,8 +234,8 @@ class ItemSerializer(I18nAwareModelSerializer):
class Meta:
model = Item
fields = ('id', 'category', 'name', 'internal_name', 'active', 'sales_channels', 'description',
'default_price', 'free_price', 'tax_rate', 'tax_rule', 'admission', 'personalized',
'position', 'picture', 'available_from', 'available_until',
'default_price', 'free_price', 'free_price_suggestion', 'tax_rate', 'tax_rule', 'admission',
'personalized', 'position', 'picture', 'available_from', 'available_until',
'require_voucher', 'hide_without_voucher', 'allow_cancel', 'require_bundling',
'min_per_order', 'max_per_order', 'checkin_attention', 'has_variations', 'variations',
'addons', 'bundles', 'original_price', 'require_approval', 'generate_tickets',
@@ -0,0 +1,22 @@
# Generated by Django 4.2.4 on 2023-10-25 12:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("pretixbase", "0247_checkinlist"),
]
operations = [
migrations.AddField(
model_name="item",
name="free_price_suggestion",
field=models.DecimalField(decimal_places=2, max_digits=13, null=True),
),
migrations.AddField(
model_name="itemvariation",
name="free_price_suggestion",
field=models.DecimalField(decimal_places=2, max_digits=13, null=True),
),
]
+12
View File
@@ -431,6 +431,12 @@ class Item(LoggedModel):
"additional donations for your event. This is currently not supported for products that are "
"bought as an add-on to other products.")
)
free_price_suggestion = models.DecimalField(
verbose_name=_("Suggested price"),
help_text=_("This price will be used as the default value of the input field. The user can choose a lower "
"value, but not lower than the price this product would have without the free price option."),
max_digits=13, decimal_places=2, null=True, blank=True,
)
tax_rule = models.ForeignKey(
'TaxRule',
verbose_name=_('Sales tax'),
@@ -1021,6 +1027,12 @@ class ItemVariation(models.Model):
help_text=_('If set, this will be displayed next to the current price to show that the current price is a '
'discounted one. This is just a cosmetic setting and will not actually impact pricing.')
)
free_price_suggestion = models.DecimalField(
verbose_name=_("Suggested price"),
help_text=_("This price will be used as the default value of the input field. The user can choose a lower "
"value, but not lower than the price this product would have without the free price option."),
max_digits=13, decimal_places=2, null=True, blank=True,
)
require_approval = models.BooleanField(
verbose_name=_('Require approval'),
default=False,
+6
View File
@@ -577,6 +577,8 @@ class ItemUpdateForm(I18nModelForm):
)
self.fields['category'].widget.choices = self.fields['category'].choices
self.fields['free_price_suggestion'].widget.attrs['data-display-dependency'] = '#id_free_price'
qs = self.event.organizer.membership_types.all()
if qs:
self.fields['require_membership_types'].queryset = qs
@@ -664,6 +666,7 @@ class ItemUpdateForm(I18nModelForm):
'picture',
'default_price',
'free_price',
'free_price_suggestion',
'tax_rule',
'available_from',
'available_until',
@@ -797,6 +800,8 @@ class ItemVariationForm(I18nModelForm):
del self.fields['require_membership']
del self.fields['require_membership_types']
self.fields['free_price_suggestion'].widget.attrs['data-display-dependency'] = '#id_free_price'
self.meta_fields = []
meta_defaults = {}
if self.instance.pk:
@@ -829,6 +834,7 @@ class ItemVariationForm(I18nModelForm):
'value',
'active',
'default_price',
'free_price_suggestion',
'original_price',
'description',
'require_approval',
@@ -72,6 +72,7 @@
{% bootstrap_field form.active layout="control" %}
{% bootstrap_field form.value layout="control" %}
{% bootstrap_field form.default_price addon_after=request.event.currency layout="control" %}
{% bootstrap_field form.free_price_suggestion addon_after=request.event.currency layout="control" %}
{% bootstrap_field form.original_price addon_after=request.event.currency layout="control" %}
{% bootstrap_field form.description layout="control" %}
{% if form.meta_fields %}
@@ -170,6 +171,7 @@
{% bootstrap_field formset.empty_form.active layout="control" %}
{% bootstrap_field formset.empty_form.value layout="control" %}
{% bootstrap_field formset.empty_form.default_price addon_after=request.event.currency layout="control" %}
{% bootstrap_field formset.empty_form.free_price_suggestion addon_after=request.event.currency layout="control" %}
{% bootstrap_field formset.empty_form.original_price addon_after=request.event.currency layout="control" %}
{% bootstrap_field formset.empty_form.description layout="control" %}
{% if formset.empty_form.meta_fields %}
@@ -147,6 +147,7 @@
{% bootstrap_field form.default_price addon_after=request.event.currency layout="control" %}
{% bootstrap_field form.tax_rule layout="control" %}
{% bootstrap_field form.free_price layout="control" %}
{% bootstrap_field form.free_price_suggestion addon_after=request.event.currency layout="control" %}
{% bootstrap_field form.original_price addon_after=request.event.currency layout="control" %}
</fieldset>
<fieldset>
+2 -2
View File
@@ -570,7 +570,7 @@ class AddOnsStep(CartMixin, AsyncAction, TemplateFlowStep):
rate=a.tax_rate,
)
else:
v.initial_price = v.display_price
v.initial_price = v.suggested_price
i.expand = any(v.initial for v in i.available_variations)
else:
i.initial = len(current_addon_products[i.pk, None])
@@ -584,7 +584,7 @@ class AddOnsStep(CartMixin, AsyncAction, TemplateFlowStep):
rate=a.tax_rate,
)
else:
i.initial_price = i.display_price
i.initial_price = i.suggested_price
if items:
formsetentry['categories'].append({
@@ -139,7 +139,15 @@
placeholder="0"
min="{% if event.settings.display_net_prices %}{{ var.display_price.net|money_numberfield:event.currency }}{% else %}{{ var.display_price.gross|money_numberfield:event.currency }}{% endif %}"
name="cp_{{ form.pos.pk }}_variation_{{ item.id }}_{{ var.id }}_price"
title="{% blocktrans trimmed with item=var.value %}Modify price for {{ item }}{% endblocktrans %}"
{% if var.initial_price.gross != var.display_price.gross %}
{% if event.settings.display_net_prices %}
title="{% blocktrans trimmed with item=var.value price=var.display_price.net|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% else %}
title="{% blocktrans trimmed with item=var.value price=var.display_price.gross|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% endif %}
{% else %}
title="{% blocktrans trimmed with item=var.value %}Modify price for {{ item }}{% endblocktrans %}"
{% endif %}
step="any"
value="{% if event.settings.display_net_prices %}{{ var.initial_price.net|money_numberfield:event.currency }}{% else %}{{ var.initial_price.gross|money_numberfield:event.currency }}{% endif %}"
>
@@ -268,7 +276,15 @@
id="price-item-{{ form.pos.pk }}-{{ item.pk }}"
min="{% if event.settings.display_net_prices %}{{ item.display_price.net|money_numberfield:event.currency }}{% else %}{{ item.display_price.gross|money_numberfield:event.currency }}{% endif %}"
name="cp_{{ form.pos.pk }}_item_{{ item.id }}_price"
title="{% blocktrans trimmed with item=item.name %}Modify price for {{ item }}{% endblocktrans %}"
{% if item.initial_price.gross != item.display_price.gross %}
{% if event.settings.display_net_prices %}
title="{% blocktrans trimmed with item=item.name price=item.display_price.net|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% else %}
title="{% blocktrans trimmed with item=item.name price=item.display_price.gross|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% endif %}
{% else %}
title="{% blocktrans trimmed with item=item.name %}Modify price for {{ item }}{% endblocktrans %}"
{% endif %}
value="{% if event.settings.display_net_prices %}{{ item.initial_price.net|money_numberfield:event.currency }}{% else %}{{ item.initial_price.gross|money_numberfield:event.currency }}{% endif %}"
step="any">
</div>
@@ -138,9 +138,17 @@
placeholder="0"
min="{% if event.settings.display_net_prices %}{{ var.display_price.net|money_numberfield:event.currency }}{% else %}{{ var.display_price.gross|money_numberfield:event.currency }}{% endif %}"
name="price_{{ item.id }}_{{ var.id }}"
title="{% blocktrans trimmed with item=var.value %}Modify price for {{ item }}{% endblocktrans %}"
{% if var.suggested_price.gross != var.display_price.gross %}
{% if event.settings.display_net_prices %}
title="{% blocktrans trimmed with item=var.value price=var.display_price.net|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% else %}
title="{% blocktrans trimmed with item=var.value price=var.display_price.gross|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% endif %}
{% else %}
title="{% blocktrans trimmed with item=var.value %}Modify price for {{ item }}{% endblocktrans %}"
{% endif %}
step="any"
value="{% if event.settings.display_net_prices %}{{ var.display_price.net|money_numberfield:event.currency }}{% else %}{{ var.display_price.gross|money_numberfield:event.currency }}{% endif %}"
value="{% if event.settings.display_net_prices %}{{ var.suggested_price.net|money_numberfield:event.currency }}{% else %}{{ var.suggested_price.gross|money_numberfield:event.currency }}{% endif %}"
>
</div>
<p>
@@ -284,8 +292,16 @@
{% if not ev.presale_is_running %}disabled{% endif %}
min="{% if event.settings.display_net_prices %}{{ item.display_price.net|money_numberfield:event.currency }}{% else %}{{ item.display_price.gross|money_numberfield:event.currency }}{% endif %}"
name="price_{{ item.id }}"
title="{% blocktrans trimmed with item=item.name %}Modify price for {{ item }}{% endblocktrans %}"
value="{% if event.settings.display_net_prices %}{{ item.display_price.net|money_numberfield:event.currency }}{% else %}{{ item.display_price.gross|money_numberfield:event.currency }}{% endif %}"
{% if item.suggested_price.gross != item.display_price.gross %}
{% if event.settings.display_net_prices %}
title="{% blocktrans trimmed with item=item.name price=item.display_price.net|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% else %}
title="{% blocktrans trimmed with item=item.name price=item.display_price.gross|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% endif %}
{% else %}
title="{% blocktrans trimmed with item=item.name %}Modify price for {{ item }}{% endblocktrans %}"
{% endif %}
value="{% if event.settings.display_net_prices %}{{ item.suggested_price.net|money_numberfield:event.currency }}{% else %}{{ item.suggested_price.gross|money_numberfield:event.currency }}{% endif %}"
step="any">
</div>
<p>
@@ -166,8 +166,16 @@
placeholder="0"
min="{% if event.settings.display_net_prices %}{{ var.display_price.net|stringformat:"0.2f" }}{% else %}{{ var.display_price.gross|stringformat:"0.2f" }}{% endif %}"
name="price_{{ item.id }}_{{ var.id }}"
title="{% blocktrans trimmed with item=var.value %}Modify price for {{ item }}{% endblocktrans %}"
value="{% if event.settings.display_net_prices %}{{var.display_price.net|stringformat:"0.2f" }}{% else %}{{ var.display_price.gross|stringformat:"0.2f" }}{% endif %}"
{% if var.suggested_price.gross != var.display_price.gross %}
{% if event.settings.display_net_prices %}
title="{% blocktrans trimmed with item=var.value price=var.display_price.net|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% else %}
title="{% blocktrans trimmed with item=var.value price=var.display_price.gross|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% endif %}
{% else %}
title="{% blocktrans trimmed with item=var.value %}Modify price for {{ item }}{% endblocktrans %}"
{% endif %}
value="{% if event.settings.display_net_prices %}{{var.suggested_price.net|stringformat:"0.2f" }}{% else %}{{ var.suggested_price.gross|stringformat:"0.2f" }}{% endif %}"
step="any">
</div>
<p>
@@ -309,8 +317,16 @@
<input type="number" class="form-control input-item-price" placeholder="0"
min="{% if event.settings.display_net_prices %}{{ item.display_price.net|stringformat:"0.2f" }}{% else %}{{ item.display_price.gross|stringformat:"0.2f" }}{% endif %}"
name="price_{{ item.id }}"
title="{% blocktrans trimmed with item=item.name %}Modify price for {{ item }}{% endblocktrans %}"
value="{% if event.settings.display_net_prices %}{{ item.display_price.net|stringformat:"0.2f" }}{% else %}{{ item.display_price.gross|stringformat:"0.2f" }}{% endif %}"
{% if item.suggested_price.gross != item.display_price.gross %}
{% if event.settings.display_net_prices %}
title="{% blocktrans trimmed with item=item.name price=item.display_price.net|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% else %}
title="{% blocktrans trimmed with item=item.name price=item.display_price.gross|money:event.currency %}Modify price for {{ item }}, at least {{ price }}{% endblocktrans %}"
{% endif %}
{% else %}
title="{% blocktrans trimmed with item=item.name %}Modify price for {{ item }}{% endblocktrans %}"
{% endif %}
value="{% if event.settings.display_net_prices %}{{ item.suggested_price.net|stringformat:"0.2f" }}{% else %}{{ item.suggested_price.gross|stringformat:"0.2f" }}{% endif %}"
step="any">
</div>
<p>
+13
View File
@@ -300,6 +300,10 @@ def get_grouped_items(event, subevent=None, voucher=None, channel='web', require
price = original_price
item.display_price = item.tax(price, currency=event.currency, include_bundled=True)
if item.free_price and item.free_price_suggestion is not None:
item.suggested_price = item.tax(max(price, item.free_price_suggestion), currency=event.currency, include_bundled=True)
else:
item.suggested_price = item.display_price
if price != original_price:
item.original_price = item.tax(original_price, currency=event.currency, include_bundled=True)
@@ -346,6 +350,15 @@ def get_grouped_items(event, subevent=None, voucher=None, channel='web', require
var.display_price = var.tax(price, currency=event.currency, include_bundled=True)
if item.free_price and var.free_price_suggestion is not None:
var.suggested_price = item.tax(max(price, var.free_price_suggestion), currency=event.currency,
include_bundled=True)
elif item.free_price and item.free_price_suggestion is not None:
var.suggested_price = item.tax(max(price, item.free_price_suggestion), currency=event.currency,
include_bundled=True)
else:
var.suggested_price = var.display_price
if price != original_price:
var.original_price = var.tax(original_price, currency=event.currency, include_bundled=True)
else:
+2 -2
View File
@@ -1355,7 +1355,7 @@ class OrderChangeMixin:
rate=a.tax_rate,
)
else:
v.initial_price = v.display_price
v.initial_price = v.suggested_price
i.expand = any(v.initial for v in i.available_variations)
else:
i.initial = len(current_addon_products[i.pk, None])
@@ -1369,7 +1369,7 @@ class OrderChangeMixin:
rate=a.tax_rate,
)
else:
i.initial_price = i.display_price
i.initial_price = i.suggested_price
if items:
p.addon_form['categories'].append({
+2
View File
@@ -274,6 +274,7 @@ class WidgetAPIProductList(EventListMixin, View):
'order_min': item.min_per_order,
'order_max': item.order_max if not item.has_variations else None,
'price': price_dict(item, item.display_price) if not item.has_variations else None,
'suggested_price': price_dict(item, item.suggested_price) if not item.has_variations else None,
'min_price': item.min_price if item.has_variations else None,
'max_price': item.max_price if item.has_variations else None,
'allow_waitinglist': item.allow_waitinglist,
@@ -296,6 +297,7 @@ class WidgetAPIProductList(EventListMixin, View):
'order_max': var.order_max,
'description': str(rich_text(var.description, safelinks=False)) if var.description else None,
'price': price_dict(item, var.display_price),
'suggested_price': price_dict(item, var.suggested_price),
'original_price': (
(
var.original_price.net
@@ -336,7 +336,7 @@ Vue.component('pricebox', {
+ '<div v-if="free_price">'
+ '{{ $root.currency }} '
+ '<input type="number" class="pretix-widget-pricebox-price-input" placeholder="0" '
+ ' :min="display_price_nonlocalized" :value="display_price_nonlocalized" :name="field_name"'
+ ' :min="display_price_nonlocalized" :value="suggested_price_nonlocalized" :name="field_name"'
+ ' step="any" aria-label="'+strings.price+'">'
+ '</div>'
+ '<small class="pretix-widget-pricebox-tax" v-if="price.rate != \'0.00\' && price.gross != \'0.00\'">'
@@ -347,6 +347,7 @@ Vue.component('pricebox', {
price: Object,
free_price: Boolean,
field_name: String,
suggested_price: Object,
original_price: String,
mandatory_priced_addons: Boolean,
},
@@ -365,6 +366,17 @@ Vue.component('pricebox', {
return parseFloat(this.price.gross).toFixed(2);
}
},
suggested_price_nonlocalized: function () {
var price = this.suggested_price;
if (price === null) {
price = this.price;
}
if (this.$root.display_net_prices) {
return parseFloat(price.net).toFixed(2);
} else {
return parseFloat(price.gross).toFixed(2);
}
},
original_line: function () {
return this.$root.currency + " " + floatformat(parseFloat(this.original_price), 2);
},
@@ -420,7 +432,7 @@ Vue.component('variation', {
// Price
+ '<div class="pretix-widget-item-price-col">'
+ '<pricebox :price="variation.price" :free_price="item.free_price" :original_price="orig_price" '
+ ' :mandatory_priced_addons="item.mandatory_priced_addons"'
+ ' :mandatory_priced_addons="item.mandatory_priced_addons" :suggested_price="variation.suggested_price"'
+ ' :field_name="\'price_\' + item.id + \'_\' + variation.id" v-if="$root.showPrices">'
+ '</pricebox>'
+ '<span v-if="!$root.showPrices">&nbsp;</span>'
@@ -478,7 +490,7 @@ Vue.component('item', {
// Price
+ '<div class="pretix-widget-item-price-col">'
+ '<pricebox :price="item.price" :free_price="item.free_price" v-if="!item.has_variations && $root.showPrices"'
+ ' :mandatory_priced_addons="item.mandatory_priced_addons"'
+ ' :mandatory_priced_addons="item.mandatory_priced_addons" :suggested_price="item.suggested_price"'
+ ' :field_name="\'price_\' + item.id" :original_price="item.original_price">'
+ '</pricebox>'
+ '<div class="pretix-widget-pricebox" v-if="item.has_variations && $root.showPrices">{{ pricerange }}</div>'
+4
View File
@@ -285,6 +285,7 @@ TEST_ITEM_RES = {
"bundles": [],
"show_quota_left": None,
"original_price": None,
"free_price_suggestion": None,
"meta_data": {
"day": "Tuesday"
},
@@ -384,6 +385,7 @@ def test_item_detail_variations(token_client, organizer, event, team, item):
"id": var.pk,
"value": {"en": "Children"},
"default_price": None,
"free_price_suggestion": None,
"price": "23.00",
"active": True,
"description": None,
@@ -1313,6 +1315,7 @@ TEST_VARIATIONS_RES = {
"available_until": None,
"hide_without_voucher": False,
"original_price": None,
"free_price_suggestion": None,
"meta_data": {}
}
@@ -1334,6 +1337,7 @@ TEST_VARIATIONS_UPDATE = {
"available_until": None,
"hide_without_voucher": False,
"original_price": None,
"free_price_suggestion": None,
"meta_data": {}
}
+21
View File
@@ -184,6 +184,7 @@ class WidgetCartTest(CartTestMixin, TestCase):
"order_min": None,
"max_price": None,
"price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00", "includes_mixed_tax_rate": False},
"picture": None,
"picture_fullsize": None,
"has_variations": 0,
@@ -204,6 +205,7 @@ class WidgetCartTest(CartTestMixin, TestCase):
"order_min": None,
"max_price": "14.00",
"price": None,
"suggested_price": None,
"picture": None,
"picture_fullsize": None,
"has_variations": 4,
@@ -219,6 +221,8 @@ class WidgetCartTest(CartTestMixin, TestCase):
'original_price': None,
"price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"description": None,
"avail": [100, None],
"order_max": 2
@@ -229,6 +233,8 @@ class WidgetCartTest(CartTestMixin, TestCase):
'original_price': None,
"price": {"gross": "12.00", "net": "10.08", "tax": "1.92", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "12.00", "net": "10.08", "tax": "1.92", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"description": None,
"avail": [100, None],
"order_max": 2
@@ -266,6 +272,8 @@ class WidgetCartTest(CartTestMixin, TestCase):
"max_price": None,
"price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00",
"includes_mixed_tax_rate": False},
"suggested_price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00",
"includes_mixed_tax_rate": False},
"picture": None,
"picture_fullsize": None,
"has_variations": 0,
@@ -312,6 +320,7 @@ class WidgetCartTest(CartTestMixin, TestCase):
"order_min": None,
"max_price": "14.00",
"price": None,
"suggested_price": None,
"picture": None,
"picture_fullsize": None,
"has_variations": 4,
@@ -327,6 +336,8 @@ class WidgetCartTest(CartTestMixin, TestCase):
'original_price': None,
"price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "14.00", "net": "11.76", "tax": "2.24", "name": "",
"rate": "19.00", "includes_mixed_tax_rate": False},
"description": None,
"avail": [100, None],
"order_max": 2
@@ -374,6 +385,7 @@ class WidgetCartTest(CartTestMixin, TestCase):
"order_min": None,
"max_price": None,
"price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00", "includes_mixed_tax_rate": False},
"suggested_price": {"gross": "23.00", "net": "19.33", "tax": "3.67", "name": "", "rate": "19.00", "includes_mixed_tax_rate": False},
"picture": None,
"picture_fullsize": None,
"has_variations": 0,
@@ -439,6 +451,7 @@ class WidgetCartTest(CartTestMixin, TestCase):
'order_min': None,
'order_max': None,
'price': None,
'suggested_price': None,
'min_price': '14.00',
'max_price': '14.00',
'free_price': False,
@@ -459,6 +472,14 @@ class WidgetCartTest(CartTestMixin, TestCase):
'name': '',
'includes_mixed_tax_rate': False
},
'suggested_price': {
'gross': '14.00',
'net': '11.76',
'tax': '2.24',
'rate': '19.00',
'name': '',
'includes_mixed_tax_rate': False
},
'avail': [100, None]
},
]