allow users to define what field sthey want to see in vehicle maintenance report.

This commit is contained in:
DESKTOP-T0O5CDB\DESK-555BD
2024-11-12 12:54:39 -07:00
parent 87fe011565
commit a671dc1937
7 changed files with 144 additions and 24 deletions

View File

@@ -320,10 +320,25 @@ namespace CarCareTracker.Controllers
return Json(new OperationResponse { Success = false, Message = "No Attachments Found" });
}
}
public IActionResult GetReportParameters()
{
var viewModel = new ReportParameter();
//get all extra fields from service records, repairs, upgrades, and tax records.
var recordTypes = new List<int>() { 0, 1, 3, 4 };
var extraFields = new List<string>();
foreach(int recordType in recordTypes)
{
extraFields.AddRange(_extraFieldDataAccess.GetExtraFieldsById(recordType).ExtraFields.Select(x => x.Name));
}
viewModel.ExtraFields = extraFields.Distinct().ToList();
return PartialView("_ReportParameters", viewModel);
}
[TypeFilter(typeof(CollaboratorFilter))]
public IActionResult GetVehicleHistory(int vehicleId)
public IActionResult GetVehicleHistory(int vehicleId, ReportParameter reportParameter)
{
var vehicleHistory = new VehicleHistoryViewModel();
vehicleHistory.ReportParameters = reportParameter;
vehicleHistory.VehicleData = _dataAccess.GetVehicleById(vehicleId);
var maxMileage = _vehicleLogic.GetMaxMileage(vehicleId);
vehicleHistory.Odometer = maxMileage.ToString("N0");
@@ -408,7 +423,8 @@ namespace CarCareTracker.Controllers
Description = x.Description,
Notes = x.Notes,
Cost = x.Cost,
DataType = ImportMode.ServiceRecord
DataType = ImportMode.ServiceRecord,
ExtraFields = x.ExtraFields
}));
//repair records
reportData.AddRange(repairRecords.Select(x => new GenericReportModel
@@ -418,7 +434,8 @@ namespace CarCareTracker.Controllers
Description = x.Description,
Notes = x.Notes,
Cost = x.Cost,
DataType = ImportMode.RepairRecord
DataType = ImportMode.RepairRecord,
ExtraFields = x.ExtraFields
}));
reportData.AddRange(upgradeRecords.Select(x => new GenericReportModel
{
@@ -427,7 +444,8 @@ namespace CarCareTracker.Controllers
Description = x.Description,
Notes = x.Notes,
Cost = x.Cost,
DataType = ImportMode.UpgradeRecord
DataType = ImportMode.UpgradeRecord,
ExtraFields = x.ExtraFields
}));
reportData.AddRange(taxRecords.Select(x => new GenericReportModel
{
@@ -436,7 +454,8 @@ namespace CarCareTracker.Controllers
Description = x.Description,
Notes = x.Notes,
Cost = x.Cost,
DataType = ImportMode.TaxRecord
DataType = ImportMode.TaxRecord,
ExtraFields = x.ExtraFields
}));
vehicleHistory.VehicleHistory = reportData.OrderBy(x => x.Date).ThenBy(x => x.Odometer).ToList();
return PartialView("_VehicleHistory", vehicleHistory);

View File

@@ -12,5 +12,6 @@
public string Notes { get; set; }
public decimal Cost { get; set; }
public List<UploadedFiles> Files { get; set; } = new List<UploadedFiles>();
public List<ExtraField> ExtraFields { get; set; } = new List<ExtraField>();
}
}

View File

@@ -0,0 +1,14 @@
namespace CarCareTracker.Models
{
public class ReportParameter
{
public List<string> VisibleColumns { get; set; } = new List<string>() {
nameof(GenericReportModel.DataType),
nameof(GenericReportModel.Date),
nameof(GenericReportModel.Odometer),
nameof(GenericReportModel.Description),
nameof(GenericReportModel.Cost),
nameof(GenericReportModel.Notes) };
public List<string> ExtraFields { get; set; } = new List<string>();
}
}

