Пример #1
0
def test_formulas():
    """
    Тест использования формул вместо цен

    :return:
    """
    value = 150
    base_price = 250
    value_type = OPTION_TYPE_CHOICES.QUANTITY
    expect_total_price = value * (base_price - 42)

    ruleset = [
        {
            "rule": {
                "condition": "AND",
                "rules": [
                    {
                        "id": "value",
                        "type": "integer",
                        "operator": "greater",
                        "value": 0,
                    },
                ],
            },
            "price": "bp - 42",
        },
    ]

    price_rule = PriceRule(ruleset=ruleset)

    result, explain = price_rule.calculate_price(value=value, value_type=value_type,
                                                 base_price=base_price)

    assert result == expect_total_price
Пример #2
0
def test_non_iso_datetime_rule():
    base_price = 250
    value = [
        '01.01.2016 09:00', '02.01.2016 19:00'
    ]
    value_type = OPTION_TYPE_CHOICES.DATETIME_RANGE_HOUR
    price_rule = PriceRule(ruleset=[])
    result, explain = price_rule.calculate_price(value=value, value_type=value_type,
                                                 base_price=base_price)
    assert result == (34 * base_price)
Пример #3
0
def test_empty_datetime_rule():
    base_price = 250
    value = [
        '2016-01-01 09:00', '2016-01-02 19:00'
    ]
    value_type = OPTION_TYPE_CHOICES.DATETIME_RANGE_HOUR
    price_rule = PriceRule(ruleset=[])
    result, explain = price_rule.calculate_price(value=value, value_type=value_type,
                                                 base_price=base_price)
    assert result == 34 * base_price
Пример #4
0
def test_empty_option():
    empty_value_types = [
        [False, OPTION_TYPE_CHOICES.BOOL]
    ]

    price_rule = PriceRule(ruleset=[])
    for value, value_type in empty_value_types:
        result, explain = price_rule.calculate_price(value=value, value_type=value_type,
                                                     base_price=100500)

        assert result == 0
Пример #5
0
def test_empty_rule():
    """
    Случай, когда нет каких либо правил, а есть только базовая цена.
    Стоимость тогда считается как quantity * base_price

    :return:
    """
    value = 150
    base_price = 250
    value_type = OPTION_TYPE_CHOICES.QUANTITY
    expect_total_price = value * base_price

    price_rule = PriceRule(ruleset=[])

    result, explain = price_rule.calculate_price(value=value, value_type=value_type,
                                                 base_price=base_price)

    assert result == expect_total_price
