Development of a Building Materials Calculator on 1C-Bitrix
A building materials calculator is a tool that translates object parameters (area, construction type, number of rooms) into a specific list of materials with quantities and prices. For the client it answers the question "how much do I need and how much will it cost." For the store — it is a ready cart that only needs to be checked out.
Types of building materials calculators
Depending on the store's niche, the calculator computes different things:
- Brick and blocks — by wall area, accounting for wall thickness, deducting openings
- Roofing materials — roof area by slope angle, overlap, eaves
- Flooring — room area plus waste allowance for cutting (usually 5–15%)
- Paint and plaster — area, number of coats, consumption per m²
- Insulation — area, layer thickness, packaging density
Each type has its own formulas and its own complexities.
Architecture: consumption norms in the database
Material consumption norms are reference data that change when new products appear. They cannot be stored in code. HL block MaterialNorms:
| Field | Type | Description |
|---|---|---|
UF_MATERIAL_ID |
Int | Product ID in the catalog |
UF_MATERIAL_NAME |
String | Name (for display) |
UF_UNIT |
Enum | Calculation unit (m², m³, linear m) |
UF_CONSUMPTION_RATE |
Float | Consumption norm per unit |
UF_WASTE_FACTOR |
Float | Waste coefficient (1.05–1.15) |
UF_PACKAGE_SIZE |
Float | Sales unit (piece, roll, bag) |
UF_PACKAGE_UNIT |
String | Package unit |
PHP: brick laying calculation logic
namespace MyProject\Services\Calculators;
class BrickCalculator
{
// Brick consumption in pieces per m² depending on wall thickness
private const CONSUMPTION_BY_THICKNESS = [
120 => ['full' => 51, 'half' => 26], // half-brick and full-brick laying
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}, ...] — openings
int $thicknessMm, // wall thickness in mm
float $wasteFactor = 1.05 // 5% allowance
): 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);
// Convert to pallets (usually 480 pieces per pallet)
$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: universal base for different materials
class MaterialCalculator
{
public static function calculate(string $materialType, array $params): array
{
$norm = self::getNorm($materialType);
if (!$norm) {
throw new \InvalidArgumentException("Unknown material type: {$materialType}");
}
$area = $params['area'] ?? 0;
// Quantity in consumption units
$rawQuantity = $area * $norm['UF_CONSUMPTION_RATE'] * $norm['UF_WASTE_FACTOR'];
// Convert to packages (round up)
$packages = ceil($rawQuantity / $norm['UF_PACKAGE_SIZE']);
$quantity = $packages * $norm['UF_PACKAGE_SIZE'];
// Get the current price from the Bitrix catalog
$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);
}
}
Ready cart from calculation results
The key competitive advantage — a direct "add all to cart" action:
// After calculation — add all materials to the Bitrix cart
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();
}
Common pitfalls and typical errors
Units of measurement not accounted for. Consumption norm is in l/m², but the product is sold in 5-liter buckets — error in package count.
Geometry ignored. A 45° roof has an area 1.41 times larger than the horizontal projection. Failing to account for the angle causes a 41% calculation error.
No cutting waste allowance. For tiles, laminate, wallpaper — a mandatory coefficient of 1.05–1.15 is required. Without it the client has to buy more later at a different price.
Timelines
| Task | Timeline |
|---|---|
| Calculator for one material type with a request form | 4–7 days |
| Multi-material calculator with norms in an HL block and add-to-cart | 2–3 weeks |
| Full renovation calculator (multiple categories, PDF estimate, history) | 4–7 weeks |
A building materials calculator that calculates accurately and offers to add the results to the cart shortens the path from idea to purchase. The client does not leave to "calculate somewhere" — they calculate right here and place the order right here.

