Compare commits

..

22 Commits

Author SHA1 Message Date
Hargata Softworks
6e4e2795b6 Merge pull request #406 from hargata/Hargata/multi.gas.edit
fixed ui bug
2024-03-16 12:24:55 -06:00
DESKTOP-GENO133\IvanPlex
d4e51b714d fixed ui bug 2024-03-16 12:23:46 -06:00
Hargata Softworks
6a164dc60b Merge pull request #405 from hargata/Hargata/multi.gas.edit
Added functionality to edit multiple gas records.
2024-03-16 12:11:52 -06:00
DESKTOP-GENO133\IvanPlex
ce602dcf66 Added functionality to edit multiple gas records. 2024-03-16 12:10:40 -06:00
Hargata Softworks
2facb1ab46 Merge pull request #402 from hargata/Hargata/further.improvements
More enhancements
2024-03-16 10:04:03 -06:00
DESKTOP-GENO133\IvanPlex
3c7d575c85 fixes and ensure that users no longer have to hard refresh their sites. 2024-03-16 10:01:48 -06:00
DESKTOP-GENO133\IvanPlex
9635c3c2c5 fixed bug where translations are not being backed up. 2024-03-16 09:44:27 -06:00
DESKTOP-GENO133\IvanPlex
72427fc19d fixed average calculation 2024-03-15 17:15:05 -06:00
DESKTOP-GENO133\IvanPlex
0bbd3c5491 fixed spelling 2024-03-15 17:09:51 -06:00
DESKTOP-GENO133\IvanPlex
871de4e75a updated translation 2024-03-15 17:07:01 -06:00
DESKTOP-GENO133\IvanPlex
bf984f280e added feature to make odometer adjustments a piece of cake. 2024-03-15 16:48:23 -06:00
DESKTOP-GENO133\IvanPlex
2b8f3cf13a properly capitalized web hook descriptions. 2024-03-15 16:21:41 -06:00
Hargata Softworks
1630a5c9ec Merge pull request #401 from hargata/Hargata/webhook
added web hooks
2024-03-15 15:12:25 -06:00
DESKTOP-T0O5CDB\DESK-555BD
f17faa33f4 fixed punctuation 2024-03-15 15:09:27 -06:00
DESKTOP-T0O5CDB\DESK-555BD
c245b848a0 reminder hooks 2024-03-15 15:06:45 -06:00
DESKTOP-T0O5CDB\DESK-555BD
0ead9112c6 added vehicle deets 2024-03-15 15:01:27 -06:00
DESKTOP-T0O5CDB\DESK-555BD
44da393369 added web hooks 2024-03-15 14:59:30 -06:00
Hargata Softworks
5ae1628b7c Merge pull request #399 from hargata/Hargata/odo.modifier
Odometer Modifier
2024-03-15 14:05:41 -06:00
DESKTOP-GENO133\IvanPlex
59511d9ddd Updated version number 2024-03-15 12:49:34 -06:00
DESKTOP-GENO133\IvanPlex
82b0fba99a added functionality to modify odometer value when adding new odometer records. 2024-03-15 12:49:02 -06:00
DESKTOP-GENO133\IvanPlex
618107e515 added fields for odometer adjustments. 2024-03-15 10:16:28 -06:00
DESKTOP-GENO133\IvanPlex
35f931adf2 additional fields for vehicle level odometer settings. 2024-03-14 23:17:48 -06:00
33 changed files with 638 additions and 73 deletions

View File

@@ -143,6 +143,7 @@ namespace CarCareTracker.Controllers
}; };
_odometerLogic.AutoInsertOdometerRecord(odometerRecord); _odometerLogic.AutoInsertOdometerRecord(odometerRecord);
} }
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Service Record via API - Description: {serviceRecord.Description}");
response.Success = true; response.Success = true;
response.Message = "Service Record Added"; response.Message = "Service Record Added";
return Json(response); return Json(response);
@@ -210,6 +211,7 @@ namespace CarCareTracker.Controllers
}; };
_odometerLogic.AutoInsertOdometerRecord(odometerRecord); _odometerLogic.AutoInsertOdometerRecord(odometerRecord);
} }
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Repair Record via API - Description: {repairRecord.Description}");
response.Success = true; response.Success = true;
response.Message = "Repair Record Added"; response.Message = "Repair Record Added";
return Json(response); return Json(response);
@@ -277,6 +279,7 @@ namespace CarCareTracker.Controllers
}; };
_odometerLogic.AutoInsertOdometerRecord(odometerRecord); _odometerLogic.AutoInsertOdometerRecord(odometerRecord);
} }
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Upgrade Record via API - Description: {upgradeRecord.Description}");
response.Success = true; response.Success = true;
response.Message = "Upgrade Record Added"; response.Message = "Upgrade Record Added";
return Json(response); return Json(response);
@@ -330,6 +333,7 @@ namespace CarCareTracker.Controllers
Cost = decimal.Parse(input.Cost) Cost = decimal.Parse(input.Cost)
}; };
_taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord); _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord);
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Tax Record via API - Description: {taxRecord.Description}");
response.Success = true; response.Success = true;
response.Message = "Tax Record Added"; response.Message = "Tax Record Added";
return Json(response); return Json(response);
@@ -396,6 +400,7 @@ namespace CarCareTracker.Controllers
Mileage = int.Parse(input.Odometer) Mileage = int.Parse(input.Odometer)
}; };
_odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord); _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord);
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Odometer Record via API - Mileage: {odometerRecord.Mileage.ToString()}");
response.Success = true; response.Success = true;
response.Message = "Odometer Record Added"; response.Message = "Odometer Record Added";
return Json(response); return Json(response);
@@ -477,6 +482,7 @@ namespace CarCareTracker.Controllers
}; };
_odometerLogic.AutoInsertOdometerRecord(odometerRecord); _odometerLogic.AutoInsertOdometerRecord(odometerRecord);
} }
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, $"Added Gas record via API - Mileage: {gasRecord.Mileage.ToString()}");
response.Success = true; response.Success = true;
response.Message = "Gas Record Added"; response.Message = "Gas Record Added";
return Json(response); return Json(response);

View File

