Merge pull request #438 from hargata/Hargata/garage.status

Hargata/garage.status
This commit is contained in:
Hargata Softworks
2024-03-27 11:41:43 -06:00
committed by GitHub
9 changed files with 121 additions and 31 deletions

View File

@@ -832,7 +832,7 @@ namespace CarCareTracker.Controllers
{ {
foreach(int reminderRecordId in serviceRecord.ReminderRecordId) foreach(int reminderRecordId in serviceRecord.ReminderRecordId)
{ {
PushbackRecurringReminderRecordWithChecks(reminderRecordId); PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(serviceRecord.Date), serviceRecord.Mileage);
} }
} }
var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord()); var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord());
@@ -924,7 +924,7 @@ namespace CarCareTracker.Controllers
{ {
foreach (int reminderRecordId in collisionRecord.ReminderRecordId) foreach (int reminderRecordId in collisionRecord.ReminderRecordId)
{ {
PushbackRecurringReminderRecordWithChecks(reminderRecordId); PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(collisionRecord.Date), collisionRecord.Mileage);
} }
} }
var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord()); var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord());
@@ -1038,7 +1038,7 @@ namespace CarCareTracker.Controllers
{ {
foreach (int reminderRecordId in taxRecord.ReminderRecordId) foreach (int reminderRecordId in taxRecord.ReminderRecordId)
{ {
PushbackRecurringReminderRecordWithChecks(reminderRecordId); PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(taxRecord.Date), null);
} }
} }
var result = _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord.ToTaxRecord()); var result = _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord.ToTaxRecord());
@@ -1336,19 +1336,36 @@ namespace CarCareTracker.Controllers
if (!string.IsNullOrWhiteSpace(vehicleHistory.VehicleData.PurchaseDate)) if (!string.IsNullOrWhiteSpace(vehicleHistory.VehicleData.PurchaseDate))
{ {
var endDate = vehicleHistory.VehicleData.SoldDate; var endDate = vehicleHistory.VehicleData.SoldDate;
int daysOwned = 0;
if (string.IsNullOrWhiteSpace(endDate)) if (string.IsNullOrWhiteSpace(endDate))
{ {
endDate = DateTime.Now.ToShortDateString(); endDate = DateTime.Now.ToShortDateString();
} }
try try
{ {
vehicleHistory.DaysOwned = (DateTime.Parse(endDate) - DateTime.Parse(vehicleHistory.VehicleData.PurchaseDate)).Days.ToString("N0"); daysOwned = (DateTime.Parse(endDate) - DateTime.Parse(vehicleHistory.VehicleData.PurchaseDate)).Days;
vehicleHistory.DaysOwned = daysOwned.ToString("N0");
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
vehicleHistory.DaysOwned = string.Empty; vehicleHistory.DaysOwned = string.Empty;
} }
//calculate depreciation
var totalDepreciation = vehicleHistory.VehicleData.PurchasePrice - vehicleHistory.VehicleData.SoldPrice;
//we only calculate depreciation if a sold price is provided.
if (totalDepreciation != default && vehicleHistory.VehicleData.SoldPrice != default)
{
vehicleHistory.TotalDepreciation = totalDepreciation;
if (daysOwned != default)
{
vehicleHistory.DepreciationPerDay = Math.Abs(totalDepreciation / daysOwned);
}
if (distanceTraveled != default)
{
vehicleHistory.DepreciationPerMile = Math.Abs(totalDepreciation / distanceTraveled);
}
}
} }
List<GenericReportModel> reportData = new List<GenericReportModel>(); List<GenericReportModel> reportData = new List<GenericReportModel>();
var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId); var serviceRecords = _serviceRecordDataAccess.GetServiceRecordsByVehicleId(vehicleId);
@@ -1568,9 +1585,7 @@ namespace CarCareTracker.Controllers
List<ReminderRecordViewModel> results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, dateCompare); List<ReminderRecordViewModel> results = _reminderHelper.GetReminderRecordViewModels(reminders, currentMileage, dateCompare);
return results; return results;
} }
[TypeFilter(typeof(CollaboratorFilter))] private bool GetAndUpdateVehicleUrgentOrPastDueReminders(int vehicleId)
[HttpGet]
public IActionResult GetVehicleHaveUrgentOrPastDueReminders(int vehicleId)
{ {
var result = GetRemindersAndUrgency(vehicleId, DateTime.Now); var result = GetRemindersAndUrgency(vehicleId, DateTime.Now);
//check if user wants auto-refresh past-due reminders //check if user wants auto-refresh past-due reminders
@@ -1585,7 +1600,7 @@ namespace CarCareTracker.Controllers
//update based on recurring intervals. //update based on recurring intervals.
//pull reminderRecord based on ID //pull reminderRecord based on ID
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecord.Id); var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecord.Id);
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder); existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, null, null);
//save to db. //save to db.
_reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder); _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
//set urgency to not urgent so it gets excluded in count. //set urgency to not urgent so it gets excluded in count.
@@ -1597,9 +1612,16 @@ namespace CarCareTracker.Controllers
var pastDueAndUrgentReminders = result.Where(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue); var pastDueAndUrgentReminders = result.Where(x => x.Urgency == ReminderUrgency.VeryUrgent || x.Urgency == ReminderUrgency.PastDue);
if (pastDueAndUrgentReminders.Any()) if (pastDueAndUrgentReminders.Any())
{ {
return Json(true); return true;
} }
return Json(false); return false;
}
[TypeFilter(typeof(CollaboratorFilter))]
[HttpGet]
public IActionResult GetVehicleHaveUrgentOrPastDueReminders(int vehicleId)
{
var result = GetAndUpdateVehicleUrgentOrPastDueReminders(vehicleId);
return Json(result);
} }
[TypeFilter(typeof(CollaboratorFilter))] [TypeFilter(typeof(CollaboratorFilter))]
[HttpGet] [HttpGet]
@@ -1619,17 +1641,17 @@ namespace CarCareTracker.Controllers
[HttpPost] [HttpPost]
public IActionResult PushbackRecurringReminderRecord(int reminderRecordId) public IActionResult PushbackRecurringReminderRecord(int reminderRecordId)
{ {
var result = PushbackRecurringReminderRecordWithChecks(reminderRecordId); var result = PushbackRecurringReminderRecordWithChecks(reminderRecordId, null, null);
return Json(result); return Json(result);
} }
private bool PushbackRecurringReminderRecordWithChecks(int reminderRecordId) private bool PushbackRecurringReminderRecordWithChecks(int reminderRecordId, DateTime? currentDate, int? currentMileage)
{ {
try try
{ {
var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecordId); var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(reminderRecordId);
if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring) if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring)
{ {
existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder); existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder, currentDate, currentMileage);
//save to db. //save to db.
var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder); var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder);
if (!reminderUpdateResult) if (!reminderUpdateResult)
@@ -1752,7 +1774,7 @@ namespace CarCareTracker.Controllers
{ {
foreach (int reminderRecordId in upgradeRecord.ReminderRecordId) foreach (int reminderRecordId in upgradeRecord.ReminderRecordId)
{ {
PushbackRecurringReminderRecordWithChecks(reminderRecordId); PushbackRecurringReminderRecordWithChecks(reminderRecordId, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Mileage);
} }
} }
var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord()); var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord());
@@ -2209,7 +2231,7 @@ namespace CarCareTracker.Controllers
//push back any reminders //push back any reminders
if (existingRecord.ReminderRecordId != default) if (existingRecord.ReminderRecordId != default)
{ {
PushbackRecurringReminderRecordWithChecks(existingRecord.ReminderRecordId); PushbackRecurringReminderRecordWithChecks(existingRecord.ReminderRecordId, DateTime.Now, odometer);
} }
} }
return Json(result); return Json(result);

