Expand finance 3D indicators
This commit is contained in:
@@ -1086,10 +1086,21 @@
|
|||||||
];
|
];
|
||||||
private readonly List<Finance3dIndicatorOption> _finance3dIndicatorOptions =
|
private readonly List<Finance3dIndicatorOption> _finance3dIndicatorOptions =
|
||||||
[
|
[
|
||||||
new(Finance3dIndicators.Actual, "Net Sales Actual", "Net sales actual"),
|
new(Finance3dIndicators.Actual, "Ist Umsatz inkl. IC", "Actual sales incl. IC"),
|
||||||
|
new(Finance3dIndicators.ActualExcludingIntercompany, "Ist Umsatz ohne IC", "Actual sales excl. IC"),
|
||||||
|
new(Finance3dIndicators.IntercompanyValue, "Intercompany Wert", "Intercompany value"),
|
||||||
|
new(Finance3dIndicators.IntercompanyShare, "Intercompany Anteil %", "Intercompany share %"),
|
||||||
|
new(Finance3dIndicators.Quantity, "Menge", "Quantity"),
|
||||||
|
new(Finance3dIndicators.CreditValue, "Gutschriften Wert", "Credit-note value"),
|
||||||
|
new(Finance3dIndicators.CreditRows, "Gutschriften Zeilen", "Credit-note rows"),
|
||||||
|
new(Finance3dIndicators.TotalRows, "Alle Zeilen", "All rows"),
|
||||||
new(Finance3dIndicators.IncludedRows, "Enthaltene Zeilen", "Included rows"),
|
new(Finance3dIndicators.IncludedRows, "Enthaltene Zeilen", "Included rows"),
|
||||||
new(Finance3dIndicators.ExcludedRows, "Ausgeschlossene Zeilen", "Excluded rows"),
|
new(Finance3dIndicators.ExcludedRows, "Ausgeschlossene Zeilen", "Excluded rows"),
|
||||||
new(Finance3dIndicators.Deviation, "Soll/Ist Differenz Filterjahr", "Actual/reference difference filter year")
|
new(Finance3dIndicators.IncludeRate, "Include Quote %", "Include rate %"),
|
||||||
|
new(Finance3dIndicators.ExcludeRate, "Exclude Quote %", "Exclude rate %"),
|
||||||
|
new(Finance3dIndicators.ReferenceValue, "Sollwert Filterjahr", "Reference value filter year"),
|
||||||
|
new(Finance3dIndicators.Deviation, "Soll/Ist Differenz Filterjahr", "Actual/reference difference filter year"),
|
||||||
|
new(Finance3dIndicators.DeviationPercent, "Soll/Ist Abweichung % Filterjahr", "Actual/reference deviation % filter year")
|
||||||
];
|
];
|
||||||
private readonly List<Finance3dChartTypeOption> _finance3dChartTypeOptions =
|
private readonly List<Finance3dChartTypeOption> _finance3dChartTypeOptions =
|
||||||
[
|
[
|
||||||
@@ -1130,7 +1141,13 @@
|
|||||||
private bool _finance3dNeedsRender;
|
private bool _finance3dNeedsRender;
|
||||||
|
|
||||||
private bool ShowProductFamilyColumn => _productFinanceGroupLevel != ProductFinanceGroupLevels.Division;
|
private bool ShowProductFamilyColumn => _productFinanceGroupLevel != ProductFinanceGroupLevels.Division;
|
||||||
private bool Finance3dScenarioAffectsValue => _finance3dIndicator is Finance3dIndicators.Actual or Finance3dIndicators.Deviation;
|
private bool Finance3dScenarioAffectsValue => _finance3dIndicator is
|
||||||
|
Finance3dIndicators.Actual or
|
||||||
|
Finance3dIndicators.ActualExcludingIntercompany or
|
||||||
|
Finance3dIndicators.IntercompanyValue or
|
||||||
|
Finance3dIndicators.CreditValue or
|
||||||
|
Finance3dIndicators.ReferenceValue or
|
||||||
|
Finance3dIndicators.Deviation;
|
||||||
private decimal Finance3dBaseTotal => CalculateFinance3dBaseTotal();
|
private decimal Finance3dBaseTotal => CalculateFinance3dBaseTotal();
|
||||||
private decimal Finance3dScenarioTotal => Finance3dScenarioAffectsValue
|
private decimal Finance3dScenarioTotal => Finance3dScenarioAffectsValue
|
||||||
? Finance3dBaseTotal * (decimal)_finance3dScenarioFactor
|
? Finance3dBaseTotal * (decimal)_finance3dScenarioFactor
|
||||||
@@ -1366,14 +1383,14 @@
|
|||||||
if (_financeResult is null)
|
if (_financeResult is null)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
var deviationsByKey = _financeResult.CountryRows
|
var countryRowsByKey = _financeResult.CountryRows
|
||||||
.Where(row => row.Difference.HasValue)
|
|
||||||
.GroupBy(row => $"{row.Year}|{row.CountryKey}", StringComparer.OrdinalIgnoreCase)
|
.GroupBy(row => $"{row.Year}|{row.CountryKey}", StringComparer.OrdinalIgnoreCase)
|
||||||
.ToDictionary(
|
.ToDictionary(
|
||||||
group => group.Key,
|
group => group.Key,
|
||||||
group => group.Sum(row => Math.Abs(row.Difference!.Value)));
|
group => group.ToList(),
|
||||||
|
StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var sourceRows = _finance3dIndicator == Finance3dIndicators.Deviation
|
var sourceRows = IsFinance3dReferenceYearIndicator(_finance3dIndicator)
|
||||||
? _financeResult.Rows
|
? _financeResult.Rows
|
||||||
: (_financeResult.YearCountryRows.Count > 0 ? _financeResult.YearCountryRows : _financeResult.Rows);
|
: (_financeResult.YearCountryRows.Count > 0 ? _financeResult.YearCountryRows : _financeResult.Rows);
|
||||||
|
|
||||||
@@ -1382,14 +1399,8 @@
|
|||||||
.ThenBy(row => row.Year)
|
.ThenBy(row => row.Year)
|
||||||
.Select(row =>
|
.Select(row =>
|
||||||
{
|
{
|
||||||
deviationsByKey.TryGetValue($"{row.Year}|{row.CountryKey}", out var deviation);
|
countryRowsByKey.TryGetValue($"{row.Year}|{row.CountryKey}", out var countryRows);
|
||||||
var value = _finance3dIndicator switch
|
var value = ResolveFinance3dRowValue(row, countryRows);
|
||||||
{
|
|
||||||
Finance3dIndicators.IncludedRows => row.IncludedRows,
|
|
||||||
Finance3dIndicators.ExcludedRows => row.ExcludedRows,
|
|
||||||
Finance3dIndicators.Deviation => deviation,
|
|
||||||
_ => Math.Abs(row.NetSalesActual)
|
|
||||||
};
|
|
||||||
return new
|
return new
|
||||||
{
|
{
|
||||||
country = row.CountryKey,
|
country = row.CountryKey,
|
||||||
@@ -1407,23 +1418,67 @@
|
|||||||
if (_financeResult is null)
|
if (_financeResult is null)
|
||||||
return 0m;
|
return 0m;
|
||||||
|
|
||||||
var sourceRows = _finance3dIndicator == Finance3dIndicators.Deviation
|
var countryRowsByKey = _financeResult.CountryRows
|
||||||
|
.GroupBy(row => $"{row.Year}|{row.CountryKey}", StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToDictionary(
|
||||||
|
group => group.Key,
|
||||||
|
group => group.ToList(),
|
||||||
|
StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var sourceRows = IsFinance3dReferenceYearIndicator(_finance3dIndicator)
|
||||||
? _financeResult.Rows
|
? _financeResult.Rows
|
||||||
: (_financeResult.YearCountryRows.Count > 0 ? _financeResult.YearCountryRows : _financeResult.Rows);
|
: (_financeResult.YearCountryRows.Count > 0 ? _financeResult.YearCountryRows : _financeResult.Rows);
|
||||||
|
|
||||||
if (_finance3dIndicator == Finance3dIndicators.Deviation)
|
var values = sourceRows
|
||||||
|
.Select(row =>
|
||||||
{
|
{
|
||||||
return _financeResult.CountryRows
|
countryRowsByKey.TryGetValue($"{row.Year}|{row.CountryKey}", out var countryRows);
|
||||||
.Where(row => row.Difference.HasValue)
|
return ResolveFinance3dRowValue(row, countryRows);
|
||||||
.Sum(row => Math.Abs(row.Difference!.Value));
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (IsFinance3dPercentIndicator(_finance3dIndicator))
|
||||||
|
{
|
||||||
|
var nonZeroValues = values.Where(value => value != 0m).ToList();
|
||||||
|
return nonZeroValues.Count == 0 ? 0m : nonZeroValues.Average();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _finance3dIndicator switch
|
return values.Sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal ResolveFinance3dRowValue(ManagementFinanceSummaryRow row, IReadOnlyCollection<ManagementFinanceCountryStatusRow>? countryRows)
|
||||||
|
=> _finance3dIndicator switch
|
||||||
{
|
{
|
||||||
Finance3dIndicators.IncludedRows => sourceRows.Sum(row => row.IncludedRows),
|
Finance3dIndicators.ActualExcludingIntercompany => Math.Abs(row.NetSalesActualExcludingIntercompany),
|
||||||
Finance3dIndicators.ExcludedRows => sourceRows.Sum(row => row.ExcludedRows),
|
Finance3dIndicators.IntercompanyValue => Math.Abs(row.IntercompanyValue),
|
||||||
_ => sourceRows.Sum(row => Math.Abs(row.NetSalesActual))
|
Finance3dIndicators.IntercompanyShare => Math.Abs(row.IntercompanySharePercent),
|
||||||
|
Finance3dIndicators.Quantity => Math.Abs(row.Quantity),
|
||||||
|
Finance3dIndicators.CreditValue => Math.Abs(row.CreditValue),
|
||||||
|
Finance3dIndicators.CreditRows => row.CreditRows,
|
||||||
|
Finance3dIndicators.TotalRows => row.TotalRows,
|
||||||
|
Finance3dIndicators.IncludedRows => row.IncludedRows,
|
||||||
|
Finance3dIndicators.ExcludedRows => row.ExcludedRows,
|
||||||
|
Finance3dIndicators.IncludeRate => row.IncludeRatePercent,
|
||||||
|
Finance3dIndicators.ExcludeRate => row.ExcludeRatePercent,
|
||||||
|
Finance3dIndicators.ReferenceValue => Math.Abs(countryRows?.Sum(item => item.ReferenceValue ?? 0m) ?? 0m),
|
||||||
|
Finance3dIndicators.Deviation => Math.Abs(countryRows?.Where(item => item.Difference.HasValue).Sum(item => item.Difference!.Value) ?? 0m),
|
||||||
|
Finance3dIndicators.DeviationPercent => Math.Abs(AverageNullablePercent(countryRows?.Select(item => item.DifferencePercent))),
|
||||||
|
_ => Math.Abs(row.NetSalesActual)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static bool IsFinance3dReferenceYearIndicator(string indicator)
|
||||||
|
=> indicator is Finance3dIndicators.ReferenceValue or Finance3dIndicators.Deviation or Finance3dIndicators.DeviationPercent;
|
||||||
|
|
||||||
|
private static bool IsFinance3dPercentIndicator(string indicator)
|
||||||
|
=> indicator is Finance3dIndicators.IntercompanyShare or Finance3dIndicators.IncludeRate or Finance3dIndicators.ExcludeRate or Finance3dIndicators.DeviationPercent;
|
||||||
|
|
||||||
|
private static decimal AverageNullablePercent(IEnumerable<decimal?>? values)
|
||||||
|
{
|
||||||
|
if (values is null)
|
||||||
|
return 0m;
|
||||||
|
|
||||||
|
var actualValues = values.Where(value => value.HasValue).Select(value => value!.Value).ToList();
|
||||||
|
return actualValues.Count == 0 ? 0m : actualValues.Average();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FormatFinance3dValue(decimal value)
|
private string FormatFinance3dValue(decimal value)
|
||||||
@@ -1740,9 +1795,20 @@
|
|||||||
private static class Finance3dIndicators
|
private static class Finance3dIndicators
|
||||||
{
|
{
|
||||||
public const string Actual = "actual";
|
public const string Actual = "actual";
|
||||||
|
public const string ActualExcludingIntercompany = "actualExcludingIntercompany";
|
||||||
|
public const string IntercompanyValue = "intercompanyValue";
|
||||||
|
public const string IntercompanyShare = "intercompanyShare";
|
||||||
|
public const string Quantity = "quantity";
|
||||||
|
public const string CreditValue = "creditValue";
|
||||||
|
public const string CreditRows = "creditRows";
|
||||||
|
public const string TotalRows = "totalRows";
|
||||||
public const string IncludedRows = "includedRows";
|
public const string IncludedRows = "includedRows";
|
||||||
public const string ExcludedRows = "excludedRows";
|
public const string ExcludedRows = "excludedRows";
|
||||||
|
public const string IncludeRate = "includeRate";
|
||||||
|
public const string ExcludeRate = "excludeRate";
|
||||||
|
public const string ReferenceValue = "referenceValue";
|
||||||
public const string Deviation = "deviation";
|
public const string Deviation = "deviation";
|
||||||
|
public const string DeviationPercent = "deviationPercent";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Finance3dChartTypes
|
private static class Finance3dChartTypes
|
||||||
|
|||||||
@@ -171,15 +171,22 @@ public class ManagementFinanceSummaryRow
|
|||||||
public string Currency { get; set; } = string.Empty;
|
public string Currency { get; set; } = string.Empty;
|
||||||
public int IncludedRows { get; set; }
|
public int IncludedRows { get; set; }
|
||||||
public int ExcludedRows { get; set; }
|
public int ExcludedRows { get; set; }
|
||||||
|
public int TotalRows { get; set; }
|
||||||
public decimal NetSalesActual { get; set; }
|
public decimal NetSalesActual { get; set; }
|
||||||
|
public decimal NetSalesActualExcludingIntercompany { get; set; }
|
||||||
|
public decimal IntercompanyValue { get; set; }
|
||||||
|
public decimal IntercompanySharePercent { get; set; }
|
||||||
|
public decimal Quantity { get; set; }
|
||||||
|
public decimal CreditValue { get; set; }
|
||||||
|
public int CreditRows { get; set; }
|
||||||
|
public decimal IncludeRatePercent { get; set; }
|
||||||
|
public decimal ExcludeRatePercent { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ManagementFinanceCountryStatusRow : ManagementFinanceSummaryRow
|
public class ManagementFinanceCountryStatusRow : ManagementFinanceSummaryRow
|
||||||
{
|
{
|
||||||
public string SourceSystems { get; set; } = string.Empty;
|
public string SourceSystems { get; set; } = string.Empty;
|
||||||
public string Tscs { get; set; } = string.Empty;
|
public string Tscs { get; set; } = string.Empty;
|
||||||
public decimal IntercompanyValue { get; set; }
|
|
||||||
public decimal NetSalesActualExcludingIntercompany { get; set; }
|
|
||||||
public decimal? ReferenceValue { get; set; }
|
public decimal? ReferenceValue { get; set; }
|
||||||
public decimal? Difference { get; set; }
|
public decimal? Difference { get; set; }
|
||||||
public decimal? DifferencePercent { get; set; }
|
public decimal? DifferencePercent { get; set; }
|
||||||
|
|||||||
@@ -1045,14 +1045,31 @@ public class ManagementCockpitService : IManagementCockpitService
|
|||||||
IEnumerable<FinanceAggregationRow> rows)
|
IEnumerable<FinanceAggregationRow> rows)
|
||||||
{
|
{
|
||||||
var rowList = rows.ToList();
|
var rowList = rows.ToList();
|
||||||
|
var includedRows = rowList.Count(row => row.Include);
|
||||||
|
var excludedRows = rowList.Count(row => !row.Include);
|
||||||
|
var actual = rowList.Sum(row => row.Value);
|
||||||
|
var intercompanyValue = rowList.Where(row => row.IsIntercompany).Sum(row => row.Value);
|
||||||
|
var creditRows = rowList.Count(row => row.Value < 0m || row.RawSalesValue < 0m || LooksLikeCreditDocument(row.DocumentType, row.InvoiceNumber));
|
||||||
|
var creditValue = rowList
|
||||||
|
.Where(row => row.Value < 0m || row.RawSalesValue < 0m || LooksLikeCreditDocument(row.DocumentType, row.InvoiceNumber))
|
||||||
|
.Sum(row => Math.Abs(row.Value));
|
||||||
return new ManagementFinanceSummaryRow
|
return new ManagementFinanceSummaryRow
|
||||||
{
|
{
|
||||||
Year = year,
|
Year = year,
|
||||||
CountryKey = countryKey,
|
CountryKey = countryKey,
|
||||||
Currency = currency,
|
Currency = currency,
|
||||||
IncludedRows = rowList.Count(row => row.Include),
|
IncludedRows = includedRows,
|
||||||
ExcludedRows = rowList.Count(row => !row.Include),
|
ExcludedRows = excludedRows,
|
||||||
NetSalesActual = rowList.Sum(row => row.Value)
|
TotalRows = rowList.Count,
|
||||||
|
NetSalesActual = actual,
|
||||||
|
NetSalesActualExcludingIntercompany = actual - intercompanyValue,
|
||||||
|
IntercompanyValue = intercompanyValue,
|
||||||
|
IntercompanySharePercent = actual == 0m ? 0m : intercompanyValue / actual * 100m,
|
||||||
|
Quantity = rowList.Sum(row => row.Quantity),
|
||||||
|
CreditValue = creditValue,
|
||||||
|
CreditRows = creditRows,
|
||||||
|
IncludeRatePercent = rowList.Count == 0 ? 0m : includedRows * 100m / rowList.Count,
|
||||||
|
ExcludeRatePercent = rowList.Count == 0 ? 0m : excludedRows * 100m / rowList.Count
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ body,
|
|||||||
|
|
||||||
.finance-3d-surface {
|
.finance-3d-surface {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 560px;
|
height: calc(100vh - 260px);
|
||||||
|
min-height: 680px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #f7f9fb;
|
background: #f7f9fb;
|
||||||
}
|
}
|
||||||
@@ -50,7 +51,7 @@ body,
|
|||||||
.finance-3d-canvas {
|
.finance-3d-canvas {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 560px;
|
height: 100%;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,10 +74,7 @@ body,
|
|||||||
|
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
.finance-3d-surface {
|
.finance-3d-surface {
|
||||||
min-height: 420px;
|
height: calc(100vh - 300px);
|
||||||
}
|
min-height: 480px;
|
||||||
|
|
||||||
.finance-3d-canvas {
|
|
||||||
height: 420px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user