@@ -7,6 +7,7 @@ using CsvHelper;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using CarCareTracker.External.Implementations;
|
||||
using CarCareTracker.MapProfile;
|
||||
|
||||
namespace CarCareTracker.Controllers
|
||||
{
|
||||
@@ -122,12 +123,12 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
#region "Bulk Imports"
|
||||
[HttpGet]
|
||||
public IActionResult GetBulkImportModalPartialView(string mode)
|
||||
public IActionResult GetBulkImportModalPartialView(ImportMode mode)
|
||||
{
|
||||
return PartialView("_BulkDataImporter", mode);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult ImportToVehicleIdFromCsv(int vehicleId, string mode, string fileName)
|
||||
public IActionResult ImportToVehicleIdFromCsv(int vehicleId, ImportMode mode, string fileName)
|
||||
{
|
||||
if (vehicleId == default || string.IsNullOrWhiteSpace(fileName))
|
||||
{
|
||||
@@ -145,81 +146,85 @@ namespace CarCareTracker.Controllers
|
||||
var config = new CsvHelper.Configuration.CsvConfiguration(System.Globalization.CultureInfo.InvariantCulture);
|
||||
config.MissingFieldFound = null;
|
||||
config.HeaderValidated = null;
|
||||
config.PrepareHeaderForMatch = args => { return args.Header.Trim().ToLower(); };
|
||||
using (var csv = new CsvReader(reader, config))
|
||||
{
|
||||
if (mode == "gasrecord")
|
||||
csv.Context.RegisterClassMap<FuellyMapper>();
|
||||
var records = csv.GetRecords<ImportModel>().ToList();
|
||||
if (records.Any())
|
||||
{
|
||||
var records = csv.GetRecords<GasRecordImport>().ToList();
|
||||
if (records.Any())
|
||||
foreach (ImportModel importModel in records)
|
||||
{
|
||||
foreach (GasRecordImport recordToInsert in records)
|
||||
if (mode == ImportMode.GasRecord)
|
||||
{
|
||||
//convert to gas model.
|
||||
var convertedRecord = new GasRecord()
|
||||
{
|
||||
VehicleId = vehicleId,
|
||||
Date = recordToInsert.Date,
|
||||
Mileage = recordToInsert.Odometer,
|
||||
Gallons = recordToInsert.FuelConsumed,
|
||||
Cost = recordToInsert.Cost
|
||||
Date = DateTime.Parse(importModel.Date),
|
||||
Mileage = int.Parse(importModel.Odometer, NumberStyles.Any),
|
||||
Gallons = decimal.Parse(importModel.FuelConsumed, NumberStyles.Any)
|
||||
};
|
||||
_gasRecordDataAccess.SaveGasRecordToVehicle(convertedRecord);
|
||||
if (string.IsNullOrWhiteSpace(importModel.Cost) && !string.IsNullOrWhiteSpace(importModel.Price))
|
||||
{
|
||||
//cost was not given but price is.
|
||||
//fuelly sometimes exports CSVs without total cost.
|
||||
var parsedPrice = decimal.Parse(importModel.Price, NumberStyles.Any);
|
||||
convertedRecord.Cost = convertedRecord.Gallons * parsedPrice;
|
||||
} else
|
||||
{
|
||||
convertedRecord.Cost = decimal.Parse(importModel.Cost, NumberStyles.Any);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(importModel.IsFillToFull) && !string.IsNullOrWhiteSpace(importModel.PartialFuelUp))
|
||||
{
|
||||
var parsedBool = importModel.PartialFuelUp.Trim() == "1";
|
||||
convertedRecord.IsFillToFull = !parsedBool;
|
||||
} else if (!string.IsNullOrWhiteSpace(importModel.IsFillToFull))
|
||||
{
|
||||
var parsedBool = importModel.IsFillToFull.Trim() == "1" || importModel.IsFillToFull.Trim() == "Full";
|
||||
convertedRecord.IsFillToFull = parsedBool;
|
||||
}
|
||||
//insert record into db, check to make sure fuelconsumed is not zero so we don't get a divide by zero error.
|
||||
if (convertedRecord.Gallons > 0)
|
||||
{
|
||||
_gasRecordDataAccess.SaveGasRecordToVehicle(convertedRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mode == "servicerecord")
|
||||
{
|
||||
var records = csv.GetRecords<ServiceRecordImport>().ToList();
|
||||
if (records.Any())
|
||||
{
|
||||
foreach (ServiceRecordImport recordToInsert in records)
|
||||
else if (mode == ImportMode.ServiceRecord)
|
||||
{
|
||||
var convertedRecord = new ServiceRecord()
|
||||
{
|
||||
VehicleId = vehicleId,
|
||||
Date = recordToInsert.Date,
|
||||
Mileage = recordToInsert.Odometer,
|
||||
Description = recordToInsert.Description,
|
||||
Notes = recordToInsert.Notes,
|
||||
Cost = recordToInsert.Cost
|
||||
Date = DateTime.Parse(importModel.Date),
|
||||
Mileage = int.Parse(importModel.Odometer, NumberStyles.Any),
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Service Record on {importModel.Date}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
|
||||
};
|
||||
_serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mode == "repairrecord")
|
||||
{
|
||||
var records = csv.GetRecords<ServiceRecordImport>().ToList();
|
||||
if (records.Any())
|
||||
{
|
||||
foreach (ServiceRecordImport recordToInsert in records)
|
||||
else if (mode == ImportMode.RepairRecord)
|
||||
{
|
||||
var convertedRecord = new CollisionRecord()
|
||||
{
|
||||
VehicleId = vehicleId,
|
||||
Date = recordToInsert.Date,
|
||||
Mileage = recordToInsert.Odometer,
|
||||
Description = recordToInsert.Description,
|
||||
Notes = recordToInsert.Notes,
|
||||
Cost = recordToInsert.Cost
|
||||
Date = DateTime.Parse(importModel.Date),
|
||||
Mileage = int.Parse(importModel.Odometer, NumberStyles.Any),
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Repair Record on {importModel.Date}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
|
||||
};
|
||||
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(convertedRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mode == "taxrecord")
|
||||
{
|
||||
var records = csv.GetRecords<TaxRecordImport>().ToList();
|
||||
if (records.Any())
|
||||
{
|
||||
foreach (TaxRecordImport recordToInsert in records)
|
||||
else if (mode == ImportMode.TaxRecord)
|
||||
{
|
||||
var convertedRecord = new TaxRecord()
|
||||
{
|
||||
VehicleId = vehicleId,
|
||||
Date = recordToInsert.Date,
|
||||
Description = recordToInsert.Description,
|
||||
Notes = recordToInsert.Notes,
|
||||
Cost = recordToInsert.Cost
|
||||
Date = DateTime.Parse(importModel.Date),
|
||||
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Tax Record on {importModel.Date}" : importModel.Description,
|
||||
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
|
||||
};
|
||||
_taxRecordDataAccess.SaveTaxRecordToVehicle(convertedRecord);
|
||||
}
|
||||
@@ -274,7 +279,8 @@ namespace CarCareTracker.Controllers
|
||||
//reset unFactored vars
|
||||
unFactoredConsumption = 0;
|
||||
unFactoredMileage = 0;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
unFactoredConsumption += currentObject.Gallons;
|
||||
unFactoredMileage += deltaMileage;
|
||||
@@ -581,7 +587,7 @@ namespace CarCareTracker.Controllers
|
||||
var currentMileage = GetMaxMileage(vehicleId);
|
||||
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
|
||||
List<ReminderRecordViewModel> reminderViewModels = new List<ReminderRecordViewModel>();
|
||||
foreach(var reminder in reminders)
|
||||
foreach (var reminder in reminders)
|
||||
{
|
||||
var reminderViewModel = new ReminderRecordViewModel()
|
||||
{
|
||||
@@ -622,12 +628,13 @@ namespace CarCareTracker.Controllers
|
||||
reminderViewModel.Urgency = ReminderUrgency.Urgent;
|
||||
reminderViewModel.Metric = ReminderMetric.Date;
|
||||
}
|
||||
else if (reminder.Mileage < currentMileage + 100)
|
||||
else if (reminder.Mileage < currentMileage + 100)
|
||||
{
|
||||
reminderViewModel.Urgency = ReminderUrgency.Urgent;
|
||||
reminderViewModel.Metric = ReminderMetric.Odometer;
|
||||
}
|
||||
} else if (reminder.Metric == ReminderMetric.Date)
|
||||
}
|
||||
else if (reminder.Metric == ReminderMetric.Date)
|
||||
{
|
||||
if (reminder.Date < DateTime.Now)
|
||||
{
|
||||
@@ -641,7 +648,8 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
reminderViewModel.Urgency = ReminderUrgency.Urgent;
|
||||
}
|
||||
} else if (reminder.Metric == ReminderMetric.Odometer)
|
||||
}
|
||||
else if (reminder.Metric == ReminderMetric.Odometer)
|
||||
{
|
||||
if (reminder.Mileage < currentMileage)
|
||||
{
|
||||
@@ -665,7 +673,7 @@ namespace CarCareTracker.Controllers
|
||||
public IActionResult GetVehicleHaveUrgentOrPastDueReminders(int vehicleId)
|
||||
{
|
||||
var result = GetRemindersAndUrgency(vehicleId);
|
||||
if (result.Where(x=>x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue).Any())
|
||||
if (result.Where(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue).Any())
|
||||
{
|
||||
return Json(true);
|
||||
}
|
||||
@@ -675,7 +683,7 @@ namespace CarCareTracker.Controllers
|
||||
public IActionResult GetReminderRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
var result = GetRemindersAndUrgency(vehicleId);
|
||||
result = result.OrderByDescending(x=>x.Urgency).ToList();
|
||||
result = result.OrderByDescending(x => x.Urgency).ToList();
|
||||
return PartialView("_ReminderRecords", result);
|
||||
}
|
||||
[HttpPost]
|
||||
|
||||
10
Enum/ImportMode.cs
Normal file
10
Enum/ImportMode.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public enum ImportMode
|
||||
{
|
||||
ServiceRecord = 0,
|
||||
RepairRecord = 1,
|
||||
GasRecord = 2,
|
||||
TaxRecord = 3
|
||||
}
|
||||
}
|
||||
21
MapProfile/FuellyMappers.cs
Normal file
21
MapProfile/FuellyMappers.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using CarCareTracker.Models;
|
||||
using CsvHelper.Configuration;
|
||||
|
||||
namespace CarCareTracker.MapProfile
|
||||
{
|
||||
public class FuellyMapper: ClassMap<ImportModel>
|
||||
{
|
||||
public FuellyMapper()
|
||||
{
|
||||
Map(m => m.Date).Name(["date", "fuelup_date"]);
|
||||
Map(m => m.Odometer).Name(["odometer"]);
|
||||
Map(m => m.FuelConsumed).Name(["gallons", "liters", "litres"]);
|
||||
Map(m => m.Cost).Name(["cost", "total cost", "totalcost"]);
|
||||
Map(m => m.Notes).Name("notes", "note");
|
||||
Map(m => m.Price).Name(["price"]);
|
||||
Map(m => m.PartialFuelUp).Name(["partial_fuelup"]);
|
||||
Map(m => m.IsFillToFull).Name(["isfilltofull", "filled up"]);
|
||||
Map(m => m.Description).Name(["description"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Models/ImportModel.cs
Normal file
18
Models/ImportModel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Import model used for importing Gas records.
|
||||
/// </summary>
|
||||
public class ImportModel
|
||||
{
|
||||
public string Date { get; set; }
|
||||
public string Odometer { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string FuelConsumed { get; set; }
|
||||
public string Cost { get; set; }
|
||||
public string Price { get; set; }
|
||||
public string PartialFuelUp { get; set; }
|
||||
public string IsFillToFull { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Import model used for importing Gas records.
|
||||
/// </summary>
|
||||
public class GasRecordImport
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
public int Odometer { get; set; }
|
||||
public decimal FuelConsumed { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Import model used for importing Service and Repair records.
|
||||
/// </summary>
|
||||
public class ServiceRecordImport
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
public int Odometer { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Import model used for importing tax records.
|
||||
/// </summary>
|
||||
public class TaxRecordImport
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@model string
|
||||
@model ImportMode
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Import Data from CSV</h5>
|
||||
<button type="button" class="btn-close" onclick="hideBulkImportModal()" aria-label="Close"></button>
|
||||
@@ -16,13 +16,13 @@
|
||||
<div class="alert alert-danger" role="alert">
|
||||
Failure to format the data correctly can cause data corruption. Please make sure you make a copy of the local database before proceeding.
|
||||
</div>
|
||||
@if (Model == "gasrecord")
|
||||
@if (Model == ImportMode.GasRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/gassample.csv" target="_blank">Download Sample</a>
|
||||
} else if (Model == "servicerecord" || Model == "repairrecord")
|
||||
} else if (Model == ImportMode.ServiceRecord || Model == ImportMode.RepairRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/servicerecordsample.csv" target="_blank">Download Sample</a>
|
||||
} else if (Model == "taxrecord")
|
||||
} else if (Model == ImportMode.TaxRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/taxrecordsample.csv" target="_blank">Download Sample</a>
|
||||
}
|
||||
@@ -52,13 +52,13 @@
|
||||
if (data) {
|
||||
successToast("Data Imported Successfully");
|
||||
hideBulkImportModal();
|
||||
if (mode == "gasrecord") {
|
||||
if (mode == "GasRecord") {
|
||||
getVehicleGasRecords(vehicleId);
|
||||
} else if (mode == "servicerecord") {
|
||||
} else if (mode == "ServiceRecord") {
|
||||
getVehicleServiceRecords(vehicleId);
|
||||
} else if (mode == "repairrecord") {
|
||||
} else if (mode == "RepairRecord") {
|
||||
getVehicleCollisionRecords(vehicleId);
|
||||
} else if (mode == "taxrecord") {
|
||||
} else if (mode == "TaxRecord") {
|
||||
getVehicleTaxRecords(vehicleId);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<span class="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('repairrecord')">Import via CSV</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('RepairRecord')">Import via CSV</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<span class="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('gasrecord')">Import via CSV</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('GasRecord')">Import via CSV</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<span class="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('servicerecord')">Import via CSV</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('ServiceRecord')">Import via CSV</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"UseDarkMode":true,"UsekWh":false,"EnableCsvImports":false,"UseMPG":true,"UseDescending":false,"EnableAuth":false,"UserNameHash":"","UserPasswordHash":""}
|
||||
{"UseDarkMode":true,"EnableCsvImports":false,"UseMPG":true,"UseDescending":false,"EnableAuth":false,"UserNameHash":"","UserPasswordHash":""}
|
||||
Reference in New Issue
Block a user