using CarCareTracker.External.Interfaces; using CarCareTracker.Models; using LiteDB; using Microsoft.AspNetCore.Mvc; using CarCareTracker.Helper; using CsvHelper; using System.Globalization; namespace CarCareTracker.Controllers { public class VehicleController : Controller { private readonly ILogger _logger; private readonly IVehicleDataAccess _dataAccess; private readonly INoteDataAccess _noteDataAccess; private readonly IServiceRecordDataAccess _serviceRecordDataAccess; private readonly IGasRecordDataAccess _gasRecordDataAccess; private readonly ICollisionRecordDataAccess _collisionRecordDataAccess; private readonly ITaxRecordDataAccess _taxRecordDataAccess; private readonly IWebHostEnvironment _webEnv; private readonly IFileHelper _fileHelper; public VehicleController(ILogger logger, IFileHelper fileHelper, IVehicleDataAccess dataAccess, INoteDataAccess noteDataAccess, IServiceRecordDataAccess serviceRecordDataAccess, IGasRecordDataAccess gasRecordDataAccess, ICollisionRecordDataAccess collisionRecordDataAccess, ITaxRecordDataAccess taxRecordDataAccess, IWebHostEnvironment webEnv) { _logger = logger; _dataAccess = dataAccess; _noteDataAccess = noteDataAccess; _fileHelper = fileHelper; _serviceRecordDataAccess = serviceRecordDataAccess; _gasRecordDataAccess = gasRecordDataAccess; _collisionRecordDataAccess = collisionRecordDataAccess; _taxRecordDataAccess = taxRecordDataAccess; _webEnv = webEnv; } [HttpGet] public IActionResult Index(int vehicleId) { var data = _dataAccess.GetVehicleById(vehicleId); return View(data); } [HttpGet] public IActionResult AddVehiclePartialView() { return PartialView("_VehicleModal", new Vehicle()); } [HttpGet] public IActionResult GetEditVehiclePartialViewById(int vehicleId) { var data = _dataAccess.GetVehicleById(vehicleId); return PartialView("_VehicleModal", data); } [HttpPost] public IActionResult SaveVehicle(Vehicle vehicleInput) { try { //move image from temp folder to images folder. vehicleInput.ImageLocation = _fileHelper.MoveFileFromTemp(vehicleInput.ImageLocation, "images/"); //save vehicle. var result = _dataAccess.SaveVehicle(vehicleInput); return Json(result); } catch (Exception ex) { _logger.LogError(ex, "Error Saving Vehicle"); return Json(false); } } [HttpPost] public IActionResult DeleteVehicle(int vehicleId) { //Delete all service records, gas records, notes, etc. var result = _gasRecordDataAccess.DeleteAllGasRecordsByVehicleId(vehicleId) && _serviceRecordDataAccess.DeleteAllServiceRecordsByVehicleId(vehicleId) && _collisionRecordDataAccess.DeleteAllCollisionRecordsByVehicleId(vehicleId) && _taxRecordDataAccess.DeleteAllTaxRecordsByVehicleId(vehicleId) && _noteDataAccess.DeleteNoteByVehicleId(vehicleId) && _dataAccess.DeleteVehicle(vehicleId); return Json(result); } [HttpPost] public IActionResult SaveNoteToVehicle(Note newNote) { //check if there is already an existing note for this vehicle. var existingNote = _noteDataAccess.GetNoteByVehicleId(newNote.VehicleId); if (existingNote.Id != default) { newNote.Id = existingNote.Id; } var result = _noteDataAccess.SaveNoteToVehicleId(newNote); return Json(result); } [HttpGet] public IActionResult GetNoteByVehicleId(int vehicleId) { var existingNote = _noteDataAccess.GetNoteByVehicleId(vehicleId); if (existingNote.Id != default) { return Json(existingNote.NoteText); } return Json(""); } #region "Bulk Imports" [HttpGet] public IActionResult GetBulkImportModalPartialView(string mode) { return PartialView("_BulkDataImporter", mode); } [HttpPost] public IActionResult ImportToVehicleIdFromCsv(int vehicleId, string mode, string fileName) { var fullFileName = _fileHelper.GetFullFilePath(fileName); if (vehicleId == default || string.IsNullOrWhiteSpace(fullFileName)) { return Json(false); } try { using (var reader = new StreamReader(fullFileName)) { var config = new CsvHelper.Configuration.CsvConfiguration(System.Globalization.CultureInfo.InvariantCulture); config.MissingFieldFound = null; config.HeaderValidated = null; using (var csv = new CsvReader(reader, config)) { if (mode == "gas") { var records = csv.GetRecords().ToList(); if (records.Any()) { foreach (GasRecordImport gasRecordToInsert in records) { var convertedGasRecord = new GasRecord() { VehicleId = vehicleId, Date = gasRecordToInsert.Date, Mileage = gasRecordToInsert.Odometer, Gallons = gasRecordToInsert.FuelConsumed, Cost = gasRecordToInsert.Cost }; _gasRecordDataAccess.SaveGasRecordToVehicle(convertedGasRecord); } } } } } return Json(true); } catch (Exception ex) { _logger.LogError(ex, "Error Occurred While Bulk Inserting"); return Json(false); } } #endregion #region "Gas Records" [HttpGet] public IActionResult GetGasRecordsByVehicleId(int vehicleId) { var result = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId); var computedResults = new List(); int previousMileage = 0; //perform computation. for(int i = 0; i < result.Count; i++) { if (i > 0) { var currentObject = result[i]; var deltaMileage = currentObject.Mileage - previousMileage; computedResults.Add(new GasRecordViewModel() { Id = currentObject.Id, VehicleId = currentObject.VehicleId, Date = currentObject.Date.ToShortDateString(), Mileage = currentObject.Mileage, Gallons = currentObject.Gallons, Cost = currentObject.Cost, DeltaMileage = deltaMileage, MilesPerGallon = deltaMileage / currentObject.Gallons, CostPerGallon = (currentObject.Cost / currentObject.Gallons) }); } else { computedResults.Add(new GasRecordViewModel() { Id = result[i].Id, VehicleId = result[i].VehicleId, Date = result[i].Date.ToShortDateString(), Mileage = result[i].Mileage, Gallons = result[i].Gallons, Cost = result[i].Cost, DeltaMileage = 0, MilesPerGallon = 0, CostPerGallon = (result[i].Cost / result[i].Gallons) }); } previousMileage = result[i].Mileage; } return PartialView("_Gas", computedResults); } [HttpPost] public IActionResult SaveGasRecordToVehicleId(GasRecordInput gasRecord) { gasRecord.Files = gasRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); var result = _gasRecordDataAccess.SaveGasRecordToVehicle(gasRecord.ToGasRecord()); return Json(result); } [HttpGet] public IActionResult GetAddGasRecordPartialView() { return PartialView("_GasModal", new GasRecordInput()); } [HttpGet] public IActionResult GetGasRecordForEditById(int gasRecordId) { var result = _gasRecordDataAccess.GetGasRecordById(gasRecordId); var convertedResult = new GasRecordInput { Id = result.Id, Mileage = result.Mileage, VehicleId = result.VehicleId, Cost = result.Cost, Date = result.Date.ToShortDateString(), Files = result.Files, Gallons = result.Gallons }; return PartialView("_GasModal", convertedResult); } [HttpPost] public IActionResult DeleteGasRecordById(int gasRecordId) { var result = _gasRecordDataAccess.DeleteGasRecordById(gasRecordId); return Json(result); } #endregion #region "Service Records" [HttpGet] public IActionResult GetServiceRecordsByVehicleId(int vehicleId) { var result = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId); return PartialView("_ServiceRecords", result); } [HttpPost] public IActionResult SaveServiceRecordToVehicleId(ServiceRecordInput serviceRecord) { //move files from temp. serviceRecord.Files = serviceRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord()); return Json(result); } [HttpGet] public IActionResult GetAddServiceRecordPartialView() { return PartialView("_ServiceRecordModal", new ServiceRecordInput()); } [HttpGet] public IActionResult GetServiceRecordForEditById(int serviceRecordId) { var result = _serviceRecordDataAccess.GetServiceRecordById(serviceRecordId); //convert to Input object. var convertedResult = new ServiceRecordInput { Id = result.Id, Cost = result.Cost, Date = result.Date.ToShortDateString(), Description = result.Description, Mileage = result.Mileage, Notes = result.Notes, VehicleId = result.VehicleId, Files = result.Files }; return PartialView("_ServiceRecordModal", convertedResult); } [HttpPost] public IActionResult DeleteServiceRecordById(int serviceRecordId) { var result = _serviceRecordDataAccess.DeleteServiceRecordById(serviceRecordId); return Json(result); } #endregion #region "Collision Records" [HttpGet] public IActionResult GetCollisionRecordsByVehicleId(int vehicleId) { var result = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId); return PartialView("_CollisionRecords", result); } [HttpPost] public IActionResult SaveCollisionRecordToVehicleId(CollisionRecordInput collisionRecord) { //move files from temp. collisionRecord.Files = collisionRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord()); return Json(result); } [HttpGet] public IActionResult GetAddCollisionRecordPartialView() { return PartialView("_CollisionRecordModal", new CollisionRecordInput()); } [HttpGet] public IActionResult GetCollisionRecordForEditById(int collisionRecordId) { var result = _collisionRecordDataAccess.GetCollisionRecordById(collisionRecordId); //convert to Input object. var convertedResult = new CollisionRecordInput { Id = result.Id, Cost = result.Cost, Date = result.Date.ToShortDateString(), Description = result.Description, Mileage = result.Mileage, Notes = result.Notes, VehicleId = result.VehicleId, Files = result.Files }; return PartialView("_CollisionRecordModal", convertedResult); } [HttpPost] public IActionResult DeleteCollisionRecordById(int collisionRecordId) { var result = _collisionRecordDataAccess.DeleteCollisionRecordById(collisionRecordId); return Json(result); } #endregion #region "Tax Records" [HttpGet] public IActionResult GetTaxRecordsByVehicleId(int vehicleId) { var result = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId); return PartialView("_TaxRecords", result); } [HttpPost] public IActionResult SaveTaxRecordToVehicleId(TaxRecordInput taxRecord) { //move files from temp. taxRecord.Files = taxRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); var result = _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord.ToTaxRecord()); return Json(result); } [HttpGet] public IActionResult GetAddTaxRecordPartialView() { return PartialView("_TaxRecordModal", new TaxRecordInput()); } [HttpGet] public IActionResult GetTaxRecordForEditById(int taxRecordId) { var result = _taxRecordDataAccess.GetTaxRecordById(taxRecordId); //convert to Input object. var convertedResult = new TaxRecordInput { Id = result.Id, Cost = result.Cost, Date = result.Date.ToShortDateString(), Description = result.Description, Notes = result.Notes, VehicleId = result.VehicleId, Files = result.Files }; return PartialView("_TaxRecordModal", convertedResult); } [HttpPost] public IActionResult DeleteTaxRecordById(int taxRecordId) { var result = _taxRecordDataAccess.DeleteTaxRecordById(taxRecordId); return Json(result); } #endregion #region "Reports" [HttpGet] public IActionResult GetReportPartialView() { return PartialView("_Report"); } [HttpGet] public IActionResult GetCostMakeUpForVehicle(int vehicleId, string startDate = "", string endDate = "") { var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId); var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId); var collisionRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId); var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId); if (!string.IsNullOrWhiteSpace(startDate) && !string.IsNullOrWhiteSpace(endDate) && DateTime.TryParse(startDate, out DateTime parsedStartDate) && DateTime.TryParse(endDate, out DateTime parsedEndDate) ) { parsedEndDate = parsedEndDate.AddDays(1).AddSeconds(-1); //if start and end dates are provided then we need to filter the data down. serviceRecords.RemoveAll(x => x.Date < parsedStartDate || x.Date > parsedEndDate); gasRecords.RemoveAll(x => x.Date < parsedStartDate || x.Date > parsedEndDate); collisionRecords.RemoveAll(x => x.Date < parsedStartDate || x.Date > parsedEndDate); taxRecords.RemoveAll(x => x.Date < parsedStartDate || x.Date > parsedEndDate); } var viewModel = new CostMakeUpForVehicle { ServiceRecordSum = serviceRecords.Sum(x => x.Cost), GasRecordSum = gasRecords.Sum(x => x.Cost), CollisionRecordSum = collisionRecords.Sum(x => x.Cost), TaxRecordSum = taxRecords.Sum(x => x.Cost) }; return PartialView("_CostMakeUpReport", viewModel); } public IActionResult GetFuelCostByMonthByVehicle(int vehicleId, int year = 0) { var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId); if (year != default) { gasRecords.RemoveAll(x => x.Date.Year != year); } var groupedGasRecord = gasRecords.GroupBy(x => x.Date.Month).OrderBy(x=>x.Key).Select(x => new GasCostForVehicleByMonth { MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key), Cost = x.Sum(y=>y.Cost) }).ToList(); return PartialView("_GasCostByMonthReport", groupedGasRecord); } #endregion } }