first commit

This commit is contained in:
Eric Gullickson
2025-07-15 20:34:05 -05:00
commit f7eca4bad5
602 changed files with 158990 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
namespace MotoVaultPro.Models
{
public class MethodParameter
{
public int Id { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string StartDate { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string EndDate { get; set; }
public string Tags { get; set; }
public bool UseMPG { get; set; }
public bool UseUKMPG { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
namespace MotoVaultPro.Models
{
/// <summary>
/// For deserializing GitHub response for latest version
/// </summary>
public class ReleaseResponse
{
public string tag_name { get; set; }
}
/// <summary>
/// For returning the version numbers via API.
/// </summary>
public class ReleaseVersion
{
public string CurrentVersion { get; set; }
public string LatestVersion { get; set; }
}
}

138
Models/API/TypeConverter.cs Normal file
View File

@@ -0,0 +1,138 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace MotoVaultPro.Models
{
public class DummyType
{
}
class InvariantConverter : JsonConverter<DummyType>
{
public override void Write(Utf8JsonWriter writer, DummyType value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
public override DummyType? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
class FromDateOptional: JsonConverter<string>
{
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var tokenType = reader.TokenType;
if (tokenType == JsonTokenType.String)
{
return reader.GetString();
}
else if (tokenType == JsonTokenType.Number)
{
if (reader.TryGetInt64(out long intInput))
{
return DateTimeOffset.FromUnixTimeSeconds(intInput).Date.ToShortDateString();
}
}
return reader.GetString();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
if (options.Converters.Any(x => x.Type == typeof(DummyType)))
{
writer.WriteStringValue(DateTime.Parse(value).ToString("yyyy-MM-dd"));
}
else
{
writer.WriteStringValue(value);
}
}
}
class FromDecimalOptional : JsonConverter<string>
{
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var tokenType = reader.TokenType;
if (tokenType == JsonTokenType.String)
{
return reader.GetString();
}
else if (tokenType == JsonTokenType.Number) {
if (reader.TryGetDecimal(out decimal decimalInput))
{
return decimalInput.ToString();
}
}
return reader.GetString();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
if (options.Converters.Any(x=>x.Type == typeof(DummyType)))
{
writer.WriteNumberValue(decimal.Parse(value));
} else
{
writer.WriteStringValue(value);
}
}
}
class FromIntOptional : JsonConverter<string>
{
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var tokenType = reader.TokenType;
if (tokenType == JsonTokenType.String)
{
return reader.GetString();
}
else if (tokenType == JsonTokenType.Number)
{
if (reader.TryGetInt32(out int intInput))
{
return intInput.ToString();
}
}
return reader.GetString();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
if (options.Converters.Any(x => x.Type == typeof(DummyType)))
{
writer.WriteNumberValue(int.Parse(value));
}
else
{
writer.WriteStringValue(value);
}
}
}
class FromBoolOptional : JsonConverter<string>
{
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var tokenType = reader.TokenType;
switch (tokenType)
{
case JsonTokenType.String:
return reader.GetString();
case JsonTokenType.True:
return "True";
case JsonTokenType.False:
return "False";
default:
return reader.GetString();
}
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
if (options.Converters.Any(x => x.Type == typeof(DummyType)))
{
writer.WriteBooleanValue(bool.Parse(value));
}
else
{
writer.WriteStringValue(value);
}
}
}
}

27
Models/API/VehicleInfo.cs Normal file
View File

@@ -0,0 +1,27 @@
namespace MotoVaultPro.Models
{
public class VehicleInfo
{
public Vehicle VehicleData { get; set; } = new Vehicle();
public int VeryUrgentReminderCount { get; set; }
public int UrgentReminderCount { get; set;}
public int NotUrgentReminderCount { get; set; }
public int PastDueReminderCount { get; set; }
public ReminderAPIExportModel NextReminder { get; set; }
public int ServiceRecordCount { get; set; }
public decimal ServiceRecordCost { get; set; }
public int RepairRecordCount { get; set; }
public decimal RepairRecordCost { get; set; }
public int UpgradeRecordCount { get; set; }
public decimal UpgradeRecordCost { get; set; }
public int TaxRecordCount { get; set; }
public decimal TaxRecordCost { get; set; }
public int GasRecordCount { get; set; }
public decimal GasRecordCost { get; set; }
public int LastReportedOdometer { get; set; }
public int PlanRecordBackLogCount { get; set; }
public int PlanRecordInProgressCount { get; set; }
public int PlanRecordTestingCount { get; set; }
public int PlanRecordDoneCount { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class AdminViewModel
{
public List<UserData> Users { get; set; }
public List<Token> Tokens { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace MotoVaultPro.Models
{
public class CollisionRecord: GenericRecord
{
}
}

View File

@@ -0,0 +1,35 @@
namespace MotoVaultPro.Models
{
public class CollisionRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public List<int> ReminderRecordId { get; set; } = new List<int>();
public string Date { get; set; } = DateTime.Now.ToShortDateString();
public int Mileage { get; set; }
public string Description { get; set; }
public decimal Cost { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<SupplyUsage> Supplies { get; set; } = new List<SupplyUsage>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public List<SupplyUsageHistory> DeletedRequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public bool CopySuppliesAttachment { get; set; } = false;
public CollisionRecord ToCollisionRecord() { return new CollisionRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(Date),
Cost = Cost,
Mileage = Mileage,
Description = Description,
Notes = Notes,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
};
}
}
}

View File

@@ -0,0 +1,11 @@
namespace MotoVaultPro.Models
{
public class MailConfig
{
public string EmailServer { get; set; }
public string EmailFrom { get; set; }
public int Port { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
}

9
Models/ErrorViewModel.cs Normal file
View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}

View File

@@ -0,0 +1,24 @@
namespace MotoVaultPro.Models
{
public class GasRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
/// <summary>
/// American moment
/// </summary>
public int Mileage { get; set; }
/// <summary>
/// Wtf is a kilometer?
/// </summary>
public decimal Gallons { get; set; }
public decimal Cost { get; set; }
public bool IsFillToFull { get; set; } = true;
public bool MissedFuelUp { get; set; } = false;
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class GasRecordEditModel
{
public List<int> RecordIds { get; set; } = new List<int>();
public GasRecord EditRecord { get; set; } = new GasRecord();
}
}

View File

@@ -0,0 +1,38 @@
namespace MotoVaultPro.Models
{
public class GasRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public string Date { get; set; } = DateTime.Now.ToShortDateString();
/// <summary>
/// American moment
/// </summary>
public int Mileage { get; set; }
/// <summary>
/// Wtf is a kilometer?
/// </summary>
public decimal Gallons { get; set; }
public decimal Cost { get; set; }
public bool IsFillToFull { get; set; } = true;
public bool MissedFuelUp { get; set; } = false;
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public GasRecord ToGasRecord() { return new GasRecord {
Id = Id,
Cost = Cost,
Date = DateTime.Parse(Date),
Gallons = Gallons,
Mileage = Mileage,
VehicleId = VehicleId,
Files = Files,
IsFillToFull = IsFillToFull,
MissedFuelUp = MissedFuelUp,
Notes = Notes,
Tags = Tags,
ExtraFields = ExtraFields
}; }
}
}

View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class GasRecordInputContainer
{
public bool UseKwh { get; set; }
public bool UseHours { get; set; }
public GasRecordInput GasRecord { get; set; }
}
}

View File

@@ -0,0 +1,29 @@
namespace MotoVaultPro.Models
{
public class GasRecordViewModel
{
public int Id { get; set; }
public int VehicleId { get; set; }
public int MonthId { get; set; }
public string Date { get; set; }
/// <summary>
/// American moment
/// </summary>
public int Mileage { get; set; }
/// <summary>
/// Wtf is a kilometer?
/// </summary>
public decimal Gallons { get; set; }
public decimal Cost { get; set; }
public int DeltaMileage { get; set; }
public decimal MilesPerGallon { get; set; }
public decimal CostPerGallon { get; set; }
public bool IsFillToFull { get; set; }
public bool MissedFuelUp { get; set; }
public string Notes { get; set; }
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public bool IncludeInAverage { get { return MilesPerGallon > 0 || (!IsFillToFull && !MissedFuelUp) || (Mileage == default && !MissedFuelUp); } }
}
}

View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class GasRecordViewModelContainer
{
public bool UseKwh { get; set; }
public bool UseHours { get; set; }
public List<GasRecordViewModel> GasRecords { get; set; } = new List<GasRecordViewModel>();
}
}

View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class GenericRecordEditModel
{
public ImportMode DataType { get; set; }
public List<int> RecordIds { get; set; } = new List<int>();
public GenericRecord EditRecord { get; set; } = new GenericRecord();
}
}

View File

@@ -0,0 +1,14 @@
namespace MotoVaultPro.Models
{
public class KioskViewModel
{
/// <summary>
/// List of vehicle ids to exclude from Kiosk Dashboard
/// </summary>
public List<int> Exclusions { get; set; } = new List<int>();
/// <summary>
/// Whether to retrieve data for vehicle, plans, or reminder view.
/// </summary>
public KioskMode KioskMode { get; set; } = KioskMode.Vehicle;
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class AuthCookie
{
public UserData UserData { get; set; }
public DateTime ExpiresOn { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace MotoVaultPro.Models
{
public class LoginModel
{
public string UserName { get; set; }
public string Password { get; set; }
public string EmailAddress { get; set; }
public string Token { get; set; }
public bool IsPersistent { get; set; } = false;
}
}

9
Models/Login/Token.cs Normal file
View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class Token
{
public int Id { get; set; }
public string Body { get; set; }
public string EmailAddress { get; set; }
}
}

14
Models/Note/Note.cs Normal file
View File

@@ -0,0 +1,14 @@
namespace MotoVaultPro.Models
{
public class Note
{
public int Id { get; set; }
public int VehicleId { get; set; }
public string Description { get; set; }
public string NoteText { get; set; }
public bool Pinned { get; set; }
public List<string> Tags { get; set; } = new List<string>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -0,0 +1,28 @@
namespace MotoVaultPro.Models
{
public class OpenIDConfig
{
public string Name { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string AuthURL { get; set; }
public string TokenURL { get; set; }
public string RedirectURL { get; set; }
public string Scope { get; set; } = "openid email";
public string State { get; set; }
public string CodeChallenge { get; set; }
public bool ValidateState { get; set; } = false;
public bool DisableRegularLogin { get; set; } = false;
public bool UsePKCE { get; set; } = false;
public string LogOutURL { get; set; } = "";
public string UserInfoURL { get; set; } = "";
public string RemoteAuthURL { get {
var redirectUrl = $"{AuthURL}?client_id={ClientId}&response_type=code&redirect_uri={RedirectURL}&scope={Scope}&state={State}";
if (UsePKCE)
{
redirectUrl += $"&code_challenge={CodeChallenge}&code_challenge_method=S256";
}
return redirectUrl;
} }
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class OpenIDResult
{
public string id_token { get; set; }
public string access_token { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace MotoVaultPro.Models
{
public class OpenIDUserInfo
{
public string email { get; set; } = "";
}
}

View File

@@ -0,0 +1,16 @@
namespace MotoVaultPro.Models
{
public class OdometerRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public int InitialMileage { get; set; }
public int Mileage { get; set; }
public int DistanceTraveled { get { return Mileage - InitialMileage; } }
public string Notes { get; set; }
public List<string> Tags { get; set; } = new List<string>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class OdometerRecordEditModel
{
public List<int> RecordIds { get; set; } = new List<int>();
public OdometerRecord EditRecord { get; set; } = new OdometerRecord();
}
}

View File

@@ -0,0 +1,16 @@
namespace MotoVaultPro.Models
{
public class OdometerRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public string Date { get; set; } = DateTime.Now.ToShortDateString();
public int InitialMileage { get; set; }
public int Mileage { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public OdometerRecord ToOdometerRecord() { return new OdometerRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Mileage = Mileage, Notes = Notes, Files = Files, Tags = Tags, ExtraFields = ExtraFields, InitialMileage = InitialMileage }; }
}
}

View File

@@ -0,0 +1,33 @@
using MotoVaultPro.Helper;
namespace MotoVaultPro.Models
{
public class OperationResponseBase
{
public bool Success { get; set; }
public string Message { get; set; }
}
public class OperationResponse: OperationResponseBase
{
public static OperationResponse Succeed(string message = "")
{
return new OperationResponse { Success = true, Message = message };
}
public static OperationResponse Failed(string message = "")
{
if (string.IsNullOrWhiteSpace(message))
{
message = StaticHelper.GenericErrorMessage;
}
return new OperationResponse { Success = false, Message = message};
}
public static OperationResponse Conditional(bool result, string successMessage = "", string errorMessage = "")
{
if (string.IsNullOrWhiteSpace(errorMessage))
{
errorMessage = StaticHelper.GenericErrorMessage;
}
return new OperationResponse { Success = result, Message = result ? successMessage : errorMessage };
}
}
}

View File

@@ -0,0 +1,20 @@
namespace MotoVaultPro.Models
{
public class PlanRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public int ReminderRecordId { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public ImportMode ImportMode { get; set; }
public PlanPriority Priority { get; set; }
public PlanProgress Progress { get; set; }
public decimal Cost { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
}
}

View File

@@ -0,0 +1,43 @@
namespace MotoVaultPro.Models
{
public class PlanRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public int ReminderRecordId { get; set; }
public string DateCreated { get; set; } = DateTime.Now.ToShortDateString();
public string DateModified { get; set; } = DateTime.Now.ToShortDateString();
public string Description { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<SupplyUsage> Supplies { get; set; } = new List<SupplyUsage>();
public ImportMode ImportMode { get; set; }
public PlanPriority Priority { get; set; }
public PlanProgress Progress { get; set; }
public decimal Cost { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public List<SupplyUsageHistory> DeletedRequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public bool CopySuppliesAttachment { get; set; } = false;
public PlanRecord ToPlanRecord() { return new PlanRecord {
Id = Id,
VehicleId = VehicleId,
ReminderRecordId = ReminderRecordId,
DateCreated = DateTime.Parse(DateCreated),
DateModified = DateTime.Parse(DateModified),
Description = Description,
Notes = Notes,
Files = Files,
ImportMode = ImportMode,
Cost = Cost,
Priority = Priority,
Progress = Progress,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
}; }
/// <summary>
/// only used to hide view template button on plan create modal.
/// </summary>
public bool CreatedFromReminder { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace MotoVaultPro.Models
{
public class ReminderUrgencyConfig
{
public int UrgentDays { get; set; } = 30;
public int VeryUrgentDays { get; set; } = 7;
public int UrgentDistance { get; set; } = 100;
public int VeryUrgentDistance { get; set; } = 50;
}
}

View File

@@ -0,0 +1,22 @@
namespace MotoVaultPro.Models
{
public class ReminderRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public int Mileage { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public bool IsRecurring { get; set; } = false;
public bool UseCustomThresholds { get; set; } = false;
public ReminderUrgencyConfig CustomThresholds { get; set; } = new ReminderUrgencyConfig();
public int CustomMileageInterval { get; set; } = 0;
public int CustomMonthInterval { get; set; } = 0;
public ReminderIntervalUnit CustomMonthIntervalUnit { get; set; } = ReminderIntervalUnit.Months;
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
public List<string> Tags { get; set; } = new List<string>();
}
}

View File

@@ -0,0 +1,44 @@
namespace MotoVaultPro.Models
{
public class ReminderRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public string Date { get; set; } = DateTime.Now.AddDays(1).ToShortDateString();
public int Mileage { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public bool IsRecurring { get; set; } = false;
public bool UseCustomThresholds { get; set; } = false;
public ReminderUrgencyConfig CustomThresholds { get; set; } = new ReminderUrgencyConfig();
public int CustomMileageInterval { get; set; } = 0;
public int CustomMonthInterval { get; set; } = 0;
public ReminderIntervalUnit CustomMonthIntervalUnit { get; set; } = ReminderIntervalUnit.Months;
public ReminderMileageInterval ReminderMileageInterval { get; set; } = ReminderMileageInterval.FiveThousandMiles;
public ReminderMonthInterval ReminderMonthInterval { get; set; } = ReminderMonthInterval.OneYear;
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
public List<string> Tags { get; set; } = new List<string>();
public ReminderRecord ToReminderRecord()
{
return new ReminderRecord
{
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(string.IsNullOrWhiteSpace(Date) ? DateTime.Now.AddDays(1).ToShortDateString() : Date),
Mileage = Mileage,
Description = Description,
Metric = Metric,
IsRecurring = IsRecurring,
UseCustomThresholds = UseCustomThresholds,
CustomThresholds = CustomThresholds,
ReminderMileageInterval = ReminderMileageInterval,
ReminderMonthInterval = ReminderMonthInterval,
CustomMileageInterval = CustomMileageInterval,
CustomMonthInterval = CustomMonthInterval,
CustomMonthIntervalUnit = CustomMonthIntervalUnit,
Notes = Notes,
Tags = Tags
};
}
}
}

View File

@@ -0,0 +1,28 @@
namespace MotoVaultPro.Models
{
public class ReminderRecordViewModel
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public int Mileage { get; set; }
public int DueDays { get; set; }
public int DueMileage { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
/// <summary>
/// The metric the user selected to calculate the urgency of this reminder.
/// </summary>
public ReminderMetric UserMetric { get; set; } = ReminderMetric.Date;
/// <summary>
/// Reason why this reminder is urgent
/// </summary>
public ReminderMetric Metric { get; set; } = ReminderMetric.Date;
public ReminderUrgency Urgency { get; set; } = ReminderUrgency.NotUrgent;
/// <summary>
/// Recurring Reminders
/// </summary>
public bool IsRecurring { get; set; } = false;
public List<string> Tags { get; set; } = new List<string>();
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class CostDistanceTableForVehicle
{
public string DistanceUnit { get; set; } = "mi.";
public List<CostForVehicleByMonth> CostData { get; set; } = new List<CostForVehicleByMonth>();
}
}

View File

@@ -0,0 +1,12 @@
namespace MotoVaultPro.Models
{
public class CostForVehicleByMonth
{
public int Year { get; set; }
public int MonthId { get; set; }
public string MonthName { get; set; }
public decimal Cost { get; set; }
public int DistanceTraveled { get; set; }
public decimal CostPerDistanceTraveled { get { if (DistanceTraveled > 0) { return Cost / DistanceTraveled; } else { return 0M; } } }
}
}

View File

@@ -0,0 +1,11 @@
namespace MotoVaultPro.Models
{
public class CostMakeUpForVehicle
{
public decimal ServiceRecordSum { get; set; }
public decimal GasRecordSum { get; set; }
public decimal TaxRecordSum { get; set; }
public decimal CollisionRecordSum { get; set; }
public decimal UpgradeRecordSum { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
namespace MotoVaultPro.Models
{
public class CostTableForVehicle
{
public string DistanceUnit { get; set; } = "Cost Per Mile";
public int TotalDistance { get; set; }
public int NumberOfDays { get; set; }
public decimal ServiceRecordSum { get; set; }
public decimal GasRecordSum { get; set; }
public decimal TaxRecordSum { get; set; }
public decimal CollisionRecordSum { get; set; }
public decimal UpgradeRecordSum { get; set; }
public decimal ServiceRecordPerMile { get { return TotalDistance != default ? ServiceRecordSum / TotalDistance : 0; } }
public decimal GasRecordPerMile { get { return TotalDistance != default ? GasRecordSum / TotalDistance : 0; } }
public decimal CollisionRecordPerMile { get { return TotalDistance != default ? CollisionRecordSum / TotalDistance : 0; } }
public decimal UpgradeRecordPerMile { get { return TotalDistance != default ? UpgradeRecordSum / TotalDistance : 0; } }
public decimal TaxRecordPerMile { get { return TotalDistance != default ? TaxRecordSum / TotalDistance : 0; } }
public decimal ServiceRecordPerDay { get { return NumberOfDays != default ? ServiceRecordSum / NumberOfDays : 0; } }
public decimal GasRecordPerDay { get { return NumberOfDays != default ? GasRecordSum / NumberOfDays : 0; } }
public decimal CollisionRecordPerDay { get { return NumberOfDays != default ? CollisionRecordSum / NumberOfDays : 0; } }
public decimal UpgradeRecordPerDay { get { return NumberOfDays != default ? UpgradeRecordSum / NumberOfDays : 0; } }
public decimal TaxRecordPerDay { get { return NumberOfDays != default ? TaxRecordSum / NumberOfDays : 0; } }
public decimal TotalPerDay { get { return ServiceRecordPerDay + CollisionRecordPerDay + UpgradeRecordPerDay + GasRecordPerDay + TaxRecordPerDay; } }
public decimal TotalPerMile { get { return ServiceRecordPerMile + CollisionRecordPerMile + UpgradeRecordPerMile + GasRecordPerMile + TaxRecordPerMile; } }
public decimal TotalCost { get { return ServiceRecordSum + CollisionRecordSum + UpgradeRecordSum + GasRecordSum + TaxRecordSum; } }
}
}

View File

@@ -0,0 +1,18 @@
namespace MotoVaultPro.Models
{
/// <summary>
/// Generic Model used for vehicle history report.
/// </summary>
public class GenericReportModel
{
public ImportMode DataType { get; set; }
public DateTime Date { get; set; }
public int Odometer { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public decimal Cost { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
}
}

View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class MPGForVehicleByMonth
{
public List<CostForVehicleByMonth> CostData { get; set; } = new List<CostForVehicleByMonth>();
public List<CostForVehicleByMonth> SortedCostData { get; set; } = new List<CostForVehicleByMonth>();
public string Unit { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace MotoVaultPro.Models
{
public class ReminderMakeUpForVehicle
{
public int NotUrgentCount { get; set; }
public int UrgentCount { get; set; }
public int VeryUrgentCount { get; set; }
public int PastDueCount { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace MotoVaultPro.Models
{
public class ReportHeader
{
public int MaxOdometer { get; set; }
public int DistanceTraveled { get; set; }
public decimal TotalCost { get; set; }
public string AverageMPG { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
namespace MotoVaultPro.Models
{
public class ReportParameter
{
public List<string> VisibleColumns { get; set; } = new List<string>();
public List<string> ExtraFields { get; set; } = new List<string>();
public TagFilter TagFilter { get; set; } = TagFilter.Exclude;
public List<string> Tags { get; set; } = new List<string>();
public bool FilterByDateRange { get; set; } = false;
public string StartDate { get; set; } = "";
public string EndDate { get; set; } = "";
public bool PrintIndividualRecords { get; set; } = false;
}
}

View File

@@ -0,0 +1,15 @@
namespace MotoVaultPro.Models
{
public class ReportViewModel
{
public ReportHeader ReportHeaderForVehicle { get; set; } = new ReportHeader();
public List<CostForVehicleByMonth> CostForVehicleByMonth { get; set; } = new List<CostForVehicleByMonth>();
public MPGForVehicleByMonth FuelMileageForVehicleByMonth { get; set; } = new MPGForVehicleByMonth();
public CostMakeUpForVehicle CostMakeUpForVehicle { get; set; } = new CostMakeUpForVehicle();
public ReminderMakeUpForVehicle ReminderMakeUpForVehicle { get; set; } = new ReminderMakeUpForVehicle();
public List<int> Years { get; set; } = new List<int>();
public List<UserCollaborator> Collaborators { get; set; } = new List<UserCollaborator>();
public bool CustomWidgetsConfigured { get; set; } = false;
public List<ImportMode> AvailableMetrics { get; set; } = new List<ImportMode>();
}
}

View File

@@ -0,0 +1,23 @@
namespace MotoVaultPro.Models
{
public class VehicleHistoryViewModel
{
public Vehicle VehicleData { get; set; }
public List<GenericReportModel> VehicleHistory { get; set; }
public ReportParameter ReportParameters { get; set; }
public string Odometer { get; set; }
public string MPG { get; set; }
public decimal TotalCost { get; set; }
public decimal TotalGasCost { get; set; }
public string DaysOwned { get; set; }
public string DistanceTraveled { get; set; }
public decimal TotalCostPerMile { get; set; }
public decimal TotalGasCostPerMile { get; set; }
public string DistanceUnit { get; set; }
public decimal TotalDepreciation { get; set; }
public decimal DepreciationPerDay { get; set; }
public decimal DepreciationPerMile { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
}
}

9
Models/SearchResult.cs Normal file
View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class SearchResult
{
public int Id { get; set; }
public ImportMode RecordType { get; set; }
public string Description { get; set; }
}
}

71
Models/ServerConfig.cs Normal file
View File

@@ -0,0 +1,71 @@
using System.Text.Json.Serialization;
namespace MotoVaultPro.Models
{
public class ServerConfig
{
[JsonPropertyName("POSTGRES_CONNECTION")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? PostgresConnection { get; set; }
[JsonPropertyName("LUBELOGGER_ALLOWED_FILE_EXTENSIONS")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? AllowedFileExtensions { get; set; }
[JsonPropertyName("LUBELOGGER_LOGO_URL")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? CustomLogoURL { get; set; }
[JsonPropertyName("LUBELOGGER_LOGO_SMALL_URL")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? CustomSmallLogoURL { get; set; }
[JsonPropertyName("LUBELOGGER_MOTD")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? MessageOfTheDay { get; set; }
[JsonPropertyName("LUBELOGGER_WEBHOOK")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? WebHookURL { get; set; }
[JsonPropertyName("LUBELOGGER_DOMAIN")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ServerURL { get; set; }
[JsonPropertyName("LUBELOGGER_CUSTOM_WIDGETS")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? CustomWidgetsEnabled { get; set; }
[JsonPropertyName("LUBELOGGER_INVARIANT_API")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? InvariantAPIEnabled { get; set; }
[JsonPropertyName("MailConfig")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public MailConfig? SMTPConfig { get; set; }
[JsonPropertyName("OpenIDConfig")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public OpenIDConfig? OIDCConfig { get; set; }
[JsonPropertyName("ReminderUrgencyConfig")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ReminderUrgencyConfig? ReminderUrgencyConfig { get; set; }
[JsonPropertyName("LUBELOGGER_OPEN_REGISTRATION")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? OpenRegistration { get; set; }
[JsonPropertyName("DisableRegistration")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? DisableRegistration { get; set; }
[JsonPropertyName("DefaultReminderEmail")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? DefaultReminderEmail { get; set; } = string.Empty;
[JsonPropertyName("EnableRootUserOIDC")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public bool? EnableRootUserOIDC { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace MotoVaultPro.Models
{
public class ServiceRecord: GenericRecord
{
}
}

View File

@@ -0,0 +1,35 @@
namespace MotoVaultPro.Models
{
public class ServiceRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public List<int> ReminderRecordId { get; set; } = new List<int>();
public string Date { get; set; } = DateTime.Now.ToShortDateString();
public int Mileage { get; set; }
public string Description { get; set; }
public decimal Cost { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<SupplyUsage> Supplies { get; set; } = new List<SupplyUsage>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public List<SupplyUsageHistory> DeletedRequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public bool CopySuppliesAttachment { get; set; } = false;
public ServiceRecord ToServiceRecord() { return new ServiceRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(Date),
Cost = Cost,
Mileage = Mileage,
Description = Description,
Notes = Notes,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
};
}
}
}

View File

@@ -0,0 +1,24 @@
namespace MotoVaultPro.Models
{
public class ServerSettingsViewModel
{
public string LocaleInfo { get; set; }
public string PostgresConnection { get; set; }
public string AllowedFileExtensions { get; set; }
public string CustomLogoURL { get; set; }
public string CustomSmallLogoURL { get; set; }
public string MessageOfTheDay { get; set; }
public string WebHookURL { get; set; }
public string Domain { get; set; }
public bool CustomWidgetsEnabled { get; set; }
public bool InvariantAPIEnabled { get; set; }
public MailConfig SMTPConfig { get; set; } = new MailConfig();
public OpenIDConfig OIDCConfig { get; set; } = new OpenIDConfig();
public bool OpenRegistration { get; set; }
public bool DisableRegistration { get; set; }
public ReminderUrgencyConfig ReminderUrgencyConfig { get; set; } = new ReminderUrgencyConfig();
public string DefaultReminderEmail { get; set; } = string.Empty;
public bool EnableRootUserOIDC { get; set; }
public bool EnableAuth { get; set; }
}
}

View File

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

View File

@@ -0,0 +1,10 @@
namespace MotoVaultPro.Models
{
public class ExtraField
{
public string Name { get; set; }
public string Value { get; set; }
public bool IsRequired { get; set; }
public ExtraFieldType FieldType { get; set; } = ExtraFieldType.Text;
}
}

View File

@@ -0,0 +1,17 @@
namespace MotoVaultPro.Models
{
public class GenericRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public int Mileage { get; set; }
public string Description { get; set; }
public decimal Cost { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set;} = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
}
}

View File

@@ -0,0 +1,179 @@
using System.Text.Json.Serialization;
namespace MotoVaultPro.Models
{
/// <summary>
/// Import model used for importing records via CSV.
/// </summary>
public class ImportModel
{
public string Date { get; set; }
public string Day { get; set; }
public string Month { get; set; }
public string Year { get; set; }
public string DateCreated { get; set; }
public string DateModified { get; set; }
public string Type { get; set; }
public string Priority { get; set; }
public string Progress { get; set; }
public string InitialOdometer { get; set; }
public string Odometer { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public string FuelConsumed { get; set; }
public string Cost { get; set; }
public string Price { get; set; }
public string PartialFuelUp { get; set; }
public string IsFillToFull { get; set; }
public string MissedFuelUp { get; set; }
public string PartNumber { get; set; }
public string PartSupplier { get; set; }
public string PartQuantity { get; set; }
public string Tags { get; set; }
public Dictionary<string,string> ExtraFields {get;set;}
}
public class SupplyRecordExportModel
{
public string Date { get; set; }
public string PartNumber { get; set; }
public string PartSupplier { get; set; }
public string PartQuantity { get; set; }
public string Description { get; set; }
public string Cost { get; set; }
public string Notes { get; set; }
public string Tags { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
public class GenericRecordExportModel
{
[JsonConverter(typeof(FromIntOptional))]
public string Id { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string Date { get; set; }
[JsonConverter(typeof(FromIntOptional))]
public string Odometer { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
[JsonConverter(typeof(FromDecimalOptional))]
public string Cost { get; set; }
public string Tags { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
}
public class OdometerRecordExportModel
{
[JsonConverter(typeof(FromIntOptional))]
public string Id { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string Date { get; set; }
[JsonConverter(typeof(FromIntOptional))]
public string InitialOdometer { get; set; }
[JsonConverter(typeof(FromIntOptional))]
public string Odometer { get; set; }
public string Notes { get; set; }
public string Tags { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
}
public class TaxRecordExportModel
{
[JsonConverter(typeof(FromIntOptional))]
public string Id { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string Date { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
[JsonConverter(typeof(FromDecimalOptional))]
public string Cost { get; set; }
public string Tags { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
}
public class GasRecordExportModel
{
[JsonConverter(typeof(FromIntOptional))]
public string Id { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string Date { get; set; }
[JsonConverter(typeof(FromIntOptional))]
public string Odometer { get; set; }
[JsonConverter(typeof(FromDecimalOptional))]
public string FuelConsumed { get; set; }
[JsonConverter(typeof(FromDecimalOptional))]
public string Cost { get; set; }
[JsonConverter(typeof(FromDecimalOptional))]
public string FuelEconomy { get; set; }
[JsonConverter(typeof(FromBoolOptional))]
public string IsFillToFull { get; set; }
[JsonConverter(typeof(FromBoolOptional))]
public string MissedFuelUp { get; set; }
public string Notes { get; set; }
public string Tags { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
}
public class ReminderExportModel
{
[JsonConverter(typeof(FromIntOptional))]
public string Id { get; set; }
public string Description { get; set; }
public string Urgency { get; set; }
public string Metric { get; set; }
public string Notes { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string DueDate { get; set; }
[JsonConverter(typeof(FromIntOptional))]
public string DueOdometer { get; set; }
public string Tags { get; set; }
}
/// <summary>
/// Only used for the API GET Method
/// </summary>
public class ReminderAPIExportModel
{
[JsonConverter(typeof(FromIntOptional))]
public string Id { get; set; }
public string Description { get; set; }
public string Urgency { get; set; }
public string Metric { get; set; }
public string UserMetric { get; set; }
public string Notes { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string DueDate { get; set; }
[JsonConverter(typeof(FromIntOptional))]
public string DueOdometer { get; set; }
[JsonConverter(typeof(FromIntOptional))]
public string DueDays { get; set; }
[JsonConverter(typeof(FromIntOptional))]
public string DueDistance { get; set; }
public string Tags { get; set; }
}
public class PlanRecordExportModel
{
[JsonConverter(typeof(FromIntOptional))]
public string Id { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string DateCreated { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string DateModified { get; set; }
public string Description { get; set; }
public string Notes { get; set; }
public string Type { get; set; }
public string Priority { get; set; }
public string Progress { get; set; }
[JsonConverter(typeof(FromDecimalOptional))]
public string Cost { get; set; }
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
}
public class UserExportModel
{
public string Username { get; set; }
public string EmailAddress { get; set; }
[JsonConverter(typeof(FromBoolOptional))]
public string IsAdmin { get; set; }
[JsonConverter(typeof(FromBoolOptional))]
public string IsRoot { get; set; }
}
}

View File

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

View File

@@ -0,0 +1,11 @@
namespace MotoVaultPro.Models
{
public class StickerViewModel
{
public ImportMode RecordType { get; set; }
public Vehicle VehicleData { get; set; } = new Vehicle();
public List<ReminderRecord> ReminderRecords { get; set; } = new List<ReminderRecord>();
public List<GenericRecord> GenericRecords { get; set; } = new List<GenericRecord>();
public List<SupplyRecord> SupplyRecords { get; set; } = new List<SupplyRecord>();
}
}

View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class UploadedFiles
{
public string Name { get; set; }
public string Location { get; set; }
public bool IsPending { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
namespace MotoVaultPro.Models
{
public class VehicleRecords
{
public List<ServiceRecord> ServiceRecords { get; set; } = new List<ServiceRecord>();
public List<CollisionRecord> CollisionRecords { get; set; } = new List<CollisionRecord>();
public List<UpgradeRecord> UpgradeRecords { get; set; } = new List<UpgradeRecord>();
public List<GasRecord> GasRecords { get; set; } = new List<GasRecord>();
public List<TaxRecord> TaxRecords { get; set; } = new List<TaxRecord>();
public List<OdometerRecord> OdometerRecords { get; set; } = new List<OdometerRecord>();
}
}

View File

@@ -0,0 +1,253 @@
using System.Text.Json.Serialization;
namespace MotoVaultPro.Models
{
/// <summary>
/// WebHookPayload Object
/// </summary>
public class WebHookPayloadBase
{
public string Type { get; set; } = "";
public string Timestamp
{
get { return DateTime.UtcNow.ToString("O"); }
}
public Dictionary<string, string> Data { get; set; } = new Dictionary<string, string>();
/// <summary>
/// Legacy attributes below
/// </summary>
public string VehicleId { get; set; } = "";
public string Username { get; set; } = "";
public string Action { get; set; } = "";
}
public class DiscordWebHook
{
public string Username { get { return "MotoVaultPro"; } }
[JsonPropertyName("avatar_url")]
public string AvatarUrl { get { return "https://github.com/ericgullickson/motovaultpro_logo_small.png"; } }
public string Content { get; set; } = "";
public static DiscordWebHook FromWebHookPayload(WebHookPayload webHookPayload)
{
return new DiscordWebHook
{
Content = webHookPayload.Action,
};
}
}
public class WebHookPayload: WebHookPayloadBase
{
private static string GetFriendlyActionType(string actionType)
{
var actionTypeParts = actionType.Split('.');
if (actionTypeParts.Length == 2)
{
var recordType = actionTypeParts[0];
var recordAction = actionTypeParts[1];
switch (recordAction)
{
case "add":
recordAction = "Added";
break;
case "update":
recordAction = "Updated";
break;
case "delete":
recordAction = "Deleted";
break;
}
if (recordType.ToLower().Contains("record"))
{
var cleanedRecordType = recordType.ToLower().Replace("record", "");
cleanedRecordType = $"{char.ToUpper(cleanedRecordType[0])}{cleanedRecordType.Substring(1)} Record";
recordType = cleanedRecordType;
} else
{
recordType = $"{char.ToUpper(recordType[0])}{recordType.Substring(1)}";
}
return $"{recordAction} {recordType}";
} else if (actionTypeParts.Length == 3)
{
var recordType = actionTypeParts[0];
var recordAction = actionTypeParts[1];
var thirdPart = actionTypeParts[2];
switch (recordAction)
{
case "add":
recordAction = "Added";
break;
case "update":
recordAction = "Updated";
break;
case "delete":
recordAction = "Deleted";
break;
}
if (recordType.ToLower().Contains("record"))
{
var cleanedRecordType = recordType.ToLower().Replace("record", "");
cleanedRecordType = $"{char.ToUpper(cleanedRecordType[0])}{cleanedRecordType.Substring(1)} Record";
recordType = cleanedRecordType;
}
else
{
recordType = $"{char.ToUpper(recordType[0])}{recordType.Substring(1)}";
}
if (thirdPart == "api")
{
return $"{recordAction} {recordType} via API";
} else
{
return $"{recordAction} {recordType}";
}
}
return actionType;
}
public static WebHookPayload FromGenericRecord(GenericRecord genericRecord, string actionType, string userName)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
payloadDictionary.Add("description", genericRecord.Description);
payloadDictionary.Add("odometer", genericRecord.Mileage.ToString());
payloadDictionary.Add("vehicleId", genericRecord.VehicleId.ToString());
payloadDictionary.Add("cost", genericRecord.Cost.ToString("F2"));
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = genericRecord.VehicleId.ToString(),
Username = userName,
Action = $"{userName} {GetFriendlyActionType(actionType)} Description: {genericRecord.Description}"
};
}
public static WebHookPayload FromGasRecord(GasRecord gasRecord, string actionType, string userName)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
payloadDictionary.Add("odometer", gasRecord.Mileage.ToString());
payloadDictionary.Add("fuelconsumed", gasRecord.Gallons.ToString());
payloadDictionary.Add("vehicleId", gasRecord.VehicleId.ToString());
payloadDictionary.Add("cost", gasRecord.Cost.ToString("F2"));
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = gasRecord.VehicleId.ToString(),
Username = userName,
Action = $"{userName} {GetFriendlyActionType(actionType)} Odometer: {gasRecord.Mileage}"
};
}
public static WebHookPayload FromOdometerRecord(OdometerRecord odometerRecord, string actionType, string userName)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
payloadDictionary.Add("initialodometer", odometerRecord.InitialMileage.ToString());
payloadDictionary.Add("odometer", odometerRecord.Mileage.ToString());
payloadDictionary.Add("vehicleId", odometerRecord.VehicleId.ToString());
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = odometerRecord.VehicleId.ToString(),
Username = userName,
Action = $"{userName} {GetFriendlyActionType(actionType)} Odometer: {odometerRecord.Mileage}"
};
}
public static WebHookPayload FromTaxRecord(TaxRecord taxRecord, string actionType, string userName)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
payloadDictionary.Add("description", taxRecord.Description);
payloadDictionary.Add("vehicleId", taxRecord.VehicleId.ToString());
payloadDictionary.Add("cost", taxRecord.Cost.ToString("F2"));
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = taxRecord.VehicleId.ToString(),
Username = userName,
Action = $"{userName} {GetFriendlyActionType(actionType)} Description: {taxRecord.Description}"
};
}
public static WebHookPayload FromPlanRecord(PlanRecord planRecord, string actionType, string userName)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
payloadDictionary.Add("description", planRecord.Description);
payloadDictionary.Add("vehicleId", planRecord.VehicleId.ToString());
payloadDictionary.Add("cost", planRecord.Cost.ToString("F2"));
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = planRecord.VehicleId.ToString(),
Username = userName,
Action = $"{userName} {GetFriendlyActionType(actionType)} Description: {planRecord.Description}"
};
}
public static WebHookPayload FromReminderRecord(ReminderRecord reminderRecord, string actionType, string userName)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
payloadDictionary.Add("description", reminderRecord.Description);
payloadDictionary.Add("vehicleId", reminderRecord.VehicleId.ToString());
payloadDictionary.Add("metric", reminderRecord.Metric.ToString());
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = reminderRecord.VehicleId.ToString(),
Username = userName,
Action = $"{userName} {GetFriendlyActionType(actionType)} Description: {reminderRecord.Description}"
};
}
public static WebHookPayload FromSupplyRecord(SupplyRecord supplyRecord, string actionType, string userName)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
payloadDictionary.Add("description", supplyRecord.Description);
payloadDictionary.Add("vehicleId", supplyRecord.VehicleId.ToString());
payloadDictionary.Add("cost", supplyRecord.Cost.ToString("F2"));
payloadDictionary.Add("quantity", supplyRecord.Quantity.ToString("F2"));
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = supplyRecord.VehicleId.ToString(),
Username = userName,
Action = $"{userName} {GetFriendlyActionType(actionType)} Description: {supplyRecord.Description}"
};
}
public static WebHookPayload FromNoteRecord(Note noteRecord, string actionType, string userName)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
payloadDictionary.Add("description", noteRecord.Description);
payloadDictionary.Add("vehicleId", noteRecord.VehicleId.ToString());
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = noteRecord.VehicleId.ToString(),
Username = userName,
Action = $"{userName} {GetFriendlyActionType(actionType)} Description: {noteRecord.Description}"
};
}
public static WebHookPayload Generic(string payload, string actionType, string userName, string vehicleId)
{
Dictionary<string, string> payloadDictionary = new Dictionary<string, string>();
payloadDictionary.Add("user", userName);
if (!string.IsNullOrWhiteSpace(payload))
{
payloadDictionary.Add("description", payload);
}
return new WebHookPayload
{
Type = actionType,
Data = payloadDictionary,
VehicleId = string.IsNullOrWhiteSpace(vehicleId) ? "N/A" : vehicleId,
Username = userName,
Action = string.IsNullOrWhiteSpace(payload) ? $"{userName} {GetFriendlyActionType(actionType)}" : $"{userName} {payload}"
};
}
}
}

10
Models/Sponsors.cs Normal file
View File

@@ -0,0 +1,10 @@
namespace MotoVaultPro.Models
{
public class Sponsors
{
public List<string> LifeTime { get; set; } = new List<string>();
public List<string> Bronze { get; set; } = new List<string>();
public List<string> Silver { get; set; } = new List<string>();
public List<string> Gold { get; set; } = new List<string>();
}
}

View File

@@ -0,0 +1,11 @@
namespace MotoVaultPro.Models
{
public class SupplyAvailability
{
public bool Missing { get; set; }
public string Description { get; set; } = string.Empty;
public decimal Required { get; set; }
public decimal InStock { get; set; }
public bool Insufficient { get { return Required > InStock; } }
}
}

View File

@@ -0,0 +1,40 @@
namespace MotoVaultPro.Models
{
public class SupplyRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
/// <summary>
/// When the part or supplies were purchased.
/// </summary>
public DateTime Date { get; set; }
/// <summary>
/// Part number can be alphanumeric.
/// </summary>
public string PartNumber { get; set; }
/// <summary>
/// Where the part/supplies were purchased from.
/// </summary>
public string PartSupplier { get; set; }
/// <summary>
/// Amount purchased, can be partial quantities such as fluids.
/// </summary>
public decimal Quantity { get; set; }
/// <summary>
/// Description of the part/supplies purchased.
/// </summary>
public string Description { get; set; }
/// <summary>
/// How much it costs
/// </summary>
public decimal Cost { get; set; }
/// <summary>
/// Additional notes.
/// </summary>
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
}
}

View File

@@ -0,0 +1,34 @@
namespace MotoVaultPro.Models
{
public class SupplyRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public string Date { get; set; } = DateTime.Now.ToShortDateString();
public string PartNumber { get; set; }
public string PartSupplier { get; set; }
public decimal Quantity { get; set; }
public string Description { get; set; }
public decimal Cost { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public SupplyRecord ToSupplyRecord() { return new SupplyRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(Date),
Cost = Cost,
PartNumber = PartNumber,
PartSupplier = PartSupplier,
Quantity = Quantity,
Description = Description,
Notes = Notes,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
}; }
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class SupplyRequisitionHistory
{
public string CostInputId { get; set; }
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class SupplyStore
{
public string Tab { get; set; }
public bool AdditionalSupplies { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace MotoVaultPro.Models
{
public class SupplyUsage {
public int SupplyId { get; set; }
public decimal Quantity { get; set; }
}
}

View File

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

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class SupplyUsageViewModel
{
public List<SupplyRecord> Supplies { get; set; } = new List<SupplyRecord>();
public List<SupplyUsage> Usage { get; set; } = new List<SupplyUsage>();
}
}

View File

@@ -0,0 +1,19 @@
namespace MotoVaultPro.Models
{
public class TaxRecord
{
public int Id { get; set; }
public int VehicleId { get; set; }
public DateTime Date { get; set; }
public string Description { get; set; }
public decimal Cost { get; set; }
public string Notes { get; set; }
public bool IsRecurring { get; set; } = false;
public ReminderMonthInterval RecurringInterval { get; set; } = ReminderMonthInterval.OneYear;
public int CustomMonthInterval { get; set; } = 0;
public ReminderIntervalUnit CustomMonthIntervalUnit { get; set; } = ReminderIntervalUnit.Months;
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -0,0 +1,35 @@
namespace MotoVaultPro.Models
{
public class TaxRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public List<int> ReminderRecordId { get; set; } = new List<int>();
public string Date { get; set; } = DateTime.Now.ToShortDateString();
public string Description { get; set; }
public decimal Cost { get; set; }
public string Notes { get; set; }
public bool IsRecurring { get; set; } = false;
public ReminderMonthInterval RecurringInterval { get; set; } = ReminderMonthInterval.ThreeMonths;
public int CustomMonthInterval { get; set; } = 0;
public ReminderIntervalUnit CustomMonthIntervalUnit { get; set; } = ReminderIntervalUnit.Months;
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public TaxRecord ToTaxRecord() { return new TaxRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(Date),
Cost = Cost,
Description = Description,
Notes = Notes,
IsRecurring = IsRecurring,
RecurringInterval = RecurringInterval,
CustomMonthInterval = CustomMonthInterval,
CustomMonthIntervalUnit = CustomMonthIntervalUnit,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields
}; }
}
}

12
Models/Translations.cs Normal file
View File

@@ -0,0 +1,12 @@
namespace MotoVaultPro.Models
{
public class Translations
{
public List<string> Africa { get; set; } = new List<string>();
public List<string> Asia { get; set; } = new List<string>();
public List<string> Europe { get; set; } = new List<string>();
public List<string> NorthAmerica { get; set; } = new List<string>();
public List<string> SouthAmerica { get; set; } = new List<string>();
public List<string> Oceania { get; set; } = new List<string>();
}
}

View File

@@ -0,0 +1,6 @@
namespace MotoVaultPro.Models
{
public class UpgradeRecord: GenericRecord
{
}
}

View File

@@ -0,0 +1,35 @@
namespace MotoVaultPro.Models
{
public class UpgradeRecordInput
{
public int Id { get; set; }
public int VehicleId { get; set; }
public List<int> ReminderRecordId { get; set; } = new List<int>();
public string Date { get; set; } = DateTime.Now.ToShortDateString();
public int Mileage { get; set; }
public string Description { get; set; }
public decimal Cost { get; set; }
public string Notes { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<SupplyUsage> Supplies { get; set; } = new List<SupplyUsage>();
public List<string> Tags { get; set; } = new List<string>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<SupplyUsageHistory> RequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public List<SupplyUsageHistory> DeletedRequisitionHistory { get; set; } = new List<SupplyUsageHistory>();
public bool CopySuppliesAttachment { get; set; } = false;
public UpgradeRecord ToUpgradeRecord() { return new UpgradeRecord {
Id = Id,
VehicleId = VehicleId,
Date = DateTime.Parse(Date),
Cost = Cost,
Mileage = Mileage,
Description = Description,
Notes = Notes,
Files = Files,
Tags = Tags,
ExtraFields = ExtraFields,
RequisitionHistory = RequisitionHistory
};
}
}
}

12
Models/User/UserAccess.cs Normal file
View File

@@ -0,0 +1,12 @@
namespace MotoVaultPro.Models
{
public class UserVehicle
{
public int UserId { get; set; }
public int VehicleId { get; set; }
}
public class UserAccess
{
public UserVehicle Id { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace MotoVaultPro.Models
{
public class UserCollaborator
{
public string UserName { get; set; }
public UserVehicle UserVehicle { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
namespace MotoVaultPro.Models
{
public class UserColumnPreference
{
public ImportMode Tab { get; set; }
public List<string> VisibleColumns { get; set; } = new List<string>();
public List<string> ColumnOrder { get; set; } = new List<string>();
}
}

View File

@@ -0,0 +1,11 @@
namespace MotoVaultPro.Models
{
public class UserConfigData
{
/// <summary>
/// User ID
/// </summary>
public int Id { get; set; }
public UserConfig UserConfig { get; set; }
}
}

12
Models/User/UserData.cs Normal file
View File

@@ -0,0 +1,12 @@
namespace MotoVaultPro.Models
{
public class UserData
{
public int Id { get; set; }
public string UserName { get; set; }
public string EmailAddress { get; set; }
public string Password { get; set; }
public bool IsAdmin { get; set; }
public bool IsRootUser { get; set; } = false;
}
}

56
Models/UserConfig.cs Normal file
View File

@@ -0,0 +1,56 @@
namespace MotoVaultPro.Models
{
public class UserConfig
{
public bool UseDarkMode { get; set; }
public bool UseSystemColorMode { get; set; }
public bool EnableCsvImports { get; set; }
public bool UseMPG { get; set; }
public bool UseDescending { get; set; }
public bool EnableAuth { get; set; }
public bool HideZero { get; set; }
public bool UseUKMPG {get;set;}
public bool UseThreeDecimalGasCost { get; set; }
public bool UseThreeDecimalGasConsumption { get; set; }
public bool UseMarkDownOnSavedNotes { get; set; }
public bool EnableAutoReminderRefresh { get; set; }
public bool EnableAutoOdometerInsert { get; set; }
public bool EnableShopSupplies { get; set; }
public bool EnableExtraFieldColumns { get; set; }
public bool HideSoldVehicles { get; set; }
public bool AutomaticDecimalFormat { get; set; }
public string PreferredGasUnit { get; set; } = string.Empty;
public string PreferredGasMileageUnit { get; set; } = string.Empty;
public bool UseUnitForFuelCost { get; set; }
public bool ShowCalendar { get; set; }
public bool ShowVehicleThumbnail { get; set; }
public List<UserColumnPreference> UserColumnPreferences { get; set; } = new List<UserColumnPreference>();
public string UserNameHash { get; set; }
public string UserPasswordHash { get; set;}
public string UserLanguage { get; set; } = "en_US";
public List<ImportMode> VisibleTabs { get; set; } = new List<ImportMode>() {
ImportMode.Dashboard,
ImportMode.ServiceRecord,
ImportMode.RepairRecord,
ImportMode.GasRecord,
ImportMode.UpgradeRecord,
ImportMode.TaxRecord,
ImportMode.ReminderRecord,
ImportMode.NoteRecord
};
public ImportMode DefaultTab { get; set; } = ImportMode.Dashboard;
public List<ImportMode> TabOrder { get; set; } = new List<ImportMode>() {
ImportMode.Dashboard,
ImportMode.PlanRecord,
ImportMode.OdometerRecord,
ImportMode.ServiceRecord,
ImportMode.RepairRecord,
ImportMode.UpgradeRecord,
ImportMode.GasRecord,
ImportMode.SupplyRecord,
ImportMode.TaxRecord,
ImportMode.NoteRecord,
ImportMode.ReminderRecord
};
}
}

42
Models/Vehicle.cs Normal file
View File

@@ -0,0 +1,42 @@
using System.Text.Json.Serialization;
namespace MotoVaultPro.Models
{
public class Vehicle
{
public int Id { get; set; }
public string ImageLocation { get; set; } = "/defaults/noimage.png";
public int Year { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public string LicensePlate { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string PurchaseDate { get; set; }
[JsonConverter(typeof(FromDateOptional))]
public string SoldDate { get; set; }
public decimal PurchasePrice { get; set; }
public decimal SoldPrice { get; set; }
public bool IsElectric { get; set; } = false;
public bool IsDiesel { get; set; } = false;
public bool UseHours { get; set; } = false;
public bool OdometerOptional { get; set; } = false;
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<string> Tags { get; set; } = new List<string>();
public bool HasOdometerAdjustment { get; set; } = false;
/// <summary>
/// Primarily used for vehicles with odometer units different from user's settings.
/// </summary>
[JsonConverter(typeof(FromDecimalOptional))]
public string OdometerMultiplier { get; set; } = "1";
/// <summary>
/// Primarily used for vehicles where the odometer does not reflect actual mileage.
/// </summary>
[JsonConverter(typeof(FromIntOptional))]
public string OdometerDifference { get; set; } = "0";
public List<DashboardMetric> DashboardMetrics { get; set; } = new List<DashboardMetric>();
/// <summary>
/// Determines what is displayed in place of the license plate.
/// </summary>
public string VehicleIdentifier { get; set; } = "LicensePlate";
}
}

View File

@@ -0,0 +1,27 @@
namespace MotoVaultPro.Models
{
public class VehicleViewModel
{
public int Id { get; set; }
public string ImageLocation { get; set; } = "/defaults/noimage.png";
public int Year { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public string LicensePlate { get; set; }
public string SoldDate { get; set; }
public bool IsElectric { get; set; } = false;
public bool IsDiesel { get; set; } = false;
public bool UseHours { get; set; } = false;
public bool OdometerOptional { get; set; } = false;
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<string> Tags { get; set; } = new List<string>();
public string VehicleIdentifier { get; set; } = "LicensePlate";
//Dashboard Metric Attributes
public List<DashboardMetric> DashboardMetrics { get; set; } = new List<DashboardMetric>();
public int LastReportedMileage { get; set; }
public bool HasReminders { get; set; } = false;
public decimal CostPerMile { get; set; }
public decimal TotalCost { get; set; }
public string DistanceUnit { get; set; }
}
}