Files
2026-04-20 14:47:24 -05:00

202 lines
8.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using LCU.Shared.Collections.RepoApiLib.Formatting;
using LCU.Shared.Collections.RepoApiLib.Models.Reporting.Responses;
namespace LCU.API.Collections.RepoApi.Factories
{
public enum ReportSumType { WholeNumber, Currency, WholeNumberAvg, CurrencyAvg, PercentageAvg }
public static class ReportTableFactory
{
public static ReportTable CreateHistoricalSummationTable<T>(
ReportSumType reportType,
IEnumerable<T> dataRows,
string pluralEntityName,
DateTime lowDateTime,
DateTime highDateTime,
Func<T, decimal?> cellValue,
Func<T, string> uniqueRowDisplay,
Func<T, DateTime?> dateTimeField,
Func<T, object> rowKey,
bool showAbsenceRow = true
)
{
var totalMonths = CalculateTotalMonths(lowDateTime, highDateTime);
var rows = CreateUniqueRowNames(dataRows, uniqueRowDisplay, pluralEntityName, showAbsenceRow);
var reportTable = new ReportTable()
{
Headers = CreateMonthHeaders(lowDateTime, highDateTime, new string[] { "" }, new string[] { "Total" }),
Cells = new ReportCell[rows.Count(), totalMonths + 2]
};
// Build the Report Table Values
var uniqueRowIdentifiers = new List<object>();
var rawValueTableLengths = new int[rows.Count(), totalMonths + 1];
var rawValueTable = new decimal[rows.Count(), totalMonths + 1];
foreach (var currentDataRow in dataRows)
{
var rowDisplay = uniqueRowDisplay(currentDataRow);
var currentKey = rowKey(currentDataRow);
var currentValue = cellValue(currentDataRow);
var currentDateOfRow = dateTimeField(currentDataRow);
if (currentDateOfRow != null &&
currentValue != null &&
!uniqueRowIdentifiers.Contains(currentKey))
{
uniqueRowIdentifiers.Add(currentKey);
var monthIndex = CalculateMonthOffset(lowDateTime, currentDateOfRow.Value);
var currentItemIndex = FindUniqueRowIndex(rows, rowDisplay);
// "All Entities" Value
rawValueTable[0, monthIndex] += currentValue.Value; // Totals for Month
rawValueTable[0, totalMonths] += currentValue.Value; // Totals for All
// "All Entities" Length
rawValueTableLengths[0, monthIndex] += 1; // Totals for Month
rawValueTableLengths[0, totalMonths] += 1; // Totals for All
// Current Auction Row
if (currentItemIndex != 0)
{
rawValueTable[currentItemIndex, monthIndex] += currentValue.Value; // Total for Month
rawValueTable[currentItemIndex, totalMonths] += currentValue.Value; // Total for Auction House.
rawValueTableLengths[currentItemIndex, monthIndex] += 1; // Total for Month
rawValueTableLengths[currentItemIndex, totalMonths] += 1; // Total for Auction House.
}
}
}
// Convert Report Table into ReportCells
for (var i = 0; i < rawValueTable.GetLength(0); i++)
{
for (var j = 0; j < rawValueTable.GetLength(1); j++)
{
var rawValue = rawValueTable[i, j];
var columnIndex = j + 1; // Add 1 to compensate for Row Display Column
if (reportType == ReportSumType.WholeNumberAvg ||
reportType == ReportSumType.PercentageAvg ||
reportType == ReportSumType.CurrencyAvg)
{
var rawValueLength = rawValueTableLengths[i, j];
if (rawValueLength != 0)
{
rawValue = rawValue / rawValueLength;
}
}
switch(reportType)
{
case ReportSumType.WholeNumberAvg:
case ReportSumType.WholeNumber:
reportTable.Cells[i, columnIndex] = ReportCellFormatting.CreateIntCell(Convert.ToInt32(rawValue));
break;
case ReportSumType.Currency:
case ReportSumType.CurrencyAvg:
reportTable.Cells[i, columnIndex] = ReportCellFormatting.CreateCurrencyCell(rawValue);
break;
case ReportSumType.PercentageAvg:
reportTable.Cells[i, columnIndex] = ReportCellFormatting.CreatePercentageCell(rawValue);
break;
}
}
}
// Add Auction Names to Left Column
for (var i = 0; i < rows.Count(); i++)
{
reportTable.Cells[i, 0] = ReportCellFormatting.CreateStringCell(rows.ElementAt(i));
}
return reportTable;
}
public static int FindUniqueRowIndex(IEnumerable<string> uniqueRows, string columnName)
{
if (columnName != null)
{
foreach (var item in uniqueRows.Select((value, index) => new { index, value }))
{
if (item.value == columnName)
{
return item.index;
}
}
}
return uniqueRows.Count() - 1;
}
private static IEnumerable<string> CreateUniqueRowNames<T>(IEnumerable<T> reportData, Func<T, string> uniqueRowDisplay, string pluralEntityName, bool showAbsenceRow = true)
{
var list = new List<string>();
list.Add("All " + pluralEntityName);
if (uniqueRowDisplay != null)
{
foreach (var row in reportData)
{
var rowName = uniqueRowDisplay(row);
if (rowName != null)
{
if (!list.Contains(rowName))
{
list.Add(rowName);
}
}
}
}
if (showAbsenceRow)
{
list.Add("No " + pluralEntityName);
}
return list;
}
private static string[] CreateMonthHeaders(DateTime lowDateTime, DateTime highDateTime, string[] preHeaders = null, string[] postHeaders = null)
{
var totalMonths = CalculateTotalMonths(lowDateTime, highDateTime);
var preHeadersLength = preHeaders?.Length ?? 0;
var postHeadersLength = postHeaders?.Length ?? 0;
string[] monthHeaders = new string[totalMonths + preHeadersLength + postHeadersLength];
for (var i = 0; i < preHeadersLength; i++)
{
monthHeaders[i] = preHeaders[i];
}
for (var i = 0; i < totalMonths; i++)
{
var currentDate = lowDateTime.AddMonths(i);
monthHeaders[preHeadersLength + i] = $"{currentDate.ToString("MMM", CultureInfo.InvariantCulture)} {currentDate.Year}";
}
for (var i = 0; i < postHeadersLength; i++)
{
monthHeaders[preHeadersLength + totalMonths + i] = postHeaders[i];
}
return monthHeaders;
}
private static int CalculateTotalMonths(DateTime lowDateTime, DateTime highDateTime)
{
return CalculateMonthOffset(lowDateTime, highDateTime) + 1;
}
private static int CalculateMonthOffset(DateTime lowDateTime, DateTime highDateTime)
{
return (((highDateTime.Year - lowDateTime.Year) * 12) + highDateTime.Month - lowDateTime.Month);
}
}
}