using System; using System.Linq; using System.Threading.Tasks; using LCU.API.Collections.RepoApi.Exceptions; using LCU.API.Collections.RepoApi.Factories; using LCU.Shared.Collections.RepoApiLib.Formatting; using LCU.Shared.Collections.RepoApiLib.Models.Reporting.Responses; using LCU.Shared.Collections.RepoApiLib.Repositories; using Serilog; namespace LCU.API.Collections.RepoApi.Services.Reporting { public class LandmarkReportingService : ILandmarkReportingService { private readonly IReportingRepository _reportingRepository; private const string RedeemedStatus = "REDEEMED"; public LandmarkReportingService(IReportingRepository reportingRepository) { _reportingRepository = reportingRepository; } public async Task GetIsActiveAccountReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetActiveAccounts(); return new ReportTableResponse() { DataTable = new DataTable() { Headers = new string[] { "Member Name", "Account No", "Status", "Days In Status", "Days Delinquent", "Last Payment Amount", "Last Payment Date", "Delinquent Amount", "Repo Type", "Balance", "Account Code", "Bankruptcy", "Collector", "Year", "Make", "Model", "Grade", "Floor Price", "Auction House", "Date Entered AutoIMS","Sold Date", "Gross % Floor", "Net % Floor", "Gross Sale Price", "Total Charges", "Repo Company", "Date Assigned", "Date Repoed", "Scheduled Sale Date" }, Rows = reportData.Select(reportRow => new RepoAccountReferenceRow() { RepoId = reportRow.RepoId, Cells = new ReportCell[] { ReportCellFormatting.CreateStringCell(reportRow.IndividualName), ReportCellFormatting.CreateStringCell(reportRow.AccountNo), ReportCellFormatting.CreateStringCell(reportRow.Status), ReportCellFormatting.CreateIntCell(reportRow.DaysInStatus), ReportCellFormatting.CreateIntCell(reportRow.DaysDelinquent), ReportCellFormatting.CreateCurrencyCell(reportRow.LastPaymentAmount), ReportCellFormatting.CreateDateCell(reportRow.LastPaymentDate), ReportCellFormatting.CreateCurrencyCell(reportRow.DelinquentAmount), ReportCellFormatting.CreateStringCell(reportRow.RepoType), ReportCellFormatting.CreateCurrencyCell(reportRow.Balance), ReportCellFormatting.CreateStringCell(reportRow.AccountTypeCode), ReportCellFormatting.CreateStringCell(reportRow.Bankruptcy), ReportCellFormatting.CreateStringCell(reportRow.Collector), ReportCellFormatting.CreateIntCell(reportRow.Year), ReportCellFormatting.CreateStringCell(reportRow.Make), ReportCellFormatting.CreateStringCell(reportRow.Model), ReportCellFormatting.CreateDecimalCell(reportRow.Grade), ReportCellFormatting.CreateCurrencyCell(reportRow.FloorPrice), ReportCellFormatting.CreateStringCell(reportRow.AuctionHouse), ReportCellFormatting.CreateDateCell(reportRow.DateEnteredAutoIMS), ReportCellFormatting.CreateDateCell(reportRow.SoldDate), ReportCellFormatting.CreatePercentageCell(reportRow.GrossPercentFloor), ReportCellFormatting.CreatePercentageCell(reportRow.NetPercentFloor), ReportCellFormatting.CreateCurrencyCell(reportRow.GrossSalePrice), ReportCellFormatting.CreateCurrencyCell(reportRow.TotalCharges), ReportCellFormatting.CreateStringCell(reportRow.RepoCompany), ReportCellFormatting.CreateDateCell(reportRow.DateAssigned), ReportCellFormatting.CreateDateCell(reportRow.DateRepoed), ReportCellFormatting.CreateDateCell(reportRow.ScheduledSaleDate) } }) } }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Is Active Account Report"); throw new ServerErrorException(); } } public async Task GetIsClosedAccountReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetClosedAccounts(lowDateTime, highDateTime); return new ReportTableResponse() { DataTable = new DataTable() { Headers = new string[] { "Member Name", "Account No", "Date Closed", "Status", "Days In Status", "Days Delinquent", "Last Payment Amount", "Last Payment Date", "Delinquent Amount", "Repo Type", "Balance", "Account Code", "Bankruptcy", "Collector", "Year", "Make", "Model", "Grade", "Floor Price", "Auction House", "Date Entered AutoIMS","Sold Date", "Gross % Floor", "Net % Floor", "Gross Sale Price", "Total Charges", "Repo Company", "Date Assigned", "Date Repoed", "Scheduled Sale Date" }, Rows = reportData.Select(reportRow => new RepoAccountReferenceRow() { RepoId = reportRow.RepoId, Cells = new ReportCell[] { ReportCellFormatting.CreateStringCell(reportRow.IndividualName), ReportCellFormatting.CreateStringCell(reportRow.AccountNo), ReportCellFormatting.CreateDateCell(reportRow.DateClosed), ReportCellFormatting.CreateStringCell(reportRow.Status), ReportCellFormatting.CreateIntCell(reportRow.DaysInStatus), ReportCellFormatting.CreateIntCell(reportRow.DaysDelinquent), ReportCellFormatting.CreateCurrencyCell(reportRow.LastPaymentAmount), ReportCellFormatting.CreateDateCell(reportRow.LastPaymentDate), ReportCellFormatting.CreateCurrencyCell(reportRow.DelinquentAmount), ReportCellFormatting.CreateStringCell(reportRow.RepoType), ReportCellFormatting.CreateCurrencyCell(reportRow.Balance), ReportCellFormatting.CreateStringCell(reportRow.AccountTypeCode), ReportCellFormatting.CreateStringCell(reportRow.Bankruptcy), ReportCellFormatting.CreateStringCell(reportRow.Collector), ReportCellFormatting.CreateIntCell(reportRow.Year), ReportCellFormatting.CreateStringCell(reportRow.Make), ReportCellFormatting.CreateStringCell(reportRow.Model), ReportCellFormatting.CreateDecimalCell(reportRow.Grade), ReportCellFormatting.CreateCurrencyCell(reportRow.FloorPrice), ReportCellFormatting.CreateStringCell(reportRow.AuctionHouse), ReportCellFormatting.CreateDateCell(reportRow.DateEnteredAutoIMS), ReportCellFormatting.CreateDateCell(reportRow.SoldDate), ReportCellFormatting.CreatePercentageCell(reportRow.GrossPercentFloor), ReportCellFormatting.CreatePercentageCell(reportRow.NetPercentFloor), ReportCellFormatting.CreateCurrencyCell(reportRow.GrossSalePrice), ReportCellFormatting.CreateCurrencyCell(reportRow.TotalCharges), ReportCellFormatting.CreateStringCell(reportRow.RepoCompany), ReportCellFormatting.CreateDateCell(reportRow.DateAssigned), ReportCellFormatting.CreateDateCell(reportRow.DateRepoed), ReportCellFormatting.CreateDateCell(reportRow.ScheduledSaleDate) } }) } }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Is Closed Account Report"); throw new ServerErrorException(); } } public async Task GetAvgDaysRepoToSoldReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetAccountsByStatusChangeInPeriod("SOLD", lowDateTime, highDateTime); return new ReportTableResponse() { ReportTable = ReportTableFactory.CreateHistoricalSummationTable( ReportSumType.WholeNumberAvg, reportData, "Sold Accounts", lowDateTime, highDateTime, (reportEntry) => { if (reportEntry.FilteredStatusChangeDate != null && reportEntry.DateRepoed != null) { return (decimal)(reportEntry.FilteredStatusChangeDate.Value - reportEntry.DateRepoed.Value).TotalDays; } return null; }, (reportEntry) => null, (reportEntry) => reportEntry.FilteredStatusChangeDate, (reportEntry) => reportEntry.RepoId, false), DataTable = DataTableFormatting.CreateDataTable( reportData, (entry) => entry.RepoId, StdReportEntryColumns.Member(), StdReportEntryColumns.AccountNo(), StdReportEntryColumns.Status(), StdReportEntryColumns.DaysCurrentDelq(), StdReportEntryColumns.DaysDelqWhenAdded(), StdReportEntryColumns.LastPaymentAmount(), StdReportEntryColumns.LastPaymentDate(), StdReportEntryColumns.DelinquentAmount(), StdReportEntryColumns.RepoType(), StdReportEntryColumns.Balance(), StdReportEntryColumns.AccountCode(), StdReportEntryColumns.Bankruptcy(), StdReportEntryColumns.Collector(), StdReportEntryColumns.Collateral(), StdReportEntryColumns.RepoCompany(), StdReportEntryColumns.RepoDuration(), StdReportEntryColumns.DateAssigned(), StdReportEntryColumns.DateRepoed(), StdReportEntryColumns.FilteredStatusChangeDate("Date Sold")) }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Avg Days Repot to Sold Report"); throw new ServerErrorException(); } } public async Task GetRedemptionCountReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetAccountsByStatusChangeInPeriod(RedeemedStatus, lowDateTime, highDateTime); return new ReportTableResponse() { ReportTable = ReportTableFactory.CreateHistoricalSummationTable( ReportSumType.WholeNumber, reportData, "Redemptions", lowDateTime, highDateTime, (reportEntry) => 1, (reportEntry) => null, (reportEntry) => reportEntry.FilteredStatusChangeDate, (reportEntry) => $"{reportEntry.RepoId}_{reportEntry.FilteredStatusChangeDate}", false), DataTable = DataTableFormatting.CreateDataTable( reportData, (entity) => entity.RepoId, StdReportEntryColumns.Member(), StdReportEntryColumns.AccountNo(), StdReportEntryColumns.Status(), StdReportEntryColumns.DaysInStatus(), StdReportEntryColumns.DaysCurrentDelq(), StdReportEntryColumns.LastPaymentDate(), StdReportEntryColumns.LastPaymentDate(), StdReportEntryColumns.DelinquentAmount(), StdReportEntryColumns.RepoType(), StdReportEntryColumns.Balance(), StdReportEntryColumns.AccountCode(), StdReportEntryColumns.Bankruptcy(), StdReportEntryColumns.Collector(), StdReportEntryColumns.Collateral(), StdReportEntryColumns.Grade(), StdReportEntryColumns.FloorPrice(), StdReportEntryColumns.Auction(), StdReportEntryColumns.DateEnteredAutoIMS(), StdReportEntryColumns.TotalCharges(), StdReportEntryColumns.DateAssigned(), StdReportEntryColumns.RepoDuration(), StdReportEntryColumns.DateRepoed()) }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Redemption Count Report"); throw new ServerErrorException(); } } public async Task GetAvgDaysDelqWhenAddedReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetAccountsByO4RDate(lowDateTime, highDateTime); return new ReportTableResponse() { ReportTable = ReportTableFactory.CreateHistoricalSummationTable( ReportSumType.WholeNumberAvg, reportData, "Accounts", lowDateTime, highDateTime, (reportEntry) => reportEntry.DaysDelqWhenAdded, (reportEntry) => null, (reportEntry) => reportEntry.O4RDate, (reportEntry) => reportEntry.RepoId, false), DataTable = DataTableFormatting.CreateDataTable( reportData, (reportRow) => reportRow.RepoId, StdReportEntryColumns.Member(), StdReportEntryColumns.AccountNo(), StdReportEntryColumns.Status(), StdReportEntryColumns.DaysCurrentDelq(), StdReportEntryColumns.DaysDelqWhenAdded(), StdReportEntryColumns.LastPaymentDate(), StdReportEntryColumns.Balance(), StdReportEntryColumns.AccountCode(), StdReportEntryColumns.Bankruptcy(), StdReportEntryColumns.Collector(), StdReportEntryColumns.Collateral(), StdReportEntryColumns.O4RDate()) }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Avg Days Delq When Added Report"); throw new ServerErrorException(); } } public async Task GetCountOfSalesReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetAccountsByStatusChangeInPeriod("SOLD", lowDateTime, highDateTime); return new ReportTableResponse() { ReportTable = ReportTableFactory.CreateHistoricalSummationTable( ReportSumType.WholeNumber, reportData, "Sold Accounts", lowDateTime, highDateTime, (reportEntry) => 1, (reportEntry) => null, (reportEntry) => reportEntry.FilteredStatusChangeDate, (reportEntry) => reportEntry.RepoId, false), DataTable = DataTableFormatting.CreateDataTable( reportData, (entry) => entry.RepoId, StdReportEntryColumns.Member(), StdReportEntryColumns.AccountNo(), StdReportEntryColumns.Status(), StdReportEntryColumns.DaysInStatus(), StdReportEntryColumns.Balance(), StdReportEntryColumns.AccountCode(), StdReportEntryColumns.Bankruptcy(), StdReportEntryColumns.Collector(), StdReportEntryColumns.Collateral(), StdReportEntryColumns.Auction(), StdReportEntryColumns.GrossSalePrice(), StdReportEntryColumns.GrossPercentFloor(), StdReportEntryColumns.NetPercentFloor(), StdReportEntryColumns.TotalCharges(), StdReportEntryColumns.FilteredStatusChangeDate("Date Sold")) }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Avg Days Repot to Sold Report"); throw new ServerErrorException(); } } public async Task GetAvgSurplusReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetAccountsByDateSoldInAutoIMS(lowDateTime, highDateTime); return new ReportTableResponse() { ReportTable = ReportTableFactory.CreateHistoricalSummationTable( ReportSumType.CurrencyAvg, reportData, "Sold Accounts", lowDateTime, highDateTime, (reportEntry) => reportEntry.GrossSalePrice - reportEntry.Balance, (reportEntry) => reportEntry.AuctionName, (reportEntry) => reportEntry.SoldDate, (reportEntry) => reportEntry.RepoId, false), DataTable = DataTableFormatting.CreateDataTable( reportData, (reportRow) => reportRow.RepoId, StdReportEntryColumns.Member(), StdReportEntryColumns.AccountNo(), StdReportEntryColumns.Status(), StdReportEntryColumns.DaysInStatus(), StdReportEntryColumns.GrossSalePrice(), StdReportEntryColumns.Balance(), StdReportEntryColumns.SurplusDeficiency(), StdReportEntryColumns.AccountCode(), StdReportEntryColumns.Bankruptcy(), StdReportEntryColumns.Collector(), StdReportEntryColumns.Collateral(), StdReportEntryColumns.Auction(), StdReportEntryColumns.DateSold()) }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Avg Surplus or Defiency Report"); throw new ServerErrorException(); } } public async Task GetRepoBalanceReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetAccountsByDateRepoed(lowDateTime, highDateTime); return new ReportTableResponse() { ReportTable = ReportTableFactory.CreateHistoricalSummationTable( ReportSumType.Currency, reportData, "Companies", lowDateTime, highDateTime, (reportEntry) => reportEntry.Balance, (reportEntry) => reportEntry.RepoCompany, (reportEntry) => reportEntry.DateRepoed, (reportEntry) => reportEntry.RepoId), DataTable = DataTableFormatting.CreateDataTable( reportData, (reportRow) => reportRow.RepoId, StdReportEntryColumns.Member(), StdReportEntryColumns.AccountNo(), StdReportEntryColumns.Status(), StdReportEntryColumns.DaysInStatus(), StdReportEntryColumns.RepoType(), StdReportEntryColumns.Balance(), StdReportEntryColumns.AccountCode(), StdReportEntryColumns.Bankruptcy(), StdReportEntryColumns.Collector(), StdReportEntryColumns.Collateral()) }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Repo Balance Report"); throw new ServerErrorException(); } } public async Task GetRedemptionBalanceReport(DateTime lowDateTime, DateTime highDateTime) { try { var reportData = await _reportingRepository.GetAccountsByStatusChangeInPeriod(RedeemedStatus, lowDateTime, highDateTime); return new ReportTableResponse() { ReportTable = ReportTableFactory.CreateHistoricalSummationTable( ReportSumType.Currency, reportData, "Redeemed Accounts", lowDateTime, highDateTime, (reportEntry) => reportEntry.Balance, (reportEntry) => null, (reportEntry) => reportEntry.FilteredStatusChangeDate, (reportEntry) => reportEntry.RepoId, false), DataTable = DataTableFormatting.CreateDataTable( reportData, (reportRow) => reportRow.RepoId, StdReportEntryColumns.Member(), StdReportEntryColumns.AccountNo(), StdReportEntryColumns.Status(), StdReportEntryColumns.DaysInStatus(), StdReportEntryColumns.Balance(), StdReportEntryColumns.AccountCode(), StdReportEntryColumns.Bankruptcy(), StdReportEntryColumns.Collector(), StdReportEntryColumns.Collateral(), StdReportEntryColumns.FilteredStatusChangeDate("Redeemed On")) }; } catch (Exception ex) { Log.Error(ex, "Failure retrieving Redemption Balance Report"); throw new ServerErrorException(); } } } }