Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
034c0c4eb7 | ||
|
|
c46094fe35 | ||
|
|
64bef27f9f | ||
|
|
f8cce56ecb | ||
|
|
3541f36831 | ||
|
|
569913fe8f | ||
|
|
d592fef352 | ||
|
|
f2b84053e6 | ||
|
|
7fef895491 | ||
|
|
0e9121c462 | ||
|
|
15e191d74e | ||
|
|
abf06c558f | ||
|
|
6436762e8d | ||
|
|
6441fa4f50 | ||
|
|
6bed370eba | ||
|
|
4cc33b56c8 | ||
|
|
f4cc443521 | ||
|
|
8ba051198f | ||
|
|
fea779bd95 | ||
|
|
e66780ccd0 | ||
|
|
cc01f92005 | ||
|
|
0a93167ea7 | ||
|
|
848a6d1ce0 | ||
|
|
f0745eae4e | ||
|
|
8471ac9319 | ||
|
|
7add96dfd5 | ||
|
|
2360402124 | ||
|
|
cadac4302d | ||
|
|
c1690bf104 | ||
|
|
ca5b719630 | ||
|
|
163fe0fac8 | ||
|
|
edf3678154 | ||
|
|
f450dc35b1 | ||
|
|
0c4611024f | ||
|
|
46e596ae23 | ||
|
|
3366cc25eb | ||
|
|
ff71e9fb7f |
@@ -2,6 +2,86 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
[v1.1.2.2][v1.1.2.2] (2026-09-14) {#v1.1.2.2}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Neue Funktionen {#v1.1.2.2-features}
|
||||||
|
|
||||||
|
* Bei einigen Fenstern werden in den Titeln nun die aktiven Filter der Suche angezeigt. (fea779bd95)
|
||||||
|
* Im Lieferungen-Fenster (`DeliveryAdminWindow`) ist es nun möglich die Tara nachträglich zu korrigieren. (8ba051198f, 6436762e8d)
|
||||||
|
|
||||||
|
### Behobene Fehler {#v1.1.2.2-bugfixes}
|
||||||
|
|
||||||
|
* Bei Lieferscheinen (`DeliveryNote`) hat bei Anmerkungen zu Teil-Lfrg. ein `:` gefehlt.
|
||||||
|
Außerdem wurden Seitenumbrüche so platziert, dass sie nicht mehr innerhalb einer Teil-Lfrg. liegen. (e66780ccd0, f4cc443521)
|
||||||
|
|
||||||
|
### Sonstiges {#v1.1.2.2-misc}
|
||||||
|
|
||||||
|
* Bei Datenbank-Fehler sind die Fehlermeldungen nun genauer bzw. auf deutsch übersetzt. (cc01f92005)
|
||||||
|
* Im Mitglieder-Fenster (`MemberAdminWindow`) wurden Überschriften und Tooltips leicht angepasst. (6441fa4f50)
|
||||||
|
* Abhängigkeiten aktualisiert. (4cc33b56c8, 6bed370eba)
|
||||||
|
|
||||||
|
[v1.1.2.2]: https://git.necronda.net/winzer/elwig/releases/tag/v1.1.2.2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[v1.1.2.1][v1.1.2.1] (2026-08-27) {#v1.1.2.1}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Behobene Fehler {#v1.1.2.1-bugfixes}
|
||||||
|
|
||||||
|
* Im Anmeldungen-Fenster (`DeliveryAncmtAdminWindow`) und im Leseplanung-Fenster (`DeliveryScheduleAdminWindow`) kam es seit [v1.1.1.2](#v1.1.1.2) (2026-08-25) zu einem Absturz. (f0745eae4e)
|
||||||
|
|
||||||
|
### Sonstiges {#v1.1.2.1-misc}
|
||||||
|
|
||||||
|
* Bei E-Mails wird ab jetzt auch Datum und Uhrzeit gesetzt. (848a6d1ce0)
|
||||||
|
|
||||||
|
[v1.1.2.1]: https://git.necronda.net/winzer/elwig/releases/tag/v1.1.2.1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[v1.1.2.0][v1.1.2.0] (2026-08-26) {#v1.1.2.0}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Neue Funktionen {#v1.1.2.0-features}
|
||||||
|
|
||||||
|
* Eine Automatische Backup-/Sicherungs-Funktion für die Datenbank wurde hinzugefügt. (ca5b719630, cadac4302d)
|
||||||
|
|
||||||
|
### Behobene Fehler {#v1.1.2.0-bugfixes}
|
||||||
|
|
||||||
|
* Wenn am heutigen Tag noch keine Lieferung übernommen wurde, wurden im Lieferungen-/Übernahme-Fenster (`DeliveryAdminWindow`) mit dem Filter "Nur heute" auch Lieferungen des vorhergehenden Tages angezeigt. (c1690bf104)
|
||||||
|
|
||||||
|
### Sonstiges {#v1.1.2.0-misc}
|
||||||
|
|
||||||
|
* Abhängigkeiten aktualisiert. (2360402124, 7add96dfd5)
|
||||||
|
|
||||||
|
[v1.1.2.0]: https://git.necronda.net/winzer/elwig/releases/tag/v1.1.2.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[v1.1.1.2][v1.1.1.2] (2026-08-25) {#v1.1.1.2}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Behobene Fehler {#v1.1.1.2-bugfixes}
|
||||||
|
|
||||||
|
* Auf Lieferscheinen (`DeliveryNote`) waren die Mengenangaben nicht rechtsbündig. (ff71e9fb7f)
|
||||||
|
* Beim Importieren von Mitgliedern mit Stamm-KG ohne Großlage kam es zu einem Fehler, obwohl die Großlage automatisch hätte zugewiesen werden müssen. (edf3678154)
|
||||||
|
|
||||||
|
### Sonstiges {#v1.1.1.2-misc}
|
||||||
|
|
||||||
|
* In Matzen werden für Planenw./Kipper und Lesewagen die Klassen automatisch gesetzt. (3366cc25eb)
|
||||||
|
* Im Lieferungen-Fenster (`DeliveryAdminWindow`) wird für "Nur heute" nicht mehr nur das Datum, sondern die letzten zusammenhängenden Lieferungen verwendet. (46e596ae23)
|
||||||
|
* Für Pamhagen wird als standard Wiege-Methode "brutto" verwendet. (0c4611024f)
|
||||||
|
* Für Waagen kann das automatische setzen von Datum und Uhrzeit nun per Opt-out ausgeschalten werden (Konfigurationsdatei -> `[scale.X]` -> `synctime = false`). (f450dc35b1)
|
||||||
|
|
||||||
|
[v1.1.1.2]: https://git.necronda.net/winzer/elwig/releases/tag/v1.1.1.2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[v1.1.1.1][v1.1.1.1] (2026-08-24) {#v1.1.1.1}
|
[v1.1.1.1][v1.1.1.1] (2026-08-24) {#v1.1.1.1}
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -2,8 +2,7 @@
|
|||||||
x:Class="Elwig.App"
|
x:Class="Elwig.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
xmlns:ctrl="clr-namespace:Elwig.Controls">
|
||||||
Exit="Application_Exit">
|
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ctrl:BoolToStringConverter x:Key="BoolToStarConverter" FalseValue="" TrueValue="*"/>
|
<ctrl:BoolToStringConverter x:Key="BoolToStarConverter" FalseValue="" TrueValue="*"/>
|
||||||
<ctrl:WidthToMarginConverter x:Key="WidthToMarginConverter"/>
|
<ctrl:WidthToMarginConverter x:Key="WidthToMarginConverter"/>
|
||||||
|
|||||||
+41
-12
@@ -25,9 +25,10 @@ namespace Elwig {
|
|||||||
|
|
||||||
protected static App CurrentApp;
|
protected static App CurrentApp;
|
||||||
public static int NumWindows => CurrentApp.Windows.Count;
|
public static int NumWindows => CurrentApp.Windows.Count;
|
||||||
public static bool ForceShutdown { get; private set; } = false;
|
public static bool ForceShutdown { get; set; } = false;
|
||||||
|
|
||||||
private readonly DispatcherTimer _autoUpdateTimer = new() { Interval = TimeSpan.FromHours(1) };
|
private readonly DispatcherTimer _autoUpdateTimer = new() { Interval = TimeSpan.FromHours(1) };
|
||||||
|
private readonly DispatcherTimer _autoBackupTimer = new() { Interval = TimeSpan.FromMinutes(10) };
|
||||||
public readonly SerialPortWatcher SerialPortWatcher = new();
|
public readonly SerialPortWatcher SerialPortWatcher = new();
|
||||||
|
|
||||||
public static readonly string DataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Elwig");
|
public static readonly string DataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Elwig");
|
||||||
@@ -74,7 +75,7 @@ namespace Elwig {
|
|||||||
Config = new(Path.GetFullPath(args[1]));
|
Config = new(Path.GetFullPath(args[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextTimer.Tick += (object? sender, EventArgs evt) => {
|
ContextTimer.Tick += (sender, evt) => {
|
||||||
var ch = CurrentLastWrite;
|
var ch = CurrentLastWrite;
|
||||||
if (ch > LastChanged) {
|
if (ch > LastChanged) {
|
||||||
LastChanged = ch;
|
LastChanged = ch;
|
||||||
@@ -92,11 +93,15 @@ namespace Elwig {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await AppDbUpdater.CheckDb();
|
await AppDbUpdater.CheckDb();
|
||||||
|
} catch (FileNotFoundException exc) {
|
||||||
|
InteractionService.ShowException("Datenbank nicht gefunden", "Die Datenbank konnte nicht gefunden werden", exc);
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
if (Config.UpdateUrl != null && Utils.HasInternetConnectivity()) {
|
if (Config.UpdateUrl != null && Utils.HasInternetConnectivity()) {
|
||||||
await CheckForUpdates();
|
await CheckForUpdates();
|
||||||
}
|
}
|
||||||
InteractionService.ShowException("Fehlerhafte Datenbank", "Fehlerhafte Datenbank", exc);
|
InteractionService.ShowException("Fehlerhafte Datenbank", "Schwerwiegender Fehler in der Datenbank, unbedingt den Programmierern melden!", exc);
|
||||||
|
if (InteractionService.AskQuestion("Backup wiederherstellen", "Soll die Datenbank aus einem Backup wiederhergestellt werden?\n\nAchtung: Das kann zu Datenverlust führen!", false))
|
||||||
|
await BackupService.RestoreDatabase();
|
||||||
Shutdown();
|
Shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -106,13 +111,14 @@ namespace Elwig {
|
|||||||
|
|
||||||
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = [];
|
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = [];
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
branches = ctx.FetchBranches()
|
branches = await ctx.FetchBranches()
|
||||||
.ToDictionaryAsync(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))
|
.ToDictionaryAsync(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));
|
||||||
.GetAwaiter().GetResult();
|
|
||||||
try {
|
try {
|
||||||
Client = new(ctx);
|
Client = new(ctx);
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
InteractionService.ShowException("Fehler", "Fehler beim Laden der Mandantendaten", exc);
|
InteractionService.ShowException("Fehler", "Fehler beim Laden der Mandantendaten, unbedingt den Programmierern melden!", exc);
|
||||||
|
if (InteractionService.AskQuestion("Backup wiederherstellen", "Soll die Datenbank aus einem Backup wiederhergestellt werden?\n\nAchtung: Das kann zu Datenverlust führen!", false))
|
||||||
|
await BackupService.RestoreDatabase();
|
||||||
Shutdown();
|
Shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -124,9 +130,23 @@ namespace Elwig {
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
});
|
});
|
||||||
|
|
||||||
Utils.RunBackground("PDF Initialization", () => Pdf.Init());
|
Utils.RunBackground("PDF Initialization", async () => Pdf.Init());
|
||||||
Utils.RunBackground("JSON Schema Initialization", BillingData.Init);
|
Utils.RunBackground("JSON Schema Initialization", BillingData.Init);
|
||||||
|
|
||||||
|
if (Config.BackupAuto) {
|
||||||
|
Utils.RunBackground("Automatisches Backup", async () => {
|
||||||
|
Directory.CreateDirectory(Config.BackupPath);
|
||||||
|
await Task.Delay(500);
|
||||||
|
await BackupService.TryDatabaseBackup();
|
||||||
|
});
|
||||||
|
_autoBackupTimer.Tick += new EventHandler((sender, evt) => {
|
||||||
|
Utils.RunBackground("Automatisches Backup", async () => {
|
||||||
|
await BackupService.TryDatabaseBackup();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
_autoBackupTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
if (Config.UpdateAuto && Config.UpdateUrl != null) {
|
if (Config.UpdateAuto && Config.UpdateUrl != null) {
|
||||||
if (Utils.HasInternetConnectivity()) {
|
if (Utils.HasInternetConnectivity()) {
|
||||||
Utils.RunBackground("Auto Updater", async () => {
|
Utils.RunBackground("Auto Updater", async () => {
|
||||||
@@ -146,7 +166,7 @@ namespace Elwig {
|
|||||||
foreach (var s in Config.Scales) {
|
foreach (var s in Config.Scales) {
|
||||||
try {
|
try {
|
||||||
var scale = Scale.FromConfig(s);
|
var scale = Scale.FromConfig(s);
|
||||||
if (scale is ICommandScale cmd) {
|
if (s.SyncTime && scale is ICommandScale cmd) {
|
||||||
try {
|
try {
|
||||||
await cmd.SetDateAndTime(DateTime.Now);
|
await cmd.SetDateAndTime(DateTime.Now);
|
||||||
} catch { }
|
} catch { }
|
||||||
@@ -179,7 +199,7 @@ namespace Elwig {
|
|||||||
Config.WeighingMode = WeighingMode.Net;
|
Config.WeighingMode = WeighingMode.Net;
|
||||||
} else if (Client.IsHaugsdorf || Client.IsSitzendorf) {
|
} else if (Client.IsHaugsdorf || Client.IsSitzendorf) {
|
||||||
Config.WeighingMode = WeighingMode.Box;
|
Config.WeighingMode = WeighingMode.Box;
|
||||||
} else if (Client.IsBaden || Client.IsGrInzersdorf) {
|
} else if (Client.IsBaden || Client.IsGrInzersdorf || Client.IsPamhagen) {
|
||||||
Config.WeighingMode = WeighingMode.Gross;
|
Config.WeighingMode = WeighingMode.Gross;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,12 +210,21 @@ namespace Elwig {
|
|||||||
window.Show();
|
window.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Application_Exit(object sender, ExitEventArgs evt) {
|
public async Task OnClosing() {
|
||||||
|
try {
|
||||||
|
await BackupService.TryDatabaseBackup();
|
||||||
|
} catch (Exception exc) {
|
||||||
|
InteractionService.ShowException("Automatisches Backup", exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnExit(ExitEventArgs evt) {
|
||||||
SerialPortWatcher.Dispose();
|
SerialPortWatcher.Dispose();
|
||||||
foreach (var s in EventScales) {
|
foreach (var s in EventScales) {
|
||||||
s.Dispose();
|
s.Dispose();
|
||||||
}
|
}
|
||||||
await Pdf.Cleanup();
|
Pdf.Cleanup();
|
||||||
|
base.OnExit(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetBranch(Branch b) {
|
public static void SetBranch(Branch b) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:Elwig.Dialogs"
|
xmlns:local="clr-namespace:Elwig.Dialogs"
|
||||||
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
ResizeMode="NoResize" ShowInTaskbar="False" Topmost="True"
|
ResizeMode="NoResize" ShowInTaskbar="False" Topmost="True"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner"
|
||||||
FocusManager.FocusedElement="{Binding ElementName=WeightInput}"
|
FocusManager.FocusedElement="{Binding ElementName=WeightInput}"
|
||||||
@@ -37,11 +38,9 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Label Content="Gewicht:" Margin="10,20,10,10"/>
|
<Label Content="Gewicht:" Margin="10,20,10,10"/>
|
||||||
<Grid Grid.Column="1" Width="70" Height="25" Margin="0,20,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
|
<ctrl:UnitTextBox x:Name="WeightInput" Grid.Column="1" Width="62" Height="25" Unit="kg"
|
||||||
<TextBox x:Name="WeightInput" TextAlignment="Right" Padding="2,2,17,2"
|
Margin="0,20,10,10" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" Padding="2"
|
||||||
TextChanged="WeightInput_TextChanged"/>
|
TextChanged="WeightInput_TextChanged"/>
|
||||||
<Label Content="kg" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10" Padding="2,4,2,4"/>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Label Content="Grund:" Margin="10,50,10,10"/>
|
<Label Content="Grund:" Margin="10,50,10,10"/>
|
||||||
<TextBox x:Name="ReasonInput" Grid.Column="1" Margin="0,50,10,10"
|
<TextBox x:Name="ReasonInput" Grid.Column="1" Margin="0,50,10,10"
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ using System.Windows.Controls;
|
|||||||
namespace Elwig.Dialogs {
|
namespace Elwig.Dialogs {
|
||||||
public partial class ManualWeighingDialog : Window {
|
public partial class ManualWeighingDialog : Window {
|
||||||
|
|
||||||
public int Weight = 0;
|
public int Weight { get; private set; }
|
||||||
public string? Reason = null;
|
public string? Reason { get; private set; }
|
||||||
|
|
||||||
public ManualWeighingDialog(string? reason = null) {
|
public ManualWeighingDialog(string? reason = null) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<Window x:Class="Elwig.Dialogs.TareCorrectionDialog"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:Elwig.Dialogs"
|
||||||
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
|
ResizeMode="NoResize" ShowInTaskbar="False" Topmost="True"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
FocusManager.FocusedElement="{Binding ElementName=TargetTareInput}"
|
||||||
|
Title="Tara korrigieren" Height="170" Width="300">
|
||||||
|
<Window.Resources>
|
||||||
|
<Style TargetType="Label">
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||||
|
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||||
|
<Setter Property="Padding" Value="2,4,2,4"/>
|
||||||
|
<Setter Property="Height" Value="25"/>
|
||||||
|
</Style>
|
||||||
|
<Style TargetType="TextBox">
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||||
|
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="Padding" Value="2"/>
|
||||||
|
<Setter Property="Height" Value="25"/>
|
||||||
|
<Setter Property="TextWrapping" Value="NoWrap"/>
|
||||||
|
</Style>
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Right"/>
|
||||||
|
<Setter Property="VerticalAlignment" Value="Bottom"/>
|
||||||
|
<Setter Property="Width" Value="100"/>
|
||||||
|
<Setter Property="Height" Value="25"/>
|
||||||
|
</Style>
|
||||||
|
</Window.Resources>
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="70"/>
|
||||||
|
<ColumnDefinition Width="3*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Label Content="Ist-Tara:" Margin="10,20,0,10" Grid.Column="1"/>
|
||||||
|
<ctrl:UnitTextBox x:Name="ActualTareInput" Grid.Column="2" Width="56" Height="25" Unit="kg" IsReadOnly="True"
|
||||||
|
Margin="0,20,10,10" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" Padding="2"
|
||||||
|
TextChanged="TareInput_TextChanged"/>
|
||||||
|
|
||||||
|
<Label Content="Soll-Tara:" Margin="10,50,0,10" Grid.Column="1"/>
|
||||||
|
<ctrl:UnitTextBox x:Name="TargetTareInput" Grid.Column="2" Width="56" Height="25" Unit="kg"
|
||||||
|
Margin="0,50,10,10" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="14" Padding="2"
|
||||||
|
TextChanged="TareInput_TextChanged"/>
|
||||||
|
|
||||||
|
<Button x:Name="ConfirmButton" Content="Bestätigen" Margin="10,10,115,10" Grid.ColumnSpan="3" IsEnabled="False" IsDefault="True"
|
||||||
|
Click="ConfirmButton_Click"/>
|
||||||
|
<Button x:Name="CancelButton" Content="Abbrechen" Margin="10,10,10,10" Grid.ColumnSpan="3" IsCancel="True"/>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using Elwig.Helpers;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace Elwig.Dialogs {
|
||||||
|
public partial class TareCorrectionDialog : Window {
|
||||||
|
|
||||||
|
public int ActualTare { get; private set; }
|
||||||
|
public int TargetTare { get; private set; }
|
||||||
|
|
||||||
|
public TareCorrectionDialog(int? actualTare, int? targetTare = null) {
|
||||||
|
InitializeComponent();
|
||||||
|
ActualTare = actualTare ?? 0;
|
||||||
|
TargetTare = targetTare ?? actualTare ?? 0;
|
||||||
|
ActualTareInput.IsReadOnly = actualTare != null;
|
||||||
|
ActualTareInput.Text = ActualTare.ToString();
|
||||||
|
TargetTareInput.Text = TargetTare.ToString();
|
||||||
|
TargetTareInput.SelectAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfirmButton_Click(object sender, RoutedEventArgs evt) {
|
||||||
|
DialogResult = true;
|
||||||
|
ActualTare = int.Parse(ActualTareInput.Text);
|
||||||
|
TargetTare = int.Parse(TargetTareInput.Text);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateButtons() {
|
||||||
|
ConfirmButton.IsEnabled = ActualTareInput.Text.Length > 0 && TargetTareInput.Text.Length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TareInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||||
|
if (sender is not TextBox b) return;
|
||||||
|
Validator.CheckInteger(b, true, 4);
|
||||||
|
UpdateButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,19 +34,23 @@ namespace Elwig.Documents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Cell NewAsideCell(Paragraph text, int colspan = 1, bool isName = false) {
|
protected Cell NewAsideCell(Paragraph text, int colspan = 1, bool isName = false, bool right = false, bool center = false) {
|
||||||
var cell = NewCell(text, colspan: colspan).SetPaddingsMM(0.25f, 0.5f, 0.25f, isName ? 1 : 0);
|
var cell = NewCell(text, colspan: colspan).SetPaddingsMM(0.25f, center ? 0 : right ? 1 : 0.5f, 0.25f, isName ? 1 : 0);
|
||||||
if (colspan > 1) {
|
if (colspan == 26) {
|
||||||
cell.SetTextAlignment(TextAlignment.CENTER).SetFont(BF)
|
cell.SetTextAlignment(TextAlignment.CENTER).SetFont(BF)
|
||||||
.SetBackgroundColor(new DeviceRgb(0xe0, 0xe0, 0xe0))
|
.SetBackgroundColor(new DeviceRgb(0xe0, 0xe0, 0xe0))
|
||||||
.SetBorderTop(new SolidBorder(new DeviceRgb(0x80, 0x80, 0x80), BorderThickness))
|
.SetBorderTop(new SolidBorder(new DeviceRgb(0x80, 0x80, 0x80), BorderThickness))
|
||||||
.SetPaddingsMM(0.5f, 1, 0.5f, 1);
|
.SetPaddingsMM(0.5f, 1, 0.5f, 1);
|
||||||
|
} else if (isName) {
|
||||||
|
cell.SetBorderLeft(new SolidBorder(new DeviceRgb(0x80, 0x80, 0x80), BorderThickness));
|
||||||
}
|
}
|
||||||
|
if (right) cell.SetTextAlignment(TextAlignment.RIGHT);
|
||||||
|
if (center) cell.SetTextAlignment(TextAlignment.CENTER);
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Cell NewAsideCell(string text, int colspan = 1, bool isName = false) {
|
protected Cell NewAsideCell(string text, int colspan = 1, bool isName = false, bool right = false, bool center = false) {
|
||||||
return NewAsideCell(new KernedParagraph(text, 10), colspan, isName);
|
return NewAsideCell(new KernedParagraph(text, 10), colspan, isName, right, center);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BusinessDocument(string title, Member m, DateOnly? dateFrom, bool includeSender = false) :
|
public BusinessDocument(string title, Member m, DateOnly? dateFrom, bool includeSender = false) :
|
||||||
@@ -60,16 +64,27 @@ namespace Elwig.Documents {
|
|||||||
|
|
||||||
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||||
base.BeforeRenderBody(doc, pdf);
|
base.BeforeRenderBody(doc, pdf);
|
||||||
var uid = new KernedParagraph(Member.UstIdNr ?? "-", 10);
|
Aside = new Table(ColsMM(2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5))
|
||||||
if (!Member.IsBuchführend) uid.Add(Normal(" ")).Add(Italic("(pauschaliert)"));
|
.SetWidth(UnitValue.CreatePointValue(65 * PtInMM)).SetFixedLayout()
|
||||||
Aside = new Table(ColsMM(22.5, 42.5))
|
|
||||||
.SetFont(NF).SetFontSize(10)
|
|
||||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||||
|
.SetFont(NF).SetFontSize(10)
|
||||||
.SetBorder(new SolidBorder(new DeviceRgb(0x80, 0x80, 0x80), BorderThickness))
|
.SetBorder(new SolidBorder(new DeviceRgb(0x80, 0x80, 0x80), BorderThickness))
|
||||||
.AddCell(NewAsideCell("Mitglied", 2))
|
.AddCell(NewAsideCell("Mitglied", 26));
|
||||||
.AddCell(NewAsideCell("Mitglieds-Nr.:", isName: true)).AddCell(NewAsideCell($"{Member.MgNr}"))
|
if (Member.IsOrganic) {
|
||||||
.AddCell(NewAsideCell("Betriebs-Nr.:", isName: true)).AddCell(NewAsideCell(Member.LfbisNr ?? ""))
|
Aside
|
||||||
.AddCell(NewAsideCell("UID:", isName: true)).AddCell(NewAsideCell(uid));
|
.AddCell(NewAsideCell("Mitgl.-Nr.:", 8, isName: true)).AddCell(NewAsideCell($"{Member.MgNr}", 4, right: true))
|
||||||
|
.AddCell(NewAsideCell("Bio-KSt.:", 6, isName: true)).AddCell(NewAsideCell(Member.OrganicAuthorityCode ?? "-", 8, right: true, center: Member.OrganicAuthorityCode == null))
|
||||||
|
.AddCell(NewAsideCell("Betr.-Nr.:", 6, isName: true)).AddCell(NewAsideCell(Member.LfbisNr ?? "-", 6, right: true, center: Member.LfbisNr == null))
|
||||||
|
.AddCell(NewAsideCell("OOC-ID:", 6, isName: true)).AddCell(NewAsideCell(Member.OrganicOperatorId ?? "-", 8, right: true, center: Member.OrganicOperatorId == null))
|
||||||
|
.AddCell(NewAsideCell("UID:", 6, isName: true)).AddCell(NewAsideCell(Member.UstIdNr ?? "-", 10, right: true, center: Member.UstIdNr == null))
|
||||||
|
.AddCell(NewAsideCell(new KernedParagraph("", 10).Add(Italic(Member.IsBuchführend ? "(buchführend)" : "(pauschaliert)")), 10, center: true));
|
||||||
|
} else {
|
||||||
|
Aside
|
||||||
|
.AddCell(NewAsideCell("Mitglieds-Nr.:", 12, isName: true)).AddCell(NewAsideCell($"{Member.MgNr}", 4, right: true)).AddCell(NewAsideCell("", 10))
|
||||||
|
.AddCell(NewAsideCell("Betriebs-Nr.:", 10, isName: true)).AddCell(NewAsideCell(Member.LfbisNr ?? "-", 6, right: true, center: Member.LfbisNr == null)).AddCell(NewAsideCell("", 10))
|
||||||
|
.AddCell(NewAsideCell("UID:", 6, isName: true)).AddCell(NewAsideCell(Member.UstIdNr ?? "-", 10, right: true, center: Member.UstIdNr == null))
|
||||||
|
.AddCell(NewAsideCell(new KernedParagraph("", 10).Add(Italic(Member.IsBuchführend ? "(buchführend)" : "(pauschaliert)")), 10, center: true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void RenderAddress(Canvas canvas, Rectangle pageSize) {
|
protected void RenderAddress(Canvas canvas, Rectangle pageSize) {
|
||||||
@@ -125,7 +140,7 @@ namespace Elwig.Documents {
|
|||||||
.Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine()
|
.Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine()
|
||||||
.Item(c.EmailAddress != null ? link1 : null)
|
.Item(c.EmailAddress != null ? link1 : null)
|
||||||
.Item(c.Website != null ? link2 : null)
|
.Item(c.Website != null ? link2 : null)
|
||||||
.Item("Betriebs-Nr.", c.LfbisNr).Item("Bio-KSt.", c.OrganicAuthority).NextLine()
|
.Item("Betriebs-Nr.", c.LfbisNr).Item("Bio-KSt.", c.OrganicAuthorityCode).NextLine()
|
||||||
.Item("UID", c.UstIdNr).Item("BIC", c.Bic).Item("IBAN", c.Iban)
|
.Item("UID", c.UstIdNr).Item("BIC", c.Bic).Item("IBAN", c.Iban)
|
||||||
.ToLeafElements());
|
.ToLeafElements());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,10 +125,10 @@ namespace Elwig.Documents {
|
|||||||
|
|
||||||
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||||
base.BeforeRenderBody(doc, pdf);
|
base.BeforeRenderBody(doc, pdf);
|
||||||
Aside?.AddCell(NewAsideCell("Gutschrift", 2))
|
Aside?.AddCell(NewAsideCell("Gutschrift", 26))
|
||||||
.AddCell(NewAsideCell("TG-Nr.:", isName: true)).AddCell(NewAsideCell(Payment?.Credit != null ? $"{Payment.Credit.Year}/{Payment.Credit.TgNr:000}" : "-"))
|
.AddCell(NewAsideCell("Tr.-Gutschr.-Nr.:", 12, isName: true)).AddCell(NewAsideCell(Payment?.Credit != null ? $"{Payment.Credit.Year}/{Payment.Credit.TgNr:000}" : "-", 14))
|
||||||
.AddCell(NewAsideCell("Datum:", isName: true)).AddCell(NewAsideCell($"{Payment?.Variant.Date:dd.MM.yyyy}"))
|
.AddCell(NewAsideCell("Datum:", 12, isName: true)).AddCell(NewAsideCell($"{Payment?.Variant.Date:dd.MM.yyyy}", 14))
|
||||||
.AddCell(NewAsideCell("Überw. am:", isName: true)).AddCell(NewAsideCell($"{Payment?.Variant.TransferDate:dd.MM.yyyy}"));
|
.AddCell(NewAsideCell("Überwiesen am:", 12, isName: true)).AddCell(NewAsideCell($"{Payment?.Variant.TransferDate:dd.MM.yyyy}", 14));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace Elwig.Documents {
|
|||||||
_year = year;
|
_year = year;
|
||||||
ShowDateAndLocation = true;
|
ShowDateAndLocation = true;
|
||||||
UseBillingAddress = true;
|
UseBillingAddress = true;
|
||||||
DocumentId = $"Anl.-Best. {_year}/{m.MgNr}";
|
DocumentId = $"Anlfrg.-Bstng. {_year}/{m.MgNr}";
|
||||||
Data = data;
|
Data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,10 +55,10 @@ namespace Elwig.Documents {
|
|||||||
base.BeforeRenderBody(doc, pdf);
|
base.BeforeRenderBody(doc, pdf);
|
||||||
var firstDay = Data.Rows.MinBy(r => r.Date)?.Date;
|
var firstDay = Data.Rows.MinBy(r => r.Date)?.Date;
|
||||||
var lastDay = Data.Rows.MaxBy(r => r.Date)?.Date;
|
var lastDay = Data.Rows.MaxBy(r => r.Date)?.Date;
|
||||||
Aside?.AddCell(NewAsideCell("Saison", 2))
|
Aside?.AddCell(NewAsideCell("Saison", 26))
|
||||||
.AddCell(NewAsideCell("Lieferungen:", isName: true)).AddCell(NewAsideCell($"{Data.Rows.DistinctBy(r => r.LsNr).Count():N0} (Teil-Lfrg.: {Data.RowNum:N0})"))
|
.AddCell(NewAsideCell("Lieferungen:", 12, isName: true)).AddCell(NewAsideCell($"{Data.Rows.DistinctBy(r => r.LsNr).Count():N0} (Teil-Lfrg.: {Data.RowNum:N0})", 14))
|
||||||
.AddCell(NewAsideCell("Zeitraum:", isName: true)).AddCell(NewAsideCell(firstDay == null || lastDay == null ? "-" : firstDay == lastDay ? $"{firstDay:dd.MM.} (1 Tag)" : $"{firstDay:dd.MM.}\u2013{lastDay:dd.MM.} ({lastDay?.DayNumber - firstDay?.DayNumber + 1:N0} Tage)"))
|
.AddCell(NewAsideCell("Zeitraum:", 8, isName: true)).AddCell(NewAsideCell(firstDay == null || lastDay == null ? "-" : firstDay == lastDay ? $"{firstDay:dd.MM.} (1 Tag)" : $"{firstDay:dd.MM.}\u2013{lastDay:dd.MM.} ({lastDay?.DayNumber - firstDay?.DayNumber + 1:N0} Tage)", 18, center: true))
|
||||||
.AddCell(NewAsideCell("Menge:", isName: true)).AddCell(NewAsideCell($"{MemberStats.Sum(s => s.Weight):N0} kg"));
|
.AddCell(NewAsideCell("Menge:", 12, isName: true)).AddCell(NewAsideCell($"{MemberStats.Sum(s => s.Weight):N0} kg", 14));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ namespace Elwig.Documents {
|
|||||||
|
|
||||||
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||||
base.BeforeRenderBody(doc, pdf);
|
base.BeforeRenderBody(doc, pdf);
|
||||||
Aside?.AddCell(NewAsideCell("Lieferung", 2))
|
Aside?.AddCell(NewAsideCell("Lieferung", 26))
|
||||||
.AddCell(NewAsideCell("LS-Nr.:", isName: true)).AddCell(NewAsideCell(Delivery.LsNr))
|
.AddCell(NewAsideCell("Lieferschein-Nr.:", 12, isName: true)).AddCell(NewAsideCell(Delivery.LsNr, 14))
|
||||||
.AddCell(NewAsideCell("Datum/Zeit:", isName: true)).AddCell(NewAsideCell($"{Delivery.Date:dd.MM.yyyy} / {Delivery.Time:HH:mm}"))
|
.AddCell(NewAsideCell("Datum/Zeit:", 12, isName: true)).AddCell(NewAsideCell($"{Delivery.Date:dd.MM.yyyy} / {Delivery.Time:HH:mm}", 14))
|
||||||
.AddCell(NewAsideCell("Zweigstelle:", isName: true)).AddCell(NewAsideCell(Delivery.Branch.Name));
|
.AddCell(NewAsideCell("Zweigstelle:", 12, isName: true)).AddCell(NewAsideCell(Delivery.Branch.Name, 14));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||||
@@ -121,7 +121,7 @@ namespace Elwig.Documents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Table NewDeliveryTable() {
|
protected Table NewDeliveryTable() {
|
||||||
var tbl = new Table(ColsMM(10, 21, 25, 19.5, 19.5, 30, 12.5, 12.5, 15), true)
|
var tbl = new Table(ColsMM(10, 21, 25, 20, 20, 30, 12.5, 12.5, 14), true)
|
||||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||||
.SetBorder(Border.NO_BORDER).SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE);
|
.SetBorder(Border.NO_BORDER).SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE);
|
||||||
|
|
||||||
@@ -130,15 +130,16 @@ namespace Elwig.Documents {
|
|||||||
.AddHeaderCell(NewTh("Attribut", colspan: 2, rowspan: 2, left: true))
|
.AddHeaderCell(NewTh("Attribut", colspan: 2, rowspan: 2, left: true))
|
||||||
.AddHeaderCell(NewTh("Qualitätsstufe", rowspan: 2, left: true))
|
.AddHeaderCell(NewTh("Qualitätsstufe", rowspan: 2, left: true))
|
||||||
.AddHeaderCell(NewTh("Gradation", colspan: 2))
|
.AddHeaderCell(NewTh("Gradation", colspan: 2))
|
||||||
.AddHeaderCell(NewTh("Menge"))
|
.AddHeaderCell(NewTh("Menge").SetPaddingRight(0))
|
||||||
.AddHeaderCell(NewTh("[°Oe]", 8))
|
.AddHeaderCell(NewTh("[°Oe]", 8))
|
||||||
.AddHeaderCell(NewTh("[°KMW]", 8))
|
.AddHeaderCell(NewTh("[°KMW]", 8))
|
||||||
.AddHeaderCell(NewTh("[kg]", 8));
|
.AddHeaderCell(NewTh("[kg]", 8).SetPaddingRight(0));
|
||||||
|
|
||||||
foreach (var part in Delivery.Parts.OrderBy(p => p.DPNr)) {
|
foreach (var part in Delivery.Parts.OrderBy(p => p.DPNr)) {
|
||||||
var sub = new Table(ColsMM(10, 21, 25, 19.5, 19.5, 30, 12.5, 12.5, 15), true)
|
var sub = new Table(ColsMM(10, 21, 25, 20, 20, 30, 12.5, 12.5, 14), true)
|
||||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE);
|
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||||
|
.SetKeepTogether(true);
|
||||||
|
|
||||||
int rowspan = 1 + (part.Cultivation != null ? 1 : 0) + 1 + part.Modifiers.Count() + 1 + (part.Comment != null ? 1 : 0) + (part.Temperature != null || part.Acid != null ? 1 : 0);
|
int rowspan = 1 + (part.Cultivation != null ? 1 : 0) + 1 + part.Modifiers.Count() + 1 + (part.Comment != null ? 1 : 0) + (part.Temperature != null || part.Acid != null ? 1 : 0);
|
||||||
sub.AddCell(NewDeliveryMainTd($"{part.DPNr:N0}", center: true))
|
sub.AddCell(NewDeliveryMainTd($"{part.DPNr:N0}", center: true))
|
||||||
@@ -147,11 +148,14 @@ namespace Elwig.Documents {
|
|||||||
.AddCell(NewDeliveryMainTd(part.Quality.Name))
|
.AddCell(NewDeliveryMainTd(part.Quality.Name))
|
||||||
.AddCell(NewDeliveryMainTd($"{part.Oe:N0}", center: true))
|
.AddCell(NewDeliveryMainTd($"{part.Oe:N0}", center: true))
|
||||||
.AddCell(NewDeliveryMainTd($"{part.Kmw:N1}", center: true))
|
.AddCell(NewDeliveryMainTd($"{part.Kmw:N1}", center: true))
|
||||||
.AddCell(NewDeliveryMainTd($"{part.Weight:N0}", center: true));
|
.AddCell(NewDeliveryMainTd($"{part.Weight:N0}", right: true).SetPaddingRight(0));
|
||||||
|
|
||||||
if (part.Cultivation != null) {
|
if (part.Cultivation != null) {
|
||||||
var cult = new KernedParagraph(8);
|
var cult = new KernedParagraph(8);
|
||||||
cult.Add(Italic("Bewirtschaftung:")).Add(Normal(" " + part.Cultivation.Name + (part.Cultivation.Description != null ? $" ({part.Cultivation.Description})" : "")));
|
cult.Add(Italic("Bewirtschaftung:")).Add(Normal(" " + part.Cultivation.Name + (part.Cultivation.Description != null ? $" ({part.Cultivation.Description})" : "")));
|
||||||
|
if (part.Cultivation.IsOrganic) {
|
||||||
|
cult.Add(" \u2013 ").Add(Italic("Kontrollstelle:")).Add(Normal($" {Member.OrganicAuthorityCode ?? "?"}"));
|
||||||
|
}
|
||||||
sub.AddCell(NewTd())
|
sub.AddCell(NewTd())
|
||||||
.AddCell(NewTd(cult, colspan: 5))
|
.AddCell(NewTd(cult, colspan: 5))
|
||||||
.AddCell(NewTd(colspan: 3));
|
.AddCell(NewTd(colspan: 3));
|
||||||
@@ -196,9 +200,17 @@ namespace Elwig.Documents {
|
|||||||
.Add(Italic("Brutto:"))
|
.Add(Italic("Brutto:"))
|
||||||
.Add(Normal($" {info.Gross:N0} kg \u2013 "))
|
.Add(Normal($" {info.Gross:N0} kg \u2013 "))
|
||||||
.Add(Italic("Tara:"))
|
.Add(Italic("Tara:"))
|
||||||
.Add(Normal($" {info.Tare:N0} kg \u2013 "))
|
.Add(Normal($" {info.Tare:N0} kg "));
|
||||||
|
if (info.TareCorrection != null && info.TareCorrection != 0)
|
||||||
|
weighing.Add(Bold($"(Korr.: {Utils.GetSign(info.TareCorrection.Value)}{Math.Abs(info.TareCorrection.Value)} kg)")).Add(" ");
|
||||||
|
weighing
|
||||||
|
.Add(Normal("\u2013 "))
|
||||||
.Add(Italic("Netto:"))
|
.Add(Italic("Netto:"))
|
||||||
.Add(Normal($" {info.Net:N0} kg \u2013 "))
|
.Add(Normal($" {info.Net:N0} kg "));
|
||||||
|
if (info.TareCorrection != null && info.TareCorrection != 0)
|
||||||
|
weighing.Add(Normal($"({Utils.GetSign(-info.TareCorrection.Value)}{Math.Abs(info.TareCorrection.Value)} kg) "));
|
||||||
|
weighing
|
||||||
|
.Add(Normal("\u2013 "))
|
||||||
.Add(Italic(part.IsNetWeight ? "gerebelt gewogen" : "nicht gerebelt gewogen"));
|
.Add(Italic(part.IsNetWeight ? "gerebelt gewogen" : "nicht gerebelt gewogen"));
|
||||||
} else {
|
} else {
|
||||||
weighing.Add(" ")
|
weighing.Add(" ")
|
||||||
@@ -210,7 +222,7 @@ namespace Elwig.Documents {
|
|||||||
.AddCell(NewCell(colspan: 3));
|
.AddCell(NewCell(colspan: 3));
|
||||||
if (part.Comment != null) {
|
if (part.Comment != null) {
|
||||||
sub.AddCell(NewCell())
|
sub.AddCell(NewCell())
|
||||||
.AddCell(NewCell(new KernedParagraph(8).Add(Italic("Anmerkung")).Add(Normal(" " + part.Comment)), colspan: 5))
|
.AddCell(NewCell(new KernedParagraph(8).Add(Italic("Anmerkung:")).Add(Normal(" " + part.Comment)), colspan: 5))
|
||||||
.AddCell(NewCell(colspan: 3));
|
.AddCell(NewCell(colspan: 3));
|
||||||
}
|
}
|
||||||
if (part.Temperature != null || part.Acid != null) {
|
if (part.Temperature != null || part.Acid != null) {
|
||||||
@@ -220,7 +232,7 @@ namespace Elwig.Documents {
|
|||||||
if (part.Temperature != null && part.Acid != null)
|
if (part.Temperature != null && part.Acid != null)
|
||||||
p.Add(Normal(", "));
|
p.Add(Normal(", "));
|
||||||
if (part.Acid != null)
|
if (part.Acid != null)
|
||||||
p.Add(Italic("Säure")).Add(Normal($" {part.Acid:N1} g/l"));
|
p.Add(Italic("Säure:")).Add(Normal($" {part.Acid:N1} g/l"));
|
||||||
sub.AddCell(NewCell())
|
sub.AddCell(NewCell())
|
||||||
.AddCell(NewCell(p, colspan: 5))
|
.AddCell(NewCell(p, colspan: 5))
|
||||||
.AddCell(NewCell(colspan: 3));
|
.AddCell(NewCell(colspan: 3));
|
||||||
@@ -229,10 +241,10 @@ namespace Elwig.Documents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Delivery.Parts.Count > 1) {
|
if (Delivery.Parts.Count > 1) {
|
||||||
tbl.AddCell(NewTd("Gesamt:", 12, bold: true, borderTop: true, colspan: 6).SetPaddingsMM(1, 1, 1, 1))
|
tbl.AddCell(NewTd("Gesamt:", 12, bold: true, borderTop: true, colspan: 6).SetPaddingsMM(1, 1, 1, 0))
|
||||||
.AddCell(NewTd($"{Delivery.Oe:N0}", 12, bold: true, center: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1))
|
.AddCell(NewTd($"{Delivery.Oe:N0}", 12, bold: true, center: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1))
|
||||||
.AddCell(NewTd($"{Delivery.Kmw:N1}", 12, bold: true, center: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1))
|
.AddCell(NewTd($"{Delivery.Kmw:N1}", 12, bold: true, center: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1))
|
||||||
.AddCell(NewTd($"{Delivery.Weight:N0}", 12, bold: true, right: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
|
.AddCell(NewTd($"{Delivery.Weight:N0}", 12, bold: true, right: true, borderTop: true).SetPaddingsMM(1, 0, 1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
return tbl;
|
return tbl;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace Elwig.Documents {
|
|||||||
public Document(string title) {
|
public Document(string title) {
|
||||||
Title = title;
|
Title = title;
|
||||||
Author = App.Client.NameFull;
|
Author = App.Client.NameFull;
|
||||||
Date = DateOnly.FromDateTime(Utils.Today);
|
Date = DateOnly.FromDateTime(DateTime.Today);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Document() {
|
~Document() {
|
||||||
@@ -252,7 +252,7 @@ namespace Elwig.Documents {
|
|||||||
|
|
||||||
public async Task Print(int copies = 1) {
|
public async Task Print(int copies = 1) {
|
||||||
if (PdfPath == null) throw new InvalidOperationException("Pdf file has not been generated yet");
|
if (PdfPath == null) throw new InvalidOperationException("Pdf file has not been generated yet");
|
||||||
await Pdf.Print(PdfPath, copies, IsDoublePaged);
|
Pdf.Print(PdfPath, copies, IsDoublePaged);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Show() {
|
public void Show() {
|
||||||
|
|||||||
@@ -161,7 +161,8 @@ namespace Elwig.Documents {
|
|||||||
.AddCell(NewDataTh("Buchführend:", colspan: 2)).AddCell(NewTd(new KernedParagraph(Member.IsBuchführend ? "Ja " : "Nein ", 10)
|
.AddCell(NewDataTh("Buchführend:", colspan: 2)).AddCell(NewTd(new KernedParagraph(Member.IsBuchführend ? "Ja " : "Nein ", 10)
|
||||||
.Add(Normal($"({(Member.IsBuchführend ? season.VatNormal : season.VatFlatrate) * 100:N0}% USt.)", 8)), colspan: 2))
|
.Add(Normal($"({(Member.IsBuchführend ? season.VatNormal : season.VatFlatrate) * 100:N0}% USt.)", 8)), colspan: 2))
|
||||||
.AddCell(NewDataTh("(Katastralgemeinde mit dem größten Anteil an Weinbauflächen)", 8, colspan: 2))
|
.AddCell(NewDataTh("(Katastralgemeinde mit dem größten Anteil an Weinbauflächen)", 8, colspan: 2))
|
||||||
.AddCell(NewDataTh("Bio:", colspan: 2)).AddCell(NewTd(Member.IsOrganic ? "Ja" : "Nein", colspan: 2))
|
.AddCell(NewDataTh("Bio:", colspan: 2)).AddCell(NewTd(new KernedParagraph(Member.IsOrganic ? "Ja" : "Nein", 10)
|
||||||
|
.Add(Normal(Member.OrganicAuthorityCode != null || Member.OrganicOperatorId != null ? $" ({Member.OrganicAuthorityCode}{(Member.OrganicAuthorityCode != null && Member.OrganicOperatorId != null ? ", " : "")}{Member.OrganicOperatorId})" : "", 8)), colspan: 2))
|
||||||
.AddCell(NewDataHdr("Genossenschaft", colspan: 6))
|
.AddCell(NewDataHdr("Genossenschaft", colspan: 6))
|
||||||
.AddCell(NewDataTh("Status:")).AddCell(NewTd(new KernedParagraph(Member.IsActive ? "Aktiv " : "Nicht aktiv ", 10)
|
.AddCell(NewDataTh("Status:")).AddCell(NewTd(new KernedParagraph(Member.IsActive ? "Aktiv " : "Nicht aktiv ", 10)
|
||||||
.Add(Normal("(" + (Member.ExitDate != null ? $"{Member.EntryDate:dd.MM.yyyy}\u2013{Member.ExitDate:dd.MM.yyyy}" : $"seit {Member.EntryDate:dd.MM.yyyy}") + ")", 8))))
|
.Add(Normal("(" + (Member.ExitDate != null ? $"{Member.EntryDate:dd.MM.yyyy}\u2013{Member.ExitDate:dd.MM.yyyy}" : $"seit {Member.EntryDate:dd.MM.yyyy}") + ")", 8))))
|
||||||
|
|||||||
+9
-9
@@ -9,7 +9,7 @@
|
|||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||||
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
|
||||||
<Version>1.1.1.1</Version>
|
<Version>1.1.2.2</Version>
|
||||||
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<ApplicationManifest>App.manifest</ApplicationManifest>
|
<ApplicationManifest>App.manifest</ApplicationManifest>
|
||||||
@@ -23,21 +23,21 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="bblanchon.PDFium.Win32" Version="153.0.8009" />
|
<PackageReference Include="bblanchon.PDFium.Win32" Version="155.0.8044" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
||||||
<PackageReference Include="itext" Version="9.7.0" />
|
<PackageReference Include="itext" Version="9.7.0" />
|
||||||
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.7.0" />
|
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.7.0" />
|
||||||
<PackageReference Include="LinqKit" Version="1.3.11" />
|
<PackageReference Include="LinqKit" Version="1.3.11" />
|
||||||
<PackageReference Include="MailKit" Version="4.17.0" />
|
<PackageReference Include="MailKit" Version="4.18.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.11" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.12" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.11" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.12" />
|
||||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.4129.50" />
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.4191.47" />
|
||||||
<PackageReference Include="NJsonSchema" Version="11.6.1" />
|
<PackageReference Include="NJsonSchema" Version="11.6.1" />
|
||||||
<PackageReference Include="ScottPlot.WPF" Version="5.1.59" />
|
<PackageReference Include="ScottPlot.WPF" Version="5.1.59" />
|
||||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.5" />
|
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.5" />
|
||||||
<PackageReference Include="System.IO.Hashing" Version="10.0.11" />
|
<PackageReference Include="System.IO.Hashing" Version="10.0.12" />
|
||||||
<PackageReference Include="System.IO.Ports" Version="10.0.11" />
|
<PackageReference Include="System.IO.Ports" Version="10.0.12" />
|
||||||
<PackageReference Include="System.Management" Version="10.0.11" />
|
<PackageReference Include="System.Management" Version="10.0.12" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Elwig.Services;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -9,15 +11,22 @@ namespace Elwig.Helpers {
|
|||||||
public static class AppDbUpdater {
|
public static class AppDbUpdater {
|
||||||
|
|
||||||
// Don't forget to update value in Tests/fetch-resources.bat!
|
// Don't forget to update value in Tests/fetch-resources.bat!
|
||||||
public static readonly int RequiredSchemaVersion = 41;
|
public static readonly int RequiredSchemaVersion = 42;
|
||||||
|
|
||||||
private static int VersionOffset = 0;
|
private static int VersionOffset = 0;
|
||||||
|
|
||||||
public static async Task<Version> CheckDb() {
|
public static async Task<Version> CheckDb() {
|
||||||
|
if (!File.Exists(App.Config.DatabaseFile))
|
||||||
|
throw new FileNotFoundException($"Die Datei \"{App.Config.DatabaseFile}\" exisitiert nicht");
|
||||||
|
|
||||||
long? applId, schemaVers;
|
long? applId, schemaVers;
|
||||||
using (var cnx = await AppDbContext.ConnectAsync()) {
|
using (var cnx = await AppDbContext.ConnectAsync()) {
|
||||||
|
|
||||||
|
await cnx.QuickCheck();
|
||||||
|
|
||||||
applId = (long?)await cnx.ExecuteScalar("PRAGMA application_id") ?? 0;
|
applId = (long?)await cnx.ExecuteScalar("PRAGMA application_id") ?? 0;
|
||||||
if (applId != 0x454C5747) throw new Exception($"Invalid application_id in database (0x{applId:X08})");
|
if (applId != 0x454C5747)
|
||||||
|
throw new FileFormatException($"Invalid application_id in database (0x{applId:X08})");
|
||||||
|
|
||||||
schemaVers = (long?)await cnx.ExecuteScalar("PRAGMA schema_version") ?? 0;
|
schemaVers = (long?)await cnx.ExecuteScalar("PRAGMA schema_version") ?? 0;
|
||||||
VersionOffset = (int)(schemaVers % 100);
|
VersionOffset = (int)(schemaVers % 100);
|
||||||
@@ -61,11 +70,11 @@ namespace Elwig.Helpers {
|
|||||||
})
|
})
|
||||||
.OrderBy(s => s.Item1).ThenBy(s => s.Item2)];
|
.OrderBy(s => s.Item1).ThenBy(s => s.Item2)];
|
||||||
|
|
||||||
List<string> toExecute = [];
|
List<(int ToVersion, string File)> toExecute = [];
|
||||||
var vers = fromVersion;
|
var vers = fromVersion;
|
||||||
while (vers < toVersion) {
|
while (vers < toVersion) {
|
||||||
var (_, to, name) = scripts.Last(s => s.From == vers);
|
var (_, to, name) = scripts.Last(s => s.From == vers);
|
||||||
toExecute.Add(name);
|
toExecute.Add((to, name));
|
||||||
vers = to;
|
vers = to;
|
||||||
}
|
}
|
||||||
if (toExecute.Count == 0)
|
if (toExecute.Count == 0)
|
||||||
@@ -76,16 +85,19 @@ namespace Elwig.Helpers {
|
|||||||
try {
|
try {
|
||||||
using var cnx = await AppDbContext.ConnectAsync();
|
using var cnx = await AppDbContext.ConnectAsync();
|
||||||
await cnx.ExecuteBatch("PRAGMA locking_mode = EXCLUSIVE");
|
await cnx.ExecuteBatch("PRAGMA locking_mode = EXCLUSIVE");
|
||||||
foreach (var script in toExecute) {
|
|
||||||
|
await cnx.IntegrityCheck();
|
||||||
|
await cnx.ForeignKeyCheck();
|
||||||
|
|
||||||
|
foreach (var (to, script) in toExecute) {
|
||||||
await cnx.ExecuteEmbeddedScript(asm, script);
|
await cnx.ExecuteEmbeddedScript(asm, script);
|
||||||
|
if (to == 42) {
|
||||||
|
await UpdateDbSchema_41_To_42(cnx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var violations = await cnx.ForeignKeyCheck();
|
await cnx.IntegrityCheck();
|
||||||
if (violations.Length > 0) {
|
await cnx.ForeignKeyCheck();
|
||||||
throw new Exception($"Foreign key violations ({violations.Length}):\n" + string.Join("\n", violations
|
|
||||||
.Take(50)
|
|
||||||
.Select(v => $"{v.Table} - {v.RowId} - {v.Parent} - {v.FkId}")));
|
|
||||||
}
|
|
||||||
|
|
||||||
await cnx.ExecuteBatch("VACUUM");
|
await cnx.ExecuteBatch("VACUUM");
|
||||||
await cnx.ExecuteBatch($"PRAGMA schema_version = {toVersion * 100 + VersionOffset}");
|
await cnx.ExecuteBatch($"PRAGMA schema_version = {toVersion * 100 + VersionOffset}");
|
||||||
@@ -96,5 +108,52 @@ namespace Elwig.Helpers {
|
|||||||
File.Delete(backup);
|
File.Delete(backup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task UpdateDbSchema_41_To_42(SqliteConnection cnx) {
|
||||||
|
List<(int MgNr, string LfbisNr, string Name, string Address, int Plz)> members = [];
|
||||||
|
using (var cmd = cnx.CreateCommand()) {
|
||||||
|
cmd.CommandText = """
|
||||||
|
SELECT m.mgnr, m.lfbis_nr,
|
||||||
|
COALESCE(a.name, (COALESCE(m.prefix || ' ', '') || COALESCE(m.given_name || ' ', '') || m.name || COALESCE(' ' || m.middle_names, '') || COALESCE(' ' || m.suffix, ''))),
|
||||||
|
COALESCE(a.address, m.address),
|
||||||
|
COALESCE(aplz.plz, mplz.plz)
|
||||||
|
FROM member m
|
||||||
|
JOIN postal_dest mp ON (mp.country, mp.id) = (m.country, m.postal_dest)
|
||||||
|
JOIN AT_plz_dest ma ON (ma.country, ma.id) = (mp.country, mp.id)
|
||||||
|
JOIN AT_plz mplz ON mplz.plz = ma.plz
|
||||||
|
LEFT JOIN member_billing_address a ON a.mgnr = m.mgnr
|
||||||
|
LEFT JOIN postal_dest ap ON (ap.country, ap.id) = (a.country, a.postal_dest)
|
||||||
|
LEFT JOIN AT_plz_dest aa ON (aa.country, aa.id) = (ap.country, mp.id)
|
||||||
|
LEFT JOIN AT_plz aplz ON aplz.plz = aa.plz
|
||||||
|
WHERE organic
|
||||||
|
""";
|
||||||
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
var header = await reader.GetColumnSchemaAsync();
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
members.Add((reader.GetInt32(0), reader.GetString(1), reader.GetString(2), reader.GetString(3), reader.GetInt32(4)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (members.Count > 0)
|
||||||
|
InteractionService.ShowInformation("Datenbank-Update", "Es wird versucht, die Bio-Kontrollstellen-Informationen der Mitglieder automatisch zu laden. Dies könnte einen kurzen Moment in Anspruch nehmen.");
|
||||||
|
|
||||||
|
foreach (var m in members) {
|
||||||
|
string? oocId = null;
|
||||||
|
string? authCode = null;
|
||||||
|
|
||||||
|
var certs = await OrganicService.FetchTracesCertificates(null, m.LfbisNr, (m.Name, m.Address, m.Plz.ToString()));
|
||||||
|
|
||||||
|
if (certs.Length > 0) {
|
||||||
|
oocId = certs[0].OperatorId;
|
||||||
|
authCode = certs[0].AuthorityCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oocId != null || authCode != null) {
|
||||||
|
oocId = oocId == null ? "NULL" : $"'{oocId}'";
|
||||||
|
authCode = authCode == null ? "NULL" : $"'{authCode}'";
|
||||||
|
await cnx.ExecuteBatch($"UPDATE member SET ooc_id = {oocId}, org_auth_code = {authCode} WHERE mgnr = {m.MgNr}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ namespace Elwig.Helpers {
|
|||||||
public string? Bic;
|
public string? Bic;
|
||||||
public string? UstIdNr;
|
public string? UstIdNr;
|
||||||
public string? LfbisNr;
|
public string? LfbisNr;
|
||||||
public string? OrganicAuthority;
|
public string? OrganicOperatorId;
|
||||||
|
public string? OrganicAuthorityCode;
|
||||||
|
|
||||||
public string? PhoneNr;
|
public string? PhoneNr;
|
||||||
public string? FaxNr;
|
public string? FaxNr;
|
||||||
@@ -114,7 +115,8 @@ namespace Elwig.Helpers {
|
|||||||
UstIdNr = parameters.GetValueOrDefault("CLIENT_USTIDNR");
|
UstIdNr = parameters.GetValueOrDefault("CLIENT_USTIDNR");
|
||||||
Bic = parameters.GetValueOrDefault("CLIENT_BIC");
|
Bic = parameters.GetValueOrDefault("CLIENT_BIC");
|
||||||
Iban = parameters.GetValueOrDefault("CLIENT_IBAN");
|
Iban = parameters.GetValueOrDefault("CLIENT_IBAN");
|
||||||
OrganicAuthority = parameters.GetValueOrDefault("CLIENT_ORGANIC_AUTHORITY");
|
OrganicOperatorId = parameters.GetValueOrDefault("CLIENT_ORGANIC_OPERATORID");
|
||||||
|
OrganicAuthorityCode = parameters.GetValueOrDefault("CLIENT_ORGANIC_AUTHORITYCODE");
|
||||||
|
|
||||||
EnableMemberHistory = (parameters.GetValueOrDefault("ENABLE_MEMBERHISTORY")?.ToUpper()) switch {
|
EnableMemberHistory = (parameters.GetValueOrDefault("ENABLE_MEMBERHISTORY")?.ToUpper()) switch {
|
||||||
"1" or "TRUE" or "YES" or "JA" => true,
|
"1" or "TRUE" or "YES" or "JA" => true,
|
||||||
@@ -273,7 +275,8 @@ namespace Elwig.Helpers {
|
|||||||
("CLIENT_USTIDNR", UstIdNr),
|
("CLIENT_USTIDNR", UstIdNr),
|
||||||
("CLIENT_BIC", Bic),
|
("CLIENT_BIC", Bic),
|
||||||
("CLIENT_IBAN", Iban),
|
("CLIENT_IBAN", Iban),
|
||||||
("CLIENT_ORGANIC_AUTHORITY", OrganicAuthority),
|
("CLIENT_ORGANIC_OPERATORID", OrganicOperatorId),
|
||||||
|
("CLIENT_ORGANIC_AUTHORITYCODE", OrganicAuthorityCode),
|
||||||
("ENABLE_MEMBERHISTORY", EnableMemberHistory ? "YES" : "NO"),
|
("ENABLE_MEMBERHISTORY", EnableMemberHistory ? "YES" : "NO"),
|
||||||
("MODE_BUSINESSSHARES", businessShares),
|
("MODE_BUSINESSSHARES", businessShares),
|
||||||
("MODE_DELIVERYNOTE_STATS", deliveryNoteStats),
|
("MODE_DELIVERYNOTE_STATS", deliveryNoteStats),
|
||||||
|
|||||||
+24
-2
@@ -17,10 +17,11 @@ namespace Elwig.Helpers {
|
|||||||
public string? Filling;
|
public string? Filling;
|
||||||
public string? Limit;
|
public string? Limit;
|
||||||
public bool Required;
|
public bool Required;
|
||||||
|
public bool SyncTime;
|
||||||
public string? Log;
|
public string? Log;
|
||||||
public string? _Log;
|
public string? _Log;
|
||||||
|
|
||||||
public ScaleConfig(string id, string? type, string? model, string? cnx, string? empty, string? filling, string? limit, bool? required, string? log) {
|
public ScaleConfig(string id, string? type, string? model, string? cnx, string? empty, string? filling, string? limit, bool? required, bool? syncTime, string? log) {
|
||||||
Id = id;
|
Id = id;
|
||||||
Type = type;
|
Type = type;
|
||||||
Model = model;
|
Model = model;
|
||||||
@@ -29,6 +30,7 @@ namespace Elwig.Helpers {
|
|||||||
Filling = filling;
|
Filling = filling;
|
||||||
Limit = limit;
|
Limit = limit;
|
||||||
Required = required ?? true;
|
Required = required ?? true;
|
||||||
|
SyncTime = syncTime ?? true;
|
||||||
_Log = log;
|
_Log = log;
|
||||||
Log = log != null ? Path.Combine(App.DataPath, log) : null;
|
Log = log != null ? Path.Combine(App.DataPath, log) : null;
|
||||||
}
|
}
|
||||||
@@ -37,16 +39,26 @@ namespace Elwig.Helpers {
|
|||||||
public class Config {
|
public class Config {
|
||||||
|
|
||||||
private static readonly string[] TrueValues = ["1", "true", "yes", "on"];
|
private static readonly string[] TrueValues = ["1", "true", "yes", "on"];
|
||||||
|
private static readonly string[] FalseValues = ["0", "false", "no", "off"];
|
||||||
|
|
||||||
private readonly string FileName;
|
private readonly string FileName;
|
||||||
|
|
||||||
public bool Debug;
|
public bool Debug;
|
||||||
public string DatabaseFile = App.DataPath + "database.sqlite3";
|
public string DatabaseFile = Path.Combine(App.DataPath, "database.sqlite3");
|
||||||
public string? DatabaseLog = null;
|
public string? DatabaseLog = null;
|
||||||
public string? Branch = null;
|
public string? Branch = null;
|
||||||
public WeighingMode? WeighingMode;
|
public WeighingMode? WeighingMode;
|
||||||
|
|
||||||
|
public bool BackupAuto = true;
|
||||||
|
public string BackupPath = Path.Combine(App.DataPath, "backups");
|
||||||
|
public int BackupRetainHours = 36;
|
||||||
|
public int BackupRetainDays = 8;
|
||||||
|
public int BackupRetainWeeks = 6;
|
||||||
|
public int BackupRetainMonths = 18;
|
||||||
|
|
||||||
public string? UpdateUrl = null;
|
public string? UpdateUrl = null;
|
||||||
public bool UpdateAuto = false;
|
public bool UpdateAuto = false;
|
||||||
|
|
||||||
public string? SyncUrl = null;
|
public string? SyncUrl = null;
|
||||||
public string SyncUsername = "";
|
public string SyncUsername = "";
|
||||||
public string SyncPassword = "";
|
public string SyncPassword = "";
|
||||||
@@ -82,8 +94,17 @@ namespace Elwig.Helpers {
|
|||||||
Debug = TrueValues.Contains(config["general:debug"]?.ToLower());
|
Debug = TrueValues.Contains(config["general:debug"]?.ToLower());
|
||||||
var weighing = config["general:weighing"];
|
var weighing = config["general:weighing"];
|
||||||
WeighingMode = weighing != null && Enum.TryParse<WeighingMode>(weighing, true, out var w) ? w : null;
|
WeighingMode = weighing != null && Enum.TryParse<WeighingMode>(weighing, true, out var w) ? w : null;
|
||||||
|
|
||||||
|
BackupAuto = !FalseValues.Contains(config["backup:auto"]?.ToLower());
|
||||||
|
BackupPath = Path.Combine(Path.GetDirectoryName(DatabaseFile) ?? App.DataPath, config["backup:path"] ?? "backups");
|
||||||
|
BackupRetainHours = int.TryParse(config["backup:retain_hours"], out var hours) ? hours : 36;
|
||||||
|
BackupRetainDays = int.TryParse(config["backup:retain_days"], out var days) ? days : 8;
|
||||||
|
BackupRetainWeeks = int.TryParse(config["backup:retain_weeks"], out var weeks) ? weeks : 6;
|
||||||
|
BackupRetainMonths = int.TryParse(config["backup:retain_months"], out var months) ? months : 18;
|
||||||
|
|
||||||
UpdateUrl = config["update:url"];
|
UpdateUrl = config["update:url"];
|
||||||
UpdateAuto = TrueValues.Contains(config["update:auto"]?.ToLower());
|
UpdateAuto = TrueValues.Contains(config["update:auto"]?.ToLower());
|
||||||
|
|
||||||
SyncUrl = config["sync:url"];
|
SyncUrl = config["sync:url"];
|
||||||
SyncUsername = config["sync:username"] ?? "";
|
SyncUsername = config["sync:username"] ?? "";
|
||||||
SyncPassword = config["sync:password"] ?? "";
|
SyncPassword = config["sync:password"] ?? "";
|
||||||
@@ -105,6 +126,7 @@ namespace Elwig.Helpers {
|
|||||||
s, config[$"scale.{s}:type"], config[$"scale.{s}:model"], config[$"scale.{s}:connection"],
|
s, config[$"scale.{s}:type"], config[$"scale.{s}:model"], config[$"scale.{s}:connection"],
|
||||||
config[$"scale.{s}:empty"], config[$"scale.{s}:filling"], config[$"scale.{s}:limit"],
|
config[$"scale.{s}:empty"], config[$"scale.{s}:filling"], config[$"scale.{s}:limit"],
|
||||||
config[$"scale.{s}:required"] != null ? TrueValues.Contains(config[$"scale.{s}:required"]?.ToLower()) : null,
|
config[$"scale.{s}:required"] != null ? TrueValues.Contains(config[$"scale.{s}:required"]?.ToLower()) : null,
|
||||||
|
config[$"scale.{s}:synctime"] != null ? !FalseValues.Contains(config[$"scale.{s}:synctime"]?.ToLower()) : null,
|
||||||
config[$"scale.{s}:log"]
|
config[$"scale.{s}:log"]
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ namespace Elwig.Helpers.Export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static async Task ExportSqlite(string filename, bool zipFile) {
|
public static async Task ExportSqlite(string filename, bool zipFile) {
|
||||||
|
var tmp = filename + ".tmp";
|
||||||
|
try {
|
||||||
|
File.Delete(tmp);
|
||||||
if (zipFile) {
|
if (zipFile) {
|
||||||
File.Delete(filename);
|
using var zip = ZipFile.Open(tmp, ZipArchiveMode.Create);
|
||||||
using var zip = ZipFile.Open(filename, ZipArchiveMode.Create);
|
|
||||||
|
|
||||||
var version = zip.CreateEntry("version", CompressionLevel.NoCompression);
|
var version = zip.CreateEntry("version", CompressionLevel.NoCompression);
|
||||||
using (var writer = new StreamWriter(version.Open(), Utils.UTF8)) {
|
using (var writer = new StreamWriter(version.Open(), Utils.UTF8)) {
|
||||||
@@ -46,14 +48,20 @@ namespace Elwig.Helpers.Export {
|
|||||||
|
|
||||||
var db = zip.CreateEntryFromFile(App.Config.DatabaseFile, "database.sqlite3", CompressionLevel.SmallestSize);
|
var db = zip.CreateEntryFromFile(App.Config.DatabaseFile, "database.sqlite3", CompressionLevel.SmallestSize);
|
||||||
} else {
|
} else {
|
||||||
File.Copy(App.Config.DatabaseFile, filename, true);
|
File.Copy(App.Config.DatabaseFile, tmp);
|
||||||
|
}
|
||||||
|
File.Move(tmp, filename, true);
|
||||||
|
} finally {
|
||||||
|
File.Delete(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task ExportSql(string filename, bool zipFile) {
|
public static async Task ExportSql(string filename, bool zipFile) {
|
||||||
|
var tmp = filename + ".tmp";
|
||||||
|
try {
|
||||||
|
File.Delete(tmp);
|
||||||
if (zipFile) {
|
if (zipFile) {
|
||||||
File.Delete(filename);
|
using var zip = ZipFile.Open(tmp, ZipArchiveMode.Create);
|
||||||
using var zip = ZipFile.Open(filename, ZipArchiveMode.Create);
|
|
||||||
|
|
||||||
var version = zip.CreateEntry("version", CompressionLevel.NoCompression);
|
var version = zip.CreateEntry("version", CompressionLevel.NoCompression);
|
||||||
using (var writer = new StreamWriter(version.Open(), Utils.UTF8)) {
|
using (var writer = new StreamWriter(version.Open(), Utils.UTF8)) {
|
||||||
@@ -82,10 +90,14 @@ namespace Elwig.Helpers.Export {
|
|||||||
await ExportSql(writer);
|
await ExportSql(writer);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
using var stream = File.OpenWrite(filename);
|
using var stream = File.OpenWrite(tmp);
|
||||||
using var writer = new StreamWriter(stream, Utils.UTF8);
|
using var writer = new StreamWriter(stream, Utils.UTF8);
|
||||||
await ExportSql(writer);
|
await ExportSql(writer);
|
||||||
}
|
}
|
||||||
|
File.Move(tmp, filename, true);
|
||||||
|
} finally {
|
||||||
|
File.Delete(tmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task ExportSql(StreamWriter writer) {
|
public static async Task ExportSql(StreamWriter writer) {
|
||||||
@@ -200,7 +212,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task ImportSqlite(string filename, bool zipFile = false) {
|
public static async Task ImportSqlite(string filename, bool zipFile = false, bool keepSource = true) {
|
||||||
if (zipFile) {
|
if (zipFile) {
|
||||||
var newName = Path.ChangeExtension(App.Config.DatabaseFile, ".new.sqlite3");
|
var newName = Path.ChangeExtension(App.Config.DatabaseFile, ".new.sqlite3");
|
||||||
try {
|
try {
|
||||||
@@ -209,7 +221,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
foreach (var entry in zip.Entries) {
|
foreach (var entry in zip.Entries) {
|
||||||
if (entry.Name.EndsWith(".sqlite3")) {
|
if (entry.Name.EndsWith(".sqlite3")) {
|
||||||
entry.ExtractToFile(newName);
|
entry.ExtractToFile(newName);
|
||||||
await ImportSqlite(newName);
|
await ImportSqlite(newName, keepSource: false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,7 +233,11 @@ namespace Elwig.Helpers.Export {
|
|||||||
|
|
||||||
var oldName = Path.ChangeExtension(App.Config.DatabaseFile, ".old.sqlite3");
|
var oldName = Path.ChangeExtension(App.Config.DatabaseFile, ".old.sqlite3");
|
||||||
File.Move(App.Config.DatabaseFile, oldName, true);
|
File.Move(App.Config.DatabaseFile, oldName, true);
|
||||||
|
if (keepSource) {
|
||||||
|
File.Copy(filename, App.Config.DatabaseFile, false);
|
||||||
|
} else {
|
||||||
File.Move(filename, App.Config.DatabaseFile, false);
|
File.Move(filename, App.Config.DatabaseFile, false);
|
||||||
|
}
|
||||||
|
|
||||||
using var cnx = await AppDbContext.ConnectAsync();
|
using var cnx = await AppDbContext.ConnectAsync();
|
||||||
await cnx.ExecuteBatch("VACUUM");
|
await cnx.ExecuteBatch("VACUUM");
|
||||||
@@ -234,7 +250,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
using (var cnx = await AppDbContext.ConnectAsync($"Data Source=\"{newName}\"; Mode=ReadWriteCreate; Foreign Keys=False; Cache=Default; Pooling=False")) {
|
using (var cnx = await AppDbContext.ConnectAsync($"Data Source=\"{newName}\"; Mode=ReadWriteCreate; Foreign Keys=False; Cache=Default; Pooling=False")) {
|
||||||
await cnx.ExecuteBatch(await reader.ReadToEndAsync());
|
await cnx.ExecuteBatch(await reader.ReadToEndAsync());
|
||||||
}
|
}
|
||||||
await ImportSqlite(newName);
|
await ImportSqlite(newName, keepSource: false);
|
||||||
} finally {
|
} finally {
|
||||||
if (File.Exists(newName)) File.Delete(newName);
|
if (File.Exists(newName)) File.Delete(newName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ using System.IO.Compression;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json.Nodes;
|
using System.Text.Json.Nodes;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace Elwig.Helpers.Export {
|
namespace Elwig.Helpers.Export {
|
||||||
public static class ElwigData {
|
public static class ElwigData {
|
||||||
@@ -36,14 +35,16 @@ namespace Elwig.Helpers.Export {
|
|||||||
public static async Task Import(IEnumerable<string> filenames, ImportMode mode) {
|
public static async Task Import(IEnumerable<string> filenames, ImportMode mode) {
|
||||||
try {
|
try {
|
||||||
Dictionary<string, Branch> branches;
|
Dictionary<string, Branch> branches;
|
||||||
|
Dictionary<int, AT_Kg> kgs;
|
||||||
Dictionary<int, int> currentDids;
|
Dictionary<int, int> currentDids;
|
||||||
Dictionary<string, int> currentLsNrs;
|
Dictionary<string, int> currentLsNrs;
|
||||||
Dictionary<int, List<WbRd>> currentWbRde;
|
Dictionary<int, List<WbRd>> currentWbRde;
|
||||||
Dictionary<int, AT_Kg> kgs;
|
Dictionary<int, WbKg> currentWbKgs;
|
||||||
List<WbGl> currentWbGls;
|
List<WbGl> currentWbGls;
|
||||||
|
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
branches = await ctx.FetchBranches().ToDictionaryAsync(b => b.ZwstId);
|
branches = await ctx.FetchBranches().ToDictionaryAsync(b => b.ZwstId);
|
||||||
|
kgs = await ctx.Katastralgemeinden.ToDictionaryAsync(k => k.KgNr);
|
||||||
currentDids = await ctx.Deliveries
|
currentDids = await ctx.Deliveries
|
||||||
.GroupBy(d => d.Year)
|
.GroupBy(d => d.Year)
|
||||||
.ToDictionaryAsync(g => g.Key, g => g.Max(d => d.DId));
|
.ToDictionaryAsync(g => g.Key, g => g.Max(d => d.DId));
|
||||||
@@ -52,8 +53,8 @@ namespace Elwig.Helpers.Export {
|
|||||||
currentWbRde = await ctx.WbRde
|
currentWbRde = await ctx.WbRde
|
||||||
.GroupBy(r => r.KgNr)
|
.GroupBy(r => r.KgNr)
|
||||||
.ToDictionaryAsync(g => g.Key, g => g.ToList());
|
.ToDictionaryAsync(g => g.Key, g => g.ToList());
|
||||||
|
currentWbKgs = await ctx.WbKgs.ToDictionaryAsync(k => k.KgNr);
|
||||||
currentWbGls = await ctx.WbGls.ToListAsync();
|
currentWbGls = await ctx.WbGls.ToListAsync();
|
||||||
kgs = await ctx.Katastralgemeinden.Include(k => k.WbKg).ToDictionaryAsync(k => k.KgNr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = new List<(
|
var data = new List<(
|
||||||
@@ -122,6 +123,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
var obj = JsonNode.Parse(line)!.AsObject();
|
var obj = JsonNode.Parse(line)!.AsObject();
|
||||||
var (k, g) = obj.ToWbKg(currentWbGls);
|
var (k, g) = obj.ToWbKg(currentWbGls);
|
||||||
r.WbKgs.Add(k);
|
r.WbKgs.Add(k);
|
||||||
|
currentWbKgs[k.KgNr] = k;
|
||||||
if (g != null) {
|
if (g != null) {
|
||||||
currentWbGls[g.GlNr] = g;
|
currentWbGls[g.GlNr] = g;
|
||||||
r.WbGls.Add(g);
|
r.WbGls.Add(g);
|
||||||
@@ -135,7 +137,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
string? line;
|
string? line;
|
||||||
while ((line = await reader.ReadLineAsync()) != null) {
|
while ((line = await reader.ReadLineAsync()) != null) {
|
||||||
var obj = JsonNode.Parse(line)!.AsObject();
|
var obj = JsonNode.Parse(line)!.AsObject();
|
||||||
var (m, b, telNrs, emailAddrs, timestamps) = obj.ToMember(kgs);
|
var (m, b, telNrs, emailAddrs, timestamps) = obj.ToMember(kgs, currentWbKgs);
|
||||||
r.Members.Add(m);
|
r.Members.Add(m);
|
||||||
if (b != null) r.BillingAddresses.Add(b);
|
if (b != null) r.BillingAddresses.Add(b);
|
||||||
r.TelephoneNumbers.AddRange(telNrs);
|
r.TelephoneNumbers.AddRange(telNrs);
|
||||||
@@ -163,7 +165,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
string? line;
|
string? line;
|
||||||
while ((line = await reader.ReadLineAsync()) != null) {
|
while ((line = await reader.ReadLineAsync()) != null) {
|
||||||
var obj = JsonNode.Parse(line)!.AsObject();
|
var obj = JsonNode.Parse(line)!.AsObject();
|
||||||
var (contract, areaCom, wbrd, timestamps) = obj.ToAreaCom(currentWbRde);
|
var (contract, areaCom, wbrd, timestamps) = obj.ToAreaCom(kgs, currentWbKgs, currentWbRde);
|
||||||
r.Contracts.Add(contract);
|
r.Contracts.Add(contract);
|
||||||
r.AreaCommitments.Add(areaCom);
|
r.AreaCommitments.Add(areaCom);
|
||||||
if (wbrd != null) {
|
if (wbrd != null) {
|
||||||
@@ -182,7 +184,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
string? line;
|
string? line;
|
||||||
while ((line = await reader.ReadLineAsync()) != null) {
|
while ((line = await reader.ReadLineAsync()) != null) {
|
||||||
var obj = JsonNode.Parse(line)!.AsObject();
|
var obj = JsonNode.Parse(line)!.AsObject();
|
||||||
var (contract, areaComs, wbrd, timestamps) = obj.ToAreaComContract(currentWbRde);
|
var (contract, areaComs, wbrd, timestamps) = obj.ToAreaComContract(kgs, currentWbKgs, currentWbRde);
|
||||||
r.Contracts.Add(contract);
|
r.Contracts.Add(contract);
|
||||||
r.AreaCommitments.AddRange(areaComs.Select(v => v.Item1));
|
r.AreaCommitments.AddRange(areaComs.Select(v => v.Item1));
|
||||||
if (wbrd != null) {
|
if (wbrd != null) {
|
||||||
@@ -203,7 +205,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
string? line;
|
string? line;
|
||||||
while ((line = await reader.ReadLineAsync()) != null) {
|
while ((line = await reader.ReadLineAsync()) != null) {
|
||||||
var obj = JsonNode.Parse(line)!.AsObject();
|
var obj = JsonNode.Parse(line)!.AsObject();
|
||||||
var (d, parts, mods, rde, timestamps) = obj.ToDelivery(currentLsNrs, currentDids, kgs, currentWbRde);
|
var (d, parts, mods, rde, timestamps) = obj.ToDelivery(currentLsNrs, currentDids, kgs, currentWbKgs, currentWbRde);
|
||||||
r.Deliveries.Add(d);
|
r.Deliveries.Add(d);
|
||||||
r.DeliveryParts.AddRange(parts.Select(p => p.Item1));
|
r.DeliveryParts.AddRange(parts.Select(p => p.Item1));
|
||||||
r.Modifiers.AddRange(mods);
|
r.Modifiers.AddRange(mods);
|
||||||
@@ -636,6 +638,8 @@ namespace Elwig.Helpers.Export {
|
|||||||
["zwstid"] = m.ZwstId,
|
["zwstid"] = m.ZwstId,
|
||||||
["lfbis_nr"] = m.LfbisNr,
|
["lfbis_nr"] = m.LfbisNr,
|
||||||
["ustid_nr"] = m.UstIdNr,
|
["ustid_nr"] = m.UstIdNr,
|
||||||
|
["ooc_id"] = m.OrganicOperatorId,
|
||||||
|
["org_auth_code"] = m.OrganicAuthorityCode,
|
||||||
["juridical_pers"] = m.IsJuridicalPerson,
|
["juridical_pers"] = m.IsJuridicalPerson,
|
||||||
["volllieferant"] = m.IsVollLieferant,
|
["volllieferant"] = m.IsVollLieferant,
|
||||||
["buchführend"] = m.IsBuchführend,
|
["buchführend"] = m.IsBuchführend,
|
||||||
@@ -680,11 +684,11 @@ namespace Elwig.Helpers.Export {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (Member, BillingAddr?, List<MemberTelNr>, List<MemberEmailAddr>, (DateTime CreatedAt, DateTime ModifiedAt)?) ToMember(this JsonNode json, Dictionary<int, AT_Kg> kgs) {
|
public static (Member, BillingAddr?, List<MemberTelNr>, List<MemberEmailAddr>, (DateTime CreatedAt, DateTime ModifiedAt)?) ToMember(this JsonNode json, Dictionary<int, AT_Kg> kgs, Dictionary<int, WbKg> currentWbKgs) {
|
||||||
var mgnr = json["mgnr"]!.AsValue().GetValue<int>();
|
var mgnr = json["mgnr"]!.AsValue().GetValue<int>();
|
||||||
var kgnr = json["default_kgnr"]?.AsValue().GetValue<int>();
|
var kgnr = json["default_kgnr"]?.AsValue().GetValue<int>();
|
||||||
if (kgnr != null && !kgs.Values.Any(k => k.WbKg?.KgNr == kgnr)) {
|
if (kgnr != null && !currentWbKgs.Values.Any(k => k.KgNr == kgnr)) {
|
||||||
throw new ArgumentException($"Für KG {(kgs.TryGetValue(kgnr.Value, out var k) ? k.Name : "?")} ({kgnr:00000}) ist noch keine Großlage festgelegt!\n(Stammdaten → Herkunftshierarchie)");
|
throw new KeyNotFoundException($"Für KG {(kgs.TryGetValue(kgnr.Value, out var k) ? k.Name : "?")} ({kgnr:00000}) ist noch keine Großlage festgelegt!\n(Stammdaten \u2192 Herkunftshierarchie)");
|
||||||
}
|
}
|
||||||
var createdAt = json["created_at"]?.AsValue().GetValue<string>();
|
var createdAt = json["created_at"]?.AsValue().GetValue<string>();
|
||||||
var modifiedAt = json["modified_at"]?.AsValue().GetValue<string>();
|
var modifiedAt = json["modified_at"]?.AsValue().GetValue<string>();
|
||||||
@@ -708,6 +712,8 @@ namespace Elwig.Helpers.Export {
|
|||||||
ZwstId = json["zwstid"]?.AsValue().GetValue<string>(),
|
ZwstId = json["zwstid"]?.AsValue().GetValue<string>(),
|
||||||
LfbisNr = json["lfbis_nr"]?.AsValue().GetValue<string>(),
|
LfbisNr = json["lfbis_nr"]?.AsValue().GetValue<string>(),
|
||||||
UstIdNr = json["ustid_nr"]?.AsValue().GetValue<string>(),
|
UstIdNr = json["ustid_nr"]?.AsValue().GetValue<string>(),
|
||||||
|
OrganicOperatorId = json["ooc_id"]?.AsValue().GetValue<string>(),
|
||||||
|
OrganicAuthorityCode = json["org_auth_code"]?.AsValue().GetValue<string>(),
|
||||||
IsJuridicalPerson = json["juridical_pers"]?.AsValue().GetValue<bool>() ?? false,
|
IsJuridicalPerson = json["juridical_pers"]?.AsValue().GetValue<bool>() ?? false,
|
||||||
IsVollLieferant = json["volllieferant"]?.AsValue().GetValue<bool>() ?? false,
|
IsVollLieferant = json["volllieferant"]?.AsValue().GetValue<bool>() ?? false,
|
||||||
IsBuchführend = json["buchführend"]?.AsValue().GetValue<bool>() ?? false,
|
IsBuchführend = json["buchführend"]?.AsValue().GetValue<bool>() ?? false,
|
||||||
@@ -760,7 +766,8 @@ namespace Elwig.Helpers.Export {
|
|||||||
["reason"] = h.Reason,
|
["reason"] = h.Reason,
|
||||||
["source"] = h.Source,
|
["source"] = h.Source,
|
||||||
["shares"] = h.Shares,
|
["shares"] = h.Shares,
|
||||||
["signed"] = h.MemberHasSigned,
|
["signed_company"] = h.CompanyHasSigned,
|
||||||
|
["signed_member"] = h.MemberHasSigned,
|
||||||
["value_per_share"] = h.ValuePerShare,
|
["value_per_share"] = h.ValuePerShare,
|
||||||
["currency"] = h.CurrencyCode,
|
["currency"] = h.CurrencyCode,
|
||||||
["deduct_year"] = h.DeductYear,
|
["deduct_year"] = h.DeductYear,
|
||||||
@@ -780,7 +787,8 @@ namespace Elwig.Helpers.Export {
|
|||||||
Reason = json["reason"]!.AsValue().GetValue<string>(),
|
Reason = json["reason"]!.AsValue().GetValue<string>(),
|
||||||
Source = json["source"]!.AsValue().GetValue<string>(),
|
Source = json["source"]!.AsValue().GetValue<string>(),
|
||||||
Shares = json["shares"]!.AsValue().GetValue<int>(),
|
Shares = json["shares"]!.AsValue().GetValue<int>(),
|
||||||
MemberHasSigned = json["signed"]?.AsValue().GetValue<bool>() ?? false,
|
CompanyHasSigned = json["signed_company"]?.AsValue().GetValue<bool>() ?? false,
|
||||||
|
MemberHasSigned = json["signed_member"]?.AsValue().GetValue<bool>() ?? false,
|
||||||
ValuePerShare = json["value_per_share"]?.AsValue().GetValue<decimal>(),
|
ValuePerShare = json["value_per_share"]?.AsValue().GetValue<decimal>(),
|
||||||
CurrencyCode = json["currency"]?.AsValue().GetValue<string>(),
|
CurrencyCode = json["currency"]?.AsValue().GetValue<string>(),
|
||||||
DeductYear = json["deduct_year"]?.AsValue().GetValue<int>(),
|
DeductYear = json["deduct_year"]?.AsValue().GetValue<int>(),
|
||||||
@@ -815,10 +823,13 @@ namespace Elwig.Helpers.Export {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (AreaComContract, List<(AreaCom, (DateTime CreatedAt, DateTime ModifiedAt)?)>, WbRd?, (DateTime CreatedAt, DateTime ModifiedAt)?) ToAreaComContract(this JsonNode json, Dictionary<int, List<WbRd>> riede) {
|
public static (AreaComContract, List<(AreaCom, (DateTime CreatedAt, DateTime ModifiedAt)?)>, WbRd?, (DateTime CreatedAt, DateTime ModifiedAt)?) ToAreaComContract(this JsonNode json, Dictionary<int, AT_Kg> kgs, Dictionary<int, WbKg> currentWbKgs, Dictionary<int, List<WbRd>> riede) {
|
||||||
var kgnr = json["kgnr"]!.AsValue().GetValue<int>();
|
var kgnr = json["kgnr"]!.AsValue().GetValue<int>();
|
||||||
var ried = json["ried"]?.AsValue().GetValue<string>();
|
var ried = json["ried"]?.AsValue().GetValue<string>();
|
||||||
var fbnr = json["fbnr"]!.AsValue()!.GetValue<int>();
|
var fbnr = json["fbnr"]!.AsValue()!.GetValue<int>();
|
||||||
|
if (!currentWbKgs.Values.Any(k => k.KgNr == kgnr)) {
|
||||||
|
throw new KeyNotFoundException($"Für KG {(kgs.TryGetValue(kgnr, out var k) ? k.Name : "?")} ({kgnr:00000}) ist noch keine Großlage festgelegt!\n(Stammdaten \u2192 Herkunftshierarchie)");
|
||||||
|
}
|
||||||
WbRd? rd = null;
|
WbRd? rd = null;
|
||||||
bool newRd = false;
|
bool newRd = false;
|
||||||
if (ried != null) {
|
if (ried != null) {
|
||||||
@@ -866,9 +877,12 @@ namespace Elwig.Helpers.Export {
|
|||||||
DateTime.ParseExact(modifiedAt, "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.None)));
|
DateTime.ParseExact(modifiedAt, "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.None)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (AreaComContract, AreaCom, WbRd?, (DateTime CreatedAt, DateTime ModifiedAt)?) ToAreaCom(this JsonNode json, Dictionary<int, List<WbRd>> riede) {
|
public static (AreaComContract, AreaCom, WbRd?, (DateTime CreatedAt, DateTime ModifiedAt)?) ToAreaCom(this JsonNode json, Dictionary<int, AT_Kg> kgs, Dictionary<int, WbKg> currentWbKgs, Dictionary<int, List<WbRd>> riede) {
|
||||||
var kgnr = json["kgnr"]!.AsValue().GetValue<int>();
|
var kgnr = json["kgnr"]!.AsValue().GetValue<int>();
|
||||||
var ried = json["ried"]?.AsValue().GetValue<string>();
|
var ried = json["ried"]?.AsValue().GetValue<string>();
|
||||||
|
if (!currentWbKgs.Values.Any(k => k.KgNr == kgnr)) {
|
||||||
|
throw new KeyNotFoundException($"Für KG {(kgs.TryGetValue(kgnr, out var k) ? k.Name : "?")} ({kgnr:00000}) ist noch keine Großlage festgelegt!\n(Stammdaten \u2192 Herkunftshierarchie)");
|
||||||
|
}
|
||||||
WbRd? rd = null;
|
WbRd? rd = null;
|
||||||
bool newRd = false;
|
bool newRd = false;
|
||||||
if (ried != null) {
|
if (ried != null) {
|
||||||
@@ -957,7 +971,7 @@ namespace Elwig.Helpers.Export {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (Delivery, List<(DeliveryPart, (DateTime CreatedAt, DateTime ModifiedAt)?)>, List<DeliveryPartModifier>, List<WbRd>, (DateTime CreatedAt, DateTime ModifiedAt)?) ToDelivery(this JsonNode json, Dictionary<string, int> currentLsNrs, Dictionary<int, int> currentDids, Dictionary<int, AT_Kg> kgs, Dictionary<int, List<WbRd>> riede) {
|
public static (Delivery, List<(DeliveryPart, (DateTime CreatedAt, DateTime ModifiedAt)?)>, List<DeliveryPartModifier>, List<WbRd>, (DateTime CreatedAt, DateTime ModifiedAt)?) ToDelivery(this JsonNode json, Dictionary<string, int> currentLsNrs, Dictionary<int, int> currentDids, Dictionary<int, AT_Kg> kgs, Dictionary<int, WbKg> currentWbKgs, Dictionary<int, List<WbRd>> riede) {
|
||||||
var year = json["year"]!.AsValue().GetValue<int>();
|
var year = json["year"]!.AsValue().GetValue<int>();
|
||||||
var lsnr = json["lsnr"]!.AsValue().GetValue<string>();
|
var lsnr = json["lsnr"]!.AsValue().GetValue<string>();
|
||||||
var did = currentLsNrs.GetValueOrDefault(lsnr, -1);
|
var did = currentLsNrs.GetValueOrDefault(lsnr, -1);
|
||||||
@@ -983,6 +997,9 @@ namespace Elwig.Helpers.Export {
|
|||||||
}, [.. json["parts"]!.AsArray().Select(p => p!.AsObject()).Select<JsonObject, (DeliveryPart, (DateTime, DateTime)?)>(p => {
|
}, [.. json["parts"]!.AsArray().Select(p => p!.AsObject()).Select<JsonObject, (DeliveryPart, (DateTime, DateTime)?)>(p => {
|
||||||
var kgnr = p["kgnr"]?.AsValue().GetValue<int>();
|
var kgnr = p["kgnr"]?.AsValue().GetValue<int>();
|
||||||
var ried = p["ried"]?.AsValue().GetValue<string>();
|
var ried = p["ried"]?.AsValue().GetValue<string>();
|
||||||
|
if (kgnr != null && !currentWbKgs.Values.Any(k => k.KgNr == kgnr)) {
|
||||||
|
throw new KeyNotFoundException($"Für KG {(kgs.TryGetValue(kgnr.Value, out var k) ? k.Name : "?")} ({kgnr:00000}) ist noch keine Großlage festgelegt!\n(Stammdaten \u2192 Herkunftshierarchie)");
|
||||||
|
}
|
||||||
WbRd? rd = null;
|
WbRd? rd = null;
|
||||||
if (ried != null && kgnr != null) {
|
if (ried != null && kgnr != null) {
|
||||||
var rde = riede.GetValueOrDefault(kgnr.Value, []);
|
var rde = riede.GetValueOrDefault(kgnr.Value, []);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.IO.Hashing;
|
using System.IO.Hashing;
|
||||||
@@ -12,6 +13,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Elwig.Helpers {
|
namespace Elwig.Helpers {
|
||||||
public static partial class Extensions {
|
public static partial class Extensions {
|
||||||
@@ -134,11 +136,39 @@ namespace Elwig.Helpers {
|
|||||||
return await cmd.ExecuteScalarAsync();
|
return await cmd.ExecuteScalarAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<(string Table, long RowId, string Parent, long FkId)[]> ForeignKeyCheck(this SqliteConnection cnx) {
|
public static async Task QuickCheck(this SqliteConnection cnx) {
|
||||||
|
using var cmd = cnx.CreateCommand();
|
||||||
|
cmd.CommandText = "PRAGMA quick_check";
|
||||||
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
var list = new List<string>();
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
list.Add(reader.GetString(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.Count != 1 || list[0] != "ok") {
|
||||||
|
throw new FileFormatException($"Integrity problems ({list.Count}):\n" + string.Join("\n", list.Take(50)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task IntegrityCheck(this SqliteConnection cnx) {
|
||||||
|
using var cmd = cnx.CreateCommand();
|
||||||
|
cmd.CommandText = "PRAGMA integrity_check";
|
||||||
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
var list = new List<string>();
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
list.Add(reader.GetString(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.Count != 1 || list[0] != "ok") {
|
||||||
|
throw new FileFormatException($"Integrity problems ({list.Count}):\n" + string.Join("\n", list.Take(50)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ForeignKeyCheck(this SqliteConnection cnx) {
|
||||||
using var cmd = cnx.CreateCommand();
|
using var cmd = cnx.CreateCommand();
|
||||||
cmd.CommandText = "PRAGMA foreign_key_check";
|
cmd.CommandText = "PRAGMA foreign_key_check";
|
||||||
using var reader = await cmd.ExecuteReaderAsync();
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
var list = new List<(string, long, string, long)>();
|
var list = new List<(string Table, long RowId, string Parent, long FkId)>();
|
||||||
while (await reader.ReadAsync()) {
|
while (await reader.ReadAsync()) {
|
||||||
var table = reader.GetString(0);
|
var table = reader.GetString(0);
|
||||||
var rowid = reader.GetInt64(1);
|
var rowid = reader.GetInt64(1);
|
||||||
@@ -146,7 +176,11 @@ namespace Elwig.Helpers {
|
|||||||
var fkid = reader.GetInt64(3);
|
var fkid = reader.GetInt64(3);
|
||||||
list.Add((table, rowid, parent, fkid));
|
list.Add((table, rowid, parent, fkid));
|
||||||
}
|
}
|
||||||
return [.. list];
|
|
||||||
|
if (list.Count > 0) {
|
||||||
|
throw new InvalidDataException($"Foreign key violations ({list.Count}):\n" + string.Join("\n", list.Take(50)
|
||||||
|
.Select(v => $"{v.Table} - {v.RowId} - {v.Parent} - {v.FkId}")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<T> Join<T>(this IEnumerable<T> src, Func<T> separatorFactory) {
|
public static IEnumerable<T> Join<T>(this IEnumerable<T> src, Func<T> separatorFactory) {
|
||||||
@@ -159,17 +193,25 @@ namespace Elwig.Helpers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddToolTipCell(this Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) {
|
public static void AddToolTipCell(this Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false, Brush? color = null) {
|
||||||
var tb = new TextBlock() {
|
var tb = new TextBlock() {
|
||||||
Text = text,
|
Text = text,
|
||||||
TextAlignment = alignRight ? TextAlignment.Right : alignCenter ? TextAlignment.Center : TextAlignment.Left,
|
TextAlignment = alignRight ? TextAlignment.Right : alignCenter ? TextAlignment.Center : TextAlignment.Left,
|
||||||
Margin = new(0, 12 * row, 0, 0),
|
Margin = new(0, 12 * row, 0, 0),
|
||||||
FontWeight = bold ? FontWeights.Bold : FontWeights.Normal,
|
FontWeight = bold ? FontWeights.Bold : FontWeights.Normal,
|
||||||
};
|
};
|
||||||
|
if (color != null) tb.Foreground = color;
|
||||||
tb.SetValue(Grid.ColumnProperty, col);
|
tb.SetValue(Grid.ColumnProperty, col);
|
||||||
tb.SetValue(Grid.ColumnSpanProperty, colSpan);
|
tb.SetValue(Grid.ColumnSpanProperty, colSpan);
|
||||||
grid.Children.Add(tb);
|
grid.Children.Add(tb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static (int Year, int Week) GetYearAndWeek(this DateTime date) {
|
||||||
|
return (ISOWeek.GetYear(date), ISOWeek.GetWeekOfYear(date));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (int Year, int Tertial) GetYearAndTertial(this DateTime date) {
|
||||||
|
return (date.Month <= 7 ? date.Year - 1 : date.Year, date.Month == 12 || date.Month <= 3 ? 2 : date.Month <= 7 ? 3 : 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
using Elwig.Services;
|
using Elwig.Services;
|
||||||
using Elwig.Windows;
|
using Elwig.Windows;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Elwig.Helpers.Printing {
|
namespace Elwig.Helpers.Printing {
|
||||||
public static class Pdf {
|
public static class Pdf {
|
||||||
|
|
||||||
public static Task Init(Action? evtHandler = null) {
|
public static void Init(Action? evtHandler = null) {
|
||||||
PdfiumNative.FPDF_InitLibrary();
|
PdfiumNative.FPDF_InitLibrary();
|
||||||
evtHandler?.Invoke();
|
evtHandler?.Invoke();
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task Cleanup() {
|
public static void Cleanup() {
|
||||||
PdfiumNative.FPDF_DestroyLibrary();
|
PdfiumNative.FPDF_DestroyLibrary();
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Show(TempFile file, string title) {
|
public static void Show(TempFile file, string title) {
|
||||||
@@ -31,14 +28,13 @@ namespace Elwig.Helpers.Printing {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task Print(string path, int copies = 1, bool doublePaged = false) {
|
public static void Print(string path, int copies = 1, bool doublePaged = false) {
|
||||||
try {
|
try {
|
||||||
var printer = new PdfPrinter();
|
var printer = new PdfPrinter();
|
||||||
printer.Print(path, copies, doublePaged);
|
printer.Print(path, copies, doublePaged);
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
InteractionService.ShowException("Fehler beim Drucken", "Beim Drucken ist ein Fehler aufgetreten", exc);
|
InteractionService.ShowException("Fehler beim Drucken", "Beim Drucken ist ein Fehler aufgetreten", exc);
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-1
@@ -45,7 +45,6 @@ namespace Elwig.Helpers {
|
|||||||
public static int CurrentNextSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0);
|
public static int CurrentNextSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0);
|
||||||
public static int CurrentLastSeason => DateTime.Now.Year - (DateTime.Now.Month <= 6 ? 1 : 0);
|
public static int CurrentLastSeason => DateTime.Now.Year - (DateTime.Now.Month <= 6 ? 1 : 0);
|
||||||
public static int FollowingSeason => DateTime.Now.Year + (DateTime.Now.Month >= 11 ? 1 : 0);
|
public static int FollowingSeason => DateTime.Now.Year + (DateTime.Now.Month >= 11 ? 1 : 0);
|
||||||
public static DateTime Today => (DateTime.Now.Hour >= 3) ? DateTime.Today : DateTime.Today.AddDays(-1);
|
|
||||||
|
|
||||||
[GeneratedRegex("^serial://([A-Za-z0-9]+):([0-9]+)(,([5-9]),([NOEMSnoems]),(0|1|1\\.5|2|))?$", RegexOptions.Compiled)]
|
[GeneratedRegex("^serial://([A-Za-z0-9]+):([0-9]+)(,([5-9]),([NOEMSnoems]),(0|1|1\\.5|2|))?$", RegexOptions.Compiled)]
|
||||||
private static partial Regex GeneratedSerialRegex();
|
private static partial Regex GeneratedSerialRegex();
|
||||||
@@ -304,6 +303,11 @@ namespace Elwig.Helpers {
|
|||||||
return d.ShowDialog() == true ? (d.Weight, d.Reason) : null;
|
return d.ShowDialog() == true ? (d.Weight, d.Reason) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int? ShowTareCorrectionDialog(int? actualTare, int? targetTare = null) {
|
||||||
|
var d = new TareCorrectionDialog(actualTare, targetTare);
|
||||||
|
return d.ShowDialog() == true ? d.TargetTare - d.ActualTare : null;
|
||||||
|
}
|
||||||
|
|
||||||
public static (string?, int[])? ShowDeliverySplittingDialog(Delivery delivery) {
|
public static (string?, int[])? ShowDeliverySplittingDialog(Delivery delivery) {
|
||||||
var d = new DeliverySplittingDialog(delivery);
|
var d = new DeliverySplittingDialog(delivery);
|
||||||
return d.ShowDialog() == true ? (d.MgNr?.ToString() ?? d.LsNr, d.Weights ?? []) : null;
|
return d.ShowDialog() == true ? (d.MgNr?.ToString() ?? d.LsNr, d.Weights ?? []) : null;
|
||||||
@@ -536,6 +540,7 @@ namespace Elwig.Helpers {
|
|||||||
msg.From.Add(new MailboxAddress(App.Client.NameFull, App.Config.Smtp.Value.From));
|
msg.From.Add(new MailboxAddress(App.Client.NameFull, App.Config.Smtp.Value.From));
|
||||||
msg.To.AddRange(member.EmailAddresses.OrderBy(a => a.Nr).Select(a => new MailboxAddress(member.AdministrativeName, a.Address)));
|
msg.To.AddRange(member.EmailAddresses.OrderBy(a => a.Nr).Select(a => new MailboxAddress(member.AdministrativeName, a.Address)));
|
||||||
msg.Subject = subject;
|
msg.Subject = subject;
|
||||||
|
msg.Date = DateTime.Now;
|
||||||
var body = new Multipart("mixed") {
|
var body = new Multipart("mixed") {
|
||||||
new TextPart("plain") { Text = text }
|
new TextPart("plain") { Text = text }
|
||||||
};
|
};
|
||||||
@@ -712,5 +717,10 @@ namespace Elwig.Helpers {
|
|||||||
var filename = Path.Combine(App.MailsPath, $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{NormalizeFileName(subject)}.txt");
|
var filename = Path.Combine(App.MailsPath, $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{NormalizeFileName(subject)}.txt");
|
||||||
await File.WriteAllTextAsync(filename, $"# {subject}\r\n# Vorgesehene Empfänger: {recipients}\r\n\r\n" + body, Utils.UTF8);
|
await File.WriteAllTextAsync(filename, $"# {subject}\r\n# Vorgesehene Empfänger: {recipients}\r\n\r\n" + body, Utils.UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetTitle(string window, IEnumerable<string> filterNames, IEnumerable<string> filter) {
|
||||||
|
var f = string.Join(" / ", filterNames.Union(filter.Select(f => $"\"{f}\"")));
|
||||||
|
return window + (f.Length == 0 ? "" : ": " + f) + " - Elwig";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -623,6 +623,37 @@ namespace Elwig.Helpers {
|
|||||||
return new(true, null);
|
return new(true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ValidationResult CheckOrganicOperatorId(TextBox input, bool required) {
|
||||||
|
string text = "";
|
||||||
|
int pos = input.CaretIndex;
|
||||||
|
for (int i = 0, v = 0; i < input.Text.Length; i++) {
|
||||||
|
char ch = input.Text[i];
|
||||||
|
if (char.IsAsciiDigit(ch)) {
|
||||||
|
if (v == 3 && text[^1] != '-')
|
||||||
|
text += "-";
|
||||||
|
v++;
|
||||||
|
text += ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == input.CaretIndex - 1) {
|
||||||
|
pos = text.Length;
|
||||||
|
} else if (v >= 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.Text = text;
|
||||||
|
input.CaretIndex = pos;
|
||||||
|
|
||||||
|
if (text.Length == 0) {
|
||||||
|
return required ? new(false, "OOC-ID ist nicht optional") : new(true, null);
|
||||||
|
} else if (!text.StartsWith("040-") || text.Length != 11) {
|
||||||
|
return new(false, "OOC-ID ist ungültig");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new(true, null);
|
||||||
|
}
|
||||||
|
|
||||||
public static ValidationResult CheckOrganicAuthorityCode(TextBox input, bool required) {
|
public static ValidationResult CheckOrganicAuthorityCode(TextBox input, bool required) {
|
||||||
string text = "";
|
string text = "";
|
||||||
int pos = input.CaretIndex;
|
int pos = input.CaretIndex;
|
||||||
@@ -631,15 +662,18 @@ namespace Elwig.Helpers {
|
|||||||
if (v < 2 && char.IsAsciiLetter(ch)) {
|
if (v < 2 && char.IsAsciiLetter(ch)) {
|
||||||
v++;
|
v++;
|
||||||
text += ch;
|
text += ch;
|
||||||
} else if ((v == 2 || v == 6) && ch == '-') {
|
} else if ((v == 2 || v == 5) && ch == '-' && text[^1] != '-') {
|
||||||
v++;
|
|
||||||
text += ch;
|
text += ch;
|
||||||
} else if (v >= 2 && char.IsLetterOrDigit(ch)) {
|
} else if (v >= 2 && v <= 4 && char.IsLetter(ch)) {
|
||||||
|
if (v == 2 && text[^1] != '-')
|
||||||
|
text += "-";
|
||||||
if (text.StartsWith("AT")) {
|
if (text.StartsWith("AT")) {
|
||||||
if (v == 3 && ch == 'B' || v == 4 && ch == 'I' || v == 5 && ch == 'O') {
|
if (v == 2 && ch == 'B' || v == 3 && ch == 'I' || v == 4 && ch == 'O') {
|
||||||
v++;
|
v++;
|
||||||
text += ch;
|
text += ch;
|
||||||
} else if (v > 6 && char.IsAsciiDigit(ch)) {
|
}
|
||||||
|
} else if (text.StartsWith("DE")) {
|
||||||
|
if (v == 2 && ch == 'Ö' || v == 3 && ch == 'K' || v == 4 && ch == 'O') {
|
||||||
v++;
|
v++;
|
||||||
text += ch;
|
text += ch;
|
||||||
}
|
}
|
||||||
@@ -647,11 +681,16 @@ namespace Elwig.Helpers {
|
|||||||
v++;
|
v++;
|
||||||
text += ch;
|
text += ch;
|
||||||
}
|
}
|
||||||
|
} else if (v >= 5 && v <= 7 && char.IsAsciiDigit(ch)) {
|
||||||
|
if (v == 5 && text[^1] != '-')
|
||||||
|
text += "-";
|
||||||
|
v++;
|
||||||
|
text += ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == input.CaretIndex - 1) {
|
if (i == input.CaretIndex - 1) {
|
||||||
pos = text.Length;
|
pos = text.Length;
|
||||||
} else if (text.StartsWith("AT") && v >= 10) {
|
} else if ((text.StartsWith("AT") || text.StartsWith("DE")) && v >= 10) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -662,7 +701,7 @@ namespace Elwig.Helpers {
|
|||||||
if (text.Length == 0)
|
if (text.Length == 0)
|
||||||
return required ? new(false, "Bio-Kontrollstellen-Code ist nicht optional") : new(true, null);
|
return required ? new(false, "Bio-Kontrollstellen-Code ist nicht optional") : new(true, null);
|
||||||
|
|
||||||
if (text.StartsWith("AT")) {
|
if (text.StartsWith("AT") || text.StartsWith("DE")) {
|
||||||
if (text.Length != 10) {
|
if (text.Length != 10) {
|
||||||
return new(false, "Bio-Kontrollstellen-Code ist ungültig");
|
return new(false, "Bio-Kontrollstellen-Code ist ungültig");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ namespace Elwig.Models.Entities {
|
|||||||
[Column("weighing_data")]
|
[Column("weighing_data")]
|
||||||
public string? WeighingData { get; set; }
|
public string? WeighingData { get; set; }
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public (string? ScaleId, string? Id, int? Gross, int? Tare, int? Net, DateOnly? Date, TimeOnly? Time) WeighingInfo {
|
public (string? ScaleId, string? Id, int? Gross, int? Tare, int? TareCorrection, int? Net, DateOnly? Date, TimeOnly? Time) WeighingInfo {
|
||||||
get {
|
get {
|
||||||
try {
|
try {
|
||||||
var obj = JsonNode.Parse(WeighingData!)!.AsObject();
|
var obj = JsonNode.Parse(WeighingData!)!.AsObject();
|
||||||
@@ -133,12 +133,13 @@ namespace Elwig.Models.Entities {
|
|||||||
obj["id"]?.AsValue().GetValue<string>(),
|
obj["id"]?.AsValue().GetValue<string>(),
|
||||||
obj["gross_weight"]?.AsValue().GetValue<int>(),
|
obj["gross_weight"]?.AsValue().GetValue<int>(),
|
||||||
obj["tare_weight"]?.AsValue().GetValue<int>(),
|
obj["tare_weight"]?.AsValue().GetValue<int>(),
|
||||||
|
obj["tare_correction"]?.AsValue().GetValue<int>(),
|
||||||
obj["net_weight"]?.AsValue().GetValue<int>(),
|
obj["net_weight"]?.AsValue().GetValue<int>(),
|
||||||
DateOnly.TryParseExact(obj["date"]?.AsValue().GetValue<string>(), "yyyy-MM-dd", out var d) ? d : null,
|
DateOnly.TryParseExact(obj["date"]?.AsValue().GetValue<string>(), "yyyy-MM-dd", out var d) ? d : null,
|
||||||
TimeOnly.TryParseExact(obj["time"]?.AsValue().GetValue<string>(), ["HH:mm:ss", "HH:mm"], out var t) ? t : null
|
TimeOnly.TryParseExact(obj["time"]?.AsValue().GetValue<string>(), ["HH:mm:ss", "HH:mm"], out var t) ? t : null
|
||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
return (null, null, null, null, null, null, null);
|
return (null, null, null, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,12 @@ namespace Elwig.Models.Entities {
|
|||||||
[Column("ustid_nr")]
|
[Column("ustid_nr")]
|
||||||
public string? UstIdNr { get; set; }
|
public string? UstIdNr { get; set; }
|
||||||
|
|
||||||
|
[Column("ooc_id")]
|
||||||
|
public string? OrganicOperatorId { get; set; }
|
||||||
|
|
||||||
|
[Column("org_auth_code")]
|
||||||
|
public string? OrganicAuthorityCode { get; set; }
|
||||||
|
|
||||||
[Column("juridical_pers")]
|
[Column("juridical_pers")]
|
||||||
public bool IsJuridicalPerson { get; set; }
|
public bool IsJuridicalPerson { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,10 @@ namespace Elwig.Models.Entities {
|
|||||||
[Column("shares")]
|
[Column("shares")]
|
||||||
public int Shares { get; set; }
|
public int Shares { get; set; }
|
||||||
|
|
||||||
[Column("signed")]
|
[Column("signed_company")]
|
||||||
|
public bool CompanyHasSigned { get; set; }
|
||||||
|
|
||||||
|
[Column("signed_member")]
|
||||||
public bool MemberHasSigned { get; set; }
|
public bool MemberHasSigned { get; set; }
|
||||||
|
|
||||||
[Column("value_per_share")]
|
[Column("value_per_share")]
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ namespace Elwig.Models.Entities {
|
|||||||
[Column("name")]
|
[Column("name")]
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
|
|
||||||
|
[Column("organic")]
|
||||||
|
public bool IsOrganic { get; set; }
|
||||||
|
|
||||||
[Column("description")]
|
[Column("description")]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
-- schema version 41 to 42
|
||||||
|
|
||||||
|
ALTER TABLE member ADD COLUMN ooc_id TEXT CHECK (ooc_id REGEXP '^[0-9]{3}-[0-9]{7}$') DEFAULT NULL;
|
||||||
|
ALTER TABLE member ADD COLUMN org_auth_code TEXT CHECK (org_auth_code REGEXP '^[A-Z]{2}-[A-ZÖØ]{3}-[0-9]{2,3}(-[A-Z]{2})?$') DEFAULT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE wine_cultivation ADD COLUMN organic INTEGER NOT NULL CHECK (organic IN (TRUE, FALSE)) DEFAULT FALSE;
|
||||||
|
|
||||||
|
ALTER TABLE member_history RENAME COLUMN signed TO signed_member;
|
||||||
|
ALTER TABLE member_history ADD COLUMN signed_company INTEGER NOT NULL CHECK (signed_company IN (TRUE, FALSE)) DEFAULT FALSE;
|
||||||
|
|
||||||
|
UPDATE member SET org_auth_code = UPPER(SUBSTR(a.name, -11, 10)) FROM member m JOIN member_billing_address a ON a.mgnr = m.mgnr WHERE a.name LIKE '%AT-BIO-___)';
|
||||||
|
UPDATE member SET org_auth_code = UPPER(SUBSTR(a.name, -10, 10)) FROM member m JOIN member_billing_address a ON a.mgnr = m.mgnr WHERE a.name LIKE '%AT-BIO-___';
|
||||||
|
UPDATE member SET org_auth_code = UPPER(suffix) WHERE suffix LIKE 'AT-BIO-___';
|
||||||
|
|
||||||
|
UPDATE wine_cultivation SET organic = TRUE WHERE name LIKE '%bio%' OR name LIKE '%org%' OR description LIKE '%AT-BIO-%';
|
||||||
|
UPDATE wine_cultivation SET description = NULL WHERE description LIKE '%AT-BIO-%';
|
||||||
|
UPDATE wine_cultivation SET description = 'Biologische Produktion' WHERE organic;
|
||||||
|
|
||||||
|
UPDATE client_parameter SET param = 'CLIENT_ORGANIC_AUTHORITYCODE' WHERE param = 'CLIENT_ORGANIC_AUTHORITY';
|
||||||
|
|
||||||
|
UPDATE member_telephone_number SET comment = NULL WHERE comment = '';
|
||||||
|
UPDATE member_email_address SET comment = NULL WHERE comment = '';
|
||||||
@@ -43,6 +43,8 @@ namespace Elwig.Services {
|
|||||||
public static async Task<(List<string>, IQueryable<AreaComContract>, IQueryable<AreaCom>, List<string>)> GetFilters(this AreaComAdminViewModel vm, AppDbContext ctx) {
|
public static async Task<(List<string>, IQueryable<AreaComContract>, IQueryable<AreaCom>, List<string>)> GetFilters(this AreaComAdminViewModel vm, AppDbContext ctx) {
|
||||||
List<string> filterNames = [];
|
List<string> filterNames = [];
|
||||||
IQueryable<AreaCom> areaComQuery = ctx.AreaCommitments.Where(a => a.MgNr == vm.FilterMember.MgNr).OrderBy(a => a.FbNr);
|
IQueryable<AreaCom> areaComQuery = ctx.AreaCommitments.Where(a => a.MgNr == vm.FilterMember.MgNr).OrderBy(a => a.FbNr);
|
||||||
|
filterNames.Add(vm.FilterMember.AdministrativeName);
|
||||||
|
|
||||||
if (vm.FilterSeason is int season) {
|
if (vm.FilterSeason is int season) {
|
||||||
areaComQuery = Utils.ActiveAreaCommitments(areaComQuery, season);
|
areaComQuery = Utils.ActiveAreaCommitments(areaComQuery, season);
|
||||||
filterNames.Add($"laufend {season}");
|
filterNames.Add($"laufend {season}");
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
using Elwig.Helpers;
|
||||||
|
using Elwig.Helpers.Export;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace Elwig.Services {
|
||||||
|
public static class BackupService {
|
||||||
|
|
||||||
|
public static bool IsAnyBackupUpToDate {
|
||||||
|
get {
|
||||||
|
var lastDbWrite = File.GetLastWriteTime(App.Config.DatabaseFile);
|
||||||
|
lastDbWrite += new TimeSpan(0, 0, -1);
|
||||||
|
return Directory.GetFiles(App.Config.BackupPath, "????-??-??_??-??-??.*.zip")
|
||||||
|
.Any(n => DateTime.ParseExact(Path.GetFileName(n)[..19], "yyyy-MM-dd_HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.None) >= lastDbWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task TryDatabaseBackup() {
|
||||||
|
if (IsAnyBackupUpToDate) return;
|
||||||
|
await BackupDatabase();
|
||||||
|
PruneBackups();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task BackupDatabase() {
|
||||||
|
await Database.ExportSql(Path.Combine(App.Config.BackupPath, $"{File.GetLastWriteTime(App.Config.DatabaseFile):yyyy-MM-dd_HH-mm-ss}.sql.zip"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PruneBackups() {
|
||||||
|
var retain = new HashSet<string>();
|
||||||
|
var backups = Directory.GetFiles(App.Config.BackupPath, "????-??-??_??-??-??.*.zip")
|
||||||
|
.Select(n => (FileName: n, Timestamp: DateTime.ParseExact(Path.GetFileName(n)[..19], "yyyy-MM-dd_HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.None)))
|
||||||
|
.OrderByDescending(t => t.Timestamp).ToArray();
|
||||||
|
|
||||||
|
DateTime now;
|
||||||
|
|
||||||
|
// retain hourly backups
|
||||||
|
now = DateTime.Now;
|
||||||
|
for (int i = 0; i < App.Config.BackupRetainHours; i++, now = now.AddHours(-1)) {
|
||||||
|
foreach (var b in backups) {
|
||||||
|
if (b.Timestamp.Date == now.Date && b.Timestamp.Hour == now.Hour) {
|
||||||
|
retain.Add(b.FileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// retain daily backups
|
||||||
|
now = DateTime.Now;
|
||||||
|
for (int i = 0; i < App.Config.BackupRetainDays; i++, now = now.AddDays(-1)) {
|
||||||
|
foreach (var b in backups) {
|
||||||
|
if (b.Timestamp.Date == now.Date) {
|
||||||
|
retain.Add(b.FileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// retain weekly backups
|
||||||
|
now = DateTime.Now;
|
||||||
|
for (int i = 0; i < App.Config.BackupRetainWeeks; i++, now = now.AddDays(-7)) {
|
||||||
|
foreach (var b in backups) {
|
||||||
|
if (b.Timestamp.GetYearAndWeek() == now.GetYearAndWeek()) {
|
||||||
|
retain.Add(b.FileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// retain monthly backups
|
||||||
|
now = DateTime.Now;
|
||||||
|
for (int i = 0; i < App.Config.BackupRetainMonths; i++, now = now.AddMonths(-1)) {
|
||||||
|
foreach (var b in backups) {
|
||||||
|
if (b.Timestamp.Year == now.Year && b.Timestamp.Month == now.Month) {
|
||||||
|
retain.Add(b.FileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// retain tertial backups
|
||||||
|
now = new DateTime(DateTime.Now.Year + 1, 3, 1);
|
||||||
|
for (int i = 0; i < 600; i++, now = now.AddMonths(-4)) {
|
||||||
|
foreach (var b in backups) {
|
||||||
|
if (b.Timestamp.GetYearAndTertial() == now.GetYearAndTertial()) {
|
||||||
|
retain.Add(b.FileName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete non-retained files
|
||||||
|
foreach (var b in backups) {
|
||||||
|
if (retain.Contains(b.FileName)) continue;
|
||||||
|
try {
|
||||||
|
File.Delete(b.FileName);
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
// delete temp files
|
||||||
|
foreach (var f in Directory.GetFiles(App.Config.BackupPath, "*.tmp")) {
|
||||||
|
try {
|
||||||
|
File.Delete(f);
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task RestoreDatabase() {
|
||||||
|
try {
|
||||||
|
var d = new OpenFileDialog() {
|
||||||
|
Title = "Datenbank wiederherstellen - Elwig",
|
||||||
|
DefaultDirectory = App.Config.BackupPath,
|
||||||
|
InitialDirectory = App.Config.BackupPath,
|
||||||
|
DefaultExt = "sql.zip",
|
||||||
|
Filter = "SQLite-Datenbank (*.sqlite3, *.sqlite3.zip, *.sql, *.sql.zip)|*.sqlite3;*.sqlite3.zip;*.sql;*.sql.zip",
|
||||||
|
};
|
||||||
|
if (d.ShowDialog() == true) {
|
||||||
|
if (!InteractionService.AskContinue("Datenbank wiederherstellen", "Soll die Datenbank wirklich unwiederruflich durch die wiederhergestellte Version ersetzt werden?"))
|
||||||
|
return;
|
||||||
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
|
await App.ReplaceDatabase(d.FileName);
|
||||||
|
}
|
||||||
|
} catch (Exception exc) {
|
||||||
|
InteractionService.ShowException(exc);
|
||||||
|
}
|
||||||
|
Mouse.OverrideCursor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,8 @@ namespace Elwig.Services {
|
|||||||
deliveryAncmtQuery = deliveryAncmtQuery.Where(a => a.Year == s.Year && a.DsNr == s.DsNr);
|
deliveryAncmtQuery = deliveryAncmtQuery.Where(a => a.Year == s.Year && a.DsNr == s.DsNr);
|
||||||
filterNames.Add($"{s.Date:dd.MM.yyyy} – {s.Branch.Name} – {s.Description}");
|
filterNames.Add($"{s.Date:dd.MM.yyyy} – {s.Branch.Name} – {s.Description}");
|
||||||
} else {
|
} else {
|
||||||
deliveryAncmtQuery = deliveryAncmtQuery.Where(a => a.Year == vm.FilterSeason && (!vm.FilterOnlyUpcoming || a.Schedule.DateString.CompareTo(Utils.Today.ToString("yyyy-MM-dd")) >= 0));
|
var today = DateTime.Today;
|
||||||
|
deliveryAncmtQuery = deliveryAncmtQuery.Where(a => a.Year == vm.FilterSeason && (!vm.FilterOnlyUpcoming || a.Schedule.DateString.CompareTo(today.ToString("yyyy-MM-dd")) >= 0));
|
||||||
filterNames.Add($"{vm.FilterSeason}");
|
filterNames.Add($"{vm.FilterSeason}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,8 +49,9 @@ namespace Elwig.Services {
|
|||||||
filterNames.Add($"{vm.FilterSeason}");
|
filterNames.Add($"{vm.FilterSeason}");
|
||||||
}
|
}
|
||||||
if (vm.FilterOnlyUpcoming) {
|
if (vm.FilterOnlyUpcoming) {
|
||||||
deliveryScheduleQuery = deliveryScheduleQuery.Where(s => s.DateString.CompareTo(Utils.Today.ToString("yyyy-MM-dd")) >= 0);
|
var today = DateTime.Today;
|
||||||
filterNames.Add($"ab {Utils.Today:dd.MM.yyyy}");
|
deliveryScheduleQuery = deliveryScheduleQuery.Where(s => s.DateString.CompareTo(today.ToString("yyyy-MM-dd")) >= 0);
|
||||||
|
filterNames.Add($"ab {today:dd.MM.yyyy}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var filterVar = new List<string>();
|
var filterVar = new List<string>();
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
using Elwig.Documents;
|
using Elwig.Documents;
|
||||||
using Elwig.Helpers.Export;
|
|
||||||
using Elwig.Helpers;
|
using Elwig.Helpers;
|
||||||
|
using Elwig.Helpers.Export;
|
||||||
using Elwig.Models.Dtos;
|
using Elwig.Models.Dtos;
|
||||||
using Elwig.Models.Entities;
|
using Elwig.Models.Entities;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System;
|
|
||||||
using Elwig.ViewModels;
|
using Elwig.ViewModels;
|
||||||
|
using iText.Commons.Internal.Runtime;
|
||||||
using LinqKit;
|
using LinqKit;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Elwig.Services {
|
namespace Elwig.Services {
|
||||||
public static class DeliveryService {
|
public static class DeliveryService {
|
||||||
@@ -35,8 +37,13 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
vm.SortId = "";
|
vm.SortId = "";
|
||||||
vm.GradationKmwString = "";
|
vm.GradationKmwString = "";
|
||||||
vm.WeightString = "";
|
|
||||||
|
vm.Weight = null;
|
||||||
|
vm.ActualTare = null;
|
||||||
|
vm.TargetTare = null;
|
||||||
|
vm.Tare = null;
|
||||||
vm.IsManualWeighing = false;
|
vm.IsManualWeighing = false;
|
||||||
|
|
||||||
vm.PartComment = "";
|
vm.PartComment = "";
|
||||||
vm.TemperatureString = "";
|
vm.TemperatureString = "";
|
||||||
vm.AcidString = "";
|
vm.AcidString = "";
|
||||||
@@ -51,7 +58,11 @@ namespace Elwig.Services {
|
|||||||
vm.WineKg = ControlUtils.GetItemFromSourceWithPk(vm.WineKgSource, p.KgNr) as AT_Kg;
|
vm.WineKg = ControlUtils.GetItemFromSourceWithPk(vm.WineKgSource, p.KgNr) as AT_Kg;
|
||||||
vm.WineRd = ControlUtils.GetItemFromSourceWithPk(vm.WineRdSource, p.KgNr, p.RdNr) as WbRd;
|
vm.WineRd = ControlUtils.GetItemFromSourceWithPk(vm.WineRdSource, p.KgNr, p.RdNr) as WbRd;
|
||||||
vm.WineOrigin = ControlUtils.GetItemFromSourceWithPk(vm.WineOriginSource, p.HkId) as WineOrigin;
|
vm.WineOrigin = ControlUtils.GetItemFromSourceWithPk(vm.WineOriginSource, p.HkId) as WineOrigin;
|
||||||
vm.WeightString = $"{p.Weight:N0}";
|
|
||||||
|
vm.Weight = p.Weight;
|
||||||
|
vm.ActualTare = p.WeighingInfo.Tare;
|
||||||
|
vm.TargetTare = vm.ActualTare + p.WeighingInfo.TareCorrection;
|
||||||
|
vm.Tare = vm.TargetTare ?? (vm.ActualTare is int t && t != 0 ? t : null);
|
||||||
vm.IsManualWeighing = p.IsManualWeighing;
|
vm.IsManualWeighing = p.IsManualWeighing;
|
||||||
vm.IsNetWeight = p.IsNetWeight;
|
vm.IsNetWeight = p.IsNetWeight;
|
||||||
|
|
||||||
@@ -72,6 +83,45 @@ namespace Elwig.Services {
|
|||||||
vm.ManualWeighingReason = p.WeighingReason;
|
vm.ManualWeighingReason = p.WeighingReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static (DateTime From, DateTime To)? GetFilterToday(DateTime today, IEnumerable<DateTime> timestamps) {
|
||||||
|
var filtered = timestamps.Where(t => t >= today.AddDays(-1) && t < today.AddDays(1)).Order().ToArray();
|
||||||
|
if (filtered.Length == 0) return null;
|
||||||
|
|
||||||
|
var latest = filtered.Last();
|
||||||
|
var since = filtered.Cast<DateTime>().Reverse().Aggregate(latest, (s, c) => s.Subtract(c).TotalHours <= 6 ? c : s);
|
||||||
|
latest += new TimeSpan(0, 1, -latest.Minute, -latest.Second, -latest.Millisecond, -latest.Microsecond);
|
||||||
|
since += new TimeSpan(0, 0, -since.Minute, -since.Second, -since.Millisecond, -since.Microsecond);
|
||||||
|
|
||||||
|
if (since.Subtract(today) <= new TimeSpan(-6, 0, 0) && latest.Subtract(today) < new TimeSpan(0, 0, 0))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return (since, latest);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<(Expression<Func<Delivery, bool>>, string)> GetFilterToday(AppDbContext ctx) {
|
||||||
|
var today = DateTime.Today;
|
||||||
|
var timestamps = (await ctx.Deliveries
|
||||||
|
.Where(d => d.DateString.CompareTo(today.AddDays(-1).ToString("yyyy-MM-dd")) >= 0)
|
||||||
|
.OrderBy(d => d.DateString).ThenBy(d => d.TimeString)
|
||||||
|
.Select(d => d.DateString + " " + d.TimeString)
|
||||||
|
.ToListAsync())
|
||||||
|
.Select(s => DateTime.TryParseExact(s, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt) ? (DateTime?)dt : null)
|
||||||
|
.Where(t => t.HasValue)
|
||||||
|
.Cast<DateTime>()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var res = GetFilterToday(today, timestamps);
|
||||||
|
if (!res.HasValue) {
|
||||||
|
return (_ => false, today.ToString("dd.MM.yyyy"));
|
||||||
|
} else {
|
||||||
|
var from = res.Value.From;
|
||||||
|
var to = res.Value.To;
|
||||||
|
return (d => (d.DateString == from.ToString("yyyy-MM-dd") && (d.TimeString == null || d.TimeString.CompareTo(from.ToString("HH:mm:ss")) >= 0)) ||
|
||||||
|
(d.DateString.CompareTo(from.ToString("yyyy-MM-dd")) > 0),
|
||||||
|
from.Date == to.Date ? from.ToString("dd.MM.yyyy") : $"{from:dd.MM.yyyy \\a\\b HH:mm} / {to:dd.MM.yyyy \\b\\i\\s HH:mm}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<(List<string>, IQueryable<Delivery>, IQueryable<DeliveryPart>, Predicate<DeliveryPart>, List<string>)> GetFilters(this DeliveryAdminViewModel vm, AppDbContext ctx) {
|
public static async Task<(List<string>, IQueryable<Delivery>, IQueryable<DeliveryPart>, Predicate<DeliveryPart>, List<string>)> GetFilters(this DeliveryAdminViewModel vm, AppDbContext ctx) {
|
||||||
List<string> filterNames = [];
|
List<string> filterNames = [];
|
||||||
IQueryable<Delivery> deliveryQuery = ctx.Deliveries;
|
IQueryable<Delivery> deliveryQuery = ctx.Deliveries;
|
||||||
@@ -84,10 +134,9 @@ namespace Elwig.Services {
|
|||||||
filterNames.Add(vm.FilterMember.AdministrativeName);
|
filterNames.Add(vm.FilterMember.AdministrativeName);
|
||||||
}
|
}
|
||||||
if (vm.FilterTodayOnly) {
|
if (vm.FilterTodayOnly) {
|
||||||
deliveryQuery = deliveryQuery
|
var (pred, name) = await GetFilterToday(ctx);
|
||||||
.Where(d => (d.DateString == Utils.Today.ToString("yyyy-MM-dd") && (d.TimeString == null || d.TimeString.CompareTo("03:00:00") > 0)) ||
|
deliveryQuery = deliveryQuery.Where(pred);
|
||||||
(d.DateString == Utils.Today.AddDays(1).ToString("yyyy-MM-dd") && (d.TimeString == null || d.TimeString.CompareTo("03:00:00") <= 0)));
|
filterNames.Add(name);
|
||||||
filterNames.Add(Utils.Today.ToString("dd.MM.yyyy"));
|
|
||||||
} else if (!vm.FilterAllSeasons) {
|
} else if (!vm.FilterAllSeasons) {
|
||||||
deliveryQuery = deliveryQuery.Where(d => d.Year == vm.FilterSeason);
|
deliveryQuery = deliveryQuery.Where(d => d.Year == vm.FilterSeason);
|
||||||
filterNames.Add($"{vm.FilterSeason}");
|
filterNames.Add($"{vm.FilterSeason}");
|
||||||
@@ -730,10 +779,9 @@ namespace Elwig.Services {
|
|||||||
query = q;
|
query = q;
|
||||||
filterNames.AddRange(f);
|
filterNames.AddRange(f);
|
||||||
} else if (subject == ExportSubject.FromToday) {
|
} else if (subject == ExportSubject.FromToday) {
|
||||||
var date = $"{Utils.Today:yyyy-MM-dd}";
|
var (pred, name) = await GetFilterToday(ctx);
|
||||||
query = ctx.DeliveryParts
|
query = ctx.Deliveries.Where(pred).SelectMany(d => d.Parts);
|
||||||
.Where(p => p.Delivery.DateString == date);
|
filterNames.Add(name);
|
||||||
filterNames.Add($"{Utils.Today:dd.MM.yyyy}");
|
|
||||||
} else if (subject == ExportSubject.FromSeasonAndBranch) {
|
} else if (subject == ExportSubject.FromSeasonAndBranch) {
|
||||||
query = ctx.DeliveryParts
|
query = ctx.DeliveryParts
|
||||||
.Where(p => p.Year == Utils.CurrentLastSeason && p.Delivery.ZwstId == App.ZwstId);
|
.Where(p => p.Year == Utils.CurrentLastSeason && p.Delivery.ZwstId == App.ZwstId);
|
||||||
@@ -805,10 +853,9 @@ namespace Elwig.Services {
|
|||||||
query = q;
|
query = q;
|
||||||
filterNames.AddRange(f);
|
filterNames.AddRange(f);
|
||||||
} else if (subject == ExportSubject.FromToday) {
|
} else if (subject == ExportSubject.FromToday) {
|
||||||
var date = $"{Utils.Today:yyyy-MM-dd}";
|
var (pred, name) = await GetFilterToday(ctx);
|
||||||
query = ctx.DeliveryParts
|
query = ctx.Deliveries.Where(pred).SelectMany(d => d.Parts);
|
||||||
.Where(p => p.Delivery.DateString == date);
|
filterNames.Add(name);
|
||||||
filterNames.Add($"{Utils.Today:dd.MM.yyyy}");
|
|
||||||
} else {
|
} else {
|
||||||
throw new ArgumentException("Invalid value for ExportSubject");
|
throw new ArgumentException("Invalid value for ExportSubject");
|
||||||
}
|
}
|
||||||
@@ -930,30 +977,40 @@ namespace Elwig.Services {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddWeightToolTipRow(Grid grid, int row, string? h1, string? h2, int weight, int? total1, int total2) {
|
private static void AddWeightToolTipRow(Grid grid, int row, string? h1, string? h2, string? h3, int weight, int? total1, int? total2, int total3, string? type) {
|
||||||
var bold = h2 == null;
|
var bold = h3 == null;
|
||||||
if (h1 != null) grid.AddToolTipCell(h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
var color = type == "R" ? Brushes.Firebrick : type == "W" ? Brushes.ForestGreen : null;
|
||||||
if (h2 != null) grid.AddToolTipCell(h2 + ":", row, 1, 1, bold);
|
if (h1 != null) grid.AddToolTipCell(h1 + ":", row, 0, (h2 == null) ? (h3 == null) ? 3 : 2 : 1, bold: bold, color: color);
|
||||||
grid.AddToolTipCell($"{weight:N0} kg", row, 2, bold: bold, alignRight: true);
|
if (h2 != null) grid.AddToolTipCell(h2 + ":", row, 1, (h3 == null) ? 2 : 1, bold: bold, color: color);
|
||||||
|
if (h3 != null) grid.AddToolTipCell(h3 + ":", row, 2, 1, bold: bold, color: color);
|
||||||
|
grid.AddToolTipCell($"{weight:N0} kg", row, 3, bold: bold, alignRight: true, color: color);
|
||||||
if (total1 != null && total1 != 0)
|
if (total1 != null && total1 != 0)
|
||||||
grid.AddToolTipCell($"{weight * 100.0 / total1:N1} %", row, 3, bold: bold, alignRight: true);
|
grid.AddToolTipCell($"{weight * 100.0 / total1:N1} %", row, 4, bold: bold, alignRight: true, color: color);
|
||||||
if (total2 != 0)
|
if (total2 != null && total2 != 0)
|
||||||
grid.AddToolTipCell($"{weight * 100.0 / total2:N1} %", row, 4, bold: bold, alignRight: true);
|
grid.AddToolTipCell($"{weight * 100.0 / total2:N1} %", row, 5, bold: bold, alignRight: true, color: color);
|
||||||
|
if (total3 != 0)
|
||||||
|
grid.AddToolTipCell($"{weight * 100.0 / total3:N1} %", row, 6, bold: bold, alignRight: true, color: color);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddGradationToolTipRow(Grid grid, int row, string? h1, string? h2, double min, double avg, double max) {
|
private static void AddGradationToolTipRow(Grid grid, int row, string? h1, string? h2, string? h3, double min, double avg, double max, string? type) {
|
||||||
var bold = h2 == null;
|
var bold = h3 == null;
|
||||||
if (h1 != null) grid.AddToolTipCell(h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
var color = type == "R" ? Brushes.Firebrick : type == "W" ? Brushes.ForestGreen : null;
|
||||||
if (h2 != null) grid.AddToolTipCell(h2 + ":", row, 1, bold: bold);
|
if (h1 != null) grid.AddToolTipCell(h1 + ":", row, 0, (h2 == null) ? (h3 == null) ? 3 : 2 : 1, bold: bold, color: color);
|
||||||
grid.AddToolTipCell($"{min:N1}°", row, 2, bold: bold, alignRight: true);
|
if (h2 != null) grid.AddToolTipCell(h2 + ":", row, 1, (h3 == null) ? 2 : 1, bold: bold, color: color);
|
||||||
grid.AddToolTipCell($"{avg:N1}°", row, 3, bold: bold, alignRight: true);
|
if (h3 != null) grid.AddToolTipCell(h3 + ":", row, 2, bold: bold, color: color);
|
||||||
grid.AddToolTipCell($"{max:N1}°", row, 4, bold: bold, alignRight: true);
|
grid.AddToolTipCell($"{min:N1}°", row, 3, bold: bold, alignRight: true, color: color);
|
||||||
|
grid.AddToolTipCell($"{avg:N1}°", row, 4, bold: bold, alignRight: true, color: color);
|
||||||
|
grid.AddToolTipCell($"{max:N1}°", row, 5, bold: bold, alignRight: true, color: color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<(string WeightText, (string?, string?, int, int?, int)[] WeightGrid, string GradationText, (string?, string?, double, double, double)[] GradationGrid)> GenerateToolTipData(IQueryable<DeliveryPart> deliveryParts) {
|
private static string? GetGroupName(params string?[] parts) {
|
||||||
var wGrid = new List<(string?, string?, int, int?, int)>();
|
return parts.All(p => p == null) ? null : string.Join(" / ", parts.Where(p => p != null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<(string WeightText, (string?, string?, string?, int, int?, int?, int, string?)[] WeightGrid, string GradationText, (string?, string?, string?, double, double, double, string?)[] GradationGrid)> GenerateToolTipData(IQueryable<DeliveryPart> deliveryParts) {
|
||||||
|
var wGrid = new List<(string?, string?, string?, int, int?, int?, int, string?)>();
|
||||||
var wText = "-";
|
var wText = "-";
|
||||||
var gGrid = new List<(string?, string?, double, double, double)>();
|
var gGrid = new List<(string?, string?, string?, double, double, double, string?)>();
|
||||||
var gText = "-";
|
var gText = "-";
|
||||||
|
|
||||||
var stat = (await deliveryParts.GroupBy(p => 0)
|
var stat = (await deliveryParts.GroupBy(p => 0)
|
||||||
@@ -968,11 +1025,11 @@ namespace Elwig.Services {
|
|||||||
.Single();
|
.Single();
|
||||||
|
|
||||||
wText = $"{stat.Weight:N0} kg";
|
wText = $"{stat.Weight:N0} kg";
|
||||||
wGrid.Add(("Menge", null, stat.Weight, null, stat.Weight));
|
wGrid.Add(("Menge", null, null, stat.Weight, null, null, stat.Weight, null));
|
||||||
|
|
||||||
if (stat.Min != null && stat.Max != null) {
|
if (stat.Min != null && stat.Max != null) {
|
||||||
gText = $"{stat.Min:N1}° / {stat.Avg:N1}° / {stat.Max:N1}°";
|
gText = $"{stat.Min:N1}° / {stat.Avg:N1}° / {stat.Max:N1}°";
|
||||||
gGrid.Add(("Gradation", null, stat.Min.Value, stat.Avg, stat.Max.Value));
|
gGrid.Add(("Gradation", null, null, stat.Min.Value, stat.Avg, stat.Max.Value, null));
|
||||||
|
|
||||||
var attrGroups = await deliveryParts
|
var attrGroups = await deliveryParts
|
||||||
.GroupBy(p => new { Attr = p.Attribute!.Name, Cult = p.Cultivation!.Name })
|
.GroupBy(p => new { Attr = p.Attribute!.Name, Cult = p.Cultivation!.Name })
|
||||||
@@ -989,9 +1046,10 @@ namespace Elwig.Services {
|
|||||||
.ThenBy(g => g.Cult)
|
.ThenBy(g => g.Cult)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
var sortGroups = await deliveryParts
|
var sortGroups = await deliveryParts
|
||||||
.GroupBy(p => p.SortId)
|
.GroupBy(p => new { p.SortId, p.Variety.Type })
|
||||||
.Select(g => new {
|
.Select(g => new {
|
||||||
SortId = g.Key,
|
g.Key.SortId,
|
||||||
|
g.Key.Type,
|
||||||
Weight = g.Sum(p => p.Weight),
|
Weight = g.Sum(p => p.Weight),
|
||||||
Min = g.Min(p => p.Kmw),
|
Min = g.Min(p => p.Kmw),
|
||||||
Avg = g.Sum(p => p.Kmw * p.Weight) / g.Sum(p => p.Weight),
|
Avg = g.Sum(p => p.Kmw * p.Weight) / g.Sum(p => p.Weight),
|
||||||
@@ -1004,11 +1062,13 @@ namespace Elwig.Services {
|
|||||||
.GroupBy(p => new {
|
.GroupBy(p => new {
|
||||||
Attr = p.Attribute!.Name,
|
Attr = p.Attribute!.Name,
|
||||||
Cult = p.Cultivation!.Name,
|
Cult = p.Cultivation!.Name,
|
||||||
|
p.Variety.Type,
|
||||||
p.SortId,
|
p.SortId,
|
||||||
})
|
})
|
||||||
.Select(g => new {
|
.Select(g => new {
|
||||||
g.Key.Attr,
|
g.Key.Attr,
|
||||||
g.Key.Cult,
|
g.Key.Cult,
|
||||||
|
g.Key.Type,
|
||||||
g.Key.SortId,
|
g.Key.SortId,
|
||||||
Weight = g.Sum(p => p.Weight),
|
Weight = g.Sum(p => p.Weight),
|
||||||
Min = g.Min(p => p.Kmw),
|
Min = g.Min(p => p.Kmw),
|
||||||
@@ -1018,27 +1078,62 @@ namespace Elwig.Services {
|
|||||||
.OrderByDescending(g => g.Weight)
|
.OrderByDescending(g => g.Weight)
|
||||||
.ThenBy(g => g.Attr)
|
.ThenBy(g => g.Attr)
|
||||||
.ThenBy(g => g.Cult)
|
.ThenBy(g => g.Cult)
|
||||||
|
.ThenBy(g => g.Type)
|
||||||
.ThenBy(g => g.SortId)
|
.ThenBy(g => g.SortId)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
foreach (var attrG in attrGroups) {
|
foreach (var attrG in attrGroups) {
|
||||||
var name = attrG.Attr == null && attrG.Cult == null ? null : attrG.Attr + (attrG.Attr != null && attrG.Cult != null ? " / " : "") + attrG.Cult;
|
var name = GetGroupName(attrG.Attr, attrG.Cult);
|
||||||
wGrid.Add((name, null, attrG.Weight, attrG.Weight, stat.Weight));
|
var typeGroups = groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult)
|
||||||
|
.GroupBy(g => g.Type)
|
||||||
|
.Select(g => new { Type = g.Key, Weight = g.Sum(p => p.Weight) })
|
||||||
|
.OrderByDescending(g => g.Weight).ThenBy(g => g.Type)
|
||||||
|
.ToList();
|
||||||
|
wGrid.Add((name, null, null, attrG.Weight, null, attrG.Weight, stat.Weight, typeGroups.Count == 1 ? typeGroups.First().Type : null));
|
||||||
|
if (typeGroups.Count == 1) {
|
||||||
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Weight).ThenBy(g => g.SortId)) {
|
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Weight).ThenBy(g => g.SortId)) {
|
||||||
wGrid.Add((null, g.SortId, g.Weight, attrG.Weight, stat.Weight));
|
wGrid.Add((null, null, g.SortId, g.Weight, null, attrG.Weight, stat.Weight, null));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach (var t in typeGroups) {
|
||||||
|
wGrid.Add((null, t.Type == "R" ? "Rot" : "Weiß", null, t.Weight, t.Weight, attrG.Weight, stat.Weight, t.Type));
|
||||||
|
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult && g.Type == t.Type).OrderByDescending(g => g.Weight).ThenBy(g => g.SortId)) {
|
||||||
|
wGrid.Add((null, null, g.SortId, g.Weight, t.Weight, attrG.Weight, stat.Weight, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (var attrG in attrGroups) {
|
foreach (var attrG in attrGroups) {
|
||||||
var name = attrG.Attr == null && attrG.Cult == null ? null : attrG.Attr + (attrG.Attr != null && attrG.Cult != null ? " / " : "") + attrG.Cult;
|
var name = GetGroupName(attrG.Attr, attrG.Cult);
|
||||||
gGrid.Add((name, null, attrG.Min, attrG.Avg, attrG.Max));
|
var typeGroups = groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult)
|
||||||
|
.GroupBy(g => g.Type)
|
||||||
|
.Select(g => new {
|
||||||
|
Type = g.Key,
|
||||||
|
Weight = g.Sum(p => p.Weight),
|
||||||
|
Min = g.Min(p => p.Min),
|
||||||
|
Avg = g.Sum(p => p.Avg * p.Weight) / g.Sum(p => p.Weight),
|
||||||
|
Max = g.Max(p => p.Max),
|
||||||
|
})
|
||||||
|
.OrderByDescending(g => g.Weight).ThenBy(g => g.Type)
|
||||||
|
.ToList();
|
||||||
|
gGrid.Add((name, null, null, attrG.Min, attrG.Avg, attrG.Max, typeGroups.Count == 1 ? typeGroups.First().Type : null));
|
||||||
|
if (typeGroups.Count == 1) {
|
||||||
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Avg).ThenBy(g => g.SortId)) {
|
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult).OrderByDescending(g => g.Avg).ThenBy(g => g.SortId)) {
|
||||||
gGrid.Add((null, g.SortId, g.Min, g.Avg, g.Max));
|
gGrid.Add((null, null, g.SortId, g.Min, g.Avg, g.Max, null));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach (var t in typeGroups) {
|
||||||
|
gGrid.Add((null, t.Type == "R" ? "Rot" : "Weiß", null, t.Min, t.Avg, t.Max, t.Type));
|
||||||
|
foreach (var g in groups.Where(g => g.Attr == attrG.Attr && g.Cult == attrG.Cult && g.Type == t.Type).OrderByDescending(g => g.Avg).ThenBy(g => g.SortId)) {
|
||||||
|
gGrid.Add((null, null, g.SortId, g.Min, g.Avg, g.Max, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrGroups.Count == 1) {
|
if (attrGroups.Count == 1) {
|
||||||
var g = attrGroups.First();
|
var g = attrGroups.First();
|
||||||
var name = g.Attr == null && g.Cult == null ? null : g.Attr + (g.Attr != null && g.Cult != null ? " / " : "") + g.Cult;
|
var name = GetGroupName(g.Attr, g.Cult);
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
wText += $" [{name}]";
|
wText += $" [{name}]";
|
||||||
gText += $" [{name}]";
|
gText += $" [{name}]";
|
||||||
@@ -1049,40 +1144,43 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else if (attrGroups.Count <= 4) {
|
} else if (attrGroups.Count <= 4) {
|
||||||
wText += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Weight:N0} kg ({(double)g.Weight / stat.Weight:0%})" + (g.Attr == null && g.Cult == null ? "" : $" [{g.Attr}{(g.Attr != null && g.Cult != null ? " / " : "")}{g.Cult}]")))}";
|
wText += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Weight:N0} kg ({(double)g.Weight / stat.Weight:0%})" + (GetGroupName(g.Attr, g.Cult) is string s ? $" [{s}]" : "")))}";
|
||||||
gText += $" = {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}]")))}";
|
gText += $" = {string.Join(" + ", attrGroups.Select(g => $"{g.Min:N1}/{g.Avg:N1}/{g.Max:N1}" + (GetGroupName(g.Attr, g.Cult) is string s ? $" [{s}]" : "")))}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (wText, wGrid.ToArray(), gText, gGrid.ToArray());
|
return (wText, wGrid.ToArray(), gText, gGrid.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (Grid WeightGrid, Grid GradationGrid) GenerateToolTip((string?, string?, int, int?, int)[] weightData, (string?, string?, double, double, double)[] gradationData) {
|
public static (Grid WeightGrid, Grid GradationGrid) GenerateToolTip((string?, string?, string?, int, int?, int?, int, string?)[] weightData, (string?, string?, string?, double, double, double, string?)[] gradationData) {
|
||||||
var wGrid = new Grid();
|
var wGrid = new Grid();
|
||||||
wGrid.ColumnDefinitions.Add(new() { Width = new(10) });
|
wGrid.ColumnDefinitions.Add(new() { Width = new(10) });
|
||||||
wGrid.ColumnDefinitions.Add(new() { Width = new(60) });
|
wGrid.ColumnDefinitions.Add(new() { Width = new(10) });
|
||||||
wGrid.ColumnDefinitions.Add(new() { Width = new(80) });
|
wGrid.ColumnDefinitions.Add(new() { Width = new(80) });
|
||||||
|
wGrid.ColumnDefinitions.Add(new() { Width = new(80) });
|
||||||
|
wGrid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||||
wGrid.ColumnDefinitions.Add(new() { Width = new(50) });
|
wGrid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||||
wGrid.ColumnDefinitions.Add(new() { Width = new(50) });
|
wGrid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||||
int rowNum = 0;
|
int rowNum = 0;
|
||||||
foreach (var row in weightData) {
|
foreach (var row in weightData) {
|
||||||
if (rowNum != 0 && row.Item2 == null) rowNum++;
|
if (rowNum != 0 && row.Item2 == null && row.Item3 == null) rowNum++;
|
||||||
AddWeightToolTipRow(wGrid, rowNum++, row.Item1, row.Item2, row.Item3, row.Item4, row.Item5);
|
AddWeightToolTipRow(wGrid, rowNum++, row.Item1, row.Item2, row.Item3, row.Item4, row.Item5, row.Item6, row.Item7, row.Item8);
|
||||||
}
|
}
|
||||||
|
|
||||||
var gGrid = new Grid();
|
var gGrid = new Grid();
|
||||||
gGrid.ColumnDefinitions.Add(new() { Width = new(10) });
|
gGrid.ColumnDefinitions.Add(new() { Width = new(10) });
|
||||||
gGrid.ColumnDefinitions.Add(new() { Width = new(60) });
|
gGrid.ColumnDefinitions.Add(new() { Width = new(10) });
|
||||||
|
gGrid.ColumnDefinitions.Add(new() { Width = new(80) });
|
||||||
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
||||||
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
||||||
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
||||||
gGrid.AddToolTipCell("Min.", 0, 2, alignCenter: true);
|
gGrid.AddToolTipCell("Min.", 0, 3, alignCenter: true);
|
||||||
gGrid.AddToolTipCell("⌀", 0, 3, alignCenter: true);
|
gGrid.AddToolTipCell("⌀", 0, 4, alignCenter: true);
|
||||||
gGrid.AddToolTipCell("Max.", 0, 4, alignCenter: true);
|
gGrid.AddToolTipCell("Max.", 0, 5, alignCenter: true);
|
||||||
rowNum = 1;
|
rowNum = 1;
|
||||||
foreach (var row in gradationData) {
|
foreach (var row in gradationData) {
|
||||||
if (rowNum != 1 && row.Item2 == null) rowNum++;
|
if (rowNum != 1 && row.Item2 == null && row.Item3 == null) rowNum++;
|
||||||
AddGradationToolTipRow(gGrid, rowNum++, row.Item1, row.Item2, row.Item3, row.Item4, row.Item5);
|
AddGradationToolTipRow(gGrid, rowNum++, row.Item1, row.Item2, row.Item3, row.Item4, row.Item5, row.Item6, row.Item7);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (wGrid, gGrid);
|
return (wGrid, gGrid);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -117,8 +118,35 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
public static void ShowException(string title, string? text, Exception exc, bool showExcType = false, bool isError = true) {
|
public static void ShowException(string title, string? text, Exception exc, bool showExcType = false, bool isError = true) {
|
||||||
text = text == null ? "" : text + (text.EndsWith('.') || text.EndsWith('!') || text.EndsWith('?') ? "" : ":") + "\n\n";
|
text = text == null ? "" : text + (text.EndsWith('.') || text.EndsWith('!') || text.EndsWith('?') ? "" : ":") + "\n\n";
|
||||||
|
if ((exc.InnerException ?? exc) is SqliteException sql) {
|
||||||
|
if (sql.SqliteErrorCode == 5 || sql.SqliteErrorCode == 6) {
|
||||||
|
// SQLITE_BUSY / SQLITE_LOCKED
|
||||||
|
text += "Die Datenbank wurde gerade von einem anderen Gerät/Prozess verwendet. Bitte noch einmal versuchen!\n\n" + sql.Message;
|
||||||
|
} else if (sql.SqliteErrorCode == 19) {
|
||||||
|
// SQLITE_CONSTRAINT
|
||||||
|
switch (sql.SqliteExtendedErrorCode) {
|
||||||
|
case 1555: // SQLITE_CONSTRAINT_PRIMARYKEY - indicating that a PRIMARY KEY constraint failed
|
||||||
|
case 2067: // SQLITE_CONSTRAINT_UNIQUE - indicating that a UNIQUE constraint failed
|
||||||
|
case 2579: // SQLITE_CONSTRAINT_ROWID - indicating that a rowid is not unique
|
||||||
|
text += "Dieser Datensatz existiert bereits!\n\n";
|
||||||
|
break;
|
||||||
|
case 787: // SQLITE_CONSTRAINT_FOREIGNKEY - indicating that a foreign key constraint failed
|
||||||
|
case 1299: // SQLITE_CONSTRAINT_NOTNULL - indicating that a NOT NULL constraint failed
|
||||||
|
case 275: // SQLITE_CONSTRAINT_CHECK - indicating that a CHECK constraint failed
|
||||||
|
case 1811: // SQLITE_CONSTRAINT_TRIGGER - indicating that a RAISE function within a trigger fired, causing the SQL statement to abort
|
||||||
|
case 531: // SQLITE_CONSTRAINT_COMMITHOOK - indicating that a commit hook callback returned non-zero that thus caused the SQL statement to be rolled back
|
||||||
|
text += "Der Datensatz ist inkonsistent!\n\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
text += sql.Message;
|
||||||
|
} else {
|
||||||
text += exc.Message + (showExcType ? $" ({exc.GetType().Name})" : "");
|
text += exc.Message + (showExcType ? $" ({exc.GetType().Name})" : "");
|
||||||
if (exc.InnerException != null) text += "\n\n" + exc.InnerException.Message;
|
if (exc.InnerException != null) text += "\n\n" + exc.InnerException.Message;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text += exc.Message + (showExcType ? $" ({exc.GetType().Name})" : "");
|
||||||
|
if (exc.InnerException != null) text += "\n\n" + exc.InnerException.Message;
|
||||||
|
}
|
||||||
if (isError) {
|
if (isError) {
|
||||||
ShowError(title, text);
|
ShowError(title, text);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Elwig.Models;
|
|||||||
using Elwig.Models.Entities;
|
using Elwig.Models.Entities;
|
||||||
using Elwig.ViewModels;
|
using Elwig.ViewModels;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
public static async Task InitInputs(this MemberBusinessSharesViewModel vm) {
|
public static async Task InitInputs(this MemberBusinessSharesViewModel vm) {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
vm.DateNoticeString = $"{Utils.Today:dd.MM.yyyy}";
|
vm.DateNoticeString = $"{DateTime.Today:dd.MM.yyyy}";
|
||||||
vm.ValuePerShare = (await ctx.Seasons.OrderBy(s => s.Year).LastOrDefaultAsync())?.BusinessShareValue;
|
vm.ValuePerShare = (await ctx.Seasons.OrderBy(s => s.Year).LastOrDefaultAsync())?.BusinessShareValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ namespace Elwig.Services {
|
|||||||
vm.DateEffective = h.DateEffective;
|
vm.DateEffective = h.DateEffective;
|
||||||
vm.Reason = h.Reason + (h.Reason == MemberHistory.REASON_TRANSFER ? $"_{(h.ToMgNr == mgnr ? "from" : "to")}" : "");
|
vm.Reason = h.Reason + (h.Reason == MemberHistory.REASON_TRANSFER ? $"_{(h.ToMgNr == mgnr ? "from" : "to")}" : "");
|
||||||
vm.Shares = h.Shares;
|
vm.Shares = h.Shares;
|
||||||
|
vm.CompanyHasSigned = h.CompanyHasSigned;
|
||||||
vm.MemberHasSigned = h.MemberHasSigned;
|
vm.MemberHasSigned = h.MemberHasSigned;
|
||||||
vm.ValuePerShare = h.ValuePerShare;
|
vm.ValuePerShare = h.ValuePerShare;
|
||||||
vm.OtherMgNr = h.FromMgNr != null && h.FromMgNr != mgnr ? h.FromMgNr : h.ToMgNr != null && h.ToMgNr != mgnr ? h.ToMgNr : null;
|
vm.OtherMgNr = h.FromMgNr != null && h.FromMgNr != mgnr ? h.FromMgNr : h.ToMgNr != null && h.ToMgNr != mgnr ? h.ToMgNr : null;
|
||||||
@@ -62,6 +64,7 @@ namespace Elwig.Services {
|
|||||||
Reason = vm.Reason?.Split("_")[0] ?? MemberHistory.REASON_CONVERT,
|
Reason = vm.Reason?.Split("_")[0] ?? MemberHistory.REASON_CONVERT,
|
||||||
Source = "manual",
|
Source = "manual",
|
||||||
Shares = vm.Shares ?? 0,
|
Shares = vm.Shares ?? 0,
|
||||||
|
CompanyHasSigned = vm.CompanyHasSigned,
|
||||||
MemberHasSigned = vm.MemberHasSigned,
|
MemberHasSigned = vm.MemberHasSigned,
|
||||||
ValuePerShare = vm.ValuePerShare,
|
ValuePerShare = vm.ValuePerShare,
|
||||||
CurrencyCode = vm.ValuePerShare != null ? "EUR" : null,
|
CurrencyCode = vm.ValuePerShare != null ? "EUR" : null,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Elwig.Services {
|
namespace Elwig.Services {
|
||||||
public static class MemberService {
|
public static class MemberService {
|
||||||
@@ -106,6 +107,8 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
vm.UstIdNr = m.UstIdNr;
|
vm.UstIdNr = m.UstIdNr;
|
||||||
vm.LfbisNr = m.LfbisNr;
|
vm.LfbisNr = m.LfbisNr;
|
||||||
|
vm.OrganicOperatorId = m.OrganicOperatorId;
|
||||||
|
vm.OrganicAuthorityCode = m.OrganicAuthorityCode;
|
||||||
vm.IsBuchführend = m.IsBuchführend;
|
vm.IsBuchführend = m.IsBuchführend;
|
||||||
vm.IsOrganic = m.IsOrganic;
|
vm.IsOrganic = m.IsOrganic;
|
||||||
|
|
||||||
@@ -187,10 +190,9 @@ namespace Elwig.Services {
|
|||||||
.GroupBy(d => d.Year)
|
.GroupBy(d => d.Year)
|
||||||
.ToDictionaryAsync(g => g.Key, g => g.Any());
|
.ToDictionaryAsync(g => g.Key, g => g.Any());
|
||||||
|
|
||||||
|
await App.MainDispatcher.BeginInvoke(() => {
|
||||||
if (m.MgNr != vm.MgNr)
|
if (m.MgNr != vm.MgNr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await App.MainDispatcher.BeginInvoke(() => {
|
|
||||||
var (d1Grid, _) = DeliveryService.GenerateToolTip(d1GridData, []);
|
var (d1Grid, _) = DeliveryService.GenerateToolTip(d1GridData, []);
|
||||||
var (d2Grid, _) = DeliveryService.GenerateToolTip(d2GridData, []);
|
var (d2Grid, _) = DeliveryService.GenerateToolTip(d2GridData, []);
|
||||||
var grid = AreaComService.GenerateToolTip(gridData);
|
var grid = AreaComService.GenerateToolTip(gridData);
|
||||||
@@ -203,13 +205,65 @@ namespace Elwig.Services {
|
|||||||
vm.StatusAreaCommitmentInfo = $"{Utils.CurrentLastSeason}";
|
vm.StatusAreaCommitmentInfo = $"{Utils.CurrentLastSeason}";
|
||||||
vm.StatusAreaCommitment = text;
|
vm.StatusAreaCommitment = text;
|
||||||
vm.StatusAreaCommitmentToolTip = grid;
|
vm.StatusAreaCommitmentToolTip = grid;
|
||||||
vm.MemberHasDeliveries = Enumerable.Range(0, 9999).Select(i => deliveries.GetValueOrDefault(i, false)).ToList();
|
vm.MemberHasDeliveries = [.. Enumerable.Range(0, 9999).Select(i => deliveries.GetValueOrDefault(i, false))];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
vm.OrganicTest1 = null;
|
||||||
|
vm.OrganicTest2 = "...";
|
||||||
|
vm.OrganicTest3 = Brushes.Black;
|
||||||
|
vm.OrganicTest4 = null;
|
||||||
|
Utils.RunBackground("Bio-Zertifikatsdaten laden", async () => {
|
||||||
|
if (App.MainDispatcher == null || !m.IsOrganic)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var certs = await OrganicService.GetTracesCertificates(m);
|
||||||
|
|
||||||
|
// TODO button for TRACES search url
|
||||||
|
// TODO button for authority search url
|
||||||
|
|
||||||
|
await App.MainDispatcher.BeginInvoke(() => {
|
||||||
|
if (m.MgNr != vm.MgNr)
|
||||||
|
return;
|
||||||
|
vm.OrganicTest2 = null;
|
||||||
|
if (certs.Length == 0) {
|
||||||
|
vm.OrganicTest1 = "Nicht gefunden";
|
||||||
|
vm.OrganicTest3 = Brushes.DarkRed;
|
||||||
|
} else {
|
||||||
|
var cert = certs[0];
|
||||||
|
vm.OrganicTest4 = $"Zertifikat-Nr.: {cert.Id}\nBio-KSt.: {cert.AuthorityCode}\nEU Operator-ID: {cert.OperatorId}\nOperator: {cert.OperatorName}";
|
||||||
|
if (cert.IsValidForWineProduction) {
|
||||||
|
vm.OrganicTest1 = "Gültig";
|
||||||
|
vm.OrganicTest2 = $" (bis {cert.ExpiresOn:dd.MM.yyyy})";
|
||||||
|
vm.OrganicTest3 = Brushes.DarkGreen;
|
||||||
|
} else if (cert.IsValid) {
|
||||||
|
vm.OrganicTest1 = "Teilw. gültig";
|
||||||
|
vm.OrganicTest2 = $" (bis {cert.ExpiresOn:dd.MM.yyyy})";
|
||||||
|
vm.OrganicTest3 = Brushes.OrangeRed;
|
||||||
|
} else {
|
||||||
|
vm.OrganicTest3 = Brushes.DarkRed;
|
||||||
|
switch (cert.Status) {
|
||||||
|
case OrganicService.TracesStatus.ISSUED:
|
||||||
|
vm.OrganicTest1 = "Ausgestellt";
|
||||||
|
vm.OrganicTest2 = $" (am {cert.LastStatusUpdateOn:dd.MM.yyyy})"; break;
|
||||||
|
case OrganicService.TracesStatus.SUSPENDED:
|
||||||
|
vm.OrganicTest1 = "Gesperrt";
|
||||||
|
vm.OrganicTest2 = $" (am {cert.LastStatusUpdateOn:dd.MM.yyyy})"; break;
|
||||||
|
case OrganicService.TracesStatus.EXPIRED:
|
||||||
|
vm.OrganicTest1 = "Ausgelaufen";
|
||||||
|
vm.OrganicTest2 = $" (am {cert.LastStatusUpdateOn:dd.MM.yyyy})"; break;
|
||||||
|
case OrganicService.TracesStatus.WITHDRAWN:
|
||||||
|
vm.OrganicTest1 = "Widerrufen";
|
||||||
|
vm.OrganicTest2 = $" (am {cert.LastStatusUpdateOn:dd.MM.yyyy})"; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
vm.MemberHasEmail = m.EmailAddresses.Count > 0;
|
vm.MemberHasEmail = m.EmailAddresses.Count > 0;
|
||||||
vm.MemberCanSendEmail = App.Config.Smtp != null && m.EmailAddresses.Count > 0;
|
vm.MemberCanSendEmail = App.Config.Smtp != null && m.EmailAddresses.Count > 0;
|
||||||
vm.MemberHasDeliveries = Enumerable.Range(0, 9999).Select(i => false).ToList();
|
vm.MemberHasDeliveries = [.. Enumerable.Range(0, 9999).Select(i => false)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<(List<string>, IQueryable<Member>, List<string>)> GetFilters(this MemberAdminViewModel vm, AppDbContext ctx) {
|
public static async Task<(List<string>, IQueryable<Member>, List<string>)> GetFilters(this MemberAdminViewModel vm, AppDbContext ctx) {
|
||||||
@@ -555,6 +609,8 @@ namespace Elwig.Services {
|
|||||||
|
|
||||||
UstIdNr = string.IsNullOrWhiteSpace(vm.UstIdNr) ? null : vm.UstIdNr,
|
UstIdNr = string.IsNullOrWhiteSpace(vm.UstIdNr) ? null : vm.UstIdNr,
|
||||||
LfbisNr = string.IsNullOrWhiteSpace(vm.LfbisNr) ? null : vm.LfbisNr,
|
LfbisNr = string.IsNullOrWhiteSpace(vm.LfbisNr) ? null : vm.LfbisNr,
|
||||||
|
OrganicOperatorId = string.IsNullOrWhiteSpace(vm.OrganicOperatorId) ? null : vm.OrganicOperatorId,
|
||||||
|
OrganicAuthorityCode = string.IsNullOrWhiteSpace(vm.OrganicAuthorityCode) ? null : vm.OrganicAuthorityCode,
|
||||||
IsBuchführend = vm.IsBuchführend,
|
IsBuchführend = vm.IsBuchführend,
|
||||||
IsOrganic = vm.IsOrganic,
|
IsOrganic = vm.IsOrganic,
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
using Elwig.Helpers;
|
||||||
|
using Elwig.Models.Entities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
namespace Elwig.Services {
|
||||||
|
public static class OrganicService {
|
||||||
|
|
||||||
|
public const string TRACES_API_URL = "https://webgate.ec.europa.eu/tracesnt/directory/publication/organic-operator/for/query";
|
||||||
|
public const string TRACES_PDF_URL_PREFIX = "https://webgate.ec.europa.eu/tracesnt/directory/publication/organic-operator/digitally-signed/";
|
||||||
|
|
||||||
|
public enum TracesStatus {
|
||||||
|
ISSUED, SUSPENDED, WITHDRAWN, EXPIRED
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TracesActivity {
|
||||||
|
PREPARATION, EXPORT, IMPORT, STORING, PRODUCTION, DISTRIBUTION, DISTRIBUTION_PLACING_ON_THE_MARKET
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TracesCategoryOfProduct {
|
||||||
|
UNPROCESSED_PLANT_PRODUCTS_INCLUDING_SEEDS, LIVESTOCK_AND_UNPROCESSED_LIVESTOCK_PRODUCTS, ALGAE_AND_UNPROCESSED_AQUACULTURE_PRODUCTS,
|
||||||
|
PROCESSED_AGRICULTURAL_PRODUCTS_INCLUDING_AQUACULTURE_FOR_USE_AS_FOOD, FEED, WINE, OTHER_PRODUCTS_NOT_COVERED_BY_PREVIOUS_CATEGORIES
|
||||||
|
}
|
||||||
|
|
||||||
|
public record TracesCertificate {
|
||||||
|
public required string Id { get; init; }
|
||||||
|
public required string AuthorityCode { get; init; }
|
||||||
|
public required string OperatorId { get; init; }
|
||||||
|
public required string OperatorName { get; init; }
|
||||||
|
public required TracesActivity[] Activities { get; init; }
|
||||||
|
public required TracesCategoryOfProduct[] CategoriesOfProduct { get; init; }
|
||||||
|
public required DateOnly IssuedOn { get; init; }
|
||||||
|
public required DateOnly ExpiresOn { get; init; }
|
||||||
|
public required DateOnly LastStatusUpdateOn { get; init; }
|
||||||
|
public required TracesStatus Status { get; init; }
|
||||||
|
|
||||||
|
public string PdfUrl => TRACES_PDF_URL_PREFIX + Id + ".pdf";
|
||||||
|
public bool IsValid => Status == TracesStatus.ISSUED && IssuedOn.ToDateTime(new()) <= DateTime.Today && ExpiresOn.ToDateTime(new()) >= DateTime.Today;
|
||||||
|
public bool IsValidForWineProduction => IsValid && Activities.Contains(TracesActivity.PRODUCTION) &&
|
||||||
|
(CategoriesOfProduct.Contains(TracesCategoryOfProduct.UNPROCESSED_PLANT_PRODUCTS_INCLUDING_SEEDS) || CategoriesOfProduct.Contains(TracesCategoryOfProduct.WINE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async static Task<TracesCertificate[]> GetTracesCertificates(Member m, bool? tryNameAndAddress = null) {
|
||||||
|
// TODO cache
|
||||||
|
return await FetchTracesCertificates(m, tryNameAndAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async static Task<JsonArray> TryFetchTracesCertificates(Dictionary<string, string> query) {
|
||||||
|
var q = HttpUtility.ParseQueryString("");
|
||||||
|
q.Add("sort", "-issuedOn");
|
||||||
|
q.Add("countryCode", "AT");
|
||||||
|
foreach (var (k, v) in query) {
|
||||||
|
q.Add(k, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
using var client = Utils.GetHttpClient();
|
||||||
|
using var res = await client.GetAsync($"{TRACES_API_URL}?{q}");
|
||||||
|
res.EnsureSuccessStatusCode();
|
||||||
|
var resJson = JsonNode.Parse(await res.Content.ReadAsStringAsync());
|
||||||
|
var certs = resJson?.AsArray() ?? throw new Exception();
|
||||||
|
if (certs.Count == 0)
|
||||||
|
throw new Exception();
|
||||||
|
return certs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<TracesCertificate[]> FetchTracesCertificates(Member m, bool? tryNameAndAddress = null) {
|
||||||
|
return FetchTracesCertificates(m.OrganicOperatorId, m.LfbisNr,
|
||||||
|
(tryNameAndAddress ?? m.IsOrganic) ? m.BillingAddress is BillingAddr a ?
|
||||||
|
(a.FullName, a.Address, $"{a.PostalDest.AtPlz?.Plz}") :
|
||||||
|
(m.FullName, m.Address, $"{m.PostalDest.AtPlz?.Plz}") :
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async static Task<TracesCertificate[]> FetchTracesCertificates(string? oocId, string? lfbisNr, (string Name, string Address, string PostalCode)? address) {
|
||||||
|
bool searchedByName = false;
|
||||||
|
|
||||||
|
JsonArray? jsonCerts = null;
|
||||||
|
if (oocId != null) {
|
||||||
|
try {
|
||||||
|
jsonCerts = await TryFetchTracesCertificates(new Dictionary<string, string> {
|
||||||
|
{ "operatorIdentifierType", "ooc_identifier" },
|
||||||
|
{ "operatorIdentifierSearchOperator", "STRICT" },
|
||||||
|
{ "operatorIdentifier", oocId },
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
jsonCerts = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonCerts == null && lfbisNr != null) {
|
||||||
|
try {
|
||||||
|
jsonCerts = await TryFetchTracesCertificates(new Dictionary<string, string> {
|
||||||
|
{ "operatorIdentifierType", "comp_reg" },
|
||||||
|
{ "operatorIdentifierSearchOperator", "STRICT" },
|
||||||
|
{ "operatorIdentifier", lfbisNr.TrimStart('0') },
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
jsonCerts = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonCerts == null && address != null) {
|
||||||
|
try {
|
||||||
|
jsonCerts = await TryFetchTracesCertificates(new Dictionary<string, string> {
|
||||||
|
{ "operatorPostalCode", address.Value.PostalCode },
|
||||||
|
{ "query", $"{address.Value.Name} {address.Value.Address}" },
|
||||||
|
});
|
||||||
|
searchedByName = true;
|
||||||
|
} catch {
|
||||||
|
jsonCerts = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonCerts == null)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
TracesCertificate[] certs = [];
|
||||||
|
try {
|
||||||
|
certs = [.. jsonCerts.Select(j => new TracesCertificate {
|
||||||
|
Id = j!["reference"]?.GetValue<string>() ?? throw new Exception(),
|
||||||
|
AuthorityCode = j["issuingBody"]?["code"]?.GetValue<string>() ?? throw new Exception(),
|
||||||
|
OperatorId = j["operatorIdentifier"]?.GetValue<string>() ?? throw new Exception(),
|
||||||
|
OperatorName = j["operator"]?["name"]?.GetValue<string>() ?? throw new Exception(),
|
||||||
|
Activities = [.. j["activities"]?.AsArray().Select(a => Enum.Parse<TracesActivity>(a?["id"]?.GetValue<string>().ToUpper().Replace("_IMPORT", "IMPORT") ?? throw new Exception())) ?? []],
|
||||||
|
CategoriesOfProduct = [.. j["categoriesOfProduct"]?.AsArray().Select(c => Enum.Parse<TracesCategoryOfProduct>(c?["id"]?.GetValue<string>() ?? throw new Exception())) ?? []],
|
||||||
|
IssuedOn = DateOnly.FromDateTime(DateTime.ParseExact(j["issuedOn"]?.GetValue<string>() ?? throw new Exception(), "yyyy-MM-ddTHH:mm:ss.fffK", CultureInfo.InvariantCulture, DateTimeStyles.None)),
|
||||||
|
ExpiresOn = DateOnly.ParseExact(j["expiresOn"]?.GetValue<string>() ?? throw new Exception(), "yyyy-MM-dd"),
|
||||||
|
LastStatusUpdateOn = DateOnly.FromDateTime(DateTime.ParseExact(j["lastStatusUpdateDateTime"]?.GetValue<string>() ?? throw new Exception(), "yyyy-MM-ddTHH:mm:ss.fffK", CultureInfo.InvariantCulture, DateTimeStyles.None)),
|
||||||
|
Status = Enum.Parse<TracesStatus>(j["status"]?["id"]?.GetValue<string>() ?? throw new Exception()),
|
||||||
|
})];
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (!searchedByName || certs.Where(c => c.Status == TracesStatus.ISSUED).Select(c => c.OperatorId).ToHashSet().Count == 1) ? certs : [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -120,6 +120,14 @@ namespace Elwig.ViewModels {
|
|||||||
set => WeightString = $"{value:N0}";
|
set => WeightString = $"{value:N0}";
|
||||||
}
|
}
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
private string? _tareString = "-";
|
||||||
|
public int? Tare {
|
||||||
|
get => int.TryParse(TareString?.Replace(Utils.GroupSeparator, "").Replace(" kg", ""), out var w) ? w : null;
|
||||||
|
set => TareString = value == null ? "-" : $"{value:N0} kg{(TargetTare != null ? "*" : "")}";
|
||||||
|
}
|
||||||
|
public int? ActualTare;
|
||||||
|
public int? TargetTare;
|
||||||
|
[ObservableProperty]
|
||||||
private bool _isManualWeighing;
|
private bool _isManualWeighing;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool? _isNetWeightValue = false;
|
private bool? _isNetWeightValue = false;
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ using System.Windows.Controls;
|
|||||||
namespace Elwig.ViewModels {
|
namespace Elwig.ViewModels {
|
||||||
public partial class DeliveryAncmtAdminViewModel : ObservableObject {
|
public partial class DeliveryAncmtAdminViewModel : ObservableObject {
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _title = "Anmeldungen - Elwig";
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string? _searchQuery = "";
|
private string? _searchQuery = "";
|
||||||
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []];
|
public List<string> TextFilter => [.. SearchQuery?.ToLower().Split(' ').ToList().FindAll(e => e.Length > 0) ?? []];
|
||||||
|
|||||||
@@ -6,11 +6,14 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Documents;
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Elwig.ViewModels {
|
namespace Elwig.ViewModels {
|
||||||
public partial class MemberAdminViewModel : ObservableObject {
|
public partial class MemberAdminViewModel : ObservableObject {
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _title = "Mitglieder - Elwig";
|
||||||
|
|
||||||
public int? TransferPredecessorAreaComs = null;
|
public int? TransferPredecessorAreaComs = null;
|
||||||
public int? CancelAreaComs = null;
|
public int? CancelAreaComs = null;
|
||||||
|
|
||||||
@@ -116,10 +119,23 @@ namespace Elwig.ViewModels {
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string? _lfbisNr;
|
private string? _lfbisNr;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
private string? _organicOperatorId;
|
||||||
|
[ObservableProperty]
|
||||||
|
private string? _organicAuthorityCode;
|
||||||
|
[ObservableProperty]
|
||||||
private bool _isBuchführend;
|
private bool _isBuchführend;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _isOrganic;
|
private bool _isOrganic;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string? _organicTest1;
|
||||||
|
[ObservableProperty]
|
||||||
|
private string? _organicTest2;
|
||||||
|
[ObservableProperty]
|
||||||
|
private Brush? _organicTest3;
|
||||||
|
[ObservableProperty]
|
||||||
|
private string? _organicTest4;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string? _entryDate;
|
private string? _entryDate;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ namespace Elwig.ViewModels {
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _deduct;
|
private bool _deduct;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
|
private bool _companyHasSigned;
|
||||||
|
[ObservableProperty]
|
||||||
private bool _memberHasSigned;
|
private bool _memberHasSigned;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string? _valuePerShareString;
|
private string? _valuePerShareString;
|
||||||
|
|||||||
@@ -576,6 +576,14 @@ namespace Elwig.Windows {
|
|||||||
InputLostFocus((TextBox)sender, Validator.CheckLfbisNr);
|
InputLostFocus((TextBox)sender, Validator.CheckLfbisNr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void OrganicOperatorIdInput_TextChanged(object sender, TextChangedEventArgs? evt) {
|
||||||
|
InputTextChanged((TextBox)sender, Validator.CheckOrganicOperatorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OrganicOperatorIdInput_LostFocus(object sender, RoutedEventArgs? evt) {
|
||||||
|
InputLostFocus((TextBox)sender, Validator.CheckOrganicOperatorId);
|
||||||
|
}
|
||||||
|
|
||||||
protected void OrganicAuthorityCodeInput_TextChanged(object sender, TextChangedEventArgs? evt) {
|
protected void OrganicAuthorityCodeInput_TextChanged(object sender, TextChangedEventArgs? evt) {
|
||||||
InputTextChanged((TextBox)sender, Validator.CheckOrganicAuthorityCode);
|
InputTextChanged((TextBox)sender, Validator.CheckOrganicAuthorityCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ namespace Elwig.Windows {
|
|||||||
CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput));
|
CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput));
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
ViewModel.FilterMember = ctx.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
ViewModel.FilterMember = ctx.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
||||||
ViewModel.Title = $"Flächenbindungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
|
||||||
ExemptInputs = [
|
ExemptInputs = [
|
||||||
AreaCommitmentList, RevisionList,
|
AreaCommitmentList, RevisionList,
|
||||||
NewAreaCommitmentButton, EditAreaCommitmentButton, DeleteAreaCommitmentButton, SaveButton,
|
NewAreaCommitmentButton, EditAreaCommitmentButton, DeleteAreaCommitmentButton, SaveButton,
|
||||||
@@ -51,9 +50,9 @@ namespace Elwig.Windows {
|
|||||||
var cursor = Mouse.OverrideCursor != null;
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
var query = (vm.SearchQuery, vm.FilterSeason);
|
var query = (vm.SearchQuery, vm.FilterSeason);
|
||||||
var (filter, contracts, areaComs, areaComCount, stat) = await Task.Run(async () => {
|
var (filterNames, filter, contracts, areaComs, areaComCount, stat) = await Task.Run(async () => {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var (_, contractQuery, areaComQuery, filter) = await vm.GetFilters(ctx);
|
var (filterNames, contractQuery, areaComQuery, filter) = await vm.GetFilters(ctx);
|
||||||
var contracts = await contractQuery
|
var contracts = await contractQuery
|
||||||
.Include(c => c.Revisions).ThenInclude(a => a.Member)
|
.Include(c => c.Revisions).ThenInclude(a => a.Member)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
@@ -73,11 +72,12 @@ namespace Elwig.Windows {
|
|||||||
var season = await ctx.FetchSeasons().FirstOrDefaultAsync();
|
var season = await ctx.FetchSeasons().FirstOrDefaultAsync();
|
||||||
var stat = await AreaComService.GenerateToolTipData(areaComQuery, season?.MaxKgPerHa ?? 10_000);
|
var stat = await AreaComService.GenerateToolTipData(areaComQuery, season?.MaxKgPerHa ?? 10_000);
|
||||||
|
|
||||||
return (filter, contracts, areaComs, areaComCount, stat);
|
return (filterNames, filter, contracts, areaComs, areaComCount, stat);
|
||||||
});
|
});
|
||||||
if (!cursor) Mouse.OverrideCursor = null;
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason)) return;
|
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason)) return;
|
||||||
|
|
||||||
|
ViewModel.Title = Utils.GetTitle("Flächenbindungen", filterNames, filter);
|
||||||
ControlUtils.RenewItemsSource(AreaCommitmentList, contracts,
|
ControlUtils.RenewItemsSource(AreaCommitmentList, contracts,
|
||||||
AreaCommitmentList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
AreaCommitmentList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
RefreshInputs();
|
RefreshInputs();
|
||||||
@@ -164,7 +164,6 @@ namespace Elwig.Windows {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ViewModel.FilterMember = m;
|
ViewModel.FilterMember = m;
|
||||||
ViewModel.Title = $"Flächenbindungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
|
||||||
|
|
||||||
ControlUtils.RenewItemsSource(KgInput, await ctx.WbKgs
|
ControlUtils.RenewItemsSource(KgInput, await ctx.WbKgs
|
||||||
.Include(k => k.AtKg.WbKg!.Rds)
|
.Include(k => k.AtKg.WbKg!.Rds)
|
||||||
|
|||||||
@@ -121,12 +121,18 @@
|
|||||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="3" Margin="0,130,10,10" Width="64"
|
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="3" Margin="0,130,10,10" Width="64"
|
||||||
TextChanged="LfbisNrInput_TextChanged" LostFocus="LfbisNrInput_LostFocus"/>
|
TextChanged="LfbisNrInput_TextChanged" LostFocus="LfbisNrInput_LostFocus"/>
|
||||||
|
|
||||||
<Label Content="Bio-Kontrollstelle:"
|
<Label Content="Bio-KSt.:" ToolTip="Bio-Konstrollstelle"
|
||||||
VerticalAlignment="Top" HorizontalAlignment="Right" Grid.Column="3" Margin="10,130,110,10"/>
|
VerticalAlignment="Top" HorizontalAlignment="Right" Grid.Column="3" Margin="10,100,110,10"/>
|
||||||
<TextBox x:Name="ClientOrganicAuthorityInput"
|
<TextBox x:Name="ClientOrganicAuthorityCodeInput"
|
||||||
VerticalAlignment="Top" HorizontalAlignment="Right" Grid.Column="3" Margin="10,130,10,10" Width="90"
|
VerticalAlignment="Top" HorizontalAlignment="Right" Grid.Column="3" Margin="10,100,10,10" Width="82"
|
||||||
TextChanged="OrganicAuthorityCodeInput_TextChanged" LostFocus="OrganicAuthorityCodeInput_LostFocus"/>
|
TextChanged="OrganicAuthorityCodeInput_TextChanged" LostFocus="OrganicAuthorityCodeInput_LostFocus"/>
|
||||||
|
|
||||||
|
<Label Content="OOC-ID:" ToolTip="Bio-EU-Operator-ID / Organic Operator Certificate ID"
|
||||||
|
VerticalAlignment="Top" HorizontalAlignment="Right" Grid.Column="3" Margin="10,130,110,10"/>
|
||||||
|
<TextBox x:Name="ClientOrganicOperatorIdInput"
|
||||||
|
VerticalAlignment="Top" HorizontalAlignment="Right" Grid.Column="3" Margin="10,130,10,10" Width="91"
|
||||||
|
TextChanged="OrganicOperatorIdInput_TextChanged" LostFocus="OrganicOperatorIdInput_LostFocus"/>
|
||||||
|
|
||||||
<Label Content="Telefon-Nr.:"
|
<Label Content="Telefon-Nr.:"
|
||||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="2" Margin="10,160,0,10"/>
|
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="2" Margin="10,160,0,10"/>
|
||||||
<TextBox x:Name="ClientPhoneNrInput" Margin="0,160,10,10" Grid.Column="3"
|
<TextBox x:Name="ClientPhoneNrInput" Margin="0,160,10,10" Grid.Column="3"
|
||||||
@@ -320,6 +326,10 @@
|
|||||||
<Label Content="Beschreibung:" Margin="10,70,0,10"/>
|
<Label Content="Beschreibung:" Margin="10,70,0,10"/>
|
||||||
<TextBox x:Name="WineCultivationDescriptionInput" Grid.Column="1" Margin="0,70,10,10"
|
<TextBox x:Name="WineCultivationDescriptionInput" Grid.Column="1" Margin="0,70,10,10"
|
||||||
TextChanged="WineCultivation_Changed"/>
|
TextChanged="WineCultivation_Changed"/>
|
||||||
|
|
||||||
|
<CheckBox x:Name="WineCultivationOrganicInput" Content="Bio" Grid.Column="1" Margin="0,105,10,10"
|
||||||
|
Checked="WineCultivation_Changed" Unchecked="WineCultivation_Changed"
|
||||||
|
HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|||||||
@@ -72,10 +72,12 @@ namespace Elwig.Windows {
|
|||||||
WineCultivationIdInput.Text = "";
|
WineCultivationIdInput.Text = "";
|
||||||
WineCultivationNameInput.Text = "";
|
WineCultivationNameInput.Text = "";
|
||||||
WineCultivationDescriptionInput.Text = "";
|
WineCultivationDescriptionInput.Text = "";
|
||||||
|
WineCultivationOrganicInput.IsChecked = false;
|
||||||
} else {
|
} else {
|
||||||
WineCultivationIdInput.Text = cult.CultId;
|
WineCultivationIdInput.Text = cult.CultId;
|
||||||
WineCultivationNameInput.Text = cult.Name;
|
WineCultivationNameInput.Text = cult.Name;
|
||||||
WineCultivationDescriptionInput.Text = cult.Description;
|
WineCultivationDescriptionInput.Text = cult.Description;
|
||||||
|
WineCultivationOrganicInput.IsChecked = cult.IsOrganic;
|
||||||
}
|
}
|
||||||
_cultUpdate = false;
|
_cultUpdate = false;
|
||||||
}
|
}
|
||||||
@@ -105,7 +107,8 @@ namespace Elwig.Windows {
|
|||||||
_cultChanged = _cultChanged ||
|
_cultChanged = _cultChanged ||
|
||||||
WineCultivationIdInput.Text != cult.CultId ||
|
WineCultivationIdInput.Text != cult.CultId ||
|
||||||
WineCultivationNameInput.Text != cult.Name ||
|
WineCultivationNameInput.Text != cult.Name ||
|
||||||
WineCultivationDescriptionInput.Text != (cult.Description ?? "");
|
WineCultivationDescriptionInput.Text != (cult.Description ?? "") ||
|
||||||
|
WineCultivationOrganicInput.IsChecked != cult.IsOrganic;
|
||||||
|
|
||||||
var old = _cultIds.GetValueOrDefault(cult);
|
var old = _cultIds.GetValueOrDefault(cult);
|
||||||
var id = WineCultivationIdInput.Text ?? "";
|
var id = WineCultivationIdInput.Text ?? "";
|
||||||
@@ -113,7 +116,8 @@ namespace Elwig.Windows {
|
|||||||
cult.CultId = id;
|
cult.CultId = id;
|
||||||
cult.Name = WineCultivationNameInput.Text ?? "";
|
cult.Name = WineCultivationNameInput.Text ?? "";
|
||||||
cult.Description = WineCultivationDescriptionInput.Text ?? "";
|
cult.Description = WineCultivationDescriptionInput.Text ?? "";
|
||||||
if (cult.Description.Length == 0) cult.Description = null;
|
cult.IsOrganic = WineCultivationOrganicInput.IsChecked ?? false;
|
||||||
|
if (string.IsNullOrWhiteSpace(cult.Description)) cult.Description = null;
|
||||||
|
|
||||||
CollectionViewSource.GetDefaultView(_cultList).Refresh();
|
CollectionViewSource.GetDefaultView(_cultList).Refresh();
|
||||||
UpdateButtons();
|
UpdateButtons();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Elwig.Windows {
|
|||||||
BranchAddressInput, BranchPhoneNrInput, BranchFaxNrInput, BranchMobileNrInput,
|
BranchAddressInput, BranchPhoneNrInput, BranchFaxNrInput, BranchMobileNrInput,
|
||||||
WineAttributeIdInput, WineAttributeNameInput, WineAttributeActiveInput,
|
WineAttributeIdInput, WineAttributeNameInput, WineAttributeActiveInput,
|
||||||
WineAttributeMaxKgPerHaInput, WineAttributeStrictInput, WineAttributeFillLowerInput,
|
WineAttributeMaxKgPerHaInput, WineAttributeStrictInput, WineAttributeFillLowerInput,
|
||||||
WineCultivationIdInput, WineCultivationNameInput, WineCultivationDescriptionInput,
|
WineCultivationIdInput, WineCultivationNameInput, WineCultivationDescriptionInput, WineCultivationOrganicInput,
|
||||||
AreaCommitmentTypeIdInput, AreaCommitmentTypeWineVariantInput, AreaCommitmentTypeWineAttributeInput,
|
AreaCommitmentTypeIdInput, AreaCommitmentTypeWineVariantInput, AreaCommitmentTypeWineAttributeInput,
|
||||||
AreaCommitmentTypeMinKgPerHaInput, AreaCommitmentTypePenaltyPerKgInput,
|
AreaCommitmentTypeMinKgPerHaInput, AreaCommitmentTypePenaltyPerKgInput,
|
||||||
AreaCommitmentTypePenaltyInput, AreaCommitmentTypePenaltyNoneInput,
|
AreaCommitmentTypePenaltyInput, AreaCommitmentTypePenaltyNoneInput,
|
||||||
@@ -67,6 +67,7 @@ namespace Elwig.Windows {
|
|||||||
WineCultivationIdInput.IsReadOnly = true;
|
WineCultivationIdInput.IsReadOnly = true;
|
||||||
WineCultivationNameInput.IsReadOnly = true;
|
WineCultivationNameInput.IsReadOnly = true;
|
||||||
WineCultivationDescriptionInput.IsReadOnly = true;
|
WineCultivationDescriptionInput.IsReadOnly = true;
|
||||||
|
WineCultivationOrganicInput.IsEnabled = false;
|
||||||
|
|
||||||
AreaCommitmentTypeWineVariantInput.IsEnabled = false;
|
AreaCommitmentTypeWineVariantInput.IsEnabled = false;
|
||||||
AreaCommitmentTypeWineAttributeInput.IsEnabled = false;
|
AreaCommitmentTypeWineAttributeInput.IsEnabled = false;
|
||||||
@@ -115,6 +116,7 @@ namespace Elwig.Windows {
|
|||||||
WineCultivationIdInput.IsReadOnly = false;
|
WineCultivationIdInput.IsReadOnly = false;
|
||||||
WineCultivationNameInput.IsReadOnly = false;
|
WineCultivationNameInput.IsReadOnly = false;
|
||||||
WineCultivationDescriptionInput.IsReadOnly = false;
|
WineCultivationDescriptionInput.IsReadOnly = false;
|
||||||
|
WineCultivationOrganicInput.IsEnabled = true;
|
||||||
|
|
||||||
AreaCommitmentTypeWineVariantInput.IsEnabled = true;
|
AreaCommitmentTypeWineVariantInput.IsEnabled = true;
|
||||||
AreaCommitmentTypeWineAttributeInput.IsEnabled = true;
|
AreaCommitmentTypeWineAttributeInput.IsEnabled = true;
|
||||||
@@ -329,7 +331,8 @@ namespace Elwig.Windows {
|
|||||||
ClientBicInput.Text = p.Bic;
|
ClientBicInput.Text = p.Bic;
|
||||||
ClientUstIdNrInput.Text = p.UstIdNr;
|
ClientUstIdNrInput.Text = p.UstIdNr;
|
||||||
ClientLfbisNrInput.Text = p.LfbisNr;
|
ClientLfbisNrInput.Text = p.LfbisNr;
|
||||||
ClientOrganicAuthorityInput.Text = p.OrganicAuthority;
|
ClientOrganicOperatorIdInput.Text = p.OrganicOperatorId;
|
||||||
|
ClientOrganicAuthorityCodeInput.Text = p.OrganicAuthorityCode;
|
||||||
ClientPhoneNrInput.Text = p.PhoneNr;
|
ClientPhoneNrInput.Text = p.PhoneNr;
|
||||||
ClientFaxNrInput.Text = p.FaxNr;
|
ClientFaxNrInput.Text = p.FaxNr;
|
||||||
ClientEmailAddressInput.Text = p.EmailAddress;
|
ClientEmailAddressInput.Text = p.EmailAddress;
|
||||||
@@ -369,7 +372,8 @@ namespace Elwig.Windows {
|
|||||||
p.Bic = string.IsNullOrWhiteSpace(ClientBicInput.Text) ? null : ClientBicInput.Text;
|
p.Bic = string.IsNullOrWhiteSpace(ClientBicInput.Text) ? null : ClientBicInput.Text;
|
||||||
p.UstIdNr = string.IsNullOrWhiteSpace(ClientUstIdNrInput.Text) ? null : ClientUstIdNrInput.Text;
|
p.UstIdNr = string.IsNullOrWhiteSpace(ClientUstIdNrInput.Text) ? null : ClientUstIdNrInput.Text;
|
||||||
p.LfbisNr = string.IsNullOrWhiteSpace(ClientLfbisNrInput.Text) ? null : ClientLfbisNrInput.Text;
|
p.LfbisNr = string.IsNullOrWhiteSpace(ClientLfbisNrInput.Text) ? null : ClientLfbisNrInput.Text;
|
||||||
p.OrganicAuthority = string.IsNullOrWhiteSpace(ClientOrganicAuthorityInput.Text) ? null : ClientOrganicAuthorityInput.Text;
|
p.OrganicOperatorId = string.IsNullOrWhiteSpace(ClientOrganicOperatorIdInput.Text) ? null : ClientOrganicOperatorIdInput.Text;
|
||||||
|
p.OrganicAuthorityCode = string.IsNullOrWhiteSpace(ClientOrganicAuthorityCodeInput.Text) ? null : ClientOrganicAuthorityCodeInput.Text;
|
||||||
p.PhoneNr = string.IsNullOrWhiteSpace(ClientPhoneNrInput.Text) ? null : ClientPhoneNrInput.Text;
|
p.PhoneNr = string.IsNullOrWhiteSpace(ClientPhoneNrInput.Text) ? null : ClientPhoneNrInput.Text;
|
||||||
p.FaxNr = string.IsNullOrWhiteSpace(ClientFaxNrInput.Text) ? null : ClientFaxNrInput.Text;
|
p.FaxNr = string.IsNullOrWhiteSpace(ClientFaxNrInput.Text) ? null : ClientFaxNrInput.Text;
|
||||||
p.EmailAddress = string.IsNullOrWhiteSpace(ClientEmailAddressInput.Text) ? null : ClientEmailAddressInput.Text;
|
p.EmailAddress = string.IsNullOrWhiteSpace(ClientEmailAddressInput.Text) ? null : ClientEmailAddressInput.Text;
|
||||||
|
|||||||
@@ -398,7 +398,8 @@
|
|||||||
<Grid Grid.Row="1" Grid.Column="2">
|
<Grid Grid.Row="1" Grid.Column="2">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="0.625*"/>
|
<RowDefinition Height="0.625*"/>
|
||||||
<RowDefinition Height="0.875*"/>
|
<RowDefinition Height="0.8125*"/>
|
||||||
|
<RowDefinition Height="0.0625*"/>
|
||||||
<RowDefinition Height="0.875*"/>
|
<RowDefinition Height="0.875*"/>
|
||||||
<RowDefinition Height="0.25*"/>
|
<RowDefinition Height="0.25*"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
@@ -434,7 +435,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
|
||||||
<GroupBox Header="Lieferung" Grid.Column="0" Grid.Row="1" Grid.RowSpan="3" Margin="5,5,5,5">
|
<GroupBox Header="Lieferung" Grid.Column="0" Grid.Row="1" Grid.RowSpan="4" Margin="5,5,5,5">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="100"/>
|
<ColumnDefinition Width="100"/>
|
||||||
@@ -553,7 +554,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
|
||||||
<GroupBox Header="Menge" Grid.Column="1" Grid.Row="2" Margin="5,5,5,5">
|
<GroupBox Header="Menge" Grid.Column="1" Grid.Row="2" Grid.RowSpan="2" Margin="5,5,5,5">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="70"/>
|
<ColumnDefinition Width="70"/>
|
||||||
@@ -565,16 +566,23 @@
|
|||||||
TextChanged="WeightInput_TextChanged"
|
TextChanged="WeightInput_TextChanged"
|
||||||
Grid.Column="1" Width="70" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
Grid.Column="1" Width="70" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||||
|
|
||||||
|
<Label Content="Tara:" Margin="10,40,10,10"/>
|
||||||
|
<TextBlock x:Name="Tare" Text="{Binding TareString}" Width="40"
|
||||||
|
Grid.Column="1" Margin="30,44,10,10" TextAlignment="Center" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||||
|
|
||||||
<CheckBox x:Name="ManualWeighingInput" IsChecked="{Binding IsManualWeighing, Mode=TwoWay}"
|
<CheckBox x:Name="ManualWeighingInput" IsChecked="{Binding IsManualWeighing, Mode=TwoWay}"
|
||||||
Content="Handwiegung" IsEnabled="False"
|
Content="Handwiegung" IsEnabled="False"
|
||||||
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,45,10,10" Grid.Column="0" Grid.ColumnSpan="2"
|
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2"
|
||||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
||||||
|
|
||||||
<CheckBox x:Name="GerebeltGewogenInput" IsChecked="{Binding IsNetWeightValue, Mode=TwoWay}"
|
<CheckBox x:Name="GerebeltGewogenInput" IsChecked="{Binding IsNetWeightValue, Mode=TwoWay}"
|
||||||
Content="Gerebelt gewogen" IsThreeState="True"
|
Content="Gerebelt gewogen" IsThreeState="True"
|
||||||
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2"
|
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,100,10,10" Grid.Column="0" Grid.ColumnSpan="2"
|
||||||
Checked="GerebeltGewogenInput_Changed" Unchecked="GerebeltGewogenInput_Changed" Indeterminate="GerebeltGewogenInput_Changed"/>
|
Checked="GerebeltGewogenInput_Changed" Unchecked="GerebeltGewogenInput_Changed" Indeterminate="GerebeltGewogenInput_Changed"/>
|
||||||
|
|
||||||
|
<Button x:Name="CorrectTareButton" Content="Tara korrigieren" Width="120" Visibility="Hidden"
|
||||||
|
Click="CorrectTareButton_Click"
|
||||||
|
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,10,10,10" Grid.Column="2"/>
|
||||||
<Button x:Name="WeighingAButton" Content="Wiegen A" Width="120"
|
<Button x:Name="WeighingAButton" Content="Wiegen A" Width="120"
|
||||||
Click="WeighingButton_Click"
|
Click="WeighingButton_Click"
|
||||||
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,10,10,10" Grid.Column="2"/>
|
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,10,10,10" Grid.Column="2"/>
|
||||||
@@ -593,7 +601,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
|
||||||
<GroupBox Header="Sonstiges" Grid.Column="1" Grid.Row="3" Grid.RowSpan="2" Margin="5,5,5,10">
|
<GroupBox Header="Sonstiges" Grid.Column="1" Grid.Row="4" Grid.RowSpan="2" Margin="5,5,5,10">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="100"/>
|
<ColumnDefinition Width="100"/>
|
||||||
@@ -646,7 +654,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
|
||||||
<GroupBox Header="Herkunft" Grid.Column="0" Grid.Row="4" Margin="5,5,5,10">
|
<GroupBox Header="Herkunft" Grid.Column="0" Grid.Row="5" Margin="5,5,5,10">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="100"/>
|
<ColumnDefinition Width="100"/>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
@@ -103,6 +104,7 @@ namespace Elwig.Windows {
|
|||||||
WeighingBButton.Visibility = Visibility.Hidden;
|
WeighingBButton.Visibility = Visibility.Hidden;
|
||||||
WeighingCButton.Visibility = Visibility.Hidden;
|
WeighingCButton.Visibility = Visibility.Hidden;
|
||||||
WeighingDButton.Visibility = Visibility.Hidden;
|
WeighingDButton.Visibility = Visibility.Hidden;
|
||||||
|
DisableWeighingButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
Menu_Statistics_WineQuality_ModeOe.IsChecked = false;
|
Menu_Statistics_WineQuality_ModeOe.IsChecked = false;
|
||||||
@@ -126,7 +128,6 @@ namespace Elwig.Windows {
|
|||||||
this() {
|
this() {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
ViewModel.FilterMember = ctx.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
ViewModel.FilterMember = ctx.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
||||||
ViewModel.Title = $"Lieferungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
|
||||||
ViewModel.EnableAllSeasons = true;
|
ViewModel.EnableAllSeasons = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +140,7 @@ namespace Elwig.Windows {
|
|||||||
if (await ctx.FetchSeasons(Utils.CurrentYear).SingleOrDefaultAsync() == null) {
|
if (await ctx.FetchSeasons(Utils.CurrentYear).SingleOrDefaultAsync() == null) {
|
||||||
InteractionService.ShowWarning("Saison noch nicht erstellt",
|
InteractionService.ShowWarning("Saison noch nicht erstellt",
|
||||||
"Die Saison für das aktuelle Jahr wurde noch nicht erstellt. Neue Lieferungen können nicht abgespeichert werden.\n\n" +
|
"Die Saison für das aktuelle Jahr wurde noch nicht erstellt. Neue Lieferungen können nicht abgespeichert werden.\n\n" +
|
||||||
"(Stammdaten -> Saisons -> Neu anlegen...)");
|
"(Stammdaten \u2192 Saisons \u2192 Neu anlegen...)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -419,9 +420,9 @@ namespace Elwig.Windows {
|
|||||||
var cursor = Mouse.OverrideCursor != null;
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
var query = (vm.SearchQuery, vm.FilterSeason, vm.FilterAllSeasons, vm.FilterTodayOnly);
|
var query = (vm.SearchQuery, vm.FilterSeason, vm.FilterAllSeasons, vm.FilterTodayOnly);
|
||||||
var (filter, deliveries, deliveryPartsNum, varieties, members, stat) = await Task.Run(async () => {
|
var (filterNames, filter, deliveries, deliveryPartsNum, varieties, members, stat) = await Task.Run(async () => {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var (_, deliveryQuery, deliveryPartsQuery, predicate, filter) = await vm.GetFilters(ctx);
|
var (filterNames, deliveryQuery, deliveryPartsQuery, predicate, filter) = await vm.GetFilters(ctx);
|
||||||
var deliveries = await deliveryQuery
|
var deliveries = await deliveryQuery
|
||||||
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier)
|
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers).ThenInclude(m => m.Modifier)
|
||||||
.Include(d => d.Parts).ThenInclude(p => p.Variety)
|
.Include(d => d.Parts).ThenInclude(p => p.Variety)
|
||||||
@@ -450,11 +451,13 @@ namespace Elwig.Windows {
|
|||||||
var members = await deliveryQuery.Select(d => d.Member).Distinct().IgnoreAutoIncludes().ToListAsync();
|
var members = await deliveryQuery.Select(d => d.Member).Distinct().IgnoreAutoIncludes().ToListAsync();
|
||||||
var stat = await DeliveryService.GenerateToolTipData(deliveryPartsQuery);
|
var stat = await DeliveryService.GenerateToolTipData(deliveryPartsQuery);
|
||||||
|
|
||||||
return (filter, deliveries, deliveryPartsNum, varieties, members, stat);
|
return (filterNames, filter, deliveries, deliveryPartsNum, varieties, members, stat);
|
||||||
});
|
});
|
||||||
if (!cursor) Mouse.OverrideCursor = null;
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason, ViewModel.FilterAllSeasons, ViewModel.FilterTodayOnly)) return;
|
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason, ViewModel.FilterAllSeasons, ViewModel.FilterTodayOnly)) return;
|
||||||
|
|
||||||
|
if (!ViewModel.IsReceipt)
|
||||||
|
ViewModel.Title = Utils.GetTitle("Lieferungen", filterNames, filter);
|
||||||
ControlUtils.RenewItemsSource(DeliveryList, deliveries,
|
ControlUtils.RenewItemsSource(DeliveryList, deliveries,
|
||||||
DeliveryList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
DeliveryList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
await RefreshDeliveryParts();
|
await RefreshDeliveryParts();
|
||||||
@@ -488,7 +491,6 @@ namespace Elwig.Windows {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ViewModel.FilterMember = m;
|
ViewModel.FilterMember = m;
|
||||||
ViewModel.Title = $"Lieferungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int year = 0;
|
int year = 0;
|
||||||
@@ -612,14 +614,34 @@ namespace Elwig.Windows {
|
|||||||
ClearOriginalValues();
|
ClearOriginalValues();
|
||||||
ClearDefaultValues();
|
ClearDefaultValues();
|
||||||
ViewModel.FillInputs(p);
|
ViewModel.FillInputs(p);
|
||||||
|
CorrectTareButton.Visibility = !ViewModel.IsReceipt && ((ViewModel.ActualTare is int t && t != 0) || ViewModel.IsUnloadingBox) ? Visibility.Visible : Visibility.Hidden;
|
||||||
FinishInputFilling();
|
FinishInputFilling();
|
||||||
}
|
}
|
||||||
|
|
||||||
new protected void ClearInputs(bool validate = false) {
|
new protected void ClearInputs(bool validate = false) {
|
||||||
ViewModel.ClearInputs();
|
ViewModel.ClearInputs();
|
||||||
|
CorrectTareButton.Visibility = Visibility.Hidden;
|
||||||
base.ClearInputs(validate);
|
base.ClearInputs(validate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CorrectTareButton_Click(object sender, RoutedEventArgs evt) {
|
||||||
|
var lastCorrection = (ViewModel.TargetTare ?? ViewModel.ActualTare ?? 0) - (ViewModel.ActualTare ?? 0);
|
||||||
|
var correction = Utils.ShowTareCorrectionDialog(ViewModel.ActualTare, ViewModel.TargetTare);
|
||||||
|
if (correction == null) return;
|
||||||
|
ViewModel.Weight += lastCorrection - correction;
|
||||||
|
if (ViewModel.WeighingData is string s) {
|
||||||
|
ViewModel.TargetTare = correction == 0 ? null : (ViewModel.ActualTare ?? 0) + correction;
|
||||||
|
ViewModel.Tare = ViewModel.TargetTare ?? ViewModel.ActualTare;
|
||||||
|
var obj = JsonNode.Parse(s)!.AsObject();
|
||||||
|
if (correction == 0) {
|
||||||
|
obj.Remove("tare_correction");
|
||||||
|
} else {
|
||||||
|
obj["tare_correction"] = correction;
|
||||||
|
}
|
||||||
|
ViewModel.WeighingData = obj.ToJsonString(Utils.JsonOpts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void WeighingButton_Click(object sender, RoutedEventArgs evt) {
|
private void WeighingButton_Click(object sender, RoutedEventArgs evt) {
|
||||||
int index = Array.IndexOf(WeighingButtons, sender as Button);
|
int index = Array.IndexOf(WeighingButtons, sender as Button);
|
||||||
if (index >= 0) WeighingButton_Click(index);
|
if (index >= 0) WeighingButton_Click(index);
|
||||||
@@ -651,12 +673,18 @@ namespace Elwig.Windows {
|
|||||||
private void OnWeighingResult(IScale scale, WeighingResult res) {
|
private void OnWeighingResult(IScale scale, WeighingResult res) {
|
||||||
if ((res.NetWeight ?? 0) > 0 && res.FullWeighingId != null) {
|
if ((res.NetWeight ?? 0) > 0 && res.FullWeighingId != null) {
|
||||||
ViewModel.Weight = res.NetWeight;
|
ViewModel.Weight = res.NetWeight;
|
||||||
|
ViewModel.ActualTare = res.TareWeight;
|
||||||
|
ViewModel.TargetTare = null;
|
||||||
|
ViewModel.Tare = ViewModel.ActualTare is int t && t != 0 ? t : null;
|
||||||
ViewModel.ScaleTerminalId = scale.ScaleTerminalId;
|
ViewModel.ScaleTerminalId = scale.ScaleTerminalId;
|
||||||
ViewModel.WeighingData = res.ToJson().ToJsonString();
|
ViewModel.WeighingData = res.ToJson().ToJsonString();
|
||||||
ViewModel.ManualWeighingReason = null;
|
ViewModel.ManualWeighingReason = null;
|
||||||
ManualWeighingInput.IsChecked = false;
|
ManualWeighingInput.IsChecked = false;
|
||||||
} else {
|
} else {
|
||||||
ViewModel.Weight = null;
|
ViewModel.Weight = null;
|
||||||
|
ViewModel.ActualTare = null;
|
||||||
|
ViewModel.TargetTare = null;
|
||||||
|
ViewModel.Tare = null;
|
||||||
ViewModel.ScaleTerminalId = null;
|
ViewModel.ScaleTerminalId = null;
|
||||||
ViewModel.WeighingData = null;
|
ViewModel.WeighingData = null;
|
||||||
}
|
}
|
||||||
@@ -685,7 +713,7 @@ namespace Elwig.Windows {
|
|||||||
private async void TodayOnlyInput_Changed(object sender, RoutedEventArgs evt) {
|
private async void TodayOnlyInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
if (!HasContextLoaded) return;
|
if (!HasContextLoaded) return;
|
||||||
if (TodayOnlyInput.IsChecked == true && AllSeasonsInput.IsChecked == false) {
|
if (TodayOnlyInput.IsChecked == true && AllSeasonsInput.IsChecked == false) {
|
||||||
ViewModel.FilterSeason = Utils.Today.Year;
|
ViewModel.FilterSeason = DateTime.Today.Year;
|
||||||
ViewModel.FilterTodayOnly = true;
|
ViewModel.FilterTodayOnly = true;
|
||||||
}
|
}
|
||||||
await RefreshList();
|
await RefreshList();
|
||||||
@@ -971,6 +999,8 @@ namespace Elwig.Windows {
|
|||||||
DeliveryList.IsEnabled = false;
|
DeliveryList.IsEnabled = false;
|
||||||
DeliveryPartList.IsEnabled = false;
|
DeliveryPartList.IsEnabled = false;
|
||||||
|
|
||||||
|
if (!ViewModel.IsReceipt)
|
||||||
|
EnableWeighingButtons();
|
||||||
HideNewEditDeleteButtons();
|
HideNewEditDeleteButtons();
|
||||||
ShowSaveResetCancelButtons();
|
ShowSaveResetCancelButtons();
|
||||||
UnlockInputs();
|
UnlockInputs();
|
||||||
@@ -1034,6 +1064,8 @@ namespace Elwig.Windows {
|
|||||||
DeliveryList.IsEnabled = true;
|
DeliveryList.IsEnabled = true;
|
||||||
DeliveryPartList.IsEnabled = true;
|
DeliveryPartList.IsEnabled = true;
|
||||||
|
|
||||||
|
if (!ViewModel.IsReceipt)
|
||||||
|
DisableWeighingButtons();
|
||||||
HideSaveResetCancelButtons();
|
HideSaveResetCancelButtons();
|
||||||
ShowNewEditDeleteButtons();
|
ShowNewEditDeleteButtons();
|
||||||
LockInputs();
|
LockInputs();
|
||||||
@@ -1067,6 +1099,8 @@ namespace Elwig.Windows {
|
|||||||
DeliveryList.IsEnabled = true;
|
DeliveryList.IsEnabled = true;
|
||||||
DeliveryPartList.IsEnabled = true;
|
DeliveryPartList.IsEnabled = true;
|
||||||
|
|
||||||
|
if (!ViewModel.IsReceipt)
|
||||||
|
DisableWeighingButtons();
|
||||||
HideSaveResetCancelButtons();
|
HideSaveResetCancelButtons();
|
||||||
ShowNewEditDeleteButtons();
|
ShowNewEditDeleteButtons();
|
||||||
RefreshInputs();
|
RefreshInputs();
|
||||||
@@ -1171,6 +1205,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void DisableWeighingButtons() {
|
private void DisableWeighingButtons() {
|
||||||
|
CorrectTareButton.IsEnabled = false;
|
||||||
WeighingManualButton.IsEnabled = false;
|
WeighingManualButton.IsEnabled = false;
|
||||||
WeighingAButton.IsEnabled = false;
|
WeighingAButton.IsEnabled = false;
|
||||||
WeighingBButton.IsEnabled = false;
|
WeighingBButton.IsEnabled = false;
|
||||||
@@ -1179,6 +1214,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void EnableWeighingButtons() {
|
private void EnableWeighingButtons() {
|
||||||
|
CorrectTareButton.IsEnabled = true;
|
||||||
WeighingManualButton.IsEnabled = true;
|
WeighingManualButton.IsEnabled = true;
|
||||||
var n = App.CommandScales.Count;
|
var n = App.CommandScales.Count;
|
||||||
WeighingAButton.IsEnabled = n > 0 && App.CommandScales[0].IsReady;
|
WeighingAButton.IsEnabled = n > 0 && App.CommandScales[0].IsReady;
|
||||||
@@ -1373,13 +1409,15 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
private void UnloadingInput_Checked(object sender, RoutedEventArgs evt) {
|
private void UnloadingInput_Checked(object sender, RoutedEventArgs evt) {
|
||||||
if (!IsEditing && !IsCreating) return;
|
if (!IsEditing && !IsCreating) return;
|
||||||
|
if (!ViewModel.IsReceipt)
|
||||||
|
CorrectTareButton.Visibility = (ViewModel.ActualTare is int t && t != 0) || ViewModel.IsUnloadingBox ? Visibility.Visible : Visibility.Hidden;
|
||||||
var mod = ViewModel.Modifiers.ToList();
|
var mod = ViewModel.Modifiers.ToList();
|
||||||
var source = ViewModel.ModifiersSource.ToList();
|
var source = ViewModel.ModifiersSource.ToList();
|
||||||
if (App.Client.IsMatzen) {
|
if (App.Client.IsMatzen) {
|
||||||
var kl = mod.Where(m => m.Name.StartsWith("Klasse ")).Select(m => m.ModId).LastOrDefault("_")[0];
|
var kl = mod.Where(m => m.Name.StartsWith("Klasse ")).Select(m => m.ModId).LastOrDefault("_")[0];
|
||||||
if (ViewModel.IsUnloadingPumped && (kl == 'A' || kl == '_')) {
|
if (ViewModel.IsUnloadingPumped && (kl == 'A' || kl == '_')) {
|
||||||
kl = 'B';
|
kl = 'B';
|
||||||
} else if (ViewModel.IsUnloadingDumper && kl == '_') {
|
} else if (ViewModel.IsUnloadingDumper && (kl == 'B' || kl == '_')) {
|
||||||
kl = 'A';
|
kl = 'A';
|
||||||
} else {
|
} else {
|
||||||
kl = '_';
|
kl = '_';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
||||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||||
Title="Anmeldungen - Elwig" Height="700" Width="980" MinWidth="600" MinHeight="400">
|
Title="{Binding Title}" Height="700" Width="980" MinWidth="600" MinHeight="400">
|
||||||
<Window.DataContext>
|
<Window.DataContext>
|
||||||
<vm:DeliveryAncmtAdminViewModel/>
|
<vm:DeliveryAncmtAdminViewModel/>
|
||||||
</Window.DataContext>
|
</Window.DataContext>
|
||||||
|
|||||||
@@ -91,8 +91,9 @@ namespace Elwig.Windows {
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
list.ForEach(v => v.Schedule.AnnouncedWeightOverride = v.AnnouncedWeight);
|
list.ForEach(v => v.Schedule.AnnouncedWeightOverride = v.AnnouncedWeight);
|
||||||
var deliverySchedules = list.Select(v => v.Schedule).ToList();
|
var deliverySchedules = list.Select(v => v.Schedule).ToList();
|
||||||
|
var today = DateTime.Today;
|
||||||
ControlUtils.RenewItemsSource(DeliveryScheduleList, deliverySchedules
|
ControlUtils.RenewItemsSource(DeliveryScheduleList, deliverySchedules
|
||||||
.Where(s => !ViewModel.FilterOnlyUpcoming || s.DateString.CompareTo(Utils.Today.ToString("yyyy-MM-dd")) >= 0)
|
.Where(s => !ViewModel.FilterOnlyUpcoming || s.DateString.CompareTo(today.ToString("yyyy-MM-dd")) >= 0)
|
||||||
.ToList(), DeliveryScheduleList_SelectionChanged, ViewModel.FilterFromAllSchedules ? ControlUtils.RenewSourceDefault.None : ControlUtils.RenewSourceDefault.First);
|
.ToList(), DeliveryScheduleList_SelectionChanged, ViewModel.FilterFromAllSchedules ? ControlUtils.RenewSourceDefault.None : ControlUtils.RenewSourceDefault.First);
|
||||||
ControlUtils.RenewItemsSource(DeliveryScheduleInput, deliverySchedules, DeliveryScheduleInput_SelectionChanged);
|
ControlUtils.RenewItemsSource(DeliveryScheduleInput, deliverySchedules, DeliveryScheduleInput_SelectionChanged);
|
||||||
}
|
}
|
||||||
@@ -102,9 +103,9 @@ namespace Elwig.Windows {
|
|||||||
var cursor = Mouse.OverrideCursor != null;
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
var query = (vm.SearchQuery, vm.FilterSeason, vm.FilterOnlyUpcoming, vm.FilterOnlyUpcoming);
|
var query = (vm.SearchQuery, vm.FilterSeason, vm.FilterOnlyUpcoming, vm.FilterOnlyUpcoming);
|
||||||
var (filter, deliveryAncmts, stat) = await Task.Run(async () => {
|
var (filterNames, filter, deliveryAncmts, stat) = await Task.Run(async () => {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var (_, deliveryAncmtQuery, filter) = await vm.GetFilters(ctx);
|
var (filterNames, deliveryAncmtQuery, filter) = await vm.GetFilters(ctx);
|
||||||
var deliveryAncmts = await deliveryAncmtQuery.ToListAsync();
|
var deliveryAncmts = await deliveryAncmtQuery.ToListAsync();
|
||||||
|
|
||||||
if (filter.Count > 0 && deliveryAncmts.Count > 0) {
|
if (filter.Count > 0 && deliveryAncmts.Count > 0) {
|
||||||
@@ -129,11 +130,12 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
var stat = await DeliveryAncmtService.GenerateToolTipData(deliveryAncmtQuery);
|
var stat = await DeliveryAncmtService.GenerateToolTipData(deliveryAncmtQuery);
|
||||||
|
|
||||||
return (filter, deliveryAncmts, stat);
|
return (filterNames, filter, deliveryAncmts, stat);
|
||||||
});
|
});
|
||||||
if (!cursor) Mouse.OverrideCursor = null;
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason, ViewModel.FilterOnlyUpcoming, ViewModel.FilterOnlyUpcoming)) return;
|
if (query != (ViewModel.SearchQuery, ViewModel.FilterSeason, ViewModel.FilterOnlyUpcoming, ViewModel.FilterOnlyUpcoming)) return;
|
||||||
|
|
||||||
|
ViewModel.Title = Utils.GetTitle("Anmeldungen", filterNames, filter);
|
||||||
ControlUtils.RenewItemsSource(DeliveryAncmtList, deliveryAncmts,
|
ControlUtils.RenewItemsSource(DeliveryAncmtList, deliveryAncmts,
|
||||||
DeliveryAncmtList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
DeliveryAncmtList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
if (updateSort && DeliveryAncmtList.SelectedItem != null)
|
if (updateSort && DeliveryAncmtList.SelectedItem != null)
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ namespace Elwig.Windows {
|
|||||||
public MailWindow(int? year = null) {
|
public MailWindow(int? year = null) {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
using (var ctx = new AppDbContext()) {
|
using (var ctx = new AppDbContext()) {
|
||||||
Year = year ?? ctx.Seasons.OrderByDescending(s => s.Year).FirstOrDefault()?.Year ?? Utils.Today.Year;
|
Year = year ?? ctx.Seasons.OrderByDescending(s => s.Year).FirstOrDefault()?.Year ?? DateTime.Today.Year;
|
||||||
Title = $"Rundschreiben - Lese {Year} - Elwig";
|
Title = $"Rundschreiben - Lese {Year} - Elwig";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ namespace Elwig.Windows {
|
|||||||
PostalSender1.Text = App.Client.Sender1;
|
PostalSender1.Text = App.Client.Sender1;
|
||||||
PostalSender2.Text = App.Client.Sender2;
|
PostalSender2.Text = App.Client.Sender2;
|
||||||
PostalLocation.Text = App.BranchLocation;
|
PostalLocation.Text = App.BranchLocation;
|
||||||
PostalDate.Text = $"{Utils.Today:dd.MM.yyyy}";
|
PostalDate.Text = $"{DateTime.Today:dd.MM.yyyy}";
|
||||||
EmailSubjectInput.Text = App.Client.TextEmailSubject ?? "Rundschreiben";
|
EmailSubjectInput.Text = App.Client.TextEmailSubject ?? "Rundschreiben";
|
||||||
EmailBodyInput.Text = App.Client.TextEmailBody ?? "Sehr geehrtes Mitglied,\n\nim Anhang finden Sie das aktuelle Rundschreiben.\n\nIhre Winzergenossenschaft\n";
|
EmailBodyInput.Text = App.Client.TextEmailBody ?? "Sehr geehrtes Mitglied,\n\nim Anhang finden Sie das aktuelle Rundschreiben.\n\nIhre Winzergenossenschaft\n";
|
||||||
}
|
}
|
||||||
@@ -438,7 +438,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
private void Date_LostFocus(object sender, RoutedEventArgs evt) {
|
private void Date_LostFocus(object sender, RoutedEventArgs evt) {
|
||||||
var res = Validator.CheckDate((TextBox)sender, true);
|
var res = Validator.CheckDate((TextBox)sender, true);
|
||||||
if (!res.IsValid) ((TextBox)sender).Text = $"{Utils.Today:dd.MM.yyyy}";
|
if (!res.IsValid) ((TextBox)sender).Text = $"{DateTime.Today:dd.MM.yyyy}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateRecipients(AppDbContext ctx) {
|
private async Task UpdateRecipients(AppDbContext ctx) {
|
||||||
@@ -937,6 +937,7 @@ namespace Elwig.Windows {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
var subject = EmailSubjectInput.Text;
|
var subject = EmailSubjectInput.Text;
|
||||||
var text = EmailBodyInput.Text;
|
var text = EmailBodyInput.Text;
|
||||||
|
var date = DateTime.Now;
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
await Utils.AddSentMailBody(subject, text, EmailDocuments.Count);
|
await Utils.AddSentMailBody(subject, text, EmailDocuments.Count);
|
||||||
foreach (var (m, docs) in EmailDocuments) {
|
foreach (var (m, docs) in EmailDocuments) {
|
||||||
@@ -944,6 +945,7 @@ namespace Elwig.Windows {
|
|||||||
msg.From.Add(new MailboxAddress(App.Client.NameFull, App.Config.Smtp.Value.From));
|
msg.From.Add(new MailboxAddress(App.Client.NameFull, App.Config.Smtp.Value.From));
|
||||||
msg.To.AddRange(m.EmailAddresses.OrderBy(a => a.Nr).Select(a => new MailboxAddress(m.AdministrativeName, a.Address)));
|
msg.To.AddRange(m.EmailAddresses.OrderBy(a => a.Nr).Select(a => new MailboxAddress(m.AdministrativeName, a.Address)));
|
||||||
msg.Subject = subject;
|
msg.Subject = subject;
|
||||||
|
msg.Date = date;
|
||||||
var body = new Multipart("mixed") {
|
var body = new Multipart("mixed") {
|
||||||
new TextPart("plain") { Text = text }
|
new TextPart("plain") { Text = text }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,23 +50,28 @@ namespace Elwig.Windows {
|
|||||||
_syncTimer.Start();
|
_syncTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Closing(object sender, CancelEventArgs evt) {
|
private async void Window_Closing(object sender, CancelEventArgs evt) {
|
||||||
|
evt.Cancel = !App.ForceShutdown;
|
||||||
|
|
||||||
if (App.NumWindows > 1 && !App.ForceShutdown) {
|
if (App.NumWindows > 1 && !App.ForceShutdown) {
|
||||||
foreach (var w in App.Current.Windows.Cast<Window>().Where(w => ((w as AdministrationWindow)?.IsEditing ?? false) || ((w as AdministrationWindow)?.IsCreating ?? false))) {
|
foreach (var w in Application.Current.Windows.Cast<Window>().Where(w => ((w as AdministrationWindow)?.IsEditing ?? false) || ((w as AdministrationWindow)?.IsCreating ?? false))) {
|
||||||
try {
|
try {
|
||||||
w.Close();
|
w.Close();
|
||||||
} catch { }
|
} catch { }
|
||||||
}
|
}
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
if (App.NumWindows > 1 && !App.Current.Windows.Cast<Window>().Any(w => ((w as AdministrationWindow)?.IsEditing ?? false) || ((w as AdministrationWindow)?.IsCreating ?? false))) {
|
if (App.NumWindows > 1 && !Application.Current.Windows.Cast<Window>().Any(w => ((w as AdministrationWindow)?.IsEditing ?? false) || ((w as AdministrationWindow)?.IsCreating ?? false))) {
|
||||||
if (!InteractionService.AskConfirmation("Elwig beenden", "Es sind noch weitere Fenster geöffnet.\nSollen alle Fenster geschlossen werden?")) {
|
if (!InteractionService.AskConfirmation("Elwig beenden", "Es sind noch weitere Fenster geöffnet.\nSollen alle Fenster geschlossen werden?")) {
|
||||||
evt.Cancel = true;
|
return;
|
||||||
} else {
|
}
|
||||||
|
App.ForceShutdown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mouse.OverrideCursor = Cursors.AppStarting;
|
||||||
|
await (Application.Current as App)!.OnClosing();
|
||||||
Application.Current.Shutdown();
|
Application.Current.Shutdown();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Menu_Help_About_Click(object sender, RoutedEventArgs evt) {
|
private void Menu_Help_About_Click(object sender, RoutedEventArgs evt) {
|
||||||
var w = new AboutWindow();
|
var w = new AboutWindow();
|
||||||
@@ -162,7 +167,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
private async void Menu_Database_Backup_Click(object sender, RoutedEventArgs evt) {
|
private async void Menu_Database_Backup_Click(object sender, RoutedEventArgs evt) {
|
||||||
try {
|
try {
|
||||||
var filename = InteractionService.SaveFile("Datenbank-Sicherung", $"database_{Utils.Today:yyyy-MM-dd}", "sql.zip");
|
var filename = InteractionService.SaveFile("Datenbank-Sicherung", $"database_{DateTime.Today:yyyy-MM-dd}", "sql.zip");
|
||||||
if (filename != null) {
|
if (filename != null) {
|
||||||
if (!filename.EndsWith(".sql.zip")) filename += ".sql.zip";
|
if (!filename.EndsWith(".sql.zip")) filename += ".sql.zip";
|
||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
@@ -177,22 +182,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void Menu_Database_Restore_Click(object sender, RoutedEventArgs evt) {
|
private async void Menu_Database_Restore_Click(object sender, RoutedEventArgs evt) {
|
||||||
try {
|
await BackupService.RestoreDatabase();
|
||||||
var d = new OpenFileDialog() {
|
|
||||||
Title = "Datenbank wiederherstellen - Elwig",
|
|
||||||
DefaultExt = "sql.zip",
|
|
||||||
Filter = "SQLite-Datenbank (*.sqlite3, *.sqlite3.zip, *.sql, *.sql.zip)|*.sqlite3;*.sqlite3.zip;*.sql;*.sql.zip",
|
|
||||||
};
|
|
||||||
if (d.ShowDialog() == true) {
|
|
||||||
if (!InteractionService.AskContinue("Datenbank wiederherstellen", "Soll die Datenbank wirklich unwiederruflich durch die wiederhergestellte Version ersetzt werden?"))
|
|
||||||
return;
|
|
||||||
Mouse.OverrideCursor = Cursors.Wait;
|
|
||||||
await App.ReplaceDatabase(d.FileName);
|
|
||||||
}
|
|
||||||
} catch (Exception exc) {
|
|
||||||
InteractionService.ShowException(exc);
|
|
||||||
}
|
|
||||||
Mouse.OverrideCursor = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SyncButton_Click(object sender, RoutedEventArgs evt) {
|
private async void SyncButton_Click(object sender, RoutedEventArgs evt) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:Elwig.Windows"
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
||||||
Title="Mitglieder - Elwig" Height="700" Width="1250" MinHeight="650" MinWidth="1150">
|
Title="{Binding Title}" Height="700" Width="1250" MinHeight="650" MinWidth="1150">
|
||||||
<Window.DataContext>
|
<Window.DataContext>
|
||||||
<vm:MemberAdminViewModel/>
|
<vm:MemberAdminViewModel/>
|
||||||
</Window.DataContext>
|
</Window.DataContext>
|
||||||
@@ -547,35 +547,53 @@
|
|||||||
<GroupBox Header="Betrieb" Grid.Column="1" Grid.Row="0" Grid.RowSpan="1" Margin="5,5,5,5">
|
<GroupBox Header="Betrieb" Grid.Column="1" Grid.Row="0" Grid.RowSpan="1" Margin="5,5,5,5">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="90"/>
|
<ColumnDefinition Width="85"/>
|
||||||
<ColumnDefinition Width="150"/>
|
<ColumnDefinition Width="69"/>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="55"/>
|
||||||
|
<ColumnDefinition Width="101"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Label Content="UID:" Margin="10,10,0,0" Grid.Column="0"/>
|
<Label Content="Betriebs-Nr.:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||||
<TextBox x:Name="UstIdNrInput" Text="{Binding UstIdNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
|
||||||
Margin="0,10,10,0" Grid.Column="1" Width="96" HorizontalAlignment="Left"
|
|
||||||
TextChanged="UstIdNrInput_TextChanged" LostFocus="UstIdNrInput_LostFocus"/>
|
|
||||||
|
|
||||||
<Label Content="Betriebs-Nr.:" Margin="10,40,0,0" Grid.Column="0"/>
|
|
||||||
<TextBox x:Name="LfbisNrInput" Text="{Binding LfbisNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
<TextBox x:Name="LfbisNrInput" Text="{Binding LfbisNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
Margin="0,40,10,0" Grid.Column="1" Width="64" HorizontalAlignment="Left" TextAlignment="Right"
|
Margin="0,10,5,0" Grid.Column="1" Width="64" HorizontalAlignment="Left" TextAlignment="Right"
|
||||||
TextChanged="LfbisNrInput_TextChanged" LostFocus="LfbisNrInput_LostFocus"/>
|
TextChanged="LfbisNrInput_TextChanged" LostFocus="LfbisNrInput_LostFocus"/>
|
||||||
|
|
||||||
<CheckBox x:Name="BuchführendInput" Content="Buchführend" IsChecked="{Binding IsBuchführend, Mode=TwoWay}" IsEnabled="False"
|
<Label Content="UID:" Margin="10,40,0,0" Grid.Column="0" ToolTip="USt-IdNr. / Umsatzsteuer-Identifikationsnummer"/>
|
||||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"
|
<TextBox x:Name="UstIdNrInput" Text="{Binding UstIdNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
Grid.Column="2" HorizontalAlignment="Left" Margin="10,15,0,0" VerticalAlignment="Top"/>
|
Margin="0,40,5,0" Grid.Column="0" Grid.ColumnSpan="2" Width="96" HorizontalAlignment="Right"
|
||||||
|
TextChanged="UstIdNrInput_TextChanged" LostFocus="UstIdNrInput_LostFocus"/>
|
||||||
|
|
||||||
<CheckBox x:Name="OrganicInput" Content="Bio" IsChecked="{Binding IsOrganic, Mode=TwoWay}" IsEnabled="False"
|
<CheckBox x:Name="OrganicInput" Content="Bio" IsChecked="{Binding IsOrganic, Mode=TwoWay}" IsEnabled="False"
|
||||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"
|
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"
|
||||||
Grid.Column="2" HorizontalAlignment="Left" Margin="10,45,0,0" VerticalAlignment="Top"/>
|
Grid.Column="2" HorizontalAlignment="Left" Margin="5,15,0,0" VerticalAlignment="Top"/>
|
||||||
<Button x:Name="OrganicButton" Content="easy-cert.com" IsEnabled="{Binding IsMemberSelected}"
|
|
||||||
Height="25" FontSize="12"
|
<CheckBox x:Name="BuchführendInput" Content="Buchführend" IsChecked="{Binding IsBuchführend, Mode=TwoWay}" IsEnabled="False"
|
||||||
Click="OrganicButton_Click"
|
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"
|
||||||
Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="60,40,0,0"/>
|
Grid.Column="2" HorizontalAlignment="Left" Margin="5,45,0,0" VerticalAlignment="Top"/>
|
||||||
|
|
||||||
|
<Label Content="Kontrollstelle:" Margin="0,10,5,0" Grid.Column="2" Grid.ColumnSpan="2" HorizontalAlignment="Right" ToolTip="Bio-Kontrollstelle"/>
|
||||||
|
<TextBox x:Name="OrganicAuthorityCodeInput" Text="{Binding OrganicAuthorityCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Margin="0,10,19,0" Grid.Column="4" Width="82" HorizontalAlignment="Left"
|
||||||
|
TextChanged="OrganicAuthorityCodeInput_TextChanged" LostFocus="OrganicAuthorityCodeInput_LostFocus"/>
|
||||||
|
|
||||||
|
<Label Content="OOC-ID:" Margin="0,40,0,0" Grid.Column="3" HorizontalAlignment="Left" ToolTip="Bio-EU-Operator-ID / Organic Operator Certificate ID"/>
|
||||||
|
<TextBox x:Name="OrganicOperatorIdInput" Text="{Binding OrganicOperatorId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Margin="0,40,10,0" Grid.Column="4" Width="91" HorizontalAlignment="Left"
|
||||||
|
TextChanged="OrganicOperatorIdInput_TextChanged" LostFocus="OrganicOperatorIdInput_LostFocus"/>
|
||||||
|
|
||||||
|
<Label Content="Bio-Zert.:" Margin="50,10,0,0" Grid.Column="2" HorizontalAlignment="Left"/>
|
||||||
|
<TextBlock FontSize="14" Margin="105,12,10,0" Grid.Column="2" HorizontalAlignment="Left" ToolTip="{Binding OrganicTest4}">
|
||||||
|
<Run Text="{Binding OrganicTest1}" FontWeight="Bold" Foreground="{Binding OrganicTest3}"/><Run FontSize="12" Text="{Binding OrganicTest2}"/>
|
||||||
|
</TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
<GroupBox Header="Rechnungsadresse (optional)" Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Margin="5,5,5,5">
|
<GroupBox Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Margin="5,5,5,5">
|
||||||
|
<GroupBox.Header>
|
||||||
|
<TextBlock>Rechnungsadresse (optional)
|
||||||
|
<Run FontSize="10">für Lieferschein, Anlfrg.-Bstng., Tr.-Gutschr.</Run>
|
||||||
|
</TextBlock>
|
||||||
|
</GroupBox.Header>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="65"/>
|
<ColumnDefinition Width="65"/>
|
||||||
@@ -619,7 +637,7 @@
|
|||||||
Margin="0,40,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
Margin="0,40,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||||
TextChanged="DateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
TextChanged="DateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
||||||
|
|
||||||
<Label Content="BH-Konto:" Margin="10,70,0,0" Grid.Column="0"/>
|
<Label Content="BH-Konto:" Margin="10,70,0,0" Grid.Column="0" ToolTip="Buchhaltungskonto"/>
|
||||||
<TextBox x:Name="AccountingNrInput" Text="{Binding AccountingNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
<TextBox x:Name="AccountingNrInput" Text="{Binding AccountingNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
Margin="0,70,10,0" Width="63" Grid.Column="1" HorizontalAlignment="Left"
|
Margin="0,70,10,0" Width="63" Grid.Column="1" HorizontalAlignment="Left"
|
||||||
TextChanged="TextBox_TextChanged"/>
|
TextChanged="TextBox_TextChanged"/>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ using Elwig.ViewModels;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
@@ -147,9 +146,9 @@ namespace Elwig.Windows {
|
|||||||
var cursor = Mouse.OverrideCursor != null;
|
var cursor = Mouse.OverrideCursor != null;
|
||||||
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||||
var query = (vm.SearchQuery, vm.ShowOnlyActiveMembers);
|
var query = (vm.SearchQuery, vm.ShowOnlyActiveMembers);
|
||||||
var (members, stat) = await Task.Run(async () => {
|
var (filterNames, members, stat, filter) = await Task.Run(async () => {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var (_, memberQuery, filter) = await vm.GetFilters(ctx);
|
var (filterNames, memberQuery, filter) = await vm.GetFilters(ctx);
|
||||||
var members = await memberQuery
|
var members = await memberQuery
|
||||||
.Include(m => m.EmailAddresses)
|
.Include(m => m.EmailAddresses)
|
||||||
.Include(m => m.TelephoneNumbers)
|
.Include(m => m.TelephoneNumbers)
|
||||||
@@ -184,11 +183,12 @@ namespace Elwig.Windows {
|
|||||||
SharesActive = g.Sum(m => m.Shares + m.SharesRed + m.SharesWhite),
|
SharesActive = g.Sum(m => m.Shares + m.SharesRed + m.SharesWhite),
|
||||||
}).ToListAsync()).Select(g => (g.Count, g.Shares, g.SharesRed, g.SharesWhite, g.SharesDormant, g.SharesTotal, g.SharesActive)).ToList();
|
}).ToListAsync()).Select(g => (g.Count, g.Shares, g.SharesRed, g.SharesWhite, g.SharesDormant, g.SharesTotal, g.SharesActive)).ToList();
|
||||||
|
|
||||||
return (members, stat[0]);
|
return (filterNames, members, stat[0], filter);
|
||||||
});
|
});
|
||||||
if (!cursor) Mouse.OverrideCursor = null;
|
if (!cursor) Mouse.OverrideCursor = null;
|
||||||
if (query != (ViewModel.SearchQuery, ViewModel.ShowOnlyActiveMembers)) return;
|
if (query != (ViewModel.SearchQuery, ViewModel.ShowOnlyActiveMembers)) return;
|
||||||
|
|
||||||
|
ViewModel.Title = Utils.GetTitle("Mitglieder", filterNames, filter);
|
||||||
ControlUtils.RenewItemsSource(MemberList, members,
|
ControlUtils.RenewItemsSource(MemberList, members,
|
||||||
MemberList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
MemberList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
|
||||||
if (updateSort && MemberList.SelectedItem != null)
|
if (updateSort && MemberList.SelectedItem != null)
|
||||||
@@ -965,17 +965,6 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OrganicButton_Click(object sender, RoutedEventArgs evt) {
|
|
||||||
if (ViewModel.SelectedMember is not Member m) return;
|
|
||||||
var url = "https://www.easy-cert.com/htm/suchergebnis.htm?" +
|
|
||||||
//$"CustomerNumber={m.LfbisNr}&" +
|
|
||||||
$"Name={(m.BillingAddress?.FullName ?? m.FullName).Replace(' ', '+')}&" +
|
|
||||||
$"PostalCode={(m.BillingAddress?.PostalDest ?? m.PostalDest).AtPlz?.Plz}";
|
|
||||||
Process.Start(new ProcessStartInfo(url) {
|
|
||||||
UseShellExecute = true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MemberReferenceButton_Click(object sender, RoutedEventArgs evt) {
|
private void MemberReferenceButton_Click(object sender, RoutedEventArgs evt) {
|
||||||
if (ViewModel.SelectedMember is not Member m || m.PredecessorMgNr == null) return;
|
if (ViewModel.SelectedMember is not Member m || m.PredecessorMgNr == null) return;
|
||||||
FocusMember((int)m.PredecessorMgNr);
|
FocusMember((int)m.PredecessorMgNr);
|
||||||
|
|||||||
@@ -173,8 +173,11 @@
|
|||||||
Margin="0,100,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
Margin="0,100,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||||
TextChanged="DateNoticeInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
TextChanged="DateNoticeInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
||||||
|
|
||||||
|
<CheckBox x:Name="HasCompanySignedInput" IsChecked="{Binding CompanyHasSigned, Mode=TwoWay}" Content="Von WG unterfertigt"
|
||||||
|
Margin="88,105,10,0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||||
|
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
||||||
<CheckBox x:Name="HasMemberSignedInput" IsChecked="{Binding MemberHasSigned, Mode=TwoWay}" Content="Von Mg. unterfertigt"
|
<CheckBox x:Name="HasMemberSignedInput" IsChecked="{Binding MemberHasSigned, Mode=TwoWay}" Content="Von Mg. unterfertigt"
|
||||||
Margin="88,105,10,0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="TOp"
|
Margin="88,135,10,0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
||||||
|
|
||||||
<Label Content="Wirksam:" Margin="10,130,0,0" Grid.Column="0"/>
|
<Label Content="Wirksam:" Margin="10,130,0,0" Grid.Column="0"/>
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ namespace Elwig.Windows {
|
|||||||
|
|
||||||
int mgnr;
|
int mgnr;
|
||||||
try {
|
try {
|
||||||
mgnr = await ViewModel.UpdateMemberHistory(ViewModel.SelectedHistoryEntry?.HistNr, IsEditing || ViewModel.DateNotice >= DateOnly.FromDateTime(Utils.Today).AddDays(-14));
|
mgnr = await ViewModel.UpdateMemberHistory(ViewModel.SelectedHistoryEntry?.HistNr, IsEditing || ViewModel.DateNotice >= DateOnly.FromDateTime(DateTime.Today).AddDays(-14));
|
||||||
App.HintContextChange();
|
App.HintContextChange();
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
InteractionService.ShowDbException("Geschäftsanteilbewegung aktualisieren", exc);
|
InteractionService.ShowDbException("Geschäftsanteilbewegung aktualisieren", exc);
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ Data and configuration folder
|
|||||||
C:\ProgramData\Elwig\
|
C:\ProgramData\Elwig\
|
||||||
- config.ini : main configuration file
|
- config.ini : main configuration file
|
||||||
- database.sqlite3 : stores all data
|
- database.sqlite3 : stores all data
|
||||||
|
- backups\ : (automatic) backups of the database
|
||||||
- imported.txt : list of all imported *.elwig.zip files to not automatically import them again
|
- imported.txt : list of all imported *.elwig.zip files to not automatically import them again
|
||||||
- mails\ : sent/outgoing email log
|
- mails\ : sent/outgoing email log
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
; Only needed, if more than one branch is stored in database
|
; Only needed, if more than one branch is stored in database
|
||||||
;branch = Zweigstelle
|
;branch = Zweigstelle
|
||||||
;debug = true
|
;debug = true
|
||||||
|
;weighing = gross ; gross/net/box
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
; Relative or absolute path to database file
|
; Relative or absolute path to database file
|
||||||
@@ -10,6 +11,14 @@ file = database.sqlite3
|
|||||||
; Enables database logging
|
; Enables database logging
|
||||||
;log = db.log
|
;log = db.log
|
||||||
|
|
||||||
|
[backup]
|
||||||
|
;auto = false
|
||||||
|
;path = backups
|
||||||
|
;retain_hours = 36
|
||||||
|
;retain_days = 8
|
||||||
|
;retain_weeks = 6
|
||||||
|
;retain_months = 18
|
||||||
|
|
||||||
[update]
|
[update]
|
||||||
url = https://elwig.at/files/elwig/latest
|
url = https://elwig.at/files/elwig/latest
|
||||||
auto = true
|
auto = true
|
||||||
@@ -38,6 +47,8 @@ auto = true
|
|||||||
;limit = 3500
|
;limit = 3500
|
||||||
; Enables scale logging
|
; Enables scale logging
|
||||||
;log = waage.log
|
;log = waage.log
|
||||||
|
; Opt-out of auto time synchronization at startup
|
||||||
|
;synctime = false
|
||||||
|
|
||||||
;[scale.B]
|
;[scale.B]
|
||||||
;type = Avery-Async
|
;type = Avery-Async
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ About
|
|||||||
**Product:** Elwig
|
**Product:** Elwig
|
||||||
**Description:** Electronic Management for Vintners' Cooperatives
|
**Description:** Electronic Management for Vintners' Cooperatives
|
||||||
**Type:** ERP system
|
**Type:** ERP system
|
||||||
**Version:** 1.1.1.1 ([Changelog](./CHANGELOG.md))
|
**Version:** 1.1.2.2 ([Changelog](./CHANGELOG.md))
|
||||||
**License:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
**License:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
||||||
**Website:** https://elwig.at/
|
**Website:** https://elwig.at/
|
||||||
**Source code:** https://git.necronda.net/winzer/elwig
|
**Source code:** https://git.necronda.net/winzer/elwig
|
||||||
@@ -33,7 +33,7 @@ Packaging: [WiX Toolset](https://www.firegiant.com/wixtoolset/)
|
|||||||
**Produkt:** Elwig
|
**Produkt:** Elwig
|
||||||
**Beschreibung:** Elektronische Winzergenossenschaftsverwaltung
|
**Beschreibung:** Elektronische Winzergenossenschaftsverwaltung
|
||||||
**Typ:** Warenwirtschaftssystem (ERP-System)
|
**Typ:** Warenwirtschaftssystem (ERP-System)
|
||||||
**Version:** 1.1.1.1 ([Änderungsprotokoll](./CHANGELOG.md))
|
**Version:** 1.1.2.2 ([Änderungsprotokoll](./CHANGELOG.md))
|
||||||
**Lizenz:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
**Lizenz:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
||||||
**Website:** https://elwig.at/
|
**Website:** https://elwig.at/
|
||||||
**Quellcode:** https://git.necronda.net/winzer/elwig
|
**Quellcode:** https://git.necronda.net/winzer/elwig
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace Tests.E2ETests {
|
|||||||
Session.App.FindElement(By.Name("Rundschreiben")).Click();
|
Session.App.FindElement(By.Name("Rundschreiben")).Click();
|
||||||
Thread.Sleep(Utils.WINDOW_OPEN_SLEEP);
|
Thread.Sleep(Utils.WINDOW_OPEN_SLEEP);
|
||||||
var window = Session.CreateWindowDriver("MailWindow");
|
var window = Session.CreateWindowDriver("MailWindow");
|
||||||
Assert.That(window.Title, Is.EqualTo($"Rundschreiben - Lese {Elwig.Helpers.Utils.Today.Year} - Elwig"));
|
Assert.That(window.Title, Is.EqualTo($"Rundschreiben - Lese {DateTime.Today.Year} - Elwig"));
|
||||||
window.Close();
|
window.Close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,12 +84,12 @@ namespace Tests.E2ETests {
|
|||||||
Window.FindElement(By.WpfId("SearchInput")).SendKeys("9999");
|
Window.FindElement(By.WpfId("SearchInput")).SendKeys("9999");
|
||||||
Thread.Sleep(500);
|
Thread.Sleep(500);
|
||||||
var memberListRow = Window.FindElement(By.WpfId("MemberList")).FindElement(By.ClassName("DataGridRow"));
|
var memberListRow = Window.FindElement(By.WpfId("MemberList")).FindElement(By.ClassName("DataGridRow"));
|
||||||
Assert.Multiple(() => {
|
using (Assert.EnterMultipleScope()) {
|
||||||
Assert.That(memberListRow, Is.Not.Null);
|
Assert.That(memberListRow, Is.Not.Null);
|
||||||
Assert.That(memberListRow.FindElement(By.Name("9999 ")), Is.Not.Null);
|
Assert.That(memberListRow.FindElement(By.Name("9999 ")), Is.Not.Null);
|
||||||
Assert.That(memberListRow.FindElement(By.Name("Norbert")), Is.Not.Null);
|
Assert.That(memberListRow.FindElement(By.Name("Norbert")), Is.Not.Null);
|
||||||
Assert.That(memberListRow.FindElement(By.Name("Neuling")), Is.Not.Null);
|
Assert.That(memberListRow.FindElement(By.Name("Neuling")), Is.Not.Null);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -128,12 +128,12 @@ namespace Tests.E2ETests {
|
|||||||
Assert.That(memberListRows, Has.Count.EqualTo(1));
|
Assert.That(memberListRows, Has.Count.EqualTo(1));
|
||||||
|
|
||||||
var memberListRow = memberListRows.First();
|
var memberListRow = memberListRows.First();
|
||||||
Assert.Multiple(() => {
|
using (Assert.EnterMultipleScope()) {
|
||||||
Assert.That(memberListRow, Is.Not.Null);
|
Assert.That(memberListRow, Is.Not.Null);
|
||||||
Assert.That(memberListRow.FindElement(By.Name("9999 ")), Is.Not.Null);
|
Assert.That(memberListRow.FindElement(By.Name("9999 ")), Is.Not.Null);
|
||||||
Assert.That(memberListRow.FindElement(By.Name("Norbert")), Is.Not.Null);
|
Assert.That(memberListRow.FindElement(By.Name("Norbert")), Is.Not.Null);
|
||||||
Assert.That(memberListRow.FindElement(By.Name("Neuling")), Is.Not.Null);
|
Assert.That(memberListRow.FindElement(By.Name("Neuling")), Is.Not.Null);
|
||||||
});
|
}
|
||||||
|
|
||||||
Window.FindElement(By.WpfId("DeleteMemberButton")).Click();
|
Window.FindElement(By.WpfId("DeleteMemberButton")).Click();
|
||||||
var dialog = Session.CreateWindowDriver("DeleteMemberDialog");
|
var dialog = Session.CreateWindowDriver("DeleteMemberDialog");
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
-- inserts for HelperTests.BillingTest
|
-- inserts for HelperTests.BillingTest
|
||||||
|
|
||||||
INSERT INTO wine_cultivation (cultid, name, description) VALUES
|
INSERT INTO wine_cultivation (cultid, name, description, organic) VALUES
|
||||||
('KIP', 'KIP', 'Kontrollierte Integrierte Produktion'),
|
('KIP', 'KIP', 'Kontrollierte Integrierte Produktion', FALSE),
|
||||||
('B', 'Bio', 'AT-BIO-302');
|
('B', 'Bio', 'Biologische Produktion', TRUE);
|
||||||
|
|
||||||
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
||||||
('K', 'Kabinett', TRUE, NULL, FALSE, 0),
|
('K', 'Kabinett', TRUE, NULL, FALSE, 0),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
-- inserts for DocumentTests
|
-- inserts for DocumentTests
|
||||||
|
|
||||||
INSERT INTO wine_cultivation (cultid, name, description) VALUES
|
INSERT INTO wine_cultivation (cultid, name, description, organic) VALUES
|
||||||
('B', 'Bio', 'AT-BIO-302');
|
('B', 'Bio', 'Biologische Produktion', TRUE);
|
||||||
|
|
||||||
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
||||||
('K', 'Kabinett', TRUE, NULL, FALSE, 0);
|
('K', 'Kabinett', TRUE, NULL, FALSE, 0);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
-- inserts for E2ETests
|
-- inserts for E2ETests
|
||||||
|
|
||||||
INSERT INTO wine_cultivation (cultid, name, description) VALUES
|
INSERT INTO wine_cultivation (cultid, name, description, organic) VALUES
|
||||||
('KIP', 'KIP', 'Kontrollierte Integrierte Produktion'),
|
('KIP', 'KIP', 'Kontrollierte Integrierte Produktion', FALSE),
|
||||||
('B', 'Bio', 'AT-BIO-302');
|
('B', 'Bio', 'Biologische Produktion', TRUE);
|
||||||
|
|
||||||
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
||||||
('K', 'Kabinett', TRUE, NULL, FALSE, 0),
|
('K', 'Kabinett', TRUE, NULL, FALSE, 0),
|
||||||
|
|||||||
@@ -66,11 +66,11 @@ INSERT INTO wb_kg (kgnr, glnr) VALUES
|
|||||||
(15216, 2),
|
(15216, 2),
|
||||||
(15224, 2);
|
(15224, 2);
|
||||||
|
|
||||||
INSERT INTO member (mgnr, given_name, name, zwstid, volllieferant, buchführend, country, postal_dest, address, default_kgnr, iban, lfbis_nr, ustid_nr) VALUES
|
INSERT INTO member (mgnr, given_name, name, zwstid, volllieferant, buchführend, country, postal_dest, address, default_kgnr, iban, lfbis_nr, ustid_nr, org_auth_code) VALUES
|
||||||
(101, 'Max', 'Mustermann', 'X', FALSE, FALSE, 40, 222303524, 'Winzerstraße 1', 06109, 'AT811234567890123457', '0123463', NULL ),
|
(101, 'Max', 'Mustermann', 'X', FALSE, FALSE, 40, 222303524, 'Winzerstraße 1', 06109, 'AT811234567890123457', '0123463', NULL , NULL ),
|
||||||
(102, 'Wernhardt', 'Weinbauer', 'X', FALSE, FALSE, 40, 222303524, 'Winzerstraße 2', 06109, 'AT541234567890123458', '0123471', 'ATU12345684'),
|
(102, 'Wernhardt', 'Weinbauer', 'X', FALSE, FALSE, 40, 222303524, 'Winzerstraße 2', 06109, 'AT541234567890123458', '0123471', 'ATU12345684', NULL ),
|
||||||
(103, 'Matthäus', 'Musterbauer', 'X', FALSE, FALSE, 40, 212005138, 'Brünner Straße 10', 15224, 'AT271234567890123459', '0123480', NULL ),
|
(103, 'Matthäus', 'Musterbauer', 'X', FALSE, FALSE, 40, 212005138, 'Brünner Straße 10', 15224, 'AT271234567890123459', '0123480', NULL , 'AT-BIO-302'),
|
||||||
(104, 'Waltraud', 'Winzer', 'X', FALSE, TRUE , 40, 212005138, 'Wiener Straße 15', 15224, 'AT971234567890123460', '0123498', 'ATU12345693');
|
(104, 'Waltraud', 'Winzer', 'X', FALSE, TRUE , 40, 212005138, 'Wiener Straße 15', 15224, 'AT971234567890123460', '0123498', 'ATU12345693', NULL );
|
||||||
|
|
||||||
INSERT INTO member_billing_address (mgnr, name, country, postal_dest, address) VALUES
|
INSERT INTO member_billing_address (mgnr, name, country, postal_dest, address) VALUES
|
||||||
(102, 'W&B Weinbauer GesbR', 40, 222303524, 'Winzerstraße 2'),
|
(102, 'W&B Weinbauer GesbR', 40, 222303524, 'Winzerstraße 2'),
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
-- inserts for ServiceTests
|
-- inserts for ServiceTests
|
||||||
|
|
||||||
|
INSERT INTO wine_cultivation (cultid, name, description, organic) VALUES
|
||||||
INSERT INTO wine_cultivation (cultid, name, description) VALUES
|
('B', 'Bio', 'Biologische Produktion', TRUE);
|
||||||
('B', 'Bio', 'AT-BIO-302');
|
|
||||||
|
|
||||||
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
||||||
('K', 'Kabinett', TRUE, NULL, FALSE, 0);
|
('K', 'Kabinett', TRUE, NULL, FALSE, 0);
|
||||||
|
|||||||
+3
-3
@@ -19,12 +19,12 @@
|
|||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.0" />
|
||||||
<PackageReference Include="Appium.WebDriver" Version="4.4.5" />
|
<PackageReference Include="Appium.WebDriver" Version="4.4.5" />
|
||||||
<PackageReference Include="NReco.PdfRenderer" Version="1.6.0" />
|
<PackageReference Include="NReco.PdfRenderer" Version="1.6.0" />
|
||||||
<PackageReference Include="NUnit" Version="4.6.1" />
|
<PackageReference Include="NUnit" Version="4.6.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="6.3.0" />
|
||||||
<PackageReference Include="NUnit.Analyzers" Version="4.14.0">
|
<PackageReference Include="NUnit.Analyzers" Version="4.15.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
"""));
|
"""));
|
||||||
Assert.That(text, Contains.Substring("0123463")); // Betriebsnummer
|
Assert.That(text, Contains.Substring("0123463")); // Betriebsnummer
|
||||||
Assert.That(text, Contains.Substring("pauschaliert"));
|
Assert.That(text, Contains.Substring("pauschaliert"));
|
||||||
Assert.That(text, Contains.Substring($"Wolkersdorf, am {Elwig.Helpers.Utils.Today:dd.MM.yyyy}"));
|
Assert.That(text, Contains.Substring($"Wolkersdorf, am {DateTime.Today:dd.MM.yyyy}"));
|
||||||
Assert.That(text, Contains.Substring("Traubengutschrift Max Mustermann – Probevariante"));
|
Assert.That(text, Contains.Substring("Traubengutschrift Max Mustermann – Probevariante"));
|
||||||
Assert.That(text, Contains.Substring("AT81 1234 5678 9012 3457"));
|
Assert.That(text, Contains.Substring("AT81 1234 5678 9012 3457"));
|
||||||
Assert.That(text, Contains.Substring("""
|
Assert.That(text, Contains.Substring("""
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
"""));
|
"""));
|
||||||
Assert.That(text, Contains.Substring("0123463")); // Betriebsnummer
|
Assert.That(text, Contains.Substring("0123463")); // Betriebsnummer
|
||||||
Assert.That(text, Contains.Substring("pauschaliert"));
|
Assert.That(text, Contains.Substring("pauschaliert"));
|
||||||
Assert.That(text, Contains.Substring($"Wolkersdorf, am {Elwig.Helpers.Utils.Today:dd.MM.yyyy}"));
|
Assert.That(text, Contains.Substring($"Wolkersdorf, am {DateTime.Today:dd.MM.yyyy}"));
|
||||||
Assert.That(text, Contains.Substring("Anlieferungsbestätigung 2020"));
|
Assert.That(text, Contains.Substring("Anlieferungsbestätigung 2020"));
|
||||||
Assert.That(text, Contains.Substring("""
|
Assert.That(text, Contains.Substring("""
|
||||||
20201001X001 1 Grüner Veltliner QUW 73 15,0 ungeb.: 3 219 3 219 ☑
|
20201001X001 1 Grüner Veltliner QUW 73 15,0 ungeb.: 3 219 3 219 ☑
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
public async Task Test_01_OneDeliveryPart() {
|
public async Task Test_01_OneDeliveryPart() {
|
||||||
using var doc = await DeliveryNote.Initialize(2020, 1);
|
using var doc = await DeliveryNote.Initialize(2020, 1);
|
||||||
var text = await Utils.GeneratePdfText(doc);
|
var text = await Utils.GeneratePdfText(doc);
|
||||||
Assert.Multiple(() => {
|
using (Assert.EnterMultipleScope()) {
|
||||||
Assert.That(text, Contains.Substring("""
|
Assert.That(text, Contains.Substring("""
|
||||||
MUSTERMANN Max
|
MUSTERMANN Max
|
||||||
Winzerstraße 1
|
Winzerstraße 1
|
||||||
@@ -26,14 +26,14 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
Waage/Terminal: ?/1, ID: 321 – 09:02, 01.10.2020
|
Waage/Terminal: ?/1, ID: 321 – 09:02, 01.10.2020
|
||||||
Brutto: 3 219 kg – Tara: 0 kg – Netto: 3 219 kg – gerebelt gewogen
|
Brutto: 3 219 kg – Tara: 0 kg – Netto: 3 219 kg – gerebelt gewogen
|
||||||
"""));
|
"""));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Test_02_TwoDeliveryParts() {
|
public async Task Test_02_TwoDeliveryParts() {
|
||||||
using var doc = await DeliveryNote.Initialize(2020, 4);
|
using var doc = await DeliveryNote.Initialize(2020, 4);
|
||||||
var text = await Utils.GeneratePdfText(doc);
|
var text = await Utils.GeneratePdfText(doc);
|
||||||
Assert.Multiple(() => {
|
using (Assert.EnterMultipleScope()) {
|
||||||
Assert.That(text, Contains.Substring("""
|
Assert.That(text, Contains.Substring("""
|
||||||
W&B Weinbauer GesbR
|
W&B Weinbauer GesbR
|
||||||
WEINBAUER Wernhardt
|
WEINBAUER Wernhardt
|
||||||
@@ -58,14 +58,14 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
Waage/Terminal: ?/?, ID: ? (gerebelt gewogen)
|
Waage/Terminal: ?/?, ID: ? (gerebelt gewogen)
|
||||||
"""));
|
"""));
|
||||||
Assert.That(text, Contains.Substring("Gesamt: 81 16,5 4 483"));
|
Assert.That(text, Contains.Substring("Gesamt: 81 16,5 4 483"));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Test_03_DeliveryPartsWithAttribute() {
|
public async Task Test_03_DeliveryPartsWithAttribute() {
|
||||||
using var doc = await DeliveryNote.Initialize(2020, 3);
|
using var doc = await DeliveryNote.Initialize(2020, 3);
|
||||||
var text = await Utils.GeneratePdfText(doc);
|
var text = await Utils.GeneratePdfText(doc);
|
||||||
Assert.Multiple(() => {
|
using (Assert.EnterMultipleScope()) {
|
||||||
Assert.That(text, Contains.Substring("""
|
Assert.That(text, Contains.Substring("""
|
||||||
MUSTERMANN Max
|
MUSTERMANN Max
|
||||||
Winzerstraße 1
|
Winzerstraße 1
|
||||||
@@ -95,14 +95,14 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
Waage/Terminal: ?/?, ID: ? (gerebelt gewogen)
|
Waage/Terminal: ?/?, ID: ? (gerebelt gewogen)
|
||||||
"""));
|
"""));
|
||||||
Assert.That(text, Contains.Substring("Gesamt: 81 16,5 6 970"));
|
Assert.That(text, Contains.Substring("Gesamt: 81 16,5 6 970"));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Test_04_DeliveryPartsWithCultivation() {
|
public async Task Test_04_DeliveryPartsWithCultivation() {
|
||||||
using var doc = await DeliveryNote.Initialize(2020, 7);
|
using var doc = await DeliveryNote.Initialize(2020, 7);
|
||||||
var text = await Utils.GeneratePdfText(doc);
|
var text = await Utils.GeneratePdfText(doc);
|
||||||
Assert.Multiple(() => {
|
using (Assert.EnterMultipleScope()) {
|
||||||
Assert.That(text, Contains.Substring("""
|
Assert.That(text, Contains.Substring("""
|
||||||
MUSTERBAUER Matthäus
|
MUSTERBAUER Matthäus
|
||||||
Brünner Straße 10
|
Brünner Straße 10
|
||||||
@@ -115,20 +115,20 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht"));
|
Assert.That(text, Contains.Substring("Das Mitglied erklärt, dass die gelieferte Ware dem österreichischen Weingesetz entspricht"));
|
||||||
Assert.That(text, Contains.Substring("""
|
Assert.That(text, Contains.Substring("""
|
||||||
1 Grüner Veltliner Wein 80 16,3 3 198
|
1 Grüner Veltliner Wein 80 16,3 3 198
|
||||||
Bewirtschaftung: Bio (AT-BIO-302)
|
Bewirtschaftung: Bio (Biologische Produktion) – Kontrollstelle: AT-BIO-302
|
||||||
Herkunft: Österreich
|
Herkunft: Österreich
|
||||||
/ Wolkersdorfer Hochleithen / Wolkersdorf im Weinviertel / KG Wolkersdorf
|
/ Wolkersdorfer Hochleithen / Wolkersdorf im Weinviertel / KG Wolkersdorf
|
||||||
Waage/Terminal: ?/?, ID: ? (gerebelt gewogen)
|
Waage/Terminal: ?/?, ID: ? (gerebelt gewogen)
|
||||||
"""));
|
"""));
|
||||||
Assert.That(text, Contains.Substring("""
|
Assert.That(text, Contains.Substring("""
|
||||||
2 Grüner Veltliner Qualitätswein 75 15,4 2 134
|
2 Grüner Veltliner Qualitätswein 75 15,4 2 134
|
||||||
Bewirtschaftung: Bio (AT-BIO-302)
|
Bewirtschaftung: Bio (Biologische Produktion) – Kontrollstelle: AT-BIO-302
|
||||||
Herkunft: Österreich / Weinland / Niederösterreich
|
Herkunft: Österreich / Weinland / Niederösterreich
|
||||||
/ Wolkersdorfer Hochleithen / Wolkersdorf im Weinviertel / KG Wolkersdorf
|
/ Wolkersdorfer Hochleithen / Wolkersdorf im Weinviertel / KG Wolkersdorf
|
||||||
Waage/Terminal: ?/?, ID: ? (gerebelt gewogen)
|
Waage/Terminal: ?/?, ID: ? (gerebelt gewogen)
|
||||||
"""));
|
"""));
|
||||||
Assert.That(text, Contains.Substring("Gesamt: 78 15,9 5 332"));
|
Assert.That(text, Contains.Substring("Gesamt: 78 15,9 5 332"));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ namespace Tests.UnitTests.DocumentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[OneTimeSetUp]
|
[OneTimeSetUp]
|
||||||
public async Task SetupPrinting() {
|
public void SetupPrinting() {
|
||||||
await Pdf.Init();
|
Pdf.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
[OneTimeTearDown]
|
[OneTimeTearDown]
|
||||||
public async Task TeardownPrinting() {
|
public void TeardownPrinting() {
|
||||||
await Pdf.Cleanup();
|
Pdf.Cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -842,5 +842,151 @@ namespace Tests.UnitTests.ServiceTests {
|
|||||||
Assert.That(await ctx.Deliveries.FindAsync(2022, 2), Is.Null);
|
Assert.That(await ctx.Deliveries.FindAsync(2022, 2), Is.Null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly DateTime[] DeliveryDates = [
|
||||||
|
new(2020, 10, 1, 17, 45, 0),
|
||||||
|
new(2020, 10, 1, 18, 30, 0),
|
||||||
|
|
||||||
|
new(2020, 10, 2, 8, 34, 0),
|
||||||
|
new(2020, 10, 2, 9, 45, 0),
|
||||||
|
new(2020, 10, 2, 10, 19, 0),
|
||||||
|
new(2020, 10, 2, 11, 22, 0),
|
||||||
|
new(2020, 10, 2, 13, 39, 0),
|
||||||
|
new(2020, 10, 2, 14, 2, 0),
|
||||||
|
new(2020, 10, 2, 15, 55, 0),
|
||||||
|
new(2020, 10, 2, 16, 28, 0),
|
||||||
|
new(2020, 10, 2, 17, 13, 0),
|
||||||
|
new(2020, 10, 2, 18, 10, 0),
|
||||||
|
|
||||||
|
new(2020, 10, 3, 8, 13, 0),
|
||||||
|
new(2020, 10, 3, 9, 39, 0),
|
||||||
|
new(2020, 10, 3, 10, 20, 0),
|
||||||
|
new(2020, 10, 3, 11, 46, 0),
|
||||||
|
new(2020, 10, 3, 13, 56, 0),
|
||||||
|
new(2020, 10, 3, 14, 4, 0),
|
||||||
|
new(2020, 10, 3, 15, 33, 0),
|
||||||
|
new(2020, 10, 3, 16, 23, 0),
|
||||||
|
new(2020, 10, 3, 17, 18, 0),
|
||||||
|
new(2020, 10, 3, 18, 19, 0),
|
||||||
|
new(2020, 10, 3, 19, 10, 0),
|
||||||
|
new(2020, 10, 3, 20, 25, 0),
|
||||||
|
|
||||||
|
new(2020, 10, 4, 5, 57, 0),
|
||||||
|
new(2020, 10, 4, 6, 13, 0),
|
||||||
|
new(2020, 10, 4, 7, 42, 0),
|
||||||
|
new(2020, 10, 4, 8, 34, 0),
|
||||||
|
new(2020, 10, 4, 9, 45, 0),
|
||||||
|
new(2020, 10, 4, 10, 19, 0),
|
||||||
|
new(2020, 10, 4, 11, 22, 0),
|
||||||
|
new(2020, 10, 4, 13, 39, 0),
|
||||||
|
new(2020, 10, 4, 14, 2, 0),
|
||||||
|
new(2020, 10, 4, 15, 55, 0),
|
||||||
|
new(2020, 10, 4, 16, 28, 0),
|
||||||
|
new(2020, 10, 4, 17, 13, 0),
|
||||||
|
new(2020, 10, 4, 18, 10, 0),
|
||||||
|
|
||||||
|
new(2020, 10, 5, 5, 57, 0),
|
||||||
|
new(2020, 10, 5, 6, 13, 0),
|
||||||
|
new(2020, 10, 5, 7, 42, 0),
|
||||||
|
new(2020, 10, 5, 8, 34, 0),
|
||||||
|
new(2020, 10, 5, 9, 45, 0),
|
||||||
|
new(2020, 10, 5, 10, 19, 0),
|
||||||
|
new(2020, 10, 5, 11, 22, 0),
|
||||||
|
new(2020, 10, 5, 13, 39, 0),
|
||||||
|
new(2020, 10, 5, 14, 2, 0),
|
||||||
|
new(2020, 10, 5, 15, 55, 0),
|
||||||
|
new(2020, 10, 5, 16, 28, 0),
|
||||||
|
new(2020, 10, 5, 17, 13, 0),
|
||||||
|
new(2020, 10, 5, 18, 10, 0),
|
||||||
|
new(2020, 10, 5, 19, 10, 0),
|
||||||
|
new(2020, 10, 5, 20, 25, 0),
|
||||||
|
|
||||||
|
new(2020, 10, 6, 16, 23, 0),
|
||||||
|
new(2020, 10, 6, 22, 24, 0),
|
||||||
|
new(2020, 10, 6, 23, 45, 0),
|
||||||
|
new(2020, 10, 7, 0, 32, 0),
|
||||||
|
new(2020, 10, 7, 1, 12, 0),
|
||||||
|
new(2020, 10, 7, 2, 16, 0),
|
||||||
|
new(2020, 10, 7, 3, 24, 0),
|
||||||
|
new(2020, 10, 7, 4, 9, 0),
|
||||||
|
new(2020, 10, 7, 5, 57, 0),
|
||||||
|
new(2020, 10, 7, 6, 41, 0),
|
||||||
|
new(2020, 10, 7, 7, 10, 0),
|
||||||
|
|
||||||
|
new(2020, 10, 7, 17, 23, 0),
|
||||||
|
new(2020, 10, 7, 18, 16, 0),
|
||||||
|
new(2020, 10, 7, 19, 39, 0),
|
||||||
|
new(2020, 10, 7, 20, 31, 0),
|
||||||
|
new(2020, 10, 7, 21, 23, 0),
|
||||||
|
new(2020, 10, 7, 22, 24, 0),
|
||||||
|
new(2020, 10, 7, 23, 45, 0),
|
||||||
|
new(2020, 10, 8, 0, 32, 0),
|
||||||
|
new(2020, 10, 8, 1, 12, 0),
|
||||||
|
new(2020, 10, 8, 2, 16, 0),
|
||||||
|
new(2020, 10, 8, 3, 24, 0),
|
||||||
|
new(2020, 10, 8, 4, 9, 0),
|
||||||
|
new(2020, 10, 8, 5, 57, 0),
|
||||||
|
new(2020, 10, 8, 6, 41, 0),
|
||||||
|
new(2020, 10, 8, 7, 10, 0),
|
||||||
|
|
||||||
|
new(2020, 10, 9, 7, 53, 0),
|
||||||
|
new(2020, 10, 9, 12, 36, 0),
|
||||||
|
new(2020, 10, 9, 16, 26, 0),
|
||||||
|
new(2020, 10, 9, 20, 19, 0),
|
||||||
|
];
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_GetFilterToday_01_Empty() {
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 10), DeliveryDates),
|
||||||
|
Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_GetFilterToday_02_Normal() {
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 2), DeliveryDates),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 2, 8, 0, 0), new DateTime(2020, 10, 2, 19, 0, 0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_GetFilterToday_03_Overtime() {
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 3), DeliveryDates),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 3, 8, 0, 0), new DateTime(2020, 10, 3, 21, 0, 0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_GetFilterToday_04_EarlyStart() {
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 4), DeliveryDates),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 4, 5, 0, 0), new DateTime(2020, 10, 4, 19, 0, 0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_GetFilterToday_05_EarlyStartAndOvertime() {
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 5), DeliveryDates),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 5, 5, 0, 0), new DateTime(2020, 10, 5, 21, 0, 0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_GetFilterToday_06_NightShift() {
|
||||||
|
using (Assert.EnterMultipleScope()) {
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 6), DeliveryDates),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 6, 22, 0, 0), new DateTime(2020, 10, 7, 0, 0, 0))));
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 7), DeliveryDates.Where(d => d <= new DateTime(2020, 10, 7, 12, 0, 0))),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 6, 22, 0, 0), new DateTime(2020, 10, 7, 8, 0, 0))));
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 7), DeliveryDates.Where(d => d <= new DateTime(2020, 10, 7, 12, 0, 0)).Append(new(2020, 10, 7, 15, 10, 0))),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 7, 15, 0, 0), new DateTime(2020, 10, 7, 16, 0, 0))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Test_GetFilterToday_07_EarlyStartNightShift() {
|
||||||
|
using (Assert.EnterMultipleScope()) {
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 7), DeliveryDates),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 7, 17, 0, 0), new DateTime(2020, 10, 8, 0, 0, 0))));
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 8), DeliveryDates),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 7, 17, 0, 0), new DateTime(2020, 10, 8, 8, 0, 0))));
|
||||||
|
Assert.That(DeliveryService.GetFilterToday(new(2020, 10, 8), DeliveryDates.Append(new(2020, 10, 8, 15, 10, 0))),
|
||||||
|
Is.EqualTo((new DateTime(2020, 10, 8, 15, 0, 0), new DateTime(2020, 10, 8, 16, 0, 0))));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
curl --fail -s -L "https://elwig.at/files/create.sql?v=41" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"
|
curl --fail -s -L "https://elwig.at/files/create.sql?v=42" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"
|
||||||
|
|||||||
Reference in New Issue
Block a user