@@ -130,6 +130,10 @@ namespace CarCareTracker.Controllers
if (isNewAddition) if (isNewAddition)
{ {
_userLogic.AddUserAccessToVehicle(GetUserID(), vehicleInput.Id); _userLogic.AddUserAccessToVehicle(GetUserID(), vehicleInput.Id);
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleInput.Id, User.Identity.Name, $"Added Vehicle - Description: {vehicleInput.Year} {vehicleInput.Make} {vehicleInput.Model}");
} else
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleInput.Id, User.Identity.Name, $"Edited Vehicle - Description: {vehicleInput.Year} {vehicleInput.Make} {vehicleInput.Model}");
} }
return Json(result); return Json(result);
} }
@@ -154,8 +158,13 @@ namespace CarCareTracker.Controllers
_planRecordDataAccess.DeleteAllPlanRecordsByVehicleId(vehicleId) && _planRecordDataAccess.DeleteAllPlanRecordsByVehicleId(vehicleId) &&
_planRecordTemplateDataAccess.DeleteAllPlanRecordTemplatesByVehicleId(vehicleId) && _planRecordTemplateDataAccess.DeleteAllPlanRecordTemplatesByVehicleId(vehicleId) &&
_supplyRecordDataAccess.DeleteAllSupplyRecordsByVehicleId(vehicleId) && _supplyRecordDataAccess.DeleteAllSupplyRecordsByVehicleId(vehicleId) &&
_odometerRecordDataAccess.DeleteAllOdometerRecordsByVehicleId(vehicleId) &&
_userLogic.DeleteAllAccessToVehicle(vehicleId) && _userLogic.DeleteAllAccessToVehicle(vehicleId) &&
_dataAccess.DeleteVehicle(vehicleId); _dataAccess.DeleteVehicle(vehicleId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), vehicleId, User.Identity.Name, "Deleted Vehicle");
}
return Json(result); return Json(result);
} }
[HttpPost] [HttpPost]
@@ -660,6 +669,10 @@ namespace CarCareTracker.Controllers
} }
gasRecord.Files = gasRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); gasRecord.Files = gasRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
var result = _gasRecordDataAccess.SaveGasRecordToVehicle(gasRecord.ToGasRecord()); var result = _gasRecordDataAccess.SaveGasRecordToVehicle(gasRecord.ToGasRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), gasRecord.VehicleId, User.Identity.Name, $"{(gasRecord.Id == default ? "Created" : "Edited")} Gas Record - Mileage: {gasRecord.Mileage.ToString()}");
}
return Json(result); return Json(result);
} }
[HttpGet] [HttpGet]
@@ -704,6 +717,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteGasRecordById(int gasRecordId) public IActionResult DeleteGasRecordById(int gasRecordId)
{ {
var result = _gasRecordDataAccess.DeleteGasRecordById(gasRecordId); var result = _gasRecordDataAccess.DeleteGasRecordById(gasRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Gas Record - Id: {gasRecordId}");
}
return Json(result); return Json(result);
} }
[HttpPost] [HttpPost]
@@ -715,6 +732,61 @@ namespace CarCareTracker.Controllers
var result = _config.SaveUserConfig(User, currentConfig); var result = _config.SaveUserConfig(User, currentConfig);
return Json(result); return Json(result);
} }
[HttpPost]
public IActionResult GetGasRecordsEditModal(List<int> recordIds)
{
return PartialView("_GasRecordsModal", new GasRecordEditModel { RecordIds = recordIds });
}
[HttpPost]
public IActionResult SaveMultipleGasRecords(GasRecordEditModel editModel)
{
var dateIsEdited = editModel.EditRecord.Date != default;
var mileageIsEdited = editModel.EditRecord.Mileage != default;
var consumptionIsEdited = editModel.EditRecord.Gallons != default;
var costIsEdited = editModel.EditRecord.Cost != default;
var noteIsEdited = !string.IsNullOrWhiteSpace(editModel.EditRecord.Notes);
var tagsIsEdited = editModel.EditRecord.Tags.Any();
//handle clear overrides
if (tagsIsEdited && editModel.EditRecord.Tags.Contains("---"))
{
editModel.EditRecord.Tags = new List<string>();
}
if (noteIsEdited && editModel.EditRecord.Notes == "---")
{
editModel.EditRecord.Notes = "";
}
bool result = false;
foreach (int recordId in editModel.RecordIds)
{
var existingRecord = _gasRecordDataAccess.GetGasRecordById(recordId);
if (dateIsEdited)
{
existingRecord.Date = editModel.EditRecord.Date;
}
if (consumptionIsEdited)
{
existingRecord.Gallons = editModel.EditRecord.Gallons;
}
if (costIsEdited)
{
existingRecord.Cost = editModel.EditRecord.Cost;
}
if (mileageIsEdited)
{
existingRecord.Mileage = editModel.EditRecord.Mileage;
}
if (noteIsEdited)
{
existingRecord.Notes = editModel.EditRecord.Notes;
}
if (tagsIsEdited)
{
existingRecord.Tags = editModel.EditRecord.Tags;
}
result = _gasRecordDataAccess.SaveGasRecordToVehicle(existingRecord);
}
return Json(result);
}
#endregion #endregion
#region "Service Records" #region "Service Records"
[TypeFilter(typeof(CollaboratorFilter))] [TypeFilter(typeof(CollaboratorFilter))]
@@ -758,6 +830,10 @@ namespace CarCareTracker.Controllers
PushbackRecurringReminderRecordWithChecks(serviceRecord.ReminderRecordId); PushbackRecurringReminderRecordWithChecks(serviceRecord.ReminderRecordId);
} }
var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord()); var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), serviceRecord.VehicleId, User.Identity.Name, $"{(serviceRecord.Id == default ? "Created" : "Edited")} Service Record - Description: {serviceRecord.Description}");
}
return Json(result); return Json(result);
} }
[HttpGet] [HttpGet]
@@ -790,6 +866,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteServiceRecordById(int serviceRecordId) public IActionResult DeleteServiceRecordById(int serviceRecordId)
{ {
var result = _serviceRecordDataAccess.DeleteServiceRecordById(serviceRecordId); var result = _serviceRecordDataAccess.DeleteServiceRecordById(serviceRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Service Record - Id: {serviceRecordId}");
}
return Json(result); return Json(result);
} }
#endregion #endregion
@@ -835,6 +915,10 @@ namespace CarCareTracker.Controllers
PushbackRecurringReminderRecordWithChecks(collisionRecord.ReminderRecordId); PushbackRecurringReminderRecordWithChecks(collisionRecord.ReminderRecordId);
} }
var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord()); var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), collisionRecord.VehicleId, User.Identity.Name, $"{(collisionRecord.Id == default ? "Created" : "Edited")} Repair Record - Description: {collisionRecord.Description}");
}
return Json(result); return Json(result);
} }
[HttpGet] [HttpGet]
@@ -867,6 +951,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteCollisionRecordById(int collisionRecordId) public IActionResult DeleteCollisionRecordById(int collisionRecordId)
{ {
var result = _collisionRecordDataAccess.DeleteCollisionRecordById(collisionRecordId); var result = _collisionRecordDataAccess.DeleteCollisionRecordById(collisionRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Repair Record - Id: {collisionRecordId}");
}
return Json(result); return Json(result);
} }
#endregion #endregion
@@ -938,6 +1026,10 @@ namespace CarCareTracker.Controllers
PushbackRecurringReminderRecordWithChecks(taxRecord.ReminderRecordId); PushbackRecurringReminderRecordWithChecks(taxRecord.ReminderRecordId);
} }
var result = _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord.ToTaxRecord()); var result = _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord.ToTaxRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), taxRecord.VehicleId, User.Identity.Name, $"{(taxRecord.Id == default ? "Created" : "Edited")} Tax Record - Description: {taxRecord.Description}");
}
return Json(result); return Json(result);
} }
[HttpGet] [HttpGet]
@@ -971,6 +1063,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteTaxRecordById(int taxRecordId) public IActionResult DeleteTaxRecordById(int taxRecordId)
{ {
var result = _taxRecordDataAccess.DeleteTaxRecordById(taxRecordId); var result = _taxRecordDataAccess.DeleteTaxRecordById(taxRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Tax Record - Id: {taxRecordId}");
}
return Json(result); return Json(result);
} }
#endregion #endregion
@@ -1543,6 +1639,10 @@ namespace CarCareTracker.Controllers
public IActionResult SaveReminderRecordToVehicleId(ReminderRecordInput reminderRecord) public IActionResult SaveReminderRecordToVehicleId(ReminderRecordInput reminderRecord)
{ {
var result = _reminderRecordDataAccess.SaveReminderRecordToVehicle(reminderRecord.ToReminderRecord()); var result = _reminderRecordDataAccess.SaveReminderRecordToVehicle(reminderRecord.ToReminderRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), reminderRecord.VehicleId, User.Identity.Name, $"{(reminderRecord.Id == default ? "Created" : "Edited")} Reminder - Description: {reminderRecord.Description}");
}
return Json(result); return Json(result);
} }
[HttpPost] [HttpPost]
@@ -1583,6 +1683,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteReminderRecordById(int reminderRecordId) public IActionResult DeleteReminderRecordById(int reminderRecordId)
{ {
var result = _reminderRecordDataAccess.DeleteReminderRecordById(reminderRecordId); var result = _reminderRecordDataAccess.DeleteReminderRecordById(reminderRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Reminder - Id: {reminderRecordId}");
}
return Json(result); return Json(result);
} }
#endregion #endregion
@@ -1628,6 +1732,10 @@ namespace CarCareTracker.Controllers
PushbackRecurringReminderRecordWithChecks(upgradeRecord.ReminderRecordId); PushbackRecurringReminderRecordWithChecks(upgradeRecord.ReminderRecordId);
} }
var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord()); var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), upgradeRecord.VehicleId, User.Identity.Name, $"{(upgradeRecord.Id == default ? "Created" : "Edited")} Upgrade Record - Description: {upgradeRecord.Description}");
}
return Json(result); return Json(result);
} }
[HttpGet] [HttpGet]
@@ -1660,6 +1768,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteUpgradeRecordById(int upgradeRecordId) public IActionResult DeleteUpgradeRecordById(int upgradeRecordId)
{ {
var result = _upgradeRecordDataAccess.DeleteUpgradeRecordById(upgradeRecordId); var result = _upgradeRecordDataAccess.DeleteUpgradeRecordById(upgradeRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Upgrade Record - Id: {upgradeRecordId}");
}
return Json(result); return Json(result);
} }
#endregion #endregion
@@ -1684,6 +1796,10 @@ namespace CarCareTracker.Controllers
public IActionResult SaveNoteToVehicleId(Note note) public IActionResult SaveNoteToVehicleId(Note note)
{ {
var result = _noteDataAccess.SaveNoteToVehicle(note); var result = _noteDataAccess.SaveNoteToVehicle(note);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), note.VehicleId, User.Identity.Name, $"{(note.Id == default ? "Created" : "Edited")} Note - Description: {note.Description}");
}
return Json(result); return Json(result);
} }
[HttpGet] [HttpGet]
@@ -1701,6 +1817,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteNoteById(int noteId) public IActionResult DeleteNoteById(int noteId)
{ {
var result = _noteDataAccess.DeleteNoteById(noteId); var result = _noteDataAccess.DeleteNoteById(noteId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Note - Id: {noteId}");
}
return Json(result); return Json(result);
} }
[HttpPost] [HttpPost]
@@ -1822,6 +1942,10 @@ namespace CarCareTracker.Controllers
//move files from temp. //move files from temp.
supplyRecord.Files = supplyRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); supplyRecord.Files = supplyRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
var result = _supplyRecordDataAccess.SaveSupplyRecordToVehicle(supplyRecord.ToSupplyRecord()); var result = _supplyRecordDataAccess.SaveSupplyRecordToVehicle(supplyRecord.ToSupplyRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), supplyRecord.VehicleId, User.Identity.Name, $"{(supplyRecord.Id == default ? "Created" : "Edited")} Supply Record - Description: {supplyRecord.Description}");
}
return Json(result); return Json(result);
} }
[HttpGet] [HttpGet]
@@ -1856,6 +1980,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteSupplyRecordById(int supplyRecordId) public IActionResult DeleteSupplyRecordById(int supplyRecordId)
{ {
var result = _supplyRecordDataAccess.DeleteSupplyRecordById(supplyRecordId); var result = _supplyRecordDataAccess.DeleteSupplyRecordById(supplyRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Supply Record - Id: {supplyRecordId}");
}
return Json(result); return Json(result);
} }
#endregion #endregion
@@ -1883,6 +2011,10 @@ namespace CarCareTracker.Controllers
planRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(planRecord.Supplies, DateTime.Parse(planRecord.DateCreated), planRecord.Description); planRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(planRecord.Supplies, DateTime.Parse(planRecord.DateCreated), planRecord.Description);
} }
var result = _planRecordDataAccess.SavePlanRecordToVehicle(planRecord.ToPlanRecord()); var result = _planRecordDataAccess.SavePlanRecordToVehicle(planRecord.ToPlanRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), planRecord.VehicleId, User.Identity.Name, $"{(planRecord.Id == default ? "Created" : "Edited")} Plan Record - Description: {planRecord.Description}");
}
return Json(result); return Json(result);
} }
[HttpPost] [HttpPost]
@@ -2068,6 +2200,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeletePlanRecordById(int planRecordId) public IActionResult DeletePlanRecordById(int planRecordId)
{ {
var result = _planRecordDataAccess.DeletePlanRecordById(planRecordId); var result = _planRecordDataAccess.DeletePlanRecordById(planRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Plan Record - Id: {planRecordId}");
}
return Json(result); return Json(result);
} }
#endregion #endregion
@@ -2107,6 +2243,10 @@ namespace CarCareTracker.Controllers
//move files from temp. //move files from temp.
odometerRecord.Files = odometerRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); odometerRecord.Files = odometerRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList();
var result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord.ToOdometerRecord()); var result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(odometerRecord.ToOdometerRecord());
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), odometerRecord.VehicleId, User.Identity.Name, $"{(odometerRecord.Id == default ? "Created" : "Edited")} Odometer Record - Mileage: {odometerRecord.Mileage.ToString()}");
}
return Json(result); return Json(result);
} }
[HttpGet] [HttpGet]
@@ -2187,6 +2327,10 @@ namespace CarCareTracker.Controllers
public IActionResult DeleteOdometerRecordById(int odometerRecordId) public IActionResult DeleteOdometerRecordById(int odometerRecordId)
{ {
var result = _odometerRecordDataAccess.DeleteOdometerRecordById(odometerRecordId); var result = _odometerRecordDataAccess.DeleteOdometerRecordById(odometerRecordId);
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted Odometer Record - Id: {odometerRecordId}");
}
return Json(result); return Json(result);
} }
#endregion #endregion
@@ -2288,6 +2432,10 @@ namespace CarCareTracker.Controllers
} }
} }
} }
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Moved multiple {source.ToString()} to {destination.ToString()} - Ids: {string.Join(",", recordIds)}");
}
return Json(result); return Json(result);
} }
public IActionResult DeleteRecords(List<int> recordIds, ImportMode importMode) public IActionResult DeleteRecords(List<int> recordIds, ImportMode importMode)
@@ -2326,6 +2474,69 @@ namespace CarCareTracker.Controllers
break; break;
} }
} }
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Deleted multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)}");
}
return Json(result);
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpPost]
public IActionResult AdjustRecordsOdometer(List<int> recordIds, int vehicleId, ImportMode importMode)
{
bool result = false;
//get vehicle's odometer adjustments
var vehicleData = _dataAccess.GetVehicleById(vehicleId);
foreach (int recordId in recordIds)
{
switch (importMode)
{
case ImportMode.ServiceRecord:
{
var existingRecord = _serviceRecordDataAccess.GetServiceRecordById(recordId);
existingRecord.Mileage += int.Parse(vehicleData.OdometerDifference);
existingRecord.Mileage = decimal.ToInt32(existingRecord.Mileage * decimal.Parse(vehicleData.OdometerMultiplier, NumberStyles.Any));
result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(existingRecord);
}
break;
case ImportMode.RepairRecord:
{
var existingRecord = _collisionRecordDataAccess.GetCollisionRecordById(recordId);
existingRecord.Mileage += int.Parse(vehicleData.OdometerDifference);
existingRecord.Mileage = decimal.ToInt32(existingRecord.Mileage * decimal.Parse(vehicleData.OdometerMultiplier, NumberStyles.Any));
result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(existingRecord);
}
break;
case ImportMode.UpgradeRecord:
{
var existingRecord = _upgradeRecordDataAccess.GetUpgradeRecordById(recordId);
existingRecord.Mileage += int.Parse(vehicleData.OdometerDifference);
existingRecord.Mileage = decimal.ToInt32(existingRecord.Mileage * decimal.Parse(vehicleData.OdometerMultiplier, NumberStyles.Any));
result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(existingRecord);
}
break;
case ImportMode.GasRecord:
{
var existingRecord = _gasRecordDataAccess.GetGasRecordById(recordId);
existingRecord.Mileage += int.Parse(vehicleData.OdometerDifference);
existingRecord.Mileage = decimal.ToInt32(existingRecord.Mileage * decimal.Parse(vehicleData.OdometerMultiplier, NumberStyles.Any));
result = _gasRecordDataAccess.SaveGasRecordToVehicle(existingRecord);
}
break;
case ImportMode.OdometerRecord:
{
var existingRecord = _odometerRecordDataAccess.GetOdometerRecordById(recordId);
existingRecord.Mileage += int.Parse(vehicleData.OdometerDifference);
existingRecord.Mileage = decimal.ToInt32(existingRecord.Mileage * decimal.Parse(vehicleData.OdometerMultiplier, NumberStyles.Any));
result = _odometerRecordDataAccess.SaveOdometerRecordToVehicle(existingRecord);
}
break;
}
}
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Adjusted odometer for multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)}");
}
return Json(result); return Json(result);
} }
public IActionResult DuplicateRecords(List<int> recordIds, ImportMode importMode) public IActionResult DuplicateRecords(List<int> recordIds, ImportMode importMode)
@@ -2400,6 +2611,10 @@ namespace CarCareTracker.Controllers
break; break;
} }
} }
if (result)
{
StaticHelper.NotifyAsync(_config.GetWebHookUrl(), 0, User.Identity.Name, $"Duplicated multiple {importMode.ToString()} - Ids: {string.Join(",", recordIds)}");
}
return Json(result); return Json(result);
} }
[HttpPost] [HttpPost]

