Compare commits

..

1 Commits

Author SHA1 Message Date
DESKTOP-T0O5CDB\DESK-555BD
7bc47363fd backend for torque integration. 2024-01-24 14:15:40 -07:00
204 changed files with 1403 additions and 10291 deletions

1
.env
View File

@@ -6,4 +6,3 @@ MailConfig__UseSSL="false"
MailConfig__Port=587
MailConfig__Username=""
MailConfig__Password=""
LOGGING__LOGLEVEL__DEFAULT=Error

View File

@@ -1,51 +0,0 @@
name: Build and Push Image to Dockerhub and GHCR
on:
push:
branches: ["main"]
release:
types: ["published"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: "${{ secrets.DH_USER }}"
password: "${{ secrets.DH_PASS }}"
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: "hargata"
password: "${{ secrets.GHCR_PAT }}"
- name: Docker Metadata
id: meta
uses: docker/metadata-action@v5
with:
context: workflow
images: |
hargata/lubelogger
ghcr.io/hargata/lubelogger
tags: |
type=edge,branch=main
type=ref,event=tag
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -0,0 +1,30 @@
name: Docker Image To Docker Hub
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: "${{ secrets.DH_USER }}"
password: "${{ secrets.DH_PASS }}"
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
hargata/lubelogger:latest

31
.github/workflows/ghcr-docker-image.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Docker Image To GHCR
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: "hargata"
password: "${{ secrets.GHCR_PAT }}"
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
ghcr.io/hargata/lubelogger:latest

4
.gitignore vendored
View File

@@ -7,7 +7,3 @@ data/cartracker.db
wwwroot/documents/
wwwroot/temp/
wwwroot/imports/
wwwroot/translations/
config/userConfig.json
CarCareTracker.csproj.user
Properties/launchSettings.json

View File

@@ -13,8 +13,6 @@
<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="LiteDB" Version="5.0.17" />
<PackageReference Include="Npgsql" Version="8.0.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<View_SelectedScaffolderID>RazorViewEmptyScaffolder</View_SelectedScaffolderID>
<View_SelectedScaffolderCategoryPath>root/Common/MVC/View</View_SelectedScaffolderCategoryPath>
</PropertyGroup>
</Project>

View File

@@ -22,14 +22,12 @@ namespace CarCareTracker.Controllers
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
private readonly IUserAccessDataAccess _userAccessDataAccess;
private readonly IUserRecordDataAccess _userRecordDataAccess;
private readonly ITorqueRecordDataAccess _torqueRecordDataAccess;
private readonly IReminderHelper _reminderHelper;
private readonly IGasHelper _gasHelper;
private readonly IUserLogic _userLogic;
private readonly IFileHelper _fileHelper;
private readonly IMailHelper _mailHelper;
private readonly IConfigHelper _config;
private readonly IConfigHelper _configHelper;
public APIController(IVehicleDataAccess dataAccess,
IGasHelper gasHelper,
IReminderHelper reminderHelper,
@@ -41,11 +39,9 @@ namespace CarCareTracker.Controllers
IReminderRecordDataAccess reminderRecordDataAccess,
IUpgradeRecordDataAccess upgradeRecordDataAccess,
IOdometerRecordDataAccess odometerRecordDataAccess,
IUserAccessDataAccess userAccessDataAccess,
IUserRecordDataAccess userRecordDataAccess,
IMailHelper mailHelper,
ITorqueRecordDataAccess torqueRecordDataAccess,
IConfigHelper configHelper,
IFileHelper fileHelper,
IConfigHelper config,
IUserLogic userLogic)
{
_dataAccess = dataAccess;
@@ -57,14 +53,12 @@ namespace CarCareTracker.Controllers
_reminderRecordDataAccess = reminderRecordDataAccess;
_upgradeRecordDataAccess = upgradeRecordDataAccess;
_odometerRecordDataAccess = odometerRecordDataAccess;
_userAccessDataAccess = userAccessDataAccess;
_userRecordDataAccess = userRecordDataAccess;
_mailHelper = mailHelper;
_torqueRecordDataAccess = torqueRecordDataAccess;
_gasHelper = gasHelper;
_configHelper = configHelper;
_reminderHelper = reminderHelper;
_userLogic = userLogic;
_fileHelper = fileHelper;
_config = config;
}
public IActionResult Index()
{
@@ -129,17 +123,6 @@ namespace CarCareTracker.Controllers
Cost = decimal.Parse(input.Cost)
};
_serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord);
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
{
var odometerRecord = new OdometerRecord()
{
VehicleId = vehicleId,
Date = DateTime.Parse(input.Date),
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
Mileage = int.Parse(input.Odometer)
};
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord);
}
response.Success = true;
response.Message = "Service Record Added";
return Json(response);
@@ -196,17 +179,6 @@ namespace CarCareTracker.Controllers
Cost = decimal.Parse(input.Cost)
};
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(repairRecord);
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
{
var odometerRecord = new OdometerRecord()
{
VehicleId = vehicleId,
Date = DateTime.Parse(input.Date),
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
Mileage = int.Parse(input.Odometer)
};
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord);
}
response.Success = true;
response.Message = "Repair Record Added";
return Json(response);
@@ -263,17 +235,6 @@ namespace CarCareTracker.Controllers
Cost = decimal.Parse(input.Cost)
};
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord);
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
{
var odometerRecord = new OdometerRecord()
{
VehicleId = vehicleId,
Date = DateTime.Parse(input.Date),
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
Mileage = int.Parse(input.Odometer)
};
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord);
}
response.Success = true;
response.Message = "Upgrade Record Added";
return Json(response);
@@ -382,7 +343,8 @@ namespace CarCareTracker.Controllers
response.Success = true;
response.Message = "Odometer Record Added";
return Json(response);
} catch (Exception ex)
}
catch (Exception ex)
{
response.Success = false;
response.Message = ex.Message;
@@ -397,7 +359,8 @@ namespace CarCareTracker.Controllers
{
var vehicleRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
var result = _gasHelper.GetGasRecordViewModels(vehicleRecords, useMPG, useUKMPG)
.Select(x => new GasRecordExportModel {
.Select(x => new GasRecordExportModel
{
Date = x.Date,
Odometer = x.Mileage.ToString(),
Cost = x.Cost.ToString(),
@@ -449,17 +412,6 @@ namespace CarCareTracker.Controllers
Cost = decimal.Parse(input.Cost)
};
_gasRecordDataAccess.SaveGasRecordToVehicle(gasRecord);
if (_config.GetUserConfig(User).EnableAutoOdometerInsert)
{
var odometerRecord = new OdometerRecord()
{
VehicleId = vehicleId,
Date = DateTime.Parse(input.Date),
Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes,
Mileage = int.Parse(input.Odometer)
};
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord);
}
response.Success = true;
response.Message = "Gas Record Added";
return Json(response);
@@ -484,64 +436,67 @@ namespace CarCareTracker.Controllers
}
[Authorize(Roles = nameof(UserData.IsRootUser))]
[HttpGet]
[Route("/api/vehicle/reminders/send")]
public IActionResult SendReminders(List<ReminderUrgency> urgencies)
{
var vehicles = _dataAccess.GetVehicles();
List<OperationResponse> operationResponses = new List<OperationResponse>();
foreach(Vehicle vehicle in vehicles)
{
var vehicleId = vehicle.Id;
//get reminders
var currentMileage = GetMaxMileage(vehicleId);
var reminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicleId);
var results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, DateTime.Now).OrderByDescending(x => x.Urgency).ToList();
results.RemoveAll(x => !urgencies.Contains(x.Urgency));
if (!results.Any())
{
continue;
}
//get list of recipients.
var userIds = _userAccessDataAccess.GetUserAccessByVehicleId(vehicleId).Select(x => x.Id.UserId);
List<string> emailRecipients = new List<string>();
foreach (int userId in userIds)
{
var userData = _userRecordDataAccess.GetUserRecordById(userId);
emailRecipients.Add(userData.EmailAddress);
};
if (!emailRecipients.Any())
{
continue;
}
var result = _mailHelper.NotifyUserForReminders(vehicle, emailRecipients, results);
operationResponses.Add(result);
}
if (operationResponses.All(x => x.Success))
{
return Json(new OperationResponse { Success = true, Message = "Emails sent" });
} else if (operationResponses.All(x => !x.Success))
{
return Json(new OperationResponse { Success = false, Message = "All emails failed, check SMTP settings" });
} else
{
return Json(new OperationResponse { Success = true, Message = "Some emails sent, some failed, check recipient settings" });
}
}
[Authorize(Roles = nameof(UserData.IsRootUser))]
[HttpGet]
[Route("/api/makebackup")]
public IActionResult MakeBackup()
{
var result = _fileHelper.MakeBackup();
return Json(result);
}
[Authorize(Roles = nameof(UserData.IsRootUser))]
[HttpGet]
[Route("/api/demo/restore")]
public IActionResult RestoreDemo()
[Route("/api/obdii/vehicle/{vehicleId}")]
[AllowAnonymous]
public IActionResult OBDII(int vehicleId, TorqueRecord record)
{
var result = _fileHelper.RestoreBackup("/defaults/demo_default.zip", true);
return Json(result);
if (record.kff1005 != default && record.kff1006 != default && vehicleId != default)
{
//check if there is an existing session.
try
{
var existingRecord = _torqueRecordDataAccess.GetTorqueRecordById(record.Session);
if (existingRecord != null)
{
//calculate difference between last coordinates.
var distance = GetDistance(existingRecord.LastLongitude, existingRecord.LastLatitude, record.kff1005, record.kff1006);
var useMPG = _configHelper.GetUserConfig(User).UseMPG;
if (useMPG)
{
distance /= 1609; //get miles.
}
else
{
distance /= 1000;
}
existingRecord.DistanceTraveled += distance;
existingRecord.LastLongitude = record.kff1005;
existingRecord.LastLatitude = record.kff1006;
_torqueRecordDataAccess.SaveTorqueRecord(existingRecord);
}
else
{
//new record.
record.InitialLongitude = record.kff1005;
record.InitialLatitude = record.kff1006;
record.LastLongitude = record.kff1005;
record.LastLatitude = record.kff1006;
_torqueRecordDataAccess.SaveTorqueRecord(record);
}
return Json(true);
}
catch (Exception ex)
{
return Json(false);
}
}
return Json(false);
}
private double GetDistance(double longitude, double latitude, double otherLongitude, double otherLatitude)
{
var d1 = latitude * (Math.PI / 180.0);
var num1 = longitude * (Math.PI / 180.0);
var d2 = otherLatitude * (Math.PI / 180.0);
var num2 = otherLongitude * (Math.PI / 180.0) - num1;
var d3 = Math.Pow(Math.Sin((d2 - d1) / 2.0), 2.0) + Math.Cos(d1) * Math.Cos(d2) * Math.Pow(Math.Sin(num2 / 2.0), 2.0);
return 6376500.0 * (2.0 * Math.Atan2(Math.Sqrt(d3), Math.Sqrt(1.0 - d3)));
}
private int GetMaxMileage(int vehicleId)
{

View File

@@ -33,26 +33,6 @@ namespace CarCareTracker.Controllers
return Json(fileName);
}
[HttpPost]
public IActionResult HandleTranslationFileUpload(IFormFile file)
{
var originalFileName = Path.GetFileNameWithoutExtension(file.FileName);
if (originalFileName == "en_US")
{
return Json(new OperationResponse { Success = false, Message = "The translation file name en_US is reserved." });
}
var fileName = UploadFile(file);
//move file from temp to translation folder.
var uploadedFilePath = _fileHelper.MoveFileFromTemp(fileName, "translations/");
//rename uploaded file so that it preserves original name.
if (!string.IsNullOrWhiteSpace(uploadedFilePath))
{
var result = _fileHelper.RenameFile(uploadedFilePath, originalFileName);
return Json(new OperationResponse { Success = result, Message = string.Empty });
}
return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage });
}
[HttpPost]
public IActionResult HandleMultipleFileUpload(List<IFormFile> file)
{
@@ -64,7 +44,7 @@ namespace CarCareTracker.Controllers
}
return Json(uploadedFiles);
}
[Authorize(Roles = nameof(UserData.IsRootUser))]
[HttpPost]
public IActionResult DeleteFiles(string fileLocation)
{

View File

@@ -15,28 +15,17 @@ namespace CarCareTracker.Controllers
private readonly ILogger<HomeController> _logger;
private readonly IVehicleDataAccess _dataAccess;
private readonly IUserLogic _userLogic;
private readonly IFileHelper _fileHelper;
private readonly IConfigHelper _config;
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
private readonly IReminderRecordDataAccess _reminderRecordDataAccess;
private readonly IReminderHelper _reminderHelper;
public HomeController(ILogger<HomeController> logger,
IVehicleDataAccess dataAccess,
IUserLogic userLogic,
IConfigHelper configuration,
IFileHelper fileHelper,
IExtraFieldDataAccess extraFieldDataAccess,
IReminderRecordDataAccess reminderRecordDataAccess,
IReminderHelper reminderHelper)
IConfigHelper configuration)
{
_logger = logger;
_dataAccess = dataAccess;
_config = configuration;
_userLogic = userLogic;
_fileHelper = fileHelper;
_extraFieldDataAccess = extraFieldDataAccess;
_reminderRecordDataAccess = reminderRecordDataAccess;
_reminderHelper = reminderHelper;
}
private int GetUserID()
{
@@ -55,45 +44,10 @@ namespace CarCareTracker.Controllers
}
return PartialView("_GarageDisplay", vehiclesStored);
}
public IActionResult Calendar()
{
var vehiclesStored = _dataAccess.GetVehicles();
if (!User.IsInRole(nameof(UserData.IsRootUser)))
{
vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID());
}
List<ReminderRecordViewModel> reminders = new List<ReminderRecordViewModel>();
foreach(Vehicle vehicle in vehiclesStored)
{
var vehicleReminders = _reminderRecordDataAccess.GetReminderRecordsByVehicleId(vehicle.Id);
vehicleReminders.RemoveAll(x => x.Metric == ReminderMetric.Odometer);
//we don't care about mileages so we can basically fake the current vehicle mileage.
if (vehicleReminders.Any())
{
var maxMileage = vehicleReminders.Max(x => x.Mileage) + 1000;
var reminderUrgency = _reminderHelper.GetReminderRecordViewModels(vehicleReminders, maxMileage, DateTime.Now);
reminderUrgency = reminderUrgency.Select(x => new ReminderRecordViewModel { Id = x.Id, Date = x.Date, Urgency = x.Urgency, Description = $"{vehicle.Year} {vehicle.Make} {vehicle.Model} #{vehicle.LicensePlate} - {x.Description}" }).ToList();
reminders.AddRange(reminderUrgency);
}
}
return PartialView("_Calendar", reminders);
}
public IActionResult ViewCalendarReminder(int reminderId)
{
var reminder = _reminderRecordDataAccess.GetReminderRecordById(reminderId);
var reminderUrgency = _reminderHelper.GetReminderRecordViewModels(new List<ReminderRecord> { reminder }, reminder.Mileage + 1000, DateTime.Now).FirstOrDefault();
return PartialView("_ReminderRecordCalendarModal", reminderUrgency);
}
public IActionResult Settings()
{
var userConfig = _config.GetUserConfig(User);
var languages = _fileHelper.GetLanguages();
var viewModel = new SettingsViewModel
{
UserConfig = userConfig,
UILanguages = languages
};
return PartialView("_Settings", viewModel);
return PartialView("_Settings", userConfig);
}
[HttpPost]
public IActionResult WriteToSettings(UserConfig userConfig)
@@ -105,30 +59,7 @@ namespace CarCareTracker.Controllers
{
return View();
}
[Authorize(Roles = nameof(UserData.IsRootUser))]
public IActionResult GetExtraFieldsModal(int importMode = 0)
{
var recordExtraFields = _extraFieldDataAccess.GetExtraFieldsById(importMode);
if (recordExtraFields.Id != importMode)
{
recordExtraFields.Id = importMode;
}
return PartialView("_ExtraFields", recordExtraFields);
}
[Authorize(Roles = nameof(UserData.IsRootUser))]
public IActionResult UpdateExtraFields(RecordExtraField record)
{
try
{
var result = _extraFieldDataAccess.SaveExtraFields(record);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
var recordExtraFields = _extraFieldDataAccess.GetExtraFieldsById(record.Id);
return PartialView("_ExtraFields", recordExtraFields);
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{

View File

@@ -4,8 +4,6 @@ using CarCareTracker.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Security.Cryptography;
using System.Text;
@@ -17,23 +15,20 @@ namespace CarCareTracker.Controllers
{
private IDataProtector _dataProtector;
private ILoginLogic _loginLogic;
private IConfigHelper _config;
private readonly ILogger<LoginController> _logger;
public LoginController(
ILogger<LoginController> logger,
IDataProtectionProvider securityProvider,
ILoginLogic loginLogic,
IConfigHelper config
ILoginLogic loginLogic
)
{
_dataProtector = securityProvider.CreateProtector("login");
_logger = logger;
_loginLogic = loginLogic;
_config = config;
}
public IActionResult Index(string redirectURL = "")
public IActionResult Index()
{
return View(model: redirectURL);
return View();
}
public IActionResult Registration()
{
@@ -47,70 +42,6 @@ namespace CarCareTracker.Controllers
{
return View();
}
public IActionResult GetRemoteLoginLink()
{
var remoteAuthURL = _config.GetOpenIDConfig().RemoteAuthURL;
return Json(remoteAuthURL);
}
public async Task<IActionResult> RemoteAuth(string code)
{
try
{
if (!string.IsNullOrWhiteSpace(code))
{
//received code from OIDC provider
//create http client to retrieve user token from OIDC
var httpClient = new HttpClient();
var openIdConfig = _config.GetOpenIDConfig();
var httpParams = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("client_id", openIdConfig.ClientId),
new KeyValuePair<string, string>("client_secret", openIdConfig.ClientSecret),
new KeyValuePair<string, string>("redirect_uri", openIdConfig.RedirectURL)
};
var httpRequest = new HttpRequestMessage(HttpMethod.Post, openIdConfig.TokenURL)
{
Content = new FormUrlEncodedContent(httpParams)
};
var tokenResult = await httpClient.SendAsync(httpRequest).Result.Content.ReadAsStringAsync();
var userJwt = JsonSerializer.Deserialize<OpenIDResult>(tokenResult)?.id_token ?? string.Empty;
if (!string.IsNullOrWhiteSpace(userJwt))
{
//validate JWT token
var tokenParser = new JwtSecurityTokenHandler();
var parsedToken = tokenParser.ReadJwtToken(userJwt);
var userEmailAddress = parsedToken.Claims.First(x => x.Type == "email").Value;
if (!string.IsNullOrWhiteSpace(userEmailAddress))
{
var userData = _loginLogic.ValidateOpenIDUser(new LoginModel() { EmailAddress = userEmailAddress });
if (userData.Id != default)
{
AuthCookie authCookie = new AuthCookie
{
UserData = userData,
ExpiresOn = DateTime.Now.AddDays(1)
};
var serializedCookie = JsonSerializer.Serialize(authCookie);
var encryptedCookie = _dataProtector.Protect(serializedCookie);
Response.Cookies.Append("ACCESS_TOKEN", encryptedCookie, new CookieOptions { Expires = new DateTimeOffset(authCookie.ExpiresOn) });
return new RedirectResult("/Home");
} else
{
_logger.LogInformation($"User {userEmailAddress} tried to login via OpenID but is not a registered user in LubeLogger.");
return View("OpenIDRegistration", model: userEmailAddress);
}
}
}
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return new RedirectResult("/Login");
}
return new RedirectResult("/Login");
}
[HttpPost]
public IActionResult Login(LoginModel credentials)
{
@@ -150,27 +81,6 @@ namespace CarCareTracker.Controllers
return Json(result);
}
[HttpPost]
public IActionResult RegisterOpenIdUser(LoginModel credentials)
{
var result = _loginLogic.RegisterOpenIdUser(credentials);
if (result.Success)
{
var userData = _loginLogic.ValidateOpenIDUser(new LoginModel() { EmailAddress = credentials.EmailAddress });
if (userData.Id != default)
{
AuthCookie authCookie = new AuthCookie
{
UserData = userData,
ExpiresOn = DateTime.Now.AddDays(1)
};
var serializedCookie = JsonSerializer.Serialize(authCookie);
var encryptedCookie = _dataProtector.Protect(serializedCookie);
Response.Cookies.Append("ACCESS_TOKEN", encryptedCookie, new CookieOptions { Expires = new DateTimeOffset(authCookie.ExpiresOn) });
}
}
return Json(result);
}
[HttpPost]
public IActionResult RequestResetPassword(LoginModel credentials)
{
var result = _loginLogic.RequestResetPassword(credentials);

View File

@@ -1,757 +0,0 @@
using CarCareTracker.External.Implementations;
using CarCareTracker.Helper;
using CarCareTracker.Models;
using LiteDB;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Npgsql;
using System.Data.Common;
using System.IO.Compression;
using System.Xml.Linq;
namespace CarCareTracker.Controllers
{
[Authorize(Roles = nameof(UserData.IsRootUser))]
public class MigrationController : Controller
{
private IConfigHelper _configHelper;
private IFileHelper _fileHelper;
private readonly ILogger<MigrationController> _logger;
public MigrationController(IConfigHelper configHelper, IFileHelper fileHelper, IConfiguration serverConfig, ILogger<MigrationController> logger)
{
_configHelper = configHelper;
_fileHelper = fileHelper;
_logger = logger;
}
public IActionResult Index()
{
if (!string.IsNullOrWhiteSpace(_configHelper.GetServerPostgresConnection()))
{
return View();
} else
{
return new RedirectResult("/Error/Unauthorized");
}
}
private void InitializeTables(NpgsqlDataSource conn)
{
var cmds = new List<string>
{
"CREATE TABLE IF NOT EXISTS app.vehicles (id INT GENERATED BY DEFAULT AS IDENTITY primary key, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.collisionrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.upgraderecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.servicerecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.gasrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.notes (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.odometerrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.reminderrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.planrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.planrecordtemplates (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.supplyrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.taxrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.userrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, username TEXT not null, emailaddress TEXT not null, password TEXT not null, isadmin BOOLEAN)",
"CREATE TABLE IF NOT EXISTS app.tokenrecords (id INT GENERATED BY DEFAULT AS IDENTITY primary key, body TEXT not null, emailaddress TEXT not null)",
"CREATE TABLE IF NOT EXISTS app.userconfigrecords (id INT primary key, data jsonb not null)",
"CREATE TABLE IF NOT EXISTS app.useraccessrecords (userId INT, vehicleId INT, PRIMARY KEY(userId, vehicleId))",
"CREATE TABLE IF NOT EXISTS app.extrafields (id INT primary key, data jsonb not null)"
};
foreach(string cmd in cmds)
{
using (var ctext = conn.CreateCommand(cmd))
{
ctext.ExecuteNonQuery();
}
}
}
public IActionResult Export()
{
if (string.IsNullOrWhiteSpace(_configHelper.GetServerPostgresConnection()))
{
return Json(new OperationResponse { Success = false, Message = "Postgres connection not set up" });
}
var tempFolder = $"temp/{Guid.NewGuid()}";
var tempPath = $"{tempFolder}/cartracker.db";
var fullFolderPath = _fileHelper.GetFullFilePath(tempFolder, false);
Directory.CreateDirectory(fullFolderPath);
var fullFileName = _fileHelper.GetFullFilePath(tempPath, false);
try
{
var pgDataSource = NpgsqlDataSource.Create(_configHelper.GetServerPostgresConnection());
InitializeTables(pgDataSource);
//pull records
var vehicles = new List<Vehicle>();
var repairrecords = new List<CollisionRecord>();
var upgraderecords = new List<UpgradeRecord>();
var servicerecords = new List<ServiceRecord>();
var gasrecords = new List<GasRecord>();
var noterecords = new List<Note>();
var odometerrecords = new List<OdometerRecord>();
var reminderrecords = new List<ReminderRecord>();
var planrecords = new List<PlanRecord>();
var planrecordtemplates = new List<PlanRecordInput>();
var supplyrecords = new List<SupplyRecord>();
var taxrecords = new List<TaxRecord>();
var userrecords = new List<UserData>();
var tokenrecords = new List<Token>();
var userconfigrecords = new List<UserConfigData>();
var useraccessrecords = new List<UserAccess>();
var extrafields = new List<RecordExtraField>();
#region "Part1"
string cmd = $"SELECT data FROM app.vehicles";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
Vehicle vehicle = System.Text.Json.JsonSerializer.Deserialize<Vehicle>(reader["data"] as string);
vehicles.Add(vehicle);
}
}
foreach (var vehicle in vehicles)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<Vehicle>("vehicles");
table.Upsert(vehicle);
};
}
cmd = $"SELECT data FROM app.collisionrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
repairrecords.Add(System.Text.Json.JsonSerializer.Deserialize<CollisionRecord>(reader["data"] as string));
}
}
foreach (var record in repairrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<CollisionRecord>("collisionrecords");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.upgraderecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
upgraderecords.Add(System.Text.Json.JsonSerializer.Deserialize<UpgradeRecord>(reader["data"] as string));
}
}
foreach (var record in upgraderecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<UpgradeRecord>("upgraderecords");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.servicerecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
servicerecords.Add(System.Text.Json.JsonSerializer.Deserialize<ServiceRecord>(reader["data"] as string));
}
}
foreach (var record in servicerecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<ServiceRecord>("servicerecords");
table.Upsert(record);
};
}
#endregion
#region "Part2"
cmd = $"SELECT data FROM app.gasrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
gasrecords.Add(System.Text.Json.JsonSerializer.Deserialize<GasRecord>(reader["data"] as string));
}
}
foreach (var record in gasrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<GasRecord>("gasrecords");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.notes";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
noterecords.Add(System.Text.Json.JsonSerializer.Deserialize<Note>(reader["data"] as string));
}
}
foreach (var record in noterecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<Note>("notes");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.odometerrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
odometerrecords.Add(System.Text.Json.JsonSerializer.Deserialize<OdometerRecord>(reader["data"] as string));
}
}
foreach (var record in odometerrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<OdometerRecord>("odometerrecords");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.reminderrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
reminderrecords.Add(System.Text.Json.JsonSerializer.Deserialize<ReminderRecord>(reader["data"] as string));
}
}
foreach (var record in reminderrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<ReminderRecord>("reminderrecords");
table.Upsert(record);
};
}
#endregion
#region "Part3"
cmd = $"SELECT data FROM app.planrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
planrecords.Add(System.Text.Json.JsonSerializer.Deserialize<PlanRecord>(reader["data"] as string));
}
}
foreach (var record in planrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<PlanRecord>("planrecords");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.planrecordtemplates";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
planrecordtemplates.Add(System.Text.Json.JsonSerializer.Deserialize<PlanRecordInput>(reader["data"] as string));
}
}
foreach (var record in planrecordtemplates)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<PlanRecordInput>("planrecordtemplates");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.supplyrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
supplyrecords.Add(System.Text.Json.JsonSerializer.Deserialize<SupplyRecord>(reader["data"] as string));
}
}
foreach (var record in supplyrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<SupplyRecord>("supplyrecords");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.taxrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
taxrecords.Add(System.Text.Json.JsonSerializer.Deserialize<TaxRecord>(reader["data"] as string));
}
}
foreach (var record in taxrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<TaxRecord>("taxrecords");
table.Upsert(record);
};
}
#endregion
#region "Part4"
cmd = $"SELECT id, username, emailaddress, password, isadmin FROM app.userrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
UserData result = new UserData();
result.Id = int.Parse(reader["id"].ToString());
result.UserName = reader["username"].ToString();
result.EmailAddress = reader["emailaddress"].ToString();
result.Password = reader["password"].ToString();
result.IsAdmin = bool.Parse(reader["isadmin"].ToString());
userrecords.Add(result);
}
}
foreach (var record in userrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<UserData>("userrecords");
table.Upsert(record);
};
}
cmd = $"SELECT id, emailaddress, body FROM app.tokenrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
Token result = new Token();
result.Id = int.Parse(reader["id"].ToString());
result.EmailAddress = reader["emailaddress"].ToString();
result.Body = reader["body"].ToString();
tokenrecords.Add(result);
}
}
foreach (var record in tokenrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<Token>("tokenrecords");
table.Upsert(record);
};
}
cmd = $"SELECT data FROM app.userconfigrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
userconfigrecords.Add(System.Text.Json.JsonSerializer.Deserialize<UserConfigData>(reader["data"] as string));
}
}
foreach (var record in userconfigrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<UserConfigData>("userconfigrecords");
table.Upsert(record);
};
}
cmd = $"SELECT userId, vehicleId FROM app.useraccessrecords";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
UserAccess result = new UserAccess()
{
Id = new UserVehicle
{
UserId = int.Parse(reader["userId"].ToString()),
VehicleId = int.Parse(reader["vehicleId"].ToString())
}
};
useraccessrecords.Add(result);
}
}
foreach (var record in useraccessrecords)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<UserAccess>("useraccessrecords");
table.Upsert(record);
};
}
#endregion
#region "Part5"
cmd = $"SELECT data FROM app.extrafields";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
extrafields.Add(System.Text.Json.JsonSerializer.Deserialize<RecordExtraField>(reader["data"] as string));
}
}
foreach (var record in extrafields)
{
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<RecordExtraField>("extrafields");
table.Upsert(record);
};
}
#endregion
var destFilePath = $"{fullFolderPath}.zip";
ZipFile.CreateFromDirectory(fullFolderPath, destFilePath);
return Json(new OperationResponse { Success = true, Message = $"/{tempFolder}.zip" });
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage });
}
}
public IActionResult Import(string fileName)
{
if (string.IsNullOrWhiteSpace(_configHelper.GetServerPostgresConnection()))
{
return Json(new OperationResponse { Success = false, Message = "Postgres connection not set up" });
}
var fullFileName = _fileHelper.GetFullFilePath(fileName);
if (string.IsNullOrWhiteSpace(fullFileName))
{
return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage });
}
try
{
var pgDataSource = NpgsqlDataSource.Create(_configHelper.GetServerPostgresConnection());
InitializeTables(pgDataSource);
//pull records
var vehicles = new List<Vehicle>();
var repairrecords = new List<CollisionRecord>();
var upgraderecords = new List<UpgradeRecord>();
var servicerecords = new List<ServiceRecord>();
var gasrecords = new List<GasRecord>();
var noterecords = new List<Note>();
var odometerrecords = new List<OdometerRecord>();
var reminderrecords = new List<ReminderRecord>();
var planrecords = new List<PlanRecord>();
var planrecordtemplates = new List<PlanRecordInput>();
var supplyrecords = new List<SupplyRecord>();
var taxrecords = new List<TaxRecord>();
var userrecords = new List<UserData>();
var tokenrecords = new List<Token>();
var userconfigrecords = new List<UserConfigData>();
var useraccessrecords = new List<UserAccess>();
var extrafields = new List<RecordExtraField>();
#region "Part1"
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<Vehicle>("vehicles");
vehicles = table.FindAll().ToList();
};
foreach(var vehicle in vehicles)
{
string cmd = $"INSERT INTO app.vehicles (id, data) VALUES(@id, CAST(@data AS jsonb)); SELECT setval('app.vehicles_id_seq', (SELECT MAX(id) from app.vehicles));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicle.Id);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(vehicle));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<CollisionRecord>("collisionrecords");
repairrecords = table.FindAll().ToList();
};
foreach (var record in repairrecords)
{
string cmd = $"INSERT INTO app.collisionrecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.collisionrecords_id_seq', (SELECT MAX(id) from app.collisionrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<ServiceRecord>("servicerecords");
servicerecords = table.FindAll().ToList();
};
foreach (var record in servicerecords)
{
string cmd = $"INSERT INTO app.servicerecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.servicerecords_id_seq', (SELECT MAX(id) from app.servicerecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<UpgradeRecord>("upgraderecords");
upgraderecords = table.FindAll().ToList();
};
foreach (var record in upgraderecords)
{
string cmd = $"INSERT INTO app.upgraderecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.upgraderecords_id_seq', (SELECT MAX(id) from app.upgraderecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
#endregion
#region "Part2"
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<GasRecord>("gasrecords");
gasrecords = table.FindAll().ToList();
};
foreach (var record in gasrecords)
{
string cmd = $"INSERT INTO app.gasrecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.gasrecords_id_seq', (SELECT MAX(id) from app.gasrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<Note>("notes");
noterecords = table.FindAll().ToList();
};
foreach (var record in noterecords)
{
string cmd = $"INSERT INTO app.notes (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.notes_id_seq', (SELECT MAX(id) from app.notes));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<OdometerRecord>("odometerrecords");
odometerrecords = table.FindAll().ToList();
};
foreach (var record in odometerrecords)
{
string cmd = $"INSERT INTO app.odometerrecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.odometerrecords_id_seq', (SELECT MAX(id) from app.odometerrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<ReminderRecord>("reminderrecords");
reminderrecords = table.FindAll().ToList();
};
foreach (var record in reminderrecords)
{
string cmd = $"INSERT INTO app.reminderrecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.reminderrecords_id_seq', (SELECT MAX(id) from app.reminderrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
#endregion
#region "Part3"
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<PlanRecord>("planrecords");
planrecords = table.FindAll().ToList();
};
foreach (var record in planrecords)
{
string cmd = $"INSERT INTO app.planrecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.planrecords_id_seq', (SELECT MAX(id) from app.planrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<PlanRecordInput>("planrecordtemplates");
planrecordtemplates = table.FindAll().ToList();
};
foreach (var record in planrecordtemplates)
{
string cmd = $"INSERT INTO app.planrecordtemplates (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.planrecordtemplates_id_seq', (SELECT MAX(id) from app.planrecordtemplates));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<SupplyRecord>("supplyrecords");
supplyrecords = table.FindAll().ToList();
};
foreach (var record in supplyrecords)
{
string cmd = $"INSERT INTO app.supplyrecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.supplyrecords_id_seq', (SELECT MAX(id) from app.supplyrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<TaxRecord>("taxrecords");
taxrecords = table.FindAll().ToList();
};
foreach (var record in taxrecords)
{
string cmd = $"INSERT INTO app.taxrecords (id, vehicleId, data) VALUES(@id, @vehicleId, CAST(@data AS jsonb)); SELECT setval('app.taxrecords_id_seq', (SELECT MAX(id) from app.taxrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("vehicleId", record.VehicleId);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
#endregion
#region "Part4"
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<UserData>("userrecords");
userrecords = table.FindAll().ToList();
};
foreach (var record in userrecords)
{
string cmd = $"INSERT INTO app.userrecords (id, username, emailaddress, password, isadmin) VALUES(@id, @username, @emailaddress, @password, @isadmin); SELECT setval('app.userrecords_id_seq', (SELECT MAX(id) from app.userrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("username", record.UserName);
ctext.Parameters.AddWithValue("emailaddress", record.EmailAddress);
ctext.Parameters.AddWithValue("password", record.Password);
ctext.Parameters.AddWithValue("isadmin", record.IsAdmin);
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<Token>("tokenrecords");
tokenrecords = table.FindAll().ToList();
};
foreach (var record in tokenrecords)
{
string cmd = $"INSERT INTO app.tokenrecords (id, emailaddress, body) VALUES(@id, @emailaddress, @body); SELECT setval('app.tokenrecords_id_seq', (SELECT MAX(id) from app.tokenrecords));";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("emailaddress", record.EmailAddress);
ctext.Parameters.AddWithValue("body", record.Body);
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<UserConfigData>("userconfigrecords");
userconfigrecords = table.FindAll().ToList();
};
foreach (var record in userconfigrecords)
{
string cmd = $"INSERT INTO app.userconfigrecords (id, data) VALUES(@id, CAST(@data AS jsonb))";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<UserAccess>("useraccessrecords");
useraccessrecords = table.FindAll().ToList();
};
foreach (var record in useraccessrecords)
{
string cmd = $"INSERT INTO app.useraccessrecords (userId, vehicleId) VALUES(@userId, @vehicleId)";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("userId", record.Id.UserId);
ctext.Parameters.AddWithValue("vehicleId", record.Id.VehicleId);
ctext.ExecuteNonQuery();
}
}
#endregion
#region "Part5"
using (var db = new LiteDatabase(fullFileName))
{
var table = db.GetCollection<RecordExtraField>("extrafields");
extrafields = table.FindAll().ToList();
};
foreach (var record in extrafields)
{
string cmd = $"INSERT INTO app.extrafields (id, data) VALUES(@id, CAST(@data AS jsonb))";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("data", System.Text.Json.JsonSerializer.Serialize(record));
ctext.ExecuteNonQuery();
}
}
#endregion
return Json(new OperationResponse { Success = true, Message = "Data Imported Successfully" });
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage });
}
}
}
}

