forked from CGM_Public/pretix_original
Discounts: Add applicability date ranges (Z#23151897) (#4927)
* Add event date fields, add preliminary range check * Remove function, use filtered queryset for subevent id limit * Improve and fix date range check * Add formfields * Add tests * Improve tests * Add new fields to API and documentation * Add migration * Change description according to suggestion * Change discount apply signature, remove unnecessary query * Rename new fields, simplify range check * Rename fields in template * Apply suggestions from code review Co-authored-by: Raphael Michel <michel@rami.io> --------- Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
@@ -35,6 +35,10 @@ subevent_mode strings Determines h
|
|||||||
``"same"`` (discount is only applied for groups within
|
``"same"`` (discount is only applied for groups within
|
||||||
the same date), or ``"distinct"`` (discount is only applied
|
the same date), or ``"distinct"`` (discount is only applied
|
||||||
for groups with no two same dates).
|
for groups with no two same dates).
|
||||||
|
subevent_date_from datetime The first date time of a subevent to which this discount can be applied
|
||||||
|
(or ``null``). Ignored in non-series events.
|
||||||
|
subevent_date_until datetime The last date time of a subevent to which this discount can be applied
|
||||||
|
(or ``null``). Ignored in non-series events.
|
||||||
condition_all_products boolean If ``true``, the discount condition applies to all items.
|
condition_all_products boolean If ``true``, the discount condition applies to all items.
|
||||||
condition_limit_products list of integers If ``condition_all_products`` is not set, this is a list
|
condition_limit_products list of integers If ``condition_all_products`` is not set, this is a list
|
||||||
of internal item IDs that the discount condition applies to.
|
of internal item IDs that the discount condition applies to.
|
||||||
@@ -105,6 +109,8 @@ Endpoints
|
|||||||
"available_from": null,
|
"available_from": null,
|
||||||
"available_until": null,
|
"available_until": null,
|
||||||
"subevent_mode": "mixed",
|
"subevent_mode": "mixed",
|
||||||
|
"subevent_date_from": null,
|
||||||
|
"subevent_date_until": null,
|
||||||
"condition_all_products": true,
|
"condition_all_products": true,
|
||||||
"condition_limit_products": [],
|
"condition_limit_products": [],
|
||||||
"condition_apply_to_addons": true,
|
"condition_apply_to_addons": true,
|
||||||
@@ -163,6 +169,8 @@ Endpoints
|
|||||||
"available_from": null,
|
"available_from": null,
|
||||||
"available_until": null,
|
"available_until": null,
|
||||||
"subevent_mode": "mixed",
|
"subevent_mode": "mixed",
|
||||||
|
"subevent_date_from": null,
|
||||||
|
"subevent_date_until": null,
|
||||||
"condition_all_products": true,
|
"condition_all_products": true,
|
||||||
"condition_limit_products": [],
|
"condition_limit_products": [],
|
||||||
"condition_apply_to_addons": true,
|
"condition_apply_to_addons": true,
|
||||||
@@ -207,6 +215,8 @@ Endpoints
|
|||||||
"available_from": null,
|
"available_from": null,
|
||||||
"available_until": null,
|
"available_until": null,
|
||||||
"subevent_mode": "mixed",
|
"subevent_mode": "mixed",
|
||||||
|
"subevent_date_from": null,
|
||||||
|
"subevent_date_until": null,
|
||||||
"condition_all_products": true,
|
"condition_all_products": true,
|
||||||
"condition_limit_products": [],
|
"condition_limit_products": [],
|
||||||
"condition_apply_to_addons": true,
|
"condition_apply_to_addons": true,
|
||||||
@@ -240,6 +250,8 @@ Endpoints
|
|||||||
"available_from": null,
|
"available_from": null,
|
||||||
"available_until": null,
|
"available_until": null,
|
||||||
"subevent_mode": "mixed",
|
"subevent_mode": "mixed",
|
||||||
|
"subevent_date_from": null,
|
||||||
|
"subevent_date_until": null,
|
||||||
"condition_all_products": true,
|
"condition_all_products": true,
|
||||||
"condition_limit_products": [],
|
"condition_limit_products": [],
|
||||||
"condition_apply_to_addons": true,
|
"condition_apply_to_addons": true,
|
||||||
@@ -302,6 +314,8 @@ Endpoints
|
|||||||
"available_from": null,
|
"available_from": null,
|
||||||
"available_until": null,
|
"available_until": null,
|
||||||
"subevent_mode": "mixed",
|
"subevent_mode": "mixed",
|
||||||
|
"subevent_date_from": null,
|
||||||
|
"subevent_date_until": null,
|
||||||
"condition_all_products": true,
|
"condition_all_products": true,
|
||||||
"condition_limit_products": [],
|
"condition_limit_products": [],
|
||||||
"condition_apply_to_addons": true,
|
"condition_apply_to_addons": true,
|
||||||
|
|||||||
@@ -38,11 +38,12 @@ class DiscountSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Discount
|
model = Discount
|
||||||
fields = ('id', 'active', 'internal_name', 'position', 'all_sales_channels', 'limit_sales_channels',
|
fields = ('id', 'active', 'internal_name', 'position', 'all_sales_channels', 'limit_sales_channels',
|
||||||
'available_from', 'available_until', 'subevent_mode', 'condition_all_products',
|
'available_from', 'available_until', 'subevent_mode', 'subevent_date_from', 'subevent_date_until',
|
||||||
'condition_limit_products', 'condition_apply_to_addons', 'condition_min_count', 'condition_min_value',
|
'condition_all_products', 'condition_limit_products', 'condition_apply_to_addons',
|
||||||
'benefit_discount_matching_percent', 'benefit_only_apply_to_cheapest_n_matches',
|
'condition_min_count', 'condition_min_value', 'benefit_discount_matching_percent',
|
||||||
'benefit_same_products', 'benefit_limit_products', 'benefit_apply_to_addons',
|
'benefit_only_apply_to_cheapest_n_matches', 'benefit_same_products', 'benefit_limit_products',
|
||||||
'benefit_ignore_voucher_discounted', 'condition_ignore_voucher_discounted')
|
'benefit_apply_to_addons', 'benefit_ignore_voucher_discounted',
|
||||||
|
'condition_ignore_voucher_discounted')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|||||||
@@ -1518,7 +1518,8 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
|||||||
self.context['event'],
|
self.context['event'],
|
||||||
order.sales_channel,
|
order.sales_channel,
|
||||||
[
|
[
|
||||||
(cp.item_id, cp.subevent_id, cp.price, bool(cp.addon_to), cp.is_bundled, pos._voucher_discount)
|
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.price,
|
||||||
|
bool(cp.addon_to), cp.is_bundled, pos._voucher_discount)
|
||||||
for cp in order_positions
|
for cp in order_positions
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 4.2.19 on 2025-03-18 09:12
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pretixbase', '0278_login_source_add_unique_together'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='discount',
|
||||||
|
name='subevent_date_from',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='discount',
|
||||||
|
name='subevent_date_until',
|
||||||
|
field=models.DateTimeField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -36,7 +36,9 @@ from django_scopes import ScopedManager
|
|||||||
from pretix.base.decimal import round_decimal
|
from pretix.base.decimal import round_decimal
|
||||||
from pretix.base.models.base import LoggedModel
|
from pretix.base.models.base import LoggedModel
|
||||||
|
|
||||||
PositionInfo = namedtuple('PositionInfo', ['item_id', 'subevent_id', 'line_price_gross', 'is_addon_to', 'voucher_discount'])
|
PositionInfo = namedtuple('PositionInfo',
|
||||||
|
['item_id', 'subevent_id', 'subevent_date_from', 'line_price_gross', 'is_addon_to',
|
||||||
|
'voucher_discount'])
|
||||||
|
|
||||||
|
|
||||||
class Discount(LoggedModel):
|
class Discount(LoggedModel):
|
||||||
@@ -171,6 +173,17 @@ class Discount(LoggedModel):
|
|||||||
"access to sold-out quota will still receive the discount."),
|
"access to sold-out quota will still receive the discount."),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
subevent_date_from = models.DateTimeField(
|
||||||
|
verbose_name=pgettext_lazy("subevent", "Available for dates starting from"),
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
|
subevent_date_until = models.DateTimeField(
|
||||||
|
verbose_name=pgettext_lazy("subevent", "Available for dates starting until"),
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
|
|
||||||
# more feature ideas:
|
# more feature ideas:
|
||||||
# - max_usages_per_order
|
# - max_usages_per_order
|
||||||
# - promote_to_user_if_almost_satisfied
|
# - promote_to_user_if_almost_satisfied
|
||||||
@@ -355,11 +368,15 @@ class Discount(LoggedModel):
|
|||||||
# First, filter out everything not even covered by our product scope
|
# First, filter out everything not even covered by our product scope
|
||||||
condition_candidates = [
|
condition_candidates = [
|
||||||
idx
|
idx
|
||||||
for idx, (item_id, subevent_id, line_price_gross, is_addon_to, voucher_discount) in positions.items()
|
for idx, (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, voucher_discount) in
|
||||||
|
positions.items()
|
||||||
if (
|
if (
|
||||||
(self.condition_all_products or item_id in limit_products) and
|
(self.condition_all_products or item_id in limit_products) and
|
||||||
(self.condition_apply_to_addons or not is_addon_to) and
|
(self.condition_apply_to_addons or not is_addon_to) and
|
||||||
(not self.condition_ignore_voucher_discounted or voucher_discount is None or voucher_discount == Decimal('0.00'))
|
(not self.condition_ignore_voucher_discounted or voucher_discount is None or voucher_discount == Decimal('0.00'))
|
||||||
|
and (not subevent_id or (
|
||||||
|
self.subevent_date_from is None or subevent_date_from >= self.subevent_date_from)) and (
|
||||||
|
self.subevent_date_until is None or subevent_date_from <= self.subevent_date_until)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -369,7 +386,8 @@ class Discount(LoggedModel):
|
|||||||
benefit_products = {p.pk for p in self.benefit_limit_products.all()}
|
benefit_products = {p.pk for p in self.benefit_limit_products.all()}
|
||||||
benefit_candidates = [
|
benefit_candidates = [
|
||||||
idx
|
idx
|
||||||
for idx, (item_id, subevent_id, line_price_gross, is_addon_to, voucher_discount) in positions.items()
|
for idx, (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, voucher_discount) in
|
||||||
|
positions.items()
|
||||||
if (
|
if (
|
||||||
item_id in benefit_products and
|
item_id in benefit_products and
|
||||||
(self.benefit_apply_to_addons or not is_addon_to) and
|
(self.benefit_apply_to_addons or not is_addon_to) and
|
||||||
|
|||||||
@@ -1398,7 +1398,8 @@ class CartManager:
|
|||||||
self.event,
|
self.event,
|
||||||
self._sales_channel.identifier,
|
self._sales_channel.identifier,
|
||||||
[
|
[
|
||||||
(cp.item_id, cp.subevent_id, cp.line_price_gross, bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
|
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
|
||||||
|
bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
|
||||||
for cp in positions
|
for cp in positions
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -120,7 +120,8 @@ class CrossSellingService:
|
|||||||
self.event,
|
self.event,
|
||||||
self.sales_channel,
|
self.sales_channel,
|
||||||
[
|
[
|
||||||
(cp.item_id, cp.subevent_id, cp.line_price_gross, bool(cp.addon_to), cp.is_bundled,
|
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
|
||||||
|
bool(cp.addon_to), cp.is_bundled,
|
||||||
cp.listed_price - cp.price_after_voucher)
|
cp.listed_price - cp.price_after_voucher)
|
||||||
for cp in self.cartpositions
|
for cp in self.cartpositions
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -875,7 +875,8 @@ def _check_positions(event: Event, now_dt: datetime, time_machine_now_dt: dateti
|
|||||||
event,
|
event,
|
||||||
sales_channel.identifier,
|
sales_channel.identifier,
|
||||||
[
|
[
|
||||||
(cp.item_id, cp.subevent_id, cp.line_price_gross, bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
|
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
|
||||||
|
bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
|
||||||
for cp in sorted_positions
|
for cp in sorted_positions
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#
|
#
|
||||||
import re
|
import re
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from datetime import datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import List, Optional, Tuple, Union
|
from typing import List, Optional, Tuple, Union
|
||||||
|
|
||||||
@@ -162,14 +163,14 @@ def get_line_price(price_after_voucher: Decimal, custom_price_input: Decimal, cu
|
|||||||
|
|
||||||
|
|
||||||
def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
|
def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
|
||||||
positions: List[Tuple[int, Optional[int], Decimal, bool, bool, Decimal]],
|
positions: List[Tuple[int, Optional[int], Optional[datetime], Decimal, bool, bool, Decimal]],
|
||||||
collect_potential_discounts: Optional[defaultdict]=None) -> List[Tuple[Decimal, Optional[Discount]]]:
|
collect_potential_discounts: Optional[defaultdict]=None) -> List[Tuple[Decimal, Optional[Discount]]]:
|
||||||
"""
|
"""
|
||||||
Applies any dynamic discounts to a cart
|
Applies any dynamic discounts to a cart
|
||||||
|
|
||||||
:param event: Event the cart belongs to
|
:param event: Event the cart belongs to
|
||||||
:param sales_channel: Sales channel the cart was created with
|
:param sales_channel: Sales channel the cart was created with
|
||||||
:param positions: Tuple of the form ``(item_id, subevent_id, line_price_gross, is_addon_to, is_bundled, voucher_discount)``
|
:param positions: Tuple of the form ``(item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)``
|
||||||
:param collect_potential_discounts: If a `defaultdict(list)` is supplied, all discounts that could be applied to the cart
|
:param collect_potential_discounts: If a `defaultdict(list)` is supplied, all discounts that could be applied to the cart
|
||||||
based on the "consumed" items, but lack matching "benefitting" items will be collected therein.
|
based on the "consumed" items, but lack matching "benefitting" items will be collected therein.
|
||||||
The dict will contain a mapping from index in the `positions` list of the item that could be consumed, to a list
|
The dict will contain a mapping from index in the `positions` list of the item that could be consumed, to a list
|
||||||
@@ -191,12 +192,14 @@ def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
|
|||||||
).prefetch_related('condition_limit_products', 'benefit_limit_products').order_by('position', 'pk')
|
).prefetch_related('condition_limit_products', 'benefit_limit_products').order_by('position', 'pk')
|
||||||
for discount in discount_qs:
|
for discount in discount_qs:
|
||||||
result = discount.apply({
|
result = discount.apply({
|
||||||
idx: PositionInfo(item_id, subevent_id, line_price_gross, is_addon_to, voucher_discount)
|
idx: PositionInfo(item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, voucher_discount)
|
||||||
for idx, (item_id, subevent_id, line_price_gross, is_addon_to, is_bundled, voucher_discount) in enumerate(positions)
|
for
|
||||||
|
idx, (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
|
||||||
|
in enumerate(positions)
|
||||||
if not is_bundled and idx not in new_prices
|
if not is_bundled and idx not in new_prices
|
||||||
}, collect_potential_discounts)
|
}, collect_potential_discounts)
|
||||||
for k in result.keys():
|
for k in result.keys():
|
||||||
result[k] = (result[k], discount)
|
result[k] = (result[k], discount)
|
||||||
new_prices.update(result)
|
new_prices.update(result)
|
||||||
|
|
||||||
return [new_prices.get(idx, (p[2], None)) for idx, p in enumerate(positions)]
|
return [new_prices.get(idx, (p[3], None)) for idx, p in enumerate(positions)]
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ class DiscountForm(I18nModelForm):
|
|||||||
'limit_sales_channels',
|
'limit_sales_channels',
|
||||||
'available_from',
|
'available_from',
|
||||||
'available_until',
|
'available_until',
|
||||||
|
'subevent_date_from',
|
||||||
|
'subevent_date_until',
|
||||||
'subevent_mode',
|
'subevent_mode',
|
||||||
'condition_all_products',
|
'condition_all_products',
|
||||||
'condition_limit_products',
|
'condition_limit_products',
|
||||||
@@ -62,6 +64,8 @@ class DiscountForm(I18nModelForm):
|
|||||||
field_classes = {
|
field_classes = {
|
||||||
'available_from': SplitDateTimeField,
|
'available_from': SplitDateTimeField,
|
||||||
'available_until': SplitDateTimeField,
|
'available_until': SplitDateTimeField,
|
||||||
|
'subevent_date_from': SplitDateTimeField,
|
||||||
|
'subevent_date_until': SplitDateTimeField,
|
||||||
'condition_limit_products': ItemMultipleChoiceField,
|
'condition_limit_products': ItemMultipleChoiceField,
|
||||||
'benefit_limit_products': ItemMultipleChoiceField,
|
'benefit_limit_products': ItemMultipleChoiceField,
|
||||||
'limit_sales_channels': SafeModelMultipleChoiceField,
|
'limit_sales_channels': SafeModelMultipleChoiceField,
|
||||||
@@ -70,6 +74,8 @@ class DiscountForm(I18nModelForm):
|
|||||||
'subevent_mode': forms.RadioSelect,
|
'subevent_mode': forms.RadioSelect,
|
||||||
'available_from': SplitDateTimePickerWidget(),
|
'available_from': SplitDateTimePickerWidget(),
|
||||||
'available_until': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_available_from_0'}),
|
'available_until': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_available_from_0'}),
|
||||||
|
'subevent_date_from': SplitDateTimePickerWidget(),
|
||||||
|
'subevent_date_until': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_subevent_date_from_0'}),
|
||||||
'condition_limit_products': forms.CheckboxSelectMultiple(attrs={
|
'condition_limit_products': forms.CheckboxSelectMultiple(attrs={
|
||||||
'data-inverse-dependency': '<[name$=all_products]',
|
'data-inverse-dependency': '<[name$=all_products]',
|
||||||
'class': 'scrolling-multiple-choice',
|
'class': 'scrolling-multiple-choice',
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
{% bootstrap_field form.condition_ignore_voucher_discounted layout="control" %}
|
{% bootstrap_field form.condition_ignore_voucher_discounted layout="control" %}
|
||||||
{% if form.subevent_mode %}
|
{% if form.subevent_mode %}
|
||||||
{% bootstrap_field form.subevent_mode layout="control" %}
|
{% bootstrap_field form.subevent_mode layout="control" %}
|
||||||
|
{% bootstrap_field form.subevent_date_from layout="control" %}
|
||||||
|
{% bootstrap_field form.subevent_date_until layout="control" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="form-group form-alternatives">
|
<div class="form-group form-alternatives">
|
||||||
<label class="col-md-3 control-label">
|
<label class="col-md-3 control-label">
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ TEST_DISCOUNT_RES = {
|
|||||||
"available_from": None,
|
"available_from": None,
|
||||||
"available_until": None,
|
"available_until": None,
|
||||||
"subevent_mode": "mixed",
|
"subevent_mode": "mixed",
|
||||||
|
"subevent_date_from": None,
|
||||||
|
"subevent_date_until": None,
|
||||||
"condition_all_products": True,
|
"condition_all_products": True,
|
||||||
"condition_limit_products": [],
|
"condition_limit_products": [],
|
||||||
"condition_apply_to_addons": True,
|
"condition_apply_to_addons": True,
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_count_matching_percent,
|
mixed_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 2,
|
) * 2,
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -152,7 +152,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_count_matching_percent,
|
mixed_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 3,
|
) * 3,
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -163,12 +163,12 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_count_matching_percent,
|
mixed_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -184,7 +184,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_count_one_free,
|
mixed_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 2,
|
) * 2,
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -194,7 +194,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_count_one_free,
|
mixed_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 3,
|
) * 3,
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -205,7 +205,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_count_one_free,
|
mixed_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 5,
|
) * 5,
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -218,7 +218,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_count_one_free,
|
mixed_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 6,
|
) * 6,
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -232,12 +232,12 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_count_one_free,
|
mixed_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('2.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('2.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('3.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('3.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('4.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('4.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('5.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('5.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('6.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('6.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -253,7 +253,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_value_matching_percent,
|
mixed_min_value_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 4,
|
) * 4,
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -265,7 +265,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_value_matching_percent,
|
mixed_min_value_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 5,
|
) * 5,
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -278,7 +278,7 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
mixed_min_value_matching_percent,
|
mixed_min_value_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
) * 10,
|
) * 10,
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -298,10 +298,10 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
same_min_count_matching_percent,
|
same_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -313,11 +313,11 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
same_min_count_matching_percent,
|
same_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -330,14 +330,14 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
same_min_count_matching_percent,
|
same_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -355,15 +355,15 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
same_min_count_one_free,
|
same_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -380,15 +380,15 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
same_min_count_one_free,
|
same_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('2.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('2.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('3.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('3.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('4.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('4.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('5.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('5.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('6.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('6.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('7.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('7.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('8.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('8.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('9.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('9.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -407,15 +407,15 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
same_min_value_matching_percent,
|
same_min_value_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -434,9 +434,9 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_matching_percent,
|
distinct_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -447,9 +447,9 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_matching_percent,
|
distinct_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -460,14 +460,14 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_matching_percent,
|
distinct_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -483,13 +483,13 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_matching_percent,
|
distinct_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 4, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 4, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -504,13 +504,13 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_matching_percent,
|
distinct_min_count_matching_percent,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 4, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 4, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('96.00'),
|
Decimal('96.00'),
|
||||||
@@ -527,9 +527,9 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_one_free,
|
distinct_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -540,9 +540,9 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_one_free,
|
distinct_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -553,12 +553,12 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_one_free,
|
distinct_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 4, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 4, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -572,12 +572,12 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_one_free,
|
distinct_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('3.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('3.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('1.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('1.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
|
||||||
(1, 4, Decimal('3.00'), False, False, Decimal('0.00')),
|
(1, 4, now(), Decimal('3.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('3.00'),
|
Decimal('3.00'),
|
||||||
@@ -591,12 +591,12 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_two_free,
|
distinct_min_count_two_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('3.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('3.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('1.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('1.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
|
||||||
(1, 4, Decimal('3.00'), False, False, Decimal('0.00')),
|
(1, 4, now(), Decimal('3.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('3.00'),
|
Decimal('3.00'),
|
||||||
@@ -610,12 +610,12 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_one_free,
|
distinct_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 4, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 4, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 5, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 5, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
(1, 6, Decimal('120.00'), False, False, Decimal('0.00')),
|
(1, 6, now(), Decimal('120.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('120.00'),
|
Decimal('120.00'),
|
||||||
@@ -629,12 +629,12 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_one_free,
|
distinct_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('1.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('1.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('2.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('2.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('3.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('3.00'), False, False, Decimal('0.00')),
|
||||||
(1, 4, Decimal('4.00'), False, False, Decimal('0.00')),
|
(1, 4, now(), Decimal('4.00'), False, False, Decimal('0.00')),
|
||||||
(1, 5, Decimal('5.00'), False, False, Decimal('0.00')),
|
(1, 5, now(), Decimal('5.00'), False, False, Decimal('0.00')),
|
||||||
(1, 6, Decimal('6.00'), False, False, Decimal('0.00')),
|
(1, 6, now(), Decimal('6.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -648,12 +648,12 @@ testcases_single_rule = [
|
|||||||
(
|
(
|
||||||
distinct_min_count_one_free,
|
distinct_min_count_one_free,
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('4.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('4.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('4.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('4.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('4.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('4.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('6.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('6.00'), False, False, Decimal('0.00')),
|
||||||
(1, 2, Decimal('6.00'), False, False, Decimal('0.00')),
|
(1, 2, now(), Decimal('6.00'), False, False, Decimal('0.00')),
|
||||||
(1, 3, Decimal('6.00'), False, False, Decimal('0.00')),
|
(1, 3, now(), Decimal('6.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
# This one is unexpected, since the customer could get a lower price
|
# This one is unexpected, since the customer could get a lower price
|
||||||
@@ -674,7 +674,7 @@ testcases_single_rule = [
|
|||||||
Discount(condition_min_count=1, benefit_discount_matching_percent=20),
|
Discount(condition_min_count=1, benefit_discount_matching_percent=20),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('80.00'),
|
Decimal('80.00'),
|
||||||
@@ -689,8 +689,8 @@ testcases_single_rule = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('0.00'),
|
Decimal('0.00'),
|
||||||
@@ -708,9 +708,9 @@ testcases_single_rule = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -728,9 +728,9 @@ testcases_single_rule = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('80.00'),
|
Decimal('80.00'),
|
||||||
@@ -747,11 +747,11 @@ testcases_single_rule = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('80.00'),
|
Decimal('80.00'),
|
||||||
@@ -770,9 +770,9 @@ testcases_single_rule = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), True, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), True, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -791,9 +791,9 @@ testcases_single_rule = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), True, True, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), True, True, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), True, True, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), True, True, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -818,9 +818,9 @@ testcases_multiple_rules = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('80.00'),
|
Decimal('80.00'),
|
||||||
@@ -843,9 +843,9 @@ testcases_multiple_rules = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('80.00'),
|
Decimal('80.00'),
|
||||||
@@ -867,9 +867,9 @@ testcases_multiple_rules = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -890,11 +890,11 @@ testcases_multiple_rules = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -917,9 +917,9 @@ testcases_multiple_rules = [
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(1, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(1, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Decimal('80.00'),
|
Decimal('80.00'),
|
||||||
@@ -954,10 +954,10 @@ def test_limit_products(event, item, item2):
|
|||||||
d2.save()
|
d2.save()
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
Decimal('80.00'),
|
Decimal('80.00'),
|
||||||
@@ -979,10 +979,10 @@ def test_limit_products_subevents_distinct(event, item, item2):
|
|||||||
d1.condition_limit_products.add(item)
|
d1.condition_limit_products.add(item)
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item.pk, 1, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, 1, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, 2, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, 2, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, 3, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, 3, now(), Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, 4, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, 4, now(), Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
Decimal('80.00'),
|
Decimal('80.00'),
|
||||||
@@ -1007,8 +1007,8 @@ def test_sales_channels(event, item):
|
|||||||
d2.limit_sales_channels.add(event.organizer.sales_channels.get(identifier="bar"))
|
d2.limit_sales_channels.add(event.organizer.sales_channels.get(identifier="bar"))
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert sorted([p for p, d in apply_discounts(event, 'bar', positions)]) == [Decimal('80.00'), Decimal('80.00')]
|
assert sorted([p for p, d in apply_discounts(event, 'bar', positions)]) == [Decimal('80.00'), Decimal('80.00')]
|
||||||
@@ -1024,8 +1024,8 @@ def test_available_from(event, item):
|
|||||||
d2.save()
|
d2.save()
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('50.00'), Decimal('50.00')]
|
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('50.00'), Decimal('50.00')]
|
||||||
@@ -1040,13 +1040,78 @@ def test_available_until(event, item):
|
|||||||
d2.save()
|
d2.save()
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('50.00'), Decimal('50.00')]
|
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('50.00'), Decimal('50.00')]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@scopes_disabled()
|
||||||
|
def test_subevent_date_from(event, item, subevent):
|
||||||
|
subevent_date = subevent.date_from # prevent test timing errors
|
||||||
|
d1 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=20,
|
||||||
|
subevent_date_from=subevent_date + timedelta(days=1))
|
||||||
|
d1.save()
|
||||||
|
d2 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=50,
|
||||||
|
subevent_date_from=subevent_date)
|
||||||
|
d2.save()
|
||||||
|
|
||||||
|
# (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
|
||||||
|
positions = (
|
||||||
|
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
|
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('50.00'), Decimal('50.00')]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@scopes_disabled()
|
||||||
|
def test_subevent_date_until(event, item, subevent):
|
||||||
|
subevent_date = subevent.date_from # prevent test timing errors
|
||||||
|
d1 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=20,
|
||||||
|
subevent_date_until=subevent_date + timedelta(days=1))
|
||||||
|
d1.save()
|
||||||
|
d2 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=50,
|
||||||
|
subevent_date_until=subevent_date)
|
||||||
|
d2.save()
|
||||||
|
|
||||||
|
# (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
|
||||||
|
positions = (
|
||||||
|
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
|
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('80.00'), Decimal('80.00')]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@scopes_disabled()
|
||||||
|
def test_subevent_date_from_until(event, item, subevent):
|
||||||
|
subevent_date = subevent.date_from # prevent test timing errors
|
||||||
|
d1 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=20,
|
||||||
|
subevent_date_from=subevent_date + timedelta(days=1),
|
||||||
|
subevent_date_until=subevent_date + timedelta(days=2))
|
||||||
|
d1.save()
|
||||||
|
d2 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=50,
|
||||||
|
subevent_date_from=subevent_date - timedelta(days=2),
|
||||||
|
subevent_date_until=subevent_date - timedelta(days=1))
|
||||||
|
d2.save()
|
||||||
|
d3 = Discount(event=event, condition_min_count=2, benefit_discount_matching_percent=80,
|
||||||
|
subevent_date_from=subevent_date, subevent_date_until=subevent_date + timedelta(days=1))
|
||||||
|
d3.save()
|
||||||
|
|
||||||
|
# (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
|
||||||
|
positions = (
|
||||||
|
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
|
(item.pk, subevent.pk, subevent.date_from, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert sorted([p for p, d in apply_discounts(event, 'web', positions)]) == [Decimal('20.00'), Decimal('20.00')]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@scopes_disabled()
|
@scopes_disabled()
|
||||||
def test_discount_other_products_min_count(event, item, item2):
|
def test_discount_other_products_min_count(event, item, item2):
|
||||||
@@ -1064,21 +1129,21 @@ def test_discount_other_products_min_count(event, item, item2):
|
|||||||
d1.benefit_limit_products.add(item)
|
d1.benefit_limit_products.add(item)
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -1120,12 +1185,12 @@ def test_discount_other_products_min_count_no_addon(event, item, item2):
|
|||||||
d1.benefit_limit_products.add(item)
|
d1.benefit_limit_products.add(item)
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('90.00'), True, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('90.00'), True, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -1158,13 +1223,13 @@ def test_discount_other_products_min_count_no_voucher(event, item, item2):
|
|||||||
d1.benefit_limit_products.add(item)
|
d1.benefit_limit_products.add(item)
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('40.00'), False, False, Decimal('50.00')),
|
(item.pk, None, None, Decimal('40.00'), False, False, Decimal('50.00')),
|
||||||
(item.pk, None, Decimal('40.00'), False, False, Decimal('50.00')),
|
(item.pk, None, None, Decimal('40.00'), False, False, Decimal('50.00')),
|
||||||
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -1199,21 +1264,21 @@ def test_discount_subgroup_cheapest_n_min_count(event, item, item2):
|
|||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
# 11 items of item2, which contribute to the total count of 15, but do not get reduced
|
# 11 items of item2, which contribute to the total count of 15, but do not get reduced
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('100.00'), False, False, Decimal('0.00')),
|
||||||
# 4 items of item, of which 3 of the cheapest will be reduced
|
# 4 items of item, of which 3 of the cheapest will be reduced
|
||||||
(item.pk, None, Decimal('110.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('110.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('110.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('110.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('90.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
Decimal('100.00'),
|
Decimal('100.00'),
|
||||||
@@ -1252,10 +1317,10 @@ def test_discount_other_products_min_value(event, item, item2):
|
|||||||
d1.benefit_limit_products.add(item2)
|
d1.benefit_limit_products.add(item2)
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
Decimal('50.00'),
|
Decimal('50.00'),
|
||||||
@@ -1268,11 +1333,11 @@ def test_discount_other_products_min_value(event, item, item2):
|
|||||||
assert sorted(new_prices) == sorted(expected)
|
assert sorted(new_prices) == sorted(expected)
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
Decimal('50.00'),
|
Decimal('50.00'),
|
||||||
@@ -1316,16 +1381,16 @@ def test_multiple_discounts_with_benefit_condition_overlap(event, item, item2):
|
|||||||
d2.condition_limit_products.add(item)
|
d2.condition_limit_products.add(item)
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
# item2 remains untouched
|
# item2 remains untouched
|
||||||
@@ -1379,16 +1444,16 @@ def test_multiple_discounts_with_same_condition(event, item, item2, item3):
|
|||||||
d2.benefit_limit_products.add(item3)
|
d2.benefit_limit_products.add(item3)
|
||||||
|
|
||||||
positions = (
|
positions = (
|
||||||
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
||||||
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
||||||
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
||||||
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
||||||
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
||||||
(item3.pk, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
(item3.pk, None, None, Decimal('42.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item2.pk, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
(item2.pk, None, None, Decimal('50.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
(item.pk, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
(item.pk, None, None, Decimal('23.00'), False, False, Decimal('0.00')),
|
||||||
)
|
)
|
||||||
expected = (
|
expected = (
|
||||||
# both item1 remain full price
|
# both item1 remain full price
|
||||||
|
|||||||
Reference in New Issue
Block a user