View File

@@ -12,6 +12,7 @@ namespace CarCareTracker.Helper
UserConfig GetUserConfig(ClaimsPrincipal user); UserConfig GetUserConfig(ClaimsPrincipal user);
bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData); bool SaveUserConfig(ClaimsPrincipal user, UserConfig configData);
bool AuthenticateRootUser(string username, string password); bool AuthenticateRootUser(string username, string password);
string GetWebHookUrl();
string GetMOTD(); string GetMOTD();
string GetLogoUrl(); string GetLogoUrl();
string GetServerLanguage(); string GetServerLanguage();
@@ -33,6 +34,15 @@ namespace CarCareTracker.Helper
_userConfig = userConfig; _userConfig = userConfig;
_cache = memoryCache; _cache = memoryCache;
} }
public string GetWebHookUrl()
{
var webhook = _config["LUBELOGGER_WEBHOOK"];
if (string.IsNullOrWhiteSpace(webhook))
{
webhook = "";
}
return webhook;
}
public string GetMOTD() public string GetMOTD()
{ {
var motd = _config["LUBELOGGER_MOTD"]; var motd = _config["LUBELOGGER_MOTD"];

View File

@@ -93,6 +93,7 @@ namespace CarCareTracker.Helper
//copy over images and documents. //copy over images and documents.
var imagePath = Path.Combine(tempPath, "images"); var imagePath = Path.Combine(tempPath, "images");
var documentPath = Path.Combine(tempPath, "documents"); var documentPath = Path.Combine(tempPath, "documents");
var translationPath = Path.Combine(tempPath, "translations");
var dataPath = Path.Combine(tempPath, StaticHelper.DbName); var dataPath = Path.Combine(tempPath, StaticHelper.DbName);
var configPath = Path.Combine(tempPath, StaticHelper.UserConfigPath); var configPath = Path.Combine(tempPath, StaticHelper.UserConfigPath);
if (Directory.Exists(imagePath)) if (Directory.Exists(imagePath))
@@ -139,6 +140,28 @@ namespace CarCareTracker.Helper
File.Copy(file, $"{existingPath}/{Path.GetFileName(file)}", true); File.Copy(file, $"{existingPath}/{Path.GetFileName(file)}", true);
} }
} }
if (Directory.Exists(translationPath))
{
var existingPath = Path.Combine(_webEnv.WebRootPath, "translations");
if (!Directory.Exists(existingPath))
{
Directory.CreateDirectory(existingPath);
}
else if (clearExisting)
{
var filesToDelete = Directory.GetFiles(existingPath);
foreach (string file in filesToDelete)
{
File.Delete(file);
}
}
//copy each files from temp folder to newPath
var filesToUpload = Directory.GetFiles(translationPath);
foreach (string file in filesToUpload)
{
File.Copy(file, $"{existingPath}/{Path.GetFileName(file)}", true);
}
}
if (File.Exists(dataPath)) if (File.Exists(dataPath))
{ {
//data path will always exist as it is created on startup if not. //data path will always exist as it is created on startup if not.
@@ -191,6 +214,7 @@ namespace CarCareTracker.Helper
var tempPath = Path.Combine(_webEnv.WebRootPath, $"temp/{folderName}"); var tempPath = Path.Combine(_webEnv.WebRootPath, $"temp/{folderName}");
var imagePath = Path.Combine(_webEnv.WebRootPath, "images"); var imagePath = Path.Combine(_webEnv.WebRootPath, "images");
var documentPath = Path.Combine(_webEnv.WebRootPath, "documents"); var documentPath = Path.Combine(_webEnv.WebRootPath, "documents");
var translationPath = Path.Combine(_webEnv.WebRootPath, "translations");
var dataPath = StaticHelper.DbName; var dataPath = StaticHelper.DbName;
var configPath = StaticHelper.UserConfigPath; var configPath = StaticHelper.UserConfigPath;
if (!Directory.Exists(tempPath)) if (!Directory.Exists(tempPath))
@@ -215,6 +239,16 @@ namespace CarCareTracker.Helper
File.Copy(file, $"{newPath}/{Path.GetFileName(file)}"); File.Copy(file, $"{newPath}/{Path.GetFileName(file)}");
} }
} }
if (Directory.Exists(translationPath))
{
var files = Directory.GetFiles(translationPath);
foreach(var file in files)
{
var newPath = Path.Combine(tempPath, "translations");
Directory.CreateDirectory(newPath);
File.Copy(file, $"{newPath}/{Path.GetFileName(file)}");
}
}
if (File.Exists(dataPath)) if (File.Exists(dataPath))
{ {
var newPath = Path.Combine(tempPath, "data"); var newPath = Path.Combine(tempPath, "data");

View File

@@ -8,7 +8,7 @@ namespace CarCareTracker.Helper
/// </summary> /// </summary>
public static class StaticHelper public static class StaticHelper
{ {
public static string VersionNumber = "1.2.6"; public static string VersionNumber = "1.2.7";
public static string DbName = "data/cartracker.db"; public static string DbName = "data/cartracker.db";
public static string UserConfigPath = "config/userConfig.json"; public static string UserConfigPath = "config/userConfig.json";
public static string GenericErrorMessage = "An error occurred, please try again later"; public static string GenericErrorMessage = "An error occurred, please try again later";
@@ -244,5 +244,20 @@ namespace CarCareTracker.Helper
var motd = config["LUBELOGGER_MOTD"] ?? "Not Configured"; var motd = config["LUBELOGGER_MOTD"] ?? "Not Configured";
Console.WriteLine($"Message Of The Day: {motd}"); Console.WriteLine($"Message Of The Day: {motd}");
} }
public static async void NotifyAsync(string webhookURL, int vehicleId, string username, string action)
{
if (string.IsNullOrWhiteSpace(webhookURL))
{
return;
}
var httpClient = new HttpClient();
var httpParams = new Dictionary<string, string>
{
{ "vehicleId", vehicleId.ToString() },
{ "username", username },
{ "action", action },
};
httpClient.PostAsJsonAsync(webhookURL, httpParams);
}
} }
} }

