CustomsCalc
Библиотека для расчёта стоимости растаможки автомобилей в Беларуси по ставкам ЕАЭС. Не знает ничего о DOM и не имеет зависимостей — подходит для любого окружения.
Установка
npm install customs-calculator
TypeScript / ESM:
import { calculate, calcDutyEur, calcUtil, Age, PersonType, EngineType, Currency } from 'customs-calculator';
CommonJS:
const { calculate, Age, EngineType } = require('customs-calculator');
CustomsCalc:<script src="https://unpkg.com/customs-calculator/dist/index.global.js"></script><script> const result = CustomsCalc.calculate({ ... }); </script>При наличии npm:
node_modules/customs-calculator/dist/index.global.js
Быстрый старт
Три шага: задайте курсы валют, опишите расходы, вызовите calculate().
import { calculate, Age, PersonType, EngineType, Currency } from 'customs-calculator';
// 1. Курсы BYN (например, от НБРБ)
const rates = { usd: 2.82, eur: 3.3 };
// 2. Фиксированные расходы — любой набор в любой валюте
const fixedCosts = [
{ id: 'delivery', amount: 1400, currency: 'EUR' },
{ id: 'warehouse', amount: 200, currency: 'BYN' },
{ id: 'epts', amount: 70, currency: 'BYN' },
];
// 3. Расчёт
const result = calculate({
age: 'under3', // возраст авто
price: 15000, // стоимость
currency: 'EUR', // валюта цены
engineType: 'fuel', // тип двигателя
volume: 2000, // объём, см³
face: 'individual', // физ. лицо
discount: false, // льгота 50%
fixedCosts,
rates,
});
console.log(result.totalEur); // итого в EUR
TypeScript с Enums
import { calculate, Age, PersonType, EngineType, Currency } from 'customs-calculator';
// те же rates и fixedCosts...
const result = calculate({
age: Age.Under3,
price: 15000,
currency: Currency.EUR,
engineType: EngineType.Fuel,
volume: 2000,
face: PersonType.Individual,
discount: false,
fixedCosts,
rates,
});
С комиссией банковского перевода
const result = calculate({
// ...остальные параметры...
commission: 1.5, // +1.5% к цене авто в totalEur
fixedCosts,
rates,
});
Прямой вызов низкоуровневых функций
import { calcDutyEur, calcUtil } from 'customs-calculator';
// Только пошлина, без остального
const duty = calcDutyEur('under3', 15000, 2000);
// Только утилизационный сбор
const util = calcUtil('individual', 'fuel', 2000, 'under3');
Типы данных
Enums
Строковые значения совместимы с обычным JS — можно передавать литералы 'under3' вместо Age.Under3.
| Enum | Значения |
|---|---|
| Age | Under3 = 'under3', From3To5 = '3to5', Over5 = 'over5' |
| PersonType | Individual = 'individual', Legal = 'legal' |
| EngineType | Fuel = 'fuel', Electric = 'electric', HybridMhev = 'hybrid_mhev', HybridHev = 'hybrid_hev', HybridPhev = 'hybrid_phev', HybridErev = 'hybrid_erev' |
| Currency | EUR = 'EUR', USD = 'USD', BYN = 'BYN' |
import { Age, PersonType, EngineType, Currency } from 'customs-calculator';
Типы двигателя
Шесть значений EngineType и то, как каждое считается:
| Значение | Что это | Пошлина | НДС физлицо | НДС юрлицо | Утильсбор (юрлицо) |
|---|---|---|---|---|---|
| 'fuel' | ДВС без электрической установки | таблицы возраст/объём | — | 20% | по объёму ДВС |
| 'hybrid_mhev' | Мягкий гибрид 48 В, электромотор не ведёт ТС сам | таблицы возраст/объём | — | 20% | по объёму ДВС |
| 'hybrid_hev' | Полный гибрид без внешней зарядки | таблицы возраст/объём | — | 20% | по объёму ДВС |
| 'hybrid_phev' | Подзаряжаемый гибрид | таблицы возраст/объём | — | 20% | по объёму ДВС |
| 'hybrid_erev' | Гибрид с генератором (range extender) | 15% от стоимости | 20% | 20% | по объёму ДВС |
| 'electric' | Только электродвигатель, без ДВС | 0 | — | — | фиксированная |
Строка «с электродвигателями» перечня ставок утильсбора распространяется только на ТС
«с электродвигателями, за исключением транспортных средств, оснащённых
различными типами гибридных силовых установок». Поэтому все гибриды, включая EREV, платят
утильсбор по строке «с объёмом двигателя» — от объёма ДВС, и для них обязательно задавать
volume. Разбор строк перечня — в разделе
ставки утилизационного сбора.
Льгота 50% по Указу №140 — только для физлиц. При face: 'legal' параметр
discount игнорируется, а не уменьшает пошлину.
'fuel', 'hybrid_mhev', 'hybrid_hev' и
'hybrid_phev' считаются одинаково, поэтому в своём интерфейсе их можно
свести в одну категорию — так сделано в демо ниже, где три кнопки вместо шести.
Отдельно стоят только 'hybrid_erev' и 'electric'.
В API типы всё равно различаются: если ставки для них разойдутся, поменяется таблица,
а не подпись функций.
Ставки утильсбора соответствуют категориям M1 и M1G и действуют с 29.04.2026 — дата
доступна как UTIL_RATES_EFFECTIVE_FROM, ссылка на источник как
UTIL_RATES_SOURCE. Категории M2/M3 и N1—N3 не реализованы.
FixedCostItem
Описывает один фиксированный расход. Передаётся в массиве fixedCosts.
| Поле | Тип | Описание |
|---|---|---|
| id | string | Произвольный идентификатор. Используется UI-слоем для привязки к элементу вывода. |
| amount | number | Сумма расхода. |
| currency | 'EUR' | 'USD' | 'BYN' | Валюта суммы. Библиотека автоматически конвертирует в EUR для итогового расчёта. |
{ id: 'delivery', amount: 1400, currency: 'EUR' }
{ id: 'warehouse', amount: 200, currency: 'BYN' }
Rates
Курсы валют — рублей (BYN) за единицу. Получаются, например, из API НБРБ.
| Поле | Тип | Описание |
|---|---|---|
| usd | number | Сколько BYN стоит 1 USD. |
| eur | number | Сколько BYN стоит 1 EUR. |
{ usd: 2.82, eur: 3.3 }
CalcResult
Объект, который возвращает calculate(). Все суммы — числа с плавающей точкой; округляйте по необходимости.
| Поле | Тип | Описание |
|---|---|---|
| priceEur | number | Стоимость авто в EUR (без комиссии). |
| priceUsd | number | Стоимость авто в USD (без комиссии). |
| dutyEur | number | Таможенная пошлина, EUR. 0 для электромобилей, 15% от стоимости для 'hybrid_erev', по таблицам возраста и объёма для остальных типов — см. типы двигателя. |
| dutyNote | string | Уточнение к пошлине отдельным полем и без оформления — скобки и прочую подачу добавляйте сами. Значения: 'электромобиль', 'гибрид PHEV', 'гибрид EREV, −50% Указ №140', '−50% Указ №140' или пустая строка. В демо ниже оно выведено слева, припиской к подписи строки «Таможенная пошлина», скобки добавлены на стороне интерфейса. |
| vatEur | number | НДС, EUR — 20% от стоимости с учётом пошлины. Когда начисляется — см. типы двигателя. Утильсбор в базу НДС не входит. |
| utilByn | number | Утилизационный сбор, BYN. Постановление №195 (апрель 2026). |
| commissionEur | number | Сумма комиссии банковского перевода в EUR. 0, если commission не задана. |
| totalEur | number | Итоговая стоимость в EUR: цена + комиссия + пошлина + НДС + все фиксированные расходы + утильсбор. |
| totalUsd | number | Итоговая стоимость в USD. |
API Reference
calculate(params)
Основная функция. Принимает все параметры сделки, возвращает полный расчёт.
calculate(params: CalculateParams): CalculateResult
Параметры
| Параметр | Тип | Описание | |
|---|---|---|---|
| age | Age | req | Возраст автомобиля. Определяет таблицу ставок пошлины и ключ утильсбора. |
| price | number | req | Стоимость авто в валюте, указанной в currency. |
| currency | Currency | req | Валюта параметра price. Регистр не важен. |
| engineType | EngineType | req | Тип двигателя — шесть значений, см. типы двигателя. |
| volume | number | req | Объём двигателя ДВС, см³. Игнорируется только для 'electric'. Для 'hybrid_erev' не влияет на пошлину, но нужен для утильсбора. |
| face | PersonType | req | Физическое ('individual') или юридическое ('legal') лицо. Влияет на таблицу утильсбора, на начисление НДС и на применимость льготы. |
| discount | boolean | opt | Таможенная льгота 50% по Указу №140. Применяется к пошлине и НДС, не к утильсбору. Игнорируется при face: 'legal' — у юридических лиц льготы нет. |
| fixedCosts | FixedCostItem[] | opt | Массив фиксированных расходов. Может быть пустым. Каждый расход конвертируется в EUR для расчёта итога. |
| rates | Rates | req | Курсы USD и EUR к BYN. Используются для конвертации цены, фиксированных расходов в BYN и утильсбора. |
| commission | number | opt | Комиссия банковского перевода, %. Прибавляется к цене в итоге: priceEur × commission / 100. На пошлину не влияет. |
totalEur = priceEur + commissionEur + dutyEur + vatEur + Σ(fixedCosts → EUR) + utilByn / rates.eur
Ставки пошлины (встроенные таблицы)
Ставки соответствуют решению Совета ЕЭК для физических лиц.
До 3 лет — MAX(% от стоимости в EUR, EUR × см³):
| До, EUR | % от цены | EUR/см³ |
|---|---|---|
| 8 500 | 54% | 2.50 |
| 16 700 | 48% | 3.50 |
| 42 300 | 48% | 5.50 |
| 84 500 | 48% | 7.50 |
| 169 000 | 48% | 15.00 |
| ∞ | 48% | 20.00 |
По этим же таблицам считаются 'hybrid_mhev', 'hybrid_hev'
и 'hybrid_phev': у них ДВС механически связан с колёсами, поэтому они попадают
в 8703 40/50/60/70 — обычный легковой автомобиль товарной позиции 8703. Сами таблицы —
единые ставки для товаров для личного пользования, Приложение 2 к Решению Совета ЕЭК
от 20.12.2017 № 107.
От 3 до 5 лет и старше 5 лет — EUR × см³ (ставка по объёму):
| До, см³ | 3–5 лет (EUR/см³) | >5 лет (EUR/см³) |
|---|---|---|
| 1 000 | 1.50 | 3.00 |
| 1 500 | 1.70 | 3.20 |
| 1 800 | 2.50 | 3.50 |
| 2 300 | 2.70 | 4.80 |
| 3 000 | 3.00 | 5.00 |
| ∞ | 3.60 | 5.70 |
Гибрид EREV ('hybrid_erev') — фиксированные ставки независимо от возраста и объёма:
| Платёж | Ставка | База |
|---|---|---|
| Таможенная пошлина | 15% | стоимость авто |
| НДС | 20% | стоимость авто + пошлина |
Льгота 50% (Указ №140), если применима, уменьшает и пошлину, и НДС вдвое. Объём двигателя в расчёте пошлины EREV не участвует, но нужен для утильсбора.
calcDutyEur(age, priceEur, volumeCc, engineType?)
Низкоуровневая функция. Вычисляет только таможенную пошлину, в отрыве от остальных расходов.
Четвёртый параметр необязателен, по умолчанию 'fuel'.
calcDutyEur(age: Age, priceEur: number, volumeCc: number, engineType?: EngineType): number
| Параметр | Тип | Описание |
|---|---|---|
| age | Age | Возраст автомобиля. |
| priceEur | number | Стоимость авто в EUR. |
| volumeCc | number | Объём двигателя, см³. |
| engineType | EngineType | Необязательный, по умолчанию 'fuel'. 'electric' → 0, 'hybrid_erev' → 15% от стоимости, остальные — по таблицам возраста и объёма. |
Возвращает: пошлину в EUR. Льгота 50% по Указу №140 здесь не применяется — её учитывает только calculate().
// BMW X5, 3.0 л, возраст 1 год, цена 50 000 EUR
calcDutyEur('under3', 50000, 3000);
// → MAX(50000 × 0.48, 3000 × 5.5) = MAX(24000, 16500) = 24000
// VW Golf, 1.6 л, возраст 4 года, цена 12 000 EUR
calcDutyEur('3to5', 12000, 1600);
// → 1600 × 2.5 = 4000
// PHEV 1.5 л, старше 5 лет — как обычный ДВС
calcDutyEur('over5', 20000, 1500, 'hybrid_phev'); // → 1500 × 3.2 = 4800
// EREV — 15% от стоимости, объём не участвует
calcDutyEur('over5', 20000, 1500, 'hybrid_erev'); // → 3000
// Электромобиль — пошлины нет
calcDutyEur('over5', 20000, 1500, 'electric'); // → 0
calcUtil(face, engineType, volumeCc, age)
Возвращает утилизационный сбор в BYN по Постановлению №195 (апрель 2026) для категорий M1 и M1G. Ставки для физических лиц зависят только от возраста; для юридических — от типа двигателя, объёма и возраста.
calcUtil(face: PersonType, engineType: EngineType, volumeCc: number, age: Age): number
| Параметр | Тип | Описание |
|---|---|---|
| face | PersonType | Физическое или юридическое лицо. |
| engineType | EngineType | Тип двигателя. Только 'electric' идёт по строке 1.1 перечня; ДВС и все четыре вида гибридов — по строке 1.2, от объёма. Разбор строк ниже. |
| volumeCc | number | Объём двигателя ДВС, см³. Игнорируется для 'electric' и для физлиц. |
| age | Age | Возраст авто. '3to5' и 'over5' попадают в группу «от 3 лет». |
Возвращает: утилизационный сбор в BYN.
Ставки утилизационного сбора
Ставки берутся из перечня видов и категорий транспортных средств, являющихся объектами обложения утилизационным сбором, а также ставок утилизационного сбора. Легковые автомобили — это раздел 1 перечня: «транспортные средства категории M1, в том числе повышенной проходимости категории M1G». Внутри раздела ровно три строки, и выбор между ними определяет всю логику функции:
| Строка перечня | Формулировка в перечне | Когда применяется |
|---|---|---|
| 1.1 | «с электродвигателями, за исключением транспортных средств, оснащенных различными типами гибридных силовых установок» | Юрлицо, 'electric' |
| 1.2 | «с объемом двигателя: …» — пять диапазонов | Юрлицо, ДВС и все четыре вида гибридов |
| 1.3 | «ввозимые (ввезенные) физическими лицами для личного пользования» | Любое физлицо, независимо от типа двигателя |
Оговорка в строке 1.1 и есть причина, по которой гибриды считаются по объёму: пункт прямо исключает ТС с гибридными силовыми установками любого типа, а строка 1.2 никаких оговорок о приводе не содержит. Отдельных строк для гибридов в перечне нет.
Строка 1.3 — физические лица, BYN
| Возраст | Сумма |
|---|---|
| До 3 лет | 624.92 |
| От 3 лет | 1 282.02 |
Строки 1.1 и 1.2 — юридические лица, BYN
| Строка | Тип | Объём, см³ | До 3 лет | От 3 лет |
|---|---|---|---|---|
| 1.1 | Электро | не важен | 1 229.28 | 2 950.38 |
| 1.2 | ДВС и гибриды | до 1 000 | 6 811.16 | 17 386.97 |
| 1.2 | ДВС и гибриды | до 2 000 | 25 226.22 | 44 374.56 |
| 1.2 | ДВС и гибриды | до 3 000 | 70 885.91 | 107 322.94 |
| 1.2 | ДВС и гибриды | до 3 500 | 81 393.68 | 124 611.62 |
| 1.2 | ДВС и гибриды | более 3 500 | 103 649.00 | 136 253.33 |
// Физлицо — строка 1.3, тип и объём не влияют
calcUtil('individual', 'fuel', 2000, 'under3'); // → 624.92
// Юрлицо, топливо 1.6 л, старше 3 лет — строка 1.2
calcUtil('legal', 'fuel', 1600, 'over5'); // → 44374.56
// Юрлицо, электромобиль до 3 лет — строка 1.1, объём не важен
calcUtil('legal', 'electric', 0, 'under3'); // → 1229.28
// Юрлицо, любой гибрид 1.5 л до 3 лет — строка 1.2, по объёму ДВС
calcUtil('legal', 'hybrid_erev', 1500, 'under3'); // → 25226.22
calcUtil('legal', 'hybrid_phev', 1500, 'under3'); // → 25226.22
Интерактивное демо
Меняйте параметры — расчёт и фрагмент кода обновляются мгновенно.
Сумма и валюта каждого расхода — как в API: { id, amount, currency }. Всё конвертируется в EUR для итога.