Розробка калькулятора вартості послуг на 1С-Бітрікс
Калькулятор вартості послуг — це інструмент кваліфікації: він відповідає на питання «скільки це коштує» в момент, коли потенційний клієнт ще не готовий телефонувати, але вже готовий приймати рішення. Правильно побудований калькулятор не обіцяє точну ціну — він дає діапазон, достатній для того, щоб клієнт зрозумів, чи вкладається це в його бюджет.
Специфіка розрахунку вартості послуг
Послуги складніші за товари: у них немає фіксованої ціни. Вартість залежить від обсягу, складності, термінів, кваліфікації виконавця, регіону, сезонності. Калькулятор повинен враховувати ці змінні, не перетворюючись на нескінченну анкету.
Типові параметри для калькулятора послуг:
- Обсяг робіт — площа, кількість одиниць, кількість годин
- Тип/категорія — базовий, стандарт, преміум
- Додаткові опції — терміновість, виїзд спеціаліста, матеріали
- Географія — регіон, відстань
Кожен параметр впливає на підсумкову суму через коефіцієнт або фіксовану надбавку.
Модель даних: тарифи в HighLoad-блоці
Тарифна таблиця для калькулятора послуг зберігається в HighLoad-блоці — це продуктивніше за інфоблок і зручніше за жорстко прописані масиви:
// Отримання тарифів з HL-блоку
$hlblock = \Bitrix\Highloadblock\HighloadBlockTable::getById(SERVICES_TARIFF_HL_ID)->fetch();
$entity = \Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock);
$className = $entity->getDataClass();
$tariffs = $className::getList([
'select' => ['UF_SERVICE_TYPE', 'UF_VOLUME_FROM', 'UF_VOLUME_TO', 'UF_BASE_PRICE', 'UF_PRICE_PER_UNIT'],
'filter' => ['=UF_ACTIVE' => true],
'order' => ['UF_SERVICE_TYPE' => 'ASC', 'UF_VOLUME_FROM' => 'ASC'],
])->fetchAll();
Структура HL-таблиці:
| Поле | Тип | Призначення |
|---|---|---|
UF_SERVICE_TYPE |
Довідник | Тип послуги |
UF_VOLUME_FROM |
Float | Мінімальний обсяг |
UF_VOLUME_TO |
Float | Максимальний обсяг |
UF_BASE_PRICE |
Float | Базова вартість |
UF_PRICE_PER_UNIT |
Float | Вартість за одиницю понад базу |
UF_COMPLEXITY_COEFFICIENT |
Float | Коефіцієнт складності |
Логіка розрахунку на PHP
Сервісний клас, що інкапсулює алгоритм розрахунку:
namespace MyProject\Services;
class ServiceCostCalculator
{
private array $tariffs;
private array $options;
public function __construct(array $tariffs, array $options)
{
$this->tariffs = $tariffs;
$this->options = $options;
}
public function calculate(string $serviceType, float $volume, array $extras = []): array
{
$tariff = $this->findTariff($serviceType, $volume);
if (!$tariff) {
throw new \InvalidArgumentException("Тариф не знайдено для обсягу {$volume}");
}
$baseCost = $tariff['UF_BASE_PRICE'];
if ($volume > $tariff['UF_VOLUME_FROM']) {
$extra = $volume - $tariff['UF_VOLUME_FROM'];
$baseCost += $extra * $tariff['UF_PRICE_PER_UNIT'];
}
// Застосовуємо коефіцієнти додаткових опцій
$optionsCost = 0;
foreach ($extras as $optionKey => $enabled) {
if ($enabled && isset($this->options[$optionKey])) {
$opt = $this->options[$optionKey];
if ($opt['type'] === 'percent') {
$optionsCost += $baseCost * ($opt['value'] / 100);
} else {
$optionsCost += $opt['value'];
}
}
}
$total = $baseCost + $optionsCost;
return [
'base_cost' => round($baseCost, 2),
'options_cost' => round($optionsCost, 2),
'total_min' => round($total * 0.9, 2), // -10% — нижня межа
'total_max' => round($total * 1.15, 2), // +15% — верхня межа
'total' => round($total, 2),
'currency' => 'UAH',
];
}
private function findTariff(string $serviceType, float $volume): ?array
{
foreach ($this->tariffs as $tariff) {
if ($tariff['UF_SERVICE_TYPE'] === $serviceType
&& $volume >= $tariff['UF_VOLUME_FROM']
&& $volume <= $tariff['UF_VOLUME_TO']) {
return $tariff;
}
}
return null;
}
}
Відображення діапазону цін
Фіксована ціна для послуг часто неможлива. Калькулятор показує діапазон:
function updateResult(data) {
const formatPrice = (p) => new Intl.NumberFormat('uk-UA', {
style: 'currency',
currency: 'UAH',
maximumFractionDigits: 0,
}).format(p);
document.getElementById('result-min').textContent = formatPrice(data.total_min);
document.getElementById('result-max').textContent = formatPrice(data.total_max);
document.getElementById('result-note').textContent =
'Точна вартість визначається після огляду об\'єкта';
}
Інтеграція з CRM: передача розрахунку в угоду
Після того як користувач залишив заявку, дані розрахунку додаються в угоду або лід CRM:
// Кастомні поля ліда для зберігання параметрів розрахунку
$lead->Add([
'TITLE' => 'Розрахунок: ' . $serviceTypeName,
'OPPORTUNITY' => $calculationResult['total'],
'CURRENCY_ID' => 'UAH',
'COMMENTS' => $this->buildCommentsFromParams($params, $calculationResult),
'UF_CALC_PARAMS' => json_encode($params), // JSON параметрів
'UF_CALC_RESULT' => json_encode($calculationResult),
]);
Терміни
| Завдання | Термін |
|---|---|
| Калькулятор з 5–7 параметрами, лінійний розрахунок, форма заявки | 5–8 днів |
| Калькулятор з тарифною сіткою з HL-блоку, діапазон цін, інтеграція з CRM | 2–3 тижні |
| Мультипослуговий калькулятор з вибором послуги, складними коефіцієнтами та історією розрахунків | 4–6 тижнів |
Хороший калькулятор вартості послуг — це не обіцянка ціни, а інструмент кваліфікації бюджету. Клієнт розуміє порядок цифр і приймає рішення про наступний крок. Завдання — зробити цей крок максимально легким.







