Compare commits
2 Commits
b206467fd1
...
ff133e0215
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff133e0215 | ||
|
|
dedd1c5c25 |
143
XLAB/App.xaml
143
XLAB/App.xaml
@@ -1,9 +1,148 @@
|
||||
<Application x:Class="XLAB.App"
|
||||
<Application x:Class="XLAB.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:XLAB"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
<LinearGradientBrush x:Key="AppWindowBackgroundBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Color="#FFF8FAFD" Offset="0" />
|
||||
<GradientStop Color="#FFF2F6FB" Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
<SolidColorBrush x:Key="AppSurfaceBrush" Color="#FFFFFFFF" />
|
||||
<SolidColorBrush x:Key="AppAccentBrush" Color="#FF5C7FA8" />
|
||||
<SolidColorBrush x:Key="AppAccentSoftBrush" Color="#FFDDE8F3" />
|
||||
<SolidColorBrush x:Key="AppBorderBrush" Color="#FFC9D6E2" />
|
||||
<SolidColorBrush x:Key="AppTextBrush" Color="#FF263645" />
|
||||
<SolidColorBrush x:Key="AppMutedTextBrush" Color="#FF6B7B88" />
|
||||
<SolidColorBrush x:Key="AppButtonBrush" Color="#FFF5F8FC" />
|
||||
<SolidColorBrush x:Key="AppButtonHoverBrush" Color="#FFEAF2FA" />
|
||||
<SolidColorBrush x:Key="AppSelectionBrush" Color="#FFDDEAF7" />
|
||||
<SolidColorBrush x:Key="AppSelectionTextBrush" Color="#FF17324A" />
|
||||
<SolidColorBrush x:Key="OpenDocumentTenDaysBrush" Color="#FFF2F8EA" />
|
||||
<SolidColorBrush x:Key="OpenDocumentTwentyDaysBrush" Color="#FFFCF4E3" />
|
||||
<SolidColorBrush x:Key="OpenDocumentOverdueBrush" Color="#FFFBE7E7" />
|
||||
<SolidColorBrush x:Key="OpenDocumentTenDaysIndicatorBrush" Color="#FFB7D79F" />
|
||||
<SolidColorBrush x:Key="OpenDocumentTwentyDaysIndicatorBrush" Color="#FFF0C87A" />
|
||||
<SolidColorBrush x:Key="OpenDocumentOverdueIndicatorBrush" Color="#FFE2A0A0" />
|
||||
|
||||
<Style TargetType="{x:Type Window}">
|
||||
<Setter Property="Background" Value="{StaticResource AppWindowBackgroundBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type GroupBox}">
|
||||
<Setter Property="Background" Value="{StaticResource AppSurfaceBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppAccentBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type Button}">
|
||||
<Setter Property="Background" Value="{StaticResource AppButtonBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
<Setter Property="Padding" Value="10,4" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
<Setter Property="Background" Value="{StaticResource AppSurfaceBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
<Setter Property="Padding" Value="6,3" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ComboBox}">
|
||||
<Setter Property="Background" Value="{StaticResource AppSurfaceBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type DatePicker}">
|
||||
<Setter Property="Background" Value="{StaticResource AppSurfaceBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type CheckBox}">
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type RadioButton}">
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type Menu}">
|
||||
<Setter Property="Background" Value="{StaticResource AppSurfaceBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ContextMenu}">
|
||||
<Setter Property="Background" Value="{StaticResource AppSurfaceBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type MenuItem}">
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ListBox}">
|
||||
<Setter Property="Background" Value="{StaticResource AppSurfaceBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="{StaticResource AppSelectionBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppSelectionTextBrush}" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type DataGrid}">
|
||||
<Setter Property="Background" Value="{StaticResource AppSurfaceBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Setter Property="RowBackground" Value="#FFFFFFFF" />
|
||||
<Setter Property="AlternatingRowBackground" Value="#FFF7FAFD" />
|
||||
<Setter Property="ColumnHeaderStyle">
|
||||
<Setter.Value>
|
||||
<Style TargetType="{x:Type DataGridColumnHeader}">
|
||||
<Setter Property="Background" Value="#FFEAF2FA" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppAccentBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource AppBorderBrush}" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type DataGridRow}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppTextBrush}" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="{StaticResource AppSelectionBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppSelectionTextBrush}" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="{x:Type DataGridCell}">
|
||||
<Setter Property="BorderBrush" Value="#FFDCE5EE" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="{StaticResource AppSelectionBrush}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AppSelectionTextBrush}" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Новый ПСВ"
|
||||
Height="220"
|
||||
Height="240"
|
||||
Width="430"
|
||||
ResizeMode="NoResize"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
<MenuItem Header="Наименования типов СИ"
|
||||
Click="SpnmtpDirectoryMenuItem_Click" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="Организации и подразделения"
|
||||
<MenuItem Header="Подразделения"
|
||||
Click="FrpdDirectoryMenuItem_Click" />
|
||||
<MenuItem Header="Персоны"
|
||||
<MenuItem Header="Персонал"
|
||||
Click="PrsnDirectoryMenuItem_Click" />
|
||||
<MenuItem Header="Типоразмеры СИ"
|
||||
<MenuItem Header="Типоразмеры"
|
||||
Click="TypeSizeDirectoryMenuItem_Click" />
|
||||
</Menu>
|
||||
|
||||
@@ -40,22 +40,35 @@
|
||||
<GroupBox Grid.Column="0" Header="Документы">
|
||||
<Grid Margin="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
<WrapPanel Grid.Row="0"
|
||||
Margin="0,0,0,8"
|
||||
VerticalAlignment="Center">
|
||||
<RadioButton Margin="0,0,16,0"
|
||||
GroupName="DocumentModeGroup"
|
||||
Content="Открытые ПСВ"
|
||||
IsChecked="{Binding ShowOpenDocuments, Mode=TwoWay}" />
|
||||
<RadioButton GroupName="DocumentModeGroup"
|
||||
Content="Закрытые ПСВ (текущий год)"
|
||||
IsChecked="{Binding ShowClosedDocuments, Mode=TwoWay}" />
|
||||
</WrapPanel>
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Margin="0,0,0,4"
|
||||
VerticalAlignment="Center"
|
||||
Text="Поиск по номеру ПСВ или заказчику" />
|
||||
Text="Поиск по номеру ПСВ или подразделению" />
|
||||
|
||||
<TextBox Grid.Row="1"
|
||||
<TextBox Grid.Row="2"
|
||||
Margin="0,0,0,8"
|
||||
Text="{Binding DocumentFilterText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
|
||||
<ListBox Grid.Row="2"
|
||||
<ListBox Grid.Row="3"
|
||||
ItemsSource="{Binding DocumentsView}"
|
||||
SelectedItem="{Binding SelectedDocument, Mode=TwoWay}"
|
||||
BorderThickness="1"
|
||||
@@ -67,6 +80,7 @@
|
||||
Command="{Binding AddDocumentCommand}" />
|
||||
<MenuItem Header="Распечатать"
|
||||
Command="{Binding PrintDocumentCommand}" />
|
||||
<Separator/>
|
||||
<MenuItem Header="Удалить"
|
||||
Command="{Binding DeleteDocumentCommand}" />
|
||||
</ContextMenu>
|
||||
@@ -85,25 +99,66 @@
|
||||
<Border Padding="8"
|
||||
BorderBrush="#DDD"
|
||||
BorderThickness="0,0,0,1">
|
||||
<StackPanel>
|
||||
<DockPanel LastChildFill="False">
|
||||
<TextBlock DockPanel.Dock="Left"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding DocumentNumber}" />
|
||||
<TextBlock DockPanel.Dock="Right"
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="18" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Ellipse Grid.Column="0"
|
||||
Width="10"
|
||||
Height="10"
|
||||
Margin="0,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Stroke="#8093A4B5"
|
||||
StrokeThickness="1">
|
||||
<Ellipse.Style>
|
||||
<Style TargetType="Ellipse">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Setter Property="Fill" Value="Transparent" />
|
||||
<Setter Property="ToolTip" Value="{x:Null}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsOpenDocumentAtTenDays}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Setter Property="Fill" Value="{StaticResource OpenDocumentTenDaysIndicatorBrush}" />
|
||||
<Setter Property="ToolTip" Value="С даты приемки прошло 10 дней." />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsOpenDocumentAtTwentyDays}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Setter Property="Fill" Value="{StaticResource OpenDocumentTwentyDaysIndicatorBrush}" />
|
||||
<Setter Property="ToolTip" Value="С даты приемки прошло 20 дней." />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsOpenDocumentOverdue}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Setter Property="Fill" Value="{StaticResource OpenDocumentOverdueIndicatorBrush}" />
|
||||
<Setter Property="ToolTip" Value="Срок ПСВ истек: дата приемки + 30 дней." />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Ellipse.Style>
|
||||
</Ellipse>
|
||||
|
||||
<StackPanel Grid.Column="1">
|
||||
<DockPanel LastChildFill="False">
|
||||
<TextBlock DockPanel.Dock="Left"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding DocumentNumber}" />
|
||||
<TextBlock DockPanel.Dock="Right"
|
||||
Foreground="DimGray"
|
||||
Text="{Binding AcceptedOn, StringFormat=d}" />
|
||||
</DockPanel>
|
||||
<TextBlock Margin="0,4,0,0"
|
||||
Foreground="DimGray"
|
||||
Text="{Binding AcceptedOn, StringFormat=d}" />
|
||||
</DockPanel>
|
||||
<TextBlock Margin="0,4,0,0"
|
||||
Foreground="DimGray"
|
||||
Text="{Binding CustomerName}" />
|
||||
</StackPanel>
|
||||
Text="{Binding CustomerName}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<TextBlock Grid.Row="3"
|
||||
<TextBlock Grid.Row="4"
|
||||
Margin="0,8,0,0"
|
||||
Foreground="DimGray"
|
||||
Text="{Binding DocumentStatusText}" />
|
||||
@@ -142,6 +197,7 @@
|
||||
<TextBox Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,12,8"
|
||||
IsEnabled="{Binding IsDocumentHeaderEditable}"
|
||||
Text="{Binding DocumentNumberEditor, UpdateSourceTrigger=PropertyChanged}" />
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
@@ -152,6 +208,7 @@
|
||||
<DatePicker Grid.Row="0"
|
||||
Grid.Column="3"
|
||||
Margin="0,0,12,8"
|
||||
IsEnabled="{Binding IsDocumentHeaderEditable}"
|
||||
SelectedDate="{Binding HeaderReceivedOn, Mode=TwoWay}"
|
||||
SelectedDateFormat="Short" />
|
||||
|
||||
@@ -163,6 +220,7 @@
|
||||
<DatePicker Grid.Row="0"
|
||||
Grid.Column="5"
|
||||
Margin="0,0,12,8"
|
||||
IsEnabled="{Binding IsDocumentHeaderEditable}"
|
||||
SelectedDate="{Binding HeaderIssuedOn, Mode=TwoWay}"
|
||||
SelectedDateFormat="Short" />
|
||||
|
||||
@@ -172,6 +230,7 @@
|
||||
HorizontalAlignment="Right">
|
||||
<Button Width="120"
|
||||
Margin="0,0,0,8"
|
||||
IsEnabled="{Binding IsDocumentHeaderEditable}"
|
||||
Command="{Binding SaveDocumentHeaderCommand}"
|
||||
Content="Сохранить" />
|
||||
</StackPanel>
|
||||
@@ -180,7 +239,7 @@
|
||||
Grid.Column="0"
|
||||
Margin="0,0,8,6"
|
||||
VerticalAlignment="Center"
|
||||
Text="Заказчик" />
|
||||
Text="Подразделение" />
|
||||
<ComboBox Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="3"
|
||||
@@ -191,18 +250,6 @@
|
||||
SelectedValue="{Binding SelectedCustomerId, Mode=TwoWay}"
|
||||
IsEnabled="{Binding IsCustomerEditable}" />
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Grid.Column="4"
|
||||
Margin="0,0,8,6"
|
||||
VerticalAlignment="Center"
|
||||
Text="Подразделение" />
|
||||
<TextBox Grid.Row="1"
|
||||
Grid.Column="5"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="0,0,0,6"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding HeaderDepartmentName, Mode=OneWay}" />
|
||||
|
||||
<TextBlock Grid.Row="2"
|
||||
Grid.ColumnSpan="7"
|
||||
Foreground="DimGray"
|
||||
@@ -224,6 +271,7 @@
|
||||
Command="{Binding OpenInstrumentPickerCommand}" />
|
||||
<MenuItem Header="Добавить по типу"
|
||||
Command="{Binding OpenInstrumentTypePickerCommand}" />
|
||||
<Separator/>
|
||||
<MenuItem Header="Удалить"
|
||||
Command="{Binding DeleteSelectedGroupsCommand}" />
|
||||
</ContextMenu>
|
||||
@@ -263,7 +311,7 @@
|
||||
<DataGridTextColumn Header="Годных"
|
||||
Width="90"
|
||||
Binding="{Binding GoodCount}" />
|
||||
<DataGridTextColumn Header="Забраковано"
|
||||
<DataGridTextColumn Header="Забракованых"
|
||||
Width="105"
|
||||
Binding="{Binding RejectedCount}" />
|
||||
</DataGrid.Columns>
|
||||
@@ -296,7 +344,7 @@
|
||||
HeadersVisibility="Column">
|
||||
<DataGrid.ContextMenu>
|
||||
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||
<MenuItem Header="Клонировать поверку по зав. №..."
|
||||
<MenuItem Header="Клонировать поверку в выбранные строки"
|
||||
Command="{Binding CloneLineVerificationCommand}" />
|
||||
<MenuItem Header="Распечатать документ о поверке"
|
||||
Command="{Binding PrintVerificationDocumentCommand}" />
|
||||
@@ -308,10 +356,14 @@
|
||||
<Separator/>
|
||||
<MenuItem Header="Отменить проверку"
|
||||
Command="{Binding ResetLineVerificationCommand}" />
|
||||
<MenuItem Header="Удалить"
|
||||
Command="{Binding DeleteSelectedLinesCommand}" />
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow">
|
||||
<EventSetter Event="MouseDoubleClick"
|
||||
Handler="DocumentLineRow_MouseDoubleClick" />
|
||||
<EventSetter Event="PreviewMouseRightButtonDown"
|
||||
Handler="DocumentLineRow_PreviewMouseRightButtonDown" />
|
||||
</Style>
|
||||
@@ -330,6 +382,9 @@
|
||||
<DataGridTextColumn Header="Зав. №"
|
||||
Width="120"
|
||||
Binding="{Binding SerialNumber}" />
|
||||
<DataGridTextColumn Header="Дата поверки"
|
||||
Width="110"
|
||||
Binding="{Binding VerificationDateDisplay}" />
|
||||
<DataGridTextColumn Header="Поверитель"
|
||||
Width="180"
|
||||
Binding="{Binding VerifierName}" />
|
||||
|
||||
@@ -35,6 +35,19 @@ namespace XLAB
|
||||
}
|
||||
}
|
||||
|
||||
private void DocumentLineRow_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var row = sender as DataGridRow;
|
||||
if (row == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
row.IsSelected = true;
|
||||
row.Focus();
|
||||
_viewModel.TryEditVerificationFromDoubleClick(row.Item as PsvDocumentLine);
|
||||
}
|
||||
|
||||
private void DocumentGroupRow_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var row = sender as DataGridRow;
|
||||
|
||||
@@ -25,10 +25,12 @@ namespace XLAB
|
||||
private DateTime? _headerReceivedOn;
|
||||
private bool _isBusy;
|
||||
private string _lineStatusText;
|
||||
private PsvDocumentLine _lastCloneSourceLine;
|
||||
private int? _selectedCustomerId;
|
||||
private PsvDocumentSummary _selectedDocument;
|
||||
private PsvDocumentGroupSummary _selectedDocumentGroup;
|
||||
private PsvDocumentLine _selectedDocumentLine;
|
||||
private bool _showClosedDocuments;
|
||||
|
||||
public MainWindowViewModel(PsvDataService service, IDialogService dialogService)
|
||||
{
|
||||
@@ -49,14 +51,15 @@ namespace XLAB
|
||||
DocumentLinesView = CollectionViewSource.GetDefaultView(DocumentLines);
|
||||
DocumentLinesView.Filter = FilterDocumentLines;
|
||||
|
||||
AddDocumentCommand = new RelayCommand(delegate { AddDocument(); }, delegate { return !IsBusy; });
|
||||
AddDocumentCommand = new RelayCommand(delegate { AddDocument(); }, delegate { return !IsBusy && !ShowClosedDocuments; });
|
||||
CloneLineVerificationCommand = new RelayCommand(delegate { CloneSelectedLineVerificationAsync(); }, delegate { return CanCloneSelectedLineVerification(); });
|
||||
DeleteDocumentCommand = new RelayCommand(delegate { DeleteDocumentAsync(); }, delegate { return !IsBusy && SelectedDocument != null; });
|
||||
DeleteSelectedLinesCommand = new RelayCommand(delegate { DeleteSelectedLinesAsync(); }, delegate { return CanDeleteSelectedLines(); });
|
||||
DeleteSelectedGroupsCommand = new RelayCommand(delegate { DeleteSelectedGroupsAsync(); }, delegate { return CanDeleteSelectedGroups(); });
|
||||
MarkLinePassedCommand = new RelayCommand(delegate { EditLineVerificationAsync(true); }, delegate { return CanEditSelectedLineVerification(); });
|
||||
MarkLineRejectedCommand = new RelayCommand(delegate { EditLineVerificationAsync(false); }, delegate { return CanEditSelectedLineVerification(); });
|
||||
OpenInstrumentPickerCommand = new RelayCommand(delegate { OpenInstrumentPickerAsync(); }, delegate { return !IsBusy && SelectedDocument != null && SelectedDocument.CustomerId.HasValue; });
|
||||
OpenInstrumentTypePickerCommand = new RelayCommand(delegate { OpenInstrumentTypePickerAsync(); }, delegate { return !IsBusy && SelectedDocument != null && SelectedDocument.CustomerId.HasValue; });
|
||||
OpenInstrumentPickerCommand = new RelayCommand(delegate { OpenInstrumentPickerAsync(); }, delegate { return CanAddInstrumentsToSelectedDocument(); });
|
||||
OpenInstrumentTypePickerCommand = new RelayCommand(delegate { OpenInstrumentTypePickerAsync(); }, delegate { return CanAddInstrumentsToSelectedDocument(); });
|
||||
PrintDocumentCommand = new RelayCommand(delegate { PrintSelectedDocumentAsync(); }, delegate { return CanPrintSelectedDocument(); });
|
||||
PrintVerificationDocumentCommand = new RelayCommand(delegate { PrintSelectedVerificationDocumentAsync(); }, delegate { return CanPrintSelectedVerificationDocument(); });
|
||||
RefreshDocumentsCommand = new RelayCommand(delegate { RefreshDocumentsAsync(null, null); }, delegate { return !IsBusy; });
|
||||
@@ -85,6 +88,35 @@ namespace XLAB
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowClosedDocuments
|
||||
{
|
||||
get { return _showClosedDocuments; }
|
||||
set
|
||||
{
|
||||
if (!SetProperty(ref _showClosedDocuments, value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OnPropertyChanged("ShowOpenDocuments");
|
||||
OnPropertyChanged("IsDocumentHeaderEditable");
|
||||
RaiseCommandStates();
|
||||
RefreshDocumentsAsync(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowOpenDocuments
|
||||
{
|
||||
get { return !ShowClosedDocuments; }
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
ShowClosedDocuments = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<PsvDocumentLine> DocumentLines { get; private set; }
|
||||
|
||||
public ICollectionView DocumentLinesView { get; private set; }
|
||||
@@ -109,6 +141,8 @@ namespace XLAB
|
||||
|
||||
public ICommand DeleteDocumentCommand { get; private set; }
|
||||
|
||||
public ICommand DeleteSelectedLinesCommand { get; private set; }
|
||||
|
||||
public ICommand DeleteSelectedGroupsCommand { get; private set; }
|
||||
|
||||
public string GroupDetailFilterText
|
||||
@@ -129,6 +163,16 @@ namespace XLAB
|
||||
private set { SetProperty(ref _headerDepartmentName, value); }
|
||||
}
|
||||
|
||||
public bool IsDocumentHeaderEditable
|
||||
{
|
||||
get
|
||||
{
|
||||
return !IsBusy
|
||||
&& SelectedDocument != null
|
||||
&& !IsDocumentClosed(SelectedDocument);
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime? HeaderIssuedOn
|
||||
{
|
||||
get { return _headerIssuedOn; }
|
||||
@@ -150,6 +194,7 @@ namespace XLAB
|
||||
{
|
||||
RaiseCommandStates();
|
||||
OnPropertyChanged("IsCustomerEditable");
|
||||
OnPropertyChanged("IsDocumentHeaderEditable");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,9 +255,11 @@ namespace XLAB
|
||||
{
|
||||
if (SetProperty(ref _selectedDocument, value))
|
||||
{
|
||||
_lastCloneSourceLine = null;
|
||||
FillHeaderFromSelection();
|
||||
RaiseCommandStates();
|
||||
OnPropertyChanged("IsCustomerEditable");
|
||||
OnPropertyChanged("IsDocumentHeaderEditable");
|
||||
LoadSelectedDocumentAsync();
|
||||
}
|
||||
}
|
||||
@@ -237,6 +284,11 @@ namespace XLAB
|
||||
{
|
||||
if (SetProperty(ref _selectedDocumentLine, value))
|
||||
{
|
||||
if (CanUseLineAsCloneSource(value))
|
||||
{
|
||||
_lastCloneSourceLine = value;
|
||||
}
|
||||
|
||||
RaiseCommandStates();
|
||||
}
|
||||
}
|
||||
@@ -297,7 +349,7 @@ namespace XLAB
|
||||
InsertDraftIntoCollection(draft);
|
||||
DocumentsView.Refresh();
|
||||
SelectedDocument = draft;
|
||||
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
|
||||
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
|
||||
}
|
||||
|
||||
private void ApplySelectedCustomer()
|
||||
@@ -321,6 +373,11 @@ namespace XLAB
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsDocumentClosed(SelectedDocument))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SelectedDocument.IsDraft)
|
||||
{
|
||||
return true;
|
||||
@@ -331,11 +388,16 @@ namespace XLAB
|
||||
|
||||
private bool CanDeleteSelectedGroups()
|
||||
{
|
||||
return !IsBusy
|
||||
&& SelectedDocument != null
|
||||
return CanModifySelectedDocument()
|
||||
&& GetDeleteTargetGroups().Count > 0;
|
||||
}
|
||||
|
||||
private bool CanDeleteSelectedLines()
|
||||
{
|
||||
return CanModifySelectedDocument()
|
||||
&& GetDeleteTargetLines().Count > 0;
|
||||
}
|
||||
|
||||
private bool CanPrintSelectedDocument()
|
||||
{
|
||||
return !IsBusy
|
||||
@@ -346,14 +408,17 @@ namespace XLAB
|
||||
private bool CanEditSelectedLineVerification()
|
||||
{
|
||||
var targetLines = GetVerificationTargetLines();
|
||||
return !IsBusy
|
||||
return CanModifySelectedDocument()
|
||||
&& targetLines.Count > 0
|
||||
&& targetLines.All(delegate(PsvDocumentLine line) { return !HasVerificationData(line); });
|
||||
}
|
||||
|
||||
private bool CanCloneSelectedLineVerification()
|
||||
{
|
||||
return !IsBusy && CanUseLineAsCloneSource(SelectedDocumentLine);
|
||||
var sourceLine = ResolveCloneSourceLine();
|
||||
return CanModifySelectedDocument()
|
||||
&& CanUseLineAsCloneSource(sourceLine)
|
||||
&& GetCheckedCloneTargetLines(sourceLine).Count > 0;
|
||||
}
|
||||
|
||||
private bool CanPrintSelectedVerificationDocument()
|
||||
@@ -364,11 +429,28 @@ namespace XLAB
|
||||
private bool CanResetSelectedLineVerification()
|
||||
{
|
||||
var targetLines = GetVerificationTargetLines();
|
||||
return !IsBusy
|
||||
return CanModifySelectedDocument()
|
||||
&& targetLines.Count > 0
|
||||
&& targetLines.All(HasVerificationData);
|
||||
}
|
||||
|
||||
private bool CanModifySelectedDocument()
|
||||
{
|
||||
return !IsBusy
|
||||
&& SelectedDocument != null
|
||||
&& !IsDocumentClosed(SelectedDocument);
|
||||
}
|
||||
|
||||
private bool CanAddInstrumentsToSelectedDocument()
|
||||
{
|
||||
return CanModifySelectedDocument() && SelectedDocument.CustomerId.HasValue;
|
||||
}
|
||||
|
||||
private static bool IsDocumentClosed(PsvDocumentSummary document)
|
||||
{
|
||||
return document != null && document.IssuedOn.HasValue;
|
||||
}
|
||||
|
||||
private static bool HasVerificationData(PsvDocumentLine line)
|
||||
{
|
||||
return line != null
|
||||
@@ -436,6 +518,14 @@ namespace XLAB
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CanEditVerificationFromDoubleClick(PsvDocumentLine line)
|
||||
{
|
||||
return CanModifySelectedDocument()
|
||||
&& line != null
|
||||
&& line.IsPassed.HasValue
|
||||
&& HasVerificationData(line);
|
||||
}
|
||||
|
||||
private List<PsvDocumentLine> GetCheckedDocumentLines()
|
||||
{
|
||||
return DocumentLinesView.Cast<object>()
|
||||
@@ -477,6 +567,57 @@ namespace XLAB
|
||||
: new List<PsvDocumentLine> { SelectedDocumentLine };
|
||||
}
|
||||
|
||||
private List<PsvDocumentLine> GetDeleteTargetLines()
|
||||
{
|
||||
var checkedLines = GetCheckedDocumentLines();
|
||||
if (checkedLines.Count > 0)
|
||||
{
|
||||
return checkedLines;
|
||||
}
|
||||
|
||||
return SelectedDocumentLine == null
|
||||
? new List<PsvDocumentLine>()
|
||||
: new List<PsvDocumentLine> { SelectedDocumentLine };
|
||||
}
|
||||
|
||||
private List<PsvDocumentLine> GetCheckedCloneTargetLines(PsvDocumentLine sourceLine)
|
||||
{
|
||||
if (sourceLine == null)
|
||||
{
|
||||
return new List<PsvDocumentLine>();
|
||||
}
|
||||
|
||||
return GetCheckedDocumentLines()
|
||||
.Where(delegate(PsvDocumentLine line)
|
||||
{
|
||||
return line != null
|
||||
&& !ReferenceEquals(line, sourceLine)
|
||||
&& BelongsToSameGroup(line, sourceLine);
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private PsvDocumentLine ResolveCloneSourceLine()
|
||||
{
|
||||
if (CanUseLineAsCloneSource(SelectedDocumentLine))
|
||||
{
|
||||
return SelectedDocumentLine;
|
||||
}
|
||||
|
||||
if (_lastCloneSourceLine != null
|
||||
&& DocumentLines.Contains(_lastCloneSourceLine)
|
||||
&& CanUseLineAsCloneSource(_lastCloneSourceLine))
|
||||
{
|
||||
return _lastCloneSourceLine;
|
||||
}
|
||||
|
||||
var checkedSourceLines = GetCheckedDocumentLines()
|
||||
.Where(CanUseLineAsCloneSource)
|
||||
.ToList();
|
||||
|
||||
return checkedSourceLines.Count == 1 ? checkedSourceLines[0] : null;
|
||||
}
|
||||
|
||||
private void ClearCollections<T>(ObservableCollection<T> collection)
|
||||
{
|
||||
collection.Clear();
|
||||
@@ -925,54 +1066,27 @@ namespace XLAB
|
||||
|
||||
private void CloneSelectedLineVerificationAsync()
|
||||
{
|
||||
var sourceLine = SelectedDocumentLine;
|
||||
var sourceLine = ResolveCloneSourceLine();
|
||||
if (!CanUseLineAsCloneSource(sourceLine))
|
||||
{
|
||||
_dialogService.ShowWarning("В выбранной строке нет полной поверки, пригодной для клонирования.");
|
||||
_dialogService.ShowWarning("Выберите строку-источник с заполненной поверкой. Источник можно выделить строкой или отметить единственную подходящую строку чекбоксом.");
|
||||
return;
|
||||
}
|
||||
|
||||
var serialNumbers = _dialogService.ShowCloneVerificationDialog(CreateCloneVerificationSeed(sourceLine));
|
||||
if (serialNumbers == null || serialNumbers.Count == 0)
|
||||
var checkedLines = GetCheckedDocumentLines();
|
||||
if (checkedLines.Count == 0)
|
||||
{
|
||||
_dialogService.ShowWarning("Отметьте чекбоксами строки, в которые нужно склонировать поверочные данные.");
|
||||
return;
|
||||
}
|
||||
|
||||
var sourceSerialNumber = NormalizeSerialNumber(sourceLine.SerialNumber);
|
||||
var requestedSerialNumbers = new HashSet<string>(serialNumbers, StringComparer.OrdinalIgnoreCase);
|
||||
var includedSourceSerialNumber = !string.IsNullOrWhiteSpace(sourceSerialNumber)
|
||||
&& requestedSerialNumbers.Remove(sourceSerialNumber);
|
||||
|
||||
var matchedLines = DocumentLines
|
||||
.Where(delegate(PsvDocumentLine line)
|
||||
{
|
||||
return line != null
|
||||
&& !ReferenceEquals(line, sourceLine)
|
||||
&& BelongsToSameGroup(line, sourceLine)
|
||||
&& requestedSerialNumbers.Contains(NormalizeSerialNumber(line.SerialNumber));
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var matchedSerialNumbers = new HashSet<string>(
|
||||
matchedLines
|
||||
.Select(delegate(PsvDocumentLine line) { return NormalizeSerialNumber(line.SerialNumber); })
|
||||
.Where(delegate(string serialNumber) { return !string.IsNullOrWhiteSpace(serialNumber); }),
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
var missingSerialNumbers = serialNumbers
|
||||
.Where(delegate(string serialNumber)
|
||||
{
|
||||
var normalized = NormalizeSerialNumber(serialNumber);
|
||||
return !string.IsNullOrWhiteSpace(normalized)
|
||||
&& !string.Equals(normalized, sourceSerialNumber, StringComparison.OrdinalIgnoreCase)
|
||||
&& !matchedSerialNumbers.Contains(normalized);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var includedSourceSerialNumber = checkedLines.Any(delegate(PsvDocumentLine line) { return ReferenceEquals(line, sourceLine); });
|
||||
var matchedLines = GetCheckedCloneTargetLines(sourceLine);
|
||||
var targetLines = matchedLines.Where(delegate(PsvDocumentLine line) { return !HasVerificationData(line); }).ToList();
|
||||
var skippedWithExistingVerificationCount = matchedLines.Count - targetLines.Count;
|
||||
if (targetLines.Count == 0)
|
||||
{
|
||||
ShowCloneVerificationResult(0, skippedWithExistingVerificationCount, missingSerialNumbers, includedSourceSerialNumber, true);
|
||||
ShowCloneVerificationResult(0, skippedWithExistingVerificationCount, includedSourceSerialNumber, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -992,7 +1106,7 @@ namespace XLAB
|
||||
}
|
||||
|
||||
RefreshAfterLineVerificationChanged(sourceLine);
|
||||
ShowCloneVerificationResult(targetLines.Count, skippedWithExistingVerificationCount, missingSerialNumbers, includedSourceSerialNumber, false);
|
||||
ShowCloneVerificationResult(targetLines.Count, skippedWithExistingVerificationCount, includedSourceSerialNumber, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1006,14 +1120,13 @@ namespace XLAB
|
||||
}
|
||||
|
||||
await ReloadSelectedDocumentLinesAsync();
|
||||
ShowCloneVerificationResult(targetLines.Count, skippedWithExistingVerificationCount, missingSerialNumbers, includedSourceSerialNumber, false);
|
||||
ShowCloneVerificationResult(targetLines.Count, skippedWithExistingVerificationCount, includedSourceSerialNumber, false);
|
||||
});
|
||||
}
|
||||
|
||||
private void ShowCloneVerificationResult(
|
||||
int clonedCount,
|
||||
int skippedWithExistingVerificationCount,
|
||||
IReadOnlyList<string> missingSerialNumbers,
|
||||
bool includedSourceSerialNumber,
|
||||
bool showWarning)
|
||||
{
|
||||
@@ -1033,14 +1146,9 @@ namespace XLAB
|
||||
messages.Add("Номер строки-источника пропущен.");
|
||||
}
|
||||
|
||||
if (missingSerialNumbers != null && missingSerialNumbers.Count > 0)
|
||||
{
|
||||
messages.Add(string.Format("Не найдены заводские номера: {0}.", BuildSerialNumberPreview(missingSerialNumbers)));
|
||||
}
|
||||
|
||||
if (messages.Count == 0)
|
||||
{
|
||||
messages.Add("Подходящих строк для клонирования не найдено.");
|
||||
messages.Add("Подходящих отмеченных строк для клонирования не найдено.");
|
||||
}
|
||||
|
||||
var message = string.Join(" ", messages.ToArray());
|
||||
@@ -1064,6 +1172,22 @@ namespace XLAB
|
||||
EditLineVerificationCoreAsync(targetLines, isPassed);
|
||||
}
|
||||
|
||||
public void TryEditVerificationFromDoubleClick(PsvDocumentLine line)
|
||||
{
|
||||
if (line == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SelectedDocumentLine = line;
|
||||
if (!CanEditVerificationFromDoubleClick(line))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditLineVerificationCoreAsync(new[] { line }, line.IsPassed.Value);
|
||||
}
|
||||
|
||||
private async void EditLineVerificationCoreAsync(IReadOnlyList<PsvDocumentLine> targetLines, bool isPassed)
|
||||
{
|
||||
IReadOnlyList<DocumentFormReference> documentForms;
|
||||
@@ -1214,7 +1338,7 @@ namespace XLAB
|
||||
Documents.Remove(draft);
|
||||
DocumentsView.Refresh();
|
||||
SelectedDocument = Documents.Count > 0 ? Documents[0] : null;
|
||||
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
|
||||
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
|
||||
}
|
||||
|
||||
private void PrintSelectedDocumentAsync()
|
||||
@@ -1331,7 +1455,115 @@ namespace XLAB
|
||||
UpdateDocumentSummaryFromLines(selectedDocument, pendingLines);
|
||||
ApplyDocumentLines(pendingLines, SelectedDocumentGroup);
|
||||
DocumentsView.Refresh();
|
||||
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
|
||||
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
|
||||
}
|
||||
else if (remainingPersistedCount == 0 && remainingPendingCount > 0)
|
||||
{
|
||||
if (!_draftDocuments.Any(delegate(PsvDocumentSummary draft) { return draft.DocumentKey == selectedDocumentKey; }))
|
||||
{
|
||||
_draftDocuments.Add(selectedDocument);
|
||||
}
|
||||
|
||||
selectedDocument.IsDraft = true;
|
||||
UpdateDocumentSummaryFromLines(selectedDocument, pendingLines);
|
||||
await RefreshDocumentsCoreAsync(selectedDocumentKey, selectedDocumentNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
await RefreshDocumentsCoreAsync(selectedDocumentKey, selectedDocumentNumber);
|
||||
}
|
||||
|
||||
var messages = new List<string>();
|
||||
if (deletedPendingCount > 0)
|
||||
{
|
||||
messages.Add(string.Format("Удалено черновых строк: {0}.", deletedPendingCount));
|
||||
}
|
||||
|
||||
if (deletedResult.DeletedEkzMkFctvlCount > 0)
|
||||
{
|
||||
messages.Add(string.Format("Удалено строк EKZMKFCTVL: {0}.", deletedResult.DeletedEkzMkFctvlCount));
|
||||
}
|
||||
|
||||
if (deletedResult.DeletedEkzMkCount > 0)
|
||||
{
|
||||
messages.Add(string.Format("Удалено строк EKZMK: {0}.", deletedResult.DeletedEkzMkCount));
|
||||
}
|
||||
|
||||
if (deletedResult.DeletedDmsCount > 0)
|
||||
{
|
||||
messages.Add(string.Format("Удалено связанных DMS: {0}.", deletedResult.DeletedDmsCount));
|
||||
}
|
||||
|
||||
if (messages.Count > 0)
|
||||
{
|
||||
_dialogService.ShowInfo(string.Join(" ", messages.ToArray()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void DeleteSelectedLinesAsync()
|
||||
{
|
||||
if (SelectedDocument == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetLines = GetDeleteTargetLines();
|
||||
if (targetLines.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_dialogService.Confirm(string.Format(
|
||||
"Удалить из ПСВ \"{0}\" строк приборов: {1}?",
|
||||
SelectedDocument.DocumentNumber,
|
||||
targetLines.Count)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedDocument = SelectedDocument;
|
||||
var selectedDocumentKey = selectedDocument.DocumentKey;
|
||||
var selectedDocumentNumber = selectedDocument.DocumentNumber;
|
||||
|
||||
RunBusyOperation(async delegate
|
||||
{
|
||||
var pendingLines = GetPendingLines(selectedDocument);
|
||||
var pendingLinesToRemove = pendingLines
|
||||
.Where(delegate(PsvDocumentLine line) { return targetLines.Any(delegate(PsvDocumentLine targetLine) { return ReferenceEquals(line, targetLine); }); })
|
||||
.ToList();
|
||||
|
||||
var persistedCardIds = targetLines
|
||||
.Where(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; })
|
||||
.Select(delegate(PsvDocumentLine line) { return line.CardId; })
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
foreach (var pendingLine in pendingLinesToRemove)
|
||||
{
|
||||
pendingLines.Remove(pendingLine);
|
||||
}
|
||||
|
||||
var deletedPendingCount = pendingLinesToRemove.Count;
|
||||
var deletedResult = new DocumentGroupDeleteResult();
|
||||
|
||||
if (persistedCardIds.Count > 0)
|
||||
{
|
||||
deletedResult = await Task.Run(delegate
|
||||
{
|
||||
return _service.DeleteDocumentGroups(selectedDocumentNumber, persistedCardIds);
|
||||
});
|
||||
}
|
||||
|
||||
var remainingPendingCount = pendingLines.Count;
|
||||
var remainingPersistedCount = DocumentLines.Count(delegate(PsvDocumentLine line) { return !line.IsPendingInsert; }) - persistedCardIds.Count;
|
||||
|
||||
if (selectedDocument.IsDraft)
|
||||
{
|
||||
UpdateDocumentSummaryFromLines(selectedDocument, pendingLines);
|
||||
ApplyDocumentLines(pendingLines, SelectedDocumentGroup);
|
||||
DocumentsView.Refresh();
|
||||
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
|
||||
}
|
||||
else if (remainingPersistedCount == 0 && remainingPendingCount > 0)
|
||||
{
|
||||
@@ -1457,11 +1689,6 @@ namespace XLAB
|
||||
return false;
|
||||
}
|
||||
|
||||
if (document.IssuedOn.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(DocumentFilterText)
|
||||
&& !Contains(document.DocumentNumber, DocumentFilterText)
|
||||
&& !Contains(document.CustomerName, DocumentFilterText))
|
||||
@@ -1472,6 +1699,16 @@ namespace XLAB
|
||||
return true;
|
||||
}
|
||||
|
||||
private string BuildDocumentStatusText(int count)
|
||||
{
|
||||
if (ShowClosedDocuments)
|
||||
{
|
||||
return string.Format("Закрытых ПСВ за {0:yyyy}: {1}.", DateTime.Today, count);
|
||||
}
|
||||
|
||||
return string.Format("Открытых ПСВ: {0}.", count);
|
||||
}
|
||||
|
||||
private bool FilterDocumentLines(object item)
|
||||
{
|
||||
var line = item as PsvDocumentLine;
|
||||
@@ -1972,6 +2209,7 @@ namespace XLAB
|
||||
((RelayCommand)AddDocumentCommand).RaiseCanExecuteChanged();
|
||||
((RelayCommand)CloneLineVerificationCommand).RaiseCanExecuteChanged();
|
||||
((RelayCommand)DeleteDocumentCommand).RaiseCanExecuteChanged();
|
||||
((RelayCommand)DeleteSelectedLinesCommand).RaiseCanExecuteChanged();
|
||||
((RelayCommand)DeleteSelectedGroupsCommand).RaiseCanExecuteChanged();
|
||||
((RelayCommand)MarkLinePassedCommand).RaiseCanExecuteChanged();
|
||||
((RelayCommand)MarkLineRejectedCommand).RaiseCanExecuteChanged();
|
||||
@@ -2041,13 +2279,15 @@ namespace XLAB
|
||||
{
|
||||
DocumentStatusText = "Загрузка списка ПСВ...";
|
||||
|
||||
var databaseDocuments = await Task.Run(delegate { return _service.LoadDocuments(); });
|
||||
var databaseDocuments = await Task.Run(delegate { return _service.LoadDocuments(ShowClosedDocuments); });
|
||||
var currentDocumentKey = documentKeyToSelect ?? (SelectedDocument != null ? SelectedDocument.DocumentKey : null);
|
||||
var currentDocumentNumber = documentNumberToSelect ?? (SelectedDocument != null ? SelectedDocument.DocumentNumber : null);
|
||||
|
||||
ClearCollections(Documents);
|
||||
|
||||
foreach (var draft in _draftDocuments.OrderByDescending(delegate(PsvDocumentSummary item) { return item.AcceptedOn ?? DateTime.MinValue; }))
|
||||
foreach (var draft in _draftDocuments
|
||||
.Where(delegate(PsvDocumentSummary item) { return !ShowClosedDocuments; })
|
||||
.OrderByDescending(delegate(PsvDocumentSummary item) { return item.AcceptedOn ?? DateTime.MinValue; }))
|
||||
{
|
||||
Documents.Add(draft);
|
||||
}
|
||||
@@ -2084,7 +2324,7 @@ namespace XLAB
|
||||
SelectedDocument = Documents[0];
|
||||
}
|
||||
|
||||
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
|
||||
DocumentStatusText = BuildDocumentStatusText(Documents.Count);
|
||||
}
|
||||
|
||||
private void SaveDocumentAsync()
|
||||
|
||||
@@ -492,9 +492,9 @@ SELECT @@ROWCOUNT;";
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<PsvDocumentSummary> LoadDocuments()
|
||||
public IReadOnlyList<PsvDocumentSummary> LoadDocuments(bool loadClosedDocumentsForCurrentYear)
|
||||
{
|
||||
const string sql = @"
|
||||
var sql = @"
|
||||
SELECT
|
||||
m.NNZVPV AS DocumentNumber,
|
||||
MAX(m.DTPRM) AS AcceptedOn,
|
||||
@@ -512,14 +512,27 @@ LEFT JOIN dbo.FRPD dep ON dep.IDFRPD = m.IDFRPD
|
||||
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||||
WHERE NULLIF(LTRIM(RTRIM(m.NNZVPV)), N'') IS NOT NULL
|
||||
GROUP BY m.NNZVPV
|
||||
HAVING MAX(m.DTVDM) IS NULL
|
||||
ORDER BY MAX(m.DTPRM) DESC, m.NNZVPV DESC;";
|
||||
HAVING " + (loadClosedDocumentsForCurrentYear
|
||||
? "MAX(m.DTVDM) >= @IssuedFrom AND MAX(m.DTVDM) < @IssuedTo"
|
||||
: "MAX(m.DTVDM) IS NULL") + @"
|
||||
ORDER BY " + (loadClosedDocumentsForCurrentYear
|
||||
? "MAX(m.DTVDM) DESC"
|
||||
: "MAX(m.DTPRM) DESC") + @", m.NNZVPV DESC;";
|
||||
|
||||
var documents = new List<PsvDocumentSummary>();
|
||||
var today = DateTime.Today;
|
||||
var currentYearStart = new DateTime(today.Year, 1, 1);
|
||||
var nextYearStart = currentYearStart.AddYears(1);
|
||||
|
||||
using (var connection = CreateConnection())
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
if (loadClosedDocumentsForCurrentYear)
|
||||
{
|
||||
command.Parameters.Add("@IssuedFrom", SqlDbType.DateTime).Value = currentYearStart;
|
||||
command.Parameters.Add("@IssuedTo", SqlDbType.DateTime).Value = nextYearStart;
|
||||
}
|
||||
|
||||
connection.Open();
|
||||
command.CommandTimeout = 60;
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace XLAB
|
||||
if (SetProperty(ref _acceptedOn, value))
|
||||
{
|
||||
OnPropertyChanged("AcceptedMonthGroup");
|
||||
RaiseOpenDocumentTimelinePropertiesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,7 +110,13 @@ namespace XLAB
|
||||
public DateTime? IssuedOn
|
||||
{
|
||||
get { return _issuedOn; }
|
||||
set { SetProperty(ref _issuedOn, value); }
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _issuedOn, value))
|
||||
{
|
||||
RaiseOpenDocumentTimelinePropertiesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int ItemCount
|
||||
@@ -123,6 +130,52 @@ namespace XLAB
|
||||
get { return _passedCount; }
|
||||
set { SetProperty(ref _passedCount, value); }
|
||||
}
|
||||
|
||||
public DateTime? DueOn
|
||||
{
|
||||
get { return AcceptedOn.HasValue ? AcceptedOn.Value.Date.AddDays(30) : (DateTime?)null; }
|
||||
}
|
||||
|
||||
public bool IsOpenDocumentOverdue
|
||||
{
|
||||
get
|
||||
{
|
||||
return !IssuedOn.HasValue
|
||||
&& DueOn.HasValue
|
||||
&& DateTime.Today.Date >= DueOn.Value.Date;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOpenDocumentAtTwentyDays
|
||||
{
|
||||
get
|
||||
{
|
||||
return !IssuedOn.HasValue
|
||||
&& AcceptedOn.HasValue
|
||||
&& !IsOpenDocumentOverdue
|
||||
&& (DateTime.Today.Date - AcceptedOn.Value.Date).TotalDays >= 20;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOpenDocumentAtTenDays
|
||||
{
|
||||
get
|
||||
{
|
||||
return !IssuedOn.HasValue
|
||||
&& AcceptedOn.HasValue
|
||||
&& !IsOpenDocumentOverdue
|
||||
&& !IsOpenDocumentAtTwentyDays
|
||||
&& (DateTime.Today.Date - AcceptedOn.Value.Date).TotalDays >= 10;
|
||||
}
|
||||
}
|
||||
|
||||
private void RaiseOpenDocumentTimelinePropertiesChanged()
|
||||
{
|
||||
OnPropertyChanged("DueOn");
|
||||
OnPropertyChanged("IsOpenDocumentOverdue");
|
||||
OnPropertyChanged("IsOpenDocumentAtTwentyDays");
|
||||
OnPropertyChanged("IsOpenDocumentAtTenDays");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PsvDocumentLine : ObservableObject
|
||||
@@ -220,6 +273,15 @@ namespace XLAB
|
||||
}
|
||||
}
|
||||
|
||||
public string VerificationDateDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
var verificationDate = VerificationPerformedOn ?? VerificationDocumentDate;
|
||||
return verificationDate.HasValue ? verificationDate.Value.ToString("d") : string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public string VerificationDocumentDisplay
|
||||
{
|
||||
get
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user