This commit is contained in:
Курнат Андрей
2026-03-11 23:46:45 +03:00
parent 44a0ce300b
commit f146b9c8be
20 changed files with 3106 additions and 18 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,7 +12,6 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Deterministic>true</Deterministic>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -32,6 +31,14 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="EntityFramework">
<HintPath>..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.SqlServer">
<HintPath>..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Runtime.Serialization" />
@@ -148,4 +155,4 @@
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="EntityFramework" version="6.4.4" targetFramework="net48" />
<package id="EntityFramework.ru" version="6.2.0" targetFramework="net48" /> <package id="EntityFramework.ru" version="6.2.0" targetFramework="net48" />
</packages> </packages>

26
XLAB.sln Normal file
View File

@@ -0,0 +1,26 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XLAB.DATA", "XLAB.DATA\XLAB.DATA.csproj", "{AE0E35D7-DFA4-4150-9889-255043B232BB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XLAB", "XLAB\XLAB.csproj", "{B8DAAB84-777A-4274-8452-E602DB1AF587}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AE0E35D7-DFA4-4150-9889-255043B232BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE0E35D7-DFA4-4150-9889-255043B232BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE0E35D7-DFA4-4150-9889-255043B232BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE0E35D7-DFA4-4150-9889-255043B232BB}.Release|Any CPU.Build.0 = Release|Any CPU
{B8DAAB84-777A-4274-8452-E602DB1AF587}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8DAAB84-777A-4274-8452-E602DB1AF587}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8DAAB84-777A-4274-8452-E602DB1AF587}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8DAAB84-777A-4274-8452-E602DB1AF587}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<configuration> <configuration>
<startup> <connectionStrings>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /> <add name="AsumsSql"
</startup> connectionString="data source=SEVENHILL\SQLEXPRESS;initial catalog=ASUMS;integrated security=True;trustservercertificate=True;MultipleActiveResultSets=True;"
</configuration> providerName="System.Data.SqlClient" />
<add name="ASUMSEntities"
connectionString="metadata=res://*/XLabModel.csdl|res://*/XLabModel.ssdl|res://*/XLabModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=SEVENHILL\SQLEXPRESS;initial catalog=ASUMS;integrated security=True;trustservercertificate=True;MultipleActiveResultSets=True;App=EntityFramework&quot;"
providerName="System.Data.EntityClient" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>

View File

@@ -1,10 +1,7 @@
using System; using System.Globalization;
using System.Collections.Generic; using System.Threading;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Markup;
namespace XLAB namespace XLAB
{ {
@@ -13,5 +10,23 @@ namespace XLAB
/// </summary> /// </summary>
public partial class App : Application public partial class App : Application
{ {
public App()
{
ApplyRussianCulture();
}
private static void ApplyRussianCulture()
{
var culture = new CultureInfo("ru-RU");
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(culture.IetfLanguageTag)));
}
} }
} }

View File

@@ -0,0 +1,70 @@
<Window x:Class="XLAB.CreateDocumentWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Новый ПСВ"
Height="220"
Width="430"
ResizeMode="NoResize"
WindowStartupLocation="CenterOwner">
<Grid Margin="16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0"
Grid.Column="0"
Margin="0,0,12,8"
VerticalAlignment="Center"
Text="Номер ПСВ" />
<TextBox Grid.Row="0"
Grid.Column="1"
MinWidth="180"
Margin="0,0,0,8"
Text="{Binding DocumentNumber, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Margin="0,0,12,8"
VerticalAlignment="Center"
Text="Дата приемки" />
<DatePicker Grid.Row="1"
Grid.Column="1"
SelectedDate="{Binding AcceptedOn, Mode=TwoWay}"
SelectedDateFormat="Short"
Margin="0,0,0,8" />
<TextBlock Grid.Row="2"
Grid.ColumnSpan="2"
Margin="0,8,0,4"
TextWrapping="Wrap"
Foreground="DimGray"
Text="ПСВ без строк EKZMK не хранится в базе. Команда «Добавить» создаёт только черновик текущего сеанса." />
<TextBlock Grid.Row="3"
Grid.ColumnSpan="2"
Foreground="Firebrick"
Text="{Binding ValidationMessage}" />
<StackPanel Grid.Row="4"
Grid.ColumnSpan="2"
Orientation="Horizontal"
HorizontalAlignment="Right">
<Button Width="90"
Margin="0,12,8,0"
IsDefault="True"
Command="{Binding ConfirmCommand}"
Content="Создать" />
<Button Width="90"
Margin="0,12,0,0"
Command="{Binding CancelCommand}"
Content="Отмена" />
</StackPanel>
</Grid>
</Window>

View File

