diff --git a/Controllers/VehicleController.cs b/Controllers/VehicleController.cs index 809c8f3..16e2e0c 100644 --- a/Controllers/VehicleController.cs +++ b/Controllers/VehicleController.cs @@ -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); diff --git a/External/Implementations/Postgres/ReminderRecordDataAccess.cs b/External/Implementations/Postgres/ReminderRecordDataAccess.cs new file mode 100644 index 0000000..b006706 --- /dev/null +++ b/External/Implementations/Postgres/ReminderRecordDataAccess.cs @@ -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 _logger; + private static string tableName = "reminderrecords"; + public PGReminderRecordDataAccess(IConfiguration config, ILogger 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 ALWAYS 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 GetReminderRecordsByVehicleId(int vehicleId) + { + try + { + string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId"; + var results = new List(); + using (var ctext = new NpgsqlCommand(cmd, pgDataSource)) + { + ctext.Parameters.AddWithValue("vehicleId", vehicleId); + using (NpgsqlDataReader reader = ctext.ExecuteReader()) + while (reader.Read()) + { + ReminderRecord reminderRecord = JsonSerializer.Deserialize(reader["data"] as string); + results.Add(reminderRecord); + } + } + return results; + } + catch (Exception ex) + { + _logger.LogError(ex.Message); + return new List(); + } + } + 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(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; + } + } + } +} diff --git a/External/Implementations/Postgres/TaxRecordDataAccess.cs b/External/Implementations/Postgres/TaxRecordDataAccess.cs new file mode 100644 index 0000000..a895336 --- /dev/null +++ b/External/Implementations/Postgres/TaxRecordDataAccess.cs @@ -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 _logger; + private static string tableName = "taxrecords"; + public PGTaxRecordDataAccess(IConfiguration config, ILogger 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 ALWAYS 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 GetTaxRecordsByVehicleId(int vehicleId) + { + try + { + string cmd = $"SELECT data FROM app.{tableName} WHERE vehicleId = @vehicleId"; + var results = new List(); + using (var ctext = new NpgsqlCommand(cmd, pgDataSource)) + { + ctext.Parameters.AddWithValue("vehicleId", vehicleId); + using (NpgsqlDataReader reader = ctext.ExecuteReader()) + while (reader.Read()) + { + TaxRecord taxRecord = JsonSerializer.Deserialize(reader["data"] as string); + results.Add(taxRecord); + } + } + return results; + } + catch (Exception ex) + { + _logger.LogError(ex.Message); + return new List(); + } + } + 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(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; + } + } + } +} diff --git a/Program.cs b/Program.cs index e9d9df6..8ba4fea 100644 --- a/Program.cs +++ b/Program.cs @@ -20,6 +20,8 @@ if (!string.IsNullOrWhiteSpace(builder.Configuration["POSTGRES_CONNECTION"])){ builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); } else { @@ -28,10 +30,10 @@ else builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); } -builder.Services.AddSingleton(); -builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); diff --git a/wwwroot/defaults/en_US.json b/wwwroot/defaults/en_US.json index 58fdb50..0ada1db 100644 --- a/wwwroot/defaults/en_US.json +++ b/wwwroot/defaults/en_US.json @@ -1 +1 @@ -{"Garage":"Garage","Settings":"Settings","Admin_Panel":"Admin Panel","Logout":"Logout","Dark_Mode":"Dark Mode","Enable_CSV_Imports":"Enable CSV Imports","Use_Imperial_Calculation_for_Fuel_Economy_Calculations(MPG)":"Use Imperial Calculation for Fuel Economy Calculations(MPG)","This_Will_Also_Change_Units_to_Miles_and_Gallons":"This Will Also Change Units to Miles and Gallons","Use_UK_MPG_Calculation":"Use UK MPG Calculation","Input_Gas_Consumption_in_Liters,_it_will_be_converted_to_UK_Gals_for_MPG_Calculation":"Input Gas Consumption in Liters, it will be converted to UK Gals for MPG Calculation","Sort_lists_in_Descending_Order(Newest_to_Oldest)":"Sort lists in Descending Order(Newest to Oldest)","Replace_$0.00_Costs_with_---":"Replace $0.00 Costs with ---","Use_Three_Decimals_For_Fuel_Cost":"Use Three Decimals For Fuel Cost","Display_Saved_Notes_in_Markdown":"Display Saved Notes in Markdown","Auto_Refresh_Lapsed_Recurring_Reminders":"Auto Refresh Lapsed Recurring Reminders","Auto_Insert_Odometer_Records":"Auto Insert Odometer Records","Only_when_Adding_Service/Repair/Upgrade/Fuel_Record_or_Completing_a_Plan":"Only when Adding Service/Repair/Upgrade/Fuel Record or Completing a Plan","Enable_Authentication":"Enable Authentication","Visible_Tabs":"Visible Tabs","Service_Records":"Service Records","Dashboard":"Dashboard","Repairs":"Repairs","Upgrades":"Upgrades","Fuel":"Fuel","Odometer":"Odometer","Taxes":"Taxes","Notes":"Notes","Reminder":"Reminder","Supplies":"Supplies","Planner":"Planner","Default_Tab":"Default Tab","Service_Record":"Service Record","Tax":"Tax","Reminders":"Reminders","Backups":"Backups","Make":"Make","Restore":"Restore","About":"About","Add_New_Vehicle":"Add New Vehicle","Year":"Year","Year(must_be_after_1900)":"Year(must be after 1900)","Model":"Model","License_Plate":"License Plate","Electric_Vehicle":"Electric Vehicle","Use_Engine_Hours":"Use Engine Hours","Tags(optional)":"Tags(optional)","Upload_a_picture(optional)":"Upload a picture(optional)","Cancel":"Cancel","Edit_Vehicle":"Edit Vehicle","Delete_Vehicle":"Delete Vehicle","Manage_Vehicle":"Manage Vehicle","Expenses_by_Type":"Expenses by Type","Service":"Service","Expenses_by_Month":"Expenses by Month","As_of_Today":"As of Today","\u002B30_Days":"\u002B30 Days","\u002B60_Days":"\u002B60 Days","\u002B90_Days":"\u002B90 Days","Not_Urgent":"Not Urgent","Urgent":"Urgent","Very_Urgent":"Very Urgent","Past_Due":"Past Due","Reminders_by_Category":"Reminders by Category","Reminders_by_Urgency":"Reminders by Urgency","Collaborators":"Collaborators","Username":"Username","Delete":"Delete","Fuel_Mileage_by_Month":"Fuel Mileage by Month","Vehicle_Maintenance_Report":"Vehicle Maintenance Report","Export_Attachments":"Export Attachments","Gasoline":"Gasoline","Last_Reported_Odometer_Reading":"Last Reported Odometer Reading","Average_Fuel_Economy":"Average Fuel Economy","Total_Spent(excl._fuel)":"Total Spent(excl. fuel)","Total_Spent_on_Fuel":"Total Spent on Fuel","Type":"Type","Date":"Date","Description":"Description","Cost":"Cost","Repair":"Repair","Upgrade":"Upgrade","#_of_Odometer_Records":"# of Odometer Records","Add_Odometer_Record":"Add Odometer Record","Import_via_CSV":"Import via CSV","Export_to_CSV":"Export to CSV","Print":"Print","Add_New_Odometer_Record":"Add New Odometer Record","Date_recorded":"Date recorded","Odometer_reading":"Odometer reading","Notes(optional)":"Notes(optional)","Upload_documents(optional)":"Upload documents(optional)","Max_File_Size:_28.6MB":"Max File Size: 28.6MB","#_of_Service_Records":"# of Service Records","Total":"Total","Add_Service_Record":"Add Service Record","No_data_found,_create_reminders_to_see_visualizations_here.":"No data found, create reminders to see visualizations here.","No_data_found,_insert/select_some_data_to_see_visualizations_here.":"No data found, insert/select some data to see visualizations here.","Edit_Odometer_Record":"Edit Odometer Record","Import_Data_from_CSV":"Import Data from CSV","In_order_for_this_utility_to_function_properly,_your_CSV_file_MUST_be_formatted_exactly_like_the_provided_sample._Dates_must_be_supplied_in_a_string._Numbers_must_be_supplied_as_numbers_without_currency_formatting.":"In order for this utility to function properly, your CSV file MUST be formatted exactly like the provided sample. Dates must be supplied in a string. Numbers must be supplied as numbers without currency formatting.","Failure_to_format_the_data_correctly_can_cause_data_corruption._Please_make_sure_you_make_a_copy_of_the_local_database_before_proceeding.":"Failure to format the data correctly can cause data corruption. Please make sure you make a copy of the local database before proceeding.","Download_Sample":"Download Sample","Upload_CSV_File":"Upload CSV File","Import":"Import","Edit_Service_Record":"Edit Service Record","Date_service_was_performed":"Date service was performed","Odometer_reading_when_serviced":"Odometer reading when serviced","Description_of_item(s)_serviced(i.e._Oil_Change)":"Description of item(s) serviced(i.e. Oil Change)","Cost_of_the_service":"Cost of the service","Move_To":"Move To","#_of_Repair_Records":"# of Repair Records","Add_Repair_Record":"Add Repair Record","Add_New_Repair_Record":"Add New Repair Record","Date_repair_was_performed":"Date repair was performed","Odometer_reading_when_repaired":"Odometer reading when repaired","Description_of_item(s)_repaired(i.e._Alternator)":"Description of item(s) repaired(i.e. Alternator)","Cost_of_the_repair":"Cost of the repair","Choose_Supplies":"Choose Supplies","Add_Reminder":"Add Reminder","Select_Supplies":"Select Supplies","No_supplies_with_quantities_greater_than_0_is_found.":"No supplies with quantities greater than 0 is found.","Select":"Select","#_of_Upgrade_Records":"# of Upgrade Records","Add_Upgrade_Record":"Add Upgrade Record","Add_New_Upgrade_Record":"Add New Upgrade Record","Date_upgrade/mods_was_installed":"Date upgrade/mods was installed","Odometer_reading_when_upgraded/modded":"Odometer reading when upgraded/modded","Description_of_item(s)_upgraded/modded":"Description of item(s) upgraded/modded","Cost_of_the_upgrade/mods":"Cost of the upgrade/mods","#_of_Gas_Records":"# of Gas Records","Total_Fuel_Consumed":"Total Fuel Consumed","Total_Cost":"Total Cost","Add_Gas_Record":"Add Gas Record","Date_Refueled":"Date Refueled","Consumption":"Consumption","Fuel_Economy":"Fuel Economy","Unit_Cost":"Unit Cost","#_of_Supply_Records":"# of Supply Records","Add_Supply_Record":"Add Supply Record","Part_#":"Part #","Supplier":"Supplier","Quantity":"Quantity","Add_New_Supply_Record":"Add New Supply Record","Date_purchased":"Date purchased","Part_Number":"Part Number","Part_#/Model_#/SKU_#":"Part #/Model #/SKU #","Description_of_the_Part/Supplies":"Description of the Part/Supplies","Supplier/Vendor":"Supplier/Vendor","Part_Supplier":"Part Supplier","Edit_Supply_Record":"Edit Supply Record","Add_New_Service_Record":"Add New Service Record","Supplies_are_requisitioned_immediately_after_the_record_is_created_and_cannot_be_modified._If_you_have_incorrectly_entered_the_amount_you_needed_you_will_need_to_correct_it_in_the_Supplies_tab.":"Supplies are requisitioned immediately after the record is created and cannot be modified. If you have incorrectly entered the amount you needed you will need to correct it in the Supplies tab.","In_Stock":"In Stock","Edit_Repair_Record":"Edit Repair Record","Edit_Upgrade_Record":"Edit Upgrade Record","Save_Vehicle":"Save Vehicle","Add_New_Gas_Record":"Add New Gas Record","Date_refueled":"Date refueled","Odometer_Reading":"Odometer Reading","Odometer_reading_when_refueled":"Odometer reading when refueled","Fuel_Consumption":"Fuel Consumption","Amount_of_gas_refueled":"Amount of gas refueled","Is_Filled_To_Full":"Is Filled To Full","Missed_Fuel_Up(Skip_MPG_Calculation)":"Missed Fuel Up(Skip MPG Calculation)","Cost_of_gas_refueled":"Cost of gas refueled","Unit":"Unit","#_of_Tax_Records":"# of Tax Records","Add_Tax_Record":"Add Tax Record","Add_New_Tax_Record":"Add New Tax Record","Date_tax_was_paid":"Date tax was paid","Description_of_tax_paid(i.e._Registration)":"Description of tax paid(i.e. Registration)","Cost_of_tax_paid":"Cost of tax paid","Is_Recurring":"Is Recurring","Month":"Month","1_Month":"1 Month","3_Months":"3 Months","6_Months":"6 Months","1_Year":"1 Year","2_Years":"2 Years","3_Years":"3 Years","5_Years":"5 Years","Edit_Tax_Record":"Edit Tax Record","#_of_Notes":"# of Notes","Add_Note":"Add Note","Note":"Note","Add_New_Note":"Add New Note","Pinned":"Pinned","Description_of_the_note":"Description of the note","Min_Fuel_Economy":"Min Fuel Economy","Max_Fuel_Economy":"Max Fuel Economy","Edit_Gas_Record":"Edit Gas Record","#_of_Plan_Records":"# of Plan Records","Add_Plan_Record":"Add Plan Record","Planned":"Planned","Doing":"Doing","Testing":"Testing","Done":"Done","Add_New_Plan_Record":"Add New Plan Record","Describe_the_Plan":"Describe the Plan","Cost_of_the_Plan":"Cost of the Plan","Priority":"Priority","Critical":"Critical","Normal":"Normal","Low":"Low","Current_Stage":"Current Stage","#_of_Reminders":"# of Reminders","Urgency":"Urgency","Metric":"Metric","Add_New_Reminder":"Add New Reminder","Reminder_Description":"Reminder Description","Remind_me_on":"Remind me on","Future_Date":"Future Date","Future_Odometer_Reading":"Future Odometer Reading","Whichever_comes_first":"Whichever comes first","Other":"Other","Edit_Reminder":"Edit Reminder","Replace_picture(optional)":"Replace picture(optional)","Language":"Language","Manage_Languages":"Manage Languages","Upload":"Upload","Tokens":"Tokens","Generate_User_Token":"Generate User Token","Auto_Notify(via_Email)":"Auto Notify(via Email)","Token":"Token","Issued_To":"Issued To","Users":"Users","Email":"Email","Is_Admin":"Is Admin","An_error_has_occurred,_please_try_again_later":"An error has occurred, please try again later","Edit_Note":"Edit Note","Password":"Password","Remember_Me":"Remember Me","Login":"Login","Forgot_Password":"Forgot Password","Register":"Register","Request":"Request","I_Have_a_Token":"I Have a Token","Back_to_Login":"Back to Login","Email_Address":"Email Address","New_Password":"New Password","Reset_Password":"Reset Password","No_data_found_or_all_records_have_zero_sums,_insert_records_with_non-zero_sums_to_see_visualizations_here.":"No data found or all records have zero sums, insert records with non-zero sums to see visualizations here.","Save_as_Template":"Save as Template","View_Templates":"View Templates","Select_Template":"Select Template","No_templates_are_found.":"No templates are found.","Use":"Use","Edit_Plan_Record":"Edit Plan Record","Date_Created":"Date Created","Last_Modified":"Last Modified"} \ No newline at end of file +{"Garage":"Garage","Settings":"Settings","Admin_Panel":"Admin Panel","Logout":"Logout","Dark_Mode":"Dark Mode","Enable_CSV_Imports":"Enable CSV Imports","Use_Imperial_Calculation_for_Fuel_Economy_Calculations(MPG)":"Use Imperial Calculation for Fuel Economy Calculations(MPG)","This_Will_Also_Change_Units_to_Miles_and_Gallons":"This Will Also Change Units to Miles and Gallons","Use_UK_MPG_Calculation":"Use UK MPG Calculation","Input_Gas_Consumption_in_Liters,_it_will_be_converted_to_UK_Gals_for_MPG_Calculation":"Input Gas Consumption in Liters, it will be converted to UK Gals for MPG Calculation","Sort_lists_in_Descending_Order(Newest_to_Oldest)":"Sort lists in Descending Order(Newest to Oldest)","Replace_$0.00_Costs_with_---":"Replace $0.00 Costs with ---","Use_Three_Decimals_For_Fuel_Cost":"Use Three Decimals For Fuel Cost","Display_Saved_Notes_in_Markdown":"Display Saved Notes in Markdown","Auto_Refresh_Lapsed_Recurring_Reminders":"Auto Refresh Lapsed Recurring Reminders","Auto_Insert_Odometer_Records":"Auto Insert Odometer Records","Only_when_Adding_Service/Repair/Upgrade/Fuel_Record_or_Completing_a_Plan":"Only when Adding Service/Repair/Upgrade/Fuel Record or Completing a Plan","Enable_Authentication":"Enable Authentication","Visible_Tabs":"Visible Tabs","Service_Records":"Service Records","Dashboard":"Dashboard","Repairs":"Repairs","Upgrades":"Upgrades","Fuel":"Fuel","Odometer":"Odometer","Taxes":"Taxes","Notes":"Notes","Reminder":"Reminder","Supplies":"Supplies","Planner":"Planner","Default_Tab":"Default Tab","Service_Record":"Service Record","Tax":"Tax","Reminders":"Reminders","Backups":"Backups","Make":"Make","Restore":"Restore","About":"About","Add_New_Vehicle":"Add New Vehicle","Year":"Year","Year(must_be_after_1900)":"Year(must be after 1900)","Model":"Model","License_Plate":"License Plate","Electric_Vehicle":"Electric Vehicle","Use_Engine_Hours":"Use Engine Hours","Tags(optional)":"Tags(optional)","Upload_a_picture(optional)":"Upload a picture(optional)","Cancel":"Cancel","Edit_Vehicle":"Edit Vehicle","Delete_Vehicle":"Delete Vehicle","Manage_Vehicle":"Manage Vehicle","Expenses_by_Type":"Expenses by Type","Service":"Service","Expenses_by_Month":"Expenses by Month","As_of_Today":"As of Today","\u002B30_Days":"\u002B30 Days","\u002B60_Days":"\u002B60 Days","\u002B90_Days":"\u002B90 Days","Not_Urgent":"Not Urgent","Urgent":"Urgent","Very_Urgent":"Very Urgent","Past_Due":"Past Due","Reminders_by_Category":"Reminders by Category","Reminders_by_Urgency":"Reminders by Urgency","Collaborators":"Collaborators","Username":"Username","Delete":"Delete","Fuel_Mileage_by_Month":"Fuel Mileage by Month","Vehicle_Maintenance_Report":"Vehicle Maintenance Report","Export_Attachments":"Export Attachments","Gasoline":"Gasoline","Last_Reported_Odometer_Reading":"Last Reported Odometer Reading","Average_Fuel_Economy":"Average Fuel Economy","Total_Spent(excl._fuel)":"Total Spent(excl. fuel)","Total_Spent_on_Fuel":"Total Spent on Fuel","Type":"Type","Date":"Date","Description":"Description","Cost":"Cost","Repair":"Repair","Upgrade":"Upgrade","#_of_Odometer_Records":"# of Odometer Records","Add_Odometer_Record":"Add Odometer Record","Import_via_CSV":"Import via CSV","Export_to_CSV":"Export to CSV","Print":"Print","Add_New_Odometer_Record":"Add New Odometer Record","Date_recorded":"Date recorded","Odometer_reading":"Odometer reading","Notes(optional)":"Notes(optional)","Upload_documents(optional)":"Upload documents(optional)","Max_File_Size:_28.6MB":"Max File Size: 28.6MB","#_of_Service_Records":"# of Service Records","Total":"Total","Add_Service_Record":"Add Service Record","No_data_found,_create_reminders_to_see_visualizations_here.":"No data found, create reminders to see visualizations here.","No_data_found,_insert/select_some_data_to_see_visualizations_here.":"No data found, insert/select some data to see visualizations here.","Edit_Odometer_Record":"Edit Odometer Record","Import_Data_from_CSV":"Import Data from CSV","In_order_for_this_utility_to_function_properly,_your_CSV_file_MUST_be_formatted_exactly_like_the_provided_sample._Dates_must_be_supplied_in_a_string._Numbers_must_be_supplied_as_numbers_without_currency_formatting.":"In order for this utility to function properly, your CSV file MUST be formatted exactly like the provided sample. Dates must be supplied in a string. Numbers must be supplied as numbers without currency formatting.","Failure_to_format_the_data_correctly_can_cause_data_corruption._Please_make_sure_you_make_a_copy_of_the_local_database_before_proceeding.":"Failure to format the data correctly can cause data corruption. Please make sure you make a copy of the local database before proceeding.","Download_Sample":"Download Sample","Upload_CSV_File":"Upload CSV File","Import":"Import","Edit_Service_Record":"Edit Service Record","Date_service_was_performed":"Date service was performed","Odometer_reading_when_serviced":"Odometer reading when serviced","Description_of_item(s)_serviced(i.e._Oil_Change)":"Description of item(s) serviced(i.e. Oil Change)","Cost_of_the_service":"Cost of the service","Move_To":"Move To","#_of_Repair_Records":"# of Repair Records","Add_Repair_Record":"Add Repair Record","Add_New_Repair_Record":"Add New Repair Record","Date_repair_was_performed":"Date repair was performed","Odometer_reading_when_repaired":"Odometer reading when repaired","Description_of_item(s)_repaired(i.e._Alternator)":"Description of item(s) repaired(i.e. Alternator)","Cost_of_the_repair":"Cost of the repair","Choose_Supplies":"Choose Supplies","Add_Reminder":"Add Reminder","Select_Supplies":"Select Supplies","No_supplies_with_quantities_greater_than_0_is_found.":"No supplies with quantities greater than 0 is found.","Select":"Select","#_of_Upgrade_Records":"# of Upgrade Records","Add_Upgrade_Record":"Add Upgrade Record","Add_New_Upgrade_Record":"Add New Upgrade Record","Date_upgrade/mods_was_installed":"Date upgrade/mods was installed","Odometer_reading_when_upgraded/modded":"Odometer reading when upgraded/modded","Description_of_item(s)_upgraded/modded":"Description of item(s) upgraded/modded","Cost_of_the_upgrade/mods":"Cost of the upgrade/mods","#_of_Gas_Records":"# of Gas Records","Total_Fuel_Consumed":"Total Fuel Consumed","Total_Cost":"Total Cost","Add_Gas_Record":"Add Gas Record","Date_Refueled":"Date Refueled","Consumption":"Consumption","Fuel_Economy":"Fuel Economy","Unit_Cost":"Unit Cost","#_of_Supply_Records":"# of Supply Records","Add_Supply_Record":"Add Supply Record","Part_#":"Part #","Supplier":"Supplier","Quantity":"Quantity","Add_New_Supply_Record":"Add New Supply Record","Date_purchased":"Date purchased","Part_Number":"Part Number","Part_#/Model_#/SKU_#":"Part #/Model #/SKU #","Description_of_the_Part/Supplies":"Description of the Part/Supplies","Supplier/Vendor":"Supplier/Vendor","Part_Supplier":"Part Supplier","Edit_Supply_Record":"Edit Supply Record","Add_New_Service_Record":"Add New Service Record","Supplies_are_requisitioned_immediately_after_the_record_is_created_and_cannot_be_modified._If_you_have_incorrectly_entered_the_amount_you_needed_you_will_need_to_correct_it_in_the_Supplies_tab.":"Supplies are requisitioned immediately after the record is created and cannot be modified. If you have incorrectly entered the amount you needed you will need to correct it in the Supplies tab.","In_Stock":"In Stock","Edit_Repair_Record":"Edit Repair Record","Edit_Upgrade_Record":"Edit Upgrade Record","Save_Vehicle":"Save Vehicle","Add_New_Gas_Record":"Add New Gas Record","Date_refueled":"Date refueled","Odometer_Reading":"Odometer Reading","Odometer_reading_when_refueled":"Odometer reading when refueled","Fuel_Consumption":"Fuel Consumption","Amount_of_gas_refueled":"Amount of gas refueled","Is_Filled_To_Full":"Is Filled To Full","Missed_Fuel_Up(Skip_MPG_Calculation)":"Missed Fuel Up(Skip MPG Calculation)","Cost_of_gas_refueled":"Cost of gas refueled","Unit":"Unit","#_of_Tax_Records":"# of Tax Records","Add_Tax_Record":"Add Tax Record","Add_New_Tax_Record":"Add New Tax Record","Date_tax_was_paid":"Date tax was paid","Description_of_tax_paid(i.e._Registration)":"Description of tax paid(i.e. Registration)","Cost_of_tax_paid":"Cost of tax paid","Is_Recurring":"Is Recurring","Month":"Month","1_Month":"1 Month","3_Months":"3 Months","6_Months":"6 Months","1_Year":"1 Year","2_Years":"2 Years","3_Years":"3 Years","5_Years":"5 Years","Edit_Tax_Record":"Edit Tax Record","#_of_Notes":"# of Notes","Add_Note":"Add Note","Note":"Note","Add_New_Note":"Add New Note","Pinned":"Pinned","Description_of_the_note":"Description of the note","Min_Fuel_Economy":"Min Fuel Economy","Max_Fuel_Economy":"Max Fuel Economy","Edit_Gas_Record":"Edit Gas Record","#_of_Plan_Records":"# of Plan Records","Add_Plan_Record":"Add Plan Record","Planned":"Planned","Doing":"Doing","Testing":"Testing","Done":"Done","Add_New_Plan_Record":"Add New Plan Record","Describe_the_Plan":"Describe the Plan","Cost_of_the_Plan":"Cost of the Plan","Priority":"Priority","Critical":"Critical","Normal":"Normal","Low":"Low","Current_Stage":"Current Stage","#_of_Reminders":"# of Reminders","Urgency":"Urgency","Metric":"Metric","Add_New_Reminder":"Add New Reminder","Reminder_Description":"Reminder Description","Remind_me_on":"Remind me on","Future_Date":"Future Date","Future_Odometer_Reading":"Future Odometer Reading","Whichever_comes_first":"Whichever comes first","Other":"Other","Edit_Reminder":"Edit Reminder","Replace_picture(optional)":"Replace picture(optional)","Language":"Language","Manage_Languages":"Manage Languages","Upload":"Upload","Tokens":"Tokens","Generate_User_Token":"Generate User Token","Auto_Notify(via_Email)":"Auto Notify(via Email)","Token":"Token","Issued_To":"Issued To","Users":"Users","Email":"Email","Is_Admin":"Is Admin","An_error_has_occurred,_please_try_again_later":"An error has occurred, please try again later","Edit_Note":"Edit Note","Password":"Password","Remember_Me":"Remember Me","Login":"Login","Forgot_Password":"Forgot Password","Register":"Register","Request":"Request","I_Have_a_Token":"I Have a Token","Back_to_Login":"Back to Login","Email_Address":"Email Address","New_Password":"New Password","Reset_Password":"Reset Password","No_data_found_or_all_records_have_zero_sums,_insert_records_with_non-zero_sums_to_see_visualizations_here.":"No data found or all records have zero sums, insert records with non-zero sums to see visualizations here.","Save_as_Template":"Save as Template","View_Templates":"View Templates","Select_Template":"Select Template","No_templates_are_found.":"No templates are found.","Use":"Use","Edit_Plan_Record":"Edit Plan Record","Date_Created":"Date Created","Last_Modified":"Last Modified","Shop_Supplies":"Shop Supplies"} \ No newline at end of file