Розробка форми розрахунку вартості на 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Розробка форми розрахунку вартості на 1С-Бітрікс
Середня
~1-2 тижні
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Розробка форми розрахунку вартості на 1С-Бітрікс

Форма розрахунку вартості — калькулятор, що дозволяє користувачеві самостійно оцінити ціну послуги або продукту до дзвінка менеджеру. Застосовується в будівництві, IT-послугах, виробництві, логістиці, страхуванні. Конверсійний ефект двоякий: частина користувачів іде, побачивши ціну, — але ті, що залишаються, приходять вже підготовленими і з реалістичними очікуваннями.

Типи калькуляторів

Простий (детермінований): кожен параметр має фіксовану ціну. Підсумок = сума компонентів. Приклад: вибір комплектації автомобіля.

Коефіцієнтний: є базова ціна і коефіцієнти — регіональний, сезонний, за складністю. Підсумок = базова_ціна × К1 × К2 × ... Застосовується в будівництві, страхуванні.

Формульний: довільна формула з кількома вхідними змінними. Приклад: вартість перевезення = вага × відстань × тариф + фіксована вартість.

З діапазоном: результат не точна сума, а діапазон «від X до Y». Застосовується в IT-розробці, коли точний розрахунок без ТЗ неможливий.

Зберігання конфігурації калькулятора

Конфігурацію краще зберігати в базі (HL-блок), а не в коді — щоб менеджери могли змінювати ціни без розробника.

class CalculatorConfigTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'b_hl_calculator_config'; }

    public static function getMap(): array
    {
        return [
            new IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
            new StringField('SLUG'),           // Ідентифікатор калькулятора
            new StringField('TITLE'),
            new TextField('PARAMS_JSON'),      // Параметри та їх ціни
            new TextField('FORMULA_JSON'),     // Формула розрахунку
            new StringField('CURRENCY'),       // RUB, USD, EUR
            new FloatField('MIN_PRICE'),       // Мінімальна ціна
            new FloatField('MAX_PRICE'),       // NULL = без обмеження
            new BooleanField('SHOW_RANGE', ['values' => [false, true]]),
            new IntegerField('RANGE_PERCENT'), // ±% для діапазону
        ];
    }
}

PARAMS_JSON — опис параметрів:

[
  {
    "id": "area",
    "label": "Площа (кв.м.)",
    "type": "range",
    "min": 10,
    "max": 500,
    "default": 50,
    "step": 5,
    "unit": "кв.м."
  },
  {
    "id": "floors",
    "label": "Кількість поверхів",
    "type": "select",
    "options": [
      {"value": 1, "label": "1 поверх",   "price": 0},
      {"value": 2, "label": "2 поверхи",  "price": 15000},
      {"value": 3, "label": "3 поверхи",  "price": 35000}
    ]
  },
  {
    "id": "foundation",
    "label": "Тип фундаменту",
    "type": "radio",
    "options": [
      {"value": "tape",    "label": "Стрічковий",  "price_per_m2": 2500},
      {"value": "pile",    "label": "Пальовий",    "price_per_m2": 1800},
      {"value": "slab",    "label": "Плитний",     "price_per_m2": 4200}
    ]
  },
  {
    "id": "finishing",
    "label": "Оздоблення",
    "type": "checkbox-group",
    "options": [
      {"value": "rough",      "label": "Чорнова",         "price_per_m2": 3000},
      {"value": "prefinish",  "label": "Передчистова",    "price_per_m2": 5500},
      {"value": "finish",     "label": "Чистова",         "price_per_m2": 9000}
    ]
  }
]

JavaScript-рушій розрахунку

class PriceCalculator {
    constructor(config) {
        this.params     = config.params;
        this.formula    = config.formula;     // 'params_sum' | 'formula' | string
        this.currency   = config.currency;
        this.minPrice   = config.min_price;
        this.showRange  = config.show_range;
        this.rangePercent = config.range_percent || 15;

        this.values     = {}; // Поточні значення параметрів
        this.initDefaults();
    }

