edit
This commit is contained in:
57
XLAB/CloneVerificationWindow.xaml
Normal file
57
XLAB/CloneVerificationWindow.xaml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<Window x:Class="XLAB.CloneVerificationWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
Title="Клонирование поверки"
|
||||||
|
Height="420"
|
||||||
|
Width="620"
|
||||||
|
MinHeight="360"
|
||||||
|
MinWidth="540"
|
||||||
|
WindowStartupLocation="CenterOwner">
|
||||||
|
<Grid Margin="16">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBlock FontWeight="SemiBold"
|
||||||
|
Text="{Binding SourceSerialNumber, StringFormat=Источник: зав. № {0}}" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1"
|
||||||
|
Margin="0,8,0,0"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Text="{Binding VerificationSummary}" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="2"
|
||||||
|
Margin="0,12,0,6"
|
||||||
|
Text="Введите заводские номера строк, в которые нужно скопировать поверку. Поддерживаются разделители: новая строка, табуляция, запятая, точка с запятой." />
|
||||||
|
|
||||||
|
<TextBox Grid.Row="3"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Text="{Binding SerialNumbersText, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="4"
|
||||||
|
Margin="0,8,0,0"
|
||||||
|
Foreground="DimGray"
|
||||||
|
Text="{Binding StatusText}" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="5"
|
||||||
|
Margin="0,12,0,0"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
HorizontalAlignment="Right">
|
||||||
|
<Button Width="110"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
IsDefault="True"
|
||||||
|
Command="{Binding ConfirmCommand}"
|
||||||
|
Content="Клонировать" />
|
||||||
|
<Button Width="90"
|
||||||
|
Command="{Binding CancelCommand}"
|
||||||
|
Content="Отмена" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
20
XLAB/CloneVerificationWindow.xaml.cs
Normal file
20
XLAB/CloneVerificationWindow.xaml.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace XLAB
|
||||||
|
{
|
||||||
|
public partial class CloneVerificationWindow : Window
|
||||||
|
{
|
||||||
|
internal CloneVerificationWindow(CloneVerificationWindowViewModel viewModel)
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = viewModel;
|
||||||
|
viewModel.CloseRequested += ViewModelOnCloseRequested;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ViewModelOnCloseRequested(object sender, bool? dialogResult)
|
||||||
|
{
|
||||||
|
DialogResult = dialogResult;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
115
XLAB/CloneVerificationWindowViewModel.cs
Normal file
115
XLAB/CloneVerificationWindowViewModel.cs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace XLAB
|
||||||
|
{
|
||||||
|
internal sealed class CloneVerificationWindowViewModel : ObservableObject
|
||||||
|
{
|
||||||
|
private string _serialNumbersText;
|
||||||
|
private string _statusText;
|
||||||
|
|
||||||
|
public CloneVerificationWindowViewModel(CloneVerificationSeed seed)
|
||||||
|
{
|
||||||
|
if (seed == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("seed");
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceSerialNumber = string.IsNullOrWhiteSpace(seed.SourceSerialNumber) ? string.Empty : seed.SourceSerialNumber.Trim();
|
||||||
|
VerificationSummary = seed.VerificationSummary ?? string.Empty;
|
||||||
|
|
||||||
|
ConfirmCommand = new RelayCommand(Confirm, CanConfirm);
|
||||||
|
CancelCommand = new RelayCommand(Cancel);
|
||||||
|
UpdateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<bool?> CloseRequested;
|
||||||
|
|
||||||
|
public ICommand CancelCommand { get; private set; }
|
||||||
|
|
||||||
|
public ICommand ConfirmCommand { get; private set; }
|
||||||
|
|
||||||
|
public string SourceSerialNumber { get; private set; }
|
||||||
|
|
||||||
|
public string SerialNumbersText
|
||||||
|
{
|
||||||
|
get { return _serialNumbersText; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref _serialNumbersText, value))
|
||||||
|
{
|
||||||
|
UpdateStatus();
|
||||||
|
((RelayCommand)ConfirmCommand).RaiseCanExecuteChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string StatusText
|
||||||
|
{
|
||||||
|
get { return _statusText; }
|
||||||
|
private set { SetProperty(ref _statusText, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string VerificationSummary { get; private set; }
|
||||||
|
|
||||||
|
public IReadOnlyList<string> GetSerialNumbers()
|
||||||
|
{
|
||||||
|
return ParseSerialNumbers(SerialNumbersText);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Cancel(object parameter)
|
||||||
|
{
|
||||||
|
RaiseCloseRequested(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CanConfirm(object parameter)
|
||||||
|
{
|
||||||
|
return ParseSerialNumbers(SerialNumbersText).Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Confirm(object parameter)
|
||||||
|
{
|
||||||
|
RaiseCloseRequested(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> ParseSerialNumbers(string value)
|
||||||
|
{
|
||||||
|
var serialNumbers = new List<string>();
|
||||||
|
var unique = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
{
|
||||||
|
return serialNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
var separators = new[] { '\r', '\n', '\t', ',', ';' };
|
||||||
|
foreach (var token in value.Split(separators, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
var serialNumber = token.Trim();
|
||||||
|
if (serialNumber.Length == 0 || !unique.Add(serialNumber))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
serialNumbers.Add(serialNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
return serialNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RaiseCloseRequested(bool? dialogResult)
|
||||||
|
{
|
||||||
|
var handler = CloseRequested;
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
handler(this, dialogResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateStatus()
|
||||||
|
{
|
||||||
|
var serialCount = ParseSerialNumbers(SerialNumbersText).Count;
|
||||||
|
StatusText = string.Format("Уникальных заводских номеров: {0}.", serialCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ namespace XLAB
|
|||||||
|
|
||||||
InstrumentTypeSelectionResult ShowInstrumentTypeDialog(string customerName, IReadOnlyList<AvailableInstrumentItem> instrumentTypes);
|
InstrumentTypeSelectionResult ShowInstrumentTypeDialog(string customerName, IReadOnlyList<AvailableInstrumentItem> instrumentTypes);
|
||||||
|
|
||||||
|
IReadOnlyList<string> ShowCloneVerificationDialog(CloneVerificationSeed seed);
|
||||||
|
|
||||||
VerificationEditResult ShowVerificationDialog(
|
VerificationEditResult ShowVerificationDialog(
|
||||||
VerificationEditSeed seed,
|
VerificationEditSeed seed,
|
||||||
IReadOnlyList<PersonReference> verifiers,
|
IReadOnlyList<PersonReference> verifiers,
|
||||||
@@ -64,6 +66,16 @@ namespace XLAB
|
|||||||
return result.HasValue && result.Value ? viewModel.GetResult() : null;
|
return result.HasValue && result.Value ? viewModel.GetResult() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<string> ShowCloneVerificationDialog(CloneVerificationSeed seed)
|
||||||
|
{
|
||||||
|
var viewModel = new CloneVerificationWindowViewModel(seed);
|
||||||
|
var window = new CloneVerificationWindow(viewModel);
|
||||||
|
window.Owner = _owner;
|
||||||
|
|
||||||
|
var result = window.ShowDialog();
|
||||||
|
return result.HasValue && result.Value ? viewModel.GetSerialNumbers() : null;
|
||||||
|
}
|
||||||
|
|
||||||
public VerificationEditResult ShowVerificationDialog(
|
public VerificationEditResult ShowVerificationDialog(
|
||||||
VerificationEditSeed seed,
|
VerificationEditSeed seed,
|
||||||
IReadOnlyList<PersonReference> verifiers,
|
IReadOnlyList<PersonReference> verifiers,
|
||||||
|
|||||||
@@ -272,6 +272,9 @@
|
|||||||
HeadersVisibility="Column">
|
HeadersVisibility="Column">
|
||||||
<DataGrid.ContextMenu>
|
<DataGrid.ContextMenu>
|
||||||
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||||
|
<MenuItem Header="Клонировать поверку по зав. №..."
|
||||||
|
Command="{Binding CloneLineVerificationCommand}" />
|
||||||
|
<Separator/>
|
||||||
<MenuItem Header="Годен"
|
<MenuItem Header="Годен"
|
||||||
Command="{Binding MarkLinePassedCommand}" />
|
Command="{Binding MarkLinePassedCommand}" />
|
||||||
<MenuItem Header="Забракован"
|
<MenuItem Header="Забракован"
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace XLAB
|
|||||||
DocumentLinesView.Filter = FilterDocumentLines;
|
DocumentLinesView.Filter = FilterDocumentLines;
|
||||||
|
|
||||||
AddDocumentCommand = new RelayCommand(delegate { AddDocument(); }, delegate { return !IsBusy; });
|
AddDocumentCommand = new RelayCommand(delegate { AddDocument(); }, delegate { return !IsBusy; });
|
||||||
|
CloneLineVerificationCommand = new RelayCommand(delegate { CloneSelectedLineVerificationAsync(); }, delegate { return CanCloneSelectedLineVerification(); });
|
||||||
DeleteDocumentCommand = new RelayCommand(delegate { DeleteDocumentAsync(); }, delegate { return !IsBusy && SelectedDocument != null; });
|
DeleteDocumentCommand = new RelayCommand(delegate { DeleteDocumentAsync(); }, delegate { return !IsBusy && SelectedDocument != null; });
|
||||||
DeleteSelectedGroupsCommand = new RelayCommand(delegate { DeleteSelectedGroupsAsync(); }, delegate { return CanDeleteSelectedGroups(); });
|
DeleteSelectedGroupsCommand = new RelayCommand(delegate { DeleteSelectedGroupsAsync(); }, delegate { return CanDeleteSelectedGroups(); });
|
||||||
MarkLinePassedCommand = new RelayCommand(delegate { EditLineVerificationAsync(true); }, delegate { return CanEditSelectedLineVerification(); });
|
MarkLinePassedCommand = new RelayCommand(delegate { EditLineVerificationAsync(true); }, delegate { return CanEditSelectedLineVerification(); });
|
||||||
@@ -64,6 +65,8 @@ namespace XLAB
|
|||||||
|
|
||||||
public ICommand AddDocumentCommand { get; private set; }
|
public ICommand AddDocumentCommand { get; private set; }
|
||||||
|
|
||||||
|
public ICommand CloneLineVerificationCommand { get; private set; }
|
||||||
|
|
||||||
public ObservableCollection<CustomerReference> Customers { get; private set; }
|
public ObservableCollection<CustomerReference> Customers { get; private set; }
|
||||||
|
|
||||||
public string DocumentFilterText
|
public string DocumentFilterText
|
||||||
@@ -333,6 +336,11 @@ namespace XLAB
|
|||||||
&& targetLines.All(delegate(PsvDocumentLine line) { return !HasVerificationData(line); });
|
&& targetLines.All(delegate(PsvDocumentLine line) { return !HasVerificationData(line); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CanCloneSelectedLineVerification()
|
||||||
|
{
|
||||||
|
return !IsBusy && CanUseLineAsCloneSource(SelectedDocumentLine);
|
||||||
|
}
|
||||||
|
|
||||||
private bool CanResetSelectedLineVerification()
|
private bool CanResetSelectedLineVerification()
|
||||||
{
|
{
|
||||||
var targetLines = GetVerificationTargetLines();
|
var targetLines = GetVerificationTargetLines();
|
||||||
@@ -355,6 +363,34 @@ namespace XLAB
|
|||||||
|| !string.IsNullOrWhiteSpace(line.RejectionReason));
|
|| !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 List<PsvDocumentLine> GetCheckedDocumentLines()
|
private List<PsvDocumentLine> GetCheckedDocumentLines()
|
||||||
{
|
{
|
||||||
return DocumentLinesView.Cast<object>()
|
return DocumentLinesView.Cast<object>()
|
||||||
@@ -510,12 +546,90 @@ namespace XLAB
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
private bool Contains(string source, string filter)
|
||||||
{
|
{
|
||||||
return !string.IsNullOrWhiteSpace(source)
|
return !string.IsNullOrWhiteSpace(source)
|
||||||
&& source.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0;
|
&& 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)
|
private string BuildOpenDocumentConflictMessage(IEnumerable<OpenDocumentConflictInfo> conflicts)
|
||||||
{
|
{
|
||||||
var materializedConflicts = NormalizeOpenDocumentConflicts(conflicts);
|
var materializedConflicts = NormalizeOpenDocumentConflicts(conflicts);
|
||||||
@@ -764,6 +878,136 @@ namespace XLAB
|
|||||||
RefreshAfterLineVerificationChanged(line);
|
RefreshAfterLineVerificationChanged(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CloneSelectedLineVerificationAsync()
|
||||||
|
{
|
||||||
|
var sourceLine = SelectedDocumentLine;
|
||||||
|
if (!CanUseLineAsCloneSource(sourceLine))
|
||||||
|
{
|
||||||
|
_dialogService.ShowWarning("В выбранной строке нет полной поверки, пригодной для клонирования.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serialNumbers = _dialogService.ShowCloneVerificationDialog(CreateCloneVerificationSeed(sourceLine));
|
||||||
|
if (serialNumbers == null || serialNumbers.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sourceSerialNumber = NormalizeSerialNumber(sourceLine.SerialNumber);
|
||||||
|
var requestedSerialNumbers = new HashSet<string>(serialNumbers, StringComparer.OrdinalIgnoreCase);
|
||||||
|
var includedSourceSerialNumber = !string.IsNullOrWhiteSpace(sourceSerialNumber)
|
||||||
|
&& requestedSerialNumbers.Remove(sourceSerialNumber);
|
||||||
|
|
||||||
|
var matchedLines = DocumentLines
|
||||||
|
.Where(delegate(PsvDocumentLine line)
|
||||||
|
{
|
||||||
|
return line != null
|
||||||
|
&& !ReferenceEquals(line, sourceLine)
|
||||||
|
&& BelongsToSameGroup(line, sourceLine)
|
||||||
|
&& requestedSerialNumbers.Contains(NormalizeSerialNumber(line.SerialNumber));
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var matchedSerialNumbers = new HashSet<string>(
|
||||||
|
matchedLines
|
||||||
|
.Select(delegate(PsvDocumentLine line) { return NormalizeSerialNumber(line.SerialNumber); })
|
||||||
|
.Where(delegate(string serialNumber) { return !string.IsNullOrWhiteSpace(serialNumber); }),
|
||||||
|
StringComparer.OrdinalIgnoreCase);
|
||||||
|
var missingSerialNumbers = serialNumbers
|
||||||
|
.Where(delegate(string serialNumber)
|
||||||
|
{
|
||||||
|
var normalized = NormalizeSerialNumber(serialNumber);
|
||||||
|
return !string.IsNullOrWhiteSpace(normalized)
|
||||||
|
&& !string.Equals(normalized, sourceSerialNumber, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& !matchedSerialNumbers.Contains(normalized);
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var targetLines = matchedLines.Where(delegate(PsvDocumentLine line) { return !HasVerificationData(line); }).ToList();
|
||||||
|
var skippedWithExistingVerificationCount = matchedLines.Count - targetLines.Count;
|
||||||
|
if (targetLines.Count == 0)
|
||||||
|
{
|
||||||
|
ShowCloneVerificationResult(0, skippedWithExistingVerificationCount, missingSerialNumbers, 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, missingSerialNumbers, includedSourceSerialNumber, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunBusyOperation(async delegate
|
||||||
|
{
|
||||||
|
await Task.Run(delegate { _service.SaveLineVerification(persistedCardIds, result); });
|
||||||
|
|
||||||
|
foreach (var pendingLine in pendingLines)
|
||||||
|
{
|
||||||
|
ApplyVerificationResultCore(pendingLine, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
await ReloadSelectedDocumentLinesAsync();
|
||||||
|
ShowCloneVerificationResult(targetLines.Count, skippedWithExistingVerificationCount, missingSerialNumbers, includedSourceSerialNumber, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowCloneVerificationResult(
|
||||||
|
int clonedCount,
|
||||||
|
int skippedWithExistingVerificationCount,
|
||||||
|
IReadOnlyList<string> missingSerialNumbers,
|
||||||
|
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 (missingSerialNumbers != null && missingSerialNumbers.Count > 0)
|
||||||
|
{
|
||||||
|
messages.Add(string.Format("Не найдены заводские номера: {0}.", BuildSerialNumberPreview(missingSerialNumbers)));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
private void EditLineVerificationAsync(bool isPassed)
|
||||||
{
|
{
|
||||||
var targetLines = GetVerificationTargetLines();
|
var targetLines = GetVerificationTargetLines();
|
||||||
@@ -1579,6 +1823,7 @@ namespace XLAB
|
|||||||
private void RaiseCommandStates()
|
private void RaiseCommandStates()
|
||||||
{
|
{
|
||||||
((RelayCommand)AddDocumentCommand).RaiseCanExecuteChanged();
|
((RelayCommand)AddDocumentCommand).RaiseCanExecuteChanged();
|
||||||
|
((RelayCommand)CloneLineVerificationCommand).RaiseCanExecuteChanged();
|
||||||
((RelayCommand)DeleteDocumentCommand).RaiseCanExecuteChanged();
|
((RelayCommand)DeleteDocumentCommand).RaiseCanExecuteChanged();
|
||||||
((RelayCommand)DeleteSelectedGroupsCommand).RaiseCanExecuteChanged();
|
((RelayCommand)DeleteSelectedGroupsCommand).RaiseCanExecuteChanged();
|
||||||
((RelayCommand)MarkLinePassedCommand).RaiseCanExecuteChanged();
|
((RelayCommand)MarkLinePassedCommand).RaiseCanExecuteChanged();
|
||||||
|
|||||||
@@ -395,6 +395,13 @@ namespace XLAB
|
|||||||
public int? VerifierId { get; set; }
|
public int? VerifierId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class CloneVerificationSeed
|
||||||
|
{
|
||||||
|
public string SourceSerialNumber { get; set; }
|
||||||
|
|
||||||
|
public string VerificationSummary { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class VerificationEditResult
|
public sealed class VerificationEditResult
|
||||||
{
|
{
|
||||||
public int DocumentFormId { get; set; }
|
public int DocumentFormId { get; set; }
|
||||||
|
|||||||
@@ -68,6 +68,15 @@
|
|||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="CreateDocumentWindowViewModel.cs" />
|
<Compile Include="CreateDocumentWindowViewModel.cs" />
|
||||||
|
<Page Include="CloneVerificationWindow.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
<Compile Include="CloneVerificationWindow.xaml.cs">
|
||||||
|
<DependentUpon>CloneVerificationWindow.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="CloneVerificationWindowViewModel.cs" />
|
||||||
<Compile Include="DialogService.cs" />
|
<Compile Include="DialogService.cs" />
|
||||||
<Page Include="MainWindow.xaml">
|
<Page Include="MainWindow.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
|||||||
Reference in New Issue
Block a user