query("SELECT COUNT(*) as total, SUM(CASE WHEN sla_compliant=TRUE THEN 1 ELSE 0 END) as compliant FROM tasks WHERE closed_at IS NOT NULL"); $slaData = $stmt->fetch(); $slaCompliance = $slaData['total'] > 0 ? ($slaData['compliant'] / $slaData['total']) * 100 : 100; // Breach severity from incidents this period $stmt = $pdo->query("SELECT severity, COUNT(*) as cnt FROM incidents WHERE created_at > NOW() - INTERVAL '30 days' GROUP BY severity"); $breaches = ['P1' => 0, 'P2' => 0, 'P3' => 0]; while ($b = $stmt->fetch()) { $breaches[$b['severity']] = (int)$b['cnt']; } $breachSeverity = calc_breach_severity($breaches['P1'], $breaches['P2'], $breaches['P3']); $slaStability = calc_sla_stability_index($slaCompliance, $breachSeverity); // ---- 2. Revenue Stability (через коэффициент вариации MRR за 6 месяцев) ---- $mrrHistory = []; $stmt = $pdo->query("SELECT TO_CHAR(created_at, 'YYYY-MM') as ym, SUM(sla_price_monthly) as mrr FROM sla_contracts WHERE status='active' GROUP BY ym ORDER BY ym DESC LIMIT 6"); while ($m = $stmt->fetch()) { $mrrHistory[] = (float)$m->mrr; } $mrrHistory = array_reverse($mrrHistory); $currentMrr = !empty($mrrHistory) ? end($mrrHistory) : 0; $revenueStability = calc_revenue_stability_index($mrrHistory); // ---- 3. Retention ---- $stmt = $pdo->query("SELECT COUNT(*) FROM sla_contracts WHERE status='active'"); $activeSla = (int)$stmt->fetchColumn(); $stmt = $pdo->query("SELECT COUNT(DISTINCT object_id) FROM sla_contracts WHERE status IN ('active','expired','cancelled')"); $totalEver = (int)$stmt->fetchColumn(); $retention = $totalEver > 0 ? round(($activeSla / $totalEver) * 100, 2) : 100; // ---- 4. Engineer Performance ---- $stmt = $pdo->query("SELECT AVG(engineer_score) FROM engineer_kpi WHERE period_end > NOW() - INTERVAL '30 days'"); $avgEs = (float)$stmt->fetchColumn(); $engineerPerformance = min(100, $avgEs ?: 70); // ---- 5. Incident Stability (с весами severity) ---- $stmt = $pdo->query("SELECT severity, COUNT(*) as cnt FROM incidents WHERE created_at > NOW() - INTERVAL '30 days' GROUP BY severity"); $incSev = ['P1' => 0, 'P2' => 0, 'P3' => 0]; while ($i = $stmt->fetch()) { $incSev[$i['severity']] = (int)$i['cnt']; } $stmt = $pdo->query("SELECT COUNT(*) FROM objects WHERE status='active'"); $objCount = max(1, (int)$stmt->fetchColumn()); $incidentStability = calc_incident_stability_index($incSev['P1'], $incSev['P2'], $incSev['P3'], $objCount); // ---- 6. Sales Flow (аудиты → SLA конверсия) ---- $stmt = $pdo->query("SELECT COUNT(*) FROM questionnaire_sessions WHERE status='completed' AND created_at > NOW() - INTERVAL '90 days'"); $audits = (int)$stmt->fetchColumn(); $stmt = $pdo->query("SELECT COUNT(*) FROM sla_contracts WHERE created_at > NOW() - INTERVAL '90 days'"); $newSla = (int)$stmt->fetchColumn(); $salesFlow = calc_sales_flow_index($audits, $newSla); // ---- 7. Operational Efficiency (выручка / (часы × стоимость)) ---- $stmt = $pdo->query("SELECT COUNT(*) FROM tasks WHERE closed_at IS NOT NULL AND closed_at > NOW() - INTERVAL '30 days'"); $closedTasks = (int)$stmt->fetchColumn(); $engineerHours = $closedTasks * 2; // approx 2h per task $costPerHour = 1500; // руб/час $operationalEfficiency = calc_operational_efficiency_index($currentMrr, $engineerHours, $costPerHour); // ---- CEO SHS через calc_ceo_shs() ---- $ceoShsScore = calc_ceo_shs( $revenueStability, /* MRR Growth proxy */ $slaStability, /* SLA Compliance */ $retention, $engineerPerformance, /* Productivity */ $salesFlow, /* Conversion */ $incidentStability ); // ---- SHS (7-факторный) через calc_shs() ---- $shsScore = calc_shs($slaStability, $revenueStability, $retention, $engineerPerformance, $incidentStability, $salesFlow, $operationalEfficiency); $shsStatus = shs_status($shsScore); // ---- ΔSHS (дельта от предыдущей записи) ---- $prevRecord = $pdo->query("SELECT shs_score FROM shs_records ORDER BY id DESC LIMIT 1 OFFSET 1")->fetch(); $shsDelta = shs_delta($shsScore, $prevRecord ? (float)$prevRecord['shs_score'] : null); // ---- Automation Rules ---- $autoAlerts = check_automation_rules($shsScore, $slaStability, $retention); // ---- Save SHS record ---- $periodStart = date('Y-m-01'); $periodEnd = date('Y-m-t'); $stmt = $pdo->prepare("INSERT INTO shs_records (recorded_by, period_start, period_end, sla_stability, revenue_stability, retention, engineer_performance, incident_stability, sales_flow, operational_efficiency, shs_score, shs_status, components_json) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"); $stmt->execute([ $userId, $periodStart, $periodEnd, $slaStability, $revenueStability, $retention, $engineerPerformance, $incidentStability, $salesFlow, $operationalEfficiency, $shsScore, $shsStatus, json_encode([ 'sla_compliance_raw' => $slaCompliance, 'breach_severity' => $breachSeverity, 'sla_stability' => $slaStability, 'revenue_stability' => $revenueStability, 'mrr_history' => $mrrHistory, 'current_mrr' => $currentMrr, 'retention' => $retention, 'active_sla' => $activeSla, 'total_ever_sla' => $totalEver, 'engineer_perf' => $engineerPerformance, 'incident_p1' => $incSev['P1'], 'incident_p2' => $incSev['P2'], 'incident_p3' => $incSev['P3'], 'object_count' => $objCount, 'incident_stability' => $incidentStability, 'audits_90d' => $audits, 'new_sla_90d' => $newSla, 'sales_flow' => $salesFlow, 'closed_tasks_30d' => $closedTasks, 'engineer_hours' => $engineerHours, 'operational_eff' => $operationalEfficiency, 'shs_delta' => $shsDelta, 'ceo_shs_score' => $ceoShsScore, 'auto_alerts' => $autoAlerts, ]) ]); auth_log($userId, 'shs_calc', "SHS: $shsScore ($shsStatus), CEO SHS: $ceoShsScore, Δ: " . ($shsDelta['delta'] ?? 'N/A')); header('Location: ceo.php?calc_ok=1'); exit;