// Данные для расчёта let calculationData = {}; // Форматирование числа в тенге function formatTenge(num) { return new Intl.NumberFormat('kk-KZ', { style: 'currency', currency: 'KZT', minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(num); } // Расчёт стоимости function calculate() { // Параметры клиента const users = parseInt(document.getElementById('users').value) || 0; const term = parseInt(document.getElementById('term').value) || 1; const serviceType = document.getElementById('serviceType').value; const minutes = parseInt(document.getElementById('minutes').value) || 0; const dataGb = parseInt(document.getElementById('dataGb').value) || 0; const addons = document.getElementById('addons').value; // Затраты компании const costMinute = parseFloat(document.getElementById('costMinute').value) || 0; const costGb = parseFloat(document.getElementById('costGb').value) || 0; const opex = parseFloat(document.getElementById('opex').value) || 0; const margin = parseFloat(document.getElementById('margin').value) || 0; let volumeDiscount = parseFloat(document.getElementById('volumeDiscount').value) || 0; let termDiscount = parseFloat(document.getElementById('termDiscount').value) || 0; // Автоматические скидки if (users >= 100) { volumeDiscount = Math.max(volumeDiscount, 10); } if (term >= 12) { termDiscount = Math.max(termDiscount, 5); } if (term >= 24) { termDiscount = Math.max(termDiscount, 10); } // Расчёт себестоимости на пользователя в месяц let serviceCost = 0; switch (serviceType) { case 'mobile': serviceCost = (minutes * costMinute) + opex; break; case 'internet': serviceCost = (dataGb * costGb) + opex; break; case 'combined': serviceCost = (minutes * costMinute) + (dataGb * costGb) + opex; break; case 'cloud': serviceCost = (dataGb * costGb * 1.5) + opex; // Облака дороже break; } // Добавочная стоимость за сервисы let addonCost = 0; switch (addons) { case 'basic': addonCost = 500; break; case 'advanced': addonCost = 1200; break; case 'premium': addonCost = 2500; break; } const totalCostPerUser = serviceCost + addonCost; // Расчёт цены с маржой const priceWithMargin = totalCostPerUser * (1 + margin / 100); // Применение скидок const totalDiscount = Math.min(volumeDiscount + termDiscount, 40); // Максимум 40% const finalPrice = priceWithMargin * (1 - totalDiscount / 100); // Данные конкурентов const competitors = [ { name: 'Kazakhtelecom', base: parseFloat(document.getElementById('comp1Base').value) || 0, biz: parseFloat(document.getElementById('comp1Biz').value) || 0, prem: parseFloat(document.getElementById('comp1Prem').value) || 0 }, { name: 'Kcell/Altel', base: parseFloat(document.getElementById('comp2Base').value) || 0, biz: parseFloat(document.getElementById('comp2Biz').value) || 0, prem: parseFloat(document.getElementById('comp2Prem').value) || 0 }, { name: 'Beeline', base: parseFloat(document.getElementById('comp3Base').value) || 0, biz: parseFloat(document.getElementById('comp3Biz').value) || 0, prem: parseFloat(document.getElementById('comp3Prem').value) || 0 }, { name: 'Tele2', base: parseFloat(document.getElementById('comp4Base').value) || 0, biz: parseFloat(document.getElementById('comp4Biz').value) || 0, prem: parseFloat(document.getElementById('comp4Prem').value) || 0 } ]; // Средние цены конкурентов const avgCompetitors = competitors.reduce((sum, c) => sum + c.biz, 0) / competitors.length; // Итого const totalMonthly = finalPrice * users; const totalContract = totalMonthly * term; // Сохранение данных calculationData = { users, term, serviceType, minutes, dataGb, addons, costMinute, costGb, opex, margin, volumeDiscount, termDiscount, totalCostPerUser, finalPrice, avgCompetitors, totalMonthly, totalContract, competitors }; // Вывод результатов document.getElementById('resultCost').textContent = formatTenge(totalCostPerUser); document.getElementById('resultPrice').textContent = formatTenge(finalPrice); document.getElementById('resultCompetitor').textContent = formatTenge(avgCompetitors); document.getElementById('resultTotal').textContent = formatTenge(totalMonthly); document.getElementById('resultContract').textContent = formatTenge(totalContract); // Конкурентное преимущество const advantage = ((avgCompetitors - finalPrice) / avgCompetitors * 100).toFixed(1); const advantageEl = document.getElementById('resultAdvantage'); if (advantage > 0) { advantageEl.textContent = `+${advantage}% дешевле конкурентов`; advantageEl.style.color = '#48bb78'; } else if (advantage < 0) { advantageEl.textContent = `${advantage}% дороже конкурентов`; advantageEl.style.color = '#f56565'; } else { advantageEl.textContent = 'На уровне рынка'; advantageEl.style.color = '#666'; } // Отрисовка сравнения renderComparison(finalPrice, competitors); // Рекомендации renderRecommendations(finalPrice, avgCompetitors, margin, totalDiscount); } // Отрисовка сравнения с конкурентами function renderComparison(ourPrice, competitors) { const container = document.getElementById('comparisonBars'); const maxValue = Math.max(ourPrice, ...competitors.map(c => c.biz)) * 1.2; let html = `
`; const compClasses = ['comp1', 'comp2', 'comp3', 'comp4']; competitors.forEach((comp, i) => { html += ` `; }); container.innerHTML = html; } // Рекомендации function renderRecommendations(price, avgCompetitorPrice, margin, discount) { const container = document.getElementById('recommendations'); const recommendations = []; if (price > avgCompetitorPrice * 1.1) { recommendations.push('Цена выше средней по рынку на 10%+. Рассмотрите возможность снижения маржинальности или увеличения скидок.'); } else if (price < avgCompetitorPrice * 0.9) { recommendations.push('Цена ниже рынка — можно увеличить маржу на 5-10% без потери конкурентоспособности.'); } else { recommendations.push('Цена находится в рыночном диапазоне — оптимально для привлечения клиентов.'); } if (margin < 15) { recommendations.push('Низкая маржинальность. Убедитесь, что операционные расходы учтены полностью.'); } else if (margin > 40) { recommendations.push('Высокая маржинальность. Проверьте, соответствует ли ценность услуги такой наценке.'); } if (discount === 0) { recommendations.push('Скидки не применяются. Рассмотрите возможность предоставления скидки за объём или срок.'); } if (discount >= 30) { recommendations.push('Высокий уровень скидок. Убедитесь, что маржинальность остаётся приемлемой.'); } const status = price <= avgCompetitorPrice ? 'Конкурентоспособно' : 'Требуется оптимизация'; const statusColor = price <= avgCompetitorPrice ? '#48bb78' : '#f56565'; container.innerHTML = `