View File

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

View File

@@ -14,5 +14,14 @@
public bool UseHours { get; set; } = false; public bool UseHours { get; set; } = false;
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>(); public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
public List<string> Tags { get; set; } = new List<string>(); 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>
public string OdometerMultiplier { get; set; } = "1";
/// <summary>
/// Primarily used for vehicles where the odometer does not reflect actual mileage.
/// </summary>
public string OdometerDifference { get; set; } = "0";
} }
} }

View File

@@ -12,8 +12,8 @@
ViewData["Title"] = "LubeLogger"; ViewData["Title"] = "LubeLogger";
} }
@section Scripts { @section Scripts {
<script src="~/js/garage.js"></script> <script src="~/js/garage.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/supplyrecord.js"></script> <script src="~/js/supplyrecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/lib/drawdown/drawdown.js"></script> <script src="~/lib/drawdown/drawdown.js"></script>
} }
<div class="lubelogger-mobile-nav" onclick="hideMobileNav()"> <div class="lubelogger-mobile-nav" onclick="hideMobileNav()">
@@ -119,7 +119,7 @@
</div> </div>
<div class="modal fade" id="addVehicleModal" tabindex="-1" role="dialog"> <div class="modal fade" id="addVehicleModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document"> <div class="modal-dialog modal-lg" role="document">
<div class="modal-content" id="addVehicleModalContent"> <div class="modal-content" id="addVehicleModalContent">
</div> </div>
</div> </div>

View File

@@ -402,6 +402,7 @@
function restoreBackup(event) { function restoreBackup(event) {
let formData = new FormData(); let formData = new FormData();
formData.append("file", event.files[0]); formData.append("file", event.files[0]);
console.log('LubeLogger - DB Restoration Started');
sloader.show(); sloader.show();
$.ajax({ $.ajax({
url: "/Files/HandleFileUpload", url: "/Files/HandleFileUpload",
@@ -415,16 +416,21 @@
$.post('/Files/RestoreBackup', { fileName: response }, function (data) { $.post('/Files/RestoreBackup', { fileName: response }, function (data) {
sloader.hide(); sloader.hide();
if (data) { if (data) {
console.log('LubeLogger - DB Restoration Completed');
successToast("Backup Restored"); successToast("Backup Restored");
setTimeout(function () { window.location.href = '/Home/Index' }, 500); setTimeout(function () { window.location.href = '/Home/Index' }, 500);
} else { } else {
errorToast(genericErrorMessage()); errorToast(genericErrorMessage());
console.log('LubeLogger - DB Restoration Failed - Failed to process backup file.');
} }
}); });
} else {
console.log('LubeLogger - DB Restoration Failed - Failed to upload backup file.');
} }
}, },
error: function () { error: function () {
sloader.hide(); sloader.hide();
console.log('LubeLogger - DB Restoration Failed - Request failed to reach backend, please check file size.');
errorToast("An error has occurred, please check the file size and try again later."); errorToast("An error has occurred, please check the file size and try again later.");
} }
}); });

View File

@@ -9,7 +9,7 @@
ViewData["Title"] = "LubeLogger - Login"; ViewData["Title"] = "LubeLogger - Login";
} }
@section Scripts { @section Scripts {
<script src="~/js/login.js"></script> <script src="~/js/login.js?v=@StaticHelper.VersionNumber"></script>
} }
<div class="container d-flex align-items-center justify-content-center" style="height:100vh"> <div class="container d-flex align-items-center justify-content-center" style="height:100vh">
<div class="row"> <div class="row">

View File