@@ -0,0 +1,20 @@
using System.Windows;
namespace XLAB
{
public partial class CreateDocumentWindow : Window
{
internal CreateDocumentWindow(CreateDocumentWindowViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
viewModel.CloseRequested += ViewModelOnCloseRequested;
}
private void ViewModelOnCloseRequested(object sender, bool? dialogResult)
{
DialogResult = dialogResult;
Close();
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Windows.Input;
namespace XLAB
{
internal sealed class CreateDocumentWindowViewModel : ObservableObject
{
private DateTime? _acceptedOn;
private string _documentNumber;
private string _validationMessage;
public CreateDocumentWindowViewModel(DocumentEditorResult seed)
{
_acceptedOn = seed != null ? seed.AcceptedOn : DateTime.Today;
_documentNumber = seed != null ? seed.DocumentNumber : string.Empty;
ConfirmCommand = new RelayCommand(Confirm);
CancelCommand = new RelayCommand(Cancel);
}
public event EventHandler<bool?> CloseRequested;
public DateTime? AcceptedOn
{
get { return _acceptedOn; }
set { SetProperty(ref _acceptedOn, value); }
}
public ICommand CancelCommand { get; private set; }
public ICommand ConfirmCommand { get; private set; }
public string DocumentNumber
{
get { return _documentNumber; }
set { SetProperty(ref _documentNumber, value); }
}
public string ValidationMessage
{
get { return _validationMessage; }
private set { SetProperty(ref _validationMessage, value); }
}
public DocumentEditorResult ToResult()
{
return new DocumentEditorResult
{
DocumentNumber = DocumentNumber == null ? string.Empty : DocumentNumber.Trim(),
AcceptedOn = AcceptedOn.HasValue ? AcceptedOn.Value : DateTime.Today,
IssuedOn = null
};
}
private void Cancel(object parameter)
{
RaiseCloseRequested(false);
}
private void Confirm(object parameter)
{
if (string.IsNullOrWhiteSpace(DocumentNumber))
{
ValidationMessage = "Введите номер ПСВ.";
return;
}
if (!AcceptedOn.HasValue)
{
ValidationMessage = "Укажите дату приемки.";
return;
}
ValidationMessage = string.Empty;
RaiseCloseRequested(true);
}
private void RaiseCloseRequested(bool? dialogResult)
{
var handler = CloseRequested;
if (handler != null)
{
handler(this, dialogResult);
}
}
}
}

57
XLAB/DialogService.cs Normal file
View File

@@ -0,0 +1,57 @@
using System.Windows;
namespace XLAB
{
internal interface IDialogService
{
DocumentEditorResult ShowCreateDocumentDialog(DocumentEditorResult seed);
bool Confirm(string message);
void ShowError(string message);
void ShowInfo(string message);
void ShowWarning(string message);
}
internal sealed class DialogService : IDialogService
{
private readonly Window _owner;
public DialogService(Window owner)
{
_owner = owner;
}
public DocumentEditorResult ShowCreateDocumentDialog(DocumentEditorResult seed)
{
var viewModel = new CreateDocumentWindowViewModel(seed);
var window = new CreateDocumentWindow(viewModel);
window.Owner = _owner;
var result = window.ShowDialog();
return result.HasValue && result.Value ? viewModel.ToResult() : null;
}
public bool Confirm(string message)
{
return MessageBox.Show(_owner, message, "ПСВ", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes;
}
public void ShowError(string message)
{
MessageBox.Show(_owner, message, "ПСВ", MessageBoxButton.OK, MessageBoxImage.Error);
}
public void ShowInfo(string message)
{
MessageBox.Show(_owner, message, "ПСВ", MessageBoxButton.OK, MessageBoxImage.Information);
}
public void ShowWarning(string message)
{
MessageBox.Show(_owner, message, "ПСВ", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
}

265
XLAB/MainWindow.xaml Normal file
View File

@@ -0,0 +1,265 @@
<Window x:Class="XLAB.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Приемо-сдаточные ведомости"
Height="860"
Width="1500"
MinHeight="700"
MinWidth="1180"
WindowState="Maximized"
Loaded="Window_Loaded">
<Grid Margin="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="430" />
<ColumnDefinition Width="12" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<GroupBox Grid.Column="0" Header="Документы">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Margin="0,0,0,4"
VerticalAlignment="Center"
Text="Поиск по номеру ПСВ или заказчику" />
<TextBox Grid.Row="1"
Margin="0,0,0,8"
Text="{Binding DocumentFilterText, UpdateSourceTrigger=PropertyChanged}" />
<ListBox Grid.Row="2"
ItemsSource="{Binding DocumentsView}"
SelectedItem="{Binding SelectedDocument, Mode=TwoWay}"
BorderThickness="1"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListBox.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Добавить"
Command="{Binding AddDocumentCommand}" />
<MenuItem Header="Удалить"
Command="{Binding DeleteDocumentCommand}" />
</ContextMenu>
</ListBox.ContextMenu>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="PreviewMouseRightButtonDown"
Handler="DocumentListItem_PreviewMouseRightButtonDown" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0,0,0,4" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<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"
Foreground="DimGray"
Text="{Binding AcceptedOn, StringFormat=d}" />
</DockPanel>
<TextBlock Margin="0,4,0,0"
Foreground="DimGray"
Text="{Binding CustomerName}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Grid.Row="3"
Margin="0,8,0,0"
Foreground="DimGray"
Text="{Binding DocumentStatusText}" />
</Grid>
</GroupBox>
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="340" />
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Header="Реквизиты документа">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110" />
<ColumnDefinition Width="220" />
<ColumnDefinition Width="110" />
<ColumnDefinition Width="160" />
<ColumnDefinition Width="110" />
<ColumnDefinition Width="160" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0"
Grid.Column="0"
Margin="0,0,8,8"
VerticalAlignment="Center"
Text="Номер ПСВ" />
<TextBox Grid.Row="0"
Grid.Column="1"
Margin="0,0,12,8"
Text="{Binding DocumentNumberEditor, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="0"
Grid.Column="2"
Margin="0,0,8,8"
VerticalAlignment="Center"
Text="Дата приемки" />
<DatePicker Grid.Row="0"
Grid.Column="3"
Margin="0,0,12,8"
SelectedDate="{Binding HeaderReceivedOn, Mode=TwoWay}"
SelectedDateFormat="Short" />
<TextBlock Grid.Row="0"
Grid.Column="4"
Margin="0,0,8,8"
VerticalAlignment="Center"
Text="Дата выдачи" />
<DatePicker Grid.Row="0"
Grid.Column="5"
Margin="0,0,12,8"
SelectedDate="{Binding HeaderIssuedOn, Mode=TwoWay}"
SelectedDateFormat="Short" />
<StackPanel Grid.Row="0"
Grid.Column="6"
Orientation="Horizontal"
HorizontalAlignment="Right">
<Button Width="120"
Margin="0,0,0,8"
Command="{Binding SaveDocumentHeaderCommand}"
Content="Сохранить" />
</StackPanel>
<TextBlock Grid.Row="1"
Grid.Column="0"
Margin="0,0,8,6"
VerticalAlignment="Center"
Text="Заказчик" />
<TextBox Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="3"
Margin="0,0,12,6"
IsReadOnly="True"
Text="{Binding HeaderCustomerName, Mode=OneWay}" />
<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"
Text="{Binding LineStatusText}" />
</Grid>
</GroupBox>
<GroupBox Grid.Row="1" Header="Группы приборов выбранного документа">
<Grid Margin="8">
<DataGrid ItemsSource="{Binding DocumentGroupSummaries}"
SelectedItem="{Binding SelectedDocumentGroup, Mode=TwoWay}"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="True"
HeadersVisibility="Column">
<DataGrid.Columns>
<DataGridTextColumn Header="Тип"
Width="180"
Binding="{Binding InstrumentType}" />
<DataGridTextColumn Header="Диапазон"
Width="170"
Binding="{Binding RangeText}" />
<DataGridTextColumn Header="Госреестр"
Width="120"
Binding="{Binding RegistryNumber}" />
<DataGridTextColumn Header="В поверке"
Width="90"
Binding="{Binding InVerificationCount}" />
<DataGridTextColumn Header="Поверено"
Width="90"
Binding="{Binding VerifiedCount}" />
<DataGridTextColumn Header="Годных"
Width="90"
Binding="{Binding GoodCount}" />
<DataGridTextColumn Header="Забраковано"
Width="105"
Binding="{Binding RejectedCount}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</GroupBox>
<GroupBox Grid.Row="2" Header="Состав выбранной группы">
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<WrapPanel Margin="0,0,0,8">
<TextBlock Width="140"
Margin="0,0,6,0"
VerticalAlignment="Center"
Text="Поиск по зав. №" />
<TextBox Width="320"
Text="{Binding GroupDetailFilterText, UpdateSourceTrigger=PropertyChanged}" />
</WrapPanel>
<DataGrid Grid.Row="1"
ItemsSource="{Binding DocumentLinesView}"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="True"
HeadersVisibility="Column">
<DataGrid.Columns>
<DataGridTextColumn Header="Зав. №"
Width="120"
Binding="{Binding SerialNumber}" />
<DataGridTextColumn Header="Поверитель"
Width="180"
Binding="{Binding VerifierName}" />
<DataGridTextColumn Header="Номер наклейки"
Width="150"
Binding="{Binding StickerNumber}" />
<DataGridTextColumn Header="Результат поверки"
Width="140"
Binding="{Binding ResultText}" />
<DataGridTextColumn Header="Номер документа по поверке"
Width="240"
Binding="{Binding VerificationDocumentDisplay}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</GroupBox>
</Grid>
</Grid>
</Window>

33
XLAB/MainWindow.xaml.cs Normal file
View File

@@ -0,0 +1,33 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace XLAB
{
public partial class MainWindow : Window
{
private readonly MainWindowViewModel _viewModel;
public MainWindow()
{
InitializeComponent();
_viewModel = new MainWindowViewModel(new PsvDataService(), new DialogService(this));
DataContext = _viewModel;
}
private void DocumentListItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
var item = sender as ListBoxItem;
if (item != null)
{
item.IsSelected = true;
item.Focus();
}
}
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
await _viewModel.InitializeAsync();
}
}
}

645
XLAB/MainWindowViewModel.cs Normal file
View File

@@ -0,0 +1,645 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Input;
namespace XLAB
{
internal sealed class MainWindowViewModel : ObservableObject
{
private readonly List<PsvDocumentSummary> _draftDocuments;
private readonly IDialogService _dialogService;
private readonly PsvDataService _service;
private string _documentFilterText;
private string _documentNumberEditor;
private string _documentStatusText;
private string _groupDetailFilterText;
private string _headerCustomerName;
private string _headerDepartmentName;
private DateTime? _headerIssuedOn;
private DateTime? _headerReceivedOn;
private bool _isBusy;
private string _lineStatusText;
private PsvDocumentSummary _selectedDocument;
private PsvDocumentGroupSummary _selectedDocumentGroup;
public MainWindowViewModel(PsvDataService service, IDialogService dialogService)
{
_service = service;
_dialogService = dialogService;
_draftDocuments = new List<PsvDocumentSummary>();
Documents = new ObservableCollection<PsvDocumentSummary>();
DocumentLines = new ObservableCollection<PsvDocumentLine>();
DocumentGroupSummaries = new ObservableCollection<PsvDocumentGroupSummary>();
DocumentsView = CollectionViewSource.GetDefaultView(Documents);
DocumentsView.Filter = FilterDocuments;
DocumentLinesView = CollectionViewSource.GetDefaultView(DocumentLines);
DocumentLinesView.Filter = FilterDocumentLines;
AddDocumentCommand = new RelayCommand(delegate { AddDocument(); }, delegate { return !IsBusy; });
DeleteDocumentCommand = new RelayCommand(delegate { DeleteDocumentAsync(); }, delegate { return !IsBusy && SelectedDocument != null; });
RefreshDocumentsCommand = new RelayCommand(delegate { RefreshDocumentsAsync(null); }, delegate { return !IsBusy; });
SaveDocumentHeaderCommand = new RelayCommand(delegate { SaveDocumentHeaderAsync(); }, delegate { return !IsBusy && SelectedDocument != null && !SelectedDocument.IsDraft; });
DocumentStatusText = "Готово.";
LineStatusText = "Документ не выбран.";
}
public ICommand AddDocumentCommand { get; private set; }
public string DocumentFilterText
{
get { return _documentFilterText; }
set
{
if (SetProperty(ref _documentFilterText, value))
{
DocumentsView.Refresh();
}
}
}
public string DocumentNumberEditor
{
get { return _documentNumberEditor; }
set { SetProperty(ref _documentNumberEditor, value); }
}
public string DocumentStatusText
{
get { return _documentStatusText; }
private set { SetProperty(ref _documentStatusText, value); }
}
public ObservableCollection<PsvDocumentLine> DocumentLines { get; private set; }
public ObservableCollection<PsvDocumentGroupSummary> DocumentGroupSummaries { get; private set; }
public ICollectionView DocumentLinesView { get; private set; }
public ObservableCollection<PsvDocumentSummary> Documents { get; private set; }
public ICollectionView DocumentsView { get; private set; }
public ICommand DeleteDocumentCommand { get; private set; }
public string GroupDetailFilterText
{
get { return _groupDetailFilterText; }
set
{
if (SetProperty(ref _groupDetailFilterText, value))
{
RefreshDocumentLinesView();
}
}
}
public string HeaderCustomerName
{
get { return _headerCustomerName; }
private set { SetProperty(ref _headerCustomerName, value); }
}
public string HeaderDepartmentName
{
get { return _headerDepartmentName; }
private set { SetProperty(ref _headerDepartmentName, value); }
}
public DateTime? HeaderIssuedOn
{
get { return _headerIssuedOn; }
set { SetProperty(ref _headerIssuedOn, value); }
}
public DateTime? HeaderReceivedOn
{
get { return _headerReceivedOn; }
set { SetProperty(ref _headerReceivedOn, value); }
}
public bool IsBusy
{
get { return _isBusy; }
private set
{
if (SetProperty(ref _isBusy, value))
{
RaiseCommandStates();
}
}
}
public string LineStatusText
{
get { return _lineStatusText; }
private set { SetProperty(ref _lineStatusText, value); }
}
public ICommand RefreshDocumentsCommand { get; private set; }
public ICommand SaveDocumentHeaderCommand { get; private set; }
public PsvDocumentSummary SelectedDocument
{
get { return _selectedDocument; }
set
{
if (SetProperty(ref _selectedDocument, value))
{
FillHeaderFromSelection();
RaiseCommandStates();
LoadSelectedDocumentAsync();
}
}
}
public PsvDocumentGroupSummary SelectedDocumentGroup
{
get { return _selectedDocumentGroup; }
set
{
if (SetProperty(ref _selectedDocumentGroup, value))
{
RefreshDocumentLinesView();
}
}
}
public async Task InitializeAsync()
{
await RefreshDocumentsCoreAsync(null);
}
private void AddDocument()
{
if (IsBusy)
{
return;
}
var request = _dialogService.ShowCreateDocumentDialog(new DocumentEditorResult
{
AcceptedOn = DateTime.Today,
IssuedOn = null,
DocumentNumber = string.Empty
});
if (request == null)
{
return;
}
request.DocumentNumber = request.DocumentNumber == null ? string.Empty : request.DocumentNumber.Trim();
request.IssuedOn = null;
if (string.IsNullOrWhiteSpace(request.DocumentNumber))
{
_dialogService.ShowWarning("Введите номер ПСВ.");
return;
}
if (Documents.Any(delegate(PsvDocumentSummary document)
{
return string.Equals(document.DocumentNumber, request.DocumentNumber, StringComparison.OrdinalIgnoreCase);
}))
{
_dialogService.ShowWarning("ПСВ с таким номером уже есть в списке.");
return;
}
var draft = new PsvDocumentSummary
{
DocumentNumber = request.DocumentNumber,
AcceptedOn = request.AcceptedOn,
IssuedOn = null,
CustomerName = "Черновик текущего сеанса",
DepartmentName = string.Empty,
ItemCount = 0,
IssuedCount = 0,
PassedCount = 0,
FailedCount = 0,
IsDraft = true
};
_draftDocuments.Add(draft);
InsertDraftIntoCollection(draft);
DocumentsView.Refresh();
SelectedDocument = draft;
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
}
private void ClearCollections<T>(ObservableCollection<T> collection)
{
collection.Clear();
}
private void ClearHeader()
{
DocumentNumberEditor = string.Empty;
HeaderReceivedOn = null;
HeaderIssuedOn = null;
HeaderCustomerName = string.Empty;
HeaderDepartmentName = string.Empty;
}
private void DeleteDocumentAsync()
{
if (SelectedDocument == null)
{
return;
}
var selectedDocument = SelectedDocument;
if (!_dialogService.Confirm(string.Format("Удалить ПСВ \"{0}\"?", selectedDocument.DocumentNumber)))
{
return;
}
if (selectedDocument.IsDraft)
{
DeleteDraftDocument(selectedDocument);
return;
}
ExecuteBusyOperationAsync(async delegate
{
var result = await Task.Run(delegate { return _service.DeleteDocument(selectedDocument.DocumentNumber); });
await RefreshDocumentsCoreAsync(null);
_dialogService.ShowInfo(
string.Format(
"Удалено строк EKZMKFCTVL: {0}. Удалено строк EKZMK: {1}. Удалено связанных DMS: {2}.",
result.DeletedEkzMkFctvlCount,
result.DeletedEkzMkCount,
result.DeletedDmsCount));
});
}
private void DeleteDraftDocument(PsvDocumentSummary draft)
{
_draftDocuments.RemoveAll(delegate(PsvDocumentSummary item)
{
return string.Equals(item.DocumentNumber, draft.DocumentNumber, StringComparison.OrdinalIgnoreCase);
});
Documents.Remove(draft);
DocumentsView.Refresh();
if (Documents.Count > 0)
{
SelectedDocument = Documents[0];
}
else
{
SelectedDocument = null;
}
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
}
private void ExecuteBusyOperationAsync(Func<Task> operation)
{
ExecuteBusyOperationCoreAsync(operation);
}
private async void ExecuteBusyOperationCoreAsync(Func<Task> operation)
{
if (IsBusy)
{
return;
}
try
{
IsBusy = true;
await operation();
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
}
finally
{
IsBusy = false;
}
}
private bool FilterDocuments(object item)
{
var document = item as PsvDocumentSummary;
if (document == null)
{
return false;
}
if (document.IssuedOn.HasValue)
{
return false;
}
if (!string.IsNullOrWhiteSpace(DocumentFilterText)
&& !Contains(document.DocumentNumber, DocumentFilterText)
&& !Contains(document.CustomerName, DocumentFilterText))
{
return false;
}
return true;
}
private bool FilterDocumentLines(object item)
{
var line = item as PsvDocumentLine;
if (line == null || SelectedDocumentGroup == null)
{
return false;
}
if (!SelectedDocumentGroup.Matches(line))
{
return false;
}
if (string.IsNullOrWhiteSpace(GroupDetailFilterText))
{
return true;
}
return Contains(line.SerialNumber, GroupDetailFilterText);
}
private void FillHeaderFromSelection()
{
if (SelectedDocument == null)
{
ClearHeader();
return;
}
DocumentNumberEditor = SelectedDocument.DocumentNumber;
HeaderReceivedOn = SelectedDocument.AcceptedOn;
HeaderIssuedOn = SelectedDocument.IssuedOn;
HeaderCustomerName = SelectedDocument.CustomerName;
HeaderDepartmentName = SelectedDocument.DepartmentName;
}
private PsvDocumentGroupSummary FindMatchingGroup(PsvDocumentGroupSummary group)
{
if (group == null)
{
return null;
}
return DocumentGroupSummaries.FirstOrDefault(delegate(PsvDocumentGroupSummary current)
{
return string.Equals(current.InstrumentType ?? string.Empty, group.InstrumentType ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(current.RangeText ?? string.Empty, group.RangeText ?? string.Empty, StringComparison.OrdinalIgnoreCase)
&& string.Equals(current.RegistryNumber ?? string.Empty, group.RegistryNumber ?? string.Empty, StringComparison.OrdinalIgnoreCase);
});
}
private void InsertDraftIntoCollection(PsvDocumentSummary draft)
{
var insertIndex = 0;
while (insertIndex < Documents.Count
&& (Documents[insertIndex].AcceptedOn ?? DateTime.MinValue) >= (draft.AcceptedOn ?? DateTime.MinValue))
{
insertIndex++;
}
Documents.Insert(insertIndex, draft);
}
private async void LoadSelectedDocumentAsync()
{
if (SelectedDocument == null)
{
ClearCollections(DocumentLines);
ClearCollections(DocumentGroupSummaries);
SelectedDocumentGroup = null;
LineStatusText = "Документ не выбран.";
return;
}
if (SelectedDocument.IsDraft)
{
ClearCollections(DocumentLines);
ClearCollections(DocumentGroupSummaries);
SelectedDocumentGroup = null;
LineStatusText = "Черновик текущего сеанса. В базе он не сохранён, потому что отдельной таблицы ПСВ нет.";
return;
}
await LoadSelectedDocumentCoreAsync();
}
private async Task LoadSelectedDocumentCoreAsync()
{
try
{
LineStatusText = "Загрузка строк документа...";
var previousGroup = SelectedDocumentGroup;
var documentNumber = SelectedDocument.DocumentNumber;
var lines = await Task.Run(delegate { return _service.LoadDocumentLines(documentNumber); });
ClearCollections(DocumentLines);
foreach (var line in lines)
{
DocumentLines.Add(line);
}
RebuildDocumentGroupSummaries(lines);
SelectedDocumentGroup = FindMatchingGroup(previousGroup) ?? DocumentGroupSummaries.FirstOrDefault();
RefreshDocumentLinesView();
}
catch (Exception ex)
{
_dialogService.ShowError(ex.Message);
}
}
private void RaiseCommandStates()
{
((RelayCommand)AddDocumentCommand).RaiseCanExecuteChanged();
((RelayCommand)DeleteDocumentCommand).RaiseCanExecuteChanged();
((RelayCommand)RefreshDocumentsCommand).RaiseCanExecuteChanged();
((RelayCommand)SaveDocumentHeaderCommand).RaiseCanExecuteChanged();
}
private void RefreshDocumentLinesView()
{
DocumentLinesView.Refresh();
UpdateLineStatus();
}
private void RefreshDocumentsAsync(string documentToSelect)
{
ExecuteBusyOperationAsync(delegate { return RefreshDocumentsCoreAsync(documentToSelect); });
}
private async Task RefreshDocumentsCoreAsync(string documentToSelect)
{
DocumentStatusText = "Загрузка списка ПСВ...";
var databaseDocuments = await Task.Run(delegate { return _service.LoadDocuments(); });
var selectedDocumentNumber = documentToSelect ?? (SelectedDocument != null ? SelectedDocument.DocumentNumber : null);
ClearCollections(Documents);
foreach (var draft in _draftDocuments.OrderByDescending(delegate(PsvDocumentSummary item)
{
return item.AcceptedOn ?? DateTime.MinValue;
}))
{
Documents.Add(draft);
}
foreach (var document in databaseDocuments)
{
if (_draftDocuments.Any(delegate(PsvDocumentSummary draft)
{
return string.Equals(draft.DocumentNumber, document.DocumentNumber, StringComparison.OrdinalIgnoreCase);
}))
{
continue;
}
Documents.Add(document);
}
DocumentsView.Refresh();
SelectedDocument = Documents.FirstOrDefault(delegate(PsvDocumentSummary document)
{
return string.Equals(document.DocumentNumber, selectedDocumentNumber, StringComparison.OrdinalIgnoreCase);
});
if (SelectedDocument == null && Documents.Count > 0)
{
SelectedDocument = Documents[0];
}
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
}
private void RebuildDocumentGroupSummaries(IEnumerable<PsvDocumentLine> lines)
{
ClearCollections(DocumentGroupSummaries);
var groups = lines.GroupBy(line => new
{
InstrumentType = line.InstrumentType ?? string.Empty,
RangeText = line.RangeText ?? string.Empty,
RegistryNumber = line.RegistryNumber ?? string.Empty
})
.OrderBy(group => group.Key.InstrumentType)
.ThenBy(group => group.Key.RegistryNumber)
.ThenBy(group => group.Key.RangeText)
.Select(group => new PsvDocumentGroupSummary
{
InstrumentType = group.Key.InstrumentType,
RangeText = group.Key.RangeText,
RegistryNumber = group.Key.RegistryNumber,
InVerificationCount = group.Count(line => !line.IsPassed.HasValue),
VerifiedCount = group.Count(line => line.IsPassed.HasValue),
GoodCount = group.Count(line => line.IsPassed == true),
RejectedCount = group.Count(line => line.IsPassed == false)
});
foreach (var group in groups)
{
DocumentGroupSummaries.Add(group);
}
}
private void SaveDocumentHeaderAsync()
{
ExecuteBusyOperationAsync(async delegate
{
if (SelectedDocument == null)
{
_dialogService.ShowWarning("Сначала выберите документ.");
return;
}
if (SelectedDocument.IsDraft)
{
_dialogService.ShowWarning("Черновик нельзя сохранить в базе без строк EKZMK.");
return;
}
if (!HeaderReceivedOn.HasValue)
{
_dialogService.ShowWarning("Укажите дату приемки.");
return;
}
var request = new DocumentEditorResult
{
DocumentNumber = DocumentNumberEditor,
AcceptedOn = HeaderReceivedOn.Value,
IssuedOn = HeaderIssuedOn
};
await Task.Run(delegate { _service.UpdateDocumentHeader(SelectedDocument.DocumentNumber, request); });
await RefreshDocumentsCoreAsync(request.DocumentNumber);
_dialogService.ShowInfo("Реквизиты ПСВ обновлены.");
});
}
private void UpdateLineStatus()
{
if (SelectedDocument == null)
{
LineStatusText = "Документ не выбран.";
return;
}
if (SelectedDocument.IsDraft)
{
LineStatusText = "Черновик текущего сеанса. Строки появятся только после создания записей EKZMK.";
return;
}
if (DocumentGroupSummaries.Count == 0)
{
LineStatusText = "В документе нет групп приборов.";
return;
}
if (SelectedDocumentGroup == null)
{
LineStatusText = string.Format("Групп: {0}. Выберите группу.", DocumentGroupSummaries.Count);
return;
}
var groupLineCount = DocumentLines.Count(delegate(PsvDocumentLine line) { return SelectedDocumentGroup.Matches(line); });
var filteredCount = DocumentLines.Count(delegate(PsvDocumentLine line)
{
return SelectedDocumentGroup.Matches(line)
&& (string.IsNullOrWhiteSpace(GroupDetailFilterText) || Contains(line.SerialNumber, GroupDetailFilterText));
});
LineStatusText = string.Format(
"Групп: {0}. Приборов в выбранной группе: {1}. Отображено по фильтру: {2}.",
DocumentGroupSummaries.Count,
groupLineCount,
filteredCount);
}
private static bool Contains(string source, string filter)
{
return !string.IsNullOrWhiteSpace(source)
&& source.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0;
}
}
}

View File

@@ -0,0 +1,71 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace XLAB
{
public abstract class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(field, value))
{
return false;
}
field = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
internal sealed class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
}

935
XLAB/PsvDataService.cs Normal file
View File

@@ -0,0 +1,935 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
namespace XLAB
{
internal sealed class PsvDataService
{
private const string PsvPrefix = "ПСВ";
public IReadOnlyList<PsvDocumentSummary> LoadDocuments()
{
const string sql = @"
SELECT
m.NNZVPV AS DocumentNumber,
MAX(m.DTPRM) AS AcceptedOn,
MAX(m.DTVDM) AS IssuedOn,
MIN(dep.NMFRPD) AS DepartmentName,
MIN(ownerOrg.NMFRPD) AS CustomerName,
COUNT(*) AS ItemCount,
SUM(CASE WHEN m.DTVDM IS NOT NULL THEN 1 ELSE 0 END) AS IssuedCount,
SUM(CASE WHEN m.GDN = 1 THEN 1 ELSE 0 END) AS PassedCount,
SUM(CASE WHEN m.GDN = 0 THEN 1 ELSE 0 END) AS FailedCount
FROM dbo.EKZMK m
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
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
AND m.NNZVPV LIKE N'ПСВ%'
GROUP BY m.NNZVPV
HAVING MAX(m.DTVDM) IS NULL
ORDER BY MAX(m.DTPRM) DESC, m.NNZVPV DESC;";
var documents = new List<PsvDocumentSummary>();
using (var connection = CreateConnection())
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
command.CommandTimeout = 60;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
documents.Add(new PsvDocumentSummary
{
DocumentNumber = GetString(reader, "DocumentNumber"),
AcceptedOn = GetNullableDateTime(reader, "AcceptedOn"),
IssuedOn = GetNullableDateTime(reader, "IssuedOn"),
DepartmentName = GetString(reader, "DepartmentName"),
CustomerName = GetString(reader, "CustomerName"),
ItemCount = GetInt32(reader, "ItemCount"),
IssuedCount = GetInt32(reader, "IssuedCount"),
PassedCount = GetInt32(reader, "PassedCount"),
FailedCount = GetInt32(reader, "FailedCount")
});
}
}
}
return documents;
}
public IReadOnlyList<PsvDocumentLine> LoadDocumentLines(string documentNumber)
{
const string sql = @"
SELECT
m.IDEKZMK AS CardId,
z.IDEKZ AS InstrumentId,
z.NNZV AS SerialNumber,
z.NNIN AS InventoryNumber,
ownerOrg.NMFRPD AS CustomerName,
tips.TP AS InstrumentType,
names.NMTP AS InstrumentName,
areas.NMOI AS MeasurementArea,
sizeInfo.DPZN AS RangeText,
sizeInfo.NNGSRS AS RegistryNumber,
sizeInfo.HRTC AS AccuracyText,
verificationType.NMVDMK AS VerificationType,
m.PRMK AS PeriodMonths,
m.DTPRM AS AcceptedOn,
m.DTVDM AS IssuedOn,
m.GDN AS IsPassed,
verifier.PRFIO AS VerifierName,
m.NNNKL AS StickerNumber,
verificationDocument.NNDMS AS VerificationDocumentNumber,
verificationDocument.DTDMS AS VerificationDocumentDate,
m.DSEKZMK AS Notes
FROM dbo.EKZMK m
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
LEFT JOIN dbo.TPRZ sizeInfo ON sizeInfo.IDTPRZ = z.IDTPRZ
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
LEFT JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
LEFT JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
LEFT JOIN dbo.SPVDMK verificationType ON verificationType.IDSPVDMK = m.IDSPVDMK
LEFT JOIN dbo.PRSN verifier ON verifier.IDPRSN = m.IDPRSN
OUTER APPLY
(
SELECT TOP (1)
d.NND AS NNDMS,
d.DTD AS DTDMS
FROM dbo.DMS d
JOIN dbo.VDODVDD vdd ON vdd.IDVDODVDD = d.IDVDODVDD
JOIN dbo.FRDMS frdms ON frdms.IDFRDMS = d.IDFRDMS
JOIN dbo.SPVDD spvdd ON spvdd.IDSPVDD = frdms.IDSPVDD
WHERE d.IDOD = m.IDEKZMK
AND vdd.IDSPVDOD = 2
AND spvdd.IDSPVDD IN (2, 6, 8)
ORDER BY d.DTD DESC
) verificationDocument
WHERE m.NNZVPV = @DocumentNumber
ORDER BY areas.NMOI, names.NMTP, tips.TP, z.NNZV;";
var lines = new List<PsvDocumentLine>();
using (var connection = CreateConnection())
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
command.CommandTimeout = 60;
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
lines.Add(new PsvDocumentLine
{
CardId = GetInt32(reader, "CardId"),
InstrumentId = GetInt32(reader, "InstrumentId"),
SerialNumber = GetString(reader, "SerialNumber"),
InventoryNumber = GetString(reader, "InventoryNumber"),
CustomerName = GetString(reader, "CustomerName"),
InstrumentType = GetString(reader, "InstrumentType"),
InstrumentName = GetString(reader, "InstrumentName"),
MeasurementArea = GetString(reader, "MeasurementArea"),
RangeText = GetString(reader, "RangeText"),
RegistryNumber = GetString(reader, "RegistryNumber"),
AccuracyText = GetString(reader, "AccuracyText"),
VerificationType = GetString(reader, "VerificationType"),
PeriodMonths = GetInt32(reader, "PeriodMonths"),
AcceptedOn = GetNullableDateTime(reader, "AcceptedOn"),
IssuedOn = GetNullableDateTime(reader, "IssuedOn"),
IsPassed = GetNullableBoolean(reader, "IsPassed"),
VerifierName = GetString(reader, "VerifierName"),
StickerNumber = GetString(reader, "StickerNumber"),
VerificationDocumentNumber = GetString(reader, "VerificationDocumentNumber"),
VerificationDocumentDate = GetNullableDateTime(reader, "VerificationDocumentDate"),
Notes = GetString(reader, "Notes")
});
}
}
}
return lines;
}
public IReadOnlyList<AvailableInstrumentItem> SearchAvailableInstruments(string searchText, string currentDocumentNumber, int take)
{
const string sql = @"
WITH FilteredInstruments AS
(
SELECT TOP (@Take)
z.IDEKZ AS InstrumentId,
z.IDTPRZ AS TypeSizeId,
z.NNZV AS SerialNumber,
z.NNIN AS InventoryNumber,
ownerOrg.NMFRPD AS CustomerName,
tips.TP AS InstrumentType,
names.NMTP AS InstrumentName,
areas.NMOI AS MeasurementArea,
sizeInfo.DPZN AS RangeText,
sizeInfo.HRTC AS AccuracyText
FROM dbo.EKZ z
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
LEFT JOIN dbo.TPRZ sizeInfo ON sizeInfo.IDTPRZ = z.IDTPRZ
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
LEFT JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
LEFT JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
WHERE (@Search = N''
OR z.NNZV LIKE @LikeSearch
OR ISNULL(z.NNIN, N'') LIKE @LikeSearch
OR ISNULL(ownerOrg.NMFRPD, N'') LIKE @LikeSearch
OR ISNULL(tips.TP, N'') LIKE @LikeSearch
OR ISNULL(names.NMTP, N'') LIKE @LikeSearch
OR ISNULL(areas.NMOI, N'') LIKE @LikeSearch
OR ISNULL(sizeInfo.DPZN, N'') LIKE @LikeSearch)
AND (@CurrentDocumentNumber = N''
OR NOT EXISTS
(
SELECT 1
FROM dbo.EKZMK existingInDocument
WHERE existingInDocument.NNZVPV = @CurrentDocumentNumber
AND existingInDocument.IDEKZ = z.IDEKZ
))
ORDER BY z.IDEKZ DESC
)
SELECT
filtered.InstrumentId,
filtered.TypeSizeId,
filtered.SerialNumber,
filtered.InventoryNumber,
filtered.CustomerName,
filtered.InstrumentType,
filtered.InstrumentName,
filtered.MeasurementArea,
filtered.RangeText,
filtered.AccuracyText,
COALESCE(instrumentTemplate.LastDocumentNumber, typeTemplate.LastDocumentNumber) AS LastDocumentNumber,
COALESCE(instrumentTemplate.LastAcceptedOn, typeTemplate.LastAcceptedOn) AS LastAcceptedOn,
CASE
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL THEN N'История прибора'
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
ELSE N''
END AS TemplateSource
FROM FilteredInstruments filtered
OUTER APPLY
(
SELECT TOP (1)
history.NNZVPV AS LastDocumentNumber,
history.DTPRM AS LastAcceptedOn
FROM dbo.EKZMK history
WHERE history.IDEKZ = filtered.InstrumentId
ORDER BY ISNULL(history.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, history.IDEKZMK DESC
) instrumentTemplate
OUTER APPLY
(
SELECT TOP (1)
history.NNZVPV AS LastDocumentNumber,
history.DTPRM AS LastAcceptedOn
FROM dbo.EKZMK history
JOIN dbo.EKZ instrumentOfSameType ON instrumentOfSameType.IDEKZ = history.IDEKZ
WHERE instrumentOfSameType.IDTPRZ = filtered.TypeSizeId
ORDER BY ISNULL(history.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, history.IDEKZMK DESC
) typeTemplate
WHERE instrumentTemplate.LastDocumentNumber IS NOT NULL
OR typeTemplate.LastDocumentNumber IS NOT NULL
ORDER BY
CASE WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL THEN 0 ELSE 1 END,
filtered.CustomerName,
filtered.InstrumentName,
filtered.SerialNumber;";
var instruments = new List<AvailableInstrumentItem>();
using (var connection = CreateConnection())
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
command.CommandTimeout = 60;
command.Parameters.Add("@Take", SqlDbType.Int).Value = Math.Max(1, take);
command.Parameters.Add("@Search", SqlDbType.NVarChar, 200).Value = searchText ?? string.Empty;
command.Parameters.Add("@LikeSearch", SqlDbType.NVarChar, 204).Value = "%" + (searchText ?? string.Empty).Trim() + "%";
command.Parameters.Add("@CurrentDocumentNumber", SqlDbType.NVarChar, 60).Value = currentDocumentNumber ?? string.Empty;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
instruments.Add(new AvailableInstrumentItem
{
InstrumentId = GetInt32(reader, "InstrumentId"),
TypeSizeId = GetInt32(reader, "TypeSizeId"),
SerialNumber = GetString(reader, "SerialNumber"),
InventoryNumber = GetString(reader, "InventoryNumber"),
CustomerName = GetString(reader, "CustomerName"),
InstrumentType = GetString(reader, "InstrumentType"),
InstrumentName = GetString(reader, "InstrumentName"),
MeasurementArea = GetString(reader, "MeasurementArea"),
RangeText = GetString(reader, "RangeText"),
AccuracyText = GetString(reader, "AccuracyText"),
LastDocumentNumber = GetString(reader, "LastDocumentNumber"),
LastAcceptedOn = GetNullableDateTime(reader, "LastAcceptedOn"),
TemplateSource = GetString(reader, "TemplateSource")
});
}
}
}
return instruments;
}
public int AddInstrumentsToDocument(DocumentEditorResult document, IEnumerable<int> instrumentIds)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}
var normalizedNumber = NormalizeDocumentNumber(document.DocumentNumber);
if (normalizedNumber == null)
{
throw new InvalidOperationException("Номер ПСВ не заполнен.");
}
var added = 0;
using (var connection = CreateConnection())
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
var verificationTypeId = LoadVerificationTypeId(connection, transaction);
foreach (var instrumentId in instrumentIds)
{
if (DocumentContainsInstrument(connection, transaction, normalizedNumber, instrumentId))
{
continue;
}
var template = LoadTemplate(connection, transaction, instrumentId);
if (template == null)
{
throw new InvalidOperationException(
string.Format("Для прибора IDEKZ={0} не найден подтверждённый шаблон EKZMK.", instrumentId));
}
InsertEkzMk(connection, transaction, verificationTypeId, document, normalizedNumber, instrumentId, template);
added++;
}
transaction.Commit();
}
}
return added;
}
public void UpdateDocumentHeader(string currentDocumentNumber, DocumentEditorResult document)
{
const string sql = @"
UPDATE dbo.EKZMK
SET NNZVPV = @NewDocumentNumber,
DTPRM = @AcceptedOn,
DTVDM = @IssuedOn
WHERE NNZVPV = @CurrentDocumentNumber;";
if (string.IsNullOrWhiteSpace(currentDocumentNumber))
{
throw new InvalidOperationException("Не выбран документ для обновления.");
}
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}
var normalizedNumber = NormalizeDocumentNumber(document.DocumentNumber);
if (normalizedNumber == null)
{
throw new InvalidOperationException("Номер ПСВ не заполнен.");
}
using (var connection = CreateConnection())
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
command.CommandTimeout = 60;
command.Parameters.Add("@NewDocumentNumber", SqlDbType.NVarChar, 60).Value = normalizedNumber;
command.Parameters.Add("@AcceptedOn", SqlDbType.DateTime).Value = document.AcceptedOn;
command.Parameters.Add("@IssuedOn", SqlDbType.DateTime).Value = (object)document.IssuedOn ?? DBNull.Value;
command.Parameters.Add("@CurrentDocumentNumber", SqlDbType.NVarChar, 60).Value = currentDocumentNumber;
command.ExecuteNonQuery();
}
}
public DocumentDeleteResult DeleteDocument(string documentNumber)
{
if (string.IsNullOrWhiteSpace(documentNumber))
{
throw new InvalidOperationException("Не выбран документ для удаления.");
}
var blockers = new List<DeleteBlockerInfo>();
using (var connection = CreateConnection())
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
blockers = LoadDeleteBlockers(connection, transaction, documentNumber);
if (blockers.Count > 0)
{
var details = string.Join(", ", blockers.Select(delegate(DeleteBlockerInfo blocker)
{
return string.Format("{0}: {1}", blocker.TableName, blocker.RowCount);
}));
throw new InvalidOperationException(
string.Format(
"ПСВ не может быть удалён, потому что на его строки EKZMK есть ссылки в таблицах: {0}. По вашему правилу приложение не трогает эти таблицы.",
details));
}
var deletedEkzMkFctvlCount = DeleteDocumentEkzMkFctvl(connection, transaction, documentNumber);
var deletedDmsCount = DeleteDocumentDms(connection, transaction, documentNumber);
var deletedEkzMkCount = DeleteDocumentEkzMk(connection, transaction, documentNumber);
if (deletedEkzMkCount == 0)
{
throw new InvalidOperationException("Строки EKZMK для выбранного ПСВ не найдены.");
}
transaction.Commit();
return new DocumentDeleteResult
{
DeletedEkzMkFctvlCount = deletedEkzMkFctvlCount,
DeletedDmsCount = deletedDmsCount,
DeletedEkzMkCount = deletedEkzMkCount
};
}
}
}
private static string NormalizeDocumentNumber(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
var trimmed = value.Trim();
if (trimmed.StartsWith(PsvPrefix, StringComparison.OrdinalIgnoreCase))
{
return trimmed;
}
return trimmed;
}
private static SqlConnection CreateConnection()
{
var connectionString = ConfigurationManager.ConnectionStrings["AsumsSql"];
if (connectionString == null || string.IsNullOrWhiteSpace(connectionString.ConnectionString))
{
throw new InvalidOperationException("В App.config не найдено подключение AsumsSql.");
}
return new SqlConnection(connectionString.ConnectionString);
}
private static bool DocumentContainsInstrument(SqlConnection connection, SqlTransaction transaction, string documentNumber, int instrumentId)
{
const string sql = @"
SELECT COUNT(1)
FROM dbo.EKZMK
WHERE NNZVPV = @DocumentNumber
AND IDEKZ = @InstrumentId;";
using (var command = new SqlCommand(sql, connection, transaction))
{
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = instrumentId;
return Convert.ToInt32(command.ExecuteScalar()) > 0;
}
}
private static int DeleteDocumentDms(SqlConnection connection, SqlTransaction transaction, string documentNumber)
{
const string sql = @"
DELETE d
FROM dbo.DMS d
JOIN dbo.VDODVDD vdd ON vdd.IDVDODVDD = d.IDVDODVDD
JOIN dbo.EKZMK m ON m.IDEKZMK = d.IDOD
WHERE m.NNZVPV = @DocumentNumber
AND vdd.IDSPVDOD = 2;
SELECT @@ROWCOUNT;";
using (var command = new SqlCommand(sql, connection, transaction))
{
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
return Convert.ToInt32(command.ExecuteScalar());
}
}
private static int DeleteDocumentEkzMkFctvl(SqlConnection connection, SqlTransaction transaction, string documentNumber)
{
const string sql = @"
DELETE child
FROM dbo.EKZMKFCTVL child
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
WHERE parent.NNZVPV = @DocumentNumber;
SELECT @@ROWCOUNT;";
using (var command = new SqlCommand(sql, connection, transaction))
{
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
return Convert.ToInt32(command.ExecuteScalar());
}
}
private static int DeleteDocumentEkzMk(SqlConnection connection, SqlTransaction transaction, string documentNumber)
{
const string sql = @"
DELETE FROM dbo.EKZMK
WHERE NNZVPV = @DocumentNumber;
SELECT @@ROWCOUNT;";
using (var command = new SqlCommand(sql, connection, transaction))
{
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
return Convert.ToInt32(command.ExecuteScalar());
}
}
private static List<DeleteBlockerInfo> LoadDeleteBlockers(SqlConnection connection, SqlTransaction transaction, string documentNumber)
{
const string sql = @"
SELECT blocker.TableName, blocker.LinkCount
FROM
(
SELECT N'EKZMKDH' AS TableName, COUNT(*) AS LinkCount
FROM dbo.EKZMKDH child
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
WHERE parent.NNZVPV = @DocumentNumber
UNION ALL
SELECT N'EKZMKEKZK', COUNT(*)
FROM dbo.EKZMKEKZK child
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
WHERE parent.NNZVPV = @DocumentNumber
UNION ALL
SELECT N'EKZMKND', COUNT(*)
FROM dbo.EKZMKND child
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
WHERE parent.NNZVPV = @DocumentNumber
UNION ALL
SELECT N'FRPTMK', COUNT(*)
FROM dbo.FRPTMK child
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
WHERE parent.NNZVPV = @DocumentNumber
UNION ALL
SELECT N'KSPELEKZMK', COUNT(*)
FROM dbo.KSPELEKZMK child
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
WHERE parent.NNZVPV = @DocumentNumber
) blocker
WHERE blocker.LinkCount > 0
ORDER BY blocker.TableName;";
var blockers = new List<DeleteBlockerInfo>();
using (var command = new SqlCommand(sql, connection, transaction))
{
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
blockers.Add(new DeleteBlockerInfo
{
TableName = GetString(reader, "TableName"),
RowCount = GetInt32(reader, "LinkCount")
});
}
}
}
return blockers;
}
private static int LoadVerificationTypeId(SqlConnection connection, SqlTransaction transaction)
{
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;";
using (var command = new SqlCommand(sql, connection, transaction))
{
var result = command.ExecuteScalar();
if (result == null || result == DBNull.Value)
{
throw new InvalidOperationException("В справочнике SPVDMK не найден вид МК 'Поверка'.");
}
return Convert.ToInt32(result);
}
}
private static EkzMkTemplate LoadTemplate(SqlConnection connection, SqlTransaction transaction, int instrumentId)
{
const string sql = @"
DECLARE @TypeSizeId int;
SELECT @TypeSizeId = IDTPRZ FROM dbo.EKZ WHERE IDEKZ = @InstrumentId;
WITH TemplateCandidates AS
(
SELECT *
FROM
(
SELECT TOP (1)
1 AS Priority,
m.IDSPMU,
m.IDGRSI,
m.IDKSPRL,
m.IDSPVDMC,
m.IDFRPD,
m.IDSPMPOB,
m.IDPRSN,
m.IDSPKMMK,
m.IDSPVDKL,
m.IDPRSNVD,
m.PRMK,
m.STMK,
m.STMKDP,
m.NCSRMK,
m.idprsnsd,
m.idprsnpr,
m.idprsnvy,
m.idsptsmp,
m.idspssmp,
m.NRVRMNDmp,
m.NRVRMmp,
m.VRMKFK,
m.IDKSP,
m.DPZNmp,
m.HRTCmp,
m.IDSPVDSBMK,
m.IDEKZETL,
CAST(N'История прибора' AS nvarchar(60)) AS SourceDescription
FROM dbo.EKZMK m
WHERE m.IDEKZ = @InstrumentId
ORDER BY ISNULL(m.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, m.IDEKZMK DESC
) instrumentTemplate
UNION ALL
SELECT *
FROM
(
SELECT TOP (1)
2 AS Priority,
m.IDSPMU,
m.IDGRSI,
m.IDKSPRL,
m.IDSPVDMC,
m.IDFRPD,
m.IDSPMPOB,
m.IDPRSN,
m.IDSPKMMK,
m.IDSPVDKL,
m.IDPRSNVD,
m.PRMK,
m.STMK,
m.STMKDP,
m.NCSRMK,
m.idprsnsd,
m.idprsnpr,
m.idprsnvy,
m.idsptsmp,
m.idspssmp,
m.NRVRMNDmp,
m.NRVRMmp,
m.VRMKFK,
m.IDKSP,
m.DPZNmp,
m.HRTCmp,
m.IDSPVDSBMK,
m.IDEKZETL,
CAST(N'Шаблон по типоразмеру' AS nvarchar(60)) AS SourceDescription
FROM dbo.EKZMK m
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
WHERE z.IDTPRZ = @TypeSizeId
ORDER BY ISNULL(m.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, m.IDEKZMK DESC
) typeTemplate
)
SELECT TOP (1) *
FROM TemplateCandidates
ORDER BY Priority;";
using (var command = new SqlCommand(sql, connection, transaction))
{
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = instrumentId;
using (var reader = command.ExecuteReader())
{
if (!reader.Read())
{
return null;
}
return new EkzMkTemplate
{
IdSpmu = GetNullableInt32(reader, "IDSPMU"),
IdGrsi = GetNullableInt32(reader, "IDGRSI"),
IdKsprl = GetNullableInt32(reader, "IDKSPRL"),
IdSpvdmc = GetNullableInt32(reader, "IDSPVDMC"),
IdFrpd = GetInt32(reader, "IDFRPD"),
IdSpmpob = GetNullableInt32(reader, "IDSPMPOB"),
IdPrsn = GetNullableInt32(reader, "IDPRSN"),
IdSpkmmk = GetNullableInt32(reader, "IDSPKMMK"),
IdSpvdkl = GetNullableInt32(reader, "IDSPVDKL"),
IdPrsnvd = GetNullableInt32(reader, "IDPRSNVD"),
Prmk = GetInt32(reader, "PRMK"),
Stmk = GetNullableDecimal(reader, "STMK"),
Stmkdp = GetNullableDecimal(reader, "STMKDP"),
NcSrmk = GetNullableDecimal(reader, "NCSRMK"),
IdPrsnsd = GetNullableInt32(reader, "idprsnsd"),
IdPrsnpr = GetNullableInt32(reader, "idprsnpr"),
IdPrsnvy = GetNullableInt32(reader, "idprsnvy"),
IdSptsmp = GetNullableInt32(reader, "idsptsmp"),
IdSpssmp = GetNullableInt32(reader, "idspssmp"),
Nrvrmndmp = GetNullableDecimal(reader, "NRVRMNDmp"),
Nrvrmmp = GetNullableDecimal(reader, "NRVRMmp"),
Vrmkfk = GetNullableDecimal(reader, "VRMKFK"),
IdKsp = GetNullableInt32(reader, "IDKSP"),
Dpznmp = GetString(reader, "DPZNmp"),
Hrtcmp = GetString(reader, "HRTCmp"),
IdSpvdsbmk = GetNullableInt32(reader, "IDSPVDSBMK"),
IdEkzetl = GetNullableInt32(reader, "IDEKZETL"),
SourceDescription = GetString(reader, "SourceDescription")
};
}
}
}
private static void InsertEkzMk(
SqlConnection connection,
SqlTransaction transaction,
int verificationTypeId,
DocumentEditorResult document,
string normalizedNumber,
int instrumentId,
EkzMkTemplate template)
{
const string sql = @"
INSERT INTO dbo.EKZMK
(
IDEKZ,
IDSPMU,
IDGRSI,
IDKSPRL,
IDSPVDMK,
IDSPVDMC,
IDFRPD,
IDSPMPOB,
IDPRSN,
IDSPKMMK,
IDEKZRM,
IDSPVDKL,
IDPRSNVD,
IDEKZTO,
IDEKZOT,
NNZVPV,
SHFKL,
NNNKL,
PRMK,
DTMKFK,
DTMKPL,
DTPRM,
DTVDM,
GDN,
PZMC,
STMK,
STMKDP,
NCSRMK,
idprsnsd,
idprsnpr,
idprsnvy,
idsptsmp,
idspssmp,
GUIDEKZMK,
DSEKZMK,
DTOTM,
DTVZM,
IDPRSNOTM,
IDPRSNVZM,
NRVRMNDmp,
NRVRMmp,
VRMKFK,
IDKSP,
DPZNmp,
HRTCmp,
IDSPVDSBMK,
PRCHNPGDN,
IDEKZETL
)
VALUES
(
@IDEKZ,
@IDSPMU,
@IDGRSI,
@IDKSPRL,
@IDSPVDMK,
@IDSPVDMC,
@IDFRPD,
@IDSPMPOB,
@IDPRSN,
@IDSPKMMK,
NULL,
@IDSPVDKL,
@IDPRSNVD,
NULL,
NULL,
@NNZVPV,
NULL,
NULL,
@PRMK,
NULL,
NULL,
@DTPRM,
@DTVDM,
NULL,
NULL,
@STMK,
@STMKDP,
@NCSRMK,
@idprsnsd,
@idprsnpr,
@idprsnvy,
@idsptsmp,
@idspssmp,
@GUIDEKZMK,
NULL,
NULL,
NULL,
NULL,
NULL,
@NRVRMNDmp,
@NRVRMmp,
@VRMKFK,
@IDKSP,
@DPZNmp,
@HRTCmp,
@IDSPVDSBMK,
NULL,
@IDEKZETL
);";
using (var command = new SqlCommand(sql, connection, transaction))
{
command.CommandTimeout = 60;
command.Parameters.Add("@IDEKZ", SqlDbType.Int).Value = instrumentId;
command.Parameters.Add("@IDSPMU", SqlDbType.Int).Value = (object)template.IdSpmu ?? DBNull.Value;
command.Parameters.Add("@IDGRSI", SqlDbType.Int).Value = (object)template.IdGrsi ?? DBNull.Value;
command.Parameters.Add("@IDKSPRL", SqlDbType.Int).Value = (object)template.IdKsprl ?? DBNull.Value;
command.Parameters.Add("@IDSPVDMK", SqlDbType.Int).Value = verificationTypeId;
command.Parameters.Add("@IDSPVDMC", SqlDbType.Int).Value = (object)template.IdSpvdmc ?? DBNull.Value;
command.Parameters.Add("@IDFRPD", SqlDbType.Int).Value = template.IdFrpd;
command.Parameters.Add("@IDSPMPOB", SqlDbType.Int).Value = (object)template.IdSpmpob ?? DBNull.Value;
command.Parameters.Add("@IDPRSN", SqlDbType.Int).Value = (object)template.IdPrsn ?? DBNull.Value;
command.Parameters.Add("@IDSPKMMK", SqlDbType.Int).Value = (object)template.IdSpkmmk ?? DBNull.Value;
command.Parameters.Add("@IDSPVDKL", SqlDbType.Int).Value = (object)template.IdSpvdkl ?? DBNull.Value;
command.Parameters.Add("@IDPRSNVD", SqlDbType.Int).Value = (object)template.IdPrsnvd ?? DBNull.Value;
command.Parameters.Add("@NNZVPV", SqlDbType.NVarChar, 60).Value = normalizedNumber;
command.Parameters.Add("@PRMK", SqlDbType.Int).Value = template.Prmk;
command.Parameters.Add("@DTPRM", SqlDbType.DateTime).Value = document.AcceptedOn;
command.Parameters.Add("@DTVDM", SqlDbType.DateTime).Value = (object)document.IssuedOn ?? DBNull.Value;
command.Parameters.Add("@STMK", SqlDbType.Money).Value = (object)template.Stmk ?? DBNull.Value;
command.Parameters.Add("@STMKDP", SqlDbType.Money).Value = (object)template.Stmkdp ?? DBNull.Value;
command.Parameters.Add("@NCSRMK", SqlDbType.Money).Value = (object)template.NcSrmk ?? DBNull.Value;
command.Parameters.Add("@idprsnsd", SqlDbType.Int).Value = (object)template.IdPrsnsd ?? DBNull.Value;
command.Parameters.Add("@idprsnpr", SqlDbType.Int).Value = (object)template.IdPrsnpr ?? DBNull.Value;
command.Parameters.Add("@idprsnvy", SqlDbType.Int).Value = (object)template.IdPrsnvy ?? DBNull.Value;
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("@NRVRMNDmp", SqlDbType.Decimal).Value = (object)template.Nrvrmndmp ?? DBNull.Value;
command.Parameters["@NRVRMNDmp"].Precision = 10;
command.Parameters["@NRVRMNDmp"].Scale = 2;
command.Parameters.Add("@NRVRMmp", SqlDbType.Decimal).Value = (object)template.Nrvrmmp ?? DBNull.Value;
command.Parameters["@NRVRMmp"].Precision = 10;
command.Parameters["@NRVRMmp"].Scale = 2;
command.Parameters.Add("@VRMKFK", SqlDbType.Decimal).Value = (object)template.Vrmkfk ?? DBNull.Value;
command.Parameters["@VRMKFK"].Precision = 10;
command.Parameters["@VRMKFK"].Scale = 2;
command.Parameters.Add("@IDKSP", SqlDbType.Int).Value = (object)template.IdKsp ?? DBNull.Value;
command.Parameters.Add("@DPZNmp", SqlDbType.NVarChar, 100).Value = (object)template.Dpznmp ?? DBNull.Value;
command.Parameters.Add("@HRTCmp", SqlDbType.NVarChar, 80).Value = (object)template.Hrtcmp ?? DBNull.Value;
command.Parameters.Add("@IDSPVDSBMK", SqlDbType.Int).Value = (object)template.IdSpvdsbmk ?? DBNull.Value;
command.Parameters.Add("@IDEKZETL", SqlDbType.Int).Value = (object)template.IdEkzetl ?? DBNull.Value;
command.ExecuteNonQuery();
}
}
private sealed class DeleteBlockerInfo
{
public string TableName { get; set; }
public int RowCount { get; set; }
}
private static int GetInt32(IDataRecord record, string columnName)
{
return Convert.ToInt32(record[columnName]);
}
private static int? GetNullableInt32(IDataRecord record, string columnName)
{
return record[columnName] == DBNull.Value ? (int?)null : Convert.ToInt32(record[columnName]);
}
private static DateTime? GetNullableDateTime(IDataRecord record, string columnName)
{
return record[columnName] == DBNull.Value ? (DateTime?)null : Convert.ToDateTime(record[columnName]);
}
private static bool? GetNullableBoolean(IDataRecord record, string columnName)
{
return record[columnName] == DBNull.Value ? (bool?)null : Convert.ToBoolean(record[columnName]);
}
private static decimal? GetNullableDecimal(IDataRecord record, string columnName)
{
return record[columnName] == DBNull.Value ? (decimal?)null : Convert.ToDecimal(record[columnName]);
}
private static string GetString(IDataRecord record, string columnName)
{
return record[columnName] == DBNull.Value ? string.Empty : Convert.ToString(record[columnName]);
}
}
}

