using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows.Input; namespace XLAB2 { internal sealed class PrsnDirectoryWindowViewModel : ObservableObject { private readonly IPrsnDirectoryDialogService _dialogService; private readonly PrsnDirectoryService _service; private bool _isBusy; private List _prsnCache; private string _searchText; private PrdspvDirectoryItem _selectedPrdspv; private PrfrDirectoryItem _selectedPrfr; private PrfrvdDirectoryItem _selectedPrfrvd; private PrsnDirectoryItem _selectedPrsn; private string _statusText; public PrsnDirectoryWindowViewModel(PrsnDirectoryService service, IPrsnDirectoryDialogService dialogService) { _service = service; _dialogService = dialogService; _prsnCache = new List(); PrsnItems = new ObservableCollection(); PrfrItems = new ObservableCollection(); PrfrvdItems = new ObservableCollection(); PrdspvItems = new ObservableCollection(); AddPrsnCommand = new RelayCommand(delegate { AddPrsnAsync(); }, delegate { return !IsBusy; }); EditPrsnCommand = new RelayCommand(delegate { EditPrsnAsync(); }, delegate { return !IsBusy && SelectedPrsn != null; }); DeletePrsnCommand = new RelayCommand(delegate { DeletePrsnAsync(); }, delegate { return !IsBusy && SelectedPrsn != null; }); AddPrfrCommand = new RelayCommand(delegate { AddPrfrAsync(); }, delegate { return !IsBusy && SelectedPrsn != null; }); EditPrfrCommand = new RelayCommand(delegate { EditPrfrAsync(); }, delegate { return !IsBusy && SelectedPrfr != null; }); DeletePrfrCommand = new RelayCommand(delegate { DeletePrfrAsync(); }, delegate { return !IsBusy && SelectedPrfr != null; }); AddPrfrvdCommand = new RelayCommand(delegate { AddPrfrvdAsync(); }, delegate { return !IsBusy && SelectedPrfr != null; }); EditPrfrvdCommand = new RelayCommand(delegate { EditPrfrvdAsync(); }, delegate { return !IsBusy && SelectedPrfrvd != null; }); DeletePrfrvdCommand = new RelayCommand(delegate { DeletePrfrvdAsync(); }, delegate { return !IsBusy && SelectedPrfrvd != null; }); AddPrdspvCommand = new RelayCommand(delegate { AddPrdspvAsync(); }, delegate { return !IsBusy && SelectedPrfr != null; }); EditPrdspvCommand = new RelayCommand(delegate { EditPrdspvAsync(); }, delegate { return !IsBusy && SelectedPrdspv != null; }); DeletePrdspvCommand = new RelayCommand(delegate { DeletePrdspvAsync(); }, delegate { return !IsBusy && SelectedPrdspv != null; }); RefreshCommand = new RelayCommand(delegate { RefreshAsync(); }, delegate { return !IsBusy; }); UpdateStatus(); } public ICommand AddPrdspvCommand { get; private set; } public ICommand AddPrfrCommand { get; private set; } public ICommand AddPrfrvdCommand { get; private set; } public ICommand AddPrsnCommand { get; private set; } public ICommand DeletePrdspvCommand { get; private set; } public ICommand DeletePrfrCommand { get; private set; } public ICommand DeletePrfrvdCommand { get; private set; } public ICommand DeletePrsnCommand { get; private set; } public ICommand EditPrdspvCommand { get; private set; } public ICommand EditPrfrCommand { get; private set; } public ICommand EditPrfrvdCommand { get; private set; } public ICommand EditPrsnCommand { get; private set; } public ObservableCollection PrdspvItems { get; private set; } public ObservableCollection PrfrItems { get; private set; } public ObservableCollection PrfrvdItems { get; private set; } public ObservableCollection PrsnItems { get; private set; } public ICommand RefreshCommand { get; private set; } public bool IsBusy { get { return _isBusy; } private set { if (SetProperty(ref _isBusy, value)) { RaiseCommandStates(); } } } public string SearchText { get { return _searchText; } set { if (SetProperty(ref _searchText, value)) { ApplySearchFilter(); UpdateStatus(); } } } public PrdspvDirectoryItem SelectedPrdspv { get { return _selectedPrdspv; } set { if (SetProperty(ref _selectedPrdspv, value)) { RaiseCommandStates(); UpdateStatus(); } } } public PrfrDirectoryItem SelectedPrfr { get { return _selectedPrfr; } set { if (SetProperty(ref _selectedPrfr, value)) { RaiseCommandStates(); LoadLeafTablesForSelection(); UpdateStatus(); } } } public PrfrvdDirectoryItem SelectedPrfrvd { get { return _selectedPrfrvd; } set { if (SetProperty(ref _selectedPrfrvd, value)) { RaiseCommandStates(); UpdateStatus(); } } } public PrsnDirectoryItem SelectedPrsn { get { return _selectedPrsn; } set { if (SetProperty(ref _selectedPrsn, value)) { RaiseCommandStates(); LoadPrfrForSelection(); UpdateStatus(); } } } public string StatusText { get { return _statusText; } private set { SetProperty(ref _statusText, value); } } public async Task InitializeAsync() { await ExecuteBusyOperationAsync(async delegate { await RefreshPrsnCoreAsync(null, null, null, null); }); } private void AddPrdspvAsync() { if (SelectedPrfr == null) { return; } var result = _dialogService.ShowPrdspvEditDialog(new PrdspvDirectoryItem { EmploymentId = SelectedPrfr.EmploymentId }, true, PrdspvItems.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { var createdId = await Task.Run(delegate { return _service.AddPrdspvItem(result); }); await RefreshPrsnCoreAsync(SelectedPrsn == null ? (int?)null : SelectedPrsn.Id, result.EmploymentId, SelectedPrfrvd == null ? (int?)null : SelectedPrfrvd.Id, createdId); _dialogService.ShowInfo("Запись PRDSPV добавлена."); }); } private void AddPrfrAsync() { if (SelectedPrsn == null) { return; } var result = _dialogService.ShowPrfrEditDialog(new PrfrDirectoryItem { PersonId = SelectedPrsn.Id }, true, PrfrItems.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { var createdId = await Task.Run(delegate { return _service.AddPrfrItem(result); }); await RefreshPrsnCoreAsync(result.PersonId, createdId, null, null); _dialogService.ShowInfo("Запись PRFR добавлена."); }); } private void AddPrfrvdAsync() { if (SelectedPrfr == null) { return; } var result = _dialogService.ShowPrfrvdEditDialog(new PrfrvdDirectoryItem { EmploymentId = SelectedPrfr.EmploymentId }, true, PrfrvdItems.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { var createdId = await Task.Run(delegate { return _service.AddPrfrvdItem(result); }); await RefreshPrsnCoreAsync(SelectedPrsn == null ? (int?)null : SelectedPrsn.Id, result.EmploymentId, createdId, SelectedPrdspv == null ? (int?)null : SelectedPrdspv.Id); _dialogService.ShowInfo("Запись PRFRVD добавлена."); }); } private void AddPrsnAsync() { var result = _dialogService.ShowPrsnEditDialog(new PrsnDirectoryItem(), true, _prsnCache.ToList()); if (result == null) { return; } RunMutationOperation(async delegate { var createdId = await Task.Run(delegate { return _service.AddPrsnItem(result); }); await RefreshPrsnCoreAsync(createdId, null, null, null); _dialogService.ShowInfo("Запись PRSN добавлена."); }); } private void ApplyPrsnFilter(int? preferredId) { var filteredItems = _prsnCache.Where(delegate(PrsnDirectoryItem item) { return MatchesSearch(item); }).ToList(); PrsnItems.Clear(); foreach (var item in filteredItems) { PrsnItems.Add(item); } SelectedPrsn = preferredId.HasValue ? PrsnItems.FirstOrDefault(delegate(PrsnDirectoryItem item) { return item.Id == preferredId.Value; }) : PrsnItems.FirstOrDefault(); } private void ApplySearchFilter() { if (!IsBusy) { ApplyPrsnFilter(SelectedPrsn == null ? (int?)null : SelectedPrsn.Id); } } private static PrdspvDirectoryItem ClonePrdspv(PrdspvDirectoryItem source) { return new PrdspvDirectoryItem { EmploymentId = source.EmploymentId, Id = source.Id, Notes = source.Notes, ReceivedOn = source.ReceivedOn, StampCode = source.StampCode, StampTypeId = source.StampTypeId, StampTypeName = source.StampTypeName }; } private static PrfrDirectoryItem ClonePrfr(PrfrDirectoryItem source) { return new PrfrDirectoryItem { DismissalDate = source.DismissalDate, EmploymentId = source.EmploymentId, Guid = source.Guid, HireDate = source.HireDate, IsPinAuth = source.IsPinAuth, LastVacationEndDate = source.LastVacationEndDate, LastVacationStartDate = source.LastVacationStartDate, NextVacationEndDate = source.NextVacationEndDate, NextVacationStartDate = source.NextVacationStartDate, OrganizationId = source.OrganizationId, OrganizationName = source.OrganizationName, PersonId = source.PersonId, PersonnelNumber = source.PersonnelNumber, PinChangedAt = source.PinChangedAt, PinHash = source.PinHash, PositionId = source.PositionId, PositionName = source.PositionName, PositionStartDate = source.PositionStartDate, QualificationPlanDate = source.QualificationPlanDate }; } private static PrfrvdDirectoryItem ClonePrfrvd(PrfrvdDirectoryItem source) { return new PrfrvdDirectoryItem { ActivityId = source.ActivityId, ActivityName = source.ActivityName, EmploymentId = source.EmploymentId, Id = source.Id }; } private static PrsnDirectoryItem ClonePrsn(PrsnDirectoryItem source) { return new PrsnDirectoryItem { Email = source.Email, ExternalId = source.ExternalId, FirstName = source.FirstName, FullName = source.FullName, Guid = source.Guid, Id = source.Id, LastName = source.LastName, Notes = source.Notes, Patronymic = source.Patronymic, Phone = source.Phone }; } private void DeletePrdspvAsync() { if (SelectedPrdspv == null) { return; } var selected = SelectedPrdspv; if (!_dialogService.Confirm(string.Format("Удалить клеймо \"{0}\"?", selected.StampCode))) { return; } RunMutationOperation(async delegate { var result = await Task.Run(delegate { return _service.DeletePrdspvItem(selected.Id); }); if (!result.IsDeleted) { _dialogService.ShowWarning(result.WarningMessage); return; } await RefreshPrsnCoreAsync(SelectedPrsn == null ? (int?)null : SelectedPrsn.Id, selected.EmploymentId, SelectedPrfrvd == null ? (int?)null : SelectedPrfrvd.Id, null); _dialogService.ShowInfo("Запись PRDSPV удалена."); }); } private void DeletePrfrAsync() { if (SelectedPrfr == null) { return; } var selected = SelectedPrfr; if (!_dialogService.Confirm(string.Format("Удалить запись персонала в организации \"{0}\"?", selected.OrganizationName))) { return; } RunMutationOperation(async delegate { var result = await Task.Run(delegate { return _service.DeletePrfrItem(selected.EmploymentId); }); if (!result.IsDeleted) { _dialogService.ShowWarning(result.WarningMessage); return; } await RefreshPrsnCoreAsync(selected.PersonId, null, null, null); _dialogService.ShowInfo("Запись PRFR удалена."); }); } private void DeletePrfrvdAsync() { if (SelectedPrfrvd == null) { return; } var selected = SelectedPrfrvd; if (!_dialogService.Confirm(string.Format("Удалить вид деятельности \"{0}\"?", selected.ActivityName))) { return; } RunMutationOperation(async delegate { var result = await Task.Run(delegate { return _service.DeletePrfrvdItem(selected.Id); }); if (!result.IsDeleted) { _dialogService.ShowWarning(result.WarningMessage); return; } await RefreshPrsnCoreAsync(SelectedPrsn == null ? (int?)null : SelectedPrsn.Id, selected.EmploymentId, null, SelectedPrdspv == null ? (int?)null : SelectedPrdspv.Id); _dialogService.ShowInfo("Запись PRFRVD удалена."); }); } private void DeletePrsnAsync() { if (SelectedPrsn == null) { return; } var selected = SelectedPrsn; if (!_dialogService.Confirm(string.Format("Удалить персону \"{0}\"?", selected.FullName))) { return; } RunMutationOperation(async delegate { var result = await Task.Run(delegate { return _service.DeletePrsnItem(selected.Id); }); if (!result.IsDeleted) { _dialogService.ShowWarning(result.WarningMessage); return; } await RefreshPrsnCoreAsync(null, null, null, null); _dialogService.ShowInfo("Запись PRSN удалена."); }); } private async Task ExecuteBusyOperationAsync(Func operation) { try { IsBusy = true; await operation(); } catch (Exception ex) { _dialogService.ShowError(ex.Message); } finally { IsBusy = false; } } private async Task ExecuteMutationOperationAsync(Func operation) { try { IsBusy = true; await operation(); } catch (InvalidOperationException ex) { _dialogService.ShowWarning(ex.Message); } catch (Exception ex) { _dialogService.ShowError(ex.Message); } finally { IsBusy = false; } } private void EditPrdspvAsync() { if (SelectedPrdspv == null) { return; } var result = _dialogService.ShowPrdspvEditDialog(ClonePrdspv(SelectedPrdspv), false, PrdspvItems.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { await Task.Run(delegate { _service.UpdatePrdspvItem(result); }); await RefreshPrsnCoreAsync(SelectedPrsn == null ? (int?)null : SelectedPrsn.Id, result.EmploymentId, SelectedPrfrvd == null ? (int?)null : SelectedPrfrvd.Id, result.Id); _dialogService.ShowInfo("Запись PRDSPV обновлена."); }); } private void EditPrfrAsync() { if (SelectedPrfr == null) { return; } var result = _dialogService.ShowPrfrEditDialog(ClonePrfr(SelectedPrfr), false, PrfrItems.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { await Task.Run(delegate { _service.UpdatePrfrItem(result); }); await RefreshPrsnCoreAsync(result.PersonId, result.EmploymentId, SelectedPrfrvd == null ? (int?)null : SelectedPrfrvd.Id, SelectedPrdspv == null ? (int?)null : SelectedPrdspv.Id); _dialogService.ShowInfo("Запись PRFR обновлена."); }); } private void EditPrfrvdAsync() { if (SelectedPrfrvd == null) { return; } var result = _dialogService.ShowPrfrvdEditDialog(ClonePrfrvd(SelectedPrfrvd), false, PrfrvdItems.ToList(), _service); if (result == null) { return; } RunMutationOperation(async delegate { await Task.Run(delegate { _service.UpdatePrfrvdItem(result); }); await RefreshPrsnCoreAsync(SelectedPrsn == null ? (int?)null : SelectedPrsn.Id, result.EmploymentId, result.Id, SelectedPrdspv == null ? (int?)null : SelectedPrdspv.Id); _dialogService.ShowInfo("Запись PRFRVD обновлена."); }); } private void EditPrsnAsync() { if (SelectedPrsn == null) { return; } var result = _dialogService.ShowPrsnEditDialog(ClonePrsn(SelectedPrsn), false, _prsnCache.ToList()); if (result == null) { return; } RunMutationOperation(async delegate { await Task.Run(delegate { _service.UpdatePrsnItem(result); }); await RefreshPrsnCoreAsync(result.Id, SelectedPrfr == null ? (int?)null : SelectedPrfr.EmploymentId, SelectedPrfrvd == null ? (int?)null : SelectedPrfrvd.Id, SelectedPrdspv == null ? (int?)null : SelectedPrdspv.Id); _dialogService.ShowInfo("Запись PRSN обновлена."); }); } private string[] GetSearchTokens() { return (SearchText ?? string.Empty) .Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) .Select(delegate(string token) { return token.Trim().ToUpperInvariant(); }) .Where(delegate(string token) { return token.Length > 0; }) .ToArray(); } private void LoadLeafTablesForSelection() { if (!IsBusy) { RunBusyOperation(async delegate { if (SelectedPrfr == null) { PrfrvdItems.Clear(); PrdspvItems.Clear(); SelectedPrfrvd = null; SelectedPrdspv = null; UpdateStatus(); return; } await RefreshLeafTablesCoreAsync(SelectedPrfr.EmploymentId, null, null); }); } } private void LoadPrfrForSelection() { if (!IsBusy) { RunBusyOperation(async delegate { if (SelectedPrsn == null) { PrfrItems.Clear(); PrfrvdItems.Clear(); PrdspvItems.Clear(); SelectedPrfr = null; SelectedPrfrvd = null; SelectedPrdspv = null; UpdateStatus(); return; } await RefreshPrfrCoreAsync(SelectedPrsn.Id, null, null, null); }); } } private bool MatchesSearch(PrsnDirectoryItem item) { if (item == null) { return false; } var tokens = GetSearchTokens(); if (tokens.Length == 0) { return true; } var haystack = string.Join( " ", new[] { item.Id.ToString(), item.FullName, item.LastName, item.FirstName, item.Patronymic, item.Phone, item.Email, item.ExternalId, item.Guid, item.OrganizationNames, item.ActivityNames, item.StampNames, item.Notes } .Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })) .ToUpperInvariant(); return tokens.All(delegate(string token) { return haystack.IndexOf(token, StringComparison.Ordinal) >= 0; }); } private async Task RefreshLeafTablesCoreAsync(int employmentId, int? prfrvdIdToSelect, int? prdspvIdToSelect) { var prfrvdTask = Task.Run(delegate { return _service.LoadPrfrvdItems(employmentId); }); var prdspvTask = Task.Run(delegate { return _service.LoadPrdspvItems(employmentId); }); await Task.WhenAll(prfrvdTask, prdspvTask); PrfrvdItems.Clear(); foreach (var item in prfrvdTask.Result) { PrfrvdItems.Add(item); } PrdspvItems.Clear(); foreach (var item in prdspvTask.Result) { PrdspvItems.Add(item); } SelectedPrfrvd = prfrvdIdToSelect.HasValue ? PrfrvdItems.FirstOrDefault(delegate(PrfrvdDirectoryItem item) { return item.Id == prfrvdIdToSelect.Value; }) : PrfrvdItems.FirstOrDefault(); SelectedPrdspv = prdspvIdToSelect.HasValue ? PrdspvItems.FirstOrDefault(delegate(PrdspvDirectoryItem item) { return item.Id == prdspvIdToSelect.Value; }) : PrdspvItems.FirstOrDefault(); UpdateStatus(); } private async Task RefreshPrfrCoreAsync(int personId, int? prfrIdToSelect, int? prfrvdIdToSelect, int? prdspvIdToSelect) { var items = await Task.Run(delegate { return _service.LoadPrfrItems(personId); }); PrfrItems.Clear(); foreach (var item in items) { PrfrItems.Add(item); } SelectedPrfr = prfrIdToSelect.HasValue ? PrfrItems.FirstOrDefault(delegate(PrfrDirectoryItem item) { return item.EmploymentId == prfrIdToSelect.Value; }) : PrfrItems.FirstOrDefault(); if (SelectedPrfr == null) { PrfrvdItems.Clear(); PrdspvItems.Clear(); SelectedPrfrvd = null; SelectedPrdspv = null; UpdateStatus(); return; } await RefreshLeafTablesCoreAsync(SelectedPrfr.EmploymentId, prfrvdIdToSelect, prdspvIdToSelect); UpdateStatus(); } private async Task RefreshPrsnCoreAsync(int? prsnIdToSelect, int? prfrIdToSelect, int? prfrvdIdToSelect, int? prdspvIdToSelect) { var currentPrsnId = SelectedPrsn == null ? (int?)null : SelectedPrsn.Id; _prsnCache = (await Task.Run(delegate { return _service.LoadPrsnItems(); })).ToList(); ApplyPrsnFilter(prsnIdToSelect.HasValue ? prsnIdToSelect : currentPrsnId); if (SelectedPrsn == null) { PrfrItems.Clear(); PrfrvdItems.Clear(); PrdspvItems.Clear(); SelectedPrfr = null; SelectedPrfrvd = null; SelectedPrdspv = null; UpdateStatus(); return; } await RefreshPrfrCoreAsync(SelectedPrsn.Id, prfrIdToSelect, prfrvdIdToSelect, prdspvIdToSelect); UpdateStatus(); } private void RaiseCommandStates() { ((RelayCommand)AddPrsnCommand).RaiseCanExecuteChanged(); ((RelayCommand)EditPrsnCommand).RaiseCanExecuteChanged(); ((RelayCommand)DeletePrsnCommand).RaiseCanExecuteChanged(); ((RelayCommand)AddPrfrCommand).RaiseCanExecuteChanged(); ((RelayCommand)EditPrfrCommand).RaiseCanExecuteChanged(); ((RelayCommand)DeletePrfrCommand).RaiseCanExecuteChanged(); ((RelayCommand)AddPrfrvdCommand).RaiseCanExecuteChanged(); ((RelayCommand)EditPrfrvdCommand).RaiseCanExecuteChanged(); ((RelayCommand)DeletePrfrvdCommand).RaiseCanExecuteChanged(); ((RelayCommand)AddPrdspvCommand).RaiseCanExecuteChanged(); ((RelayCommand)EditPrdspvCommand).RaiseCanExecuteChanged(); ((RelayCommand)DeletePrdspvCommand).RaiseCanExecuteChanged(); ((RelayCommand)RefreshCommand).RaiseCanExecuteChanged(); } private void RefreshAsync() { RunBusyOperation(async delegate { await RefreshPrsnCoreAsync( SelectedPrsn == null ? (int?)null : SelectedPrsn.Id, SelectedPrfr == null ? (int?)null : SelectedPrfr.EmploymentId, SelectedPrfrvd == null ? (int?)null : SelectedPrfrvd.Id, SelectedPrdspv == null ? (int?)null : SelectedPrdspv.Id); }); } private async void RunBusyOperation(Func operation) { try { await ExecuteBusyOperationAsync(operation); } catch (Exception ex) { IsBusy = false; _dialogService.ShowError(ex.Message); } } private async void RunMutationOperation(Func operation) { try { await ExecuteMutationOperationAsync(operation); } catch (Exception ex) { IsBusy = false; _dialogService.ShowError(ex.Message); } } private void UpdateStatus() { var searchText = string.IsNullOrWhiteSpace(SearchText) ? null : SearchText.Trim(); StatusText = string.Format( "{0}PRSN: {1}/{2}. PRFR: {3}. PRFRVD: {4}. PRDSPV: {5}.", string.IsNullOrWhiteSpace(searchText) ? string.Empty : string.Format("Поиск: \"{0}\". ", searchText), PrsnItems.Count, _prsnCache.Count, PrfrItems.Count, PrfrvdItems.Count, PrdspvItems.Count); } } }