Разработка формы расчета стоимости на 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка формы расчета стоимости на 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • 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 Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка формы расчета стоимости на 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('ru-RU', {
            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 дней