Add product division finance analysis
This commit is contained in:
@@ -284,6 +284,95 @@
|
|||||||
</MudTable>
|
</MudTable>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
</MudTabPanel>
|
</MudTabPanel>
|
||||||
|
<MudTabPanel Text="@T("Sparten-Finanzanalyse", "Division finance")" Icon="@Icons.Material.Filled.PieChart">
|
||||||
|
<MudGrid Class="mb-4">
|
||||||
|
<MudItem xs="12" sm="6" md="3">
|
||||||
|
<MudPaper Class="pa-4" Elevation="1">
|
||||||
|
<MudText Typo="Typo.caption">@T("Gesamtumsatz", "Total sales")</MudText>
|
||||||
|
<MudText Typo="Typo.h6">@FormatValue(_financeResult.ProductFinanceSummary.TotalValue, _financeResult.ProductFinanceSummary.DisplayCurrency)</MudText>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3">
|
||||||
|
<MudPaper Class="pa-4" Elevation="1">
|
||||||
|
<MudText Typo="Typo.caption">@T("Zugeordneter Umsatz", "Assigned sales")</MudText>
|
||||||
|
<MudText Typo="Typo.h6">@FormatValue(_financeResult.ProductFinanceSummary.AssignedValue, _financeResult.ProductFinanceSummary.DisplayCurrency)</MudText>
|
||||||
|
<MudText Typo="Typo.caption">@FormatPercent(_financeResult.ProductFinanceSummary.AssignedValuePercent)</MudText>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3">
|
||||||
|
<MudPaper Class="pa-4" Elevation="1">
|
||||||
|
<MudText Typo="Typo.caption">@T("Nicht zugeordnet", "Unassigned")</MudText>
|
||||||
|
<MudText Typo="Typo.h6">@FormatValue(_financeResult.ProductFinanceSummary.UnassignedValue, _financeResult.ProductFinanceSummary.DisplayCurrency)</MudText>
|
||||||
|
<MudText Typo="Typo.caption">@FormatPercent(_financeResult.ProductFinanceSummary.UnassignedValuePercent)</MudText>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3">
|
||||||
|
<MudPaper Class="pa-4" Elevation="1">
|
||||||
|
<MudText Typo="Typo.caption">@T("Nicht im Stamm", "Not in master")</MudText>
|
||||||
|
<MudText Typo="Typo.h6">@FormatValue(_financeResult.ProductFinanceSummary.MissingReferenceValue, _financeResult.ProductFinanceSummary.DisplayCurrency)</MudText>
|
||||||
|
<MudText Typo="Typo.caption">@FormatPercent(_financeResult.ProductFinanceSummary.MissingReferenceValuePercent)</MudText>
|
||||||
|
</MudPaper>
|
||||||
|
</MudItem>
|
||||||
|
</MudGrid>
|
||||||
|
|
||||||
|
<MudPaper Class="pa-4 mb-4" Elevation="1">
|
||||||
|
<MudText Typo="Typo.h6" Class="mb-2">@T("Umsatz nach Produktsparte", "Sales by product division")</MudText>
|
||||||
|
<MudTable Items="_financeResult.ProductDivisionFinanceRows" Dense Hover Striped>
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>@T("Produktsparte", "Product division")</MudTh>
|
||||||
|
<MudTh>@T("Produktfamilie", "Product family")</MudTh>
|
||||||
|
<MudTh>PAPH1</MudTh>
|
||||||
|
<MudTh>@T("Umsatz", "Sales")</MudTh>
|
||||||
|
<MudTh>@T("Anteil", "Share")</MudTh>
|
||||||
|
<MudTh>@T("Materialien", "Materials")</MudTh>
|
||||||
|
<MudTh>@T("Zeilen", "Rows")</MudTh>
|
||||||
|
<MudTh>@T("Laender", "Countries")</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd>@BuildCodeText(context.ProductDivisionCode, context.ProductDivisionText)</MudTd>
|
||||||
|
<MudTd>@BuildCodeText(context.ProductFamilyCode, context.ProductFamilyText)</MudTd>
|
||||||
|
<MudTd>@BuildCodeText(context.ProductHierarchyCode, context.ProductHierarchyText)</MudTd>
|
||||||
|
<MudTd>@FormatValue(context.NetSalesActual, context.Currency)</MudTd>
|
||||||
|
<MudTd>@FormatPercent(context.SharePercent)</MudTd>
|
||||||
|
<MudTd>@context.MaterialCount.ToString("N0")</MudTd>
|
||||||
|
<MudTd>@context.RowCount.ToString("N0")</MudTd>
|
||||||
|
<MudTd>@context.Countries</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<NoRecordsContent>
|
||||||
|
<MudText Typo="Typo.body2">@T("Keine zugeordneten Spartenumsaetze fuer diese Filter.", "No assigned division sales for these filters.")</MudText>
|
||||||
|
</NoRecordsContent>
|
||||||
|
</MudTable>
|
||||||
|
</MudPaper>
|
||||||
|
|
||||||
|
<MudPaper Class="pa-4" Elevation="1">
|
||||||
|
<MudText Typo="Typo.h6" Class="mb-2">@T("Umsatzabdeckung nach Land", "Sales coverage by country")</MudText>
|
||||||
|
<MudTable Items="_financeResult.ProductFinanceCountryRows" Dense Hover Striped>
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>@T("Land", "Country")</MudTh>
|
||||||
|
<MudTh>TSC</MudTh>
|
||||||
|
<MudTh>@T("Gesamt", "Total")</MudTh>
|
||||||
|
<MudTh>@T("Zugeordnet", "Assigned")</MudTh>
|
||||||
|
<MudTh>@T("Nicht zugeordnet", "Unassigned")</MudTh>
|
||||||
|
<MudTh>@T("Nicht im Stamm", "Not in master")</MudTh>
|
||||||
|
<MudTh>@T("Material fehlt", "Material missing")</MudTh>
|
||||||
|
<MudTh>@T("Abdeckung", "Coverage")</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd>@context.CountryKey</MudTd>
|
||||||
|
<MudTd>@context.Tsc</MudTd>
|
||||||
|
<MudTd>@FormatValue(context.TotalValue, context.Currency)</MudTd>
|
||||||
|
<MudTd>@FormatValue(context.AssignedValue, context.Currency)</MudTd>
|
||||||
|
<MudTd>@FormatValue(context.UnassignedValue, context.Currency)</MudTd>
|
||||||
|
<MudTd>@FormatValue(context.MissingReferenceValue, context.Currency)</MudTd>
|
||||||
|
<MudTd>@FormatValue(context.MissingMaterialValue, context.Currency)</MudTd>
|
||||||
|
<MudTd>@FormatPercent(context.AssignedValuePercent)</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
<NoRecordsContent>
|
||||||
|
<MudText Typo="Typo.body2">@T("Keine Umsatzabdeckung fuer diese Filter.", "No sales coverage for these filters.")</MudText>
|
||||||
|
</NoRecordsContent>
|
||||||
|
</MudTable>
|
||||||
|
</MudPaper>
|
||||||
|
</MudTabPanel>
|
||||||
<MudTabPanel Text="@T("Zentrale Spartenzuordnung", "Central division mapping")" Icon="@Icons.Material.Filled.AccountTree">
|
<MudTabPanel Text="@T("Zentrale Spartenzuordnung", "Central division mapping")" Icon="@Icons.Material.Filled.AccountTree">
|
||||||
<MudGrid Class="mb-4">
|
<MudGrid Class="mb-4">
|
||||||
<MudItem xs="12" sm="6" md="2">
|
<MudItem xs="12" sm="6" md="2">
|
||||||
|
|||||||
@@ -225,6 +225,48 @@ public class ManagementProductAssignmentSummary
|
|||||||
public int ReferenceMaterialCount { get; set; }
|
public int ReferenceMaterialCount { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ManagementProductFinanceSummary
|
||||||
|
{
|
||||||
|
public decimal TotalValue { get; set; }
|
||||||
|
public decimal AssignedValue { get; set; }
|
||||||
|
public decimal UnassignedValue { get; set; }
|
||||||
|
public decimal MissingReferenceValue { get; set; }
|
||||||
|
public decimal MissingMaterialValue { get; set; }
|
||||||
|
public decimal AssignedValuePercent { get; set; }
|
||||||
|
public decimal UnassignedValuePercent { get; set; }
|
||||||
|
public decimal MissingReferenceValuePercent { get; set; }
|
||||||
|
public string DisplayCurrency { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ManagementProductDivisionFinanceRow
|
||||||
|
{
|
||||||
|
public string ProductDivisionCode { get; set; } = string.Empty;
|
||||||
|
public string ProductDivisionText { get; set; } = string.Empty;
|
||||||
|
public string ProductFamilyCode { get; set; } = string.Empty;
|
||||||
|
public string ProductFamilyText { get; set; } = string.Empty;
|
||||||
|
public string ProductHierarchyCode { get; set; } = string.Empty;
|
||||||
|
public string ProductHierarchyText { get; set; } = string.Empty;
|
||||||
|
public string Currency { get; set; } = string.Empty;
|
||||||
|
public decimal NetSalesActual { get; set; }
|
||||||
|
public decimal SharePercent { get; set; }
|
||||||
|
public int MaterialCount { get; set; }
|
||||||
|
public int RowCount { get; set; }
|
||||||
|
public string Countries { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ManagementProductFinanceCountryRow
|
||||||
|
{
|
||||||
|
public string CountryKey { get; set; } = string.Empty;
|
||||||
|
public string Tsc { get; set; } = string.Empty;
|
||||||
|
public string Currency { get; set; } = string.Empty;
|
||||||
|
public decimal TotalValue { get; set; }
|
||||||
|
public decimal AssignedValue { get; set; }
|
||||||
|
public decimal UnassignedValue { get; set; }
|
||||||
|
public decimal MissingReferenceValue { get; set; }
|
||||||
|
public decimal MissingMaterialValue { get; set; }
|
||||||
|
public decimal AssignedValuePercent { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class ManagementProductAssignmentCountryRow
|
public class ManagementProductAssignmentCountryRow
|
||||||
{
|
{
|
||||||
public string CountryKey { get; set; } = string.Empty;
|
public string CountryKey { get; set; } = string.Empty;
|
||||||
@@ -278,6 +320,9 @@ public class ManagementFinanceSummaryResult
|
|||||||
public List<ManagementFinanceDataStatusRow> DataStatusRows { get; set; } = [];
|
public List<ManagementFinanceDataStatusRow> DataStatusRows { get; set; } = [];
|
||||||
public List<ManagementFinanceCreditCandidateRow> CreditCandidates { get; set; } = [];
|
public List<ManagementFinanceCreditCandidateRow> CreditCandidates { get; set; } = [];
|
||||||
public List<ManagementFinanceDataQualityRow> DataQualityRows { get; set; } = [];
|
public List<ManagementFinanceDataQualityRow> DataQualityRows { get; set; } = [];
|
||||||
|
public ManagementProductFinanceSummary ProductFinanceSummary { get; set; } = new();
|
||||||
|
public List<ManagementProductDivisionFinanceRow> ProductDivisionFinanceRows { get; set; } = [];
|
||||||
|
public List<ManagementProductFinanceCountryRow> ProductFinanceCountryRows { get; set; } = [];
|
||||||
public ManagementProductAssignmentSummary ProductAssignmentSummary { get; set; } = new();
|
public ManagementProductAssignmentSummary ProductAssignmentSummary { get; set; } = new();
|
||||||
public List<ManagementProductAssignmentCountryRow> ProductAssignmentCountryRows { get; set; } = [];
|
public List<ManagementProductAssignmentCountryRow> ProductAssignmentCountryRows { get; set; } = [];
|
||||||
public List<ManagementProductAssignmentRow> ProductAssignmentRows { get; set; } = [];
|
public List<ManagementProductAssignmentRow> ProductAssignmentRows { get; set; } = [];
|
||||||
|
|||||||
@@ -460,6 +460,7 @@ public class ManagementCockpitService : IManagementCockpitService
|
|||||||
var dataStatusRows = await BuildFinanceDataStatusRowsAsync(db);
|
var dataStatusRows = await BuildFinanceDataStatusRowsAsync(db);
|
||||||
var countryRows = BuildFinanceCountryStatusRows(scopedRows, referenceByKey);
|
var countryRows = BuildFinanceCountryStatusRows(scopedRows, referenceByKey);
|
||||||
var productAssignmentRows = BuildProductAssignmentRows(scopedRows, allRows);
|
var productAssignmentRows = BuildProductAssignmentRows(scopedRows, allRows);
|
||||||
|
var productFinanceSummary = BuildProductFinanceSummary(productAssignmentRows, resultCurrencies);
|
||||||
|
|
||||||
return new ManagementFinanceSummaryResult
|
return new ManagementFinanceSummaryResult
|
||||||
{
|
{
|
||||||
@@ -497,6 +498,9 @@ public class ManagementCockpitService : IManagementCockpitService
|
|||||||
DataStatusRows = dataStatusRows,
|
DataStatusRows = dataStatusRows,
|
||||||
CreditCandidates = BuildFinanceCreditCandidates(scopedRows),
|
CreditCandidates = BuildFinanceCreditCandidates(scopedRows),
|
||||||
DataQualityRows = BuildFinanceDataQualityRows(scopedRows),
|
DataQualityRows = BuildFinanceDataQualityRows(scopedRows),
|
||||||
|
ProductFinanceSummary = productFinanceSummary,
|
||||||
|
ProductDivisionFinanceRows = BuildProductDivisionFinanceRows(productAssignmentRows),
|
||||||
|
ProductFinanceCountryRows = BuildProductFinanceCountryRows(productAssignmentRows),
|
||||||
ProductAssignmentSummary = BuildProductAssignmentSummary(productAssignmentRows),
|
ProductAssignmentSummary = BuildProductAssignmentSummary(productAssignmentRows),
|
||||||
ProductAssignmentCountryRows = BuildProductAssignmentCountryRows(productAssignmentRows),
|
ProductAssignmentCountryRows = BuildProductAssignmentCountryRows(productAssignmentRows),
|
||||||
ProductAssignmentRows = productAssignmentRows
|
ProductAssignmentRows = productAssignmentRows
|
||||||
@@ -711,6 +715,101 @@ public class ManagementCockpitService : IManagementCockpitService
|
|||||||
.Count()
|
.Count()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static ManagementProductFinanceSummary BuildProductFinanceSummary(
|
||||||
|
IReadOnlyCollection<ManagementProductAssignmentRow> rows,
|
||||||
|
IReadOnlyCollection<string> currencies)
|
||||||
|
{
|
||||||
|
var total = rows.Sum(row => row.NetSalesActual);
|
||||||
|
var assigned = rows.Where(row => row.Status == ProductAssignmentStatuses.Assigned).Sum(row => row.NetSalesActual);
|
||||||
|
var unassigned = rows.Where(row => row.Status == ProductAssignmentStatuses.Unassigned).Sum(row => row.NetSalesActual);
|
||||||
|
var missingReference = rows.Where(row => row.Status == ProductAssignmentStatuses.NoReference).Sum(row => row.NetSalesActual);
|
||||||
|
var missingMaterial = rows.Where(row => row.Status == ProductAssignmentStatuses.MissingMaterial).Sum(row => row.NetSalesActual);
|
||||||
|
|
||||||
|
return new ManagementProductFinanceSummary
|
||||||
|
{
|
||||||
|
TotalValue = total,
|
||||||
|
AssignedValue = assigned,
|
||||||
|
UnassignedValue = unassigned,
|
||||||
|
MissingReferenceValue = missingReference,
|
||||||
|
MissingMaterialValue = missingMaterial,
|
||||||
|
AssignedValuePercent = PercentOf(assigned, total),
|
||||||
|
UnassignedValuePercent = PercentOf(unassigned, total),
|
||||||
|
MissingReferenceValuePercent = PercentOf(missingReference, total),
|
||||||
|
DisplayCurrency = BuildDisplayCurrencyLabel(currencies)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ManagementProductDivisionFinanceRow> BuildProductDivisionFinanceRows(IEnumerable<ManagementProductAssignmentRow> rows)
|
||||||
|
{
|
||||||
|
var assignedRows = rows
|
||||||
|
.Where(row => row.Status == ProductAssignmentStatuses.Assigned)
|
||||||
|
.ToList();
|
||||||
|
var totalsByCurrency = assignedRows
|
||||||
|
.GroupBy(row => row.Currency, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToDictionary(group => group.Key, group => group.Sum(row => row.NetSalesActual), StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
return assignedRows
|
||||||
|
.GroupBy(row => new
|
||||||
|
{
|
||||||
|
row.ProductDivisionCode,
|
||||||
|
row.ProductDivisionText,
|
||||||
|
row.ProductFamilyCode,
|
||||||
|
row.ProductFamilyText,
|
||||||
|
row.ProductHierarchyCode,
|
||||||
|
row.ProductHierarchyText,
|
||||||
|
row.Currency
|
||||||
|
})
|
||||||
|
.Select(group =>
|
||||||
|
{
|
||||||
|
var value = group.Sum(row => row.NetSalesActual);
|
||||||
|
totalsByCurrency.TryGetValue(group.Key.Currency, out var total);
|
||||||
|
return new ManagementProductDivisionFinanceRow
|
||||||
|
{
|
||||||
|
ProductDivisionCode = group.Key.ProductDivisionCode,
|
||||||
|
ProductDivisionText = group.Key.ProductDivisionText,
|
||||||
|
ProductFamilyCode = group.Key.ProductFamilyCode,
|
||||||
|
ProductFamilyText = group.Key.ProductFamilyText,
|
||||||
|
ProductHierarchyCode = group.Key.ProductHierarchyCode,
|
||||||
|
ProductHierarchyText = group.Key.ProductHierarchyText,
|
||||||
|
Currency = group.Key.Currency,
|
||||||
|
NetSalesActual = value,
|
||||||
|
SharePercent = PercentOf(value, total),
|
||||||
|
MaterialCount = group.Select(row => row.Material).Distinct(StringComparer.OrdinalIgnoreCase).Count(),
|
||||||
|
RowCount = group.Sum(row => row.RowCount),
|
||||||
|
Countries = JoinDistinct(group.Select(row => row.CountryKey))
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.OrderByDescending(row => Math.Abs(row.NetSalesActual))
|
||||||
|
.ThenBy(row => row.ProductDivisionCode, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ManagementProductFinanceCountryRow> BuildProductFinanceCountryRows(IEnumerable<ManagementProductAssignmentRow> rows)
|
||||||
|
=> rows
|
||||||
|
.GroupBy(row => new { row.CountryKey, row.Tsc, row.Currency })
|
||||||
|
.Select(group =>
|
||||||
|
{
|
||||||
|
var rowList = group.ToList();
|
||||||
|
var total = rowList.Sum(row => row.NetSalesActual);
|
||||||
|
var assigned = rowList.Where(row => row.Status == ProductAssignmentStatuses.Assigned).Sum(row => row.NetSalesActual);
|
||||||
|
return new ManagementProductFinanceCountryRow
|
||||||
|
{
|
||||||
|
CountryKey = group.Key.CountryKey,
|
||||||
|
Tsc = group.Key.Tsc,
|
||||||
|
Currency = group.Key.Currency,
|
||||||
|
TotalValue = total,
|
||||||
|
AssignedValue = assigned,
|
||||||
|
UnassignedValue = rowList.Where(row => row.Status == ProductAssignmentStatuses.Unassigned).Sum(row => row.NetSalesActual),
|
||||||
|
MissingReferenceValue = rowList.Where(row => row.Status == ProductAssignmentStatuses.NoReference).Sum(row => row.NetSalesActual),
|
||||||
|
MissingMaterialValue = rowList.Where(row => row.Status == ProductAssignmentStatuses.MissingMaterial).Sum(row => row.NetSalesActual),
|
||||||
|
AssignedValuePercent = PercentOf(assigned, total)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.OrderBy(row => row.CountryKey, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ThenBy(row => row.Tsc, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ThenBy(row => row.Currency, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
private static List<ManagementProductAssignmentCountryRow> BuildProductAssignmentCountryRows(IEnumerable<ManagementProductAssignmentRow> rows)
|
private static List<ManagementProductAssignmentCountryRow> BuildProductAssignmentCountryRows(IEnumerable<ManagementProductAssignmentRow> rows)
|
||||||
=> rows
|
=> rows
|
||||||
.GroupBy(row => new { row.CountryKey, row.Tsc })
|
.GroupBy(row => new { row.CountryKey, row.Tsc })
|
||||||
@@ -774,6 +873,9 @@ public class ManagementCockpitService : IManagementCockpitService
|
|||||||
private static string NormalizeMaterialKey(string value)
|
private static string NormalizeMaterialKey(string value)
|
||||||
=> string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim().ToUpperInvariant();
|
=> string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim().ToUpperInvariant();
|
||||||
|
|
||||||
|
private static decimal PercentOf(decimal value, decimal total)
|
||||||
|
=> total == 0m ? 0m : value * 100m / total;
|
||||||
|
|
||||||
private static ManagementFinanceDataQualityRow BuildQualityRow(string issue, int count, int totalRows)
|
private static ManagementFinanceDataQualityRow BuildQualityRow(string issue, int count, int totalRows)
|
||||||
{
|
{
|
||||||
var share = totalRows == 0 ? 0m : count / (decimal)totalRows;
|
var share = totalRows == 0 ? 0m : count / (decimal)totalRows;
|
||||||
|
|||||||
@@ -368,6 +368,29 @@ public class ManagementCockpitServiceTests : IDisposable
|
|||||||
row.Tsc == "TRDE" &&
|
row.Tsc == "TRDE" &&
|
||||||
row.MatchedMaterialCount == 1 &&
|
row.MatchedMaterialCount == 1 &&
|
||||||
row.UnassignedMaterialCount == 1);
|
row.UnassignedMaterialCount == 1);
|
||||||
|
|
||||||
|
Assert.Equal(260m, result.ProductFinanceSummary.TotalValue);
|
||||||
|
Assert.Equal(180m, result.ProductFinanceSummary.AssignedValue);
|
||||||
|
Assert.Equal(30m, result.ProductFinanceSummary.UnassignedValue);
|
||||||
|
Assert.Equal(50m, result.ProductFinanceSummary.MissingReferenceValue);
|
||||||
|
Assert.Equal(180m * 100m / 260m, result.ProductFinanceSummary.AssignedValuePercent);
|
||||||
|
|
||||||
|
Assert.Contains(result.ProductDivisionFinanceRows, row =>
|
||||||
|
row.ProductDivisionCode == "0001" &&
|
||||||
|
row.Currency == "EUR" &&
|
||||||
|
row.NetSalesActual == 80m &&
|
||||||
|
row.MaterialCount == 1 &&
|
||||||
|
row.Countries == "DE");
|
||||||
|
Assert.Contains(result.ProductDivisionFinanceRows, row =>
|
||||||
|
row.ProductDivisionCode == "0001" &&
|
||||||
|
row.Currency == "CHF" &&
|
||||||
|
row.NetSalesActual == 100m);
|
||||||
|
|
||||||
|
var deFinanceCoverage = Assert.Single(result.ProductFinanceCountryRows, row => row.CountryKey == "DE" && row.Tsc == "TRDE");
|
||||||
|
Assert.Equal(100m, deFinanceCoverage.TotalValue);
|
||||||
|
Assert.Equal(80m, deFinanceCoverage.AssignedValue);
|
||||||
|
Assert.Equal(20m, deFinanceCoverage.UnassignedValue);
|
||||||
|
Assert.Equal(80m, deFinanceCoverage.AssignedValuePercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SeedCentralRowsAsync(params CentralSalesRecord[] rows)
|
private async Task SeedCentralRowsAsync(params CentralSalesRecord[] rows)
|
||||||
|
|||||||
Reference in New Issue
Block a user