View File

@@ -4,6 +4,7 @@
{
public Vehicle VehicleData { get; set; }
public List<GenericReportModel> VehicleHistory { get; set; }
public ReportParameter ReportParameters { get; set; }
public string Odometer { get; set; }
public string MPG { get; set; }
public decimal TotalCost { get; set; }

View File

@@ -0,0 +1,26 @@
@using CarCareTracker.Helper
@inject IConfigHelper config
@inject ITranslationHelper translator
@{
var userConfig = config.GetUserConfig(User);
var userLanguage = userConfig.UserLanguage;
}
@model ReportParameter
<div id="columnSelector">
<ul class="list-group">
@foreach(string column in Model.VisibleColumns)
{
<li class="list-group-item text-start">
<input class="form-check-input column-default" type="checkbox" value="@column" id="visibleColumn_@column" checked>
<label class="form-check-label stretched-link" for="visibleColumn_@column">@(translator.Translate(userLanguage, column == nameof(GenericReportModel.DataType) ? "Type" : column))</label>
</li>
}
@foreach(string extraField in Model.ExtraFields)
{
<li class="list-group-item text-start">
<input class="form-check-input column-extrafield" type="checkbox" value="@extraField" id="extraField_@extraField">
<label class="form-check-label stretched-link" for="extraField_@extraField">@extraField</label>
</li>
}
</ul>
</div>

View File

@@ -1,12 +1,13 @@
@using CarCareTracker.Helper
@inject IConfigHelper config
@inject ITranslationHelper translator
@model VehicleHistoryViewModel
@{
var userConfig = config.GetUserConfig(User);
var hideZero = userConfig.HideZero;
var userLanguage = userConfig.UserLanguage;
var extraFields = Model.ReportParameters.ExtraFields;
}
@model VehicleHistoryViewModel
<div class="vehicleDetailTabContainer">
<div class="row mt-2">
<div class="d-flex">
@@ -107,19 +108,23 @@
<table class="table table-hover">
<thead>
<tr class="d-flex">
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1">@translator.Translate(userLanguage, "Type")</th>
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1">@translator.Translate(userLanguage, "Date")</th>
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1">@translator.Translate(userLanguage, "Odometer")</th>
<th scope="col" class="col-3 text-truncate flex-grow-1 flex-shrink-1">@translator.Translate(userLanguage, "Description")</th>
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1">@translator.Translate(userLanguage, "Cost")</th>
<th scope="col" class="col-4 text-truncate flex-grow-1 flex-shrink-1">@translator.Translate(userLanguage, "Notes")</th>
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.DataType)) ? "" : "d-none")">@translator.Translate(userLanguage, "Type")</th>
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Date)) ? "" : "d-none")">@translator.Translate(userLanguage, "Date")</th>
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Odometer)) ? "" : "d-none")">@translator.Translate(userLanguage, "Odometer")</th>
<th scope="col" class="col-3 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Description)) ? "" : "d-none")">@translator.Translate(userLanguage, "Description")</th>
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Cost)) ? "" : "d-none")">@translator.Translate(userLanguage, "Cost")</th>
<th scope="col" class="col-4 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Notes)) ? "" : "d-none")">@translator.Translate(userLanguage, "Notes")</th>
@foreach(string extraField in extraFields)
{
<th scope="col" class="col-2 text-truncate flex-grow-1 flex-shrink-1">@extraField</th>
}
</tr>
</thead>
<tbody>
@foreach (GenericReportModel reportData in Model.VehicleHistory)
{
<tr class="d-flex">
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1">
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.DataType)) ? "" : "d-none")">
@if (reportData.DataType == ImportMode.ServiceRecord)
{
<span><i class="bi bi-card-checklist me-2"></i>@translator.Translate(userLanguage, "Service")</span>
@@ -137,11 +142,15 @@
<span><i class="bi bi-currency-dollar me-2"></i>@translator.Translate(userLanguage, "Tax")</span>
}
</td>
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1">@reportData.Date.ToShortDateString()</td>
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1">@(reportData.Odometer == default ? "---" : reportData.Odometer.ToString("N0"))</td>
<td class="col-3 text-truncate flex-grow-1 flex-shrink-1">@reportData.Description</td>
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1">@((hideZero && reportData.Cost == default) ? "---" : reportData.Cost.ToString("C"))</td>
<td class="col-4 flex-grow-1 flex-shrink-1 text-wrap">@StaticHelper.TruncateStrings(reportData.Notes, 100)</td>
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Date)) ? "" : "d-none")">@reportData.Date.ToShortDateString()</td>
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Odometer)) ? "" : "d-none")">@(reportData.Odometer == default ? "---" : reportData.Odometer.ToString("N0"))</td>
<td class="col-3 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Description)) ? "" : "d-none")">@reportData.Description</td>
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1 @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Cost)) ? "" : "d-none")">@((hideZero && reportData.Cost == default) ? "---" : reportData.Cost.ToString("C"))</td>
<td class="col-4 flex-grow-1 flex-shrink-1 text-wrap text-break @(Model.ReportParameters.VisibleColumns.Contains(nameof(GenericReportModel.Notes)) ? "" : "d-none")">@StaticHelper.TruncateStrings(reportData.Notes, 100)</td>
@foreach(string extraField in extraFields)
{
<td class="col-2 text-truncate flex-grow-1 flex-shrink-1">@(reportData.ExtraFields.Where(x => x.Name == extraField)?.FirstOrDefault()?.Value ?? "")</td>
}
</tr>
}
<tr class="d-flex">

