mirror of
https://github.com/hargata/lubelog.git
synced 2025-12-10 00:46:08 -06:00
commit
e1a5a871ae
@ -46,12 +46,25 @@ namespace CarCareTracker.Controllers
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult DeleteFiles(string fileLocation)
|
||||
public IActionResult DeleteFiles(string fileLocation)
|
||||
{
|
||||
var result = _fileHelper.DeleteFile(fileLocation);
|
||||
return Json(result);
|
||||
}
|
||||
|
||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||
[HttpGet]
|
||||
public IActionResult MakeBackup()
|
||||
{
|
||||
var result = _fileHelper.MakeBackup();
|
||||
return Json(result);
|
||||
}
|
||||
[Authorize(Roles = nameof(UserData.IsRootUser))]
|
||||
[HttpPost]
|
||||
public IActionResult RestoreBackup(string fileName)
|
||||
{
|
||||
var result = _fileHelper.RestoreBackup(fileName);
|
||||
return Json(result);
|
||||
}
|
||||
private string UploadFile(IFormFile fileToUpload)
|
||||
{
|
||||
string uploadDirectory = "temp/";
|
||||
|
||||
@ -25,6 +25,7 @@ namespace CarCareTracker.Controllers
|
||||
private readonly ITaxRecordDataAccess _taxRecordDataAccess;
|
||||
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
|
||||
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
|
||||
private readonly ISupplyRecordDataAccess _supplyRecordDataAccess;
|
||||
private readonly IWebHostEnvironment _webEnv;
|
||||
private readonly bool _useDescending;
|
||||
private readonly IConfigHelper _config;
|
||||
@ -47,6 +48,7 @@ namespace CarCareTracker.Controllers
|
||||
ITaxRecordDataAccess taxRecordDataAccess,
|
||||
IReminderRecordDataAccess reminderRecordDataAccess,
|
||||
IUpgradeRecordDataAccess upgradeRecordDataAccess,
|
||||
ISupplyRecordDataAccess supplyRecordDataAccess,
|
||||
IUserLogic userLogic,
|
||||
IWebHostEnvironment webEnv,
|
||||
IConfigHelper config)
|
||||
@ -64,6 +66,7 @@ namespace CarCareTracker.Controllers
|
||||
_taxRecordDataAccess = taxRecordDataAccess;
|
||||
_reminderRecordDataAccess = reminderRecordDataAccess;
|
||||
_upgradeRecordDataAccess = upgradeRecordDataAccess;
|
||||
_supplyRecordDataAccess = supplyRecordDataAccess;
|
||||
_userLogic = userLogic;
|
||||
_webEnv = webEnv;
|
||||
_config = config;
|
||||
@ -133,6 +136,7 @@ namespace CarCareTracker.Controllers
|
||||
_noteDataAccess.DeleteAllNotesByVehicleId(vehicleId) &&
|
||||
_reminderRecordDataAccess.DeleteAllReminderRecordsByVehicleId(vehicleId) &&
|
||||
_upgradeRecordDataAccess.DeleteAllUpgradeRecordsByVehicleId(vehicleId) &&
|
||||
_supplyRecordDataAccess.DeleteAllSupplyRecordsByVehicleId(vehicleId) &&
|
||||
_userLogic.DeleteAllAccessToVehicle(vehicleId) &&
|
||||
_dataAccess.DeleteVehicle(vehicleId);
|
||||
return Json(result);
|
||||
@ -209,7 +213,33 @@ namespace CarCareTracker.Controllers
|
||||
return Json($"/{fileNameToExport}");
|
||||
}
|
||||
}
|
||||
else if (mode == ImportMode.TaxRecord) {
|
||||
else if (mode == ImportMode.SupplyRecord)
|
||||
{
|
||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
||||
var vehicleRecords = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicleId);
|
||||
if (vehicleRecords.Any())
|
||||
{
|
||||
var exportData = vehicleRecords.Select(x => new SupplyRecordExportModel {
|
||||
Date = x.Date.ToShortDateString(),
|
||||
Description = x.Description,
|
||||
Cost = x.Cost.ToString("C"),
|
||||
PartNumber = x.PartNumber,
|
||||
PartQuantity = x.Quantity.ToString(),
|
||||
PartSupplier = x.PartSupplier,
|
||||
Notes = x.Notes });
|
||||
using (var writer = new StreamWriter(fullExportFilePath))
|
||||
{
|
||||
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
|
||||
{
|
||||
csv.WriteRecords(exportData);
|
||||
}
|
||||
}
|
||||
return Json($"/{fileNameToExport}");
|
||||
}
|
||||
}
|
||||
else if (mode == ImportMode.TaxRecord)
|
||||
{
|
||||
var fileNameToExport = $"temp/{Guid.NewGuid()}.csv";
|
||||
var fullExportFilePath = _fileHelper.GetFullFilePath(fileNameToExport, false);
|
||||
var vehicleRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
|
||||
@ -235,11 +265,12 @@ namespace CarCareTracker.Controllers
|
||||
bool useUKMPG = _config.GetUserConfig(User).UseUKMPG;
|
||||
vehicleRecords = vehicleRecords.OrderBy(x => x.Date).ThenBy(x => x.Mileage).ToList();
|
||||
var convertedRecords = _gasHelper.GetGasRecordViewModels(vehicleRecords, useMPG, useUKMPG);
|
||||
var exportData = convertedRecords.Select(x => new GasRecordExportModel {
|
||||
Date = x.Date.ToString(),
|
||||
Cost = x.Cost.ToString(),
|
||||
FuelConsumed = x.Gallons.ToString(),
|
||||
FuelEconomy = x.MilesPerGallon.ToString(),
|
||||
var exportData = convertedRecords.Select(x => new GasRecordExportModel
|
||||
{
|
||||
Date = x.Date.ToString(),
|
||||
Cost = x.Cost.ToString(),
|
||||
FuelConsumed = x.Gallons.ToString(),
|
||||
FuelEconomy = x.MilesPerGallon.ToString(),
|
||||
Odometer = x.Mileage.ToString(),
|
||||
IsFillToFull = x.IsFillToFull.ToString(),
|
||||
MissedFuelUp = x.MissedFuelUp.ToString()
|
||||
@ -278,7 +309,7 @@ namespace CarCareTracker.Controllers
|
||||
config.PrepareHeaderForMatch = args => { return args.Header.Trim().ToLower(); };
|
||||
using (var csv = new CsvReader(reader, config))
|
||||
{
|
||||
csv.Context.RegisterClassMap<FuellyMapper>();
|
||||
csv.Context.RegisterClassMap<ImportMapper>();
|
||||
var records = csv.GetRecords<ImportModel>().ToList();
|
||||
if (records.Any())
|
||||
{
|
||||
@ -300,7 +331,8 @@ namespace CarCareTracker.Controllers
|
||||
//fuelly sometimes exports CSVs without total cost.
|
||||
var parsedPrice = decimal.Parse(importModel.Price, NumberStyles.Any);
|
||||
convertedRecord.Cost = convertedRecord.Gallons * parsedPrice;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
convertedRecord.Cost = decimal.Parse(importModel.Cost, NumberStyles.Any);
|
||||
}
|
||||
@ -308,7 +340,8 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
var parsedBool = importModel.PartialFuelUp.Trim() == "1";
|
||||
convertedRecord.IsFillToFull = !parsedBool;
|
||||
} else if (!string.IsNullOrWhiteSpace(importModel.IsFillToFull))
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(importModel.IsFillToFull))
|
||||
{
|
||||
var possibleFillToFullValues = new List<string> { "1", "true", "full" };
|
||||
var parsedBool = possibleFillToFullValues.Contains(importModel.IsFillToFull.Trim().ToLower());
|
||||
@ -365,6 +398,21 @@ namespace CarCareTracker.Controllers
|
||||
};
|
||||
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(convertedRecord);
|
||||
}
|
||||
else if (mode == ImportMode.SupplyRecord)
|
||||
{
|
||||
var convertedRecord = new SupplyRecord()
|
||||
{
|
||||
VehicleId = vehicleId,
|
||||
Date = DateTime.Parse(importModel.Date),
|
||||
PartNumber = importModel.PartNumber,
|
||||
PartSupplier = importModel.PartSupplier,
|
||||
Quantity = decimal.Parse(importModel.PartQuantity, NumberStyles.Any),
|
||||
Description = importModel.Description,
|
||||
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
|
||||
Notes = importModel.Notes
|
||||
};
|
||||
_supplyRecordDataAccess.SaveSupplyRecordToVehicle(convertedRecord);
|
||||
}
|
||||
else if (mode == ImportMode.TaxRecord)
|
||||
{
|
||||
var convertedRecord = new TaxRecord()
|
||||
@ -678,9 +726,9 @@ namespace CarCareTracker.Controllers
|
||||
{
|
||||
numbersArray.Add(upgradeRecords.Min(x => x.Date.Year));
|
||||
}
|
||||
var minYear = numbersArray.Any() ? numbersArray.Min() : DateTime.Now.AddYears(-5).Year;
|
||||
var minYear = numbersArray.Any() ? numbersArray.Min() : DateTime.Now.AddYears(-5).Year;
|
||||
var yearDifference = DateTime.Now.Year - minYear + 1;
|
||||
for(int i = 0; i < yearDifference; i++)
|
||||
for (int i = 0; i < yearDifference; i++)
|
||||
{
|
||||
viewModel.Years.Add(DateTime.Now.AddYears(i * -1).Year);
|
||||
}
|
||||
@ -691,16 +739,16 @@ namespace CarCareTracker.Controllers
|
||||
var userConfig = _config.GetUserConfig(User);
|
||||
var mileageData = _gasHelper.GetGasRecordViewModels(gasRecords, userConfig.UseMPG, userConfig.UseUKMPG);
|
||||
mileageData.RemoveAll(x => x.MilesPerGallon == default);
|
||||
var monthlyMileageData = mileageData.GroupBy(x=>x.MonthId).OrderBy(x => x.Key).Select(x => new CostForVehicleByMonth
|
||||
var monthlyMileageData = mileageData.GroupBy(x => x.MonthId).OrderBy(x => x.Key).Select(x => new CostForVehicleByMonth
|
||||
{
|
||||
MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key),
|
||||
Cost = x.Average(y=>y.MilesPerGallon)
|
||||
Cost = x.Average(y => y.MilesPerGallon)
|
||||
}).ToList();
|
||||
viewModel.FuelMileageForVehicleByMonth = monthlyMileageData;
|
||||
return PartialView("_Report", viewModel);
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
[HttpGet]
|
||||
public IActionResult GetCollaboratorsForVehicle(int vehicleId)
|
||||
{
|
||||
var result = _userLogic.GetCollaboratorsForVehicle(vehicleId);
|
||||
@ -743,7 +791,7 @@ namespace CarCareTracker.Controllers
|
||||
GasRecordSum = gasRecords.Sum(x => x.Cost),
|
||||
CollisionRecordSum = collisionRecords.Sum(x => x.Cost),
|
||||
TaxRecordSum = taxRecords.Sum(x => x.Cost),
|
||||
UpgradeRecordSum = upgradeRecords.Sum(x=>x.Cost)
|
||||
UpgradeRecordSum = upgradeRecords.Sum(x => x.Cost)
|
||||
};
|
||||
return PartialView("_CostMakeUpReport", viewModel);
|
||||
}
|
||||
@ -821,7 +869,7 @@ namespace CarCareTracker.Controllers
|
||||
Cost = x.Cost,
|
||||
DataType = ImportMode.TaxRecord
|
||||
}));
|
||||
vehicleHistory.VehicleHistory = reportData.OrderBy(x=>x.Date).ThenBy(x=>x.Odometer).ToList();
|
||||
vehicleHistory.VehicleHistory = reportData.OrderBy(x => x.Date).ThenBy(x => x.Odometer).ToList();
|
||||
return PartialView("_VehicleHistory", vehicleHistory);
|
||||
}
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
@ -1062,5 +1110,61 @@ namespace CarCareTracker.Controllers
|
||||
return Json(result);
|
||||
}
|
||||
#endregion
|
||||
#region "Supply Records"
|
||||
[TypeFilter(typeof(CollaboratorFilter))]
|
||||
[HttpGet]
|
||||
public IActionResult GetSupplyRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
var result = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicleId);
|
||||
if (_useDescending)
|
||||
{
|
||||
result = result.OrderByDescending(x => x.Date).ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result.OrderBy(x => x.Date).ToList();
|
||||
}
|
||||
return PartialView("_SupplyRecords", result);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult SaveSupplyRecordToVehicleId(SupplyRecordInput supplyRecord)
|
||||
{
|
||||
//move files from temp.
|
||||
supplyRecord.Files = supplyRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
|
||||
var result = _supplyRecordDataAccess.SaveSupplyRecordToVehicle(supplyRecord.ToSupplyRecord());
|
||||
return Json(result);
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetAddSupplyRecordPartialView()
|
||||
{
|
||||
return PartialView("_SupplyRecordModal", new SupplyRecordInput());
|
||||
}
|
||||
[HttpGet]
|
||||
public IActionResult GetSupplyRecordForEditById(int supplyRecordId)
|
||||
{
|
||||
var result = _supplyRecordDataAccess.GetSupplyRecordById(supplyRecordId);
|
||||
//convert to Input object.
|
||||
var convertedResult = new SupplyRecordInput
|
||||
{
|
||||
Id = result.Id,
|
||||
Cost = result.Cost,
|
||||
Date = result.Date.ToShortDateString(),
|
||||
Description = result.Description,
|
||||
PartNumber = result.PartNumber,
|
||||
Quantity = result.Quantity,
|
||||
PartSupplier = result.PartSupplier,
|
||||
Notes = result.Notes,
|
||||
VehicleId = result.VehicleId,
|
||||
Files = result.Files
|
||||
};
|
||||
return PartialView("_SupplyRecordModal", convertedResult);
|
||||
}
|
||||
[HttpPost]
|
||||
public IActionResult DeleteSupplyRecordById(int supplyRecordId)
|
||||
{
|
||||
var result = _supplyRecordDataAccess.DeleteSupplyRecordById(supplyRecordId);
|
||||
return Json(result);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,10 @@
|
||||
RepairRecord = 1,
|
||||
GasRecord = 2,
|
||||
TaxRecord = 3,
|
||||
UpgradeRecord = 4
|
||||
UpgradeRecord = 4,
|
||||
ReminderRecord = 5,
|
||||
NoteRecord = 6,
|
||||
SupplyRecord = 7,
|
||||
Dashboard = 8
|
||||
}
|
||||
}
|
||||
|
||||
57
External/Implementations/SupplyRecordDataAccess.cs
vendored
Normal file
57
External/Implementations/SupplyRecordDataAccess.cs
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
using CarCareTracker.External.Interfaces;
|
||||
using CarCareTracker.Helper;
|
||||
using CarCareTracker.Models;
|
||||
using LiteDB;
|
||||
|
||||
namespace CarCareTracker.External.Implementations
|
||||
{
|
||||
public class SupplyRecordDataAccess : ISupplyRecordDataAccess
|
||||
{
|
||||
private static string dbName = StaticHelper.DbName;
|
||||
private static string tableName = "supplyrecords";
|
||||
public List<SupplyRecord> GetSupplyRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
var supplyRecords = table.Find(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
||||
return supplyRecords.ToList() ?? new List<SupplyRecord>();
|
||||
};
|
||||
}
|
||||
public SupplyRecord GetSupplyRecordById(int supplyRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
return table.FindById(supplyRecordId);
|
||||
};
|
||||
}
|
||||
public bool DeleteSupplyRecordById(int supplyRecordId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
table.Delete(supplyRecordId);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
public bool SaveSupplyRecordToVehicle(SupplyRecord supplyRecord)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
table.Upsert(supplyRecord);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
public bool DeleteAllSupplyRecordsByVehicleId(int vehicleId)
|
||||
{
|
||||
using (var db = new LiteDatabase(dbName))
|
||||
{
|
||||
var table = db.GetCollection<SupplyRecord>(tableName);
|
||||
var supplyRecords = table.DeleteMany(Query.EQ(nameof(SupplyRecord.VehicleId), vehicleId));
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
13
External/Interfaces/ISupplyRecordDataAccess.cs
vendored
Normal file
13
External/Interfaces/ISupplyRecordDataAccess.cs
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
using CarCareTracker.Models;
|
||||
|
||||
namespace CarCareTracker.External.Interfaces
|
||||
{
|
||||
public interface ISupplyRecordDataAccess
|
||||
{
|
||||
public List<SupplyRecord> GetSupplyRecordsByVehicleId(int vehicleId);
|
||||
public SupplyRecord GetSupplyRecordById(int supplyRecordId);
|
||||
public bool DeleteSupplyRecordById(int supplyRecordId);
|
||||
public bool SaveSupplyRecordToVehicle(SupplyRecord supplyRecord);
|
||||
public bool DeleteAllSupplyRecordsByVehicleId(int vehicleId);
|
||||
}
|
||||
}
|
||||
@ -94,7 +94,9 @@ namespace CarCareTracker.Helper
|
||||
EnableAuth = bool.Parse(_config[nameof(UserConfig.EnableAuth)]),
|
||||
HideZero = bool.Parse(_config[nameof(UserConfig.HideZero)]),
|
||||
UseUKMPG = bool.Parse(_config[nameof(UserConfig.UseUKMPG)]),
|
||||
UseThreeDecimalGasCost = bool.Parse(_config[nameof(UserConfig.UseThreeDecimalGasCost)])
|
||||
UseThreeDecimalGasCost = bool.Parse(_config[nameof(UserConfig.UseThreeDecimalGasCost)]),
|
||||
VisibleTabs = _config.GetSection("VisibleTabs").Get<List<ImportMode>>(),
|
||||
DefaultTab = (ImportMode)int.Parse(_config[nameof(UserConfig.DefaultTab)])
|
||||
};
|
||||
int userId = 0;
|
||||
if (user != null)
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
namespace CarCareTracker.Helper
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace CarCareTracker.Helper
|
||||
{
|
||||
public interface IFileHelper
|
||||
{
|
||||
string GetFullFilePath(string currentFilePath, bool mustExist = true);
|
||||
string MoveFileFromTemp(string currentFilePath, string newFolder);
|
||||
bool DeleteFile(string currentFilePath);
|
||||
string MakeBackup();
|
||||
bool RestoreBackup(string fileName);
|
||||
}
|
||||
public class FileHelper: IFileHelper
|
||||
public class FileHelper : IFileHelper
|
||||
{
|
||||
private readonly IWebHostEnvironment _webEnv;
|
||||
public FileHelper(IWebHostEnvironment webEnv)
|
||||
@ -23,7 +27,8 @@
|
||||
if (File.Exists(oldFilePath))
|
||||
{
|
||||
return oldFilePath;
|
||||
} else if (!mustExist)
|
||||
}
|
||||
else if (!mustExist)
|
||||
{
|
||||
return oldFilePath;
|
||||
}
|
||||
@ -31,6 +36,111 @@
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
public bool RestoreBackup(string fileName)
|
||||
{
|
||||
var fullFilePath = GetFullFilePath(fileName);
|
||||
if (string.IsNullOrWhiteSpace(fullFilePath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
var tempPath = Path.Combine(_webEnv.WebRootPath, $"temp/{Guid.NewGuid()}");
|
||||
if (!Directory.Exists(tempPath))
|
||||
Directory.CreateDirectory(tempPath);
|
||||
//extract zip file
|
||||
ZipFile.ExtractToDirectory(fullFilePath, tempPath);
|
||||
//copy over images and documents.
|
||||
var imagePath = Path.Combine(tempPath, "images");
|
||||
var documentPath = Path.Combine(tempPath, "documents");
|
||||
var dataPath = Path.Combine(tempPath, StaticHelper.DbName);
|
||||
var configPath = Path.Combine(tempPath, StaticHelper.UserConfigPath);
|
||||
if (Directory.Exists(imagePath))
|
||||
{
|
||||
var existingPath = Path.Combine(_webEnv.WebRootPath, "images");
|
||||
if (Directory.Exists(existingPath))
|
||||
{
|
||||
Directory.Delete(existingPath, true);
|
||||
}
|
||||
Directory.Move(imagePath, existingPath);
|
||||
}
|
||||
if (Directory.Exists(documentPath))
|
||||
{
|
||||
var existingPath = Path.Combine(_webEnv.WebRootPath, "documents");
|
||||
if (Directory.Exists(existingPath))
|
||||
{
|
||||
Directory.Delete(existingPath, true);
|
||||
}
|
||||
Directory.Move(documentPath, existingPath);
|
||||
}
|
||||
if (File.Exists(dataPath))
|
||||
{
|
||||
//data path will always exist as it is created on startup if not.
|
||||
File.Move(dataPath, StaticHelper.DbName, true);
|
||||
}
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
//check if config folder exists.
|
||||
if (!Directory.Exists("config/"))
|
||||
{
|
||||
Directory.CreateDirectory("config/");
|
||||
}
|
||||
File.Move(configPath, StaticHelper.UserConfigPath, true);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public string MakeBackup()
|
||||
{
|
||||
var folderName = $"db_backup_{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}";
|
||||
var tempPath = Path.Combine(_webEnv.WebRootPath, $"temp/{folderName}");
|
||||
var imagePath = Path.Combine(_webEnv.WebRootPath, "images");
|
||||
var documentPath = Path.Combine(_webEnv.WebRootPath, "documents");
|
||||
var dataPath = StaticHelper.DbName;
|
||||
var configPath = StaticHelper.UserConfigPath;
|
||||
if (!Directory.Exists(tempPath))
|
||||
Directory.CreateDirectory(tempPath);
|
||||
if (Directory.Exists(imagePath))
|
||||
{
|
||||
var files = Directory.GetFiles(imagePath);
|
||||
foreach (var file in files)
|
||||
{
|
||||
var newPath = Path.Combine(tempPath, "images");
|
||||
Directory.CreateDirectory(newPath);
|
||||
File.Copy(file, $"{newPath}/{Path.GetFileName(file)}");
|
||||
}
|
||||
}
|
||||
if (Directory.Exists(documentPath))
|
||||
{
|
||||
var files = Directory.GetFiles(documentPath);
|
||||
foreach (var file in files)
|
||||
{
|
||||
var newPath = Path.Combine(tempPath, "documents");
|
||||
Directory.CreateDirectory(newPath);
|
||||
File.Copy(file, $"{newPath}/{Path.GetFileName(file)}");
|
||||
}
|
||||
}
|
||||
if (File.Exists(dataPath))
|
||||
{
|
||||
var newPath = Path.Combine(tempPath, "data");
|
||||
Directory.CreateDirectory(newPath);
|
||||
File.Copy(dataPath, $"{newPath}/{Path.GetFileName(dataPath)}");
|
||||
}
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
var newPath = Path.Combine(tempPath, "config");
|
||||
Directory.CreateDirectory(newPath);
|
||||
File.Copy(configPath, $"{newPath}/{Path.GetFileName(configPath)}");
|
||||
}
|
||||
var destFilePath = $"{tempPath}.zip";
|
||||
ZipFile.CreateFromDirectory(tempPath, destFilePath);
|
||||
//delete temp directory
|
||||
Directory.Delete(tempPath, true);
|
||||
return $"/temp/{folderName}.zip";
|
||||
}
|
||||
public string MoveFileFromTemp(string currentFilePath, string newFolder)
|
||||
{
|
||||
string tempPath = "temp/";
|
||||
@ -38,7 +148,8 @@
|
||||
{
|
||||
return currentFilePath;
|
||||
}
|
||||
if (currentFilePath.StartsWith("/")) {
|
||||
if (currentFilePath.StartsWith("/"))
|
||||
{
|
||||
currentFilePath = currentFilePath.Substring(1);
|
||||
}
|
||||
string uploadPath = Path.Combine(_webEnv.WebRootPath, newFolder);
|
||||
@ -67,7 +178,8 @@
|
||||
if (!File.Exists(filePath)) //verify file no longer exists.
|
||||
{
|
||||
return true;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
namespace CarCareTracker.Helper
|
||||
using CarCareTracker.Models;
|
||||
|
||||
namespace CarCareTracker.Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// helper method for static vars
|
||||
@ -18,10 +20,48 @@
|
||||
if (input.Length > maxLength)
|
||||
{
|
||||
return (input.Substring(0, maxLength) + "...");
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
return input;
|
||||
}
|
||||
}
|
||||
public static string DefaultActiveTab(UserConfig userConfig, ImportMode tab)
|
||||
{
|
||||
var defaultTab = userConfig.DefaultTab;
|
||||
var visibleTabs = userConfig.VisibleTabs;
|
||||
if (visibleTabs.Contains(tab) && tab == defaultTab)
|
||||
{
|
||||
return "active";
|
||||
}
|
||||
else if (!visibleTabs.Contains(tab))
|
||||
{
|
||||
return "d-none";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
public static string DefaultActiveTabContent(UserConfig userConfig, ImportMode tab)
|
||||
{
|
||||
var defaultTab = userConfig.DefaultTab;
|
||||
if (tab == defaultTab)
|
||||
{
|
||||
return "show active";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
public static string DefaultTabSelected(UserConfig userConfig, ImportMode tab)
|
||||
{
|
||||
var defaultTab = userConfig.DefaultTab;
|
||||
var visibleTabs = userConfig.VisibleTabs;
|
||||
if (!visibleTabs.Contains(tab))
|
||||
{
|
||||
return "disabled";
|
||||
}
|
||||
else if (tab == defaultTab)
|
||||
{
|
||||
return "selected";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,9 +3,9 @@ using CsvHelper.Configuration;
|
||||
|
||||
namespace CarCareTracker.MapProfile
|
||||
{
|
||||
public class FuellyMapper: ClassMap<ImportModel>
|
||||
public class ImportMapper: ClassMap<ImportModel>
|
||||
{
|
||||
public FuellyMapper()
|
||||
public ImportMapper()
|
||||
{
|
||||
Map(m => m.Date).Name(["date", "fuelup_date"]);
|
||||
Map(m => m.Odometer).Name(["odometer"]);
|
||||
@ -17,6 +17,9 @@ namespace CarCareTracker.MapProfile
|
||||
Map(m => m.IsFillToFull).Name(["isfilltofull", "filled up"]);
|
||||
Map(m => m.Description).Name(["description"]);
|
||||
Map(m => m.MissedFuelUp).Name(["missed_fuelup", "missedfuelup"]);
|
||||
Map(m => m.PartSupplier).Name(["partsupplier"]);
|
||||
Map(m => m.PartQuantity).Name(["partquantity"]);
|
||||
Map(m => m.PartNumber).Name(["partnumber"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,20 @@
|
||||
public string PartialFuelUp { get; set; }
|
||||
public string IsFillToFull { get; set; }
|
||||
public string MissedFuelUp { get; set; }
|
||||
public string PartNumber { get; set; }
|
||||
public string PartSupplier { get; set; }
|
||||
public string PartQuantity { get; set; }
|
||||
}
|
||||
|
||||
public class SupplyRecordExportModel
|
||||
{
|
||||
public string Date { get; set; }
|
||||
public string PartNumber { get; set; }
|
||||
public string PartSupplier { get; set; }
|
||||
public string PartQuantity { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Cost { get; set; }
|
||||
public string Notes { get; set; }
|
||||
}
|
||||
|
||||
public class ServiceRecordExportModel
|
||||
|
||||
37
Models/Supply/SupplyRecord.cs
Normal file
37
Models/Supply/SupplyRecord.cs
Normal file
@ -0,0 +1,37 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class SupplyRecord
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
/// <summary>
|
||||
/// When the part or supplies were purchased.
|
||||
/// </summary>
|
||||
public DateTime Date { get; set; }
|
||||
/// <summary>
|
||||
/// Part number can be alphanumeric.
|
||||
/// </summary>
|
||||
public string PartNumber { get; set; }
|
||||
/// <summary>
|
||||
/// Where the part/supplies were purchased from.
|
||||
/// </summary>
|
||||
public string PartSupplier { get; set; }
|
||||
/// <summary>
|
||||
/// Amount purchased, can be partial quantities such as fluids.
|
||||
/// </summary>
|
||||
public decimal Quantity { get; set; }
|
||||
/// <summary>
|
||||
/// Description of the part/supplies purchased.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
/// <summary>
|
||||
/// How much it costs
|
||||
/// </summary>
|
||||
public decimal Cost { get; set; }
|
||||
/// <summary>
|
||||
/// Additional notes.
|
||||
/// </summary>
|
||||
public string Notes { get; set; }
|
||||
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||
}
|
||||
}
|
||||
27
Models/Supply/SupplyRecordInput.cs
Normal file
27
Models/Supply/SupplyRecordInput.cs
Normal file
@ -0,0 +1,27 @@
|
||||
namespace CarCareTracker.Models
|
||||
{
|
||||
public class SupplyRecordInput
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int VehicleId { get; set; }
|
||||
public string Date { get; set; } = DateTime.Now.ToShortDateString();
|
||||
public string PartNumber { get; set; }
|
||||
public string PartSupplier { get; set; }
|
||||
public decimal Quantity { get; set; }
|
||||
public string Description { get; set; }
|
||||
public decimal Cost { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
|
||||
public SupplyRecord ToSupplyRecord() { return new SupplyRecord {
|
||||
Id = Id,
|
||||
VehicleId = VehicleId,
|
||||
Date = DateTime.Parse(Date),
|
||||
Cost = Cost,
|
||||
PartNumber = PartNumber,
|
||||
PartSupplier = PartSupplier,
|
||||
Quantity = Quantity,
|
||||
Description = Description,
|
||||
Notes = Notes,
|
||||
Files = Files }; }
|
||||
}
|
||||
}
|
||||
@ -12,5 +12,15 @@
|
||||
public bool UseThreeDecimalGasCost { get; set; }
|
||||
public string UserNameHash { get; set; }
|
||||
public string UserPasswordHash { get; set;}
|
||||
public List<ImportMode> VisibleTabs { get; set; } = new List<ImportMode>() {
|
||||
ImportMode.Dashboard,
|
||||
ImportMode.ServiceRecord,
|
||||
ImportMode.RepairRecord,
|
||||
ImportMode.GasRecord,
|
||||
ImportMode.UpgradeRecord,
|
||||
ImportMode.TaxRecord,
|
||||
ImportMode.ReminderRecord,
|
||||
ImportMode.NoteRecord};
|
||||
public ImportMode DefaultTab { get; set; } = ImportMode.Dashboard;
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,7 @@ builder.Services.AddSingleton<IUserRecordDataAccess, UserRecordDataAccess>();
|
||||
builder.Services.AddSingleton<ITokenRecordDataAccess, TokenRecordDataAccess>();
|
||||
builder.Services.AddSingleton<IUserAccessDataAccess, UserAccessDataAccess>();
|
||||
builder.Services.AddSingleton<IUserConfigDataAccess, UserConfigDataAccess>();
|
||||
builder.Services.AddSingleton<ISupplyRecordDataAccess, SupplyRecordDataAccess>();
|
||||
|
||||
//configure helpers
|
||||
builder.Services.AddSingleton<IFileHelper, FileHelper>();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
@model UserConfig
|
||||
@using CarCareTracker.Helper
|
||||
@model UserConfig
|
||||
|
||||
<div class="row">
|
||||
<div class="d-flex justify-content-center">
|
||||
@ -22,8 +23,6 @@
|
||||
<input class="form-check-input" onChange="updateSettings()" type="checkbox" role="switch" id="useUKMPG" checked="@Model.UseUKMPG">
|
||||
<label class="form-check-label" for="useUKMPG">Use UK MPG Calculation<br /><small class="text-body-secondary">Input Gas Consumption in Liters, it will be converted to UK Gals for MPG Calculation</small></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" onChange="updateSettings()" type="checkbox" role="switch" id="useDescending" checked="@Model.UseDescending">
|
||||
<label class="form-check-label" for="useDescending">Sort lists in Descending Order(Newest to Oldest)</label>
|
||||
@ -44,6 +43,88 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="row" id="visibleTabs">
|
||||
<div class="col-12">
|
||||
<span class="lead">Visible Tabs</span>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="ServiceRecord" id="serviceRecordTab" @(Model.VisibleTabs.Contains(ImportMode.ServiceRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="serviceRecordTab">Service Records</label>
|
||||
</li>
|
||||
<li class="list-group-item d-none">
|
||||
<input onChange="updateSettings()" disabled class="form-check-input me-1" type="checkbox" value="Dashboard" id="dashboardTab" @(Model.VisibleTabs.Contains(ImportMode.Dashboard) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="dashboardTab">Dashboard</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="RepairRecord" id="repairRecordTab" @(Model.VisibleTabs.Contains(ImportMode.RepairRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="repairRecordTab">Repairs</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="UpgradeRecord" id="upgradeRecordTab" @(Model.VisibleTabs.Contains(ImportMode.UpgradeRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="upgradeRecordTab">Upgrades</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="GasRecord" id="gasRecordTab" @(Model.VisibleTabs.Contains(ImportMode.GasRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="gasRecordTab">Fuel</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="TaxRecord" id="taxRecordTab" @(Model.VisibleTabs.Contains(ImportMode.TaxRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="taxRecordTab">Taxes</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="NoteRecord" id="noteRecordTab" @(Model.VisibleTabs.Contains(ImportMode.NoteRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="noteRecordTab">Notes</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="ReminderRecord" id="reminderRecordTab" @(Model.VisibleTabs.Contains(ImportMode.ReminderRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="reminderRecordTab">Reminder</label>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<input onChange="updateSettings()" class="form-check-input me-1" type="checkbox" value="SupplyRecord" id="supplyRecordTab" @(Model.VisibleTabs.Contains(ImportMode.SupplyRecord) ? "checked" : "")>
|
||||
<label class="form-check-label stretched-link" for="supplyRecordTab">Supplies</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<span class="lead">Default Tab</span>
|
||||
<select class="form-select" onchange="updateSettings()" id="defaultTab">
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.Dashboard)) value="Dashboard">Dashboard</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model,ImportMode.ServiceRecord)) value="ServiceRecord">Service Record</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.RepairRecord)) value="RepairRecord">Repairs</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.UpgradeRecord)) value="UpgradeRecord">Upgrades</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.GasRecord)) value="GasRecord">Fuel</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.TaxRecord)) value="TaxRecord">Tax</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.NoteRecord)) value="NoteRecord">Notes</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.ReminderRecord)) value="ReminderRecord">Reminders</!option>
|
||||
<!option @(StaticHelper.DefaultTabSelected(Model, ImportMode.SupplyRecord)) value="SupplyRecord">Supplies</!option>
|
||||
</select>
|
||||
</div>
|
||||
@if (User.IsInRole(nameof(UserData.IsRootUser)))
|
||||
{
|
||||
<div class="col-12 col-md-6">
|
||||
<span class="lead">Backups</span>
|
||||
<div class="row">
|
||||
<div class="col-6 d-grid">
|
||||
<button onclick="makeBackup()" class="btn btn-primary btn-md">Make</button>
|
||||
</div>
|
||||
<div class="col-6 d-grid">
|
||||
<input onChange="restoreBackup(this)" type="file" accept=".zip" class="d-none" id="inputBackup">
|
||||
<button onclick="openRestoreBackup()" class="btn btn-secondary btn-md">Restore</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="d-flex justify-content-center">
|
||||
@ -86,7 +167,18 @@
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function getCheckedTabs() {
|
||||
var visibleTabs = $("#visibleTabs :checked").map(function () {
|
||||
return this.value;
|
||||
});
|
||||
return visibleTabs.toArray();
|
||||
}
|
||||
function updateSettings(){
|
||||
var visibleTabs = getCheckedTabs();
|
||||
var defaultTab = $("#defaultTab").val();
|
||||
if (!visibleTabs.includes(defaultTab)){
|
||||
defaultTab = "Dashboard"; //default to dashboard.
|
||||
}
|
||||
var userConfigObject = {
|
||||
useDarkMode: $("#enableDarkMode").is(':checked'),
|
||||
enableCsvImports: $("#enableCsvImports").is(':checked'),
|
||||
@ -94,9 +186,13 @@
|
||||
useDescending: $("#useDescending").is(':checked'),
|
||||
hideZero: $("#hideZero").is(":checked"),
|
||||
useUKMpg: $("#useUKMPG").is(":checked"),
|
||||
useThreeDecimalGasCost: $("#useThreeDecimal").is(":checked")
|
||||
useThreeDecimalGasCost: $("#useThreeDecimal").is(":checked"),
|
||||
visibleTabs: visibleTabs,
|
||||
defaultTab: defaultTab
|
||||
}
|
||||
sloader.show();
|
||||
$.post('/Home/WriteToSettings', { userConfig: userConfigObject}, function(data){
|
||||
sloader.hide();
|
||||
if (data) {
|
||||
setTimeout(function () { window.location.href = '/Home/Index?tab=settings' }, 500);
|
||||
} else {
|
||||
@ -104,6 +200,40 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
function makeBackup() {
|
||||
$.get('/Files/MakeBackup', function (data) {
|
||||
window.location.href = data;
|
||||
});
|
||||
}
|
||||
function openRestoreBackup(){
|
||||
$("#inputBackup").click();
|
||||
}
|
||||
function restoreBackup(event) {
|
||||
let formData = new FormData();
|
||||
formData.append("file", event.files[0]);
|
||||
sloader.show();
|
||||
$.ajax({
|
||||
url: "/Files/HandleFileUpload",
|
||||
data: formData,
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
type: 'POST',
|
||||
success: function (response) {
|
||||
if (response.trim() != '') {
|
||||
$.post('/Files/RestoreBackup', { fileName : response}, function (data) {
|
||||
sloader.hide();
|
||||
if (data){
|
||||
successToast("Backup Restored");
|
||||
setTimeout(function () { window.location.href = '/Home/Index' }, 500);
|
||||
} else {
|
||||
errorToast("An error occurred, please try again later.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function enableAuthCheckChanged(){
|
||||
var enableAuth = $("#enableAuth").is(":checked");
|
||||
if (enableAuth) {
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
@{
|
||||
@using CarCareTracker.Helper
|
||||
@{
|
||||
ViewData["Title"] = "LubeLogger - View Vehicle";
|
||||
}
|
||||
@inject IConfigHelper config
|
||||
@{
|
||||
var userConfig = config.GetUserConfig(User);
|
||||
}
|
||||
@model Vehicle
|
||||
@section Scripts {
|
||||
<script src="~/js/vehicle.js" asp-append-version="true"></script>
|
||||
@ -12,6 +17,7 @@
|
||||
<script src="~/js/upgraderecord.js" asp-append-version="true"></script>
|
||||
<script src="~/js/note.js" asp-append-version="true"></script>
|
||||
<script src="~/js/reports.js" asp-append-version="true"></script>
|
||||
<script src="~/js/supplyrecord.js" asp-append-version="true"></script>
|
||||
<script src="~/lib/chart-js/chart.umd.js"></script>
|
||||
}
|
||||
<div class="lubelogger-mobile-nav" onclick="hideMobileNav()">
|
||||
@ -23,28 +29,31 @@
|
||||
<button class="nav-link" onclick="editVehicle(@Model.Id)"><span class="display-3 ms-2"><i class="bi bi-pencil-square"></i>Edit Vehicle</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="report-tab" data-bs-toggle="tab" data-bs-target="#report-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-file-bar-graph me-2"></i>Dashboard</span></button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.Dashboard)" id="report-tab" data-bs-toggle="tab" data-bs-target="#report-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-file-bar-graph me-2"></i>Dashboard</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="servicerecord-tab" data-bs-toggle="tab" data-bs-target="#servicerecord-tab-pane" type="button" role="tab" aria-selected="true"><span class="display-3 ms-2"><i class="bi bi-card-checklist me-2"></i>Service Records</span></button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ServiceRecord)" id="servicerecord-tab" data-bs-toggle="tab" data-bs-target="#servicerecord-tab-pane" type="button" role="tab" aria-selected="true"><span class="display-3 ms-2"><i class="bi bi-card-checklist me-2"></i>Service Records</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="accident-tab" data-bs-toggle="tab" data-bs-target="#accident-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-exclamation-octagon me-2"></i>Repairs</span></button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.RepairRecord)" id="accident-tab" data-bs-toggle="tab" data-bs-target="#accident-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-exclamation-octagon me-2"></i>Repairs</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="upgrade-tab" data-bs-toggle="tab" data-bs-target="#upgrade-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-wrench-adjustable me-2"></i>Upgrades</span></button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.UpgradeRecord)" id="upgrade-tab" data-bs-toggle="tab" data-bs-target="#upgrade-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-wrench-adjustable me-2"></i>Upgrades</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="gas-tab" data-bs-toggle="tab" data-bs-target="#gas-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-fuel-pump me-2"></i>Fuel</span></button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.GasRecord)" id="gas-tab" data-bs-toggle="tab" data-bs-target="#gas-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-fuel-pump me-2"></i>Fuel</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="tax-tab" data-bs-toggle="tab" data-bs-target="#tax-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-currency-dollar me-2"></i>Taxes</span></button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.SupplyRecord)" id="supply-tab" data-bs-toggle="tab" data-bs-target="#supply-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-shop me-2"></i>Supplies</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="notes-tab" data-bs-toggle="tab" data-bs-target="#notes-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-journal-bookmark me-2"></i>Notes</span></button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.TaxRecord)" id="tax-tab" data-bs-toggle="tab" data-bs-target="#tax-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-currency-dollar me-2"></i>Taxes</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="reminder-tab" data-bs-toggle="tab" data-bs-target="#reminder-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><div class="reminderBellDiv" style="display:inline-flex;"><i class="reminderBell bi bi-bell me-2"></i></div>Reminders</span></button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.NoteRecord)" id="notes-tab" data-bs-toggle="tab" data-bs-target="#notes-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><i class="bi bi-journal-bookmark me-2"></i>Notes</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ReminderRecord)" id="reminder-tab" data-bs-toggle="tab" data-bs-target="#reminder-tab-pane" type="button" role="tab" aria-selected="false"><span class="display-3 ms-2"><div class="reminderBellDiv" style="display:inline-flex;"><i class="reminderBell bi bi-bell me-2"></i></div>Reminders</span></button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button onclick="deleteVehicle(@Model.Id)" class="dropdown-item"><span class="display-3 ms-2"><i class="bi bi-trash me-2"></i>Delete Vehicle</span></button>
|
||||
@ -65,28 +74,31 @@
|
||||
<hr />
|
||||
<ul class="nav nav-tabs lubelogger-tab" id="vehicleTab" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="report-tab" data-bs-toggle="tab" data-bs-target="#report-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-file-bar-graph me-2"></i>Dash</button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.Dashboard)" id="report-tab" data-bs-toggle="tab" data-bs-target="#report-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-file-bar-graph me-2"></i>Dash</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="servicerecord-tab" data-bs-toggle="tab" data-bs-target="#servicerecord-tab-pane" type="button" role="tab" aria-selected="true"><i class="bi bi-card-checklist me-2"></i>Service Records</button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ServiceRecord)" id="servicerecord-tab" data-bs-toggle="tab" data-bs-target="#servicerecord-tab-pane" type="button" role="tab" aria-selected="true"><i class="bi bi-card-checklist me-2"></i>Service Records</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="accident-tab" data-bs-toggle="tab" data-bs-target="#accident-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-exclamation-octagon me-2"></i>Repairs</button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.RepairRecord)" id="accident-tab" data-bs-toggle="tab" data-bs-target="#accident-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-exclamation-octagon me-2"></i>Repairs</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="upgrade-tab" data-bs-toggle="tab" data-bs-target="#upgrade-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-wrench-adjustable me-2"></i>Upgrades</button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.UpgradeRecord)" id="upgrade-tab" data-bs-toggle="tab" data-bs-target="#upgrade-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-wrench-adjustable me-2"></i>Upgrades</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="gas-tab" data-bs-toggle="tab" data-bs-target="#gas-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-fuel-pump me-2"></i>Fuel</button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.GasRecord)" id="gas-tab" data-bs-toggle="tab" data-bs-target="#gas-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-fuel-pump me-2"></i>Fuel</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="tax-tab" data-bs-toggle="tab" data-bs-target="#tax-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-currency-dollar me-2"></i>Taxes</button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.SupplyRecord)" id="supply-tab" data-bs-toggle="tab" data-bs-target="#supply-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-shop me-2"></i>Supplies</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="notes-tab" data-bs-toggle="tab" data-bs-target="#notes-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-journal-bookmark me-2"></i>Notes</button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.TaxRecord)" id="tax-tab" data-bs-toggle="tab" data-bs-target="#tax-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-currency-dollar me-2"></i>Taxes</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="reminder-tab" data-bs-toggle="tab" data-bs-target="#reminder-tab-pane" type="button" role="tab" aria-selected="false"><div class="reminderBellDiv" style="display:inline-flex;"><i class="reminderBell bi bi-bell me-2"></i></div>Reminders</button>
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.NoteRecord)" id="notes-tab" data-bs-toggle="tab" data-bs-target="#notes-tab-pane" type="button" role="tab" aria-selected="false"><i class="bi bi-journal-bookmark me-2"></i>Notes</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link @StaticHelper.DefaultActiveTab(userConfig, ImportMode.ReminderRecord)" id="reminder-tab" data-bs-toggle="tab" data-bs-target="#reminder-tab-pane" type="button" role="tab" aria-selected="false"><div class="reminderBellDiv" style="display:inline-flex;"><i class="reminderBell bi bi-bell me-2"></i></div>Reminders</button>
|
||||
</li>
|
||||
<li class="nav-item dropdown ms-auto" role="presentation">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-expanded="false">Manage Vehicle</a>
|
||||
@ -96,14 +108,15 @@
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="vehicleTabContent">
|
||||
<div class="tab-pane fade" id="servicerecord-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="gas-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="tax-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="notes-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="accident-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="reminder-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade show active" id="report-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade" id="upgrade-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.ServiceRecord)" id="servicerecord-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.GasRecord)" id="gas-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.TaxRecord)" id="tax-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.NoteRecord)" id="notes-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.RepairRecord)" id="accident-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.ReminderRecord)" id="reminder-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.Dashboard)" id="report-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.UpgradeRecord)" id="upgrade-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
<div class="tab-pane fade @StaticHelper.DefaultActiveTabContent(userConfig, ImportMode.SupplyRecord)" id="supply-tab-pane" role="tabpanel" tabindex="0"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="editVehicleModal" tabindex="-1" role="dialog">
|
||||
@ -128,5 +141,8 @@
|
||||
function GetVehicleId() {
|
||||
return { vehicleId: @Model.Id};
|
||||
}
|
||||
function GetDefaultTab() {
|
||||
return { tab: "@userConfig.DefaultTab" };
|
||||
}
|
||||
bindWindowResize();
|
||||
</script>
|
||||
@ -25,6 +25,9 @@
|
||||
} else if (Model == ImportMode.TaxRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/taxrecordsample.csv" target="_blank">Download Sample</a>
|
||||
} else if (Model == ImportMode.SupplyRecord)
|
||||
{
|
||||
<a class="btn btn-link" href="/defaults/supplysample.csv" target="_blank">Download Sample</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@ -62,6 +65,8 @@
|
||||
getVehicleTaxRecords(vehicleId);
|
||||
} else if (mode == "UpgradeRecord") {
|
||||
getVehicleUpgradeRecords(vehicleId);
|
||||
} else if (mode == "SupplyRecord") {
|
||||
getVehicleSupplyRecords(vehicleId);
|
||||
}
|
||||
} else {
|
||||
errorToast("An error has occurred, please double check the data and try again.");
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
new Chart($("#pie-chart"), {
|
||||
type: 'pie',
|
||||
data: {
|
||||
labels: ["Planned Maintenance(Service Records)", "Unplanned Maintenance(Repairs)", "Upgrades", "Tax", "Fuel"],
|
||||
labels: ["Service Records", "Repairs", "Upgrades", "Tax", "Fuel"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Expenses by Category",
|
||||
|
||||
85
Views/Vehicle/_SupplyRecordModal.cshtml
Normal file
85
Views/Vehicle/_SupplyRecordModal.cshtml
Normal file
@ -0,0 +1,85 @@
|
||||
@model SupplyRecordInput
|
||||
@{
|
||||
var isNew = Model.Id == 0;
|
||||
}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(isNew ? "Add New Supply Record" : "Edit Supply Record")</h5>
|
||||
<button type="button" class="btn-close" onclick="hideAddSupplyRecordModal()" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<input type="text" id="workAroundInput" style="height:0px; width:0px; display:none;">
|
||||
<label for="supplyRecordDate">Date</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="supplyRecordDate" class="form-control" placeholder="Date purchased" value="@Model.Date">
|
||||
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
|
||||
</div>
|
||||
<label for="supplyRecordPartNumber">Part Number</label>
|
||||
<input type="text" id="supplyRecordPartNumber" class="form-control" placeholder="Part #/Model #/SKU #" value="@(isNew ? "" : Model.PartNumber)">
|
||||
<label for="supplyRecordDescription">Description</label>
|
||||
<input type="text" id="supplyRecordDescription" class="form-control" placeholder="Description of the Part/Supplies" value="@Model.Description">
|
||||
<label for="supplyRecordSupplier">Supplier/Vendor</label>
|
||||
<input type="text" id="supplyRecordSupplier" class="form-control" placeholder="Part Supplier" value="@Model.PartSupplier">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="supplyRecordQuantity">Quantity</label>
|
||||
<input type="text" id="supplyRecordQuantity" class="form-control" placeholder="Quantity" value="@(isNew ? "1" : Model.Quantity)">
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="supplyRecordCost">Cost</label>
|
||||
<input type="text" id="supplyRecordCost" class="form-control" placeholder="Cost" value="@(isNew ? "" : Model.Cost)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-12">
|
||||
<label for="supplyRecordNotes">Notes(optional)</label>
|
||||
<textarea id="supplyRecordNotes" class="form-control" rows="5">@Model.Notes</textarea>
|
||||
@if (Model.Files.Any())
|
||||
{
|
||||
<div>
|
||||
@await Html.PartialAsync("_UploadedFiles", Model.Files)
|
||||
<label for="supplyRecordFiles">Upload more documents</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="supplyRecordFiles">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<label for="supplyRecordFiles">Upload documents(optional)</label>
|
||||
<input onChange="uploadVehicleFilesAsync(this)" type="file" multiple accept=".png,.jpg,.jpeg,.pdf,.xls,.xlsx,.docx" class="form-control-file" id="supplyRecordFiles">
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-danger" onclick="deleteSupplyRecord(@Model.Id)" style="margin-right:auto;">Delete</button>
|
||||
}
|
||||
<button type="button" class="btn btn-secondary" onclick="hideAddSupplyRecordModal()">Cancel</button>
|
||||
@if (isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveSupplyRecordToVehicle()">Add New Supply Record</button>
|
||||
}
|
||||
else if (!isNew)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" onclick="saveSupplyRecordToVehicle(true)">Edit Supply Record</button>
|
||||
}
|
||||
</div>
|
||||
<script>
|
||||
var uploadedFiles = [];
|
||||
getUploadedFilesFromModel();
|
||||
function getUploadedFilesFromModel() {
|
||||
@foreach (UploadedFiles filesUploaded in Model.Files)
|
||||
{
|
||||
@:uploadedFiles.push({ name: "@filesUploaded.Name", location: "@filesUploaded.Location" });
|
||||
}
|
||||
}
|
||||
function getSupplyRecordModelData() {
|
||||
return { id: @Model.Id}
|
||||
}
|
||||
</script>
|
||||
78
Views/Vehicle/_SupplyRecords.cshtml
Normal file
78
Views/Vehicle/_SupplyRecords.cshtml
Normal file
@ -0,0 +1,78 @@
|
||||
@using CarCareTracker.Helper
|
||||
@inject IConfigHelper config
|
||||
@{
|
||||
var enableCsvImports = config.GetUserConfig(User).EnableCsvImports;
|
||||
var hideZero = config.GetUserConfig(User).HideZero;
|
||||
}
|
||||
@model List<SupplyRecord>
|
||||
<div class="row">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="d-flex align-items-center flex-wrap">
|
||||
<span class="ms-2 badge bg-success">@($"# of Supply Records: {Model.Count()}")</span>
|
||||
<span class="ms-2 badge bg-primary">@($"Total: {Model.Sum(x => x.Cost).ToString("C")}")</span>
|
||||
</div>
|
||||
<div>
|
||||
@if (enableCsvImports)
|
||||
{
|
||||
<div class="btn-group">
|
||||
<button onclick="showAddSupplyRecordModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>Add Supply Record</button>
|
||||
<button type="button" class="btn btn-md btn-primary btn-md mt-1 mb-1 dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span class="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="showBulkImportModal('SupplyRecord')">Import via CSV</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="exportVehicleData('SupplyRecord')">Export to CSV</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button onclick="showAddSupplyRecordModal()" class="btn btn-primary btn-md mt-1 mb-1"><i class="bi bi-pencil-square me-2"></i>Add Supply Record</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row vehicleDetailTabContainer">
|
||||
<div class="col-12">
|
||||
<div class="row mt-2 showOnPrint">
|
||||
<div class="d-flex">
|
||||
<img src="/defaults/lubelogger_logo.png" />
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<thead class="sticky-top">
|
||||
<tr class="d-flex">
|
||||
<th scope="col" class="col-1">Date</th>
|
||||
<th scope="col" class="col-2">Part #</th>
|
||||
<th scope="col" class="col-2">Supplier</th>
|
||||
<th scope="col" class="col-3">Description</th>
|
||||
<th scope="col" class="col-1">Quantity</th>
|
||||
<th scope="col" class="col-1">Cost</th>
|
||||
<th scope="col" class="col-2">Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (SupplyRecord supplyRecord in Model)
|
||||
{
|
||||
<tr class="d-flex" style="cursor:pointer;" onclick="showEditSupplyRecordModal(@supplyRecord.Id)">
|
||||
<td class="col-1">@supplyRecord.Date.ToShortDateString()</td>
|
||||
<td class="col-2">@supplyRecord.PartNumber</td>
|
||||
<td class="col-2">@supplyRecord.PartSupplier</td>
|
||||
<td class="col-3">@supplyRecord.Description</td>
|
||||
<td class="col-1">@supplyRecord.Quantity</td>
|
||||
<td class="col-1">@((hideZero && supplyRecord.Cost == default) ? "---" : supplyRecord.Cost.ToString("C"))</td>
|
||||
<td class="col-2 text-truncate">@CarCareTracker.Helper.StaticHelper.TruncateStrings(supplyRecord.Notes)</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal fade" data-bs-focus="false" id="supplyRecordModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content" id="supplyRecordModalContent">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -14,6 +14,8 @@
|
||||
"HideZero": false,
|
||||
"UseUKMPG": false,
|
||||
"UseThreeDecimalGasCost": true,
|
||||
"VisibleTabs": [ 0, 1, 4, 2, 3, 6, 5, 8 ],
|
||||
"DefaultTab": 8,
|
||||
"UserNameHash": "",
|
||||
"UserPasswordHash": ""
|
||||
}
|
||||
|
||||
2
wwwroot/defaults/supplysample.csv
Normal file
2
wwwroot/defaults/supplysample.csv
Normal file
@ -0,0 +1,2 @@
|
||||
Date,PartNumber,PartSupplier,PartQuantity,Description,Cost,Notes
|
||||
1/16/2024,EVA17872045551,Evan Fischer,1,Front Bumper,$95.14,Altima Activities
|
||||
|
121
wwwroot/js/supplyrecord.js
Normal file
121
wwwroot/js/supplyrecord.js
Normal file
@ -0,0 +1,121 @@
|
||||
function showAddSupplyRecordModal() {
|
||||
$.get('/Vehicle/GetAddSupplyRecordPartialView', function (data) {
|
||||
if (data) {
|
||||
$("#supplyRecordModalContent").html(data);
|
||||
//initiate datepicker
|
||||
initDatePicker($('#supplyRecordDate'));
|
||||
$('#supplyRecordModal').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
function showEditSupplyRecordModal(supplyRecordId) {
|
||||
$.get(`/Vehicle/GetSupplyRecordForEditById?supplyRecordId=${supplyRecordId}`, function (data) {
|
||||
if (data) {
|
||||
$("#supplyRecordModalContent").html(data);
|
||||
//initiate datepicker
|
||||
initDatePicker($('#supplyRecordDate'));
|
||||
$('#supplyRecordModal').modal('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
function hideAddSupplyRecordModal() {
|
||||
$('#supplyRecordModal').modal('hide');
|
||||
}
|
||||
function deleteSupplyRecord(supplyRecordId) {
|
||||
$("#workAroundInput").show();
|
||||
Swal.fire({
|
||||
title: "Confirm Deletion?",
|
||||
text: "Deleted Supply Records cannot be restored.",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Delete",
|
||||
confirmButtonColor: "#dc3545"
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.post(`/Vehicle/DeleteSupplyRecordById?supplyRecordId=${supplyRecordId}`, function (data) {
|
||||
if (data) {
|
||||
hideAddSupplyRecordModal();
|
||||
successToast("Supply Record Deleted");
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
getVehicleSupplyRecords(vehicleId);
|
||||
} else {
|
||||
errorToast("An error has occurred, please try again later.");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$("#workAroundInput").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
function saveSupplyRecordToVehicle(isEdit) {
|
||||
//get values
|
||||
var formValues = getAndValidateSupplyRecordValues();
|
||||
//validate
|
||||
if (formValues.hasError) {
|
||||
errorToast("Please check the form data");
|
||||
return;
|
||||
}
|
||||
//save to db.
|
||||
$.post('/Vehicle/SaveSupplyRecordToVehicleId', { supplyRecord: formValues }, function (data) {
|
||||
if (data) {
|
||||
successToast(isEdit ? "Supply Record Updated" : "Supply Record Added.");
|
||||
hideAddSupplyRecordModal();
|
||||
saveScrollPosition();
|
||||
getVehicleSupplyRecords(formValues.vehicleId);
|
||||
if (formValues.addReminderRecord) {
|
||||
setTimeout(function () { showAddReminderModal(formValues); }, 500);
|
||||
}
|
||||
} else {
|
||||
errorToast("An error has occurred, please try again later.");
|
||||
}
|
||||
})
|
||||
}
|
||||
function getAndValidateSupplyRecordValues() {
|
||||
var supplyDate = $("#supplyRecordDate").val();
|
||||
var supplyPartNumber = $("#supplyRecordPartNumber").val();
|
||||
var supplyDescription = $("#supplyRecordDescription").val();
|
||||
var supplySupplier = $("#supplyRecordSupplier").val();
|
||||
var supplyQuantity = $("#supplyRecordQuantity").val();
|
||||
var supplyCost = $("#supplyRecordCost").val();
|
||||
var supplyNotes = $("#supplyRecordNotes").val();
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var supplyRecordId = getSupplyRecordModelData().id;
|
||||
//validation
|
||||
var hasError = false;
|
||||
if (supplyDate.trim() == '') { //eliminates whitespace.
|
||||
hasError = true;
|
||||
$("#supplyRecordDate").addClass("is-invalid");
|
||||
} else {
|
||||
$("#supplyRecordDate").removeClass("is-invalid");
|
||||
}
|
||||
if (supplyDescription.trim() == '') {
|
||||
hasError = true;
|
||||
$("#supplyRecordDescription").addClass("is-invalid");
|
||||
} else {
|
||||
$("#supplyRecordDescription").removeClass("is-invalid");
|
||||
}
|
||||
if (supplyQuantity.trim() == '' || !isValidMoney(supplyQuantity) || parseFloat(supplyQuantity) < 0) {
|
||||
hasError = true;
|
||||
$("#supplyRecordQuantity").addClass("is-invalid");
|
||||
} else {
|
||||
$("#supplyRecordQuantity").removeClass("is-invalid");
|
||||
}
|
||||
if (supplyCost.trim() == '' || !isValidMoney(supplyCost)) {
|
||||
hasError = true;
|
||||
$("#supplyRecordCost").addClass("is-invalid");
|
||||
} else {
|
||||
$("#supplyRecordCost").removeClass("is-invalid");
|
||||
}
|
||||
return {
|
||||
id: supplyRecordId,
|
||||
hasError: hasError,
|
||||
vehicleId: vehicleId,
|
||||
date: supplyDate,
|
||||
partNumber: supplyPartNumber,
|
||||
partSupplier: supplySupplier,
|
||||
description: supplyDescription,
|
||||
cost: supplyCost,
|
||||
notes: supplyNotes,
|
||||
quantity: supplyQuantity,
|
||||
files: uploadedFiles
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,9 @@ $(document).ready(function () {
|
||||
case "upgrade-tab":
|
||||
getVehicleUpgradeRecords(vehicleId);
|
||||
break;
|
||||
case "supply-tab":
|
||||
getVehicleSupplyRecords(vehicleId);
|
||||
break;
|
||||
}
|
||||
switch (e.relatedTarget.id) { //clear out previous tabs with grids in them to help with performance
|
||||
case "servicerecord-tab":
|
||||
@ -56,9 +59,41 @@ $(document).ready(function () {
|
||||
case "notes-tab":
|
||||
$("#notes-tab-pane").html("");
|
||||
break;
|
||||
case "supply-tab":
|
||||
$("#supply-tab-pane").html("");
|
||||
break;
|
||||
}
|
||||
});
|
||||
getVehicleReport(vehicleId);
|
||||
var defaultTab = GetDefaultTab().tab;
|
||||
switch (defaultTab) {
|
||||
case "ServiceRecord":
|
||||
getVehicleServiceRecords(vehicleId);
|
||||
break;
|
||||
case "NoteRecord":
|
||||
getVehicleNotes(vehicleId);
|
||||
break;
|
||||
case "GasRecord":
|
||||
getVehicleGasRecords(vehicleId);
|
||||
break;
|
||||
case "RepairRecord":
|
||||
getVehicleCollisionRecords(vehicleId);
|
||||
break;
|
||||
case "TaxRecord":
|
||||
getVehicleTaxRecords(vehicleId);
|
||||
break;
|
||||
case "Dashboard":
|
||||
getVehicleReport(vehicleId);
|
||||
break;
|
||||
case "ReminderRecord":
|
||||
getVehicleReminders(vehicleId);
|
||||
break;
|
||||
case "UpgradeRecord":
|
||||
getVehicleUpgradeRecords(vehicleId);
|
||||
break;
|
||||
case "SupplyRecord":
|
||||
getVehicleSupplyRecords(vehicleId);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
function getVehicleNotes(vehicleId) {
|
||||
@ -78,6 +113,15 @@ function getVehicleServiceRecords(vehicleId) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function getVehicleSupplyRecords(vehicleId) {
|
||||
$.get(`/Vehicle/GetSupplyRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
$("#supply-tab-pane").html(data);
|
||||
restoreScrollPosition();
|
||||
getVehicleHaveImportantReminders(vehicleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
function getVehicleUpgradeRecords(vehicleId) {
|
||||
$.get(`/Vehicle/GetUpgradeRecordsByVehicleId?vehicleId=${vehicleId}`, function (data) {
|
||||
if (data) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user