Merge pull request #253 from hargata/Hargata/postgres

Added Postgres backend support.
This commit is contained in:
Hargata Softworks
2024-02-09 14:56:08 -07:00
committed by GitHub
43 changed files with 3439 additions and 28 deletions

View File

@@ -13,6 +13,7 @@
<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="LiteDB" Version="5.0.17" />
<PackageReference Include="Npgsql" Version="8.0.1" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,718 @@
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 View("401");
}
}
private void InitializeTables(NpgsqlConnection 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))"
};
foreach(string cmd in cmds)
{
using (var ctext = new NpgsqlCommand(cmd, conn))
{
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 = new NpgsqlConnection(_configHelper.GetServerPostgresConnection());
pgDataSource.Open();
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>();
#region "Part1"
string cmd = $"SELECT data FROM app.vehicles";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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
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 = new NpgsqlConnection(_configHelper.GetServerPostgresConnection());
pgDataSource.Open();
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>();
#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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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))";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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)";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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)";
using (var ctext = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("userId", record.Id.UserId);
ctext.Parameters.AddWithValue("vehicleId", record.Id.VehicleId);
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

@@ -161,6 +161,10 @@ namespace CarCareTracker.Controllers
[HttpGet]
public IActionResult ExportFromVehicleToCsv(int vehicleId, ImportMode mode)
{
if (vehicleId == default && mode != ImportMode.SupplyRecord)
{
return Json(false);
}
string uploadDirectory = "temp/";
string uploadPath = Path.Combine(_webEnv.WebRootPath, uploadDirectory);
if (!Directory.Exists(uploadPath))
@@ -345,6 +349,10 @@ 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))
{
return Json(false);

View File

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

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGCollisionRecordDataAccess : ICollisionRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGCollisionRecordDataAccess> _logger;
private static string tableName = "collisionrecords";
public PGCollisionRecordDataAccess(IConfiguration config, ILogger<PGCollisionRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGGasRecordDataAccess: IGasRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGGasRecordDataAccess> _logger;
private static string tableName = "gasrecords";
public PGGasRecordDataAccess(IConfiguration config, ILogger<PGGasRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,154 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGNoteDataAccess: INoteDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGNoteDataAccess> _logger;
private static string tableName = "notes";
public PGNoteDataAccess(IConfiguration config, ILogger<PGNoteDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
} catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGOdometerRecordDataAccess : IOdometerRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGOdometerRecordDataAccess> _logger;
private static string tableName = "odometerrecords";
public PGOdometerRecordDataAccess(IConfiguration config, ILogger<PGOdometerRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGPlanRecordDataAccess : IPlanRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGPlanRecordDataAccess> _logger;
private static string tableName = "planrecords";
public PGPlanRecordDataAccess(IConfiguration config, ILogger<PGPlanRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGPlanRecordTemplateDataAccess : IPlanRecordTemplateDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGPlanRecordTemplateDataAccess> _logger;
private static string tableName = "planrecordtemplates";
public PGPlanRecordTemplateDataAccess(IConfiguration config, ILogger<PGPlanRecordTemplateDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGReminderRecordDataAccess : IReminderRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGReminderRecordDataAccess> _logger;
private static string tableName = "reminderrecords";
public PGReminderRecordDataAccess(IConfiguration config, ILogger<PGReminderRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGServiceRecordDataAccess: IServiceRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGServiceRecordDataAccess> _logger;
private static string tableName = "servicerecords";
public PGServiceRecordDataAccess(IConfiguration config, ILogger<PGServiceRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGSupplyRecordDataAccess : ISupplyRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGSupplyRecordDataAccess> _logger;
private static string tableName = "supplyrecords";
public PGSupplyRecordDataAccess(IConfiguration config, ILogger<PGSupplyRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGTaxRecordDataAccess : ITaxRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGTaxRecordDataAccess> _logger;
private static string tableName = "taxrecords";
public PGTaxRecordDataAccess(IConfiguration config, ILogger<PGTaxRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,144 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
namespace CarCareTracker.External.Implementations
{
public class PGTokenRecordDataAccess : ITokenRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGTokenRecordDataAccess> _logger;
private static string tableName = "tokenrecords";
public PGTokenRecordDataAccess(IConfiguration config, ILogger<PGTokenRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", tokenId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,160 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGUpgradeRecordDataAccess : IUpgradeRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGUpgradeRecordDataAccess> _logger;
private static string tableName = "upgraderecords";
public PGUpgradeRecordDataAccess(IConfiguration config, ILogger<PGUpgradeRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", vehicleId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,212 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Net.Mail;
namespace CarCareTracker.External.Implementations
{
public class PGUserAccessDataAccess : IUserAccessDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGUserAccessDataAccess> _logger;
private static string tableName = "useraccessrecords";
public PGUserAccessDataAccess(IConfiguration config, ILogger<PGUserAccessDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("userId", userId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,108 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGUserConfigDataAccess: IUserConfigDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGUserConfigDataAccess> _logger;
private static string tableName = "userconfigrecords";
public PGUserConfigDataAccess(IConfiguration config, ILogger<PGUserConfigDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", userId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,195 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
namespace CarCareTracker.External.Implementations
{
public class PGUserRecordDataAccess : IUserRecordDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGUserRecordDataAccess> _logger;
private static string tableName = "userrecords";
public PGUserRecordDataAccess(IConfiguration config, ILogger<PGUserRecordDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
ctext.Parameters.AddWithValue("id", userId);
return ctext.ExecuteNonQuery() > 0;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
return false;
}
}
}
}

View File

@@ -0,0 +1,139 @@
using CarCareTracker.External.Interfaces;
using CarCareTracker.Models;
using Npgsql;
using System.Text.Json;
namespace CarCareTracker.External.Implementations
{
public class PGVehicleDataAccess: IVehicleDataAccess
{
private NpgsqlConnection pgDataSource;
private readonly ILogger<PGVehicleDataAccess> _logger;
private static string tableName = "vehicles";
public PGVehicleDataAccess(IConfiguration config, ILogger<PGVehicleDataAccess> logger)
{
pgDataSource = new NpgsqlConnection(config["POSTGRES_CONNECTION"]);
_logger = logger;
try
{
pgDataSource.Open();
//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 = new NpgsqlCommand(initCMD, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmdU, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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 = new NpgsqlCommand(cmd, pgDataSource))
{
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

@@ -17,7 +17,6 @@ namespace CarCareTracker.Filter
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var shopSupplyEndpoints = new List<string> { "ImportToVehicleIdFromCsv", "GetSupplyRecordsByVehicleId", "ExportFromVehicleToCsv" };
if (!filterContext.HttpContext.User.IsInRole(nameof(UserData.IsRootUser)))
{
var vehicleId = int.Parse(filterContext.ActionArguments["vehicleId"].ToString());
@@ -28,14 +27,19 @@ namespace CarCareTracker.Filter
{
filterContext.Result = new RedirectResult("/Error/Unauthorized");
}
} else if (shopSupplyEndpoints.Contains(filterContext.RouteData.Values["action"].ToString()) && !_config.GetServerEnableShopSupplies())
} else
{
//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");
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

@@ -12,6 +12,7 @@ namespace CarCareTracker.Helper
string GetLogoUrl();
string GetServerLanguage();
bool GetServerEnableShopSupplies();
string GetServerPostgresConnection();
public bool DeleteUserConfig(int userId);
}
public class ConfigHelper : IConfigHelper
@@ -41,6 +42,16 @@ namespace CarCareTracker.Helper
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");

View File

@@ -48,6 +48,12 @@ 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

@@ -12,22 +12,45 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddSingleton<IVehicleDataAccess, VehicleDataAccess>();
builder.Services.AddSingleton<INoteDataAccess, NoteDataAccess>();
builder.Services.AddSingleton<IServiceRecordDataAccess, ServiceRecordDataAccess>();
builder.Services.AddSingleton<IGasRecordDataAccess, GasRecordDataAccess>();
builder.Services.AddSingleton<ICollisionRecordDataAccess, CollisionRecordDataAccess>();
builder.Services.AddSingleton<ITaxRecordDataAccess, TaxRecordDataAccess>();
builder.Services.AddSingleton<IReminderRecordDataAccess, ReminderRecordDataAccess>();
builder.Services.AddSingleton<IUpgradeRecordDataAccess, UpgradeRecordDataAccess>();
builder.Services.AddSingleton<IUserRecordDataAccess, UserRecordDataAccess>();
builder.Services.AddSingleton<ITokenRecordDataAccess, TokenRecordDataAccess>();
builder.Services.AddSingleton<IUserAccessDataAccess, UserAccessDataAccess>();
builder.Services.AddSingleton<IUserConfigDataAccess, UserConfigDataAccess>();
builder.Services.AddSingleton<ISupplyRecordDataAccess, SupplyRecordDataAccess>();
builder.Services.AddSingleton<IPlanRecordDataAccess, PlanRecordDataAccess>();
builder.Services.AddSingleton<IPlanRecordTemplateDataAccess, PlanRecordTemplateDataAccess>();
builder.Services.AddSingleton<IOdometerRecordDataAccess, OdometerRecordDataAccess>();
//data access method
if (!string.IsNullOrWhiteSpace(builder.Configuration["POSTGRES_CONNECTION"])){
builder.Services.AddSingleton<IVehicleDataAccess, PGVehicleDataAccess>();
builder.Services.AddSingleton<INoteDataAccess, PGNoteDataAccess>();
builder.Services.AddSingleton<IServiceRecordDataAccess, PGServiceRecordDataAccess>();
builder.Services.AddSingleton<IGasRecordDataAccess, PGGasRecordDataAccess>();
builder.Services.AddSingleton<ICollisionRecordDataAccess, PGCollisionRecordDataAccess>();
builder.Services.AddSingleton<ITaxRecordDataAccess, PGTaxRecordDataAccess>();
builder.Services.AddSingleton<IReminderRecordDataAccess, PGReminderRecordDataAccess>();
builder.Services.AddSingleton<IUpgradeRecordDataAccess, PGUpgradeRecordDataAccess>();
builder.Services.AddSingleton<IOdometerRecordDataAccess, PGOdometerRecordDataAccess>();
builder.Services.AddSingleton<ISupplyRecordDataAccess, PGSupplyRecordDataAccess>();
builder.Services.AddSingleton<IPlanRecordDataAccess, PGPlanRecordDataAccess>();
builder.Services.AddSingleton<IPlanRecordTemplateDataAccess, PGPlanRecordTemplateDataAccess>();
builder.Services.AddSingleton<IUserConfigDataAccess, PGUserConfigDataAccess>();
builder.Services.AddSingleton<IUserRecordDataAccess, PGUserRecordDataAccess>();
builder.Services.AddSingleton<ITokenRecordDataAccess, PGTokenRecordDataAccess>();
builder.Services.AddSingleton<IUserAccessDataAccess, PGUserAccessDataAccess>();
}
else
{
builder.Services.AddSingleton<IVehicleDataAccess, VehicleDataAccess>();
builder.Services.AddSingleton<INoteDataAccess, NoteDataAccess>();
builder.Services.AddSingleton<IServiceRecordDataAccess, ServiceRecordDataAccess>();
builder.Services.AddSingleton<IGasRecordDataAccess, GasRecordDataAccess>();
builder.Services.AddSingleton<ICollisionRecordDataAccess, CollisionRecordDataAccess>();
builder.Services.AddSingleton<ITaxRecordDataAccess, TaxRecordDataAccess>();
builder.Services.AddSingleton<IReminderRecordDataAccess, ReminderRecordDataAccess>();
builder.Services.AddSingleton<IUpgradeRecordDataAccess, UpgradeRecordDataAccess>();
builder.Services.AddSingleton<IOdometerRecordDataAccess, OdometerRecordDataAccess>();
builder.Services.AddSingleton<ISupplyRecordDataAccess, SupplyRecordDataAccess>();
builder.Services.AddSingleton<IPlanRecordDataAccess, PlanRecordDataAccess>();
builder.Services.AddSingleton<IPlanRecordTemplateDataAccess, PlanRecordTemplateDataAccess>();
builder.Services.AddSingleton<IUserConfigDataAccess, UserConfigDataAccess>();
builder.Services.AddSingleton<IUserRecordDataAccess, UserRecordDataAccess>();
builder.Services.AddSingleton<ITokenRecordDataAccess, TokenRecordDataAccess>();
builder.Services.AddSingleton<IUserAccessDataAccess, UserAccessDataAccess>();
}
//configure helpers
builder.Services.AddSingleton<IFileHelper, FileHelper>();

View File

@@ -191,7 +191,7 @@
<img src="/defaults/lubelogger_logo.png" />
</div>
<div class="d-flex justify-content-center">
<small class="text-body-secondary">Version 1.1.4</small>
<small class="text-body-secondary">Version 1.1.5</small>
</div>
<p class="lead">
Proudly developed in the rural town of Price, Utah by Hargata Softworks.
@@ -221,6 +221,7 @@
<li class="list-group-item">Bootstrap</li>
<li class="list-group-item">Bootstrap-DatePicker</li>
<li class="list-group-item">LiteDB</li>
<li class="list-group-item">Npgsql</li>
<li class="list-group-item">SweetAlert2</li>
<li class="list-group-item">CsvHelper</li>
<li class="list-group-item">Chart.js</li>

View File

@@ -0,0 +1,88 @@
@using CarCareTracker.Helper
@{
ViewData["Title"] = "Admin";
}
@inject IConfiguration config;
@inject ITranslationHelper translator
@{
var userLanguage = config[nameof(UserConfig.UserLanguage)] ?? "en_US";
}
@model AdminViewModel
<div class="container">
<div class="row">
<div class="col-1">
<a href="/Home" class="btn btn-secondary btn-md mt-1 mb-1"><i class="bi bi-arrow-left-square"></i></a>
</div>
<div class="col-11">
<span class="display-6">@translator.Translate(userLanguage, "Database Migration")</span>
</div>
</div>
<hr />
<div class="row">
<div class="col-12">
<ul class="list-group list-group-flush">
<li class="list-group-item">Instructions</li>
<li class="list-group-item">Use this tool to migrate data between LiteDB and Postgres</li>
<li class="list-group-item">Note that it is recommended that the Postgres DB is empty when importing from LiteDB to prevent primary key errors.</li>
</ul>
</div>
</div>
<hr />
<div class="row d-flex justify-content-center">
<div class="col-3">
<div class="d-grid">
<input onChange="importPostgresData(this)" type="file" accept=".db" class="d-none" id="inputImport">
<button type="button" class="btn btn-warning mt-2" onclick="importToPostgres()"><i class="bi bi-upload me-2"></i>@translator.Translate(userLanguage, "Import To Postgres")</button>
</div>
<div class="d-grid">
<button type="button" class="btn btn-warning mt-2" onclick="exportFromPostgres()"><i class="bi bi-download me-2"></i>@translator.Translate(userLanguage, "Export From Postgres")</button>
</div>
</div>
</div>
</div>
<script>
function exportFromPostgres(){
sloader.show();
$.get('/Migration/Export', function (data) {
sloader.hide();
if (data.success) {
window.location.href = data.message;
} else {
errorToast(genericErrorMessage());
}
});
}
function importPostgresData(event) {
let formData = new FormData();
formData.append("file", event.files[0]);
sloader.show();
$.ajax({
url: "/Files/HandleFileUpload",
data: formData,
cache: false,
processData: false,
contentType: false,
type: 'POST',
success: function (response) {
if (response.trim() != '') {
$.post('/Migration/Import', { fileName: response }, function (data) {
sloader.hide();
if (data.success) {
successToast(data.message);
setTimeout(function () { window.location.href = '/Home/Index' }, 500);
} else {
errorToast(genericErrorMessage());
}
});
}
},
error: function () {
sloader.hide();
errorToast("An error has occurred, please check the file size and try again later.");
}
});
}
function importToPostgres() {
$("#inputImport").click();
}
</script>

View File

@@ -1 +1 @@
{"UseDarkMode":true,"EnableCsvImports":false,"UseMPG":true,"UseDescending":false,"EnableAuth":false,"UserNameHash":"","UserPasswordHash":""}
{"UseDarkMode":true,"EnableCsvImports":true,"UseMPG":false,"UseDescending":true,"EnableAuth":true,"HideZero":false,"UseUKMPG":false,"UseThreeDecimalGasCost":true,"UseMarkDownOnSavedNotes":false,"EnableAutoReminderRefresh":false,"EnableAutoOdometerInsert":false,"EnableShopSupplies":false,"PreferredGasUnit":"l","PreferredGasMileageUnit":"l/100km","UserNameHash":"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918","UserPasswordHash":"8b3b357e205f36f3c3858994f0d15ce9451284e0e42493a817fc0d66a02bc3a2","UserLanguage":"en_US","VisibleTabs":[0,8,1,4,2,3,6,7],"DefaultTab":8}

File diff suppressed because one or more lines are too long