View File

@@ -27,7 +27,6 @@ namespace CarCareTracker.Controllers
private readonly IUpgradeRecordDataAccess _upgradeRecordDataAccess;
private readonly ISupplyRecordDataAccess _supplyRecordDataAccess;
private readonly IPlanRecordDataAccess _planRecordDataAccess;
private readonly IPlanRecordTemplateDataAccess _planRecordTemplateDataAccess;
private readonly IOdometerRecordDataAccess _odometerRecordDataAccess;
private readonly IWebHostEnvironment _webEnv;
private readonly IConfigHelper _config;
@@ -36,7 +35,6 @@ namespace CarCareTracker.Controllers
private readonly IReminderHelper _reminderHelper;
private readonly IReportHelper _reportHelper;
private readonly IUserLogic _userLogic;
private readonly IExtraFieldDataAccess _extraFieldDataAccess;
public VehicleController(ILogger<VehicleController> logger,
IFileHelper fileHelper,
@@ -53,9 +51,7 @@ namespace CarCareTracker.Controllers
IUpgradeRecordDataAccess upgradeRecordDataAccess,
ISupplyRecordDataAccess supplyRecordDataAccess,
IPlanRecordDataAccess planRecordDataAccess,
IPlanRecordTemplateDataAccess planRecordTemplateDataAccess,
IOdometerRecordDataAccess odometerRecordDataAccess,
IExtraFieldDataAccess extraFieldDataAccess,
IUserLogic userLogic,
IWebHostEnvironment webEnv,
IConfigHelper config)
@@ -75,9 +71,7 @@ namespace CarCareTracker.Controllers
_upgradeRecordDataAccess = upgradeRecordDataAccess;
_supplyRecordDataAccess = supplyRecordDataAccess;
_planRecordDataAccess = planRecordDataAccess;
_planRecordTemplateDataAccess = planRecordTemplateDataAccess;
_odometerRecordDataAccess = odometerRecordDataAccess;
_extraFieldDataAccess = extraFieldDataAccess;
_userLogic = userLogic;
_webEnv = webEnv;
_config = config;
@@ -148,40 +142,11 @@ namespace CarCareTracker.Controllers
_reminderRecordDataAccess.DeleteAllReminderRecordsByVehicleId(vehicleId) &&
_upgradeRecordDataAccess.DeleteAllUpgradeRecordsByVehicleId(vehicleId) &&
_planRecordDataAccess.DeleteAllPlanRecordsByVehicleId(vehicleId) &&
_planRecordTemplateDataAccess.DeleteAllPlanRecordTemplatesByVehicleId(vehicleId) &&
_supplyRecordDataAccess.DeleteAllSupplyRecordsByVehicleId(vehicleId) &&
_userLogic.DeleteAllAccessToVehicle(vehicleId) &&
_dataAccess.DeleteVehicle(vehicleId);
return Json(result);
}
[HttpPost]
public IActionResult DuplicateVehicleCollaborators(int sourceVehicleId, int destVehicleId)
{
try
{
//retrieve collaborators for both source and destination vehicle id.
if (_userLogic.UserCanEditVehicle(GetUserID(), sourceVehicleId) && _userLogic.UserCanEditVehicle(GetUserID(), destVehicleId))
{
var sourceCollaborators = _userLogic.GetCollaboratorsForVehicle(sourceVehicleId).Select(x => x.UserVehicle.UserId).ToList();
var destCollaborators = _userLogic.GetCollaboratorsForVehicle(destVehicleId).Select(x => x.UserVehicle.UserId).ToList();
sourceCollaborators.RemoveAll(x => destCollaborators.Contains(x));
if (sourceCollaborators.Any()) {
foreach (int collaboratorId in sourceCollaborators)
{
_userLogic.AddUserAccessToVehicle(collaboratorId, destVehicleId);
}
} else
{
return Json(new OperationResponse { Success = false, Message = "Both vehicles already have identical collaborators" });
}
}
return Json(new OperationResponse { Success = true, Message = "Collaborators Copied"});
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage });
}
}
#region "Bulk Imports and Exports"
[HttpGet]
public IActionResult GetBulkImportModalPartialView(ImportMode mode)
@@ -192,7 +157,7 @@ namespace CarCareTracker.Controllers
[HttpGet]
public IActionResult ExportFromVehicleToCsv(int vehicleId, ImportMode mode)
{
if (vehicleId == default && mode != ImportMode.SupplyRecord)
if (vehicleId == default)
{
return Json(false);
}
@@ -207,7 +172,7 @@ namespace CarCareTracker.Controllers
var vehicleRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
if (vehicleRecords.Any())
{
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) });
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString() });
using (var writer = new StreamWriter(fullExportFilePath))
{
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
@@ -225,7 +190,7 @@ namespace CarCareTracker.Controllers
var vehicleRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
if (vehicleRecords.Any())
{
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) });
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString() });
using (var writer = new StreamWriter(fullExportFilePath))
{
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
@@ -243,7 +208,7 @@ namespace CarCareTracker.Controllers
var vehicleRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
if (vehicleRecords.Any())
{
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) });
var exportData = vehicleRecords.Select(x => new ServiceRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Odometer = x.Mileage.ToString() });
using (var writer = new StreamWriter(fullExportFilePath))
{
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
@@ -261,7 +226,7 @@ namespace CarCareTracker.Controllers
var vehicleRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
if (vehicleRecords.Any())
{
var exportData = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), Notes = x.Notes, Odometer = x.Mileage.ToString(), Tags = string.Join(" ", x.Tags) });
var exportData = vehicleRecords.Select(x => new OdometerRecordExportModel { Date = x.Date.ToShortDateString(), Notes = x.Notes, Odometer = x.Mileage.ToString() });
using (var writer = new StreamWriter(fullExportFilePath))
{
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
@@ -287,8 +252,7 @@ namespace CarCareTracker.Controllers
PartNumber = x.PartNumber,
PartQuantity = x.Quantity.ToString(),
PartSupplier = x.PartSupplier,
Notes = x.Notes,
Tags = string.Join(" ", x.Tags)
Notes = x.Notes
});
using (var writer = new StreamWriter(fullExportFilePath))
{
@@ -307,7 +271,7 @@ namespace CarCareTracker.Controllers
var vehicleRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
if (vehicleRecords.Any())
{
var exportData = vehicleRecords.Select(x => new TaxRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes, Tags = string.Join(" ", x.Tags) });
var exportData = vehicleRecords.Select(x => new TaxRecordExportModel { Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString("C"), Notes = x.Notes });
using (var writer = new StreamWriter(fullExportFilePath))
{
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
@@ -353,6 +317,7 @@ namespace CarCareTracker.Controllers
var vehicleRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
bool useMPG = _config.GetUserConfig(User).UseMPG;
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
{
@@ -363,8 +328,7 @@ namespace CarCareTracker.Controllers
Odometer = x.Mileage.ToString(),
IsFillToFull = x.IsFillToFull.ToString(),
MissedFuelUp = x.MissedFuelUp.ToString(),
Notes = x.Notes,
Tags = string.Join(" ", x.Tags)
Notes = x.Notes
});
using (var writer = new StreamWriter(fullExportFilePath))
{
@@ -381,11 +345,7 @@ namespace CarCareTracker.Controllers
[HttpPost]
public IActionResult ImportToVehicleIdFromCsv(int vehicleId, ImportMode mode, string fileName)
{
if (vehicleId == default && mode != ImportMode.SupplyRecord)
{
return Json(false);
}
if (string.IsNullOrWhiteSpace(fileName))
if (vehicleId == default || string.IsNullOrWhiteSpace(fileName))
{
return Json(false);
}
@@ -417,10 +377,9 @@ namespace CarCareTracker.Controllers
{
VehicleId = vehicleId,
Date = DateTime.Parse(importModel.Date),
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
Mileage = int.Parse(importModel.Odometer, NumberStyles.Any),
Gallons = decimal.Parse(importModel.FuelConsumed, NumberStyles.Any),
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes
};
if (string.IsNullOrWhiteSpace(importModel.Cost) && !string.IsNullOrWhiteSpace(importModel.Price))
{
@@ -462,11 +421,10 @@ namespace CarCareTracker.Controllers
{
VehicleId = vehicleId,
Date = DateTime.Parse(importModel.Date),
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
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),
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
};
_serviceRecordDataAccess.SaveServiceRecordToVehicle(convertedRecord);
}
@@ -476,9 +434,8 @@ namespace CarCareTracker.Controllers
{
VehicleId = vehicleId,
Date = DateTime.Parse(importModel.Date),
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
Mileage = int.Parse(importModel.Odometer, NumberStyles.Any),
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes
};
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(convertedRecord);
}
@@ -507,11 +464,10 @@ namespace CarCareTracker.Controllers
{
VehicleId = vehicleId,
Date = DateTime.Parse(importModel.Date),
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
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),
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
};
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(convertedRecord);
}
@@ -521,11 +477,10 @@ namespace CarCareTracker.Controllers
{
VehicleId = vehicleId,
Date = DateTime.Parse(importModel.Date),
Mileage = decimal.ToInt32(decimal.Parse(importModel.Odometer, NumberStyles.Any)),
Mileage = int.Parse(importModel.Odometer, NumberStyles.Any),
Description = string.IsNullOrWhiteSpace(importModel.Description) ? $"Upgrade Record on {importModel.Date}" : importModel.Description,
Notes = string.IsNullOrWhiteSpace(importModel.Notes) ? "" : importModel.Notes,
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
};
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(convertedRecord);
}
@@ -540,8 +495,7 @@ namespace CarCareTracker.Controllers
Quantity = decimal.Parse(importModel.PartQuantity, NumberStyles.Any),
Description = importModel.Description,
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any),
Notes = importModel.Notes,
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
Notes = importModel.Notes
};
_supplyRecordDataAccess.SaveSupplyRecordToVehicle(convertedRecord);
}
@@ -553,8 +507,7 @@ namespace CarCareTracker.Controllers
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),
Tags = string.IsNullOrWhiteSpace(importModel.Tags) ? [] : importModel.Tags.Split(" ").ToList()
Cost = decimal.Parse(importModel.Cost, NumberStyles.Any)
};
_taxRecordDataAccess.SaveTaxRecordToVehicle(convertedRecord);
}
@@ -577,6 +530,8 @@ namespace CarCareTracker.Controllers
public IActionResult GetGasRecordsByVehicleId(int vehicleId)
{
var result = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
//need it in ascending order to perform computation.
result = result.OrderBy(x => x.Date).ThenBy(x => x.Mileage).ToList();
//check if the user uses MPG or Liters per 100km.
var userConfig = _config.GetUserConfig(User);
bool useMPG = userConfig.UseMPG;
@@ -586,13 +541,10 @@ namespace CarCareTracker.Controllers
{
computedResults = computedResults.OrderByDescending(x => DateTime.Parse(x.Date)).ThenByDescending(x => x.Mileage).ToList();
}
var vehicleData = _dataAccess.GetVehicleById(vehicleId);
var vehicleIsElectric = vehicleData.IsElectric;
var vehicleUseHours = vehicleData.UseHours;
var vehicleIsElectric = _dataAccess.GetVehicleById(vehicleId).IsElectric;
var viewModel = new GasRecordViewModelContainer()
{
UseKwh = vehicleIsElectric,
UseHours = vehicleUseHours,
GasRecords = computedResults
};
return PartialView("_Gas", viewModel);
@@ -615,12 +567,9 @@ namespace CarCareTracker.Controllers
return Json(result);
}
[HttpGet]
public IActionResult GetAddGasRecordPartialView(int vehicleId)
public IActionResult GetAddGasRecordPartialView()
{
var vehicleData = _dataAccess.GetVehicleById(vehicleId);
var vehicleIsElectric = vehicleData.IsElectric;
var vehicleUseHours = vehicleData.UseHours;
return PartialView("_GasModal", new GasRecordInputContainer() { UseKwh = vehicleIsElectric, UseHours = vehicleUseHours, GasRecord = new GasRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.GasRecord).ExtraFields } });
return PartialView("_GasModal", new GasRecordInputContainer() { GasRecord = new GasRecordInput() });
}
[HttpGet]
public IActionResult GetGasRecordForEditById(int gasRecordId)
@@ -637,17 +586,12 @@ namespace CarCareTracker.Controllers
Gallons = result.Gallons,
IsFillToFull = result.IsFillToFull,
MissedFuelUp = result.MissedFuelUp,
Notes = result.Notes,
Tags = result.Tags,
ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.GasRecord).ExtraFields)
Notes = result.Notes
};
var vehicleData = _dataAccess.GetVehicleById(convertedResult.VehicleId);
var vehicleIsElectric = vehicleData.IsElectric;
var vehicleUseHours = vehicleData.UseHours;
var vehicleIsElectric = _dataAccess.GetVehicleById(convertedResult.VehicleId).IsElectric;
var viewModel = new GasRecordInputContainer()
{
UseKwh = vehicleIsElectric,
UseHours = vehicleUseHours,
GasRecord = convertedResult
};
return PartialView("_GasModal", viewModel);
@@ -658,15 +602,6 @@ namespace CarCareTracker.Controllers
var result = _gasRecordDataAccess.DeleteGasRecordById(gasRecordId);
return Json(result);
}
[HttpPost]
public IActionResult SaveUserGasTabPreferences(string gasUnit, string fuelMileageUnit)
{
var currentConfig = _config.GetUserConfig(User);
currentConfig.PreferredGasUnit = gasUnit;
currentConfig.PreferredGasMileageUnit = fuelMileageUnit;
var result = _config.SaveUserConfig(User, currentConfig);
return Json(result);
}
#endregion
#region "Service Records"
[TypeFilter(typeof(CollaboratorFilter))]
@@ -700,17 +635,17 @@ namespace CarCareTracker.Controllers
}
//move files from temp.
serviceRecord.Files = serviceRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
if (serviceRecord.Supplies.Any())
{
serviceRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(serviceRecord.Supplies, DateTime.Parse(serviceRecord.Date), serviceRecord.Description);
}
var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord());
if (result && serviceRecord.Supplies.Any())
{
RequisitionSupplyRecordsByUsage(serviceRecord.Supplies);
}
return Json(result);
}
[HttpGet]
public IActionResult GetAddServiceRecordPartialView()
{
return PartialView("_ServiceRecordModal", new ServiceRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.ServiceRecord).ExtraFields });
return PartialView("_ServiceRecordModal", new ServiceRecordInput());
}
[HttpGet]
public IActionResult GetServiceRecordForEditById(int serviceRecordId)
@@ -726,10 +661,7 @@ namespace CarCareTracker.Controllers
Mileage = result.Mileage,
Notes = result.Notes,
VehicleId = result.VehicleId,
Files = result.Files,
Tags = result.Tags,
RequisitionHistory = result.RequisitionHistory,
ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.ServiceRecord).ExtraFields)
Files = result.Files
};
return PartialView("_ServiceRecordModal", convertedResult);
}
@@ -772,17 +704,17 @@ namespace CarCareTracker.Controllers
}
//move files from temp.
collisionRecord.Files = collisionRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
if (collisionRecord.Supplies.Any())
{
collisionRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(collisionRecord.Supplies, DateTime.Parse(collisionRecord.Date), collisionRecord.Description);
}
var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord());
if (result && collisionRecord.Supplies.Any())
{
RequisitionSupplyRecordsByUsage(collisionRecord.Supplies);
}
return Json(result);
}
[HttpGet]
public IActionResult GetAddCollisionRecordPartialView()
{
return PartialView("_CollisionRecordModal", new CollisionRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.RepairRecord).ExtraFields });
return PartialView("_CollisionRecordModal", new CollisionRecordInput());
}
[HttpGet]
public IActionResult GetCollisionRecordForEditById(int collisionRecordId)
@@ -798,10 +730,7 @@ namespace CarCareTracker.Controllers
Mileage = result.Mileage,
Notes = result.Notes,
VehicleId = result.VehicleId,
Files = result.Files,
Tags = result.Tags,
RequisitionHistory = result.RequisitionHistory,
ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.RepairRecord).ExtraFields)
Files = result.Files
};
return PartialView("_CollisionRecordModal", convertedResult);
}
@@ -837,14 +766,7 @@ namespace CarCareTracker.Controllers
{
foreach(TaxRecord recurringFee in recurringFees)
{
var newDate = new DateTime();
if (recurringFee.RecurringInterval != ReminderMonthInterval.Other)
{
newDate = recurringFee.Date.AddMonths((int)recurringFee.RecurringInterval);
} else
{
newDate = recurringFee.Date.AddMonths(recurringFee.CustomMonthInterval);
}
var newDate = recurringFee.Date.AddMonths((int)recurringFee.RecurringInterval);
if (DateTime.Now > newDate){
recurringFee.IsRecurring = false;
var newRecurringFee = new TaxRecord()
@@ -856,10 +778,7 @@ namespace CarCareTracker.Controllers
IsRecurring = true,
Notes = recurringFee.Notes,
RecurringInterval = recurringFee.RecurringInterval,
CustomMonthInterval = recurringFee.CustomMonthInterval,
Files = recurringFee.Files,
Tags = recurringFee.Tags,
ExtraFields = recurringFee.ExtraFields
Files = recurringFee.Files
};
_taxRecordDataAccess.SaveTaxRecordToVehicle(recurringFee);
_taxRecordDataAccess.SaveTaxRecordToVehicle(newRecurringFee);
@@ -878,7 +797,7 @@ namespace CarCareTracker.Controllers
[HttpGet]
public IActionResult GetAddTaxRecordPartialView()
{
return PartialView("_TaxRecordModal", new TaxRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.TaxRecord).ExtraFields });
return PartialView("_TaxRecordModal", new TaxRecordInput());
}
[HttpGet]
public IActionResult GetTaxRecordForEditById(int taxRecordId)
@@ -895,10 +814,7 @@ namespace CarCareTracker.Controllers
VehicleId = result.VehicleId,
IsRecurring = result.IsRecurring,
RecurringInterval = result.RecurringInterval,
CustomMonthInterval = result.CustomMonthInterval,
Files = result.Files,
Tags = result.Tags,
ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.TaxRecord).ExtraFields)
Files = result.Files
};
return PartialView("_TaxRecordModal", convertedResult);
}
@@ -920,7 +836,6 @@ namespace CarCareTracker.Controllers
var collisionRecords = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId);
var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
var upgradeRecords = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId);
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
var viewModel = new ReportViewModel();
//get totalCostMakeUp
viewModel.CostMakeUpForVehicle = new CostMakeUpForVehicle
@@ -938,12 +853,10 @@ namespace CarCareTracker.Controllers
allCosts.AddRange(_reportHelper.GetUpgradeRecordSum(upgradeRecords, 0));
allCosts.AddRange(_reportHelper.GetGasRecordSum(gasRecords, 0));
allCosts.AddRange(_reportHelper.GetTaxRecordSum(taxRecords, 0));
allCosts.AddRange(_reportHelper.GetOdometerRecordSum(odometerRecords, 0));
viewModel.CostForVehicleByMonth = allCosts.GroupBy(x => new { x.MonthName, x.MonthId }).OrderBy(x => x.Key.MonthId).Select(x => new CostForVehicleByMonth
{
MonthName = x.Key.MonthName,
Cost = x.Sum(y => y.Cost),
DistanceTraveled = x.Any(y=>y.MinMileage != default) ? x.Max(y=>y.MaxMileage) - x.Where(y=>y.MinMileage != default).Min(y=>y.MinMileage) : 0
Cost = x.Sum(y => y.Cost)
}).ToList();
//get reminders
var reminders = GetRemindersAndUrgency(vehicleId, DateTime.Now);
@@ -1062,84 +975,6 @@ namespace CarCareTracker.Controllers
return PartialView("_ReminderMakeUpReport", viewModel);
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpPost]
public IActionResult GetVehicleAttachments(int vehicleId, List<ImportMode> exportTabs)
{
List<GenericReportModel> attachmentData = new List<GenericReportModel>();
if (exportTabs.Contains(ImportMode.ServiceRecord)){
var records = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId).Where(x=>x.Files.Any());
attachmentData.AddRange(records.Select(x => new GenericReportModel
{
Date = x.Date,
Odometer = x.Mileage,
Files = x.Files
}));
}
if (exportTabs.Contains(ImportMode.RepairRecord))
{
var records = _collisionRecordDataAccess.GetCollisionRecordsByVehicleId(vehicleId).Where(x => x.Files.Any());
attachmentData.AddRange(records.Select(x => new GenericReportModel
{
Date = x.Date,
Odometer = x.Mileage,
Files = x.Files
}));
}
if (exportTabs.Contains(ImportMode.UpgradeRecord))
{
var records = _upgradeRecordDataAccess.GetUpgradeRecordsByVehicleId(vehicleId).Where(x => x.Files.Any());
attachmentData.AddRange(records.Select(x => new GenericReportModel
{
Date = x.Date,
Odometer = x.Mileage,
Files = x.Files
}));
}
if (exportTabs.Contains(ImportMode.GasRecord))
{
var records = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId).Where(x => x.Files.Any());
attachmentData.AddRange(records.Select(x => new GenericReportModel
{
Date = x.Date,
Odometer = x.Mileage,
Files = x.Files
}));
}
if (exportTabs.Contains(ImportMode.TaxRecord))
{
var records = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId).Where(x => x.Files.Any());
attachmentData.AddRange(records.Select(x => new GenericReportModel
{
Date = x.Date,
Odometer = 0,
Files = x.Files
}));
}
if (exportTabs.Contains(ImportMode.OdometerRecord))
{
var records = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId).Where(x => x.Files.Any());
attachmentData.AddRange(records.Select(x => new GenericReportModel
{
Date = x.Date,
Odometer = x.Mileage,
Files = x.Files
}));
}
if (attachmentData.Any())
{
attachmentData = attachmentData.OrderBy(x => x.Date).ThenBy(x => x.Odometer).ToList();
var result = _fileHelper.MakeAttachmentsExport(attachmentData);
if (string.IsNullOrWhiteSpace(result))
{
return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage });
}
return Json(new OperationResponse { Success = true, Message = result });
} else
{
return Json(new OperationResponse { Success = false, Message = "No Attachments Found" });
}
}
[TypeFilter(typeof(CollaboratorFilter))]
public IActionResult GetVehicleHistory(int vehicleId)
{
var vehicleHistory = new VehicleHistoryViewModel();
@@ -1153,28 +988,15 @@ namespace CarCareTracker.Controllers
var gasRecords = _gasRecordDataAccess.GetGasRecordsByVehicleId(vehicleId);
bool useMPG = _config.GetUserConfig(User).UseMPG;
bool useUKMPG = _config.GetUserConfig(User).UseUKMPG;
string preferredFuelMileageUnit = _config.GetUserConfig(User).PreferredGasMileageUnit;
vehicleHistory.TotalGasCost = gasRecords.Sum(x => x.Cost);
vehicleHistory.TotalCost = serviceRecords.Sum(x => x.Cost) + repairRecords.Sum(x => x.Cost) + upgradeRecords.Sum(x => x.Cost) + taxRecords.Sum(x => x.Cost);
var averageMPG = "0";
var gasViewModels = _gasHelper.GetGasRecordViewModels(gasRecords, useMPG, useUKMPG);
if (gasViewModels.Any())
{
averageMPG = _gasHelper.GetAverageGasMileage(gasViewModels, useMPG);
averageMPG = _gasHelper.GetAverageGasMileage(gasViewModels);
}
var fuelEconomyMileageUnit = StaticHelper.GetFuelEconomyUnit(vehicleHistory.VehicleData.IsElectric, vehicleHistory.VehicleData.UseHours, useMPG, useUKMPG);
if (fuelEconomyMileageUnit == "l/100km" && preferredFuelMileageUnit == "km/l")
{
//conversion needed.
var newAverageMPG = decimal.Parse(averageMPG, NumberStyles.Any);
if (newAverageMPG != 0)
{
newAverageMPG = 100 / newAverageMPG;
}
averageMPG = newAverageMPG.ToString("F");
fuelEconomyMileageUnit = preferredFuelMileageUnit;
}
vehicleHistory.MPG = $"{averageMPG} {fuelEconomyMileageUnit}";
vehicleHistory.MPG = averageMPG;
//insert servicerecords
reportData.AddRange(serviceRecords.Select(x => new GenericReportModel
{
@@ -1272,16 +1094,10 @@ namespace CarCareTracker.Controllers
var taxRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId);
allCosts.AddRange(_reportHelper.GetTaxRecordSum(taxRecords, year));
}
if (selectedMetrics.Contains(ImportMode.OdometerRecord))
{
var odometerRecords = _odometerRecordDataAccess.GetOdometerRecordsByVehicleId(vehicleId);
allCosts.AddRange(_reportHelper.GetOdometerRecordSum(odometerRecords, year));
}
var groupedRecord = allCosts.GroupBy(x => new { x.MonthName, x.MonthId }).OrderBy(x => x.Key.MonthId).Select(x => new CostForVehicleByMonth
{
MonthName = x.Key.MonthName,
Cost = x.Sum(y => y.Cost),
DistanceTraveled = x.Any(y => y.MinMileage != default) ? x.Max(y => y.MaxMileage) - x.Where(y => y.MinMileage != default).Min(y => y.MinMileage) : 0
Cost = x.Sum(y => y.Cost)
}).ToList();
return PartialView("_GasCostByMonthReport", groupedRecord);
}
@@ -1409,9 +1225,7 @@ namespace CarCareTracker.Controllers
Metric = result.Metric,
IsRecurring = result.IsRecurring,
ReminderMileageInterval = result.ReminderMileageInterval,
ReminderMonthInterval = result.ReminderMonthInterval,
CustomMileageInterval = result.CustomMileageInterval,
CustomMonthInterval = result.CustomMonthInterval
ReminderMonthInterval = result.ReminderMonthInterval
};
return PartialView("_ReminderRecordModal", convertedResult);
}
@@ -1454,17 +1268,17 @@ namespace CarCareTracker.Controllers
}
//move files from temp.
upgradeRecord.Files = upgradeRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
if (upgradeRecord.Supplies.Any())
{
upgradeRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(upgradeRecord.Supplies, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Description);
}
var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord());
if (result && upgradeRecord.Supplies.Any())
{
RequisitionSupplyRecordsByUsage(upgradeRecord.Supplies);
}
return Json(result);
}
[HttpGet]
public IActionResult GetAddUpgradeRecordPartialView()
{
return PartialView("_UpgradeRecordModal", new UpgradeRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.UpgradeRecord).ExtraFields });
return PartialView("_UpgradeRecordModal", new UpgradeRecordInput());
}
[HttpGet]
public IActionResult GetUpgradeRecordForEditById(int upgradeRecordId)
@@ -1480,10 +1294,7 @@ namespace CarCareTracker.Controllers
Mileage = result.Mileage,
Notes = result.Notes,
VehicleId = result.VehicleId,
Files = result.Files,
Tags = result.Tags,
RequisitionHistory = result.RequisitionHistory,
ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.UpgradeRecord).ExtraFields)
Files = result.Files
};
return PartialView("_UpgradeRecordModal", convertedResult);
}
@@ -1503,14 +1314,6 @@ namespace CarCareTracker.Controllers
result = result.OrderByDescending(x => x.Pinned).ToList();
return PartialView("_Notes", result);
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpGet]
public IActionResult GetPinnedNotesByVehicleId(int vehicleId)
{
var result = _noteDataAccess.GetNotesByVehicleId(vehicleId);
result = result.Where(x=>x.Pinned).ToList();
return Json(result);
}
[HttpPost]
public IActionResult SaveNoteToVehicleId(Note note)
{
@@ -1536,28 +1339,8 @@ namespace CarCareTracker.Controllers
}
#endregion
#region "Supply Records"
private List<string> CheckSupplyRecordsAvailability(List<SupplyUsage> supplyUsage)
private void RequisitionSupplyRecordsByUsage(List<SupplyUsage> supplyUsage)
{
//returns empty string if all supplies are available
var result = new List<string>();
foreach (SupplyUsage supply in supplyUsage)
{
//get supply record.
var supplyData = _supplyRecordDataAccess.GetSupplyRecordById(supply.SupplyId);
if (supplyData == null)
{
result.Add("Missing Supplies, Please Delete This Template and Recreate It.");
}
else if (supply.Quantity > supplyData.Quantity)
{
result.Add($"Insufficient Quantity for {supplyData.Description}, need: {supply.Quantity}, available: {supplyData.Quantity}");
}
}
return result;
}
private List<SupplyUsageHistory> RequisitionSupplyRecordsByUsage(List<SupplyUsage> supplyUsage, DateTime dateRequisitioned, string usageDescription)
{
List<SupplyUsageHistory> results = new List<SupplyUsageHistory>();
foreach(SupplyUsage supply in supplyUsage)
{
//get supply record.
@@ -1567,29 +1350,9 @@ namespace CarCareTracker.Controllers
result.Quantity -= supply.Quantity;
//deduct cost.
result.Cost -= (supply.Quantity * unitCost);
//check decimal places to ensure that it always has a max of 3 decimal places.
var roundedDecimal = decimal.Round(result.Cost, 3);
if (roundedDecimal != result.Cost)
{
//Too many decimals
result.Cost = roundedDecimal;
}
//create new requisitionrrecord
var requisitionRecord = new SupplyUsageHistory
{
Date = dateRequisitioned,
Description = usageDescription,
Quantity = supply.Quantity,
Cost = (supply.Quantity * unitCost)
};
result.RequisitionHistory.Add(requisitionRecord);
//save
_supplyRecordDataAccess.SaveSupplyRecordToVehicle(result);
requisitionRecord.Description = result.Description; //change the name of the description for plan/service/repair/upgrade records
requisitionRecord.PartNumber = result.PartNumber; //populate part number if not displayed in supplies modal.
results.Add(requisitionRecord);
}
return results;
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpGet]
@@ -1612,10 +1375,6 @@ namespace CarCareTracker.Controllers
public IActionResult GetSupplyRecordsForRecordsByVehicleId(int vehicleId)
{
var result = _supplyRecordDataAccess.GetSupplyRecordsByVehicleId(vehicleId);
if (_config.GetServerEnableShopSupplies())
{
result.AddRange(_supplyRecordDataAccess.GetSupplyRecordsByVehicleId(0)); // add shop supplies
}
result.RemoveAll(x => x.Quantity <= 0);
bool _useDescending = _config.GetUserConfig(User).UseDescending;
if (_useDescending)
@@ -1639,7 +1398,7 @@ namespace CarCareTracker.Controllers
[HttpGet]
public IActionResult GetAddSupplyRecordPartialView()
{
return PartialView("_SupplyRecordModal", new SupplyRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.SupplyRecord).ExtraFields });
return PartialView("_SupplyRecordModal", new SupplyRecordInput());
}
[HttpGet]
public IActionResult GetSupplyRecordForEditById(int supplyRecordId)
@@ -1657,10 +1416,7 @@ namespace CarCareTracker.Controllers
PartSupplier = result.PartSupplier,
Notes = result.Notes,
VehicleId = result.VehicleId,
Files = result.Files,
Tags = result.Tags,
RequisitionHistory = result.RequisitionHistory,
ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.SupplyRecord).ExtraFields)
Files = result.Files
};
return PartialView("_SupplyRecordModal", convertedResult);
}
@@ -1690,90 +1446,17 @@ namespace CarCareTracker.Controllers
planRecord.DateModified = DateTime.Now.ToString("G");
//move files from temp.
planRecord.Files = planRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
if (planRecord.Supplies.Any())
{
planRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(planRecord.Supplies, DateTime.Parse(planRecord.DateCreated), planRecord.Description);
}
var result = _planRecordDataAccess.SavePlanRecordToVehicle(planRecord.ToPlanRecord());
if (result && planRecord.Supplies.Any())
{
RequisitionSupplyRecordsByUsage(planRecord.Supplies);
}
return Json(result);
}
[HttpPost]
public IActionResult SavePlanRecordTemplateToVehicleId(PlanRecordInput planRecord)
{
//check if template name already taken.
var existingRecord = _planRecordTemplateDataAccess.GetPlanRecordTemplatesByVehicleId(planRecord.VehicleId).Where(x=>x.Description == planRecord.Description).Any();
if (existingRecord)
{
return Json(new OperationResponse { Success = false, Message = "A template with that description already exists for this vehicle"});
}
planRecord.Files = planRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
var result = _planRecordTemplateDataAccess.SavePlanRecordTemplateToVehicle(planRecord);
return Json(new OperationResponse { Success = result, Message = result ? "Template Added" : StaticHelper.GenericErrorMessage });
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpGet]
public IActionResult GetPlanRecordTemplatesForVehicleId(int vehicleId)
{
var result = _planRecordTemplateDataAccess.GetPlanRecordTemplatesByVehicleId(vehicleId);
return PartialView("_PlanRecordTemplateModal", result);
}
[HttpPost]
public IActionResult DeletePlanRecordTemplateById(int planRecordTemplateId)
{
var result = _planRecordTemplateDataAccess.DeletePlanRecordTemplateById(planRecordTemplateId);
return Json(result);
}
[HttpPost]
public IActionResult ConvertPlanRecordTemplateToPlanRecord(int planRecordTemplateId)
{
var existingRecord = _planRecordTemplateDataAccess.GetPlanRecordTemplateById(planRecordTemplateId);
if (existingRecord.Id == default)
{
return Json(new OperationResponse { Success = false, Message = "Unable to find template" });
}
if (existingRecord.Supplies.Any())
{
//check if all supplies are available
var supplyAvailability = CheckSupplyRecordsAvailability(existingRecord.Supplies);
if (supplyAvailability.Any())
{
return Json(new OperationResponse { Success = false, Message = string.Join("<br>", supplyAvailability) });
}
}
if (existingRecord.ReminderRecordId != default)
{
//check if reminder still exists and is still recurring.
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(existingRecord.ReminderRecordId);
if (existingReminder is null || existingReminder.Id == default || !existingReminder.IsRecurring)
{
return Json(new OperationResponse { Success = false, Message = "Missing or Non-recurring Reminder, Please Delete This Template and Recreate It." });
}
}
//populate createdDate
existingRecord.DateCreated = DateTime.Now.ToString("G");
existingRecord.DateModified = DateTime.Now.ToString("G");
existingRecord.Id = default;
if (existingRecord.Supplies.Any())
{
existingRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(existingRecord.Supplies, DateTime.Parse(existingRecord.DateCreated), existingRecord.Description);
}
var result = _planRecordDataAccess.SavePlanRecordToVehicle(existingRecord.ToPlanRecord());
return Json(new OperationResponse { Success = result, Message = result ? "Plan Record Added" : StaticHelper.GenericErrorMessage });
}
[HttpGet]
public IActionResult GetAddPlanRecordPartialView()
{
return PartialView("_PlanRecordModal", new PlanRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.PlanRecord).ExtraFields });
}
[HttpPost]
public IActionResult GetAddPlanRecordPartialView(PlanRecordInput? planModel)
{
if (planModel is not null)
{
planModel.ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.PlanRecord).ExtraFields;
return PartialView("_PlanRecordModal", planModel);
}
return PartialView("_PlanRecordModal", new PlanRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.PlanRecord).ExtraFields });
return PartialView("_PlanRecordModal", new PlanRecordInput());
}
[HttpPost]
public IActionResult UpdatePlanRecordProgress(int planRecordId, PlanProgress planProgress, int odometer = 0)
@@ -1791,8 +1474,7 @@ namespace CarCareTracker.Controllers
Date = DateTime.Now,
VehicleId = existingRecord.VehicleId,
Mileage = odometer,
Notes = $"Auto Insert From Plan Record: {existingRecord.Description}",
ExtraFields = existingRecord.ExtraFields
Notes = $"Auto Insert From Plan Record: {existingRecord.Description}"
});
}
//convert plan record to service/upgrade/repair record.
@@ -1806,9 +1488,7 @@ namespace CarCareTracker.Controllers
Description = existingRecord.Description,
Cost = existingRecord.Cost,
Notes = existingRecord.Notes,
Files = existingRecord.Files,
RequisitionHistory = existingRecord.RequisitionHistory,
ExtraFields = existingRecord.ExtraFields
Files = existingRecord.Files
};
_serviceRecordDataAccess.SaveServiceRecordToVehicle(newRecord);
}
@@ -1822,9 +1502,7 @@ namespace CarCareTracker.Controllers
Description = existingRecord.Description,
Cost = existingRecord.Cost,
Notes = existingRecord.Notes,
Files = existingRecord.Files,
RequisitionHistory = existingRecord.RequisitionHistory,
ExtraFields = existingRecord.ExtraFields
Files = existingRecord.Files
};
_collisionRecordDataAccess.SaveCollisionRecordToVehicle(newRecord);
}
@@ -1838,30 +1516,10 @@ namespace CarCareTracker.Controllers
Description = existingRecord.Description,
Cost = existingRecord.Cost,
Notes = existingRecord.Notes,
Files = existingRecord.Files,
RequisitionHistory = existingRecord.RequisitionHistory,
ExtraFields = existingRecord.ExtraFields
Files = existingRecord.Files
};
_upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(newRecord);
}
//push back any reminders
if (existingRecord.ReminderRecordId != default)
{
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(existingRecord.ReminderRecordId);
if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring)
{
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder);
//save to db.
var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
if (!reminderUpdateResult)
{
_logger.LogError("Unable to update reminder either because the reminder no longer exists or is no longer recurring");
}
} else
{
_logger.LogError("Unable to update reminder because it no longer exists.");
}
}
}
return Json(result);
}
@@ -1882,10 +1540,7 @@ namespace CarCareTracker.Controllers
Cost = result.Cost,
Notes = result.Notes,
VehicleId = result.VehicleId,
Files = result.Files,
RequisitionHistory = result.RequisitionHistory,
ReminderRecordId = result.ReminderRecordId,
ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.PlanRecord).ExtraFields)
Files = result.Files
};
return PartialView("_PlanRecordModal", convertedResult);
}
@@ -1924,7 +1579,7 @@ namespace CarCareTracker.Controllers
[HttpGet]
public IActionResult GetAddOdometerRecordPartialView()
{
return PartialView("_OdometerRecordModal", new OdometerRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.OdometerRecord).ExtraFields });
return PartialView("_OdometerRecordModal", new OdometerRecordInput());
}
[HttpGet]
public IActionResult GetOdometerRecordForEditById(int odometerRecordId)
@@ -1938,9 +1593,7 @@ namespace CarCareTracker.Controllers
Mileage = result.Mileage,
Notes = result.Notes,
VehicleId = result.VehicleId,
Files = result.Files,
Tags = result.Tags,
ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.OdometerRecord).ExtraFields)
Files = result.Files
};
return PartialView("_OdometerRecordModal", convertedResult);
}
@@ -1951,56 +1604,5 @@ namespace CarCareTracker.Controllers
return Json(result);
}
#endregion
#region "Shared Methods"
public IActionResult MoveRecord(int recordId, ImportMode source, ImportMode destination)
{
var genericRecord = new GenericRecord();
bool result = false;
//get
switch (source)
{
case ImportMode.ServiceRecord:
genericRecord = _serviceRecordDataAccess.GetServiceRecordById(recordId);
break;
case ImportMode.RepairRecord:
genericRecord = _collisionRecordDataAccess.GetCollisionRecordById(recordId);
break;
case ImportMode.UpgradeRecord:
genericRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId);
break;
}
//save
switch (destination)
{
case ImportMode.ServiceRecord:
result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(StaticHelper.GenericToServiceRecord(genericRecord));
break;
case ImportMode.RepairRecord:
result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(StaticHelper.GenericToRepairRecord(genericRecord));
break;
case ImportMode.UpgradeRecord:
result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(StaticHelper.GenericToUpgradeRecord(genericRecord));
break;
}
//delete
if (result)
{
switch (source)
{
case ImportMode.ServiceRecord:
_serviceRecordDataAccess.DeleteServiceRecordById(recordId);
break;
case ImportMode.RepairRecord:
_collisionRecordDataAccess.DeleteCollisionRecordById(recordId);
break;
case ImportMode.UpgradeRecord:
_upgradeRecordDataAccess.DeleteUpgradeRecordById(recordId);
break;
}
}
return Json(result);
}
#endregion
}
}