View File

@@ -1,14 +1,64 @@
function getYear() {
return $("#yearOption").val() ?? '0';
}
function getAndValidateSelectedColumns() {
var reportVisibleColumns = [];
var reportExtraFields = [];
$("#columnSelector :checked").map(function () {
if ($(this).hasClass('column-default')) {
reportVisibleColumns.push(this.value);
} else {
reportExtraFields.push(this.value);
}
});
if (reportVisibleColumns.length + reportExtraFields.length == 0) {
return {
hasError: true,
visibleColumns: [],
extraFields: []
}
} else {
return {
hasError: false,
visibleColumns: reportVisibleColumns,
extraFields: reportExtraFields
}
}
}
function generateVehicleHistoryReport() {
var vehicleId = GetVehicleId().vehicleId;
$.get(`/Vehicle/GetVehicleHistory?vehicleId=${vehicleId}`, function (data) {
$.get(`/Vehicle/GetReportParameters`, function (data) {
if (data) {
$("#vehicleHistoryReport").html(data);
setTimeout(function () {
window.print();
}, 500);
//prompt user to select a vehicle
Swal.fire({
title: 'Select Columns',
html: data,
confirmButtonText: 'Generate Report',
focusConfirm: false,
preConfirm: () => {
//validate
var selectedColumnsData = getAndValidateSelectedColumns();
if (selectedColumnsData.hasError) {
Swal.showValidationMessage(`You must select at least one column`);
}
return { selectedColumnsData }
},
}).then(function (result) {
if (result.isConfirmed) {
var vehicleId = GetVehicleId().vehicleId;
$.post(`/Vehicle/GetVehicleHistory?vehicleId=${vehicleId}`, {
reportParameter: { visibleColumns: result.value.selectedColumnsData.visibleColumns, extraFields: result.value.selectedColumnsData.extraFields }
}, function (data) {
if (data) {
$("#vehicleHistoryReport").html(data);
setTimeout(function () {
window.print();
}, 500);
}
})
}
});
} else {
errorToast(genericErrorMessage());
}
})
}