View File

@@ -4,7 +4,7 @@ namespace CarCareTracker.Helper
{ {
public interface IReminderHelper public interface IReminderHelper
{ {
ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder); ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder, DateTime? currentDate, int? currentMileage);
List<ReminderRecordViewModel> GetReminderRecordViewModels(List<ReminderRecord> reminders, int currentMileage, DateTime dateCompare); List<ReminderRecordViewModel> GetReminderRecordViewModels(List<ReminderRecord> reminders, int currentMileage, DateTime dateCompare);
} }
public class ReminderHelper: IReminderHelper public class ReminderHelper: IReminderHelper
@@ -14,46 +14,48 @@ namespace CarCareTracker.Helper
{ {
_config = config; _config = config;
} }
public ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder) public ReminderRecord GetUpdatedRecurringReminderRecord(ReminderRecord existingReminder, DateTime? currentDate, int? currentMileage)
{ {
var newDate = currentDate ?? existingReminder.Date;
var newMileage = currentMileage ?? existingReminder.Mileage;
if (existingReminder.Metric == ReminderMetric.Both) if (existingReminder.Metric == ReminderMetric.Both)
{ {
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other) if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
{ {
existingReminder.Date = existingReminder.Date.AddMonths((int)existingReminder.ReminderMonthInterval); existingReminder.Date = newDate.AddMonths((int)existingReminder.ReminderMonthInterval);
} else } else
{ {
existingReminder.Date = existingReminder.Date.AddMonths(existingReminder.CustomMonthInterval); existingReminder.Date = newDate.Date.AddMonths(existingReminder.CustomMonthInterval);
} }
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other) if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
{ {
existingReminder.Mileage += (int)existingReminder.ReminderMileageInterval; existingReminder.Mileage = newMileage + (int)existingReminder.ReminderMileageInterval;
} }
else else
{ {
existingReminder.Mileage += existingReminder.CustomMileageInterval; existingReminder.Mileage = newMileage + existingReminder.CustomMileageInterval;
} }
} }
else if (existingReminder.Metric == ReminderMetric.Odometer) else if (existingReminder.Metric == ReminderMetric.Odometer)
{ {
if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other) if (existingReminder.ReminderMileageInterval != ReminderMileageInterval.Other)
{ {
existingReminder.Mileage += (int)existingReminder.ReminderMileageInterval; existingReminder.Mileage = newMileage + (int)existingReminder.ReminderMileageInterval;
} else } else
{ {
existingReminder.Mileage += existingReminder.CustomMileageInterval; existingReminder.Mileage = newMileage + existingReminder.CustomMileageInterval;
} }
} }
else if (existingReminder.Metric == ReminderMetric.Date) else if (existingReminder.Metric == ReminderMetric.Date)
{ {
if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other) if (existingReminder.ReminderMonthInterval != ReminderMonthInterval.Other)
{ {
existingReminder.Date = existingReminder.Date.AddMonths((int)existingReminder.ReminderMonthInterval); existingReminder.Date = newDate.AddMonths((int)existingReminder.ReminderMonthInterval);
} }
else else
{ {
existingReminder.Date = existingReminder.Date.AddMonths(existingReminder.CustomMonthInterval); existingReminder.Date = newDate.AddMonths(existingReminder.CustomMonthInterval);
} }
} }
return existingReminder; return existingReminder;

