diff --git a/Controllers/APIController.cs b/Controllers/APIController.cs index db480fb..2f8cebb 100644 --- a/Controllers/APIController.cs +++ b/Controllers/APIController.cs @@ -27,6 +27,7 @@ namespace CarCareTracker.Controllers private readonly IReminderHelper _reminderHelper; private readonly IGasHelper _gasHelper; private readonly IUserLogic _userLogic; + private readonly IOdometerLogic _odometerLogic; private readonly IFileHelper _fileHelper; private readonly IMailHelper _mailHelper; private readonly IConfigHelper _config; @@ -46,7 +47,8 @@ namespace CarCareTracker.Controllers IMailHelper mailHelper, IFileHelper fileHelper, IConfigHelper config, - IUserLogic userLogic) + IUserLogic userLogic, + IOdometerLogic odometerLogic) { _dataAccess = dataAccess; _noteDataAccess = noteDataAccess; @@ -63,6 +65,7 @@ namespace CarCareTracker.Controllers _gasHelper = gasHelper; _reminderHelper = reminderHelper; _userLogic = userLogic; + _odometerLogic = odometerLogic; _fileHelper = fileHelper; _config = config; } @@ -138,7 +141,7 @@ namespace CarCareTracker.Controllers Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Mileage = int.Parse(input.Odometer) }; - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord); + _odometerLogic.AutoInsertOdometerRecord(odometerRecord); } response.Success = true; response.Message = "Service Record Added"; @@ -205,7 +208,7 @@ namespace CarCareTracker.Controllers Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Mileage = int.Parse(input.Odometer) }; - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord); + _odometerLogic.AutoInsertOdometerRecord(odometerRecord); } response.Success = true; response.Message = "Repair Record Added"; @@ -272,7 +275,7 @@ namespace CarCareTracker.Controllers Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Mileage = int.Parse(input.Odometer) }; - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord); + _odometerLogic.AutoInsertOdometerRecord(odometerRecord); } response.Success = true; response.Message = "Upgrade Record Added"; @@ -353,7 +356,12 @@ namespace CarCareTracker.Controllers public IActionResult OdometerRecords(int vehicleId) { var vehicleRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId); - var result = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), Odometer = x.Mileage.ToString(), Notes = x.Notes }); + //determine if conversion is needed. + if (vehicleRecords.All(x => x.InitialMileage == default)) + { + vehicleRecords = _odometerLogic.AutoConvertOdometerRecord(vehicleRecords); + } + var result = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), InitialOdometer = x.InitialMileage.ToString(), Odometer = x.Mileage.ToString(), Notes = x.Notes }); return Json(result); } [TypeFilter(typeof(CollaboratorFilter))] @@ -384,6 +392,7 @@ namespace CarCareTracker.Controllers VehicleId = vehicleId, Date = DateTime.Parse(input.Date), Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, + InitialMileage = (string.IsNullOrWhiteSpace(input.InitialOdometer) || int.Parse(input.InitialOdometer) == default) ? _odometerLogic.GetLastOdometerRecordMileage(vehicleId, new List()) : int.Parse(input.InitialOdometer), Mileage = int.Parse(input.Odometer) }; _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord); @@ -466,7 +475,7 @@ namespace CarCareTracker.Controllers Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Mileage = int.Parse(input.Odometer) }; - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord); + _odometerLogic.AutoInsertOdometerRecord(odometerRecord); } response.Success = true; response.Message = "Gas Record Added"; diff --git a/Controllers/VehicleController.cs b/Controllers/VehicleController.cs index 46f1005..0d31f0b 100644 --- a/Controllers/VehicleController.cs +++ b/Controllers/VehicleController.cs @@ -36,6 +36,7 @@ namespace CarCareTracker.Controllers private readonly IReminderHelper _reminderHelper; private readonly IReportHelper _reportHelper; private readonly IUserLogic _userLogic; + private readonly IOdometerLogic _odometerLogic; private readonly IExtraFieldDataAccess _extraFieldDataAccess; public VehicleController(ILogger logger, @@ -57,6 +58,7 @@ namespace CarCareTracker.Controllers IOdometerRecordDataAccess odometerRecordDataAccess, IExtraFieldDataAccess extraFieldDataAccess, IUserLogic userLogic, + IOdometerLogic odometerLogic, IWebHostEnvironment webEnv, IConfigHelper config) { @@ -79,6 +81,7 @@ namespace CarCareTracker.Controllers _odometerRecordDataAccess = odometerRecordDataAccess; _extraFieldDataAccess = extraFieldDataAccess; _userLogic = userLogic; + _odometerLogic = odometerLogic; _webEnv = webEnv; _config = config; } @@ -265,7 +268,7 @@ namespace CarCareTracker.Controllers var vehicleRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId); if (vehicleRecords.Any()) { - var exportData = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) }); + var exportData = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), Notes = x.Notes, InitialOdometer = x.InitialMileage.ToString(), Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) }); using (var writer = new StreamWriter(fullExportFilePath)) { using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture)) @@ -460,7 +463,7 @@ namespace CarCareTracker.Controllers _gasRecordDataAccess.SaveGasRecordToVehicle(convertedRecord); if (_config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = convertedRecord.Date, VehicleId = convertedRecord.VehicleId, @@ -485,7 +488,7 @@ namespace CarCareTracker.Controllers _serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord); if (_config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = convertedRecord.Date, VehicleId = convertedRecord.VehicleId, @@ -500,6 +503,7 @@ namespace CarCareTracker.Controllers { VehicleId = vehicleId, Date = DateTime.Parse(importModel.Date), + InitialMileage = decimal.ToInt32(decimal.Parse(importModel.InitialOdometer, NumberStyles.Any)), Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)), Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes, Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList() @@ -540,7 +544,7 @@ namespace CarCareTracker.Controllers _collisionRecordDataAccess.SaveCollisionRecordToVehicle(convertedRecord); if (_config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = convertedRecord.Date, VehicleId = convertedRecord.VehicleId, @@ -564,7 +568,7 @@ namespace CarCareTracker.Controllers _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(convertedRecord); if (_config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = convertedRecord.Date, VehicleId = convertedRecord.VehicleId, @@ -646,7 +650,7 @@ namespace CarCareTracker.Controllers { if (gasRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = DateTime.Parse(gasRecord.Date), VehicleId = gasRecord.VehicleId, @@ -734,7 +738,7 @@ namespace CarCareTracker.Controllers { if (serviceRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = DateTime.Parse(serviceRecord.Date), VehicleId = serviceRecord.VehicleId, @@ -811,7 +815,7 @@ namespace CarCareTracker.Controllers { if (collisionRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = DateTime.Parse(collisionRecord.Date), VehicleId = collisionRecord.VehicleId, @@ -1004,7 +1008,7 @@ namespace CarCareTracker.Controllers { MonthName = x.Key.MonthName, Cost = x.Sum(y => y.Cost), - DistanceTraveled = x.Any(y => y.MinMileage != default) ? x.Max(y => y.MaxMileage) - x.Where(y => y.MinMileage != default).Min(y => y.MinMileage) : 0 + DistanceTraveled = 0 }).ToList(); //get reminders var reminders = GetRemindersAndUrgency(vehicleId, DateTime.Now); @@ -1376,7 +1380,7 @@ namespace CarCareTracker.Controllers { MonthName = x.Key.MonthName, Cost = x.Sum(y => y.Cost), - DistanceTraveled = x.Any(y => y.MinMileage != default) ? x.Max(y => y.MaxMileage) - x.Where(y => y.MinMileage != default).Min(y => y.MinMileage) : 0 + DistanceTraveled = 0 }).ToList(); return PartialView("_GasCostByMonthReport", groupedRecord); } @@ -1603,7 +1607,7 @@ namespace CarCareTracker.Controllers { if (upgradeRecord.Id == default && _config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = DateTime.Parse(upgradeRecord.Date), VehicleId = upgradeRecord.VehicleId, @@ -1968,7 +1972,7 @@ namespace CarCareTracker.Controllers { if (_config.GetUserConfig(User).EnableAutoOdometerInsert) { - _odometerRecordDataAccess.SaveOdometerRecordToVehicle(new OdometerRecord + _odometerLogic.AutoInsertOdometerRecord(new OdometerRecord { Date = DateTime.Now, VehicleId = existingRecord.VehicleId, @@ -2071,6 +2075,11 @@ namespace CarCareTracker.Controllers public IActionResult GetOdometerRecordsByVehicleId(int vehicleId) { var result = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId); + //determine if conversion is needed. + if (result.All(x=>x.InitialMileage == default)) + { + result = _odometerLogic.AutoConvertOdometerRecord(result); + } bool _useDescending = _config.GetUserConfig(User).UseDescending; if (_useDescending) { @@ -2087,13 +2096,17 @@ namespace CarCareTracker.Controllers { //move files from temp. odometerRecord.Files = odometerRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); + if (odometerRecord.InitialMileage == default) + { + odometerRecord.InitialMileage = _odometerLogic.GetLastOdometerRecordMileage(odometerRecord.VehicleId, new List()); + } var result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord.ToOdometerRecord()); return Json(result); } [HttpGet] - public IActionResult GetAddOdometerRecordPartialView() + public IActionResult GetAddOdometerRecordPartialView(int vehicleId) { - return PartialView("_OdometerRecordModal", new OdometerRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.OdometerRecord).ExtraFields }); + return PartialView("_OdometerRecordModal", new OdometerRecordInput() { InitialMileage = _odometerLogic.GetLastOdometerRecordMileage(vehicleId, new List()), ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.OdometerRecord).ExtraFields }); } [HttpGet] public IActionResult GetOdometerRecordForEditById(int odometerRecordId) @@ -2104,6 +2117,7 @@ namespace CarCareTracker.Controllers { Id = result.Id, Date = result.Date.ToShortDateString(), + InitialMileage = result.InitialMileage, Mileage = result.Mileage, Notes = result.Notes, VehicleId = result.VehicleId, diff --git a/Helper/ReportHelper.cs b/Helper/ReportHelper.cs index 1457942..f61c06d 100644 --- a/Helper/ReportHelper.cs +++ b/Helper/ReportHelper.cs @@ -24,9 +24,7 @@ namespace CarCareTracker.Helper { MonthId = x.Key, MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key), - Cost = 0, - MaxMileage = x.Max(y => y.Mileage), - MinMileage = x.Min(y => y.Mileage) + Cost = 0 }); } public IEnumerable GetServiceRecordSum(List serviceRecords, int year = 0) @@ -39,9 +37,7 @@ namespace CarCareTracker.Helper { MonthId = x.Key, MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key), - Cost = x.Sum(y => y.Cost), - MaxMileage = x.Max(y=>y.Mileage), - MinMileage = x.Min(y=>y.Mileage) + Cost = x.Sum(y => y.Cost) }); } public IEnumerable GetRepairRecordSum(List repairRecords, int year = 0) @@ -54,9 +50,7 @@ namespace CarCareTracker.Helper { MonthId = x.Key, MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key), - Cost = x.Sum(y => y.Cost), - MaxMileage = x.Max(y => y.Mileage), - MinMileage = x.Min(y => y.Mileage) + Cost = x.Sum(y => y.Cost) }); } public IEnumerable GetUpgradeRecordSum(List upgradeRecords, int year = 0) @@ -69,9 +63,7 @@ namespace CarCareTracker.Helper { MonthId = x.Key, MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key), - Cost = x.Sum(y => y.Cost), - MaxMileage = x.Max(y => y.Mileage), - MinMileage = x.Min(y => y.Mileage) + Cost = x.Sum(y => y.Cost) }); } public IEnumerable GetGasRecordSum(List gasRecords, int year = 0) @@ -84,9 +76,7 @@ namespace CarCareTracker.Helper { MonthId = x.Key, MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key), - Cost = x.Sum(y => y.Cost), - MaxMileage = x.Max(y => y.Mileage), - MinMileage = x.Min(y => y.Mileage) + Cost = x.Sum(y => y.Cost) }); } public IEnumerable GetTaxRecordSum(List taxRecords, int year = 0) diff --git a/Logic/OdometerLogic.cs b/Logic/OdometerLogic.cs new file mode 100644 index 0000000..d9db83a --- /dev/null +++ b/Logic/OdometerLogic.cs @@ -0,0 +1,67 @@ +using CarCareTracker.External.Interfaces; +using CarCareTracker.Models; + +namespace CarCareTracker.Logic +{ + public interface IOdometerLogic + { + int GetLastOdometerRecordMileage(int vehicleId, List odometerRecords); + bool AutoInsertOdometerRecord(OdometerRecord odometer); + List AutoConvertOdometerRecord(List odometerRecords); + } + public class OdometerLogic: IOdometerLogic + { + private readonly IOdometerRecordDataAccess _odometerRecordDataAccess; + private readonly ILogger _logger; + public OdometerLogic(IOdometerRecordDataAccess odometerRecordDataAccess, ILogger logger) + { + _odometerRecordDataAccess = odometerRecordDataAccess; + _logger = logger; + } + public int GetLastOdometerRecordMileage(int vehicleId, List odometerRecords) + { + if (!odometerRecords.Any()) + { + odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId); + } + if (!odometerRecords.Any()) + { + //no existing odometer records for this vehicle. + return 0; + } + return odometerRecords.Max(x => x.Mileage); + } + public bool AutoInsertOdometerRecord(OdometerRecord odometer) + { + var lastReportedMileage = GetLastOdometerRecordMileage(odometer.VehicleId, new List()); + odometer.InitialMileage = lastReportedMileage != default ? lastReportedMileage : odometer.Mileage; + + var result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometer); + return result; + } + public List AutoConvertOdometerRecord(List odometerRecords) + { + //perform ordering + odometerRecords = odometerRecords.OrderBy(x => x.Date).ThenBy(x => x.Mileage).ToList(); + int previousMileage = 0; + for (int i = 0; i < odometerRecords.Count; i++) + { + var currentObject = odometerRecords[i]; + if (previousMileage == default) + { + //first record + currentObject.InitialMileage = currentObject.Mileage; + } + else + { + //subsequent records + currentObject.InitialMileage = previousMileage; + } + //save to db. + _odometerRecordDataAccess.SaveOdometerRecordToVehicle(currentObject); + previousMileage = currentObject.Mileage; + } + return odometerRecords; + } + } +} diff --git a/MapProfile/ImportMappers.cs b/MapProfile/ImportMappers.cs index 2df1898..f44203b 100644 --- a/MapProfile/ImportMappers.cs +++ b/MapProfile/ImportMappers.cs @@ -10,6 +10,7 @@ namespace CarCareTracker.MapProfile Map(m => m.Date).Name(["date", "fuelup_date"]); Map(m => m.DateCreated).Name(["datecreated"]); Map(m => m.DateModified).Name(["datemodified"]); + Map(m => m.InitialOdometer).Name(["initialodometer"]); Map(m => m.Odometer).Name(["odometer"]); Map(m => m.FuelConsumed).Name(["gallons", "liters", "litres", "consumption", "quantity", "fuelconsumed"]); Map(m => m.Cost).Name(["cost", "total cost", "totalcost", "total price"]); diff --git a/Models/OdometerRecord/OdometerRecord.cs b/Models/OdometerRecord/OdometerRecord.cs index 45594c5..2f52988 100644 --- a/Models/OdometerRecord/OdometerRecord.cs +++ b/Models/OdometerRecord/OdometerRecord.cs @@ -5,7 +5,9 @@ public int Id { get; set; } public int VehicleId { get; set; } public DateTime Date { get; set; } + public int InitialMileage { get; set; } public int Mileage { get; set; } + public int DistanceTraveled { get { return Mileage - InitialMileage; } } public string Notes { get; set; } public List Tags { get; set; } = new List(); public List Files { get; set; } = new List(); diff --git a/Models/OdometerRecord/OdometerRecordInput.cs b/Models/OdometerRecord/OdometerRecordInput.cs index f2c445d..80a5089 100644 --- a/Models/OdometerRecord/OdometerRecordInput.cs +++ b/Models/OdometerRecord/OdometerRecordInput.cs @@ -5,11 +5,12 @@ public int Id { get; set; } public int VehicleId { get; set; } public string Date { get; set; } = DateTime.Now.ToShortDateString(); + public int InitialMileage { get; set; } public int Mileage { get; set; } public string Notes { get; set; } public List Files { get; set; } = new List(); public List Tags { get; set; } = new List(); public List ExtraFields { get; set; } = new List(); - public OdometerRecord ToOdometerRecord() { return new OdometerRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Mileage = Mileage, Notes = Notes, Files = Files, Tags = Tags, ExtraFields = ExtraFields }; } + public OdometerRecord ToOdometerRecord() { return new OdometerRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Mileage = Mileage, Notes = Notes, Files = Files, Tags = Tags, ExtraFields = ExtraFields, InitialMileage = InitialMileage }; } } } diff --git a/Models/Report/CostForVehicleByMonth.cs b/Models/Report/CostForVehicleByMonth.cs index 83549b4..d4185e5 100644 --- a/Models/Report/CostForVehicleByMonth.cs +++ b/Models/Report/CostForVehicleByMonth.cs @@ -5,8 +5,6 @@ public int MonthId { get; set; } public string MonthName { get; set; } public decimal Cost { get; set; } - public int MaxMileage { get; set; } - public int MinMileage { get; set; } public int DistanceTraveled { get; set; } } } diff --git a/Models/Shared/ImportModel.cs b/Models/Shared/ImportModel.cs index b727eee..73c4e7b 100644 --- a/Models/Shared/ImportModel.cs +++ b/Models/Shared/ImportModel.cs @@ -11,6 +11,7 @@ public string Type { get; set; } public string Priority { get; set; } public string Progress { get; set; } + public string InitialOdometer { get; set; } public string Odometer { get; set; } public string Description { get; set; } public string Notes { get; set; } @@ -50,6 +51,7 @@ public class OdometerRecordExportModel { public string Date { get; set; } + public string InitialOdometer { get; set; } public string Odometer { get; set; } public string Notes { get; set; } public string Tags { get; set; } diff --git a/Program.cs b/Program.cs index a1d39ca..eab5fd5 100644 --- a/Program.cs +++ b/Program.cs @@ -69,6 +69,7 @@ builder.Services.AddSingleton(); //configure logic builder.Services.AddSingleton(); builder.Services.AddSingleton(); +builder.Services.AddSingleton(); if (!Directory.Exists("data")) { diff --git a/Views/API/Index.cshtml b/Views/API/Index.cshtml index 8542ab9..a1a092a 100644 --- a/Views/API/Index.cshtml +++ b/Views/API/Index.cshtml @@ -314,6 +314,7 @@
Body(form-data): {
date - Date to be entered
+ initialOdometer - Initial Odometer reading(optional)
odometer - Odometer reading
notes - notes(optional)
} diff --git a/Views/Vehicle/_OdometerRecordModal.cshtml b/Views/Vehicle/_OdometerRecordModal.cshtml index 74e701d..a26d522 100644 --- a/Views/Vehicle/_OdometerRecordModal.cshtml +++ b/Views/Vehicle/_OdometerRecordModal.cshtml @@ -22,6 +22,8 @@ + + diff --git a/Views/Vehicle/_OdometerRecords.cshtml b/Views/Vehicle/_OdometerRecords.cshtml index ca1cb0d..79921e3 100644 --- a/Views/Vehicle/_OdometerRecords.cshtml +++ b/Views/Vehicle/_OdometerRecords.cshtml @@ -52,12 +52,24 @@ + +