Compare commits

...

55 Commits

Author SHA1 Message Date
de298ffef1 Bump verion to 0.3.4 2023-09-29 23:01:39 +02:00
eaf7b6bd41 DeliveryJournal: Fix ordering 2 2023-09-29 15:38:30 +02:00
2bb8205da0 DeliveryJournal: Fix ordering 2023-09-29 15:25:29 +02:00
f623aa1fee DeliveryAdminWindow: use 'unter' instead of 'bis' for gradation in journal 2023-09-29 15:16:44 +02:00
00e7eeb774 DeliveryAdminWindow: Fix delivery ordering 2023-09-29 15:01:35 +02:00
47d51ded51 DeliveryAdminWindow: Allow date and time to be edited 2023-09-29 14:46:28 +02:00
532bb826e1 MemberAdminWindow: Only print letterheads of members with contact via post checkbox 2023-09-29 13:06:27 +02:00
8193bf483c BusinessDocument: Update Address generation 2023-09-29 12:59:00 +02:00
34dcaf26d9 DeliveryAdminWindow: Center WineVariety column 2023-09-28 22:03:58 +02:00
7411f570ee DeliveryAdminWindow: Add ToolTip to StatusBar 2023-09-28 21:34:55 +02:00
52702f3fa2 DeliveryAdminWindow: Add GridSplitter 2023-09-28 21:28:31 +02:00
7f3573cede DeliveryAdminWindow: Add Gradation to DataGrid 2023-09-28 20:55:54 +02:00
72359dc8be MemberAdminWindow: Add warning for printing Letterheads 2023-09-28 20:17:53 +02:00
0e17aa5408 Windows: Use Cursor.AppStarting instead of Cursor.Wait 2023-09-28 20:09:12 +02:00
2bf850bc55 Documents/Pdf: Add /s to PdfToPrinter call 2023-09-28 20:05:29 +02:00
aadf536d13 Windows: Fix Tag="Print" issue 2023-09-28 20:04:05 +02:00
3be6371be1 ControlUtils: Fix FinAllChildren 2023-09-28 20:03:00 +02:00
ca1b68aa4f Documents: Add Letterhead 2023-09-28 19:38:29 +02:00
d4e5ac6753 MemberAdminWindow: Send email to all addresses of member 2023-09-28 15:50:04 +02:00
c9f49927a8 BusinessDocument: Do not hard code destination country 2023-09-28 14:35:54 +02:00
1794b5b8ca BusinessDocument: Use Ort Name instead of Destination Name 2023-09-28 14:23:18 +02:00
7347439034 Bump version number 2023-09-28 14:06:47 +02:00
51ad8f99fd DeliveryAdminWindow: Add DeliveryJournal filter options 2023-09-19 19:31:02 +02:00
39279a5dda Bump version to 0.3.2 2023-09-19 16:29:34 +02:00
5271f357f5 DeliveryAdminWindow: Add DeliveryJournal 2023-09-19 02:11:30 +02:00
13ba3f90f6 DeliveryAdminWindow: Add Filter to BKI export 2023-09-19 00:57:59 +02:00
43be8bf391 DeliveryAdminWindow: Empty scale only after saving to database 2023-09-19 00:47:10 +02:00
826a76c56c AppDbUpdater: Add schema_version 2 2023-09-19 00:37:46 +02:00
efaae5f490 DeliveryAdminWindow: 'Activate()' window after awaiting doc.Print(2) 2023-09-18 21:48:03 +02:00
3a73265a75 ContextWindow: Change renew context event handling 2023-09-18 21:46:14 +02:00
a6fef7fd9b Utils: Fix GetSearchScore for multiple occurances of keyword in haystack 2023-09-18 21:17:37 +02:00
a08df4c3ed DeliveryAdminWindow: Add auto focus for weighing buttons on enter 2023-09-18 20:59:59 +02:00
9701af9e36 AppDbUpdater: Fix version comparison 2023-09-18 10:03:48 +02:00
b4f1eeee84 Bump version to 0.3.1 2023-09-18 02:05:16 +02:00
2922fe0138 BaseDataWindow: Remove DecimalInput check 2023-09-18 01:40:59 +02:00
704facbc6b App: Use Ort insteas of Destination for Branch Location 2023-09-18 01:32:54 +02:00
404e8a0c27 BaseDataWindow: Fix Modifier creation 2023-09-18 01:30:45 +02:00
ef621fab2d Validator: Fix usage of maxLen and maxDecimal in CheckDecimal 2023-09-18 01:27:15 +02:00
0938e33fe1 DeliveryAdminWindow: Fix LNr calculation for new deliveries 2023-09-18 01:04:09 +02:00
6b5c283e10 Update dependencies 2023-09-17 22:12:15 +02:00
b6400c41c4 Bump version to 0.3.0 2023-09-17 21:31:06 +02:00
24b7078a05 Add AppDbUpdater 2023-09-17 20:48:07 +02:00
dc215d3350 BusinessDocument: Make aside table a bit more compact 2023-09-15 14:35:25 +02:00
b80cbc037c AreaComAdminWindow: Add comment input 2023-09-14 23:43:38 +02:00
4891501f62 DeliveryAdminWindow: Fix filter count check 2023-09-14 23:27:43 +02:00
6d3adc48f6 DeliveryNote: Add manual weighing reason 2023-09-14 23:25:37 +02:00
f5eea1e906 Models: Add MemberEmailAddr 2023-09-14 22:32:28 +02:00
ba691f4d17 Documents: Make business documents more compact 2023-09-14 20:44:48 +02:00
470f092482 DeliveryAdminWindow: Move manual weighing button to last position 2023-09-14 17:51:48 +02:00
e9e4c75edd Bump version to 0.2.1 2023-09-13 23:37:26 +02:00
ff1a4e7182 Documents: Add ShowFoldMarks flag 2023-09-13 23:22:35 +02:00
1e9cad6de7 DeliveryAdminWindow: Use last scale error as default manual weighing reason 2023-09-13 23:19:04 +02:00
62fe087598 DeliveryAdminWindow: Hopefully fix 'Erste Übernahme' bug 2023-09-13 22:57:21 +02:00
7f01b85878 HelpersUtilsTest: fix file encoding 2023-09-13 22:04:01 +02:00
a659d07db2 Config: add debug flag 2023-09-13 22:02:50 +02:00
45 changed files with 1250 additions and 498 deletions

View File

@ -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;
@ -144,9 +157,12 @@ namespace Elwig {
protected void OnPrintingReadyChanged(EventArgs evt) { protected void OnPrintingReadyChanged(EventArgs evt) {
foreach (Window w in Windows) { foreach (Window w in Windows) {
foreach (var b in ControlUtils.FindAllChildren<Button>(w).Where(b => "Print".Equals(b.Tag))) { foreach (var b in ControlUtils.FindAllChildren<Button>(w).Where(b => b.Tag?.ToString() == "Print")) {
b.IsEnabled = IsPrintingReady; b.IsEnabled = IsPrintingReady;
} }
foreach (var i in ControlUtils.FindAllChildren<MenuItem>(w).Where(i => i.Tag?.ToString() == "Print")) {
i.IsEnabled = IsPrintingReady;
}
} }
} }
} }

View File

@ -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();
} }

View File

@ -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()

View File

@ -1,8 +1,11 @@
using Elwig.Helpers;
using Elwig.Models; 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 +14,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>" +
@ -24,14 +27,9 @@ namespace Elwig.Documents {
public string Address { public string Address {
get { get {
var b = Member.BillingAddress; IAddress addr = (Member.BillingAddress != null && UseBillingAddress) ? Member.BillingAddress : Member;
if (b != null && UseBillingAddress) { var plz = addr.PostalDest.AtPlz;
var plz = b.PostalDest.AtPlz; return (addr is BillingAddr ? $"{addr.Name}\n" : "") + $"{Member.AdministrativeName}\n{addr.Address}\n{plz?.Plz} {plz?.Ort.Name.Split(",")[0]}\n{addr.PostalDest.Country.Name}";
return $"{b.Name}\n{Member.AdministrativeName}\n{b.Address}\n{plz.Plz} {plz.Dest}\nÖsterreich";
} else {
var plz = Member.PostalDest.AtPlz;
return $"{Member.AdministrativeName}\n{Member.Address}\n{plz.Plz} {plz.Dest}\nÖsterreich";
}
} }
} }
} }

View File

@ -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>

View File

@ -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>" +

View File

@ -0,0 +1,67 @@
@using RazorLight
@inherits TemplatePage<Elwig.Documents.DeliveryJournal>
@model Elwig.Documents.DeliveryJournal
@{ Layout = "Document"; }
<link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\style-deliveryjournal.css"/>
<main>
<h1>Lieferjournal</h1>
<h2>@Model.Filter</h2>
<table class="journal">
<colgroup>
<col style="width: 25mm;"/>
<col style="width: 5mm;"/>
<col style="width: 17mm;"/>
<col style="width: 10mm;"/>
<col style="width: 8mm;"/>
<col style="width: 38mm;"/>
<col style="width: 28mm;"/>
<col style="width: 10mm;"/>
<col style="width: 10mm;"/>
<col style="width: 14mm;"/>
</colgroup>
<thead>
<tr>
<th rowspan="2" style="text-align: left;">Lieferschein-Nr.</th>
<th rowspan="2">Pos.</th>
<th rowspan="2">Datum</th>
<th rowspan="2">Zeit</th>
<th colspan="2" rowspan="2" style="text-align: left;">Mitglied</th>
<th rowspan="2" style="text-align: left;">Sorte</th>
<th colspan="2">Gradation</th>
<th>Gewicht</th>
</tr>
<tr>
<th>[°Oe]</th>
<th>[°KMW]</th>
<th>[kg]</th>
</tr>
</thead>
<tbody>
@foreach (var p in Model.Deliveries) {
<tr>
<td>@p.Delivery.LsNr</td>
<td>@p.DPNr</td>
<td>@($"{p.Delivery.Date:dd.MM.yyyy}")</td>
<td>@($"{p.Delivery.Time:HH:mm}")</td>
<td class="mgnr">@p.Delivery.Member.MgNr</td>
<td>@p.Delivery.Member.AdministrativeName</td>
<td>@p.Variant.Name</td>
<td class="grad">@($"{p.Oe:N0}")</td>
<td class="grad">@($"{p.Kmw:N1}")</td>
<td class="weight">@($"{p.Weight:N0}")</td>
</tr>
}
<tr class="sum">
@{
var kmw = Elwig.Helpers.Utils.AggregateDeliveryPartsKmw(Model.Deliveries);
var oe = Elwig.Helpers.Utils.KmwToOe(kmw);
}
<td colspan="2">Gesamt:</td>
<td colspan="5">(Teil-)Lieferungen: @($"{Model.Deliveries.DistinctBy(p => p.Delivery).Count():N0}") (@($"{Model.Deliveries.Count():N0}"))</td>
<td class="grad">@($"{oe:N0}")</td>
<td class="grad">@($"{kmw:N1}")</td>
<td class="weight">@($"{Model.Deliveries.Sum(p => p.Weight):N0}")</td>
</tr>
</tbody>
</table>
</main>

View File

@ -0,0 +1,34 @@
using Elwig.Helpers;
using Elwig.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Elwig.Documents {
public class DeliveryJournal : Document {
public string Filter;
public IEnumerable<DeliveryPart> Deliveries;
public DeliveryJournal(string filter, IEnumerable<DeliveryPart> deliveries) : base($"Lieferjournal {filter}") {
Filter = filter;
Deliveries = deliveries;
}
public DeliveryJournal(string filter, IQueryable<DeliveryPart> deliveries) :
this(filter, deliveries
.Include(p => p.Delivery)
.Include(p => p.Delivery.Member)
.Include(p => p.Variant)
.ToList()) { }
public DeliveryJournal(AppDbContext ctx, DateOnly date) :
this(date.ToString("dd.MM.yyyy"), ctx.DeliveryParts
.Where(p => p.Delivery.DateString == date.ToString("yyy-MM-dd"))
.OrderBy(p => p.Delivery.DateString)
.ThenBy(p => p.Delivery.TimeString)
.ThenBy(p => p.Delivery.LsNr)
.ThenBy(p => p.DPNr)) { }
}
}

View File

@ -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))

View File

@ -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>" +

View File

@ -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>

View File