@@ -11,7 +11,7 @@
ViewData["Title"] = "LubeLogger - Login"; ViewData["Title"] = "LubeLogger - Login";
} }
@section Scripts { @section Scripts {
<script src="~/js/login.js"></script> <script src="~/js/login.js?v=@StaticHelper.VersionNumber"></script>
} }
<div class="container d-flex align-items-center justify-content-center" style="height:100vh"> <div class="container d-flex align-items-center justify-content-center" style="height:100vh">
<div class="row"> <div class="row">

View File

@@ -10,7 +10,7 @@
ViewData["Title"] = "LubeLogger - Register"; ViewData["Title"] = "LubeLogger - Register";
} }
@section Scripts { @section Scripts {
<script src="~/js/login.js"></script> <script src="~/js/login.js?v=@StaticHelper.VersionNumber"></script>
} }
<div class="container d-flex align-items-center justify-content-center" style="height:100vh"> <div class="container d-flex align-items-center justify-content-center" style="height:100vh">
<div class="row"> <div class="row">

View File

@@ -9,7 +9,7 @@
ViewData["Title"] = "LubeLogger - Register"; ViewData["Title"] = "LubeLogger - Register";
} }
@section Scripts { @section Scripts {
<script src="~/js/login.js"></script> <script src="~/js/login.js?v=@StaticHelper.VersionNumber"></script>
} }
<div class="container d-flex align-items-center justify-content-center" style="height:100vh"> <div class="container d-flex align-items-center justify-content-center" style="height:100vh">
<div class="row"> <div class="row">

View File

@@ -9,7 +9,7 @@
ViewData["Title"] = "LubeLogger - Register"; ViewData["Title"] = "LubeLogger - Register";
} }
@section Scripts { @section Scripts {
<script src="~/js/login.js"></script> <script src="~/js/login.js?v=@StaticHelper.VersionNumber"></script>
} }
<div class="container d-flex align-items-center justify-content-center" style="height:100vh"> <div class="container d-flex align-items-center justify-content-center" style="height:100vh">
<div class="row"> <div class="row">

View File

