From d1638d15bff7002ab4b5d3c251da78ba8b68cea8 Mon Sep 17 00:00:00 2001 From: Qwerty Date: Thu, 12 Jan 2017 08:41:17 +0300 Subject: [PATCH] Last changes: tarif exporting. --- WpfApp/App.config | 27 +- WpfApp/App.xaml | 1 + WpfApp/App.xaml.cs | 11 + .../Core/DirtyPropertyChangeNotifier.cs | 6 + WpfApp/Framework/Core/ViewModelBase.cs | 2 +- WpfApp/Framework/ViewViewModelPair.cs | 6 +- WpfApp/NLog.xsd | 116 +++- WpfApp/Settings/AppFilePaths.cs | 15 +- WpfApp/Util/CommonHelper.cs | 19 +- WpfApp/Util/WordWorker.cs | 132 ++-- WpfApp/View/AddChildWindow.xaml | 578 +++++++++--------- WpfApp/View/AddTarifWindow.xaml | 1 + WpfApp/View/ChangeDebtWindow.xaml | 23 + WpfApp/View/ChangeDebtWindow.xaml.cs | 27 + WpfApp/View/ChildDetailsWindow.xaml | 3 +- WpfApp/View/InputTextDialog.xaml | 4 +- WpfApp/View/MainWindow.xaml | 13 +- .../View/SaveOrRepealParentChangesDialog.xaml | 1 - WpfApp/View/UI/MonthlyPaymentsInYear.cs | 9 +- WpfApp/ViewModel/AddChildViewModel.cs | 67 +- WpfApp/ViewModel/AddParentViewModel.cs | 2 +- WpfApp/ViewModel/ChangeDebtViewModel.cs | 50 ++ WpfApp/ViewModel/ChildDetailsViewModel.cs | 199 ++++-- WpfApp/ViewModel/MainViewModel.cs | 179 ++++-- WpfApp/WpfApp.csproj | 13 +- WpfApp/packages.config | 6 +- .../resources/default_resource_structure.json | 7 +- .../ru_default_resource_structure.json | 7 +- 28 files changed, 1031 insertions(+), 493 deletions(-) create mode 100644 WpfApp/View/ChangeDebtWindow.xaml create mode 100644 WpfApp/View/ChangeDebtWindow.xaml.cs create mode 100644 WpfApp/ViewModel/ChangeDebtViewModel.cs diff --git a/WpfApp/App.config b/WpfApp/App.config index 3543ca2..e937882 100644 --- a/WpfApp/App.config +++ b/WpfApp/App.config @@ -8,12 +8,12 @@ - - - - - - + + + + + + @@ -31,6 +31,19 @@ - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WpfApp/App.xaml b/WpfApp/App.xaml index 3583a87..347538b 100644 --- a/WpfApp/App.xaml +++ b/WpfApp/App.xaml @@ -20,6 +20,7 @@ + diff --git a/WpfApp/App.xaml.cs b/WpfApp/App.xaml.cs index bafe536..11d2698 100644 --- a/WpfApp/App.xaml.cs +++ b/WpfApp/App.xaml.cs @@ -2,6 +2,7 @@ using System.Configuration; using System.IO; using System.Windows; +using Microsoft.Win32; using NLog; using WpfApp.Framework; using WpfApp.Settings; @@ -64,5 +65,15 @@ public static void EnsureAllDirectories() Directory.CreateDirectory(AppFilePaths.PersonImages); Logger.Trace("Directories was created"); } + + + public static SaveFileDialog GetDocumentSaveFileDialog(string fileName) + { + if (_documentSaveFileDialog == null) + _documentSaveFileDialog = new SaveFileDialog { Filter = "Word|*.docx" }; + _documentSaveFileDialog.FileName = fileName; + return _documentSaveFileDialog; + } + private static SaveFileDialog _documentSaveFileDialog; } } diff --git a/WpfApp/Framework/Core/DirtyPropertyChangeNotifier.cs b/WpfApp/Framework/Core/DirtyPropertyChangeNotifier.cs index 36a782b..7e16600 100644 --- a/WpfApp/Framework/Core/DirtyPropertyChangeNotifier.cs +++ b/WpfApp/Framework/Core/DirtyPropertyChangeNotifier.cs @@ -86,5 +86,11 @@ public void StopTracking() public event Action RemovedDirty; public event PropertyChangedEventHandler PropertyChanged; public event Action DirtyCountChanged; + + public bool WasPropertyChanged(string propertyName) + { + object value; + return _dirtyValues.TryGetValue(propertyName, out value) && _firstValues[propertyName] != value; + } } } \ No newline at end of file diff --git a/WpfApp/Framework/Core/ViewModelBase.cs b/WpfApp/Framework/Core/ViewModelBase.cs index 5b68b32..18f67d5 100644 --- a/WpfApp/Framework/Core/ViewModelBase.cs +++ b/WpfApp/Framework/Core/ViewModelBase.cs @@ -61,7 +61,7 @@ public object this[string key] get { object result; - return _data.TryGetValue(key, out result) ? result : /*this[key] =*/ defaultValue; // save current defaultValue if not exists + return _data.TryGetValue(key, out result) ? result : this[key] = defaultValue; // save current defaultValue if not exists } set { this[key] = value; } // for Mode=TwoWay } diff --git a/WpfApp/Framework/ViewViewModelPair.cs b/WpfApp/Framework/ViewViewModelPair.cs index 7deb5a7..df63d0f 100644 --- a/WpfApp/Framework/ViewViewModelPair.cs +++ b/WpfApp/Framework/ViewViewModelPair.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Reflection; using System.Windows; using WpfApp.Framework.Core; @@ -38,11 +37,8 @@ private void StartLifeCycle(Window window, ViewModelBase viewModel, Pipe pipe) window.DataContext = viewModel; window.Loaded += (s, e) => viewModel.OnLoaded(); - window.Closing += (s, e) => { e.Cancel = !viewModel.OnFinishing(); }; - var sw = new Stopwatch(); - sw.Start(); + window.Closing += (s, e) => e.Cancel = !viewModel.OnFinishing(); var conf = WindowStateSaver.ConfigureWindow(View.OriginalString, window, viewModel); - sw.Stop(); bool closed = false; window.Closed += (s, e) => { diff --git a/WpfApp/NLog.xsd b/WpfApp/NLog.xsd index 08e0f9f..bbbacc4 100644 --- a/WpfApp/NLog.xsd +++ b/WpfApp/NLog.xsd @@ -244,32 +244,6 @@ - - - - - - - - - - - Name of the target. - - - - - Layout used to format log messages. - - - - - Indicates whether to add <!-- --> comments around all written texts. - - - - - @@ -320,12 +294,18 @@ + Name of the target. + + + Condition expression. Log events who meet this condition will cause a flush on the wrapped target. + + @@ -785,7 +765,7 @@ - Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some replaceDict providers require this. + Obsolete - value will be ignored! The logging code always runs outside of transaction. Gets or sets a value indicating whether to use database transactions. Some data providers require this. @@ -1039,10 +1019,11 @@ - + - + + @@ -1123,9 +1104,9 @@ Maximum number of archive files that should be kept. - + - Is the an absolute or relative path? + Gets or set a value indicating whether a managed file stream is forced, instead of using the native implementation. @@ -1138,9 +1119,14 @@ Cleanup invalid values in a filename, e.g. slashes in a filename. If set to true, this can impact the performance of massive writes. If set to false, nothing gets written when the filename is wrong. - + - Gets or set a value indicating whether a managed file stream is forced, instead of used the native implementation. + Is the an absolute or relative path? + + + + + Value indicationg whether file creation calls should be synchronized by a system global mutex. @@ -1385,6 +1371,32 @@ + + + + + + + + + + + Name of the target. + + + + + Interval in which messages will be written up to the number of messages. + + + + + Maximum allowed number of messages written per . + + + + + @@ -2241,10 +2253,14 @@ + + + + @@ -2261,6 +2277,16 @@ Encoding. + + + Value whether escaping be done according to the old NLog style (Very non-standard) + + + + + Value whether escaping be done according to Rfc3986 (Supports Internationalized Resource Identifiers - IRIs) + + Web service method name. Only used with Soap. @@ -2281,6 +2307,16 @@ Web service URL. + + + Name of the root XML element, if POST of XML document chosen. If so, this property must not be null. (see and ). + + + + + (optional) root namespace of the XML document, if POST of XML document chosen. (see and ). + + @@ -2290,6 +2326,8 @@ + + @@ -2400,9 +2438,21 @@ + + + + + List of property names to exclude when is true + + + + + Option to include all properties from the log events + + Option to render the empty object value {} diff --git a/WpfApp/Settings/AppFilePaths.cs b/WpfApp/Settings/AppFilePaths.cs index 733945b..d0a0766 100644 --- a/WpfApp/Settings/AppFilePaths.cs +++ b/WpfApp/Settings/AppFilePaths.cs @@ -48,7 +48,8 @@ private static string GetDocumentName(string document, int childId) public static string GetTakingChildTemplatePath() => GetDocumentName("taking_child"); - public static string GetOrderOfAdmissionFileName(Child child) => GetDocumentName("order_of_admission", child.Id); + public static string GetOrderOfAdmissionFileName(Child child) => + string.Format(MyDocumentSettings.FilenameOfDocumentsAndTemplates["order_of_admission"][1], child.Id, string.Empty); public static string GetOrderOfAdmissionFileName(Child child, DateTime enterDate) => string.Format(MyDocumentSettings.FilenameOfDocumentsAndTemplates["order_of_admission"][1], child.Id, "_" + enterDate.ToString(OtherSettings.DateFormat)); public static string GetOrderOfAdmissionTemplatePath() => GetDocumentName("order_of_admission"); @@ -80,6 +81,18 @@ public static string GetGroupTypeChangedFileName() => MyDocumentSettings.FilenameOfDocumentsAndTemplates["group_type_changed"][1]; public static string GetGroupTypeChangedTemplatePath() => GetDocumentName("group_type_changed"); + public static string GetChildListFileName() => + MyDocumentSettings.FilenameOfDocumentsAndTemplates["child_list"][1]; + public static string GetChildListTemplatePath() => GetDocumentName("child_list"); + + public static string GetPaymentListFileName() => + MyDocumentSettings.FilenameOfDocumentsAndTemplates["payment_list"][1]; + public static string GetPaymentListTemplatePath() => GetDocumentName("payment_list"); + + public static string GetTarifChangeFileName(Child child) => + string.Format(MyDocumentSettings.FilenameOfDocumentsAndTemplates["tarif_change"][1], child.Id, DateTime.Now.ToString(OtherSettings.DateFormat)); + public static string GetTarifChangeTemplatePath() => GetDocumentName("tarif_change"); + static AppFilePaths() { diff --git a/WpfApp/Util/CommonHelper.cs b/WpfApp/Util/CommonHelper.cs index f986c1f..ac57f55 100644 --- a/WpfApp/Util/CommonHelper.cs +++ b/WpfApp/Util/CommonHelper.cs @@ -45,20 +45,27 @@ public static string ChangeFileNameIfFileExists(string path, int i = 2) return p; } + public static string GetRightRussianWord(int num, string singular, string plural) + { + var m100 = num % 100; + return m100 >= 10 && m100 <= 20 || m100%10 != 1 ? plural : singular; + } + + ///1 рубль, 2 рубля, 5 рублей => GetRightRussianWord(ruble, "рубль", "рубля", "рублей") public static string GetRightRussianWord(int num, string s1, string s2, string s5) { - var n100 = num % 100; - if (n100 >= 10 && n100 <= 20) return s5; + var m100 = num % 100; + if (m100 >= 10 && m100 <= 20) return s5; - var n10 = n100 % 10; - if (n10 == 1) return s1; - if (n10 > 1 && n10 < 5) return s2; + var m10 = m100 % 10; + if (m10 == 1) return s1; + if (m10 > 1 && m10 < 5) return s2; return s5; } public static void OpenFileOrDirectory(string path) { - // #if OS_is_Windows + // #if OS_IS_WINDOWS Process.Start("explorer.exe", $"\"{path}\""); } public static void OpenFileOrDirectoryWithSelected(string path) diff --git a/WpfApp/Util/WordWorker.cs b/WpfApp/Util/WordWorker.cs index 1e2ec6b..758655f 100644 --- a/WpfApp/Util/WordWorker.cs +++ b/WpfApp/Util/WordWorker.cs @@ -2,8 +2,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Text.RegularExpressions; +using System.Windows; using Microsoft.Office.Interop.Word; +using Application = Microsoft.Office.Interop.Word.Application; namespace WpfApp.Util { @@ -11,6 +14,11 @@ public class WordWorker { public static void Replace(string templateName, string destination, IDictionary data, string picturePath = null) { + if (!File.Exists(templateName)) + { + ShowFileNotFound(templateName); + return; + } var app = new Application(); try { @@ -31,7 +39,7 @@ public static void Replace(string templateName, string destination } finally { - app.Documents.Close(); + CloseDocuments(app.Documents); } } finally @@ -41,8 +49,18 @@ public static void Replace(string templateName, string destination } } + private static void CloseDocuments(Documents documents) + { + documents.Close(SaveChanges: WdSaveOptions.wdDoNotSaveChanges); + } + public static void InsertTable(string templateName, string destination, IDictionary header, IDictionary[] body) { + if (!File.Exists(templateName)) + { + ShowFileNotFound(templateName); + return; + } var app = new Application(); try { @@ -62,7 +80,7 @@ public static void InsertTable(string templateName, string destina .Rows[1] .Cells .Cast() - .Select(c => Regex.Replace(c.Range.Text, "[\\s\\n\\r\\a\\t]", "")) + .Select(c => CellRegex.Replace(c.Range.Text, "")) .ToArray(); foreach (var line in body) @@ -80,7 +98,7 @@ public static void InsertTable(string templateName, string destina } finally { - app.Documents.Close(); + CloseDocuments(app.Documents); } } finally @@ -93,12 +111,20 @@ public static void InsertTable(string templateName, string destina private static void DocumentSaveAs(Document doc, string file) { var dir = Path.GetDirectoryName(file); + // ReSharper disable once AssignNullToNotNullAttribute if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); doc.SaveAs(FileName: file); } + private static readonly Regex CellRegex = new Regex(@"[\s\n\r\a\t]"); + public static void InsertTableAndReplaceText(string templateName, string destination, IList> body, IDictionary replaceDict, string picturePath = null) { + if (!File.Exists(templateName)) + { + ShowFileNotFound(templateName); + return; + } var app = new Application(); try { @@ -109,24 +135,26 @@ public static void InsertTableAndReplaceText(string templateName, s.Find.ClearFormatting(); s.Find.Replacement.ClearFormatting(); - var tableCount = doc.Tables.Count; - for (int tableIndex = 1; tableIndex <= tableCount; tableIndex++) + if (body.Count > 0) { - var table = doc.Tables[tableIndex]; + var keys = body[0].Select(p => p.Key).ToList(); - int rowIndex = -1; - try + var tableCount = doc.Tables.Count; + for (int tableIndex = 1; tableIndex <= tableCount; tableIndex++) { - for (var col = 1; col <= table.Columns.Count; col++) + var table = doc.Tables[tableIndex]; + + int rowIndex = -1; + try { - for (int row = 1; row <= table.Rows.Count; row++) + for (var col = 1; col <= table.Columns.Count; col++) { - var text = table.Columns[col].Cells[row].Range.Text; - text = Regex.Replace(text, @"[\s\n\r\a\t]", ""); - - foreach (var line in body) + for (int row = 1; row <= table.Rows.Count; row++) { - if (line.ContainsKey(text)) + var text = table.Columns[col].Cells[row].Range.Text; + //text = CellRegex.Replace(text, ""); + + if (keys.Any(k => text.Contains(k))) { rowIndex = row; goto out_of_cycle; @@ -134,38 +162,48 @@ public static void InsertTableAndReplaceText(string templateName, } } } - } - catch (Exception e) - { - App.Logger.Warn(e.Message); - } - out_of_cycle: + catch (Exception e) + { + App.Logger.Warn(e.Message); + } + out_of_cycle: - if (rowIndex == -1) continue; + if (rowIndex == -1) continue; - var replaceRow = table.Rows[rowIndex]; - var headerCells = replaceRow - .Cells - .Cast() - .Select(c => Regex.Replace(c.Range.Text, "[\\s\\n\\r\\a\\t]", "")) - .ToArray(); + var replaceRow = table.Rows[rowIndex]; + string[] headerCells = replaceRow + .Cells + .Cast() + //.Select(c => CellRegex.Replace(c.Range.Text, "")) + .Select(c => c.Range.Text) + .ToArray(); - foreach (var line in body) - { - var row = table.Rows.Add(); - for (int cellIndex = 0; cellIndex < headerCells.Length; cellIndex++) + foreach (var dict in body) { - TValue value; - if (line.TryGetValue(headerCells[cellIndex], out value)) - row.Cells[cellIndex + 1].Range.Text = value.ToString(); + var row = table.Rows.Add(); + for (int cellIndex = 0; cellIndex < headerCells.Length; cellIndex++) + { + var sb = new StringBuilder(headerCells[cellIndex]); + foreach (var pair in dict) + { + sb.Replace(pair.Key, pair.Value?.ToString()); + } + var res = sb.ToString(); + if (headerCells[cellIndex] != res) + row.Cells[cellIndex + 1].Range.Text = res; + //TValue value; + //if (dict.TryGetValue(headerCells[cellIndex], out value)) + // row.Cells[cellIndex + 1].Range.Text = value.ToString(); + } } + replaceRow.Delete(); } - replaceRow.Delete(); - } - foreach (var pair in replaceDict) - { - s.Find.Execute(FindText: pair.Key, ReplaceWith: pair.Value, MatchCase: false, Replace: WdReplace.wdReplaceAll); } + if (replaceDict != null) + foreach (var pair in replaceDict) + { + s.Find.Execute(FindText: pair.Key, ReplaceWith: pair.Value, MatchCase: false, Replace: WdReplace.wdReplaceAll); + } if (picturePath != null) { ReplaceByPicture(s, picturePath, "&img"); @@ -174,7 +212,7 @@ public static void InsertTableAndReplaceText(string templateName, } finally { - app.Documents.Close(); + CloseDocuments(app.Documents); } } finally @@ -186,6 +224,11 @@ public static void InsertTableAndReplaceText(string templateName, public static void ReplaceWithDuplicate(string templateName, string destination, IDictionary[] data, string picturePath = null) { + if (!File.Exists(templateName)) + { + ShowFileNotFound(templateName); + return; + } var app = new Application(); try { @@ -220,7 +263,7 @@ public static void ReplaceWithDuplicate(string templateName, strin } finally { - app.Documents.Close(); + CloseDocuments(app.Documents); } } finally @@ -240,5 +283,10 @@ private static void ReplaceByPicture(Selection s, string picturePath, string pla s.Find.Execute(placeOf, ReplaceWith: string.Empty, MatchCase: false, Replace: WdReplace.wdReplaceAll); } } + + private static void ShowFileNotFound(string fileName) + { + MessageBox.Show($"Внимание, шаблон \"{fileName}\" не найден!", "Файл не найден", MessageBoxButton.OK, MessageBoxImage.Warning); + } } } diff --git a/WpfApp/View/AddChildWindow.xaml b/WpfApp/View/AddChildWindow.xaml index b9fea70..4b47878 100644 --- a/WpfApp/View/AddChildWindow.xaml +++ b/WpfApp/View/AddChildWindow.xaml @@ -10,7 +10,7 @@ xmlns:converter="clr-namespace:WpfApp.View.Converter" xmlns:system="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" - Title="Добавление ребёнка" Height="551.333" Width="1317.417" + Title="Добавление ребёнка" Height="577.333" Width="1317.417" Name="ThisWindow"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + - - - Father - Mother - Other - - - - - - - - - - - - - -