View File

@@ -2,7 +2,6 @@
{
public enum ReminderMileageInterval
{
Other = 0,
FiftyMiles = 50,
OneHundredMiles = 100,
FiveHundredMiles = 500,
@@ -15,9 +14,7 @@
FifteenThousandMiles = 15000,
TwentyThousandMiles = 20000,
ThirtyThousandMiles = 30000,
FortyThousandMiles = 40000,
FiftyThousandMiles = 50000,
SixtyThousandMiles = 60000,
OneHundredThousandMiles = 100000,
OneHundredFiftyThousandMiles = 150000
}

View File

@@ -2,7 +2,6 @@
{
public enum ReminderMonthInterval
{
Other = 0,
OneMonth = 1,
ThreeMonths = 3,
SixMonths = 6,

View File

@@ -1,30 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Helper;
using CarCareTracker.Models;
using LiteDB;
namespace CarCareTracker.External.Implementations
{
public class ExtraFieldDataAccess: IExtraFieldDataAccess
{
private static string dbName = StaticHelper.DbName;
private static string tableName = "extrafields";
public RecordExtraField GetExtraFieldsById(int importMode)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<RecordExtraField>(tableName);
return table.FindById(importMode) ?? new RecordExtraField();
};
}
public bool SaveExtraFields(RecordExtraField record)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<RecordExtraField>(tableName);
table.Upsert(record);
return true;
};
}
}
}

