Compare commits
	
		
			22 Commits
		
	
	
		
			v0.2.0
			...
			b4f1eeee84
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b4f1eeee84 | |||
| 2922fe0138 | |||
| 704facbc6b | |||
| 404e8a0c27 | |||
| ef621fab2d | |||
| 0938e33fe1 | |||
| 6b5c283e10 | |||
| b6400c41c4 | |||
| 24b7078a05 | |||
| dc215d3350 | |||
| b80cbc037c | |||
| 4891501f62 | |||
| 6d3adc48f6 | |||
| f5eea1e906 | |||
| ba691f4d17 | |||
| 470f092482 | |||
| e9e4c75edd | |||
| ff1a4e7182 | |||
| 1e9cad6de7 | |||
| 62fe087598 | |||
| 7f01b85878 | |||
| a659d07db2 | 
| @@ -11,6 +11,7 @@ using System.Windows.Threading; | |||||||
| using System.Globalization; | using System.Globalization; | ||||||
| using System.Threading; | using System.Threading; | ||||||
| using System.Windows.Markup; | using System.Windows.Markup; | ||||||
|  | using System.Reflection; | ||||||
|  |  | ||||||
| namespace Elwig { | namespace Elwig { | ||||||
|     public partial class App : Application { |     public partial class App : Application { | ||||||
| @@ -20,10 +21,23 @@ namespace Elwig { | |||||||
|         public static readonly string TempPath = Path.Combine(Path.GetTempPath(), "Elwig"); |         public static readonly string TempPath = Path.Combine(Path.GetTempPath(), "Elwig"); | ||||||
|         public static readonly Config Config = new(DataPath + "config.ini"); |         public static readonly Config Config = new(DataPath + "config.ini"); | ||||||
|  |  | ||||||
|  |         public static int VersionMajor { get; private set; } | ||||||
|  |         public static int VersionMinor { get; private set; } | ||||||
|  |         public static int VersionPatch { get; private set; } | ||||||
|  |         public static string Version { | ||||||
|  |             get => $"{VersionMajor}.{VersionMinor}.{VersionPatch}"; | ||||||
|  |             private set { | ||||||
|  |                 var p = value.Split(".").Select(p => int.Parse(p.Trim())).ToArray(); | ||||||
|  |                 VersionMajor = p.ElementAtOrDefault(0); | ||||||
|  |                 VersionMinor = p.ElementAtOrDefault(1); | ||||||
|  |                 VersionPatch = p.ElementAtOrDefault(2); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         public static string ZwstId { get; private set; } |         public static string ZwstId { get; private set; } | ||||||
|         public static string BranchName { get; private set; } |         public static string BranchName { get; private set; } | ||||||
|         public static int? BranchPlz { get; private set; } |         public static int? BranchPlz { get; private set; } | ||||||
|         public static string? BranchOrt { get; private set; } |         public static string? BranchLocation { get; private set; } | ||||||
|         public static string? BranchAddress { get; private set; } |         public static string? BranchAddress { get; private set; } | ||||||
|         public static string? BranchPhoneNr { get; private set; } |         public static string? BranchPhoneNr { get; private set; } | ||||||
|         public static string? BranchFaxNr { get; private set; } |         public static string? BranchFaxNr { get; private set; } | ||||||
| @@ -36,7 +50,7 @@ namespace Elwig { | |||||||
|  |  | ||||||
|         public App() : base() { |         public App() : base() { | ||||||
|             System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); |             System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); | ||||||
|             Directory.CreateDirectory(App.TempPath); |             Directory.CreateDirectory(TempPath); | ||||||
|             Directory.CreateDirectory(DataPath); |             Directory.CreateDirectory(DataPath); | ||||||
|             MainDispatcher = Dispatcher; |             MainDispatcher = Dispatcher; | ||||||
|             Scales = Array.Empty<IScale>(); |             Scales = Array.Empty<IScale>(); | ||||||
| @@ -56,29 +70,28 @@ namespace Elwig { | |||||||
|                 new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)) |                 new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)) | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
|  |             Version = typeof(App).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? ""; | ||||||
|  |  | ||||||
|  |             try { | ||||||
|  |                 AppDbUpdater.CheckDb(); | ||||||
|  |             } catch (Exception e) { | ||||||
|  |                 MessageBox.Show($"Invalid Database:\n\n{e.Message}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error); | ||||||
|  |                 Shutdown(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = new(); |             Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = new(); | ||||||
|             using (var ctx = new AppDbContext()) { |             using (var ctx = new AppDbContext()) { | ||||||
|  |                 branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Ort.Name, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr)); | ||||||
|                 try { |                 try { | ||||||
|                     if (!ctx.Database.CanConnect()) { |                     Client = new(ctx); | ||||||
|                         MessageBox.Show($"Invalid Database:\n\n{Config.DatabaseFile}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error); |  | ||||||
|                         Shutdown(); |  | ||||||
|                         return; |  | ||||||
|                     } else { |  | ||||||
|                         branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Dest, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr)); |  | ||||||
|                         try { |  | ||||||
|                             Client = new(ctx); |  | ||||||
|                         } catch (Exception e) { |  | ||||||
|                             MessageBox.Show($"Fehler beim Laden der Mandantendaten:\n\n{e.Message}", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); |  | ||||||
|                             Shutdown(); |  | ||||||
|                             return; |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } catch (Exception e) { |                 } catch (Exception e) { | ||||||
|                     MessageBox.Show($"Invalid Database:\n\n{e.Message}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error); |                     MessageBox.Show($"Fehler beim Laden der Mandantendaten:\n\n{e.Message}", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); | ||||||
|                     Shutdown(); |                     Shutdown(); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             Utils.RunBackground("HTML Initialization", () => Documents.Html.Init(PrintingReadyChanged)); |             Utils.RunBackground("HTML Initialization", () => Documents.Html.Init(PrintingReadyChanged)); | ||||||
|             Utils.RunBackground("PDF Initialization", () => Documents.Pdf.Init(PrintingReadyChanged)); |             Utils.RunBackground("PDF Initialization", () => Documents.Pdf.Init(PrintingReadyChanged)); | ||||||
|  |  | ||||||
| @@ -114,7 +127,7 @@ namespace Elwig { | |||||||
|                     ZwstId = entry.Item1; |                     ZwstId = entry.Item1; | ||||||
|                     BranchName = entry.Item2; |                     BranchName = entry.Item2; | ||||||
|                     BranchPlz = entry.Item3; |                     BranchPlz = entry.Item3; | ||||||
|                     BranchOrt = entry.Item4; |                     BranchLocation = entry.Item4; | ||||||
|                     BranchAddress = entry.Item5; |                     BranchAddress = entry.Item5; | ||||||
|                     BranchPhoneNr = entry.Item6; |                     BranchPhoneNr = entry.Item6; | ||||||
|                     BranchFaxNr = entry.Item7; |                     BranchFaxNr = entry.Item7; | ||||||
| @@ -125,7 +138,7 @@ namespace Elwig { | |||||||
|                 ZwstId = entry.Item1; |                 ZwstId = entry.Item1; | ||||||
|                 BranchName = entry.Item2; |                 BranchName = entry.Item2; | ||||||
|                 BranchPlz = entry.Item3; |                 BranchPlz = entry.Item3; | ||||||
|                 BranchOrt = entry.Item4; |                 BranchLocation = entry.Item4; | ||||||
|                 BranchAddress = entry.Item5; |                 BranchAddress = entry.Item5; | ||||||
|                 BranchPhoneNr = entry.Item6; |                 BranchPhoneNr = entry.Item6; | ||||||
|                 BranchFaxNr = entry.Item7; |                 BranchFaxNr = entry.Item7; | ||||||
|   | |||||||
| @@ -9,19 +9,16 @@ namespace Elwig.Dialogs { | |||||||
|         public int Weight = 0; |         public int Weight = 0; | ||||||
|         public string? Reason = null; |         public string? Reason = null; | ||||||
|  |  | ||||||
|         public ManualWeighingDialog() { |         public ManualWeighingDialog(string? reason = null) { | ||||||
|             InitializeComponent(); |             InitializeComponent(); | ||||||
|  |             ReasonInput.Text = reason; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ConfirmButton_Click(object sender, RoutedEventArgs evt) { |         private void ConfirmButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|             DialogResult = true; |             DialogResult = true; | ||||||
|             Weight = int.Parse(WeightInput.Text); |             Weight = int.Parse(WeightInput.Text); | ||||||
|             Reason = Regex.Replace(ReasonInput.Text, @"\s+", "").Trim(); |             Reason = Regex.Replace(ReasonInput.Text, @"\s+", " ").Trim(); | ||||||
|             if (Reason == "") { |             if (Reason == "") Reason = null; | ||||||
|                 Reason = null; |  | ||||||
|             } else if (!Reason.EndsWith(".") || !Reason.EndsWith("!") || !Reason.EndsWith("?")) { |  | ||||||
|                 Reason += "."; |  | ||||||
|             } |  | ||||||
|             Close(); |             Close(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,5 +14,8 @@ | |||||||
|         <address>@Model.Address</address> |         <address>@Model.Address</address> | ||||||
|     </div> |     </div> | ||||||
|     <aside>@Raw(Model.Aside)</aside> |     <aside>@Raw(Model.Aside)</aside> | ||||||
|  |     @if (Model.ShowDateAndLocation) { | ||||||
|  |         <div class="date">@Model.Location, am @($"{Model.Date:dd.MM.yyyy}")</div> | ||||||
|  |     } | ||||||
| </div> | </div> | ||||||
| @RenderBody() | @RenderBody() | ||||||
|   | |||||||
| @@ -3,6 +3,8 @@ using Elwig.Models; | |||||||
| namespace Elwig.Documents { | namespace Elwig.Documents { | ||||||
|     public abstract class BusinessDocument : Document { |     public abstract class BusinessDocument : Document { | ||||||
|  |  | ||||||
|  |         public bool ShowDateAndLocation = false; | ||||||
|  |  | ||||||
|         public Member Member; |         public Member Member; | ||||||
|         public bool IncludeSender = false; |         public bool IncludeSender = false; | ||||||
|         public bool UseBillingAddress = false; |         public bool UseBillingAddress = false; | ||||||
| @@ -11,7 +13,7 @@ namespace Elwig.Documents { | |||||||
|  |  | ||||||
|         public BusinessDocument(string title, Member m, bool includeSender = false) : base(title) { |         public BusinessDocument(string title, Member m, bool includeSender = false) : base(title) { | ||||||
|             Member = m; |             Member = m; | ||||||
|             Location = App.BranchName; |             Location = App.BranchLocation; | ||||||
|             IncludeSender = includeSender; |             IncludeSender = includeSender; | ||||||
|             var uid = (m.UstIdNr ?? "-") + (m.IsBuchführend ? "" : " <i>(pauschaliert)</i>"); |             var uid = (m.UstIdNr ?? "-") + (m.IsBuchführend ? "" : " <i>(pauschaliert)</i>"); | ||||||
|             Aside = $"<table><colgroup><col span='1' style='width: 22.5mm;'/><col span='1' style='width: 42.5mm;'/></colgroup>" + |             Aside = $"<table><colgroup><col span='1' style='width: 22.5mm;'/><col span='1' style='width: 42.5mm;'/></colgroup>" + | ||||||
|   | |||||||
| @@ -7,7 +7,6 @@ | |||||||
|     var bucketNum = Model.BucketNames.Length; |     var bucketNum = Model.BucketNames.Length; | ||||||
| } | } | ||||||
| <main> | <main> | ||||||
|     <div class="date">@Model.Location, am @($"{Model.Date:dd.MM.yyyy}")</div> |  | ||||||
|     <h1>@Model.Title</h1> |     <h1>@Model.Title</h1> | ||||||
|     <table class="credit"> |     <table class="credit"> | ||||||
|         <colgroup> |         <colgroup> | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ namespace Elwig.Documents { | |||||||
|  |  | ||||||
|         public CreditNote(Credit c, AppDbContext ctx) : base($"Traubengutschrift Nr. {c.TgId} – {c.Payment.Variant.Name}", c.Member) { |         public CreditNote(Credit c, AppDbContext ctx) : base($"Traubengutschrift Nr. {c.TgId} – {c.Payment.Variant.Name}", c.Member) { | ||||||
|             UseBillingAddress = true; |             UseBillingAddress = true; | ||||||
|  |             ShowDateAndLocation = true; | ||||||
|             Credit = c; |             Credit = c; | ||||||
|             Aside = Aside.Replace("</table>", "") + |             Aside = Aside.Replace("</table>", "") + | ||||||
|                 $"<thead><tr><th colspan='2'>Gutschrift</th></tr></thead><tbody>" + |                 $"<thead><tr><th colspan='2'>Gutschrift</th></tr></thead><tbody>" + | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ | |||||||
| @{ Layout = "BusinessDocument"; } | @{ Layout = "BusinessDocument"; } | ||||||
| <link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\style-deliverynote.css" /> | <link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\style-deliverynote.css" /> | ||||||
| <main> | <main> | ||||||
| <div class="date">@Model.Location, am @($"{Model.Date:dd.MM.yyyy}")</div> |  | ||||||
| <h1>@Model.Title</h1> | <h1>@Model.Title</h1> | ||||||
| @{ | @{ | ||||||
|     bool displayStats = true;  // Model.Delivery.Year == Model.CurrentNextSeason |     bool displayStats = true;  // Model.Delivery.Year == Model.CurrentNextSeason | ||||||
| @@ -91,7 +90,8 @@ | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             <tr><td></td><td colspan="5"> |             <tr><td></td><td colspan="5"> | ||||||
|                 @Raw(part.ManualWeighing ? "<i>Handwiegung</i>" : $"<i>Waage:</i> {part.ScaleId ?? "?"}, <i>ID:</i> {part.WeighingId ?? "?"}") (@(part.IsGerebelt ? "gerebelt gewogen" : "nicht gerebelt gewogen")) |                 @Raw(part.ManualWeighing ? "<i>Handwiegung</i>" : $"<i>Waage:</i> {part.ScaleId ?? "?"}, <i>ID:</i> {part.WeighingId ?? "?"}") | ||||||
|  |                 (@(part.IsGerebelt ? "gerebelt gewogen" : "nicht gerebelt gewogen"))@Raw(part.WeighingReason != null ? $", <i>Begründung:</i>" : "") @part.WeighingReason | ||||||
|             </td></tr> |             </td></tr> | ||||||
|             @if (part.Comment != null) { |             @if (part.Comment != null) { | ||||||
|                 <tr><td></td><td colspan="5"><i>Anmerkung:</i> @part.Comment</td></tr> |                 <tr><td></td><td colspan="5"><i>Anmerkung:</i> @part.Comment</td></tr> | ||||||
| @@ -127,7 +127,7 @@ | |||||||
|             </colgroup> |             </colgroup> | ||||||
|             <thead> |             <thead> | ||||||
|                 <tr> |                 <tr> | ||||||
|                     <th><b>Gesamtlieferung</b> [kg]</th> |                     <th><b>Lese @Model.Delivery.Year</b> per @($"{Model.Date:dd.MM.yyyy}") [kg]</th> | ||||||
|                     <th>Lieferpflicht</th> |                     <th>Lieferpflicht</th> | ||||||
|                     <th>Lieferrecht</th> |                     <th>Lieferrecht</th> | ||||||
|                     <th>Unterliefert</th> |                     <th>Unterliefert</th> | ||||||
| @@ -147,13 +147,14 @@ | |||||||
|                             $"<td>{sum:N0}</td>"; |                             $"<td>{sum:N0}</td>"; | ||||||
|                     } |                     } | ||||||
|                     var sortids = Model.Delivery.Parts.Select(p => p.SortId).ToList(); |                     var sortids = Model.Delivery.Parts.Select(p => p.SortId).ToList(); | ||||||
|  |                     var buckets = Model.MemberBuckets.GroupBy(b => b.Item1[..2]).ToDictionary(g => g.Key, g => g.Count()); | ||||||
|                 } |                 } | ||||||
|                 <tr> |                 <tr> | ||||||
|                     <th>Geschäftsanteile</th> |                     <th>Gesamtlieferung</th> | ||||||
|                     @Raw(FormatRow(Model.Member.DeliveryObligation, Model.Member.DeliveryRight, Model.Member.Deliveries.Where(d => d.Year == Model.Delivery.Year).Sum(d => d.Weight))) |                     @Raw(FormatRow(Model.Member.DeliveryObligation, Model.Member.DeliveryRight, Model.Member.Deliveries.Where(d => d.Year == Model.Delivery.Year).Sum(d => d.Weight))) | ||||||
|                 </tr> |                 </tr> | ||||||
|                 @foreach (var (id, name, right, obligation, sum) in Model.MemberBuckets.OrderBy(b => b.Item1)) { |                 @foreach (var (id, name, right, obligation, sum) in Model.MemberBuckets.OrderBy(b => b.Item1)) { | ||||||
|                     if (right > 0 && obligation > 0) { |                     if (right > 0 || obligation > 0 || (sum > 0 && buckets[id[..2]] > 1 && !id.EndsWith('_'))) { | ||||||
|                         <tr class="@(sortids.Contains(id[..2]) ? "" : "optional")"> |                         <tr class="@(sortids.Contains(id[..2]) ? "" : "optional")"> | ||||||
|                             <th>@name</th> |                             <th>@name</th> | ||||||
|                             @Raw(FormatRow(obligation, right, sum)) |                             @Raw(FormatRow(obligation, right, sum)) | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ namespace Elwig.Documents { | |||||||
|  |  | ||||||
|         public DeliveryNote(Delivery d, AppDbContext ctx) : base($"Traubenübernahmeschein Nr. {d.LsNr}", d.Member) { |         public DeliveryNote(Delivery d, AppDbContext ctx) : base($"Traubenübernahmeschein Nr. {d.LsNr}", d.Member) { | ||||||
|             UseBillingAddress = true; |             UseBillingAddress = true; | ||||||
|  |             ShowDateAndLocation = true; | ||||||
|             Delivery = d; |             Delivery = d; | ||||||
|             Aside = Aside.Replace("</table>", "") + |             Aside = Aside.Replace("</table>", "") + | ||||||
|                 $"<thead><tr><th colspan='2'>Lieferung</th></tr></thead><tbody>" + |                 $"<thead><tr><th colspan='2'>Lieferung</th></tr></thead><tbody>" + | ||||||
|   | |||||||
| @@ -18,12 +18,14 @@ | |||||||
|     <link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\style-page.css"/> |     <link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\style-page.css"/> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
|     <div class="m1"></div> |     @if (Model.ShowFoldMarks) { | ||||||
|     <div class="m2"></div> |         <div class="m1"></div> | ||||||
|     <div class="m3"></div> |         <div class="m2"></div> | ||||||
|     <div class="m1 r"></div> |         <div class="m3"></div> | ||||||
|     <div class="m2 r"></div> |         <div class="m1 r"></div> | ||||||
|     <div class="m3 r"></div> |         <div class="m2 r"></div> | ||||||
|  |         <div class="m3 r"></div> | ||||||
|  |     } | ||||||
|     <div class="footer-wrapper"> |     <div class="footer-wrapper"> | ||||||
|         <div class="pre-footer"> |         <div class="pre-footer"> | ||||||
|             <span class="date">@($"{Model.Date:dddd, d. MMMM yyyy}")</span> |             <span class="date">@($"{Model.Date:dddd, d. MMMM yyyy}")</span> | ||||||
|   | |||||||
| @@ -8,6 +8,8 @@ namespace Elwig.Documents { | |||||||
|  |  | ||||||
|         private TempFile? PdfFile = null; |         private TempFile? PdfFile = null; | ||||||
|  |  | ||||||
|  |         public bool ShowFoldMarks = App.Config.Debug; | ||||||
|  |  | ||||||
|         public string DataPath; |         public string DataPath; | ||||||
|         public int CurrentNextSeason; |         public int CurrentNextSeason; | ||||||
|         public string? DocumentId; |         public string? DocumentId; | ||||||
| @@ -22,8 +24,8 @@ namespace Elwig.Documents { | |||||||
|             DataPath = App.DataPath; |             DataPath = App.DataPath; | ||||||
|             CurrentNextSeason = Utils.CurrentNextSeason; |             CurrentNextSeason = Utils.CurrentNextSeason; | ||||||
|             Title = title; |             Title = title; | ||||||
|             Author = App.Client.NameFull; |             Author = c.NameFull; | ||||||
|             Header = $"<h1>{c.Name}</h1>"; |             Header = $"<div class='name'>{c.Name}</div><div class='suffix'>{c.NameSuffix}</div>"; | ||||||
|             Footer = Utils.GenerateFooter("<br/>", " \u00b7 ") |             Footer = Utils.GenerateFooter("<br/>", " \u00b7 ") | ||||||
|                 .Item(c.NameFull).NextLine() |                 .Item(c.NameFull).NextLine() | ||||||
|                 .Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine() |                 .Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine() | ||||||
|   | |||||||
| @@ -14,6 +14,13 @@ | |||||||
|     position: relative; |     position: relative; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .info-wrapper .date { | ||||||
|  |     text-align: right; | ||||||
|  |     position: absolute; | ||||||
|  |     right: 0; | ||||||
|  |     bottom: -1.5em; | ||||||
|  | } | ||||||
|  |  | ||||||
| .address-wrapper { | .address-wrapper { | ||||||
|     height: 45mm; |     height: 45mm; | ||||||
|     width: 85mm; |     width: 85mm; | ||||||
| @@ -68,6 +75,14 @@ aside table tbody td { | |||||||
|     font-size: 10pt; |     font-size: 10pt; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | aside table tbody th { | ||||||
|  |     padding: 0.25mm 0.5mm 0.25mm 1mm; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | aside table tbody td { | ||||||
|  |     padding: 0.25mm 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| aside table tbody th { | aside table tbody th { | ||||||
|     font-weight: normal; |     font-weight: normal; | ||||||
| } | } | ||||||
| @@ -80,7 +95,7 @@ main > *:first-child { | |||||||
|     margin-top: 0; |     margin-top: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| .main-wrapper h1, .main-wrapper p { | main h1, .main-wrapper p { | ||||||
|     font-size: 12pt; |     font-size: 12pt; | ||||||
|     margin: 1em 0; |     margin: 1em 0; | ||||||
|     text-align: justify; |     text-align: justify; | ||||||
| @@ -92,12 +107,8 @@ main > *:first-child { | |||||||
|     hyphens: manual; |     hyphens: manual; | ||||||
| } | } | ||||||
|  |  | ||||||
| .main-wrapper .date { | main h1 { | ||||||
|     margin-bottom: 2em; |     margin-top: 0; | ||||||
|     text-align: right; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .main-wrapper h1 { |  | ||||||
|     margin-bottom: 2em; |     margin-bottom: 2em; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,4 +1,8 @@ | |||||||
|  |  | ||||||
|  | main h1 { | ||||||
|  |     margin-bottom: 1.5em !important; | ||||||
|  | } | ||||||
|  |  | ||||||
| table.delivery { | table.delivery { | ||||||
|     margin-bottom: 5mm; |     margin-bottom: 5mm; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ table th { | |||||||
|  |  | ||||||
| header { | header { | ||||||
|     height: 45mm; |     height: 45mm; | ||||||
|     padding: 5mm; |     padding: 10mm 0 0 0; | ||||||
|     position: absolute; |     position: absolute; | ||||||
|     top: -25mm; |     top: -25mm; | ||||||
|     left: 0; |     left: 0; | ||||||
| @@ -38,9 +38,15 @@ header { | |||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
| } | } | ||||||
|  |  | ||||||
| header h1 { | header .name { | ||||||
|     font-size: 18pt; |     font-size: 18pt; | ||||||
|     margin-top: 10mm; |     margin-top: 10mm; | ||||||
|  |     font-weight: bold; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | header .suffix { | ||||||
|  |     font-size: 12pt; | ||||||
|  |     font-weight: bold; | ||||||
| } | } | ||||||
|  |  | ||||||
| .footer-wrapper { | .footer-wrapper { | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|     <UseWPF>true</UseWPF> |     <UseWPF>true</UseWPF> | ||||||
|     <PreserveCompilationContext>true</PreserveCompilationContext> |     <PreserveCompilationContext>true</PreserveCompilationContext> | ||||||
|     <ApplicationIcon>elwig.ico</ApplicationIcon> |     <ApplicationIcon>elwig.ico</ApplicationIcon> | ||||||
|     <Version>0.2.0</Version> |     <Version>0.3.1</Version> | ||||||
|     <SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages> |     <SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
| @@ -19,9 +19,9 @@ | |||||||
|     <PackageReference Include="Balbarak.WeasyPrint" Version="2.0.2" /> |     <PackageReference Include="Balbarak.WeasyPrint" Version="2.0.2" /> | ||||||
|     <PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.1" /> |     <PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.1" /> | ||||||
|     <PackageReference Include="ini-parser" Version="2.5.2" /> |     <PackageReference Include="ini-parser" Version="2.5.2" /> | ||||||
|     <PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.21" /> |     <PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.22" /> | ||||||
|     <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.10" /> |     <PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.11" /> | ||||||
|     <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.10" /> |     <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.11" /> | ||||||
|     <PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1938.49" /> |     <PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1938.49" /> | ||||||
|     <PackageReference Include="RazorLight" Version="2.3.1" /> |     <PackageReference Include="RazorLight" Version="2.3.1" /> | ||||||
|     <PackageReference Include="ScottPlot.WPF" Version="4.1.67" /> |     <PackageReference Include="ScottPlot.WPF" Version="4.1.67" /> | ||||||
|   | |||||||
							
								
								
									
										78
									
								
								Elwig/Helpers/AppDbUpdater.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								Elwig/Helpers/AppDbUpdater.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | using Microsoft.Data.Sqlite; | ||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace Elwig.Helpers { | ||||||
|  |     public static class AppDbUpdater { | ||||||
|  |  | ||||||
|  |         public static readonly int RequiredSchemaVersion = 1; | ||||||
|  |  | ||||||
|  |         private static int _versionOffset = 0; | ||||||
|  |         private static readonly Action<SqliteConnection>[] _updaters = new[] { | ||||||
|  |             UpdateDbSchema_1_To_2, UpdateDbSchema_2_To_3 | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         private static void ExecuteNonQuery(SqliteConnection cnx, string sql) { | ||||||
|  |             using var cmd = cnx.CreateCommand(); | ||||||
|  |             cmd.CommandText = sql; | ||||||
|  |             cmd.ExecuteNonQuery(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static object? ExecuteScalar(SqliteConnection cnx, string sql) { | ||||||
|  |             using var cmd = cnx.CreateCommand(); | ||||||
|  |             cmd.CommandText = sql; | ||||||
|  |             return cmd.ExecuteScalar(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static string CheckDb() { | ||||||
|  |             using var cnx = AppDbContext.Connect(); | ||||||
|  |  | ||||||
|  |             var applId = (long?)ExecuteScalar(cnx, "PRAGMA application_id") ?? 0; | ||||||
|  |             if (applId != 0x454C5747) throw new Exception("Invalid application_id of database"); | ||||||
|  |  | ||||||
|  |             var schemaVers = (long?)ExecuteScalar(cnx, "PRAGMA schema_version") ?? 0; | ||||||
|  |             _versionOffset = (int)(schemaVers % 100); | ||||||
|  |             if (_versionOffset != 0) { | ||||||
|  |                 // schema was modified manually/externally | ||||||
|  |                 // TODO issue warning | ||||||
|  |             } | ||||||
|  |             UpdateDbSchema(cnx, (int)(schemaVers / 100), RequiredSchemaVersion); | ||||||
|  |  | ||||||
|  |             var userVers = (long?)ExecuteScalar(cnx, "PRAGMA user_version") ?? 0; | ||||||
|  |             var major = userVers >> 24; | ||||||
|  |             var minor = (userVers >> 16) & 0xFF; | ||||||
|  |             var patch = userVers & 0xFFFF; | ||||||
|  |  | ||||||
|  |             if (App.VersionMajor > major || App.VersionMinor > minor || App.VersionPatch > patch) { | ||||||
|  |                 long vers = (App.VersionMajor << 24) | (App.VersionMinor << 16) | App.VersionPatch; | ||||||
|  |                 ExecuteNonQuery(cnx, $"PRAGMA user_version = {vers}"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return $"{major}.{minor}.{patch}"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void UpdateDbSchema(SqliteConnection cnx, int fromVersion, int toVersion) { | ||||||
|  |             if (fromVersion == toVersion) { | ||||||
|  |                 return; | ||||||
|  |             } else if (fromVersion > toVersion) { | ||||||
|  |                 throw new Exception("schema_version of database is too new"); | ||||||
|  |             } else if (toVersion - 1 > _updaters.Length) { | ||||||
|  |                 throw new Exception("Unable to update database schema: Updater not implemented"); | ||||||
|  |             } else if (fromVersion <= 0) { | ||||||
|  |                 throw new Exception("schema_version of database is invalid"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             ExecuteNonQuery(cnx, "PRAGMA locking_mode = EXCLUSIVE"); | ||||||
|  |             ExecuteNonQuery(cnx, "BEGIN EXCLUSIVE"); | ||||||
|  |             for (int i = fromVersion; i < toVersion; i++) { | ||||||
|  |                 _updaters[i - 1](cnx); | ||||||
|  |             } | ||||||
|  |             ExecuteNonQuery(cnx, "COMMIT"); | ||||||
|  |             ExecuteNonQuery(cnx, "VACUUM"); | ||||||
|  |             ExecuteNonQuery(cnx, $"PRAGMA schema_version = {toVersion * 100 + _versionOffset}"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void UpdateDbSchema_1_To_2(SqliteConnection cnx) { } | ||||||
|  |  | ||||||
|  |         private static void UpdateDbSchema_2_To_3(SqliteConnection cnx) { } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -8,6 +8,7 @@ namespace Elwig.Helpers { | |||||||
|     public class Config { |     public class Config { | ||||||
|  |  | ||||||
|         private readonly string FileName; |         private readonly string FileName; | ||||||
|  |         public bool Debug; | ||||||
|         public string DatabaseFile = App.DataPath + "database.sqlite3"; |         public string DatabaseFile = App.DataPath + "database.sqlite3"; | ||||||
|         public string? DatabaseLog = null; |         public string? DatabaseLog = null; | ||||||
|         public string? Branch = null; |         public string? Branch = null; | ||||||
| @@ -49,6 +50,13 @@ namespace Elwig.Helpers { | |||||||
|                 Branch = branch; |                 Branch = branch; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             if (ini == null || !ini.TryGetKey("general.debug", out string debug)) { | ||||||
|  |                 Debug = false; | ||||||
|  |             } else { | ||||||
|  |                 debug = debug.ToLower(); | ||||||
|  |                 Debug = debug == "1" || debug == "true" || debug == "yes" || debug == "on"; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             ScaleList.Clear(); |             ScaleList.Clear(); | ||||||
|             Scales = ScaleList; |             Scales = ScaleList; | ||||||
|             if (ini != null) { |             if (ini != null) { | ||||||
| @@ -72,6 +80,7 @@ namespace Elwig.Helpers { | |||||||
|             using var file = new StreamWriter(FileName, false, Utils.UTF8); |             using var file = new StreamWriter(FileName, false, Utils.UTF8); | ||||||
|             file.Write($"\r\n[general]\r\n"); |             file.Write($"\r\n[general]\r\n"); | ||||||
|             if (Branch != null) file.Write($"branch = {Branch}\r\n"); |             if (Branch != null) file.Write($"branch = {Branch}\r\n"); | ||||||
|  |             if (Debug) file.Write("debug = true\r\n"); | ||||||
|             file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n"); |             file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n"); | ||||||
|             if (DatabaseLog != null) file.Write($"log = {DatabaseLog}\r\n"); |             if (DatabaseLog != null) file.Write($"log = {DatabaseLog}\r\n"); | ||||||
|             foreach (var s in ScaleList) { |             foreach (var s in ScaleList) { | ||||||
|   | |||||||
| @@ -219,8 +219,8 @@ namespace Elwig.Helpers { | |||||||
|                 .Sum(); |                 .Sum(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static (int, string?)? ShowManualWeighingDialog() { |         public static (int, string?)? ShowManualWeighingDialog(string? reason = null) { | ||||||
|             var d = new ManualWeighingDialog(); |             var d = new ManualWeighingDialog(reason); | ||||||
|             return d.ShowDialog() == true ? (d.Weight, d.Reason) : null; |             return d.ShowDialog() == true ? (d.Weight, d.Reason) : null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -70,9 +70,9 @@ namespace Elwig.Helpers { | |||||||
|             for (int i = 0; i < input.Text.Length; i++) { |             for (int i = 0; i < input.Text.Length; i++) { | ||||||
|                 char ch = input.Text[i]; |                 char ch = input.Text[i]; | ||||||
|                 if (char.IsAsciiDigit(ch)) { |                 if (char.IsAsciiDigit(ch)) { | ||||||
|                     if (v2 == -1 && v1 < maxLen) { |                     if (v2 == -1 && (maxLen == -1 || v1 < maxLen)) { | ||||||
|                         text += ch; v1++; |                         text += ch; v1++; | ||||||
|                     } else if (v2 != -1 && v2 < maxDecimal) { |                     } else if (v2 != -1 && (maxDecimal == -1 || v2 < maxDecimal)) { | ||||||
|                         text += ch; v2++; |                         text += ch; v2++; | ||||||
|                     } |                     } | ||||||
|                 } else if (v2 == 0-1 && ch == ',' || ch == '.') { |                 } else if (v2 == 0-1 && ch == ',' || ch == '.') { | ||||||
|   | |||||||
| @@ -87,6 +87,9 @@ namespace Elwig.Models { | |||||||
|         [Column("weighing_id")] |         [Column("weighing_id")] | ||||||
|         public string? WeighingId { get; set; } |         public string? WeighingId { get; set; } | ||||||
|  |  | ||||||
|  |         [Column("weighing_reason")] | ||||||
|  |         public string? WeighingReason { get; set; } | ||||||
|  |  | ||||||
|         [Column("comment")] |         [Column("comment")] | ||||||
|         public string? Comment { get; set; } |         public string? Comment { get; set; } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -128,9 +128,6 @@ namespace Elwig.Models { | |||||||
|         [Column("address")] |         [Column("address")] | ||||||
|         public string Address { get; set; } |         public string Address { get; set; } | ||||||
|  |  | ||||||
|         [Column("email")] |  | ||||||
|         public string? Email { get; set; } |  | ||||||
|  |  | ||||||
|         [Column("default_kgnr")] |         [Column("default_kgnr")] | ||||||
|         public int? DefaultKgNr { get; set; } |         public int? DefaultKgNr { get; set; } | ||||||
|  |  | ||||||
| @@ -174,6 +171,9 @@ namespace Elwig.Models { | |||||||
|         [InverseProperty("Member")] |         [InverseProperty("Member")] | ||||||
|         public virtual ISet<MemberTelNr> TelephoneNumbers { get; private set; } |         public virtual ISet<MemberTelNr> TelephoneNumbers { get; private set; } | ||||||
|  |  | ||||||
|  |         [InverseProperty("member")] | ||||||
|  |         public virtual ISet<MemberEmailAddr> EmailAddresses { get; private set; } | ||||||
|  |  | ||||||
|         public string FullAddress => $"{Address}, {PostalDest.AtPlz.Plz} {PostalDest.AtPlz.Ort.Name}"; |         public string FullAddress => $"{Address}, {PostalDest.AtPlz.Plz} {PostalDest.AtPlz.Ort.Name}"; | ||||||
|  |  | ||||||
|         public int DeliveryRight => BusinessShares * App.Client.DeliveryRight; |         public int DeliveryRight => BusinessShares * App.Client.DeliveryRight; | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								Elwig/Models/MemberEmailAddr.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Elwig/Models/MemberEmailAddr.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  |  | ||||||
|  | namespace Elwig.Models { | ||||||
|  |     [Table("member_email_address"), PrimaryKey("MgNr", "Nr")] | ||||||
|  |     public class MemberEmailAddr { | ||||||
|  |         [Column("mgnr")] | ||||||
|  |         public int MgNr { get; set; } | ||||||
|  |  | ||||||
|  |         [Column("nr")] | ||||||
|  |         public int Nr { get; set; } | ||||||
|  |  | ||||||
|  |         [Column("address")] | ||||||
|  |         public string Address { get; set; } | ||||||
|  |  | ||||||
|  |         [Column("comment")] | ||||||
|  |         public string? Comment { get; set; } | ||||||
|  |  | ||||||
|  |         [ForeignKey("MgNr")] | ||||||
|  |         public virtual Member Member { get; private set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -413,7 +413,7 @@ namespace Elwig.Windows { | |||||||
|             UpdateButtons(); |             UpdateButtons(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected void TextBox_TextChanged(object sender, RoutedEventArgs evt) { |         protected void TextBox_TextChanged(object sender, RoutedEventArgs? evt) { | ||||||
|             var input = (TextBox)sender; |             var input = (TextBox)sender; | ||||||
|             if (SenderIsRequired(input) && input.Text.Length == 0) { |             if (SenderIsRequired(input) && input.Text.Length == 0) { | ||||||
|                 ValidateInput(input, false); |                 ValidateInput(input, false); | ||||||
| @@ -462,6 +462,10 @@ namespace Elwig.Windows { | |||||||
|             InputTextChanged((TextBox)sender, Validator.CheckInteger); |             InputTextChanged((TextBox)sender, Validator.CheckInteger); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         protected void DecimalInput_TextChanged(object sender, RoutedEventArgs evt) { | ||||||
|  |             InputTextChanged((TextBox)sender, Validator.CheckDecimal); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         protected void PartialDateInput_TextChanged(object sender, RoutedEventArgs evt) { |         protected void PartialDateInput_TextChanged(object sender, RoutedEventArgs evt) { | ||||||
|             InputTextChanged((TextBox)sender, Validator.CheckPartialDate); |             InputTextChanged((TextBox)sender, Validator.CheckPartialDate); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -131,6 +131,10 @@ | |||||||
|                 <Label Content="Bewirt.-Art:" Margin="10,100,0,0" Grid.Column="0" Grid.ColumnSpan="2"/> |                 <Label Content="Bewirt.-Art:" Margin="10,100,0,0" Grid.Column="0" Grid.ColumnSpan="2"/> | ||||||
|                 <ComboBox x:Name="WineCultivationInput" DisplayMemberPath="Name" TextSearch.TextPath="Name" |                 <ComboBox x:Name="WineCultivationInput" DisplayMemberPath="Name" TextSearch.TextPath="Name" | ||||||
|                           HorizontalAlignment="Stretch" Margin="0,100,10,0" Grid.Column="1" Grid.ColumnSpan="3"/> |                           HorizontalAlignment="Stretch" Margin="0,100,10,0" Grid.Column="1" Grid.ColumnSpan="3"/> | ||||||
|  |  | ||||||
|  |                 <Label Content="Anmerkung:" Margin="10,130,0,0" Grid.Column="0" Grid.ColumnSpan="2"/> | ||||||
|  |                 <TextBox x:Name="CommentInput" TextChanged="TextBox_TextChanged" | ||||||
|  |                          HorizontalAlignment="Stretch" Margin="0,130,10,0" Grid.Column="1" Grid.ColumnSpan="3"/> | ||||||
|             </Grid> |             </Grid> | ||||||
|         </GroupBox> |         </GroupBox> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -40,11 +40,8 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|         private async Task RefreshAreaCommitmentListQuery() { |         private async Task RefreshAreaCommitmentListQuery() { | ||||||
|             List<AreaCom> areaComs = await Context.AreaCommitments.Where(a => a.MgNr == Member.MgNr).OrderBy(a => a.FbNr).ToListAsync(); |             List<AreaCom> areaComs = await Context.AreaCommitments.Where(a => a.MgNr == Member.MgNr).OrderBy(a => a.FbNr).ToListAsync(); | ||||||
|  |             ControlUtils.RenewItemsSource(AreaCommitmentList, areaComs, i => (i as AreaCom)?.FbNr, | ||||||
|             ControlUtils.RenewItemsSource(AreaCommitmentList, areaComs, i => (i as AreaCom)?.FbNr); |                 AreaCommitmentList_SelectionChanged, ControlUtils.RenewSourceDefault.None); | ||||||
|             if (areaComs.Count == 1) |  | ||||||
|                 AreaCommitmentList.SelectedIndex = 0; |  | ||||||
|  |  | ||||||
|             RefreshInputs(); |             RefreshInputs(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -82,6 +79,8 @@ namespace Elwig.Windows { | |||||||
|             AreaComTypeInput.SelectedItem = a.AreaComType; |             AreaComTypeInput.SelectedItem = a.AreaComType; | ||||||
|             WineCultivationInput.SelectedItem = a.WineCult; |             WineCultivationInput.SelectedItem = a.WineCult; | ||||||
|  |  | ||||||
|  |             CommentInput.Text = a.Comment; | ||||||
|  |  | ||||||
|             FinishInputFilling(); |             FinishInputFilling(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -151,6 +150,7 @@ namespace Elwig.Windows { | |||||||
|             a.Area = int.Parse(AreaInput.Text); |             a.Area = int.Parse(AreaInput.Text); | ||||||
|             a.VtrgId = (AreaComTypeInput.SelectedItem as AreaComType)?.VtrgId; |             a.VtrgId = (AreaComTypeInput.SelectedItem as AreaComType)?.VtrgId; | ||||||
|             a.CultId = (WineCultivationInput.SelectedItem as WineCult)?.CultId; |             a.CultId = (WineCultivationInput.SelectedItem as WineCult)?.CultId; | ||||||
|  |             a.Comment = (CommentInput.Text == "") ? null : CommentInput.Text; | ||||||
|  |  | ||||||
|             EntityEntry<AreaCom>? tr = null; |             EntityEntry<AreaCom>? tr = null; | ||||||
|             try { |             try { | ||||||
|   | |||||||
| @@ -117,6 +117,7 @@ namespace Elwig.Windows { | |||||||
|             await Context.SaveChangesAsync(); |             await Context.SaveChangesAsync(); | ||||||
|  |  | ||||||
|             foreach (var mod in ModifierList.Where(m => !ModifierIds.ContainsKey(m))) { |             foreach (var mod in ModifierList.Where(m => !ModifierIds.ContainsKey(m))) { | ||||||
|  |                 if (mod.ModId == null) continue; | ||||||
|                 await Context.AddAsync(mod); |                 await Context.AddAsync(mod); | ||||||
|             } |             } | ||||||
|             await Context.SaveChangesAsync(); |             await Context.SaveChangesAsync(); | ||||||
| @@ -321,6 +322,7 @@ namespace Elwig.Windows { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void SeasonModifierRelInput_TextChanged(object sender, TextChangedEventArgs evt) { |         private void SeasonModifierRelInput_TextChanged(object sender, TextChangedEventArgs evt) { | ||||||
|  |             // DecimalInput_TextChanged(sender, evt); FIXME '-' is ignored | ||||||
|             if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod) return; |             if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod) return; | ||||||
|             ModifiersChanged = ModifiersChanged || (SeasonModifierRelInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Rel?.ToString() ?? ""); |             ModifiersChanged = ModifiersChanged || (SeasonModifierRelInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Rel?.ToString() ?? ""); | ||||||
|             if (ModifierUpdate) return; |             if (ModifierUpdate) return; | ||||||
| @@ -331,11 +333,13 @@ namespace Elwig.Windows { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void SeasonModifierAbsInput_TextChanged(object sender, TextChangedEventArgs evt) { |         private void SeasonModifierAbsInput_TextChanged(object sender, TextChangedEventArgs evt) { | ||||||
|             if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod) return; |             // DecimalInput_TextChanged(sender, evt); FIXME '-' is ignored | ||||||
|  |             if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod || SeasonList.SelectedItem is not Season s) return; | ||||||
|             ModifiersChanged = ModifiersChanged || (SeasonModifierAbsInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Abs?.ToString() ?? ""); |             ModifiersChanged = ModifiersChanged || (SeasonModifierAbsInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Abs?.ToString() ?? ""); | ||||||
|             if (ModifierUpdate) return; |             if (ModifierUpdate) return; | ||||||
|             mod.Abs = decimal.TryParse(SeasonModifierAbsInput.Text, out var v) ? v : null; |             // FIXME ValueStr does not work in ModifierList when modifier is newly created | ||||||
|             if (mod.Abs != null) SeasonModifierRelInput.Text = ""; |             mod.AbsValue = decimal.TryParse(SeasonModifierAbsInput.Text, out var v) ? Utils.DecToDb(v, s.Precision) : null; | ||||||
|  |             if (mod.AbsValue != null) SeasonModifierRelInput.Text = ""; | ||||||
|             CollectionViewSource.GetDefaultView(ModifierList).Refresh(); |             CollectionViewSource.GetDefaultView(ModifierList).Refresh(); | ||||||
|             UpdateButtons(); |             UpdateButtons(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -272,22 +272,21 @@ | |||||||
|                           VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2" |                           VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2" | ||||||
|                           Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/> |                           Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/> | ||||||
|  |  | ||||||
|                 <Button x:Name="WeighingManualButton" Content="Handwiegung" Width="120" |  | ||||||
|                         Click="WeighingManualButton_Click" |  | ||||||
|                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,10,10,10" Grid.Column="2"/> |  | ||||||
|                 <Button x:Name="WeighingAButton" Content="Wiegen A" Width="120" |                 <Button x:Name="WeighingAButton" Content="Wiegen A" Width="120" | ||||||
|                         Click="WeighingButton_Click" |                         Click="WeighingButton_Click" | ||||||
|                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,42,10,10" Grid.Column="2"/> |                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,10,10,10" Grid.Column="2"/> | ||||||
|                 <Button x:Name="WeighingBButton" Content="Wiegen B" Width="120" |                 <Button x:Name="WeighingBButton" Content="Wiegen B" Width="120" | ||||||
|                         Click="WeighingButton_Click" |                         Click="WeighingButton_Click" | ||||||
|                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,74,10,10" Grid.Column="2"/> |                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,42,10,10" Grid.Column="2"/> | ||||||
|                 <Button x:Name="WeighingCButton" Content="Wiegen C" Width="120" |                 <Button x:Name="WeighingCButton" Content="Wiegen C" Width="120" | ||||||
|                         Click="WeighingButton_Click" |                         Click="WeighingButton_Click" | ||||||
|                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,106,10,10" Grid.Column="2"/> |                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,74,10,10" Grid.Column="2"/> | ||||||
|                 <Button x:Name="WeighingDButton" Content="Wiegen D" Width="120" |                 <Button x:Name="WeighingDButton" Content="Wiegen D" Width="120" | ||||||
|                         Click="WeighingButton_Click" |                         Click="WeighingButton_Click" | ||||||
|  |                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,106,10,10" Grid.Column="2"/> | ||||||
|  |                 <Button x:Name="WeighingManualButton" Content="Handwiegung" Width="120" | ||||||
|  |                         Click="WeighingManualButton_Click" | ||||||
|                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,138,10,10" Grid.Column="2"/> |                         VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,138,10,10" Grid.Column="2"/> | ||||||
|  |  | ||||||
|             </Grid> |             </Grid> | ||||||
|         </GroupBox> |         </GroupBox> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ namespace Elwig.Windows { | |||||||
|         private List<string> TextFilter = new(); |         private List<string> TextFilter = new(); | ||||||
|         private readonly RoutedCommand CtrlF = new(); |         private readonly RoutedCommand CtrlF = new(); | ||||||
|  |  | ||||||
|  |         private string? LastScaleError = null; | ||||||
|         private string? ManualWeighingReason = null; |         private string? ManualWeighingReason = null; | ||||||
|         private string? ScaleId = null; |         private string? ScaleId = null; | ||||||
|         private string? WeighingId = null; |         private string? WeighingId = null; | ||||||
| @@ -75,6 +76,7 @@ namespace Elwig.Windows { | |||||||
|                 if (n >= 2) WeighingBButton.Content = $"Wiegen {App.Scales[1].ScaleId}"; |                 if (n >= 2) WeighingBButton.Content = $"Wiegen {App.Scales[1].ScaleId}"; | ||||||
|                 if (n >= 3) WeighingCButton.Content = $"Wiegen {App.Scales[2].ScaleId}"; |                 if (n >= 3) WeighingCButton.Content = $"Wiegen {App.Scales[2].ScaleId}"; | ||||||
|                 if (n >= 4) WeighingDButton.Content = $"Wiegen {App.Scales[3].ScaleId}"; |                 if (n >= 4) WeighingDButton.Content = $"Wiegen {App.Scales[3].ScaleId}"; | ||||||
|  |                 WeighingManualButton.Margin = new Thickness(10, 10 + n * 32, 10, 10); | ||||||
|             } else { |             } else { | ||||||
|                 WeighingManualButton.Visibility = Visibility.Hidden; |                 WeighingManualButton.Visibility = Visibility.Hidden; | ||||||
|                 WeighingAButton.Visibility = Visibility.Hidden; |                 WeighingAButton.Visibility = Visibility.Hidden; | ||||||
| @@ -91,13 +93,13 @@ namespace Elwig.Windows { | |||||||
|             AllSeasonsInput.IsChecked = true; |             AllSeasonsInput.IsChecked = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private async void Window_Loaded(object sender, RoutedEventArgs evt) { |         private void Window_Loaded(object sender, RoutedEventArgs evt) { | ||||||
|             OnSecondPassed(null, null); |             OnSecondPassed(null, null); | ||||||
|             Timer.Start(); |             Timer.Start(); | ||||||
|             LockInputs(); |             LockInputs(); | ||||||
|             if (IsReceipt) { |             if (IsReceipt) { | ||||||
|                 NewDeliveryButton_Click(null, null); |                 NewDeliveryButton_Click(null, null); | ||||||
|                 if ((await Context.Seasons.FindAsync(Utils.CurrentYear)) == null) { |                 if ((Context.Seasons.Find(Utils.CurrentYear)) == null) { | ||||||
|                     MessageBox.Show("Die Saison für das aktuelle Jahr wurde noch nicht erstellt. Neue Lieferungen können nicht abgespeichert werden.", |                     MessageBox.Show("Die Saison für das aktuelle Jahr wurde noch nicht erstellt. Neue Lieferungen können nicht abgespeichert werden.", | ||||||
|                         "Saison noch nicht erstellt", MessageBoxButton.OK, MessageBoxImage.Error); |                         "Saison noch nicht erstellt", MessageBoxButton.OK, MessageBoxImage.Error); | ||||||
|                 } |                 } | ||||||
| @@ -147,6 +149,11 @@ namespace Elwig.Windows { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void InitialInputs() { |         private void InitialInputs() { | ||||||
|  |             LastScaleError = null; | ||||||
|  |             WeighingId = null; | ||||||
|  |             ScaleId = null; | ||||||
|  |             ManualWeighingReason = null; | ||||||
|  |  | ||||||
|             ClearOriginalValues(); |             ClearOriginalValues(); | ||||||
|             ClearDefaultValues(); |             ClearDefaultValues(); | ||||||
|  |  | ||||||
| @@ -331,7 +338,8 @@ namespace Elwig.Windows { | |||||||
|                     .ToList(); |                     .ToList(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             ControlUtils.RenewItemsSource(DeliveryList, deliveries, d => ((d as Delivery)?.Year, (d as Delivery)?.DId), DeliveryList_SelectionChanged, IsCreating ? ControlUtils.RenewSourceDefault.None : ControlUtils.RenewSourceDefault.IfOnly, !updateSort); |             ControlUtils.RenewItemsSource(DeliveryList, deliveries, d => ((d as Delivery)?.Year, (d as Delivery)?.DId), | ||||||
|  |                 DeliveryList_SelectionChanged, filter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort); | ||||||
|  |  | ||||||
|             var members = deliveries.Select(d => d.Member).DistinctBy(m => m.MgNr).ToList(); |             var members = deliveries.Select(d => d.Member).DistinctBy(m => m.MgNr).ToList(); | ||||||
|             StatusMembers.Text = $"Mitglieder: {members.Count}" + (members.Count > 0 && members.Count <= 4 ? $" ({string.Join(", ", members.Select(m => m.AdministrativeName))})" : ""); |             StatusMembers.Text = $"Mitglieder: {members.Count}" + (members.Count > 0 && members.Count <= 4 ? $" ({string.Join(", ", members.Select(m => m.AdministrativeName))})" : ""); | ||||||
| @@ -423,7 +431,6 @@ namespace Elwig.Windows { | |||||||
|                 Menu_Export_Bki.Items.Add(i); |                 Menu_Export_Bki.Items.Add(i); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // FIXME on "only one" delivery, RenewContext doees not work |  | ||||||
|             await RefreshDeliveryList(); |             await RefreshDeliveryList(); | ||||||
|             var d = DeliveryList.SelectedItem as Delivery; |             var d = DeliveryList.SelectedItem as Delivery; | ||||||
|             var y = d?.Year ?? Utils.CurrentLastSeason; |             var y = d?.Year ?? Utils.CurrentLastSeason; | ||||||
| @@ -441,6 +448,7 @@ namespace Elwig.Windows { | |||||||
|             if (IsCreating) await UpdateLsNr(); |             if (IsCreating) await UpdateLsNr(); | ||||||
|  |  | ||||||
|             await RefreshDeliveryParts(); |             await RefreshDeliveryParts(); | ||||||
|  |             RefreshInputs(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void FocusSearchInput(object sender, RoutedEventArgs evt) { |         private void FocusSearchInput(object sender, RoutedEventArgs evt) { | ||||||
| @@ -521,6 +529,7 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|             ScaleId = p?.ScaleId; |             ScaleId = p?.ScaleId; | ||||||
|             WeighingId = p?.WeighingId; |             WeighingId = p?.WeighingId; | ||||||
|  |             ManualWeighingReason = p?.WeighingReason; | ||||||
|  |  | ||||||
|             FinishInputFilling(); |             FinishInputFilling(); | ||||||
|         } |         } | ||||||
| @@ -551,7 +560,7 @@ namespace Elwig.Windows { | |||||||
|             p.DPNr = dpnr; |             p.DPNr = dpnr; | ||||||
|  |  | ||||||
|             d.DateString = string.Join("-", DateInput.Text.Split(".").Reverse()); |             d.DateString = string.Join("-", DateInput.Text.Split(".").Reverse()); | ||||||
|             if (IsCreating || InputHasChanged(DateInput)) { |             if (deliveryNew || InputHasChanged(DateInput)) { | ||||||
|                 d.LNr = await Context.NextLNr(d.Date); |                 d.LNr = await Context.NextLNr(d.Date); | ||||||
|             } |             } | ||||||
|             if (IsCreating) { |             if (IsCreating) { | ||||||
| @@ -582,8 +591,7 @@ namespace Elwig.Windows { | |||||||
|             p.ManualWeighing = ManualWeighingInput.IsChecked ?? false; |             p.ManualWeighing = ManualWeighingInput.IsChecked ?? false; | ||||||
|             p.ScaleId = ScaleId; |             p.ScaleId = ScaleId; | ||||||
|             p.WeighingId = WeighingId; |             p.WeighingId = WeighingId; | ||||||
|             if (ManualWeighingReason != null) |             p.WeighingReason = ManualWeighingReason; | ||||||
|                 p.Comment = (p.Comment != null ? $"{p.Comment} / " : "") + $"Begründung Handwiegung: {ManualWeighingReason}"; |  | ||||||
|  |  | ||||||
|             EntityEntry<Delivery>? dEntry = null; |             EntityEntry<Delivery>? dEntry = null; | ||||||
|             EntityEntry<DeliveryPart>? pEntry = null; |             EntityEntry<DeliveryPart>? pEntry = null; | ||||||
| @@ -649,12 +657,18 @@ namespace Elwig.Windows { | |||||||
|                     ScaleId = null; |                     ScaleId = null; | ||||||
|                     WeighingId = null; |                     WeighingId = null; | ||||||
|                 } |                 } | ||||||
|                 ManualWeighingReason = null; |                 LastScaleError = null; | ||||||
|                 ManualWeighingInput.IsChecked = false; |  | ||||||
|             } catch (Exception e) { |             } catch (Exception e) { | ||||||
|  |                 LastScaleError = e.Message.Split(": ")[^1]; | ||||||
|  |                 WeightInput.Text = ""; | ||||||
|  |                 ScaleId = null; | ||||||
|  |                 WeighingId = null; | ||||||
|                 MessageBox.Show($"Beim Wiegen ist ein Fehler aufgetreten:\n\n{e.Message}", "Waagenfehler", |                 MessageBox.Show($"Beim Wiegen ist ein Fehler aufgetreten:\n\n{e.Message}", "Waagenfehler", | ||||||
|                        MessageBoxButton.OK, MessageBoxImage.Error); |                        MessageBoxButton.OK, MessageBoxImage.Error); | ||||||
|             } |             } | ||||||
|  |             ManualWeighingReason = null; | ||||||
|  |             ManualWeighingInput.IsChecked = false; | ||||||
|  |             base.TextBox_TextChanged(WeightInput, null); | ||||||
|             EnableWeighingButtons(); |             EnableWeighingButtons(); | ||||||
|             UpdateButtons(); |             UpdateButtons(); | ||||||
|         } |         } | ||||||
| @@ -771,8 +785,11 @@ namespace Elwig.Windows { | |||||||
|                 using var doc = new DeliveryNote(p.Delivery, Context); |                 using var doc = new DeliveryNote(p.Delivery, Context); | ||||||
|                 await doc.Generate(); |                 await doc.Generate(); | ||||||
|                 Mouse.OverrideCursor = null; |                 Mouse.OverrideCursor = null; | ||||||
|                 doc.Show(); |                 if (App.Config.Debug) { | ||||||
|                 //await doc.Print(2); |                     doc.Show(); | ||||||
|  |                 } else { | ||||||
|  |                     await doc.Print(2); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             FinishButton.Cursor = null; |             FinishButton.Cursor = null; | ||||||
|             DeliveryList.SelectedItem = null; |             DeliveryList.SelectedItem = null; | ||||||
| @@ -880,7 +897,7 @@ namespace Elwig.Windows { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void WeighingManualButton_Click(object sender, RoutedEventArgs evt) { |         private void WeighingManualButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|             var res = Utils.ShowManualWeighingDialog(); |             var res = Utils.ShowManualWeighingDialog(LastScaleError); | ||||||
|             if (res == null) return; |             if (res == null) return; | ||||||
|             WeightInput.Text = $"{res?.Item1:N0}"; |             WeightInput.Text = $"{res?.Item1:N0}"; | ||||||
|             ManualWeighingInput.IsChecked = true; |             ManualWeighingInput.IsChecked = true; | ||||||
|   | |||||||
| @@ -5,6 +5,10 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|         public MainWindow() { |         public MainWindow() { | ||||||
|             InitializeComponent(); |             InitializeComponent(); | ||||||
|  |             if (!App.Config.Debug) { | ||||||
|  |                 TestWindowButton.Visibility = Visibility.Hidden; | ||||||
|  |                 //QueryWindowButton.Visibility = Visibility.Hidden; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void Window_Loaded(object sender, RoutedEventArgs evt) { } |         private void Window_Loaded(object sender, RoutedEventArgs evt) { } | ||||||
|   | |||||||
| @@ -178,60 +178,64 @@ | |||||||
|                     <ColumnDefinition Width="2*"/> |                     <ColumnDefinition Width="2*"/> | ||||||
|                 </Grid.ColumnDefinitions> |                 </Grid.ColumnDefinitions> | ||||||
|  |  | ||||||
|                 <Label Content="E-Mail-Adresse:" Margin="10,10,0,0" Grid.Column="0"/> |                 <Label Content="E-Mail-Adresse (1):" Margin="10,10,0,0" Grid.Column="0"/> | ||||||
|                 <TextBox x:Name="EmailAddressInput" Margin="0,10,10,0" Grid.Column="1" Grid.ColumnSpan="2" |                 <TextBox x:Name="EmailAddress1Input" Margin="0,10,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|                          TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> |                          TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr1TypeInput" DisplayMemberPath="Value" Margin="6,40,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <Label Content="E-Mail-Adresse (2):" Margin="10,40,0,0" Grid.Column="0"/> | ||||||
|                 <TextBox x:Name="PhoneNr1Input" Margin="0,40,5,0" Grid.Column="1" |                 <TextBox x:Name="EmailAddress2Input" Margin="0,40,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|  |                          TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|  |                 <ComboBox x:Name="PhoneNr1TypeInput" DisplayMemberPath="Value" Margin="6,70,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|  |                 <TextBox x:Name="PhoneNr1Input" Margin="0,70,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr1CommentInput" Margin="0,40,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr1CommentInput" Margin="0,70,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr2TypeInput" DisplayMemberPath="Value" Margin="6,70,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <ComboBox x:Name="PhoneNr2TypeInput" DisplayMemberPath="Value" Margin="6,100,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                 <TextBox x:Name="PhoneNr2Input" Margin="0,70,5,0" Grid.Column="1" |                 <TextBox x:Name="PhoneNr2Input" Margin="0,100,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr2CommentInput" Margin="0,70,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr2CommentInput" Margin="0,100,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr3TypeInput" DisplayMemberPath="Value" Margin="6,100,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <ComboBox x:Name="PhoneNr3TypeInput" DisplayMemberPath="Value" Margin="6,130,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                 <TextBox x:Name="PhoneNr3Input" Margin="0,100,5,0" Grid.Column="1" |                 <TextBox x:Name="PhoneNr3Input" Margin="0,130,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr3CommentInput" Margin="0,100,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr3CommentInput" Margin="0,130,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr4TypeInput" DisplayMemberPath="Value" Margin="6,130,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <ComboBox x:Name="PhoneNr4TypeInput" DisplayMemberPath="Value" Margin="6,160,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                 <TextBox x:Name="PhoneNr4Input" Margin="0,130,5,0" Grid.Column="1" |                 <TextBox x:Name="PhoneNr4Input" Margin="0,160,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr4CommentInput" Margin="0,130,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr4CommentInput" Margin="0,160,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr5TypeInput" DisplayMemberPath="Value" Margin="6,160,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <ComboBox x:Name="PhoneNr5TypeInput" DisplayMemberPath="Value" Margin="6,190,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                 <TextBox x:Name="PhoneNr5Input" Margin="0,160,5,0" Grid.Column="1" |                 <TextBox x:Name="PhoneNr5Input" Margin="0,190,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr5CommentInput" Margin="0,160,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr5CommentInput" Margin="0,190,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr6TypeInput" DisplayMemberPath="Value" Margin="6,190,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <ComboBox x:Name="PhoneNr6TypeInput" DisplayMemberPath="Value" Margin="6,220,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                 <TextBox x:Name="PhoneNr6Input" Margin="0,190,5,0" Grid.Column="1" |                 <TextBox x:Name="PhoneNr6Input" Margin="0,220,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr6CommentInput" Margin="0,190,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr6CommentInput" Margin="0,220,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr7TypeInput" DisplayMemberPath="Value" Margin="6,220,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <ComboBox x:Name="PhoneNr7TypeInput" DisplayMemberPath="Value" Margin="6,250,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                 <TextBox x:Name="PhoneNr7Input" Margin="0,220,5,0" Grid.Column="1" |                 <TextBox x:Name="PhoneNr7Input" Margin="0,250,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr7CommentInput" Margin="0,220,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr7CommentInput" Margin="0,250,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr8TypeInput" DisplayMemberPath="Value" Margin="6,250,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <ComboBox x:Name="PhoneNr8TypeInput" DisplayMemberPath="Value" Margin="6,280,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                 <TextBox x:Name="PhoneNr8Input" Margin="0,250,5,0" Grid.Column="1" |                 <TextBox x:Name="PhoneNr8Input" Margin="0,280,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr8CommentInput" Margin="0,250,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr8CommentInput" Margin="0,280,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |  | ||||||
|                 <ComboBox x:Name="PhoneNr9TypeInput" DisplayMemberPath="Value" Margin="6,280,5,0" FontSize="12" Padding="6,4,4,4"/> |                 <ComboBox x:Name="PhoneNr9TypeInput" DisplayMemberPath="Value" Margin="6,310,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                 <TextBox x:Name="PhoneNr9Input" Margin="0,280,5,0" Grid.Column="1" |                 <TextBox x:Name="PhoneNr9Input" Margin="0,310,5,0" Grid.Column="1" | ||||||
|                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                          TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|                 <TextBox x:Name="PhoneNr9CommentInput" Margin="0,280,10,0" Grid.Column="2" |                 <TextBox x:Name="PhoneNr9CommentInput" Margin="0,280,10,0" Grid.Column="2" | ||||||
|                          TextChanged="TextBox_TextChanged"/> |                          TextChanged="TextBox_TextChanged"/> | ||||||
|   | |||||||
| @@ -89,7 +89,8 @@ namespace Elwig.Windows { | |||||||
|                     .ToList(); |                     .ToList(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             ControlUtils.RenewItemsSource(MemberList, members, i => (i as Member)?.MgNr, MemberList_SelectionChanged, ControlUtils.RenewSourceDefault.IfOnly, !updateSort); |             ControlUtils.RenewItemsSource(MemberList, members, i => (i as Member)?.MgNr, | ||||||
|  |                 MemberList_SelectionChanged, TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void RefreshInputs(bool validate = false) { |         private void RefreshInputs(bool validate = false) { | ||||||
| @@ -265,7 +266,7 @@ namespace Elwig.Windows { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void Menu_Member_SendEmail_Click(object sender, RoutedEventArgs evt) { |         private void Menu_Member_SendEmail_Click(object sender, RoutedEventArgs evt) { | ||||||
|             Utils.MailTo(((Member)MemberList.SelectedItem).Email); |             Utils.MailTo(((Member)MemberList.SelectedItem).EmailAddresses.First().Address); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void FocusSearchInput(object sender, RoutedEventArgs evt) { |         private void FocusSearchInput(object sender, RoutedEventArgs evt) { | ||||||
| @@ -348,8 +349,6 @@ namespace Elwig.Windows { | |||||||
|             m.PostalDestId = ((AT_PlzDest)OrtInput.SelectedItem).Id; |             m.PostalDestId = ((AT_PlzDest)OrtInput.SelectedItem).Id; | ||||||
|             m.Address = AddressInput.Text; |             m.Address = AddressInput.Text; | ||||||
|  |  | ||||||
|             m.Email = (EmailAddressInput.Text == "") ? null : EmailAddressInput.Text; |  | ||||||
|  |  | ||||||
|             m.Iban = (IbanInput.Text == "") ? null : IbanInput.Text.Replace(" ", ""); |             m.Iban = (IbanInput.Text == "") ? null : IbanInput.Text.Replace(" ", ""); | ||||||
|             m.Bic = (BicInput.Text == "") ? null : BicInput.Text; |             m.Bic = (BicInput.Text == "") ? null : BicInput.Text; | ||||||
|  |  | ||||||
| @@ -423,6 +422,27 @@ namespace Elwig.Windows { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |                 for (int i = 0; i < 2; i++) { | ||||||
|  |                     var input = i == 0 ? EmailAddress1Input : EmailAddress2Input; | ||||||
|  |                     var emailAddr = m.EmailAddresses.FirstOrDefault(a => a.Nr - 1 == i); | ||||||
|  |                     if (input.Text == "") { | ||||||
|  |                         if (emailAddr != null) { | ||||||
|  |                             Context.Remove(emailAddr); | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         MemberEmailAddr a = emailAddr ?? Context.CreateProxy<MemberEmailAddr>(); | ||||||
|  |                         a.Nr = i + 1; | ||||||
|  |                         a.Address = input.Text; | ||||||
|  |                         a.Comment = null; | ||||||
|  |                         if (emailAddr == null) { | ||||||
|  |                             a.MgNr = newMgNr; | ||||||
|  |                             await Context.AddAsync(a); | ||||||
|  |                         } else { | ||||||
|  |                             Context.Update(a); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|                 await Context.SaveChangesAsync(); |                 await Context.SaveChangesAsync(); | ||||||
|  |  | ||||||
|                 if (newMgNr != m.MgNr) { |                 if (newMgNr != m.MgNr) { | ||||||
| @@ -474,7 +494,10 @@ namespace Elwig.Windows { | |||||||
|                 OrtInput.SelectedItem = null; |                 OrtInput.SelectedItem = null; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             EmailAddressInput.Text = m.Email; |             var emailAddrs = m.EmailAddresses.OrderBy(a => a.Nr).ToList(); | ||||||
|  |             EmailAddress1Input.Text = emailAddrs.Count > 0 ? emailAddrs[0].Address : ""; | ||||||
|  |             EmailAddress2Input.Text = emailAddrs.Count > 1 ? emailAddrs[1].Address : ""; | ||||||
|  |  | ||||||
|             var phoneNrs = m.TelephoneNumbers.OrderBy(p => p.Nr).ToList(); |             var phoneNrs = m.TelephoneNumbers.OrderBy(p => p.Nr).ToList(); | ||||||
|             for (int i = 0; i < PhoneNrInputs.Length; i++) { |             for (int i = 0; i < PhoneNrInputs.Length; i++) { | ||||||
|                 if (i < phoneNrs.Count) { |                 if (i < phoneNrs.Count) { | ||||||
| @@ -524,7 +547,7 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|             AreaCommitment.Text = $"{m.ActiveAreaCommitments.Select(c => c.Area).Sum():N0} m²"; |             AreaCommitment.Text = $"{m.ActiveAreaCommitments.Select(c => c.Area).Sum():N0} m²"; | ||||||
|  |  | ||||||
|             Menu_Member_SendEmail.IsEnabled = m.Email != null; |             Menu_Member_SendEmail.IsEnabled = m.EmailAddresses.Count > 0; | ||||||
|  |  | ||||||
|             FinishInputFilling(); |             FinishInputFilling(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
| [general] | [general] | ||||||
| ; Only needed, if more than one branch is stored in database | ; Only needed, if more than one branch is stored in database | ||||||
| branch = Zweigstelle | branch = Zweigstelle | ||||||
|  | ;debug = true | ||||||
|  |  | ||||||
| [database] | [database] | ||||||
| ; Relative or absolute path to database file | ; Relative or absolute path to database file | ||||||
|   | |||||||
| @@ -72,14 +72,14 @@ namespace Tests { | |||||||
|         [Test] |         [Test] | ||||||
|         public void Test_SplitAddress() { |         public void Test_SplitAddress() { | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 1"), Is.EqualTo(("Winzerstra<EFBFBD>e", "1"))); |                 Assert.That(Utils.SplitAddress("Winzerstraße 1"), Is.EqualTo(("Winzerstraße", "1"))); | ||||||
|                 Assert.That(Utils.SplitAddress("Auf dem Feld 12"), Is.EqualTo(("Auf dem Feld", "12"))); |                 Assert.That(Utils.SplitAddress("Auf dem Feld 12"), Is.EqualTo(("Auf dem Feld", "12"))); | ||||||
|                 Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 5a"), Is.EqualTo(("Winzerstra<EFBFBD>e", "5a"))); |                 Assert.That(Utils.SplitAddress("Winzerstraße 5a"), Is.EqualTo(("Winzerstraße", "5a"))); | ||||||
|                 Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 1-3/2"), Is.EqualTo(("Winzerstra<EFBFBD>e", "1-3/2"))); |                 Assert.That(Utils.SplitAddress("Winzerstraße 1-3/2"), Is.EqualTo(("Winzerstraße", "1-3/2"))); | ||||||
|                 Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 3/4/5"), Is.EqualTo(("Winzerstra<EFBFBD>e", "3/4/5"))); |                 Assert.That(Utils.SplitAddress("Winzerstraße 3/4/5"), Is.EqualTo(("Winzerstraße", "3/4/5"))); | ||||||
|                 Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 7/2/4/77"), Is.EqualTo(("Winzerstra<EFBFBD>e", "7/2/4/77"))); |                 Assert.That(Utils.SplitAddress("Winzerstraße 7/2/4/77"), Is.EqualTo(("Winzerstraße", "7/2/4/77"))); | ||||||
|                 Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 95b"), Is.EqualTo(("Winzerstra<EFBFBD>e", "95b"))); |                 Assert.That(Utils.SplitAddress("Winzerstraße 95b"), Is.EqualTo(("Winzerstraße", "95b"))); | ||||||
|                 Assert.That(Utils.SplitAddress("Winzerstra<EFBFBD>e 1, TOP 3"), Is.EqualTo(("Winzerstra<EFBFBD>e", "1, TOP 3"))); |                 Assert.That(Utils.SplitAddress("Winzerstraße 1, TOP 3"), Is.EqualTo(("Winzerstraße", "1, TOP 3"))); | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user