View File

@@ -13,5 +13,8 @@
public decimal TotalCostPerMile { get; set; } public decimal TotalCostPerMile { get; set; }
public decimal TotalGasCostPerMile { get; set; } public decimal TotalGasCostPerMile { get; set; }
public string DistanceUnit { get; set; } public string DistanceUnit { get; set; }
public decimal TotalDepreciation { get; set; }
public decimal DepreciationPerDay { get; set; }
public decimal DepreciationPerMile { get; set; }
} }
} }

View File

@@ -10,6 +10,8 @@
public string LicensePlate { get; set; } public string LicensePlate { get; set; }
public string PurchaseDate { get; set; } public string PurchaseDate { get; set; }
public string SoldDate { get; set; } public string SoldDate { get; set; }
public decimal PurchasePrice { get; set; }
public decimal SoldPrice { get; set; }
public bool IsElectric { get; set; } = false; public bool IsElectric { get; set; } = false;
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>();

View File

@@ -62,6 +62,30 @@
</div> </div>
</div> </div>
<hr /> <hr />
@if (Model.TotalDepreciation != default)
{
<div class="row">
<div class="col-3">
@(Model.TotalDepreciation > 0 ? translator.Translate(userLanguage, "Depreciation") : translator.Translate(userLanguage, "Appreciation"))
</div>
<div class="col-3">
<span><i class="bi @(Model.TotalDepreciation > 0 ? "bi-graph-down-arrow" : "bi-graph-up-arrow") me-2"></i>@Math.Abs(Model.TotalDepreciation).ToString("C")</span>
</div>
@if (Model.DepreciationPerDay != default)
{
<div class="col-3">
<span><i class="bi bi-calendar-event me-2"></i>@($"{Model.DepreciationPerDay.ToString("C")}/{translator.Translate(userLanguage, "day")}")</span>
</div>
}
@if (Model.DepreciationPerMile != default)
{
<div class="col-3">
<span><i class="bi bi-speedometer me-2"></i>@($"{Model.DepreciationPerMile.ToString("C")}/{Model.DistanceUnit}")</span>
</div>
}
</div>
<hr />
}
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<table class="table table-hover"> <table class="table table-hover">

View File

