This commit is contained in:
Курнат Андрей
2026-04-02 21:44:28 +03:00
parent db15503315
commit 22ed7d978a
25 changed files with 1064 additions and 156 deletions

View File

@@ -358,7 +358,7 @@
Margin="12,0,0,0"
VerticalAlignment="Center"
Foreground="DimGray"
Text="Поиск по наименованию, типу, диапазону, госреестру или зав. №" />
Text="Поиск по наименованию, типу, диапазону, характеристикам, госреестру или зав. №" />
</Grid>
<DataGrid Grid.Row="1"
@@ -443,6 +443,9 @@
<DataGridTextColumn Header="Диапазон"
Width="160"
Binding="{Binding RangeText}" />
<DataGridTextColumn Header="Характеристики"
Width="160"
Binding="{Binding AccuracyText}" />
<DataGridTextColumn Header="Госреестр"
Width="120"
Binding="{Binding RegistryNumber}" />

View File

@@ -1786,6 +1786,7 @@ namespace XLAB2
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);
}
@@ -1860,6 +1861,7 @@ namespace XLAB2
&& 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);
}
@@ -2268,16 +2270,15 @@ namespace XLAB2
_pendingLinesByDocumentKey[pendingKey] = pendingLines;
}
var serialNumber = string.IsNullOrWhiteSpace(result.SerialNumber) ? string.Empty : result.SerialNumber.Trim();
if (string.IsNullOrWhiteSpace(serialNumber))
{
_dialogService.ShowWarning("Введите заводской номер.");
return;
}
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 (serialNumber.Length > EkzDirectoryRules.SerialNumberMaxLength)
if (serialNumbers.Count == 0)
{
_dialogService.ShowWarning(string.Format("Заводской номер не должен превышать {0} символов.", EkzDirectoryRules.SerialNumberMaxLength));
_dialogService.ShowWarning("Введите хотя бы один заводской номер.");
return;
}
@@ -2287,11 +2288,34 @@ namespace XLAB2
return;
}
var candidateLine = CreatePendingTypeLine(result.TypeItem, serialNumber);
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(new[] { candidateLine });
openDocumentConflicts = FindOpenDocumentConflicts(candidateLines);
}
catch (Exception ex)
{
@@ -2299,36 +2323,88 @@ namespace XLAB2
return;
}
if (openDocumentConflicts.Count > 0)
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)
{
_dialogService.ShowWarning(BuildOpenDocumentConflictMessage(openDocumentConflicts));
return;
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++;
}
var duplicateKey = PsvDocumentLine.BuildDuplicateKey(
result.TypeItem.InstrumentType,
result.TypeItem.RangeText,
result.TypeItem.RegistryNumber,
serialNumber);
if (DocumentLines.Any(delegate(PsvDocumentLine line)
if (addedCount == 0 && skippedDuplicateCount > 0 && skippedOpenDocumentCount == 0 && skippedInvalidLengthCount == 0)
{
return string.Equals(line.DuplicateKey, duplicateKey, StringComparison.OrdinalIgnoreCase);
}))
{
_dialogService.ShowWarning("Такой прибор уже есть в ПСВ.");
_dialogService.ShowWarning("Такие приборы уже есть в ПСВ.");
return;
}
pendingLines.Add(candidateLine);
if (SelectedDocument.IsDraft)
{
UpdateDocumentSummaryFromLines(SelectedDocument, pendingLines);
}
LoadSelectedDocumentAsync();
_dialogService.ShowInfo("Прибор по типу добавлен в ПСВ.");
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");
}
@@ -2395,22 +2471,26 @@ namespace XLAB2
{
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),

View File

