Files
XLAB/XLAB2/MainWindowViewModel.cs
Курнат Андрей 22ed7d978a edit
2026-04-02 21:44:28 +03:00

2776 lines
107 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Input;
namespace XLAB2
{
internal sealed class MainWindowViewModel : ObservableObject
{
private readonly List<PsvDocumentSummary> _draftDocuments;
private readonly IDialogService _dialogService;
private readonly Dictionary<string, List<PsvDocumentLine>> _pendingLinesByDocumentKey;
private readonly PsvPrintService _printService;
private readonly PsvDataService _service;
private string _documentFilterText;
private string _documentNumberEditor;
private string _documentStatusText;
private string _detailTableCountText;
private string _groupFilterText;
private string _groupDetailFilterText;
private string _headerDepartmentName;
private int _headerInstrumentCount;
private DateTime? _headerIssuedOn;
private DateTime? _headerReceivedOn;
private bool _isBusy;
private string _lineStatusText;
private PsvDocumentLine _lastCloneSourceLine;
private int? _selectedCustomerId;
private PsvDocumentSummary _selectedDocument;
private PsvDocumentGroupSummary _selectedDocumentGroup;
private PsvDocumentLine _selectedDocumentLine;
private bool _showClosedDocuments;
public MainWindowViewModel(PsvDataService service, IDialogService dialogService)
{
_service = service;
_dialogService = dialogService;
_printService = new PsvPrintService();
_draftDocuments = new List<PsvDocumentSummary>();
_pendingLinesByDocumentKey = new Dictionary<string, List<PsvDocumentLine>>(StringComparer.OrdinalIgnoreCase);
Customers = new ObservableCollection<CustomerReference>();
Documents = new ObservableCollection<PsvDocumentSummary>();
DocumentLines = new ObservableCollection<PsvDocumentLine>();
DocumentGroupSummaries = new ObservableCollection<PsvDocumentGroupSummary>();
DocumentsView = CollectionViewSource.GetDefaultView(Documents);
DocumentsView.Filter = FilterDocuments;
DocumentGroupsView = CollectionViewSource.GetDefaultView(DocumentGroupSummaries);
DocumentGroupsView.Filter = FilterDocumentGroups;
DocumentLinesView = CollectionViewSource.GetDefaultView(DocumentLines);
DocumentLinesView.Filter = FilterDocumentLines;
AddDocumentCommand = new RelayCommand(delegate { AddDocument(); }, delegate { return !IsBusy && !ShowClosedDocuments; });
CloneLineVerificationCommand = new RelayCommand(delegate { CloneSelectedLineVerificationAsync(); }, delegate { return CanCloneSelectedLineVerification(); });
DeleteDocumentCommand = new RelayCommand(delegate { DeleteDocumentAsync(); }, delegate { return !IsBusy && SelectedDocument != null; });
DeleteSelectedLinesCommand = new RelayCommand(delegate { DeleteSelectedLinesAsync(); }, delegate { return CanDeleteSelectedLines(); });
DeleteSelectedGroupsCommand = new RelayCommand(delegate { DeleteSelectedGroupsAsync(); }, delegate { return CanDeleteSelectedGroups(); });
MarkLinePassedCommand = new RelayCommand(delegate { EditLineVerificationAsync(true); }, delegate { return CanEditSelectedLineVerification(); });
MarkLineRejectedCommand = new RelayCommand(delegate { EditLineVerificationAsync(false); }, delegate { return CanEditSelectedLineVerification(); });
OpenInstrumentPickerCommand = new RelayCommand(delegate { OpenInstrumentPickerAsync(); }, delegate { return CanAddInstrumentsToSelectedDocument(); });
OpenInstrumentTypePickerCommand = new RelayCommand(delegate { OpenInstrumentTypePickerAsync(); }, delegate { return CanAddInstrumentsToSelectedDocument(); });
PrintDocumentCommand = new RelayCommand(delegate { PrintSelectedDocumentAsync(); }, delegate { return CanPrintSelectedDocument(); });
PrintVerificationDocumentCommand = new RelayCommand(delegate { PrintSelectedVerificationDocumentAsync(); }, delegate { return CanPrintSelectedVerificationDocument(); });
RefreshDocumentsCommand = new RelayCommand(delegate { RefreshDocumentsAsync(null, null); }, delegate { return !IsBusy; });
ResetLineVerificationCommand = new RelayCommand(delegate { ResetSelectedLineVerificationAsync(); }, delegate { return CanResetSelectedLineVerification(); });
SaveDocumentHeaderCommand = new RelayCommand(delegate { SaveDocumentAsync(); }, delegate { return CanSaveDocument(); });
DocumentStatusText = "Готово.";
DetailTableCountText = "Приборов в таблице: 0.";
LineStatusText = "Документ не выбран.";
}
public ICommand AddDocumentCommand { get; private set; }
public ICommand CloneLineVerificationCommand { get; private set; }
public ObservableCollection<CustomerReference> Customers { get; private set; }
public string DocumentFilterText
{
get { return _documentFilterText; }
set
{
if (SetProperty(ref _documentFilterText, value))
{
DocumentsView.Refresh();
}
}
}
public bool ShowClosedDocuments
{
get { return _showClosedDocuments; }
set
{
if (!SetProperty(ref _showClosedDocuments, value))
{
return;
}
OnPropertyChanged("ShowOpenDocuments");
OnPropertyChanged("IsDocumentHeaderEditable");
RaiseCommandStates();
RefreshDocumentsAsync(null, null);
}
}
public bool ShowOpenDocuments
{
get { return !ShowClosedDocuments; }
set
{
if (value)
{
ShowClosedDocuments = false;
}
}
}
public ObservableCollection<PsvDocumentLine> DocumentLines { get; private set; }
public ICollectionView DocumentLinesView { get; private set; }
public string DocumentNumberEditor
{
get { return _documentNumberEditor; }
set { SetProperty(ref _documentNumberEditor, value); }
}
public ObservableCollection<PsvDocumentGroupSummary> DocumentGroupSummaries { get; private set; }
public ICollectionView DocumentGroupsView { get; private set; }
public string DocumentStatusText
{
get { return _documentStatusText; }
private set { SetProperty(ref _documentStatusText, value); }
}
public string DetailTableCountText
{
get { return _detailTableCountText; }
private set { SetProperty(ref _detailTableCountText, value); }
}
public ObservableCollection<PsvDocumentSummary> Documents { get; private set; }
public ICollectionView DocumentsView { get; private set; }
public ICommand DeleteDocumentCommand { get; private set; }
public ICommand DeleteSelectedLinesCommand { get; private set; }
public ICommand DeleteSelectedGroupsCommand { get; private set; }
public string GroupFilterText
{
get { return _groupFilterText; }
set
{
if (SetProperty(ref _groupFilterText, value))
{
RefreshDocumentGroupsView();
}
}
}
public string GroupDetailFilterText
{
get { return _groupDetailFilterText; }
set
{
if (SetProperty(ref _groupDetailFilterText, value))
{
RefreshDocumentLinesView();
}
}
}
public string HeaderDepartmentName
{
get { return _headerDepartmentName; }
private set { SetProperty(ref _headerDepartmentName, value); }
}
public int HeaderInstrumentCount
{
get { return _headerInstrumentCount; }
private set { SetProperty(ref _headerInstrumentCount, value); }
}
public bool IsDocumentHeaderEditable
{
get
{
return !IsBusy
&& SelectedDocument != null
&& !IsDocumentClosed(SelectedDocument);
}
}
public bool IsDocumentLinesReadOnly
{
get { return !CanModifySelectedDocument(); }
}
public DateTime? HeaderIssuedOn
{
get { return _headerIssuedOn; }
set { SetProperty(ref _headerIssuedOn, value); }
}
public DateTime? HeaderReceivedOn
{
get { return _headerReceivedOn; }
set { SetProperty(ref _headerReceivedOn, value); }
}
public bool IsBusy
{
get { return _isBusy; }
private set
{
if (SetProperty(ref _isBusy, value))
{
RaiseCommandStates();
OnPropertyChanged("IsCustomerEditable");
OnPropertyChanged("IsDocumentHeaderEditable");
OnPropertyChanged("IsDocumentLinesReadOnly");
}
}
}
public bool IsCustomerEditable
{
get
{
return !IsBusy
&& SelectedDocument != null
&& SelectedDocument.IsDraft
&& GetPendingLines(SelectedDocument).Count == 0;
}
}
public string LineStatusText
{
get { return _lineStatusText; }
private set { SetProperty(ref _lineStatusText, value); }
}
public ICommand MarkLinePassedCommand { get; private set; }
public ICommand MarkLineRejectedCommand { get; private set; }
public ICommand OpenInstrumentPickerCommand { get; private set; }
public ICommand OpenInstrumentTypePickerCommand { get; private set; }
public ICommand PrintDocumentCommand { get; private set; }
public ICommand PrintVerificationDocumentCommand { get; private set; }
public ICommand RefreshDocumentsCommand { get; private set; }
public ICommand ResetLineVerificationCommand { get; private set; }
public ICommand SaveDocumentHeaderCommand { get; private set; }
public int? SelectedCustomerId
{
get { return _selectedCustomerId; }
set
{
if (!SetProperty(ref _selectedCustomerId, value))
{
return;
}
ApplySelectedCustomer();
}
}
public PsvDocumentSummary SelectedDocument
{
get { return _selectedDocument; }
set
{
if (SetProperty(ref _selectedDocument, value))
{
_lastCloneSourceLine = null;
FillHeaderFromSelection();
RaiseCommandStates();
OnPropertyChanged("IsCustomerEditable");
OnPropertyChanged("IsDocumentHeaderEditable");
OnPropertyChanged("IsDocumentLinesReadOnly");
LoadSelectedDocumentAsync();
}
}
}
public PsvDocumentGroupSummary SelectedDocumentGroup
{
get { return _selectedDocumentGroup; }
set
{
if (SetProperty(ref _selectedDocumentGroup, value))
{
RefreshDocumentLinesView();
}
}
}
public PsvDocumentLine SelectedDocumentLine
{
get { return _selectedDocumentLine; }
set
{
if (SetProperty(ref _selectedDocumentLine, value))
{
if (CanUseLineAsCloneSource(value))
{
_lastCloneSourceLine = value;
}
RaiseCommandStates();
}
}
}
public async Task InitializeAsync()
{
await ExecuteBusyOperationAsync(async delegate
{
await LoadCustomersCoreAsync();
await RefreshDocumentsCoreAsync(null, null);
});
}
private void AddDocument()
{
var request = _dialogService.ShowCreateDocumentDialog(new DocumentEditorResult
{
AcceptedOn = DateTime.Today,
IssuedOn = null,
DocumentNumber = string.Empty
});
if (request == null)
{
return;
}
if (string.IsNullOrWhiteSpace(request.DocumentNumber))
{
_dialogService.ShowWarning("Введите номер ПСВ.");
return;
}
if (DocumentExistsInCollections(request.DocumentNumber, null))
{
_dialogService.ShowWarning("ПСВ с таким номером уже есть в списке.");
return;
}
var draft = new PsvDocumentSummary
{
DocumentKey = Guid.NewGuid().ToString("N"),
DocumentNumber = request.DocumentNumber.Trim(),
AcceptedOn = request.AcceptedOn,
IssuedOn = null,
CustomerName = string.Empty,
CustomerId = null,
DepartmentName = string.Empty,
ItemCount = 0,
IssuedCount = 0,
PassedCount = 0,
FailedCount = 0,
IsDraft = true
};
_draftDocuments.Add(draft);
InsertDraftIntoCollection(draft);
DocumentsView.Refresh();
SelectedDocument = draft;
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
}
private void ApplySelectedCustomer()
{
if (SelectedDocument == null || !SelectedDocument.IsDraft)
{
return;
}
SelectedDocument.CustomerId = SelectedCustomerId;
var customer = Customers.FirstOrDefault(delegate(CustomerReference item) { return item.CustomerId == SelectedCustomerId; });
SelectedDocument.CustomerName = customer == null ? string.Empty : customer.CustomerName;
DocumentsView.Refresh();
RaiseCommandStates();
}
private bool CanSaveDocument()
{
if (IsBusy || SelectedDocument == null)
{
return false;
}
if (IsDocumentClosed(SelectedDocument))
{
return false;
}
if (!SelectedDocument.IsDraft)
{
return true;
}
return GetPendingLines(SelectedDocument).Count > 0;
}
private bool CanDeleteSelectedGroups()
{
return CanModifySelectedDocument()
&& GetDeleteTargetGroups().Count > 0;
}
private bool CanDeleteSelectedLines()
{
return CanModifySelectedDocument()
&& GetDeleteTargetLines().Count > 0;
}
private bool CanPrintSelectedDocument()
{
return !IsBusy
&& SelectedDocument != null
&& !SelectedDocument.IsDraft;
}
private bool CanEditSelectedLineVerification()
{
var targetLines = GetVerificationTargetLines();
return CanModifySelectedDocument()
&& targetLines.Count > 0
&& targetLines.All(delegate(PsvDocumentLine line) { return !HasVerificationData(line); });
}
private bool CanCloneSelectedLineVerification()
{
var sourceLine = ResolveCloneSourceLine();
return CanModifySelectedDocument()
&& CanUseLineAsCloneSource(sourceLine)
&& GetCheckedCloneTargetLines(sourceLine).Count > 0;
}
private bool CanPrintSelectedVerificationDocument()
{
return !IsBusy && HasPrintableVerificationDocument(SelectedDocumentLine);
}
private bool CanResetSelectedLineVerification()
{
var targetLines = GetVerificationTargetLines();
return CanModifySelectedDocument()
&& targetLines.Count > 0
&& targetLines.All(HasVerificationData);
}
private bool CanModifySelectedDocument()
{
return !IsBusy
&& SelectedDocument != null
&& !IsDocumentClosed(SelectedDocument);
}
private bool CanAddInstrumentsToSelectedDocument()
{
return CanModifySelectedDocument() && SelectedDocument.CustomerId.HasValue;
}
private static bool IsDocumentClosed(PsvDocumentSummary document)
{
return document != null && document.IssuedOn.HasValue;
}
private static string BuildSerialNumbersText(IEnumerable<PsvDocumentLine> lines)
{
var serialNumbers = (lines ?? Enumerable.Empty<PsvDocumentLine>())
.Select(delegate(PsvDocumentLine line)
{
return line == null || string.IsNullOrWhiteSpace(line.SerialNumber)
? null
: line.SerialNumber.Trim();
})
.Where(delegate(string serialNumber) { return !string.IsNullOrWhiteSpace(serialNumber); })
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(delegate(string serialNumber) { return serialNumber; }, StringComparer.OrdinalIgnoreCase)
.ToList();
return serialNumbers.Count == 0 ? string.Empty : string.Join(", ", serialNumbers.ToArray());
}
private static string BuildInstrumentNamesText(IEnumerable<PsvDocumentLine> lines)
{
var instrumentNames = (lines ?? Enumerable.Empty<PsvDocumentLine>())
.Select(delegate(PsvDocumentLine line)
{
return line == null || string.IsNullOrWhiteSpace(line.InstrumentName)
? null
: line.InstrumentName.Trim();
})
.Where(delegate(string instrumentName) { return !string.IsNullOrWhiteSpace(instrumentName); })
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(delegate(string instrumentName) { return instrumentName; }, StringComparer.OrdinalIgnoreCase)
.ToList();
return instrumentNames.Count == 0 ? string.Empty : string.Join("; ", instrumentNames.ToArray());
}
private static bool HasVerificationData(PsvDocumentLine line)
{
return line != null
&& (line.IsPassed.HasValue
|| line.VerificationPerformedOn.HasValue
|| line.VerifierId.HasValue
|| !string.IsNullOrWhiteSpace(line.StickerNumber)
|| line.VerificationDocumentFormId.HasValue
|| line.VerificationDocumentLinkTypeId.HasValue
|| !string.IsNullOrWhiteSpace(line.VerificationDocumentNumber)
|| line.VerificationDocumentDate.HasValue
|| !string.IsNullOrWhiteSpace(line.RejectionReason));
}
private static bool CanUseLineAsCloneSource(PsvDocumentLine line)
{
if (line == null || !line.IsPassed.HasValue || !line.VerifierId.HasValue)
{
return false;
}
if (!line.VerificationPerformedOn.HasValue && !line.VerificationDocumentDate.HasValue)
{
return false;
}
if (!line.IsPassed.Value
&& (string.IsNullOrWhiteSpace(line.RejectionReason)
|| string.IsNullOrWhiteSpace(line.VerificationDocumentNumber)))
{
return false;
}
if (!string.IsNullOrWhiteSpace(line.VerificationDocumentNumber)
&& (!line.VerificationDocumentFormId.HasValue || !line.VerificationDocumentLinkTypeId.HasValue))
{
return false;
}
return true;
}
private static bool HasPrintableVerificationDocument(PsvDocumentLine line)
{
if (line == null || !line.IsPassed.HasValue)
{
return false;
}
if (string.IsNullOrWhiteSpace(line.VerificationDocumentNumber))
{
return false;
}
if (!line.VerificationPerformedOn.HasValue && !line.VerificationDocumentDate.HasValue)
{
return false;
}
if (!line.IsPassed.Value && string.IsNullOrWhiteSpace(line.RejectionReason))
{
return false;
}
return true;
}
private bool CanEditVerificationFromDoubleClick(PsvDocumentLine line)
{
return CanModifySelectedDocument()
&& line != null
&& line.IsPassed.HasValue
&& HasVerificationData(line);
}
private List<PsvDocumentLine> GetCheckedDocumentLines()
{
return DocumentLinesView.Cast<object>()
.OfType<PsvDocumentLine>()
.Where(delegate(PsvDocumentLine line) { return line.IsBatchSelected; })
.ToList();
}
private List<PsvDocumentGroupSummary> GetCheckedDocumentGroups()
{
return DocumentGroupSummaries
.Where(delegate(PsvDocumentGroupSummary group) { return group.IsBatchSelected; })
.ToList();
}
private List<PsvDocumentGroupSummary> GetDeleteTargetGroups()
{
var checkedGroups = GetCheckedDocumentGroups();
if (checkedGroups.Count > 0)
{
return checkedGroups;
}
return SelectedDocumentGroup == null
? new List<PsvDocumentGroupSummary>()
: new List<PsvDocumentGroupSummary> { SelectedDocumentGroup };
}
private List<PsvDocumentLine> GetVerificationTargetLines()
{
var checkedLines = GetCheckedDocumentLines();
if (checkedLines.Count > 0)
{
return checkedLines;
}
return SelectedDocumentLine == null
? new List<PsvDocumentLine>()
: new List<PsvDocumentLine> { SelectedDocumentLine };
}
private List<PsvDocumentLine> GetDeleteTargetLines()
{
var checkedLines = GetCheckedDocumentLines();
if (checkedLines.Count > 0)
{
return checkedLines;
}
return SelectedDocumentLine == null
? new List<PsvDocumentLine>()
: new List<PsvDocumentLine> { SelectedDocumentLine };
}
private List<PsvDocumentLine> GetCheckedCloneTargetLines(PsvDocumentLine sourceLine)
{
if (sourceLine == null)
{
return new List<PsvDocumentLine>();
}
return GetCheckedDocumentLines()
.Where(delegate(PsvDocumentLine line)
{
return line != null
&& !ReferenceEquals(line, sourceLine)
&& BelongsToSameGroup(line, sourceLine);
})
.ToList();
}
private PsvDocumentLine ResolveCloneSourceLine()
{
if (CanUseLineAsCloneSource(SelectedDocumentLine))
{
return SelectedDocumentLine;
}
if (_lastCloneSourceLine != null
&& DocumentLines.Contains(_lastCloneSourceLine)
&& CanUseLineAsCloneSource(_lastCloneSourceLine))
{
return _lastCloneSourceLine;
}
var checkedSourceLines = GetCheckedDocumentLines()
.Where(CanUseLineAsCloneSource)
.ToList();
return checkedSourceLines.Count == 1 ? checkedSourceLines[0] : null;
}
private void ClearCollections<T>(ObservableCollection<T> collection)
{
collection.Clear();
}
private void ClearDocumentLines()
{
foreach (var line in DocumentLines.ToList())
{
UnsubscribeFromDocumentLine(line);
}
ClearCollections(DocumentLines);
HeaderInstrumentCount = 0;
}
private void ClearDocumentGroups()
{
foreach (var group in DocumentGroupSummaries.ToList())
{
UnsubscribeFromDocumentGroup(group);
}
ClearCollections(DocumentGroupSummaries);
}
private void SubscribeToDocumentLine(PsvDocumentLine line)
{
if (line == null)
{
return;
}
line.PropertyChanged -= DocumentLine_PropertyChanged;
line.PropertyChanged += DocumentLine_PropertyChanged;
}
private void SubscribeToDocumentGroup(PsvDocumentGroupSummary group)
{
if (group == null)
{
return;
}
group.PropertyChanged -= DocumentGroup_PropertyChanged;
group.PropertyChanged += DocumentGroup_PropertyChanged;
}
private void UnsubscribeFromDocumentLine(PsvDocumentLine line)
{
if (line == null)
{
return;
}
line.PropertyChanged -= DocumentLine_PropertyChanged;
}
private void UnsubscribeFromDocumentGroup(PsvDocumentGroupSummary group)
{
if (group == null)
{
return;
}
group.PropertyChanged -= DocumentGroup_PropertyChanged;
}
private void DocumentLine_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (string.Equals(e.PropertyName, "IsBatchSelected", StringComparison.Ordinal))
{
UpdateLineStatus();
RaiseCommandStates();
}
}
private void DocumentGroup_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (string.Equals(e.PropertyName, "IsBatchSelected", StringComparison.Ordinal))
{
RaiseCommandStates();
}
}
private void ClearHeader()
{
DocumentNumberEditor = string.Empty;
HeaderReceivedOn = null;
HeaderIssuedOn = null;
HeaderDepartmentName = string.Empty;
SelectedCustomerId = null;
}
private VerificationEditSeed CreateVerificationSeed(PsvDocumentLine line, bool isPassed, IReadOnlyList<DocumentFormReference> documentForms)
{
var selectedForm = documentForms == null
? null
: documentForms.FirstOrDefault(delegate(DocumentFormReference item)
{
return item.DocumentFormId == line.VerificationDocumentFormId;
});
return new VerificationEditSeed
{
DocumentForm = selectedForm,
IsPassed = isPassed,
RejectionReason = isPassed ? string.Empty : line.RejectionReason,
StickerNumber = isPassed ? line.StickerNumber : string.Empty,
VerificationDate = line.VerificationPerformedOn ?? line.VerificationDocumentDate ?? DateTime.Today,
VerificationDocumentNumber = line.VerificationDocumentNumber,
VerifierId = line.VerifierId
};
}
private CloneVerificationSeed CreateCloneVerificationSeed(PsvDocumentLine sourceLine)
{
var documentDisplay = string.IsNullOrWhiteSpace(sourceLine.VerificationDocumentDisplay)
? "не указан"
: sourceLine.VerificationDocumentDisplay;
var rejectionPart = sourceLine.IsPassed == false && !string.IsNullOrWhiteSpace(sourceLine.RejectionReason)
? string.Format(" Причина: {0}.", sourceLine.RejectionReason.Trim())
: string.Empty;
return new CloneVerificationSeed
{
SourceSerialNumber = sourceLine.SerialNumber,
VerificationSummary = string.Format(
"Результат: {0}. Дата поверки: {1:d}. Поверитель: {2}. Документ: {3}.{4}",
sourceLine.ResultText,
sourceLine.VerificationPerformedOn ?? sourceLine.VerificationDocumentDate ?? DateTime.Today,
string.IsNullOrWhiteSpace(sourceLine.VerifierName) ? "не указан" : sourceLine.VerifierName,
documentDisplay,
rejectionPart)
};
}
private VerificationEditResult CreateVerificationResultFromLine(PsvDocumentLine sourceLine)
{
return new VerificationEditResult
{
DocumentFormId = string.IsNullOrWhiteSpace(sourceLine.VerificationDocumentNumber)
? 0
: sourceLine.VerificationDocumentFormId.GetValueOrDefault(),
DocumentLinkTypeId = string.IsNullOrWhiteSpace(sourceLine.VerificationDocumentNumber)
? 0
: sourceLine.VerificationDocumentLinkTypeId.GetValueOrDefault(),
IsPassed = sourceLine.IsPassed.GetValueOrDefault(),
RejectionReason = string.IsNullOrWhiteSpace(sourceLine.RejectionReason) ? string.Empty : sourceLine.RejectionReason.Trim(),
StickerNumber = string.IsNullOrWhiteSpace(sourceLine.StickerNumber) ? string.Empty : sourceLine.StickerNumber.Trim(),
VerificationDate = sourceLine.VerificationPerformedOn ?? sourceLine.VerificationDocumentDate ?? DateTime.Today,
VerificationDocumentNumber = string.IsNullOrWhiteSpace(sourceLine.VerificationDocumentNumber) ? string.Empty : sourceLine.VerificationDocumentNumber.Trim(),
VerifierId = sourceLine.VerifierId.GetValueOrDefault(),
VerifierName = string.IsNullOrWhiteSpace(sourceLine.VerifierName) ? string.Empty : sourceLine.VerifierName
};
}
private bool Contains(string source, string filter)
{
return !string.IsNullOrWhiteSpace(source)
&& source.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0;
}
private static bool BelongsToSameGroup(PsvDocumentLine candidate, PsvDocumentLine sourceLine)
{
return candidate != null
&& sourceLine != null
&& string.Equals(candidate.InstrumentType ?? string.Empty, sourceLine.InstrumentType ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(candidate.RangeText ?? string.Empty, sourceLine.RangeText ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(candidate.RegistryNumber ?? string.Empty, sourceLine.RegistryNumber ?? string.Empty, StringComparison.OrdinalIgnoreCase);
}
private static string NormalizeSerialNumber(string serialNumber)
{
return string.IsNullOrWhiteSpace(serialNumber) ? string.Empty : serialNumber.Trim();
}
private static string BuildSerialNumberPreview(IEnumerable<string> serialNumbers)
{
var materialized = serialNumbers == null
? new List<string>()
: serialNumbers
.Where(delegate(string serialNumber) { return !string.IsNullOrWhiteSpace(serialNumber); })
.ToList();
var preview = materialized.Take(5).ToList();
if (preview.Count == 0)
{
return string.Empty;
}
var text = string.Join(", ", preview);
if (materialized.Count > preview.Count)
{
text += ", ...";
}
return text;
}
private string BuildOpenDocumentConflictMessage(IEnumerable<OpenDocumentConflictInfo> conflicts)
{
var materializedConflicts = NormalizeOpenDocumentConflicts(conflicts);
if (materializedConflicts.Count == 0)
{
return "Прибор уже находится в другой открытой ПСВ этого заказчика.";
}
var preview = materializedConflicts
.Take(5)
.Select(delegate(OpenDocumentConflictInfo conflict)
{
return string.Format("зав. № {0} -> {1}", conflict.SerialNumber, conflict.DocumentNumber);
})
.ToList();
var suffix = materializedConflicts.Count > preview.Count
? string.Format(" Еще конфликтов: {0}.", materializedConflicts.Count - preview.Count)
: string.Empty;
return string.Format(
"Приборы уже находятся в других открытых ПСВ этого заказчика: {0}.{1}",
string.Join("; ", preview.ToArray()),
suffix);
}
private List<OpenDocumentConflictInfo> FindOpenDocumentConflicts(IEnumerable<PsvDocumentLine> candidateLines)
{
if (SelectedDocument == null || !SelectedDocument.CustomerId.HasValue || candidateLines == null)
{
return new List<OpenDocumentConflictInfo>();
}
var conflicts = FindPendingOpenDocumentConflicts(SelectedDocument, candidateLines);
conflicts.AddRange(_service.FindOpenDocumentConflicts(
SelectedDocument.CustomerId.Value,
SelectedDocument.IsDraft ? null : SelectedDocument.DocumentNumber,
candidateLines));
return NormalizeOpenDocumentConflicts(conflicts);
}
private List<OpenDocumentConflictInfo> FindPendingOpenDocumentConflicts(PsvDocumentSummary currentDocument, IEnumerable<PsvDocumentLine> candidateLines)
{
if (currentDocument == null || !currentDocument.CustomerId.HasValue || candidateLines == null)
{
return new List<OpenDocumentConflictInfo>();
}
var candidateKeys = new HashSet<string>(
candidateLines
.Where(delegate(PsvDocumentLine line)
{
return line != null
&& line.TypeSizeId > 0
&& !string.IsNullOrWhiteSpace(line.SerialNumber);
})
.Select(delegate(PsvDocumentLine line) { return line.OpenDocumentConflictKey; }),
StringComparer.OrdinalIgnoreCase);
if (candidateKeys.Count == 0)
{
return new List<OpenDocumentConflictInfo>();
}
var conflicts = new List<OpenDocumentConflictInfo>();
foreach (var pendingLinesByDocument in _pendingLinesByDocumentKey)
{
if (MatchesPendingLinesStorageKey(currentDocument, pendingLinesByDocument.Key))
{
continue;
}
var otherDocument = Documents.FirstOrDefault(delegate(PsvDocumentSummary document)
{
return MatchesPendingLinesStorageKey(document, pendingLinesByDocument.Key);
});
if (otherDocument == null
|| !otherDocument.CustomerId.HasValue
|| otherDocument.CustomerId.Value != currentDocument.CustomerId.Value)
{
continue;
}
foreach (var otherLine in pendingLinesByDocument.Value.Where(delegate(PsvDocumentLine line)
{
return line != null
&& line.TypeSizeId > 0
&& !string.IsNullOrWhiteSpace(line.SerialNumber);
}))
{
if (!candidateKeys.Contains(otherLine.OpenDocumentConflictKey))
{
continue;
}
conflicts.Add(new OpenDocumentConflictInfo
{
DocumentNumber = otherDocument.DocumentNumber,
TypeSizeId = otherLine.TypeSizeId,
SerialNumber = otherLine.SerialNumber
});
}
}
return NormalizeOpenDocumentConflicts(conflicts);
}
private static List<OpenDocumentConflictInfo> NormalizeOpenDocumentConflicts(IEnumerable<OpenDocumentConflictInfo> conflicts)
{
return (conflicts ?? Enumerable.Empty<OpenDocumentConflictInfo>())
.Where(delegate(OpenDocumentConflictInfo conflict) { return conflict != null; })
.GroupBy(delegate(OpenDocumentConflictInfo conflict)
{
return string.Format(
"{0}|{1}|{2}",
conflict.DocumentNumber ?? string.Empty,
conflict.TypeSizeId,
conflict.SerialNumber ?? string.Empty);
}, StringComparer.OrdinalIgnoreCase)
.Select(delegate(IGrouping<string, OpenDocumentConflictInfo> group) { return group.First(); })
.OrderBy(delegate(OpenDocumentConflictInfo conflict) { return conflict.SerialNumber ?? string.Empty; })
.ThenBy(delegate(OpenDocumentConflictInfo conflict) { return conflict.DocumentNumber ?? string.Empty; })
.ToList();
}
private PsvDocumentLine CreatePendingLine(AvailableInstrumentItem item)
{
return new PsvDocumentLine
{
CardId = 0,
InstrumentId = item.InstrumentId,
TypeSizeId = item.TypeSizeId,
SerialNumber = item.SerialNumber,
InventoryNumber = item.InventoryNumber,
CustomerName = item.CustomerName,
InstrumentType = item.InstrumentType,
InstrumentName = item.InstrumentName,
MeasurementArea = item.MeasurementArea,
RangeText = item.RangeText,
RegistryNumber = item.RegistryNumber,
AccuracyText = item.AccuracyText,
VerificationType = string.Empty,
PeriodMonths = 0,
AcceptedOn = HeaderReceivedOn,
IssuedOn = null,
IsPassed = null,
VerificationPerformedOn = null,
VerifierId = null,
VerifierName = string.Empty,
StickerNumber = string.Empty,
VerificationDocumentFormId = null,
VerificationDocumentLinkTypeId = null,
VerificationDocumentNumber = string.Empty,
VerificationDocumentDate = null,
RejectionReason = string.Empty,
Notes = string.Empty,
IsPendingInsert = true
};
}
private PsvDocumentLine CreatePendingTypeLine(AvailableInstrumentItem item, string serialNumber)
{
return new PsvDocumentLine
{
CardId = 0,
InstrumentId = 0,
TypeSizeId = item.TypeSizeId,
SerialNumber = string.IsNullOrWhiteSpace(serialNumber) ? string.Empty : serialNumber.Trim(),
InventoryNumber = string.Empty,
CustomerName = SelectedDocument == null ? string.Empty : SelectedDocument.CustomerName,
InstrumentType = item.InstrumentType,
InstrumentName = item.InstrumentName,
MeasurementArea = item.MeasurementArea,
RangeText = item.RangeText,
RegistryNumber = item.RegistryNumber,
AccuracyText = item.AccuracyText,
VerificationType = string.Empty,
PeriodMonths = 0,
AcceptedOn = HeaderReceivedOn,
IssuedOn = null,
IsPassed = null,
VerificationPerformedOn = null,
VerifierId = null,
VerifierName = string.Empty,
StickerNumber = string.Empty,
VerificationDocumentFormId = null,
VerificationDocumentLinkTypeId = null,
VerificationDocumentNumber = string.Empty,
VerificationDocumentDate = null,
RejectionReason = string.Empty,
Notes = string.Empty,
IsPendingInsert = true
};
}
private static void ApplyVerificationResultCore(PsvDocumentLine line, VerificationEditResult result)
{
if (line == null || result == null)
{
return;
}
line.IsPassed = result.IsPassed;
line.VerificationPerformedOn = result.VerificationDate;
line.VerifierId = result.VerifierId;
line.VerifierName = result.VerifierName;
line.StickerNumber = result.IsPassed ? result.StickerNumber : string.Empty;
line.VerificationDocumentFormId = string.IsNullOrWhiteSpace(result.VerificationDocumentNumber) ? (int?)null : result.DocumentFormId;
line.VerificationDocumentLinkTypeId = string.IsNullOrWhiteSpace(result.VerificationDocumentNumber) ? (int?)null : result.DocumentLinkTypeId;
line.VerificationDocumentNumber = result.VerificationDocumentNumber;
line.VerificationDocumentDate = result.VerificationDate;
line.RejectionReason = result.IsPassed ? string.Empty : result.RejectionReason;
}
private void ApplyVerificationResultToLine(PsvDocumentLine line, VerificationEditResult result)
{
ApplyVerificationResultCore(line, result);
RefreshAfterLineVerificationChanged(line);
}
private static void ClearVerificationFromLineCore(PsvDocumentLine line)
{
if (line == null)
{
return;
}
line.IsPassed = null;
line.VerificationPerformedOn = null;
line.VerifierId = null;
line.VerifierName = string.Empty;
line.StickerNumber = string.Empty;
line.VerificationDocumentFormId = null;
line.VerificationDocumentLinkTypeId = null;
line.VerificationDocumentNumber = string.Empty;
line.VerificationDocumentDate = null;
line.RejectionReason = string.Empty;
}
private void ClearVerificationFromLine(PsvDocumentLine line)
{
ClearVerificationFromLineCore(line);
RefreshAfterLineVerificationChanged(line);
}
private void CloneSelectedLineVerificationAsync()
{
var sourceLine = ResolveCloneSourceLine();
if (!CanUseLineAsCloneSource(sourceLine))
{
_dialogService.ShowWarning("Выберите строку-источник с заполненной поверкой. Источник можно выделить строкой или отметить единственную подходящую строку чекбоксом.");
return;
}
var checkedLines = GetCheckedDocumentLines();
if (checkedLines.Count == 0)
{
_dialogService.ShowWarning("Отметьте чекбоксами строки, в которые нужно склонировать поверочные данные.");
return;
}
var includedSourceSerialNumber = checkedLines.Any(delegate(PsvDocumentLine line) { return ReferenceEquals(line, sourceLine); });
var matchedLines = GetCheckedCloneTargetLines(sourceLine);
var targetLines = matchedLines.Where(delegate(PsvDocumentLine line) { return !HasVerificationData(line); }).ToList();
var skippedWithExistingVerificationCount = matchedLines.Count - targetLines.Count;
if (targetLines.Count == 0)
{
ShowCloneVerificationResult(0, skippedWithExistingVerificationCount, includedSourceSerialNumber, true);
return;
}
var result = CreateVerificationResultFromLine(sourceLine);
var pendingLines = targetLines.Where(delegate(PsvDocumentLine line) { return line.IsPendingInsert; }).ToList();
var persistedCardIds = targetLines
.Where(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; })
.Select(delegate(PsvDocumentLine line) { return line.CardId; })
.Distinct()
.ToList();
if (persistedCardIds.Count == 0)
{
foreach (var pendingLine in pendingLines)
{
ApplyVerificationResultCore(pendingLine, result);
}
RefreshAfterLineVerificationChanged(sourceLine);
ShowCloneVerificationResult(targetLines.Count, skippedWithExistingVerificationCount, includedSourceSerialNumber, false);
return;
}
RunBusyOperation(async delegate
{
await _service.SaveLineVerificationAsync(persistedCardIds, result);
foreach (var pendingLine in pendingLines)
{
ApplyVerificationResultCore(pendingLine, result);
}
await ReloadSelectedDocumentLinesAsync();
ShowCloneVerificationResult(targetLines.Count, skippedWithExistingVerificationCount, includedSourceSerialNumber, false);
});
}
private void ShowCloneVerificationResult(
int clonedCount,
int skippedWithExistingVerificationCount,
bool includedSourceSerialNumber,
bool showWarning)
{
var messages = new List<string>();
if (clonedCount > 0)
{
messages.Add(string.Format("Клонировано поверок: {0}.", clonedCount));
}
if (skippedWithExistingVerificationCount > 0)
{
messages.Add(string.Format("Пропущено строк с уже заполненной поверкой: {0}.", skippedWithExistingVerificationCount));
}
if (includedSourceSerialNumber)
{
messages.Add("Номер строки-источника пропущен.");
}
if (messages.Count == 0)
{
messages.Add("Подходящих отмеченных строк для клонирования не найдено.");
}
var message = string.Join(" ", messages.ToArray());
if (showWarning || clonedCount == 0)
{
_dialogService.ShowWarning(message);
return;
}
_dialogService.ShowInfo(message);
}
private void EditLineVerificationAsync(bool isPassed)
{
var targetLines = GetVerificationTargetLines();
if (targetLines.Count == 0)
{
return;
}
EditLineVerificationCoreAsync(targetLines, isPassed);
}
public void TryEditVerificationFromDoubleClick(PsvDocumentLine line)
{
if (line == null)
{
return;
}
SelectedDocumentLine = line;
if (!CanEditVerificationFromDoubleClick(line))
{
return;
}
EditLineVerificationCoreAsync(new[] { line }, line.IsPassed.Value);
}
private async void EditLineVerificationCoreAsync(IReadOnlyList<PsvDocumentLine> targetLines, bool isPassed)
{
IReadOnlyList<DocumentFormReference> documentForms;
IReadOnlyList<PersonReference> verifiers;
try
{
IsBusy = true;
verifiers = await _service.LoadVerifiersAsync();
documentForms = await _service.LoadVerificationDocumentFormsAsync(isPassed);
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
return;
}
finally
{
IsBusy = false;
}
var seed = CreateVerificationSeed(targetLines[0], isPassed, documentForms);
var result = _dialogService.ShowVerificationDialog(seed, verifiers, documentForms);
if (result == null)
{
return;
}
var pendingLines = targetLines.Where(delegate(PsvDocumentLine line) { return line.IsPendingInsert; }).ToList();
var persistedCardIds = targetLines.Where(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; })
.Select(delegate(PsvDocumentLine line) { return line.CardId; })
.Distinct()
.ToList();
if (persistedCardIds.Count == 0)
{
foreach (var pendingLine in pendingLines)
{
ApplyVerificationResultCore(pendingLine, result);
pendingLine.IsBatchSelected = false;
}
RefreshAfterLineVerificationChanged(targetLines[0]);
return;
}
RunBusyOperation(async delegate
{
await _service.SaveLineVerificationAsync(persistedCardIds, result);
foreach (var pendingLine in pendingLines)
{
ApplyVerificationResultCore(pendingLine, result);
pendingLine.IsBatchSelected = false;
}
await ReloadSelectedDocumentLinesAsync();
});
}
private void RefreshAfterLineVerificationChanged(PsvDocumentLine line)
{
var previousGroup = SelectedDocumentGroup;
RebuildDocumentGroupSummaries(DocumentLines);
SelectedDocumentGroup = FindMatchingGroup(previousGroup) ?? DocumentGroupSummaries.FirstOrDefault();
RefreshDocumentLinesView();
SelectedDocumentLine = line;
RaiseCommandStates();
}
private void ResetSelectedLineVerificationAsync()
{
var targetLines = GetVerificationTargetLines();
if (targetLines.Count == 0)
{
return;
}
var pendingLines = targetLines.Where(delegate(PsvDocumentLine line) { return line.IsPendingInsert; }).ToList();
var persistedCardIds = targetLines.Where(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; })
.Select(delegate(PsvDocumentLine line) { return line.CardId; })
.Distinct()
.ToList();
if (persistedCardIds.Count == 0)
{
foreach (var pendingLine in pendingLines)
{
ClearVerificationFromLineCore(pendingLine);
pendingLine.IsBatchSelected = false;
}
RefreshAfterLineVerificationChanged(targetLines[0]);
return;
}
RunBusyOperation(async delegate
{
await _service.ResetLineVerificationAsync(persistedCardIds);
foreach (var pendingLine in pendingLines)
{
ClearVerificationFromLineCore(pendingLine);
pendingLine.IsBatchSelected = false;
}
await ReloadSelectedDocumentLinesAsync();
});
}
private void DeleteDocumentAsync()
{
if (SelectedDocument == null)
{
return;
}
var selectedDocument = SelectedDocument;
if (!_dialogService.Confirm(string.Format("Удалить ПСВ \"{0}\"?", selectedDocument.DocumentNumber)))
{
return;
}
if (selectedDocument.IsDraft)
{
DeleteDraftDocument(selectedDocument);
return;
}
RunBusyOperation(async delegate
{
var result = await _service.DeleteDocumentAsync(selectedDocument.DocumentNumber);
_pendingLinesByDocumentKey.Remove(GetPendingLinesStorageKey(selectedDocument));
await RefreshDocumentsCoreAsync(null, null);
_dialogService.ShowInfo(
string.Format(
"Удалено строк EKZMKFCTVL: {0}. Удалено строк EKZMK: {1}. Удалено связанных DMS: {2}.",
result.DeletedEkzMkFctvlCount,
result.DeletedEkzMkCount,
result.DeletedDmsCount));
});
}
private void DeleteDraftDocument(PsvDocumentSummary draft)
{
_draftDocuments.RemoveAll(delegate(PsvDocumentSummary item) { return item.DocumentKey == draft.DocumentKey; });
_pendingLinesByDocumentKey.Remove(GetPendingLinesStorageKey(draft));
Documents.Remove(draft);
DocumentsView.Refresh();
SelectedDocument = Documents.Count > 0 ? Documents[0] : null;
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
}
private void PrintSelectedDocumentAsync()
{
if (SelectedDocument == null)
{
return;
}
var selectedDocument = SelectedDocument;
if (selectedDocument.IsDraft)
{
_dialogService.ShowWarning("Черновик нельзя распечатать. Сначала сохраните ПСВ.");
return;
}
if (string.IsNullOrWhiteSpace(selectedDocument.DocumentNumber))
{
_dialogService.ShowWarning("Для печати не указан номер ПСВ.");
return;
}
RunBusyOperation(async delegate
{
var persistedLines = await _service.LoadDocumentLinesAsync(selectedDocument.DocumentNumber);
var linesToPrint = MergeDocumentLinesForPrint(selectedDocument, persistedLines);
if (linesToPrint.Count == 0)
{
_dialogService.ShowWarning("В выбранном ПСВ нет строк для печати.");
return;
}
_printService.PrintDocument(selectedDocument, linesToPrint);
});
}
private void DeleteSelectedGroupsAsync()
{
if (SelectedDocument == null)
{
return;
}
var targetGroups = GetDeleteTargetGroups();
if (targetGroups.Count == 0)
{
return;
}
var targetLines = DocumentLines
.Where(delegate(PsvDocumentLine line)
{
return targetGroups.Any(delegate(PsvDocumentGroupSummary group) { return group.Matches(line); });
})
.ToList();
if (targetLines.Count == 0)
{
_dialogService.ShowWarning("Для удаления не найдено строк выбранных групп.");
return;
}
if (!_dialogService.Confirm(string.Format(
"Удалить из ПСВ \"{0}\" групп: {1}, строк приборов: {2}?",
SelectedDocument.DocumentNumber,
targetGroups.Count,
targetLines.Count)))
{
return;
}
var selectedDocument = SelectedDocument;
var selectedDocumentKey = selectedDocument.DocumentKey;
var selectedDocumentNumber = selectedDocument.DocumentNumber;
RunBusyOperation(async delegate
{
var pendingLines = GetPendingLines(selectedDocument);
var pendingLinesToRemove = pendingLines
.Where(delegate(PsvDocumentLine line)
{
return line.IsPendingInsert
&& targetGroups.Any(delegate(PsvDocumentGroupSummary group) { return group.Matches(line); });
})
.ToList();
var persistedCardIds = targetLines
.Where(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; })
.Select(delegate(PsvDocumentLine line) { return line.CardId; })
.Distinct()
.ToList();
foreach (var pendingLine in pendingLinesToRemove)
{
pendingLines.Remove(pendingLine);
}
var deletedPendingCount = pendingLinesToRemove.Count;
var deletedResult = new DocumentGroupDeleteResult();
if (persistedCardIds.Count > 0)
{
deletedResult = await _service.DeleteDocumentGroupsAsync(selectedDocumentNumber, persistedCardIds);
}
var remainingPendingCount = pendingLines.Count;
var remainingPersistedCount = DocumentLines.Count(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; }) - persistedCardIds.Count;
if (selectedDocument.IsDraft)
{
UpdateDocumentSummaryFromLines(selectedDocument, pendingLines);
ApplyDocumentLines(pendingLines, SelectedDocumentGroup);
DocumentsView.Refresh();
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
}
else if (remainingPersistedCount == 0 && remainingPendingCount > 0)
{
if (!_draftDocuments.Any(delegate(PsvDocumentSummary draft) { return draft.DocumentKey == selectedDocumentKey; }))
{
_draftDocuments.Add(selectedDocument);
}
selectedDocument.IsDraft = true;
UpdateDocumentSummaryFromLines(selectedDocument, pendingLines);
await RefreshDocumentsCoreAsync(selectedDocumentKey, selectedDocumentNumber);
}
else
{
await RefreshDocumentsCoreAsync(selectedDocumentKey, selectedDocumentNumber);
}
var messages = new List<string>();
if (deletedPendingCount > 0)
{
messages.Add(string.Format("Удалено черновых строк: {0}.", deletedPendingCount));
}
if (deletedResult.DeletedEkzMkFctvlCount > 0)
{
messages.Add(string.Format("Удалено строк EKZMKFCTVL: {0}.", deletedResult.DeletedEkzMkFctvlCount));
}
if (deletedResult.DeletedEkzMkCount > 0)
{
messages.Add(string.Format("Удалено строк EKZMK: {0}.", deletedResult.DeletedEkzMkCount));
}
if (deletedResult.DeletedDmsCount > 0)
{
messages.Add(string.Format("Удалено связанных DMS: {0}.", deletedResult.DeletedDmsCount));
}
if (messages.Count > 0)
{
_dialogService.ShowInfo(string.Join(" ", messages.ToArray()));
}
});
}
private void DeleteSelectedLinesAsync()
{
if (SelectedDocument == null)
{
return;
}
var targetLines = GetDeleteTargetLines();
if (targetLines.Count == 0)
{
return;
}
if (!_dialogService.Confirm(string.Format(
"Удалить из ПСВ \"{0}\" строк приборов: {1}?",
SelectedDocument.DocumentNumber,
targetLines.Count)))
{
return;
}
var selectedDocument = SelectedDocument;
var selectedDocumentKey = selectedDocument.DocumentKey;
var selectedDocumentNumber = selectedDocument.DocumentNumber;
RunBusyOperation(async delegate
{
var pendingLines = GetPendingLines(selectedDocument);
var pendingLinesToRemove = pendingLines
.Where(delegate(PsvDocumentLine line) { return targetLines.Any(delegate(PsvDocumentLine targetLine) { return ReferenceEquals(line, targetLine); }); })
.ToList();
var persistedCardIds = targetLines
.Where(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; })
.Select(delegate(PsvDocumentLine line) { return line.CardId; })
.Distinct()
.ToList();
foreach (var pendingLine in pendingLinesToRemove)
{
pendingLines.Remove(pendingLine);
}
var deletedPendingCount = pendingLinesToRemove.Count;
var deletedResult = new DocumentGroupDeleteResult();
if (persistedCardIds.Count > 0)
{
deletedResult = await _service.DeleteDocumentGroupsAsync(selectedDocumentNumber, persistedCardIds);
}
var remainingPendingCount = pendingLines.Count;
var remainingPersistedCount = DocumentLines.Count(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; }) - persistedCardIds.Count;
if (selectedDocument.IsDraft)
{
UpdateDocumentSummaryFromLines(selectedDocument, pendingLines);
ApplyDocumentLines(pendingLines, SelectedDocumentGroup);
DocumentsView.Refresh();
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
}
else if (remainingPersistedCount == 0 && remainingPendingCount > 0)
{
if (!_draftDocuments.Any(delegate(PsvDocumentSummary draft) { return draft.DocumentKey == selectedDocumentKey; }))
{
_draftDocuments.Add(selectedDocument);
}
selectedDocument.IsDraft = true;
UpdateDocumentSummaryFromLines(selectedDocument, pendingLines);
await RefreshDocumentsCoreAsync(selectedDocumentKey, selectedDocumentNumber);
}
else
{
await RefreshDocumentsCoreAsync(selectedDocumentKey, selectedDocumentNumber);
}
var messages = new List<string>();
if (deletedPendingCount > 0)
{
messages.Add(string.Format("Удалено черновых строк: {0}.", deletedPendingCount));
}
if (deletedResult.DeletedEkzMkFctvlCount > 0)
{
messages.Add(string.Format("Удалено строк EKZMKFCTVL: {0}.", deletedResult.DeletedEkzMkFctvlCount));
}
if (deletedResult.DeletedEkzMkCount > 0)
{
messages.Add(string.Format("Удалено строк EKZMK: {0}.", deletedResult.DeletedEkzMkCount));
}
if (deletedResult.DeletedDmsCount > 0)
{
messages.Add(string.Format("Удалено связанных DMS: {0}.", deletedResult.DeletedDmsCount));
}
if (messages.Count > 0)
{
_dialogService.ShowInfo(string.Join(" ", messages.ToArray()));
}
});
}
private bool DocumentExistsInCollections(string documentNumber, string excludeDocumentKey)
{
return Documents.Any(delegate(PsvDocumentSummary document)
{
return !string.Equals(document.DocumentKey, excludeDocumentKey, StringComparison.OrdinalIgnoreCase)
&& string.Equals(document.DocumentNumber, documentNumber, StringComparison.OrdinalIgnoreCase);
});
}
private void PrintSelectedVerificationDocumentAsync()
{
var selectedLine = SelectedDocumentLine;
if (selectedLine == null)
{
_dialogService.ShowWarning("Сначала выберите строку прибора.");
return;
}
if (!HasPrintableVerificationDocument(selectedLine))
{
_dialogService.ShowWarning("Для выбранной строки не указан печатаемый документ по поверке.");
return;
}
RunBusyOperation(delegate
{
_printService.PrintVerificationDocument(selectedLine);
return Task.FromResult(0);
});
}
private static void UpdateDocumentSummaryFromLines(PsvDocumentSummary document, IEnumerable<PsvDocumentLine> lines)
{
if (document == null)
{
return;
}
var materializedLines = lines == null ? new List<PsvDocumentLine>() : lines.ToList();
document.ItemCount = materializedLines.Count;
document.PassedCount = materializedLines.Count(delegate(PsvDocumentLine line) { return line.IsPassed == true; });
document.FailedCount = materializedLines.Count(delegate(PsvDocumentLine line) { return line.IsPassed == false; });
document.IssuedCount = materializedLines.Count(delegate(PsvDocumentLine line) { return line.IssuedOn.HasValue; });
document.SerialNumbersText = BuildSerialNumbersText(materializedLines);
}
private async Task ExecuteBusyOperationAsync(Func<Task> operation)
{
if (IsBusy)
{
return;
}
try
{
IsBusy = true;
await operation();
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
}
finally
{
IsBusy = false;
}
}
private async void RunBusyOperation(Func<Task> operation)
{
await ExecuteBusyOperationAsync(operation);
}
private bool FilterDocuments(object item)
{
var document = item as PsvDocumentSummary;
if (document == null)
{
return false;
}
if (!string.IsNullOrWhiteSpace(DocumentFilterText)
&& !Contains(document.DocumentNumber, DocumentFilterText)
&& !Contains(document.CustomerName, DocumentFilterText)
&& !Contains(document.SerialNumbersText, DocumentFilterText))
{
return false;
}
return true;
}
private bool FilterDocumentGroups(object item)
{
var group = item as PsvDocumentGroupSummary;
if (group == null)
{
return false;
}
if (string.IsNullOrWhiteSpace(GroupFilterText))
{
return true;
}
return Contains(group.InstrumentName, GroupFilterText)
|| Contains(group.InstrumentType, GroupFilterText)
|| Contains(group.RangeText, GroupFilterText)
|| Contains(group.AccuracyText, GroupFilterText)
|| Contains(group.RegistryNumber, GroupFilterText)
|| Contains(group.SerialNumbersText, GroupFilterText);
}
private string BuildDocumentStatusText(int count)
{
if (ShowClosedDocuments)
{
return string.Format("Закрытых ПСВ за {0:yyyy}: {1}.", DateTime.Today, count);
}
return string.Format("Открытых ПСВ: {0}.", count);
}
private bool FilterDocumentLines(object item)
{
var line = item as PsvDocumentLine;
if (line == null || SelectedDocumentGroup == null)
{
return false;
}
if (!SelectedDocumentGroup.Matches(line))
{
return false;
}
if (string.IsNullOrWhiteSpace(GroupDetailFilterText))
{
return true;
}
return Contains(line.SerialNumber, GroupDetailFilterText);
}
private PsvDocumentGroupSummary FindMatchingGroup(PsvDocumentGroupSummary group)
{
if (group == null)
{
return null;
}
return DocumentGroupSummaries.FirstOrDefault(delegate(PsvDocumentGroupSummary current)
{
return AreSameGroup(current, group);
});
}
private PsvDocumentGroupSummary FindMatchingVisibleGroup(PsvDocumentGroupSummary group)
{
if (group == null)
{
return null;
}
return GetVisibleDocumentGroups().FirstOrDefault(delegate(PsvDocumentGroupSummary current)
{
return AreSameGroup(current, group);
});
}
private List<PsvDocumentGroupSummary> GetVisibleDocumentGroups()
{
return DocumentGroupsView == null
? new List<PsvDocumentGroupSummary>()
: DocumentGroupsView.Cast<object>().OfType<PsvDocumentGroupSummary>().ToList();
}
private static bool AreSameGroup(PsvDocumentGroupSummary left, PsvDocumentGroupSummary right)
{
return left != null
&& right != null
&& string.Equals(left.InstrumentType ?? string.Empty, right.InstrumentType ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(left.RangeText ?? string.Empty, right.RangeText ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(left.AccuracyText ?? string.Empty, right.AccuracyText ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(left.RegistryNumber ?? string.Empty, right.RegistryNumber ?? string.Empty, StringComparison.OrdinalIgnoreCase);
}
private void FillHeaderFromSelection()
{
if (SelectedDocument == null)
{
ClearHeader();
return;
}
DocumentNumberEditor = SelectedDocument.DocumentNumber;
HeaderReceivedOn = SelectedDocument.AcceptedOn;
HeaderIssuedOn = SelectedDocument.IssuedOn;
HeaderDepartmentName = SelectedDocument.DepartmentName;
SelectedCustomerId = SelectedDocument.CustomerId;
}
private List<PsvDocumentLine> GetPendingLines(PsvDocumentSummary document)
{
if (document == null)
{
return new List<PsvDocumentLine>();
}
var pendingKey = GetPendingLinesStorageKey(document);
if (string.IsNullOrWhiteSpace(pendingKey))
{
return new List<PsvDocumentLine>();
}
List<PsvDocumentLine> lines;
return _pendingLinesByDocumentKey.TryGetValue(pendingKey, out lines)
? lines
: new List<PsvDocumentLine>();
}
private static string GetPendingLinesStorageKey(PsvDocumentSummary document)
{
if (document == null)
{
return string.Empty;
}
if (!document.IsDraft && !string.IsNullOrWhiteSpace(document.DocumentNumber))
{
return document.DocumentNumber.Trim();
}
return string.IsNullOrWhiteSpace(document.DocumentKey)
? string.Empty
: document.DocumentKey.Trim();
}
private static bool MatchesPendingLinesStorageKey(PsvDocumentSummary document, string pendingKey)
{
return !string.IsNullOrWhiteSpace(pendingKey)
&& string.Equals(GetPendingLinesStorageKey(document), pendingKey, StringComparison.OrdinalIgnoreCase);
}
private List<PsvDocumentLine> MergeDocumentLinesForPrint(PsvDocumentSummary document, IEnumerable<PsvDocumentLine> persistedLines)
{
var mergedLines = new List<PsvDocumentLine>();
if (persistedLines != null)
{
mergedLines.AddRange(persistedLines);
}
mergedLines.AddRange(GetPendingLines(document));
return mergedLines;
}
private PsvDocumentSummary CreateSavedDocumentSummaryForPrint(PsvDocumentSummary source, DocumentEditorResult request)
{
return new PsvDocumentSummary
{
DocumentKey = source == null ? null : source.DocumentKey,
DocumentNumber = request == null ? string.Empty : request.DocumentNumber,
AcceptedOn = request == null ? (DateTime?)null : request.AcceptedOn,
IssuedOn = request == null ? (DateTime?)null : request.IssuedOn,
CustomerId = request == null ? null : request.CustomerId,
CustomerName = ResolveCustomerNameForPrint(source, request),
DepartmentName = source == null ? string.Empty : source.DepartmentName,
IsDraft = false
};
}
private string ResolveCustomerNameForPrint(PsvDocumentSummary source, DocumentEditorResult request)
{
if (source != null && !string.IsNullOrWhiteSpace(source.CustomerName))
{
return source.CustomerName;
}
if (request != null && request.CustomerId.HasValue)
{
var customer = Customers.FirstOrDefault(delegate(CustomerReference item) { return item.CustomerId == request.CustomerId.Value; });
if (customer != null)
{
return customer.CustomerName;
}
}
return string.Empty;
}
private void InsertDraftIntoCollection(PsvDocumentSummary draft)
{
var insertIndex = 0;
while (insertIndex < Documents.Count
&& (Documents[insertIndex].AcceptedOn ?? DateTime.MinValue) >= (draft.AcceptedOn ?? DateTime.MinValue))
{
insertIndex++;
}
Documents.Insert(insertIndex, draft);
}
private async Task LoadCustomersCoreAsync()
{
var customers = await _service.LoadCustomersAsync();
ClearCollections(Customers);
foreach (var customer in customers)
{
Customers.Add(customer);
}
}
private async void LoadSelectedDocumentAsync()
{
if (SelectedDocument == null)
{
ClearDocumentLines();
ClearDocumentGroups();
SelectedDocumentGroup = null;
SelectedDocumentLine = null;
LineStatusText = "Документ не выбран.";
return;
}
try
{
await ReloadSelectedDocumentLinesAsync();
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
}
}
private async Task ReloadSelectedDocumentLinesAsync()
{
if (SelectedDocument == null)
{
ClearDocumentLines();
ClearDocumentGroups();
SelectedDocumentGroup = null;
SelectedDocumentLine = null;
return;
}
if (SelectedDocument.IsDraft)
{
ApplyDocumentLines(GetPendingLines(SelectedDocument), SelectedDocumentGroup);
return;
}
LineStatusText = "Загрузка строк документа...";
var previousGroup = SelectedDocumentGroup;
var documentNumber = SelectedDocument.DocumentNumber;
var persistedLines = await _service.LoadDocumentLinesAsync(documentNumber);
var mergedLines = persistedLines.Concat(GetPendingLines(SelectedDocument)).ToList();
ApplyDocumentLines(mergedLines, previousGroup);
}
private void OpenInstrumentPickerAsync()
{
if (SelectedDocument == null)
{
return;
}
if (!SelectedDocument.CustomerId.HasValue)
{
_dialogService.ShowWarning("Сначала выберите заказчика в ПСВ.");
return;
}
OpenInstrumentPickerCoreAsync(SelectedDocument.CustomerId.Value, SelectedDocument.CustomerName);
}
private async void OpenInstrumentPickerCoreAsync(int customerId, string customerName)
{
IReadOnlyList<AvailableInstrumentItem> instruments;
try
{
IsBusy = true;
instruments = await _service.LoadCustomerInstrumentsAsync(customerId);
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
return;
}
finally
{
IsBusy = false;
}
var selectedItems = _dialogService.ShowInstrumentPickerDialog(customerName, instruments);
if (selectedItems == null || selectedItems.Count == 0)
{
return;
}
AddSelectedInstruments(selectedItems);
}
private void OpenInstrumentTypePickerAsync()
{
if (SelectedDocument == null)
{
return;
}
if (!SelectedDocument.CustomerId.HasValue)
{
_dialogService.ShowWarning("Сначала выберите заказчика в ПСВ.");
return;
}
OpenInstrumentTypePickerCoreAsync(SelectedDocument.CustomerName);
}
private async void OpenInstrumentTypePickerCoreAsync(string customerName)
{
IReadOnlyList<AvailableInstrumentItem> instrumentTypes;
try
{
IsBusy = true;
instrumentTypes = await _service.LoadInstrumentTypesAsync();
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
return;
}
finally
{
IsBusy = false;
}
var result = _dialogService.ShowInstrumentTypeDialog(customerName, instrumentTypes);
if (result == null || result.TypeItem == null)
{
return;
}
AddSelectedTypeInstrument(result);
}
private void AddSelectedInstruments(IReadOnlyList<AvailableInstrumentItem> selectedItems)
{
if (SelectedDocument == null)
{
return;
}
var pendingKey = GetPendingLinesStorageKey(SelectedDocument);
if (string.IsNullOrWhiteSpace(pendingKey))
{
return;
}
List<PsvDocumentLine> pendingLines;
if (!_pendingLinesByDocumentKey.TryGetValue(pendingKey, out pendingLines))
{
pendingLines = new List<PsvDocumentLine>();
_pendingLinesByDocumentKey[pendingKey] = pendingLines;
}
var candidateLines = selectedItems
.Where(delegate(AvailableInstrumentItem item) { return item != null; })
.Select(CreatePendingLine)
.ToList();
List<OpenDocumentConflictInfo> openDocumentConflicts;
try
{
openDocumentConflicts = FindOpenDocumentConflicts(candidateLines);
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
return;
}
var openConflictKeys = new HashSet<string>(
openDocumentConflicts.Select(delegate(OpenDocumentConflictInfo conflict) { return conflict.OpenDocumentConflictKey; }),
StringComparer.OrdinalIgnoreCase);
var duplicateKeys = new HashSet<string>(DocumentLines.Select(delegate(PsvDocumentLine line) { return line.DuplicateKey; }), StringComparer.OrdinalIgnoreCase);
var addedCount = 0;
var skippedDuplicateCount = 0;
var skippedOpenDocumentCount = 0;
var skippedWithoutTemplateCount = 0;
foreach (var item in selectedItems)
{
if (item == null)
{
continue;
}
if (openConflictKeys.Contains(PsvDocumentLine.BuildOpenDocumentConflictKey(item.TypeSizeId, item.SerialNumber)))
{
skippedOpenDocumentCount++;
continue;
}
if (!item.HasTemplate)
{
skippedWithoutTemplateCount++;
continue;
}
var duplicateKey = PsvDocumentLine.BuildDuplicateKey(item.InstrumentType, item.RangeText, item.RegistryNumber, item.SerialNumber);
if (duplicateKeys.Contains(duplicateKey))
{
skippedDuplicateCount++;
continue;
}
pendingLines.Add(CreatePendingLine(item));
duplicateKeys.Add(duplicateKey);
addedCount++;
}
if (SelectedDocument.IsDraft)
{
UpdateDocumentSummaryFromLines(SelectedDocument, pendingLines);
}
LoadSelectedDocumentAsync();
var messages = new List<string>();
if (addedCount > 0)
{
messages.Add(string.Format("Добавлено приборов: {0}.", addedCount));
}
if (skippedDuplicateCount > 0)
{
messages.Add(string.Format("Исключено дублей: {0}.", skippedDuplicateCount));
}
if (skippedWithoutTemplateCount > 0)
{
messages.Add(string.Format("Пропущено без источника данных для EKZMK: {0}.", skippedWithoutTemplateCount));
}
if (skippedOpenDocumentCount > 0)
{
messages.Add(string.Format("Пропущено из-за других открытых ПСВ: {0}.", skippedOpenDocumentCount));
messages.Add(BuildOpenDocumentConflictMessage(openDocumentConflicts));
}
if (messages.Count > 0)
{
var message = string.Join(" ", messages.ToArray());
if (addedCount == 0 && skippedOpenDocumentCount > 0)
{
_dialogService.ShowWarning(message);
}
else
{
_dialogService.ShowInfo(message);
}
}
RaiseCommandStates();
OnPropertyChanged("IsCustomerEditable");
}
private void AddSelectedTypeInstrument(InstrumentTypeSelectionResult result)
{
if (SelectedDocument == null || result == null || result.TypeItem == null)
{
return;
}
var pendingKey = GetPendingLinesStorageKey(SelectedDocument);
if (string.IsNullOrWhiteSpace(pendingKey))
{
return;
}
List<PsvDocumentLine> pendingLines;
if (!_pendingLinesByDocumentKey.TryGetValue(pendingKey, out pendingLines))
{
pendingLines = new List<PsvDocumentLine>();
_pendingLinesByDocumentKey[pendingKey] = pendingLines;
}
var serialNumbers = (result.SerialNumbers ?? Array.Empty<string>())
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
.Select(delegate(string value) { return value.Trim(); })
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
if (serialNumbers.Count == 0)
{
_dialogService.ShowWarning("Введите хотя бы один заводской номер.");
return;
}
if (!result.TypeItem.HasTemplate)
{
_dialogService.ShowWarning("Выбранный тип нельзя добавить: для него не найден шаблон EKZMK, период из TPRMCP или регистрационный период TIPS.");
return;
}
var validSerialNumbers = new List<string>();
var skippedInvalidLengthCount = 0;
foreach (var serialNumber in serialNumbers)
{
if (serialNumber.Length > EkzDirectoryRules.SerialNumberMaxLength)
{
skippedInvalidLengthCount++;
continue;
}
validSerialNumbers.Add(serialNumber);
}
if (validSerialNumbers.Count == 0)
{
_dialogService.ShowWarning(string.Format("Каждый заводской номер должен содержать не более {0} символов.", EkzDirectoryRules.SerialNumberMaxLength));
return;
}
var candidateLines = validSerialNumbers
.Select(delegate(string serialNumber) { return CreatePendingTypeLine(result.TypeItem, serialNumber); })
.ToList();
List<OpenDocumentConflictInfo> openDocumentConflicts;
try
{
openDocumentConflicts = FindOpenDocumentConflicts(candidateLines);
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
return;
}
var openConflictKeys = new HashSet<string>(
openDocumentConflicts.Select(delegate(OpenDocumentConflictInfo conflict) { return conflict.OpenDocumentConflictKey; }),
StringComparer.OrdinalIgnoreCase);
var duplicateKeys = new HashSet<string>(DocumentLines.Select(delegate(PsvDocumentLine line) { return line.DuplicateKey; }), StringComparer.OrdinalIgnoreCase);
var addedCount = 0;
var skippedDuplicateCount = 0;
var skippedOpenDocumentCount = 0;
foreach (var serialNumber in validSerialNumbers)
{
if (openConflictKeys.Contains(PsvDocumentLine.BuildOpenDocumentConflictKey(result.TypeItem.TypeSizeId, serialNumber)))
{
skippedOpenDocumentCount++;
continue;
}
var duplicateKey = PsvDocumentLine.BuildDuplicateKey(
result.TypeItem.InstrumentType,
result.TypeItem.RangeText,
result.TypeItem.RegistryNumber,
serialNumber);
if (duplicateKeys.Contains(duplicateKey))
{
skippedDuplicateCount++;
continue;
}
pendingLines.Add(CreatePendingTypeLine(result.TypeItem, serialNumber));
duplicateKeys.Add(duplicateKey);
addedCount++;
}
if (addedCount == 0 && skippedDuplicateCount > 0 && skippedOpenDocumentCount == 0 && skippedInvalidLengthCount == 0)
{
_dialogService.ShowWarning("Такие приборы уже есть в ПСВ.");
return;
}
if (SelectedDocument.IsDraft)
{
UpdateDocumentSummaryFromLines(SelectedDocument, pendingLines);
}
LoadSelectedDocumentAsync();
var messages = new List<string>();
if (addedCount > 0)
{
messages.Add(string.Format("Добавлено приборов по типу: {0}.", addedCount));
}
if (skippedDuplicateCount > 0)
{
messages.Add(string.Format("Исключено дублей: {0}.", skippedDuplicateCount));
}
if (skippedInvalidLengthCount > 0)
{
messages.Add(string.Format("Пропущено из-за длины зав. № более {0} символов: {1}.", EkzDirectoryRules.SerialNumberMaxLength, skippedInvalidLengthCount));
}
if (skippedOpenDocumentCount > 0)
{
messages.Add(string.Format("Пропущено из-за других открытых ПСВ: {0}.", skippedOpenDocumentCount));
messages.Add(BuildOpenDocumentConflictMessage(openDocumentConflicts));
}
if (messages.Count > 0)
{
var message = string.Join(" ", messages.ToArray());
if (addedCount == 0)
{
_dialogService.ShowWarning(message);
}
else
{
_dialogService.ShowInfo(message);
}
}
RaiseCommandStates();
OnPropertyChanged("IsCustomerEditable");
}
private void ApplyDocumentLines(IEnumerable<PsvDocumentLine> lines, PsvDocumentGroupSummary previousGroup)
{
var previousLine = SelectedDocumentLine;
ClearDocumentLines();
foreach (var line in lines)
{
SubscribeToDocumentLine(line);
DocumentLines.Add(line);
}
RebuildDocumentGroupSummaries(DocumentLines);
SelectedDocumentGroup = FindMatchingVisibleGroup(previousGroup)
?? GetVisibleDocumentGroups().FirstOrDefault();
SelectedDocumentLine = previousLine == null
? null
: DocumentLines.FirstOrDefault(delegate(PsvDocumentLine line)
{
if (previousLine.CardId > 0 && line.CardId > 0)
{
return line.CardId == previousLine.CardId;
}
return line.IsPendingInsert
&& previousLine.IsPendingInsert
&& string.Equals(line.DuplicateKey, previousLine.DuplicateKey, StringComparison.OrdinalIgnoreCase);
});
HeaderInstrumentCount = DocumentLines.Count;
RefreshDocumentGroupsView();
RefreshDocumentLinesView();
RaiseCommandStates();
}
private void RaiseCommandStates()
{
((RelayCommand)AddDocumentCommand).RaiseCanExecuteChanged();
((RelayCommand)CloneLineVerificationCommand).RaiseCanExecuteChanged();
((RelayCommand)DeleteDocumentCommand).RaiseCanExecuteChanged();
((RelayCommand)DeleteSelectedLinesCommand).RaiseCanExecuteChanged();
((RelayCommand)DeleteSelectedGroupsCommand).RaiseCanExecuteChanged();
((RelayCommand)MarkLinePassedCommand).RaiseCanExecuteChanged();
((RelayCommand)MarkLineRejectedCommand).RaiseCanExecuteChanged();
((RelayCommand)OpenInstrumentPickerCommand).RaiseCanExecuteChanged();
((RelayCommand)OpenInstrumentTypePickerCommand).RaiseCanExecuteChanged();
((RelayCommand)PrintDocumentCommand).RaiseCanExecuteChanged();
((RelayCommand)PrintVerificationDocumentCommand).RaiseCanExecuteChanged();
((RelayCommand)RefreshDocumentsCommand).RaiseCanExecuteChanged();
((RelayCommand)ResetLineVerificationCommand).RaiseCanExecuteChanged();
((RelayCommand)SaveDocumentHeaderCommand).RaiseCanExecuteChanged();
}
private void RebuildDocumentGroupSummaries(IEnumerable<PsvDocumentLine> lines)
{
var checkedGroups = DocumentGroupSummaries
.Where(delegate(PsvDocumentGroupSummary group) { return group.IsBatchSelected; })
.ToList();
ClearDocumentGroups();
var groups = lines.GroupBy(line => new
{
InstrumentType = line.InstrumentType ?? string.Empty,
RangeText = line.RangeText ?? string.Empty,
AccuracyText = line.AccuracyText ?? string.Empty,
RegistryNumber = line.RegistryNumber ?? string.Empty
})
.OrderBy(group => group.Key.InstrumentType)
.ThenBy(group => group.Key.RegistryNumber)
.ThenBy(group => group.Key.RangeText)
.ThenBy(group => group.Key.AccuracyText)
.Select(group => new PsvDocumentGroupSummary
{
InstrumentName = BuildInstrumentNamesText(group),
InstrumentType = group.Key.InstrumentType,
RangeText = group.Key.RangeText,
AccuracyText = group.Key.AccuracyText,
RegistryNumber = group.Key.RegistryNumber,
SerialNumbersText = BuildSerialNumbersText(group),
IsBatchSelected = checkedGroups.Any(delegate(PsvDocumentGroupSummary previous)
{
return string.Equals(previous.InstrumentType ?? string.Empty, group.Key.InstrumentType, StringComparison.OrdinalIgnoreCase)
&& string.Equals(previous.RangeText ?? string.Empty, group.Key.RangeText, StringComparison.OrdinalIgnoreCase)
&& string.Equals(previous.AccuracyText ?? string.Empty, group.Key.AccuracyText, StringComparison.OrdinalIgnoreCase)
&& string.Equals(previous.RegistryNumber ?? string.Empty, group.Key.RegistryNumber, StringComparison.OrdinalIgnoreCase);
}),
InVerificationCount = group.Count(line => !line.IsPassed.HasValue),
VerifiedCount = group.Count(line => line.IsPassed.HasValue),
GoodCount = group.Count(line => line.IsPassed == true),
RejectedCount = group.Count(line => line.IsPassed == false)
});
foreach (var group in groups)
{
SubscribeToDocumentGroup(group);
DocumentGroupSummaries.Add(group);
}
}
private void RefreshDocumentGroupsView()
{
if (DocumentGroupsView != null)
{
DocumentGroupsView.Refresh();
}
var selectedVisibleGroup = FindMatchingVisibleGroup(SelectedDocumentGroup);
if (selectedVisibleGroup != null)
{
if (!ReferenceEquals(SelectedDocumentGroup, selectedVisibleGroup))
{
SelectedDocumentGroup = selectedVisibleGroup;
return;
}
RefreshDocumentLinesView();
return;
}
var firstVisibleGroup = GetVisibleDocumentGroups().FirstOrDefault();
if (!ReferenceEquals(SelectedDocumentGroup, firstVisibleGroup))
{
SelectedDocumentGroup = firstVisibleGroup;
return;
}
RefreshDocumentLinesView();
}
private void RefreshDocumentLinesView()
{
DocumentLinesView.Refresh();
UpdateLineStatus();
RaiseCommandStates();
}
private void RefreshDocumentsAsync(string documentKeyToSelect, string documentNumberToSelect)
{
RunBusyOperation(delegate { return RefreshDocumentsCoreAsync(documentKeyToSelect, documentNumberToSelect); });
}
private async Task RefreshDocumentsCoreAsync(string documentKeyToSelect, string documentNumberToSelect)
{
DocumentStatusText = "Загрузка списка ПСВ...";
var databaseDocuments = await _service.LoadDocumentsAsync(ShowClosedDocuments);
var currentDocumentKey = documentKeyToSelect ?? (SelectedDocument != null ? SelectedDocument.DocumentKey : null);
var currentDocumentNumber = documentNumberToSelect ?? (SelectedDocument != null ? SelectedDocument.DocumentNumber : null);
ClearCollections(Documents);
foreach (var draft in _draftDocuments
.Where(delegate(PsvDocumentSummary item) { return !ShowClosedDocuments; })
.OrderByDescending(delegate(PsvDocumentSummary item) { return item.AcceptedOn ?? DateTime.MinValue; }))
{
Documents.Add(draft);
}
foreach (var document in databaseDocuments)
{
if (_draftDocuments.Any(delegate(PsvDocumentSummary draft)
{
return string.Equals(draft.DocumentNumber, document.DocumentNumber, StringComparison.OrdinalIgnoreCase);
}))
{
continue;
}
Documents.Add(document);
}
DocumentsView.Refresh();
SelectedDocument = Documents.FirstOrDefault(delegate(PsvDocumentSummary document)
{
if (!string.IsNullOrWhiteSpace(currentDocumentKey)
&& string.Equals(document.DocumentKey, currentDocumentKey, StringComparison.OrdinalIgnoreCase))
{
return true;
}
return !string.IsNullOrWhiteSpace(currentDocumentNumber)
&& string.Equals(document.DocumentNumber, currentDocumentNumber, StringComparison.OrdinalIgnoreCase);
});
if (SelectedDocument == null && Documents.Count > 0)
{
SelectedDocument = Documents[0];
}
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
}
private void SaveDocumentAsync()
{
RunBusyOperation(async delegate
{
if (SelectedDocument == null)
{
_dialogService.ShowWarning("Сначала выберите документ.");
return;
}
var selectedDocument = SelectedDocument;
if (!HeaderReceivedOn.HasValue)
{
_dialogService.ShowWarning("Укажите дату приемки.");
return;
}
if (string.IsNullOrWhiteSpace(DocumentNumberEditor))
{
_dialogService.ShowWarning("Введите номер ПСВ.");
return;
}
if (selectedDocument.IsDraft && !SelectedCustomerId.HasValue)
{
_dialogService.ShowWarning("Для новой ПСВ сначала выберите заказчика.");
return;
}
if (DocumentExistsInCollections(DocumentNumberEditor.Trim(), selectedDocument.DocumentKey)
|| await _service.DocumentNumberExistsAsync(DocumentNumberEditor.Trim(), selectedDocument.IsDraft ? null : selectedDocument.DocumentNumber))
{
_dialogService.ShowWarning("ПСВ с таким номером уже существует.");
return;
}
var pendingLines = GetPendingLines(selectedDocument)
.Where(delegate(PsvDocumentLine line)
{
return line != null
&& (line.InstrumentId > 0
|| (line.TypeSizeId > 0 && !string.IsNullOrWhiteSpace(line.SerialNumber)));
})
.ToList();
if (selectedDocument.IsDraft && pendingLines.Count == 0)
{
_dialogService.ShowWarning("Черновик нельзя сохранить без строк EKZMK.");
return;
}
var openDocumentConflicts = FindPendingOpenDocumentConflicts(selectedDocument, pendingLines);
if (openDocumentConflicts.Count > 0)
{
_dialogService.ShowWarning(BuildOpenDocumentConflictMessage(openDocumentConflicts));
return;
}
var request = new DocumentEditorResult
{
DocumentNumber = DocumentNumberEditor.Trim(),
AcceptedOn = HeaderReceivedOn.Value,
IssuedOn = HeaderIssuedOn,
CustomerId = selectedDocument.CustomerId ?? SelectedCustomerId
};
var currentDocumentNumber = selectedDocument.IsDraft ? null : selectedDocument.DocumentNumber;
var documentKey = selectedDocument.DocumentKey;
var documentPendingKey = GetPendingLinesStorageKey(selectedDocument);
var wasDraft = selectedDocument.IsDraft;
var closingNow = !selectedDocument.IssuedOn.HasValue && request.IssuedOn.HasValue;
var printDocument = closingNow ? CreateSavedDocumentSummaryForPrint(selectedDocument, request) : null;
var documentLinesSnapshot = DocumentLines.ToList();
var result = await Task.Run(delegate { return _service.SaveDocument(currentDocumentNumber, request, documentLinesSnapshot); });
_pendingLinesByDocumentKey.Remove(documentPendingKey);
if (wasDraft)
{
_draftDocuments.RemoveAll(delegate(PsvDocumentSummary draft) { return draft.DocumentKey == documentKey; });
}
var messages = new List<string>();
messages.Add(string.Format("Обновлено строк EKZMK: {0}.", result.UpdatedEkzMkCount));
messages.Add(string.Format("Добавлено строк EKZMK: {0}.", result.InsertedEkzMkCount));
if (result.SkippedDuplicateCount > 0)
{
messages.Add(string.Format("Исключено дублей: {0}.", result.SkippedDuplicateCount));
}
if (result.SkippedWithoutTemplateCount > 0)
{
messages.Add(string.Format("Пропущено без источника данных для EKZMK: {0}.", result.SkippedWithoutTemplateCount));
}
var messageText = string.Join(" ", messages.ToArray());
if (closingNow)
{
var prompt = messageText + " ПСВ закрыта. Распечатать приемо-сдаточную ведомость?";
if (_dialogService.Confirm(prompt))
{
var printLines = await _service.LoadDocumentLinesAsync(result.DocumentNumber);
if (printDocument != null)
{
printDocument.DocumentNumber = result.DocumentNumber;
_printService.PrintDocument(printDocument, printLines.ToList());
}
}
}
else
{
_dialogService.ShowInfo(messageText);
}
await RefreshDocumentsCoreAsync(null, closingNow ? null : result.DocumentNumber);
});
}
private void UpdateLineStatus()
{
var visibleGroupCount = GetVisibleDocumentGroups().Count;
if (SelectedDocument == null)
{
DetailTableCountText = "Приборов в таблице: 0.";
LineStatusText = "Документ не выбран.";
return;
}
if (DocumentGroupSummaries.Count == 0)
{
DetailTableCountText = "Приборов в таблице: 0.";
LineStatusText = SelectedDocument.IsDraft
? "Черновик пуст. Добавьте приборы через контекстное меню таблицы групп."
: "В документе нет групп приборов.";
return;
}
if (visibleGroupCount == 0)
{
DetailTableCountText = "Приборов в таблице: 0.";
LineStatusText = string.IsNullOrWhiteSpace(GroupFilterText)
? "Выберите группу."
: string.Format("Группы по фильтру \"{0}\" не найдены.", GroupFilterText.Trim());
return;
}
if (SelectedDocumentGroup == null)
{
DetailTableCountText = "Приборов в таблице: 0.";
LineStatusText = string.Format("Групп: {0}/{1}. Выберите группу.", visibleGroupCount, DocumentGroupSummaries.Count);
return;
}
var groupLineCount = DocumentLines.Count(delegate(PsvDocumentLine line) { return SelectedDocumentGroup.Matches(line); });
var filteredCount = DocumentLines.Count(delegate(PsvDocumentLine line)
{
return SelectedDocumentGroup.Matches(line)
&& (string.IsNullOrWhiteSpace(GroupDetailFilterText) || Contains(line.SerialNumber, GroupDetailFilterText));
});
var pendingCount = DocumentLines.Count(delegate(PsvDocumentLine line) { return line.IsPendingInsert; });
DetailTableCountText = string.Format("Приборов в таблице: {0}.", filteredCount);
LineStatusText = string.Format(
"Групп: {0}/{1}. Приборов в выбранной группе: {2}. Отображено по фильтру: {3}. Не сохранено строк: {4}.",
visibleGroupCount,
DocumentGroupSummaries.Count,
groupLineCount,
filteredCount,
pendingCount);
}
}
}