Developing a building materials calculator using 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages

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.