@ -2,11 +2,17 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.IO; using System.IO;
using Elwig.Helpers; using Elwig.Helpers;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;
namespace Elwig.Documents { namespace Elwig.Documents {
public abstract class Document : IDisposable { public abstract partial class Document : IDisposable {
private TempFile? PdfFile = null; private TempFile? _pdfFile = null;
private string? _renderedHtml = null;
public bool ShowFoldMarks = App.Config.Debug;
public string DataPath; public string DataPath;
public int CurrentNextSeason; public int CurrentNextSeason;
@ -22,8 +28,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()
@ -33,17 +39,56 @@ namespace Elwig.Documents {
Date = DateTime.Today; Date = DateTime.Today;
} }
[GeneratedRegex(@"</body>.*?</footer>\s*</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)]
private static partial Regex GeneratedDocumentHeaderRegex();
private static readonly Regex DocumentHeaderRegex = GeneratedDocumentHeaderRegex();
[GeneratedRegex(@"<style>.*?/style>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)]
private static partial Regex GeneratedHtmlStyleRegex();
private static readonly Regex HtmlStyleRegex = GeneratedHtmlStyleRegex();
[GeneratedRegex(@"<link[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)]
private static partial Regex GeneratedHtmlLinkRegex();
private static readonly Regex HtmlLinkRegex = GeneratedHtmlLinkRegex();
~Document() { ~Document() {
Dispose(); Dispose();
} }
public void Dispose() { public void Dispose() {
PdfFile?.Dispose(); _pdfFile?.Dispose();
PdfFile = null; _pdfFile = null;
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
private Task<string> Render() { public static async Task<Document> Merge(IEnumerable<Document> docs) {
string html = "";
var styles = new List<string>();
foreach (var d in docs) {
var h = await d.Render();
var s = HtmlStyleRegex.Matches(h).Select(m => m.Value).ToList();
var l = HtmlLinkRegex.Matches(h).Select(m => m.Value).ToList();
if (s.All(styles.Contains)) {
h = HtmlStyleRegex.Replace(h, "");
} else {
styles.AddRange(s);
}
if (l.All(styles.Contains)) {
h = HtmlLinkRegex.Replace(h, "");
} else {
styles.AddRange(l);
}
html += h;
}
html = DocumentHeaderRegex.Replace(html, "<div class='document-break'/>");
return new InternalDocument("Mehrere Dokumente") {
_renderedHtml = html,
};
}
private async Task<string> Render() {
if (_renderedHtml != null)
return _renderedHtml;
string name; string name;
if (this is BusinessLetter) { if (this is BusinessLetter) {
name = "BusinessLetter"; name = "BusinessLetter";
@ -51,14 +96,19 @@ namespace Elwig.Documents {
name = "DeliveryNote"; name = "DeliveryNote";
} else if (this is CreditNote) { } else if (this is CreditNote) {
name = "CreditNote"; name = "CreditNote";
} else if (this is DeliveryJournal) {
name = "DeliveryJournal";
} else if (this is Letterhead) {
name = "Letterhead";
} else { } else {
throw new InvalidOperationException("Invalid document object"); throw new InvalidOperationException("Invalid document object");
} }
return Render(name); return await Render(name);
} }
private Task<string> Render(string name) { private async Task<string> Render(string name) {
return Html.CompileRenderAsync(name, this); _renderedHtml = await Html.CompileRenderAsync(name, this);
return _renderedHtml;
} }
public async Task Generate() { public async Task Generate() {
@ -67,22 +117,26 @@ namespace Elwig.Documents {
await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Utils.UTF8); await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Utils.UTF8);
await Pdf.Convert(tmpHtml.FilePath, pdf.FilePath); await Pdf.Convert(tmpHtml.FilePath, pdf.FilePath);
} }
PdfFile = pdf; _pdfFile = pdf;
} }
public void SaveTo(string pdfPath) { public void SaveTo(string pdfPath) {
if (PdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet"); if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet");
File.Copy(PdfFile.FilePath, pdfPath); File.Copy(_pdfFile.FilePath, pdfPath);
} }
public async Task Print(int copies = 1) { public async Task Print(int copies = 1) {
if (PdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet"); if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet");
await Pdf.Print(PdfFile.FilePath, copies); await Pdf.Print(_pdfFile.FilePath, copies);
} }
public void Show() { public void Show() {
if (PdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet"); if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet");
Pdf.Show(PdfFile.NewReference(), Title); Pdf.Show(_pdfFile.NewReference(), Title);
}
private class InternalDocument : Document {
public InternalDocument(string title) : base(title) { }
} }
} }
} }

View File

@ -19,6 +19,8 @@ namespace Elwig.Documents {
await e.CompileTemplateAsync("BusinessLetter"); await e.CompileTemplateAsync("BusinessLetter");
await e.CompileTemplateAsync("DeliveryNote"); await e.CompileTemplateAsync("DeliveryNote");
await e.CompileTemplateAsync("CreditNote"); await e.CompileTemplateAsync("CreditNote");
await e.CompileTemplateAsync("DeliveryJournal");
await e.CompileTemplateAsync("Letterhead");
Engine = e; Engine = e;
evtHandler(); evtHandler();

View File

@ -0,0 +1,9 @@
@using RazorLight
@inherits TemplatePage<Elwig.Documents.Letterhead>
@model Elwig.Documents.Letterhead
@{ Layout = "BusinessDocument"; }
<style>
header, .footer-wrapper {
visibility: hidden;
}
</style>

View File

@ -0,0 +1,9 @@
using Elwig.Models;
namespace Elwig.Documents {
public class Letterhead : BusinessDocument {
public Letterhead(Member m) : base($"Briefkopf {m.Name}", m, true) {
Aside = "";
}
}
}

View File

@ -59,6 +59,7 @@ namespace Elwig.Documents {
public static async Task Print(string path, int copies = 1) { public static async Task Print(string path, int copies = 1) {
var p = new Process() { StartInfo = new() { FileName = PdfToPrinter } }; var p = new Process() { StartInfo = new() { FileName = PdfToPrinter } };
p.StartInfo.ArgumentList.Add(path); p.StartInfo.ArgumentList.Add(path);
p.StartInfo.ArgumentList.Add("/s");
p.StartInfo.ArgumentList.Add($"copies={copies}"); p.StartInfo.ArgumentList.Add($"copies={copies}");
p.Start(); p.Start();
await p.WaitForExitAsync(); await p.WaitForExitAsync();

View File

@ -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;
} }

View File

@ -0,0 +1,47 @@
h1 {
text-align: center;
font-size: 24pt;
margin-bottom: 2mm;
}
h2 {
text-align: center;
font-size: 14pt;
margin-top: 2mm;
}
table.journal {
font-size: 10pt;
}
table.journal thead {
font-size: 8pt;
}
table.journal th {
font-weight: normal;
font-style: italic;
}
table.journal td {
overflow: hidden;
white-space: nowrap;
}
table.journal .mgnr,
table.journal .weight {
text-align: right;
}
table.journal .grad {
text-align: center;
}
table.journal tr.sum {
font-weight: bold;
}
table.journal tr.sum td {
border-top: 0.5pt solid black;
}

View File

@ -1,4 +1,8 @@
main h1 {
margin-bottom: 1.5em !important;
}
table.delivery { table.delivery {
margin-bottom: 5mm; margin-bottom: 5mm;
} }

View File

@ -20,6 +20,9 @@
hr.page-break { hr.page-break {
display: none; display: none;
} }
.document-break {
break-before: page;
}
@page { @page {
size: A4; size: A4;

View File

@ -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 {

View File

@ -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.4</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" />

View File

@ -0,0 +1,85 @@
using Microsoft.Data.Sqlite;
using System;
namespace Elwig.Helpers {
public static class AppDbUpdater {
public static readonly int RequiredSchemaVersion = 2;
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.VersionMajor == major && App.VersionMinor > minor) ||
(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) {
ExecuteNonQuery(cnx, "DROP VIEW v_area_commitment");
ExecuteNonQuery(cnx, "ALTER TABLE delivery_part DROP COLUMN weighing_reason");
ExecuteNonQuery(cnx, "ALTER TABLE delivery_part ADD COLUMN weighing_reason TEXT CHECK(NOT (manual_weighing = FALSE AND weighing_reason IS NOT NULL))");
}
private static void UpdateDbSchema_2_To_3(SqliteConnection cnx) { }
}
}

View File

@ -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) {

View File

@ -58,7 +58,8 @@ namespace Elwig.Helpers {
continue; continue;
} else if (child is T t) { } else if (child is T t) {
yield return t; yield return t;
} else if (child is DependencyObject childDepOpj) { }
if (child is DependencyObject childDepOpj) {
foreach (T childOfChild in FindAllChildren<T>(childDepOpj)) { foreach (T childOfChild in FindAllChildren<T>(childDepOpj)) {
yield return childOfChild; yield return childOfChild;
} }

View File

@ -157,8 +157,12 @@ namespace Elwig.Helpers {
} }
public static void MailTo(string emailAddress) { public static void MailTo(string emailAddress) {
MailTo(new string[] { emailAddress });
}
public static void MailTo(IEnumerable<string> emailAddresses) {
Process.Start(new ProcessStartInfo() { Process.Start(new ProcessStartInfo() {
FileName = $"mailto:{emailAddress}", FileName = $"mailto:{string.Join(",%20", emailAddresses)}",
UseShellExecute = true, UseShellExecute = true,
}); });
} }
@ -193,34 +197,33 @@ namespace Elwig.Helpers {
if (!searchKeywords.Any()) if (!searchKeywords.Any())
return 0; return 0;
return words return searchKeywords
.Select(w => { .Select(k => {
w = w?.ToLower(); k = k.ToLower();
var p = w?.ToLower()?.Split(" "); var scores = words.Select(w => {
if (w == null || p == null) w = w?.ToLower();
return 0; var p = w?.ToLower()?.Split(" ");
if (w == null || p == null) {
var t1 = searchKeywords.Where(f => w == f).Select(f => f.Length).OrderDescending().FirstOrDefault(0); return 0;
var t2 = searchKeywords.Where(f => p.Any(a => a == f)).Select(f => f.Length).OrderDescending().FirstOrDefault(0); } else if (k == w) {
var t3 = searchKeywords.Where(f => p.Any(a => a.StartsWith(f))).Select(f => f.Length).OrderDescending().FirstOrDefault(0); return 4 + k.Length;
var t4 = searchKeywords.Where(f => w.Contains(f)).Select(f => f.Length).OrderDescending().FirstOrDefault(0); } else if (p.Any(a => a == k)) {
if (t1 > 0) { return 3 + k.Length;
return 4 + t1; } else if (p.Any(a => a.StartsWith(k))) {
} else if (t2 > 0) { return 2 + k.Length;
return 3 + t2; } else if (w.Contains(k)) {
} else if (t3 > 0) { return 1 + k.Length;
return 2 + t3; } else {
} else if (t4 > 0) { return 0;
return 1 + t4; }
} else { });
return 0; return scores.Max() + scores.Count(s => s > 0);
}
}) })
.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;
} }

View File

@ -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 == '.') {
@ -521,6 +521,36 @@ namespace Elwig.Helpers {
return new(true, null); return new(true, null);
} }
public static ValidationResult CheckTime(TextBox input, bool required) {
string text = "";
int pos = input.CaretIndex;
int v = 0;
for (int i = 0; i < input.Text.Length; i++) {
char ch = input.Text[i];
if (v >= 0 && v < 5 && v != 2 && char.IsAsciiDigit(ch)) {
if ((v == 0 && ch <= '2') || (v == 1 && (text[0] < '2' || ch <= '3')) || (v == 3 && ch <= '5') || v == 4) {
text += ch;
v++;
}
} else if (v == 2 && ch == ':') {
text += ch;
v++;
}
if (i == input.CaretIndex - 1)
pos = text.Length;
}
input.Text = text;
input.CaretIndex = pos;
if (text.Length == 0) {
return required ? new(false, "Wert ist nicht optional") : new(true, null);
} else if (v != 5) {
return new(false, "Zeit ist ungültig");
} else {
return new(true, null);
}
}
public static ValidationResult CheckFbNr(TextBox input, bool required, AppDbContext ctx, AreaCom? c) { public static ValidationResult CheckFbNr(TextBox input, bool required, AppDbContext ctx, AreaCom? c) {
var res = CheckInteger(input, required); var res = CheckInteger(input, required);
if (!res.IsValid) { if (!res.IsValid) {

View File

@ -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; }

View File

@ -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;

View 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; }
}
}

View File

@ -16,20 +16,20 @@ namespace Elwig.Windows {
protected Control[] ExemptInputs { private get; set; } protected Control[] ExemptInputs { private get; set; }
protected Control[] RequiredInputs { private get; set; } protected Control[] RequiredInputs { private get; set; }
private bool _IsEditing; private bool _isEditing;
private bool _IsCreating; private bool _isCreating;
protected bool IsEditing { protected bool IsEditing {
get { return _IsEditing; } get { return _isEditing; }
set { set {
_IsEditing = value; _isEditing = value;
LockContext = IsEditing; LockContext = IsEditing || IsCreating;
} }
} }
protected bool IsCreating { protected bool IsCreating {
get { return _IsCreating; } get { return _isCreating; }
set { set {
_IsCreating = value; _isCreating = value;
LockContext = IsEditing; LockContext = IsEditing || IsCreating;
} }
} }
protected bool DoShowWarningWindows = true; protected bool DoShowWarningWindows = true;
@ -99,7 +99,7 @@ namespace Elwig.Windows {
abstract protected void UpdateButtons(); abstract protected void UpdateButtons();
protected override async Task RenewContext() { protected override async Task OnRenewContext() {
for (int i = 0; i < PlzInputs.Length; i++) for (int i = 0; i < PlzInputs.Length; i++)
UpdatePlz(PlzInputs[i], PlzOrtInputs[i]); UpdatePlz(PlzInputs[i], PlzOrtInputs[i]);
} }
@ -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);
} }
@ -478,6 +482,14 @@ namespace Elwig.Windows {
InputLostFocus((TextBox)sender, Validator.CheckDate); InputLostFocus((TextBox)sender, Validator.CheckDate);
} }
protected void TimeInput_TextChanged(object sender, RoutedEventArgs evt) {
InputTextChanged((TextBox)sender, Validator.CheckTime);
}
protected void TimeInput_LostFocus(object sender, RoutedEventArgs evt) {
InputLostFocus((TextBox)sender, Validator.CheckTime);
}
protected void PlzInput_TextChanged(object sender, RoutedEventArgs evt) { protected void PlzInput_TextChanged(object sender, RoutedEventArgs evt) {
var plz = (TextBox)sender; var plz = (TextBox)sender;
InputTextChanged(plz, Validator.CheckPlz); InputTextChanged(plz, Validator.CheckPlz);

View File

@ -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>

View File

@ -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();
} }
@ -96,8 +95,8 @@ namespace Elwig.Windows {
ValidateRequiredInputs(); ValidateRequiredInputs();
} }
protected override async Task RenewContext() { protected override async Task OnRenewContext() {
await base.RenewContext(); await base.OnRenewContext();
ControlUtils.RenewItemsSource(KgInput, await Context.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync(), i => (i as AT_Kg)?.KgNr); ControlUtils.RenewItemsSource(KgInput, await Context.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync(), i => (i as AT_Kg)?.KgNr);
ControlUtils.RenewItemsSource(AreaComTypeInput, await Context.AreaCommitmentTypes.OrderBy(v => v.VtrgId).ToListAsync(), i => (i as AreaComType)?.VtrgId); ControlUtils.RenewItemsSource(AreaComTypeInput, await Context.AreaCommitmentTypes.OrderBy(v => v.VtrgId).ToListAsync(), i => (i as AreaComType)?.VtrgId);
ControlUtils.RenewItemsSource(WineCultivationInput, await Context.WineCultivations.OrderBy(c => c.Name).ToListAsync(), i => (i as WineCult)?.CultId); ControlUtils.RenewItemsSource(WineCultivationInput, await Context.WineCultivations.OrderBy(c => c.Name).ToListAsync(), i => (i as WineCult)?.CultId);
@ -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 {

View File

@ -52,8 +52,8 @@ namespace Elwig.Windows {
FillInputs(App.Client); FillInputs(App.Client);
} }
protected override async Task RenewContext() { protected override async Task OnRenewContext() {
await base.RenewContext(); await base.OnRenewContext();
ControlUtils.RenewItemsSource(SeasonList, await Context.Seasons.OrderByDescending(s => s.Year).ToListAsync(), s => (s as Season)?.Year, null, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(SeasonList, await Context.Seasons.OrderByDescending(s => s.Year).ToListAsync(), s => (s as Season)?.Year, null, ControlUtils.RenewSourceDefault.First);
var year = (SeasonList.SelectedItem as Season)?.Year; var year = (SeasonList.SelectedItem as Season)?.Year;
ControlUtils.RenewItemsSource(SeasonModifierList, await Context.Modifiers.Where(m => m.Year == year).OrderBy(m => m.Ordering).ToListAsync(), m => (m as Modifier)?.ModId); ControlUtils.RenewItemsSource(SeasonModifierList, await Context.Modifiers.Where(m => m.Year == year).OrderBy(m => m.Ordering).ToListAsync(), m => (m as Modifier)?.ModId);
@ -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();
} }

View File

@ -214,8 +214,8 @@ namespace Elwig.Windows {
FinishInputFilling(); FinishInputFilling();
} }
protected override async Task RenewContext() { protected override async Task OnRenewContext() {
await base.RenewContext(); await base.OnRenewContext();
await RefreshGraphList(); await RefreshGraphList();
} }

View File

@ -7,30 +7,32 @@ using System.Windows.Threading;
namespace Elwig.Windows { namespace Elwig.Windows {
public abstract class ContextWindow : Window { public abstract class ContextWindow : Window {
public static readonly int RenewSec = 10;
protected AppDbContext Context { get; private set; } protected AppDbContext Context { get; private set; }
protected bool LockContext { get; set; } = false; protected bool LockContext { get; set; } = false;
private readonly DispatcherTimer ContextRenewTimer; private readonly DispatcherTimer _timer;
private static readonly int ContextRenewSec = 10; private bool _renewPending = false;
public ContextWindow() : base() { public ContextWindow() : base() {
ContextRenewTimer = new DispatcherTimer(); _timer = new DispatcherTimer();
ContextRenewTimer.Tick += new EventHandler(OnRenewContext); _timer.Tick += new EventHandler(OnShouldRenewContext);
ContextRenewTimer.Interval = new TimeSpan(0, 0, ContextRenewSec); _timer.Interval = new TimeSpan(0, 0, RenewSec);
ContextRenewTimer.Start(); _timer.Start();
Context = new(); Context = new();
Loaded += OnLoaded; Loaded += OnLoaded;
} }
private void OnRenewContext(object? sender, EventArgs evt) { private async void OnShouldRenewContext(object? sender, EventArgs evt) {
if (LockContext || !Context.HasBackendChanged) return; if (!Context.HasBackendChanged) return;
Context.Dispose(); _renewPending = true;
Context = new(); if (LockContext) return;
RenewContext().GetAwaiter().GetResult(); await RenewContext();
} }
private void OnLoaded(object sender, RoutedEventArgs evt) { private void OnLoaded(object sender, RoutedEventArgs evt) {
RenewContext().GetAwaiter().GetResult(); OnRenewContext().GetAwaiter().GetResult();
} }
protected override void OnClosed(EventArgs evt) { protected override void OnClosed(EventArgs evt) {
@ -38,6 +40,14 @@ namespace Elwig.Windows {
Context.Dispose(); Context.Dispose();
} }
abstract protected Task RenewContext(); protected async Task RenewContext() {
if (!_renewPending) return;
Context.Dispose();
Context = new();
await OnRenewContext();
_renewPending = false;
}
abstract protected Task OnRenewContext();
} }
} }

View File

@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Elwig.Windows" xmlns:local="clr-namespace:Elwig.Windows"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="Lieferungen - Elwig" Height="720" Width="1100" MinHeight="700" MinWidth="1000" Title="Lieferungen - Elwig" Height="720" Width="1100" MinHeight="720" MinWidth="1000"
Loaded="Window_Loaded"> Loaded="Window_Loaded">
<Window.Resources> <Window.Resources>
<Style TargetType="Label"> <Style TargetType="Label">
@ -43,36 +43,42 @@
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="19"/> <RowDefinition Height="19"/>
<RowDefinition Height="0.625*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
<RowDefinition Height="24"/> <RowDefinition Height="24"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="400"/> <ColumnDefinition Width="1*" MinWidth="400"/>
<ColumnDefinition Width="1*"/> <ColumnDefinition Width="5"/>
<ColumnDefinition Width="1*"/> <ColumnDefinition Width="2*" MinWidth="560"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Menu Grid.ColumnSpan="3" BorderThickness="0,0,0,1" BorderBrush="LightGray" Background="White"> <Menu Grid.ColumnSpan="3" BorderThickness="0,0,0,1" BorderBrush="LightGray" Background="White">
<MenuItem Header="Lieferung">
</MenuItem>
<MenuItem Header="Drucken"> <MenuItem Header="Drucken">
<MenuItem x:Name="Menu_Print_ShowDeliveryNote" Header="Lieferschein anzeigen" IsEnabled="False" <MenuItem x:Name="Menu_Print_ShowDeliveryNote" Header="Lieferschein anzeigen" IsEnabled="False"
Click="Menu_Print_ShowDeliveryNote_Click"/> Click="Menu_Print_ShowDeliveryNote_Click"/>
<MenuItem x:Name="Menu_Print_PrintDeliveryNote" Header="Lieferschein drucken" IsEnabled="False" <MenuItem x:Name="Menu_Print_PrintDeliveryNote" Header="Lieferschein drucken" IsEnabled="False"
Click="Menu_Print_PrintDeliveryNote_Click"/> Click="Menu_Print_PrintDeliveryNote_Click"/>
<MenuItem x:Name="Menu_Print_DeliveryJournal" Header="Lieferjournal">
<MenuItem x:Name="Menu_Print_DeliveryJournal_ShowToday" Header="von heute anzeigen" IsEnabled="False" Tag="Print"
Click="Menu_Print_DeliveryJournal_ShowToday_Click"/>
<MenuItem x:Name="Menu_Print_DeliveryJournal_PrintToday" Header="von heute drucken" IsEnabled="False" Tag="Print"
Click="Menu_Print_DeliveryJournal_PrintToday_Click"/>
<MenuItem x:Name="Menu_Print_DeliveryJournal_ShowFilter" Header="aus Filtern anzeigen" IsEnabled="False" Tag="Print"
Click="Menu_Print_DeliveryJournal_ShowFilter_Click"/>
<MenuItem x:Name="Menu_Print_DeliveryJournal_PrintFilter" Header="aus Filtern drucken" IsEnabled="False" Tag="Print"
Click="Menu_Print_DeliveryJournal_PrintFilter_Click"/>
</MenuItem>
</MenuItem> </MenuItem>
<MenuItem Header="Exportieren"> <MenuItem Header="Exportieren">
<MenuItem x:Name="Menu_Export_Bki" Header="Traubentransportscheinliste (BKI)"/> <MenuItem x:Name="Menu_Export_Bki" Header="Traubentransportscheinliste (BKI)"/>
</MenuItem> </MenuItem>
<MenuItem Header="Werkzeuge"> <MenuItem Header="Einstellungen">
<MenuItem Header="Alle Lieferscheine überprüfen"/> <MenuItem x:Name="Menu_Settings_EnableFreeEditing" Header="Freie Bearbeitung aktivieren"
IsCheckable="True" Checked="Menu_Settings_EnableFreeEditing_Checked" Unchecked="Menu_Settings_EnableFreeEditing_Unchecked"/>
</MenuItem> </MenuItem>
</Menu> </Menu>
<Grid Grid.RowSpan="4" Grid.Row="1" Margin="5,0,5,0"> <Grid Grid.Row="1" Margin="5,0,0,0">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="42"/> <RowDefinition Height="42"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
@ -100,17 +106,49 @@
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False"
Margin="5,0,5,0" Grid.Row="1" FontSize="14" Grid.ColumnSpan="3"> Margin="5,0,5,0" Grid.Row="1" FontSize="14" Grid.ColumnSpan="3">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="MgNr." Binding="{Binding MgNr}" Width="70"/> <DataGridTextColumn Header="MgNr." Binding="{Binding MgNr, StringFormat='{}{0} '}" Width="50">
<DataGridTextColumn Header="Datum" Binding="{Binding Date, StringFormat='dd.MM.yy'}" Width="70"/>
<DataGridTextColumn Header="Zeit" Binding="{Binding Time, StringFormat='HH:mm'}" Width="70"/>
<DataGridTextColumn Header="Sorte" Binding="{Binding SortIdString}" Width="60"/>
<DataGridTextColumn Header="Gewicht" Binding="{Binding Weight, StringFormat='{}{0:N0} kg'}" Width="70">
<DataGridTextColumn.CellStyle> <DataGridTextColumn.CellStyle>
<Style> <Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/> <Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style> </Style>
</DataGridTextColumn.CellStyle> </DataGridTextColumn.CellStyle>
</DataGridTextColumn> </DataGridTextColumn>
<DataGridTextColumn Header="Datum" Binding="{Binding Date, StringFormat='dd.MM.yy'}" Width="70">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Zeit" Binding="{Binding Time, StringFormat='HH:mm'}" Width="50">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Sorte" Binding="{Binding SortIdString}" Width="50">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Gewicht" Binding="{Binding Weight, StringFormat='{}{0:N0} kg '}" Width="75">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Gradation" Binding="{Binding Kmw, StringFormat='{}{0:N1}° '}" Width="50">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="LsNr." Binding="{Binding LsNr}" Width="120"/>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
@ -151,238 +189,255 @@
Click="CancelButton_Click"/> Click="CancelButton_Click"/>
</Grid> </Grid>
<GroupBox Header="Mitglied" Grid.Column="1" Grid.Row="1" Margin="5,5,5,5"> <GridSplitter Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Mitglied:" Margin="10,10,0,0" Grid.Column="0"/> <Grid Grid.Row="1" Grid.Column="2">
<TextBox x:Name="MgNrInput" Width="48" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left" TextAlignment="Right" <Grid.RowDefinitions>
TextChanged="MgNrInput_TextChanged" LostFocus="MgNrInput_LostFocus" KeyUp="Input_KeyUp"/> <RowDefinition Height="0.625*"/>
<ComboBox x:Name="MemberInput" Grid.Column="1" Margin="53,10,10,10" IsEditable="True" <RowDefinition Height="*"/>
ItemTemplate="{StaticResource MemberAdminNameTemplate}" TextSearch.TextPath="AdministrativeName" <RowDefinition Height="*"/>
SelectionChanged="MemberInput_SelectionChanged" KeyUp="Input_KeyUp"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Wohnort:" Margin="10,38,0,0" Grid.Column="0"/> <GroupBox Header="Mitglied" Grid.Column="0" Grid.Row="0" Margin="5,5,5,5">
<TextBox x:Name="MemberAddressField" Grid.Column="1" Margin="0,40,10,10" FontSize="12" Height="22" <Grid>
IsReadOnly="True" IsTabStop="False"/> <Grid.ColumnDefinitions>
</Grid> <ColumnDefinition Width="70"/>
</GroupBox> <ColumnDefinition/>
</Grid.ColumnDefinitions>
<GroupBox Header="Lieferung" Grid.Column="1" Grid.Row="2" Margin="5,5,5,5"> <Label Content="Mitglied:" Margin="10,10,0,0" Grid.Column="0"/>
<Grid> <TextBox x:Name="MgNrInput" Width="48" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left" TextAlignment="Right"
<Grid.ColumnDefinitions> TextChanged="MgNrInput_TextChanged" LostFocus="MgNrInput_LostFocus" KeyUp="Input_KeyUp"/>
<ColumnDefinition Width="100"/> <ComboBox x:Name="MemberInput" Grid.Column="1" Margin="53,10,10,10" IsEditable="True"
<ColumnDefinition/> ItemTemplate="{StaticResource MemberAdminNameTemplate}" TextSearch.TextPath="AdministrativeName"
</Grid.ColumnDefinitions> SelectionChanged="MemberInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<Label Content="LieferscheinNr.:" Margin="10,10,0,0" Grid.Column="0"/> <Label Content="Wohnort:" Margin="10,38,0,0" Grid.Column="0"/>
<TextBox x:Name="LsNrInput" Width="126" Grid.Column="1" HorizontalAlignment="Left" Margin="0,10,0,0" <TextBox x:Name="MemberAddressField" Grid.Column="1" Margin="0,40,10,10" FontSize="12" Height="22"
IsReadOnly="True" IsTabStop="False"/> IsReadOnly="True" IsTabStop="False"/>
<Label Content="Datum/Uhrzeit:" Margin="10,40,0,0" Grid.Column="0"/>
<TextBox x:Name="DateInput" Width="77" Grid.Column="1" HorizontalAlignment="Left" Margin="0,40,0,0"
IsReadOnly="True" IsTabStop="False"
TextChanged="DateInput_TextChanged"/>
<TextBox x:Name="TimeInput" Width="44" Grid.Column="1" HorizontalAlignment="Left" Margin="82,40,0,0"
IsReadOnly="True" IsTabStop="False"/>
<Label Content="Zweigstelle:" Margin="10,70,0,0" Grid.Column="0"/>
<ComboBox x:Name="BranchInput" Width="126" Margin="0,70,10,0" Grid.Column="1" HorizontalAlignment="Left"
IsEnabled="False"
DisplayMemberPath="Name" TextSearch.TextPath="Name"/>
<Label Content="Anmerkung:" Margin="10,100,0,10"/>
<TextBox x:Name="CommentInput" Grid.Column="1" Margin="0,100,10,10"
TextChanged="TextBox_TextChanged"/>
</Grid>
</GroupBox>
<GroupBox Header="Sorte" Grid.Column="2" Grid.Row="1" Margin="5,5,5,5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Sorte:" Margin="10,10,0,0" Grid.Column="0"/>
<TextBox x:Name="SortIdInput" Width="36" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left"
TextChanged="SortIdInput_TextChanged" LostFocus="SortIdInput_LostFocus" KeyUp="Input_KeyUp"/>
<ComboBox x:Name="WineVarietyInput" Grid.Row="1" Grid.Column="1" Margin="41,10,10,10"
ItemTemplate="{StaticResource WineVarietyTemplate}" TextSearch.TextPath="Name"
SelectionChanged="WineVarietyInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<Label Content="Attribute:" Margin="10,40,0,0" Grid.Column="0"/>
<xctk:CheckComboBox x:Name="AttributesInput" Grid.Row="1" Grid.Column="1" Margin="0,40,10,10"
DisplayMemberPath="Name" Delimiter=", " AllItemsSelectedContent="Alle"
ItemSelectionChanged="AttributesInput_SelectionChanged" KeyUp="Input_KeyUp"/>
</Grid>
</GroupBox>
<GroupBox Header="Gradation" Grid.Column="2" Grid.Row="2" Margin="5,5,5,5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Gradation:" Margin="10,10,10,10"/>
<Grid Grid.Column="1" Width="54" Height="25" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBox x:Name="GradationOeInput" TextAlignment="Right" Padding="2,2,23,2"
TextChanged="GradationOeInput_TextChanged" LostFocus="GradationOeInput_LostFocus"/>
<Label Content="°Oe" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
</Grid> </Grid>
<Label Content="=" Margin="60,10,10,10" Grid.Column="1"/> </GroupBox>
<Grid Grid.Column="1" Width="68" Height="25" Margin="78,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBox x:Name="GradationKmwInput" TextAlignment="Right" Padding="2,2,34,2" SnapsToDevicePixels="True" <GroupBox Header="Lieferung" Grid.Column="0" Grid.Row="1" Margin="5,5,5,5">
TextChanged="GradationKmwInput_TextChanged" LostFocus="GradationKmwInput_LostFocus"/> <Grid>
<Label Content="°KMW" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/> <Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="LieferscheinNr.:" Margin="10,10,0,0" Grid.Column="0"/>
<TextBox x:Name="LsNrInput" Width="126" Grid.Column="1" HorizontalAlignment="Left" Margin="0,10,0,0"
IsReadOnly="True" IsTabStop="False"
TextChanged="TextBox_TextChanged"/>
<Label Content="Datum/Uhrzeit:" Margin="10,40,0,0" Grid.Column="0"/>
<TextBox x:Name="DateInput" Width="77" Grid.Column="1" HorizontalAlignment="Left" Margin="0,40,0,0"
IsReadOnly="True"
TextChanged="DateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
<TextBox x:Name="TimeInput" Width="44" Grid.Column="1" HorizontalAlignment="Left" Margin="82,40,0,0"
IsReadOnly="True"
TextChanged="TimeInput_TextChanged" LostFocus="TimeInput_LostFocus"/>
<Label Content="Zweigstelle:" Margin="10,70,0,0" Grid.Column="0"/>
<ComboBox x:Name="BranchInput" Width="126" Margin="0,70,10,0" Grid.Column="1" HorizontalAlignment="Left"
IsEnabled="False"
SelectionChanged="BranchInput_SelectionChanged"
DisplayMemberPath="Name" TextSearch.TextPath="Name"/>
<Label Content="Anmerkung:" Margin="10,100,0,10"/>
<TextBox x:Name="CommentInput" Grid.Column="1" Margin="0,100,10,10"
TextChanged="TextBox_TextChanged"/>
</Grid> </Grid>
</GroupBox>
<Label Content="Qualitätsstufe:" Margin="10,40,10,10"/> <GroupBox Header="Sorte" Grid.Column="1" Grid.Row="0" Margin="5,5,5,5">
<ComboBox x:Name="WineQualityLevelInput" Width="146" Margin="0,40,10,10" Grid.Column="1" HorizontalAlignment="Left" <Grid>
ItemTemplate="{StaticResource WineQualityLevelTemplate}" <Grid.ColumnDefinitions>
SelectionChanged="WineQualityLevelInput_SelectionChanged"/> <ColumnDefinition Width="70"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<CheckBox x:Name="AbgewertetInput" Content="Abgewertet" IsEnabled="False" <Label Content="Sorte:" Margin="10,10,0,0" Grid.Column="0"/>
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2"/> <TextBox x:Name="SortIdInput" Width="36" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left"
</Grid> TextChanged="SortIdInput_TextChanged" LostFocus="SortIdInput_LostFocus" KeyUp="Input_KeyUp"/>
</GroupBox> <ComboBox x:Name="WineVarietyInput" Grid.Row="1" Grid.Column="1" Margin="41,10,10,10"
ItemTemplate="{StaticResource WineVarietyTemplate}" TextSearch.TextPath="Name"
SelectionChanged="WineVarietyInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<GroupBox Header="Gewicht" Grid.Column="2" Grid.Row="3" Margin="5,5,5,5"> <Label Content="Attribute:" Margin="10,40,0,0" Grid.Column="0"/>
<Grid> <xctk:CheckComboBox x:Name="AttributesInput" Grid.Row="1" Grid.Column="1" Margin="0,40,10,10"
<Grid.ColumnDefinitions> DisplayMemberPath="Name" Delimiter=", " AllItemsSelectedContent="Alle"
<ColumnDefinition Width="70"/> ItemSelectionChanged="AttributesInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Gewicht:" Margin="10,10,10,10"/>
<Grid Grid.Column="1" Width="70" Height="25" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBox x:Name="WeightInput" TextAlignment="Right" Padding="2,2,17,2" IsReadOnly="True"
TextChanged="WeightInput_TextChanged"/>
<Label Content="kg" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
</Grid> </Grid>
</GroupBox>
<CheckBox x:Name="ManualWeighingInput" Content="Handwiegung" IsEnabled="False" <GroupBox Header="Gradation" Grid.Column="1" Grid.Row="1" Margin="5,5,5,5">
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,45,10,10" Grid.Column="0" Grid.ColumnSpan="2" <Grid>
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/> <Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Gradation:" Margin="10,10,10,10"/>
<Grid Grid.Column="1" Width="54" Height="25" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBox x:Name="GradationOeInput" TextAlignment="Right" Padding="2,2,23,2"
TextChanged="GradationOeInput_TextChanged" LostFocus="GradationOeInput_LostFocus" KeyUp="Input_KeyUp"/>
<Label Content="°Oe" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
</Grid>
<Label Content="=" Margin="60,10,10,10" Grid.Column="1"/>
<Grid Grid.Column="1" Width="68" Height="25" Margin="78,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBox x:Name="GradationKmwInput" TextAlignment="Right" Padding="2,2,34,2" SnapsToDevicePixels="True"
TextChanged="GradationKmwInput_TextChanged" LostFocus="GradationKmwInput_LostFocus" KeyUp="Input_KeyUp"/>
<Label Content="°KMW" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
</Grid>
<CheckBox x:Name="GerebeltGewogenInput" Content="Gerebelt gewogen" <Label Content="Qualitätsstufe:" Margin="10,40,10,10"/>
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2" <ComboBox x:Name="WineQualityLevelInput" Width="146" Margin="0,40,10,10" Grid.Column="1" HorizontalAlignment="Left"
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/> ItemTemplate="{StaticResource WineQualityLevelTemplate}"
SelectionChanged="WineQualityLevelInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<Button x:Name="WeighingManualButton" Content="Handwiegung" Width="120" <CheckBox x:Name="AbgewertetInput" Content="Abgewertet" IsEnabled="False"
Click="WeighingManualButton_Click" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2"/>
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,10,10,10" Grid.Column="2"/>
<Button x:Name="WeighingAButton" Content="Wiegen A" Width="120"
Click="WeighingButton_Click"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,42,10,10" Grid.Column="2"/>
<Button x:Name="WeighingBButton" Content="Wiegen B" Width="120"
Click="WeighingButton_Click"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,74,10,10" Grid.Column="2"/>
<Button x:Name="WeighingCButton" Content="Wiegen C" Width="120"
Click="WeighingButton_Click"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,106,10,10" Grid.Column="2"/>
<Button x:Name="WeighingDButton" Content="Wiegen D" Width="120"
Click="WeighingButton_Click"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,138,10,10" Grid.Column="2"/>
</Grid>
</GroupBox>
<GroupBox Header="Sonstiges" Grid.Column="2" Grid.Row="4" Margin="5,5,5,10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="65"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Zu-/Abschläge:" Margin="10,10,0,10"/>
<xctk:CheckComboBox x:Name="ModifiersInput" Margin="0,10,10,10" Grid.Column="1" Grid.ColumnSpan="2"
ItemTemplate="{StaticResource ModifierTemplate}" Delimiter=", " AllItemsSelectedContent="Alle"
ItemSelectionChanged="ModifiersInput_SelectionChanged"/>
<Label Content="Anmerkung:" Margin="10,40,0,10"/>
<TextBox x:Name="PartCommentInput" Grid.Column="1" Margin="0,40,10,10" Grid.ColumnSpan="2"
TextChanged="TextBox_TextChanged"/>
<Label Content="Temperatur:" Margin="10,70,0,10"/>
<Grid Grid.Column="1" Height="25" Margin="0,70,10,10" VerticalAlignment="Top">
<TextBox x:Name="TemperatureInput" TextAlignment="Right" Padding="2,2,16,2"
TextChanged="TemperatureAcidInput_TextChanged" LostFocus="TemperatureAcidInput_LostFocus"/>
<Label Content="°C" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
</Grid> </Grid>
</GroupBox>
<Label Content="Säure:" Margin="10,100,0,10"/> <GroupBox Header="Gewicht" Grid.Column="1" Grid.Row="2" Margin="5,5,5,5">
<Grid Grid.Column="1" Height="25" Margin="0,100,10,10" VerticalAlignment="Top"> <Grid>
<TextBox x:Name="AcidInput" TextAlignment="Right" Padding="2,2,19,2" <Grid.ColumnDefinitions>
TextChanged="TemperatureAcidInput_TextChanged" LostFocus="TemperatureAcidInput_LostFocus"/> <ColumnDefinition Width="70"/>
<Label Content="g/l" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/> <ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Gewicht:" Margin="10,10,10,10"/>
<Grid Grid.Column="1" Width="70" Height="25" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBox x:Name="WeightInput" TextAlignment="Right" Padding="2,2,17,2" IsReadOnly="True"
TextChanged="WeightInput_TextChanged"/>
<Label Content="kg" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
</Grid>
<CheckBox x:Name="ManualWeighingInput" Content="Handwiegung" IsEnabled="False"
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,45,10,10" Grid.Column="0" Grid.ColumnSpan="2"
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
<CheckBox x:Name="GerebeltGewogenInput" Content="Gerebelt gewogen"
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2"
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
<Button x:Name="WeighingAButton" Content="Wiegen A" Width="120"
Click="WeighingButton_Click"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,10,10,10" Grid.Column="2"/>
<Button x:Name="WeighingBButton" Content="Wiegen B" Width="120"
Click="WeighingButton_Click"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,42,10,10" Grid.Column="2"/>
<Button x:Name="WeighingCButton" Content="Wiegen C" Width="120"
Click="WeighingButton_Click"
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,74,10,10" Grid.Column="2"/>
<Button x:Name="WeighingDButton" Content="Wiegen D" Width="120"
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"/>
</Grid> </Grid>
</GroupBox>
<CheckBox x:Name="LesewagenInput" Content="Lesewagen" Margin="10,75,0,0" Grid.Column="2" <GroupBox Header="Sonstiges" Grid.Column="1" Grid.Row="3" Margin="5,5,5,10">
VerticalAlignment="Top" HorizontalAlignment="Left" <Grid>
Checked="LesewagenInput_Changed" Unchecked="LesewagenInput_Changed"/> <Grid.ColumnDefinitions>
<CheckBox x:Name="HandPickedInput" Content="Handlese" Margin="10,105,0,0" Grid.Column="2" IsThreeState="True" <ColumnDefinition Width="100"/>
VerticalAlignment="Top" HorizontalAlignment="Left" <ColumnDefinition Width="65"/>
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/> <ColumnDefinition/>
</Grid> </Grid.ColumnDefinitions>
</GroupBox>
<GroupBox Header="Teillieferungen" Grid.Column="1" Grid.Row="3" Margin="5,5,5,5"> <Label Content="Zu-/Abschläge:" Margin="10,10,0,10"/>
<Grid> <xctk:CheckComboBox x:Name="ModifiersInput" Margin="0,10,10,10" Grid.Column="1" Grid.ColumnSpan="2"
<Grid.ColumnDefinitions> ItemTemplate="{StaticResource ModifierTemplate}" Delimiter=", " AllItemsSelectedContent="Alle"
<ColumnDefinition/> ItemSelectionChanged="ModifiersInput_SelectionChanged"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox x:Name="DeliveryPartList" Margin="5,5,5,38" Grid.ColumnSpan="2"
SelectionChanged="DeliveryPartList_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding DPNr}" Width="20"/>
<TextBlock Text="{Binding SortId}" Width="30"/>
<TextBlock Text="{Binding Kmw, StringFormat='{}{0:0.0}°'}" Width="40" TextAlignment="Right" Padding="0,0,10,0"/>
<TextBlock Text="{Binding QualId}" Width="30"/>
<TextBlock Text="{Binding Weight, StringFormat='{}{0:N0} kg'}" Width="60" TextAlignment="Right"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="ExtractDeliveryPartButton" Content="Extrahieren" IsEnabled="False" <Label Content="Anmerkung:" Margin="10,40,0,10"/>
ToolTip="Ausgewählte Teillieferung aus aktueller Lieferung entfernen und entweder anderer oder neuer Lieferung zuordnen" <TextBox x:Name="PartCommentInput" Grid.Column="1" Margin="0,40,10,10" Grid.ColumnSpan="2"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,10,2.5,5" Grid.Column="0" Grid.Row="2" TextChanged="TextBox_TextChanged"/>
Click="ExtractDeliveryPartButton_Click"/>
<Button x:Name="DeleteDeliveryPartButton" Content="Löschen" IsEnabled="False"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,10,5,5" Grid.Column="1" Grid.Row="2"
Click="DeleteDeliveryPartButton_Click"/>
</Grid>
</GroupBox>
<GroupBox Header="Herkunft" Grid.Column="1" Grid.Row="4" Margin="5,5,5,10"> <Label Content="Temperatur:" Margin="10,70,0,10"/>
<Grid> <Grid Grid.Column="1" Height="25" Margin="0,70,10,10" VerticalAlignment="Top">
<Grid.ColumnDefinitions> <TextBox x:Name="TemperatureInput" TextAlignment="Right" Padding="2,2,16,2"
<ColumnDefinition Width="100"/> TextChanged="TemperatureAcidInput_TextChanged" LostFocus="TemperatureAcidInput_LostFocus"/>
<ColumnDefinition/> <Label Content="°C" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
</Grid.ColumnDefinitions> </Grid>
<Label Content="Weinbaugebiet:" Margin="10,10,0,10" Grid.Column="0"/> <Label Content="Säure:" Margin="10,100,0,10"/>
<ComboBox x:Name="WineOriginInput" Margin="0,10,10,10" Grid.Column="1" <Grid Grid.Column="1" Height="25" Margin="0,100,10,10" VerticalAlignment="Top">
ItemTemplate="{StaticResource WineOriginTemplate}"/> <TextBox x:Name="AcidInput" TextAlignment="Right" Padding="2,2,19,2"
TextChanged="TemperatureAcidInput_TextChanged" LostFocus="TemperatureAcidInput_LostFocus"/>
<Label Content="g/l" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
</Grid>
<Label Content="Weinbau-KG:" Margin="10,40,0,10" Grid.Column="0"/> <CheckBox x:Name="LesewagenInput" Content="Lesewagen" Margin="10,75,0,0" Grid.Column="2"
<ComboBox x:Name="WineKgInput" Margin="0,40,10,10" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Left"
DisplayMemberPath="Name" Checked="LesewagenInput_Changed" Unchecked="LesewagenInput_Changed"/>
SelectionChanged="WineKgInput_SelectionChanged"/> <CheckBox x:Name="HandPickedInput" Content="Handlese" Margin="10,105,0,0" Grid.Column="2" IsThreeState="True"
VerticalAlignment="Top" HorizontalAlignment="Left"
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
</Grid>
</GroupBox>
<Label Content="Ried:" Margin="10,70,0,10" Grid.Column="0"/> <GroupBox Header="Teillieferungen" Grid.Column="0" Grid.Row="2" Margin="5,5,5,5">
<ComboBox x:Name="WineRdInput" Margin="0,70,10,10" Grid.Column="1" <Grid>
DisplayMemberPath="Name"/> <Grid.ColumnDefinitions>
</Grid> <ColumnDefinition/>
</GroupBox> <ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox x:Name="DeliveryPartList" Margin="5,5,5,38" Grid.ColumnSpan="2"
SelectionChanged="DeliveryPartList_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding DPNr}" Width="20"/>
<TextBlock Text="{Binding SortId}" Width="30"/>
<TextBlock Text="{Binding Kmw, StringFormat='{}{0:0.0}°'}" Width="40" TextAlignment="Right" Padding="0,0,10,0"/>
<TextBlock Text="{Binding QualId}" Width="30"/>
<TextBlock Text="{Binding Weight, StringFormat='{}{0:N0} kg'}" Width="60" TextAlignment="Right"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="ExtractDeliveryPartButton" Content="Extrahieren" IsEnabled="False"
ToolTip="Ausgewählte Teillieferung aus aktueller Lieferung entfernen und entweder anderer oder neuer Lieferung zuordnen"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,10,2.5,5" Grid.Column="0" Grid.Row="2"
Click="ExtractDeliveryPartButton_Click"/>
<Button x:Name="DeleteDeliveryPartButton" Content="Löschen" IsEnabled="False"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,10,5,5" Grid.Column="1" Grid.Row="2"
Click="DeleteDeliveryPartButton_Click"/>
</Grid>
</GroupBox>
<GroupBox Header="Herkunft" Grid.Column="0" Grid.Row="3" Margin="5,5,5,10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Content="Weinbaugebiet:" Margin="10,10,0,10" Grid.Column="0"/>
<ComboBox x:Name="WineOriginInput" Margin="0,10,10,10" Grid.Column="1"
ItemTemplate="{StaticResource WineOriginTemplate}"/>
<Label Content="Weinbau-KG:" Margin="10,40,0,10" Grid.Column="0"/>
<ComboBox x:Name="WineKgInput" Margin="0,40,10,10" Grid.Column="1"
DisplayMemberPath="Name"
SelectionChanged="WineKgInput_SelectionChanged"/>
<Label Content="Ried:" Margin="10,70,0,10" Grid.Column="0"/>
<ComboBox x:Name="WineRdInput" Margin="0,70,10,10" Grid.Column="1"
DisplayMemberPath="Name"/>
</Grid>
</GroupBox>
</Grid>
<StatusBar Grid.Row="5" Grid.ColumnSpan="3" BorderThickness="0,1,0,0" BorderBrush="Gray"> <StatusBar Grid.Row="5" Grid.ColumnSpan="3" BorderThickness="0,1,0,0" BorderBrush="Gray">
<StatusBar.ItemsPanel> <StatusBar.ItemsPanel>

View File

@ -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,18 @@ 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) {
Menu_Print_DeliveryJournal_ShowToday.IsEnabled = App.IsPrintingReady;
Menu_Print_DeliveryJournal_PrintToday.IsEnabled = App.IsPrintingReady;
Menu_Print_DeliveryJournal_ShowFilter.IsEnabled = App.IsPrintingReady;
Menu_Print_DeliveryJournal_PrintFilter.IsEnabled = App.IsPrintingReady;
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);
} }
@ -106,16 +113,16 @@ namespace Elwig.Windows {
private async void Menu_Print_ShowDeliveryNote_Click(object sender, RoutedEventArgs evt) { private async void Menu_Print_ShowDeliveryNote_Click(object sender, RoutedEventArgs evt) {
if (DeliveryList.SelectedItem is not Delivery d) return; if (DeliveryList.SelectedItem is not Delivery d) return;
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
using var doc = new DeliveryNote(d, Context); using var doc = new DeliveryNote(d, Context);
await doc.Generate(); await doc.Generate();
doc.Show();
Mouse.OverrideCursor = null; Mouse.OverrideCursor = null;
doc.Show();
} }
private async void Menu_Print_PrintDeliveryNote_Click(object sender, RoutedEventArgs evt) { private async void Menu_Print_PrintDeliveryNote_Click(object sender, RoutedEventArgs evt) {
if (DeliveryList.SelectedItem is not Delivery d) return; if (DeliveryList.SelectedItem is not Delivery d) return;
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
using var doc = new DeliveryNote(d, Context); using var doc = new DeliveryNote(d, Context);
await doc.Generate(); await doc.Generate();
Mouse.OverrideCursor = null; Mouse.OverrideCursor = null;
@ -126,27 +133,86 @@ namespace Elwig.Windows {
if (sender is not MenuItem m) return; if (sender is not MenuItem m) return;
var year = int.Parse(m.Header.ToString()?.Split(" ")[^1] ?? Utils.CurrentLastSeason.ToString()); var year = int.Parse(m.Header.ToString()?.Split(" ")[^1] ?? Utils.CurrentLastSeason.ToString());
var d = new SaveFileDialog() { var d = new SaveFileDialog() {
FileName = $"{App.Client.NameToken}-Traubentransportscheinliste-{year}", FileName = $"{App.Client.NameToken}-Traubentransportscheinliste-{year}.{Bki.FileExtension}",
DefaultExt = Bki.FileExtension, DefaultExt = Bki.FileExtension,
Filter = "CSV-Datei (*.csv)|*.csv",
Title = $"Traubentransportscheinliste (BKI) speichern unter - Elwig" Title = $"Traubentransportscheinliste (BKI) speichern unter - Elwig"
}; };
if (d.ShowDialog() == true) { if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
using var file = new Bki(d.FileName); using var file = new Bki(d.FileName);
await file.ExportAsync(year); await file.ExportAsync(year);
Mouse.OverrideCursor = null; Mouse.OverrideCursor = null;
} }
} }
private async void Menu_Print_DeliveryJournal_ShowToday_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.AppStarting;
var doc = new DeliveryJournal(Context, DateOnly.FromDateTime(Utils.Today));
await doc.Generate();
Mouse.OverrideCursor = null;
doc.Show();
}
private async void Menu_Print_DeliveryJournal_PrintToday_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.AppStarting;
var doc = new DeliveryJournal(Context, DateOnly.FromDateTime(Utils.Today));
await doc.Generate();
Mouse.OverrideCursor = null;
await doc.Print();
}
private async void Menu_Print_DeliveryJournal_ShowFilter_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.AppStarting;
var (f, _, d, _) = await GetFilters();
var doc = new DeliveryJournal(string.Join(" / ", f), d);
await doc.Generate();
Mouse.OverrideCursor = null;
doc.Show();
}
private async void Menu_Print_DeliveryJournal_PrintFilter_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.AppStarting;
var (f, _, d, _) = await GetFilters();
var doc = new DeliveryJournal(string.Join(" / ", f), d);
await doc.Generate();
Mouse.OverrideCursor = null;
doc.Show();
}
private void Menu_Settings_EnableFreeEditing_Checked(object sender, RoutedEventArgs evt) {
if (IsEditing || IsCreating) {
DateInput.IsReadOnly = false;
TimeInput.IsReadOnly = false;
BranchInput.IsEnabled = true;
if (IsCreating) TimeInput.Text = "";
OnSecondPassed(null, null);
}
}
private void Menu_Settings_EnableFreeEditing_Unchecked(object sender, RoutedEventArgs evt) {
DateInput.IsReadOnly = true;
TimeInput.IsReadOnly = true;
BranchInput.IsEnabled = false;
OnSecondPassed(null, null);
}
private void OnSecondPassed(object? sender, EventArgs? evt) { private void OnSecondPassed(object? sender, EventArgs? evt) {
if (IsReceipt && IsCreating) { if (IsReceipt && IsCreating && !Menu_Settings_EnableFreeEditing.IsChecked) {
var now = DateTime.Now; var now = DateTime.Now;
TimeInput.Text = now.ToString("HH:mm"); TimeInput.Text = now.ToString("HH:mm");
DateInput.Text = now.ToString("dd.MM.yyyy"); DateInput.Text = now.ToString("dd.MM.yyyy");
SetDefaultValue(TimeInput);
SetDefaultValue(DateInput);
} }
} }
private void InitialInputs() { private void InitialInputs() {
LastScaleError = null;
WeighingId = null;
ScaleId = null;
ManualWeighingReason = null;
ClearOriginalValues(); ClearOriginalValues();
ClearDefaultValues(); ClearDefaultValues();
@ -188,9 +254,14 @@ namespace Elwig.Windows {
if (sender is not Control ctrl) return; if (sender is not Control ctrl) return;
if (evt.Key != Key.Enter) return; if (evt.Key != Key.Enter) return;
if (ctrl == MgNrInput || ctrl == MemberInput) { if (ctrl == MgNrInput || ctrl == MemberInput) {
SortIdInput.Focus(); SortIdInput.SelectAll(); SortIdInput.Focus();
SortIdInput.SelectAll();
} else if (ctrl == SortIdInput || ctrl == WineVarietyInput || ctrl == AttributesInput) { } else if (ctrl == SortIdInput || ctrl == WineVarietyInput || ctrl == AttributesInput) {
GradationOeInput.Focus(); GradationOeInput.SelectAll(); GradationOeInput.Focus();
GradationOeInput.SelectAll();
} else if (ctrl == GradationKmwInput || ctrl == GradationOeInput || ctrl == WineQualityLevelInput) {
if (WeighingAButton.IsVisible) WeighingAButton.Focus();
else WeighingManualButton.Focus();
} }
} }
@ -198,19 +269,32 @@ namespace Elwig.Windows {
await RefreshDeliveryListQuery(); await RefreshDeliveryListQuery();
} }
private async Task RefreshDeliveryListQuery(bool updateSort = false) { private async Task<(List<string>, IQueryable<Delivery>, IQueryable<DeliveryPart>, List<string>)> GetFilters() {
List<string> filterNames = new();
IQueryable<Delivery> deliveryQuery = Context.Deliveries; IQueryable<Delivery> deliveryQuery = Context.Deliveries;
if (Member != null) { if (Member != null) {
deliveryQuery = deliveryQuery.Where(d => d.MgNr == Member.MgNr); deliveryQuery = deliveryQuery.Where(d => d.MgNr == Member.MgNr);
filterNames.Add(Member.AdministrativeName);
} }
if (TodayOnlyInput.IsChecked == true) { if (TodayOnlyInput.IsChecked == true) {
deliveryQuery = deliveryQuery deliveryQuery = deliveryQuery
.Where(d => (d.DateString == Utils.Today.ToString("yyyy-MM-dd") && d.TimeString.CompareTo("03:00:00") > 0) || .Where(d => (d.DateString == Utils.Today.ToString("yyyy-MM-dd") && (d.TimeString == null || d.TimeString.CompareTo("03:00:00") > 0)) ||
(d.DateString == Utils.Today.AddDays(1).ToString("yyyy-MM-dd") && d.TimeString.CompareTo("03:00:00") <= 0)); (d.DateString == Utils.Today.AddDays(1).ToString("yyyy-MM-dd") && (d.TimeString == null || d.TimeString.CompareTo("03:00:00") <= 0)));
filterNames.Add(Utils.Today.ToString("dd.MM.yyyy"));
} else if (AllSeasonsInput.IsChecked == false) { } else if (AllSeasonsInput.IsChecked == false) {
deliveryQuery = deliveryQuery.Where(d => d.Year == SeasonInput.Value); deliveryQuery = deliveryQuery.Where(d => d.Year == SeasonInput.Value);
filterNames.Add(SeasonInput.Value.ToString() ?? "");
} }
IQueryable<DeliveryPart> dpq = deliveryQuery
.SelectMany(d => d.Parts)
.OrderBy(p => p.Delivery.DateString)
.ThenBy(p => p.Delivery.TimeString)
.ThenBy(p => p.Delivery.LsNr)
.ThenBy(p => p.DPNr);
// TODO add filter for:
// attributes
// branches
var filterVar = new List<string>(); var filterVar = new List<string>();
var filterQual = new List<string>(); var filterQual = new List<string>();
var filterMgNr = new List<int>(); var filterMgNr = new List<int>();
@ -227,21 +311,24 @@ namespace Elwig.Windows {
var filter = TextFilter.ToList(); var filter = TextFilter.ToList();
if (filter.Count > 0) { if (filter.Count > 0) {
var var = await Context.WineVarieties.Select(v => v.SortId).ToListAsync(); var var = await Context.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
var qual = await Context.WineQualityLevels.Select(q => q.QualId).ToListAsync(); var qual = await Context.WineQualityLevels.ToDictionaryAsync(q => q.QualId, q => q);
var mgnr = await Context.Members.Select(m => m.MgNr.ToString()).ToListAsync(); var mgnr = await Context.Members.ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
for (int i = 0; i < filter.Count; i++) { for (int i = 0; i < filter.Count; i++) {
var e = filter[i]; var e = filter[i];
if (e.Length == 2 && var.Contains(e.ToUpper())) { if (e.Length == 2 && var.ContainsKey(e.ToUpper())) {
filterVar.Add(e.ToUpper()); filterVar.Add(e.ToUpper());
filter.RemoveAt(i--); filter.RemoveAt(i--);
} else if (e.Length == 3 && qual.Contains(e.ToUpper())) { filterNames.Add(var[e.ToUpper()].Name);
} else if (e.Length == 3 && qual.ContainsKey(e.ToUpper())) {
filterQual.Add(e.ToUpper()); filterQual.Add(e.ToUpper());
filter.RemoveAt(i--); filter.RemoveAt(i--);
} else if (e.All(char.IsAsciiDigit) && mgnr.Contains(e)) { filterNames.Add(qual[e.ToUpper()].Name);
} else if (e.All(char.IsAsciiDigit) && mgnr.ContainsKey(e)) {
filterMgNr.Add(int.Parse(e)); filterMgNr.Add(int.Parse(e));
filter.RemoveAt(i--); filter.RemoveAt(i--);
filterNames.Add(mgnr[e].AdministrativeName);
} else if (e.StartsWith(">") || e.StartsWith("<")) { } else if (e.StartsWith(">") || e.StartsWith("<")) {
if (double.TryParse(e[1..], out var num)) { if (double.TryParse(e[1..], out var num)) {
switch ((e[0], num)) { switch ((e[0], num)) {
@ -290,12 +377,23 @@ namespace Elwig.Windows {
filterTimeLt = TimeOnly.TryParse(parts[1], out var to) ? $"{to:HH:mm}" : null; filterTimeLt = TimeOnly.TryParse(parts[1], out var to) ? $"{to:HH:mm}" : null;
filter.RemoveAt(i--); filter.RemoveAt(i--);
} else if (DateOnly.TryParse(e, out var date)) { } else if (DateOnly.TryParse(e, out var date)) {
filterDate.Add($"{date:yyyy-MM-dd}"); // TODO allow date ranges
filterDate.Add(date.ToString("yyyy-MM-dd"));
filter.RemoveAt(i--); filter.RemoveAt(i--);
filterNames.Add(date.ToString("dd.MM.yyyy"));
} else if (Utils.PartialDateRegex.IsMatch(e)) { } else if (Utils.PartialDateRegex.IsMatch(e)) {
// TODO allow date ranges
var parts = e.Split("."); var parts = e.Split(".");
filterPartDate.Add($"-{int.Parse(parts[1]):00}-{int.Parse(parts[0]):00}"); var p0 = int.Parse(parts[0]);
var p1 = int.Parse(parts[1]);
filterPartDate.Add($"-{p1:00}-{p0:00}");
filter.RemoveAt(i--); filter.RemoveAt(i--);
if (filterNames.Contains(SeasonInput.Value.ToString())) {
filterNames.Remove(SeasonInput.Value.ToString());
filterNames.Add($"{p0:00}.{p1:00}.{SeasonInput.Value:0000}");
} else {
filterNames.Add($"{p0:00}.{p1:00}.");
}
} else if (e.Length > 2 && e.StartsWith("\"") && e.EndsWith("\"")) { } else if (e.Length > 2 && e.StartsWith("\"") && e.EndsWith("\"")) {
filter[i] = e[1..^1]; filter[i] = e[1..^1];
} else if (e.Length <= 2) { } else if (e.Length <= 2) {
@ -303,22 +401,58 @@ namespace Elwig.Windows {
} }
} }
if (filterMgNr.Count > 0) deliveryQuery = deliveryQuery.Where(d => filterMgNr.Contains(d.MgNr)); if (filterMgNr.Count > 0) dpq = dpq.Where(p => filterMgNr.Contains(p.Delivery.MgNr));
if (filterDate.Count > 0) deliveryQuery = deliveryQuery.Where(d => filterDate.Contains(d.DateString)); if (filterDate.Count > 0) dpq = dpq.Where(p => filterDate.Contains(p.Delivery.DateString));
if (filterPartDate.Count > 0) deliveryQuery = deliveryQuery.Where(d => filterPartDate.Contains(d.DateString.Substring(4))); if (filterPartDate.Count > 0) dpq = dpq.Where(p => filterPartDate.Contains(p.Delivery.DateString.Substring(4)));
if (filterYearGt > 0) deliveryQuery = deliveryQuery.Where(d => d.Year >= filterYearGt); if (filterYearGt > 0) dpq = dpq.Where(p => p.Year >= filterYearGt);
if (filterYearLt > 0) deliveryQuery = deliveryQuery.Where(d => d.Year < filterYearLt); if (filterYearLt > 0) dpq = dpq.Where(p => p.Year < filterYearLt);
if (filterTimeGt != null) deliveryQuery = deliveryQuery.Where(d => filterTimeGt.CompareTo(d.TimeString) <= 0); if (filterTimeGt != null) dpq = dpq.Where(p => p.Delivery.TimeString != null && filterTimeGt.CompareTo(p.Delivery.TimeString) <= 0);
if (filterTimeLt != null) deliveryQuery = deliveryQuery.Where(d => filterTimeLt.CompareTo(d.TimeString) > 0); if (filterTimeLt != null) dpq = dpq.Where(p => p.Delivery.TimeString != null && filterTimeLt.CompareTo(p.Delivery.TimeString) > 0);
if (filterVar.Count > 0) deliveryQuery = deliveryQuery.Where(d => d.Parts.Any(p => filterVar.Contains(p.SortId))); if (filterVar.Count > 0) dpq = dpq.Where(p => filterVar.Contains(p.SortId));
if (filterQual.Count > 0) deliveryQuery = deliveryQuery.Where(d => d.Parts.Any(p => filterQual.Contains(p.QualId))); if (filterQual.Count > 0) dpq = dpq.Where(p => filterQual.Contains(p.QualId));
if (filterKmwGt > 0) deliveryQuery = deliveryQuery.Where(d => d.Parts.Any(p => p.Kmw >= filterKmwGt)); if (filterKmwGt > 0) dpq = dpq.Where(p => p.Kmw >= filterKmwGt);
if (filterKmwLt > 0) deliveryQuery = deliveryQuery.Where(d => d.Parts.Any(p => p.Kmw < filterKmwLt)); if (filterKmwLt > 0) dpq = dpq.Where(p => p.Kmw < filterKmwLt);
if (filterOeGt > 0) deliveryQuery = deliveryQuery.Where(d => d.Parts.Any(p => p.Kmw * (4.54 + 0.022 * p.Kmw) >= filterOeGt)); if (filterOeGt > 0) dpq = dpq.Where(p => p.Kmw * (4.54 + 0.022 * p.Kmw) >= filterOeGt);
if (filterOeLt > 0) deliveryQuery = deliveryQuery.Where(d => d.Parts.Any(p => p.Kmw * (4.54 + 0.022 * p.Kmw) < filterOeLt)); if (filterOeLt > 0) dpq = dpq.Where(p => p.Kmw * (4.54 + 0.022 * p.Kmw) < filterOeLt);
if (filterYearGt > 0 && filterYearLt > 0) {
filterNames.Insert(0, $"{filterYearGt}{filterYearLt - 1}");
} else if (filterYearGt > 0) {
filterNames.Insert(0, $"ab {filterYearGt}");
} else if (filterYearLt > 0) {
filterNames.Insert(0, $"bis {filterYearLt - 1}");
}
if (filterKmwGt > 0 && filterKmwLt > 0) {
filterNames.Add($"{filterKmwGt:N1}{filterKmwLt:N1} °KMW");
} else if (filterKmwGt > 0) {
filterNames.Add($"ab {filterKmwGt:N1} °KMW");
} else if (filterKmwLt > 0) {
filterNames.Add($"unter {filterKmwLt:N1} °KMW");
}
if (filterOeGt > 0 && filterOeLt > 0) {
filterNames.Add($"{filterOeGt:N1}{filterOeLt:N1} °Oe");
} else if (filterOeGt > 0) {
filterNames.Add($"ab {filterOeGt:N1} °Oe");
} else if (filterOeLt > 0) {
filterNames.Add($"unter {filterOeLt:N1} °Oe");
}
if (filterTimeGt != null && filterTimeLt != null) {
filterNames.Add($"{filterTimeGt}{filterTimeLt}");
} else if (filterTimeGt != null) {
filterNames.Add($"ab {filterTimeGt}");
} else if (filterTimeLt != null) {
filterNames.Add($"bis {filterTimeLt}");
}
} }
List<Delivery> deliveries = await deliveryQuery.OrderByDescending(d => d.DateString).ThenByDescending(d => d.TimeString).ToListAsync(); return (filterNames, dpq.Select(p => p.Delivery).Distinct().OrderBy(d => d.DateString).ThenBy(d => d.TimeString), dpq, filter);
}
private async Task RefreshDeliveryListQuery(bool updateSort = false) {
var (_, deliveryQuery, deliveryPartsQuery, filter) = await GetFilters();
var deliveries = await deliveryQuery.ToListAsync();
deliveries.Reverse();
if (filter.Count > 0 && deliveries.Count > 0) { if (filter.Count > 0 && deliveries.Count > 0) {
var dict = deliveries.AsParallel() var dict = deliveries.AsParallel()
.ToDictionary(d => d, d => d.SearchScore(TextFilter)) .ToDictionary(d => d, d => d.SearchScore(TextFilter))
@ -331,22 +465,16 @@ 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))})" : "");
StatusMembers.ToolTip = StatusMembers.Text;
StatusDeliveries.Text = $"Lieferungen: {deliveries.Count}"; StatusDeliveries.Text = $"Lieferungen: {deliveries.Count}";
if (filter.Count == 0) { if (filter.Count == 0) {
var partsQuery = deliveryQuery.SelectMany(d => d.Parts); var deliveryParts = deliveryPartsQuery;
if (filterVar.Count > 0) partsQuery = partsQuery.Where(p => filterVar.Contains(p.SortId));
if (filterQual.Count > 0) partsQuery = partsQuery.Where(p => filterQual.Contains(p.QualId));
if (filterKmwGt > 0) partsQuery = partsQuery.Where(p => p.Kmw >= filterKmwGt);
if (filterKmwLt > 0) partsQuery = partsQuery.Where(p => p.Kmw < filterKmwLt);
if (filterOeGt > 0) partsQuery = partsQuery.Where(p => p.Kmw * (4.54 + 0.022 * p.Kmw) >= filterOeGt);
if (filterOeLt > 0) partsQuery = partsQuery.Where(p => p.Kmw * (4.54 + 0.022 * p.Kmw) < filterOeLt);
var deliveryParts = partsQuery;
var n = await deliveryParts.CountAsync(); var n = await deliveryParts.CountAsync();
StatusDeliveries.Text = $"Lieferungen: {deliveries.Count} ({n})"; StatusDeliveries.Text = $"Lieferungen: {deliveries.Count} ({n})";
var varieties = await deliveryParts.Select(d => d.SortId).Distinct().ToListAsync(); var varieties = await deliveryParts.Select(d => d.SortId).Distinct().ToListAsync();
@ -364,9 +492,8 @@ namespace Elwig.Windows {
StatusGradation.Text = "Gradation: -"; StatusGradation.Text = "Gradation: -";
} }
if (n > 0 && (n <= 200 || TodayOnlyInput.IsChecked == true)) { if (n > 0 && (n <= 200 || TodayOnlyInput.IsChecked == true)) {
var parts = (await deliveryParts.ToListAsync()); var parts = await deliveryParts.ToListAsync();
var groups = parts var groups = parts
.GroupBy(p => string.Join("/", p.Attributes.Select(a => a.Name))) .GroupBy(p => string.Join("/", p.Attributes.Select(a => a.Name)))
.Select(g => (g.Key, g.Sum(p => p.Weight), g.Min(p => p.Kmw), Utils.AggregateDeliveryPartsKmw(g), g.Max(p => p.Kmw))) .Select(g => (g.Key, g.Sum(p => p.Weight), g.Min(p => p.Kmw), Utils.AggregateDeliveryPartsKmw(g), g.Max(p => p.Kmw)))
@ -400,10 +527,14 @@ namespace Elwig.Windows {
StatusWeight.Text = "Gewicht: -"; StatusWeight.Text = "Gewicht: -";
StatusGradation.Text = "Gradation: -"; StatusGradation.Text = "Gradation: -";
} }
StatusVarieties.ToolTip = StatusVarieties.Text;
StatusWeight.ToolTip = StatusWeight.Text;
StatusGradation.ToolTip = StatusGradation.Text;
} }
protected override async Task RenewContext() { protected override async Task OnRenewContext() {
await base.RenewContext(); await base.OnRenewContext();
if (Member != null) { if (Member != null) {
if (Context.Members.Find(Member.MgNr) is not Member m) { if (Context.Members.Find(Member.MgNr) is not Member m) {
@ -423,7 +554,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 +571,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 +652,7 @@ namespace Elwig.Windows {
ScaleId = p?.ScaleId; ScaleId = p?.ScaleId;
WeighingId = p?.WeighingId; WeighingId = p?.WeighingId;
ManualWeighingReason = p?.WeighingReason;
FinishInputFilling(); FinishInputFilling();
} }
@ -551,13 +683,13 @@ 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 && !InputIsNotDefault(TimeInput)) {
d.TimeString = DateTime.Now.ToString("HH:mm:ss"); d.TimeString = DateTime.Now.ToString("HH:mm:ss");
} else if (InputHasChanged(TimeInput)) { } else if (IsCreating || InputHasChanged(TimeInput)) {
d.TimeString = TimeInput.Text + ":00"; d.TimeString = (TimeInput.Text != "") ? TimeInput.Text + ":00" : null;
} }
d.ZwstId = (BranchInput.SelectedItem as Branch)?.ZwstId; d.ZwstId = (BranchInput.SelectedItem as Branch)?.ZwstId;
d.LsNr = LsNrInput.Text; d.LsNr = LsNrInput.Text;
@ -582,8 +714,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;
@ -643,18 +774,23 @@ namespace Elwig.Windows {
WeightInput.Text = $"{res.Weight:N0}"; WeightInput.Text = $"{res.Weight:N0}";
ScaleId = s.ScaleId; ScaleId = s.ScaleId;
WeighingId = res.FullWeighingId; WeighingId = res.FullWeighingId;
s.Empty();
} else { } else {
WeightInput.Text = ""; WeightInput.Text = "";
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();
} }
@ -743,12 +879,19 @@ namespace Elwig.Windows {
} }
} }
private void EmptyScale() {
var scale = App.Scales.Where(s => s.ScaleId == ScaleId).FirstOrDefault();
if (scale == null) return;
scale.Empty();
}
private async void NewDeliveryPartButton_Click(object sender, RoutedEventArgs evt) { private async void NewDeliveryPartButton_Click(object sender, RoutedEventArgs evt) {
FinishButton.IsEnabled = false; FinishButton.IsEnabled = false;
NewDeliveryPartButton.IsEnabled = false; NewDeliveryPartButton.IsEnabled = false;
NewDeliveryPartButton.Cursor = Cursors.Wait; NewDeliveryPartButton.Cursor = Cursors.Wait;
DeliveryPartList.IsEnabled = false; DeliveryPartList.IsEnabled = false;
var p = await UpdateDeliveryPart(DeliveryList.SelectedItem as Delivery, DeliveryPartList.SelectedItem as DeliveryPart); var p = await UpdateDeliveryPart(DeliveryList.SelectedItem as Delivery, DeliveryPartList.SelectedItem as DeliveryPart);
EmptyScale();
await RefreshDeliveryList(); await RefreshDeliveryList();
await RefreshDeliveryParts(); await RefreshDeliveryParts();
NewDeliveryPartButton.Cursor = null; NewDeliveryPartButton.Cursor = null;
@ -764,18 +907,23 @@ namespace Elwig.Windows {
FinishButton.Cursor = Cursors.Wait; FinishButton.Cursor = Cursors.Wait;
DeliveryPartList.IsEnabled = false; DeliveryPartList.IsEnabled = false;
var p = await UpdateDeliveryPart(DeliveryList.SelectedItem as Delivery, DeliveryPartList.SelectedItem as DeliveryPart); var p = await UpdateDeliveryPart(DeliveryList.SelectedItem as Delivery, DeliveryPartList.SelectedItem as DeliveryPart);
EmptyScale();
await RefreshDeliveryList(); await RefreshDeliveryList();
await RefreshDeliveryParts(); await RefreshDeliveryParts();
if (p?.Delivery != null) { if (p?.Delivery != null) {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
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 {
doc.Print(2);
}
} }
FinishButton.Cursor = null; FinishButton.Cursor = null;
DeliveryList.SelectedItem = null; DeliveryList.SelectedItem = null;
await RenewContext();
RefreshInputs(); RefreshInputs();
InitInputs(); InitInputs();
} }
@ -798,6 +946,7 @@ namespace Elwig.Windows {
DisableWeighingButtons(); DisableWeighingButtons();
HideFinishNewPartDeliveryCancelButtons(); HideFinishNewPartDeliveryCancelButtons();
ShowNewEditDeleteButtons(); ShowNewEditDeleteButtons();
await RenewContext();
RefreshInputs(); RefreshInputs();
ClearInputStates(); ClearInputStates();
LockInputs(); LockInputs();
@ -833,7 +982,7 @@ namespace Elwig.Windows {
try { try {
if (res == null || res <= 0) if (res == null || res <= 0)
return; return;
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
ClearOriginalValues(); ClearOriginalValues();
if (res >= p.Weight) { if (res >= p.Weight) {
ControlUtils.SelectComboBoxItem(WineQualityLevelInput, q => (q as WineQualLevel)?.QualId, "WEI"); ControlUtils.SelectComboBoxItem(WineQualityLevelInput, q => (q as WineQualLevel)?.QualId, "WEI");
@ -880,7 +1029,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;
@ -915,7 +1064,7 @@ namespace Elwig.Windows {
$"Soll die Lieferung {d.LsNr} ({d.Member.AdministrativeName}, MgNr. {d.Member.MgNr}) wirklich unwiderruflich gelöscht werden?", $"Soll die Lieferung {d.LsNr} ({d.Member.AdministrativeName}, MgNr. {d.Member.MgNr}) wirklich unwiderruflich gelöscht werden?",
"Lieferung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); "Lieferung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r == MessageBoxResult.Yes) { if (r == MessageBoxResult.Yes) {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
Context.Remove(d); Context.Remove(d);
await Context.SaveChangesAsync(); await Context.SaveChangesAsync();
await RefreshDeliveryList(); await RefreshDeliveryList();
@ -990,8 +1139,8 @@ namespace Elwig.Windows {
day = day.AddDays(-1); day = day.AddDays(-1);
var lsnrs = await Context.Deliveries var lsnrs = await Context.Deliveries
.Where(d => d.ZwstId == delivery.ZwstId) .Where(d => d.ZwstId == delivery.ZwstId)
.Where(d => (d.DateString == day.ToString("yyyy-MM-dd") && d.TimeString.CompareTo("03:00:00") > 0) || .Where(d => (d.DateString == day.ToString("yyyy-MM-dd") && (d.TimeString == null || d.TimeString.CompareTo("03:00:00") > 0)) ||
(d.DateString == day.AddDays(1).ToString("yyyy-MM-dd") && d.TimeString.CompareTo("03:00:00") <= 0)) (d.DateString == day.AddDays(1).ToString("yyyy-MM-dd") && (d.TimeString == null || d.TimeString.CompareTo("03:00:00") <= 0)))
.Where(d => d.LsNr != delivery.LsNr) .Where(d => d.LsNr != delivery.LsNr)
.OrderBy(d => d.LsNr) .OrderBy(d => d.LsNr)
.Select(d => d.LsNr) .Select(d => d.LsNr)
@ -1002,7 +1151,7 @@ namespace Elwig.Windows {
EntityEntry<Delivery>? entry = null; EntityEntry<Delivery>? entry = null;
try { try {
Delivery? d = null; Delivery? d = null;
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
if (res == "new") { if (res == "new") {
d = Context.CreateProxy<Delivery>(); d = Context.CreateProxy<Delivery>();
d.Date = delivery.Date; d.Date = delivery.Date;
@ -1053,7 +1202,7 @@ namespace Elwig.Windows {
$"Soll die Teillieferung Nr. {p.DPNr} wirklich unwiderruflich gelöscht werden?", $"Soll die Teillieferung Nr. {p.DPNr} wirklich unwiderruflich gelöscht werden?",
"Lieferung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); "Lieferung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r == MessageBoxResult.Yes) { if (r == MessageBoxResult.Yes) {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
Context.Remove(p); Context.Remove(p);
await Context.SaveChangesAsync(); await Context.SaveChangesAsync();
await RefreshDeliveryParts(); await RefreshDeliveryParts();
@ -1143,9 +1292,9 @@ namespace Elwig.Windows {
AbgewertetInput.IsEnabled = false; AbgewertetInput.IsEnabled = false;
ManualWeighingInput.IsEnabled = false; ManualWeighingInput.IsEnabled = false;
LsNrInput.IsReadOnly = true; LsNrInput.IsReadOnly = true;
DateInput.IsReadOnly = true; DateInput.IsReadOnly = !Menu_Settings_EnableFreeEditing.IsChecked;
TimeInput.IsReadOnly = true; TimeInput.IsReadOnly = !Menu_Settings_EnableFreeEditing.IsChecked;
BranchInput.IsEnabled = false; BranchInput.IsEnabled = Menu_Settings_EnableFreeEditing.IsChecked;
} }
private void DisableWeighingButtons() { private void DisableWeighingButtons() {
@ -1169,15 +1318,25 @@ namespace Elwig.Windows {
if (DateInput.Text == "" || BranchInput.SelectedItem == null) { if (DateInput.Text == "" || BranchInput.SelectedItem == null) {
LsNrInput.Text = ""; LsNrInput.Text = "";
} else { } else {
var branch = (Branch)BranchInput.SelectedItem; try {
var date = DateOnly.ParseExact(DateInput.Text, "dd.MM.yyyy"); var branch = (Branch)BranchInput.SelectedItem;
var lnr = await Context.NextLNr(date); var date = DateOnly.ParseExact(DateInput.Text, "dd.MM.yyyy");
LsNrInput.Text = Utils.GenerateLsNr(date, branch.ZwstId, lnr); var lnr = await Context.NextLNr(date);
LsNrInput.Text = Utils.GenerateLsNr(date, branch.ZwstId, lnr);
} catch {
LsNrInput.Text = "";
}
} }
} }
private void DateInput_TextChanged(object sender, TextChangedEventArgs evt) { private void DateInput_TextChanged(object sender, TextChangedEventArgs evt) {
if (IsCreating) UpdateLsNr().GetAwaiter().GetResult(); base.DateInput_TextChanged(sender, evt);
if (IsEditing || IsCreating) UpdateLsNr().GetAwaiter().GetResult();
}
private void BranchInput_SelectionChanged(object sender, RoutedEventArgs evt) {
base.ComboBox_SelectionChanged(sender, evt);
if (IsEditing || IsCreating) UpdateLsNr().GetAwaiter().GetResult();
} }
private void UpdateWineVariety(bool valid) { private void UpdateWineVariety(bool valid) {

View File

@ -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) { }

View File

@ -55,7 +55,12 @@
</MenuItem> </MenuItem>
<MenuItem Header="Drucken"> <MenuItem Header="Drucken">
<MenuItem Header="Stammdatenblatt drucken"/> <MenuItem Header="Stammdatenblatt drucken"/>
<MenuItem Header="Mitgliederliste drucken"/> <MenuItem Header="Briefköpfe drucken">
<MenuItem x:Name="Menu_Print_Letterheads_MgNr" Header="nach MgNr. sortiert" IsEnabled="False" Tag="Print"
Click="Menu_Print_Letterheads_MgNr_Click"/>
<MenuItem x:Name="Menu_Print_Letterheads_Name" Header="nach Name sortiert" IsEnabled="False" Tag="Print"
Click="Menu_Print_Letterheads_Name_Click"/>
</MenuItem>
</MenuItem> </MenuItem>
<MenuItem Header="Rundschreiben"> <MenuItem Header="Rundschreiben">
<MenuItem Header="Runschreiben ausschicken"/> <MenuItem Header="Runschreiben ausschicken"/>
@ -88,9 +93,15 @@
SelectionChanged="MemberList_SelectionChanged" SelectionChanged="MemberList_SelectionChanged"
Margin="5,0,5,0" Grid.Row="1" FontSize="14" Grid.ColumnSpan="3"> Margin="5,0,5,0" Grid.Row="1" FontSize="14" Grid.ColumnSpan="3">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="MgNr." Binding="{Binding MgNr}" Width="70"/> <DataGridTextColumn Header="MgNr." Binding="{Binding MgNr, StringFormat='{}{0} '}" Width="50">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Nachname" Binding="{Binding FamilyName}" Width="4*"/> <DataGridTextColumn Header="Nachname" Binding="{Binding FamilyName}" Width="4*"/>
<DataGridTextColumn Header="Vorname" Binding="{Binding GivenName}" Width="3*"/> <DataGridTextColumn Header="Vorname" Binding="{Binding GivenName}" Width="3*"/>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
@ -178,60 +189,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"/>

View File

@ -10,6 +10,7 @@ using Elwig.Models;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.ChangeTracking;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using Elwig.Documents;
namespace Elwig.Windows { namespace Elwig.Windows {
public partial class MemberAdminWindow : AdministrationWindow { public partial class MemberAdminWindow : AdministrationWindow {
@ -54,6 +55,9 @@ namespace Elwig.Windows {
} }
private void Window_Loaded(object sender, RoutedEventArgs evt) { private void Window_Loaded(object sender, RoutedEventArgs evt) {
Menu_Print_Letterheads_MgNr.IsEnabled = App.IsPrintingReady;
Menu_Print_Letterheads_Name.IsEnabled = App.IsPrintingReady;
ActiveMemberInput.IsChecked = true; ActiveMemberInput.IsChecked = true;
UpdatePhoneNrInputVisibility(); UpdatePhoneNrInputVisibility();
LockInputs(); LockInputs();
@ -89,7 +93,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) {
@ -130,8 +135,8 @@ namespace Elwig.Windows {
ValidateRequiredInputs(); ValidateRequiredInputs();
} }
protected override async Task RenewContext() { protected override async Task OnRenewContext() {
await base.RenewContext(); await base.OnRenewContext();
ControlUtils.RenewItemsSource(BranchInput, await Context.Branches.OrderBy(b => b.Name).ToListAsync(), i => (i as Branch)?.ZwstId); ControlUtils.RenewItemsSource(BranchInput, await Context.Branches.OrderBy(b => b.Name).ToListAsync(), i => (i as Branch)?.ZwstId);
ControlUtils.RenewItemsSource(DefaultKgInput, await Context.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync(), i => (i as AT_Kg)?.KgNr); ControlUtils.RenewItemsSource(DefaultKgInput, await Context.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync(), i => (i as AT_Kg)?.KgNr);
await RefreshMemberList(); await RefreshMemberList();
@ -265,7 +270,50 @@ 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.Select(a => a.Address));
}
private async void Menu_Print_Letterheads_MgNr_Click(object sender, RoutedEventArgs evt) {
var n = await Context.Members.CountAsync(m => m.IsActive);
var res = MessageBox.Show(
$"Sollen wirklich {n} Seiten gedruckt werden?", "Ausdruck Bestätigen",
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (res != MessageBoxResult.Yes)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
using var doc = await Document.Merge(Context.Members
.Where(m => m.IsActive && m.ContactViaPost)
.OrderBy(m => m.MgNr)
.Select(m => new Letterhead(m)));
await doc.Generate();
Mouse.OverrideCursor = null;
if (App.Config.Debug) {
doc.Show();
} else {
await doc.Print();
}
}
private async void Menu_Print_Letterheads_Name_Click(object sender, RoutedEventArgs evt) {
var n = await Context.Members.CountAsync(m => m.IsActive);
var res = MessageBox.Show(
$"Sollen wirklich {n} Seiten gedruckt werden?", "Ausdruck Bestätigen",
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (res != MessageBoxResult.Yes)
return;
Mouse.OverrideCursor = Cursors.AppStarting;
using var doc = await Document.Merge(Context.Members
.Where(m => m.IsActive && m.ContactViaPost)
.OrderBy(m => m.FamilyName)
.ThenBy(m => m.GivenName)
.Select(m => new Letterhead(m)));
await doc.Generate();
Mouse.OverrideCursor = null;
if (App.Config.Debug) {
doc.Show();
} else {
await doc.Print();
}
} }
private void FocusSearchInput(object sender, RoutedEventArgs evt) { private void FocusSearchInput(object sender, RoutedEventArgs evt) {
@ -348,8 +396,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 +469,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 +541,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 +594,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();
} }

View File

@ -19,9 +19,9 @@
<Button x:Name="ChartButton" Content="Chart" Click="ChartButton_Click" <Button x:Name="ChartButton" Content="Chart" Click="ChartButton_Click"
Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="PdfDeliveryButton" Content="Lieferschein Erzeugen" Click="PdfDeliveryButton_Click" Tag="Print" <Button x:Name="PdfDeliveryButton" Content="Lieferschein Erzeugen" Click="PdfDeliveryButton_Click" Tag="Print" IsEnabled="False"
Margin="260,190,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> Margin="260,190,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button x:Name="PdfCreditButton" Content="Gutschrift Erzeugen" Click="PdfCreditButton_Click" Tag="Print" <Button x:Name="PdfCreditButton" Content="Gutschrift Erzeugen" Click="PdfCreditButton_Click" Tag="Print" IsEnabled="False"
Margin="260,160,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> Margin="260,160,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
</Grid> </Grid>
</Window> </Window>

View File

@ -51,7 +51,7 @@ namespace Elwig.Windows {
} }
private async void PdfDeliveryButton_Click(object sender, RoutedEventArgs evt) { private async void PdfDeliveryButton_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
using var doc = new DeliveryNote(await ctx.Deliveries.OrderBy(d => d.Parts.Count).ThenBy(d => d.Year).ThenBy(d => d.DId).LastAsync(), ctx); using var doc = new DeliveryNote(await ctx.Deliveries.OrderBy(d => d.Parts.Count).ThenBy(d => d.Year).ThenBy(d => d.DId).LastAsync(), ctx);
await doc.Generate(); await doc.Generate();
@ -60,7 +60,7 @@ namespace Elwig.Windows {
} }
private async void PdfCreditButton_Click(object sender, RoutedEventArgs evt) { private async void PdfCreditButton_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.AppStarting;
using var ctx = new AppDbContext(); using var ctx = new AppDbContext();
using var doc = new CreditNote(await ctx.Credits.FirstAsync(), ctx); using var doc = new CreditNote(await ctx.Credits.FirstAsync(), ctx);
await doc.Generate(); await doc.Generate();

View File

@ -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

View 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")));
}); });
} }