Пример #6
0
def test_change_base_price():
    """

    Тест использования правил на изменение базовой цены (объемная скидка)

    :return:
    """
    value = 150
    base_price = 250
    value_type = OPTION_TYPE_CHOICES.QUANTITY
    expect_total_price = value * (base_price - 42)

    ruleset = [
        {
            "rule": {
                "condition": "AND",
                "rules": [
                    {
                        "id": "total_value",
                        "field": "total_value",
                        "type": "integer",
                        "operator": "greater",
                        "value": 100,
                    },
                ],
            },
            "price": "bp - 42",
        },
    ]

    price_rule = PriceRule(ruleset=ruleset)

    result, explain = price_rule.calculate_price(value=value, value_type=value_type,
                                                 base_price=base_price)

    assert result == expect_total_price
    def test_service_1791(self):
        """
        Проблема в граничных условиях 23:00-00:00 - час подачи
        :return:
        """

        ruleset = [
            {
                "id": 2384,
                "rule": {
                    "rules": [
                        {
                            "value": [
                                "06:00",
                                "23:00"
                            ],
                            "field": "27526.time",
                            "operator": "between",
                            "input": "text",
                            "type": "time",
                            "id": "27526.time"
                        },
                        {
                            "value": [
                                "true"
                            ],
                            "field": "27528.value",
                            "operator": "equal",
                            "input": "checkbox",
                            "type": "boolean",
                            "id": "27528.value"
                        }
                    ],
                    "condition": "AND"
                },
                "title": "Дневной тариф",
                "price": "700",
                "order": 1000,
                "to_option": 27528
            },
            {
                "id": 2383,
                "rule": {
                    "rules": [
                        {
                            "value": [
                                "23:00",
                                "06:00",
                            ],
                            "field": "27526.time",
                            "operator": "between",
                            "input": "text",
                            "type": "time",
                            "id": "27526.time"
                        },
                        {
                            "value": [
                                "true"
                            ],
                            "field": "27528.value",
                            "operator": "equal",
                            "input": "checkbox",
                            "type": "boolean",
                            "id": "27528.value"
                        }
                    ],
                    "condition": "AND"
                },
                "title": "Ночной тариф",
                "price": "945",
                "order": 1000,
                "to_option": 27528
            }
        ]

        values_info = {
            27526: {
                "type": "datetime_range_hour",
            },
            27528: {"type": "bool"},
        }

        expected_results = [
            ({
                 27526: ["2016-05-27T23:00", "2016-05-28T00:00"],
                 27528: True,
             }, {27528: 700}
            ),
            ({
                 27526: ["2016-05-27T23:01", "2016-05-28T00:00"],
                 27528: True,
             }, {27528: 945}),
            ({
                 27526: ["2016-05-27T01:00", "2016-05-28T01:00"],
                 27528: True,
             }, {27528: 945}
            ),
            ({
                 27526: ["2016-05-27T23:01", "2016-05-28T07:00"],
                 27528: True,
             }, {27528: 945}
            ),
        ]

        ruleset = PriceRule(ruleset=ruleset)

        for value_dict, expected_result in expected_results:
            _value_data = copy(values_info)
            for field, value in value_dict.items():
                _value_data[field]['value'] = value

            result, explain = ruleset.calculate_group_price(_value_data)

            self.assertEquals(result, expected_result, [result, expected_result, value_dict])
    def test_variant_calculation(self):
        """
        Поиск бага
        :return:
        """
        null = None

        values_info = {
            27253: {u'type': u'datetime_range_day', u'value': None},
            27515: {u'type': u'text', u'value': None},
            27516: {u'type': u'text', u'value': None},
            27517: {u'type': u'bool', u'value': None},
            27518: {u'type': u'bool', u'value': None},
            27519: {u'type': u'bool', u'value': None},
            27520: {u'type': u'bool', u'value': None}
        }
        ruleset = [
            {
                "id": 6,
                "rule": {
                    "rules": [
                        {
                            "value": null,
                            "field": "27253.datetime",
                            "operator": "is_not_null",
                            "input": "text",
                            "type": "datetime",
                            "id": "27253.datetime"
                        },
                        {
                            "value": [
                                "true"
                            ],
                            "field": "27520.value",
                            "operator": "equal",
                            "input": "checkbox",
                            "type": "boolean",
                            "id": "27520.value"
                        }
                    ],
                    "condition": "AND"
                },
                "title": "Цена навигатора на период аренды",
                "price": "300 * o_27253.days",
                "order": 1000,
                "to_option": 27520
            },
            {
                "id": 7,
                "rule": {
                    "rules": [
                        {
                            "value": null,
                            "field": "27253.datetime",
                            "operator": "is_not_null",
                            "input": "text",
                            "type": "datetime",
                            "id": "27253.datetime"
                        },
                        {
                            "value": [
                                "true"
                            ],
                            "field": "27518.value",
                            "operator": "equal",
                            "input": "checkbox",
                            "type": "boolean",
                            "id": "27518.value"
                        }
                    ],
                    "condition": "AND"
                },
                "title": "Цена автокресла на период аренды",
                "price": "350 * o_27253.days",
                "order": 1000,
                "to_option": 27518
            },
            {
                "id": 8,
                "rule": {
                    "rules": [
                        {
                            "value": null,
                            "field": "27253.datetime",
                            "operator": "is_not_null",
                            "input": "text",
                            "type": "datetime",
                            "id": "27253.datetime"
                        },
                        {
                            "value": [
                                "true"
                            ],
                            "field": "27519.value",
                            "operator": "equal",
                            "input": "checkbox",
                            "type": "boolean",
                            "id": "27519.value"
                        }
                    ],
                    "condition": "AND"
                },
                "title": "Цена автолюльки на период аренды",
                "price": "250 * o_27253.days",
                "order": 1000,
                "to_option": 27519
            },
            {
                "id": 9,
                "rule": {
                    "rules": [
                        {
                            "value": null,
                            "field": "27253.datetime",
                            "operator": "is_not_null",
                            "input": "text",
                            "type": "datetime",
                            "id": "27253.datetime"
                        },
                        {
                            "value": [
                                "true"
                            ],
                            "field": "27517.value",
                            "operator": "equal",
                            "input": "checkbox",
                            "type": "boolean",
                            "id": "27517.value"
                        }
                    ],
                    "condition": "AND"
                },
                "title": "Цена за дополнительного водителя на период аренды",
                "price": "317 * o_27253.days",
                "order": 1000,
                "to_option": 27517
            }
        ]

        expected_results = [
            (
                {27253: [u'2016-05-24T16:00', u'2016-05-24T16:00'],
                 27515: u'',
                 27516: u'',
                 27517: False,
                 27519: False,
                 27518: True,
                 27520: True
                 },
                {27520: 300, 27518: 350}
            ),
            (
                {27253: [u'2016-05-24T16:00', u'2016-05-26T16:01'],
                 27515: u'',
                 27516: u'',
                 27517: False,
                 27519: False,
                 27518: True,
                 27520: True
                 },
                {27520: 300 * 3, 27518: 350 * 3}
            ),
            (
                {27253: [u'2016-05-24T16:00', u'2016-05-26T16:00'],
                 27515: u'',
                 27516: u'',
                 27517: False,
                 27519: False,
                 27518: True,
                 27520: True
                 },
                {27520: 300 * 1, 27518: 350 * 1}
            ),
        ]

        price_rule = PriceRule(ruleset=ruleset)

        for value_dict, expected_result in expected_results:
            _value_data = copy(values_info)
            for field, value in value_dict.items():
                _value_data[field]['value'] = value

            result, explain = price_rule.calculate_group_price(_value_data)

            self.assertEquals(result, expected_result)
    def test_price_calculation(self):
        """
        Нужна возможность внутри варианта использовать формулы со ссылкой на результат другой ценовой опции.

        Например, опция "Навигатор" должна иметь стоимость:
        N р. * [количество получившихся суток в ценовой позиции "интервал времени(сутки)"]
        :return:
        """

        RENT_OPT = '11'
        NAV_OPT = '12'

        values_info = {
            NAV_OPT: {
                "value": None,
                "type": OPTION_TYPE_CHOICES.BOOL,
            },
            RENT_OPT: {
                "value": None,
                "type": OPTION_TYPE_CHOICES.DATETIME_RANGE_DAY
            }
        }

        ruleset = [
            {
                "rule": {

                    "condition": "AND",
                    "rules": [
                        {
                            "id": "11.value",
                            "type": "time",
                            "operator": "is_not_empty",
                        },
                        {
                            "id": "12.value",
                            "type": "boolean",
                            "operator": "equal",
                            "value": "true",
                        },
                    ],
                },
                "price": "100 * o_11.days",
                "to_option": "12",
            },
        ]

        expected_results = [
            (
                {"11": ['2016-01-01 05:00', '2016-01-13 05:01'], "12": True},
                {"12": 100 * 13}
            ),
            (
                {"11": ['2016-01-01 05:00', '2016-01-13 05:00'], "12": True},
                {"12": 100 * 12}
            ),
            (
                {"11": ['2016-01-01 05:00', '2016-01-13 04:00'], "12": False},
                {None: 0}
            ),
        ]

        price_rule = PriceRule(ruleset=ruleset)

        for value_dict, expected_result in expected_results:
            _value_data = copy(values_info)
            for field, value in value_dict.items():
                _value_data[field]['value'] = value

            result, explain = price_rule.calculate_group_price(_value_data)

            self.assertEquals(result, expected_result)
    def test_generic(self):
        """
        Для варианта считаются комбинированые опции, скорее всего редко будет использоватьтся,
        но может использоваться в комбинации с с выражениями,

         По умолчанию проще всего считать для опций, которые могут зависеть от остальных выражений.


        Дано:

        Есть следующие поля - аренда стульев

        [1] Количество  стульев
        [2] Опция - доставка стульев, максимум 30 стульев

        Правила:

        1) Стоимость опции доставки увеличвается от стоимости количества доставки по следующим критериям
            до 5 стульев - базовая цена доставки
            до 10 - +200р (>5)
            до 20 - +300р (>10)
            от 21 - +400р.

        :return:
        """

        values_info = {
            'quantity': {
                "value": None,
                "type": OPTION_TYPE_CHOICES.QUANTITY,
            },
            'ship': {
                "value": None,
                "type": OPTION_TYPE_CHOICES.BOOL
            }
        }

        ruleset = [
            {
                "rule": {

                    "condition": "AND",
                    "rules": [
                        {
                            "id": "quantity.value",
                            "type": "integer",
                            "operator": "greater",
                            "value": "20",
                        },
                        {
                            "id": "ship.value",
                            "type": "boolean",
                            "operator": "equal",
                            "value": "true",
                        },
                    ],
                },
                "price": "400",
                "to_option": "ship",
            },
            {
                "rule": {
                    "condition": "AND",
                    "rules": [
                        {
                            "id": "quantity.value",
                            "type": "integer",
                            "operator": "greater",
                            "value": "10",
                        },
                        {
                            "id": "ship.value",
                            "type": "boolean",
                            "operator": "equal",
                            "value": "true",
                        },
                    ],

                },
                "price": "300",
                "to_option": "ship",
            },
            {
                "rule": {
                    "condition": "AND",
                    "rules": [
                        {
                            "id": "quantity.value",
                            "type": "integer",
                            "operator": "greater",
                            "value": "5",
                        },
                        {
                            "id": "ship.value",
                            "type": "boolean",
                            "operator": "equal",
                            "value": "true",
                        },
                    ],

                },
                "price": "200",
                "to_option": "ship",
            },
        ]

        expected_results = [
            (
                {"quantity": 30, "ship": True},
                {"ship": 400}
            ),
            (
                {"quantity": 20, "ship": True},
                {"ship": 300}
            ),
            (
                {"quantity": 10, "ship": True},
                {"ship": 200}
            ),
            (
                {"quantity": 5, "ship": True},
                {None: 0}
            ),
            (
                {"quantity": 1, "ship": True},
                {None: 0}
            ),

        ]

        price_rule = PriceRule(ruleset=ruleset)

        for value_dict, expected_result in expected_results:
            _value_data = copy(values_info)
            for field, value in value_dict.items():
                _value_data[field]['value'] = value

            result, explain = price_rule.calculate_group_price(_value_data)

            self.assertEquals(result, expected_result)
