2776 lines
107 KiB
C#
2776 lines
107 KiB
C#
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);
|
||
}
|
||
}
|
||
}
|