diff --git a/Web.Tests/DAL/LogDocs/Logs.xls b/Web.Tests/DAL/LogDocs/Logs.xls index a0b2c35..6c37ce9 100644 Binary files a/Web.Tests/DAL/LogDocs/Logs.xls and b/Web.Tests/DAL/LogDocs/Logs.xls differ diff --git a/Web.Tests/Utility/CustomExtensionsTests.cs b/Web.Tests/Utility/CustomExtensionsTests.cs index 5a0a78a..61919ae 100644 --- a/Web.Tests/Utility/CustomExtensionsTests.cs +++ b/Web.Tests/Utility/CustomExtensionsTests.cs @@ -4,7 +4,9 @@ using MileageTraker.Web.Models; using MileageTraker.Web.Utility; using MileageTraker.Web.ViewModels; using MileageTraker.Web.ViewModels.CreateLog; +using MileageTraker.Web.ViewModels.Log; using NUnit.Framework; +using ImportLogViewModel = MileageTraker.Web.ViewModels.Log.ImportLogViewModel; namespace Web.Tests.Utility { @@ -70,7 +72,7 @@ namespace Web.Tests.Utility [Test] public void Type_GetPropertyNames() { - var propertyNames = (typeof (LogImportViewModel).GetPropertyNames()).ToList(); + var propertyNames = (typeof (ImportLogViewModel).GetPropertyNames()).ToList(); Assert.That(propertyNames, Has.Member("Vehicle ID")); Assert.That(propertyNames, Has.Count.GreaterThan(5)); diff --git a/Web.Tests/ViewModels/CreateLog/LogImportViewModelTests.cs b/Web.Tests/ViewModels/CreateLog/LogImportViewModelTests.cs index d36f839..d7e5382 100644 --- a/Web.Tests/ViewModels/CreateLog/LogImportViewModelTests.cs +++ b/Web.Tests/ViewModels/CreateLog/LogImportViewModelTests.cs @@ -1,6 +1,7 @@ using System; using AutoMapper; using MileageTraker.Web.ViewModels; +using MileageTraker.Web.ViewModels.Log; using NUnit.Framework; namespace Web.Tests.ViewModels.CreateLog @@ -8,9 +9,9 @@ namespace Web.Tests.ViewModels.CreateLog [TestFixture] public class LogImportViewModelTests { - private LogImportViewModel GetTestModel() + private ImportLogViewModel GetTestModel() { - return new LogImportViewModel + return new ImportLogViewModel { CityName = "City", Date = "10-20-2010", diff --git a/Web/Attributes/DenyPreviousMonthDateAttribute.cs b/Web/Attributes/DenyPreviousMonthDateAttribute.cs index 56b4d1e..9adbd6d 100644 --- a/Web/Attributes/DenyPreviousMonthDateAttribute.cs +++ b/Web/Attributes/DenyPreviousMonthDateAttribute.cs @@ -8,18 +8,15 @@ namespace MileageTraker.Web.Attributes { public override bool IsValid(object value) { - var date = DateTime.Parse(value.ToString()); + DateTime date; + if (value == null || !DateTime.TryParse(value.ToString(), out date)) + return false; return date.Date >= GetCutoff(); } private static DateTime GetCutoff() { return DomainRules.GetLogEntryCutoff(); - //var today = DateTime.Today; - //return today.AddMonths(-1).AddDays(-today.Day + 1); // last two months - //if (today.Day > 10) - // return today.AddDays(-today.Day); // beginning of this month - //return today.AddMonths(-1).AddDays(-today.Day); // beginning of previous month } } } \ No newline at end of file diff --git a/Web/Controllers/CreateLogController.cs b/Web/Controllers/CreateLogController.cs index 1a3695a..3c3b915 100644 --- a/Web/Controllers/CreateLogController.cs +++ b/Web/Controllers/CreateLogController.cs @@ -205,7 +205,7 @@ namespace MileageTraker.Web.Controllers [HttpPost] [ActionLog] - public ActionResult ImportCreate(LogImportViewModel viewModel) + public ActionResult ImportCreate(ImportLogViewModel viewModel) { var buttonAttributes = new Dictionary { { "class", "btn btn-mini" }, { "target", "_blank" } }; @@ -316,11 +316,11 @@ namespace MileageTraker.Web.Controllers } } - private string GetFixLink(LogImportViewModel viewModel) + private string GetFixLink(ImportLogViewModel viewModel) { try { - viewModel.GetLogViewModel(); + viewModel.GetCreateLogViewModel(); } catch { @@ -331,7 +331,7 @@ namespace MileageTraker.Web.Controllers } [HttpPost] - public ActionResult ImportFix(LogImportViewModel viewModel) + public ActionResult ImportFix(ImportLogViewModel viewModel) { var createGetLogViewModel = viewModel.GetCreateLogViewModel(); createGetLogViewModel.Purpose = new SelectListViewModel diff --git a/Web/Controllers/LogController.cs b/Web/Controllers/LogController.cs index 2ff8e18..0089215 100644 --- a/Web/Controllers/LogController.cs +++ b/Web/Controllers/LogController.cs @@ -268,7 +268,7 @@ namespace MileageTraker.Web.Controllers var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName); viewModel.File.SaveAs(path); - IEnumerable logImports; + IEnumerable logImports; try { logImports = LogImporter.Import(path); @@ -294,7 +294,7 @@ namespace MileageTraker.Web.Controllers [HttpPost] [ActionLog] - public ActionResult ImportCreate(LogImportViewModel viewModel, string userFullName) + public ActionResult ImportCreate(ImportLogViewModel viewModel, string userFullName) { var buttonAttributes = new Dictionary { { "class", "btn btn-mini" }, { "target", "_blank" } }; @@ -405,7 +405,7 @@ namespace MileageTraker.Web.Controllers } } - private string GetFixLink(LogImportViewModel viewModel) + private string GetFixLink(ImportLogViewModel viewModel) { try { @@ -420,7 +420,7 @@ namespace MileageTraker.Web.Controllers } [HttpPost] - public ActionResult ImportFix(LogImportViewModel viewModel) + public ActionResult ImportFix(ImportLogViewModel viewModel) { var logViewModel = viewModel.GetLogViewModel(); logViewModel.Purpose.Available = GetPurposeTypesSelectList(); diff --git a/Web/DAL/LogImportTemplateWriter.cs b/Web/DAL/LogImportTemplateWriter.cs index d1ac06c..d2ca6d2 100644 --- a/Web/DAL/LogImportTemplateWriter.cs +++ b/Web/DAL/LogImportTemplateWriter.cs @@ -4,6 +4,7 @@ using ExcelLibrary.SpreadSheet; using MileageTraker.Web.Models; using MileageTraker.Web.Utility; using MileageTraker.Web.ViewModels; +using MileageTraker.Web.ViewModels.Log; namespace MileageTraker.Web.DAL { @@ -12,7 +13,7 @@ namespace MileageTraker.Web.DAL public static byte[] Write() { var example = - new LogImportViewModel + new ImportLogViewModel { CityName = "City Name", Date = "10/20/2010", @@ -27,10 +28,10 @@ namespace MileageTraker.Web.DAL var worksheet = new Worksheet("LogImport"); - ExcelWriter.WriteColumnHeaders(worksheet, formatString: headerFormat); - ExcelWriter.WriteItems(worksheet, new[] { example }, 1); // write the example item + ExcelWriter.WriteColumnHeaders(worksheet, formatString: headerFormat); + ExcelWriter.WriteItems(worksheet, new[] { example }, 1); // write the example item - var propertyCount = ExcelWriter.GetPropertyCount(); + var propertyCount = ExcelWriter.GetPropertyCount(); worksheet.Cells[0, propertyCount + 1] = new Cell("Accepted values for fields:", headerFormat); @@ -50,7 +51,7 @@ namespace MileageTraker.Web.DAL worksheet.Cells[1, propertyCount + 1] = new Cell("Type", headerFormat); ExcelWriter.WriteItems(worksheet, logTypes, 2, propertyCount + 1); - ExcelWriter.PadWorksheet(worksheet); + ExcelWriter.PadWorksheet(worksheet); // save it var workbook = new Workbook(); diff --git a/Web/DAL/LogImporter.cs b/Web/DAL/LogImporter.cs index d130d30..e41c2dd 100644 --- a/Web/DAL/LogImporter.cs +++ b/Web/DAL/LogImporter.cs @@ -4,14 +4,13 @@ using System.IO; using System.Linq; using ExcelLibrary.SpreadSheet; using MileageTraker.Web.Utility; -using MileageTraker.Web.ViewModels; -using MileageTraker.Web.ViewModels.CreateLog; +using MileageTraker.Web.ViewModels.Log; namespace MileageTraker.Web.DAL { public static class LogImporter { - public static IEnumerable Import(string filename) + public static IEnumerable Import(string filename) { var fileInfo = new FileInfo(filename); return Import(Workbook.Load(fileInfo.FullName)); @@ -19,13 +18,13 @@ namespace MileageTraker.Web.DAL private static IList GetMissingHeaderColumns(IEnumerable headerColumns) { - var properties = typeof(LogImportViewModel).GetPropertyNames(); + var properties = typeof(ImportLogViewModel).GetPropertyNames(); var pset = new HashSet(properties); var cset = new HashSet(headerColumns); return pset.Except(cset).ToList(); } - private static IEnumerable Import(Workbook workbook) + private static IEnumerable Import(Workbook workbook) { var sheet = workbook.Worksheets[0]; @@ -62,7 +61,7 @@ namespace MileageTraker.Web.DAL }; var logImportViewModel = - new LogImportViewModel + new ImportLogViewModel { CityName = getRowValue("Destination City"), Date = getRowDateValue("Date"), diff --git a/Web/Scripts/Shared/Site.js b/Web/Scripts/Shared/Site.js index 44e490f..1f44e3b 100644 --- a/Web/Scripts/Shared/Site.js +++ b/Web/Scripts/Shared/Site.js @@ -96,11 +96,16 @@ $(function() { 'vehicle-nav': /\/vehicle/i, 'user-nav': /\/user/i }; + var set = false; $.each(idNavActiveRegex, function (id, regex) { if (regex.test(document.URL)) { - $("#" + id).addClass('active'); + $("#" + id).addClass('active'); + set = true; } }); + if (!set) { + $("#" + 'create-nav').addClass('active'); + } }); function addButtonIcons () { diff --git a/Web/ViewModels/LogImportViewModel.cs b/Web/ViewModels/CreateLog/ImportLogViewModel.cs similarity index 80% rename from Web/ViewModels/LogImportViewModel.cs rename to Web/ViewModels/CreateLog/ImportLogViewModel.cs index ebc8bc0..7fc8dc0 100644 --- a/Web/ViewModels/LogImportViewModel.cs +++ b/Web/ViewModels/CreateLog/ImportLogViewModel.cs @@ -4,12 +4,10 @@ using System.Web.Mvc; using AutoMapper; using MileageTraker.Web.Attributes; using MileageTraker.Web.Utility; -using MileageTraker.Web.ViewModels.CreateLog; -using MileageTraker.Web.ViewModels.Log; -namespace MileageTraker.Web.ViewModels +namespace MileageTraker.Web.ViewModels.CreateLog { - public class LogImportViewModel + public class ImportLogViewModel { [Required(ErrorMessage = "Required")] [StringLength(6, MinimumLength = 4, ErrorMessage = "Must be a 4 digit number")] @@ -51,21 +49,19 @@ namespace MileageTraker.Web.ViewModels [Required(ErrorMessage = "Required")] [DataType(DataType.Date)] [DenyFutureDate(ErrorMessage = "Future date")] + [DenyPreviousMonthDate(ErrorMessage = "Previous Month")] [HiddenInput] public string Date { get; set; } - static LogImportViewModel() + static ImportLogViewModel() { Mapper.CreateMap().ConvertUsing(Convert.ToInt32); Mapper.CreateMap().ConvertUsing(Convert.ToDouble); Mapper.CreateMap().ConvertUsing(new DateTimeTypeConverter()); - Mapper.CreateMap() - .ForMember(u => u.LogType, opt => opt.Ignore()) - .ForMember(u => u.Purpose, opt => opt.Ignore()); - Mapper.CreateMap() + Mapper.CreateMap() .ForMember(u => u.LogType, opt => opt.Ignore()) .ForMember(u => u.Purpose, opt => opt.Ignore()); - Mapper.CreateMap() + Mapper.CreateMap() .ForMember(u => u.Purpose, opt => opt.Ignore()) .ForMember(dest => dest.GasPurchased, opt => @@ -74,18 +70,7 @@ namespace MileageTraker.Web.ViewModels ? 0 : Math.Round(Double.Parse(vm.GasPurchased), 3))); } - - public LogImportViewModel() - { - } - - public LogViewModel GetLogViewModel() - { - var log = new LogViewModel(); - Mapper.Map(this, log); - return log; - } - + public CreateLogViewModel GetCreateLogViewModel() { var log = new CreateLogViewModel(); diff --git a/Web/ViewModels/Log/ImportLogViewModel.cs b/Web/ViewModels/Log/ImportLogViewModel.cs new file mode 100644 index 0000000..9302765 --- /dev/null +++ b/Web/ViewModels/Log/ImportLogViewModel.cs @@ -0,0 +1,94 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.Web.Mvc; +using AutoMapper; +using MileageTraker.Web.Attributes; +using MileageTraker.Web.Utility; + +namespace MileageTraker.Web.ViewModels.Log +{ + public class ImportLogViewModel + { + [Required(ErrorMessage = "Required")] + [StringLength(6, MinimumLength = 4, ErrorMessage = "Must be a 4 digit number")] + [Display(Name = "Vehicle ID")] + [HiddenInput] + public string VehicleId { get; set; } + + [Required(ErrorMessage = "Required")] + [Range(1, 500000, ErrorMessage = "Between 1 and 500k")] + [Display(Name = "End Odometer")] + [HiddenInput] + public string EndOdometer { get; set; } + + [Required(ErrorMessage = "Required")] + [MileageLogTypeValid(ErrorMessage = "Invalid Log Type")] + [Display(Name = "Type")] + [HiddenInput] + public string LogType { get; set; } + + [Required(ErrorMessage = "Required")] + [Display(Name = "Destination City")] + [StringLength(64, MinimumLength = 3, ErrorMessage = "Minimum 3 characters")] + [HiddenInput] + public string CityName { get; set; } + + [Required(ErrorMessage = "Required")] + [Display(Name = "Purpose")] + [HiddenInput] + public string Purpose { get; set; } + + [StringLength(64, MinimumLength = 3, ErrorMessage = "Minimum 3 characters")] + [HiddenInput] + public string Notes { get; set; } + + [Display(Name = "Gas Purchased")] + [HiddenInput] + public string GasPurchased { get; set; } + + [Required(ErrorMessage = "Required")] + [DataType(DataType.Date)] + [DenyFutureDate(ErrorMessage = "Future date")] + [HiddenInput] + public string Date { get; set; } + + static ImportLogViewModel() + { + Mapper.CreateMap().ConvertUsing(Convert.ToInt32); + Mapper.CreateMap().ConvertUsing(Convert.ToDouble); + Mapper.CreateMap().ConvertUsing(new DateTimeTypeConverter()); + Mapper.CreateMap() + .ForMember(u => u.LogType, opt => opt.Ignore()) + .ForMember(u => u.Purpose, opt => opt.Ignore()); + Mapper.CreateMap() + .ForMember(u => u.Purpose, opt => opt.Ignore()) + .ForMember(dest => dest.GasPurchased, + opt => + opt.ResolveUsing(vm => + string.IsNullOrEmpty(vm.GasPurchased) + ? 0 + : Math.Round(Double.Parse(vm.GasPurchased), 3))); + } + + public LogViewModel GetLogViewModel() + { + var log = new LogViewModel(); + Mapper.Map(this, log); + return log; + } + + public Models.Log GetLog() + { + var log = new Models.Log(); + Mapper.Map(this, log); + return log; + } + + public override string ToString() + { + return string.Format( + "vehicle: {0}, odo: {1}, type: {2}, city: {3}, gas: {4}, purpose: {5}, date: {6}", + VehicleId, EndOdometer, LogType, CityName, GasPurchased, Purpose, Date); + } + } +} \ No newline at end of file diff --git a/Web/Views/CreateLog/Import.cshtml b/Web/Views/CreateLog/Import.cshtml index fd213dc..6778261 100644 --- a/Web/Views/CreateLog/Import.cshtml +++ b/Web/Views/CreateLog/Import.cshtml @@ -1,4 +1,4 @@ -@model IList +@model IList @{ ViewBag.Title = "Import Logs"; diff --git a/Web/Views/CreateLog/ImportFix.cshtml b/Web/Views/CreateLog/ImportFix.cshtml index 8f15159..1b3ddec 100644 --- a/Web/Views/CreateLog/ImportFix.cshtml +++ b/Web/Views/CreateLog/ImportFix.cshtml @@ -1,4 +1,4 @@ -@model MileageTraker.Web.ViewModels.LogImportViewModel +@model MileageTraker.Web.ViewModels.CreateLog.ImportLogViewModel @{ Layout = null; } diff --git a/Web/Views/Log/Import.cshtml b/Web/Views/Log/Import.cshtml index f9fbb27..eff1208 100644 --- a/Web/Views/Log/Import.cshtml +++ b/Web/Views/Log/Import.cshtml @@ -1,4 +1,4 @@ -@model IList +@model IList @{ ViewBag.Title = "Import Logs"; diff --git a/Web/Views/Log/ImportFix.cshtml b/Web/Views/Log/ImportFix.cshtml index 0e37cee..d95c6e4 100644 --- a/Web/Views/Log/ImportFix.cshtml +++ b/Web/Views/Log/ImportFix.cshtml @@ -1,4 +1,4 @@ -@model MileageTraker.Web.ViewModels.LogImportViewModel +@model MileageTraker.Web.ViewModels.Log.ImportLogViewModel @{ Layout = null; } diff --git a/Web/Views/Shared/_Layout.cshtml b/Web/Views/Shared/_Layout.cshtml index b427023..9c9d91c 100644 --- a/Web/Views/Shared/_Layout.cshtml +++ b/Web/Views/Shared/_Layout.cshtml @@ -25,7 +25,7 @@