259
XLAB/PsvModels.cs Normal file
View File

@@ -0,0 +1,259 @@
using System;
namespace XLAB
{
public sealed class GroupOption
{
public string Key { get; set; }
public string Title { get; set; }
public override string ToString()
{
return Title ?? string.Empty;
}
}
public sealed class PsvDocumentSummary
{
public string DocumentNumber { get; set; }
public DateTime? AcceptedOn { get; set; }
public DateTime? IssuedOn { get; set; }
public string DepartmentName { get; set; }
public string CustomerName { get; set; }
public int ItemCount { get; set; }
public int IssuedCount { get; set; }
public int PassedCount { get; set; }
public int FailedCount { get; set; }
public bool IsDraft { get; set; }
public string AcceptedMonthGroup
{
get { return AcceptedOn.HasValue ? AcceptedOn.Value.ToString("yyyy-MM") : "Без даты"; }
}
}
public sealed class PsvDocumentLine
{
public int CardId { get; set; }
public int InstrumentId { get; set; }
public string SerialNumber { get; set; }
public string InventoryNumber { get; set; }
public string CustomerName { get; set; }
public string InstrumentType { get; set; }
public string InstrumentName { get; set; }
public string MeasurementArea { get; set; }
public string RangeText { get; set; }
public string RegistryNumber { get; set; }
public string AccuracyText { get; set; }
public string VerificationType { get; set; }
public int PeriodMonths { get; set; }
public DateTime? AcceptedOn { get; set; }
public DateTime? IssuedOn { get; set; }
public bool? IsPassed { get; set; }
public string VerifierName { get; set; }
public string StickerNumber { get; set; }
public string VerificationDocumentNumber { get; set; }
public DateTime? VerificationDocumentDate { get; set; }
public string Notes { get; set; }
public string ResultText
{
get
{
if (!IsPassed.HasValue)
{
return string.Empty;
}
return IsPassed.Value ? "Годен" : "Не годен";
}
}
public string VerificationDocumentDisplay
{
get
{
if (string.IsNullOrWhiteSpace(VerificationDocumentNumber))
{
return VerificationDocumentDate.HasValue ? VerificationDocumentDate.Value.ToString("d") : string.Empty;
}
if (!VerificationDocumentDate.HasValue)
{
return VerificationDocumentNumber;
}
return string.Format("{0} от {1:d}", VerificationDocumentNumber, VerificationDocumentDate.Value);
}
}
}
public sealed class PsvDocumentGroupSummary
{
public string InstrumentType { get; set; }
public string RangeText { get; set; }
public string RegistryNumber { get; set; }
public int InVerificationCount { get; set; }
public int VerifiedCount { get; set; }
public int GoodCount { get; set; }
public int RejectedCount { get; set; }
public bool Matches(PsvDocumentLine line)
{
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(RegistryNumber ?? string.Empty, line.RegistryNumber ?? string.Empty, StringComparison.OrdinalIgnoreCase);
}
}
public sealed class AvailableInstrumentItem : ObservableObject
{
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set { SetProperty(ref _isSelected, value); }
}
public int InstrumentId { get; set; }
public int TypeSizeId { get; set; }
public string SerialNumber { get; set; }
public string InventoryNumber { get; set; }
public string CustomerName { get; set; }
public string InstrumentType { get; set; }
public string InstrumentName { get; set; }
public string MeasurementArea { get; set; }
public string RangeText { get; set; }
public string AccuracyText { get; set; }
public string LastDocumentNumber { get; set; }
public DateTime? LastAcceptedOn { get; set; }
public string TemplateSource { get; set; }
}
public sealed class DocumentEditorResult
{
public string DocumentNumber { get; set; }
public DateTime AcceptedOn { get; set; }
public DateTime? IssuedOn { get; set; }
}
internal sealed class DocumentDeleteResult
{
public int DeletedEkzMkFctvlCount { get; set; }
public int DeletedEkzMkCount { get; set; }
public int DeletedDmsCount { get; set; }
}
internal sealed class EkzMkTemplate
{
public int? IdSpmu { get; set; }
public int? IdGrsi { get; set; }
public int? IdKsprl { get; set; }
public int? IdSpvdmc { get; set; }
public int IdFrpd { get; set; }
public int? IdSpmpob { get; set; }
public int? IdPrsn { get; set; }
public int? IdSpkmmk { get; set; }
public int? IdSpvdkl { get; set; }
public int? IdPrsnvd { get; set; }
public int Prmk { get; set; }
public decimal? Stmk { get; set; }
public decimal? Stmkdp { get; set; }
public decimal? NcSrmk { get; set; }
public int? IdPrsnsd { get; set; }
public int? IdPrsnpr { get; set; }
public int? IdPrsnvy { get; set; }
public int? IdSptsmp { get; set; }
public int? IdSpssmp { get; set; }
public decimal? Nrvrmndmp { get; set; }
public decimal? Nrvrmmp { get; set; }
public decimal? Vrmkfk { get; set; }
public int? IdKsp { get; set; }
public string Dpznmp { get; set; }
public string Hrtcmp { get; set; }
public int? IdSpvdsbmk { get; set; }
public int? IdEkzetl { get; set; }
public string SourceDescription { get; set; }
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -13,7 +13,6 @@
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@@ -36,6 +35,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
@@ -59,6 +59,28 @@
<DependentUpon>App.xaml</DependentUpon> <DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Page Include="CreateDocumentWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="CreateDocumentWindow.xaml.cs">
<DependentUpon>CreateDocumentWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="CreateDocumentWindowViewModel.cs" />
<Compile Include="DialogService.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindowViewModel.cs" />
<Compile Include="MvvmInfrastructure.cs" />
<Compile Include="PsvDataService.cs" />
<Compile Include="PsvModels.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
@@ -87,4 +109,4 @@
<None Include="App.config" /> <None Include="App.config" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

9
up_EkzmkEdit_ta.sql Normal file
View File

@@ -0,0 +1,9 @@
-- =============================================
-- Author: ta
-- Create date:
-- DatabaseModel: Metr7
-- Description: Изменение события МК
-- Use:
--
-- Changes:
-- 18.05.2021 Сафонов А.Е. DATAMODEL70-93 Ссылка на эталон

246
up_EkzmkEdit_ta_full.sql Normal file
View File

@@ -0,0 +1,246 @@
-- =============================================
-- Author: ta
-- Create date:
-- DatabaseModel: Metr7
-- Description: Изменение события МК
-- Use:
--
-- Changes:
-- 18.05.2021 Сафонов А.Е. DATAMODEL70-93 Ссылка на эталон перенесена из EKZMKDH в EKZMK. Отформатирован код.
-- 12.05.2021 Сафонов А.Е. DATAMODEL70-165 Исправления для ролей
-- 27.04.2021 Сафонов А.Е. DATAMODEL70-93 Добавляется ссылка на эталон в доп.сведения события МК, отформатирован код
-- 16.04.2021 Седаков А.В. DATAMODEL70-145 Если для редактируемого события МК нет записи о дополнительных сведениях, добавить её, используя вызов процедуры на добавление записи дополнительных сведений для @IDEKZMK.
-- 29.12.2020 Сафонов А.Е. Процедура обернута в транзакцию
-- 23.12.2020 Седаков А.В. ASUMS70-376. После изменения события МК выполняется добавление Методик МК по изменяемому событию МК.
-- Перед изменением события МК удаляются записи из таблицы EKZMKND по изменяемому событию МК.
-- 07.12.2020 Сафонов А.Е. Добавлена проверка прав доступа
-- 13.10.2020 Седаков А.В. ASUMS70-209. Из таблицы EKZMK удалено поле MKPRV и добавлены поля IDSPVDSBMK, PRCHNPGDN.
-- 04.09.2020 Седаков А.В. ASUMS70-209. Добавлено новое поле MKPRV из таблицы EKZMK.
-- 18.03.2020 Седаков А.В. DATAMODEL70-28. Добавлены 2 новых поля из таблицы EKZMK: DPZNmp, HRTCmp.
-- 13.03.2020 Седаков А.В. Изменение типа данных для полей NNZVPV, NNNKL и соответствующих входных параметров с INT на NVARCHAR(30).
-- 05.02.2020 Сафонов А.Е. ELMETRO-5 Добавлены входные параметры GUID-ов, добавление выходного параметра GUIDEKZMK
-- 03.02.2020 Седаков А.В. DATAMODEL70-28. Добавлены новые поля из таблицы EKZMK.
-- =============================================
CREATE PROCEDURE dbo.up_EkzmkEdit_ta
@idekzmk int = NULL -- 1
,@idekz int = NULL -- 2
,@idspmu int = NULL -- 3
,@idgrsi int -- 4
,@idksprl int -- 5
,@idspvdmk int -- 6
,@idspvdmc int -- 7
,@idfrpd int = NULL -- 8
,@idspmpob int -- 9
,@idprsn int = NULL -- 10
,@idspkmmk int -- 11
,@idspvdkl int -- 12
,@idprsnvd int -- 13
,@nnzvpv nvarchar(30) -- 14
,@shfkl varchar(20) -- 15
,@nnnkl nvarchar(30) -- 16
,@prmk int -- 17
,@dtmkfk datetime -- 18
,@dtmkpl datetime -- 19
,@dtprm datetime -- 20
,@dtvdm datetime -- 21
,@gdn bit -- 22
,@pzmc int -- 23
,@stmk money -- 24
,@stmkdp money -- 25
,@ncsrmk money -- 26
,@idprsnsd int = NULL -- 27
,@idprsnpr int = NULL -- 28
,@idprsnvy int = NULL -- 29
,@idspssmp int = NULL -- 30
,@idsptsmp int = NULL -- id технического состояния в момент приёмки
,@dsekzmk nvarchar(300) = NULL
,@dtotm datetime = NULL
,@dtvzm datetime = NULL
,@idprsnotm int = NULL
,@idprsnvzm int = NULL
,@nrvrmndmp decimal(6, 2) = NULL
,@nrvrmmp decimal(6, 2) = NULL
,@dtzvpv datetime = NULL
,@vrmkfk decimal(6, 2) = NULL
,@idksp int = NULL
,@dpznmp nvarchar(50) = NULL
,@hrtcmp nvarchar(40) = NULL
,@idspvdsbmk int = NULL
,@prchnpgdn nvarchar(1024) = NULL
,@idekzetl int = NULL
,@guidekzmk uniqueidentifier = NULL -- guid события мк
,@guidekz uniqueidentifier = NULL -- guid экземляра си
,@guidspmu uniqueidentifier = NULL -- guid справочника места установки
,@guidfrpd uniqueidentifier = NULL -- guid повер/калиб орг-ции
,@guidprsnisp uniqueidentifier = NULL -- guid персоны поверителя
,@guidprsnvd uniqueidentifier = NULL -- guid персоны получателя
,@guidprsnsd uniqueidentifier = NULL -- guid персоны сдавшего
,@guidprsnpr uniqueidentifier = NULL -- guid персоны принявшего
,@guidprsnvy uniqueidentifier = NULL -- guid персоны выдавшего
AS
BEGIN TRY
set dateformat dmy
set nocount on
BEGIN TRANSACTION
if LEN(@shfkl) = 0
set @shfkl = NULL
if @guidekzmk is NULL
select
@guidekzmk = guidekzmk
,@idspssmp = COALESCE(@idspssmp, idspssmp)
,@idsptsmp = COALESCE(@idsptsmp, idsptsmp)
from ekzmk
where idekzmk = @idekzmk
else if @idekzmk is NULL
select
@idekzmk = idekzmk
,@idspssmp = COALESCE(@idspssmp, idspssmp)
,@idsptsmp = COALESCE(@idsptsmp, idsptsmp)
from ekzmk
where guidekzmk = @guidekzmk
if @guidekz is NULL
select @guidekz = guidekz
from ekz
where idekz = @idekz
else if @idekz is NULL
select @idekz = idekz
from ekz
where guidekz = @guidekz
if @idspmu is NULL and @guidspmu is not NULL
select @idspmu = idspmu
from spmu
where guidspmu = @guidspmu
if @idfrpd is NULL and @guidfrpd is not NULL
select @idfrpd = idfrpd
from frpd
where CAST(frpdguid as uniqueidentifier) = @guidfrpd
if @idprsn is NULL and @guidprsnisp is not NULL
select @idprsn = idprsn
from prsn
where CAST(guidprsn as uniqueidentifier) = @guidprsnisp
if @idprsnvd is NULL and @guidprsnvd is not NULL
select @idprsnvd = idprsn
from prsn
where CAST(guidprsn as uniqueidentifier) = @guidprsnvd
if @idprsnsd is NULL and @guidprsnsd is not NULL
select @idprsnsd = idprsn
from prsn
where CAST(guidprsn as uniqueidentifier) = @guidprsnsd
if @idprsnpr is NULL and @guidprsnpr is not NULL
select @idprsnpr = idprsn
from prsn
where CAST(guidprsn as uniqueidentifier) = @guidprsnpr
if @idprsnvy is NULL and @guidprsnvy is not NULL
select @idprsnvy = idprsn
from prsn
where CAST(guidprsn as uniqueidentifier) = @guidprsnvy
declare @idekz_old int, @idgrsi_old int, @idspvdmk_old int
select @idekz_old = idekz, @idgrsi_old = idgrsi, @idspvdmk_old = idspvdmk
from ekzmk
where idekzmk = @idekzmk
if (@idekz_old <> @idekz) or
(ISNULL(@idgrsi_old, 0) <> ISNULL(@idgrsi, 0)) or
(ISNULL(@idspvdmk_old, 0) <> ISNULL(@idspvdmk, 0))
delete from ekzmknd
where idekzmk = @idekzmk
update ekzmk
set idekz = @idekz -- 2
,idspmu = @idspmu -- 3
,idgrsi = @idgrsi -- 4
,idksprl = @idksprl -- 5
,idspvdmk = @idspvdmk -- 6
,idspvdmc = @idspvdmc -- 7
,idfrpd = @idfrpd -- 8
,idspmpob = @idspmpob -- 9
,idprsn = @idprsn -- 10
,idspkmmk = @idspkmmk -- 11
,idspvdkl = @idspvdkl -- 12
,idprsnvd = @idprsnvd -- 13
,nnzvpv = @nnzvpv -- 14
,shfkl = @shfkl -- 15
,nnnkl = @nnnkl -- 16
,prmk = @prmk -- 17
,dtmkfk = @dtmkfk -- 18
,dtmkpl = @dtmkpl -- 19
,dtprm = @dtprm -- 20
,dtvdm = @dtvdm -- 21
,gdn = @gdn -- 22
,pzmc = @pzmc -- 23
,stmk = @stmk -- 24
,stmkdp = @stmkdp -- 25
,ncsrmk = @ncsrmk -- 26
,idprsnsd = @idprsnsd -- 27
,idprsnpr = @idprsnpr -- 28
,idprsnvy = @idprsnvy -- 29
,idspssmp = @idspssmp -- не менять поля если указан null
,idsptsmp = @idsptsmp -- не менять поля если указан null
,dsekzmk = @dsekzmk
,dtotm = @dtotm
,dtvzm = @dtvzm
,idprsnotm = @idprsnotm
,idprsnvzm = @idprsnvzm
,nrvrmndmp = @nrvrmndmp
,nrvrmmp = @nrvrmmp
,dtzvpv = @dtzvpv
,vrmkfk = @vrmkfk
,idksp = @idksp
,dpznmp = @dpznmp
,hrtcmp = @hrtcmp
,idspvdsbmk = @idspvdsbmk
,prchnpgdn = @prchnpgdn
,guidekzmk = @guidekzmk
,idekzetl = @idekzetl
where idekzmk = @idekzmk -- 1
-- проверка прав доступа после изменения объекта
exec dbo.EKZMK_CheckPermissions @idekzmk, null, 'U'
select
@@ROWCOUNT
-- Добавление Методик МК по событию МК.
insert into ekzmknd(idekzmk, idnd)
select distinct ekzmk.idekzmk, ekzndvdmk.idnd
from ekzmk
join ekzndvdmk on ekzmk.idekz = ekzndvdmk.idekz and
ISNULL(ekzmk.idgrsi, 0) = ISNULL(ekzndvdmk.idgrsi, 0) and
ISNULL(ekzmk.idspvdmk, 0) = ISNULL(ekzndvdmk.idspvdmk , 0)
left join ekzmknd on ekzmk.idekzmk = ekzmknd.idekzmk and ekzndvdmk.idnd = ekzmknd.idnd
where ekzmknd.idekzmknd is NULL and ekzmk.idekzmk = @idekzmk
-- Если для редактируемого события МК нет записи о дополнительных сведениях, добавить её, используя вызов процедуры на добавление записи дополнительных сведений для @IDEKZMK.
if (not exists(select 1 from ekzmkdh where idekzmk = @idekzmk))
exec dbo.EKZMKDH_Insert @idekzmk
if @@TRANCOUNT > 0
COMMIT
END TRY
BEGIN CATCH
declare @ErrorMessage nvarchar(400);
declare @ErrorSeverity int;
declare @ErrorState int;
select @ErrorMessage = ERROR_MESSAGE();
select @ErrorSeverity = ERROR_SEVERITY();
select @ErrorState = ERROR_STATE();
if @@TRANCOUNT > 0
ROLLBACK
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH

9
up_ds_EkzmkSelect.sql Normal file
View File

@@ -0,0 +1,9 @@
-- =============================================
-- Author:
-- Create date:
-- DatabaseModel: Metr7
-- Description:
-- Use:
-- Changes:
-- 20.05.2021 Сафонов А.Е. DATAMODEL70-136 Исправлена ошибка с пересечением. Отформатирован код
--

303
up_ds_EkzmkSelect_full.sql Normal file
View File

@@ -0,0 +1,303 @@
-- =============================================
-- Author:
-- Create date:
-- DatabaseModel: Metr7
-- Description:
-- Use:
-- Changes:
-- 20.05.2021 Сафонов А.Е. DATAMODEL70-136 Исправлена ошибка с пересечением. Отформатирован код
-- 12.05.2021 Седаков А.В. DATAMODEL70-155 Отказ от физического удаления записей в экземплярах СИ.
-- 13.10.2020 Седаков А.В. ASUMS70-209. Из таблицы EKZMK удалено поле MKPRV и добавлены поля IDSPVDSBMK, PRCHNPGDN.
-- 04.09.2020 Седаков А.В. ASUMS70-209. Добавлено новое поле MKPRV из таблицы EKZMK.
-- 18.03.2020 Седаков А.В. DATAMODEL70-28. Добавлены 2 новых поля из таблицы EKZMK: DPZNmp, HRTCmp.
-- 13.02.2020 Сафонов А.Е. ELMETRO-5 Добавлен GUID организации,
-- убрана "звездочка" при выборке из uf_vw_FRPD_ms() и uf_vw_SPMU_ms()
-- 03.02.2020 Седаков А.В. DATAMODEL70-28. Добавлены новые поля из таблицы EKZMK.
-- =============================================
CREATE PROCEDURE dbo.up_ds_EkzmkSelect
@fltr varchar(MAX) = '',
@vbr varchar(MAX) = '',
@prm varchar(MAX) = '',
@nmid varchar(200) = '',
@nnid int = 0,
@per varchar(2) = '0', --"0" - нет пересечений, "1" - пересечение,
--"-1" - НЕпересечение, "2" - заполнить таблицу пересечения.
@idspvdd varchar(20) = '0'
WITH EXECUTE AS 'metr6'
AS
BEGIN
set dateformat dmy
set nocount on
declare @systemUser varchar(100)
execute as caller
select @systemUser = CAST(SYSTEM_USER AS nvarchar(MAX))
revert
declare @s varchar(MAX)
declare @select varchar(MAX)
if @per = '2' -- при заполнении данных для пересечения идентификатор в фильтре не учитывается
begin
set @nmid = ''
set @nnid = 0
end
set @fltr = dbo.uf_GetSelectFltr_dk(@fltr, @vbr, @prm, @nmid, @nnid)
set @s = '
IF OBJECT_ID(N''#TempFRPD'', N''U'') IS NOT NULL
DROP TABLE #TempFRPD;
CREATE TABLE #TempFRPD
(
IDFRPD int PRIMARY KEY NOT NULL,
IDFRPDR int,
NMFRPD varchar(80) collate Cyrillic_General_CI_AS,
LEVEL int,
KDFRPDLC varchar(20) collate Cyrillic_General_CI_AS,
PATH VARCHAR(8000) collate Cyrillic_General_CI_AS,
GUIDFRPD UNIQUEIDENTIFIER
);
CREATE NONCLUSTERED INDEX RIndex ON #TempFRPD (IDFRPDR)
INSERT INTO #TempFRPD SELECT IDFRPD, IDFRPDR, NMFRPD, LEVEL, KDFRPDLC, PATH, GUIDFRPD FROM uf_vw_FRPD_ms();
IF OBJECT_ID (N''#TempSPMU'', N''U'') IS NOT NULL
DROP TABLE #TempSPMU;
CREATE TABLE #TempSPMU
(
nmmu varchar(50) collate Cyrillic_General_CI_AS,
IDSPMU int PRIMARY KEY NOT NULL,
IDSPMUR int,
LEVEL int,
PATH VARCHAR(8000) collate Cyrillic_General_CI_AS,
mu1 varchar(50) collate Cyrillic_General_CI_AS,
mu2 varchar(50) collate Cyrillic_General_CI_AS,
mu3 varchar(50) collate Cyrillic_General_CI_AS,
mu4 varchar(50) collate Cyrillic_General_CI_AS
);
CREATE NONCLUSTERED INDEX RIndex ON #TempSPMU (IDSPMUR)
INSERT INTO #TempSPMU SELECT nmmu, IDSPMU, IDSPMUR, LEVEL, PATH, mu1, mu2, mu3, mu4 FROM uf_vw_SPMU_ms();
IF OBJECT_ID (N''#TempEkzmkShfkl'', N''U'') IS NOT NULL
DROP TABLE #TempEkzmkShfkl;
CREATE TABLE #TempEkzmkShfkl
(
IDEKZMK int,
NNNKL nvarchar(30),
SHFKL varchar(30) collate Cyrillic_General_CI_AS,
DTPREVMK datetime
);
insert into #TempEkzmkShfkl(idekzmk, SHFKL, NNNKL, DTPREVMK)
select IDEKZMK, SHFKL, NNNKL, DTMKFK from (
select ekzmk.IDEKZMK, e2.SHFKL, e2.NNNKL, e2.dtmkfk,
ROW_NUMBER() over (partition by ekzmk.idekzmk order by e2.dtmkfk desc) nn
from EKZMK
left join EKZMK e2 on ekzmk.IDEKZ = e2.IDEKZ and e2.GDN = 1 and e2.DTMKFK < ekzmk.dtmkfk
) s
where nn = 1;
IF OBJECT_ID (N''#TempEkzmkNNDMS'', N''U'') IS NOT NULL
DROP TABLE #TempEkzmkNNDMS;
CREATE TABLE #TempEkzmkNNDMS
(
IDEKZMK int,
NNDMS varchar(30) collate Cyrillic_General_CI_AS,
dtd datetime,
nmvdd varchar(50) collate Cyrillic_General_CI_AS ,
nmfrd varchar(50) collate Cyrillic_General_CI_AS,
PTTXDMS varchar(max) collate Cyrillic_General_CI_AS
);
insert into #TempEkzmkNNDMS(idekzmk, NNDMS, dtd, nmvdd, nmfrd, PTTXDMS)
select idod, nnd, dtd, nmvdd, nmfrd, PTTXDMS from (
select IDOD, NND, dtd, nmvdd, nmfrd, pttxdms,
ROW_NUMBER() over (partition by idod order by dtd desc) nn
from DMS
join VDODVDD vdd on vdd.IDVDODVDD = dms.IDVDODVDD
join FRDMS on frdms.IDFRDMS = dms.IDFRDMS
join SPVDD on spvdd.IDSPVDD = frdms.IDSPVDD
where IDSPVDOD = 2 and spvdd.IDSPVDD in (2,6,8)
) s
where nn = 1;
'
set @s = @s + '
SELECT DISTINCT
SPOI.KDOI,
SPNMTP.NMTP,
SPKT.NMKT,
SPKI.NMKI,
TIPS.TP,
TPRZ.DPZN,
TPRZ.HRTC,
EKZ.IDEKZ,
EKZ.NNZV,
EKZ.NNIN,
EKZ.KLSIPR,
SPSS.NMSS,
SPTS.NMTS,
VL.NMFRPD AS FRPDVL,
MKF.NMFRPD AS FRPDMK,
VL.PATH AS VL_PATH,
MKF.PATH AS MKF_PATH,
VD.PRFIO AS PRSNVD,
sD.PRFIO AS PRSNSD,
pr.PRFIO AS PRSNPR,
Vy.PRFIO AS PRSNVY,
ssmp.NMSS as NMSSMP,
tsmp.NMTS as NMTSMP,
GRSI.NMGRSI,
GRSI.KDGRSI,
KSPRL.KDKSPRL,
SPVDMK.NMVDMK,
EKZMK.PZMC,
SPMPOB.NMMPOB,
PRSN.PRFIO,
SPKMMK.KMMK,
EKZMK.NNZVPV,
SPVDKL.NMVDKL,
EKZMK.NNNKL,
EKZMK.DTMKFK,
EKZMK.DTMKPL,
EKZMK.DTPRM,
EKZMK.DTVDM,
EKZMK.GDN,
EKZMK.STMK,
EKZMK.STMKDP,
EKZMK.NCSRMK,
EKZMK.PRMK,
EKZMK.SHFKL,
SPVDMC.NMVDMC,
MU.MU1 ''MU1'',
MU.MU2 ''MU2'',
MU.MU3 ''MU3'',
MU.MU4 ''MU4'',
MU.PATH,
DTMAXM,
MU.IDSPMU,
EKZMK.IDEKZMK,
EKZMK.IDGRSI,
EKZMK.IDKSPRL,
EKZMK.IDSPVDMK,
EKZMK.IDSPVDMC,
EKZMK.IDFRPD,
EKZMK.IDSPMPOB,
EKZMK.IDPRSN,
EKZMK.IDSPKMMK,
EKZMK.IDEKZRM,
EKZMK.IDSPVDKL,
EKZ.IDSPKT,
EKZ.IDTPRZ,
EKZ.IDSPSS,
EKZ.IDSPTS,
EKZ.IDFRPDV,
EKZMK.IDPRSNVD,
TPRZ.IDTIPS,
ekzmk.idprsnsd,
ekzmk.idprsnpr,
ekzmk.idprsnvy,
ekzmk.idsptsmp,
ekzmk.idspssmp ,
FRPDRK.FULLNAME,
FRPDRK.ADRES,
FRDSPV.FIORKMS,
FRDSPV.DLRKMS,
nnd.nmvdd,
nnd.nmfrd,
nnd.nndms,
nnd.dtd,
nnd.pttxdms,
EKZMK.DSEKZMK,
EKZMK.DTOTM,
EKZMK.DTVZM,
EKZMK.IDPRSNOTM,
EKZMK.IDPRSNVZM,
EKZMK.NRVRMNDmp,
EKZMK.NRVRMmp,
EKZMK.DTZVPV,
EKZMK.VRMKFK,
EKZMK.IDKSP,
EKZMK.DPZNmp,
EKZMK.HRTCmp,
EKZMK.IDSPVDSBMK,
SPVDSBMK.NMVDSBMK,
EKZMK.PRCHNPGDN
FROM EKZMK
INNER JOIN EKZ ON EKZMK.IDEKZ=EKZ.IDEKZ and ISNULL(EKZ.IsDeleted, 0) = 0
LEFT JOIN GRSI ON EKZMK.IDGRSI=GRSI.IDGRSI
LEFT JOIN SPVDMC ON EKZMK.IDSPVDMC=SPVDMC.IDSPVDMC
LEFT JOIN KSPRL ON EKZMK.IDKSPRL=KSPRL.IDKSPRL
INNER JOIN SPVDMK ON EKZMK.IDSPVDMK=SPVDMK.IDSPVDMK
LEFT JOIN SPMPOB ON EKZMK.IDSPMPOB=SPMPOB.IDSPMPOB
LEFT JOIN PRSN ON EKZMK.IDPRSN=PRSN.IDPRSN
LEFT JOIN SPKMMK ON EKZMK.IDSPKMMK=SPKMMK.IDSPKMMK
LEFT JOIN SPVDKL ON EKZMK.IDSPVDKL=SPVDKL.IDSPVDKL
LEFT JOIN #TempSPMU MU ON MU.IDSPMU=EKZMK.IDSPMU
INNER JOIN #TempFRPD MKF ON EKZMK.IDFRPD=MKF.IDFRPD
LEFT JOIN #TempFRPD VL ON EKZ.IDFRPDV=VL.IDFRPD
LEFT JOIN PRSN VD ON EKZMK.IDPRSNVD=VD.IDPRSN
LEFT JOIN SPKT ON EKZ.IDSPKT=SPKT.IDSPKT
LEFT JOIN SPSS ON EKZ.IDSPSS=SPSS.IDSPSS
LEFT JOIN SPTS ON EKZ.IDSPTS=SPTS.IDSPTS
LEFT JOIN EKZRM ON EKZ.IDEKZ=EKZRM.IDEKZ
INNER JOIN TPRZ ON EKZ.IDTPRZ=TPRZ.IDTPRZ
INNER JOIN TIPS ON TIPS.IDTIPS=TPRZ.IDTIPS
INNER JOIN SPNMTP ON TIPS.IDSPNMTP=SPNMTP.IDSPNMTP
LEFT JOIN SPKI ON TIPS.IDSPKI=SPKI.IDSPKI
INNER JOIN SPOI ON TIPS.IDSPOI=SPOI.IDSPOI
LEFT JOIN PRSN sd ON EKZMK.IDPRSNsd=sd.IDPRSN
LEFT JOIN PRSN pr ON EKZMK.IDPRSNpr=pr.IDPRSN
LEFT JOIN PRSN vy ON EKZMK.IDPRSNvy=vy.IDPRSN
LEFT JOIN SPSS ssmp ON EKZmk.IDSPSSmp=ssmp.IDSPSS
LEFT JOIN SPTS tsmp ON EKZmk.IDSPTSmp=tsmp.IDSPTS
LEFT JOIN FRPDRK on FRPDRK.IDFRPD = EKZMK.IDFRPD
LEFT JOIN FRDSPV on FRDSPV.IDFRPD = EKZMK.IDFRPD
LEFT JOIN #TempEkzmkShfkl pk on pk.idekzmk = ekzmk.idekzmk
LEFT join #TempEkzmkNNDMS nnd on nnd.idekzmk = ekzmk.idekzmk
LEFT JOIN SPVDSBMK ON EKZMK.IDSPVDSBMK=SPVDSBMK.IDSPVDSBMK
where '
set @select = @select + @fltr
if @per = '1'
set @fltr = @fltr +
' and ekz.idekz in (select idekz from PS_TempFltrEkz where suser = ''' + @systemuser + ''') '
if @per = '-1'
set @fltr = @fltr +
' and ekz.idekz not in (select idekz from PS_TempFltrEkz where suser = ''' + @systemuser + ''') '
set @s = @s + @fltr
set @s = @s + '
IF OBJECT_ID(N''#TempFRPD'', N''U'') IS NOT NULL
DROP TABLE #TempFRPD;
IF OBJECT_ID (N''#TempSPMU'', N''U'') IS NOT NULL
DROP TABLE #TempSPMU;'
if @per = '2'
set @s = @select
exec (@s)
END