mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Introduce original price (#905)
* Introduce original price * Rebase and styling * Widget
This commit is contained in:
@@ -79,7 +79,7 @@ class ItemSerializer(I18nAwareModelSerializer):
|
||||
'position', 'picture', 'available_from', 'available_until',
|
||||
'require_voucher', 'hide_without_voucher', 'allow_cancel',
|
||||
'min_per_order', 'max_per_order', 'checkin_attention', 'has_variations',
|
||||
'variations', 'addons')
|
||||
'variations', 'addons', 'original_price')
|
||||
read_only_fields = ('has_variations', 'picture')
|
||||
|
||||
def get_serializer_context(self):
|
||||
|
||||
23
src/pretix/base/migrations/0092_auto_20180511_1224.py
Normal file
23
src/pretix/base/migrations/0092_auto_20180511_1224.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.11 on 2018-05-11 12:24
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('pretixbase', '0091_auto_20180513_1641'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='item',
|
||||
name='original_price',
|
||||
field=models.DecimalField(blank=True, decimal_places=2,
|
||||
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.',
|
||||
max_digits=7, null=True, verbose_name='Original price'),
|
||||
),
|
||||
]
|
||||
@@ -191,6 +191,8 @@ class Item(LoggedModel):
|
||||
:type min_per_order: int
|
||||
:param checkin_attention: Requires special attention at check-in
|
||||
:type checkin_attention: bool
|
||||
:param original_price: The item's "original" price. Will not be used for any calculations, will just be shown.
|
||||
:type original_price: decimal.Decimal
|
||||
"""
|
||||
|
||||
event = models.ForeignKey(
|
||||
@@ -311,8 +313,15 @@ class Item(LoggedModel):
|
||||
'attention. You can use this for example for student tickets to indicate to the person at '
|
||||
'check-in that the student ID card still needs to be checked.')
|
||||
)
|
||||
original_price = models.DecimalField(
|
||||
verbose_name=_('Original price'),
|
||||
blank=True, null=True,
|
||||
max_digits=7, decimal_places=2,
|
||||
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.')
|
||||
)
|
||||
# !!! Attention: If you add new fields here, also add them to the copying code in
|
||||
# pretix/control/views/item.py if applicable.
|
||||
# pretix/control/forms/item.py if applicable.
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Product")
|
||||
|
||||
@@ -226,6 +226,7 @@ class ItemCreateForm(I18nModelForm):
|
||||
self.instance.max_per_order = self.cleaned_data['copy_from'].max_per_order
|
||||
self.instance.checkin_attention = self.cleaned_data['copy_from'].checkin_attention
|
||||
self.instance.free_price = self.cleaned_data['copy_from'].free_price
|
||||
self.instance.original_price = self.cleaned_data['copy_from'].original_price
|
||||
|
||||
self.instance.position = (self.event.items.aggregate(p=Max('position'))['p'] or 0) + 1
|
||||
instance = super().save(*args, **kwargs)
|
||||
@@ -325,7 +326,8 @@ class ItemUpdateForm(I18nModelForm):
|
||||
'allow_cancel',
|
||||
'max_per_order',
|
||||
'min_per_order',
|
||||
'checkin_attention'
|
||||
'checkin_attention',
|
||||
'original_price'
|
||||
]
|
||||
field_classes = {
|
||||
'available_from': forms.SplitDateTimeField,
|
||||
|
||||
@@ -38,14 +38,13 @@
|
||||
<legend>{% trans "Check-in" %}</legend>
|
||||
{% bootstrap_field form.checkin_attention layout="control" %}
|
||||
</fieldset>
|
||||
{% if plugin_forms %}
|
||||
<fieldset>
|
||||
<legend>{% trans "Additional settings" %}</legend>
|
||||
{% for f in plugin_forms %}
|
||||
{% bootstrap_form f layout="control" %}
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<fieldset>
|
||||
<legend>{% trans "Additional settings" %}</legend>
|
||||
{% bootstrap_field form.original_price addon_after=request.event.currency layout="control" %}
|
||||
{% for f in plugin_forms %}
|
||||
{% bootstrap_form f layout="control" %}
|
||||
{% endfor %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="col-xs-12 col-lg-2">
|
||||
<div class="panel panel-default">
|
||||
|
||||
@@ -288,6 +288,10 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-2 col-xs-6 price">
|
||||
{% if item.original_price %}
|
||||
<del>{{ item.original_price|money:event.currency }}</del>
|
||||
<ins>
|
||||
{% endif %}
|
||||
{% if item.free_price %}
|
||||
<div class="input-group input-group-price">
|
||||
<span class="input-group-addon">{{ event.currency }}</span>
|
||||
@@ -307,6 +311,9 @@
|
||||
{% else %}
|
||||
{{ var.display_price.gross|money:event.currency }}
|
||||
{% endif %}
|
||||
{% if item.original_price %}
|
||||
</ins>
|
||||
{% endif %}
|
||||
{% if var.display_price.rate and var.display_price.gross and event.settings.display_net_prices %}
|
||||
<small>{% blocktrans trimmed with rate=var.display_price.rate name=var.display_price.name %}
|
||||
<strong>plus</strong> {{ rate }}% {{ name }}
|
||||
@@ -383,6 +390,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2 col-xs-6 price">
|
||||
{% if item.original_price %}
|
||||
<del>{{ item.original_price|money:event.currency }}</del>
|
||||
<ins>
|
||||
{% endif %}
|
||||
{% if item.free_price %}
|
||||
<div class="input-group input-group-price">
|
||||
<span class="input-group-addon">{{ event.currency }}</span>
|
||||
@@ -400,6 +411,9 @@
|
||||
{% else %}
|
||||
{{ item.display_price.gross|money:event.currency }}
|
||||
{% endif %}
|
||||
{% if item.original_price %}
|
||||
</ins>
|
||||
{% endif %}
|
||||
{% if item.display_price.rate and item.display_price.gross and event.settings.display_net_prices %}
|
||||
<small>{% blocktrans trimmed with rate=item.display_price.rate name=item.display_price.name %}
|
||||
<strong>plus</strong> {{ rate }}% {{ name }}
|
||||
|
||||
@@ -177,6 +177,7 @@ class WidgetAPIProductList(View):
|
||||
item.cached_availability[0],
|
||||
item.cached_availability[1] if self.request.event.settings.show_quota_left else None
|
||||
] if not item.has_variations else None,
|
||||
'original_price': item.original_price,
|
||||
'variations': [
|
||||
{
|
||||
'id': var.id,
|
||||
|
||||
@@ -185,7 +185,10 @@ Vue.component('availbox', {
|
||||
});
|
||||
Vue.component('pricebox', {
|
||||
template: ('<div class="pretix-widget-pricebox">'
|
||||
+ '<span v-if="!free_price">{{ priceline }}</span>'
|
||||
+ '<span v-if="!free_price && !original_price">{{ priceline }}</span>'
|
||||
+ '<span v-if="!free_price && original_price">'
|
||||
+ '<del class="pretix-widget-pricebox-original-price">{{ original_line }}</del> '
|
||||
+ '<ins class="pretix-widget-pricebox-new-price">{{ priceline }}</ins></span>'
|
||||
+ '<div v-if="free_price">'
|
||||
+ '{{ $root.currency }} '
|
||||
+ '<input type="number" class="pretix-widget-pricebox-price-input" placeholder="0" '
|
||||
@@ -199,7 +202,8 @@ Vue.component('pricebox', {
|
||||
props: {
|
||||
price: Object,
|
||||
free_price: Boolean,
|
||||
field_name: String
|
||||
field_name: String,
|
||||
original_price: String
|
||||
},
|
||||
computed: {
|
||||
display_price: function () {
|
||||
@@ -209,6 +213,9 @@ Vue.component('pricebox', {
|
||||
return roundTo(parseFloat(this.price.gross), 2).toFixed(2);
|
||||
}
|
||||
},
|
||||
original_line: function () {
|
||||
return this.$root.currency + " " + roundTo(parseFloat(this.original_price), 2).toFixed(2);
|
||||
},
|
||||
priceline: function () {
|
||||
if (this.price.gross === "0.00") {
|
||||
return strings.free;
|
||||
@@ -247,7 +254,7 @@ Vue.component('variation', {
|
||||
+ '</div>'
|
||||
|
||||
+ '<div class="pretix-widget-item-price-col">'
|
||||
+ '<pricebox :price="variation.price" :free_price="item.free_price"'
|
||||
+ '<pricebox :price="variation.price" :free_price="item.free_price" :original_price="item.original_price"'
|
||||
+ ' :field_name="\'price_\' + item.id + \'_\' + variation.id">'
|
||||
+ '</pricebox>'
|
||||
+ '</div>'
|
||||
@@ -293,7 +300,7 @@ Vue.component('item', {
|
||||
|
||||
+ '<div class="pretix-widget-item-price-col">'
|
||||
+ '<pricebox :price="item.price" :free_price="item.free_price" v-if="!item.has_variations"'
|
||||
+ ' :field_name="\'price_\' + item.id">'
|
||||
+ ' :field_name="\'price_\' + item.id" :original_price="item.original_price">'
|
||||
+ '</pricebox>'
|
||||
+ '<div class="pretix-widget-pricebox" v-if="item.has_variations">{{ pricerange }}</div>'
|
||||
+ '</div>'
|
||||
|
||||
@@ -64,6 +64,15 @@
|
||||
margin: 0;
|
||||
line-height: inherit;
|
||||
}
|
||||
.price del {
|
||||
color: $text-muted;
|
||||
}
|
||||
.price ins {
|
||||
color: $brand-success;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.radio .variation-description {
|
||||
|
||||
@@ -200,6 +200,16 @@
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
del.pretix-widget-pricebox-original-price {
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
ins.pretix-widget-pricebox-new-price {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.pretix-widget-clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user