Development of a Credit Calculator on 1C-Bitrix
A credit calculator solves the task more simply than a mortgage one: there is no down payment, no property insurance, but it has its own specifics — types of credit products (consumer loan, car loan, cash loan), bank commissions, early repayment. For business the calculator is especially important: it helps the client understand the affordability of a purchase and eliminates the main objection "it's too expensive."
Credit product types in the calculator
| Type | Calculation specifics |
|---|---|
| Consumer loan | Annuity or differentiated, rate range by amount/term |
| Car loan | Comprehensive insurance mandatory, trade-in possible as a down payment |
| Cash loan | Minimum documentation, higher rate |
| POS loan (in-store) | Often 0% from the bank, but with a store commission |
| Targeted loan | Rate depends on product category |
Calculation formulas
Annuity payment (equal payments, standard for most loans):
function calcAnnuity(amount, annualRate, termMonths) {
if (annualRate === 0) {
return amount / termMonths;
}
const r = annualRate / 12 / 100;
return amount * r * Math.pow(1 + r, termMonths) / (Math.pow(1 + r, termMonths) - 1);
}
Differentiated payment (decreasing — first payments are higher, total overpayment is lower):
function calcDifferentiated(amount, annualRate, termMonths, monthNumber) {
const r = annualRate / 12 / 100;
const principalPart = amount / termMonths;
const remainingDebt = amount - principalPart * (monthNumber - 1);
const interestPart = remainingDebt * r;
return {
payment: principalPart + interestPart,
principal: principalPart,
interest: interestPart,
};
}
Server-side implementation in PHP
Server-side calculation is needed for validation and passing data to CRM:
namespace MyProject\Services;
class CreditCalculator
{
public static function calculate(
float $amount,
float $annualRate,
int $termMonths,
string $type = 'annuity',
float $commissionPercent = 0
): array {
$commission = $amount * ($commissionPercent / 100);
if ($type === 'annuity') {
$monthlyRate = $annualRate / 12 / 100;
if ($monthlyRate > 0) {
$payment = $amount * $monthlyRate
* pow(1 + $monthlyRate, $termMonths)
/ (pow(1 + $monthlyRate, $termMonths) - 1);
} else {
$payment = $amount / $termMonths;
}
$totalPayment = $payment * $termMonths;
$totalInterest = $totalPayment - $amount;
} else {
// Differentiated — sum all payments
$totalPayment = 0;
$totalInterest = 0;
$monthlyRate = $annualRate / 12 / 100;
$principalPart = $amount / $termMonths;
$remaining = $amount;
$maxPayment = 0;
for ($m = 1; $m <= $termMonths; $m++) {
$interestPart = $remaining * $monthlyRate;
$monthPayment = $principalPart + $interestPart;
$totalPayment += $monthPayment;
$totalInterest += $interestPart;
$remaining -= $principalPart;
$maxPayment = max($maxPayment, $monthPayment);
}
$payment = $maxPayment; // first (maximum) payment
}
return [
'amount' => $amount,
'first_payment' => round($payment, 2),
'total_payment' => round($totalPayment + $commission, 2),
'total_interest' => round($totalInterest, 2),
'commission' => round($commission, 2),
'overpayment' => round($totalInterest + $commission, 2),
'effective_rate' => self::calcEffectiveRate($amount, $payment, $termMonths),
];
}
private static function calcEffectiveRate(float $amount, float $payment, int $termMonths): float
{
// Approximation via iteration (APR — Annual Percentage Rate)
$rate = 0.01;
for ($i = 0; $i < 1000; $i++) {
$pv = $payment * (1 - pow(1 + $rate, -$termMonths)) / $rate;
if (abs($pv - $amount) < 0.01) break;
$rate += ($pv > $amount) ? 0.00001 : -0.00001;
}
return round($rate * 12 * 100, 2);
}
}
Configuring conditions via the admin interface
Credit conditions are stored in an HL block CreditConditions:
| Field | Type | Description |
|---|---|---|
UF_BANK_NAME |
String | Bank / product name |
UF_AMOUNT_FROM |
Float | Minimum amount |
UF_AMOUNT_TO |
Float | Maximum amount |
UF_TERM_FROM |
Int | Minimum term (months) |
UF_TERM_TO |
Int | Maximum term (months) |
UF_RATE |
Float | Interest rate |
UF_COMMISSION |
Float | Commission (%) |
UF_CALC_TYPE |
Enum | annuity / differentiated |
When entering an amount and term, the system automatically finds matching conditions and displays options.
Early repayment
The client asks: "If I repay part early in month three, how much will I save?" — this is a separate calculation:
public static function withEarlyRepayment(
float $loanAmount,
float $annualRate,
int $termMonths,
int $repaymentMonth,
float $repaymentAmount,
string $repaymentType = 'reduce_payment' // or 'reduce_term'
): array {
// Before early repayment
$schedule1 = self::buildSchedule($loanAmount, $annualRate, $termMonths);
// Remaining debt after N months
$remainingDebt = $schedule1[$repaymentMonth - 1]['balance'] - $repaymentAmount;
if ($repaymentType === 'reduce_term') {
// Same payment — term decreases
$newTerm = self::calcTerm($remainingDebt, $annualRate, $schedule1[0]['payment']);
$schedule2 = self::buildSchedule($remainingDebt, $annualRate, $newTerm);
} else {
// Same term — payment decreases
$newTermMonths = $termMonths - $repaymentMonth;
$schedule2 = self::buildSchedule($remainingDebt, $annualRate, $newTermMonths);
}
return [
'original_total' => array_sum(array_column($schedule1, 'interest')),
'new_total_interest' => array_sum(array_column($schedule2, 'interest')),
'savings' => /* difference */,
];
}
Timelines
| Task | Timeline |
|---|---|
| Basic calculator (annuity, request form) | 4–7 days |
| Full calculator (both payment types, multiple conditions, APR) | 2–3 weeks |
| Calculator with early repayment, offer comparison, history | 3–5 weeks |
A credit calculator lowers the entry barrier: the client sees a specific monthly payment figure and compares it to their own capabilities before even talking to a manager. Conversion to an application among visitors who used the calculator is on average 2–3 times higher.







