edit
This commit is contained in:
@@ -46,6 +46,8 @@
|
||||
Click="TypeSizeDirectoryMenuItem_Click" />
|
||||
<MenuItem Header="Экземпляры"
|
||||
Click="EkzDirectoryMenuItem_Click" />
|
||||
<MenuItem Header="Планирование"
|
||||
Click="PlanningMenuItem_Click" />
|
||||
<MenuItem Header="Отчеты"
|
||||
Click="VerificationReportsMenuItem_Click" />
|
||||
</Menu>
|
||||
|
||||
@@ -100,6 +100,13 @@ namespace XLAB
|
||||
window.ShowDialog();
|
||||
}
|
||||
|
||||
private void PlanningMenuItem_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = new PlanningWindow();
|
||||
window.Owner = this;
|
||||
window.ShowDialog();
|
||||
}
|
||||
|
||||
private void SpoiDirectoryMenuItem_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = new SpoiDirectoryWindow();
|
||||
|
||||
70
XLAB/PlanningDialogService.cs
Normal file
70
XLAB/PlanningDialogService.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
internal interface IPlanningDialogService
|
||||
{
|
||||
PlanningEditResult ShowPlanningEditDialog(PlanningEditSeed seed, bool isNew, IReadOnlyList<PlanningInstrumentOption> instruments, PlanningService service);
|
||||
|
||||
EkzDirectoryItem ShowEkzEditDialog(EkzDirectoryItem seed, bool isNew, IReadOnlyList<EkzDirectoryItem> existingItems, EkzDirectoryService service);
|
||||
|
||||
bool Confirm(string message);
|
||||
|
||||
void ShowError(string message);
|
||||
|
||||
void ShowInfo(string message);
|
||||
|
||||
void ShowWarning(string message);
|
||||
}
|
||||
|
||||
internal sealed class PlanningDialogService : IPlanningDialogService
|
||||
{
|
||||
private readonly Window _owner;
|
||||
|
||||
public PlanningDialogService(Window owner)
|
||||
{
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
public bool Confirm(string message)
|
||||
{
|
||||
return MessageBox.Show(_owner, message, "ПСВ", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes;
|
||||
}
|
||||
|
||||
public EkzDirectoryItem ShowEkzEditDialog(EkzDirectoryItem seed, bool isNew, IReadOnlyList<EkzDirectoryItem> existingItems, EkzDirectoryService service)
|
||||
{
|
||||
var viewModel = new EkzEditWindowViewModel(seed, isNew, existingItems, service);
|
||||
var window = new EkzEditWindow(viewModel);
|
||||
window.Owner = _owner;
|
||||
|
||||
var result = window.ShowDialog();
|
||||
return result.HasValue && result.Value ? viewModel.ToResult() : null;
|
||||
}
|
||||
|
||||
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 PlanningEditResult ShowPlanningEditDialog(PlanningEditSeed seed, bool isNew, IReadOnlyList<PlanningInstrumentOption> instruments, PlanningService service)
|
||||
{
|
||||
var viewModel = new PlanningEditWindowViewModel(seed, isNew, instruments, service);
|
||||
var window = new PlanningEditWindow(viewModel);
|
||||
window.Owner = _owner;
|
||||
|
||||
var result = window.ShowDialog();
|
||||
return result.HasValue && result.Value ? viewModel.ToResult() : null;
|
||||
}
|
||||
|
||||
public void ShowWarning(string message)
|
||||
{
|
||||
MessageBox.Show(_owner, message, "ПСВ", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
111
XLAB/PlanningEditWindow.xaml
Normal file
111
XLAB/PlanningEditWindow.xaml
Normal file
@@ -0,0 +1,111 @@
|
||||
<Window x:Class="XLAB.PlanningEditWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="{Binding Title}"
|
||||
Height="360"
|
||||
Width="980"
|
||||
MinHeight="360"
|
||||
MinWidth="860"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Grid Margin="16">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="220" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,12,8"
|
||||
VerticalAlignment="Center"
|
||||
Text="Прибор (EKZ)" />
|
||||
<ComboBox Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,8"
|
||||
ItemsSource="{Binding InstrumentItems}"
|
||||
SelectedValue="{Binding SelectedInstrumentId}"
|
||||
SelectedValuePath="Id"
|
||||
DisplayMemberPath="DisplayName"
|
||||
IsTextSearchEnabled="True" />
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,12,8"
|
||||
VerticalAlignment="Center"
|
||||
Text="Период (TPRMCP)" />
|
||||
<ComboBox Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,8"
|
||||
ItemsSource="{Binding TemplateItems}"
|
||||
SelectedValue="{Binding SelectedTemplateId}"
|
||||
SelectedValuePath="Id"
|
||||
DisplayMemberPath="DisplayName"
|
||||
IsTextSearchEnabled="True" />
|
||||
|
||||
<TextBlock Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,12,8"
|
||||
VerticalAlignment="Center"
|
||||
Text="Плановая дата" />
|
||||
<DatePicker Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,8"
|
||||
HorizontalAlignment="Left"
|
||||
SelectedDate="{Binding PlannedOn, Mode=TwoWay}"
|
||||
SelectedDateFormat="Short" />
|
||||
|
||||
<TextBlock Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,12,8"
|
||||
VerticalAlignment="Top"
|
||||
Text="Выбранный прибор" />
|
||||
<TextBlock Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,8"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding SelectedInstrumentDescription}" />
|
||||
|
||||
<TextBlock Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="0,0,12,0"
|
||||
VerticalAlignment="Top"
|
||||
Text="Пояснение" />
|
||||
<TextBlock Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Foreground="DimGray"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding TemplateWarningMessage}" />
|
||||
</Grid>
|
||||
|
||||
<DockPanel Grid.Row="1"
|
||||
Margin="0,12,0,0">
|
||||
<TextBlock DockPanel.Dock="Left"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="Firebrick"
|
||||
Text="{Binding ValidationMessage}" />
|
||||
<StackPanel DockPanel.Dock="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button Width="100"
|
||||
Margin="0,0,8,0"
|
||||
IsDefault="True"
|
||||
Command="{Binding ConfirmCommand}"
|
||||
Content="Сохранить" />
|
||||
<Button Width="90"
|
||||
Command="{Binding CancelCommand}"
|
||||
Content="Отмена" />
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
20
XLAB/PlanningEditWindow.xaml.cs
Normal file
20
XLAB/PlanningEditWindow.xaml.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
public partial class PlanningEditWindow : Window
|
||||
{
|
||||
internal PlanningEditWindow(PlanningEditWindowViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
viewModel.CloseRequested += ViewModelOnCloseRequested;
|
||||
}
|
||||
|
||||
private void ViewModelOnCloseRequested(object sender, bool? dialogResult)
|
||||
{
|
||||
DialogResult = dialogResult;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
250
XLAB/PlanningEditWindowViewModel.cs
Normal file
250
XLAB/PlanningEditWindowViewModel.cs
Normal file
@@ -0,0 +1,250 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
internal sealed class PlanningEditWindowViewModel : ObservableObject
|
||||
{
|
||||
private readonly IReadOnlyList<PlanningInstrumentOption> _instrumentItems;
|
||||
private readonly bool _isNew;
|
||||
private readonly int? _seedTemplateId;
|
||||
private readonly PlanningService _service;
|
||||
private int _selectedInstrumentId;
|
||||
private int? _selectedTemplateId;
|
||||
private IReadOnlyList<PlanningTemplateOption> _templateItems;
|
||||
private DateTime? _plannedOn;
|
||||
private string _validationMessage;
|
||||
|
||||
public PlanningEditWindowViewModel(PlanningEditSeed seed, bool isNew, IReadOnlyList<PlanningInstrumentOption> instruments, PlanningService service)
|
||||
{
|
||||
if (seed == null)
|
||||
{
|
||||
throw new ArgumentNullException("seed");
|
||||
}
|
||||
|
||||
_instrumentItems = instruments ?? Array.Empty<PlanningInstrumentOption>();
|
||||
_service = service ?? throw new ArgumentNullException("service");
|
||||
_isNew = isNew;
|
||||
_seedTemplateId = seed.TemplateId;
|
||||
|
||||
PlanId = seed.PlanId;
|
||||
TargetYear = seed.TargetYear;
|
||||
InstrumentItems = _instrumentItems
|
||||
.OrderBy(delegate(PlanningInstrumentOption item) { return item.DisplayName; }, StringComparer.CurrentCultureIgnoreCase)
|
||||
.ToList();
|
||||
TemplateItems = Array.Empty<PlanningTemplateOption>();
|
||||
PlannedOn = seed.PlannedOn;
|
||||
|
||||
ConfirmCommand = new RelayCommand(Confirm);
|
||||
CancelCommand = new RelayCommand(Cancel);
|
||||
|
||||
if (seed.InstrumentId > 0)
|
||||
{
|
||||
SelectedInstrumentId = seed.InstrumentId;
|
||||
}
|
||||
else if (InstrumentItems.Count > 0)
|
||||
{
|
||||
SelectedInstrumentId = InstrumentItems[0].Id;
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<bool?> CloseRequested;
|
||||
|
||||
public ICommand CancelCommand { get; private set; }
|
||||
|
||||
public ICommand ConfirmCommand { get; private set; }
|
||||
|
||||
public IReadOnlyList<PlanningInstrumentOption> InstrumentItems { get; private set; }
|
||||
|
||||
public int? PlanId { get; private set; }
|
||||
|
||||
public DateTime? PlannedOn
|
||||
{
|
||||
get { return _plannedOn; }
|
||||
set { SetProperty(ref _plannedOn, value); }
|
||||
}
|
||||
|
||||
public int SelectedInstrumentId
|
||||
{
|
||||
get { return _selectedInstrumentId; }
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedInstrumentId, value))
|
||||
{
|
||||
LoadTemplates();
|
||||
OnPropertyChanged("SelectedInstrumentDescription");
|
||||
OnPropertyChanged("TemplateWarningMessage");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PlanningInstrumentOption SelectedInstrument
|
||||
{
|
||||
get { return InstrumentItems.FirstOrDefault(delegate(PlanningInstrumentOption item) { return item.Id == SelectedInstrumentId; }); }
|
||||
}
|
||||
|
||||
public string SelectedInstrumentDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
return SelectedInstrument == null ? string.Empty : SelectedInstrument.DisplayName;
|
||||
}
|
||||
}
|
||||
|
||||
public int? SelectedTemplateId
|
||||
{
|
||||
get { return _selectedTemplateId; }
|
||||
set { SetProperty(ref _selectedTemplateId, value); }
|
||||
}
|
||||
|
||||
public IReadOnlyList<PlanningTemplateOption> TemplateItems
|
||||
{
|
||||
get { return _templateItems; }
|
||||
private set
|
||||
{
|
||||
_templateItems = value ?? Array.Empty<PlanningTemplateOption>();
|
||||
OnPropertyChanged("TemplateItems");
|
||||
OnPropertyChanged("SelectedTemplateDescription");
|
||||
}
|
||||
}
|
||||
|
||||
public string SelectedTemplateDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
var selected = TemplateItems.FirstOrDefault(delegate(PlanningTemplateOption item) { return item.Id == SelectedTemplateId; });
|
||||
return selected == null ? string.Empty : selected.DisplayName;
|
||||
}
|
||||
}
|
||||
|
||||
public string TemplateWarningMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SelectedInstrument == null || TemplateItems.Count > 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return "Для выбранного прибора в TPRMCP не найден период. Расчет можно показать, но запись в EKZMCP сохранить нельзя.";
|
||||
}
|
||||
}
|
||||
|
||||
public int TargetYear { get; private set; }
|
||||
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isNew || !PlanId.HasValue
|
||||
? string.Format("Планирование на {0} год", TargetYear)
|
||||
: string.Format("Редактирование плана {0}", TargetYear);
|
||||
}
|
||||
}
|
||||
|
||||
public string ValidationMessage
|
||||
{
|
||||
get { return _validationMessage; }
|
||||
private set { SetProperty(ref _validationMessage, value); }
|
||||
}
|
||||
|
||||
public PlanningEditResult ToResult()
|
||||
{
|
||||
if (!PlannedOn.HasValue || !SelectedTemplateId.HasValue)
|
||||
{
|
||||
throw new InvalidOperationException("Результат плановой записи недоступен без даты и периода.");
|
||||
}
|
||||
|
||||
return new PlanningEditResult
|
||||
{
|
||||
PlanId = PlanId,
|
||||
InstrumentId = SelectedInstrumentId,
|
||||
TemplateId = SelectedTemplateId.Value,
|
||||
PlannedOn = PlannedOn.Value.Date
|
||||
};
|
||||
}
|
||||
|
||||
private void Cancel(object parameter)
|
||||
{
|
||||
RaiseCloseRequested(false);
|
||||
}
|
||||
|
||||
private void Confirm(object parameter)
|
||||
{
|
||||
if (SelectedInstrument == null)
|
||||
{
|
||||
ValidationMessage = "Выберите прибор.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (TemplateItems.Count == 0)
|
||||
{
|
||||
ValidationMessage = "Для выбранного прибора отсутствует период TPRMCP. Сохранить запись в EKZMCP нельзя.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SelectedTemplateId.HasValue || TemplateItems.All(delegate(PlanningTemplateOption item) { return item.Id != SelectedTemplateId.Value; }))
|
||||
{
|
||||
ValidationMessage = "Выберите период из TPRMCP.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PlannedOn.HasValue)
|
||||
{
|
||||
ValidationMessage = "Укажите плановую дату.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlannedOn.Value.Year != TargetYear)
|
||||
{
|
||||
ValidationMessage = string.Format("Плановая дата должна относиться к {0} году.", TargetYear);
|
||||
return;
|
||||
}
|
||||
|
||||
ValidationMessage = string.Empty;
|
||||
RaiseCloseRequested(true);
|
||||
}
|
||||
|
||||
private void LoadTemplates()
|
||||
{
|
||||
var instrument = SelectedInstrument;
|
||||
if (instrument == null)
|
||||
{
|
||||
TemplateItems = Array.Empty<PlanningTemplateOption>();
|
||||
SelectedTemplateId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var templates = _service.LoadTemplateOptions(instrument.TypeSizeId)
|
||||
.OrderBy(delegate(PlanningTemplateOption item) { return item.PeriodMonths; })
|
||||
.ThenBy(delegate(PlanningTemplateOption item) { return item.DisplayName; }, StringComparer.CurrentCultureIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
TemplateItems = templates;
|
||||
|
||||
if (_seedTemplateId.HasValue && templates.Any(delegate(PlanningTemplateOption item) { return item.Id == _seedTemplateId.Value; }))
|
||||
{
|
||||
SelectedTemplateId = _seedTemplateId.Value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (SelectedTemplateId.HasValue && templates.Any(delegate(PlanningTemplateOption item) { return item.Id == SelectedTemplateId.Value; }))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SelectedTemplateId = templates.Count > 0 ? (int?)templates[0].Id : null;
|
||||
}
|
||||
|
||||
private void RaiseCloseRequested(bool? dialogResult)
|
||||
{
|
||||
var handler = CloseRequested;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, dialogResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
157
XLAB/PlanningModels.cs
Normal file
157
XLAB/PlanningModels.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
public sealed class PlanningItem
|
||||
{
|
||||
public int InstrumentId { get; set; }
|
||||
|
||||
public int TypeSizeId { get; set; }
|
||||
|
||||
public int OwnerOrganizationId { get; set; }
|
||||
|
||||
public string OwnerOrganizationName { get; set; }
|
||||
|
||||
public string MeasurementAreaName { get; set; }
|
||||
|
||||
public string InstrumentName { get; set; }
|
||||
|
||||
public string TypeName { get; set; }
|
||||
|
||||
public string RangeText { get; set; }
|
||||
|
||||
public string RegistryNumber { get; set; }
|
||||
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
public string InventoryNumber { get; set; }
|
||||
|
||||
public int? PlanId { get; set; }
|
||||
|
||||
public int? EffectiveTemplateId { get; set; }
|
||||
|
||||
public int? PeriodMonths { get; set; }
|
||||
|
||||
public DateTime? LastVerificationOn { get; set; }
|
||||
|
||||
public DateTime? PlannedOn { get; set; }
|
||||
|
||||
public bool IsExplicitPlan { get; set; }
|
||||
|
||||
public string PlanSource { get; set; }
|
||||
|
||||
public string PeriodSource { get; set; }
|
||||
|
||||
public bool CanPersistPlan
|
||||
{
|
||||
get { return PlanId.HasValue || EffectiveTemplateId.HasValue; }
|
||||
}
|
||||
|
||||
public string PeriodDisplay
|
||||
{
|
||||
get { return PeriodMonths.HasValue ? string.Format("{0} мес.", PeriodMonths.Value) : string.Empty; }
|
||||
}
|
||||
|
||||
public string RecordKindText
|
||||
{
|
||||
get { return IsExplicitPlan ? "EKZMCP" : "Расчет"; }
|
||||
}
|
||||
|
||||
public string PersistenceText
|
||||
{
|
||||
get { return CanPersistPlan ? string.Empty : "Только расчет"; }
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PlanningInstrumentOption
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int TypeSizeId { get; set; }
|
||||
|
||||
public int OwnerOrganizationId { get; set; }
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return DisplayName ?? string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PlanningTemplateOption
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int TypeSizeId { get; set; }
|
||||
|
||||
public int? CycleId { get; set; }
|
||||
|
||||
public string CycleName { get; set; }
|
||||
|
||||
public int? GroupId { get; set; }
|
||||
|
||||
public string GroupName { get; set; }
|
||||
|
||||
public int PeriodMonths { get; set; }
|
||||
|
||||
public string Comment { get; set; }
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get
|
||||
{
|
||||
var parts = new System.Collections.Generic.List<string>
|
||||
{
|
||||
string.Format("{0} мес.", PeriodMonths)
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(CycleName))
|
||||
{
|
||||
parts.Add(CycleName.Trim());
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(GroupName))
|
||||
{
|
||||
parts.Add(GroupName.Trim());
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Comment))
|
||||
{
|
||||
parts.Add(Comment.Trim());
|
||||
}
|
||||
|
||||
return string.Join(" / ", parts.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return DisplayName;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PlanningEditSeed
|
||||
{
|
||||
public int TargetYear { get; set; }
|
||||
|
||||
public int? PlanId { get; set; }
|
||||
|
||||
public int InstrumentId { get; set; }
|
||||
|
||||
public int? TemplateId { get; set; }
|
||||
|
||||
public DateTime? PlannedOn { get; set; }
|
||||
}
|
||||
|
||||
internal sealed class PlanningEditResult
|
||||
{
|
||||
public int? PlanId { get; set; }
|
||||
|
||||
public int InstrumentId { get; set; }
|
||||
|
||||
public int TemplateId { get; set; }
|
||||
|
||||
public DateTime PlannedOn { get; set; }
|
||||
}
|
||||
}
|
||||
394
XLAB/PlanningService.cs
Normal file
394
XLAB/PlanningService.cs
Normal file
@@ -0,0 +1,394 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
internal sealed class PlanningService
|
||||
{
|
||||
public int AddPlanItem(PlanningEditResult item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new InvalidOperationException("Не переданы данные плановой записи.");
|
||||
}
|
||||
|
||||
const string sql = @"
|
||||
INSERT INTO dbo.EKZMCP
|
||||
(
|
||||
IDEKZ,
|
||||
IDTPRMCP,
|
||||
DTMKPLO,
|
||||
PZMCO,
|
||||
IDSPVDMK
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
@InstrumentId,
|
||||
@TemplateId,
|
||||
@PlannedOn,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
SELECT CAST(SCOPE_IDENTITY() AS int);";
|
||||
|
||||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
connection.Open();
|
||||
EnsurePlanIsUnique(connection, item.InstrumentId, item.TemplateId, null);
|
||||
|
||||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||||
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = item.InstrumentId;
|
||||
command.Parameters.Add("@TemplateId", SqlDbType.Int).Value = item.TemplateId;
|
||||
command.Parameters.Add("@PlannedOn", SqlDbType.DateTime).Value = item.PlannedOn.Date;
|
||||
|
||||
try
|
||||
{
|
||||
return Convert.ToInt32(command.ExecuteScalar());
|
||||
}
|
||||
catch (SqlException ex) when (ReferenceDirectorySqlHelpers.IsDuplicateViolation(ex, "XAK1EKZMCP"))
|
||||
{
|
||||
throw CreatePlanDuplicateException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DeletePlanItem(int id)
|
||||
{
|
||||
if (id <= 0)
|
||||
{
|
||||
throw new InvalidOperationException("Не выбрана запись EKZMCP для удаления.");
|
||||
}
|
||||
|
||||
const string sql = @"
|
||||
DELETE FROM dbo.EKZMCP
|
||||
WHERE IDEKZMCP = @Id;
|
||||
|
||||
SELECT @@ROWCOUNT;";
|
||||
|
||||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
connection.Open();
|
||||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||||
command.Parameters.Add("@Id", SqlDbType.Int).Value = id;
|
||||
|
||||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Запись EKZMCP для удаления не найдена.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<DirectoryLookupItem> LoadOwnerItems()
|
||||
{
|
||||
return ReferenceDirectorySqlHelpers.LoadLookupItems(@"
|
||||
SELECT
|
||||
fr.IDFRPD AS Id,
|
||||
fr.NMFRPD AS Name
|
||||
FROM dbo.FRPD fr
|
||||
WHERE NULLIF(LTRIM(RTRIM(fr.NMFRPD)), '') IS NOT NULL
|
||||
ORDER BY fr.NMFRPD, fr.IDFRPD;");
|
||||
}
|
||||
|
||||
public IReadOnlyList<PlanningItem> LoadPlanItems(int year)
|
||||
{
|
||||
if (year < 2000 || year > 2100)
|
||||
{
|
||||
throw new InvalidOperationException("Год планирования должен быть в диапазоне 2000-2100.");
|
||||
}
|
||||
|
||||
const string sql = @"
|
||||
SELECT
|
||||
z.IDEKZ AS InstrumentId,
|
||||
z.IDTPRZ AS TypeSizeId,
|
||||
z.IDFRPDV AS OwnerOrganizationId,
|
||||
ownerOrg.NMFRPD AS OwnerOrganizationName,
|
||||
areas.NMOI AS MeasurementAreaName,
|
||||
names.NMTP AS InstrumentName,
|
||||
tips.TP AS TypeName,
|
||||
tprz.DPZN AS RangeText,
|
||||
CONVERT(nvarchar(50), tprz.NNGSRS) AS RegistryNumber,
|
||||
z.NNZV AS SerialNumber,
|
||||
z.NNIN AS InventoryNumber,
|
||||
lastMk.LastVerificationOn,
|
||||
selectedPlan.IDEKZMCP AS PlanId,
|
||||
CASE
|
||||
WHEN selectedPlan.IDEKZMCP IS NOT NULL THEN selectedPlan.IDTPRMCP
|
||||
ELSE COALESCE(periodByInstrument.IDTPRMCP, periodByType.IDTPRMCP)
|
||||
END AS EffectiveTemplateId,
|
||||
CASE
|
||||
WHEN selectedPlan.IDEKZMCP IS NOT NULL THEN selectedPlan.PRMK
|
||||
ELSE COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR)
|
||||
END AS PeriodMonths,
|
||||
CASE
|
||||
WHEN selectedPlan.IDEKZMCP IS NOT NULL THEN selectedPlan.DTMKPLO
|
||||
ELSE DATEADD(month, COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR), lastMk.LastVerificationOn)
|
||||
END AS PlannedOn,
|
||||
CASE
|
||||
WHEN selectedPlan.IDEKZMCP IS NOT NULL THEN CAST(1 AS bit)
|
||||
ELSE CAST(0 AS bit)
|
||||
END AS IsExplicitPlan,
|
||||
CASE
|
||||
WHEN selectedPlan.IDEKZMCP IS NOT NULL THEN N'План из EKZMCP'
|
||||
WHEN periodByInstrument.IDTPRMCP IS NOT NULL THEN N'Расчет по TPRMCP экземпляра'
|
||||
WHEN periodByType.IDTPRMCP IS NOT NULL THEN N'Расчет по TPRMCP типоразмера'
|
||||
WHEN tips.PRMKGR IS NOT NULL THEN N'Расчет по TIPS.PRMKGR'
|
||||
ELSE N''
|
||||
END AS PlanSource,
|
||||
CASE
|
||||
WHEN selectedPlan.IDEKZMCP IS NOT NULL THEN N'EKZMCP / TPRMCP'
|
||||
WHEN periodByInstrument.IDTPRMCP IS NOT NULL THEN N'TPRMCP экземпляра'
|
||||
WHEN periodByType.IDTPRMCP IS NOT NULL THEN N'TPRMCP типоразмера'
|
||||
WHEN tips.PRMKGR IS NOT NULL THEN N'TIPS.PRMKGR'
|
||||
ELSE N''
|
||||
END AS PeriodSource
|
||||
FROM dbo.EKZ z
|
||||
JOIN dbo.TPRZ tprz ON tprz.IDTPRZ = z.IDTPRZ
|
||||
JOIN dbo.TIPS tips ON tips.IDTIPS = tprz.IDTIPS
|
||||
JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||||
JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||||
JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
COALESCE(m.DTMKFK, m.DTVDM, m.DTPRM) AS LastVerificationOn
|
||||
FROM dbo.EKZMK m
|
||||
WHERE m.IDEKZ = z.IDEKZ
|
||||
AND COALESCE(m.DTMKFK, m.DTVDM, m.DTPRM) IS NOT NULL
|
||||
ORDER BY COALESCE(m.DTMKFK, m.DTVDM, m.DTPRM) DESC, m.IDEKZMK DESC
|
||||
) lastMk
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
e.IDEKZMCP,
|
||||
e.IDTPRMCP,
|
||||
e.DTMKPLO,
|
||||
t.PRMK
|
||||
FROM dbo.EKZMCP e
|
||||
JOIN dbo.TPRMCP t ON t.IDTPRMCP = e.IDTPRMCP
|
||||
WHERE e.IDEKZ = z.IDEKZ
|
||||
AND e.DTMKPLO >= @YearStart
|
||||
AND e.DTMKPLO < @YearEnd
|
||||
ORDER BY e.DTMKPLO, e.IDEKZMCP DESC
|
||||
) selectedPlan
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
e.IDEKZMCP AS PlanId
|
||||
FROM dbo.EKZMCP e
|
||||
WHERE e.IDEKZ = z.IDEKZ
|
||||
AND e.DTMKPLO >= @YearEnd
|
||||
ORDER BY e.DTMKPLO, e.IDEKZMCP DESC
|
||||
) futurePlan
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
e.IDTPRMCP,
|
||||
t.PRMK
|
||||
FROM dbo.EKZMCP e
|
||||
JOIN dbo.TPRMCP t ON t.IDTPRMCP = e.IDTPRMCP
|
||||
WHERE e.IDEKZ = z.IDEKZ
|
||||
ORDER BY e.IDEKZMCP DESC, t.IDTPRMCP DESC
|
||||
) periodByInstrument
|
||||
OUTER APPLY
|
||||
(
|
||||
SELECT TOP (1)
|
||||
t.IDTPRMCP,
|
||||
t.PRMK
|
||||
FROM dbo.TPRMCP t
|
||||
WHERE t.IDTPRZ = z.IDTPRZ
|
||||
ORDER BY t.IDTPRMCP DESC
|
||||
) periodByType
|
||||
WHERE ISNULL(z.IsDeleted, 0) = 0
|
||||
AND
|
||||
(
|
||||
selectedPlan.IDEKZMCP IS NOT NULL
|
||||
OR
|
||||
(
|
||||
futurePlan.PlanId IS NULL
|
||||
AND lastMk.LastVerificationOn IS NOT NULL
|
||||
AND COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR) IS NOT NULL
|
||||
AND DATEADD(month, COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR), lastMk.LastVerificationOn) >= @YearStart
|
||||
AND DATEADD(month, COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR), lastMk.LastVerificationOn) < @YearEnd
|
||||
)
|
||||
)
|
||||
ORDER BY ownerOrg.NMFRPD, areas.NMOI, names.NMTP, tips.TP, tprz.DPZN, z.NNZV, z.IDEKZ;";
|
||||
|
||||
var yearStart = new DateTime(year, 1, 1);
|
||||
var yearEnd = yearStart.AddYears(1);
|
||||
var items = new List<PlanningItem>();
|
||||
|
||||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
connection.Open();
|
||||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||||
command.Parameters.Add("@YearStart", SqlDbType.DateTime).Value = yearStart;
|
||||
command.Parameters.Add("@YearEnd", SqlDbType.DateTime).Value = yearEnd;
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
items.Add(new PlanningItem
|
||||
{
|
||||
InstrumentId = ReferenceDirectorySqlHelpers.GetInt32(reader, "InstrumentId"),
|
||||
TypeSizeId = ReferenceDirectorySqlHelpers.GetInt32(reader, "TypeSizeId"),
|
||||
OwnerOrganizationId = ReferenceDirectorySqlHelpers.GetInt32(reader, "OwnerOrganizationId"),
|
||||
OwnerOrganizationName = ReferenceDirectorySqlHelpers.GetString(reader, "OwnerOrganizationName"),
|
||||
MeasurementAreaName = ReferenceDirectorySqlHelpers.GetString(reader, "MeasurementAreaName"),
|
||||
InstrumentName = ReferenceDirectorySqlHelpers.GetString(reader, "InstrumentName"),
|
||||
TypeName = ReferenceDirectorySqlHelpers.GetString(reader, "TypeName"),
|
||||
RangeText = ReferenceDirectorySqlHelpers.GetString(reader, "RangeText"),
|
||||
RegistryNumber = ReferenceDirectorySqlHelpers.GetString(reader, "RegistryNumber"),
|
||||
SerialNumber = ReferenceDirectorySqlHelpers.GetString(reader, "SerialNumber"),
|
||||
InventoryNumber = ReferenceDirectorySqlHelpers.GetString(reader, "InventoryNumber"),
|
||||
LastVerificationOn = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "LastVerificationOn"),
|
||||
PlanId = ReferenceDirectorySqlHelpers.GetNullableInt32(reader, "PlanId"),
|
||||
EffectiveTemplateId = ReferenceDirectorySqlHelpers.GetNullableInt32(reader, "EffectiveTemplateId"),
|
||||
PeriodMonths = ReferenceDirectorySqlHelpers.GetNullableInt32(reader, "PeriodMonths"),
|
||||
PlannedOn = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "PlannedOn"),
|
||||
IsExplicitPlan = Convert.ToBoolean(reader.GetValue(reader.GetOrdinal("IsExplicitPlan"))),
|
||||
PlanSource = ReferenceDirectorySqlHelpers.GetString(reader, "PlanSource"),
|
||||
PeriodSource = ReferenceDirectorySqlHelpers.GetString(reader, "PeriodSource")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public IReadOnlyList<PlanningTemplateOption> LoadTemplateOptions(int typeSizeId)
|
||||
{
|
||||
if (typeSizeId <= 0)
|
||||
{
|
||||
return Array.Empty<PlanningTemplateOption>();
|
||||
}
|
||||
|
||||
const string sql = @"
|
||||
SELECT
|
||||
t.IDTPRMCP AS Id,
|
||||
t.IDTPRZ AS TypeSizeId,
|
||||
t.IDSPVDMC AS CycleId,
|
||||
cycle.NMVDMC AS CycleName,
|
||||
t.IDGRSI AS GroupId,
|
||||
groups.NMGRSI AS GroupName,
|
||||
t.PRMK AS PeriodMonths,
|
||||
CAST(t.KM AS nvarchar(max)) AS Comment
|
||||
FROM dbo.TPRMCP t
|
||||
LEFT JOIN dbo.SPVDMC cycle ON cycle.IDSPVDMC = t.IDSPVDMC
|
||||
LEFT JOIN dbo.GRSI groups ON groups.IDGRSI = t.IDGRSI
|
||||
WHERE t.IDTPRZ = @TypeSizeId
|
||||
ORDER BY t.PRMK, cycle.NMVDMC, groups.NMGRSI, t.IDTPRMCP;";
|
||||
|
||||
var items = new List<PlanningTemplateOption>();
|
||||
|
||||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
connection.Open();
|
||||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||||
command.Parameters.Add("@TypeSizeId", SqlDbType.Int).Value = typeSizeId;
|
||||
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
items.Add(new PlanningTemplateOption
|
||||
{
|
||||
Id = ReferenceDirectorySqlHelpers.GetInt32(reader, "Id"),
|
||||
TypeSizeId = ReferenceDirectorySqlHelpers.GetInt32(reader, "TypeSizeId"),
|
||||
CycleId = ReferenceDirectorySqlHelpers.GetNullableInt32(reader, "CycleId"),
|
||||
CycleName = ReferenceDirectorySqlHelpers.GetString(reader, "CycleName"),
|
||||
GroupId = ReferenceDirectorySqlHelpers.GetNullableInt32(reader, "GroupId"),
|
||||
GroupName = ReferenceDirectorySqlHelpers.GetString(reader, "GroupName"),
|
||||
PeriodMonths = ReferenceDirectorySqlHelpers.GetInt32(reader, "PeriodMonths"),
|
||||
Comment = ReferenceDirectorySqlHelpers.GetString(reader, "Comment")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public void UpdatePlanItem(PlanningEditResult item)
|
||||
{
|
||||
if (item == null || !item.PlanId.HasValue || item.PlanId.Value <= 0)
|
||||
{
|
||||
throw new InvalidOperationException("Не выбрана запись EKZMCP для изменения.");
|
||||
}
|
||||
|
||||
const string sql = @"
|
||||
UPDATE dbo.EKZMCP
|
||||
SET IDEKZ = @InstrumentId,
|
||||
IDTPRMCP = @TemplateId,
|
||||
DTMKPLO = @PlannedOn
|
||||
WHERE IDEKZMCP = @Id;
|
||||
|
||||
SELECT @@ROWCOUNT;";
|
||||
|
||||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
connection.Open();
|
||||
EnsurePlanIsUnique(connection, item.InstrumentId, item.TemplateId, item.PlanId.Value);
|
||||
|
||||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||||
command.Parameters.Add("@Id", SqlDbType.Int).Value = item.PlanId.Value;
|
||||
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = item.InstrumentId;
|
||||
command.Parameters.Add("@TemplateId", SqlDbType.Int).Value = item.TemplateId;
|
||||
command.Parameters.Add("@PlannedOn", SqlDbType.DateTime).Value = item.PlannedOn.Date;
|
||||
|
||||
try
|
||||
{
|
||||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Запись EKZMCP для изменения не найдена.");
|
||||
}
|
||||
}
|
||||
catch (SqlException ex) when (ReferenceDirectorySqlHelpers.IsDuplicateViolation(ex, "XAK1EKZMCP"))
|
||||
{
|
||||
throw CreatePlanDuplicateException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Exception CreatePlanDuplicateException(SqlException ex)
|
||||
{
|
||||
var suffix = ex == null || string.IsNullOrWhiteSpace(ex.Message)
|
||||
? string.Empty
|
||||
: " " + ex.Message.Trim();
|
||||
|
||||
return new InvalidOperationException("Для выбранного прибора и периода TPRMCP запись EKZMCP уже существует." + suffix, ex);
|
||||
}
|
||||
|
||||
private static void EnsurePlanIsUnique(SqlConnection connection, int instrumentId, int templateId, int? excludeId)
|
||||
{
|
||||
const string sql = @"
|
||||
SELECT TOP (1) IDEKZMCP
|
||||
FROM dbo.EKZMCP
|
||||
WHERE IDEKZ = @InstrumentId
|
||||
AND IDTPRMCP = @TemplateId
|
||||
AND (@ExcludeId IS NULL OR IDEKZMCP <> @ExcludeId);";
|
||||
|
||||
using (var command = new SqlCommand(sql, connection))
|
||||
{
|
||||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||||
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = instrumentId;
|
||||
command.Parameters.Add("@TemplateId", SqlDbType.Int).Value = templateId;
|
||||
command.Parameters.Add("@ExcludeId", SqlDbType.Int).Value = (object)excludeId ?? DBNull.Value;
|
||||
|
||||
if (command.ExecuteScalar() != null)
|
||||
{
|
||||
throw CreatePlanDuplicateException(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
161
XLAB/PlanningWindow.xaml
Normal file
161
XLAB/PlanningWindow.xaml
Normal file
@@ -0,0 +1,161 @@
|
||||
<Window x:Class="XLAB.PlanningWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Планирование"
|
||||
Height="860"
|
||||
Width="1540"
|
||||
MinHeight="720"
|
||||
MinWidth="1240"
|
||||
Loaded="Window_Loaded"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Grid Margin="12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox Grid.Row="0"
|
||||
Header="Параметры плана-графика">
|
||||
<Grid Margin="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<DockPanel Grid.Row="0">
|
||||
<StackPanel DockPanel.Dock="Right"
|
||||
Orientation="Horizontal">
|
||||
</StackPanel>
|
||||
|
||||
<WrapPanel>
|
||||
<StackPanel Margin="0,0,16,8">
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="Год" />
|
||||
<ComboBox Width="120"
|
||||
ItemsSource="{Binding YearItems}"
|
||||
SelectedItem="{Binding SelectedYear}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,16,8">
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="Организация-владелец" />
|
||||
<ComboBox Width="360"
|
||||
ItemsSource="{Binding OwnerFilterItems}"
|
||||
SelectedValue="{Binding SelectedOwnerFilterId}"
|
||||
SelectedValuePath="Id"
|
||||
DisplayMemberPath="Name"
|
||||
IsTextSearchEnabled="True" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="0,0,16,8">
|
||||
<TextBlock Margin="0,0,0,4"
|
||||
Text="Поиск" />
|
||||
<TextBox Width="360"
|
||||
Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
</DockPanel>
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Foreground="DimGray"
|
||||
Text="Явный план берётся из EKZMCP.DTMKPLO; при отсутствии записи строка рассчитывается по EKZMK и периоду поверки." />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Grid.Row="1"
|
||||
Margin="0,12,0,0"
|
||||
Header="План-график поверки">
|
||||
<DataGrid ItemsSource="{Binding PlanItems}"
|
||||
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
HeadersVisibility="Column">
|
||||
<DataGrid.ContextMenu>
|
||||
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||
<MenuItem Header="Добавить прибор"
|
||||
Command="{Binding AddInstrumentCommand}" />
|
||||
<MenuItem Header="Изменить прибор"
|
||||
Command="{Binding EditInstrumentCommand}" />
|
||||
<Separator />
|
||||
<MenuItem Header="Добавить план"
|
||||
Command="{Binding AddPlanCommand}" />
|
||||
<MenuItem Header="Изменить план"
|
||||
Command="{Binding EditPlanCommand}" />
|
||||
<MenuItem Header="Удалить план"
|
||||
Command="{Binding DeletePlanCommand}" />
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow">
|
||||
<EventSetter Event="PreviewMouseRightButtonDown"
|
||||
Handler="DataGridRow_PreviewMouseRightButtonDown" />
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="План"
|
||||
Width="95"
|
||||
Binding="{Binding PlannedOn, StringFormat=d}" />
|
||||
<DataGridTextColumn Header="Тип записи"
|
||||
Width="95"
|
||||
Binding="{Binding RecordKindText}" />
|
||||
<DataGridTextColumn Header="Источник"
|
||||
Width="210"
|
||||
Binding="{Binding PlanSource}" />
|
||||
<DataGridTextColumn Header="Основание периода"
|
||||
Width="170"
|
||||
Binding="{Binding PeriodSource}" />
|
||||
<DataGridTextColumn Header="Период"
|
||||
Width="90"
|
||||
Binding="{Binding PeriodDisplay}" />
|
||||
<DataGridTextColumn Header="Последняя поверка"
|
||||
Width="105"
|
||||
Binding="{Binding LastVerificationOn, StringFormat=d}" />
|
||||
<DataGridTextColumn Header="Организация-владелец"
|
||||
Width="210"
|
||||
Binding="{Binding OwnerOrganizationName}" />
|
||||
<DataGridTextColumn Header="Область измерений"
|
||||
Width="160"
|
||||
Binding="{Binding MeasurementAreaName}" />
|
||||
<DataGridTextColumn Header="Наименование"
|
||||
Width="210"
|
||||
Binding="{Binding InstrumentName}" />
|
||||
<DataGridTextColumn Header="Тип"
|
||||
Width="170"
|
||||
Binding="{Binding TypeName}" />
|
||||
<DataGridTextColumn Header="Диапазон"
|
||||
Width="220"
|
||||
Binding="{Binding RangeText}" />
|
||||
<DataGridTextColumn Header="№ Госреестра"
|
||||
Width="110"
|
||||
Binding="{Binding RegistryNumber}" />
|
||||
<DataGridTextColumn Header="Заводской номер"
|
||||
Width="130"
|
||||
Binding="{Binding SerialNumber}" />
|
||||
<DataGridTextColumn Header="Инвентарный номер"
|
||||
Width="130"
|
||||
Binding="{Binding InventoryNumber}" />
|
||||
<DataGridTextColumn Header="Сохранение"
|
||||
Width="110"
|
||||
Binding="{Binding PersistenceText}" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</GroupBox>
|
||||
|
||||
<TextBlock Grid.Row="2"
|
||||
Margin="0,8,0,0"
|
||||
Foreground="DimGray"
|
||||
Text="{Binding StatusText}" />
|
||||
|
||||
<StackPanel Grid.Row="3"
|
||||
Margin="0,12,0,0"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
<Button Width="90"
|
||||
IsCancel="True"
|
||||
Content="Закрыть" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
33
XLAB/PlanningWindow.xaml.cs
Normal file
33
XLAB/PlanningWindow.xaml.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
public partial class PlanningWindow : Window
|
||||
{
|
||||
private readonly PlanningWindowViewModel _viewModel;
|
||||
|
||||
public PlanningWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
_viewModel = new PlanningWindowViewModel(new PlanningService(), new EkzDirectoryService(), new PlanningDialogService(this));
|
||||
DataContext = _viewModel;
|
||||
}
|
||||
|
||||
private void DataGridRow_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var row = sender as DataGridRow;
|
||||
if (row != null)
|
||||
{
|
||||
row.IsSelected = true;
|
||||
row.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private async void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await _viewModel.InitializeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
546
XLAB/PlanningWindowViewModel.cs
Normal file
546
XLAB/PlanningWindowViewModel.cs
Normal file
@@ -0,0 +1,546 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace XLAB
|
||||
{
|
||||
internal sealed class PlanningWindowViewModel : ObservableObject
|
||||
{
|
||||
private readonly IPlanningDialogService _dialogService;
|
||||
private readonly EkzDirectoryService _ekzService;
|
||||
private readonly PlanningService _service;
|
||||
private List<EkzDirectoryItem> _ekzCache;
|
||||
private bool _isBusy;
|
||||
private List<PlanningItem> _planCache;
|
||||
private string _searchText;
|
||||
private PlanningItem _selectedItem;
|
||||
private int _selectedOwnerFilterId;
|
||||
private int _selectedYear;
|
||||
private string _statusText;
|
||||
|
||||
public PlanningWindowViewModel(PlanningService service, EkzDirectoryService ekzService, IPlanningDialogService dialogService)
|
||||
{
|
||||
_service = service;
|
||||
_ekzService = ekzService;
|
||||
_dialogService = dialogService;
|
||||
_planCache = new List<PlanningItem>();
|
||||
_ekzCache = new List<EkzDirectoryItem>();
|
||||
|
||||
PlanItems = new ObservableCollection<PlanningItem>();
|
||||
OwnerFilterItems = new ObservableCollection<DirectoryLookupItem>();
|
||||
YearItems = new ObservableCollection<int>();
|
||||
|
||||
var currentYear = DateTime.Today.Year;
|
||||
for (var year = currentYear; year <= currentYear + 5; year++)
|
||||
{
|
||||
YearItems.Add(year);
|
||||
}
|
||||
|
||||
_selectedYear = currentYear + 1;
|
||||
|
||||
OwnerFilterItems.Add(new DirectoryLookupItem { Id = 0, Name = "Все организации" });
|
||||
|
||||
AddInstrumentCommand = new RelayCommand(delegate { AddInstrumentAsync(); }, delegate { return !IsBusy; });
|
||||
EditInstrumentCommand = new RelayCommand(delegate { EditInstrumentAsync(); }, delegate { return !IsBusy && SelectedItem != null; });
|
||||
AddPlanCommand = new RelayCommand(delegate { AddPlanAsync(); }, delegate { return !IsBusy && _ekzCache.Count > 0; });
|
||||
EditPlanCommand = new RelayCommand(delegate { EditPlanAsync(); }, delegate { return !IsBusy && SelectedItem != null && SelectedItem.CanPersistPlan; });
|
||||
DeletePlanCommand = new RelayCommand(delegate { DeletePlanAsync(); }, delegate { return !IsBusy && SelectedItem != null && SelectedItem.PlanId.HasValue; });
|
||||
RefreshCommand = new RelayCommand(delegate { RefreshAsync(); }, delegate { return !IsBusy; });
|
||||
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
public ICommand AddInstrumentCommand { get; private set; }
|
||||
|
||||
public ICommand AddPlanCommand { get; private set; }
|
||||
|
||||
public ICommand DeletePlanCommand { get; private set; }
|
||||
|
||||
public ICommand EditInstrumentCommand { get; private set; }
|
||||
|
||||
public ICommand EditPlanCommand { get; private set; }
|
||||
|
||||
public bool IsBusy
|
||||
{
|
||||
get { return _isBusy; }
|
||||
private set
|
||||
{
|
||||
if (SetProperty(ref _isBusy, value))
|
||||
{
|
||||
RaiseCommandStates();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<DirectoryLookupItem> OwnerFilterItems { get; private set; }
|
||||
|
||||
public ObservableCollection<PlanningItem> PlanItems { get; private set; }
|
||||
|
||||
public ICommand RefreshCommand { get; private set; }
|
||||
|
||||
public string SearchText
|
||||
{
|
||||
get { return _searchText; }
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _searchText, value))
|
||||
{
|
||||
ApplyFilter(GetPreferredRowKey(SelectedItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PlanningItem SelectedItem
|
||||
{
|
||||
get { return _selectedItem; }
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedItem, value))
|
||||
{
|
||||
RaiseCommandStates();
|
||||
UpdateStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int SelectedOwnerFilterId
|
||||
{
|
||||
get { return _selectedOwnerFilterId; }
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedOwnerFilterId, value))
|
||||
{
|
||||
ApplyFilter(GetPreferredRowKey(SelectedItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int SelectedYear
|
||||
{
|
||||
get { return _selectedYear; }
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedYear, value) && !IsBusy)
|
||||
{
|
||||
RefreshAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string StatusText
|
||||
{
|
||||
get { return _statusText; }
|
||||
private set { SetProperty(ref _statusText, value); }
|
||||
}
|
||||
|
||||
public ObservableCollection<int> YearItems { get; private set; }
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
await ExecuteBusyOperationAsync(delegate { return RefreshCoreAsync(null); });
|
||||
}
|
||||
|
||||
private async void AddInstrumentAsync()
|
||||
{
|
||||
var result = _dialogService.ShowEkzEditDialog(new EkzDirectoryItem(), true, _ekzCache.ToList(), _ekzService);
|
||||
if (result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await RunMutationOperation(async delegate
|
||||
{
|
||||
var createdId = await Task.Run(delegate { return _ekzService.AddEkzItem(result); });
|
||||
await RefreshCoreAsync(CreatePreferredRowKey(createdId, null));
|
||||
_dialogService.ShowInfo("Запись EKZ добавлена.");
|
||||
});
|
||||
}
|
||||
|
||||
private async void AddPlanAsync()
|
||||
{
|
||||
if (_ekzCache.Count == 0)
|
||||
{
|
||||
_dialogService.ShowWarning("Список приборов EKZ пуст.");
|
||||
return;
|
||||
}
|
||||
|
||||
var seed = new PlanningEditSeed
|
||||
{
|
||||
TargetYear = SelectedYear,
|
||||
InstrumentId = SelectedItem == null ? 0 : SelectedItem.InstrumentId,
|
||||
TemplateId = SelectedItem == null ? (int?)null : SelectedItem.EffectiveTemplateId,
|
||||
PlannedOn = SelectedItem != null && SelectedItem.PlannedOn.HasValue && SelectedItem.PlannedOn.Value.Year == SelectedYear
|
||||
? SelectedItem.PlannedOn
|
||||
: (DateTime?)null
|
||||
};
|
||||
|
||||
var result = _dialogService.ShowPlanningEditDialog(seed, true, BuildInstrumentOptions(), _service);
|
||||
if (result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await RunMutationOperation(async delegate
|
||||
{
|
||||
var createdId = await Task.Run(delegate { return _service.AddPlanItem(result); });
|
||||
await RefreshCoreAsync(CreatePreferredRowKey(result.InstrumentId, createdId));
|
||||
_dialogService.ShowInfo("Плановая запись EKZMCP добавлена.");
|
||||
});
|
||||
}
|
||||
|
||||
private void ApplyFilter(string preferredKey)
|
||||
{
|
||||
var filteredItems = _planCache.Where(delegate(PlanningItem item)
|
||||
{
|
||||
return MatchesOwnerFilter(item) && MatchesSearch(item);
|
||||
}).ToList();
|
||||
|
||||
PlanItems.Clear();
|
||||
foreach (var item in filteredItems)
|
||||
{
|
||||
PlanItems.Add(item);
|
||||
}
|
||||
|
||||
SelectedItem = string.IsNullOrWhiteSpace(preferredKey)
|
||||
? PlanItems.FirstOrDefault()
|
||||
: PlanItems.FirstOrDefault(delegate(PlanningItem item) { return string.Equals(GetPreferredRowKey(item), preferredKey, StringComparison.OrdinalIgnoreCase); })
|
||||
?? PlanItems.FirstOrDefault();
|
||||
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private List<PlanningInstrumentOption> BuildInstrumentOptions()
|
||||
{
|
||||
return _ekzCache
|
||||
.Select(delegate(EkzDirectoryItem item)
|
||||
{
|
||||
var tail = string.IsNullOrWhiteSpace(item.InventoryNumber)
|
||||
? string.Empty
|
||||
: string.Format(" / инв.№ {0}", item.InventoryNumber);
|
||||
|
||||
return new PlanningInstrumentOption
|
||||
{
|
||||
Id = item.Id,
|
||||
TypeSizeId = item.TypeSizeId,
|
||||
OwnerOrganizationId = item.OwnerOrganizationId,
|
||||
DisplayName = string.Format(
|
||||
"{0} / {1} / {2} / {3} / {4} / зав.№ {5}{6}",
|
||||
item.OwnerOrganizationName,
|
||||
item.MeasurementAreaName,
|
||||
item.InstrumentName,
|
||||
item.TypeName,
|
||||
item.RangeText,
|
||||
item.SerialNumber,
|
||||
tail)
|
||||
};
|
||||
})
|
||||
.OrderBy(delegate(PlanningInstrumentOption item) { return item.DisplayName; }, StringComparer.CurrentCultureIgnoreCase)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static string CloneValue(string value)
|
||||
{
|
||||
return value == null ? string.Empty : string.Copy(value);
|
||||
}
|
||||
|
||||
private static EkzDirectoryItem CloneEkz(EkzDirectoryItem source)
|
||||
{
|
||||
return new EkzDirectoryItem
|
||||
{
|
||||
Id = source.Id,
|
||||
TypeSizeId = source.TypeSizeId,
|
||||
MeasurementAreaName = CloneValue(source.MeasurementAreaName),
|
||||
InstrumentName = CloneValue(source.InstrumentName),
|
||||
TypeName = CloneValue(source.TypeName),
|
||||
RangeText = CloneValue(source.RangeText),
|
||||
AccuracyText = CloneValue(source.AccuracyText),
|
||||
RegistryNumber = CloneValue(source.RegistryNumber),
|
||||
OwnerOrganizationId = source.OwnerOrganizationId,
|
||||
OwnerOrganizationName = CloneValue(source.OwnerOrganizationName),
|
||||
SerialNumber = CloneValue(source.SerialNumber),
|
||||
InventoryNumber = CloneValue(source.InventoryNumber),
|
||||
Notes = CloneValue(source.Notes)
|
||||
};
|
||||
}
|
||||
|
||||
private static string CreatePreferredRowKey(int instrumentId, int? planId)
|
||||
{
|
||||
return string.Format(
|
||||
"{0}:{1}",
|
||||
instrumentId,
|
||||
planId.HasValue ? planId.Value.ToString() : "0");
|
||||
}
|
||||
|
||||
private async void DeletePlanAsync()
|
||||
{
|
||||
if (SelectedItem == null || !SelectedItem.PlanId.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var selected = SelectedItem;
|
||||
var plannedDateText = selected.PlannedOn.HasValue
|
||||
? selected.PlannedOn.Value.ToString("d")
|
||||
: "без даты";
|
||||
var question = string.Format(
|
||||
"Удалить плановую запись EKZMCP для прибора \"{0}\" с датой {1}?",
|
||||
selected.SerialNumber,
|
||||
plannedDateText);
|
||||
|
||||
if (!_dialogService.Confirm(question))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await RunMutationOperation(async delegate
|
||||
{
|
||||
await Task.Run(delegate { _service.DeletePlanItem(selected.PlanId.Value); });
|
||||
await RefreshCoreAsync(CreatePreferredRowKey(selected.InstrumentId, null));
|
||||
_dialogService.ShowInfo("Плановая запись EKZMCP удалена.");
|
||||
});
|
||||
}
|
||||
|
||||
private async void EditInstrumentAsync()
|
||||
{
|
||||
if (SelectedItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var current = _ekzCache.FirstOrDefault(delegate(EkzDirectoryItem item) { return item.Id == SelectedItem.InstrumentId; });
|
||||
if (current == null)
|
||||
{
|
||||
_dialogService.ShowWarning("Выбранный прибор не найден в EKZ.");
|
||||
return;
|
||||
}
|
||||
|
||||
var result = _dialogService.ShowEkzEditDialog(CloneEkz(current), false, _ekzCache.ToList(), _ekzService);
|
||||
if (result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var preferredKey = GetPreferredRowKey(SelectedItem);
|
||||
|
||||
await RunMutationOperation(async delegate
|
||||
{
|
||||
await Task.Run(delegate { _ekzService.UpdateEkzItem(result); });
|
||||
await RefreshCoreAsync(preferredKey);
|
||||
_dialogService.ShowInfo("Запись EKZ обновлена.");
|
||||
});
|
||||
}
|
||||
|
||||
private async void EditPlanAsync()
|
||||
{
|
||||
if (SelectedItem == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SelectedItem.CanPersistPlan)
|
||||
{
|
||||
_dialogService.ShowWarning("Для выбранного прибора найден только расчетный период без TPRMCP. Сохранить запись в EKZMCP нельзя.");
|
||||
return;
|
||||
}
|
||||
|
||||
var seed = new PlanningEditSeed
|
||||
{
|
||||
TargetYear = SelectedYear,
|
||||
PlanId = SelectedItem.PlanId,
|
||||
InstrumentId = SelectedItem.InstrumentId,
|
||||
TemplateId = SelectedItem.EffectiveTemplateId,
|
||||
PlannedOn = SelectedItem.PlannedOn
|
||||
};
|
||||
|
||||
var isNew = !SelectedItem.PlanId.HasValue;
|
||||
var result = _dialogService.ShowPlanningEditDialog(seed, isNew, BuildInstrumentOptions(), _service);
|
||||
if (result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await RunMutationOperation(async delegate
|
||||
{
|
||||
if (result.PlanId.HasValue)
|
||||
{
|
||||
await Task.Run(delegate { _service.UpdatePlanItem(result); });
|
||||
await RefreshCoreAsync(CreatePreferredRowKey(result.InstrumentId, result.PlanId));
|
||||
_dialogService.ShowInfo("Плановая запись EKZMCP обновлена.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var createdId = await Task.Run(delegate { return _service.AddPlanItem(result); });
|
||||
await RefreshCoreAsync(CreatePreferredRowKey(result.InstrumentId, createdId));
|
||||
_dialogService.ShowInfo("Плановая запись EKZMCP добавлена.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task ExecuteBusyOperationAsync(Func<Task> operation)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsBusy = true;
|
||||
await operation();
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
_dialogService.ShowWarning(ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_dialogService.ShowError(ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
private string[] GetSearchTokens()
|
||||
{
|
||||
return (SearchText ?? string.Empty)
|
||||
.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(delegate(string token) { return token.Trim().ToUpperInvariant(); })
|
||||
.Where(delegate(string token) { return token.Length > 0; })
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static string GetPreferredRowKey(PlanningItem item)
|
||||
{
|
||||
return item == null ? null : CreatePreferredRowKey(item.InstrumentId, item.PlanId);
|
||||
}
|
||||
|
||||
private bool MatchesOwnerFilter(PlanningItem item)
|
||||
{
|
||||
return SelectedOwnerFilterId <= 0
|
||||
|| (item != null && item.OwnerOrganizationId == SelectedOwnerFilterId);
|
||||
}
|
||||
|
||||
private bool MatchesSearch(PlanningItem item)
|
||||
{
|
||||
var tokens = GetSearchTokens();
|
||||
if (tokens.Length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var haystack = string.Join(
|
||||
" ",
|
||||
new[]
|
||||
{
|
||||
item == null ? null : item.OwnerOrganizationName,
|
||||
item == null ? null : item.MeasurementAreaName,
|
||||
item == null ? null : item.InstrumentName,
|
||||
item == null ? null : item.TypeName,
|
||||
item == null ? null : item.RangeText,
|
||||
item == null ? null : item.RegistryNumber,
|
||||
item == null ? null : item.SerialNumber,
|
||||
item == null ? null : item.InventoryNumber,
|
||||
item == null ? null : item.PlanSource,
|
||||
item == null ? null : item.PeriodSource
|
||||
})
|
||||
.ToUpperInvariant();
|
||||
|
||||
return tokens.All(delegate(string token) { return haystack.Contains(token); });
|
||||
}
|
||||
|
||||
private void RaiseCommandStates()
|
||||
{
|
||||
var addInstrumentCommand = AddInstrumentCommand as RelayCommand;
|
||||
if (addInstrumentCommand != null)
|
||||
{
|
||||
addInstrumentCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
var editInstrumentCommand = EditInstrumentCommand as RelayCommand;
|
||||
if (editInstrumentCommand != null)
|
||||
{
|
||||
editInstrumentCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
var addPlanCommand = AddPlanCommand as RelayCommand;
|
||||
if (addPlanCommand != null)
|
||||
{
|
||||
addPlanCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
var editPlanCommand = EditPlanCommand as RelayCommand;
|
||||
if (editPlanCommand != null)
|
||||
{
|
||||
editPlanCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
var deletePlanCommand = DeletePlanCommand as RelayCommand;
|
||||
if (deletePlanCommand != null)
|
||||
{
|
||||
deletePlanCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
|
||||
var refreshCommand = RefreshCommand as RelayCommand;
|
||||
if (refreshCommand != null)
|
||||
{
|
||||
refreshCommand.RaiseCanExecuteChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RefreshCoreAsync(string preferredKey)
|
||||
{
|
||||
var planTask = Task.Run(delegate { return _service.LoadPlanItems(SelectedYear); });
|
||||
var ownerTask = Task.Run(delegate { return _service.LoadOwnerItems(); });
|
||||
var ekzTask = Task.Run(delegate { return _ekzService.LoadEkzItems(); });
|
||||
|
||||
await Task.WhenAll(planTask, ownerTask, ekzTask);
|
||||
|
||||
_planCache = planTask.Result.ToList();
|
||||
_ekzCache = ekzTask.Result.ToList();
|
||||
|
||||
ApplyOwnerItems(ownerTask.Result);
|
||||
ApplyFilter(preferredKey);
|
||||
}
|
||||
|
||||
private void ApplyOwnerItems(IReadOnlyList<DirectoryLookupItem> items)
|
||||
{
|
||||
OwnerFilterItems.Clear();
|
||||
OwnerFilterItems.Add(new DirectoryLookupItem { Id = 0, Name = "Все организации" });
|
||||
|
||||
foreach (var item in items ?? Array.Empty<DirectoryLookupItem>())
|
||||
{
|
||||
OwnerFilterItems.Add(item);
|
||||
}
|
||||
|
||||
if (!OwnerFilterItems.Any(delegate(DirectoryLookupItem item) { return item.Id == SelectedOwnerFilterId; }))
|
||||
{
|
||||
SelectedOwnerFilterId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private async void RefreshAsync()
|
||||
{
|
||||
await ExecuteBusyOperationAsync(delegate { return RefreshCoreAsync(GetPreferredRowKey(SelectedItem)); });
|
||||
}
|
||||
|
||||
private async Task RunMutationOperation(Func<Task> operation)
|
||||
{
|
||||
await ExecuteBusyOperationAsync(operation);
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
{
|
||||
var explicitCount = PlanItems.Count(delegate(PlanningItem item) { return item.IsExplicitPlan; });
|
||||
var calculatedCount = PlanItems.Count - explicitCount;
|
||||
var nonPersistableCount = PlanItems.Count(delegate(PlanningItem item) { return !item.CanPersistPlan; });
|
||||
|
||||
StatusText = string.Format(
|
||||
"Год: {0}. Позиций: {1}. Явных планов EKZMCP: {2}. Расчетных позиций: {3}. Без TPRMCP: {4}.",
|
||||
SelectedYear,
|
||||
PlanItems.Count,
|
||||
explicitCount,
|
||||
calculatedCount,
|
||||
nonPersistableCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,6 +112,9 @@
|
||||
</Compile>
|
||||
<Compile Include="MainWindowViewModel.cs" />
|
||||
<Compile Include="MvvmInfrastructure.cs" />
|
||||
<Compile Include="PlanningDialogService.cs" />
|
||||
<Compile Include="PlanningModels.cs" />
|
||||
<Compile Include="PlanningService.cs" />
|
||||
<Compile Include="PsvDataService.cs" />
|
||||
<Compile Include="PsvPrintService.cs" />
|
||||
<Compile Include="PsvModels.cs" />
|
||||
@@ -284,6 +287,24 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PrdspvEditWindowViewModel.cs" />
|
||||
<Page Include="PlanningEditWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="PlanningEditWindow.xaml.cs">
|
||||
<DependentUpon>PlanningEditWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PlanningEditWindowViewModel.cs" />
|
||||
<Page Include="PlanningWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="PlanningWindow.xaml.cs">
|
||||
<DependentUpon>PlanningWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PlanningWindowViewModel.cs" />
|
||||
<Page Include="TprmcpEditWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
|
||||
Reference in New Issue
Block a user