Пример #11
0
def test_generic():
    """

    Простое правило вида

    Количество.

    до 10 штук - 250р
    до 50 штук - 200р
    до 100 штук - 100р
    от 100 штук - 50р



    :return:
    """
    value = 150
    base_price = 250
    value_type = OPTION_TYPE_CHOICES.QUANTITY
    expect_total_price = ((10 * 250)
                          + ((50 - 10) * 200)
                          + ((100 - 50) * 100)
                          + ((value - 100) * 50)
                          )

    ruleset = [
        {
            "rule": {
                "condition": "AND",
                "rules": [
                    {
                        "id": "value",
                        "type": "integer",
                        "operator": "between",
                        "value": ["11", "50"],
                    },
                ],
            },
            "price": "200",
        },
        {
            "rule": {
                "condition": "AND",
                "rules": [
                    {
                        "id": "value",
                        "type": "integer",
                        "operator": "between",
                        "value": ["51", "100"],
                    },
                ],
            },
            "price": "100",
        },
        {
            "rule": {
                "condition": "AND",
                "rules": [
                    {
                        "id": "value",
                        "type": "integer",
                        "operator": "greater",
                        "value": "100",
                    },
                ],
            },
            "price": "50",
        },
    ]

    price_rule = PriceRule(ruleset=ruleset)

    result, explain = price_rule.calculate_price(value=value, value_type=value_type,
                                                 base_price=base_price)

    assert result == expect_total_price
