Service reminder implemented.
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Web.Mvc;
|
||||
using AutoMapper;
|
||||
using MileageTraker.Web.Attributes;
|
||||
using MileageTraker.Web.DAL;
|
||||
|
||||
namespace MileageTraker.Web.ViewModels.ServiceReminder
|
||||
{
|
||||
public class ServiceReminderViewModel
|
||||
public class ServiceReminderViewModel : IComparable<ServiceReminderViewModel>, IValidatableObject
|
||||
{
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public int? ServiceReminderId { get; set; }
|
||||
@@ -19,17 +22,28 @@ namespace MileageTraker.Web.ViewModels.ServiceReminder
|
||||
[InputSize("mini")]
|
||||
public string VehicleId { get; set; }
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public int? CurrentOdometer { get; set; }
|
||||
|
||||
[InputSize("small")]
|
||||
public int TargetOdometer { get; set; }
|
||||
[Range(1, 500000, ErrorMessage = "Between 1 and 500k")]
|
||||
public int TargetOdometer { get; set; }
|
||||
|
||||
[StringLength(64)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public bool IsServiceOverdue { get { return ServiceDueInMiles <= 0; } }
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public int ServiceDueInMiles { get { return CurrentOdometer.HasValue ? TargetOdometer - CurrentOdometer.Value : int.MaxValue; } }
|
||||
|
||||
static ServiceReminderViewModel()
|
||||
{
|
||||
Mapper.CreateMap<ServiceReminderViewModel, Models.ServiceReminder>();
|
||||
Mapper.CreateMap<Models.ServiceReminder, ServiceReminderViewModel>()
|
||||
.ForMember(dest => dest.VehicleId, opt => opt.MapFrom(src => src.Vehicle.VehicleId));
|
||||
.ForMember(dest => dest.VehicleId, opt => opt.MapFrom(src => src.Vehicle.VehicleId))
|
||||
.ForMember(dest => dest.CurrentOdometer, opt => opt.MapFrom(src => src.Vehicle.CurrentOdometer));
|
||||
}
|
||||
|
||||
public ServiceReminderViewModel(Models.ServiceReminder serviceReminder)
|
||||
@@ -47,5 +61,32 @@ namespace MileageTraker.Web.ViewModels.ServiceReminder
|
||||
Mapper.Map(this, serviceReminder);
|
||||
return serviceReminder;
|
||||
}
|
||||
|
||||
public int CompareTo(ServiceReminderViewModel other)
|
||||
{
|
||||
return ServiceDueInMiles - other.ServiceDueInMiles;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
using (var dataService = new DataService())
|
||||
{
|
||||
var duplicateServiceReminder = dataService.FindDuplicateServiceReminder(VehicleId, TargetOdometer, Description);
|
||||
|
||||
if (duplicateServiceReminder != null)
|
||||
yield return new ValidationResult("Exact duplicate of this reminder already exists");
|
||||
|
||||
var vehicle = dataService.GetVehicle(VehicleId);
|
||||
|
||||
if (vehicle.InactiveDate.HasValue)
|
||||
yield return new ValidationResult("Vehicle is inactive, no service reminder permitted");
|
||||
|
||||
// no reminders for mileage less than the current odometer
|
||||
if (vehicle.CurrentOdometer.HasValue && TargetOdometer <= vehicle.CurrentOdometer)
|
||||
yield return new ValidationResult(
|
||||
string.Format("Target odometer {0} must be greater than current odometer {1}",
|
||||
TargetOdometer, vehicle.CurrentOdometer.Value), new[]{"TargetOdometer"});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ namespace MileageTraker.Web.ViewModels.Vehicle
|
||||
{
|
||||
public class VehicleResultsViewModel
|
||||
{
|
||||
public IEnumerable<Models.Vehicle> Vehicles { get; set; }
|
||||
public IEnumerable<VehicleViewModel> Vehicles { get; set; }
|
||||
public bool Inactive { get; set; }
|
||||
|
||||
public VehicleResultsViewModel(IEnumerable<Models.Vehicle> vehicles, bool activeInactive)
|
||||
public VehicleResultsViewModel(IEnumerable<VehicleViewModel> vehicles, bool activeInactive)
|
||||
{
|
||||
Vehicles = vehicles;
|
||||
Inactive = activeInactive;
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using AutoMapper;
|
||||
using MileageTraker.Web.Attributes;
|
||||
|
||||
namespace MileageTraker.Web.ViewModels.Vehicle
|
||||
{
|
||||
public class VehicleViewModel
|
||||
{
|
||||
[Required]
|
||||
[InputSize("mini")]
|
||||
public int Key { get; set; }
|
||||
|
||||
[Key]
|
||||
[Required]
|
||||
[StringLength(6, MinimumLength = 4, ErrorMessage = "Must be at least a 4 digit number")]
|
||||
[Display(Name = "EHTRA ID")]
|
||||
[RegularExpression(@"\d+", ErrorMessage = "Vehicle ID must be all numbers")]
|
||||
[InputSize("mini")]
|
||||
public string VehicleId { get; set; }
|
||||
|
||||
[Required]
|
||||
[RegularExpression(@"\d{4}", ErrorMessage = "Must be 4 numbers")]
|
||||
[InputSize("mini")]
|
||||
public string ModelYear { get; set; }
|
||||
|
||||
[Required]
|
||||
[InputSize("medium")]
|
||||
public string Make { get; set; }
|
||||
|
||||
[Display(Name = "Model")]
|
||||
[Required]
|
||||
[InputSize("medium")]
|
||||
public string CarModel { get; set; }
|
||||
|
||||
[InputSize("small")]
|
||||
public string Color { get; set; }
|
||||
|
||||
[Required]
|
||||
[RegularExpression(@"Car|Truck|SUV|Van", ErrorMessage = "Must be Car, Truck, SUV, or Van")]
|
||||
[FormatHint("Car, Truck, SUV or Van")]
|
||||
[InputSize("mini")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[Required]
|
||||
[Display(Name = "VIN")]
|
||||
[RegularExpression(@"[0-9A-HJ-NPR-Z]{17}", ErrorMessage = "VIN must be 17-characters, not including letters I, O or Q")]
|
||||
[InputSize("large")]
|
||||
public string Vin { get; set; }
|
||||
|
||||
[Required]
|
||||
[InputSize("small")]
|
||||
[Currency]
|
||||
public decimal Price { get; set; }
|
||||
|
||||
[Required]
|
||||
[RegularExpression(@"\d{1,2}/\d{2}", ErrorMessage = "PurDate must be in mm/yy format")]
|
||||
[InputSize("small")]
|
||||
[FormatHint("mm/yy")]
|
||||
public string PurDate { get; set; }
|
||||
|
||||
[DataType(DataType.DateTime)]
|
||||
[DisplayFormat(NullDisplayText = "Currently Active", DataFormatString = @"{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
|
||||
[InputSize("small")]
|
||||
[FormatHint("mm/dd/yyyy")]
|
||||
public DateTime? InactiveDate { get; set; }
|
||||
|
||||
[Required]
|
||||
[Display(Name = "Tag#")]
|
||||
[InputSize("small")]
|
||||
public string TagNumber { get; set; }
|
||||
|
||||
[Required]
|
||||
[InputSize("medium")]
|
||||
public string Prog { get; set; }
|
||||
|
||||
[RegularExpression(@"Unassigned|[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Please enter the full name")]
|
||||
[DisplayFormat(NullDisplayText = "Unassigned")]
|
||||
[FormatHint("Blank for Unassigned")]
|
||||
public string Assigned { get; set; }
|
||||
|
||||
[InputSize("medium")]
|
||||
public string Notes { get; set; }
|
||||
|
||||
[Display(Name = "Current Odometer", ShortName= "ODO")]
|
||||
[DisplayFormat(NullDisplayText = "?")]
|
||||
[InputSize("small")]
|
||||
public int? CurrentOdometer { get; set; }
|
||||
|
||||
[HiddenInput(DisplayValue = true)]
|
||||
public int? NextServiceOdometer { get; set; }
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public bool IsNextServiceOverdue
|
||||
{
|
||||
get { return NextServiceDueInMiles <= 0; }
|
||||
}
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public int NextServiceDueInMiles
|
||||
{
|
||||
get
|
||||
{
|
||||
return CurrentOdometer.HasValue && NextServiceOdometer.HasValue
|
||||
? NextServiceOdometer.Value - CurrentOdometer.Value
|
||||
: int.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static VehicleViewModel()
|
||||
{
|
||||
Mapper.CreateMap<VehicleViewModel, Models.Vehicle>();
|
||||
Mapper.CreateMap<Models.Vehicle, VehicleViewModel>()
|
||||
.ForMember(dest => dest.NextServiceOdometer,
|
||||
opt => opt.ResolveUsing(v =>
|
||||
v.ServiceReminders
|
||||
.OrderBy(s => s.TargetOdometer)
|
||||
.Select(s => (int?) s.TargetOdometer)
|
||||
.FirstOrDefault()
|
||||
));
|
||||
}
|
||||
|
||||
public VehicleViewModel(Models.Vehicle vehicle)
|
||||
{
|
||||
Mapper.Map(vehicle, this);
|
||||
}
|
||||
|
||||
public VehicleViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public Models.Vehicle GetVehicle()
|
||||
{
|
||||
var vehicle = new Models.Vehicle();
|
||||
Mapper.Map(this, vehicle);
|
||||
return vehicle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Web.Mvc;
|
||||
using AutoMapper;
|
||||
using MileageTraker.Web.Attributes;
|
||||
using MileageTraker.Web.DAL;
|
||||
using MileageTraker.Web.ViewModels.ServiceReminder;
|
||||
|
||||
namespace MileageTraker.Web.ViewModels.VehicleService
|
||||
{
|
||||
public class UpdateServiceRemindersViewModel : IValidatableObject
|
||||
{
|
||||
[Display(Name = "Existing Reminders")]
|
||||
public CheckBoxViewModel DeleteServiceReminders { get; set; }
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public int? ServiceReminderId { get; set; }
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
[Required]
|
||||
[Remote("Exists", "Vehicle", ErrorMessage = "ID not found")]
|
||||
[StringLength(6, MinimumLength = 4, ErrorMessage = "Must be at least a 4 digit number")]
|
||||
[Display(Name = "Vehicle ID")]
|
||||
[RegularExpression(@"\d+", ErrorMessage = "Vehicle ID must be all numbers")]
|
||||
[InputSize("mini")]
|
||||
public string VehicleId { get; set; }
|
||||
|
||||
[HiddenInput(DisplayValue = false)]
|
||||
public int? CurrentOdometer { get; set; }
|
||||
|
||||
[InputSize("small")]
|
||||
[Range(1, 500000, ErrorMessage = "Between 1 and 500k")]
|
||||
public int? TargetOdometer { get; set; }
|
||||
|
||||
[StringLength(64)]
|
||||
public string Description { get; set; }
|
||||
|
||||
static UpdateServiceRemindersViewModel()
|
||||
{
|
||||
Mapper.CreateMap<UpdateServiceRemindersViewModel, Models.ServiceReminder>();
|
||||
}
|
||||
|
||||
public Models.ServiceReminder GetServiceReminder()
|
||||
{
|
||||
if (!TargetOdometer.HasValue || TargetOdometer.Value == 0)
|
||||
return null;
|
||||
var serviceReminder = new Models.ServiceReminder();
|
||||
Mapper.Map(this, serviceReminder);
|
||||
return serviceReminder;
|
||||
}
|
||||
|
||||
public static string FormatServiceReminder(Models.ServiceReminder serviceReminder)
|
||||
{
|
||||
var s = "Target ODO: " + serviceReminder.TargetOdometer;
|
||||
if (!string.IsNullOrEmpty(serviceReminder.Description))
|
||||
s += " Description: " + serviceReminder.Description;
|
||||
return s;
|
||||
}
|
||||
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
if (!TargetOdometer.HasValue) yield break;
|
||||
|
||||
using (var dataService = new DataService())
|
||||
{
|
||||
var duplicateServiceReminder = dataService.FindDuplicateServiceReminder(VehicleId, TargetOdometer.Value, Description);
|
||||
|
||||
if (duplicateServiceReminder != null)
|
||||
yield return new ValidationResult("Exact duplicate of this reminder already exists");
|
||||
|
||||
var vehicle = dataService.GetVehicle(VehicleId);
|
||||
|
||||
if (vehicle.InactiveDate.HasValue)
|
||||
yield return new ValidationResult("Vehicle is inactive, no service reminder permitted");
|
||||
|
||||
// no reminders for mileage less than the current odometer
|
||||
if (vehicle.CurrentOdometer.HasValue && TargetOdometer <= vehicle.CurrentOdometer)
|
||||
yield return new ValidationResult(
|
||||
string.Format("Target odometer {0} must be greater than current odometer {1}",
|
||||
TargetOdometer, vehicle.CurrentOdometer.Value), new[] {"TargetOdometer"});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using MileageTraker.Web.ViewModels.ServiceReminder;
|
||||
|
||||
namespace MileageTraker.Web.ViewModels.VehicleService
|
||||
{
|
||||
public class VehicleServiceResultsViewModel
|
||||
{
|
||||
public IEnumerable<VehicleServiceViewModel> ServiceItems { get; set; }
|
||||
public IList<ServiceReminderViewModel> UpcomingServiceReminders { get; set; }
|
||||
public Dictionary<string, List<string>> AvailableYearMonths { get; set; }
|
||||
public IEnumerable<string> SelectedYearMonths
|
||||
{
|
||||
@@ -24,10 +26,12 @@ namespace MileageTraker.Web.ViewModels.VehicleService
|
||||
|
||||
public VehicleServiceResultsViewModel(
|
||||
IEnumerable<VehicleServiceViewModel> serviceItems,
|
||||
IList<ServiceReminderViewModel> upcomingServiceReminders,
|
||||
VehicleServiceQueryViewModel query,
|
||||
Dictionary<string, List<string>> availableYearMonths)
|
||||
{
|
||||
ServiceItems = serviceItems;
|
||||
UpcomingServiceReminders = upcomingServiceReminders;
|
||||
AvailableYearMonths = availableYearMonths;
|
||||
Year = query.Year.HasValue ? query.Year.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;
|
||||
Month = query.Month.HasValue ? query.Month.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;
|
||||
|
||||
@@ -21,8 +21,10 @@ namespace MileageTraker.Web.ViewModels.VehicleService
|
||||
|
||||
[DataType(DataType.DateTime)]
|
||||
[DisplayFormatAttribute(ApplyFormatInEditMode = true, DataFormatString = "{0:d}")]
|
||||
[DenyFutureDate(ErrorMessage = "Future date")]
|
||||
[FormatHint("mm/dd/yyyy")]
|
||||
[InputSize("small")]
|
||||
[Required]
|
||||
public DateTime? InvoiceDate { get; set; }
|
||||
|
||||
[Required]
|
||||
|
||||
Reference in New Issue
Block a user