Align main finance comparison with probe

This commit is contained in:
2026-05-18 21:39:10 +02:00
parent bc6bfdfa27
commit 8f1b1b88de
2 changed files with 127 additions and 24 deletions
@@ -12,7 +12,7 @@
<MudStack Row AlignItems="AlignItems.Center" Class="mb-3">
<div>
<MudText Typo="Typo.h6">@T("Net Sales Actuals 2025 Referenz", "Net sales actuals 2025 reference")</MudText>
<MudText Typo="Typo.caption">check.xlsx / Power BI Stand 29.04.2026</MudText>
<MudText Typo="Typo.caption">@T("Gleiche Berechnungslogik wie FinanceProbe/Testprogramm", "Same calculation logic as FinanceProbe/test program")</MudText>
</div>
<MudSpacer />
<MudButton Variant="Variant.Outlined" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Refresh"
@@ -23,43 +23,70 @@
<MudTable Items="_netSalesReferenceRows" Dense Hover Striped Loading="_loading">
<HeaderContent>
<MudTh>@T("Firma", "Company")</MudTh>
<MudTh>@T("Ampel", "Status")</MudTh>
<MudTh>@T("Land", "Country")</MudTh>
<MudTh>@T("Ist 2025", "Actual 2025")</MudTh>
<MudTh>@T("IC-Abzug", "IC deduction")</MudTh>
<MudTh>@T("Ist exkl. IC", "Actual excl. IC")</MudTh>
<MudTh>@T("Referenz", "Reference")</MudTh>
<MudTh>@T("Summenfeld", "Value field")</MudTh>
<MudTh>@T("Quelle", "Source")</MudTh>
<MudTh>@T("Differenz", "Difference")</MudTh>
<MudTh>@T("Diff exkl. IC", "Diff excl. IC")</MudTh>
<MudTh>@T("Waehrung", "Currency")</MudTh>
<MudTh>@T("Berechnung", "Calculation")</MudTh>
<MudTh>@T("Zeilen", "Rows")</MudTh>
<MudTh>@T("Status", "Status")</MudTh>
<MudTh>@T("Varianten", "Variants")</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Label</MudTd>
<MudTd>
<MudChip T="string" Size="Size.Small" Color="@StatusColor(context.Status)" Variant="Variant.Filled">
@StatusText(context.Status)
</MudChip>
</MudTd>
<MudTd>
<MudText Typo="Typo.body2">@context.Label</MudText>
<MudText Typo="Typo.caption">@context.Key</MudText>
</MudTd>
<MudTd>@FormatAmount(context.ActualValue)</MudTd>
<MudTd>@FormatAmount(context.IntercompanyDeduction)</MudTd>
<MudTd>@FormatAmount(context.ActualValueExcludingIntercompany)</MudTd>
<MudTd>@FormatAmount(context.ReferenceValue)</MudTd>
<MudTd>@(string.IsNullOrWhiteSpace(context.ValueField) ? "-" : context.ValueField)</MudTd>
<MudTd>@context.ReferenceSource</MudTd>
<MudTd>@FormatAmount(context.Difference)</MudTd>
<MudTd>@FormatAmount(context.DifferenceExcludingIntercompany)</MudTd>
<MudTd>@(string.IsNullOrWhiteSpace(context.Currencies) ? "-" : context.Currencies)</MudTd>
<MudTd>@FormatCurrency(context)</MudTd>
<MudTd>
<MudText Typo="Typo.body2">@(string.IsNullOrWhiteSpace(context.ValueField) ? "-" : context.ValueField)</MudText>
<MudText Typo="Typo.caption">@BuildCalculationHint(context)</MudText>
</MudTd>
<MudTd>@(context.RowCount > 0 ? context.RowCount.ToString("N0") : "-")</MudTd>
<MudTd>
@if (context.Status == "OK")
@if (context.Candidates.Count > 0)
{
<MudChip T="string" Size="Size.Small" Color="Color.Success" Variant="Variant.Filled">OK</MudChip>
}
else if (context.Status == "Pruefen")
{
<MudChip T="string" Size="Size.Small" Color="Color.Warning" Variant="Variant.Filled">@T("Pruefen", "Check")</MudChip>
<details>
<summary>@context.Candidates.Count @T("Varianten anzeigen", "show variants")</summary>
<table class="finance-variant-table">
<thead>
<tr>
<th>@T("Abgrenzung", "Scope")</th>
<th>@T("Waehrung", "Currency")</th>
<th>@T("Wert", "Value")</th>
<th>@T("Diff.", "Diff.")</th>
<th>@T("IC", "IC")</th>
<th>@T("Diff ohne IC", "Diff excl. IC")</th>
</tr>
</thead>
<tbody>
@foreach (var candidate in context.Candidates)
{
<tr class="@(candidate.IsPreferred ? "preferred-variant" : string.Empty)">
<td>@candidate.Label</td>
<td>@candidate.Currency</td>
<td class="num">@FormatAmount(candidate.Value)</td>
<td class="num">@FormatAmount(candidate.Difference)</td>
<td class="num">@FormatAmount(candidate.IntercompanyValue)</td>
<td class="num">@FormatAmount(candidate.DifferenceExcludingIntercompany)</td>
</tr>
}
</tbody>
</table>
</details>
}
else
{
<MudChip T="string" Size="Size.Small" Color="Color.Default" Variant="Variant.Outlined">@T("Keine Daten", "No data")</MudChip>
<span>-</span>
}
</MudTd>
</RowTemplate>
@@ -69,10 +96,42 @@
</MudTable>
<MudAlert Severity="Severity.Info" Dense Variant="Variant.Outlined" Class="mt-3">
@T("Vergleich: Jahr 2025 aus Buchungsdatum, sonst Invoice Date, sonst Extraction Date. Das Summenfeld wird automatisch aus Sales Price/Value, DocTotalFC - VatSumFC oder DocTotal - VatSum gewaehlt; Belegkopfwerte werden pro DocEntry nur einmal gezaehlt. IC-Abzug ist eine Diagnose fuer den aktuellen Abgleich und veraendert die Originaldaten nicht.", "Comparison: year 2025 from posting date, otherwise invoice date, otherwise extraction date. The value field is selected automatically from Sales Price/Value, DocTotalFC - VatSumFC, or DocTotal - VatSum; document header values are counted only once per DocEntry. IC deduction is a diagnostic value for the current reconciliation and does not change the original data.")
@T("Diese Seite nutzt dieselbe FinanceReconciliationService-Logik wie das lokale Testprogramm. Vergleich: Jahr 2025 aus Buchungsdatum, sonst Invoice Date, sonst Extraction Date. Das Summenfeld wird automatisch aus Sales Price/Value, DocTotalFC - VatSumFC oder DocTotal - VatSum gewaehlt; Belegkopfwerte werden pro DocEntry nur einmal gezaehlt. IC-Abzug ist eine Diagnose fuer den aktuellen Abgleich und veraendert die Originaldaten nicht.", "This page uses the same FinanceReconciliationService logic as the local test program. Comparison: year 2025 from posting date, otherwise invoice date, otherwise extraction date. The value field is selected automatically from Sales Price/Value, DocTotalFC - VatSumFC, or DocTotal - VatSum; document header values are counted only once per DocEntry. IC deduction is a diagnostic value for the current reconciliation and does not change the original data.")
</MudAlert>
</MudPaper>
<style>
.finance-variant-table {
border-collapse: collapse;
margin-top: 8px;
min-width: 720px;
font-size: 0.82rem;
}
.finance-variant-table th,
.finance-variant-table td {
border: 1px solid var(--mud-palette-lines-default);
padding: 4px 6px;
vertical-align: top;
}
.finance-variant-table th {
background: var(--mud-palette-background-grey);
font-weight: 600;
text-align: left;
}
.finance-variant-table .num {
text-align: right;
white-space: nowrap;
font-variant-numeric: tabular-nums;
}
.preferred-variant {
background: rgba(33, 150, 243, 0.08);
}
</style>
@code {
private List<NetSalesReferenceRow> _netSalesReferenceRows = new();
private bool _loading = true;
@@ -92,5 +151,43 @@
private static string FormatAmount(decimal? value)
=> value.HasValue ? value.Value.ToString("N2") : "-";
private static string FormatCurrency(NetSalesReferenceRow row)
{
if (!string.IsNullOrWhiteSpace(row.ActualCurrency))
return row.ReferenceCurrency == "LC"
? $"{row.ActualCurrency} / Soll LC"
: row.ActualCurrency;
return string.IsNullOrWhiteSpace(row.Currencies) ? "-" : row.Currencies;
}
private string BuildCalculationHint(NetSalesReferenceRow row)
{
if (row.Key.Equals("UK", StringComparison.OrdinalIgnoreCase))
return T("Sage Netto in GBP; Credit Notes negativ; Soll ist Local Currency.", "Sage net in GBP; credit notes negative; reference is local currency.");
if (row.Key.Equals("ES", StringComparison.OrdinalIgnoreCase))
return T("Sage ImporteNeto; REC/Credit Notes negativ; Zuschlaege/Nebenkosten noch pruefen.", "Sage ImporteNeto; REC/credit notes negative; surcharges/charges still to check.");
if (row.Key.Equals("IT", StringComparison.OrdinalIgnoreCase))
return T("B1 Arbeitsfilter 47005 ohne 4700504 plus provisorischer Kundenausschluss.", "B1 working filter 47005 excluding 4700504 plus provisional customer exclusions.");
if (row.Key.Equals("FR", StringComparison.OrdinalIgnoreCase) ||
row.Key.Equals("IN", StringComparison.OrdinalIgnoreCase) ||
row.Key.Equals("US", StringComparison.OrdinalIgnoreCase))
return T("Passt gegen Soll; Sales Price/Value ist bevorzugte Variante.", "Matches reference; Sales Price/Value is the preferred variant.");
return row.ReferenceCurrency == "LC"
? T("Vergleich gegen Local Currency Referenz.", "Compared against local currency reference.")
: T("Vergleich gegen Check-/Sollwert.", "Compared against check/reference value.");
}
private Color StatusColor(string status)
=> status == "OK" ? Color.Success
: status == "Pruefen" ? Color.Warning
: Color.Default;
private string StatusText(string status)
=> status == "OK" ? "OK"
: status == "Pruefen" ? T("Pruefen", "Check")
: T("Keine Daten", "No data");
private string T(string german, string english) => UiText.Text(german, english);
}
@@ -620,7 +620,7 @@ public class DatabaseSeedService : IDatabaseSeedService
new FinanceReference { Key = "CN", Label = "Trafag CN", Year = 2025 },
new FinanceReference { Key = "CZ", Label = "Trafag CZ", Year = 2025, LocalCurrencyValue = 95458782m },
new FinanceReference { Key = "DE", Label = "Trafag DE", Year = 2025, LocalCurrencyValue = 3635923m },
new FinanceReference { Key = "ES", Label = "Trafag ES", Year = 2025, LocalCurrencyValue = 3102334m },
new FinanceReference { Key = "ES", Label = "Trafag ES", Year = 2025, LocalCurrencyValue = 3102333.61m },
new FinanceReference { Key = "FR", Label = "Trafag FR", Year = 2025, LocalCurrencyValue = 1450582m, CheckValue = 1471218m },
new FinanceReference { Key = "GFS", Label = "Trafag GfS", Year = 2025, LocalCurrencyValue = 6495513m },
new FinanceReference { Key = "IN", Label = "Trafag IN", Year = 2025, LocalCurrencyValue = 747341702m, CheckValue = 750936591m },
@@ -656,6 +656,12 @@ public class DatabaseSeedService : IDatabaseSeedService
}
}
if (current.Key == "ES" && current.Year == 2025 && current.LocalCurrencyValue != 3102333.61m)
{
current.LocalCurrencyValue = 3102333.61m;
changed = true;
}
continue;
}