using System; using System.Collections.Generic; using System.Linq; using System.Windows.Input; namespace XLAB2 { internal sealed class TprmkEditWindowViewModel : ObservableObject { private readonly IReadOnlyList _existingItems; private string _costText; private string _extraCostText; private int _groupId; private int _organizationId; private int _placeId; private int _qualificationId; private string _rushMarkupText; private string _timeNormCode; private string _timeNormHoursText; private string _normDocHoursText; private string _validationMessage; private string _verificationCode; private int _verificationTypeId; private string _verifierCountText; public TprmkEditWindowViewModel(TprmkDirectoryItem seed, bool isNew, IReadOnlyList existingItems, TypeSizeDirectoryService service) { var source = seed ?? new TprmkDirectoryItem(); _existingItems = existingItems ?? Array.Empty(); Id = source.Id; TypeSizeId = source.TypeSizeId; IsNew = isNew; VerificationTypes = service.LoadSpvdmkReferences(); Organizations = service.LoadFrpdReferences(); Qualifications = WithEmpty(service.LoadSpkvReferences()); Groups = WithEmpty(service.LoadGrsiReferences()); Places = WithEmpty(service.LoadSpmpobReferences()); VerificationTypeId = source.VerificationTypeId; OrganizationId = source.OrganizationId; QualificationId = source.QualificationId ?? 0; GroupId = source.GroupId ?? 0; PlaceId = source.PlaceId ?? 0; CostText = ToString(source.Cost); ExtraCostText = ToString(source.ExtraCost); RushMarkupText = ToString(source.RushMarkup); TimeNormHoursText = ToString(source.TimeNormHours); NormDocHoursText = ToString(source.NormDocHours); TimeNormCode = source.TimeNormCode ?? string.Empty; VerificationCode = source.VerificationCode ?? string.Empty; VerifierCountText = source.VerifierCount.ToString(); ConfirmCommand = new RelayCommand(Confirm); CancelCommand = new RelayCommand(Cancel); } public event EventHandler CloseRequested; public ICommand CancelCommand { get; private set; } public ICommand ConfirmCommand { get; private set; } public IReadOnlyList VerificationTypes { get; private set; } public IReadOnlyList Organizations { get; private set; } public IReadOnlyList Qualifications { get; private set; } public IReadOnlyList Groups { get; private set; } public IReadOnlyList Places { get; private set; } public int Id { get; private set; } public bool IsNew { get; private set; } public int TypeSizeId { get; private set; } public int VerificationTypeId { get { return _verificationTypeId; } set { SetProperty(ref _verificationTypeId, value); } } public int OrganizationId { get { return _organizationId; } set { SetProperty(ref _organizationId, value); } } public int QualificationId { get { return _qualificationId; } set { SetProperty(ref _qualificationId, value); } } public int GroupId { get { return _groupId; } set { SetProperty(ref _groupId, value); } } public int PlaceId { get { return _placeId; } set { SetProperty(ref _placeId, value); } } public string CostText { get { return _costText; } set { SetProperty(ref _costText, value); } } public string ExtraCostText { get { return _extraCostText; } set { SetProperty(ref _extraCostText, value); } } public string RushMarkupText { get { return _rushMarkupText; } set { SetProperty(ref _rushMarkupText, value); } } public string TimeNormHoursText { get { return _timeNormHoursText; } set { SetProperty(ref _timeNormHoursText, value); } } public string NormDocHoursText { get { return _normDocHoursText; } set { SetProperty(ref _normDocHoursText, value); } } public string TimeNormCode { get { return _timeNormCode; } set { SetProperty(ref _timeNormCode, value); } } public string VerificationCode { get { return _verificationCode; } set { SetProperty(ref _verificationCode, value); } } public string VerifierCountText { get { return _verifierCountText; } set { SetProperty(ref _verifierCountText, value); } } public string Title { get { return IsNew ? "Новый регламент МК" : "Редактирование регламента МК"; } } public string ValidationMessage { get { return _validationMessage; } private set { SetProperty(ref _validationMessage, value); } } public TprmkDirectoryItem ToResult() { return new TprmkDirectoryItem { Id = Id, TypeSizeId = TypeSizeId, VerificationTypeId = VerificationTypeId, OrganizationId = OrganizationId, QualificationId = QualificationId > 0 ? (int?)QualificationId : null, GroupId = GroupId > 0 ? (int?)GroupId : null, PlaceId = PlaceId > 0 ? (int?)PlaceId : null, Cost = ParseNullableDecimal(CostText), ExtraCost = ParseNullableDecimal(ExtraCostText), RushMarkup = ParseNullableDecimal(RushMarkupText), TimeNormHours = ParseNullableDecimal(TimeNormHoursText), NormDocHours = ParseNullableDecimal(NormDocHoursText), TimeNormCode = Normalize(TimeNormCode), VerificationCode = Normalize(VerificationCode), VerifierCount = int.Parse(VerifierCountText.Trim()) }; } private void Cancel(object parameter) { RaiseCloseRequested(false); } private void Confirm(object parameter) { if (VerificationTypeId <= 0) { ValidationMessage = "Укажите вид МК."; return; } if (OrganizationId <= 0) { ValidationMessage = "Укажите организацию/подразделение."; return; } int verifierCount; if (!int.TryParse((VerifierCountText ?? string.Empty).Trim(), out verifierCount)) { ValidationMessage = "Количество поверителей должно быть целым числом."; return; } decimal? value; if (!TryParseNullableDecimal(CostText, out value)) { ValidationMessage = "Стоимость должна быть числом."; return; } if (!TryParseNullableDecimal(ExtraCostText, out value)) { ValidationMessage = "Дополнительная стоимость должна быть числом."; return; } if (!TryParseNullableDecimal(RushMarkupText, out value)) { ValidationMessage = "Наценка за срочность должна быть числом."; return; } if (!TryParseNullableDecimal(TimeNormHoursText, out value)) { ValidationMessage = "Норма времени должна быть числом."; return; } if (!TryParseNullableDecimal(NormDocHoursText, out value)) { ValidationMessage = "Норма времени по НД должна быть числом."; return; } var timeNormCode = Normalize(TimeNormCode); if (!string.IsNullOrWhiteSpace(timeNormCode) && timeNormCode.Length > TprmkDirectoryRules.TimeNormCodeMaxLength) { ValidationMessage = string.Format("Код нормы не должен превышать {0} символов.", TprmkDirectoryRules.TimeNormCodeMaxLength); return; } var verificationCode = Normalize(VerificationCode); if (!string.IsNullOrWhiteSpace(verificationCode) && verificationCode.Length > TprmkDirectoryRules.VerificationCodeMaxLength) { ValidationMessage = string.Format("Код поверки не должен превышать {0} символов.", TprmkDirectoryRules.VerificationCodeMaxLength); return; } var duplicate = _existingItems.FirstOrDefault(delegate(TprmkDirectoryItem item) { return item != null && item.Id != Id && item.VerificationTypeId == VerificationTypeId && item.OrganizationId == OrganizationId && item.GroupId == (GroupId > 0 ? (int?)GroupId : null) && item.PlaceId == (PlaceId > 0 ? (int?)PlaceId : null); }); if (duplicate != null) { ValidationMessage = "Такой регламент МК уже существует для выбранного типоразмера."; return; } ValidationMessage = string.Empty; RaiseCloseRequested(true); } private static IReadOnlyList WithEmpty(IReadOnlyList source) { return new[] { new DirectoryLookupItem { Id = 0, Name = string.Empty } }.Concat(source ?? Array.Empty()).ToList(); } private static string Normalize(string value) { return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim(); } private static string ToString(decimal? value) { return value.HasValue ? value.Value.ToString("0.##") : string.Empty; } private static decimal? ParseNullableDecimal(string value) { decimal? parsed; return TryParseNullableDecimal(value, out parsed) ? parsed : (decimal?)null; } private static bool TryParseNullableDecimal(string value, out decimal? result) { if (string.IsNullOrWhiteSpace(value)) { result = null; return true; } decimal parsed; if (decimal.TryParse(value.Trim(), out parsed)) { result = parsed; return true; } result = null; return false; } private void RaiseCloseRequested(bool? dialogResult) { var handler = CloseRequested; if (handler != null) handler(this, dialogResult); } } }