Разработка калькулятора стройматериалов на 1С-Битрикс
Калькулятор стройматериалов — это инструмент, который переводит параметры объекта (площадь, тип конструкции, количество комнат) в конкретный список материалов с количеством и ценой. Для клиента это ответ на вопрос «сколько мне нужно и сколько это стоит». Для магазина — готовая корзина, которую остаётся только оформить.
Типы калькуляторов стройматериалов
В зависимости от ниши магазина калькулятор считает разные вещи:
- Кирпич и блоки — по площади стены, с учётом толщины кладки, вычетом проёмов
- Кровельные материалы — площадь кровли по углу наклона, нахлёст, карнизы
- Напольные покрытия — площадь помещения + запас на подрезку (обычно 5–15%)
- Краска и штукатурка — площадь, количество слоёв, расход на м²
- Утеплитель — площадь, толщина слоя, плотность упаковки
Каждый тип имеет свои формулы и свои сложности.
Архитектура: нормы расхода в базе данных
Нормы расхода материалов — это справочные данные, которые меняются при появлении новых продуктов. Хранить их в коде нельзя. HL-блок MaterialNorms:
| Поле | Тип | Описание |
|---|---|---|
UF_MATERIAL_ID |
Int | ID товара в каталоге |
UF_MATERIAL_NAME |
String | Название (для отображения) |
UF_UNIT |
Enum | Единица расчёта (м², м³, пог.м.) |
UF_CONSUMPTION_RATE |
Float | Норма расхода на единицу |
UF_WASTE_FACTOR |
Float | Коэффициент отходов (1.05–1.15) |
UF_PACKAGE_SIZE |
Float | Единица продажи (шт., рулон, мешок) |
UF_PACKAGE_UNIT |
String | Единица упаковки |
PHP: логика расчёта кирпичной кладки
namespace MyProject\Services\Calculators;
class BrickCalculator
{
// Расход кирпича в штуках на м² в зависимости от толщины кладки
private const CONSUMPTION_BY_THICKNESS = [
120 => ['full' => 51, 'half' => 26], // кладка в полкирпича и в кирпич
250 => ['full' => 102, 'half' => 51],
380 => ['full' => 153, 'half' => 77],
510 => ['full' => 204, 'half' => 102],
];
public static function calculate(
float $wallLength,
float $wallHeight,
array $openings, // [{width, height}, ...] — проёмы
int $thicknessMm, // толщина стены в мм
float $wasteFactor = 1.05 // запас 5%
): array {
$wallArea = $wallLength * $wallHeight;
$openingsArea = array_sum(array_map(fn($o) => $o['width'] * $o['height'], $openings));
$netArea = $wallArea - $openingsArea;
$consumption = self::CONSUMPTION_BY_THICKNESS[$thicknessMm]['full'] ?? 102;
$brickCount = ceil($netArea * $consumption * $wasteFactor);
// Перевод в паллеты (обычно 480 штук на паллете)
$palletsNeeded = ceil($brickCount / 480);
return [
'wall_area' => round($netArea, 2),
'openings_area' => round($openingsArea, 2),
'brick_count' => $brickCount,
'pallets' => $palletsNeeded,
'waste_count' => ceil($netArea * $consumption * ($wasteFactor - 1)),
];
}
}
PHP: универсальная база для разных материалов
class MaterialCalculator
{
public static function calculate(string $materialType, array $params): array
{
$norm = self::getNorm($materialType);
if (!$norm) {
throw new \InvalidArgumentException("Неизвестный тип материала: {$materialType}");
}
$area = $params['area'] ?? 0;
// Количество в единицах расхода
$rawQuantity = $area * $norm['UF_CONSUMPTION_RATE'] * $norm['UF_WASTE_FACTOR'];
// Перевод в упаковки (округляем вверх)
$packages = ceil($rawQuantity / $norm['UF_PACKAGE_SIZE']);
$quantity = $packages * $norm['UF_PACKAGE_SIZE'];
// Получаем актуальную цену из каталога Битрикс
$price = self::getPrice($norm['UF_MATERIAL_ID']);
return [
'material_id' => $norm['UF_MATERIAL_ID'],
'name' => $norm['UF_MATERIAL_NAME'],
'quantity' => $quantity,
'packages' => $packages,
'package_unit' => $norm['UF_PACKAGE_UNIT'],
'price' => $price,
'total' => round($packages * $price, 2),
];
}
private static function getPrice(int $productId): float
{
$price = \CPrice::GetBasePrice($productId);
return (float)($price['PRICE'] ?? 0);
}
}
Готовая корзина из результатов расчёта
Ключевое конкурентное преимущество — прямой переход «добавить всё в корзину»:
// После расчёта — добавляем все материалы в корзину Битрикс
public function addToCart(array $calculationResult): \Bitrix\Main\Result
{
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(
\Bitrix\Sale\Fuser::getId(),
\Bitrix\Main\Context::getCurrent()->getSite()
);
foreach ($calculationResult['materials'] as $material) {
$item = $basket->createItem('catalog', $material['material_id']);
$item->setField('QUANTITY', $material['packages']);
}
return $basket->save();
}
Сложности и типичные ошибки
Не учтены единицы измерения. Норма расхода в л/м², а продаётся в ведрах по 5 литров — ошибка в расчёте пачек.
Игнорируется геометрия. Кровля 45° имеет площадь в 1.41 раза больше горизонтальной проекции. Если не учесть угол, расчёт ошибочен на 41%.
Нет запаса на подрезку. Для плитки, ламината, обоев — обязательный коэффициент 1.05–1.15. Без него клиент докупает позже по другой цене.
Сроки
| Задача | Срок |
|---|---|
| Калькулятор одного типа материала с формой заявки | 4–7 дней |
| Мультиматериальный калькулятор с нормами в HL-блоке и добавлением в корзину | 2–3 недели |
| Полный калькулятор ремонта (несколько категорий, смета PDF, история) | 4–7 недель |
Калькулятор стройматериалов, который считает точно и предлагает добавить результат в корзину, сокращает путь от задумки до покупки. Клиент не уходит «посчитать» — он считает прямо здесь и здесь же оформляет заказ.