@@ -46,10 +46,6 @@
} }
</div> </div>
<div class="col-12 col-md-6"> <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"> <div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="inputIsElectric" checked="@Model.IsElectric"> <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> <label class="form-check-label" for="inputIsElectric">@translator.Translate(userLanguage, "Electric Vehicle")</label>
@@ -70,6 +66,25 @@
<input type="text" id="inputOdometerDifference" class="form-control" placeholder="@translator.Translate(userLanguage, "Odometer Difference")" value="@Model.OdometerDifference"> <input type="text" id="inputOdometerDifference" class="form-control" placeholder="@translator.Translate(userLanguage, "Odometer Difference")" value="@Model.OdometerDifference">
</div> </div>
</div> </div>
<div class="accordion accordion-flush" id="vehicleModalAccordion">
<div class="accordion-item">
<div class="accordion-header">
<button class="accordion-button skinny collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePurchaseInfo">
@translator.Translate(userLanguage, "Purchase/Sold Information(optional)")
</button>
</div>
<div id="collapsePurchaseInfo" class="accordion-collapse collapse" data-bs-parent="#vehicleModalAccordion">
<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">
<label for="inputPurchasePrice">@translator.Translate(userLanguage, "Purchased Price(optional)")</label>
<input type="text" inputmode="decimal" id="inputPurchasePrice" class="form-control" placeholder="@translator.Translate(userLanguage, "Purchased Price")" value="@(Model.PurchasePrice == default ? "" : Model.PurchasePrice)">
<label for="inputSoldPrice">@translator.Translate(userLanguage, "Sold Price(optional)")</label>
<input type="text" inputmode="decimal" id="inputSoldPrice" class="form-control" placeholder="@translator.Translate(userLanguage, "Sold Price")" value="@(Model.SoldPrice == default ? "" : Model.SoldPrice)">
</div>
</div>
</div>
<label for="inputTag">@translator.Translate(userLanguage, "Tags(optional)")</label> <label for="inputTag">@translator.Translate(userLanguage, "Tags(optional)")</label>
<select multiple class="form-select" id="inputTag"> <select multiple class="form-select" id="inputTag">
@foreach (string tag in Model.Tags) @foreach (string tag in Model.Tags)

View File

@@ -373,4 +373,8 @@ input[type="file"] {
} }
.copyable{ .copyable{
cursor: pointer; cursor: pointer;
}
.accordion-button.skinny {
padding: 0.438rem 0rem !important;
background-color: inherit !important;
} }

File diff suppressed because one or more lines are too long

View File

@@ -45,6 +45,8 @@ function saveVehicle(isEdit) {
var vehicleHasOdometerAdjustment = $("#inputHasOdometerAdjustment").is(':checked'); var vehicleHasOdometerAdjustment = $("#inputHasOdometerAdjustment").is(':checked');
var vehicleOdometerMultiplier = $("#inputOdometerMultiplier").val(); var vehicleOdometerMultiplier = $("#inputOdometerMultiplier").val();
var vehicleOdometerDifference = parseInt(globalParseFloat($("#inputOdometerDifference").val())).toString(); var vehicleOdometerDifference = parseInt(globalParseFloat($("#inputOdometerDifference").val())).toString();
var vehiclePurchasePrice = $("#inputPurchasePrice").val();
var vehicleSoldPrice = $("#inputSoldPrice").val();
var extraFields = getAndValidateExtraFields(true); var extraFields = getAndValidateExtraFields(true);
//validate //validate
var hasError = false; var hasError = false;
@@ -92,6 +94,20 @@ function saveVehicle(isEdit) {
$("#inputOdometerDifference").removeClass("is-invalid"); $("#inputOdometerDifference").removeClass("is-invalid");
} }
} }
if (vehiclePurchasePrice.trim() != '' && !isValidMoney(vehiclePurchasePrice)) {
hasError = true;
$("#inputPurchasePrice").addClass("is-invalid");
$("#collapsePurchaseInfo").collapse('show');
} else {
$("#inputPurchasePrice").removeClass("is-invalid");
}
if (vehicleSoldPrice.trim() != '' && !isValidMoney(vehicleSoldPrice)) {
hasError = true;
$("#inputSoldPrice").addClass("is-invalid");
$("#collapsePurchaseInfo").collapse('show');
} else {
$("#inputSoldPrice").removeClass("is-invalid");
}
if (hasError) { if (hasError) {
return; return;
} }
@@ -110,7 +126,9 @@ function saveVehicle(isEdit) {
soldDate: vehicleSoldDate, soldDate: vehicleSoldDate,
hasOdometerAdjustment: vehicleHasOdometerAdjustment, hasOdometerAdjustment: vehicleHasOdometerAdjustment,
odometerMultiplier: vehicleOdometerMultiplier, odometerMultiplier: vehicleOdometerMultiplier,
odometerDifference: vehicleOdometerDifference odometerDifference: vehicleOdometerDifference,
purchasePrice: vehiclePurchasePrice,
soldPrice: vehicleSoldPrice
}, function (data) { }, function (data) {
if (data) { if (data) {
if (!isEdit) { if (!isEdit) {