edit
This commit is contained in:
BIN
ClosePsv.docx
Normal file
BIN
ClosePsv.docx
Normal file
Binary file not shown.
BIN
OpenPsv.docx
Normal file
BIN
OpenPsv.docx
Normal file
Binary file not shown.
@@ -65,6 +65,8 @@
|
|||||||
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||||
<MenuItem Header="Добавить"
|
<MenuItem Header="Добавить"
|
||||||
Command="{Binding AddDocumentCommand}" />
|
Command="{Binding AddDocumentCommand}" />
|
||||||
|
<MenuItem Header="Распечатать"
|
||||||
|
Command="{Binding PrintDocumentCommand}" />
|
||||||
<MenuItem Header="Удалить"
|
<MenuItem Header="Удалить"
|
||||||
Command="{Binding DeleteDocumentCommand}" />
|
Command="{Binding DeleteDocumentCommand}" />
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
@@ -296,6 +298,8 @@
|
|||||||
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
|
||||||
<MenuItem Header="Клонировать поверку по зав. №..."
|
<MenuItem Header="Клонировать поверку по зав. №..."
|
||||||
Command="{Binding CloneLineVerificationCommand}" />
|
Command="{Binding CloneLineVerificationCommand}" />
|
||||||
|
<MenuItem Header="Распечатать документ о поверке"
|
||||||
|
Command="{Binding PrintVerificationDocumentCommand}" />
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Header="Годен"
|
<MenuItem Header="Годен"
|
||||||
Command="{Binding MarkLinePassedCommand}" />
|
Command="{Binding MarkLinePassedCommand}" />
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace XLAB
|
|||||||
private readonly List<PsvDocumentSummary> _draftDocuments;
|
private readonly List<PsvDocumentSummary> _draftDocuments;
|
||||||
private readonly IDialogService _dialogService;
|
private readonly IDialogService _dialogService;
|
||||||
private readonly Dictionary<string, List<PsvDocumentLine>> _pendingLinesByDocumentKey;
|
private readonly Dictionary<string, List<PsvDocumentLine>> _pendingLinesByDocumentKey;
|
||||||
|
private readonly PsvPrintService _printService;
|
||||||
private readonly PsvDataService _service;
|
private readonly PsvDataService _service;
|
||||||
private string _documentFilterText;
|
private string _documentFilterText;
|
||||||
private string _documentNumberEditor;
|
private string _documentNumberEditor;
|
||||||
@@ -33,6 +34,7 @@ namespace XLAB
|
|||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_dialogService = dialogService;
|
_dialogService = dialogService;
|
||||||
|
_printService = new PsvPrintService();
|
||||||
_draftDocuments = new List<PsvDocumentSummary>();
|
_draftDocuments = new List<PsvDocumentSummary>();
|
||||||
_pendingLinesByDocumentKey = new Dictionary<string, List<PsvDocumentLine>>(StringComparer.OrdinalIgnoreCase);
|
_pendingLinesByDocumentKey = new Dictionary<string, List<PsvDocumentLine>>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
@@ -55,6 +57,8 @@ namespace XLAB
|
|||||||
MarkLineRejectedCommand = new RelayCommand(delegate { EditLineVerificationAsync(false); }, delegate { return CanEditSelectedLineVerification(); });
|
MarkLineRejectedCommand = new RelayCommand(delegate { EditLineVerificationAsync(false); }, delegate { return CanEditSelectedLineVerification(); });
|
||||||
OpenInstrumentPickerCommand = new RelayCommand(delegate { OpenInstrumentPickerAsync(); }, delegate { return !IsBusy && SelectedDocument != null && SelectedDocument.CustomerId.HasValue; });
|
OpenInstrumentPickerCommand = new RelayCommand(delegate { OpenInstrumentPickerAsync(); }, delegate { return !IsBusy && SelectedDocument != null && SelectedDocument.CustomerId.HasValue; });
|
||||||
OpenInstrumentTypePickerCommand = new RelayCommand(delegate { OpenInstrumentTypePickerAsync(); }, delegate { return !IsBusy && SelectedDocument != null && SelectedDocument.CustomerId.HasValue; });
|
OpenInstrumentTypePickerCommand = new RelayCommand(delegate { OpenInstrumentTypePickerAsync(); }, delegate { return !IsBusy && SelectedDocument != null && SelectedDocument.CustomerId.HasValue; });
|
||||||
|
PrintDocumentCommand = new RelayCommand(delegate { PrintSelectedDocumentAsync(); }, delegate { return CanPrintSelectedDocument(); });
|
||||||
|
PrintVerificationDocumentCommand = new RelayCommand(delegate { PrintSelectedVerificationDocumentAsync(); }, delegate { return CanPrintSelectedVerificationDocument(); });
|
||||||
RefreshDocumentsCommand = new RelayCommand(delegate { RefreshDocumentsAsync(null, null); }, delegate { return !IsBusy; });
|
RefreshDocumentsCommand = new RelayCommand(delegate { RefreshDocumentsAsync(null, null); }, delegate { return !IsBusy; });
|
||||||
ResetLineVerificationCommand = new RelayCommand(delegate { ResetSelectedLineVerificationAsync(); }, delegate { return CanResetSelectedLineVerification(); });
|
ResetLineVerificationCommand = new RelayCommand(delegate { ResetSelectedLineVerificationAsync(); }, delegate { return CanResetSelectedLineVerification(); });
|
||||||
SaveDocumentHeaderCommand = new RelayCommand(delegate { SaveDocumentAsync(); }, delegate { return CanSaveDocument(); });
|
SaveDocumentHeaderCommand = new RelayCommand(delegate { SaveDocumentAsync(); }, delegate { return CanSaveDocument(); });
|
||||||
@@ -175,6 +179,10 @@ namespace XLAB
|
|||||||
|
|
||||||
public ICommand OpenInstrumentTypePickerCommand { get; private set; }
|
public ICommand OpenInstrumentTypePickerCommand { get; private set; }
|
||||||
|
|
||||||
|
public ICommand PrintDocumentCommand { get; private set; }
|
||||||
|
|
||||||
|
public ICommand PrintVerificationDocumentCommand { get; private set; }
|
||||||
|
|
||||||
public ICommand RefreshDocumentsCommand { get; private set; }
|
public ICommand RefreshDocumentsCommand { get; private set; }
|
||||||
|
|
||||||
public ICommand ResetLineVerificationCommand { get; private set; }
|
public ICommand ResetLineVerificationCommand { get; private set; }
|
||||||
@@ -328,6 +336,13 @@ namespace XLAB
|
|||||||
&& GetDeleteTargetGroups().Count > 0;
|
&& GetDeleteTargetGroups().Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CanPrintSelectedDocument()
|
||||||
|
{
|
||||||
|
return !IsBusy
|
||||||
|
&& SelectedDocument != null
|
||||||
|
&& !SelectedDocument.IsDraft;
|
||||||
|
}
|
||||||
|
|
||||||
private bool CanEditSelectedLineVerification()
|
private bool CanEditSelectedLineVerification()
|
||||||
{
|
{
|
||||||
var targetLines = GetVerificationTargetLines();
|
var targetLines = GetVerificationTargetLines();
|
||||||
@@ -341,6 +356,11 @@ namespace XLAB
|
|||||||
return !IsBusy && CanUseLineAsCloneSource(SelectedDocumentLine);
|
return !IsBusy && CanUseLineAsCloneSource(SelectedDocumentLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CanPrintSelectedVerificationDocument()
|
||||||
|
{
|
||||||
|
return !IsBusy && HasPrintableVerificationDocument(SelectedDocumentLine);
|
||||||
|
}
|
||||||
|
|
||||||
private bool CanResetSelectedLineVerification()
|
private bool CanResetSelectedLineVerification()
|
||||||
{
|
{
|
||||||
var targetLines = GetVerificationTargetLines();
|
var targetLines = GetVerificationTargetLines();
|
||||||
@@ -391,6 +411,31 @@ namespace XLAB
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool HasPrintableVerificationDocument(PsvDocumentLine line)
|
||||||
|
{
|
||||||
|
if (line == null || !line.IsPassed.HasValue)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(line.VerificationDocumentNumber))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.VerificationPerformedOn.HasValue && !line.VerificationDocumentDate.HasValue)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.IsPassed.Value && string.IsNullOrWhiteSpace(line.RejectionReason))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private List<PsvDocumentLine> GetCheckedDocumentLines()
|
private List<PsvDocumentLine> GetCheckedDocumentLines()
|
||||||
{
|
{
|
||||||
return DocumentLinesView.Cast<object>()
|
return DocumentLinesView.Cast<object>()
|
||||||
@@ -1172,6 +1217,40 @@ namespace XLAB
|
|||||||
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
|
DocumentStatusText = string.Format("Документов: {0}.", Documents.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PrintSelectedDocumentAsync()
|
||||||
|
{
|
||||||
|
if (SelectedDocument == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedDocument = SelectedDocument;
|
||||||
|
if (selectedDocument.IsDraft)
|
||||||
|
{
|
||||||
|
_dialogService.ShowWarning("Черновик нельзя распечатать. Сначала сохраните ПСВ.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(selectedDocument.DocumentNumber))
|
||||||
|
{
|
||||||
|
_dialogService.ShowWarning("Для печати не указан номер ПСВ.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunBusyOperation(async delegate
|
||||||
|
{
|
||||||
|
var persistedLines = await Task.Run(delegate { return _service.LoadDocumentLines(selectedDocument.DocumentNumber); });
|
||||||
|
var linesToPrint = MergeDocumentLinesForPrint(selectedDocument, persistedLines);
|
||||||
|
if (linesToPrint.Count == 0)
|
||||||
|
{
|
||||||
|
_dialogService.ShowWarning("В выбранном ПСВ нет строк для печати.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_printService.PrintDocument(selectedDocument, linesToPrint);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void DeleteSelectedGroupsAsync()
|
private void DeleteSelectedGroupsAsync()
|
||||||
{
|
{
|
||||||
if (SelectedDocument == null)
|
if (SelectedDocument == null)
|
||||||
@@ -1307,6 +1386,28 @@ namespace XLAB
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PrintSelectedVerificationDocumentAsync()
|
||||||
|
{
|
||||||
|
var selectedLine = SelectedDocumentLine;
|
||||||
|
if (selectedLine == null)
|
||||||
|
{
|
||||||
|
_dialogService.ShowWarning("Сначала выберите строку прибора.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HasPrintableVerificationDocument(selectedLine))
|
||||||
|
{
|
||||||
|
_dialogService.ShowWarning("Для выбранной строки не указан печатаемый документ по поверке.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunBusyOperation(delegate
|
||||||
|
{
|
||||||
|
_printService.PrintVerificationDocument(selectedLine);
|
||||||
|
return Task.FromResult(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static void UpdateDocumentSummaryFromLines(PsvDocumentSummary document, IEnumerable<PsvDocumentLine> lines)
|
private static void UpdateDocumentSummaryFromLines(PsvDocumentSummary document, IEnumerable<PsvDocumentLine> lines)
|
||||||
{
|
{
|
||||||
if (document == null)
|
if (document == null)
|
||||||
@@ -1442,6 +1543,52 @@ namespace XLAB
|
|||||||
: new List<PsvDocumentLine>();
|
: new List<PsvDocumentLine>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<PsvDocumentLine> MergeDocumentLinesForPrint(PsvDocumentSummary document, IEnumerable<PsvDocumentLine> persistedLines)
|
||||||
|
{
|
||||||
|
var mergedLines = new List<PsvDocumentLine>();
|
||||||
|
if (persistedLines != null)
|
||||||
|
{
|
||||||
|
mergedLines.AddRange(persistedLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
mergedLines.AddRange(GetPendingLines(document));
|
||||||
|
return mergedLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PsvDocumentSummary CreateSavedDocumentSummaryForPrint(PsvDocumentSummary source, DocumentEditorResult request)
|
||||||
|
{
|
||||||
|
return new PsvDocumentSummary
|
||||||
|
{
|
||||||
|
DocumentKey = source == null ? null : source.DocumentKey,
|
||||||
|
DocumentNumber = request == null ? string.Empty : request.DocumentNumber,
|
||||||
|
AcceptedOn = request == null ? (DateTime?)null : request.AcceptedOn,
|
||||||
|
IssuedOn = request == null ? (DateTime?)null : request.IssuedOn,
|
||||||
|
CustomerId = request == null ? null : request.CustomerId,
|
||||||
|
CustomerName = ResolveCustomerNameForPrint(source, request),
|
||||||
|
DepartmentName = source == null ? string.Empty : source.DepartmentName,
|
||||||
|
IsDraft = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ResolveCustomerNameForPrint(PsvDocumentSummary source, DocumentEditorResult request)
|
||||||
|
{
|
||||||
|
if (source != null && !string.IsNullOrWhiteSpace(source.CustomerName))
|
||||||
|
{
|
||||||
|
return source.CustomerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request != null && request.CustomerId.HasValue)
|
||||||
|
{
|
||||||
|
var customer = Customers.FirstOrDefault(delegate(CustomerReference item) { return item.CustomerId == request.CustomerId.Value; });
|
||||||
|
if (customer != null)
|
||||||
|
{
|
||||||
|
return customer.CustomerName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
private void InsertDraftIntoCollection(PsvDocumentSummary draft)
|
private void InsertDraftIntoCollection(PsvDocumentSummary draft)
|
||||||
{
|
{
|
||||||
var insertIndex = 0;
|
var insertIndex = 0;
|
||||||
@@ -1692,7 +1839,7 @@ namespace XLAB
|
|||||||
|
|
||||||
if (skippedWithoutTemplateCount > 0)
|
if (skippedWithoutTemplateCount > 0)
|
||||||
{
|
{
|
||||||
messages.Add(string.Format("Пропущено без шаблона EKZMK: {0}.", skippedWithoutTemplateCount));
|
messages.Add(string.Format("Пропущено без источника данных для EKZMK: {0}.", skippedWithoutTemplateCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skippedOpenDocumentCount > 0)
|
if (skippedOpenDocumentCount > 0)
|
||||||
@@ -1741,7 +1888,7 @@ namespace XLAB
|
|||||||
|
|
||||||
if (!result.TypeItem.HasTemplate)
|
if (!result.TypeItem.HasTemplate)
|
||||||
{
|
{
|
||||||
_dialogService.ShowWarning("Выбранный тип нельзя добавить: для него не найден шаблон EKZMK или период МК.");
|
_dialogService.ShowWarning("Выбранный тип нельзя добавить: для него не найден шаблон EKZMK, период из TPRMCP или регистрационный период TIPS.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1830,6 +1977,8 @@ namespace XLAB
|
|||||||
((RelayCommand)MarkLineRejectedCommand).RaiseCanExecuteChanged();
|
((RelayCommand)MarkLineRejectedCommand).RaiseCanExecuteChanged();
|
||||||
((RelayCommand)OpenInstrumentPickerCommand).RaiseCanExecuteChanged();
|
((RelayCommand)OpenInstrumentPickerCommand).RaiseCanExecuteChanged();
|
||||||
((RelayCommand)OpenInstrumentTypePickerCommand).RaiseCanExecuteChanged();
|
((RelayCommand)OpenInstrumentTypePickerCommand).RaiseCanExecuteChanged();
|
||||||
|
((RelayCommand)PrintDocumentCommand).RaiseCanExecuteChanged();
|
||||||
|
((RelayCommand)PrintVerificationDocumentCommand).RaiseCanExecuteChanged();
|
||||||
((RelayCommand)RefreshDocumentsCommand).RaiseCanExecuteChanged();
|
((RelayCommand)RefreshDocumentsCommand).RaiseCanExecuteChanged();
|
||||||
((RelayCommand)ResetLineVerificationCommand).RaiseCanExecuteChanged();
|
((RelayCommand)ResetLineVerificationCommand).RaiseCanExecuteChanged();
|
||||||
((RelayCommand)SaveDocumentHeaderCommand).RaiseCanExecuteChanged();
|
((RelayCommand)SaveDocumentHeaderCommand).RaiseCanExecuteChanged();
|
||||||
@@ -1948,6 +2097,8 @@ namespace XLAB
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var selectedDocument = SelectedDocument;
|
||||||
|
|
||||||
if (!HeaderReceivedOn.HasValue)
|
if (!HeaderReceivedOn.HasValue)
|
||||||
{
|
{
|
||||||
_dialogService.ShowWarning("Укажите дату приемки.");
|
_dialogService.ShowWarning("Укажите дату приемки.");
|
||||||
@@ -1960,20 +2111,20 @@ namespace XLAB
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SelectedDocument.IsDraft && !SelectedCustomerId.HasValue)
|
if (selectedDocument.IsDraft && !SelectedCustomerId.HasValue)
|
||||||
{
|
{
|
||||||
_dialogService.ShowWarning("Для новой ПСВ сначала выберите заказчика.");
|
_dialogService.ShowWarning("Для новой ПСВ сначала выберите заказчика.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DocumentExistsInCollections(DocumentNumberEditor.Trim(), SelectedDocument.DocumentKey)
|
if (DocumentExistsInCollections(DocumentNumberEditor.Trim(), selectedDocument.DocumentKey)
|
||||||
|| _service.DocumentNumberExists(DocumentNumberEditor.Trim(), SelectedDocument.IsDraft ? null : SelectedDocument.DocumentNumber))
|
|| _service.DocumentNumberExists(DocumentNumberEditor.Trim(), selectedDocument.IsDraft ? null : selectedDocument.DocumentNumber))
|
||||||
{
|
{
|
||||||
_dialogService.ShowWarning("ПСВ с таким номером уже существует.");
|
_dialogService.ShowWarning("ПСВ с таким номером уже существует.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pendingLines = GetPendingLines(SelectedDocument)
|
var pendingLines = GetPendingLines(selectedDocument)
|
||||||
.Where(delegate(PsvDocumentLine line)
|
.Where(delegate(PsvDocumentLine line)
|
||||||
{
|
{
|
||||||
return line != null
|
return line != null
|
||||||
@@ -1981,13 +2132,13 @@ namespace XLAB
|
|||||||
|| (line.TypeSizeId > 0 && !string.IsNullOrWhiteSpace(line.SerialNumber)));
|
|| (line.TypeSizeId > 0 && !string.IsNullOrWhiteSpace(line.SerialNumber)));
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
if (SelectedDocument.IsDraft && pendingLines.Count == 0)
|
if (selectedDocument.IsDraft && pendingLines.Count == 0)
|
||||||
{
|
{
|
||||||
_dialogService.ShowWarning("Черновик нельзя сохранить без строк EKZMK.");
|
_dialogService.ShowWarning("Черновик нельзя сохранить без строк EKZMK.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var openDocumentConflicts = FindPendingOpenDocumentConflicts(SelectedDocument, pendingLines);
|
var openDocumentConflicts = FindPendingOpenDocumentConflicts(selectedDocument, pendingLines);
|
||||||
if (openDocumentConflicts.Count > 0)
|
if (openDocumentConflicts.Count > 0)
|
||||||
{
|
{
|
||||||
_dialogService.ShowWarning(BuildOpenDocumentConflictMessage(openDocumentConflicts));
|
_dialogService.ShowWarning(BuildOpenDocumentConflictMessage(openDocumentConflicts));
|
||||||
@@ -1999,12 +2150,14 @@ namespace XLAB
|
|||||||
DocumentNumber = DocumentNumberEditor.Trim(),
|
DocumentNumber = DocumentNumberEditor.Trim(),
|
||||||
AcceptedOn = HeaderReceivedOn.Value,
|
AcceptedOn = HeaderReceivedOn.Value,
|
||||||
IssuedOn = HeaderIssuedOn,
|
IssuedOn = HeaderIssuedOn,
|
||||||
CustomerId = SelectedDocument.CustomerId ?? SelectedCustomerId
|
CustomerId = selectedDocument.CustomerId ?? SelectedCustomerId
|
||||||
};
|
};
|
||||||
|
|
||||||
var currentDocumentNumber = SelectedDocument.IsDraft ? null : SelectedDocument.DocumentNumber;
|
var currentDocumentNumber = selectedDocument.IsDraft ? null : selectedDocument.DocumentNumber;
|
||||||
var documentKey = SelectedDocument.DocumentKey;
|
var documentKey = selectedDocument.DocumentKey;
|
||||||
var wasDraft = SelectedDocument.IsDraft;
|
var wasDraft = selectedDocument.IsDraft;
|
||||||
|
var closingNow = !selectedDocument.IssuedOn.HasValue && request.IssuedOn.HasValue;
|
||||||
|
var printDocument = closingNow ? CreateSavedDocumentSummaryForPrint(selectedDocument, request) : null;
|
||||||
var result = await Task.Run(delegate { return _service.SaveDocument(currentDocumentNumber, request, pendingLines); });
|
var result = await Task.Run(delegate { return _service.SaveDocument(currentDocumentNumber, request, pendingLines); });
|
||||||
|
|
||||||
_pendingLinesByDocumentKey.Remove(documentKey);
|
_pendingLinesByDocumentKey.Remove(documentKey);
|
||||||
@@ -2013,8 +2166,6 @@ namespace XLAB
|
|||||||
_draftDocuments.RemoveAll(delegate(PsvDocumentSummary draft) { return draft.DocumentKey == documentKey; });
|
_draftDocuments.RemoveAll(delegate(PsvDocumentSummary draft) { return draft.DocumentKey == documentKey; });
|
||||||
}
|
}
|
||||||
|
|
||||||
await RefreshDocumentsCoreAsync(null, result.DocumentNumber);
|
|
||||||
|
|
||||||
var messages = new List<string>();
|
var messages = new List<string>();
|
||||||
messages.Add(string.Format("Обновлено строк EKZMK: {0}.", result.UpdatedEkzMkCount));
|
messages.Add(string.Format("Обновлено строк EKZMK: {0}.", result.UpdatedEkzMkCount));
|
||||||
messages.Add(string.Format("Добавлено строк EKZMK: {0}.", result.InsertedEkzMkCount));
|
messages.Add(string.Format("Добавлено строк EKZMK: {0}.", result.InsertedEkzMkCount));
|
||||||
@@ -2026,10 +2177,29 @@ namespace XLAB
|
|||||||
|
|
||||||
if (result.SkippedWithoutTemplateCount > 0)
|
if (result.SkippedWithoutTemplateCount > 0)
|
||||||
{
|
{
|
||||||
messages.Add(string.Format("Пропущено без шаблона EKZMK: {0}.", result.SkippedWithoutTemplateCount));
|
messages.Add(string.Format("Пропущено без источника данных для EKZMK: {0}.", result.SkippedWithoutTemplateCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
_dialogService.ShowInfo(string.Join(" ", messages.ToArray()));
|
var messageText = string.Join(" ", messages.ToArray());
|
||||||
|
if (closingNow)
|
||||||
|
{
|
||||||
|
var prompt = messageText + " ПСВ закрыта. Распечатать приемо-сдаточную ведомость?";
|
||||||
|
if (_dialogService.Confirm(prompt))
|
||||||
|
{
|
||||||
|
var printLines = await Task.Run(delegate { return _service.LoadDocumentLines(result.DocumentNumber); });
|
||||||
|
if (printDocument != null)
|
||||||
|
{
|
||||||
|
printDocument.DocumentNumber = result.DocumentNumber;
|
||||||
|
_printService.PrintDocument(printDocument, printLines.ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_dialogService.ShowInfo(messageText);
|
||||||
|
}
|
||||||
|
|
||||||
|
await RefreshDocumentsCoreAsync(null, closingNow ? null : result.DocumentNumber);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -678,7 +678,7 @@ SELECT
|
|||||||
CASE
|
CASE
|
||||||
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL
|
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL
|
||||||
OR typeTemplate.LastDocumentNumber IS NOT NULL
|
OR typeTemplate.LastDocumentNumber IS NOT NULL
|
||||||
OR COALESCE(periodByInstrument.PRMK, periodByType.PRMK) IS NOT NULL
|
OR COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR) IS NOT NULL
|
||||||
THEN CAST(1 AS bit)
|
THEN CAST(1 AS bit)
|
||||||
ELSE CAST(0 AS bit)
|
ELSE CAST(0 AS bit)
|
||||||
END AS HasTemplate,
|
END AS HasTemplate,
|
||||||
@@ -687,7 +687,8 @@ SELECT
|
|||||||
CASE
|
CASE
|
||||||
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL THEN N'История прибора'
|
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL THEN N'История прибора'
|
||||||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
|
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
|
||||||
WHEN COALESCE(periodByInstrument.PRMK, periodByType.PRMK) IS NOT NULL THEN N'Период из TPRMCP'
|
WHEN COALESCE(periodByInstrument.PRMK, periodByType.PRMK) IS NOT NULL THEN N'Период из TPRMCP'
|
||||||
|
WHEN tips.PRMKGR IS NOT NULL THEN N'Регистрационный период из TIPS'
|
||||||
ELSE N''
|
ELSE N''
|
||||||
END AS TemplateSource
|
END AS TemplateSource
|
||||||
FROM dbo.EKZ z
|
FROM dbo.EKZ z
|
||||||
@@ -791,6 +792,7 @@ SELECT
|
|||||||
CASE
|
CASE
|
||||||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL
|
WHEN typeTemplate.LastDocumentNumber IS NOT NULL
|
||||||
OR periodByType.PRMK IS NOT NULL
|
OR periodByType.PRMK IS NOT NULL
|
||||||
|
OR tips.PRMKGR IS NOT NULL
|
||||||
THEN CAST(1 AS bit)
|
THEN CAST(1 AS bit)
|
||||||
ELSE CAST(0 AS bit)
|
ELSE CAST(0 AS bit)
|
||||||
END AS HasTemplate,
|
END AS HasTemplate,
|
||||||
@@ -799,6 +801,7 @@ SELECT
|
|||||||
CASE
|
CASE
|
||||||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
|
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
|
||||||
WHEN periodByType.PRMK IS NOT NULL THEN N'Период из TPRMCP'
|
WHEN periodByType.PRMK IS NOT NULL THEN N'Период из TPRMCP'
|
||||||
|
WHEN tips.PRMKGR IS NOT NULL THEN N'Регистрационный период из TIPS'
|
||||||
ELSE N''
|
ELSE N''
|
||||||
END AS TemplateSource
|
END AS TemplateSource
|
||||||
FROM dbo.TPRZ sizeInfo
|
FROM dbo.TPRZ sizeInfo
|
||||||
@@ -2394,12 +2397,18 @@ SELECT TOP (1)
|
|||||||
COALESCE(periodByInstrument.IDSPVDMC, periodByType.IDSPVDMC) AS IDSPVDMC,
|
COALESCE(periodByInstrument.IDSPVDMC, periodByType.IDSPVDMC) AS IDSPVDMC,
|
||||||
defaultLab.DefaultIdFrpd AS IDFRPD,
|
defaultLab.DefaultIdFrpd AS IDFRPD,
|
||||||
tprz.IDSPKMMK,
|
tprz.IDSPKMMK,
|
||||||
COALESCE(periodByInstrument.PRMK, periodByType.PRMK) AS PRMK,
|
COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR) AS PRMK,
|
||||||
tprz.DPZN AS DPZNmp,
|
tprz.DPZN AS DPZNmp,
|
||||||
tprz.HRTC AS HRTCmp,
|
tprz.HRTC AS HRTCmp,
|
||||||
CAST(N'Период из TPRMCP' AS nvarchar(60)) AS SourceDescription
|
CAST(
|
||||||
|
CASE
|
||||||
|
WHEN COALESCE(periodByInstrument.PRMK, periodByType.PRMK) IS NOT NULL THEN N'Период из TPRMCP'
|
||||||
|
WHEN tips.PRMKGR IS NOT NULL THEN N'Регистрационный период из TIPS'
|
||||||
|
ELSE N''
|
||||||
|
END AS nvarchar(60)) AS SourceDescription
|
||||||
FROM dbo.EKZ z
|
FROM dbo.EKZ z
|
||||||
JOIN dbo.TPRZ tprz ON tprz.IDTPRZ = z.IDTPRZ
|
JOIN dbo.TPRZ tprz ON tprz.IDTPRZ = z.IDTPRZ
|
||||||
|
JOIN dbo.TIPS tips ON tips.IDTIPS = tprz.IDTIPS
|
||||||
CROSS JOIN DefaultLab defaultLab
|
CROSS JOIN DefaultLab defaultLab
|
||||||
OUTER APPLY
|
OUTER APPLY
|
||||||
(
|
(
|
||||||
@@ -2424,7 +2433,7 @@ OUTER APPLY
|
|||||||
) periodByType
|
) periodByType
|
||||||
WHERE z.IDEKZ = @InstrumentId
|
WHERE z.IDEKZ = @InstrumentId
|
||||||
AND defaultLab.DefaultIdFrpd IS NOT NULL
|
AND defaultLab.DefaultIdFrpd IS NOT NULL
|
||||||
AND COALESCE(periodByInstrument.PRMK, periodByType.PRMK) IS NOT NULL;";
|
AND COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR) IS NOT NULL;";
|
||||||
|
|
||||||
using (var command = new SqlCommand(sql, connection, transaction))
|
using (var command = new SqlCommand(sql, connection, transaction))
|
||||||
{
|
{
|
||||||
|
|||||||
587
XLAB/PsvPrintService.cs
Normal file
587
XLAB/PsvPrintService.cs
Normal file
@@ -0,0 +1,587 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace XLAB
|
||||||
|
{
|
||||||
|
internal sealed class PsvPrintService
|
||||||
|
{
|
||||||
|
private const int PrintDialogId = 88;
|
||||||
|
private const int WordAlertsNone = 0;
|
||||||
|
private const int WordCloseDoNotSaveChanges = 0;
|
||||||
|
|
||||||
|
public void PrintDocument(PsvDocumentSummary document, IReadOnlyList<PsvDocumentLine> lines)
|
||||||
|
{
|
||||||
|
if (document == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("document");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("lines");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines.Count == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("В выбранном ПСВ нет строк для печати.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var templateFileName = document.IssuedOn.HasValue ? "ClosePsv.docx" : "OpenPsv.docx";
|
||||||
|
PrintWordTemplate(
|
||||||
|
templateFileName,
|
||||||
|
document.DocumentNumber,
|
||||||
|
delegate(object wordDocument)
|
||||||
|
{
|
||||||
|
PopulatePsvTemplate((dynamic)wordDocument, document, lines);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrintVerificationDocument(PsvDocumentLine line)
|
||||||
|
{
|
||||||
|
if (line == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("line");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.IsPassed.HasValue)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Для печати документа о поверке не указан результат поверки.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(line.VerificationDocumentNumber))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Для печати документа о поверке не указан номер документа.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.VerificationPerformedOn.HasValue && !line.VerificationDocumentDate.HasValue)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Для печати документа о поверке не указана дата поверки.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.IsPassed.Value && string.IsNullOrWhiteSpace(line.RejectionReason))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Для печати извещения о непригодности не указана причина непригодности.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var templateFileName = line.IsPassed.Value ? "Svid.docx" : "Izv.docx";
|
||||||
|
PrintWordTemplate(
|
||||||
|
templateFileName,
|
||||||
|
line.VerificationDocumentNumber,
|
||||||
|
delegate(object wordDocument)
|
||||||
|
{
|
||||||
|
PopulateVerificationTemplate((dynamic)wordDocument, line);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PrintWordTemplate(string templateFileName, string printNumber, Action<object> populateDocument)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(templateFileName))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Не указано имя шаблона печати.", "templateFileName");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (populateDocument == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("populateDocument");
|
||||||
|
}
|
||||||
|
|
||||||
|
var templatePath = ResolveTemplatePath(templateFileName);
|
||||||
|
var workingCopyPath = CreateWorkingCopy(templatePath, printNumber);
|
||||||
|
object wordApplication = null;
|
||||||
|
object wordDocument = null;
|
||||||
|
object dialogs = null;
|
||||||
|
object printDialog = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var wordType = Type.GetTypeFromProgID("Word.Application");
|
||||||
|
if (wordType == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Microsoft Word не найден. Печать ПСВ по шаблону DOCX недоступна.");
|
||||||
|
}
|
||||||
|
|
||||||
|
wordApplication = Activator.CreateInstance(wordType);
|
||||||
|
dynamic word = wordApplication;
|
||||||
|
word.Visible = true;
|
||||||
|
word.DisplayAlerts = WordAlertsNone;
|
||||||
|
|
||||||
|
wordDocument = word.Documents.Open(
|
||||||
|
FileName: workingCopyPath,
|
||||||
|
ConfirmConversions: false,
|
||||||
|
ReadOnly: false,
|
||||||
|
AddToRecentFiles: false,
|
||||||
|
Visible: true);
|
||||||
|
|
||||||
|
populateDocument(wordDocument);
|
||||||
|
((dynamic)wordDocument).Save();
|
||||||
|
word.Activate();
|
||||||
|
((dynamic)wordDocument).Activate();
|
||||||
|
|
||||||
|
dialogs = word.Dialogs;
|
||||||
|
printDialog = ((dynamic)dialogs).Item(PrintDialogId);
|
||||||
|
((dynamic)printDialog).Show();
|
||||||
|
|
||||||
|
((dynamic)wordDocument).Close(WordCloseDoNotSaveChanges);
|
||||||
|
wordDocument = null;
|
||||||
|
|
||||||
|
word.Quit();
|
||||||
|
wordApplication = null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ReleaseComObject(printDialog);
|
||||||
|
ReleaseComObject(dialogs);
|
||||||
|
ReleaseComObject(wordDocument);
|
||||||
|
ReleaseComObject(wordApplication);
|
||||||
|
TryDeleteFile(workingCopyPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PopulatePsvTemplate(dynamic document, PsvDocumentSummary summary, IReadOnlyList<PsvDocumentLine> lines)
|
||||||
|
{
|
||||||
|
var groupedLines = BuildPrintedGroups(lines, summary.IssuedOn.HasValue);
|
||||||
|
|
||||||
|
ReplacePlaceholder(document, "number", NormalizeText(summary.DocumentNumber));
|
||||||
|
ReplacePlaceholder(document, "div", NormalizeText(summary.CustomerName));
|
||||||
|
ReplacePlaceholder(document, "date", FormatDate(summary.AcceptedOn));
|
||||||
|
ReplacePlaceholder(document, "count", lines.Count.ToString(CultureInfo.InvariantCulture));
|
||||||
|
ReplacePlaceholder(document, "person", string.Empty);
|
||||||
|
|
||||||
|
if (summary.IssuedOn.HasValue)
|
||||||
|
{
|
||||||
|
ReplacePlaceholder(document, "today", FormatDate(summary.IssuedOn));
|
||||||
|
ReplacePlaceholder(document, "good", lines.Count(delegate(PsvDocumentLine line) { return line.IsPassed == true; }).ToString(CultureInfo.InvariantCulture));
|
||||||
|
ReplacePlaceholder(document, "bad", lines.Count(delegate(PsvDocumentLine line) { return line.IsPassed == false; }).ToString(CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var dueDate = summary.AcceptedOn.HasValue
|
||||||
|
? summary.AcceptedOn.Value.AddDays(30)
|
||||||
|
: (DateTime?)null;
|
||||||
|
ReplacePlaceholder(document, "next", FormatDate(dueDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
FillTable(document, groupedLines);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PopulateVerificationTemplate(dynamic document, PsvDocumentLine line)
|
||||||
|
{
|
||||||
|
var verificationDate = ResolveVerificationDate(line);
|
||||||
|
|
||||||
|
ReplacePlaceholder(document, "number", NormalizeText(line.VerificationDocumentNumber));
|
||||||
|
ReplacePlaceholder(document, "nextpovdate", FormatDate(ResolveNextVerificationDate(line, verificationDate)));
|
||||||
|
ReplacePlaceholder(document, "name", NormalizeText(line.InstrumentName));
|
||||||
|
ReplacePlaceholder(document, "type (рег. № gr)", BuildVerificationTypeText(line));
|
||||||
|
ReplacePlaceholder(document, "serial", NormalizeText(line.SerialNumber));
|
||||||
|
ReplacePlaceholder(document, "erial", NormalizeText(line.SerialNumber));
|
||||||
|
ReplacePlaceholder(document, "method", string.Empty);
|
||||||
|
ReplacePlaceholder(document, "temp", string.Empty);
|
||||||
|
ReplacePlaceholder(document, "hum", string.Empty);
|
||||||
|
ReplacePlaceholder(document, "press", string.Empty);
|
||||||
|
ReplacePlaceholder(document, "person", NormalizeText(line.VerifierName));
|
||||||
|
ReplacePlaceholder(document, "reason", NormalizeText(line.RejectionReason));
|
||||||
|
ReplacePlaceholder(document, "date", FormatDate(verificationDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FillTable(dynamic document, IReadOnlyList<PrintedGroupRow> rowsToPrint)
|
||||||
|
{
|
||||||
|
dynamic table = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
table = document.Tables.Item(1);
|
||||||
|
|
||||||
|
for (var index = 0; index < rowsToPrint.Count; index++)
|
||||||
|
{
|
||||||
|
var rowData = rowsToPrint[index];
|
||||||
|
dynamic row = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
row = table.Rows.Add();
|
||||||
|
SetCellText(row, 1, (index + 1).ToString(CultureInfo.InvariantCulture), true);
|
||||||
|
SetCellText(row, 2, rowData.InstrumentName, false);
|
||||||
|
SetCellText(row, 3, rowData.InstrumentType, false);
|
||||||
|
SetCellText(row, 4, rowData.RangeText, false);
|
||||||
|
SetCellText(row, 5, rowData.SerialNumberText, false);
|
||||||
|
SetCellText(row, 6, rowData.GroupCount.ToString(CultureInfo.InvariantCulture), true);
|
||||||
|
SetCellText(row, 7, rowData.PassedCount > 0 ? rowData.PassedCount.ToString(CultureInfo.InvariantCulture) : string.Empty, true);
|
||||||
|
SetCellText(row, 8, rowData.FailedCount > 0 ? rowData.FailedCount.ToString(CultureInfo.InvariantCulture) : string.Empty, true);
|
||||||
|
SetCellText(row, 9, rowData.Notes, false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ReleaseComObject(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ReleaseComObject(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetCellText(dynamic row, int columnIndex, string value, bool centerAlign)
|
||||||
|
{
|
||||||
|
dynamic cell = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cell = row.Cells.Item(columnIndex);
|
||||||
|
cell.Range.Text = NormalizeText(value);
|
||||||
|
cell.Range.Bold = 0;
|
||||||
|
cell.Range.Font.Underline = 0;
|
||||||
|
cell.Range.ParagraphFormat.Alignment = centerAlign ? 1 : 0;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ReleaseComObject(cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReplacePlaceholder(dynamic document, string placeholder, string replacement)
|
||||||
|
{
|
||||||
|
dynamic range = null;
|
||||||
|
dynamic find = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
range = document.Content;
|
||||||
|
find = range.Find;
|
||||||
|
find.ClearFormatting();
|
||||||
|
find.Replacement.ClearFormatting();
|
||||||
|
find.Execute(
|
||||||
|
FindText: placeholder,
|
||||||
|
MatchCase: false,
|
||||||
|
MatchWholeWord: false,
|
||||||
|
MatchWildcards: false,
|
||||||
|
MatchSoundsLike: false,
|
||||||
|
MatchAllWordForms: false,
|
||||||
|
Forward: true,
|
||||||
|
Wrap: 1,
|
||||||
|
Format: false,
|
||||||
|
ReplaceWith: NormalizeText(replacement),
|
||||||
|
Replace: 2);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ReleaseComObject(find);
|
||||||
|
ReleaseComObject(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IReadOnlyList<PrintedGroupRow> BuildPrintedGroups(IEnumerable<PsvDocumentLine> lines, bool includeClosedNotes)
|
||||||
|
{
|
||||||
|
return (lines ?? Enumerable.Empty<PsvDocumentLine>())
|
||||||
|
.GroupBy(delegate(PsvDocumentLine line)
|
||||||
|
{
|
||||||
|
return new PrintGroupKey
|
||||||
|
{
|
||||||
|
InstrumentType = NormalizeText(line == null ? null : line.InstrumentType),
|
||||||
|
RangeText = NormalizeText(line == null ? null : line.RangeText),
|
||||||
|
RegistryNumber = NormalizeText(line == null ? null : line.RegistryNumber)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.OrderBy(delegate(IGrouping<PrintGroupKey, PsvDocumentLine> group) { return group.Key.InstrumentType; }, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ThenBy(delegate(IGrouping<PrintGroupKey, PsvDocumentLine> group) { return group.Key.RegistryNumber; }, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ThenBy(delegate(IGrouping<PrintGroupKey, PsvDocumentLine> group) { return group.Key.RangeText; }, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.Select(delegate(IGrouping<PrintGroupKey, PsvDocumentLine> group)
|
||||||
|
{
|
||||||
|
var materializedLines = group.Where(delegate(PsvDocumentLine line) { return line != null; }).ToList();
|
||||||
|
|
||||||
|
return new PrintedGroupRow
|
||||||
|
{
|
||||||
|
InstrumentName = BuildInstrumentNameText(materializedLines),
|
||||||
|
InstrumentType = group.Key.InstrumentType,
|
||||||
|
RangeText = group.Key.RangeText,
|
||||||
|
SerialNumberText = BuildSerialNumberText(materializedLines),
|
||||||
|
GroupCount = materializedLines.Count,
|
||||||
|
PassedCount = materializedLines.Count(delegate(PsvDocumentLine line) { return line.IsPassed == true; }),
|
||||||
|
FailedCount = materializedLines.Count(delegate(PsvDocumentLine line) { return line.IsPassed == false; }),
|
||||||
|
Notes = includeClosedNotes ? BuildClosedNotesText(materializedLines) : string.Empty
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildInstrumentNameText(IReadOnlyList<PsvDocumentLine> lines)
|
||||||
|
{
|
||||||
|
return string.Join("; ", lines
|
||||||
|
.Select(delegate(PsvDocumentLine line) { return NormalizeText(line.InstrumentName); })
|
||||||
|
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.OrderBy(delegate(string value) { return value; }, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildSerialNumberText(IReadOnlyList<PsvDocumentLine> lines)
|
||||||
|
{
|
||||||
|
var serialNumbers = lines
|
||||||
|
.Select(delegate(PsvDocumentLine line) { return NormalizeText(line.SerialNumber); })
|
||||||
|
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.OrderBy(delegate(string value) { return value; }, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (serialNumbers.Count == 0)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serialNumbers.Count > 3)
|
||||||
|
{
|
||||||
|
return string.Format(CultureInfo.InvariantCulture, "{0} зав. номеров", serialNumbers.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join(", ", serialNumbers.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildClosedNotesText(IReadOnlyList<PsvDocumentLine> lines)
|
||||||
|
{
|
||||||
|
var parts = new List<string>();
|
||||||
|
|
||||||
|
var verificationDocuments = lines
|
||||||
|
.Select(FormatVerificationDocument)
|
||||||
|
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.OrderBy(delegate(string value) { return value; }, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (verificationDocuments.Count > 0)
|
||||||
|
{
|
||||||
|
parts.Add("Документы: " + string.Join("; ", verificationDocuments.ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
var stickerNumbers = lines
|
||||||
|
.Select(delegate(PsvDocumentLine line) { return NormalizeText(line.StickerNumber); })
|
||||||
|
.Where(delegate(string value) { return !string.IsNullOrWhiteSpace(value); })
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.OrderBy(delegate(string value) { return value; }, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (stickerNumbers.Count > 0)
|
||||||
|
{
|
||||||
|
parts.Add("Наклейки: " + string.Join(", ", stickerNumbers.ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join(". ", parts.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatVerificationDocument(PsvDocumentLine line)
|
||||||
|
{
|
||||||
|
if (line == null)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var number = NormalizeText(line.VerificationDocumentNumber);
|
||||||
|
var date = FormatDate(line.VerificationDocumentDate);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(number))
|
||||||
|
{
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(date))
|
||||||
|
{
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Format(CultureInfo.InvariantCulture, "{0} от {1}", number, date);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildVerificationTypeText(PsvDocumentLine line)
|
||||||
|
{
|
||||||
|
if (line == null)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = NormalizeText(line.InstrumentType);
|
||||||
|
var registryNumber = NormalizeText(line.RegistryNumber);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(type))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.IsNullOrWhiteSpace(registryNumber)
|
||||||
|
? type
|
||||||
|
: string.Format(CultureInfo.InvariantCulture, "{0} (рег. № {1})", type, registryNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DateTime? ResolveVerificationDate(PsvDocumentLine line)
|
||||||
|
{
|
||||||
|
if (line == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return line.VerificationPerformedOn ?? line.VerificationDocumentDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DateTime? ResolveNextVerificationDate(PsvDocumentLine line, DateTime? verificationDate)
|
||||||
|
{
|
||||||
|
if (line == null || !line.IsPassed.HasValue || !line.IsPassed.Value)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!verificationDate.HasValue || line.PeriodMonths <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return verificationDate.Value.AddMonths(line.PeriodMonths);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveTemplatePath(string fileName)
|
||||||
|
{
|
||||||
|
var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
var candidates = new[]
|
||||||
|
{
|
||||||
|
Path.Combine(baseDirectory, fileName),
|
||||||
|
Path.GetFullPath(Path.Combine(baseDirectory, "..", "..", fileName)),
|
||||||
|
Path.GetFullPath(Path.Combine(baseDirectory, "..", "..", "..", fileName))
|
||||||
|
};
|
||||||
|
|
||||||
|
var templatePath = candidates.FirstOrDefault(File.Exists);
|
||||||
|
if (templatePath == null)
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException(string.Format("Не найден шаблон печати ПСВ: {0}.", fileName), fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return templatePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CreateWorkingCopy(string templatePath, string documentNumber)
|
||||||
|
{
|
||||||
|
var tempDirectory = Path.Combine(Path.GetTempPath(), "XLAB", "Print");
|
||||||
|
Directory.CreateDirectory(tempDirectory);
|
||||||
|
|
||||||
|
var safeDocumentNumber = string.IsNullOrWhiteSpace(documentNumber)
|
||||||
|
? "PSV"
|
||||||
|
: string.Concat(documentNumber.Where(delegate(char ch)
|
||||||
|
{
|
||||||
|
return !Path.GetInvalidFileNameChars().Contains(ch);
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(safeDocumentNumber))
|
||||||
|
{
|
||||||
|
safeDocumentNumber = "PSV";
|
||||||
|
}
|
||||||
|
|
||||||
|
var tempFileName = string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"{0}_{1:yyyyMMdd_HHmmss_fff}_{2}",
|
||||||
|
safeDocumentNumber,
|
||||||
|
DateTime.Now,
|
||||||
|
Path.GetFileName(templatePath));
|
||||||
|
|
||||||
|
var workingCopyPath = Path.Combine(tempDirectory, tempFileName);
|
||||||
|
File.Copy(templatePath, workingCopyPath, true);
|
||||||
|
return workingCopyPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatDate(DateTime? value)
|
||||||
|
{
|
||||||
|
return value.HasValue
|
||||||
|
? value.Value.ToString("dd.MM.yyyy", CultureInfo.InvariantCulture)
|
||||||
|
: string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizeText(string value)
|
||||||
|
{
|
||||||
|
return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TryDeleteFile(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(path);
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReleaseComObject(object value)
|
||||||
|
{
|
||||||
|
if (value == null || !Marshal.IsComObject(value))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Marshal.FinalReleaseComObject(value);
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class PrintedGroupRow
|
||||||
|
{
|
||||||
|
public int FailedCount { get; set; }
|
||||||
|
|
||||||
|
public int GroupCount { get; set; }
|
||||||
|
|
||||||
|
public string InstrumentName { get; set; }
|
||||||
|
|
||||||
|
public string InstrumentType { get; set; }
|
||||||
|
|
||||||
|
public string Notes { get; set; }
|
||||||
|
|
||||||
|
public int PassedCount { get; set; }
|
||||||
|
|
||||||
|
public string RangeText { get; set; }
|
||||||
|
|
||||||
|
public string SerialNumberText { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class PrintGroupKey : IEquatable<PrintGroupKey>
|
||||||
|
{
|
||||||
|
public string InstrumentType { get; set; }
|
||||||
|
|
||||||
|
public string RangeText { get; set; }
|
||||||
|
|
||||||
|
public string RegistryNumber { get; set; }
|
||||||
|
|
||||||
|
public bool Equals(PrintGroupKey other)
|
||||||
|
{
|
||||||
|
return other != null
|
||||||
|
&& string.Equals(InstrumentType ?? string.Empty, other.InstrumentType ?? string.Empty, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& string.Equals(RangeText ?? string.Empty, other.RangeText ?? string.Empty, StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& string.Equals(RegistryNumber ?? string.Empty, other.RegistryNumber ?? string.Empty, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return Equals(obj as PrintGroupKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return string.Concat(
|
||||||
|
(InstrumentType ?? string.Empty).ToUpperInvariant(), "|",
|
||||||
|
(RangeText ?? string.Empty).ToUpperInvariant(), "|",
|
||||||
|
(RegistryNumber ?? string.Empty).ToUpperInvariant())
|
||||||
|
.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,6 +92,7 @@
|
|||||||
<Compile Include="MainWindowViewModel.cs" />
|
<Compile Include="MainWindowViewModel.cs" />
|
||||||
<Compile Include="MvvmInfrastructure.cs" />
|
<Compile Include="MvvmInfrastructure.cs" />
|
||||||
<Compile Include="PsvDataService.cs" />
|
<Compile Include="PsvDataService.cs" />
|
||||||
|
<Compile Include="PsvPrintService.cs" />
|
||||||
<Compile Include="PsvModels.cs" />
|
<Compile Include="PsvModels.cs" />
|
||||||
<Compile Include="ReferenceDirectorySqlHelpers.cs" />
|
<Compile Include="ReferenceDirectorySqlHelpers.cs" />
|
||||||
<Page Include="FrpdDirectoryWindow.xaml">
|
<Page Include="FrpdDirectoryWindow.xaml">
|
||||||
@@ -324,6 +325,22 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
|
<Content Include="..\ClosePsv.docx">
|
||||||
|
<Link>ClosePsv.docx</Link>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="..\Izv.docx">
|
||||||
|
<Link>Izv.docx</Link>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="..\OpenPsv.docx">
|
||||||
|
<Link>OpenPsv.docx</Link>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="..\Svid.docx">
|
||||||
|
<Link>Svid.docx</Link>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
BIN
_codex_build/ClosePsv.docx
Normal file
BIN
_codex_build/ClosePsv.docx
Normal file
Binary file not shown.
BIN
_codex_build/EntityFramework.SqlServer.dll
Normal file
BIN
_codex_build/EntityFramework.SqlServer.dll
Normal file
Binary file not shown.
2156
_codex_build/EntityFramework.SqlServer.xml
Normal file
2156
_codex_build/EntityFramework.SqlServer.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
_codex_build/EntityFramework.dll
Normal file
BIN
_codex_build/EntityFramework.dll
Normal file
Binary file not shown.
54121
_codex_build/EntityFramework.xml
Normal file
54121
_codex_build/EntityFramework.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
_codex_build/Izv.docx
Normal file
BIN
_codex_build/Izv.docx
Normal file
Binary file not shown.
BIN
_codex_build/OpenPsv.docx
Normal file
BIN
_codex_build/OpenPsv.docx
Normal file
Binary file not shown.
BIN
_codex_build/Svid.docx
Normal file
BIN
_codex_build/Svid.docx
Normal file
Binary file not shown.
BIN
_codex_build/XLAB.DATA.dll
Normal file
BIN
_codex_build/XLAB.DATA.dll
Normal file
Binary file not shown.
6
_codex_build/XLAB.DATA.dll.config
Normal file
6
_codex_build/XLAB.DATA.dll.config
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<connectionStrings>
|
||||||
|
<add name="ASUMSEntities" connectionString="metadata=res://*/XLabModel.csdl|res://*/XLabModel.ssdl|res://*/XLabModel.msl;provider=System.Data.SqlClient;provider connection string="data source=SEVENHILL\SQLEXPRESS;initial catalog=ASUMS;integrated security=True;trustservercertificate=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
|
||||||
|
</connectionStrings>
|
||||||
|
</configuration>
|
||||||
BIN
_codex_build/XLAB.exe
Normal file
BIN
_codex_build/XLAB.exe
Normal file
Binary file not shown.
14
_codex_build/XLAB.exe.config
Normal file
14
_codex_build/XLAB.exe.config
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<connectionStrings>
|
||||||
|
<add name="AsumsSql"
|
||||||
|
connectionString="data source=SEVENHILL\SQLEXPRESS;initial catalog=ASUMS;integrated security=True;trustservercertificate=True;MultipleActiveResultSets=True;"
|
||||||
|
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="data source=SEVENHILL\SQLEXPRESS;initial catalog=ASUMS;integrated security=True;trustservercertificate=True;MultipleActiveResultSets=True;App=EntityFramework""
|
||||||
|
providerName="System.Data.EntityClient" />
|
||||||
|
</connectionStrings>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||||
|
</startup>
|
||||||
|
</configuration>
|
||||||
Reference in New Issue
Block a user