View File

@@ -1,57 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Helper;
using CarCareTracker.Models;
using LiteDB;
namespace CarCareTracker.External.Implementations
{
public class PlanRecordTemplateDataAccess : IPlanRecordTemplateDataAccess
{
private static string dbName = StaticHelper.DbName;
private static string tableName = "planrecordtemplates";
public List<PlanRecordInput> GetPlanRecordTemplatesByVehicleId(int vehicleId)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<PlanRecordInput>(tableName);
var planRecords = table.Find(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
return planRecords.ToList() ?? new List<PlanRecordInput>();
};
}
public PlanRecordInput GetPlanRecordTemplateById(int planRecordId)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<PlanRecordInput>(tableName);
return table.FindById(planRecordId);
};
}
public bool DeletePlanRecordTemplateById(int planRecordId)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<PlanRecordInput>(tableName);
table.Delete(planRecordId);
return true;
};
}
public bool SavePlanRecordTemplateToVehicle(PlanRecordInput planRecord)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<PlanRecordInput>(tableName);
table.Upsert(planRecord);
return true;
};
}
public bool DeleteAllPlanRecordTemplatesByVehicleId(int vehicleId)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<PlanRecord>(tableName);
var planRecords = table.DeleteMany(Query.EQ(nameof(PlanRecordInput.VehicleId), vehicleId));
return true;
};
}
}
}

