diff --git a/Web/Controllers/FuelLogController.cs b/Web/Controllers/FuelLogController.cs index 969f5ad..2f82f5b 100644 --- a/Web/Controllers/FuelLogController.cs +++ b/Web/Controllers/FuelLogController.cs @@ -23,30 +23,17 @@ namespace MileageTraker.Web.Controllers // default parameter processing if (!query.HasParameters()) { - query.Year = validLogYearMonths.First().Year; + query.FiscalYear = validLogYearMonths.First().Year; query.Month = validLogYearMonths.First().Month; } - if (query.Year.HasValue && !query.Month.HasValue) - { - var validLogMonths = validLogYearMonths.Where(dt => dt.Year == query.Year).ToList(); - query.Month = validLogMonths.Min(dt => dt.Month); - } var fuelLogs = DataService.GetFuelLogs(); - //fuelLogs.OrderBy(f => f.FuelLogId); + var flvm = from fl in DataService.FilterFuelLogs(fuelLogs, query).ToList() + orderby fl.Date ascending + select new FuelLogIndexViewModel(fl); - //var filteredLogs = - // (from log in DataService.GetFuelLogIndexViewModels(DataService.FilterLogs(fuelLogs, query)) - // orderby log. descending - // select log).ToList(); - - var flvm = from fl in fuelLogs.ToList() - select new FuelLogIndexViewModel(fl); - - var viewModel = new ResultsViewModel(flvm, query, CustomExtensions.YearMonthList(validLogYearMonths)); - - //Session.Add("FuelLogPage", Request.Url.PathAndQuery); + var viewModel = new FuelLogResultsViewModel(flvm, query, CustomExtensions.YearMonthList(validLogYearMonths)); return View(viewModel); } @@ -173,7 +160,7 @@ namespace MileageTraker.Web.Controllers { Status = MatchStatus.NoMatch.ToString(), Message = "Already matched to log", - Action = RenderRazorViewToString("ImportMatchLogView", fuelLog.Log.LogId) + Action = RenderRazorViewToString("MatchLink", new MatchLinkViewModel(fuelLog)) }, JsonRequestBehavior.AllowGet); } @@ -185,7 +172,8 @@ namespace MileageTraker.Web.Controllers return Json(new { Status = MatchStatus.NoMatch.ToString(), - Message = "Unable to find match" + Message = "Unable to find match", + Action = RenderRazorViewToString("MatchLink", new MatchLinkViewModel(fuelLog)) }, JsonRequestBehavior.AllowGet); } fuelLog.Log = matchingLog; @@ -193,7 +181,7 @@ namespace MileageTraker.Web.Controllers return Json(new { Status = MatchStatus.Match.ToString(), - Action = RenderRazorViewToString("ImportMatchedLog", new ImportMatchedLogViewModel { LogId = fuelLog.Log.LogId }) + Action = RenderRazorViewToString("MatchLink", new MatchLinkViewModel(fuelLog)) }, JsonRequestBehavior.AllowGet); } diff --git a/Web/DAL/DataService.cs b/Web/DAL/DataService.cs index a8406f7..c325b9c 100644 --- a/Web/DAL/DataService.cs +++ b/Web/DAL/DataService.cs @@ -7,6 +7,7 @@ using MileageTraker.Web.Context; using MileageTraker.Web.Models; using MileageTraker.Web.Utility; using MileageTraker.Web.ViewModels; +using MileageTraker.Web.ViewModels.FuelLog; using MileageTraker.Web.ViewModels.Log; using MileageTraker.Web.ViewModels.Vehicle; @@ -658,6 +659,30 @@ namespace MileageTraker.Web.DAL return _db.FuelLogs.Find(id); } + public static IQueryable FilterFuelLogs(IQueryable fuelLogs, FuelLogQueryViewModel query) + { + const int fiscalYearStartMonth = 7; + + // date filtering + if (query.FiscalYear.HasValue & query.Month.HasValue) + { + var start = new DateTime(query.FiscalYear.Value, query.Month.Value, 1); + var end = start.AddMonths(1); + fuelLogs = fuelLogs.Where(l => l.Date >= start && l.Date < end); + } + else if (query.FiscalYear.HasValue) + { + var start = new DateTime(query.FiscalYear.Value, fiscalYearStartMonth, 1); + var end = start.AddYears(1); + fuelLogs = fuelLogs.Where(l => l.Date >= start && l.Date < end); + } + if (query.Unmatched) + { + fuelLogs = fuelLogs.Where(l => l.Log == null); + } + return fuelLogs; + } + public IEnumerable GetDuplicateFuelLogs(FuelLog log) { return @@ -671,23 +696,35 @@ namespace MileageTraker.Web.DAL public Log GetMatchingLog(FuelLog fuelLog) { - var logs = GetLogs(); + // add a little wiggle room for the gas - it is common to be off by a couple hundreths + const double gasRange = .01; + var gasMax = fuelLog.GasPurchased + gasRange; + var gasMin = fuelLog.GasPurchased - gasRange; + + var dateGasVehicleQuery = GetLogs(); // matching by Date, Gas Purchased (gallons), and Vehicle - var vehicle = GetVehicleByTag(fuelLog.TagNumber); if (vehicle != null) - logs = logs.Where(log => log.VehicleId == vehicle.VehicleId); - else return null; + dateGasVehicleQuery = dateGasVehicleQuery.Where(log => log.VehicleId == vehicle.VehicleId); - logs = logs.Where(log => - log.Date.Year == fuelLog.Date.Year && - log.Date.Month == fuelLog.Date.Month && - log.Date.Day == fuelLog.Date.Day - ); - logs = logs.Where(log => log.GasPurchased == fuelLog.GasPurchased); - - return logs.FirstOrDefault(); + dateGasVehicleQuery = dateGasVehicleQuery + .Where(log => + log.Date.Year == fuelLog.Date.Year && + log.Date.Month == fuelLog.Date.Month && + log.Date.Day == fuelLog.Date.Day) + .Where(log => log.GasPurchased <= gasMax && log.GasPurchased >= gasMin); + + var dateDriverGasQuery + = GetLogs() + .Where(log => + log.Date.Year == fuelLog.Date.Year && + log.Date.Month == fuelLog.Date.Month && + log.Date.Day == fuelLog.Date.Day) + .Where(log => log.User.FullName.Contains(fuelLog.DriverFullName)) + .Where(log => log.GasPurchased <= gasMax && log.GasPurchased >= gasMin); + + return dateGasVehicleQuery.Union(dateDriverGasQuery).FirstOrDefault(); } public IEnumerable GetPossibleMatchingLogs(FuelLog fuelLog) diff --git a/Web/Scripts/Shared/FuelLogImport.js b/Web/Scripts/Shared/FuelLogImport.js index ba33eed..de81a50 100644 --- a/Web/Scripts/Shared/FuelLogImport.js +++ b/Web/Scripts/Shared/FuelLogImport.js @@ -1,12 +1,13 @@ -function importFuelLogs() { +function matchFuelLogs() { $('.breadcrumb').hide(); $('tr:not(.complete) .match-status').append('Pending tbody > tr:not(.complete)").length; - $('#page-match-status').html(' Matching In Progress Keep page open until complete.'); + $('#page-match-status').html(' Matching In Progress for ' + total + ' fuel logs. Keep page open until complete.'); $('#page-match-status').after('
'); submitNext(); - var failureCount = 0; + var unmatchedCount = 0; + var errorCount = 0; function submitNext() { var $fuelLogs = $("#fuellogs > tbody > tr:not(.complete)"); @@ -32,12 +33,13 @@ else if (result.Status == "NoMatch" || result.Status == "Error") { if (result.Status == "NoMatch") { $('.match-status', $row).html('No Match'); + unmatchedCount++; } else { $('.match-status', $row).html('Error'); + errorCount++; + $('.progress .bar').addClass('bar-warning'); } $('.match-message', $row).text(result.Message); - failureCount++; - $('.progress .bar').addClass('bar-warning'); } if (result.Action != undefined && result.Action != null) { $('.match-status', $row).append(" " + result.Action); @@ -50,11 +52,11 @@ $('.breadcrumb').show(); $('.progress').removeClass('progress-striped'); $('.progress').removeClass('active'); - if (failureCount == 0) { - $('#page-match-status').html('Complete with all matches.'); + if (errorCount == 0) { + $('#page-match-status').html('Complete ' + total + ' total with ' + unmatchedCount + ' left unmatched.'); $('.progress .bar').addClass('bar-success'); } else { - $('#page-match-status').html('Complete but with errors. See details below.'); + $('#page-match-status').html('Complete with errors. See below.'); } } } diff --git a/Web/ViewModels/FuelLog/FuelLogQueryViewModel.cs b/Web/ViewModels/FuelLog/FuelLogQueryViewModel.cs index 6003b81..c7ea0d7 100644 --- a/Web/ViewModels/FuelLog/FuelLogQueryViewModel.cs +++ b/Web/ViewModels/FuelLog/FuelLogQueryViewModel.cs @@ -5,27 +5,28 @@ namespace MileageTraker.Web.ViewModels.FuelLog { public class FuelLogQueryViewModel { - public int? Year { get; set; } + public int? FiscalYear { get; set; } public int? Month { get; set; } + public bool Unmatched { get; set; } public string YearMonthStart {get { - return string.Format("{0}-{1:00}", Year, Month); + return string.Format("{0}-{1:00}", FiscalYear, Month); }} public override string ToString() { var v = new List(); - if (Year.HasValue && Month.HasValue) + if (FiscalYear.HasValue && Month.HasValue) { var str = YearMonthStart; v.Add(str); } - else if (Year.HasValue) + else if (FiscalYear.HasValue) { - v.Add(Year.ToString()); + v.Add(FiscalYear.ToString()); } return String.Join("_", v).Replace(' ', '-'); @@ -33,7 +34,7 @@ namespace MileageTraker.Web.ViewModels.FuelLog public bool HasParameters() { - return Year.HasValue; + return FiscalYear.HasValue; } } } \ No newline at end of file diff --git a/Web/ViewModels/FuelLog/ResultsViewModel.cs b/Web/ViewModels/FuelLog/FuelLogResultsViewModel.cs similarity index 53% rename from Web/ViewModels/FuelLog/ResultsViewModel.cs rename to Web/ViewModels/FuelLog/FuelLogResultsViewModel.cs index 1c8b921..2e8dd67 100644 --- a/Web/ViewModels/FuelLog/ResultsViewModel.cs +++ b/Web/ViewModels/FuelLog/FuelLogResultsViewModel.cs @@ -3,27 +3,29 @@ using System.Globalization; namespace MileageTraker.Web.ViewModels.FuelLog { - public class ResultsViewModel + public class FuelLogResultsViewModel { public IEnumerable FuelLogs { get; set; } public Dictionary> AvailableYearMonths { get; set; } public IEnumerable SelectedYearMonths{get { - if (!string.IsNullOrEmpty(Year)) - return AvailableYearMonths[Year]; + if (!string.IsNullOrEmpty(FiscalYear)) + return AvailableYearMonths[FiscalYear]; return new List(); }} // filter parameters - public string Year { get; set; } + public string FiscalYear { get; set; } public string Month { get; set; } + public bool Unmatched { get; set; } - public ResultsViewModel(IEnumerable fuelLogs, FuelLogQueryViewModel query, Dictionary> availableYearMonths) + public FuelLogResultsViewModel(IEnumerable fuelLogs, FuelLogQueryViewModel query, Dictionary> availableYearMonths) { FuelLogs = fuelLogs; AvailableYearMonths = availableYearMonths; - Year = query.Year.HasValue ? query.Year.Value.ToString(CultureInfo.InvariantCulture) : string.Empty; + FiscalYear = query.FiscalYear.HasValue ? query.FiscalYear.Value.ToString(CultureInfo.InvariantCulture) : string.Empty; Month = query.Month.HasValue ? query.Month.Value.ToString(CultureInfo.InvariantCulture) : string.Empty; + Unmatched = query.Unmatched; } } } \ No newline at end of file diff --git a/Web/ViewModels/FuelLog/ImportMatchedLogViewModel.cs b/Web/ViewModels/FuelLog/ImportMatchedLogViewModel.cs deleted file mode 100644 index 34342a9..0000000 --- a/Web/ViewModels/FuelLog/ImportMatchedLogViewModel.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace MileageTraker.Web.ViewModels.FuelLog -{ - public class ImportMatchedLogViewModel - { - public int LogId { get; set; } - } -} \ No newline at end of file diff --git a/Web/ViewModels/FuelLog/MatchLinkViewModel.cs b/Web/ViewModels/FuelLog/MatchLinkViewModel.cs new file mode 100644 index 0000000..294765a --- /dev/null +++ b/Web/ViewModels/FuelLog/MatchLinkViewModel.cs @@ -0,0 +1,22 @@ +namespace MileageTraker.Web.ViewModels.FuelLog +{ + public class MatchLinkViewModel + { + public int FuelLogId { get; set; } + public int? LogId { get; set; } + + public MatchLinkViewModel(Models.FuelLog fuelLog) + { + FuelLogId = fuelLog.FuelLogId; + if (fuelLog.Log != null) + LogId = fuelLog.Log.LogId; + } + + public MatchLinkViewModel(ImportFuelLogViewModel viewModel) + { + FuelLogId = viewModel.FuelLogId; + if (viewModel.LogId != null) + LogId = viewModel.LogId; + } + } +} \ No newline at end of file diff --git a/Web/ViewModels/Log/LogResultsViewModel.cs b/Web/ViewModels/Log/LogResultsViewModel.cs index 5b59817..9e78ad7 100644 --- a/Web/ViewModels/Log/LogResultsViewModel.cs +++ b/Web/ViewModels/Log/LogResultsViewModel.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.Mvc; -using MiscUtil.Collections; +using System.Collections.Generic; namespace MileageTraker.Web.ViewModels.Log { diff --git a/Web/Views/FuelLog/Import.cshtml b/Web/Views/FuelLog/Import.cshtml index 9d7f853..11143aa 100644 --- a/Web/Views/FuelLog/Import.cshtml +++ b/Web/Views/FuelLog/Import.cshtml @@ -45,7 +45,7 @@ } @if (viewModel.LogId != null) { - @Html.Partial("ImportMatchedLog", new ImportMatchedLogViewModel { LogId = viewModel.LogId.Value }) + @Html.Partial("MatchLink", new MatchLinkViewModel (viewModel)) } @@ -65,7 +65,7 @@ } \ No newline at end of file diff --git a/Web/Views/FuelLog/ImportMatchedLog.cshtml b/Web/Views/FuelLog/ImportMatchedLog.cshtml deleted file mode 100644 index f64c7eb..0000000 --- a/Web/Views/FuelLog/ImportMatchedLog.cshtml +++ /dev/null @@ -1,5 +0,0 @@ -@model MileageTraker.Web.ViewModels.FuelLog.ImportMatchedLogViewModel -@{ - Layout = null; -} -@Html.ActionLink("View Log", "Details", "Log", new{id=Model.LogId}, new{@class="btn btn-mini", target="_blank"}) diff --git a/Web/Views/FuelLog/Index.cshtml b/Web/Views/FuelLog/Index.cshtml index fb1d77d..81709e3 100644 --- a/Web/Views/FuelLog/Index.cshtml +++ b/Web/Views/FuelLog/Index.cshtml @@ -1,10 +1,10 @@ @using MileageTraker.Web.Utility -@model MileageTraker.Web.ViewModels.FuelLog.ResultsViewModel +@model MileageTraker.Web.ViewModels.FuelLog.FuelLogResultsViewModel @{ ViewBag.Title = "Fuel Logs"; var grid = new WebGrid(Model.FuelLogs, rowsPerPage: 45); - var parameters = new {Model.Year, Model.Month}; + var parameters = new {Year = Model.FiscalYear, Model.Month}; } @section Styles { @@ -12,9 +12,9 @@ @section Scripts { @@ -22,12 +22,10 @@ @Html.Partial("_StatusMessage") -
- @using (Html.BeginForm("Index", "Log", FormMethod.Get, new { id = "filter", @class = "form" })) +
+ @using (Html.BeginForm("Index", "FuelLog", FormMethod.Get, new { id = "filter", @class = "form" })) { -
- @*@Html.EditorForModel()*@ -
+ @Html.EditorForModel() }
@@ -54,8 +52,11 @@ : Html.ActionLink("Match", "Match", new {id = item.FuelLogId}, new {@class = "btn btn-warning btn-mini", target="_blank"})) )), htmlAttributes: new { @class = "table table-striped table-bordered table-hover table-condensed"}, - numericLinksCount: 20 - ) + numericLinksCount: 20 + ) +
@if (!Model.FuelLogs.Any()) { diff --git a/Web/Views/FuelLog/MatchLink.cshtml b/Web/Views/FuelLog/MatchLink.cshtml new file mode 100644 index 0000000..e56c1fa --- /dev/null +++ b/Web/Views/FuelLog/MatchLink.cshtml @@ -0,0 +1,12 @@ +@model MileageTraker.Web.ViewModels.FuelLog.MatchLinkViewModel +@{ + Layout = null; +} +@if (Model.LogId != null) +{ + @Html.ActionLink("View Match", "Match", new {id = Model.FuelLogId}, new {@class = "btn btn-mini", target = "_blank"}) +} +else +{ + @Html.ActionLink("Match", "Match", new {id = Model.FuelLogId}, new {@class = "btn btn-warning btn-mini", target = "_blank"}) +} diff --git a/Web/Views/Shared/EditorTemplates/FuelLogResultsViewModel.cshtml b/Web/Views/Shared/EditorTemplates/FuelLogResultsViewModel.cshtml new file mode 100644 index 0000000..dc8ef09 --- /dev/null +++ b/Web/Views/Shared/EditorTemplates/FuelLogResultsViewModel.cshtml @@ -0,0 +1,21 @@ +@using MileageTraker.Web.Models +@using MileageTraker.Web.Utility +@model MileageTraker.Web.ViewModels.FuelLog.FuelLogResultsViewModel + +
+
+ @Html.Label("FiscalYear", "Fiscal Year") + @Html.DropDownList("FiscalYear", new SelectList(Model.AvailableYearMonths.Keys, Model.FiscalYear), "Select Year", new { @class = "input-small" }) +
+
+ @Html.Label("Month", "Month") + @Html.DropDownList("Month", new SelectList(Model.SelectedYearMonths, Model.Month), "All Months", new { @class = "input-small" }) +
+
+ @Html.Label("Unmatched", "Unmatched Only", new{style = "padding-top:22px"}) + +
+
+ +
+
\ No newline at end of file diff --git a/Web/Web.csproj b/Web/Web.csproj index fea8238..a19f1ce 100644 --- a/Web/Web.csproj +++ b/Web/Web.csproj @@ -233,12 +233,12 @@ - + - + @@ -307,12 +307,13 @@ - + +