Development of a 1C-Bitrix service calculator module

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

1C-Bitrix Service Calculator Module Development

A service calculator is a conversion tool. The user enters parameters (area, quantity, deadlines, options), receives an instant price, and submits a request. A properly built calculator increases conversion: the client understands the pricing and is not afraid of unexpected totals.

Ready-made solutions in the Bitrix marketplace are practically non-existent, or they are too simplistic. For a serious business — an insurance company, a construction contractor, a print shop — a module with a flexible formula engine and CRM integration is required.

What the Module Must Do

  • Multiple independent calculators on one site (for different services)
  • Multi-step parameter input
  • Complex formulas with conditions (if area > 100, apply 10% discount)
  • Dependent fields (selecting one field changes the list of options in another)
  • Binding to prices from the Bitrix trade catalogue (b_catalog_price)
  • Submitting the estimate to CRM as a lead or deal
  • Real-time recalculation without page reload

Data Structure

The vendor.calculator module with the following tables:

  • b_vendor_calc_calculator — calculators: id, name, slug, config (JSON fields and steps), formula (JSON computation tree), crm_target (lead/deal), is_active
  • b_vendor_calc_field — calculator fields: id, calculator_id, type, name, label, options (JSON), depends_on, validation_rules, sort
  • b_vendor_calc_result — saved estimates: id, calculator_id, session_id, user_id, params (JSON), result (JSON totals), created_at
  • b_vendor_calc_lead — link between an estimate and a CRM lead/deal: result_id, crm_type, crm_id

Field Types

Supported calculator field types:

  • number — numeric field with min/max/step
  • slider — range slider
  • select — dropdown with coefficient binding
  • checkbox — flag with an additional cost
  • radio — single-option selection
  • area — two-dimensional input (width × height)
  • catalog_product — product selection from an info block with automatic price substitution

Formula Engine

The formula is stored as a JSON structure that is interpreted both server-side (PHP) and client-side (JavaScript). Consistency is critical: the total shown in the interface must match the total recorded in CRM.

Example formula for calculating renovation work:

{
  "type": "add",
  "operands": [
    {
      "type": "multiply",
      "operands": [
        {"type": "field", "name": "area"},
        {"type": "field", "name": "work_type_price"}
      ]
    },
    {
      "type": "if",
      "condition": {"type": "gt", "left": {"type": "field", "name": "area"}, "right": 100},
      "then": {"type": "multiply", "operands": [{"type": "ref", "name": "subtotal"}, -0.1]},
      "else": 0
    }
  ]
}

The PHP interpreter FormulaEvaluator::evaluate($formula, $fieldValues) recursively traverses the tree and computes the result.

JavaScript Part

On the frontend — reactive recalculation. When any field changes:

  1. Current values of all fields are collected
  2. A local copy of the formula is evaluated in JS (same logic as PHP)
  3. The result is instantly updated in the interface
  4. Additionally: an AJAX request to the server for an accurate calculation using current prices from the database
// Recalculate on field change
document.querySelectorAll('.calc-field').forEach(field => {
    field.addEventListener('change', () => {
        const values = collectFieldValues();
        const localResult = evaluateFormula(calculatorConfig.formula, values);
        updateResultDisplay(localResult);
        debounce(() => fetchServerResult(values), 500)();
    });
});

Dependent Fields

Dependencies are described in the field configuration:

{
  "name": "material_type",
  "type": "select",
  "depends_on": {
    "field": "work_type",
    "map": {
      "painting": ["latex", "acrylic", "oil"],
      "wallpaper": ["paper", "vinyl", "non-woven"],
      "tile": ["ceramic", "porcelain", "mosaic"]
    }
  }
}

When work_type = 'painting' is selected, the material list is filtered to ["latex", "acrylic", "oil"]. The logic works on the client side and is validated on the server when the form is submitted.

CRM Submission

After the estimate is complete, the user fills in contact details and submits the request. The module creates a lead or deal:

$leadFields = [
    'TITLE'       => 'Calculator estimate: ' . $calculator['NAME'],
    'NAME'        => $formData['name'],
    'PHONE'       => [['VALUE' => $formData['phone'], 'VALUE_TYPE' => 'WORK']],
    'EMAIL'       => [['VALUE' => $formData['email'], 'VALUE_TYPE' => 'WORK']],
    'COMMENTS'    => $this->buildCalculatorComment($result),
    'UF_CALC_SUM' => $result['total'],
    'SOURCE_ID'   => 'CALCULATOR',
];

$leadId = \Bitrix\Crm\LeadTable::add($leadFields)->getId();

The estimate parameters are written to the lead comment and to the custom field UF_CALC_PARAMS (JSON).

Development Timeline

Stage Duration
Architecture, tables, installer 1 day
Field builder and configurator 2 days
Formula engine PHP + JS 3 days
Dependent fields, reactive recalculation 2 days
Catalogue price integration 1 day
CRM submission 1 day
Administrative interface 2 days
Page component 1 day

Total: 13 working days. Non-standard formulas with external reference tables (tariff grids, regional coefficients) — +2–3 days.