View File

@@ -1,160 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGCollisionRecordDataAccess : ICollisionRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGCollisionRecordDataAccess> _logger;
private static string tableName = "collisionrecords";
public PGCollisionRecordDataAccess(IConfiguration config, ILogger<PGCollisionRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<CollisionRecord> GetCollisionRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<CollisionRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
CollisionRecord collisionRecord = JsonSerializer.Deserialize<CollisionRecord>(reader["data"] as string);
results.Add(collisionRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<CollisionRecord>();
}
}
public CollisionRecord GetCollisionRecordById(int collisionRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new CollisionRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", collisionRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
CollisionRecord collisionRecord = JsonSerializer.Deserialize<CollisionRecord>(reader["data"] as string);
result = collisionRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new CollisionRecord();
}
}
public bool DeleteCollisionRecordById(int collisionRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", collisionRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SaveCollisionRecordToVehicle(CollisionRecord collisionRecord)
{
try
{
if (collisionRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", collisionRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
collisionRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (collisionRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(collisionRecord);
ctextU.Parameters.AddWithValue("id", collisionRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return collisionRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(collisionRecord);
ctext.Parameters.AddWithValue("id", collisionRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllCollisionRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,76 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGExtraFieldDataAccess : IExtraFieldDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGExtraFieldDataAccess> _logger;
private static string tableName = "extrafields";
public PGExtraFieldDataAccess(IConfiguration config, ILogger<PGExtraFieldDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT primary key, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public RecordExtraField GetExtraFieldsById(int importMode)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var results = new RecordExtraField();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", importMode);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
RecordExtraField result = JsonSerializer.Deserialize<RecordExtraField>(reader["data"] as string);
results = result;
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new RecordExtraField();
}
}
public bool SaveExtraFields(RecordExtraField record)
{
try
{
var existingRecord = GetExtraFieldsById(record.Id);
string cmd = $"INSERT INTO app.{tableName} (id, data) VALUES(@id, CAST(@data AS jsonb)) ON CONFLICT(id) DO UPDATE SET data = CAST(@data AS jsonb)";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", record.Id);
ctext.Parameters.AddWithValue("data", JsonSerializer.Serialize(record));
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGGasRecordDataAccess: IGasRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGGasRecordDataAccess> _logger;
private static string tableName = "gasrecords";
public PGGasRecordDataAccess(IConfiguration config, ILogger<PGGasRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<GasRecord> GetGasRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<GasRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
GasRecord gasRecord = JsonSerializer.Deserialize<GasRecord>(reader["data"] as string);
results.Add(gasRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<GasRecord>();
}
}
public GasRecord GetGasRecordById(int gasRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new GasRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", gasRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
GasRecord gasRecord = JsonSerializer.Deserialize<GasRecord>(reader["data"] as string);
result = gasRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new GasRecord();
}
}
public bool DeleteGasRecordById(int gasRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", gasRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SaveGasRecordToVehicle(GasRecord gasRecord)
{
try
{
if (gasRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", gasRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
gasRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (gasRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(gasRecord);
ctextU.Parameters.AddWithValue("id", gasRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return gasRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(gasRecord);
ctext.Parameters.AddWithValue("id", gasRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllGasRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,153 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGNoteDataAccess: INoteDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGNoteDataAccess> _logger;
private static string tableName = "notes";
public PGNoteDataAccess(IConfiguration config, ILogger<PGNoteDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<Note> GetNotesByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<Note>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
Note note = JsonSerializer.Deserialize<Note>(reader["data"] as string);
results.Add(note);
}
}
return results;
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<Note>();
}
}
public Note GetNoteById(int noteId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new Note();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", noteId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
Note note = JsonSerializer.Deserialize<Note>(reader["data"] as string);
result = note;
}
}
return result;
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return new Note();
}
}
public bool SaveNoteToVehicle(Note note)
{
try
{
if (note.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", note.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
note.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (note.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(note);
ctextU.Parameters.AddWithValue("id", note.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return note.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(note);
ctext.Parameters.AddWithValue("id", note.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteNoteById(int noteId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", noteId);
return ctext.ExecuteNonQuery() > 0;
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllNotesByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGOdometerRecordDataAccess : IOdometerRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGOdometerRecordDataAccess> _logger;
private static string tableName = "odometerrecords";
public PGOdometerRecordDataAccess(IConfiguration config, ILogger<PGOdometerRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<OdometerRecord> GetOdometerRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<OdometerRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
OdometerRecord odometerRecord = JsonSerializer.Deserialize<OdometerRecord>(reader["data"] as string);
results.Add(odometerRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<OdometerRecord>();
}
}
public OdometerRecord GetOdometerRecordById(int odometerRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new OdometerRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", odometerRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
OdometerRecord odometerRecord = JsonSerializer.Deserialize<OdometerRecord>(reader["data"] as string);
result = odometerRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new OdometerRecord();
}
}
public bool DeleteOdometerRecordById(int odometerRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", odometerRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SaveOdometerRecordToVehicle(OdometerRecord odometerRecord)
{
try
{
if (odometerRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", odometerRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
odometerRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (odometerRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(odometerRecord);
ctextU.Parameters.AddWithValue("id", odometerRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return odometerRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(odometerRecord);
ctext.Parameters.AddWithValue("id", odometerRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllOdometerRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGPlanRecordDataAccess : IPlanRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGPlanRecordDataAccess> _logger;
private static string tableName = "planrecords";
public PGPlanRecordDataAccess(IConfiguration config, ILogger<PGPlanRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<PlanRecord> GetPlanRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<PlanRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
PlanRecord planRecord = JsonSerializer.Deserialize<PlanRecord>(reader["data"] as string);
results.Add(planRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<PlanRecord>();
}
}
public PlanRecord GetPlanRecordById(int planRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new PlanRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", planRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
PlanRecord planRecord = JsonSerializer.Deserialize<PlanRecord>(reader["data"] as string);
result = planRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new PlanRecord();
}
}
public bool DeletePlanRecordById(int planRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", planRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SavePlanRecordToVehicle(PlanRecord planRecord)
{
try
{
if (planRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", planRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
planRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (planRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(planRecord);
ctextU.Parameters.AddWithValue("id", planRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return planRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(planRecord);
ctext.Parameters.AddWithValue("id", planRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllPlanRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGPlanRecordTemplateDataAccess : IPlanRecordTemplateDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGPlanRecordTemplateDataAccess> _logger;
private static string tableName = "planrecordtemplates";
public PGPlanRecordTemplateDataAccess(IConfiguration config, ILogger<PGPlanRecordTemplateDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<PlanRecordInput> GetPlanRecordTemplatesByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<PlanRecordInput>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
PlanRecordInput planRecord = JsonSerializer.Deserialize<PlanRecordInput>(reader["data"] as string);
results.Add(planRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<PlanRecordInput>();
}
}
public PlanRecordInput GetPlanRecordTemplateById(int planRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new PlanRecordInput();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", planRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
PlanRecordInput planRecord = JsonSerializer.Deserialize<PlanRecordInput>(reader["data"] as string);
result = planRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new PlanRecordInput();
}
}
public bool DeletePlanRecordTemplateById(int planRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", planRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SavePlanRecordTemplateToVehicle(PlanRecordInput planRecord)
{
try
{
if (planRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", planRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
planRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (planRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(planRecord);
ctextU.Parameters.AddWithValue("id", planRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return planRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(planRecord);
ctext.Parameters.AddWithValue("id", planRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllPlanRecordTemplatesByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGReminderRecordDataAccess : IReminderRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGReminderRecordDataAccess> _logger;
private static string tableName = "reminderrecords";
public PGReminderRecordDataAccess(IConfiguration config, ILogger<PGReminderRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<ReminderRecord> GetReminderRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<ReminderRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
ReminderRecord reminderRecord = JsonSerializer.Deserialize<ReminderRecord>(reader["data"] as string);
results.Add(reminderRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<ReminderRecord>();
}
}
public ReminderRecord GetReminderRecordById(int reminderRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new ReminderRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", reminderRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
ReminderRecord reminderRecord = JsonSerializer.Deserialize<ReminderRecord>(reader["data"] as string);
result = reminderRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new ReminderRecord();
}
}
public bool DeleteReminderRecordById(int reminderRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", reminderRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SaveReminderRecordToVehicle(ReminderRecord reminderRecord)
{
try
{
if (reminderRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", reminderRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
reminderRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (reminderRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(reminderRecord);
ctextU.Parameters.AddWithValue("id", reminderRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return reminderRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(reminderRecord);
ctext.Parameters.AddWithValue("id", reminderRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllReminderRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGServiceRecordDataAccess: IServiceRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGServiceRecordDataAccess> _logger;
private static string tableName = "servicerecords";
public PGServiceRecordDataAccess(IConfiguration config, ILogger<PGServiceRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<ServiceRecord> GetServiceRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<ServiceRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
ServiceRecord serviceRecord = JsonSerializer.Deserialize<ServiceRecord>(reader["data"] as string);
results.Add(serviceRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<ServiceRecord>();
}
}
public ServiceRecord GetServiceRecordById(int serviceRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new ServiceRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", serviceRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
ServiceRecord serviceRecord = JsonSerializer.Deserialize<ServiceRecord>(reader["data"] as string);
result = serviceRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new ServiceRecord();
}
}
public bool DeleteServiceRecordById(int serviceRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", serviceRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SaveServiceRecordToVehicle(ServiceRecord serviceRecord)
{
try
{
if (serviceRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", serviceRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
serviceRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (serviceRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(serviceRecord);
ctextU.Parameters.AddWithValue("id", serviceRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return serviceRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(serviceRecord);
ctext.Parameters.AddWithValue("id", serviceRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllServiceRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGSupplyRecordDataAccess : ISupplyRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGSupplyRecordDataAccess> _logger;
private static string tableName = "supplyrecords";
public PGSupplyRecordDataAccess(IConfiguration config, ILogger<PGSupplyRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<SupplyRecord> GetSupplyRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<SupplyRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
SupplyRecord supplyRecord = JsonSerializer.Deserialize<SupplyRecord>(reader["data"] as string);
results.Add(supplyRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<SupplyRecord>();
}
}
public SupplyRecord GetSupplyRecordById(int supplyRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new SupplyRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", supplyRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
SupplyRecord supplyRecord = JsonSerializer.Deserialize<SupplyRecord>(reader["data"] as string);
result = supplyRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new SupplyRecord();
}
}
public bool DeleteSupplyRecordById(int supplyRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", supplyRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SaveSupplyRecordToVehicle(SupplyRecord supplyRecord)
{
try
{
if (supplyRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", supplyRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
supplyRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (supplyRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(supplyRecord);
ctextU.Parameters.AddWithValue("id", supplyRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return supplyRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(supplyRecord);
ctext.Parameters.AddWithValue("id", supplyRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllSupplyRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGTaxRecordDataAccess : ITaxRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGTaxRecordDataAccess> _logger;
private static string tableName = "taxrecords";
public PGTaxRecordDataAccess(IConfiguration config, ILogger<PGTaxRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<TaxRecord> GetTaxRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<TaxRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
TaxRecord taxRecord = JsonSerializer.Deserialize<TaxRecord>(reader["data"] as string);
results.Add(taxRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<TaxRecord>();
}
}
public TaxRecord GetTaxRecordById(int taxRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new TaxRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", taxRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
TaxRecord taxRecord = JsonSerializer.Deserialize<TaxRecord>(reader["data"] as string);
result = taxRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new TaxRecord();
}
}
public bool DeleteTaxRecordById(int taxRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", taxRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SaveTaxRecordToVehicle(TaxRecord taxRecord)
{
try
{
if (taxRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", taxRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
taxRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (taxRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(taxRecord);
ctextU.Parameters.AddWithValue("id", taxRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return taxRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(taxRecord);
ctext.Parameters.AddWithValue("id", taxRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllTaxRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,143 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
namespace CarCareTracker.External.Implementations
{
public class PGTokenRecordDataAccess : ITokenRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGTokenRecordDataAccess> _logger;
private static string tableName = "tokenrecords";
public PGTokenRecordDataAccess(IConfiguration config, ILogger<PGTokenRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, body TEXT not null, emailaddress TEXT not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<Token> GetTokens()
{
try
{
string cmd = $"SELECT id, emailaddress, body FROM app.{tableName}";
var results = new List<Token>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
Token result = new Token();
result.Id = int.Parse(reader["id"].ToString());
result.EmailAddress = reader["emailaddress"].ToString();
result.Body = reader["body"].ToString();
results.Add(result);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<Token>();
}
}
public Token GetTokenRecordByBody(string tokenBody)
{
try
{
string cmd = $"SELECT id, emailaddress, body FROM app.{tableName} WHERE body = @body";
var result = new Token();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("body", tokenBody);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
result.Id = int.Parse(reader["id"].ToString());
result.EmailAddress = reader["emailaddress"].ToString();
result.Body = reader["body"].ToString();
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new Token();
}
}
public Token GetTokenRecordByEmailAddress(string emailAddress)
{
try
{
string cmd = $"SELECT id, emailaddress, body FROM app.{tableName} WHERE emailaddress = @emailaddress";
var result = new Token();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("emailaddress", emailAddress);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
result.Id = int.Parse(reader["id"].ToString());
result.EmailAddress = reader["emailaddress"].ToString();
result.Body = reader["body"].ToString();
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new Token();
}
}
public bool CreateNewToken(Token token)
{
try
{
string cmd = $"INSERT INTO app.{tableName} (emailaddress, body) VALUES(@emailaddress, @body) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("emailaddress", token.EmailAddress);
ctext.Parameters.AddWithValue("body", token.Body);
token.Id = Convert.ToInt32(ctext.ExecuteScalar());
return token.Id != default;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteToken(int tokenId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", tokenId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,159 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGUpgradeRecordDataAccess : IUpgradeRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGUpgradeRecordDataAccess> _logger;
private static string tableName = "upgraderecords";
public PGUpgradeRecordDataAccess(IConfiguration config, ILogger<PGUpgradeRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, vehicleId INT not null, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<UpgradeRecord> GetUpgradeRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<UpgradeRecord>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
UpgradeRecord upgradeRecord = JsonSerializer.Deserialize<UpgradeRecord>(reader["data"] as string);
results.Add(upgradeRecord);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<UpgradeRecord>();
}
}
public UpgradeRecord GetUpgradeRecordById(int upgradeRecordId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
var result = new UpgradeRecord();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", upgradeRecordId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
UpgradeRecord upgradeRecord = JsonSerializer.Deserialize<UpgradeRecord>(reader["data"] as string);
result = upgradeRecord;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new UpgradeRecord();
}
}
public bool DeleteUpgradeRecordById(int upgradeRecordId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", upgradeRecordId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool SaveUpgradeRecordToVehicle(UpgradeRecord upgradeRecord)
{
try
{
if (upgradeRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (vehicleId, data) VALUES(@vehicleId, CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", upgradeRecord.VehicleId);
ctext.Parameters.AddWithValue("data", "{}");
upgradeRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (upgradeRecord.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(upgradeRecord);
ctextU.Parameters.AddWithValue("id", upgradeRecord.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return upgradeRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(upgradeRecord);
ctext.Parameters.AddWithValue("id", upgradeRecord.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteAllUpgradeRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,211 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Net.Mail;
namespace CarCareTracker.External.Implementations
{
public class PGUserAccessDataAccess : IUserAccessDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGUserAccessDataAccess> _logger;
private static string tableName = "useraccessrecords";
public PGUserAccessDataAccess(IConfiguration config, ILogger<PGUserAccessDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (userId INT, vehicleId INT, PRIMARY KEY(userId, vehicleId))";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
/// <summary>
/// Gets a list of vehicles user have access to.
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public List<UserAccess> GetUserAccessByUserId(int userId)
{
try
{
string cmd = $"SELECT userId, vehicleId FROM app.{tableName} WHERE userId = @userId";
var results = new List<UserAccess>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("userId", userId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
UserAccess result = new UserAccess()
{
Id = new UserVehicle
{
UserId = int.Parse(reader["userId"].ToString()),
VehicleId = int.Parse(reader["vehicleId"].ToString())
}
};
results.Add(result);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<UserAccess>();
}
}
public UserAccess GetUserAccessByVehicleAndUserId(int userId, int vehicleId)
{
try
{
string cmd = $"SELECT userId, vehicleId FROM app.{tableName} WHERE userId = @userId AND vehicleId = @vehicleId";
UserAccess result = null;
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("userId", userId);
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
result = new UserAccess()
{
Id = new UserVehicle
{
UserId = int.Parse(reader["userId"].ToString()),
VehicleId = int.Parse(reader["vehicleId"].ToString())
}
};
return result;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new UserAccess();
}
}
public List<UserAccess> GetUserAccessByVehicleId(int vehicleId)
{
try
{
string cmd = $"SELECT userId, vehicleId FROM app.{tableName} WHERE vehicleId = @vehicleId";
var results = new List<UserAccess>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
UserAccess result = new UserAccess()
{
Id = new UserVehicle
{
UserId = int.Parse(reader["userId"].ToString()),
VehicleId = int.Parse(reader["vehicleId"].ToString())
}
};
results.Add(result);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<UserAccess>();
}
}
public bool SaveUserAccess(UserAccess userAccess)
{
try
{
string cmd = $"INSERT INTO app.{tableName} (userId, vehicleId) VALUES(@userId, @vehicleId)";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("userId", userAccess.Id.UserId);
ctext.Parameters.AddWithValue("vehicleId", userAccess.Id.VehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteUserAccess(int userId, int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE userId = @userId AND vehicleId = @vehicleId";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("userId", userId);
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
/// <summary>
/// Delete all access records when a vehicle is deleted.
/// </summary>
/// <param name="vehicleId"></param>
/// <returns></returns>
public bool DeleteAllAccessRecordsByVehicleId(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE vehicleId = @vehicleId";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("vehicleId", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
/// <summary>
/// Delee all access records when a user is deleted.
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public bool DeleteAllAccessRecordsByUserId(int userId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE userId = @userId";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("userId", userId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,107 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGUserConfigDataAccess: IUserConfigDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGUserConfigDataAccess> _logger;
private static string tableName = "userconfigrecords";
public PGUserConfigDataAccess(IConfiguration config, ILogger<PGUserConfigDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT primary key, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public UserConfigData GetUserConfig(int userId)
{
try
{
string cmd = $"SELECT data FROM app.{tableName} WHERE id = @id";
UserConfigData result = null;
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", userId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
UserConfigData userConfig = JsonSerializer.Deserialize<UserConfigData>(reader["data"] as string);
result = userConfig;
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new UserConfigData();
}
}
public bool SaveUserConfig(UserConfigData userConfigData)
{
var existingRecord = GetUserConfig(userConfigData.Id);
try
{
if (existingRecord == null)
{
string cmd = $"INSERT INTO app.{tableName} (id, data) VALUES(@id, CAST(@data AS jsonb))";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(userConfigData);
ctext.Parameters.AddWithValue("id", userConfigData.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(userConfigData);
ctext.Parameters.AddWithValue("id", userConfigData.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteUserConfig(int userId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", userId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,194 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
namespace CarCareTracker.External.Implementations
{
public class PGUserRecordDataAccess : IUserRecordDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGUserRecordDataAccess> _logger;
private static string tableName = "userrecords";
public PGUserRecordDataAccess(IConfiguration config, ILogger<PGUserRecordDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, username TEXT not null, emailaddress TEXT not null, password TEXT not null, isadmin BOOLEAN)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public List<UserData> GetUsers()
{
try
{
string cmd = $"SELECT id, username, emailaddress, password, isadmin FROM app.{tableName}";
var results = new List<UserData>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
UserData result = new UserData();
result.Id = int.Parse(reader["id"].ToString());
result.UserName = reader["username"].ToString();
result.EmailAddress = reader["emailaddress"].ToString();
result.Password = reader["password"].ToString();
result.IsAdmin = bool.Parse(reader["isadmin"].ToString());
results.Add(result);
}
}
return results;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<UserData>();
}
}
public UserData GetUserRecordByUserName(string userName)
{
try
{
string cmd = $"SELECT id, username, emailaddress, password, isadmin FROM app.{tableName} WHERE username = @username";
var result = new UserData();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("username", userName);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
result.Id = int.Parse(reader["id"].ToString());
result.UserName = reader["username"].ToString();
result.EmailAddress = reader["emailaddress"].ToString();
result.Password = reader["password"].ToString();
result.IsAdmin = bool.Parse(reader["isadmin"].ToString());
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new UserData();
}
}
public UserData GetUserRecordByEmailAddress(string emailAddress)
{
try
{
string cmd = $"SELECT id, username, emailaddress, password, isadmin FROM app.{tableName} WHERE emailaddress = @emailaddress";
var result = new UserData();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("emailaddress", emailAddress);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
result.Id = int.Parse(reader["id"].ToString());
result.UserName = reader["username"].ToString();
result.EmailAddress = reader["emailaddress"].ToString();
result.Password = reader["password"].ToString();
result.IsAdmin = bool.Parse(reader["isadmin"].ToString());
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new UserData();
}
}
public UserData GetUserRecordById(int userId)
{
try
{
string cmd = $"SELECT id, username, emailaddress, password, isadmin FROM app.{tableName} WHERE id = @id";
var result = new UserData();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", userId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
result.Id = int.Parse(reader["id"].ToString());
result.UserName = reader["username"].ToString();
result.EmailAddress = reader["emailaddress"].ToString();
result.Password = reader["password"].ToString();
result.IsAdmin = bool.Parse(reader["isadmin"].ToString());
}
}
return result;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return new UserData();
}
}
public bool SaveUserRecord(UserData userRecord)
{
try
{
if (userRecord.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (username, emailaddress, password, isadmin) VALUES(@username, @emailaddress, @password, @isadmin) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("username", userRecord.UserName);
ctext.Parameters.AddWithValue("emailaddress", userRecord.EmailAddress);
ctext.Parameters.AddWithValue("password", userRecord.Password);
ctext.Parameters.AddWithValue("isadmin", userRecord.IsAdmin);
userRecord.Id = Convert.ToInt32(ctext.ExecuteScalar());
return userRecord.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET username = @username, emailaddress = @emailaddress, password = @password, isadmin = @isadmin WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", userRecord.Id);
ctext.Parameters.AddWithValue("username", userRecord.UserName);
ctext.Parameters.AddWithValue("emailaddress", userRecord.EmailAddress);
ctext.Parameters.AddWithValue("password", userRecord.Password);
ctext.Parameters.AddWithValue("isadmin", userRecord.IsAdmin);
return ctext.ExecuteNonQuery() > 0;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public bool DeleteUserRecord(int userId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", userId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -1,138 +0,0 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGVehicleDataAccess: IVehicleDataAccess
{
private NpgsqlDataSource pgDataSource;
private readonly ILogger<PGVehicleDataAccess> _logger;
private static string tableName = "vehicles";
public PGVehicleDataAccess(IConfiguration config, ILogger<PGVehicleDataAccess> logger)
{
pgDataSource = NpgsqlDataSource.Create(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
//create table if not exist.
string initCMD = $"CREATE TABLE IF NOT EXISTS app.{tableName} (id INT GENERATED BY DEFAULT AS IDENTITY primary key, data jsonb not null)";
using (var ctext = pgDataSource.CreateCommand(initCMD))
{
ctext.ExecuteNonQuery();
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
public bool SaveVehicle(Vehicle vehicle)
{
try
{
if (string.IsNullOrWhiteSpace(vehicle.ImageLocation))
{
vehicle.ImageLocation = "/defaults/noimage.png";
}
if (vehicle.Id == default)
{
string cmd = $"INSERT INTO app.{tableName} (data) VALUES(CAST(@data AS jsonb)) RETURNING id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("data", "{}");
vehicle.Id = Convert.ToInt32(ctext.ExecuteScalar());
//update json data
if (vehicle.Id != default)
{
string cmdU = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctextU = pgDataSource.CreateCommand(cmdU))
{
var serializedData = JsonSerializer.Serialize(vehicle);
ctextU.Parameters.AddWithValue("id", vehicle.Id);
ctextU.Parameters.AddWithValue("data", serializedData);
return ctextU.ExecuteNonQuery() > 0;
}
}
return vehicle.Id != default;
}
}
else
{
string cmd = $"UPDATE app.{tableName} SET data = CAST(@data AS jsonb) WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
var serializedData = JsonSerializer.Serialize(vehicle);
ctext.Parameters.AddWithValue("id", vehicle.Id);
ctext.Parameters.AddWithValue("data", serializedData);
return ctext.ExecuteNonQuery() > 0;
}
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
}
return false;
}
public bool DeleteVehicle(int vehicleId)
{
try
{
string cmd = $"DELETE FROM app.{tableName} WHERE id = @id";
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
public List<Vehicle> GetVehicles()
{
try
{
string cmd = $"SELECT id, data FROM app.{tableName} ORDER BY id ASC";
var results = new List<Vehicle>();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
Vehicle vehicle = JsonSerializer.Deserialize<Vehicle>(reader["data"] as string);
results.Add(vehicle);
}
}
return results;
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return new List<Vehicle>();
}
}
public Vehicle GetVehicleById(int vehicleId)
{
try
{
string cmd = $"SELECT id, data FROM app.{tableName} WHERE id = @id";
Vehicle vehicle = new Vehicle();
using (var ctext = pgDataSource.CreateCommand(cmd))
{
ctext.Parameters.AddWithValue("id", vehicleId);
using (NpgsqlDataReader reader = ctext.ExecuteReader())
while (reader.Read())
{
vehicle = JsonSerializer.Deserialize<Vehicle>(reader["data"] as string);
}
}
return vehicle;
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return new Vehicle();
}
}
}
}

View File

@@ -0,0 +1,39 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Helper;
using CarCareTracker.Models;
using LiteDB;
namespace CarCareTracker.External.Implementations
{
public class TorqueRecordDataAccess: ITorqueRecordDataAccess
{
private static string dbName = StaticHelper.DbName;
private static string tableName = "torquerecords";
public TorqueRecord GetTorqueRecordById(string torqueRecordId)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<TorqueRecord>(tableName);
return table.FindById(torqueRecordId);
};
}
public bool DeleteTorqueRecordById(int torqueRecordId)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<TorqueRecord>(tableName);
table.Delete(torqueRecordId);
return true;
};
}
public bool SaveTorqueRecord(TorqueRecord torqueRecord)
{
using (var db = new LiteDatabase(dbName))
{
var table = db.GetCollection<TorqueRecord>(tableName);
table.Upsert(torqueRecord);
return true;
};
}
}
}

View File

@@ -2,6 +2,7 @@
using CarCareTracker.Helper;
using CarCareTracker.Models;
using LiteDB;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace CarCareTracker.External.Implementations
{

View File

@@ -1,10 +0,0 @@
using CarCareTracker.Models;
namespace CarCareTracker.External.Interfaces
{
public interface IExtraFieldDataAccess
{
public RecordExtraField GetExtraFieldsById(int importMode);
public bool SaveExtraFields(RecordExtraField record);
}
}

View File

@@ -1,13 +0,0 @@
using CarCareTracker.Models;
namespace CarCareTracker.External.Interfaces
{
public interface IPlanRecordTemplateDataAccess
{
public List<PlanRecordInput> GetPlanRecordTemplatesByVehicleId(int vehicleId);
public PlanRecordInput GetPlanRecordTemplateById(int planRecordId);
public bool DeletePlanRecordTemplateById(int planRecordId);
public bool SavePlanRecordTemplateToVehicle(PlanRecordInput planRecord);
public bool DeleteAllPlanRecordTemplatesByVehicleId(int vehicleId);
}
}

View File

@@ -0,0 +1,11 @@
using CarCareTracker.Models;
namespace CarCareTracker.External.Interfaces
{
public interface ITorqueRecordDataAccess
{
public TorqueRecord GetTorqueRecordById(string torqueRecordId);
public bool DeleteTorqueRecordById(int torqueRecordId);
public bool SaveTorqueRecord(TorqueRecord torqueRecord);
}
}

View File

@@ -1,5 +1,4 @@
using CarCareTracker.Helper;
using CarCareTracker.Logic;
using CarCareTracker.Logic;
using CarCareTracker.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
@@ -10,37 +9,19 @@ namespace CarCareTracker.Filter
public class CollaboratorFilter: ActionFilterAttribute
{
private readonly IUserLogic _userLogic;
private readonly IConfigHelper _config;
public CollaboratorFilter(IUserLogic userLogic, IConfigHelper config) {
public CollaboratorFilter(IUserLogic userLogic) {
_userLogic = userLogic;
_config = config;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.User.IsInRole(nameof(UserData.IsRootUser)))
{
var vehicleId = int.Parse(filterContext.ActionArguments["vehicleId"].ToString());
if (vehicleId != default)
{
var userId = int.Parse(filterContext.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier));
if (!_userLogic.UserCanEditVehicle(userId, vehicleId))
{
filterContext.Result = new RedirectResult("/Error/Unauthorized");
}
} else
{
var shopSupplyEndpoints = new List<string> { "ImportToVehicleIdFromCsv", "GetSupplyRecordsByVehicleId", "ExportFromVehicleToCsv" };
if (shopSupplyEndpoints.Contains(filterContext.RouteData.Values["action"].ToString()) && !_config.GetServerEnableShopSupplies())
{
//user trying to access shop supplies but shop supplies is not enabled by root user.
filterContext.Result = new RedirectResult("/Error/Unauthorized");
}
else if (!shopSupplyEndpoints.Contains(filterContext.RouteData.Values["action"].ToString()))
{
//user trying to access any other endpoints using 0 as vehicle id.
filterContext.Result = new RedirectResult("/Error/Unauthorized");
}
}
}
}
}

View File

@@ -7,13 +7,8 @@ namespace CarCareTracker.Helper
{
public interface IConfigHelper
{
OpenIDConfig GetOpenIDConfig();
UserConfig GetUserConfig(ClaimsPrincipal user);
bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData);
string GetLogoUrl();
string GetServerLanguage();
bool GetServerEnableShopSupplies();
string GetServerPostgresConnection();
public bool DeleteUserConfig(int userId);
}
public class ConfigHelper : IConfigHelper
@@ -29,39 +24,6 @@ namespace CarCareTracker.Helper
_userConfig = userConfig;
_cache = memoryCache;
}
public OpenIDConfig GetOpenIDConfig()
{
OpenIDConfig openIdConfig = _config.GetSection("OpenIDConfig").Get<OpenIDConfig>() ?? new OpenIDConfig();
return openIdConfig;
}
public string GetLogoUrl()
{
var logoUrl = _config["LUBELOGGER_LOGO_URL"];
if (string.IsNullOrWhiteSpace(logoUrl))
{
logoUrl = "/defaults/lubelogger_logo.png";
}
return logoUrl;
}
public string GetServerLanguage()
{
var serverLanguage = _config[nameof(UserConfig.UserLanguage)] ?? "en_US";
return serverLanguage;
}
public string GetServerPostgresConnection()
{
if (!string.IsNullOrWhiteSpace(_config["POSTGRES_CONNECTION"]))
{
return _config["POSTGRES_CONNECTION"];
} else
{
return string.Empty;
}
}
public bool GetServerEnableShopSupplies()
{
return bool.Parse(_config[nameof(UserConfig.EnableShopSupplies)] ?? "false");
}
public bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData)
{
var storedUserId = user.FindFirstValue(ClaimTypes.NameIdentifier);
@@ -132,14 +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)]),
UseMarkDownOnSavedNotes = bool.Parse(_config[nameof(UserConfig.UseMarkDownOnSavedNotes)]),
UseThreeDecimalGasCost = bool.Parse(_config[nameof(UserConfig.UseThreeDecimalGasCost)]),
EnableAutoReminderRefresh = bool.Parse(_config[nameof(UserConfig.EnableAutoReminderRefresh)]),
EnableAutoOdometerInsert = bool.Parse(_config[nameof(UserConfig.EnableAutoOdometerInsert)]),
PreferredGasMileageUnit = _config[nameof(UserConfig.PreferredGasMileageUnit)],
PreferredGasUnit = _config[nameof(UserConfig.PreferredGasUnit)],
UserLanguage = _config[nameof(UserConfig.UserLanguage)],
EnableShopSupplies = bool.Parse(_config[nameof(UserConfig.EnableShopSupplies)]),
VisibleTabs = _config.GetSection("VisibleTabs").Get<List<ImportMode>>(),
DefaultTab = (ImportMode)int.Parse(_config[nameof(UserConfig.DefaultTab)])
};

View File

@@ -1,5 +1,4 @@
using CarCareTracker.Models;
using System.IO.Compression;
using System.IO.Compression;
namespace CarCareTracker.Helper
{
@@ -7,12 +6,9 @@ namespace CarCareTracker.Helper
{
string GetFullFilePath(string currentFilePath, bool mustExist = true);
string MoveFileFromTemp(string currentFilePath, string newFolder);
bool RenameFile(string currentFilePath, string newName);
bool DeleteFile(string currentFilePath);
string MakeBackup();
bool RestoreBackup(string fileName, bool clearExisting = false);
string MakeAttachmentsExport(List<GenericReportModel> exportData);
List<string> GetLanguages();
bool RestoreBackup(string fileName);
}
public class FileHelper : IFileHelper
{
@@ -23,40 +19,6 @@ namespace CarCareTracker.Helper
_webEnv = webEnv;
_logger = logger;
}
public List<string> GetLanguages()
{
var languagePath = Path.Combine(_webEnv.WebRootPath, "translations");
var defaultList = new List<string>() { "en_US" };
if (Directory.Exists(languagePath))
{
var listOfLanguages = Directory.GetFiles(languagePath);
if (listOfLanguages.Any())
{
defaultList.AddRange(listOfLanguages.Select(x => Path.GetFileNameWithoutExtension(x)));
}
}
return defaultList;
}
public bool RenameFile(string currentFilePath, string newName)
{
var fullFilePath = GetFullFilePath(currentFilePath);
if (!string.IsNullOrWhiteSpace(fullFilePath))
{
try
{
var originalFileName = Path.GetFileNameWithoutExtension(fullFilePath);
var newFilePath = fullFilePath.Replace(originalFileName, newName);
File.Move(fullFilePath, newFilePath);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
return false;
}
public string GetFullFilePath(string currentFilePath, bool mustExist = true)
{
if (currentFilePath.StartsWith("/"))
@@ -76,7 +38,7 @@ namespace CarCareTracker.Helper
return string.Empty;
}
}
public bool RestoreBackup(string fileName, bool clearExisting = false)
public bool RestoreBackup(string fileName)
{
var fullFilePath = GetFullFilePath(fileName);
if (string.IsNullOrWhiteSpace(fullFilePath))
@@ -102,14 +64,6 @@ namespace CarCareTracker.Helper
{
Directory.CreateDirectory(existingPath);
}
else if (clearExisting)
{
var filesToDelete = Directory.GetFiles(existingPath);
foreach (string file in filesToDelete)
{
File.Delete(file);
}
}
//copy each files from temp folder to newPath
var filesToUpload = Directory.GetFiles(imagePath);
foreach(string file in filesToUpload)
@@ -124,14 +78,6 @@ namespace CarCareTracker.Helper
{
Directory.CreateDirectory(existingPath);
}
else if (clearExisting)
{
var filesToDelete = Directory.GetFiles(existingPath);
foreach (string file in filesToDelete)
{
File.Delete(file);
}
}
//copy each files from temp folder to newPath
var filesToUpload = Directory.GetFiles(documentPath);
foreach (string file in filesToUpload)
@@ -154,37 +100,12 @@ namespace CarCareTracker.Helper
File.Move(configPath, StaticHelper.UserConfigPath, true);
}
return true;
}
catch (Exception ex)
} catch (Exception ex)
{
_logger.LogError(ex, $"Error Restoring Database Backup: {ex.Message}");
return false;
}
}
public string MakeAttachmentsExport(List<GenericReportModel> exportData)
{
var folderName = Guid.NewGuid();
var tempPath = Path.Combine(_webEnv.WebRootPath, $"temp/{folderName}");
if (!Directory.Exists(tempPath))
Directory.CreateDirectory(tempPath);
int fileIndex = 0;
foreach (GenericReportModel reportModel in exportData)
{
foreach (UploadedFiles file in reportModel.Files)
{
var fileToCopy = GetFullFilePath(file.Location);
var destFileName = $"{tempPath}/{fileIndex}{Path.GetExtension(file.Location)}";
File.Copy(fileToCopy, destFileName);
fileIndex++;
}
}
var destFilePath = $"{tempPath}.zip";
ZipFile.CreateFromDirectory(tempPath, destFilePath);
//delete temp directory
Directory.Delete(tempPath, true);
var zipFileName = $"/temp/{folderName}.zip";
return zipFileName;
}
public string MakeBackup()
{
var folderName = $"db_backup_{DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")}";

View File

@@ -5,36 +5,26 @@ namespace CarCareTracker.Helper
public interface IGasHelper
{
List<GasRecordViewModel> GetGasRecordViewModels(List<GasRecord> result, bool useMPG, bool useUKMPG);
string GetAverageGasMileage(List<GasRecordViewModel> results, bool useMPG);
string GetAverageGasMileage(List<GasRecordViewModel> results);
}
public class GasHelper : IGasHelper
{
public string GetAverageGasMileage(List<GasRecordViewModel> results, bool useMPG)
public string GetAverageGasMileage(List<GasRecordViewModel> results)
{
var recordsToCalculate = results.Where(x => x.IncludeInAverage);
if (recordsToCalculate.Any())
var recordWithCalculatedMPG = results.Where(x => x.MilesPerGallon > 0);
var minMileage = results.Min(x => x.Mileage);
if (recordWithCalculatedMPG.Any())
{
try
{
var totalMileage = recordsToCalculate.Sum(x => x.DeltaMileage);
var totalGallons = recordsToCalculate.Sum(x => x.Gallons);
var averageGasMileage = totalMileage / totalGallons;
if (!useMPG && averageGasMileage > 0)
{
averageGasMileage = 100 / averageGasMileage;
}
var maxMileage = recordWithCalculatedMPG.Max(x => x.Mileage);
var totalGallonsConsumed = recordWithCalculatedMPG.Sum(x => x.Gallons);
var deltaMileage = maxMileage - minMileage;
var averageGasMileage = (maxMileage - minMileage) / totalGallonsConsumed;
return averageGasMileage.ToString("F");
} catch (Exception ex)
{
return "0";
}
}
return "0";
}
public List<GasRecordViewModel> GetGasRecordViewModels(List<GasRecord> result, bool useMPG, bool useUKMPG)
{
//need to order by to get correct results
result = result.OrderBy(x => x.Date).ThenBy(x => x.Mileage).ToList();
var computedResults = new List<GasRecordViewModel>();
int previousMileage = 0;
decimal unFactoredConsumption = 0.00M;
@@ -70,8 +60,7 @@ namespace CarCareTracker.Helper
CostPerGallon = convertedConsumption > 0.00M ? currentObject.Cost / convertedConsumption : 0,
IsFillToFull = currentObject.IsFillToFull,
MissedFuelUp = currentObject.MissedFuelUp,
Notes = currentObject.Notes,
Tags = currentObject.Tags
Notes = currentObject.Notes
};
if (currentObject.MissedFuelUp)
{
@@ -84,17 +73,10 @@ namespace CarCareTracker.Helper
else if (currentObject.IsFillToFull)
{
//if user filled to full.
if (convertedConsumption > 0.00M && deltaMileage > 0)
{
try
if (convertedConsumption > 0.00M)
{
gasRecordViewModel.MilesPerGallon = useMPG ? (unFactoredMileage + deltaMileage) / (unFactoredConsumption + convertedConsumption) : 100 / ((unFactoredMileage + deltaMileage) / (unFactoredConsumption + convertedConsumption));
}
catch (Exception ex)
{
gasRecordViewModel.MilesPerGallon = 0;
}
}
//reset unFactored vars
unFactoredConsumption = 0;
unFactoredMileage = 0;
@@ -123,8 +105,7 @@ namespace CarCareTracker.Helper
CostPerGallon = convertedConsumption > 0.00M ? currentObject.Cost / convertedConsumption : 0,
IsFillToFull = currentObject.IsFillToFull,
MissedFuelUp = currentObject.MissedFuelUp,
Notes = currentObject.Notes,
Tags = currentObject.Tags
Notes = currentObject.Notes
});
}
previousMileage = currentObject.Mileage;

View File

@@ -8,19 +8,15 @@ namespace CarCareTracker.Helper
{
OperationResponse NotifyUserForRegistration(string emailAddress, string token);
OperationResponse NotifyUserForPasswordReset(string emailAddress, string token);
OperationResponse NotifyUserForReminders(Vehicle vehicle, List<string> emailAddresses, List<ReminderRecordViewModel> reminders);
}
public class MailHelper : IMailHelper
{
private readonly MailConfig mailConfig;
private readonly IFileHelper _fileHelper;
public MailHelper(
IConfiguration config,
IFileHelper fileHelper
IConfiguration config
) {
//load mailConfig from Configuration
mailConfig = config.GetSection("MailConfig").Get<MailConfig>();
_fileHelper = fileHelper;
}
public OperationResponse NotifyUserForRegistration(string emailAddress, string token)
{
@@ -64,67 +60,20 @@ namespace CarCareTracker.Helper
return new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage };
}
}
public OperationResponse NotifyUserForReminders(Vehicle vehicle, List<string> emailAddresses, List<ReminderRecordViewModel> reminders)
{
if (string.IsNullOrWhiteSpace(mailConfig.EmailServer))
{
return new OperationResponse { Success = false, Message = "SMTP Server Not Setup" };
}
if (!emailAddresses.Any())
{
return new OperationResponse { Success = false, Message = "No recipients could be found" };
}
if (!reminders.Any())
{
return new OperationResponse { Success = false, Message = "No reminders could be found" };
}
//get email template, this file has to exist since it's a static file.
var emailTemplatePath = _fileHelper.GetFullFilePath(StaticHelper.ReminderEmailTemplate);
string emailSubject = $"Vehicle Reminders From LubeLogger - {DateTime.Now.ToShortDateString()}";
//construct html table.
string emailBody = File.ReadAllText(emailTemplatePath);
emailBody = emailBody.Replace("{VehicleInformation}", $"{vehicle.Year} {vehicle.Make} {vehicle.Model} #{vehicle.LicensePlate}");
string tableBody = "";
foreach(ReminderRecordViewModel reminder in reminders)
{
var dueOn = reminder.Metric == ReminderMetric.Both ? $"{reminder.Date} or {reminder.Mileage}" : reminder.Metric == ReminderMetric.Date ? $"{reminder.Date.ToShortDateString()}" : $"{reminder.Mileage}";
tableBody += $"<tr class='{reminder.Urgency}'><td>{StaticHelper.GetTitleCaseReminderUrgency(reminder.Urgency)}</td><td>{reminder.Description}</td><td>{dueOn}</td></tr>";
}
emailBody = emailBody.Replace("{TableBody}", tableBody);
try
{
foreach (string emailAddress in emailAddresses)
{
SendEmail(emailAddress, emailSubject, emailBody, true, true);
}
return new OperationResponse { Success = true, Message = "Email Sent!" };
} catch (Exception ex)
{
return new OperationResponse { Success = false, Message = ex.Message };
}
}
private bool SendEmail(string emailTo, string emailSubject, string emailBody, bool isBodyHtml = false, bool useAsync = false) {
private bool SendEmail(string emailTo, string emailSubject, string emailBody) {
string to = emailTo;
string from = mailConfig.EmailFrom;
var server = mailConfig.EmailServer;
MailMessage message = new MailMessage(from, to);
message.Subject = emailSubject;
message.Body = emailBody;
message.IsBodyHtml = isBodyHtml;
SmtpClient client = new SmtpClient(server);
client.EnableSsl = mailConfig.UseSSL;
client.Port = mailConfig.Port;
client.Credentials = new NetworkCredential(mailConfig.Username, mailConfig.Password);
try
{
if (useAsync)
{
client.SendMailAsync(message, new CancellationToken());
}
else
{
client.Send(message);
}
return true;
}
catch (Exception ex)

View File

@@ -12,45 +12,18 @@ namespace CarCareTracker.Helper
public ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder)
{
if (existingReminder.Metric == ReminderMetric.Both)
{
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
{
existingReminder.Date = existingReminder.Date.AddMonths((int)existingReminder.ReminderMonthInterval);
} else
{
existingReminder.Date = existingReminder.Date.AddMonths(existingReminder.CustomMonthInterval);
}
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
{
existingReminder.Mileage += (int)existingReminder.ReminderMileageInterval;
}
else
{
existingReminder.Mileage += existingReminder.CustomMileageInterval;
}
}
else if (existingReminder.Metric == ReminderMetric.Odometer)
{
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
{
existingReminder.Mileage += (int)existingReminder.ReminderMileageInterval;
} else
{
existingReminder.Mileage += existingReminder.CustomMileageInterval;
}
}
else if (existingReminder.Metric == ReminderMetric.Date)
{
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
{
existingReminder.Date = existingReminder.Date.AddMonths((int)existingReminder.ReminderMonthInterval);
}
else
{
existingReminder.Date = existingReminder.Date.AddMonths(existingReminder.CustomMonthInterval);
}
}
return existingReminder;
}
public List<ReminderRecordViewModel> GetReminderRecordViewModels(List<ReminderRecord> reminders, int currentMileage, DateTime dateCompare)

View File

@@ -5,7 +5,6 @@ namespace CarCareTracker.Helper
{
public interface IReportHelper
{
IEnumerable<CostForVehicleByMonth> GetOdometerRecordSum(List<OdometerRecord> odometerRecords, int year = 0);
IEnumerable<CostForVehicleByMonth> GetServiceRecordSum(List<ServiceRecord> serviceRecords, int year = 0);
IEnumerable<CostForVehicleByMonth> GetRepairRecordSum(List<CollisionRecord> repairRecords, int year = 0);
IEnumerable<CostForVehicleByMonth> GetUpgradeRecordSum(List<UpgradeRecord> upgradeRecords, int year = 0);
@@ -14,21 +13,6 @@ namespace CarCareTracker.Helper
}
public class ReportHelper: IReportHelper
{
public IEnumerable<CostForVehicleByMonth> GetOdometerRecordSum(List<OdometerRecord> odometerRecords, int year = 0)
{
if (year != default)
{
odometerRecords.RemoveAll(x => x.Date.Year != year);
}
return odometerRecords.GroupBy(x => x.Date.Month).OrderBy(x => x.Key).Select(x => new CostForVehicleByMonth
{
MonthId = x.Key,
MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key),
Cost = 0,
MaxMileage = x.Max(y => y.Mileage),
MinMileage = x.Min(y => y.Mileage)
});
}
public IEnumerable<CostForVehicleByMonth> GetServiceRecordSum(List<ServiceRecord> serviceRecords, int year = 0)
{
if (year != default)
@@ -39,9 +23,7 @@ namespace CarCareTracker.Helper
{
MonthId = x.Key,
MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key),
Cost = x.Sum(y => y.Cost),
MaxMileage = x.Max(y=>y.Mileage),
MinMileage = x.Min(y=>y.Mileage)
Cost = x.Sum(y => y.Cost)
});
}
public IEnumerable<CostForVehicleByMonth> GetRepairRecordSum(List<CollisionRecord> repairRecords, int year = 0)
@@ -54,9 +36,7 @@ namespace CarCareTracker.Helper
{
MonthId = x.Key,
MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key),
Cost = x.Sum(y => y.Cost),
MaxMileage = x.Max(y => y.Mileage),
MinMileage = x.Min(y => y.Mileage)
Cost = x.Sum(y => y.Cost)
});
}
public IEnumerable<CostForVehicleByMonth> GetUpgradeRecordSum(List<UpgradeRecord> upgradeRecords, int year = 0)
@@ -69,9 +49,7 @@ namespace CarCareTracker.Helper
{
MonthId = x.Key,
MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key),
Cost = x.Sum(y => y.Cost),
MaxMileage = x.Max(y => y.Mileage),
MinMileage = x.Min(y => y.Mileage)
Cost = x.Sum(y => y.Cost)
});
}
public IEnumerable<CostForVehicleByMonth> GetGasRecordSum(List<GasRecord> gasRecords, int year = 0)
@@ -84,9 +62,7 @@ namespace CarCareTracker.Helper
{
MonthId = x.Key,
MonthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x.Key),
Cost = x.Sum(y => y.Cost),
MaxMileage = x.Max(y => y.Mileage),
MinMileage = x.Min(y => y.Mileage)
Cost = x.Sum(y => y.Cost)
});
}
public IEnumerable<CostForVehicleByMonth> GetTaxRecordSum(List<TaxRecord> taxRecords, int year = 0)

View File

@@ -1,6 +1,5 @@
using CarCareTracker.Models;
using System.Globalization;
using System.Linq;
namespace CarCareTracker.Helper
{
@@ -12,22 +11,6 @@ namespace CarCareTracker.Helper
public static string DbName = "data/cartracker.db";
public static string UserConfigPath = "config/userConfig.json";
public static string GenericErrorMessage = "An error occurred, please try again later";
public static string ReminderEmailTemplate = "defaults/reminderemailtemplate.txt";
public static string GetTitleCaseReminderUrgency(ReminderUrgency input)
{
switch (input)
{
case ReminderUrgency.NotUrgent:
return "Not Urgent";
case ReminderUrgency.VeryUrgent:
return "Very Urgent";
case ReminderUrgency.PastDue:
return "Past Due";
default:
return input.ToString();
}
}
public static string TruncateStrings(string input, int maxLength = 25)
{
@@ -117,102 +100,5 @@ namespace CarCareTracker.Helper
new CostForVehicleByMonth { MonthId = 12, Cost = 0M}
};
}
public static ServiceRecord GenericToServiceRecord(GenericRecord input)
{
return new ServiceRecord
{
VehicleId = input.VehicleId,
Date = input.Date,
Description = input.Description,
Cost = input.Cost,
Mileage = input.Mileage,
Files = input.Files,
Notes = input.Notes,
Tags = input.Tags,
ExtraFields = input.ExtraFields
};
}
public static CollisionRecord GenericToRepairRecord(GenericRecord input)
{
return new CollisionRecord
{
VehicleId = input.VehicleId,
Date = input.Date,
Description = input.Description,
Cost = input.Cost,
Mileage = input.Mileage,
Files = input.Files,
Notes = input.Notes,
Tags = input.Tags,
ExtraFields = input.ExtraFields
};
}
public static UpgradeRecord GenericToUpgradeRecord(GenericRecord input)
{
return new UpgradeRecord
{
VehicleId = input.VehicleId,
Date = input.Date,
Description = input.Description,
Cost = input.Cost,
Mileage = input.Mileage,
Files = input.Files,
Notes = input.Notes,
Tags = input.Tags,
ExtraFields = input.ExtraFields
};
}
public static List<ExtraField> AddExtraFields(List<ExtraField> recordExtraFields, List<ExtraField> templateExtraFields)
{
if (!templateExtraFields.Any()) {
return new List<ExtraField>();
}
if (!recordExtraFields.Any())
{
return templateExtraFields;
}
var fieldNames = templateExtraFields.Select(x => x.Name);
//remove fields that are no longer present in template.
recordExtraFields.RemoveAll(x => !fieldNames.Contains(x.Name));
if (!recordExtraFields.Any())
{
return templateExtraFields;
}
//append the fields.
foreach (ExtraField extraField in recordExtraFields)
{
extraField.IsRequired = templateExtraFields.Where(x => x.Name == extraField.Name).First().IsRequired;
}
return recordExtraFields;
}
public static string GetFuelEconomyUnit(bool useKwh, bool useHours, bool useMPG, bool useUKMPG)
{
string fuelEconomyUnit;
if (useKwh)
{
var distanceUnit = useHours ? "h" : (useMPG ? "mi." : "km");
fuelEconomyUnit = useMPG ? $"{distanceUnit}/kWh" : $"kWh/100{distanceUnit}";
}
else if (useMPG && useUKMPG)
{
fuelEconomyUnit = useHours ? "h/g" : "mpg";
}
else if (useUKMPG)
{
fuelEconomyUnit = useHours ? "l/100h" : "l/100mi.";
}
else
{
fuelEconomyUnit = useHours ? (useMPG ? "h/g" : "l/100h") : (useMPG ? "mpg" : "l/100km");
}
return fuelEconomyUnit;
}
public static long GetEpochFromDateTime(DateTime date)
{
return new DateTimeOffset(date).ToUnixTimeMilliseconds();
}
}
}

View File

@@ -1,62 +0,0 @@
using CarCareTracker.Models;
using Microsoft.Extensions.Caching.Memory;
using System.Text.Json;
namespace CarCareTracker.Helper
{
public interface ITranslationHelper
{
string Translate(string userLanguage, string text);
}
public class TranslationHelper : ITranslationHelper
{
private readonly IFileHelper _fileHelper;
private readonly IConfiguration _config;
private IMemoryCache _cache;
public TranslationHelper(IFileHelper fileHelper, IConfiguration config, IMemoryCache memoryCache)
{
_fileHelper = fileHelper;
_config = config;
_cache = memoryCache;
}
public string Translate(string userLanguage, string text)
{
bool create = bool.Parse(_config["LUBELOGGER_TRANSLATOR"] ?? "false");
//transform input text into key.
string translationKey = text.Replace(" ", "_");
var translationFilePath = userLanguage == "en_US" ? _fileHelper.GetFullFilePath($"/defaults/en_US.json") : _fileHelper.GetFullFilePath($"/translations/{userLanguage}.json", false);
var dictionary = _cache.GetOrCreate<Dictionary<string, string>>($"lang_{userLanguage}", entry =>
{
entry.SlidingExpiration = TimeSpan.FromHours(1);
if (File.Exists(translationFilePath))
{
try
{
var translationFile = File.ReadAllText(translationFilePath);
var translationDictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(translationFile);
return translationDictionary ?? new Dictionary<string, string>();
} catch (Exception ex)
{
return new Dictionary<string, string>();
}
}
else
{
return new Dictionary<string, string>();
}
});
if (dictionary != null && dictionary.ContainsKey(translationKey))
{
return dictionary[translationKey];
}
else if (create && File.Exists(translationFilePath))
{
//create entry
dictionary.Add(translationKey, text);
File.WriteAllText(translationFilePath, JsonSerializer.Serialize(dictionary));
return text;
}
return text;
}
}
}

View File

@@ -16,13 +16,11 @@ namespace CarCareTracker.Logic
OperationResponse GenerateUserToken(string emailAddress, bool autoNotify);
bool DeleteUserToken(int tokenId);
bool DeleteUser(int userId);
OperationResponse RegisterOpenIdUser(LoginModel credentials);
OperationResponse RegisterNewUser(LoginModel credentials);
OperationResponse RequestResetPassword(LoginModel credentials);
OperationResponse ResetPasswordByUser(LoginModel credentials);
OperationResponse ResetUserPassword(LoginModel credentials);
UserData ValidateUserCredentials(LoginModel credentials);
UserData ValidateOpenIDUser(LoginModel credentials);
bool CheckIfUserIsValid(int userId);
bool CreateRootUserCredentials(LoginModel credentials);
bool DeleteRootUserCredentials();
@@ -61,45 +59,6 @@ namespace CarCareTracker.Logic
return result.Id != 0;
}
}
public OperationResponse RegisterOpenIdUser(LoginModel credentials)
{
//validate their token.
var existingToken = _tokenData.GetTokenRecordByBody(credentials.Token);
if (existingToken.Id == default || existingToken.EmailAddress != credentials.EmailAddress)
{
return new OperationResponse { Success = false, Message = "Invalid Token" };
}
if (string.IsNullOrWhiteSpace(credentials.EmailAddress) || string.IsNullOrWhiteSpace(credentials.UserName))
{
return new OperationResponse { Success = false, Message = "Username cannot be blank" };
}
var existingUser = _userData.GetUserRecordByUserName(credentials.UserName);
if (existingUser.Id != default)
{
return new OperationResponse { Success = false, Message = "Username already taken" };
}
var existingUserWithEmail = _userData.GetUserRecordByEmailAddress(credentials.EmailAddress);
if (existingUserWithEmail.Id != default)
{
return new OperationResponse { Success = false, Message = "A user with that email already exists" };
}
_tokenData.DeleteToken(existingToken.Id);
var newUser = new UserData()
{
UserName = credentials.UserName,
Password = GetHash(NewToken()), //generate a password for OpenID User
EmailAddress = credentials.EmailAddress
};
var result = _userData.SaveUserRecord(newUser);
if (result)
{
return new OperationResponse { Success = true, Message = "You will be logged in briefly." };
}
else
{
return new OperationResponse { Success = false, Message = "Something went wrong, please try again later." };
}
}
//handles user registration
public OperationResponse RegisterNewUser(LoginModel credentials)
{
@@ -234,19 +193,6 @@ namespace CarCareTracker.Logic
}
}
}
public UserData ValidateOpenIDUser(LoginModel credentials)
{
var result = _userData.GetUserRecordByEmailAddress(credentials.EmailAddress);
if (result.Id != default)
{
result.Password = string.Empty;
return result;
}
else
{
return new UserData();
}
}
#region "Admin Functions"
public bool MakeUserAdmin(int userId, bool isAdmin)
{
@@ -333,9 +279,6 @@ namespace CarCareTracker.Logic
#endregion
#region "Root User"
public bool CreateRootUserCredentials(LoginModel credentials)
{
//check if file exists
if (File.Exists(StaticHelper.UserConfigPath))
{
var configFileContents = File.ReadAllText(StaticHelper.UserConfigPath);
var existingUserConfig = JsonSerializer.Deserialize<UserConfig>(configFileContents);
@@ -350,16 +293,6 @@ namespace CarCareTracker.Logic
existingUserConfig.UserPasswordHash = hashedPassword;
}
File.WriteAllText(StaticHelper.UserConfigPath, JsonSerializer.Serialize(existingUserConfig));
} else
{
var newUserConfig = new UserConfig()
{
EnableAuth = true,
UserNameHash = GetHash(credentials.UserName),
UserPasswordHash = GetHash(credentials.Password)
};
File.WriteAllText(StaticHelper.UserConfigPath, JsonSerializer.Serialize(newUserConfig));
}
_cache.Remove("userConfig_-1");
return true;
}

View File

@@ -48,12 +48,6 @@ namespace CarCareTracker.Logic
if (existingUser.Id != default)
{
//user exists.
//check if user is already a collaborator
var userAccess = _userAccess.GetUserAccessByVehicleAndUserId(existingUser.Id, vehicleId);
if (userAccess != null)
{
return new OperationResponse { Success = false, Message = "User is already a collaborator" };
}
var result = AddUserAccessToVehicle(existingUser.Id, vehicleId);
if (result)
{

View File

@@ -25,7 +25,6 @@ namespace CarCareTracker.MapProfile
Map(m => m.Progress).Name(["progress"]);
Map(m => m.Type).Name(["type"]);
Map(m => m.Priority).Name(["priority"]);
Map(m => m.Tags).Name(["tags"]);
}
}
}

View File

@@ -157,13 +157,7 @@ namespace CarCareTracker.Middleware
return Task.CompletedTask;
}
}
if (Request.Path.Value == "/Vehicle/Index" && Request.QueryString.HasValue)
{
Response.Redirect($"/Login/Index?redirectURL={Request.Path.Value}{Request.QueryString.Value}");
} else
{
Response.Redirect("/Login/Index");
}
return Task.CompletedTask;
}
protected override Task HandleForbiddenAsync(AuthenticationProperties properties)
@@ -176,7 +170,7 @@ namespace CarCareTracker.Middleware
return Task.CompletedTask;
}
}
Response.Redirect("/Error/Unauthorized");
Response.Redirect("/Error/401");
return Task.CompletedTask;
}
}

View File

@@ -1,6 +1,14 @@
namespace CarCareTracker.Models
{
public class CollisionRecord: GenericRecord
public class CollisionRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public int Mileage { 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>();
}
}

View File

@@ -11,22 +11,6 @@
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<SupplyUsage> Supplies { get; set; } = new List<SupplyUsage>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public CollisionRecord ToCollisionRecord() { return new CollisionRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(Date),
Cost = Cost,
Mileage = Mileage,
Description = Description,
Notes = Notes,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
};
}
public CollisionRecord ToCollisionRecord() { return new CollisionRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes, Files = Files }; }
}
}

View File

@@ -1,9 +0,0 @@
namespace CarCareTracker.Models
{
public class ExtraField
{
public string Name { get; set; }
public string Value { get; set; }
public bool IsRequired { get; set; }
}
}

View File

@@ -18,7 +18,5 @@
public bool MissedFuelUp { get; set; } = false;
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -18,8 +18,6 @@
public bool MissedFuelUp { get; set; } = false;
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public GasRecord ToGasRecord() { return new GasRecord {
Id = Id,
Cost = Cost,
@@ -30,9 +28,7 @@
Files = Files,
IsFillToFull = IsFillToFull,
MissedFuelUp = MissedFuelUp,
Notes = Notes,
Tags = Tags,
ExtraFields = ExtraFields
Notes = Notes
}; }
}
}

View File

@@ -3,7 +3,6 @@
public class GasRecordInputContainer
{
public bool UseKwh { get; set; }
public bool UseHours { get; set; }
public GasRecordInput GasRecord { get; set; }
}
}

View File

@@ -21,7 +21,5 @@
public bool IsFillToFull { get; set; }
public bool MissedFuelUp { get; set; }
public string Notes { get; set; }
public List<string> Tags { get; set; } = new List<string>();
public bool IncludeInAverage { get { return MilesPerGallon > 0 || (!IsFillToFull && !MissedFuelUp); } }
}
}

View File

@@ -3,7 +3,6 @@
public class GasRecordViewModelContainer
{
public bool UseKwh { get; set; }
public bool UseHours { get; set; }
public List<GasRecordViewModel> GasRecords { get; set; } = new List<GasRecordViewModel>();
}
}

View File

@@ -1,17 +0,0 @@
namespace CarCareTracker.Models
{
public class GenericRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public int Mileage { 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 List<string> Tags { get; set;} = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
}
}

View File

@@ -23,7 +23,6 @@
public string PartNumber { get; set; }
public string PartSupplier { get; set; }
public string PartQuantity { get; set; }
public string Tags { get; set; }
}
public class SupplyRecordExportModel
@@ -35,7 +34,6 @@
public string Description { get; set; }
public string Cost { get; set; }
public string Notes { get; set; }
public string Tags { get; set; }
}
public class ServiceRecordExportModel
@@ -45,14 +43,12 @@
public string Description { get; set; }
public string Notes { get; set; }
public string Cost { get; set; }
public string Tags { get; set; }
}
public class OdometerRecordExportModel
{
public string Date { get; set; }
public string Odometer { get; set; }
public string Notes { get; set; }
public string Tags { get; set; }
}
public class TaxRecordExportModel
{
@@ -60,7 +56,6 @@
public string Description { get; set; }
public string Notes { get; set; }
public string Cost { get; set; }
public string Tags { get; set; }
}
public class GasRecordExportModel
{
@@ -72,7 +67,6 @@
public string IsFillToFull { get; set; }
public string MissedFuelUp { get; set; }
public string Notes { get; set; }
public string Tags { get; set; }
}
public class ReminderExportModel
{

View File

@@ -7,7 +7,5 @@
public string Description { get; set; }
public string NoteText { get; set; }
public bool Pinned { get; set; }
public List<string> Tags { get; set; } = new List<string>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
}
}

View File

@@ -1,14 +0,0 @@
namespace CarCareTracker.Models
{
public class OpenIDConfig
{
public string Name { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string AuthURL { get; set; }
public string TokenURL { get; set; }
public string RedirectURL { get; set; }
public string Scope { get; set; }
public string RemoteAuthURL { get { return $"{AuthURL}?client_id={ClientId}&response_type=code&redirect_uri={RedirectURL}&scope={Scope}"; } }
}
}

View File

@@ -1,7 +0,0 @@
namespace CarCareTracker.Models
{
public class OpenIDResult
{
public string id_token { get; set; }
}
}

View File

@@ -7,8 +7,6 @@
public DateTime Date { get; set; }
public int Mileage { get; set; }
public string Notes { get; set; }
public List<string> Tags { get; set; } = new List<string>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -8,8 +8,6 @@
public int Mileage { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public OdometerRecord ToOdometerRecord() { return new OdometerRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Mileage = Mileage, Notes = Notes, Files = Files, Tags = Tags, ExtraFields = ExtraFields }; }
public OdometerRecord ToOdometerRecord() { return new OdometerRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Mileage = Mileage, Notes = Notes, Files = Files }; }
}
}

View File

@@ -0,0 +1,8 @@
namespace CarCareTracker.Models
{
public class PlanCostItem
{
public string CostName { get; set; }
public decimal CostAmount { get; set; }
}
}

View File

@@ -4,7 +4,6 @@
{
public int Id { get; set; }
public int VehicleId { get; set; }
public int ReminderRecordId { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
public string Description { get; set; }
@@ -14,7 +13,5 @@
public PlanPriority Priority { get; set; }
public PlanProgress Progress { get; set; }
public decimal Cost { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
}
}

View File

@@ -4,7 +4,6 @@
{
public int Id { get; set; }
public int VehicleId { get; set; }
public int ReminderRecordId { get; set; }
public string DateCreated { get; set; } = DateTime.Now.ToShortDateString();
public string DateModified { get; set; } = DateTime.Now.ToShortDateString();
public string Description { get; set; }
@@ -15,12 +14,9 @@
public PlanPriority Priority { get; set; }
public PlanProgress Progress { get; set; }
public decimal Cost { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public PlanRecord ToPlanRecord() { return new PlanRecord {
Id = Id,
VehicleId = VehicleId,
ReminderRecordId = ReminderRecordId,
DateCreated = DateTime.Parse(DateCreated),
DateModified = DateTime.Parse(DateModified),
Description = Description,
@@ -29,13 +25,7 @@
ImportMode = ImportMode,
Cost = Cost,
Priority = Priority,
Progress = Progress,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
Progress = Progress
}; }
/// <summary>
/// only used to hide view template button on plan create modal.
/// </summary>
public bool CreatedFromReminder { get; set; }
}
}

View File

@@ -1,14 +0,0 @@
using LiteDB;
namespace CarCareTracker.Models
{
public class RecordExtraField
{
/// <summary>
/// Corresponds to int value of ImportMode enum
/// </summary>
[BsonId(false)]
public int Id { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -9,8 +9,6 @@
public string Description { get; set; }
public string Notes { get; set; }
public bool IsRecurring { get; set; } = false;
public int CustomMileageInterval { get; set; } = 0;
public int CustomMonthInterval { get; set; } = 0;
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;

View File

@@ -9,15 +9,10 @@
public string Description { get; set; }
public string Notes { get; set; }
public bool IsRecurring { get; set; } = false;
public int CustomMileageInterval { get; set; } = 0;
public int CustomMonthInterval { get; set; } = 0;
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
public ReminderRecord ToReminderRecord()
{
return new ReminderRecord
{
public ReminderRecord ToReminderRecord() { return new ReminderRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(string.IsNullOrWhiteSpace(Date) ? DateTime.Now.AddDays(1).ToShortDateString() : Date),
@@ -27,10 +22,6 @@
IsRecurring = IsRecurring,
ReminderMileageInterval = ReminderMileageInterval,
ReminderMonthInterval = ReminderMonthInterval,
CustomMileageInterval = CustomMileageInterval,
CustomMonthInterval = CustomMonthInterval,
Notes = Notes
};
}
Notes = Notes }; }
}
}

View File

@@ -5,8 +5,5 @@
public int MonthId { get; set; }
public string MonthName { get; set; }
public decimal Cost { get; set; }
public int MaxMileage { get; set; }
public int MinMileage { get; set; }
public int DistanceTraveled { get; set; }
}
}

View File

@@ -11,6 +11,5 @@
public string Description { get; set; }
public string Notes { get; set; }
public decimal Cost { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
}
}

View File

@@ -1,6 +1,14 @@
namespace CarCareTracker.Models
{
public class ServiceRecord: GenericRecord
public class ServiceRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public int Mileage { 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>();
}
}

View File

@@ -11,22 +11,6 @@
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<SupplyUsage> Supplies { get; set; } = new List<SupplyUsage>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public ServiceRecord ToServiceRecord() { return new ServiceRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(Date),
Cost = Cost,
Mileage = Mileage,
Description = Description,
Notes = Notes,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
};
}
public ServiceRecord ToServiceRecord() { return new ServiceRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes, Files = Files }; }
}
}

View File

@@ -1,8 +0,0 @@
namespace CarCareTracker.Models
{
public class SettingsViewModel
{
public UserConfig UserConfig { get; set; }
public List<string> UILanguages { get; set; }
}
}

View File

@@ -33,8 +33,5 @@
/// </summary>
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
}
}

View File

@@ -12,9 +12,6 @@
public decimal Cost { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public SupplyRecord ToSupplyRecord() { return new SupplyRecord {
Id = Id,
VehicleId = VehicleId,
@@ -25,10 +22,6 @@
Quantity = Quantity,
Description = Description,
Notes = Notes,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
}; }
Files = Files }; }
}
}

View File

@@ -1,10 +0,0 @@
namespace CarCareTracker.Models
{
public class SupplyUsageHistory {
public DateTime Date { get; set; }
public string PartNumber { get; set; }
public string Description { get; set; }
public decimal Quantity { get; set; }
public decimal Cost { get; set; }
}
}

View File

@@ -10,9 +10,6 @@
public string Notes { get; set; }
public bool IsRecurring { get; set; } = false;
public ReminderMonthInterval RecurringInterval { get; set; } = ReminderMonthInterval.OneYear;
public int CustomMonthInterval { get; set; } = 0;
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -10,10 +10,7 @@
public string Notes { get; set; }
public bool IsRecurring { get; set; } = false;
public ReminderMonthInterval RecurringInterval { get; set; } = ReminderMonthInterval.ThreeMonths;
public int CustomMonthInterval { get; set; } = 0;
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public TaxRecord ToTaxRecord() { return new TaxRecord {
Id = Id,
VehicleId = VehicleId,
@@ -23,10 +20,6 @@
Notes = Notes,
IsRecurring = IsRecurring,
RecurringInterval = RecurringInterval,
CustomMonthInterval = CustomMonthInterval,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields
}; }
Files = Files }; }
}
}

View File

@@ -0,0 +1,38 @@
using LiteDB;
namespace CarCareTracker.Models
{
public class TorqueRecord
{
/// <summary>
/// Session Id provided by Torque
/// </summary>
[BsonId]
public string Session { get; set; }
/// <summary>
/// VehicleId
/// </summary>
public int VehicleId { get; set; }
/// <summary>
/// Email Address
/// </summary>
public string Eml { get; set; }
/// <summary>
/// longitude
/// </summary>
public double kff1005 { get; set; }
/// <summary>
/// latitude
/// </summary>
public double kff1006 { get; set; }
/// <summary>
/// Calculated fields.
/// </summary>
public double InitialLongitude { get; set; }
public double InitialLatitude { get; set; }
public double LastLongitude { get; set; }
public double LastLatitude { get; set; }
public double DistanceTraveled { get; set; }
}
}

View File

@@ -1,6 +1,14 @@
namespace CarCareTracker.Models
{
public class UpgradeRecord: GenericRecord
public class UpgradeRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public int Mileage { 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>();
}
}

View File

@@ -11,22 +11,6 @@
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<SupplyUsage> Supplies { get; set; } = new List<SupplyUsage>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public UpgradeRecord ToUpgradeRecord() { return new UpgradeRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(Date),
Cost = Cost,
Mileage = Mileage,
Description = Description,
Notes = Notes,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
};
}
public UpgradeRecord ToUpgradeRecord() { return new UpgradeRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes, Files = Files }; }
}
}

Some files were not shown because too many files have changed in this diff Show More