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