Проджект Эксперт - Полная финансовая модель бизнеса

Финансовая модель проекта

???? Основные показатели выручки
???? Динамика роста
// server.js - Полнофункциональный бэкенд const express = require('express'); const cors = require('cors'); const bodyParser = require('body-parser'); const fs = require('fs'); const path = require('path'); const ExcelJS = require('exceljs'); const app = express(); const PORT = process.env.PORT || 3000; // Middleware app.use(cors()); app.use(bodyParser.json({ limit: '50mb' })); app.use(express.static('public')); // Хранилище проектов const projectsDB = new Map(); const parametersDB = loadParametersDatabase(); // Загрузка базы параметров function loadParametersDatabase() { try { const data = fs.readFileSync('parameters.json', 'utf8'); return JSON.parse(data); } catch (e) { console.log('Creating new parameters database...'); return initializeParametersDB(); } } function initializeParametersDB() { // Здесь должна быть полная база из 10,000+ параметров // Для примера создаем минимальный набор return { // ... (содержимое из предыдущего примера) }; } // API Endpoints // Получение параметров по региону и отрасли app.get('/api/parameters', (req, res) => { const { region, industry } = req.query; const params = calculateRegionalParameters(region, industry); res.json({ success: true, parameters: params }); }); // Расчет проекта app.post('/api/calculate', async (req, res) => { try { const { projectId, parameters } = req.body; // Выполняем комплексные расчеты const calculations = await performAdvancedCalculations(parameters); // Анализ рисков AI const riskAnalysis = await analyzeRisks(calculations, parameters); // Генерация рекомендаций const recommendations = generateAIRecommendations(calculations, riskAnalysis); // Сохраняем проект const project = { id: projectId || 'proj_' + Date.now(), parameters, calculations, riskAnalysis, recommendations, timestamp: new Date().toISOString() }; projectsDB.set(project.id, project); res.json({ success: true, project, metrics: calculations.metrics, reports: { financial: generateFinancialReport(calculations), investment: generateInvestmentReport(calculations), risks: riskAnalysis } }); } catch (error) { console.error('Calculation error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Экспорт в Excel app.post('/api/export/excel', async (req, res) => { try { const { projectId } = req.body; const project = projectsDB.get(projectId); if (!project) { return res.status(404).json({ success: false, error: 'Project not found' }); } const workbook = await createExcelReport(project); // Сохраняем файл const filename = `project_${projectId}_${Date.now()}.xlsx`; const filepath = path.join(__dirname, 'exports', filename); await workbook.xlsx.writeFile(filepath); res.json({ success: true, filename, downloadUrl: `/exports/${filename}` }); } catch (error) { console.error('Export error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Экспорт в Project Expert формат app.post('/api/export/project-expert', (req, res) => { const { projectId } = req.body; const project = projectsDB.get(projectId); if (!project) { return res.status(404).json({ success: false, error: 'Project not found' }); } // Конвертация в XML формат Project Expert const peXml = convertToProjectExpertXML(project); res.json({ success: true, format: 'xml', data: peXml, filename: `project_${projectId}.xml` }); }); // Сохранение проекта app.post('/api/project/save', (req, res) => { const { project, userId } = req.body; try { // Сохраняем в файл const userDir = path.join(__dirname, 'projects', userId); if (!fs.existsSync(userDir)) { fs.mkdirSync(userDir, { recursive: true }); } const filename = `project_${project.id}_${Date.now()}.json`; const filepath = path.join(userDir, filename); fs.writeFileSync(filepath, JSON.stringify(project, null, 2)); res.json({ success: true, filename, saved: new Date().toISOString() }); } catch (error) { console.error('Save error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Загрузка проекта app.get('/api/project/load', (req, res) => { const { userId, projectId } = req.query; try { const userDir = path.join(__dirname, 'projects', userId); const files = fs.readdirSync(userDir); const projectFile = files.find(f => f.includes(projectId)); if (!projectFile) { return res.status(404).json({ success: false, error: 'Project not found' }); } const filepath = path.join(userDir, projectFile); const projectData = JSON.parse(fs.readFileSync(filepath, 'utf8')); res.json({ success: true, project: projectData }); } catch (error) { console.error('Load error:', error); res.status(500).json({ success: false, error: error.message }); } }); // Telegram вебхук app.post('/api/telegram/webhook', (req, res) => { const { message } = req.body; if (message && message.text) { const chatId = message.chat.id; const text = message.text.toLowerCase(); let response = ''; if (text.includes('/start')) { response = `???? Добро пожаловать в Проджект Эксперт!\n\nЯ помогу рассчитать финансовую модель вашего бизнеса.\n\nДоступные команды:\n/calculate - Новый расчет\n/templates - Шаблоны проектов\n/support - Связь с экспертом`; } else if (text.includes('расчет') || text.includes('посчитать')) { response = `Для расчета проекта перейдите на наш сайт или используйте веб-версию.\n\nСсылка: https://project-expert.ru/calculator`; } else { response = `Я передам ваш вопрос эксперту. Ожидайте ответа в течение 15 минут.\n\nТакже вы можете напрямую написать: @Dveneo`; } // Отправляем ответ в Telegram sendTelegramMessage(chatId, response); } res.json({ ok: true }); }); // Функции расчетов async function performAdvancedCalculations(parameters) { const results = {}; // 1. Расчет выручки с учетом сезонности results.revenue = calculateRevenue(parameters); // 2. Расчет себестоимости results.cost = calculateCost(parameters); // 3. Расчет OPEX results.opex = calculateOpexDetailed(parameters); // 4. Расчет налогов results.taxes = calculateTaxes(results.revenue, results.opex, parameters); // 5. Расчет денежных потоков results.cashFlow = calculateCashFlow(results, parameters); // 6. Расчет инвестиционных показателей results.metrics = calculateInvestmentMetrics(results, parameters); // 7. Анализ чувствительности results.sensitivity = analyzeSensitivity(results, parameters); return results; } function calculateRevenue(params) { const monthly = params.monthly_revenue || 1000000; const growth = params.growth_rate || 0.03; const seasonality = params.seasonality_coefficients || [1, 0.9, 0.8, 1.1, 1.2, 1.3, 1.1, 1.0, 0.9, 1.0, 1.1, 1.2]; const revenue = []; let current = monthly; for (let month = 0; month < 36; month++) { const season = seasonality[month % 12]; const monthRevenue = current * season; revenue.push(monthRevenue); // Ежеквартальный рост if ((month + 1) % 3 === 0) { current *= (1 + growth); } } return { monthly: revenue, total: revenue.reduce((a, b) => a + b, 0), average: revenue.reduce((a, b) => a + b, 0) / revenue.length, growth: growth }; } function calculateCost(params) { // Детальный расчет себестоимости const costs = { materials: params.material_cost || 0, labor: params.labor_cost || 0, energy: params.energy_cost || 0, depreciation: params.depreciation || 0, other: params.other_costs || 0 }; const total = Object.values(costs).reduce((a, b) => a + b, 0); return { ...costs, total, asPercentage: total / (params.monthly_revenue || 1000000) * 100 }; } function calculateOpexDetailed(params) { const opex = { // Персонал salaries: calculateSalaries(params), taxes: calculateSalaryTaxes(params), // Аренда rent: params.rent_office + params.rent_production + params.rent_warehouse || 0, utilities: params.utilities || 0, // Маркетинг marketing: calculateMarketingCost(params), // Административные admin: params.admin_costs || 0, professional: params.professional_fees || 0, // Прочие other: params.other_opex || 0 }; opex.total = Object.values(opex).reduce((a, b) => a + b, 0); return opex; } function calculateSalaries(params) { // Расчет фонда оплаты труда let total = 0; // Управление total += (params.ceo_salary || 0); total += (params.cto_salary || 0); total += (params.cfo_salary || 0); // Производство const workers = params.worker_count || 5; total += (params.worker_salary || 0) * workers; // Офис total += (params.manager_salary || 0) * (params.manager_count || 3); total += (params.admin_salary || 0); return total; } function calculateSalaryTaxes(params) { const salaries = calculateSalaries(params); return salaries * 0.302; // 30.2% страховые взносы } function calculateMarketingCost(params) { let total = 0; // Digital total += params.context_ads || 0; total += params.smm || 0; total += params.seo || 0; // Традиционный total += params.print_ads || 0; total += params.events || 0; // Комиссии if (params.commission_percent) { total += (params.monthly_revenue || 0) * (params.commission_percent / 100); } return total; } function calculateTaxes(revenue, opex, params) { const taxSystem = params.tax_system || 'osn'; switch(taxSystem) { case 'usn_6': // УСН 6% от доходов return revenue.total * 0.06; case 'usn_15': // УСН 15% от прибыли const profit = revenue.total - opex.total; return Math.max(profit * 0.15, revenue.total * 0.01); case 'patent': // Патент (фиксированная сумма) return params.patent_cost || 0; default: // ОСН: НДС 20% + налог на прибыль 20% const vat = revenue.total * 0.2; const profitTax = (revenue.total - opex.total) * 0.2; return vat + profitTax; } } function calculateCashFlow(results, params) { const cashFlow = []; const capex = params.capex_total || 0; for (let month = 0; month < 36; month++) { const monthly = { month: month + 1, revenue: results.revenue.monthly[month] || 0, cost: results.cost.total || 0, opex: results.opex.total / 12 || 0, taxes: results.taxes / 12 || 0, capex: month < 3 ? capex / 3 : 0 // Распределяем CAPEX на первые 3 месяца }; monthly.netCash = monthly.revenue - monthly.cost - monthly.opex - monthly.taxes - monthly.capex; monthly.cumulative = (cashFlow[month - 1]?.cumulative || 0) + monthly.netCash; cashFlow.push(monthly); } return cashFlow; } function calculateInvestmentMetrics(results, params) { const cashFlow = results.cashFlow; const capex = params.capex_total || 0; // NPV (чистая приведенная стоимость) const discountRate = 0.15; // 15% let npv = -capex; for (let i = 0; i < cashFlow.length; i++) { npv += cashFlow[i].netCash / Math.pow(1 + discountRate, (i + 1) / 12); } // IRR (методом последовательных приближений) let irr = calculateIRR(capex, cashFlow); // Срок окупаемости let paybackPeriod = null; let cumulative = 0; for (let i = 0; i < cashFlow.length; i++) { cumulative += cashFlow[i].netCash; if (cumulative >= capex && !paybackPeriod) { paybackPeriod = i + 1; // месяц break; } } // ROI const totalProfit = cashFlow.reduce((sum, month) => sum + month.netCash, 0); const roi = ((totalProfit - capex) / capex * 100).toFixed(1); // Точка безубыточности const fixedCosts = results.opex.total / 12; const contributionMargin = (results.revenue.average - results.cost.total) / results.revenue.average; const breakEvenRevenue = fixedCosts / contributionMargin; const breakEvenMonths = breakEvenRevenue / results.revenue.average; return { npv: Math.round(npv), irr: (irr * 100).toFixed(1) + '%', paybackPeriod: paybackPeriod ? paybackPeriod + ' месяцев' : 'Не окупится', roi: roi + '%', breakEven: Math.ceil(breakEvenMonths) + ' месяцев', profitIndex: (npv + capex) / capex }; } function calculateIRR(initialInvestment, cashFlows) { // Метод Ньютона для расчета IRR let irr = 0.1; // Начальное предположение 10% const maxIterations = 1000; const tolerance = 0.0001; for (let i = 0; i < maxIterations; i++) { let npv = -initialInvestment; let dnpv = 0; for (let t = 0; t < cashFlows.length; t++) { npv += cashFlows[t].netCash / Math.pow(1 + irr, (t + 1) / 12); dnpv -= (cashFlows[t].netCash * (t + 1) / 12) / Math.pow(1 + irr, (t + 1) / 12 + 1); } if (Math.abs(npv) < tolerance) { break; } irr = irr - npv / dnpv; // Ограничиваем разумными значениями if (irr < -0.9) irr = -0.9; if (irr > 5) irr = 5; } return irr; } function analyzeSensitivity(results, params) { const baseNPV = results.metrics.npv; const sensitivities = []; // Анализ чувствительности к ключевым параметрам const factors = [ { name: 'Выручка', change: -0.1 }, // -10% { name: 'Выручка', change: 0.1 }, // +10% { name: 'Затраты', change: -0.1 }, { name: 'Затраты', change: 0.1 }, { name: 'CAPEX', change: -0.1 }, { name: 'CAPEX', change: 0.1 } ]; factors.forEach(factor => { // Упрощенный расчет изменения NPV let npvChange = 0; switch(factor.name) { case 'Выручка': npvChange = baseNPV * factor.change * 1.5; break; case 'Затраты': npvChange = baseNPV * factor.change * -1.2; break; case 'CAPEX': npvChange = baseNPV * factor.change * -0.8; break; } sensitivities.push({ factor: factor.name, change: (factor.change * 100).toFixed(0) + '%', npvChange: Math.round(npvChange), newNPV: Math.round(baseNPV + npvChange) }); }); return sensitivities; } async function analyzeRisks(calculations, params) { const risks = []; // Финансовые риски if (calculations.metrics.paybackPeriod.includes('Не окупится')) { risks.push({ level: 'high', category: 'financial', description: 'Проект не окупается в течение 3 лет', probability: 0.8, impact: 'Полная потеря инвестиций', mitigation: 'Снижение CAPEX, увеличение маржи' }); } if (parseFloat(calculations.metrics.roi) < 15) { risks.push({ level: 'medium', category: 'financial', description: 'ROI ниже 15% - низкая доходность', probability: 0.6, impact: 'Низкая привлекательность для инвесторов', mitigation: 'Оптимизация операционных расходов' }); } // Операционные риски if (calculations.cost.asPercentage > 70) { risks.push({ level: 'high', category: 'operational', description: 'Высокая себестоимость (>70%)', probability: 0.7, impact: 'Низкая рентабельность', mitigation: 'Поиск новых поставщиков, оптимизация процессов' }); } // Рыночные риски if (params.competition_level === 'high') { risks.push({ level: 'medium', category: 'market', description: 'Высокий уровень конкуренции', probability: 0.5, impact: 'Сложности с привлечением клиентов', mitigation: 'Дифференциация предложения, нишевый маркетинг' }); } return risks; } function generateAIRecommendations(calculations, risks) { const recommendations = []; // Финансовые рекомендации if (parseFloat(calculations.metrics.roi) < 20) { recommendations.push({ priority: 'high', area: 'Финансы', action: 'Повысить ROI до 20%+', steps: [ 'Снизить операционные расходы на 15%', 'Увеличить средний чек на 10%', 'Оптимизировать налоговую нагрузку' ], expectedImpact: 'Рост ROI на 5-8%' }); } // Операционные рекомендации if (calculations.cost.asPercentage > 60) { recommendations.push({ priority: 'high', area: 'Операции', action: 'Снизить себестоимость', steps: [ 'Поиск альтернативных поставщиков', 'Оптимизация производственных процессов', 'Внедрение системы контроля качества' ], expectedImpact: 'Снижение себестоимости на 10-15%' }); } // Маркетинговые рекомендации if (calculations.opex.marketing / calculations.revenue.average > 0.25) { recommendations.push({ priority: 'medium', area: 'Маркетинг', action: 'Оптимизировать маркетинговые расходы', steps: [ 'Фокус на ROI-позитивные каналы', 'Внедрение CRO (Conversion Rate Optimization)', 'Развитие реферальной программы' ], expectedImpact: 'Снижение CAC на 20-30%' }); } // Если рисков много, добавляем общие рекомендации if (risks.length > 3) { recommendations.push({ priority: 'high', area: 'Управление рисками', action: 'Создать резервный фонд', steps: [ 'Резерв на 3 месяца операционных расходов', 'Страхование ключевых рисков', 'Диверсификация клиентской базы' ], expectedImpact: 'Снижение вероятности банкротства на 40%' }); } return recommendations; } // Генерация отчетов function generateFinancialReport(calculations) { return { summary: { totalRevenue: calculations.revenue.total, totalCost: calculations.cost.total * 3, // 3 года totalOpex: calculations.opex.total * 3, netProfit: calculations.revenue.total - (calculations.cost.total * 3) - (calculations.opex.total * 3) - calculations.taxes, profitability: ((calculations.revenue.total - (calculations.cost.total * 3) - (calculations.opex.total * 3) - calculations.taxes) / calculations.revenue.total * 100).toFixed(1) + '%' }, monthly: calculations.cashFlow.slice(0, 12), // Первый год metrics: calculations.metrics }; } function generateInvestmentReport(calculations) { return { investmentMetrics: calculations.metrics, sensitivityAnalysis: calculations.sensitivity, scenarios: { pessimistic: generateScenario(calculations, -0.2), base: calculations, optimistic: generateScenario(calculations, 0.2) } }; } function generateScenario(base, multiplier) { // Генерация сценария с изменением ключевых параметров return { revenue: base.revenue.total * (1 + multiplier), npv: base.metrics.npv * (1 + multiplier * 1.5), roi: (parseFloat(base.metrics.roi) * (1 + multiplier * 0.8)).toFixed(1) + '%', paybackPeriod: Math.round(parseInt(base.metrics.paybackPeriod) * (1 - multiplier * 0.3)) + ' месяцев' }; } // Создание Excel отчета async function createExcelReport(project) { const workbook = new ExcelJS.Workbook(); // Лист с основными показателями const summarySheet = workbook.addWorksheet('Сводка'); summarySheet.columns = [ { header: 'Показатель', width: 30 }, { header: 'Значение', width: 20 }, { header: 'Единица измерения', width: 20 } ]; const summaryData = [ ['Месячная выручка', project.calculations.revenue.average, 'руб'], ['Себестоимость', project.calculations.cost.total, 'руб/мес'], ['OPEX', project.calculations.opex.total, 'руб/мес'], ['Чистая прибыль', project.calculations.cashFlow[0]?.netCash || 0, 'руб/мес'], ['NPV', project.calculations.metrics.npv, 'руб'], ['IRR', project.calculations.metrics.irr, '%'], ['ROI', project.calculations.metrics.roi, '%'], ['Срок окупаемости', project.calculations.metrics.paybackPeriod, 'месяцев'] ]; summaryData.forEach(row => { summarySheet.addRow(row); }); // Лист с денежными потоками const cashFlowSheet = workbook.addWorksheet('Денежные потоки'); cashFlowSheet.columns = [ { header: 'Месяц', width: 10 }, { header: 'Выручка', width: 15 }, { header: 'Расходы', width: 15 }, { header: 'Денежный поток', width: 15 }, { header: 'Накопительный', width: 15 } ]; project.calculations.cashFlow.forEach((month, index) => { cashFlowSheet.addRow([ month.month, month.revenue, month.cost + month.opex + month.taxes + month.capex, month.netCash, month.cumulative ]); }); // Лист с рисками const risksSheet = workbook.addWorksheet('Риски'); risksSheet.columns = [ { header: 'Уровень', width: 10 }, { header: 'Категория', width: 15 }, { header: 'Описание', width: 40 }, { header: 'Вероятность', width: 15 }, { header: 'Влияние', width: 20 }, { header: 'Меры снижения', width: 40 } ]; project.riskAnalysis.forEach(risk => { risksSheet.addRow([ risk.level === 'high' ? 'Высокий' : risk.level === 'medium' ? 'Средний' : 'Низкий', risk.category, risk.description, (risk.probability * 100).toFixed(0) + '%', risk.impact, risk.mitigation ]); }); // Лист с рекомендациями const recommendationsSheet = workbook.addWorksheet('Рекомендации'); recommendationsSheet.columns = [ { header: 'Приоритет', width: 10 }, { header: 'Область', width: 15 }, { header: 'Действие', width: 30 }, { header: 'Шаги', width: 50 }, { header: 'Ожидаемый эффект', width: 30 } ]; project.recommendations.forEach(rec => { recommendationsSheet.addRow([ rec.priority === 'high' ? 'Высокий' : 'Средний', rec.area, rec.action, rec.steps.join('; '), rec.expectedImpact ]); }); return workbook; } // Конвертация в формат Project Expert function convertToProjectExpertXML(project) { return ` ${project.id} ${project.timestamp} ${Object.entries(project.parameters).map(([key, value]) => `${value}` ).join('\n ')} ${project.calculations.metrics.npv} ${project.calculations.metrics.irr} ${project.calculations.metrics.roi} ${project.calculations.cashFlow.map(month => `` ).join('\n ')} `; } // Вспомогательные функции function calculateRegionalParameters(region, industry) { // Расчет параметров с учетом региона и отрасли const base = parametersDB.base || {}; const regionalCoeff = parametersDB.regions[region]?.coefficient || 1.0; const industryCoeff = parametersDB.industries[industry]?.coefficient || 1.0; const params = {}; // Применяем коэффициенты for (const [key, value] of Object.entries(base)) { params[key] = value * regionalCoeff * industryCoeff; } return params; } function sendTelegramMessage(chatId, text) { // Реализация отправки сообщений в Telegram const token = process.env.TELEGRAM_BOT_TOKEN; if (!token) return; const url = `https://api.telegram.org/bot${token}/sendMessage`; fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: chatId, text: text, parse_mode: 'HTML' }) }).catch(console.error); } // Создание директорий function ensureDirectories() { const dirs = ['exports', 'projects', 'uploads']; dirs.forEach(dir => { const dirPath = path.join(__dirname, dir); if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } }); } // Запуск сервера ensureDirectories(); app.listen(PORT, () => { console.log(`???? Project Expert API запущен на порту ${PORT}`); console.log(`???? База параметров: ${Object.keys(parametersDB).length} категорий`); console.log(`???? Хранилище проектов: ${projectsDB.size} в памяти`); console.log(`???? Telegram бот: ${process.env.TELEGRAM_BOT_TOKEN ? 'активен' : 'не настроен'}`); });
{ "name": "project-expert", "version": "1.0.0", "description": "Professional financial modeling platform", "main": "server.js", "scripts": { "start": "node server.js", "dev": "nodemon server.js", "build": "echo 'Build complete'" }, "dependencies": { "express": "^4.18.2", "cors": "^2.8.5", "body-parser": "^1.20.2", "exceljs": "^4.4.0", "mongoose": "^7.5.0", "axios": "^1.5.0", "dotenv": "^16.3.1", "uuid": "^9.0.0", "compression": "^1.7.4", "helmet": "^7.0.0", "rate-limiter-flexible": "^2.4.2" }, "devDependencies": { "nodemon": "^3.0.1" }, "engines": { "node": ">=18.0.0" } }
# Server PORT=3000 NODE_ENV=production # Database MONGODB_URI=mongodb://localhost:27017/project_expert REDIS_URL=redis://localhost:6379 # Telegram TELEGRAM_BOT_TOKEN=your_bot_token_here TELEGRAM_CHANNEL_ID=@projectexpert_updates TELEGRAM_SUPPORT_CHAT=@Dveneo # Payments YOOKASSA_SHOP_ID=your_shop_id YOOKASSA_SECRET_KEY=your_secret_key # Email SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=your_email@gmail.com SMTP_PASS=your_app_password # Security JWT_SECRET=your_jwt_secret_key_here ENCRYPTION_KEY=your_encryption_key_here # Analytics GOOGLE_ANALYTICS_ID=UA-XXXXX-Y YANDEX_METRIKA_ID=XXXXXXXX # External APIs HH_API_KEY=your_hh_api_key CIAN_API_KEY=your_cian_api_key ROSDATA_API_KEY=your_rosdata_api_key
Contact us
Telegram