edit
This commit is contained in:
BIN
ClosePsv.docx
BIN
ClosePsv.docx
Binary file not shown.
BIN
OpenPsv.docx
BIN
OpenPsv.docx
Binary file not shown.
164
XLAB/App.xaml
164
XLAB/App.xaml
@@ -17,6 +17,10 @@
|
||||
<SolidColorBrush x:Key="AppMutedTextBrush" Color="#FF6B7B88" />
|
||||
<SolidColorBrush x:Key="AppButtonBrush" Color="#FFF7FAFD" />
|
||||
<SolidColorBrush x:Key="AppButtonHoverBrush" Color="#FFE7F0F9" />
|
||||
<SolidColorBrush x:Key="AppMenuIconAccentBrush" Color="#FF4F7FA7" />
|
||||
<SolidColorBrush x:Key="AppMenuIconSuccessBrush" Color="#FF47A772" />
|
||||
<SolidColorBrush x:Key="AppMenuIconDangerBrush" Color="#FFC76868" />
|
||||
<SolidColorBrush x:Key="AppMenuIconWarningBrush" Color="#FFCC9B52" />
|
||||
<SolidColorBrush x:Key="AppSelectionBrush" Color="#FFD8E6F4" />
|
||||
<SolidColorBrush x:Key="AppSelectionTextBrush" Color="#FF17324A" />
|
||||
<SolidColorBrush x:Key="OpenDocumentTenDaysBrush" Color="#FFF2F8EA" />
|
||||
@@ -118,6 +122,166 @@
|
||||
<Style TargetType="{x:Type MenuItem}">
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Header" Value="Добавить">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Grid Width="16" Height="16">
|
||||
<Ellipse Width="14" Height="14" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Width="2" Height="8" Fill="White" RadiusX="1" RadiusY="1" />
|
||||
<Rectangle Width="8" Height="2" Fill="White" RadiusX="1" RadiusY="1" />
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Изменить">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Path Fill="{StaticResource AppMenuIconAccentBrush}" Data="M11.7,1.4 L14.6,4.3 L5.5,13.4 L2.5,13.9 L3,10.9 Z" />
|
||||
<Path Fill="#FFEAF3FB" Data="M10.7,2.4 L13.6,5.3 L12.8,6.1 L9.9,3.2 Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Удалить">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Rectangle Canvas.Left="4" Canvas.Top="5" Width="8" Height="8" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconDangerBrush}" />
|
||||
<Rectangle Canvas.Left="3" Canvas.Top="3" Width="10" Height="2" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconDangerBrush}" />
|
||||
<Rectangle Canvas.Left="6" Canvas.Top="1.5" Width="4" Height="2" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconDangerBrush}" />
|
||||
<Rectangle Canvas.Left="6" Canvas.Top="6.5" Width="1" Height="5" Fill="White" />
|
||||
<Rectangle Canvas.Left="9" Canvas.Top="6.5" Width="1" Height="5" Fill="White" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Распечатать">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Rectangle Canvas.Left="4" Canvas.Top="1.5" Width="8" Height="4" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="2" Canvas.Top="5" Width="12" Height="5" RadiusX="1.5" RadiusY="1.5" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="4" Canvas.Top="8.5" Width="8" Height="5" Fill="#FFF9FCFE" Stroke="{StaticResource AppMenuIconAccentBrush}" StrokeThickness="1" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Добавить по заводским номерам">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Rectangle Canvas.Left="2" Canvas.Top="3" Width="8" Height="2" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="2" Canvas.Top="7" Width="8" Height="2" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="2" Canvas.Top="11" Width="6" Height="2" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Ellipse Canvas.Left="10.5" Canvas.Top="6" Width="4" Height="4" Fill="{StaticResource AppMenuIconSuccessBrush}" />
|
||||
<Rectangle Canvas.Left="12" Canvas.Top="4.5" Width="1" Height="7" Fill="{StaticResource AppMenuIconSuccessBrush}" />
|
||||
<Rectangle Canvas.Left="9.5" Canvas.Top="7" Width="6" Height="1" Fill="{StaticResource AppMenuIconSuccessBrush}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Добавить по типу">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Rectangle Canvas.Left="2" Canvas.Top="3" Width="5" Height="5" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="2" Canvas.Top="9" Width="5" Height="5" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="8" Canvas.Top="6" Width="5" Height="5" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="12" Canvas.Top="1.5" Width="1.5" Height="5" Fill="{StaticResource AppMenuIconSuccessBrush}" />
|
||||
<Rectangle Canvas.Left="10.25" Canvas.Top="3.25" Width="5" Height="1.5" Fill="{StaticResource AppMenuIconSuccessBrush}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Клонировать поверку в выбранные строки">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Rectangle Canvas.Left="3" Canvas.Top="4" Width="7" Height="8" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="6" Canvas.Top="2" Width="7" Height="8" RadiusX="1" RadiusY="1" Fill="#FFEAF3FB" Stroke="{StaticResource AppMenuIconAccentBrush}" StrokeThickness="1" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Распечатать документ о поверке">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Rectangle Canvas.Left="4" Canvas.Top="1.5" Width="8" Height="4" RadiusX="1" RadiusY="1" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="2" Canvas.Top="5" Width="12" Height="5" RadiusX="1.5" RadiusY="1.5" Fill="{StaticResource AppMenuIconAccentBrush}" />
|
||||
<Rectangle Canvas.Left="4" Canvas.Top="8.5" Width="8" Height="5" Fill="#FFF9FCFE" Stroke="{StaticResource AppMenuIconAccentBrush}" StrokeThickness="1" />
|
||||
<Ellipse Canvas.Left="10.5" Canvas.Top="9.5" Width="4" Height="4" Fill="{StaticResource AppMenuIconSuccessBrush}" />
|
||||
<Path Fill="White" Data="M12.1,10.4 L12.9,11.2 L14.2,9.6 L14.8,10.1 L12.9,12.4 L11.5,11 Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Годен">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Grid Width="16" Height="16">
|
||||
<Ellipse Width="14" Height="14" Fill="{StaticResource AppMenuIconSuccessBrush}" />
|
||||
<Path Fill="White" Data="M5.1,8.2 L7.2,10.3 L11.6,5.6 L12.8,6.6 L7.3,12.3 L3.9,8.9 Z" />
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Забракован">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Grid Width="16" Height="16">
|
||||
<Ellipse Width="14" Height="14" Fill="{StaticResource AppMenuIconDangerBrush}" />
|
||||
<Path Stroke="White" StrokeThickness="1.8" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Data="M5.1,5.1 L10.9,10.9 M10.9,5.1 L5.1,10.9" />
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Отменить проверку">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Path Fill="{StaticResource AppMenuIconWarningBrush}" Data="M7.8,2.2 C10.8,2.2 13.2,4.6 13.2,7.6 C13.2,10.6 10.8,13 7.8,13 C5.5,13 3.6,11.6 2.8,9.5 L4.5,9.5 C5.2,10.8 6.4,11.5 7.8,11.5 C10,11.5 11.7,9.8 11.7,7.6 C11.7,5.4 10,3.7 7.8,3.7 C6.5,3.7 5.3,4.3 4.6,5.4 L6.7,5.4 L3.8,8.2 L1.1,5.4 L3.1,5.4 C4,3.4 5.8,2.2 7.8,2.2 Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="Header" Value="Виды клейм...">
|
||||
<Setter Property="Icon">
|
||||
<Setter.Value>
|
||||
<Viewbox Width="14" Height="14">
|
||||
<Canvas Width="16" Height="16">
|
||||
<Ellipse Canvas.Left="2.5" Canvas.Top="2.5" Width="11" Height="11" Fill="{StaticResource AppMenuIconWarningBrush}" />
|
||||
<Path Fill="White" Data="M8,4 L8.9,6.2 L11.3,6.3 L9.4,7.8 L10.1,10.1 L8,8.8 L5.9,10.1 L6.6,7.8 L4.7,6.3 L7.1,6.2 Z" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ListBox}">
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace XLAB
|
||||
|
||||
public string InventoryNumber { get; set; }
|
||||
|
||||
public string StickerNumbers { get; set; }
|
||||
|
||||
public string Notes { get; set; }
|
||||
}
|
||||
|
||||
@@ -48,6 +50,10 @@ namespace XLAB
|
||||
|
||||
public DateTime? VerificationDocumentDate { get; set; }
|
||||
|
||||
public string StickerNumber { get; set; }
|
||||
|
||||
public string VerifierName { get; set; }
|
||||
|
||||
public int PeriodMonths { get; set; }
|
||||
|
||||
public DateTime? AcceptedOn { get; set; }
|
||||
|
||||
@@ -166,6 +166,7 @@ SELECT
|
||||
ownerOrg.NMFRPD AS OwnerOrganizationName,
|
||||
z.NNZV AS SerialNumber,
|
||||
z.NNIN AS InventoryNumber,
|
||||
stickers.StickerNumbers AS StickerNumbers,
|
||||
CAST(z.DSEKZ AS nvarchar(max)) AS Notes
|
||||
FROM dbo.EKZ z
|
||||
JOIN dbo.TPRZ tprz ON tprz.IDTPRZ = z.IDTPRZ
|
||||
@@ -173,6 +174,25 @@ JOIN dbo.TIPS tips ON tips.IDTIPS = tprz.IDTIPS
|
||||
JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||||
JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||||
JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT STUFF(
|
||||
(
|
||||
SELECT N' ' + sticker.StickerNumber
|
||||
FROM
|
||||
(
|
||||
SELECT DISTINCT LTRIM(RTRIM(m.NNNKL)) AS StickerNumber
|
||||
FROM dbo.EKZMK m
|
||||
WHERE m.IDEKZ = z.IDEKZ
|
||||
AND NULLIF(LTRIM(RTRIM(m.NNNKL)), N'') IS NOT NULL
|
||||
) sticker
|
||||
ORDER BY sticker.StickerNumber
|
||||
FOR XML PATH(''), TYPE
|
||||
).value('.', 'nvarchar(max)'),
|
||||
1,
|
||||
1,
|
||||
N'') AS StickerNumbers
|
||||
) stickers
|
||||
WHERE ISNULL(z.IsDeleted, 0) = 0
|
||||
ORDER BY ownerOrg.NMFRPD, areas.NMOI, names.NMTP, tips.TP, tprz.DPZN, z.NNZV, z.IDEKZ;";
|
||||
|
||||
@@ -202,6 +222,7 @@ ORDER BY ownerOrg.NMFRPD, areas.NMOI, names.NMTP, tips.TP, tprz.DPZN, z.NNZV, z.
|
||||
OwnerOrganizationName = ReferenceDirectorySqlHelpers.GetString(reader, "OwnerOrganizationName"),
|
||||
SerialNumber = ReferenceDirectorySqlHelpers.GetString(reader, "SerialNumber"),
|
||||
InventoryNumber = ReferenceDirectorySqlHelpers.GetString(reader, "InventoryNumber"),
|
||||
StickerNumbers = ReferenceDirectorySqlHelpers.GetString(reader, "StickerNumbers"),
|
||||
Notes = ReferenceDirectorySqlHelpers.GetString(reader, "Notes")
|
||||
});
|
||||
}
|
||||
@@ -222,6 +243,8 @@ SELECT
|
||||
m.NNZVPV AS DocumentNumber,
|
||||
verificationDocument.NNDMS AS VerificationDocumentNumber,
|
||||
verificationDocument.DTDMS AS VerificationDocumentDate,
|
||||
m.NNNKL AS StickerNumber,
|
||||
verifier.PRFIO AS VerifierName,
|
||||
m.PRMK AS PeriodMonths,
|
||||
m.DTPRM AS AcceptedOn,
|
||||
m.DTMKPL AS PlannedOn,
|
||||
@@ -232,6 +255,7 @@ SELECT
|
||||
FROM dbo.EKZMK m
|
||||
LEFT JOIN dbo.SPVDMK verificationType ON verificationType.IDSPVDMK = m.IDSPVDMK
|
||||
LEFT JOIN dbo.FRPD organization ON organization.IDFRPD = m.IDFRPD
|
||||
LEFT JOIN dbo.PRSN verifier ON verifier.IDPRSN = m.IDPRSN
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
@@ -271,6 +295,8 @@ ORDER BY ISNULL(m.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, m.IDEKZMK DES
|
||||
DocumentNumber = ReferenceDirectorySqlHelpers.GetString(reader, "DocumentNumber"),
|
||||
VerificationDocumentNumber = ReferenceDirectorySqlHelpers.GetString(reader, "VerificationDocumentNumber"),
|
||||
VerificationDocumentDate = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "VerificationDocumentDate"),
|
||||
StickerNumber = ReferenceDirectorySqlHelpers.GetString(reader, "StickerNumber"),
|
||||
VerifierName = ReferenceDirectorySqlHelpers.GetString(reader, "VerifierName"),
|
||||
PeriodMonths = ReferenceDirectorySqlHelpers.GetInt32(reader, "PeriodMonths"),
|
||||
AcceptedOn = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "AcceptedOn"),
|
||||
PlannedOn = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "PlannedOn"),
|
||||
|
||||
@@ -119,12 +119,18 @@
|
||||
IsReadOnly="True"
|
||||
HeadersVisibility="Column">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Документ"
|
||||
<DataGridTextColumn Header="ПСВ/Акт-справка"
|
||||
Width="220"
|
||||
Binding="{Binding DocumentNumber}" />
|
||||
<DataGridTextColumn Header="Документ по поверке"
|
||||
Width="180"
|
||||
Binding="{Binding VerificationDocumentDisplay}" />
|
||||
<DataGridTextColumn Header="Номер наклейки"
|
||||
Width="140"
|
||||
Binding="{Binding StickerNumber}" />
|
||||
<DataGridTextColumn Header="Поверитель"
|
||||
Width="180"
|
||||
Binding="{Binding VerifierName}" />
|
||||
<DataGridTextColumn Header="Вид МК"
|
||||
Width="120"
|
||||
Binding="{Binding VerificationTypeName}" />
|
||||
@@ -140,7 +146,7 @@
|
||||
<DataGridTextColumn Header="План"
|
||||
Width="95"
|
||||
Binding="{Binding PlannedOn, StringFormat=d}" />
|
||||
<DataGridTextColumn Header="Выполнен"
|
||||
<DataGridTextColumn Header="Поверен"
|
||||
Width="95"
|
||||
Binding="{Binding PerformedOn, StringFormat=d}" />
|
||||
<DataGridTextColumn Header="Выдан"
|
||||
|
||||
@@ -183,6 +183,7 @@ namespace XLAB
|
||||
OwnerOrganizationName = source.OwnerOrganizationName,
|
||||
SerialNumber = source.SerialNumber,
|
||||
InventoryNumber = source.InventoryNumber,
|
||||
StickerNumbers = source.StickerNumbers,
|
||||
Notes = source.Notes
|
||||
};
|
||||
}
|
||||
@@ -422,6 +423,7 @@ namespace XLAB
|
||||
item == null ? null : item.RegistryNumber,
|
||||
item == null ? null : item.SerialNumber,
|
||||
item == null ? null : item.InventoryNumber,
|
||||
item == null ? null : item.StickerNumbers,
|
||||
item == null ? null : item.Notes
|
||||
}.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); }))
|
||||
.ToUpperInvariant();
|
||||
|
||||
@@ -327,7 +327,7 @@
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="DimGray"
|
||||
Text="Поиск по типу, диапазону, госреестру или зав. №" />
|
||||
Text="Поиск по наименованию, типу, диапазону, характеристикам, госреестру или зав. №" />
|
||||
</Grid>
|
||||
|
||||
<DataGrid Grid.Row="1"
|
||||
@@ -365,12 +365,18 @@
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
<DataGridTextColumn Header="Наименование"
|
||||
Width="220"
|
||||
Binding="{Binding InstrumentName}" />
|
||||
<DataGridTextColumn Header="Тип"
|
||||
Width="180"
|
||||
Width="160"
|
||||
Binding="{Binding InstrumentType}" />
|
||||
<DataGridTextColumn Header="Диапазон"
|
||||
Width="170"
|
||||
Width="160"
|
||||
Binding="{Binding RangeText}" />
|
||||
<DataGridTextColumn Header="Характеристики"
|
||||
Width="160"
|
||||
Binding="{Binding AccuracyText}" />
|
||||
<DataGridTextColumn Header="Госреестр"
|
||||
Width="120"
|
||||
Binding="{Binding RegistryNumber}" />
|
||||
@@ -432,7 +438,7 @@
|
||||
SelectedItem="{Binding SelectedDocumentLine, Mode=TwoWay}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
IsReadOnly="{Binding IsDocumentLinesReadOnly}"
|
||||
HeadersVisibility="Column">
|
||||
<DataGrid.ContextMenu>
|
||||
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||
@@ -473,22 +479,31 @@
|
||||
</DataGridTemplateColumn>
|
||||
<DataGridTextColumn Header="Зав. №"
|
||||
Width="120"
|
||||
Binding="{Binding SerialNumber}" />
|
||||
Binding="{Binding SerialNumber}"
|
||||
IsReadOnly="True" />
|
||||
<DataGridTextColumn Header="Дата поверки"
|
||||
Width="110"
|
||||
Binding="{Binding VerificationDateDisplay}" />
|
||||
Binding="{Binding VerificationDateDisplay}"
|
||||
IsReadOnly="True" />
|
||||
<DataGridTextColumn Header="Поверитель"
|
||||
Width="180"
|
||||
Binding="{Binding VerifierName}" />
|
||||
Binding="{Binding VerifierName}"
|
||||
IsReadOnly="True" />
|
||||
<DataGridTextColumn Header="Номер наклейки"
|
||||
Width="150"
|
||||
Binding="{Binding StickerNumber}" />
|
||||
Binding="{Binding StickerNumber}"
|
||||
IsReadOnly="True" />
|
||||
<DataGridTextColumn Header="Результат поверки"
|
||||
Width="140"
|
||||
Binding="{Binding ResultText}" />
|
||||
Binding="{Binding ResultText}"
|
||||
IsReadOnly="True" />
|
||||
<DataGridTextColumn Header="Номер документа по поверке"
|
||||
Width="240"
|
||||
Binding="{Binding VerificationDocumentDisplay}" />
|
||||
Binding="{Binding VerificationDocumentDisplay}"
|
||||
IsReadOnly="True" />
|
||||
<DataGridTextColumn Header="Комплектность"
|
||||
Width="240"
|
||||
Binding="{Binding Completeness, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
|
||||
@@ -206,6 +206,11 @@ namespace XLAB
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDocumentLinesReadOnly
|
||||
{
|
||||
get { return !CanModifySelectedDocument(); }
|
||||
}
|
||||
|
||||
public DateTime? HeaderIssuedOn
|
||||
{
|
||||
get { return _headerIssuedOn; }
|
||||
@@ -228,6 +233,7 @@ namespace XLAB
|
||||
RaiseCommandStates();
|
||||
OnPropertyChanged("IsCustomerEditable");
|
||||
OnPropertyChanged("IsDocumentHeaderEditable");
|
||||
OnPropertyChanged("IsDocumentLinesReadOnly");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,6 +299,7 @@ namespace XLAB
|
||||
RaiseCommandStates();
|
||||
OnPropertyChanged("IsCustomerEditable");
|
||||
OnPropertyChanged("IsDocumentHeaderEditable");
|
||||
OnPropertyChanged("IsDocumentLinesReadOnly");
|
||||
LoadSelectedDocumentAsync();
|
||||
}
|
||||
}
|
||||
@@ -501,6 +508,23 @@ namespace XLAB
|
||||
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
|
||||
@@ -936,14 +960,14 @@ namespace XLAB
|
||||
|
||||
foreach (var pendingLinesByDocument in _pendingLinesByDocumentKey)
|
||||
{
|
||||
if (string.Equals(pendingLinesByDocument.Key, currentDocument.DocumentKey, StringComparison.OrdinalIgnoreCase))
|
||||
if (MatchesPendingLinesStorageKey(currentDocument, pendingLinesByDocument.Key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var otherDocument = Documents.FirstOrDefault(delegate(PsvDocumentSummary document)
|
||||
{
|
||||
return string.Equals(document.DocumentKey, pendingLinesByDocument.Key, StringComparison.OrdinalIgnoreCase);
|
||||
return MatchesPendingLinesStorageKey(document, pendingLinesByDocument.Key);
|
||||
});
|
||||
|
||||
if (otherDocument == null
|
||||
@@ -1371,7 +1395,7 @@ namespace XLAB
|
||||
RunBusyOperation(async delegate
|
||||
{
|
||||
var result = await _service.DeleteDocumentAsync(selectedDocument.DocumentNumber);
|
||||
_pendingLinesByDocumentKey.Remove(selectedDocument.DocumentKey);
|
||||
_pendingLinesByDocumentKey.Remove(GetPendingLinesStorageKey(selectedDocument));
|
||||
await RefreshDocumentsCoreAsync(null, null);
|
||||
_dialogService.ShowInfo(
|
||||
string.Format(
|
||||
@@ -1385,7 +1409,7 @@ namespace XLAB
|
||||
private void DeleteDraftDocument(PsvDocumentSummary draft)
|
||||
{
|
||||
_draftDocuments.RemoveAll(delegate(PsvDocumentSummary item) { return item.DocumentKey == draft.DocumentKey; });
|
||||
_pendingLinesByDocumentKey.Remove(draft.DocumentKey);
|
||||
_pendingLinesByDocumentKey.Remove(GetPendingLinesStorageKey(draft));
|
||||
Documents.Remove(draft);
|
||||
DocumentsView.Refresh();
|
||||
SelectedDocument = Documents.Count > 0 ? Documents[0] : null;
|
||||
@@ -1760,7 +1784,9 @@ namespace XLAB
|
||||
}
|
||||
|
||||
return Contains(group.InstrumentType, GroupFilterText)
|
||||
|| Contains(group.InstrumentName, GroupFilterText)
|
||||
|| Contains(group.RangeText, GroupFilterText)
|
||||
|| Contains(group.AccuracyText, GroupFilterText)
|
||||
|| Contains(group.RegistryNumber, GroupFilterText)
|
||||
|| Contains(group.SerialNumbersText, GroupFilterText);
|
||||
}
|
||||
@@ -1835,6 +1861,7 @@ namespace XLAB
|
||||
&& 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);
|
||||
}
|
||||
|
||||
@@ -1860,12 +1887,41 @@ namespace XLAB
|
||||
return new List<PsvDocumentLine>();
|
||||
}
|
||||
|
||||
var pendingKey = GetPendingLinesStorageKey(document);
|
||||
if (string.IsNullOrWhiteSpace(pendingKey))
|
||||
{
|
||||
return new List<PsvDocumentLine>();
|
||||
}
|
||||
|
||||
List<PsvDocumentLine> lines;
|
||||
return _pendingLinesByDocumentKey.TryGetValue(document.DocumentKey, out 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>();
|
||||
@@ -2078,11 +2134,17 @@ namespace XLAB
|
||||
return;
|
||||
}
|
||||
|
||||
var pendingKey = GetPendingLinesStorageKey(SelectedDocument);
|
||||
if (string.IsNullOrWhiteSpace(pendingKey))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<PsvDocumentLine> pendingLines;
|
||||
if (!_pendingLinesByDocumentKey.TryGetValue(SelectedDocument.DocumentKey, out pendingLines))
|
||||
if (!_pendingLinesByDocumentKey.TryGetValue(pendingKey, out pendingLines))
|
||||
{
|
||||
pendingLines = new List<PsvDocumentLine>();
|
||||
_pendingLinesByDocumentKey[SelectedDocument.DocumentKey] = pendingLines;
|
||||
_pendingLinesByDocumentKey[pendingKey] = pendingLines;
|
||||
}
|
||||
|
||||
var candidateLines = selectedItems
|
||||
@@ -2195,17 +2257,28 @@ namespace XLAB
|
||||
return;
|
||||
}
|
||||
|
||||
List<PsvDocumentLine> pendingLines;
|
||||
if (!_pendingLinesByDocumentKey.TryGetValue(SelectedDocument.DocumentKey, out pendingLines))
|
||||
var pendingKey = GetPendingLinesStorageKey(SelectedDocument);
|
||||
if (string.IsNullOrWhiteSpace(pendingKey))
|
||||
{
|
||||
pendingLines = new List<PsvDocumentLine>();
|
||||
_pendingLinesByDocumentKey[SelectedDocument.DocumentKey] = pendingLines;
|
||||
return;
|
||||
}
|
||||
|
||||
var serialNumber = string.IsNullOrWhiteSpace(result.SerialNumber) ? string.Empty : result.SerialNumber.Trim();
|
||||
if (string.IsNullOrWhiteSpace(serialNumber))
|
||||
List<PsvDocumentLine> pendingLines;
|
||||
if (!_pendingLinesByDocumentKey.TryGetValue(pendingKey, out pendingLines))
|
||||
{
|
||||
_dialogService.ShowWarning("Введите заводской номер.");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -2215,11 +2288,34 @@ namespace XLAB
|
||||
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)
|
||||
{
|
||||
@@ -2227,10 +2323,21 @@ namespace XLAB
|
||||
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(
|
||||
@@ -2239,16 +2346,22 @@ namespace XLAB
|
||||
result.TypeItem.RegistryNumber,
|
||||
serialNumber);
|
||||
|
||||
if (DocumentLines.Any(delegate(PsvDocumentLine line)
|
||||
if (duplicateKeys.Contains(duplicateKey))
|
||||
{
|
||||
return string.Equals(line.DuplicateKey, duplicateKey, StringComparison.OrdinalIgnoreCase);
|
||||
}))
|
||||
{
|
||||
_dialogService.ShowWarning("Такой прибор уже есть в ПСВ.");
|
||||
return;
|
||||
skippedDuplicateCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
pendingLines.Add(candidateLine);
|
||||
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)
|
||||
{
|
||||
@@ -2256,7 +2369,42 @@ namespace XLAB
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
@@ -2323,21 +2471,26 @@ namespace XLAB
|
||||
{
|
||||
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),
|
||||
@@ -2515,12 +2668,14 @@ namespace XLAB
|
||||
|
||||
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 result = await Task.Run(delegate { return _service.SaveDocument(currentDocumentNumber, request, pendingLines); });
|
||||
var documentLinesSnapshot = DocumentLines.ToList();
|
||||
var result = await Task.Run(delegate { return _service.SaveDocument(currentDocumentNumber, request, documentLinesSnapshot); });
|
||||
|
||||
_pendingLinesByDocumentKey.Remove(documentKey);
|
||||
_pendingLinesByDocumentKey.Remove(documentPendingKey);
|
||||
if (wasDraft)
|
||||
{
|
||||
_draftDocuments.RemoveAll(delegate(PsvDocumentSummary draft) { return draft.DocumentKey == documentKey; });
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace XLAB
|
||||
{
|
||||
internal sealed class PsvDataService
|
||||
{
|
||||
private const int EkzMkCompletenessMaxLength = 600;
|
||||
|
||||
public bool DocumentNumberExists(string documentNumber, string excludeDocumentNumber)
|
||||
{
|
||||
var normalizedNumber = NormalizeDocumentNumber(documentNumber);
|
||||
@@ -1109,7 +1111,7 @@ ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, sizeInfo.NNGSRS;";
|
||||
}
|
||||
}
|
||||
|
||||
public DocumentSaveResult SaveDocument(string currentDocumentNumber, DocumentEditorResult document, IEnumerable<PsvDocumentLine> pendingLines)
|
||||
public DocumentSaveResult SaveDocument(string currentDocumentNumber, DocumentEditorResult document, IEnumerable<PsvDocumentLine> documentLines)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
@@ -1124,13 +1126,22 @@ ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, sizeInfo.NNGSRS;";
|
||||
|
||||
document.DocumentNumber = normalizedNumber;
|
||||
|
||||
var distinctPendingLines = pendingLines == null
|
||||
var materializedDocumentLines = documentLines == null
|
||||
? new List<PsvDocumentLine>()
|
||||
: pendingLines
|
||||
: documentLines
|
||||
.Where(delegate(PsvDocumentLine line) { return line != null; })
|
||||
.ToList();
|
||||
|
||||
var distinctPendingLines = materializedDocumentLines
|
||||
.Where(IsPendingLineReadyForSave)
|
||||
.GroupBy(GetPendingLineSaveKey, StringComparer.OrdinalIgnoreCase)
|
||||
.Select(delegate(IGrouping<string, PsvDocumentLine> group) { return group.First(); })
|
||||
.ToList();
|
||||
var persistedLines = materializedDocumentLines
|
||||
.Where(delegate(PsvDocumentLine line) { return !line.IsPendingInsert && line.CardId > 0; })
|
||||
.GroupBy(delegate(PsvDocumentLine line) { return line.CardId; })
|
||||
.Select(delegate(IGrouping<int, PsvDocumentLine> group) { return group.First(); })
|
||||
.ToList();
|
||||
|
||||
using (var connection = CreateConnection())
|
||||
{
|
||||
@@ -1165,6 +1176,12 @@ ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, sizeInfo.NNGSRS;";
|
||||
{
|
||||
throw new InvalidOperationException("Строки EKZMK для выбранного ПСВ не найдены.");
|
||||
}
|
||||
|
||||
var updatedCompletenessCount = UpdateDocumentLineCompleteness(connection, transaction, normalizedNumber, persistedLines);
|
||||
if (updatedCompletenessCount > updatedEkzMkCount)
|
||||
{
|
||||
updatedEkzMkCount = updatedCompletenessCount;
|
||||
}
|
||||
}
|
||||
|
||||
var insertedEkzMkCount = 0;
|
||||
@@ -1206,13 +1223,19 @@ ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, sizeInfo.NNGSRS;";
|
||||
continue;
|
||||
}
|
||||
|
||||
var effectiveVerificationTypeId = template.IdSpvdmk;
|
||||
if (!effectiveVerificationTypeId.HasValue || effectiveVerificationTypeId.Value <= 0)
|
||||
{
|
||||
if (!verificationTypeLoaded)
|
||||
{
|
||||
verificationTypeId = LoadVerificationTypeId(connection, transaction);
|
||||
verificationTypeLoaded = true;
|
||||
}
|
||||
|
||||
var cardId = InsertEkzMk(connection, transaction, verificationTypeId, document, normalizedNumber, instrumentId, template, pendingLine);
|
||||
effectiveVerificationTypeId = verificationTypeId;
|
||||
}
|
||||
|
||||
var cardId = InsertEkzMk(connection, transaction, effectiveVerificationTypeId.Value, document, normalizedNumber, instrumentId, template, pendingLine);
|
||||
if (!string.IsNullOrWhiteSpace(pendingLine.VerificationDocumentNumber))
|
||||
{
|
||||
if (!pendingLine.VerificationDocumentFormId.HasValue || !pendingLine.VerificationDocumentLinkTypeId.HasValue)
|
||||
@@ -1493,6 +1516,7 @@ ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, sizeInfo.NNGSRS;";
|
||||
private static bool IsPendingLineReadyForSave(PsvDocumentLine line)
|
||||
{
|
||||
return line != null
|
||||
&& line.IsPendingInsert
|
||||
&& (line.InstrumentId > 0
|
||||
|| (line.TypeSizeId > 0 && !string.IsNullOrWhiteSpace(line.SerialNumber)));
|
||||
}
|
||||
@@ -1520,6 +1544,11 @@ ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, sizeInfo.NNGSRS;";
|
||||
throw new InvalidOperationException("Для новой строки ПСВ не указан заводской номер.");
|
||||
}
|
||||
|
||||
if (serialNumber.Length > EkzDirectoryRules.SerialNumberMaxLength)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Заводской номер не должен превышать {0} символов.", EkzDirectoryRules.SerialNumberMaxLength));
|
||||
}
|
||||
|
||||
if (!document.CustomerId.HasValue)
|
||||
{
|
||||
throw new InvalidOperationException("Для добавления прибора по типу должен быть выбран заказчик ПСВ.");
|
||||
@@ -2135,7 +2164,7 @@ VALUES
|
||||
@idsptsmp,
|
||||
@idspssmp,
|
||||
@GUIDEKZMK,
|
||||
NULL,
|
||||
@DSEKZMK,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -2189,6 +2218,9 @@ SELECT CAST(SCOPE_IDENTITY() AS int);";
|
||||
command.Parameters.Add("@idsptsmp", SqlDbType.Int).Value = (object)template.IdSptsmp ?? DBNull.Value;
|
||||
command.Parameters.Add("@idspssmp", SqlDbType.Int).Value = (object)template.IdSpssmp ?? DBNull.Value;
|
||||
command.Parameters.Add("@GUIDEKZMK", SqlDbType.UniqueIdentifier).Value = Guid.NewGuid();
|
||||
command.Parameters.Add("@DSEKZMK", SqlDbType.NVarChar, EkzMkCompletenessMaxLength).Value = pendingLine == null
|
||||
? DBNull.Value
|
||||
: (object)NormalizeOptionalCompleteness(pendingLine.Notes) ?? DBNull.Value;
|
||||
command.Parameters.Add("@NRVRMNDmp", SqlDbType.Decimal).Value = (object)template.Nrvrmndmp ?? DBNull.Value;
|
||||
command.Parameters["@NRVRMNDmp"].Precision = 10;
|
||||
command.Parameters["@NRVRMNDmp"].Scale = 2;
|
||||
@@ -2447,8 +2479,17 @@ WHERE z.IDEKZ = @InstrumentId;";
|
||||
const string sql = @"
|
||||
SELECT TOP (1) IDSPVDMK
|
||||
FROM dbo.SPVDMK
|
||||
WHERE OBVDMK = N'П' OR NMVDMK = N'Поверка'
|
||||
ORDER BY CASE WHEN OBVDMK = N'П' THEN 0 ELSE 1 END, IDSPVDMK;";
|
||||
WHERE UPPER(LTRIM(RTRIM(ISNULL(OBVDMK, N'')))) = N'П'
|
||||
OR UPPER(LTRIM(RTRIM(ISNULL(NMVDMK, N'')))) = N'ПОВЕРКА'
|
||||
OR UPPER(LTRIM(RTRIM(ISNULL(NMVDMK, N'')))) LIKE N'ПОВЕРК%'
|
||||
OR UPPER(LTRIM(RTRIM(ISNULL(NMVDMK, N'')))) LIKE N'%ПОВЕРК%'
|
||||
ORDER BY CASE
|
||||
WHEN UPPER(LTRIM(RTRIM(ISNULL(OBVDMK, N'')))) = N'П' THEN 0
|
||||
WHEN UPPER(LTRIM(RTRIM(ISNULL(NMVDMK, N'')))) = N'ПОВЕРКА' THEN 1
|
||||
WHEN UPPER(LTRIM(RTRIM(ISNULL(NMVDMK, N'')))) LIKE N'ПОВЕРК%' THEN 2
|
||||
ELSE 3
|
||||
END,
|
||||
IDSPVDMK;";
|
||||
|
||||
using (var command = new SqlCommand(sql, connection, transaction))
|
||||
{
|
||||
@@ -2478,6 +2519,7 @@ WITH TemplateCandidates AS
|
||||
m.IDSPMU,
|
||||
m.IDGRSI,
|
||||
m.IDKSPRL,
|
||||
m.IDSPVDMK,
|
||||
m.IDSPVDMC,
|
||||
m.IDFRPD,
|
||||
m.IDSPMPOB,
|
||||
@@ -2516,6 +2558,7 @@ WITH TemplateCandidates AS
|
||||
m.IDSPMU,
|
||||
m.IDGRSI,
|
||||
m.IDKSPRL,
|
||||
m.IDSPVDMK,
|
||||
m.IDSPVDMC,
|
||||
m.IDFRPD,
|
||||
m.IDSPMPOB,
|
||||
@@ -2564,6 +2607,7 @@ ORDER BY Priority;";
|
||||
IdSpmu = GetNullableInt32(reader, "IDSPMU"),
|
||||
IdGrsi = GetNullableInt32(reader, "IDGRSI"),
|
||||
IdKsprl = GetNullableInt32(reader, "IDKSPRL"),
|
||||
IdSpvdmk = GetNullableInt32(reader, "IDSPVDMK"),
|
||||
IdSpvdmc = GetNullableInt32(reader, "IDSPVDMC"),
|
||||
IdFrpd = GetInt32(reader, "IDFRPD"),
|
||||
IdSpmpob = GetNullableInt32(reader, "IDSPMPOB"),
|
||||
@@ -2665,6 +2709,7 @@ WHERE z.IDEKZ = @InstrumentId
|
||||
IdSpmu = null,
|
||||
IdGrsi = GetNullableInt32(reader, "IDGRSI"),
|
||||
IdKsprl = null,
|
||||
IdSpvdmk = null,
|
||||
IdSpvdmc = GetNullableInt32(reader, "IDSPVDMC"),
|
||||
IdFrpd = GetInt32(reader, "IDFRPD"),
|
||||
IdSpmpob = null,
|
||||
@@ -2695,6 +2740,75 @@ WHERE z.IDEKZ = @InstrumentId
|
||||
}
|
||||
}
|
||||
|
||||
private static int UpdateDocumentLineCompleteness(
|
||||
SqlConnection connection,
|
||||
SqlTransaction transaction,
|
||||
string documentNumber,
|
||||
IEnumerable<PsvDocumentLine> persistedLines)
|
||||
{
|
||||
var materializedLines = persistedLines == null
|
||||
? new List<PsvDocumentLine>()
|
||||
: persistedLines
|
||||
.Where(delegate(PsvDocumentLine line) { return line != null && line.CardId > 0; })
|
||||
.GroupBy(delegate(PsvDocumentLine line) { return line.CardId; })
|
||||
.Select(delegate(IGrouping<int, PsvDocumentLine> group) { return group.First(); })
|
||||
.ToList();
|
||||
|
||||
var updatedCount = 0;
|
||||
foreach (var line in materializedLines)
|
||||
{
|
||||
updatedCount += UpdateDocumentLineCompletenessCore(
|
||||
connection,
|
||||
transaction,
|
||||
documentNumber,
|
||||
line.CardId,
|
||||
NormalizeOptionalCompleteness(line.Notes));
|
||||
}
|
||||
|
||||
return updatedCount;
|
||||
}
|
||||
|
||||
private static int UpdateDocumentLineCompletenessCore(
|
||||
SqlConnection connection,
|
||||
SqlTransaction transaction,
|
||||
string documentNumber,
|
||||
int cardId,
|
||||
string completeness)
|
||||
{
|
||||
const string sql = @"
|
||||
UPDATE dbo.EKZMK
|
||||
SET DSEKZMK = @Completeness
|
||||
WHERE NNZVPV = @DocumentNumber
|
||||
AND IDEKZMK = @CardId;
|
||||
|
||||
SELECT @@ROWCOUNT;";
|
||||
|
||||
using (var command = new SqlCommand(sql, connection, transaction))
|
||||
{
|
||||
command.CommandTimeout = 60;
|
||||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||||
command.Parameters.Add("@Completeness", SqlDbType.NVarChar, EkzMkCompletenessMaxLength).Value = (object)completeness ?? DBNull.Value;
|
||||
return Convert.ToInt32(command.ExecuteScalar());
|
||||
}
|
||||
}
|
||||
|
||||
private static string NormalizeOptionalCompleteness(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var normalizedValue = value.Trim();
|
||||
if (normalizedValue.Length > EkzMkCompletenessMaxLength)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Комплектность не должна превышать {0} символов.", EkzMkCompletenessMaxLength));
|
||||
}
|
||||
|
||||
return normalizedValue;
|
||||
}
|
||||
|
||||
private static string NormalizeDocumentNumber(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
|
||||
@@ -204,6 +204,7 @@ namespace XLAB
|
||||
public sealed class PsvDocumentLine : ObservableObject
|
||||
{
|
||||
private bool _isBatchSelected;
|
||||
private string _notes;
|
||||
|
||||
public int CardId { get; set; }
|
||||
|
||||
@@ -257,7 +258,23 @@ namespace XLAB
|
||||
|
||||
public string RejectionReason { get; set; }
|
||||
|
||||
public string Notes { get; set; }
|
||||
public string Notes
|
||||
{
|
||||
get { return _notes; }
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _notes, value))
|
||||
{
|
||||
OnPropertyChanged("Completeness");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Completeness
|
||||
{
|
||||
get { return Notes; }
|
||||
set { Notes = value; }
|
||||
}
|
||||
|
||||
public bool IsPendingInsert { get; set; }
|
||||
|
||||
@@ -347,10 +364,14 @@ namespace XLAB
|
||||
{
|
||||
private bool _isBatchSelected;
|
||||
|
||||
public string InstrumentName { get; set; }
|
||||
|
||||
public string InstrumentType { get; set; }
|
||||
|
||||
public string RangeText { get; set; }
|
||||
|
||||
public string AccuracyText { get; set; }
|
||||
|
||||
public string RegistryNumber { get; set; }
|
||||
|
||||
public string SerialNumbersText { get; set; }
|
||||
@@ -374,6 +395,7 @@ namespace XLAB
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -508,7 +530,7 @@ namespace XLAB
|
||||
{
|
||||
public AvailableInstrumentItem TypeItem { get; set; }
|
||||
|
||||
public string SerialNumber { get; set; }
|
||||
public System.Collections.Generic.IReadOnlyList<string> SerialNumbers { get; set; }
|
||||
}
|
||||
|
||||
public sealed class VerificationEditSeed
|
||||
@@ -640,6 +662,8 @@ namespace XLAB
|
||||
|
||||
public int? IdSptsmp { get; set; }
|
||||
|
||||
public int? IdSpvdmk { get; set; }
|
||||
|
||||
public int? IdSpvdkl { get; set; }
|
||||
|
||||
public int? IdSpvdsbmk { get; set; }
|
||||
|
||||
@@ -3,15 +3,21 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
internal sealed class PsvPrintService
|
||||
{
|
||||
private const int ClosePsvTableColumnCount = 12;
|
||||
private const int OpenPsvTableColumnCount = 7;
|
||||
private const int PrintDialogId = 88;
|
||||
private const int WordActiveEndAdjustedPageNumber = 1;
|
||||
private const int WordAlertsNone = 0;
|
||||
private const int WordCloseDoNotSaveChanges = 0;
|
||||
private const int WordParagraphTrue = -1;
|
||||
private const int WordStatisticPages = 2;
|
||||
|
||||
public void PrintDocument(PsvDocumentSummary document, IReadOnlyList<PsvDocumentLine> lines)
|
||||
{
|
||||
@@ -165,7 +171,7 @@ namespace XLAB
|
||||
ReplacePlaceholder(document, "next", FormatDate(dueDate));
|
||||
}
|
||||
|
||||
FillTable(document, groupedLines);
|
||||
FillTable(document, groupedLines, summary.IssuedOn.HasValue);
|
||||
}
|
||||
|
||||
private static void PopulateVerificationTemplate(dynamic document, PsvDocumentLine line)
|
||||
@@ -187,13 +193,14 @@ namespace XLAB
|
||||
ReplacePlaceholder(document, "date", FormatDate(verificationDate));
|
||||
}
|
||||
|
||||
private static void FillTable(dynamic document, IReadOnlyList<PrintedGroupRow> rowsToPrint)
|
||||
private static void FillTable(dynamic document, IReadOnlyList<PrintedGroupRow> rowsToPrint, bool isClosedDocument)
|
||||
{
|
||||
dynamic table = null;
|
||||
|
||||
try
|
||||
{
|
||||
table = document.Tables.Item(1);
|
||||
EnsurePsvTableLayout(table, isClosedDocument ? ClosePsvTableColumnCount : OpenPsvTableColumnCount);
|
||||
|
||||
for (var index = 0; index < rowsToPrint.Count; index++)
|
||||
{
|
||||
@@ -209,15 +216,28 @@ namespace XLAB
|
||||
SetCellText(row, 4, rowData.RangeText, false);
|
||||
SetCellText(row, 5, rowData.SerialNumberText, false);
|
||||
SetCellText(row, 6, rowData.GroupCount.ToString(CultureInfo.InvariantCulture), true);
|
||||
|
||||
if (isClosedDocument)
|
||||
{
|
||||
SetCellText(row, 7, rowData.PassedCount > 0 ? rowData.PassedCount.ToString(CultureInfo.InvariantCulture) : string.Empty, true);
|
||||
SetCellText(row, 8, rowData.FailedCount > 0 ? rowData.FailedCount.ToString(CultureInfo.InvariantCulture) : string.Empty, true);
|
||||
SetCellText(row, 9, rowData.Notes, false);
|
||||
SetCellText(row, 9, rowData.VerificationDocumentText, false);
|
||||
SetCellText(row, 10, rowData.StickerNumberText, false);
|
||||
SetCellText(row, 11, rowData.VerifierNameText, false);
|
||||
SetCellText(row, 12, rowData.Notes, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCellText(row, 7, rowData.Notes, false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseComObject(row);
|
||||
}
|
||||
}
|
||||
|
||||
EnsureTableSpillsToNextPage(document, table);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -225,6 +245,99 @@ namespace XLAB
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsureTableSpillsToNextPage(dynamic document, dynamic table)
|
||||
{
|
||||
if (document == null || table == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var rowCount = Convert.ToInt32(table.Rows.Count, CultureInfo.InvariantCulture);
|
||||
if (rowCount <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RepaginateDocument(document);
|
||||
|
||||
var totalPages = InvokeComIntMethod(document, "ComputeStatistics", WordStatisticPages);
|
||||
if (totalPages <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dynamic lastRow = null;
|
||||
dynamic firstCell = null;
|
||||
dynamic lastRowRange = null;
|
||||
dynamic firstCellRange = null;
|
||||
dynamic paragraphFormat = null;
|
||||
|
||||
try
|
||||
{
|
||||
lastRow = table.Rows.Item(rowCount);
|
||||
lastRowRange = lastRow.Range;
|
||||
|
||||
var lastRowPage = GetRangePageNumber(lastRowRange);
|
||||
if (lastRowPage >= totalPages)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
firstCell = lastRow.Cells.Item(1);
|
||||
firstCellRange = firstCell.Range;
|
||||
paragraphFormat = firstCellRange.ParagraphFormat;
|
||||
paragraphFormat.PageBreakBefore = WordParagraphTrue;
|
||||
RepaginateDocument(document);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseComObject(paragraphFormat);
|
||||
ReleaseComObject(firstCellRange);
|
||||
ReleaseComObject(lastRowRange);
|
||||
ReleaseComObject(firstCell);
|
||||
ReleaseComObject(lastRow);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnsurePsvTableLayout(dynamic table, int expectedColumnCount)
|
||||
{
|
||||
if (table == null)
|
||||
{
|
||||
throw new InvalidOperationException("В шаблоне ПСВ не найдена таблица для печати.");
|
||||
}
|
||||
|
||||
int actualColumnCount;
|
||||
|
||||
try
|
||||
{
|
||||
actualColumnCount = Convert.ToInt32(table.Columns.Count, CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Не удалось определить структуру таблицы шаблона ПСВ.", ex);
|
||||
}
|
||||
|
||||
if (actualColumnCount != expectedColumnCount)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Шаблон ПСВ имеет неверную структуру таблицы: ожидается {0} колонок, найдено {1}.",
|
||||
expectedColumnCount,
|
||||
actualColumnCount));
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetRangePageNumber(object range)
|
||||
{
|
||||
return InvokeComIndexedIntProperty(range, "Information", WordActiveEndAdjustedPageNumber);
|
||||
}
|
||||
|
||||
private static void RepaginateDocument(object document)
|
||||
{
|
||||
InvokeComMethod(document, "Repaginate");
|
||||
}
|
||||
|
||||
private static void SetCellText(dynamic row, int columnIndex, string value, bool centerAlign)
|
||||
{
|
||||
dynamic cell = null;
|
||||
@@ -274,7 +387,56 @@ namespace XLAB
|
||||
}
|
||||
}
|
||||
|
||||
private static IReadOnlyList<PrintedGroupRow> BuildPrintedGroups(IEnumerable<PsvDocumentLine> lines, bool includeClosedNotes)
|
||||
private static int InvokeComIndexedIntProperty(object target, string propertyName, object argument)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
throw new ArgumentNullException("target");
|
||||
}
|
||||
|
||||
return Convert.ToInt32(
|
||||
target.GetType().InvokeMember(
|
||||
propertyName,
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
target,
|
||||
new[] { argument }),
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private static int InvokeComIntMethod(object target, string methodName, object argument)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
throw new ArgumentNullException("target");
|
||||
}
|
||||
|
||||
return Convert.ToInt32(
|
||||
target.GetType().InvokeMember(
|
||||
methodName,
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
target,
|
||||
new[] { argument }),
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private static void InvokeComMethod(object target, string methodName)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
throw new ArgumentNullException("target");
|
||||
}
|
||||
|
||||
target.GetType().InvokeMember(
|
||||
methodName,
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
target,
|
||||
Array.Empty<object>());
|
||||
}
|
||||
|
||||
private static IReadOnlyList<PrintedGroupRow> BuildPrintedGroups(IEnumerable<PsvDocumentLine> lines, bool includeClosedDetails)
|
||||
{
|
||||
return (lines ?? Enumerable.Empty<PsvDocumentLine>())
|
||||
.GroupBy(delegate(PsvDocumentLine line)
|
||||
@@ -302,7 +464,10 @@ namespace XLAB
|
||||
GroupCount = materializedLines.Count,
|
||||
PassedCount = materializedLines.Count(delegate(PsvDocumentLine line) { return line.IsPassed == true; }),
|
||||
FailedCount = materializedLines.Count(delegate(PsvDocumentLine line) { return line.IsPassed == false; }),
|
||||
Notes = includeClosedNotes ? BuildClosedNotesText(materializedLines) : string.Empty
|
||||
VerificationDocumentText = includeClosedDetails ? BuildVerificationDocumentText(materializedLines) : string.Empty,
|
||||
StickerNumberText = includeClosedDetails ? BuildStickerNumberText(materializedLines) : string.Empty,
|
||||
VerifierNameText = includeClosedDetails ? BuildVerifierNameText(materializedLines) : string.Empty,
|
||||
Notes = BuildNotesText(materializedLines)
|
||||
};
|
||||
})
|
||||
.ToList();
|
||||
@@ -332,7 +497,7 @@ namespace XLAB
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (serialNumbers.Count > 3)
|
||||
if (serialNumbers.Count > 10)
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0} зав. номеров", serialNumbers.Count);
|
||||
}
|
||||
@@ -371,6 +536,46 @@ namespace XLAB
|
||||
return string.Join(". ", parts.ToArray());
|
||||
}
|
||||
|
||||
private static string BuildNotesText(IReadOnlyList<PsvDocumentLine> lines)
|
||||
{
|
||||
return string.Join("; ", lines
|
||||
.Select(delegate(PsvDocumentLine line) { return NormalizeText(line == null ? null : line.Notes); })
|
||||
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(delegate(string value) { return value; }, StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
private static string BuildVerificationDocumentText(IReadOnlyList<PsvDocumentLine> lines)
|
||||
{
|
||||
return string.Join("; ", lines
|
||||
.Select(FormatVerificationDocument)
|
||||
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(delegate(string value) { return value; }, StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
private static string BuildStickerNumberText(IReadOnlyList<PsvDocumentLine> lines)
|
||||
{
|
||||
return string.Join(", ", lines
|
||||
.Select(delegate(PsvDocumentLine line) { return NormalizeText(line == null ? null : line.StickerNumber); })
|
||||
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(delegate(string value) { return value; }, StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
private static string BuildVerifierNameText(IReadOnlyList<PsvDocumentLine> lines)
|
||||
{
|
||||
return string.Join("; ", lines
|
||||
.Select(delegate(PsvDocumentLine line) { return NormalizeText(line == null ? null : line.VerifierName); })
|
||||
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(delegate(string value) { return value; }, StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
private static string FormatVerificationDocument(PsvDocumentLine line)
|
||||
{
|
||||
if (line == null)
|
||||
@@ -445,6 +650,7 @@ namespace XLAB
|
||||
var candidates = new[]
|
||||
{
|
||||
Path.Combine(baseDirectory, fileName),
|
||||
Path.GetFullPath(Path.Combine(baseDirectory, "..", fileName)),
|
||||
Path.GetFullPath(Path.Combine(baseDirectory, "..", "..", fileName)),
|
||||
Path.GetFullPath(Path.Combine(baseDirectory, "..", "..", "..", fileName))
|
||||
};
|
||||
@@ -551,6 +757,12 @@ namespace XLAB
|
||||
public string RangeText { get; set; }
|
||||
|
||||
public string SerialNumberText { get; set; }
|
||||
|
||||
public string StickerNumberText { get; set; }
|
||||
|
||||
public string VerificationDocumentText { get; set; }
|
||||
|
||||
public string VerifierNameText { get; set; }
|
||||
}
|
||||
|
||||
private sealed class PrintGroupKey : IEquatable<PrintGroupKey>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace XLAB
|
||||
{
|
||||
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 XLAB
|
||||
}
|
||||
}
|
||||
|
||||
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 XLAB
|
||||
|
||||
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 XLAB
|
||||
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 XLAB
|
||||
&& 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 XLAB
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
|
||||
<DataGrid Grid.Row="2"
|
||||
<DataGrid x:Name="InstrumentsGrid"
|
||||
Grid.Row="2"
|
||||
ItemsSource="{Binding InstrumentsView}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
@@ -13,6 +14,12 @@ namespace XLAB
|
||||
|
||||
private void ViewModelOnCloseRequested(object sender, bool? dialogResult)
|
||||
{
|
||||
if (dialogResult.GetValueOrDefault())
|
||||
{
|
||||
InstrumentsGrid.CommitEdit(DataGridEditingUnit.Cell, true);
|
||||
InstrumentsGrid.CommitEdit(DataGridEditingUnit.Row, true);
|
||||
}
|
||||
|
||||
DialogResult = dialogResult;
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -44,6 +44,22 @@
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
HeadersVisibility="Column">
|
||||
<DataGrid.ContextMenu>
|
||||
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||
<MenuItem Header="Добавить"
|
||||
Command="{Binding AddCommand}" />
|
||||
<MenuItem Header="Изменить"
|
||||
Command="{Binding EditCommand}" />
|
||||
<MenuItem Header="Удалить"
|
||||
Command="{Binding DeleteCommand}" />
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow">
|
||||
<EventSetter Event="PreviewMouseRightButtonDown"
|
||||
Handler="DataGridRow_PreviewMouseRightButtonDown" />
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="ID"
|
||||
Width="90"
|
||||
@@ -66,18 +82,6 @@
|
||||
Margin="0,12,0,0"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
<Button Width="110"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding AddCommand}"
|
||||
Content="Добавить" />
|
||||
<Button Width="110"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding EditCommand}"
|
||||
Content="Изменить" />
|
||||
<Button Width="110"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding DeleteCommand}"
|
||||
Content="Удалить" />
|
||||
<Button Width="90"
|
||||
IsCancel="True"
|
||||
Content="Закрыть" />
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
@@ -13,6 +15,16 @@ namespace XLAB
|
||||
DataContext = _viewModel;
|
||||
}
|
||||
|
||||
private void DataGridRow_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var row = sender as DataGridRow;
|
||||
if (row != null)
|
||||
{
|
||||
row.IsSelected = true;
|
||||
row.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private async void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await _viewModel.InitializeAsync();
|
||||
|
||||
@@ -44,6 +44,22 @@
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
HeadersVisibility="Column">
|
||||
<DataGrid.ContextMenu>
|
||||
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||
<MenuItem Header="Добавить"
|
||||
Command="{Binding AddCommand}" />
|
||||
<MenuItem Header="Изменить"
|
||||
Command="{Binding EditCommand}" />
|
||||
<MenuItem Header="Удалить"
|
||||
Command="{Binding DeleteCommand}" />
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow">
|
||||
<EventSetter Event="PreviewMouseRightButtonDown"
|
||||
Handler="DataGridRow_PreviewMouseRightButtonDown" />
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="ID"
|
||||
Width="90"
|
||||
@@ -66,18 +82,6 @@
|
||||
Margin="0,12,0,0"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
<Button Width="110"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding AddCommand}"
|
||||
Content="Добавить" />
|
||||
<Button Width="110"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding EditCommand}"
|
||||
Content="Изменить" />
|
||||
<Button Width="110"
|
||||
Margin="0,0,8,0"
|
||||
Command="{Binding DeleteCommand}"
|
||||
Content="Удалить" />
|
||||
<Button Width="90"
|
||||
IsCancel="True"
|
||||
Content="Закрыть" />
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
@@ -13,6 +15,16 @@ namespace XLAB
|
||||
DataContext = _viewModel;
|
||||
}
|
||||
|
||||
private void DataGridRow_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var row = sender as DataGridRow;
|
||||
if (row != null)
|
||||
{
|
||||
row.IsSelected = true;
|
||||
row.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private async void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await _viewModel.InitializeAsync();
|
||||
|
||||
@@ -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}" />
|
||||
|
||||
@@ -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,10 +2323,21 @@ 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(
|
||||
@@ -2311,16 +2346,22 @@ namespace XLAB2
|
||||
result.TypeItem.RegistryNumber,
|
||||
serialNumber);
|
||||
|
||||
if (DocumentLines.Any(delegate(PsvDocumentLine line)
|
||||
if (duplicateKeys.Contains(duplicateKey))
|
||||
{
|
||||
return string.Equals(line.DuplicateKey, duplicateKey, StringComparison.OrdinalIgnoreCase);
|
||||
}))
|
||||
{
|
||||
_dialogService.ShowWarning("Такой прибор уже есть в ПСВ.");
|
||||
return;
|
||||
skippedDuplicateCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
pendingLines.Add(candidateLine);
|
||||
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)
|
||||
{
|
||||
@@ -2328,7 +2369,42 @@ namespace XLAB2
|
||||
}
|
||||
|
||||
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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user