@@ -370,6 +370,8 @@ namespace XLAB2
public string RangeText { get; set; }
public string AccuracyText { get; set; }
public string RegistryNumber { get; set; }
public string SerialNumbersText { get; set; }
@@ -393,6 +395,7 @@ namespace XLAB2
return line != null
&& string.Equals(InstrumentType ?? string.Empty, line.InstrumentType ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(RangeText ?? string.Empty, line.RangeText ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(AccuracyText ?? string.Empty, line.AccuracyText ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(RegistryNumber ?? string.Empty, line.RegistryNumber ?? string.Empty, StringComparison.OrdinalIgnoreCase);
}
}
@@ -527,7 +530,7 @@ namespace XLAB2
{
public AvailableInstrumentItem TypeItem { get; set; }
public string SerialNumber { get; set; }
public IReadOnlyList<string> SerialNumbers { get; set; }
}
public sealed class VerificationEditSeed

View File

@@ -61,14 +61,17 @@
</DataGrid>
<StackPanel Grid.Row="3"
Margin="0,10,0,0"
Orientation="Horizontal">
<TextBlock Width="150"
Margin="0,0,8,0"
VerticalAlignment="Center"
Text="Заводской номер" />
<TextBox Width="320"
Text="{Binding SerialNumber, UpdateSourceTrigger=PropertyChanged}" />
Margin="0,10,0,0">
<TextBlock Text="Заводские номера" />
<TextBlock Margin="0,4,0,0"
Foreground="DimGray"
Text="Перечислите номера через запятую, точку с запятой или с новой строки." />
<TextBox Margin="0,6,0,0"
Height="96"
AcceptsReturn="True"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
Text="{Binding SerialNumbersText, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<TextBlock Grid.Row="4"

View File

@@ -12,7 +12,7 @@ namespace XLAB2
{
private string _searchText;
private AvailableInstrumentItem _selectedType;
private string _serialNumber;
private string _serialNumbersText;
private string _statusText;
public SelectInstrumentTypeWindowViewModel(string customerName, IReadOnlyList<AvailableInstrumentItem> instrumentTypes)
@@ -65,12 +65,12 @@ namespace XLAB2
}
}
public string SerialNumber
public string SerialNumbersText
{
get { return _serialNumber; }
get { return _serialNumbersText; }
set
{
if (SetProperty(ref _serialNumber, value))
if (SetProperty(ref _serialNumbersText, value))
{
((RelayCommand)ConfirmCommand).RaiseCanExecuteChanged();
UpdateStatus();
@@ -86,12 +86,13 @@ namespace XLAB2
public InstrumentTypeSelectionResult GetResult()
{
var serialNumbers = ParseSerialNumbers(SerialNumbersText);
return SelectedType == null
? null
: new InstrumentTypeSelectionResult
{
TypeItem = SelectedType,
SerialNumber = string.IsNullOrWhiteSpace(SerialNumber) ? string.Empty : SerialNumber.Trim()
SerialNumbers = serialNumbers
};
}
@@ -103,7 +104,7 @@ namespace XLAB2
private bool CanConfirm(object parameter)
{
return SelectedType != null
&& !string.IsNullOrWhiteSpace(SerialNumber);
&& ParseSerialNumbers(SerialNumbersText).Count > 0;
}
private void Confirm(object parameter)
@@ -138,6 +139,30 @@ namespace XLAB2
&& source.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0;
}
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;
@@ -150,12 +175,13 @@ namespace XLAB2
private void UpdateStatus()
{
var visibleCount = InstrumentTypesView.Cast<object>().Count();
var serialCount = ParseSerialNumbers(SerialNumbersText).Count;
StatusText = string.Format(
"Всего типов: {0}. По фильтру: {1}. Выбран тип: {2}. Заводской номер: {3}.",
"Всего типов: {0}. По фильтру: {1}. Выбран тип: {2}. Уникальных зав. №: {3}.",
InstrumentTypes.Count,
visibleCount,
SelectedType == null ? "нет" : "да",
string.IsNullOrWhiteSpace(SerialNumber) ? "не указан" : "указан");
serialCount);
}
}
}