diff --git a/Controllers/VehicleController.cs b/Controllers/VehicleController.cs index a9473ad5..cb6e0236 100644 --- a/Controllers/VehicleController.cs +++ b/Controllers/VehicleController.cs @@ -1140,6 +1140,7 @@ public IActionResult GetReportPartialView(int vehicleId) var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId); var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId); var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId); + var userConfig = _config.GetUserConfig(User); var viewModel = new ReportViewModel(); //get totalCostMakeUp viewModel.CostMakeUpForVehicle = new CostMakeUpForVehicle @@ -1205,7 +1206,6 @@ public IActionResult GetReportPartialView(int vehicleId) var collaborators = _userLogic.GetCollaboratorsForVehicle(vehicleId); viewModel.Collaborators = collaborators; //get MPG per month. - var userConfig = _config.GetUserConfig(User); var mileageData = _gasHelper.GetGasRecordViewModels(gasRecords, userConfig.UseMPG, userConfig.UseUKMPG); mileageData.RemoveAll(x => x.MilesPerGallon == default); var monthlyMileageData = StaticHelper.GetBaseLineCostsNoMonthName(); @@ -1272,6 +1272,44 @@ public IActionResult GetCostMakeUpForVehicle(int vehicleId, int year = 0) return PartialView("_CostMakeUpReport", viewModel); } [TypeFilter(typeof(CollaboratorFilter))] + [HttpGet] + public IActionResult GetCostTableForVehicle(int vehicleId, int year = 0) + { + var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId); + var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId); + var collisionRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId); + var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId); + var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId); + var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId); + if (year != default) + { + serviceRecords.RemoveAll(x => x.Date.Year != year); + gasRecords.RemoveAll(x => x.Date.Year != year); + collisionRecords.RemoveAll(x => x.Date.Year != year); + taxRecords.RemoveAll(x => x.Date.Year != year); + upgradeRecords.RemoveAll(x => x.Date.Year != year); + odometerRecords.RemoveAll(x => x.Date.Year != year); + } + var maxMileage = _vehicleLogic.GetMaxMileage(serviceRecords, collisionRecords, gasRecords, upgradeRecords, odometerRecords); + var minMileage = _vehicleLogic.GetMinMileage(serviceRecords, collisionRecords, gasRecords, upgradeRecords, odometerRecords); + var vehicleData = _dataAccess.GetVehicleById(vehicleId); + var userConfig = _config.GetUserConfig(User); + var totalDistanceTraveled = maxMileage - minMileage; + var totalDays = _vehicleLogic.GetOwnershipDays(vehicleData.PurchaseDate, vehicleData.SoldDate, serviceRecords, collisionRecords, gasRecords, upgradeRecords, odometerRecords, taxRecords); + var viewModel = new CostTableForVehicle + { + ServiceRecordSum = serviceRecords.Sum(x => x.Cost), + GasRecordSum = gasRecords.Sum(x => x.Cost), + CollisionRecordSum = collisionRecords.Sum(x => x.Cost), + TaxRecordSum = taxRecords.Sum(x => x.Cost), + UpgradeRecordSum = upgradeRecords.Sum(x => x.Cost), + TotalDistance = totalDistanceTraveled, + DistanceUnit = vehicleData.UseHours ? "Cost Per Hour" : userConfig.UseMPG ? "Cost Per Mile" : "Cost Per Kilometer", + NumberOfDays = totalDays + }; + return PartialView("_CostTableReport", viewModel); + } + [TypeFilter(typeof(CollaboratorFilter))] public IActionResult GetReminderMakeUpByVehicle(int vehicleId, int daysToAdd) { var reminders = GetRemindersAndUrgency(vehicleId, DateTime.Now.AddDays(daysToAdd)); diff --git a/Logic/VehicleLogic.cs b/Logic/VehicleLogic.cs index 38f06969..e656443a 100644 --- a/Logic/VehicleLogic.cs +++ b/Logic/VehicleLogic.cs @@ -7,7 +7,10 @@ namespace CarCareTracker.Logic public interface IVehicleLogic { int GetMaxMileage(int vehicleId); + int GetMaxMileage(List serviceRecords, List repairRecords, List gasRecords, List upgradeRecords, List odometerRecords); int GetMinMileage(int vehicleId); + int GetMinMileage(List serviceRecords, List repairRecords, List gasRecords, List upgradeRecords, List odometerRecords); + int GetOwnershipDays(string purchaseDate, string soldDate, List serviceRecords, List repairRecords, List gasRecords, List upgradeRecords, List odometerRecords, List taxRecords); bool GetVehicleHasUrgentOrPastDueReminders(int vehicleId); } public class VehicleLogic: IVehicleLogic @@ -66,6 +69,31 @@ public int GetMaxMileage(int vehicleId) } return numbersArray.Any() ? numbersArray.Max() : 0; } + public int GetMaxMileage(List serviceRecords, List repairRecords, List gasRecords, List upgradeRecords, List odometerRecords) + { + var numbersArray = new List(); + if (serviceRecords.Any()) + { + numbersArray.Add(serviceRecords.Max(x => x.Mileage)); + } + if (repairRecords.Any()) + { + numbersArray.Add(repairRecords.Max(x => x.Mileage)); + } + if (gasRecords.Any()) + { + numbersArray.Add(gasRecords.Max(x => x.Mileage)); + } + if (upgradeRecords.Any()) + { + numbersArray.Add(upgradeRecords.Max(x => x.Mileage)); + } + if (odometerRecords.Any()) + { + numbersArray.Add(odometerRecords.Max(x => x.Mileage)); + } + return numbersArray.Any() ? numbersArray.Max() : 0; + } public int GetMinMileage(int vehicleId) { var numbersArray = new List(); @@ -96,6 +124,68 @@ public int GetMinMileage(int vehicleId) } return numbersArray.Any() ? numbersArray.Min() : 0; } + public int GetMinMileage(List serviceRecords, List repairRecords, List gasRecords, List upgradeRecords, List odometerRecords) + { + var numbersArray = new List(); + var _serviceRecords = serviceRecords.Where(x => x.Mileage != default).ToList(); + if (_serviceRecords.Any()) + { + numbersArray.Add(_serviceRecords.Min(x => x.Mileage)); + } + var _repairRecords = repairRecords.Where(x => x.Mileage != default).ToList(); + if (_repairRecords.Any()) + { + numbersArray.Add(_repairRecords.Min(x => x.Mileage)); + } + var _gasRecords = gasRecords.Where(x => x.Mileage != default).ToList(); + if (_gasRecords.Any()) + { + numbersArray.Add(_gasRecords.Min(x => x.Mileage)); + } + var _upgradeRecords = upgradeRecords.Where(x => x.Mileage != default).ToList(); + if (_upgradeRecords.Any()) + { + numbersArray.Add(_upgradeRecords.Min(x => x.Mileage)); + } + var _odometerRecords = odometerRecords.Where(x => x.Mileage != default).ToList(); + if (_odometerRecords.Any()) + { + numbersArray.Add(_odometerRecords.Min(x => x.Mileage)); + } + return numbersArray.Any() ? numbersArray.Min() : 0; + } + public int GetOwnershipDays(string purchaseDate, string soldDate, List serviceRecords, List repairRecords, List gasRecords, List upgradeRecords, List odometerRecords, List taxRecords) + { + var startDate = DateTime.Now; + var endDate = DateTime.Now; + if (!string.IsNullOrWhiteSpace(soldDate)) + { + endDate = DateTime.Parse(soldDate); + } + if (!string.IsNullOrWhiteSpace(purchaseDate)) + { + //if purchase date is provided, then we just have to subtract the begin date to end date and return number of months + startDate = DateTime.Parse(purchaseDate); + var timeElapsed = (int)Math.Floor((endDate - startDate).TotalDays); + return timeElapsed; + } + var dateArray = new List(); + dateArray.AddRange(serviceRecords.Select(x => x.Date)); + dateArray.AddRange(repairRecords.Select(x => x.Date)); + dateArray.AddRange(gasRecords.Select(x => x.Date)); + dateArray.AddRange(upgradeRecords.Select(x => x.Date)); + dateArray.AddRange(odometerRecords.Select(x => x.Date)); + dateArray.AddRange(taxRecords.Select(x => x.Date)); + if (dateArray.Any()) + { + startDate = dateArray.Min(); + var timeElapsed = (int)Math.Floor((endDate - startDate).TotalDays); + return timeElapsed; + } else + { + return 1; + } + } public bool GetVehicleHasUrgentOrPastDueReminders(int vehicleId) { var currentMileage = GetMaxMileage(vehicleId); diff --git a/Models/Report/CostTableForVehicle.cs b/Models/Report/CostTableForVehicle.cs new file mode 100644 index 00000000..937bdbff --- /dev/null +++ b/Models/Report/CostTableForVehicle.cs @@ -0,0 +1,26 @@ +namespace CarCareTracker.Models +{ + public class CostTableForVehicle + { + public string DistanceUnit { get; set; } = "Per Mile"; + public int TotalDistance { get; set; } + public int NumberOfDays { get; set; } + public decimal ServiceRecordSum { get; set; } + public decimal GasRecordSum { get; set; } + public decimal TaxRecordSum { get; set; } + public decimal CollisionRecordSum { get; set; } + public decimal UpgradeRecordSum { get; set; } + public decimal ServiceRecordPerMile { get { return TotalDistance != default ? ServiceRecordSum / TotalDistance : 0; } } + public decimal GasRecordPerMile { get { return TotalDistance != default ? GasRecordSum / TotalDistance : 0; } } + public decimal CollisionRecordPerMile { get { return TotalDistance != default ? CollisionRecordSum / TotalDistance : 0; } } + public decimal UpgradeRecordPerMile { get { return TotalDistance != default ? UpgradeRecordSum / TotalDistance : 0; } } + public decimal ServiceRecordPerMonth { get { return NumberOfDays != default ? ServiceRecordSum / NumberOfDays : 0; } } + public decimal GasRecordPerMonth { get { return NumberOfDays != default ? GasRecordSum / NumberOfDays : 0; } } + public decimal CollisionRecordPerMonth { get { return NumberOfDays != default ? CollisionRecordSum / NumberOfDays : 0; } } + public decimal UpgradeRecordPerMonth { get { return NumberOfDays != default ? UpgradeRecordSum / NumberOfDays : 0; } } + public decimal TaxRecordPerMonth { get { return NumberOfDays != default ? TaxRecordSum / NumberOfDays : 0; } } + public decimal TotalPerMonth { get { return ServiceRecordPerMonth + CollisionRecordPerMonth + UpgradeRecordPerMonth + GasRecordPerMonth + TaxRecordPerMonth; } } + public decimal TotalPerMile { get { return ServiceRecordPerMile + CollisionRecordPerMile + UpgradeRecordPerMile + GasRecordPerMile; } } + public decimal TotalCost { get { return ServiceRecordSum + CollisionRecordSum + UpgradeRecordSum + GasRecordSum + TaxRecordSum; } } + } +} diff --git a/Views/Vehicle/_CostMakeUpReport.cshtml b/Views/Vehicle/_CostMakeUpReport.cshtml index 160bd1d5..bbd15703 100644 --- a/Views/Vehicle/_CostMakeUpReport.cshtml +++ b/Views/Vehicle/_CostMakeUpReport.cshtml @@ -36,6 +36,9 @@ ] }, options: { + onClick: (e) => { + showDataTable(); + }, plugins: { legend: { position: "bottom", diff --git a/Views/Vehicle/_CostTableReport.cshtml b/Views/Vehicle/_CostTableReport.cshtml new file mode 100644 index 00000000..95efea88 --- /dev/null +++ b/Views/Vehicle/_CostTableReport.cshtml @@ -0,0 +1,78 @@ +@using CarCareTracker.Helper +@inject IConfigHelper config +@inject ITranslationHelper translator +@{ + var userConfig = config.GetUserConfig(User); + var userLanguage = userConfig.UserLanguage; + var hideZero = userConfig.HideZero; +} +@model CostTableForVehicle +@if (Model.CollisionRecordSum + Model.ServiceRecordSum + Model.GasRecordSum + Model.TaxRecordSum + Model.UpgradeRecordSum > 0) +{ +
+ + +
+} +else +{ +
+

@translator.Translate(userLanguage, "No data found or all records have zero sums, insert records with non-zero sums to see visualizations here.")

+
+} diff --git a/Views/Vehicle/_Report.cshtml b/Views/Vehicle/_Report.cshtml index fa1af5f1..47534f48 100644 --- a/Views/Vehicle/_Report.cshtml +++ b/Views/Vehicle/_Report.cshtml @@ -146,6 +146,13 @@ +