@@ -45,12 +45,12 @@
<link rel="apple-touch-startup-image" href="~/defaults/lubelogger_launch.png" /> <link rel="apple-touch-startup-image" href="~/defaults/lubelogger_launch.png" />
<link rel="manifest" href="~/manifest.json"> <link rel="manifest" href="~/manifest.json">
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/shared.js"></script> <script src="~/js/shared.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/lib/bootstrap-datepicker/js/bootstrap-datepicker.min.js"></script> <script src="~/lib/bootstrap-datepicker/js/bootstrap-datepicker.min.js"></script>
<script src="~/lib/bootstrap-tagsinput/bootstrap-tagsinput.js"></script> <script src="~/lib/bootstrap-tagsinput/bootstrap-tagsinput.js"></script>
<script src="~/sweetalert/sweetalert2.all.min.js"></script> <script src="~/sweetalert/sweetalert2.all.min.js"></script>
<script src="~/js/loader.js"></script> <script src="~/js/loader.js?v=@StaticHelper.VersionNumber"></script>
<script> <script>
function getGlobalConfig() { function getGlobalConfig() {
return { return {

View File

@@ -10,18 +10,18 @@
} }
@model Vehicle @model Vehicle
@section Scripts { @section Scripts {
<script src="~/js/vehicle.js"></script> <script src="~/js/vehicle.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/servicerecord.js"></script> <script src="~/js/servicerecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/gasrecord.js"></script> <script src="~/js/gasrecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/collisionrecord.js"></script> <script src="~/js/collisionrecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/taxrecord.js"></script> <script src="~/js/taxrecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/reminderrecord.js"></script> <script src="~/js/reminderrecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/upgraderecord.js"></script> <script src="~/js/upgraderecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/note.js"></script> <script src="~/js/note.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/reports.js"></script> <script src="~/js/reports.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/supplyrecord.js"></script> <script src="~/js/supplyrecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/planrecord.js"></script> <script src="~/js/planrecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/js/odometerrecord.js"></script> <script src="~/js/odometerrecord.js?v=@StaticHelper.VersionNumber"></script>
<script src="~/lib/chart-js/chart.umd.js"></script> <script src="~/lib/chart-js/chart.umd.js"></script>
<script src="~/lib/drawdown/drawdown.js"></script> <script src="~/lib/drawdown/drawdown.js"></script>
} }
@@ -139,7 +139,7 @@
</div> </div>
</div> </div>
<div class="modal fade" id="editVehicleModal" tabindex="-1" role="dialog"> <div class="modal fade" id="editVehicleModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document"> <div class="modal-dialog modal-lg" role="document">
<div class="modal-content" id="editVehicleModalContent"> <div class="modal-content" id="editVehicleModalContent">
</div> </div>
</div> </div>
@@ -169,7 +169,12 @@
</div> </div>
<script> <script>
function GetVehicleId() { function GetVehicleId() {
return { vehicleId: @Model.Id}; return {
vehicleId: @Model.Id,
hasOdometerAdjustment: @Model.HasOdometerAdjustment.ToString().ToLower(),
odometerDifference: decodeHTMLEntities('@Model.OdometerDifference'),
odometerMultiplier: decodeHTMLEntities('@Model.OdometerMultiplier')
};
} }
function GetDefaultTab() { function GetDefaultTab() {
return { tab: "@userConfig.DefaultTab" }; return { tab: "@userConfig.DefaultTab" };

View File

@@ -159,6 +159,8 @@
<li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'RepairRecord')">@translator.Translate(userLanguage, "Delete")</a></li> <li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'RepairRecord')">@translator.Translate(userLanguage, "Delete")</a></li>
<li><hr class="context-menu-active-multiple dropdown-divider"></li> <li><hr class="context-menu-active-multiple dropdown-divider"></li>
<li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li> <li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li>
<li><hr class="context-menu-odometer-adjustment dropdown-divider"></li>
<li><a class="context-menu-odometer-adjustment dropdown-item" href="#" onclick="adjustRecordsOdometer(selectedRow, 'RepairRecord')">@translator.Translate(userLanguage, "Adjust Odometer")</a></li>
</ul> </ul>
@if (userColumnPreferences.Any()) @if (userColumnPreferences.Any())
{ {

View File

@@ -219,9 +219,12 @@
<ul class="table-context-menu dropdown-menu" style="display:none;"> <ul class="table-context-menu dropdown-menu" style="display:none;">
<li><a class="context-menu-multiple context-menu-select-all dropdown-item" href="#" onclick="selectAllRows()">@translator.Translate(userLanguage, "Select All")</a></li> <li><a class="context-menu-multiple context-menu-select-all dropdown-item" href="#" onclick="selectAllRows()">@translator.Translate(userLanguage, "Select All")</a></li>
<li><a class="context-menu-multiple context-menu-deselect-all dropdown-item" href="#" onclick="clearSelectedRows()">@translator.Translate(userLanguage, "Deselect All")</a></li> <li><a class="context-menu-multiple context-menu-deselect-all dropdown-item" href="#" onclick="clearSelectedRows()">@translator.Translate(userLanguage, "Deselect All")</a></li>
<li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="editMultipleGasRecords(selectedRow)">@translator.Translate(userLanguage, "Edit Multiple")</a></li>
<li><hr class="context-menu-multiple dropdown-divider"></li> <li><hr class="context-menu-multiple dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="duplicateRecords(selectedRow, 'GasRecord')">@translator.Translate(userLanguage, "Duplicate")</a></li> <li><a class="dropdown-item" href="#" onclick="duplicateRecords(selectedRow, 'GasRecord')">@translator.Translate(userLanguage, "Duplicate")</a></li>
<li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'GasRecord')">@translator.Translate(userLanguage, "Delete")</a></li> <li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'GasRecord')">@translator.Translate(userLanguage, "Delete")</a></li>
<li><hr class="context-menu-odometer-adjustment dropdown-divider"></li>
<li><a class="context-menu-odometer-adjustment dropdown-item" href="#" onclick="adjustRecordsOdometer(selectedRow, 'GasRecord')">@translator.Translate(userLanguage, "Adjust Odometer")</a></li>
</ul> </ul>
@if (userColumnPreferences.Any()) @if (userColumnPreferences.Any())
{ {

View File

@@ -0,0 +1,50 @@
@using CarCareTracker.Helper
@inject IConfigHelper config
@inject ITranslationHelper translator
@model GasRecordEditModel
@{
var userConfig = config.GetUserConfig(User);
var userLanguage = userConfig.UserLanguage;
}
<div class="modal-header">
<h5 class="modal-title">@translator.Translate(userLanguage,"Edit Multiple Gas Records")</h5>
<button type="button" class="btn-close" onclick="hideAddGasRecordModal()" aria-label="Close"></button>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<div class="row">
<div class="col-md-6 col-12">
<label for="gasRecordDate">@translator.Translate(userLanguage, "Date")</label>
<div class="input-group">
<input type="text" id="gasRecordDate" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
<span class="input-group-text"><i class="bi bi-calendar-event"></i></span>
</div>
<label for="gasRecordMileage">@translator.Translate(userLanguage, "Odometer")</label>
<input type="number" inputmode="numeric" id="gasRecordMileage" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
<label for="gasRecordConsumption">@translator.Translate(userLanguage, "Fuel Consumption")</label>
<input type="text" inputmode="decimal" id="gasRecordConsumption" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
<label for="gasRecordCost">@translator.Translate(userLanguage, "Cost")</label>
<input type="text" inputmode="decimal" id="gasRecordCost" class="form-control" placeholder="@translator.Translate(userLanguage,"(multiple)")">
<label for="gasRecordTag">@translator.Translate(userLanguage, "Tags(use --- to clear all existing tags)")</label>
<select multiple class="form-select" id="gasRecordTag"></select>
</div>
<div class="col-md-6 col-12">
<label for="gasRecordNotes">@translator.Translate(userLanguage, "Notes(use --- to clear all existing notes)")<a class="link-underline link-underline-opacity-0" onclick="showLinks(this)"><i class="bi bi-markdown ms-2"></i></a></label>
<textarea id="gasRecordNotes" class="form-control" rows="5"></textarea>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="hideAddGasRecordModal()">@translator.Translate(userLanguage, "Cancel")</button>
<button type="button" class="btn btn-primary" onclick="saveMultipleGasRecordsToVehicle()">@translator.Translate(userLanguage, "Edit")</button>
</div>
<script>
var recordsToEdit = [];
@foreach(int recordId in Model.RecordIds)
{
@:recordsToEdit.push(@recordId);
}
</script>

View File

@@ -155,6 +155,8 @@
<li><hr class="context-menu-multiple dropdown-divider"></li> <li><hr class="context-menu-multiple dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="duplicateRecords(selectedRow, 'OdometerRecord')">@translator.Translate(userLanguage, "Duplicate")</a></li> <li><a class="dropdown-item" href="#" onclick="duplicateRecords(selectedRow, 'OdometerRecord')">@translator.Translate(userLanguage, "Duplicate")</a></li>
<li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'OdometerRecord')">@translator.Translate(userLanguage, "Delete")</a></li> <li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'OdometerRecord')">@translator.Translate(userLanguage, "Delete")</a></li>
<li><hr class="context-menu-odometer-adjustment dropdown-divider"></li>
<li><a class="context-menu-odometer-adjustment dropdown-item" href="#" onclick="adjustRecordsOdometer(selectedRow, 'OdometerRecord')">@translator.Translate(userLanguage, "Adjust Odometer")</a></li>
</ul> </ul>
@if (userColumnPreferences.Any()) @if (userColumnPreferences.Any())
{ {

View File

@@ -159,6 +159,8 @@
<li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'ServiceRecord')">@translator.Translate(userLanguage, "Delete")</a></li> <li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'ServiceRecord')">@translator.Translate(userLanguage, "Delete")</a></li>
<li><hr class="context-menu-active-multiple dropdown-divider"></li> <li><hr class="context-menu-active-multiple dropdown-divider"></li>
<li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li> <li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li>
<li><hr class="context-menu-odometer-adjustment dropdown-divider"></li>
<li><a class="context-menu-odometer-adjustment dropdown-item" href="#" onclick="adjustRecordsOdometer(selectedRow, 'ServiceRecord')">@translator.Translate(userLanguage, "Adjust Odometer")</a></li>
</ul> </ul>
@if (userColumnPreferences.Any()) @if (userColumnPreferences.Any())
{ {

View File

@@ -158,6 +158,8 @@
<li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'UpgradeRecord')">@translator.Translate(userLanguage, "Delete")</a></li> <li><a class="dropdown-item" href="#" onclick="deleteRecords(selectedRow, 'UpgradeRecord')">@translator.Translate(userLanguage, "Delete")</a></li>
<li><hr class="context-menu-active-multiple dropdown-divider"></li> <li><hr class="context-menu-active-multiple dropdown-divider"></li>
<li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li> <li><a class="context-menu-active-multiple dropdown-item" href="#" onclick="getRecordsDeltaStats(selectedRow)">@translator.Translate(userLanguage, "Statistics")</a></li>
<li><hr class="context-menu-odometer-adjustment dropdown-divider"></li>
<li><a class="context-menu-odometer-adjustment dropdown-item" href="#" onclick="adjustRecordsOdometer(selectedRow, 'UpgradeRecord')">@translator.Translate(userLanguage, "Adjust Odometer")</a></li>
</ul> </ul>
@if (userColumnPreferences.Any()) @if (userColumnPreferences.Any())
{ {

View File

@@ -26,50 +26,69 @@
<div class="modal-body"> <div class="modal-body">
<form class="form-inline"> <form class="form-inline">
<div class="form-group"> <div class="form-group">
<label for="inputYear">@translator.Translate(userLanguage, "Year")</label> <div class="row">
<input type="number" inputmode="numeric" id="inputYear" class="form-control" placeholder="@translator.Translate(userLanguage, "Year(must be after 1900)")" value="@(isNew ? "" : Model.Year)"> <div class="col-12 col-md-6">
<label for="inputMake">@translator.Translate(userLanguage, "Make")</label> <label for="inputYear">@translator.Translate(userLanguage, "Year")</label>
<input type="text" id="inputMake" class="form-control" placeholder="@translator.Translate(userLanguage, "Make")" value="@Model.Make"> <input type="number" inputmode="numeric" id="inputYear" class="form-control" placeholder="@translator.Translate(userLanguage, "Year(must be after 1900)")" value="@(isNew ? "" : Model.Year)">
<label for="inputModel">@translator.Translate(userLanguage, "Model")</label> <label for="inputMake">@translator.Translate(userLanguage, "Make")</label>
<input type="text" id="inputModel" class="form-control" placeholder="@translator.Translate(userLanguage, "Model")" value="@Model.Model"> <input type="text" id="inputMake" class="form-control" placeholder="@translator.Translate(userLanguage, "Make")" value="@Model.Make">
<label for="inputLicensePlate">@translator.Translate(userLanguage, "License Plate")</label> <label for="inputModel">@translator.Translate(userLanguage, "Model")</label>
<input type="text" id="inputLicensePlate" class="form-control" placeholder="@translator.Translate(userLanguage, "License Plate")" value="@Model.LicensePlate"> <input type="text" id="inputModel" class="form-control" placeholder="@translator.Translate(userLanguage, "Model")" value="@Model.Model">
<label for="inputPurchaseDate">@translator.Translate(userLanguage, "Purchased Date(optional)")</label> <label for="inputLicensePlate">@translator.Translate(userLanguage, "License Plate")</label>
<input type="text" id="inputPurchaseDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Purchased Date")" value="@Model.PurchaseDate"> <input type="text" id="inputLicensePlate" class="form-control" placeholder="@translator.Translate(userLanguage, "License Plate")" value="@Model.LicensePlate">
<label for="inputSoldDate">@translator.Translate(userLanguage, "Sold Date(optional)")</label> @foreach (ExtraField field in Model.ExtraFields)
<input type="text" id="inputSoldDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Sold Date")" value="@Model.SoldDate"> {
<div class="form-check form-switch"> var elementId = Guid.NewGuid();
<input class="form-check-input" type="checkbox" role="switch" id="inputIsElectric" checked="@Model.IsElectric"> <div class="extra-field">
<label class="form-check-label" for="inputIsElectric">@translator.Translate(userLanguage, "Electric Vehicle")</label> <label for="@elementId">@field.Name</label>
</div> <input type="text" id="@elementId" class="form-control @(field.IsRequired ? "extra-field-required" : "")" placeholder="@field.Name" value="@field.Value">
<div class="form-check form-switch"> </div>
<input class="form-check-input" type="checkbox" role="switch" id="inputUseHours" checked="@Model.UseHours"> }
<label class="form-check-label" for="inputUseHours">@translator.Translate(userLanguage, "Use Engine Hours")</label>
</div>
<label for="inputTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
<select multiple class="form-select" id="inputTag">
@foreach (string tag in Model.Tags)
{
<!option value="@tag">@tag</!option>
}
</select>
@foreach (ExtraField field in Model.ExtraFields)
{
var elementId = Guid.NewGuid();
<div class="extra-field">
<label for="@elementId">@field.Name</label>
<input type="text" id="@elementId" class="form-control @(field.IsRequired ? "extra-field-required" : "")" placeholder="@field.Name" value="@field.Value">
</div> </div>
} <div class="col-12 col-md-6">
@if (!string.IsNullOrWhiteSpace(Model.ImageLocation)) <label for="inputPurchaseDate">@translator.Translate(userLanguage, "Purchased Date(optional)")</label>
{ <input type="text" id="inputPurchaseDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Purchased Date")" value="@Model.PurchaseDate">
<label for="inputImage">@translator.Translate(userLanguage, "Replace picture(optional)")</label> <label for="inputSoldDate">@translator.Translate(userLanguage, "Sold Date(optional)")</label>
<input onChange="uploadFileAsync(this)" type="file" accept=".png,.jpg,.jpeg" class="form-control-file" id="inputImage"> <input type="text" id="inputSoldDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Sold Date")" value="@Model.SoldDate">
} else <div class="form-check form-switch">
{ <input class="form-check-input" type="checkbox" role="switch" id="inputIsElectric" checked="@Model.IsElectric">
<label for="inputImage">@translator.Translate(userLanguage, "Upload a picture(optional)")</label> <label class="form-check-label" for="inputIsElectric">@translator.Translate(userLanguage, "Electric Vehicle")</label>
<input onChange="uploadFileAsync(this)" type="file" accept=".png,.jpg,.jpeg" class="form-control-file" id="inputImage"> </div>
} <div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="inputUseHours" checked="@Model.UseHours">
<label class="form-check-label" for="inputUseHours">@translator.Translate(userLanguage, "Use Engine Hours")</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" onchange="toggleOdometerAdjustment()" id="inputHasOdometerAdjustment" checked="@Model.HasOdometerAdjustment">
<label class="form-check-label" for="inputHasOdometerAdjustment">@translator.Translate(userLanguage, "Odometer Adjustments")</label>
</div>
<div class="collapse @(Model.HasOdometerAdjustment ? "show" : "")" id="odometerAdjustments">
<div>
<label for="inputOdometerMultiplier">@translator.Translate(userLanguage, "Odometer Multiplier")</label>
<input type="text" id="inputOdometerMultiplier" class="form-control" placeholder="@translator.Translate(userLanguage, "Odometer Multiplier")" value="@Model.OdometerMultiplier">
<label for="inputOdometerDifference">@translator.Translate(userLanguage, "Odometer Difference")</label>
<input type="text" id="inputOdometerDifference" class="form-control" placeholder="@translator.Translate(userLanguage, "Odometer Difference")" value="@Model.OdometerDifference">
</div>
</div>
<label for="inputTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
<select multiple class="form-select" id="inputTag">
@foreach (string tag in Model.Tags)
{
<!option value="@tag">@tag</!option>
}
</select>
@if (!string.IsNullOrWhiteSpace(Model.ImageLocation))
{
<label for="inputImage">@translator.Translate(userLanguage, "Replace picture(optional)")</label>
<input onChange="uploadFileAsync(this)" type="file" accept=".png,.jpg,.jpeg" class="form-control-file" id="inputImage">
}
else
{
<label for="inputImage">@translator.Translate(userLanguage, "Upload a picture(optional)")</label>
<input onChange="uploadFileAsync(this)" type="file" accept=".png,.jpg,.jpeg" class="form-control-file" id="inputImage">
}
</div>
</div>
</div> </div>
</form> </form>
</div> </div>

File diff suppressed because one or more lines are too long

View File

@@ -86,6 +86,8 @@ function getAndValidateCollisionRecordValues() {
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
var collisionRecordId = getCollisionRecordModelData().id; var collisionRecordId = getCollisionRecordModelData().id;
var addReminderRecord = $("#addReminderCheck").is(":checked"); var addReminderRecord = $("#addReminderCheck").is(":checked");
//Odometer Adjustments
collisionMileage = GetAdjustedOdometer(collisionRecordId, collisionMileage);
//validation //validation
var hasError = false; var hasError = false;
var extraFields = getAndValidateExtraFields(); var extraFields = getAndValidateExtraFields();

View File

@@ -35,7 +35,7 @@ function getVehicleSupplyRecords() {
}); });
} }
function GetVehicleId() { function GetVehicleId() {
return { vehicleId: 0 }; return { vehicleId: 0, hasOdometerAdjustment: false };
} }
function bindTabEvent() { function bindTabEvent() {
$('button[data-bs-toggle="tab"]').on('show.bs.tab', function (e) { $('button[data-bs-toggle="tab"]').on('show.bs.tab', function (e) {

View File

@@ -85,6 +85,8 @@ function getAndValidateGasRecordValues() {
var gasTags = $("#gasRecordTag").val(); var gasTags = $("#gasRecordTag").val();
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
var gasRecordId = getGasRecordModelData().id; var gasRecordId = getGasRecordModelData().id;
//Odometer Adjustments
gasMileage = GetAdjustedOdometer(gasRecordId, gasMileage);
//validation //validation
var hasError = false; var hasError = false;
var extraFields = getAndValidateExtraFields(); var extraFields = getAndValidateExtraFields();
@@ -425,3 +427,68 @@ function searchGasTableRows() {
} }
}); });
} }
function editMultipleGasRecords(ids) {
$.post('/Vehicle/GetGasRecordsEditModal', { recordIds: ids }, function (data) {
if (data) {
$("#gasRecordModalContent").html(data);
//initiate datepicker
initDatePicker($('#gasRecordDate'));
initTagSelector($("#gasRecordTag"));
$('#gasRecordModal').modal('show');
}
});
}
function saveMultipleGasRecordsToVehicle() {
var gasDate = $("#gasRecordDate").val();
var gasMileage = $("#gasRecordMileage").val();
var gasMileageToParse = parseInt(globalParseFloat($("#gasRecordMileage").val())).toString();
var gasConsumption = $("#gasRecordConsumption").val();
var gasCost = $("#gasRecordCost").val();
var gasNotes = $("#gasRecordNotes").val();
var gasTags = $("#gasRecordTag").val();
//validation
var hasError = false;
if (gasMileage.trim() != '' && (isNaN(gasMileageToParse) || parseInt(gasMileageToParse) < 0)) {
hasError = true;
$("#gasRecordMileage").addClass("is-invalid");
} else {
$("#gasRecordMileage").removeClass("is-invalid");
}
if (gasConsumption.trim() != '' && !isValidMoney(gasConsumption)) {
hasError = true;
$("#gasRecordConsumption").addClass("is-invalid");
} else {
$("#gasRecordConsumption").removeClass("is-invalid");
}
if (gasCost.trim() != '' && !isValidMoney(gasCost)) {
hasError = true;
$("#gasRecordCost").addClass("is-invalid");
} else {
$("#gasRecordCost").removeClass("is-invalid");
}
if (hasError) {
errorToast("Please check the form data");
return;
}
var formValues = {
recordIds: recordsToEdit,
editRecord: {
date: gasDate,
mileage: gasMileageToParse,
gallons: gasConsumption,
cost: gasCost,
notes: gasNotes,
tags: gasTags
}
}
$.post('/Vehicle/SaveMultipleGasRecords', { editModel: formValues }, function (data) {
if (data) {
successToast("Gas Records Updated");
hideAddGasRecordModal();
saveScrollPosition();
getVehicleGasRecords(GetVehicleId().vehicleId);
} else {
errorToast(genericErrorMessage());
}
})
}