Пример #12
0
def test_generic_rent_car_buggy():
    """

    Простое правило аренды

    Аренда почасовая

    Дневной тариф - с 9 до 18 - 400 руб
    Ночной тариф - с 18 до 9 - 600 руб

    Арендуем с 2016-01-01 09:00 по 2016-01-02 19:00

    :return:
    """
    value_type = OPTION_TYPE_CHOICES.DATETIME_RANGE_HOUR

    base_price = None

    ruleset = [
        {
            "rule": {
                "condition": "AND",
                "rules": [
                    {
                        "id": "time",
                        "type": "time",
                        "operator": "between",
                        "value": ["09:01", "18:00"],
                    },
                ],
            },
            "price": "400",
        },
        {
            "rule": {
                "condition": "AND",
                "rules": [
                    {
                        "id": "time",
                        "type": "time",
                        "operator": "not_between",
                        "value": ["09:01", "18:00"],
                    },
                ],
            },
            "price": "600",
        },
    ]

    price_rule = PriceRule(ruleset=ruleset)

    expected = [
        (
            ['2016-01-01 18:00', '2016-01-02 9:00'],
            (
                + (14 * 600)  # 8400
            )
        ),
    ]

    for value, expect_total in expected:
        result, explain = price_rule.calculate_price(value=value, value_type=value_type,
                                                     base_price=base_price)

        assert result == expect_total