2179 lines
108 KiB
C#
2179 lines
108 KiB
C#
using Elwig.Documents;
|
||
using Elwig.Helpers;
|
||
using Elwig.Helpers.Export;
|
||
using Elwig.Helpers.Weighing;
|
||
using Elwig.Models.Dtos;
|
||
using Elwig.Models.Entities;
|
||
using LinqKit;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||
using Microsoft.Win32;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Globalization;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Linq.Expressions;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Input;
|
||
using System.Windows.Threading;
|
||
|
||
namespace Elwig.Windows {
|
||
public partial class DeliveryAdminWindow : AdministrationWindow {
|
||
|
||
public readonly bool IsReceipt = false;
|
||
public int? MgNr => Member?.MgNr;
|
||
|
||
private bool IsUpdatingGradation = false;
|
||
private Member? Member = null;
|
||
private readonly DispatcherTimer Timer;
|
||
private List<string> TextFilter = [];
|
||
|
||
private readonly RoutedCommand CtrlF = new("CtrlF", typeof(DeliveryAdminWindow), [new KeyGesture(Key.F, ModifierKeys.Control)]);
|
||
private readonly RoutedCommand CtrlL = new("CtrlL", typeof(DeliveryAdminWindow), [new KeyGesture(Key.L, ModifierKeys.Control)]);
|
||
private readonly RoutedCommand CtrlP = new("CtrlP", typeof(DeliveryAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control)]);
|
||
private readonly RoutedCommand CtrlO = new("CtrlO", typeof(DeliveryAdminWindow), [new KeyGesture(Key.O, ModifierKeys.Control)]);
|
||
private readonly RoutedCommand CtrlJ = new("CtrlJ", typeof(DeliveryAdminWindow), [new KeyGesture(Key.J, ModifierKeys.Control)]);
|
||
private readonly RoutedCommand CtrlQ = new("CtrlQ", typeof(DeliveryAdminWindow), [new KeyGesture(Key.Q, ModifierKeys.Control)]);
|
||
private readonly RoutedCommand CtrlH = new("CtrlH", typeof(DeliveryAdminWindow), [new KeyGesture(Key.H, ModifierKeys.Control)]);
|
||
private readonly RoutedCommand CtrlShiftP = new("CtrlShiftP", typeof(DeliveryAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control | ModifierKeys.Shift)]);
|
||
private readonly RoutedCommand CtrlShiftO = new("CtrlShiftO", typeof(DeliveryAdminWindow), [new KeyGesture(Key.O, ModifierKeys.Control | ModifierKeys.Shift)]);
|
||
|
||
private string? LastScaleError = null;
|
||
private string? ManualWeighingReason = null;
|
||
private string? ScaleId = null;
|
||
private string? WeighingId = null;
|
||
private readonly Button[] WeighingButtons;
|
||
|
||
public DeliveryAdminWindow(bool receipt = false) {
|
||
InitializeComponent();
|
||
CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput));
|
||
CommandBindings.Add(new CommandBinding(CtrlL, Menu_DeliveryJournal_SaveFilters_Click));
|
||
CommandBindings.Add(new CommandBinding(CtrlP, Menu_DeliveryNote_Show_Click));
|
||
CommandBindings.Add(new CommandBinding(CtrlO, Menu_DeliveryJournal_ShowFilters_Click));
|
||
CommandBindings.Add(new CommandBinding(CtrlJ, Menu_DeliveryJournal_PrintToday_Click));
|
||
CommandBindings.Add(new CommandBinding(CtrlQ, Menu_WineQualityStatistics_PrintToday_Click));
|
||
CommandBindings.Add(new CommandBinding(CtrlH, Menu_Export_UploadToday_Click));
|
||
CommandBindings.Add(new CommandBinding(CtrlShiftP, Menu_DeliveryNote_Print_Click));
|
||
CommandBindings.Add(new CommandBinding(CtrlShiftO, Menu_DeliveryJournal_PrintFilters_Click));
|
||
RequiredInputs = [
|
||
MgNrInput, MemberInput,
|
||
LsNrInput, DateInput, BranchInput,
|
||
SortIdInput, WineVarietyInput,
|
||
GradationOeInput, GradationKmwInput, WineQualityLevelInput,
|
||
WineOriginInput, WineKgInput,
|
||
WeightInput
|
||
];
|
||
ExemptInputs = [
|
||
SearchInput, SeasonInput, TodayOnlyInput, AllSeasonsInput,
|
||
DeliveryList, DeliveryPartList,
|
||
MemberAddressField,
|
||
];
|
||
WeighingButtons = [
|
||
WeighingAButton, WeighingBButton, WeighingCButton, WeighingDButton,
|
||
];
|
||
IsReceipt = receipt;
|
||
|
||
Timer = new DispatcherTimer();
|
||
Timer.Tick += new EventHandler(OnSecondPassed);
|
||
Timer.Interval = new TimeSpan(0, 0, 1);
|
||
|
||
InitializeDelayTimer(SearchInput, SearchInput_TextChanged);
|
||
SearchInput.TextChanged -= SearchInput_TextChanged;
|
||
SeasonInput.Value = Utils.CurrentLastSeason;
|
||
|
||
DoShowWarningWindows = false;
|
||
|
||
if (IsReceipt) {
|
||
Title = $"Übernahme - {App.BranchName} - Elwig";
|
||
TodayOnlyInput.IsChecked = true;
|
||
var n = App.CommandScales.Count;
|
||
if (n < 1) WeighingAButton.Visibility = Visibility.Hidden;
|
||
if (n < 2) WeighingBButton.Visibility = Visibility.Hidden;
|
||
if (n < 3) WeighingCButton.Visibility = Visibility.Hidden;
|
||
if (n < 4) WeighingDButton.Visibility = Visibility.Hidden;
|
||
if (n == 1) WeighingAButton.Content = "Wiegen";
|
||
if (n > 1) WeighingAButton.Content = $"Wiegen {App.CommandScales[0].ScaleId}";
|
||
if (n >= 2) WeighingBButton.Content = $"Wiegen {App.CommandScales[1].ScaleId}";
|
||
if (n >= 3) WeighingCButton.Content = $"Wiegen {App.CommandScales[2].ScaleId}";
|
||
if (n >= 4) WeighingDButton.Content = $"Wiegen {App.CommandScales[3].ScaleId}";
|
||
WeighingManualButton.Margin = new Thickness(10, 10 + n * 32, 10, 10);
|
||
foreach (var s in App.EventScales) {
|
||
s.WeighingEvent += Scale_Weighing;
|
||
}
|
||
} else {
|
||
WeighingManualButton.Visibility = Visibility.Hidden;
|
||
WeighingAButton.Visibility = Visibility.Hidden;
|
||
WeighingBButton.Visibility = Visibility.Hidden;
|
||
WeighingCButton.Visibility = Visibility.Hidden;
|
||
WeighingDButton.Visibility = Visibility.Hidden;
|
||
}
|
||
|
||
Menu_WineQualityStatistics_ModeOe.IsChecked = false;
|
||
Menu_WineQualityStatistics_ModeKmw1.IsChecked = false;
|
||
Menu_WineQualityStatistics_ModeKmw2.IsChecked = false;
|
||
Menu_WineQualityStatistics_ModeKmw5.IsChecked = false;
|
||
Menu_WineQualityStatistics_ModeKmw10.IsChecked = false;
|
||
switch (App.Client.OrderingMemberList) {
|
||
case 0: Menu_WineQualityStatistics_ModeOe.IsChecked = true; break;
|
||
case 1: Menu_WineQualityStatistics_ModeKmw1.IsChecked = true; break;
|
||
case 2: Menu_WineQualityStatistics_ModeKmw2.IsChecked = true; break;
|
||
case 3: Menu_WineQualityStatistics_ModeKmw5.IsChecked = true; break;
|
||
case 4: Menu_WineQualityStatistics_ModeKmw10.IsChecked = true; break;
|
||
}
|
||
|
||
Menu_Export_UploadFilters.IsEnabled = App.Config.SyncUrl != null;
|
||
Menu_Export_UploadToday.IsEnabled = App.Config.SyncUrl != null;
|
||
}
|
||
|
||
public DeliveryAdminWindow(int mgnr) : this() {
|
||
using var ctx = new AppDbContext();
|
||
Member = GetMember(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
||
Title = $"Lieferungen - {Member.AdministrativeName} - Elwig";
|
||
AllSeasonsInput.IsEnabled = true;
|
||
}
|
||
|
||
private static async Task<Member?> GetMemberAsync(int mgnr) {
|
||
using var ctx = new AppDbContext();
|
||
return await ctx.Members
|
||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
||
.Include(m => m.DefaultWbKg!.AtKg)
|
||
.FirstOrDefaultAsync(m => m.MgNr == mgnr);
|
||
}
|
||
|
||
private static Member? GetMember(int mgnr) {
|
||
return GetMemberAsync(mgnr).GetAwaiter().GetResult();
|
||
}
|
||
|
||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
||
OnSecondPassed(null, null);
|
||
Timer.Start();
|
||
LockInputs();
|
||
if (IsReceipt) {
|
||
NewDeliveryButton_Click(null, null);
|
||
using var ctx = new AppDbContext();
|
||
if (ctx.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.Warning);
|
||
}
|
||
}
|
||
}
|
||
|
||
private async void Menu_DeliveryNote_Show_Click(object sender, RoutedEventArgs evt) {
|
||
if (DeliveryList.SelectedItem is not Delivery d)
|
||
return;
|
||
await GenerateDeliveryNote(d.Year, d.DId, ExportMode.Show);
|
||
}
|
||
|
||
private async void Menu_DeliveryNote_SavePdf_Click(object sender, RoutedEventArgs evt) {
|
||
if (DeliveryList.SelectedItem is not Delivery d)
|
||
return;
|
||
await GenerateDeliveryNote(d.Year, d.DId, ExportMode.SavePdf);
|
||
}
|
||
|
||
private async void Menu_DeliveryNote_Print_Click(object sender, RoutedEventArgs evt) {
|
||
if (DeliveryList.SelectedItem is not Delivery d)
|
||
return;
|
||
await GenerateDeliveryNote(d.Year, d.DId, ExportMode.Print);
|
||
}
|
||
|
||
private async void Menu_DeliveryNote_Email_Click(object sender, RoutedEventArgs evt) {
|
||
if (DeliveryList.SelectedItem is not Delivery d)
|
||
return;
|
||
await GenerateDeliveryNote(d.Year, d.DId, ExportMode.Email);
|
||
}
|
||
|
||
private static async Task GenerateDeliveryNote(int year, int did, ExportMode mode) {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
using var ctx = new AppDbContext();
|
||
var d = (await ctx.Deliveries.FindAsync(year, did))!;
|
||
using var doc = new DeliveryNote(d, ctx);
|
||
await Utils.ExportDocument(doc, mode, d.LsNr, (d.Member, $"{DeliveryNote.Name} Nr. {d.LsNr}", $"Im Anhang finden Sie den {DeliveryNote.Name} Nr. {d.LsNr}"));
|
||
} catch (Exception exc) {
|
||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
|
||
private async void Menu_Bki_SaveList_Click(object sender, RoutedEventArgs evt) {
|
||
if (sender is not MenuItem m) return;
|
||
var year = int.Parse(m.Header.ToString()?.Split(" ")[^1] ?? Utils.CurrentLastSeason.ToString());
|
||
var d = new SaveFileDialog() {
|
||
FileName = $"{App.Client.NameToken}-Traubentransportscheinliste-{year}.{Bki.FileExtension}",
|
||
DefaultExt = Bki.FileExtension,
|
||
Filter = "CSV-Datei (*.csv)|*.csv",
|
||
Title = $"Traubentransportscheinliste (BKI) speichern unter - Elwig"
|
||
};
|
||
if (d.ShowDialog() == true) {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
using var file = new Bki(d.FileName);
|
||
await file.ExportAsync(year);
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
}
|
||
|
||
private async void Menu_DeliveryJournal_SaveToday_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(1, ExportMode.SaveList);
|
||
}
|
||
|
||
private async void Menu_DeliveryJournal_SavePdfToday_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(1, ExportMode.SavePdf);
|
||
}
|
||
|
||
private async void Menu_DeliveryJournal_ShowToday_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(1, ExportMode.Show);
|
||
}
|
||
|
||
private async void Menu_Export_ExportToday_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(1, ExportMode.Export);
|
||
}
|
||
|
||
private async void Menu_Export_UploadToday_Click(object sender, RoutedEventArgs evt) {
|
||
if (App.Config.SyncUrl == null) return;
|
||
await GenerateDeliveryJournal(1, ExportMode.Upload);
|
||
}
|
||
|
||
private async void Menu_DeliveryJournal_PrintToday_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(1, ExportMode.Print);
|
||
}
|
||
|
||
private async void Menu_DeliveryJournal_SaveFilters_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(0, ExportMode.SaveList);
|
||
}
|
||
|
||
private async void Menu_DeliveryJournal_SavePdfFilters_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(0, ExportMode.SavePdf);
|
||
}
|
||
|
||
private async void Menu_DeliveryJournal_ShowFilters_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(0, ExportMode.Show);
|
||
}
|
||
|
||
private async void Menu_DeliveryJournal_PrintFilters_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(0, ExportMode.Print);
|
||
}
|
||
|
||
private async void Menu_Export_ExportFilters_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateDeliveryJournal(0, ExportMode.Export);
|
||
}
|
||
|
||
private async void Menu_Export_UploadFilters_Click(object sender, RoutedEventArgs evt) {
|
||
if (App.Config.SyncUrl == null) return;
|
||
await GenerateDeliveryJournal(0, ExportMode.Upload);
|
||
}
|
||
|
||
private async Task GenerateDeliveryJournal(int modeWho, ExportMode exportMode) {
|
||
using var ctx = new AppDbContext();
|
||
IQueryable<DeliveryPart> query;
|
||
List<string> filterNames = [];
|
||
if (modeWho == 0) {
|
||
var (f, _, q, _, _) = await GetFilters(ctx);
|
||
query = q;
|
||
filterNames.AddRange(f);
|
||
} else {
|
||
var date = $"{Utils.Today:yyyy-MM-dd}";
|
||
query = ctx.DeliveryParts
|
||
.Where(p => p.Delivery.DateString == date);
|
||
filterNames.Add($"{Utils.Today:dd.MM.yyyy}");
|
||
}
|
||
if (exportMode == ExportMode.Upload && !filterNames.Contains($"Zweigstelle {App.BranchName}")) {
|
||
query = query.Where(p => p.Delivery.ZwstId == App.ZwstId);
|
||
filterNames.Add($"Zweigstelle {App.BranchName}");
|
||
}
|
||
|
||
query = query
|
||
.OrderBy(p => p.Delivery.DateString)
|
||
.ThenBy(p => p.Delivery.TimeString)
|
||
.ThenBy(p => p.Delivery.LsNr)
|
||
.ThenBy(p => p.DPNr);
|
||
|
||
if (exportMode == ExportMode.SaveList) {
|
||
var d = new SaveFileDialog() {
|
||
FileName = $"{DeliveryJournal.Name}.ods",
|
||
DefaultExt = "ods",
|
||
Filter = "OpenDocument Format Spreadsheet (*.ods)|*.ods",
|
||
Title = $"{DeliveryJournal.Name} speichern unter - Elwig"
|
||
};
|
||
if (d.ShowDialog() == true) {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
var data = await DeliveryJournalData.FromQuery(query, filterNames);
|
||
using var ods = new OdsFile(d.FileName);
|
||
await ods.AddTable(data);
|
||
} catch (Exception exc) {
|
||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
} else if (exportMode == ExportMode.Export) {
|
||
var d = new SaveFileDialog() {
|
||
FileName = $"Lieferungen.zip",
|
||
DefaultExt = "zip",
|
||
Filter = "ZIP-Datei (*.zip)|*.zip",
|
||
Title = $"{DeliveryJournal.Name} speichern unter - Elwig"
|
||
};
|
||
if (d.ShowDialog() == true) {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
await ElwigData.ExportDeliveries(d.FileName, await query.Select(p => p.Delivery).Distinct().ToListAsync(), filterNames);
|
||
} catch (Exception exc) {
|
||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
} else if (exportMode == ExportMode.Upload && App.Config.SyncUrl != null) {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
var filename = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{App.ZwstId}.zip";
|
||
var path = Path.Combine(App.TempPath, filename);
|
||
var list = await query.Select(p => p.Delivery).Distinct().ToListAsync();
|
||
if (list.Count == 0) {
|
||
MessageBox.Show("Es wurden keine Lieferungen zum Hochladen ausgewählt!", "Fehler",
|
||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||
} else {
|
||
await ElwigData.ExportDeliveries(path, list, filterNames);
|
||
await Utils.UploadExportData(path, App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword);
|
||
MessageBox.Show($"Lieferungen erfolgreich hochgeladen!", "Lieferungen hochgeladen",
|
||
MessageBoxButton.OK, MessageBoxImage.Information);
|
||
}
|
||
} catch (Exception exc) {
|
||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
} else {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
var data = await DeliveryJournalData.FromQuery(query, filterNames);
|
||
using var doc = new DeliveryJournal(string.Join(" / ", filterNames), data);
|
||
await Utils.ExportDocument(doc, exportMode);
|
||
} catch (Exception exc) {
|
||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
}
|
||
|
||
private async void Menu_WineQualityStatistics_ShowToday_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateWineQualityStatistics(1, ExportMode.Show);
|
||
}
|
||
|
||
private async void Menu_WineQualityStatistics_SavePdfToday_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateWineQualityStatistics(1, ExportMode.SavePdf);
|
||
}
|
||
|
||
private async void Menu_WineQualityStatistics_PrintToday_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateWineQualityStatistics(1, ExportMode.Print);
|
||
}
|
||
|
||
private async void Menu_WineQualityStatistics_ShowFilters_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateWineQualityStatistics(0, ExportMode.Show);
|
||
}
|
||
|
||
private async void Menu_WineQualityStatistics_SavePdfFilters_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateWineQualityStatistics(0, ExportMode.SavePdf);
|
||
}
|
||
|
||
private async void Menu_WineQualityStatistics_PrintFilters_Click(object sender, RoutedEventArgs evt) {
|
||
await GenerateWineQualityStatistics(0, ExportMode.Print);
|
||
}
|
||
|
||
private async Task GenerateWineQualityStatistics(int modeWho, ExportMode exportMode) {
|
||
using var ctx = new AppDbContext();
|
||
IQueryable<DeliveryPart> query;
|
||
List<string> filterNames = [];
|
||
if (modeWho == 0) {
|
||
var (f, _, q, _, _) = await GetFilters(ctx);
|
||
query = q;
|
||
filterNames.AddRange(f);
|
||
} else {
|
||
var date = $"{Utils.Today:yyyy-MM-dd}";
|
||
query = ctx.DeliveryParts
|
||
.Where(p => p.Delivery.DateString == date);
|
||
filterNames.Add($"{Utils.Today:dd.MM.yyyy}");
|
||
}
|
||
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
var data = await WineQualityStatisticsData.FromQuery(query, App.Client.OrderingMemberList);
|
||
using var doc = new WineQualityStatistics(string.Join(" / ", filterNames), data);
|
||
await Utils.ExportDocument(doc, exportMode);
|
||
} catch (Exception exc) {
|
||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
|
||
private async void Menu_WineQualityStatistics_Mode_Click(object sender, RoutedEventArgs evt) {
|
||
Menu_WineQualityStatistics.IsSubmenuOpen = true;
|
||
if (sender == Menu_WineQualityStatistics_ModeOe) {
|
||
App.Client.OrderingMemberList = 0;
|
||
} else if (sender == Menu_WineQualityStatistics_ModeKmw1) {
|
||
App.Client.OrderingMemberList = 1;
|
||
} else if (sender == Menu_WineQualityStatistics_ModeKmw2) {
|
||
App.Client.OrderingMemberList = 2;
|
||
} else if (sender == Menu_WineQualityStatistics_ModeKmw5) {
|
||
App.Client.OrderingMemberList = 3;
|
||
} else if (sender == Menu_WineQualityStatistics_ModeKmw10) {
|
||
App.Client.OrderingMemberList = 4;
|
||
}
|
||
Menu_WineQualityStatistics_ModeOe.IsChecked = App.Client.OrderingMemberList == 0;
|
||
Menu_WineQualityStatistics_ModeKmw1.IsChecked = App.Client.OrderingMemberList == 1;
|
||
Menu_WineQualityStatistics_ModeKmw2.IsChecked = App.Client.OrderingMemberList == 2;
|
||
Menu_WineQualityStatistics_ModeKmw5.IsChecked = App.Client.OrderingMemberList == 3;
|
||
Menu_WineQualityStatistics_ModeKmw10.IsChecked = App.Client.OrderingMemberList == 4;
|
||
await App.Client.UpdateValues();
|
||
}
|
||
|
||
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) {
|
||
if (IsReceipt && IsCreating && !Menu_Settings_EnableFreeEditing.IsChecked) {
|
||
var now = DateTime.Now;
|
||
TimeInput.Text = now.ToString("HH:mm");
|
||
DateInput.Text = now.ToString("dd.MM.yyyy");
|
||
SetDefaultValue(TimeInput);
|
||
SetDefaultValue(DateInput);
|
||
}
|
||
}
|
||
|
||
private void InitialDefaultInputs() {
|
||
if (App.Client.HasNetWeighing(BranchInput.SelectedValue as Branch)) {
|
||
GerebeltGewogenInput.IsEnabled = false;
|
||
SetDefaultValue(GerebeltGewogenInput, true);
|
||
} else {
|
||
GerebeltGewogenInput.IsEnabled = true;
|
||
UnsetDefaultValue(GerebeltGewogenInput);
|
||
}
|
||
|
||
if (!App.Client.HasNetWeighing(BranchInput.SelectedValue as Branch)) {
|
||
LesewagenInput.IsEnabled = false;
|
||
SetDefaultValue(LesewagenInput, false);
|
||
HandPickedInput.IsThreeState = false;
|
||
UnsetDefaultValue(HandPickedInput);
|
||
} else {
|
||
LesewagenInput.IsEnabled = true;
|
||
UnsetDefaultValue(LesewagenInput);
|
||
HandPickedInput.IsThreeState = true;
|
||
SetDefaultValue(HandPickedInput, null);
|
||
}
|
||
|
||
if (App.Client.IsMatzen || App.Client.IsWinzerkeller) {
|
||
GebundenInput.IsEnabled = false;
|
||
SetDefaultValue(GebundenInput, null);
|
||
} else {
|
||
GebundenInput.IsEnabled = true;
|
||
UnsetDefaultValue(GebundenInput);
|
||
}
|
||
}
|
||
|
||
private void InitialInputs() {
|
||
LastScaleError = null;
|
||
WeighingId = null;
|
||
ScaleId = null;
|
||
ManualWeighingReason = null;
|
||
|
||
ClearOriginalValues();
|
||
ClearDefaultValues();
|
||
|
||
GerebeltGewogenInput.IsChecked = App.Client.HasNetWeighing(BranchInput.SelectedValue as Branch);
|
||
LesewagenInput.IsChecked = false;
|
||
HandPickedInput.IsChecked = !App.Client.HasNetWeighing(BranchInput.SelectedValue as Branch) ? true : null;
|
||
GebundenInput.IsChecked = null;
|
||
InitialDefaultInputs();
|
||
|
||
WineQualityLevelInput.IsEnabled = false;
|
||
ValidateRequiredInputs();
|
||
}
|
||
|
||
private void InitInputs() {
|
||
ControlUtils.SelectItemWithPk(BranchInput, App.ZwstId);
|
||
OnSecondPassed(null, null);
|
||
UpdateLsNr().GetAwaiter().GetResult();
|
||
InitialInputs();
|
||
}
|
||
|
||
protected override void UpdateButtons() {
|
||
if (!IsEditing && !IsCreating) return;
|
||
bool ch = HasChanged, v = IsValid;
|
||
ResetButton.IsEnabled = ch;
|
||
SaveButton.IsEnabled = v && ch;
|
||
FinishButton.IsEnabled = v && ch;
|
||
NewDeliveryPartButton.IsEnabled = v && ch;
|
||
CancelCreatingButton.IsEnabled = DeliveryList.SelectedItem == null || DeliveryPartList.SelectedItem == null;
|
||
}
|
||
|
||
private void Input_KeyUp(object sender, KeyEventArgs evt) {
|
||
if (sender is not Control ctrl) return;
|
||
if (evt.Key != Key.Enter) return;
|
||
if (ctrl == MgNrInput || ctrl == MemberInput) {
|
||
SortIdInput.Focus();
|
||
SortIdInput.SelectAll();
|
||
} else if (ctrl == SortIdInput || ctrl == WineVarietyInput || ctrl == AttributeInput || ctrl == CultivationInput) {
|
||
GradationOeInput.Focus();
|
||
GradationOeInput.SelectAll();
|
||
} else if (ctrl == GradationKmwInput || ctrl == GradationOeInput || ctrl == WineQualityLevelInput) {
|
||
if (WeighingAButton.IsVisible) WeighingAButton.Focus();
|
||
else WeighingManualButton.Focus();
|
||
}
|
||
}
|
||
|
||
private async Task RefreshDeliveryList() {
|
||
await RefreshDeliveryListQuery();
|
||
}
|
||
|
||
private async Task<(List<string>, IQueryable<Delivery>, IQueryable<DeliveryPart>, Predicate<DeliveryPart>, List<string>)> GetFilters(AppDbContext ctx) {
|
||
List<string> filterNames = [];
|
||
IQueryable<Delivery> deliveryQuery = ctx.Deliveries;
|
||
if (IsReceipt && App.BranchNum > 1) {
|
||
deliveryQuery = deliveryQuery.Where(d => d.ZwstId == App.ZwstId);
|
||
filterNames.Add($"Zweigstelle {App.BranchName}");
|
||
}
|
||
if (Member != null) {
|
||
deliveryQuery = deliveryQuery.Where(d => d.MgNr == Member.MgNr);
|
||
filterNames.Add(Member.AdministrativeName);
|
||
}
|
||
if (TodayOnlyInput.IsChecked == true) {
|
||
deliveryQuery = deliveryQuery
|
||
.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 == null || d.TimeString.CompareTo("03:00:00") <= 0)));
|
||
filterNames.Add(Utils.Today.ToString("dd.MM.yyyy"));
|
||
} else if (AllSeasonsInput.IsChecked == false) {
|
||
deliveryQuery = deliveryQuery.Where(d => d.Year == SeasonInput.Value);
|
||
filterNames.Add(SeasonInput.Value.ToString() ?? "");
|
||
}
|
||
|
||
Expression<Func<DeliveryPart, bool>> prd = p => true;
|
||
|
||
var filterVar = new List<string>();
|
||
var filterNotVar = new List<string>();
|
||
var filterQual = new List<string>();
|
||
var filterNotQual = new List<string>();
|
||
var filterMgNr = new List<int>();
|
||
var filterZwst = new List<string>();
|
||
var filterAttr = new List<string>();
|
||
var filterNotAttr = new List<string>();
|
||
var filterCult = new List<string>();
|
||
var filterNotCult = new List<string>();
|
||
var filterDate = new List<(string?, string?)>();
|
||
var filterTime = new List<(string?, string?)>();
|
||
int filterYearGt = 0, filterYearLt = 0;
|
||
double filterKmwGt = 0, filterKmwLt = 0;
|
||
double filterOeGt = 0, filterOeLt = 0;
|
||
|
||
var filter = TextFilter.ToList();
|
||
if (filter.Count > 0) {
|
||
var var = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
|
||
var qual = await ctx.WineQualityLevels.Where(q => !q.IsPredicate).ToDictionaryAsync(q => q.QualId, q => q);
|
||
var mgnr = await ctx.Members.ToDictionaryAsync(m => m.MgNr.ToString(), m => m);
|
||
var zwst = await ctx.Branches.ToDictionaryAsync(b => b.Name.ToLower().Split(" ")[0], b => b);
|
||
var attr = await ctx.WineAttributes.ToDictionaryAsync(a => a.Name.ToLower().Split(' ')[0], a => a);
|
||
var cult = await ctx.WineCultivations.ToDictionaryAsync(c => c.Name.ToLower().Split(' ')[0], c => c);
|
||
|
||
for (int i = 0; i < filter.Count; i++) {
|
||
var e = filter[i];
|
||
if (e.ToLower() is "r" or "rot") {
|
||
filterVar.AddRange(var.Values.Where(v => v.IsRed).Select(v => v.SortId));
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("Rotweinsorten");
|
||
} else if (e.ToLower() is "w" or "weiß" or "weiss") {
|
||
filterVar.AddRange(var.Values.Where(v => v.IsWhite).Select(v => v.SortId));
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("Weißweinsorten");
|
||
} else if (e.Length >= 3 && e.Length <= 8 && "gebunden".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsGebunden == true);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("gebunden");
|
||
} else if (e.Length >= 4 && e.Length <= 9 && "!gebunden".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsGebunden != true);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("nicht gebunden");
|
||
} else if (e.Length >= 5 && e.Length <= 10 && "ungebunden".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsGebunden == false);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("ungebunden");
|
||
} else if (e.Length >= 6 && e.Length <= 11 && "!ungebunden".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsGebunden != false);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("nicht ungebunden");
|
||
} else if (e.Length >= 5 && e.Length <= 8 && "handlese".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsHandPicked == true);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("Handlese");
|
||
} else if (e.Length >= 6 && e.Length <= 9 && "!handlese".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsHandPicked == false);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("keine Handlese");
|
||
} else if (e.Length >= 5 && e.Length <= 11 && "handwiegung".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsManualWeighing == true);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("Handwiegung");
|
||
} else if (e.Length >= 6 && e.Length <= 12 && "!handwiegung".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsManualWeighing == false);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("keine Handwiegung");
|
||
} else if (e.ToLower() is "bto" or "brut" or "brutt" or "brutto" or "!gerebelt") {
|
||
prd = prd.And(p => p.IsNetWeight == false);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("brutto Wiegung");
|
||
} else if (e.ToLower() is "nto" or "net" or "nett" or "netto" or "gerebelt") {
|
||
prd = prd.And(p => p.IsNetWeight == true);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("netto Wiegung");
|
||
} else if (e.Length >= 5 && e.Length <= 9 && "lesewagen".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsLesewagen == true);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("Lesewagen");
|
||
} else if (e.Length >= 6 && e.Length <= 10 && "!lesewagen".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
prd = prd.And(p => p.IsLesewagen == false);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("kein Lesewagen");
|
||
} else if (e.Length == 2 && var.ContainsKey(e.ToUpper())) {
|
||
filterVar.Add(e.ToUpper());
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add(var[e.ToUpper()].Name);
|
||
} else if (e.Length == 3 && e[0] == '!' && var.ContainsKey(e[1..].ToUpper())) {
|
||
filterNotVar.Add(e[1..].ToUpper());
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("außer " + var[e[1..].ToUpper()].Name);
|
||
} else if (e.Length == 3 && qual.ContainsKey(e.ToUpper())) {
|
||
var qualId = e.ToUpper();
|
||
filterQual.Add(qualId);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add(qualId == "WEI" ? "abgewertet" : qual[e.ToUpper()].Name);
|
||
} else if (e[0] == '!' && qual.ContainsKey(e[1..].ToUpper())) {
|
||
var qualId = e[1..].ToUpper();
|
||
filterNotQual.Add(qualId);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add(qualId == "WEI" ? "nicht abgewertet" : "außer " + qual[e[1..].ToUpper()].Name);
|
||
} else if (e.Length >= 5 && e.Length <= 10 && "abgewertet".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
filterQual.Add("WEI");
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("abgewertet");
|
||
} else if (e.Length >= 6 && e.Length <= 11 && "!abgewertet".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) {
|
||
filterNotQual.Add("WEI");
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add("nicht abgewertet");
|
||
} else if (e.All(char.IsAsciiDigit) && mgnr.TryGetValue(e, out var member)) {
|
||
filterMgNr.Add(int.Parse(e));
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add(member.AdministrativeName);
|
||
} else if (attr.ContainsKey(e.ToLower())) {
|
||
var a = attr[e.ToLower()];
|
||
filterAttr.Add(a.AttrId);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add($"Attribut {a.Name}");
|
||
} else if (e[0] == '!' && attr.ContainsKey(e[1..].ToLower())) {
|
||
var a = attr[e[1..].ToLower()];
|
||
filterNotAttr.Add(a.AttrId);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add($"ohne Attribut {a.Name}");
|
||
} else if (cult.ContainsKey(e.ToLower())) {
|
||
var c = cult[e.ToLower()];
|
||
filterCult.Add(c.CultId);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add($"Bewirtschaftung {c.Name}");
|
||
} else if (e[0] == '!' && cult.ContainsKey(e[1..].ToLower())) {
|
||
var c = cult[e[1..].ToLower()];
|
||
filterNotCult.Add(c.CultId);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add($"ohne Bewirtschaftung {c.Name}");
|
||
} else if (zwst.ContainsKey(e.ToLower())) {
|
||
var b = zwst[e.ToLower()];
|
||
filterZwst.Add(b.ZwstId);
|
||
filter.RemoveAt(i--);
|
||
filterNames.Add($"Zweigstelle {b.Name}");
|
||
} else if (e.StartsWith('>') || e.StartsWith('<')) {
|
||
if (double.TryParse(e[1..], out var num)) {
|
||
switch ((e[0], num)) {
|
||
case ('>', <= 30): filterKmwGt = num; break;
|
||
case ('<', <= 30): filterKmwLt = num; break;
|
||
case ('>', >= 1900): filterYearGt = (int)num; break;
|
||
case ('<', >= 1900): filterYearLt = (int)num; break;
|
||
case ('>', _): filterOeGt = num; break;
|
||
case ('<', _): filterOeLt = num; break;
|
||
}
|
||
filter.RemoveAt(i--);
|
||
}
|
||
if (e.Length == 1) filter.RemoveAt(i--);
|
||
} else if (e.Length > 1 && Utils.FromToRegex.IsMatch(e)) {
|
||
var parts = e.Split("-");
|
||
double? from = (parts[0].Length > 0) ? double.Parse(parts[0], CultureInfo.InvariantCulture) : null;
|
||
double? to = (parts[1].Length > 0) ? double.Parse(parts[1], CultureInfo.InvariantCulture) : null;
|
||
switch ((from, to)) {
|
||
case ( <= 30, <= 30):
|
||
case ( <= 30, null):
|
||
case (null, <= 30):
|
||
filterKmwGt = from ?? 0;
|
||
filterKmwLt = to ?? 0;
|
||
break;
|
||
case ( >= 1900, >= 1900):
|
||
case ( >= 1900, null):
|
||
case (null, >= 1900):
|
||
filterYearGt = (int)(from ?? 0);
|
||
filterYearLt = (int)(to ?? -1) + 1;
|
||
break;
|
||
case (_, _):
|
||
filterOeGt = from ?? 0;
|
||
filterOeLt = to ?? 0;
|
||
break;
|
||
}
|
||
filter.RemoveAt(i--);
|
||
} else if (e.Length > 1 && Utils.FromToTimeRegex.IsMatch(e)) {
|
||
var parts = e.Split("-");
|
||
filterTime.Add((TimeOnly.TryParse(parts[0], out var from) ? $"{from:HH:mm}" : null, TimeOnly.TryParse(parts[1], out var to) ? $"{to:HH:mm}" : null));
|
||
filter.RemoveAt(i--);
|
||
var t = filterTime.Last();
|
||
if (t.Item1 != null && t.Item2 != null) {
|
||
filterNames.Add($"{t.Item1}–{t.Item2}");
|
||
} else if (t.Item1 != null) {
|
||
filterNames.Add($"ab {t.Item1}");
|
||
} else if (t.Item2 != null) {
|
||
filterNames.Add($"bis {t.Item2}");
|
||
}
|
||
} else if (DateOnly.TryParse(e, out var date)) {
|
||
var s = date.ToString("yyyy-MM-dd");
|
||
filterDate.Add((s, s));
|
||
filter.RemoveAt(i--);
|
||
if (filterNames.Contains(SeasonInput.Value.ToString()!) && SeasonInput.Value == date.Year)
|
||
filterNames.Remove(SeasonInput.Value.ToString()!);
|
||
filterNames.Add(date.ToString("dd.MM.yyyy"));
|
||
} else if (Utils.DateFromToRegex.IsMatch(e)) {
|
||
var parts = e.Split("-");
|
||
if (parts.Length == 1) {
|
||
// single date
|
||
var dParts = parts[0].Split('.');
|
||
var s = $"{dParts[2]}-{dParts[1].PadLeft(2, '0')}-{dParts[0].PadLeft(2, '0')}";
|
||
filterDate.Add((s, s));
|
||
filter.RemoveAt(i--);
|
||
var n = string.Join('.', s.Split('-').Reverse());
|
||
if (dParts[2] == "") {
|
||
filterNames.Remove(SeasonInput.Value.ToString()!);
|
||
filterNames.Add(n + SeasonInput.Value.ToString());
|
||
} else {
|
||
if (SeasonInput.Value.ToString() == dParts[2])
|
||
filterNames.Remove(SeasonInput.Value.ToString()!);
|
||
filterNames.Add(n);
|
||
}
|
||
} else if (parts.Length == 2) {
|
||
// from/to date
|
||
var d1Parts = parts[0].Split('.');
|
||
var d2Parts = parts[1].Split('.');
|
||
var s1 = d1Parts.Length < 2 ? null : $"{d1Parts.ElementAtOrDefault(2)}-{d1Parts[1].PadLeft(2, '0')}-{d1Parts[0].PadLeft(2, '0')}";
|
||
var s2 = d2Parts.Length < 2 ? null : $"{d2Parts.ElementAtOrDefault(2)}-{d2Parts[1].PadLeft(2, '0')}-{d2Parts[0].PadLeft(2, '0')}";
|
||
filterDate.Add((s1, s2));
|
||
filter.RemoveAt(i--);
|
||
var n1 = s1 == null ? null : string.Join('.', s1.Split('-').Reverse());
|
||
var n2 = s2 == null ? null : string.Join('.', s2.Split('-').Reverse());
|
||
if (n1 != null && n2 != null) {
|
||
filterNames.Add($"{n1}–{n2}");
|
||
} else if (n1 != null) {
|
||
filterNames.Add($"ab dem {n1}");
|
||
} else if (n2 != null) {
|
||
filterNames.Add($"bis zum {n2}");
|
||
}
|
||
}
|
||
} else if (e.Length > 2 && e.StartsWith('"') && e.EndsWith('"')) {
|
||
filter[i] = e[1..^1];
|
||
} else if (e.Length <= 2) {
|
||
filter.RemoveAt(i--);
|
||
}
|
||
}
|
||
|
||
if (filterYearGt > 0) prd = prd.And(p => p.Year >= filterYearGt);
|
||
if (filterYearLt > 0) prd = prd.And(p => p.Year < filterYearLt);
|
||
if (filterMgNr.Count > 0) prd = prd.And(p => filterMgNr.Contains(p.Delivery.MgNr));
|
||
if (filterDate.Count > 0) {
|
||
var pr = PredicateBuilder.New<DeliveryPart>(false);
|
||
foreach (var (d1, d2) in filterDate)
|
||
pr.Or(p => (d1 == null || d1.CompareTo(p.Delivery.DateString.Substring(10 - d1.Length)) <= 0) && (d2 == null || d2.CompareTo(p.Delivery.DateString.Substring(10 - d2.Length)) >= 0));
|
||
prd = prd.And(pr);
|
||
}
|
||
if (filterTime.Count > 0) {
|
||
var pr = PredicateBuilder.New<DeliveryPart>(false);
|
||
foreach (var (t1, t2) in filterTime)
|
||
pr.Or(p => (t1 == null || t1.CompareTo(p.Delivery.TimeString) <= 0) && (t2 == null || t2.CompareTo(p.Delivery.TimeString) > 0));
|
||
prd = prd.And(p => p.Delivery.TimeString != null).And(pr);
|
||
}
|
||
if (filterVar.Count > 0) prd = prd.And(p => filterVar.Contains(p.SortId));
|
||
if (filterNotVar.Count > 0) prd = prd.And(p => !filterNotVar.Contains(p.SortId));
|
||
if (filterQual.Count > 0) prd = prd.And(p => filterQual.Contains(p.QualId));
|
||
if (filterNotQual.Count > 0) prd = prd.And(p => !filterNotQual.Contains(p.QualId));
|
||
if (filterZwst.Count > 0) prd = prd.And(p => filterZwst.Contains(p.Delivery.ZwstId));
|
||
if (filterAttr.Count > 0) prd = prd.And(p => p.AttrId != null && filterAttr.Contains(p.AttrId));
|
||
if (filterNotAttr.Count > 0) prd = prd.And(p => p.AttrId == null || !filterNotAttr.Contains(p.AttrId));
|
||
if (filterCult.Count > 0) prd = prd.And(p => p.CultId != null && filterCult.Contains(p.CultId));
|
||
if (filterNotCult.Count > 0) prd = prd.And(p => p.CultId == null || !filterNotCult.Contains(p.CultId));
|
||
if (filterKmwGt > 0) prd = prd.And(p => p.Kmw >= filterKmwGt);
|
||
if (filterKmwLt > 0) prd = prd.And(p => p.Kmw < filterKmwLt);
|
||
if (filterOeGt > 0) prd = prd.And(p => p.Kmw * (4.54 + 0.022 * p.Kmw) >= filterOeGt);
|
||
if (filterOeLt > 0) prd = prd.And(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");
|
||
}
|
||
}
|
||
|
||
IQueryable<DeliveryPart> dpq = deliveryQuery
|
||
.SelectMany(d => d.Parts)
|
||
.Where(prd)
|
||
.OrderBy(p => p.Delivery.DateString)
|
||
.ThenBy(p => p.Delivery.TimeString)
|
||
.ThenBy(p => p.Delivery.LsNr)
|
||
.ThenBy(p => p.DPNr);
|
||
|
||
return (filterNames, dpq.Select(p => p.Delivery).Distinct().OrderBy(d => d.DateString).ThenBy(d => d.TimeString), dpq, prd.Invoke, filter);
|
||
}
|
||
|
||
private static void AddToolTipCell(Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) {
|
||
var tb = new TextBlock() {
|
||
Text = text,
|
||
TextAlignment = alignRight ? TextAlignment.Right : alignCenter ? TextAlignment.Center : TextAlignment.Left,
|
||
Margin = new(0, 12 * row, 0, 0),
|
||
FontWeight = bold ? FontWeights.Bold : FontWeights.Normal,
|
||
};
|
||
tb.SetValue(Grid.ColumnProperty, col);
|
||
tb.SetValue(Grid.ColumnSpanProperty, colSpan);
|
||
grid.Children.Add(tb);
|
||
}
|
||
|
||
private void AddWeightToolTipRow(int row, string? h1, string? h2, int weight, int? total1, int total2) {
|
||
var bold = h2 == null;
|
||
if (h1 != null) AddToolTipCell(StatusWeightToolTip, h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||
if (h2 != null) AddToolTipCell(StatusWeightToolTip, h2 + ":", row, 1, 1, bold);
|
||
AddToolTipCell(StatusWeightToolTip, $"{weight:N0} kg", row, 2, 1, bold, true);
|
||
if (total1 != null && total1 != 0)
|
||
AddToolTipCell(StatusWeightToolTip, $"{weight * 100.0 / total1:N1} %", row, 3, 1, bold, true);
|
||
if (total2 != 0)
|
||
AddToolTipCell(StatusWeightToolTip, $"{weight * 100.0 / total2:N1} %", row, 4, 1, bold, true);
|
||
}
|
||
|
||
private void AddGradationToolTipRow(int row, string? h1, string? h2, double min, double avg, double max) {
|
||
var bold = h2 == null;
|
||
if (h1 != null) AddToolTipCell(StatusGradationToolTip, h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||
if (h2 != null) AddToolTipCell(StatusGradationToolTip, h2 + ":", row, 1, 1, bold);
|
||
AddToolTipCell(StatusGradationToolTip, $"{min:N1}°", row, 2, 1, bold, true);
|
||
AddToolTipCell(StatusGradationToolTip, $"{avg:N1}°", row, 3, 1, bold, true);
|
||
AddToolTipCell(StatusGradationToolTip, $"{max:N1}°", row, 4, 1, bold, true);
|
||
}
|
||
|
||
private async Task RefreshDeliveryListQuery(bool updateSort = false) {
|
||
using var ctx = new AppDbContext();
|
||
var (_, deliveryQuery, deliveryPartsQuery, predicate, filter) = await GetFilters(ctx);
|
||
var deliveries = await deliveryQuery
|
||
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier)
|
||
.Include(d => d.Parts).ThenInclude(p => p.Attribute)
|
||
.Include(d => d.Parts).ThenInclude(p => p.Cultivation)
|
||
.Include(d => d.Parts).ThenInclude(p => p.Variety)
|
||
.Include(d => d.Member.EmailAddresses)
|
||
.AsSplitQuery()
|
||
.ToListAsync();
|
||
deliveries.Reverse();
|
||
|
||
if (filter.Count > 0 && deliveries.Count > 0) {
|
||
var dict = deliveries.AsParallel()
|
||
.ToDictionary(d => d, d => d.SearchScore(TextFilter))
|
||
.OrderByDescending(a => a.Value)
|
||
.ThenBy(a => a.Key.DateTime);
|
||
var threshold = dict.Select(a => a.Value).Max() * 3 / 4;
|
||
deliveries = dict
|
||
.Where(a => a.Value > threshold)
|
||
.Select(a => a.Key)
|
||
.ToList();
|
||
}
|
||
|
||
deliveries.ForEach(d => { d.PartFilter = predicate; });
|
||
ControlUtils.RenewItemsSource(DeliveryList, deliveries,
|
||
DeliveryList_SelectionChanged, filter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||
await RefreshDeliveryParts();
|
||
|
||
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.ToolTip = StatusMembers.Text;
|
||
StatusDeliveries.Text = $"Lieferungen: {deliveries.Count}";
|
||
|
||
if (filter.Count == 0) {
|
||
var deliveryParts = deliveryPartsQuery;
|
||
var n = await deliveryParts.CountAsync();
|
||
StatusDeliveries.Text = $"Lieferungen: {deliveries.Count} ({n})";
|
||
var varieties = await deliveryParts.Select(d => d.SortId).Distinct().ToListAsync();
|
||
StatusVarieties.Text = $"Sorten: {varieties.Count}" + (varieties.Count > 0 && varieties.Count <= 10 ? $" ({string.Join(", ", varieties)})" : "");
|
||
|
||
StatusWeightToolTip.Children.Clear();
|
||
StatusGradationToolTip.Children.Clear();
|
||
|
||
var weight = await deliveryParts.SumAsync(p => p.Weight);
|
||
StatusWeight.Text = $"Gewicht: {weight:N0} kg";
|
||
AddWeightToolTipRow(0, "Gewicht", null, weight, null, weight);
|
||
|
||
if (n > 0) {
|
||
var kmwMin = await deliveryParts.MinAsync(p => p.Kmw);
|
||
var kmwAvg = Utils.AggregateDeliveryPartsKmw(deliveryParts);
|
||
var kmwMax = await deliveryParts.MaxAsync(p => p.Kmw);
|
||
StatusGradation.Text = $"Gradation: {kmwMin:N1}° / {kmwAvg:N1}° / {kmwMax:N1}°";
|
||
AddToolTipCell(StatusGradationToolTip, "Min.", 0, 2, 1, false, false, true);
|
||
AddToolTipCell(StatusGradationToolTip, "⌀", 0, 3, 1, false, false, true);
|
||
AddToolTipCell(StatusGradationToolTip, "Max.", 0, 4, 1, false, false, true);
|
||
AddGradationToolTipRow(1, "Gradation", null, kmwMin, kmwAvg, kmwMax);
|
||
|
||
var attrGroups = await deliveryParts
|
||
.GroupBy(p => new { Attr = p.Attribute!.Name, Cult = p.Cultivation!.Name })
|
||
.Select(g => new {
|
||
g.Key.Attr,
|
||
g.Key.Cult,
|
||
Weight = g.Sum(p => p.Weight),
|
||
Min = g.Min(p => p.Kmw),
|
||
Avg = g.Sum(p => p.Kmw * p.Weight) / g.Sum(p => p.Weight),
|
||
Max = g.Max(p => p.Kmw),
|
||
})
|
||
.OrderByDescending(g => g.Weight)
|
||
.ThenBy(g => g.Attr)
|
||
.ToListAsync();
|
||
var sortGroups = await deliveryParts
|
||
.GroupBy(p => p.SortId)
|
||
.Select(g => new {
|
||
SortId = g.Key,
|
||
Weight = g.Sum(p => p.Weight),
|
||
Min = g.Min(p => p.Kmw),
|
||
Avg = g.Sum(p => p.Kmw * p.Weight) / g.Sum(p => p.Weight),
|
||
Max = g.Max(p => p.Kmw),
|
||
})
|
||
.OrderByDescending(g => g.Weight)
|
||
.ThenBy(g => g.SortId)
|
||
.ToListAsync();
|
||
var groups = await deliveryParts
|
||
.GroupBy(p => new {
|
||
Attr = p.Attribute!.Name,
|
||
Cult = p.Cultivation!.Name,
|
||
p.SortId,
|
||
})
|
||
.Select(g => new {
|
||
g.Key.Attr,
|
||
g.Key.Cult,
|
||
g.Key.SortId,
|
||
Weight = g.Sum(p => p.Weight),
|
||
Min = g.Min(p => p.Kmw),
|
||
Avg = g.Sum(p => p.Kmw * p.Weight) / g.Sum(p => p.Weight),
|
||
Max = g.Max(p => p.Kmw)
|
||
})
|
||
.OrderByDescending(g => g.SortId)
|
||
.ThenBy(g => g.Attr)
|
||
.ThenBy(g => g.SortId)
|
||
.ToListAsync();
|
||
|
||
int rowNum = 1;
|
||
foreach (var attrG in attrGroups) {
|
||
rowNum++;
|
||
var name = attrG.Attr == null && attrG.Cult == null ? null : attrG.Attr + (attrG.Attr != null && attrG.Cult != null ? " / " : "") + attrG.Cult;
|
||
AddWeightToolTipRow(rowNum++, name, null, attrG.Weight, attrG.Weight, weight);
|
||
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Weight).ThenBy(g => g.SortId)) {
|
||
AddWeightToolTipRow(rowNum++, null, g.SortId, g.Weight, attrG.Weight, weight);
|
||
}
|
||
}
|
||
rowNum = 2;
|
||
foreach (var attrG in attrGroups) {
|
||
rowNum++;
|
||
var name = attrG.Attr == null && attrG.Cult == null ? null : attrG.Attr + (attrG.Attr != null && attrG.Cult != null ? " / " : "") + attrG.Cult;
|
||
AddGradationToolTipRow(rowNum++, name, null, attrG.Min, attrG.Avg, attrG.Max);
|
||
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Avg).ThenBy(g => g.SortId)) {
|
||
AddGradationToolTipRow(rowNum++, null, g.SortId, g.Min, g.Avg, g.Max);
|
||
}
|
||
}
|
||
|
||
if (attrGroups.Count == 1) {
|
||
var g = attrGroups.First();
|
||
var name = g.Attr == null && g.Cult == null ? null : g.Attr + (g.Attr != null && g.Cult != null ? " / " : "") + g.Cult;
|
||
if (name != null) {
|
||
StatusWeight.Text += $" [{name}]";
|
||
StatusGradation.Text += $" [{name}]";
|
||
}
|
||
if (sortGroups.Count > 1 && sortGroups.Count <= 4) {
|
||
StatusWeight.Text += $" = {string.Join(" + ", sortGroups.Select(g => $"{g.Weight:N0} kg ({(double)g.Weight / weight:0%})" + (g.SortId == null ? "" : $" [{g.SortId}]")))}";
|
||
StatusGradation.Text += $" = {string.Join(" + ", sortGroups.Select(g => $"{g.Min:N1}/{g.Avg:N1}/{g.Max:N1}" + (g.SortId == null ? "" : $" [{g.SortId}]")))}";
|
||
|
||
}
|
||
} else if (attrGroups.Count <= 4) {
|
||
StatusWeight.Text += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Weight:N0} kg ({(double)g.Weight / weight:0%})" + (g.Attr == null && g.Cult == null ? "" : $" [{g.Attr}{(g.Attr != null && g.Cult != null ? " / " : "")}{g.Cult}]")))}";
|
||
StatusGradation.Text += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Min:N1}/{g.Avg:N1}/{g.Max:N1}" + (g.Attr == null && g.Cult == null ? "" : $" [{g.Attr}{(g.Attr != null && g.Cult != null ? " / " : "")}{g.Cult}]")))}";
|
||
}
|
||
} else {
|
||
StatusGradation.Text = "Gradation: -";
|
||
}
|
||
} else {
|
||
StatusVarieties.Text = "Sorten: -";
|
||
StatusWeight.Text = "Gewicht: -";
|
||
StatusGradation.Text = "Gradation: -";
|
||
}
|
||
|
||
StatusVarieties.ToolTip = StatusVarieties.Text;
|
||
}
|
||
|
||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||
await base.OnRenewContext(ctx);
|
||
|
||
if (Member != null) {
|
||
if (await GetMemberAsync(Member.MgNr) is not Member m) {
|
||
Close();
|
||
return;
|
||
}
|
||
Member = m;
|
||
Title = $"Lieferungen - {Member.AdministrativeName} - Elwig";
|
||
}
|
||
|
||
Menu_Bki_SaveList.Items.Clear();
|
||
foreach (var s in await ctx.Seasons.OrderByDescending(s => s.Year).ToListAsync()) {
|
||
var i = new MenuItem {
|
||
Header = $"Saison {s.Year}",
|
||
};
|
||
i.Click += Menu_Bki_SaveList_Click;
|
||
Menu_Bki_SaveList.Items.Add(i);
|
||
}
|
||
|
||
await RefreshDeliveryList();
|
||
var d = DeliveryList.SelectedItem as Delivery;
|
||
var y = d?.Year ?? SeasonInput.Value;
|
||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
||
.Where(m => m.IsActive || !IsCreating)
|
||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
||
.Include(m => m.DefaultWbKg!.AtKg)
|
||
.OrderBy(m => m.FamilyName)
|
||
.ThenBy(m => m.GivenName)
|
||
.ToListAsync());
|
||
ControlUtils.RenewItemsSource(BranchInput, await ctx.Branches.OrderBy(b => b.Name).ToListAsync());
|
||
ControlUtils.RenewItemsSource(WineVarietyInput, await ctx.WineVarieties.OrderBy(v => v.Name).ToListAsync());
|
||
var attrList = await ctx.WineAttributes.Where(a => !IsCreating || a.IsActive).OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
||
attrList.Insert(0, new NullItem(""));
|
||
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
||
var cultList = await ctx.WineCultivations.OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
||
cultList.Insert(0, new NullItem(""));
|
||
ControlUtils.RenewItemsSource(CultivationInput, cultList, null, ControlUtils.RenewSourceDefault.First);
|
||
ControlUtils.RenewItemsSource(WineQualityLevelInput, await ctx.WineQualityLevels.ToListAsync());
|
||
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
|
||
.Where(m => m.Year == y)
|
||
.OrderBy(m => m.Ordering)
|
||
.Include(m => m.Season.Currency)
|
||
.ToListAsync());
|
||
ControlUtils.RenewItemsSource(WineOriginInput, (await ctx.WineOrigins.ToListAsync()).OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId));
|
||
var kgList = (await ctx.Katastralgemeinden
|
||
.Where(k => k.WbKg != null)
|
||
.Include(k => k.WbKg)
|
||
.Include(k => k.Gem.WbGem)
|
||
.OrderBy(k => k.Name)
|
||
.AsSplitQuery()
|
||
.ToListAsync()).Cast<object>().ToList();
|
||
kgList.Insert(0, new NullItem());
|
||
ControlUtils.RenewItemsSource(WineKgInput, kgList);
|
||
UpdateRdInput();
|
||
if (IsCreating) await UpdateLsNr();
|
||
|
||
await RefreshDeliveryParts();
|
||
RefreshInputs();
|
||
}
|
||
|
||
private void FocusSearchInput(object sender, RoutedEventArgs evt) {
|
||
if (!IsEditing && !IsCreating) {
|
||
SearchInput.Focus();
|
||
SearchInput.SelectAll();
|
||
}
|
||
}
|
||
|
||
private async Task RefreshDeliveryParts() {
|
||
using var ctx = new AppDbContext();
|
||
if (DeliveryList.SelectedItem is Delivery d) {
|
||
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
|
||
.Where(m => m.Year == d.Year)
|
||
.OrderBy(m => m.Ordering)
|
||
.Include(m => m.Season.Currency)
|
||
.ToListAsync());
|
||
ControlUtils.RenewItemsSource(DeliveryPartList, d.FilteredParts.OrderBy(p => p.DPNr).ToList(), DeliveryPartList_SelectionChanged, ControlUtils.RenewSourceDefault.First);
|
||
} else {
|
||
ControlUtils.RenewItemsSource(ModifiersInput, await ctx.Modifiers
|
||
.Where(m => m.Year == SeasonInput.Value)
|
||
.OrderBy(m => m.Ordering)
|
||
.Include(m => m.Season.Currency)
|
||
.ToListAsync());
|
||
DeliveryPartList.ItemsSource = null;
|
||
}
|
||
}
|
||
|
||
private void RefreshInputs(bool validate = false) {
|
||
ClearInputStates();
|
||
if (DeliveryPartList.SelectedItem is DeliveryPart p) {
|
||
FillInputs(p);
|
||
} else if (DeliveryList.SelectedItem is Delivery d) {
|
||
FillInputs(d);
|
||
} else {
|
||
ClearOriginalValues();
|
||
ClearDefaultValues();
|
||
ClearInputs(validate);
|
||
ClearInputStates();
|
||
}
|
||
GC.Collect();
|
||
}
|
||
|
||
private void FillInputs(Delivery d) {
|
||
ClearOriginalValues();
|
||
ClearDefaultValues();
|
||
|
||
MgNrInput.Text = d.MgNr.ToString();
|
||
ControlUtils.SelectItemWithPk(BranchInput, d.ZwstId);
|
||
LsNrInput.Text = d.LsNr;
|
||
DateInput.Text = d.Date.ToString("dd.MM.yyyy");
|
||
TimeInput.Text = d.Time?.ToString("HH:mm") ?? "";
|
||
CommentInput.Text = d.Comment ?? "";
|
||
|
||
SortIdInput.Text = "";
|
||
GradationKmwInput.Text = "";
|
||
WeightInput.Text = "";
|
||
ManualWeighingInput.IsChecked = false;
|
||
PartCommentInput.Text = "";
|
||
TemperatureInput.Text = "";
|
||
AcidInput.Text = "";
|
||
|
||
FinishInputFilling();
|
||
}
|
||
|
||
private void FillInputs(DeliveryPart p) {
|
||
FillInputs(p.Delivery);
|
||
ClearOriginalValues();
|
||
ClearDefaultValues();
|
||
|
||
SortIdInput.Text = p?.SortId ?? "";
|
||
ControlUtils.SelectItemWithPk(AttributeInput, p?.AttrId);
|
||
ControlUtils.SelectItemWithPk(CultivationInput, p?.CultId);
|
||
GradationKmwInput.Text = (p != null) ? $"{p.Kmw:N1}" : "";
|
||
ControlUtils.SelectItemWithPk(WineQualityLevelInput, p?.QualId);
|
||
ControlUtils.SelectItemWithPk(WineKgInput, p?.KgNr);
|
||
ControlUtils.SelectItemWithPk(WineRdInput, p?.KgNr, p?.RdNr);
|
||
ControlUtils.SelectItemWithPk(WineOriginInput, p?.HkId);
|
||
WeightInput.Text = (p != null) ? $"{p.Weight:N0}" : "";
|
||
ManualWeighingInput.IsChecked = p?.IsManualWeighing ?? false;
|
||
GerebeltGewogenInput.IsChecked = p?.IsNetWeight ?? false;
|
||
ControlUtils.SelectItems(ModifiersInput, p?.Modifiers);
|
||
PartCommentInput.Text = p?.Comment ?? "";
|
||
TemperatureInput.Text = (p != null && p.Temperature != null) ? $"{p.Temperature:N1}" : "";
|
||
AcidInput.Text = (p != null && p.Acid != null) ? $"{p.Acid:N1}" : "";
|
||
LesewagenInput.IsChecked = p?.IsLesewagen ?? false;
|
||
HandPickedInput.IsChecked = p?.IsHandPicked;
|
||
GebundenInput.IsChecked = p?.IsGebunden;
|
||
|
||
ScaleId = p?.ScaleId;
|
||
WeighingId = p?.WeighingId;
|
||
ManualWeighingReason = p?.WeighingReason;
|
||
|
||
FinishInputFilling();
|
||
}
|
||
|
||
private async Task<DeliveryPart> UpdateDeliveryPart(int? oldYear, int? oldDid, int? oldDpnr) {
|
||
using var ctx = new AppDbContext();
|
||
|
||
int year = oldYear ?? Utils.CurrentYear;
|
||
int did = oldDid ?? await ctx.NextDId(year);
|
||
int dpnr = oldDpnr ?? await ctx.NextDPNr(year, did);
|
||
|
||
var oldDelivery = await ctx.Deliveries.FindAsync(year, did);
|
||
bool deliveryNew = (oldDid == null);
|
||
bool partNew = (oldDpnr == null);
|
||
var originalMgNr = oldDelivery?.MgNr;
|
||
var originalMemberKgNr = oldDelivery?.Member.DefaultKgNr;
|
||
|
||
var date = DateOnly.ParseExact(DateInput.Text, "dd.MM.yyyy");
|
||
int? newLnr = (deliveryNew || InputHasChanged(DateInput)) ? await ctx.NextLNr(date) : null;
|
||
|
||
string? newTimeString = null;
|
||
if (IsCreating && !InputIsNotDefault(TimeInput)) {
|
||
newTimeString = DateTime.Now.ToString("HH:mm:ss");
|
||
} else if (IsCreating || InputHasChanged(TimeInput)) {
|
||
newTimeString = (TimeInput.Text != "") ? TimeInput.Text + ":00" : null;
|
||
}
|
||
|
||
var d = new Delivery {
|
||
Year = year,
|
||
DId = did,
|
||
DateString = $"{date:yyyy-MM-dd}",
|
||
TimeString = newTimeString ?? oldDelivery?.TimeString,
|
||
LNr = newLnr ?? oldDelivery!.LNr,
|
||
ZwstId = (BranchInput.SelectedItem as Branch)!.ZwstId,
|
||
LsNr = LsNrInput.Text,
|
||
MgNr = int.Parse(MgNrInput.Text),
|
||
Comment = (CommentInput.Text == "") ? null : CommentInput.Text,
|
||
};
|
||
|
||
var p = new DeliveryPart {
|
||
Year = year,
|
||
DId = did,
|
||
DPNr = dpnr,
|
||
|
||
SortId = (WineVarietyInput.SelectedItem as WineVar)!.SortId,
|
||
AttrId = (AttributeInput.SelectedItem as WineAttr)?.AttrId,
|
||
CultId = (CultivationInput.SelectedItem as WineCult)?.CultId,
|
||
Kmw = double.Parse(GradationKmwInput.Text),
|
||
QualId = (WineQualityLevelInput.SelectedItem as WineQualLevel)!.QualId,
|
||
HkId = (WineOriginInput.SelectedItem as WineOrigin)!.HkId,
|
||
KgNr = (WineKgInput.SelectedItem as AT_Kg)?.KgNr,
|
||
RdNr = (WineRdInput.SelectedItem as WbRd)?.RdNr,
|
||
|
||
IsNetWeight = GerebeltGewogenInput.IsChecked ?? false,
|
||
IsHandPicked = HandPickedInput.IsChecked,
|
||
IsLesewagen = LesewagenInput.IsChecked,
|
||
IsGebunden = GebundenInput.IsChecked,
|
||
Temperature = (TemperatureInput.Text == "") ? null : double.Parse(TemperatureInput.Text),
|
||
Acid = (AcidInput.Text == "") ? null : double.Parse(AcidInput.Text),
|
||
Comment = (PartCommentInput.Text == "") ? null : PartCommentInput.Text,
|
||
|
||
Weight = int.Parse(WeightInput.Text.Replace(Utils.GroupSeparator, "")),
|
||
IsManualWeighing = ManualWeighingInput.IsChecked ?? false,
|
||
ScaleId = ScaleId,
|
||
WeighingId = WeighingId,
|
||
WeighingReason = ManualWeighingReason,
|
||
};
|
||
|
||
try {
|
||
if (oldDelivery != null && ctx.Entry(oldDelivery) is EntityEntry<Delivery> entry) {
|
||
entry.State = EntityState.Detached;
|
||
}
|
||
if (IsEditing || !deliveryNew) {
|
||
ctx.Update(d);
|
||
} else {
|
||
ctx.Add(d);
|
||
}
|
||
if (IsEditing || !partNew) {
|
||
ctx.Update(p);
|
||
} else {
|
||
ctx.Add(p);
|
||
}
|
||
|
||
ctx.UpdateDeliveryPartModifiers(p, await ctx.DeliveryPartModifiers
|
||
.Where(m => m.Year == p.Year && m.DId == p.DId && m.DPNr == p.DPNr)
|
||
.Select(m => m.Modifier)
|
||
.ToListAsync(), ModifiersInput.SelectedItems.Cast<Modifier>());
|
||
|
||
if (originalMgNr != null && originalMgNr.Value != d.MgNr) {
|
||
// update origin (KgNr), if default is selected
|
||
var newKgNr = (await ctx.Members.FindAsync(d.MgNr))?.DefaultKgNr;
|
||
foreach (var part in d.Parts.Where(part => part.DPNr != dpnr && part.KgNr == originalMemberKgNr)) {
|
||
part.KgNr = newKgNr;
|
||
ctx.Update(part);
|
||
}
|
||
}
|
||
|
||
await ctx.SaveChangesAsync();
|
||
} catch (Exception exc) {
|
||
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||
MessageBox.Show(str, "Lieferung aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
|
||
return p;
|
||
}
|
||
|
||
private void WeighingButton_Click(object sender, RoutedEventArgs evt) {
|
||
int index = Array.IndexOf(WeighingButtons, sender as Button);
|
||
if (index >= 0) WeighingButton_Click(index);
|
||
}
|
||
|
||
private async void WeighingButton_Click(int index) {
|
||
DisableWeighingButtons();
|
||
var start = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||
FinishButton.IsEnabled = false;
|
||
NewDeliveryPartButton.IsEnabled = false;
|
||
CancelCreatingButton.IsEnabled = false;
|
||
var s = App.CommandScales[index];
|
||
try {
|
||
var res = await s.Weigh();
|
||
OnWeighingResult(s, res);
|
||
} catch (Exception ex) {
|
||
LastScaleError = ex.Message.Split(": ")[^1];
|
||
OnWeighingResult(s, new() { Weight = 0 });
|
||
MessageBox.Show($"Beim Wiegen ist ein Fehler aufgetreten:\n\n{ex.Message}", "Waagenfehler",
|
||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
ManualWeighingReason = null;
|
||
ManualWeighingInput.IsChecked = false;
|
||
var end = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||
int diff = (int)(end - start);
|
||
if (diff < 1000 && WeightInput.Text.Length != 0) await Task.Delay(1000 - diff);
|
||
EnableWeighingButtons();
|
||
}
|
||
|
||
private void OnWeighingResult(IScale scale, WeighingResult res) {
|
||
if ((res.Weight ?? 0) > 0 && res.FullWeighingId != null) {
|
||
WeightInput.Text = $"{res.Weight:N0}";
|
||
ScaleId = scale.ScaleId;
|
||
WeighingId = res.FullWeighingId;
|
||
ManualWeighingReason = null;
|
||
ManualWeighingInput.IsChecked = false;
|
||
} else {
|
||
WeightInput.Text = "";
|
||
ScaleId = null;
|
||
WeighingId = null;
|
||
}
|
||
LastScaleError = null;
|
||
TextBox_TextChanged(WeightInput, null);
|
||
UpdateButtons();
|
||
}
|
||
|
||
private void Scale_Weighing(object sender, WeighingEventArgs evt) {
|
||
if (sender is not IScale scale) return;
|
||
App.MainDispatcher.BeginInvoke(() => OnWeighingResult(scale, evt.Result));
|
||
}
|
||
|
||
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||
TextFilter = SearchInput.Text.ToLower().Split(" ").ToList().FindAll(e => e.Length > 0);
|
||
await RefreshDeliveryListQuery(true);
|
||
}
|
||
|
||
private async void SeasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||
if (SeasonInput.Value == null || TodayOnlyInput == null || AllSeasonsInput == null) return;
|
||
TodayOnlyInput.IsChecked = false;
|
||
AllSeasonsInput.IsChecked = false;
|
||
await RefreshDeliveryListQuery();
|
||
}
|
||
|
||
private async void TodayOnlyInput_Changed(object sender, RoutedEventArgs evt) {
|
||
if (TodayOnlyInput.IsChecked == true && AllSeasonsInput.IsChecked == false) {
|
||
SeasonInput.Value = Utils.Today.Year;
|
||
TodayOnlyInput.IsChecked = true;
|
||
}
|
||
await RefreshDeliveryListQuery();
|
||
}
|
||
|
||
private async void AllSeasonsInput_Changed(object sender, RoutedEventArgs evt) {
|
||
if (AllSeasonsInput.IsChecked == true) {
|
||
SeasonInput.IsEnabled = false;
|
||
SeasonInput.Text = "";
|
||
} else {
|
||
SeasonInput.IsEnabled = true;
|
||
var today = TodayOnlyInput.IsChecked;
|
||
SeasonInput.Value = Utils.CurrentLastSeason;
|
||
TodayOnlyInput.IsChecked = today;
|
||
}
|
||
await RefreshDeliveryListQuery();
|
||
}
|
||
|
||
private async void DeliveryList_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||
await RefreshDeliveryParts();
|
||
if (DeliveryList.SelectedItem is Delivery d) {
|
||
DeleteDeliveryButton.IsEnabled = true;
|
||
Menu_DeliveryNote_Show.IsEnabled = !IsEditing && !IsCreating;
|
||
Menu_DeliveryNote_SavePdf.IsEnabled = !IsEditing && !IsCreating;
|
||
Menu_DeliveryNote_Print.IsEnabled = !IsEditing && !IsCreating;
|
||
Menu_DeliveryNote_Email.IsEnabled = !IsEditing && !IsCreating && App.Config.Smtp != null && d.Member.EmailAddresses.Count > 0;
|
||
} else {
|
||
DeleteDeliveryButton.IsEnabled = false;
|
||
Menu_DeliveryNote_Show.IsEnabled = false;
|
||
Menu_DeliveryNote_SavePdf.IsEnabled = false;
|
||
Menu_DeliveryNote_Print.IsEnabled = false;
|
||
Menu_DeliveryNote_Email.IsEnabled = false;
|
||
}
|
||
}
|
||
|
||
private void DeliveryPartList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
||
RefreshInputs();
|
||
if (DeliveryPartList.SelectedItem is DeliveryPart p) {
|
||
AbwertenButton.IsEnabled = p.QualId != "WEI";
|
||
EditDeliveryButton.IsEnabled = true;
|
||
ExtractDeliveryPartButton.IsEnabled = !IsCreating;
|
||
DeleteDeliveryPartButton.IsEnabled = DeliveryList.SelectedItem is Delivery { Parts.Count: > 1 } && !IsCreating;
|
||
} else {
|
||
AbwertenButton.IsEnabled = false;
|
||
EditDeliveryButton.IsEnabled = false;
|
||
ExtractDeliveryPartButton.IsEnabled = false;
|
||
DeleteDeliveryPartButton.IsEnabled = false;
|
||
}
|
||
}
|
||
|
||
private void MgNrInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||
var valid = InputTextChanged((TextBox)sender, Validator.CheckMgNr);
|
||
ControlUtils.SelectItemWithPk(MemberInput, valid ? int.Parse(MgNrInput.Text) : null);
|
||
}
|
||
|
||
private void MgNrInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||
var valid = InputLostFocus((TextBox)sender, Validator.CheckMgNr);
|
||
ControlUtils.SelectItemWithPk(MemberInput, valid ? int.Parse(MgNrInput.Text) : null);
|
||
}
|
||
|
||
private void MemberInput_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
||
var m = MemberInput.SelectedItem as Member;
|
||
if (m != null) MgNrInput.Text = m.MgNr.ToString();
|
||
MemberAddressField.Text = m?.FullAddress;
|
||
if (m == null) {
|
||
UnsetDefaultValue(WineKgInput);
|
||
WineKgInput.SelectedIndex = 0;
|
||
} else {
|
||
ControlUtils.SelectItemWithPk(WineKgInput, m.DefaultKgNr);
|
||
SetDefaultValue(WineKgInput);
|
||
}
|
||
}
|
||
|
||
private void EmptyScale() {
|
||
var scale = App.Scales.Where(s => s.ScaleId == ScaleId).FirstOrDefault();
|
||
if (scale is not ICommandScale cs) return;
|
||
cs.Empty();
|
||
}
|
||
|
||
private async void NewDeliveryPartButton_Click(object sender, RoutedEventArgs evt) {
|
||
FinishButton.IsEnabled = false;
|
||
NewDeliveryPartButton.IsEnabled = false;
|
||
NewDeliveryPartButton.Cursor = Cursors.Wait;
|
||
DeliveryPartList.IsEnabled = false;
|
||
var p = await UpdateDeliveryPart(
|
||
(DeliveryList.SelectedItem as Delivery)?.Year,
|
||
(DeliveryList.SelectedItem as Delivery)?.DId,
|
||
(DeliveryPartList.SelectedItem as DeliveryPart)?.DPNr
|
||
);
|
||
EmptyScale();
|
||
await RefreshDeliveryList();
|
||
await RefreshDeliveryParts();
|
||
NewDeliveryPartButton.Cursor = null;
|
||
ControlUtils.SelectItem(DeliveryList, p?.Delivery);
|
||
DeliveryPartList.SelectedItem = null;
|
||
RefreshInputs();
|
||
InitialInputs();
|
||
}
|
||
|
||
private async void FinishButton_Click(object sender, RoutedEventArgs evt) {
|
||
FinishButton.IsEnabled = false;
|
||
NewDeliveryPartButton.IsEnabled = false;
|
||
FinishButton.Cursor = Cursors.Wait;
|
||
DeliveryPartList.IsEnabled = false;
|
||
var p = await UpdateDeliveryPart(
|
||
(DeliveryList.SelectedItem as Delivery)?.Year,
|
||
(DeliveryList.SelectedItem as Delivery)?.DId,
|
||
(DeliveryPartList.SelectedItem as DeliveryPart)?.DPNr
|
||
);
|
||
EmptyScale();
|
||
await RefreshDeliveryList();
|
||
await RefreshDeliveryParts();
|
||
if (p?.Delivery != null) {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
using var ctx = new AppDbContext();
|
||
using var doc = new DeliveryNote((await ctx.Deliveries.FindAsync(p.Year, p.DId))!, ctx);
|
||
await doc.Generate();
|
||
if (App.Config.Debug) {
|
||
doc.Show();
|
||
} else {
|
||
await doc.Print(2);
|
||
}
|
||
} catch (Exception exc) {
|
||
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
FinishButton.Cursor = null;
|
||
DeliveryList.SelectedItem = null;
|
||
await RenewContext();
|
||
RefreshInputs();
|
||
InitInputs();
|
||
}
|
||
|
||
private async void CancelCreatingButton_Click(object sender, RoutedEventArgs evt) {
|
||
if (IsCreating && HasChanged) {
|
||
var r = MessageBox.Show("Soll der Vorgang wirklich abgebrochen werden?", "Abbrechen bestätigen",
|
||
MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
|
||
if (r != MessageBoxResult.Yes) return;
|
||
}
|
||
|
||
using var ctx = new AppDbContext();
|
||
var attrList = await ctx.WineAttributes.OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
||
attrList.Insert(0, new NullItem(""));
|
||
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
||
.Where(m => m.IsActive || !IsReceipt)
|
||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
||
.Include(m => m.DefaultWbKg!.AtKg)
|
||
.OrderBy(m => m.FamilyName)
|
||
.ThenBy(m => m.GivenName)
|
||
.ToListAsync());
|
||
if (DeliveryList.SelectedItem is not Delivery d) {
|
||
// switch away from creating mode
|
||
IsCreating = false;
|
||
IsEditing = false;
|
||
DeliveryList.IsEnabled = true;
|
||
DeliveryPartList.IsEnabled = true;
|
||
DisableWeighingButtons();
|
||
HideFinishNewPartDeliveryCancelButtons();
|
||
ShowNewEditDeleteButtons();
|
||
await RenewContext();
|
||
RefreshInputs();
|
||
ClearInputStates();
|
||
LockInputs();
|
||
UnlockSearchInputs();
|
||
} else {
|
||
// switch to last delivery part
|
||
DeliveryPartList.IsEnabled = true;
|
||
ControlUtils.SelectItem(DeliveryPartList, d.FilteredParts.Last());
|
||
}
|
||
}
|
||
|
||
protected override void ShortcutNew() {
|
||
if (!NewDeliveryButton.IsEnabled || NewDeliveryButton.Visibility != Visibility.Visible)
|
||
return;
|
||
NewDeliveryButton_Click(null, null);
|
||
}
|
||
|
||
private async void NewDeliveryButton_Click(object? sender, RoutedEventArgs? evt) {
|
||
TodayOnlyInput.IsChecked = true;
|
||
SearchInput.Text = "";
|
||
using var ctx = new AppDbContext();
|
||
var attrList = await ctx.WineAttributes.Where(a => a.IsActive).OrderBy(a => a.Name).Cast<object>().ToListAsync();
|
||
attrList.Insert(0, new NullItem(""));
|
||
ControlUtils.RenewItemsSource(AttributeInput, attrList, null, ControlUtils.RenewSourceDefault.First);
|
||
ControlUtils.RenewItemsSource(MemberInput, await ctx.Members
|
||
.Where(m => m.IsActive || !IsReceipt)
|
||
.Include(m => m.PostalDest.AtPlz!.Ort)
|
||
.Include(m => m.DefaultWbKg!.AtKg)
|
||
.OrderBy(m => m.FamilyName)
|
||
.ThenBy(m => m.GivenName)
|
||
.ToListAsync());
|
||
IsCreating = true;
|
||
DeliveryList.IsEnabled = false;
|
||
DeliveryPartList.IsEnabled = false;
|
||
EnableWeighingButtons();
|
||
DeliveryList.SelectedItem = null;
|
||
HideNewEditDeleteButtons();
|
||
UnlockInputs();
|
||
InitInputs();
|
||
ShowFinishNewPartDeliveryCancelButtons();
|
||
LockSearchInputs();
|
||
}
|
||
|
||
private async void AbwertenButton_Click(object sender, RoutedEventArgs evt) {
|
||
if (DeliveryPartList.SelectedItem is not DeliveryPart p) return;
|
||
var res = Utils.ShowAbwertenDialog($"{p.Delivery.LsNr}/{p.DPNr}", p.Delivery.Member.AdministrativeName, p.Weight);
|
||
if (res == null || res <= 0)
|
||
return;
|
||
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
using var ctx = new AppDbContext();
|
||
ClearOriginalValues();
|
||
if (res >= p.Weight) {
|
||
ControlUtils.SelectItemWithPk(WineQualityLevelInput, "WEI");
|
||
ControlUtils.SelectItemWithPk(WineOriginInput, "OEST");
|
||
p.QualId = "WEI";
|
||
p.HkId = "OEST";
|
||
ctx.Update(p);
|
||
} else {
|
||
var w = p.Weight - res.Value;
|
||
WeightInput.Text = $"{w:N0}";
|
||
p.Weight = w;
|
||
ctx.Update(p);
|
||
|
||
var d = p.Delivery;
|
||
var p2 = ctx.CreateProxy<DeliveryPart>();
|
||
var values = ctx.Entry(p).CurrentValues;
|
||
ctx.Entry(p2).CurrentValues.SetValues(values);
|
||
p2.DPNr = await ctx.NextDPNr(d.Year, d.DId);
|
||
p2.Weight = res.Value;
|
||
p2.QualId = "WEI";
|
||
p2.HkId = "OEST";
|
||
ctx.Add(p2);
|
||
|
||
ctx.UpdateDeliveryPartModifiers(p2, [], p.Modifiers);
|
||
}
|
||
await ctx.SaveChangesAsync();
|
||
await RefreshDeliveryParts();
|
||
FinishInputFilling();
|
||
} catch (Exception exc) {
|
||
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||
MessageBox.Show(str, "Lieferung aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
|
||
private void WeighingManualButton_Click(object sender, RoutedEventArgs evt) {
|
||
var res = Utils.ShowManualWeighingDialog(LastScaleError);
|
||
if (res == null) return;
|
||
WeightInput.Text = $"{res?.Item1:N0}";
|
||
ManualWeighingInput.IsChecked = true;
|
||
ManualWeighingReason = res?.Item2;
|
||
ScaleId = null;
|
||
WeighingId = null;
|
||
}
|
||
|
||
protected override void ShortcutEdit() {
|
||
if (!EditDeliveryButton.IsEnabled || EditDeliveryButton.Visibility != Visibility.Visible)
|
||
return;
|
||
EditDeliveryButton_Click(null, null);
|
||
}
|
||
|
||
private void EditDeliveryButton_Click(object? sender, RoutedEventArgs? evt) {
|
||
if (DeliveryPartList.SelectedItem == null)
|
||
return;
|
||
|
||
IsEditing = true;
|
||
DeliveryList.IsEnabled = false;
|
||
DeliveryPartList.IsEnabled = false;
|
||
|
||
HideNewEditDeleteButtons();
|
||
ShowSaveResetCancelButtons();
|
||
UnlockInputs();
|
||
LockSearchInputs();
|
||
|
||
AbwertenButton.IsEnabled = false;
|
||
ExtractDeliveryPartButton.IsEnabled = false;
|
||
DeleteDeliveryPartButton.IsEnabled = false;
|
||
}
|
||
|
||
protected override void ShortcutDelete() {
|
||
if (!DeleteDeliveryButton.IsEnabled || DeleteDeliveryButton.Visibility != Visibility.Visible)
|
||
return;
|
||
DeleteDeliveryButton_Click(null, null);
|
||
}
|
||
|
||
private async void DeleteDeliveryButton_Click(object? sender, RoutedEventArgs? evt) {
|
||
if (DeliveryList.SelectedItem is not Delivery d)
|
||
return;
|
||
|
||
var r = MessageBox.Show(
|
||
$"Soll die Lieferung {d.LsNr} ({d.Member.AdministrativeName}, MgNr. {d.Member.MgNr}) wirklich unwiderruflich gelöscht werden?",
|
||
"Lieferung löschen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
|
||
if (r == MessageBoxResult.OK) {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
using (var ctx = new AppDbContext()) {
|
||
ctx.Remove(d);
|
||
await ctx.SaveChangesAsync();
|
||
}
|
||
await RefreshDeliveryList();
|
||
await RefreshDeliveryParts();
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
}
|
||
|
||
protected override void ShortcutSave() {
|
||
if (!SaveButton.IsEnabled || SaveButton.Visibility != Visibility.Visible)
|
||
return;
|
||
SaveButton_Click(null, null);
|
||
}
|
||
|
||
private async void SaveButton_Click(object? sender, RoutedEventArgs? evt) {
|
||
SaveButton.IsEnabled = false;
|
||
SaveButton.Cursor = Cursors.Wait;
|
||
|
||
IsEditing = false;
|
||
IsCreating = false;
|
||
DeliveryList.IsEnabled = true;
|
||
DeliveryPartList.IsEnabled = true;
|
||
|
||
var p = await UpdateDeliveryPart(
|
||
(DeliveryList.SelectedItem as Delivery)?.Year,
|
||
(DeliveryList.SelectedItem as Delivery)?.DId,
|
||
(DeliveryPartList.SelectedItem as DeliveryPart)?.DPNr
|
||
);
|
||
|
||
SaveButton.Cursor = null;
|
||
|
||
HideSaveResetCancelButtons();
|
||
ShowNewEditDeleteButtons();
|
||
LockInputs();
|
||
UnlockSearchInputs();
|
||
FinishInputFilling();
|
||
await RefreshDeliveryList();
|
||
await RefreshDeliveryParts();
|
||
RefreshInputs();
|
||
|
||
AbwertenButton.IsEnabled = p.QualId != "WEI";
|
||
ExtractDeliveryPartButton.IsEnabled = DeliveryPartList.SelectedItem != null && !IsCreating;
|
||
DeleteDeliveryPartButton.IsEnabled = DeliveryList.SelectedItem is Delivery { Parts.Count: > 1 } && !IsCreating;
|
||
}
|
||
|
||
protected override void ShortcutReset() {
|
||
if (!ResetButton.IsEnabled || ResetButton.Visibility != Visibility.Visible)
|
||
return;
|
||
ResetButton_Click(null, null);
|
||
}
|
||
|
||
private void ResetButton_Click(object? sender, RoutedEventArgs? evt) {
|
||
if (IsEditing) {
|
||
RefreshInputs();
|
||
} else if (IsCreating) {
|
||
ClearInputs();
|
||
InitInputs();
|
||
}
|
||
UpdateButtons();
|
||
}
|
||
|
||
private void CancelButton_Click(object sender, RoutedEventArgs evt) {
|
||
IsEditing = false;
|
||
IsCreating = false;
|
||
DeliveryList.IsEnabled = true;
|
||
DeliveryPartList.IsEnabled = true;
|
||
|
||
HideSaveResetCancelButtons();
|
||
ShowNewEditDeleteButtons();
|
||
RefreshInputs();
|
||
LockInputs();
|
||
UnlockSearchInputs();
|
||
|
||
AbwertenButton.IsEnabled = DeliveryPartList.SelectedItem is DeliveryPart p && p.QualId != "WEI";
|
||
ExtractDeliveryPartButton.IsEnabled = DeliveryPartList.SelectedItem != null && !IsCreating;
|
||
DeleteDeliveryPartButton.IsEnabled = DeliveryList.SelectedItem is Delivery { Parts.Count: > 1 } && !IsCreating;
|
||
}
|
||
|
||
private async void ExtractDeliveryPartButton_Click(object sender, RoutedEventArgs evt) {
|
||
if (DeliveryPartList.SelectedItem is not DeliveryPart p)
|
||
return;
|
||
|
||
var delivery = p.Delivery;
|
||
var day = delivery.Date;
|
||
var count = delivery.Parts.Count;
|
||
|
||
if (delivery.Time <= new TimeOnly(3, 0))
|
||
day = day.AddDays(-1);
|
||
|
||
string? res;
|
||
using (var ctx = new AppDbContext()) {
|
||
var lsnrs = await ctx.Deliveries
|
||
.Where(d => d.ZwstId == delivery.ZwstId)
|
||
.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 == null || d.TimeString.CompareTo("03:00:00") <= 0)))
|
||
.Where(d => d.LsNr != delivery.LsNr)
|
||
.OrderBy(d => d.LsNr)
|
||
.Select(d => d.LsNr)
|
||
.ToListAsync();
|
||
|
||
res = Utils.ShowDeliveryExtractionDialog($"{delivery.LsNr}/{p.DPNr}", delivery.Member.AdministrativeName, count == 1, lsnrs);
|
||
if (res == null)
|
||
return;
|
||
}
|
||
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
try {
|
||
using var ctx = new AppDbContext();
|
||
if (res == "new") {
|
||
var lnr = await ctx.NextLNr(delivery.Date);
|
||
ctx.Add(new Delivery {
|
||
Year = p.Year,
|
||
DId = await ctx.NextDId(p.Year),
|
||
LNr = lnr,
|
||
DateString = $"{delivery.Date:yyyy-MM-dd}",
|
||
TimeString = $"{delivery.Time:HH:mm:SS}",
|
||
ZwstId = delivery.ZwstId,
|
||
MgNr = delivery.MgNr,
|
||
Comment = delivery.Comment,
|
||
LsNr = Utils.GenerateLsNr(delivery.Date, delivery.ZwstId, lnr),
|
||
});
|
||
await ctx.SaveChangesAsync();
|
||
}
|
||
Delivery? d = await ctx.Deliveries.Where(d => d.LsNr == res).FirstOrDefaultAsync();
|
||
if (d == null) return;
|
||
|
||
await ctx.Database.ExecuteSqlAsync($"UPDATE delivery_part SET year = {d.Year}, did = {d.DId}, dpnr = {await ctx.NextDPNr(d.Year, d.DId)} WHERE (year, did, dpnr) = ({p.Year}, {p.DId}, {p.DPNr})");
|
||
if (count == 1) {
|
||
await ctx.Database.ExecuteSqlAsync($"DELETE FROM delivery WHERE (year, did) = ({delivery.Year}, {delivery.DId})");
|
||
}
|
||
await ctx.SaveChangesAsync();
|
||
|
||
await RefreshDeliveryList();
|
||
ControlUtils.SelectItem(DeliveryList, d);
|
||
} catch (Exception exc) {
|
||
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||
MessageBox.Show(str, "Lieferung aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
|
||
private async void DeleteDeliveryPartButton_Click(object sender, RoutedEventArgs evt) {
|
||
if (DeliveryPartList.SelectedItem is not DeliveryPart p)
|
||
return;
|
||
|
||
var r = MessageBox.Show(
|
||
$"Soll die Teillieferung Nr. {p.DPNr} wirklich unwiderruflich gelöscht werden?",
|
||
"Lieferung löschen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
|
||
if (r == MessageBoxResult.OK) {
|
||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||
using (var ctx = new AppDbContext()) {
|
||
ctx.Remove(p);
|
||
await ctx.SaveChangesAsync();
|
||
}
|
||
await RefreshDeliveryParts();
|
||
Mouse.OverrideCursor = null;
|
||
}
|
||
}
|
||
|
||
private void ShowSaveResetCancelButtons() {
|
||
SaveButton.IsEnabled = false;
|
||
ResetButton.IsEnabled = false;
|
||
CancelButton.IsEnabled = true;
|
||
SaveButton.Visibility = Visibility.Visible;
|
||
ResetButton.Visibility = Visibility.Visible;
|
||
CancelButton.Visibility = Visibility.Visible;
|
||
}
|
||
|
||
private void HideSaveResetCancelButtons() {
|
||
SaveButton.IsEnabled = false;
|
||
ResetButton.IsEnabled = false;
|
||
CancelButton.IsEnabled = false;
|
||
SaveButton.Visibility = Visibility.Hidden;
|
||
ResetButton.Visibility = Visibility.Hidden;
|
||
CancelButton.Visibility = Visibility.Hidden;
|
||
}
|
||
|
||
private void ShowNewEditDeleteButtons() {
|
||
NewDeliveryButton.IsEnabled = IsReceipt;
|
||
AbwertenButton.IsEnabled = DeliveryPartList.SelectedItem is DeliveryPart p && p.QualId == "WEI";
|
||
EditDeliveryButton.IsEnabled = DeliveryPartList.SelectedItem != null;
|
||
DeleteDeliveryButton.IsEnabled = DeliveryList.SelectedItem != null;
|
||
NewDeliveryButton.Visibility = IsReceipt ? Visibility.Visible : Visibility.Hidden;
|
||
AbwertenButton.Visibility = !IsReceipt ? Visibility.Visible : Visibility.Hidden;
|
||
EditDeliveryButton.Visibility = Visibility.Visible;
|
||
DeleteDeliveryButton.Visibility = Visibility.Visible;
|
||
}
|
||
|
||
private void HideNewEditDeleteButtons() {
|
||
NewDeliveryButton.IsEnabled = false;
|
||
AbwertenButton.IsEnabled = false;
|
||
EditDeliveryButton.IsEnabled = false;
|
||
DeleteDeliveryButton.IsEnabled = false;
|
||
NewDeliveryButton.Visibility = Visibility.Hidden;
|
||
AbwertenButton.Visibility = Visibility.Hidden;
|
||
EditDeliveryButton.Visibility = Visibility.Hidden;
|
||
DeleteDeliveryButton.Visibility = Visibility.Hidden;
|
||
}
|
||
|
||
private void ShowFinishNewPartDeliveryCancelButtons() {
|
||
FinishButton.IsEnabled = false;
|
||
NewDeliveryPartButton.IsEnabled = false;
|
||
CancelCreatingButton.IsEnabled = true;
|
||
FinishButton.Visibility = Visibility.Visible;
|
||
NewDeliveryPartButton.Visibility = Visibility.Visible;
|
||
CancelCreatingButton.Visibility = Visibility.Visible;
|
||
}
|
||
|
||
private void HideFinishNewPartDeliveryCancelButtons() {
|
||
FinishButton.IsEnabled = false;
|
||
NewDeliveryPartButton.IsEnabled = false;
|
||
CancelCreatingButton.IsEnabled = false;
|
||
FinishButton.Visibility = Visibility.Hidden;
|
||
NewDeliveryPartButton.Visibility = Visibility.Hidden;
|
||
CancelCreatingButton.Visibility = Visibility.Hidden;
|
||
}
|
||
|
||
private void LockSearchInputs() {
|
||
SearchInput.IsEnabled = false;
|
||
SeasonInput.IsEnabled = false;
|
||
TodayOnlyInput.IsEnabled = false;
|
||
AllSeasonsInput.IsEnabled = false;
|
||
}
|
||
|
||
private void UnlockSearchInputs() {
|
||
SearchInput.IsEnabled = true;
|
||
SeasonInput.IsEnabled = true;
|
||
TodayOnlyInput.IsEnabled = true;
|
||
AllSeasonsInput.IsEnabled = (Member != null);
|
||
}
|
||
|
||
new protected void UnlockInputs() {
|
||
base.UnlockInputs();
|
||
if (WineQualityLevelInput.SelectedItem != null && WineKgInput.SelectedItem != null)
|
||
WineOriginInput.IsEnabled = false;
|
||
if (WineKgInput.SelectedItem == null)
|
||
WineRdInput.IsEnabled = false;
|
||
WeightInput.IsReadOnly = true;
|
||
AbgewertetInput.IsEnabled = false;
|
||
ManualWeighingInput.IsEnabled = false;
|
||
LsNrInput.IsReadOnly = true;
|
||
DateInput.IsReadOnly = !Menu_Settings_EnableFreeEditing.IsChecked;
|
||
TimeInput.IsReadOnly = !Menu_Settings_EnableFreeEditing.IsChecked;
|
||
BranchInput.IsEnabled = Menu_Settings_EnableFreeEditing.IsChecked;
|
||
}
|
||
|
||
private void DisableWeighingButtons() {
|
||
WeighingManualButton.IsEnabled = false;
|
||
WeighingAButton.IsEnabled = false;
|
||
WeighingBButton.IsEnabled = false;
|
||
WeighingCButton.IsEnabled = false;
|
||
WeighingDButton.IsEnabled = false;
|
||
}
|
||
|
||
private void EnableWeighingButtons() {
|
||
WeighingManualButton.IsEnabled = true;
|
||
var n = App.CommandScales.Count;
|
||
WeighingAButton.IsEnabled = n > 0 && App.CommandScales[0].IsReady;
|
||
WeighingBButton.IsEnabled = n > 1 && App.CommandScales[1].IsReady;
|
||
WeighingCButton.IsEnabled = n > 2 && App.CommandScales[2].IsReady;
|
||
WeighingDButton.IsEnabled = n > 3 && App.CommandScales[3].IsReady;
|
||
}
|
||
|
||
private async Task UpdateLsNr() {
|
||
if (DateInput.Text == "" || BranchInput.SelectedItem == null) {
|
||
LsNrInput.Text = "";
|
||
} else {
|
||
try {
|
||
var branch = (Branch)BranchInput.SelectedItem;
|
||
var date = DateOnly.ParseExact(DateInput.Text, "dd.MM.yyyy");
|
||
using var ctx = new AppDbContext();
|
||
var lnr = await ctx.NextLNr(date);
|
||
LsNrInput.Text = Utils.GenerateLsNr(date, branch.ZwstId, lnr);
|
||
} catch {
|
||
LsNrInput.Text = "";
|
||
}
|
||
}
|
||
}
|
||
|
||
private new async void DateInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||
base.DateInput_TextChanged(sender, evt);
|
||
if (IsEditing || IsCreating) await UpdateLsNr();
|
||
}
|
||
|
||
private async void BranchInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||
base.ComboBox_SelectionChanged(sender, evt);
|
||
if (IsEditing || IsCreating) {
|
||
await UpdateLsNr();
|
||
InitialDefaultInputs();
|
||
}
|
||
}
|
||
|
||
private void UpdateWineVariety(bool valid) {
|
||
if (valid) {
|
||
var text = SortIdInput.Text;
|
||
ControlUtils.SelectItemWithPk(WineVarietyInput, text[0..2]);
|
||
if (text.Length >= 3) {
|
||
ControlUtils.SelectItemWithPk(AttributeInput, text[2..]);
|
||
ControlUtils.SelectItemWithPk(CultivationInput, text[2..]);
|
||
SortIdInput.Text = text[0..2];
|
||
}
|
||
} else {
|
||
WineVarietyInput.SelectedItem = null;
|
||
AttributeInput.SelectedIndex = 0;
|
||
CultivationInput.SelectedIndex = 0;
|
||
}
|
||
}
|
||
|
||
private void SortIdInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||
UpdateWineVariety(InputTextChanged((TextBox)sender, Validator.CheckSortId));
|
||
}
|
||
|
||
private void SortIdInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||
UpdateWineVariety(InputLostFocus((TextBox)sender, Validator.CheckSortId));
|
||
}
|
||
|
||
private void WineVarietyInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||
if (WineVarietyInput.SelectedItem is WineVar s)
|
||
SortIdInput.Text = s.SortId;
|
||
}
|
||
|
||
private void UpdateWineQualityLevels() {
|
||
using var ctx = new AppDbContext();
|
||
if (!GetInputValid(GradationKmwInput)) {
|
||
UnsetDefaultValue(WineQualityLevelInput);
|
||
WineQualityLevelInput.ItemsSource = ctx.WineQualityLevels.Where(q => q.QualId == "WEI").ToList();
|
||
return;
|
||
}
|
||
var kmw = double.Parse(GradationKmwInput.Text);
|
||
WineQualityLevelInput.ItemsSource = ctx.WineQualityLevels.Where(q => q.MinKmw == null || q.MinKmw <= kmw).ToList();
|
||
var qual = ctx.GetWineQualityLevel(kmw).GetAwaiter().GetResult();
|
||
SetDefaultValue(WineQualityLevelInput, qual);
|
||
if (WineQualityLevelInput.SelectedItem == null || (WineQualityLevelInput.SelectedItem is WineQualLevel selected && !selected.IsPredicate)) {
|
||
ControlUtils.SelectItem(WineQualityLevelInput, qual);
|
||
}
|
||
}
|
||
|
||
private void UpdateGradationKmw() {
|
||
IsUpdatingGradation = true;
|
||
var caret = GradationKmwInput.CaretIndex;
|
||
GradationKmwInput.Text = $"{Utils.OeToKmw(double.Parse(GradationOeInput.Text)):#.0}";
|
||
GradationKmwInput.CaretIndex = caret;
|
||
IsUpdatingGradation = false;
|
||
}
|
||
|
||
private void UpdateGradationOe() {
|
||
IsUpdatingGradation = true;
|
||
var caret = GradationOeInput.CaretIndex;
|
||
GradationOeInput.Text = $"{Utils.KmwToOe(double.Parse(GradationKmwInput.Text)):#}";
|
||
GradationOeInput.CaretIndex = caret;
|
||
IsUpdatingGradation = false;
|
||
}
|
||
|
||
private void GradationOeInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||
var valid = InputTextChanged((TextBox)sender, Validator.CheckGradatoinOe);
|
||
if (!IsUpdatingGradation) {
|
||
if (valid) UpdateGradationKmw();
|
||
else if (GradationOeInput.Text.Length == 0) GradationKmwInput.Text = "";
|
||
if (valid || GradationOeInput.Text.Length == 0) UpdateWineQualityLevels();
|
||
}
|
||
}
|
||
|
||
private void GradationOeInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||
InputLostFocus((TextBox)sender, Validator.CheckGradatoinOe);
|
||
}
|
||
|
||
private void GradationKmwInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||
var valid = InputTextChanged((TextBox)sender, Validator.CheckGradationKmw);
|
||
if (!IsUpdatingGradation) {
|
||
if (valid) UpdateGradationOe();
|
||
else if (GradationKmwInput.Text.Length == 0) GradationOeInput.Text = "";
|
||
if (valid || GradationKmwInput.Text.Length == 0) UpdateWineQualityLevels();
|
||
}
|
||
}
|
||
|
||
private void GradationKmwInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||
if (GradationKmwInput.Text.EndsWith(',')) GradationKmwInput.Text += "0";
|
||
InputLostFocus((TextBox)sender, Validator.CheckGradationKmw);
|
||
if (GradationKmwInput.Text.Length != 0 && !GradationKmwInput.Text.Contains(','))
|
||
GradationKmwInput.Text += ",0";
|
||
}
|
||
|
||
private void AttributeInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||
|
||
}
|
||
|
||
private void CultivationInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||
|
||
}
|
||
|
||
private void ModifiersInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||
if (!IsEditing && !IsCreating) return;
|
||
var mod = ModifiersInput.SelectedItems.Cast<Modifier>();
|
||
var source = ModifiersInput.ItemsSource.Cast<Modifier>();
|
||
if (App.Client.IsMatzen) {
|
||
var kl = mod.Where(m => m.Name.StartsWith("Klasse "));
|
||
if (kl.Count() > 1) {
|
||
foreach (var r in kl.Take(kl.Count() - 1)) ModifiersInput.SelectedItems.Remove(r);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void LesewagenInput_Changed(object sender, RoutedEventArgs evt) {
|
||
if (!IsEditing && !IsCreating) return;
|
||
var mod = ModifiersInput.SelectedItems.Cast<Modifier>();
|
||
var source = ModifiersInput.ItemsSource.Cast<Modifier>();
|
||
var lw = LesewagenInput.IsChecked == true;
|
||
if (App.Client.IsMatzen) {
|
||
var kl = mod.Where(m => m.Name.StartsWith("Klasse ")).Select(m => m.ModId).LastOrDefault("A")[0];
|
||
if (lw) kl++; else kl--;
|
||
var newKl = source.Where(m => m.ModId == kl.ToString()).FirstOrDefault();
|
||
if (newKl != null) ModifiersInput.SelectedItems.Add(newKl);
|
||
}
|
||
CheckBox_Changed(sender, evt);
|
||
}
|
||
|
||
private void UpdateWineOrigin() {
|
||
var qual = WineQualityLevelInput.SelectedItem as WineQualLevel;
|
||
var kg = (WineKgInput.SelectedItem as AT_Kg)?.WbKg;
|
||
if (qual == null || kg == null) {
|
||
WineOriginInput.IsEnabled = (IsEditing || IsCreating);
|
||
UnsetDefaultValue(WineOriginInput);
|
||
return;
|
||
}
|
||
WineOriginInput.IsEnabled = false;
|
||
var o = kg.Origin;
|
||
while (o != null && o.Level > qual.OriginLevel) o = o.Parent;
|
||
SetDefaultValue(WineOriginInput, o);
|
||
ControlUtils.SelectItem(WineOriginInput, o);
|
||
}
|
||
|
||
private void WineQualityLevelInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||
UpdateWineOrigin();
|
||
UpdateAbgewertet();
|
||
}
|
||
|
||
private void UpdateRdInput() {
|
||
if (WineKgInput.SelectedItem is AT_Kg kg) {
|
||
using var ctx = new AppDbContext();
|
||
var list = ctx.WbRde.Where(r => r.KgNr == kg.KgNr).OrderBy(r => r.Name).Cast<object>().ToList();
|
||
list.Insert(0, new NullItem());
|
||
ControlUtils.RenewItemsSource(WineRdInput, list);
|
||
if (WineRdInput.SelectedItem == null) WineRdInput.SelectedIndex = 0;
|
||
WineRdInput.IsEnabled = (IsEditing || IsCreating) && list.Count > 1;
|
||
} else {
|
||
WineRdInput.ItemsSource = null;
|
||
WineRdInput.IsEnabled = false;
|
||
}
|
||
}
|
||
|
||
private void WineKgInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||
UpdateWineOrigin();
|
||
UpdateRdInput();
|
||
}
|
||
|
||
private void UpdateAbgewertet() {
|
||
if (!GetInputValid(GradationKmwInput))
|
||
return;
|
||
var qual = WineQualityLevelInput.SelectedItem as WineQualLevel;
|
||
if (qual == null) {
|
||
AbgewertetInput.IsChecked = false;
|
||
return;
|
||
}
|
||
using var ctx = new AppDbContext();
|
||
var defQual = ctx.GetWineQualityLevel(double.Parse(GradationKmwInput.Text)).GetAwaiter().GetResult();
|
||
AbgewertetInput.IsChecked = !qual.IsPredicate && defQual != qual;
|
||
}
|
||
|
||
private void WeightInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||
InputTextChanged((TextBox)sender);
|
||
}
|
||
|
||
private void TemperatureAcidInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||
InputTextChanged((TextBox)sender, Validator.CheckDecimal((TextBox)sender, false, 2, 1));
|
||
}
|
||
|
||
private void TemperatureAcidInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||
if (sender is not TextBox tb) return;
|
||
if (tb.Text.Length > 0) {
|
||
if (!tb.Text.Contains(',')) tb.Text += ",0";
|
||
if (tb.Text.EndsWith(',')) tb.Text += "0";
|
||
}
|
||
InputLostFocus(tb, Validator.CheckDecimal(tb, false, 2, 1));
|
||
}
|
||
|
||
private void GerebeltGewogenInput_Changed(object sender, RoutedEventArgs evt) {
|
||
if (!App.Client.HasNetWeighing(BranchInput.SelectedValue as Branch)) {
|
||
HandPickedInput.IsChecked = !GerebeltGewogenInput.IsChecked;
|
||
}
|
||
CheckBox_Changed(sender, evt);
|
||
}
|
||
|
||
private void HandPickedInput_Changed(object sender, RoutedEventArgs evt) {
|
||
if (!App.Client.HasNetWeighing(BranchInput.SelectedValue as Branch)) {
|
||
GerebeltGewogenInput.IsChecked = !HandPickedInput.IsChecked;
|
||
}
|
||
CheckBox_Changed(sender, evt);
|
||
}
|
||
|
||
private void MemberReferenceButton_Click(object sender, RoutedEventArgs evt) {
|
||
if (MemberInput.SelectedItem is not Member m) return;
|
||
App.FocusMember(m.MgNr);
|
||
}
|
||
}
|
||
}
|