View File

@@ -84,6 +84,8 @@ function getAndValidateOdometerRecordValues() {
var serviceTags = $("#odometerRecordTag").val(); var serviceTags = $("#odometerRecordTag").val();
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
var odometerRecordId = getOdometerRecordModelData().id; var odometerRecordId = getOdometerRecordModelData().id;
//Odometer Adjustments
serviceMileage = GetAdjustedOdometer(odometerRecordId, serviceMileage);
//validation //validation
var hasError = false; var hasError = false;
var extraFields = getAndValidateExtraFields(); var extraFields = getAndValidateExtraFields();

View File

@@ -241,7 +241,9 @@ function updatePlanRecordProgress(newProgress) {
}, },
}).then(function (result) { }).then(function (result) {
if (result.isConfirmed) { if (result.isConfirmed) {
$.post('/Vehicle/UpdatePlanRecordProgress', { planRecordId: draggedId, planProgress: newProgress, odometer: result.value.odometer }, function (data) { //Odometer Adjustments
var adjustedOdometer = GetAdjustedOdometer(0, result.value.odometer);
$.post('/Vehicle/UpdatePlanRecordProgress', { planRecordId: draggedId, planProgress: newProgress, odometer: adjustedOdometer }, function (data) {
if (data) { if (data) {
successToast("Plan Progress Updated"); successToast("Plan Progress Updated");
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;

View File

@@ -86,6 +86,8 @@ function getAndValidateServiceRecordValues() {
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
var serviceRecordId = getServiceRecordModelData().id; var serviceRecordId = getServiceRecordModelData().id;
var addReminderRecord = $("#addReminderCheck").is(":checked"); var addReminderRecord = $("#addReminderCheck").is(":checked");
//Odometer Adjustments
serviceMileage = GetAdjustedOdometer(serviceRecordId, serviceMileage);
//validation //validation
var hasError = false; var hasError = false;
var extraFields = getAndValidateExtraFields(); var extraFields = getAndValidateExtraFields();

View File

@@ -42,6 +42,9 @@ function saveVehicle(isEdit) {
var vehicleLicensePlate = $("#inputLicensePlate").val(); var vehicleLicensePlate = $("#inputLicensePlate").val();
var vehicleIsElectric = $("#inputIsElectric").is(":checked"); var vehicleIsElectric = $("#inputIsElectric").is(":checked");
var vehicleUseHours = $("#inputUseHours").is(":checked"); var vehicleUseHours = $("#inputUseHours").is(":checked");
var vehicleHasOdometerAdjustment = $("#inputHasOdometerAdjustment").is(':checked');
var vehicleOdometerMultiplier = $("#inputOdometerMultiplier").val();
var vehicleOdometerDifference = parseInt(globalParseFloat($("#inputOdometerDifference").val())).toString();
var extraFields = getAndValidateExtraFields(true); var extraFields = getAndValidateExtraFields(true);
//validate //validate
var hasError = false; var hasError = false;
@@ -72,6 +75,23 @@ function saveVehicle(isEdit) {
} else { } else {
$("#inputLicensePlate").removeClass("is-invalid"); $("#inputLicensePlate").removeClass("is-invalid");
} }
if (vehicleHasOdometerAdjustment) {
//validate odometer adjustments
//validate multiplier
if (vehicleOdometerMultiplier.trim() == '' || !isValidMoney(vehicleOdometerMultiplier)) {
hasError = true;
$("#inputOdometerMultiplier").addClass("is-invalid");
} else {
$("#inputOdometerMultiplier").removeClass("is-invalid");
}
//validate difference
if (vehicleOdometerDifference.trim() == '' || isNaN(vehicleOdometerDifference)) {
hasError = true;
$("#inputOdometerDifference").addClass("is-invalid");
} else {
$("#inputOdometerDifference").removeClass("is-invalid");
}
}
if (hasError) { if (hasError) {
return; return;
} }
@@ -87,7 +107,10 @@ function saveVehicle(isEdit) {
useHours: vehicleUseHours, useHours: vehicleUseHours,
extraFields: extraFields.extraFields, extraFields: extraFields.extraFields,
purchaseDate: vehiclePurchaseDate, purchaseDate: vehiclePurchaseDate,
soldDate: vehicleSoldDate soldDate: vehicleSoldDate,
hasOdometerAdjustment: vehicleHasOdometerAdjustment,
odometerMultiplier: vehicleOdometerMultiplier,
odometerDifference: vehicleOdometerDifference
}, function (data) { }, function (data) {
if (data) { if (data) {
if (!isEdit) { if (!isEdit) {
@@ -105,6 +128,14 @@ function saveVehicle(isEdit) {
} }
}); });
} }
function toggleOdometerAdjustment() {
var isChecked = $("#inputHasOdometerAdjustment").is(':checked');
if (isChecked) {
$("#odometerAdjustments").collapse('show');
} else {
$("#odometerAdjustments").collapse('hide');
}
}
function uploadFileAsync(event) { function uploadFileAsync(event) {
let formData = new FormData(); let formData = new FormData();
formData.append("file", event.files[0]); formData.append("file", event.files[0]);
@@ -783,6 +814,11 @@ function determineContextMenuItems() {
} else { } else {
$(".context-menu-multiple").hide(); $(".context-menu-multiple").hide();
} }
if (GetVehicleId().hasOdometerAdjustment) {
$(".context-menu-odometer-adjustment").show();
} else {
$(".context-menu-odometer-adjustment").hide();
}
} }
function getMenuPosition(mouse, direction, scrollDir) { function getMenuPosition(mouse, direction, scrollDir) {
var win = $(window)[direction](), var win = $(window)[direction](),

View File

@@ -86,6 +86,8 @@ function getAndValidateUpgradeRecordValues() {
var vehicleId = GetVehicleId().vehicleId; var vehicleId = GetVehicleId().vehicleId;
var upgradeRecordId = getUpgradeRecordModelData().id; var upgradeRecordId = getUpgradeRecordModelData().id;
var addReminderRecord = $("#addReminderCheck").is(":checked"); var addReminderRecord = $("#addReminderCheck").is(":checked");
//Odometer Adjustments
upgradeMileage = GetAdjustedOdometer(upgradeRecordId, upgradeMileage);
//validation //validation
var hasError = false; var hasError = false;
var extraFields = getAndValidateExtraFields(); var extraFields = getAndValidateExtraFields();

View File

@@ -476,7 +476,7 @@ function getRecordsDeltaStats(recordIds) {
var divisibleCount = recordIds.length - 1; var divisibleCount = recordIds.length - 1;
var averageOdo = diffOdo > 0 ? (diffOdo / divisibleCount).toFixed(2) : 0; var averageOdo = diffOdo > 0 ? (diffOdo / divisibleCount).toFixed(2) : 0;
var averageDays = diffDate > 0 ? Math.floor((diffDate / divisibleCount) / 8.64e7) : 0; var averageDays = diffDate > 0 ? Math.floor((diffDate / divisibleCount) / 8.64e7) : 0;
var averageSum = costSum > 0 ? (costSum / divisibleCount).toFixed(2) : 0; var averageSum = costSum > 0 ? (costSum / recordIds.length).toFixed(2) : 0;
costSum = costSum.toFixed(2); costSum = costSum.toFixed(2);
Swal.fire({ Swal.fire({
title: "Record Statistics", title: "Record Statistics",
@@ -491,3 +491,67 @@ function getRecordsDeltaStats(recordIds) {
icon: "info" icon: "info"
}); });
} }
function GetAdjustedOdometer(id, odometerInput) {
//if editing an existing record or vehicle does not have odometer adjustment or input is NaN then just return the original input.
if (id > 0 || !GetVehicleId().hasOdometerAdjustment || isNaN(odometerInput)) {
return odometerInput;
}
//apply odometer adjustments first.
var adjustedOdometer = parseInt(odometerInput) + parseInt(GetVehicleId().odometerDifference);
//apply odometer multiplier.
adjustedOdometer *= globalParseFloat(GetVehicleId().odometerMultiplier);
return adjustedOdometer.toFixed(0);
}
function adjustRecordsOdometer(ids, source) {
if (ids.length == 0) {
return;
}
$("#workAroundInput").show();
var friendlySource = "";
var refreshDataCallBack;
var recordVerbiage = ids.length > 1 ? `these ${ids.length} records` : "this record";
switch (source) {
case "ServiceRecord":
friendlySource = "Service Records";
refreshDataCallBack = getVehicleServiceRecords;
break;
case "RepairRecord":
friendlySource = "Repairs";
refreshDataCallBack = getVehicleCollisionRecords;
break;
case "UpgradeRecord":
friendlySource = "Upgrades";
refreshDataCallBack = getVehicleUpgradeRecords;
break;
case "OdometerRecord":
friendlySource = "Odometer Records";
refreshDataCallBack = getVehicleOdometerRecords;
break;
case "GasRecord":
friendlySource = "Fuel Records";
refreshDataCallBack = getVehicleGasRecords;
break;
}
Swal.fire({
title: "Adjust Odometer?",
text: `Apply Odometer Adjustments to ${recordVerbiage}?`,
showCancelButton: true,
confirmButtonText: "Adjust",
confirmButtonColor: "#dc3545"
}).then((result) => {
if (result.isConfirmed) {
$.post('/Vehicle/AdjustRecordsOdometer', { recordIds: ids, vehicleId: GetVehicleId().vehicleId, importMode: source }, function (data) {
if (data) {
successToast(`${ids.length} Record(s) Updated`);
var vehicleId = GetVehicleId().vehicleId;
refreshDataCallBack(vehicleId);
} else {
errorToast(genericErrorMessage());
}
});
} else {
$("#workAroundInput").hide();
}
});
}