mirror of
https://github.com/pretix/pretix.git
synced 2026-05-04 15:04:03 +00:00
Refs #145 -- Vouchers that grant discounts
This commit is contained in:
30
src/pretix/base/migrations/0048_auto_20161129_1330.py
Normal file
30
src/pretix/base/migrations/0048_auto_20161129_1330.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.3 on 2016-11-29 13:30
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0047_auto_20161126_1300'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='voucher',
|
||||
name='price_mode',
|
||||
field=models.CharField(choices=[('none', 'No effect'), ('set', 'Set product price to'), ('subtract', 'Subtract from product price'), ('percent', 'Reduce product price by (%)')], default='set', max_length=100, verbose_name='Price mode'),
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='voucher',
|
||||
old_name='price',
|
||||
new_name='value',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='voucher',
|
||||
name='value',
|
||||
field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='Voucher value'),
|
||||
),
|
||||
]
|
||||
@@ -1,3 +1,5 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
@@ -5,6 +7,7 @@ from django.utils.crypto import get_random_string
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..decimal import round_decimal
|
||||
from .base import LoggedModel
|
||||
from .event import Event
|
||||
from .items import Item, ItemVariation, Quota
|
||||
@@ -59,6 +62,13 @@ class Voucher(LoggedModel):
|
||||
* You need to either select a quota or an item
|
||||
* If you select an item that has variations but do not select a variation, you cannot set block_quota
|
||||
"""
|
||||
PRICE_MODES = (
|
||||
('none', _('No effect')),
|
||||
('set', _('Set product price to')),
|
||||
('subtract', _('Subtract from product price')),
|
||||
('percent', _('Reduce product price by (%)')),
|
||||
)
|
||||
|
||||
event = models.ForeignKey(
|
||||
Event,
|
||||
on_delete=models.CASCADE,
|
||||
@@ -98,10 +108,15 @@ class Voucher(LoggedModel):
|
||||
"If activated, a holder of this voucher code can buy tickets, even if there are none left."
|
||||
)
|
||||
)
|
||||
price = models.DecimalField(
|
||||
verbose_name=_("Set product price to"),
|
||||
price_mode = models.CharField(
|
||||
verbose_name=_("Price mode"),
|
||||
max_length=100,
|
||||
choices=PRICE_MODES,
|
||||
default='set'
|
||||
)
|
||||
value = models.DecimalField(
|
||||
verbose_name=_("Voucher value"),
|
||||
decimal_places=2, max_digits=10, null=True, blank=True,
|
||||
help_text=_('If empty, the product will cost its normal price.')
|
||||
)
|
||||
item = models.ForeignKey(
|
||||
Item, related_name='vouchers',
|
||||
@@ -208,3 +223,19 @@ class Voucher(LoggedModel):
|
||||
if self.valid_until and self.valid_until < now():
|
||||
return False
|
||||
return True
|
||||
|
||||
def calculate_price(self, original_price: Decimal) -> Decimal:
|
||||
"""
|
||||
Returns how the price given in original_price would be modified if this
|
||||
voucher is applied, i.e. replaced by a different price or reduced by a
|
||||
certain percentage. If the voucher does not modify the price, the
|
||||
original price will be returned.
|
||||
"""
|
||||
if self.value:
|
||||
if self.price_mode == 'set':
|
||||
return self.value
|
||||
elif self.price_mode == 'subtract':
|
||||
return original_price - self.value
|
||||
elif self.price_mode == 'percent':
|
||||
return round_decimal(original_price * (Decimal('100.00') - self.value) / Decimal('100.00'))
|
||||
return original_price
|
||||
|
||||
@@ -168,11 +168,10 @@ def _add_new_items(event: Event, items: List[dict],
|
||||
err = err or error_messages['in_part']
|
||||
quota_ok = min(quota_ok, avail[1])
|
||||
|
||||
if voucher and voucher.price is not None:
|
||||
price = voucher.price
|
||||
else:
|
||||
price = item.default_price if variation is None else (
|
||||
variation.default_price if variation.default_price is not None else item.default_price)
|
||||
price = item.default_price if variation is None else (
|
||||
variation.default_price if variation.default_price is not None else item.default_price)
|
||||
if voucher:
|
||||
price = voucher.calculate_price(price)
|
||||
|
||||
if item.free_price and 'price' in i and i['price'] is not None and i['price'] != "":
|
||||
custom_price = i['price']
|
||||
|
||||
@@ -233,8 +233,7 @@ def _check_positions(event: Event, now_dt: datetime, positions: List[CartPositio
|
||||
err = err or error_messages['voucher_expired']
|
||||
cp.delete()
|
||||
continue
|
||||
if cp.voucher.price is not None:
|
||||
price = cp.voucher.price
|
||||
price = cp.voucher.calculate_price(price)
|
||||
|
||||
if price != cp.price and not (cp.item.free_price and cp.price > price):
|
||||
positions[i] = cp
|
||||
|
||||
Reference in New Issue
Block a user