    initDefaults() {
        this.params.forEach(param => {
            if (param.default !== undefined) {
                this.values[param.id] = param.default;
            } else if (param.type === 'select' || param.type === 'radio') {
                this.values[param.id] = param.options[0]?.value;
            } else if (param.type === 'checkbox-group') {
                this.values[param.id] = [];
            }
        });
    }

    setValue(paramId, value) {
        this.values[paramId] = value;
    }

    calculate() {
        let total = 0;
        const area = parseFloat(this.values['area']) || 1;

        this.params.forEach(param => {
            const val = this.values[param.id];
            if (!val && val !== 0) return;

            switch (param.type) {
                case 'range':
                case 'number':
                    // Базова ціна за одиницю (якщо задана)
                    if (param.price_per_unit) {
                        total += parseFloat(val) * param.price_per_unit;
                    }
                    break;

                case 'select':
                case 'radio': {
                    const opt = param.options.find(o => String(o.value) === String(val));
                    if (opt) {
                        total += (opt.price || 0) + (opt.price_per_m2 || 0) * area;
                    }
                    break;
                }

                case 'checkbox-group': {
                    const selected = Array.isArray(val) ? val : [val];
                    selected.forEach(v => {
                        const opt = param.options.find(o => String(o.value) === String(v));
                        if (opt) {
                            total += (opt.price || 0) + (opt.price_per_m2 || 0) * area;
                        }
                    });
                    break;
                }
            }
        });

        if (this.minPrice && total < this.minPrice) {
            total = this.minPrice;
        }

        if (this.showRange) {
            const delta = total * (this.rangePercent / 100);
            return {
                min:   Math.floor(total - delta),
                max:   Math.ceil(total + delta),
                exact: null,
            };
        }

        return {min: null, max: null, exact: total};
    }

    formatPrice(value) {
        return new Intl.NumberFormat('uk-UA', {
            style: 'currency',
            currency: this.currency,
            maximumFractionDigits: 0,
        }).format(value);
    }
}

Інтеграція з формою заявки

Після розрахунку — кнопка «Залишити заявку» відкриває форму з попередньо заповненим полем розрахунку:

document.getElementById('btn-get-quote').addEventListener('click', () => {
    const result = calculator.calculate();
    const resultText = result.exact
        ? calculator.formatPrice(result.exact)
        : `від ${calculator.formatPrice(result.min)} до ${calculator.formatPrice(result.max)}`;

    // Заповнити приховані поля форми
    document.getElementById('form-calc-result').value = resultText;
    document.getElementById('form-calc-params').value = JSON.stringify(calculator.values);

    // Прокрутити до форми або відкрити модальне вікно
    document.getElementById('quote-form').scrollIntoView({behavior: 'smooth'});
});

Обробник на сервері зберігає параметри розрахунку в коментарі ліда:

$calcParams = json_decode($data['calc_params'] ?? '{}', true);
$paramsSummary = [];
foreach ($calcParams as $paramId => $value) {
    $paramsSummary[] = $paramId . ': ' . (is_array($value) ? implode(', ', $value) : $value);
}

$lead = new \CCrmLead(false);
$lead->Add([
    'TITLE'    => 'Розрахунок вартості — ' . $name,
    'COMMENTS' => "Результат розрахунку: {$calcResult}\n" . implode("\n", $paramsSummary),
]);

Збереження розрахунків

Корисно зберігати розрахунки для аналітики — які параметри обирають частіше, які значення призводять до заявки:

class CalculatorLeadTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'b_hl_calc_leads'; }
    // CALC_ID, PARAMS_JSON, RESULT_MIN, RESULT_MAX, RESULT_EXACT, SESSION_ID, CONVERTED (bool), CREATED_AT
}

Записувати при кожному натисканні «Розрахувати», помічати CONVERTED = true при створенні ліда. Відсоток конверсії = CONVERTED / всього записів.

Терміни розробки

Варіант Склад Термін
Простий калькулятор Фіксовані ціни, підсумок, форма 3–5 днів
Коефіцієнтний Базова ціна × коефіцієнти, діапазон 5–8 днів
З конфігуратором Управління цінами через адміністративну панель 8–14 днів