Merge pull request #399 from hargata/Hargata/odo.modifier
Odometer Modifier
This commit is contained in:
@@ -154,6 +154,7 @@ namespace CarCareTracker.Controllers
|
||||
_planRecordDataAccess.DeleteAllPlanRecordsByVehicleId(vehicleId) &&
|
||||
_planRecordTemplateDataAccess.DeleteAllPlanRecordTemplatesByVehicleId(vehicleId) &&
|
||||
_supplyRecordDataAccess.DeleteAllSupplyRecordsByVehicleId(vehicleId) &&
|
||||
_odometerRecordDataAccess.DeleteAllOdometerRecordsByVehicleId(vehicleId) &&
|
||||
_userLogic.DeleteAllAccessToVehicle(vehicleId) &&
|
||||
_dataAccess.DeleteVehicle(vehicleId);
|
||||
return Json(result);
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace CarCareTracker.Helper
|
||||
/// </summary>
|
||||
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 UserConfigPath = "config/userConfig.json";
|
||||
public static string GenericErrorMessage = "An error occurred, please try again later";
|
||||
|
||||
@@ -14,5 +14,14 @@
|
||||
public bool UseHours { get; set; } = false;
|
||||
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
|
||||
public List<string> Tags { get; set; } = new List<string>();
|
||||
public bool HasOdometerAdjustment { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Primarily used for vehicles with odometer units different from user's settings.
|
||||
/// </summary>
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
@@ -169,7 +169,12 @@
|
||||
</div>
|
||||
<script>
|
||||
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() {
|
||||
return { tab: "@userConfig.DefaultTab" };
|
||||
|
||||
@@ -26,50 +26,69 @@
|
||||
<div class="modal-body">
|
||||
<form class="form-inline">
|
||||
<div class="form-group">
|
||||
<label for="inputYear">@translator.Translate(userLanguage, "Year")</label>
|
||||
<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="inputMake">@translator.Translate(userLanguage, "Make")</label>
|
||||
<input type="text" id="inputMake" class="form-control" placeholder="@translator.Translate(userLanguage, "Make")" value="@Model.Make">
|
||||
<label for="inputModel">@translator.Translate(userLanguage, "Model")</label>
|
||||
<input type="text" id="inputModel" class="form-control" placeholder="@translator.Translate(userLanguage, "Model")" value="@Model.Model">
|
||||
<label for="inputLicensePlate">@translator.Translate(userLanguage, "License Plate")</label>
|
||||
<input type="text" id="inputLicensePlate" class="form-control" placeholder="@translator.Translate(userLanguage, "License Plate")" value="@Model.LicensePlate">
|
||||
<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="inputSoldDate">@translator.Translate(userLanguage, "Sold Date(optional)")</label>
|
||||
<input type="text" id="inputSoldDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Sold Date")" value="@Model.SoldDate">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="inputIsElectric" checked="@Model.IsElectric">
|
||||
<label class="form-check-label" for="inputIsElectric">@translator.Translate(userLanguage, "Electric Vehicle")</label>
|
||||
</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>
|
||||
<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 class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<label for="inputYear">@translator.Translate(userLanguage, "Year")</label>
|
||||
<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="inputMake">@translator.Translate(userLanguage, "Make")</label>
|
||||
<input type="text" id="inputMake" class="form-control" placeholder="@translator.Translate(userLanguage, "Make")" value="@Model.Make">
|
||||
<label for="inputModel">@translator.Translate(userLanguage, "Model")</label>
|
||||
<input type="text" id="inputModel" class="form-control" placeholder="@translator.Translate(userLanguage, "Model")" value="@Model.Model">
|
||||
<label for="inputLicensePlate">@translator.Translate(userLanguage, "License Plate")</label>
|
||||
<input type="text" id="inputLicensePlate" class="form-control" placeholder="@translator.Translate(userLanguage, "License Plate")" value="@Model.LicensePlate">
|
||||
@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>
|
||||
}
|
||||
@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 class="col-12 col-md-6">
|
||||
<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="inputSoldDate">@translator.Translate(userLanguage, "Sold Date(optional)")</label>
|
||||
<input type="text" id="inputSoldDate" class="form-control" placeholder="@translator.Translate(userLanguage, "Sold Date")" value="@Model.SoldDate">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="inputIsElectric" checked="@Model.IsElectric">
|
||||
<label class="form-check-label" for="inputIsElectric">@translator.Translate(userLanguage, "Electric Vehicle")</label>
|
||||
</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>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -86,6 +86,8 @@ function getAndValidateCollisionRecordValues() {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var collisionRecordId = getCollisionRecordModelData().id;
|
||||
var addReminderRecord = $("#addReminderCheck").is(":checked");
|
||||
//Odometer Adjustments
|
||||
collisionMileage = GetAdjustedOdometer(collisionRecordId, collisionMileage);
|
||||
//validation
|
||||
var hasError = false;
|
||||
var extraFields = getAndValidateExtraFields();
|
||||
|
||||
@@ -85,6 +85,8 @@ function getAndValidateGasRecordValues() {
|
||||
var gasTags = $("#gasRecordTag").val();
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var gasRecordId = getGasRecordModelData().id;
|
||||
//Odometer Adjustments
|
||||
gasMileage = GetAdjustedOdometer(gasRecordId, gasMileage);
|
||||
//validation
|
||||
var hasError = false;
|
||||
var extraFields = getAndValidateExtraFields();
|
||||
|
||||
@@ -84,6 +84,8 @@ function getAndValidateOdometerRecordValues() {
|
||||
var serviceTags = $("#odometerRecordTag").val();
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var odometerRecordId = getOdometerRecordModelData().id;
|
||||
//Odometer Adjustments
|
||||
serviceMileage = GetAdjustedOdometer(odometerRecordId, serviceMileage);
|
||||
//validation
|
||||
var hasError = false;
|
||||
var extraFields = getAndValidateExtraFields();
|
||||
|
||||
@@ -241,7 +241,9 @@ function updatePlanRecordProgress(newProgress) {
|
||||
},
|
||||
}).then(function (result) {
|
||||
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) {
|
||||
successToast("Plan Progress Updated");
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
|
||||
@@ -86,6 +86,8 @@ function getAndValidateServiceRecordValues() {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var serviceRecordId = getServiceRecordModelData().id;
|
||||
var addReminderRecord = $("#addReminderCheck").is(":checked");
|
||||
//Odometer Adjustments
|
||||
serviceMileage = GetAdjustedOdometer(serviceRecordId, serviceMileage);
|
||||
//validation
|
||||
var hasError = false;
|
||||
var extraFields = getAndValidateExtraFields();
|
||||
|
||||
@@ -42,6 +42,9 @@ function saveVehicle(isEdit) {
|
||||
var vehicleLicensePlate = $("#inputLicensePlate").val();
|
||||
var vehicleIsElectric = $("#inputIsElectric").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);
|
||||
//validate
|
||||
var hasError = false;
|
||||
@@ -72,6 +75,23 @@ function saveVehicle(isEdit) {
|
||||
} else {
|
||||
$("#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) {
|
||||
return;
|
||||
}
|
||||
@@ -87,7 +107,10 @@ function saveVehicle(isEdit) {
|
||||
useHours: vehicleUseHours,
|
||||
extraFields: extraFields.extraFields,
|
||||
purchaseDate: vehiclePurchaseDate,
|
||||
soldDate: vehicleSoldDate
|
||||
soldDate: vehicleSoldDate,
|
||||
hasOdometerAdjustment: vehicleHasOdometerAdjustment,
|
||||
odometerMultiplier: vehicleOdometerMultiplier,
|
||||
odometerDifference: vehicleOdometerDifference
|
||||
}, function (data) {
|
||||
if (data) {
|
||||
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) {
|
||||
let formData = new FormData();
|
||||
formData.append("file", event.files[0]);
|
||||
|
||||
@@ -86,6 +86,8 @@ function getAndValidateUpgradeRecordValues() {
|
||||
var vehicleId = GetVehicleId().vehicleId;
|
||||
var upgradeRecordId = getUpgradeRecordModelData().id;
|
||||
var addReminderRecord = $("#addReminderCheck").is(":checked");
|
||||
//Odometer Adjustments
|
||||
upgradeMileage = GetAdjustedOdometer(upgradeRecordId, upgradeMileage);
|
||||
//validation
|
||||
var hasError = false;
|
||||
var extraFields = getAndValidateExtraFields();
|
||||
|
||||
@@ -490,4 +490,15 @@ function getRecordsDeltaStats(recordIds) {
|
||||
,
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user