@page "/management-cockpit" @using TrafagSalesExporter.Models @using TrafagSalesExporter.Services @inject IManagementCockpitService CockpitService @inject ISnackbar Snackbar @inject IUiTextService UiText @T("Management Cockpit", "Management Cockpit") @T("Management Cockpit", "Management Cockpit") @foreach (var file in _files) { @file.DisplayName } @T("Dateien laden", "Load files") @(_analyzing ? T("Analysiere...", "Analyzing...") : T("Cockpit erzeugen", "Build cockpit")) @T("Zentrale Roh-Auswertung", "Central raw analysis") @T("Diese Sicht arbeitet direkt auf `CentralSalesRecords` und zeigt nur fachlich neutrale Rohkennzahlen. Kein Intercompany-Filter, keine CHF-Umrechnung, kein Budget, keine Spartenlogik.", "This view works directly on `CentralSalesRecords` and shows only neutral raw metrics. No intercompany filter, no CHF conversion, no budget, no divisional logic.") @foreach (var year in _centralYears) { @year } @foreach (var month in Enumerable.Range(1, 12)) { @($"{month:D2}") } @(_analyzingCentral ? T("Analysiere...", "Analyzing...") : T("Zentrale Auswertung laden", "Load central analysis")) @if (_result is not null) { @T("Land", "Country")@_result.Summary.Land TSC@_result.Summary.Tsc @T("Umsatz", "Sales")@_result.Summary.SalesValueTotal.ToString("N2") @T("Geschaetzte Marge", "Estimated margin")@($"{_result.Summary.EstimatedMarginPercent:F1}%") @T("Management Aussagen", "Management statements") @foreach (var finding in _result.Findings) { @finding.Title: @finding.Detail } @T("Top Kunden", "Top customers") @foreach (var item in _result.TopCustomers) { @($"{item.Label}: {item.Value:N2} ({item.SharePercent:F1}%)") } @T("Top Produktgruppen", "Top product groups") @foreach (var item in _result.TopProductGroups) { @($"{item.Label}: {item.Value:N2} ({item.SharePercent:F1}%)") } @T("Top Sales Owner", "Top sales owner") @foreach (var item in _result.TopSalesEmployees) { @($"{item.Label}: {item.Value:N2} ({item.SharePercent:F1}%)") } @T("Datenqualitaet", "Data quality") @foreach (var entry in _result.DataQualityCounts.OrderByDescending(x => x.Value)) { @($"{entry.Key}: {entry.Value}") } } @if (_centralResult is not null) { @T("Zeilen", "Rows")@_centralResult.Summary.RowCount.ToString("N0") @T("Rechnungen", "Invoices")@_centralResult.Summary.InvoiceCount.ToString("N0") @T("Standorte", "Sites")@_centralResult.Summary.SiteCount.ToString("N0") @T("Laender", "Countries")@_centralResult.Summary.CountryCount.ToString("N0") @T("Waehrungen", "Currencies")@_centralResult.Summary.CurrencyCount.ToString("N0") @T("Periode", "Period")@BuildPeriodLabel(_centralResult) @T("Hinweise", "Notes") @foreach (var notice in _centralResult.Notices) { @notice } @T("Jahresumsatz 2025/2026", "Yearly sales 2025/2026") @T("Jahr", "Year") @T("Waehrung", "Currency") @T("Umsatz", "Sales") @T("Zeilen", "Rows") @context.Year @context.Currency @context.SalesValue.ToString("N2") @context.RowCount.ToString("N0") @T("Monatsumsatz", "Monthly sales") @T("Monat", "Month") @T("Waehrung", "Currency") @T("Umsatz", "Sales") @T("Zeilen", "Rows") @context.Label @context.Currency @context.SalesValue.ToString("N2") @context.RowCount.ToString("N0") @T("Tagesumsatz im ausgewaehlten Monat", "Daily sales in selected month") @T("Tag", "Day") @T("Waehrung", "Currency") @T("Umsatz", "Sales") @T("Zeilen", "Rows") @context.Label @context.Currency @context.SalesValue.ToString("N2") @context.RowCount.ToString("N0") @T("Fuer die Tagessicht bitte zusaetzlich einen Monat waehlen.", "Please select a month as well for the daily view.") @T("Umsatz nach Quelle", "Sales by source") @T("Quelle", "Source") @T("Waehrung", "Currency") @T("Umsatz", "Sales") @T("Rechnungen", "Invoices") @context.Label @context.Currency @context.SalesValue.ToString("N2") @context.InvoiceCount.ToString("N0") @T("Umsatz nach Land", "Sales by country") @T("Land", "Country") @T("Waehrung", "Currency") @T("Umsatz", "Sales") @T("Rechnungen", "Invoices") @T("Zeilen", "Rows") @context.Label @context.Currency @context.SalesValue.ToString("N2") @context.InvoiceCount.ToString("N0") @context.RowCount.ToString("N0") } @code { private List _files = []; private List _centralYears = []; private string? _selectedFilePath; private ManagementCockpitResult? _result; private ManagementCockpitCentralResult? _centralResult; private int _selectedCentralYear; private int? _selectedCentralMonth; private bool _loadingFiles; private bool _analyzing; private bool _analyzingCentral; protected override async Task OnInitializedAsync() { await ReloadFiles(); await ReloadCentralYears(); } private async Task ReloadFiles() { _loadingFiles = true; try { _files = await CockpitService.GetAvailableFilesAsync(); _selectedFilePath ??= _files.FirstOrDefault()?.Path; } finally { _loadingFiles = false; } } private async Task ReloadCentralYears() { _centralYears = await CockpitService.GetAvailableCentralYearsAsync(); if (_selectedCentralYear == 0) _selectedCentralYear = _centralYears.LastOrDefault(); } private async Task Analyze() { if (string.IsNullOrWhiteSpace(_selectedFilePath)) return; _analyzing = true; try { _result = await CockpitService.AnalyzeAsync(_selectedFilePath); } catch (Exception ex) { Snackbar.Add(string.Format(T("Cockpit konnte nicht erzeugt werden: {0}", "Could not build cockpit: {0}"), ex.Message), Severity.Error); } finally { _analyzing = false; } } private async Task AnalyzeCentral() { if (_selectedCentralYear == 0) return; _analyzingCentral = true; try { _centralResult = await CockpitService.AnalyzeCentralAsync(_selectedCentralYear, _selectedCentralMonth); } catch (Exception ex) { Snackbar.Add(string.Format(T("Zentrale Auswertung konnte nicht erzeugt werden: {0}", "Could not build central analysis: {0}"), ex.Message), Severity.Error); } finally { _analyzingCentral = false; } } private static Severity MapSeverity(string severity) => severity switch { "Warning" => Severity.Warning, "Error" => Severity.Error, _ => Severity.Info }; private static string BuildPeriodLabel(ManagementCockpitCentralResult result) { if (result.Summary.PeriodStart is null || result.Summary.PeriodEnd is null) return "-"; return $"{result.Summary.PeriodStart.Value:dd.MM.yyyy} - {result.Summary.PeriodEnd.Value:dd.MM.yyyy}"; } } @code { private string T(string german, string english) => UiText.Text(german, english); }