Compare commits
171 Commits
d6059e724b
...
v0.1.0
Author | SHA1 | Date | |
---|---|---|---|
c933fa3423 | |||
0958728418 | |||
cb8d405dcf | |||
6f4e3474b8 | |||
545622a2ab | |||
3a0736a73f | |||
048a7e0f13 | |||
cad475fc20 | |||
8b0f1e35c8 | |||
67dbf62eb7 | |||
9b59208373 | |||
146560c796 | |||
286e3515d4 | |||
c1d3a9042d | |||
e656bde54d | |||
33d763d968 | |||
56a0eb794e | |||
effc9f9230 | |||
4817a2aedc | |||
b67628c566 | |||
5aa8e45652 | |||
1f377483a5 | |||
9b84452b86 | |||
75e6c1bd5d | |||
a96a05d3de | |||
3f09e62c74 | |||
a98bc3ae4a | |||
93d4365d36 | |||
33e10d00bf | |||
7c2bf711c7 | |||
ff7fe34d5b | |||
973f49fabc | |||
8899e8bd32 | |||
6dda9e09cf | |||
c0a6f16374 | |||
ba71618463 | |||
6261217e7c | |||
5dd56d9666 | |||
83a82c17c6 | |||
03cf88a058 | |||
4bb0acb4a2 | |||
04db3fe0c5 | |||
28bb8f2d3f | |||
5074f945cf | |||
3a12837706 | |||
cfa1f1eeea | |||
85e4ccd215 | |||
0e13e269d0 | |||
4aa8fe2e2d | |||
a94bf651de | |||
00078a1f4e | |||
ded7dbec06 | |||
8534ff6bba | |||
f735da0059 | |||
5093706a4a | |||
8f7d699b4e | |||
b87710cc67 | |||
0d609c1013 | |||
58235e3b02 | |||
3ab2b8a8dc | |||
258b2b3c5b | |||
9e1ea293aa | |||
12a81bd924 | |||
84edec2b54 | |||
c871dea873 | |||
99a6f53307 | |||
f8af155c60 | |||
244de52b19 | |||
0ea77656e3 | |||
65bcc7bbb1 | |||
cbb57f7039 | |||
644362f492 | |||
b11dcd273d | |||
041e674af9 | |||
c65ffaf161 | |||
e7cb698026 | |||
2800b8b3e6 | |||
94a0adc55a | |||
a24edfffa3 | |||
dfda5e36c8 | |||
29b8f046f4 | |||
8290b57cd4 | |||
e1630e9919 | |||
91a20662da | |||
7af27ab5de | |||
f4c24d9578 | |||
1226e85c4a | |||
d05eb145b6 | |||
a984c4f16c | |||
921871cab1 | |||
baf694621c | |||
75dfdb155b | |||
704337aa1d | |||
a62fb9ab16 | |||
d06ea4f045 | |||
69d89ecd56 | |||
4571b06279 | |||
c68c798b49 | |||
bfedf436d8 | |||
fd7a15bc5a | |||
5cee928978 | |||
75322da405 | |||
9ba45e58f6 | |||
d43633cb65 | |||
cf1b1f7865 | |||
df4e254305 | |||
05f9e94260 | |||
75b87719b3 | |||
2eef0496ba | |||
9584f12fc5 | |||
8c0df674ec | |||
592df9e56d | |||
c0e584143e | |||
cb2534d678 | |||
db5f6dbef0 | |||
5c2f7ae69a | |||
7c2a0ca1a6 | |||
f90319fc9f | |||
fd26ee4f52 | |||
e8919cc629 | |||
8d9e713c81 | |||
ad538ba767 | |||
79a92be9d2 | |||
8b55490b76 | |||
c1b8b68513 | |||
70ad8188c4 | |||
ee7aaf81d9 | |||
a6699320ef | |||
1abe8de810 | |||
4c402d81ab | |||
df7f2174e5 | |||
577a3a0a63 | |||
ad47aa2a79 | |||
fb077bc557 | |||
9229f27cf7 | |||
7468af3970 | |||
27abf559e8 | |||
5b9aedd1a4 | |||
3315b758ad | |||
4cd1114def | |||
2281ec80ae | |||
dc236bab62 | |||
3bf7d65dea | |||
2ee7e90bcc | |||
d2c0884b44 | |||
2210b6b829 | |||
92ff8a5dc9 | |||
4d78cdd8a5 | |||
f49f7534e9 | |||
b70608966d | |||
bfe6363d95 | |||
9e61ead3ad | |||
c8f0537976 | |||
54aaf9fda0 | |||
735f16731e | |||
4b52af6fe9 | |||
0dfb42a5ce | |||
3f11a498bc | |||
351a0b8d57 | |||
a65345c0d9 | |||
af6bcb4a96 | |||
35421bb585 | |||
4456b2228d | |||
77781d227c | |||
15f999869a | |||
8ffd478ca9 | |||
7b252a5bb5 | |||
26ec59507d | |||
50d0de57f5 | |||
0365669ea2 | |||
6acdbee154 |
76
Elwig.sln
76
Elwig.sln
@@ -4,22 +4,88 @@ VisualStudioVersion = 17.3.32929.385
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elwig", "Elwig\Elwig.csproj", "{00868460-16F6-4B48-AA9B-998F6263693B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{AF4B84F8-08E6-409C-9E94-D7D990469597}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}"
|
||||
EndProject
|
||||
Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "Installer", "Installer\Installer.wixproj", "{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}"
|
||||
EndProject
|
||||
Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "Setup", "Setup\Setup.wixproj", "{952E309C-2090-4978-8996-65900D8E8FA4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AF4B84F8-08E6-409C-9E94-D7D990469597}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AF4B84F8-08E6-409C-9E94-D7D990469597}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AF4B84F8-08E6-409C-9E94-D7D990469597}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AF4B84F8-08E6-409C-9E94-D7D990469597}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{00868460-16F6-4B48-AA9B-998F6263693B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{30D7700A-7B0A-4E5D-B839-B4C1D95E307E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Debug|x64.Build.0 = Debug|x64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Debug|x86.Build.0 = Debug|x86
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Release|Any CPU.Build.0 = Release|x64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Release|x64.ActiveCfg = Release|x64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Release|x64.Build.0 = Release|x64
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Release|x86.ActiveCfg = Release|x86
|
||||
{4A82C9C0-EB6D-409C-B0B2-09A5F727D16F}.Release|x86.Build.0 = Release|x86
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Debug|x64.Build.0 = Debug|x64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Debug|x86.Build.0 = Debug|x86
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Release|Any CPU.Build.0 = Release|x64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Release|x64.ActiveCfg = Release|x64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Release|x64.Build.0 = Release|x64
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Release|x86.ActiveCfg = Release|x86
|
||||
{952E309C-2090-4978-8996-65900D8E8FA4}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@@ -2,32 +2,105 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Elwig"
|
||||
xmlns:controls="clr-namespace:Elwig.Controls"
|
||||
StartupUri="Windows\MainWindow.xaml"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019">
|
||||
<Application.Resources>
|
||||
<!--<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ui:ThemeResources />
|
||||
<ui:XamlControlsResources />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>-->
|
||||
<DataTemplate x:Key="PostalDestComboBoxTemplate">
|
||||
<controls:BoolToStringConverter x:Key="BoolToStarConverter" FalseValue="" TrueValue="*"/>
|
||||
|
||||
<DataTemplate x:Key="PostalDestTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Dest}"/>
|
||||
<TextBlock Text=" ("/>
|
||||
<TextBlock Text="{Binding Ort.Name}"/>
|
||||
<TextBlock Text=")"/>
|
||||
<TextBlock Text="{Binding Ort.Name, StringFormat='{} ({0})'}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="BranchTemplate">
|
||||
<DataTemplate x:Key="KgNrTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
<TextBlock Text="{Binding KgNr, StringFormat='{} ({0:00000})'}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="MemberAdminNameTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding MgNr}" MinWidth="48" Margin="0,0,10,0" TextAlignment="Right"/>
|
||||
<TextBlock Text="{Binding AdministrativeName1}" MinWidth="100" Margin="0,0,5,0"/>
|
||||
<TextBlock Text="{Binding AdministrativeName2}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<ControlTemplate x:Key="WineVarietyTemplateSimple">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="WineVarietyTemplateExtended">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding SortId}" MinWidth="36" Margin="0,0,10,0"/>
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
<TextBlock Text="{Binding CommentFormat}" FontSize="10" VerticalAlignment="Bottom" Margin="0,0,0,2"/>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
<DataTemplate x:Key="WineVarietyTemplate">
|
||||
<Control x:Name="Control" Focusable="False" Template="{StaticResource WineVarietyTemplateExtended}"/>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="{x:Null}">
|
||||
<Setter TargetName="Control" Property="Template" Value="{StaticResource WineVarietyTemplateSimple}"/>
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="KgTemplate">
|
||||
|
||||
<DataTemplate x:Key="ModifierTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Name}" MinWidth="250" Margin="0,0,10,0"/>
|
||||
<TextBlock Text="{Binding ValueStr}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="WineAttributeTemplate">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Name}" MinWidth="150" Margin="0,0,10,0"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<ControlTemplate x:Key="WineQualityLevelTemplateSimple">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="WineQualityLevelTemplateExtended">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding IsPredicate, Converter={StaticResource BoolToStarConverter}}" MinWidth="6"/>
|
||||
<TextBlock Text="{Binding Name}" MinWidth="100" Margin="0,0,10,0"/>
|
||||
<TextBlock Text="{Binding MinKmwStr}"/>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
<DataTemplate x:Key="WineQualityLevelTemplate">
|
||||
<Control x:Name="Control" Focusable="False" Template="{StaticResource WineQualityLevelTemplateExtended}"/>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="{x:Null}">
|
||||
<Setter TargetName="Control" Property="Template" Value="{StaticResource WineQualityLevelTemplateSimple}"/>
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
|
||||
<ControlTemplate x:Key="WineOriginTemplateSimple">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="WineOriginTemplateExtended">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding HkIdLevel}" MinWidth="70" Margin="0,0,10,0"/>
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
<DataTemplate x:Key="WineOriginTemplate">
|
||||
<Control x:Name="Control" Focusable="False" Template="{StaticResource WineOriginTemplateExtended}"/>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="{x:Null}">
|
||||
<Setter TargetName="Control" Property="Template" Value="{StaticResource WineOriginTemplateSimple}"/>
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
@@ -8,48 +8,93 @@ using Elwig.Helpers;
|
||||
using Elwig.Helpers.Weighing;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Threading;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Elwig {
|
||||
public partial class App : Application {
|
||||
|
||||
public static readonly string DataPath = @"C:\ProgramData\Elwig\";
|
||||
public static readonly string ExePath = @"C:\Program Files\Elwig\";
|
||||
public static readonly string TempPath = Path.Combine(Path.GetTempPath(), "Elwig");
|
||||
public static readonly Config Config = new(DataPath + "config.ini");
|
||||
public static IEnumerable<IScale> Scales { get; private set; }
|
||||
|
||||
public static string ZwstId { get; private set; }
|
||||
public static string BranchName { get; private set; }
|
||||
public static int? BranchPlz { get; private set; }
|
||||
public static string? BranchOrt { get; private set; }
|
||||
public static string? BranchAddress { get; private set; }
|
||||
public static string? BranchPhoneNr { get; private set; }
|
||||
public static string? BranchFaxNr { get; private set; }
|
||||
public static string? BranchMobileNr { get; private set; }
|
||||
public static IList<IScale> Scales { get; private set; }
|
||||
public static ClientParameters Client { get; private set; }
|
||||
|
||||
public static bool IsPrintingReady => Documents.Html.IsReady && Documents.Pdf.IsReady;
|
||||
public static Dispatcher MainDispatcher { get; private set; }
|
||||
|
||||
public App() : base() {
|
||||
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
||||
Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "Elwig"));
|
||||
Directory.CreateDirectory(App.TempPath);
|
||||
Directory.CreateDirectory(DataPath);
|
||||
MainDispatcher = Dispatcher;
|
||||
Scales = Array.Empty<IScale>();
|
||||
}
|
||||
|
||||
protected override void OnStartup(StartupEventArgs evt) {
|
||||
var locale = new CultureInfo("de-AT");
|
||||
locale.NumberFormat.CurrencyGroupSeparator = "\u202f";
|
||||
locale.NumberFormat.NumberGroupSeparator = "\u202f";
|
||||
locale.NumberFormat.PercentGroupSeparator = "\u202f";
|
||||
Thread.CurrentThread.CurrentCulture = locale;
|
||||
Thread.CurrentThread.CurrentUICulture = locale;
|
||||
CultureInfo.DefaultThreadCurrentCulture = locale;
|
||||
CultureInfo.DefaultThreadCurrentUICulture = locale;
|
||||
FrameworkElement.LanguageProperty.OverrideMetadata(
|
||||
typeof(FrameworkElement),
|
||||
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))
|
||||
);
|
||||
|
||||
Dictionary<string, (string, string, int?, string?, string?, string?, string?, string?)> branches = new();
|
||||
using (var ctx = new AppDbContext()) {
|
||||
if (!ctx.Database.CanConnect()) {
|
||||
MessageBox.Show($"Invalid Database:\n\n{Config.DatabaseFile}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
try {
|
||||
if (!ctx.Database.CanConnect()) {
|
||||
MessageBox.Show($"Invalid Database:\n\n{Config.DatabaseFile}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Shutdown();
|
||||
return;
|
||||
} else {
|
||||
branches = ctx.Branches.ToDictionary(b => b.Name.ToLower(), b => (b.ZwstId, b.Name, b.PostalDest?.AtPlz?.Plz, b.PostalDest?.AtPlz?.Dest, b.Address, b.PhoneNr, b.FaxNr, b.MobileNr));
|
||||
try {
|
||||
Client = new(ctx);
|
||||
} catch (Exception e) {
|
||||
MessageBox.Show($"Fehler beim Laden der Mandantendaten:\n\n{e.Message}", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
MessageBox.Show($"Invalid Database:\n\n{e.Message}", "Invalid Database", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Utils.RunBackground("HTML Initialization", () => Documents.Html.Init(PrintingReadyChanged));
|
||||
Utils.RunBackground("PDF Initialization", () => Documents.Pdf.Init(PrintingReadyChanged));
|
||||
|
||||
var list = new LinkedList<IScale>();
|
||||
var list = new List<IScale>();
|
||||
foreach (var s in Config.Scales) {
|
||||
try {
|
||||
var scaleNr = int.Parse(s[0]);
|
||||
var type = s[1].ToLower();
|
||||
var id = s[0];
|
||||
var type = s[1]?.ToLower();
|
||||
var model = s[2];
|
||||
var cnx = s[3];
|
||||
var empty = s[4];
|
||||
var filling = s[5];
|
||||
int? limit = s[6] == null ? null : int.Parse(s[6]);
|
||||
var log = s[7];
|
||||
if (type == "systec") {
|
||||
list.AddLast(new SystecScale(scaleNr, model, cnx, empty, filling, limit));
|
||||
list.Add(new SystecScale(id, model, cnx, empty, filling, limit, log));
|
||||
} else {
|
||||
throw new ArgumentException($"Invalid scale type: \"{type}\"");
|
||||
}
|
||||
@@ -59,6 +104,36 @@ namespace Elwig {
|
||||
}
|
||||
Scales = list;
|
||||
|
||||
if (Config.Branch != null) {
|
||||
if (!branches.ContainsKey(Config.Branch.ToLower())) {
|
||||
MessageBox.Show("Invalid branch name in config!", "Invalid Branch Config", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Shutdown();
|
||||
} else {
|
||||
var entry = branches[Config.Branch.ToLower()];
|
||||
ZwstId = entry.Item1;
|
||||
BranchName = entry.Item2;
|
||||
BranchPlz = entry.Item3;
|
||||
BranchOrt = entry.Item4;
|
||||
BranchAddress = entry.Item5;
|
||||
BranchPhoneNr = entry.Item6;
|
||||
BranchFaxNr = entry.Item7;
|
||||
BranchMobileNr = entry.Item8;
|
||||
}
|
||||
} else if (branches.Count == 1) {
|
||||
var entry = branches.First().Value;
|
||||
ZwstId = entry.Item1;
|
||||
BranchName = entry.Item2;
|
||||
BranchPlz = entry.Item3;
|
||||
BranchOrt = entry.Item4;
|
||||
BranchAddress = entry.Item5;
|
||||
BranchPhoneNr = entry.Item6;
|
||||
BranchFaxNr = entry.Item7;
|
||||
BranchMobileNr = entry.Item8;
|
||||
} else {
|
||||
MessageBox.Show("Unable to determine local branch!", "Invalid Branch Config", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
base.OnStartup(evt);
|
||||
}
|
||||
|
||||
@@ -73,7 +148,7 @@ namespace Elwig {
|
||||
|
||||
protected void OnPrintingReadyChanged(EventArgs evt) {
|
||||
foreach (Window w in Windows) {
|
||||
foreach (var b in Utils.FindAllChildren<Button>(w).Where(b => "Print".Equals(b.Tag))) {
|
||||
foreach (var b in ControlUtils.FindAllChildren<Button>(w).Where(b => "Print".Equals(b.Tag))) {
|
||||
b.IsEnabled = IsPrintingReady;
|
||||
}
|
||||
}
|
||||
|
19
Elwig/Controls/BoolToValueConverter.cs
Normal file
19
Elwig/Controls/BoolToValueConverter.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Elwig.Controls {
|
||||
public class BoolToValueConverter<T> : IValueConverter {
|
||||
public T FalseValue { get; set; }
|
||||
public T TrueValue { get; set; }
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
|
||||
return (bool)value ? TrueValue : FalseValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
|
||||
return value?.Equals(TrueValue) ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
public class BoolToStringConverter : BoolToValueConverter<string> { }
|
||||
}
|
59
Elwig/Dialogs/AbwertenDialog.xaml
Normal file
59
Elwig/Dialogs/AbwertenDialog.xaml
Normal file
@@ -0,0 +1,59 @@
|
||||
<Window x:Class="Elwig.Dialogs.AbwertenDialog"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Topmost="True"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
FocusManager.FocusedElement="{Binding ElementName=WeightInput}"
|
||||
Title="Teillieferung abwerten" Height="190" Width="400">
|
||||
<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="70"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Margin="10,10,10,10" Grid.ColumnSpan="2" TextWrapping="Wrap" TextAlignment="Center">
|
||||
Welche Menge der Teillieferung <Run x:Name="TextLsNr" FontWeight="Bold" Text="20201010A000/1"/><LineBreak/>
|
||||
von <Run x:Name="TextMember" FontWeight="Bold" Text="Max Mustermann"/><LineBreak/>
|
||||
mit <Run x:Name="TextWeight" FontWeight="Bold" Text="1 000 kg"/> soll abgewertet werden?
|
||||
</TextBlock>
|
||||
|
||||
<Label Content="Gewicht:" Margin="10,70,10,10"/>
|
||||
<Grid Grid.Column="1" Width="70" Height="25" Margin="0,70,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<TextBox x:Name="WeightInput" TextAlignment="Right" Padding="2,2,17,2"
|
||||
TextChanged="WeightInput_TextChanged"/>
|
||||
<Label Content="kg" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10" Padding="2,4,2,4"/>
|
||||
</Grid>
|
||||
|
||||
<Button x:Name="ConfirmButton" Content="Bestätigen" Margin="10,10,115,10" Grid.Column="1" IsEnabled="False" IsDefault="True"
|
||||
Click="ConfirmButton_Click"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" Margin="10,10,10,10" Grid.Column="1" IsCancel="True"/>
|
||||
</Grid>
|
||||
</Window>
|
33
Elwig/Dialogs/AbwertenDialog.xaml.cs
Normal file
33
Elwig/Dialogs/AbwertenDialog.xaml.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Elwig.Helpers;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Elwig.Dialogs {
|
||||
public partial class AbwertenDialog : Window {
|
||||
|
||||
public int Weight;
|
||||
|
||||
public AbwertenDialog(string lsnr, string name, int weight) {
|
||||
Weight = weight;
|
||||
InitializeComponent();
|
||||
TextLsNr.Text = lsnr;
|
||||
TextMember.Text = name;
|
||||
TextWeight.Text = $"{weight:N0}\u202fkg";
|
||||
}
|
||||
|
||||
private void ConfirmButton_Click(object sender, RoutedEventArgs evt) {
|
||||
DialogResult = true;
|
||||
Weight = int.Parse(WeightInput.Text);
|
||||
Close();
|
||||
}
|
||||
|
||||
private void UpdateButtons() {
|
||||
ConfirmButton.IsEnabled = int.TryParse(WeightInput.Text, out var w) && w > 0 && w <= Weight;
|
||||
}
|
||||
|
||||
private void WeightInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
Validator.CheckInteger(WeightInput, true, 5);
|
||||
UpdateButtons();
|
||||
}
|
||||
}
|
||||
}
|
60
Elwig/Dialogs/DeliveryExtractionDialog.xaml
Normal file
60
Elwig/Dialogs/DeliveryExtractionDialog.xaml
Normal file
@@ -0,0 +1,60 @@
|
||||
<Window x:Class="Elwig.Dialogs.DeliveryExtractionDialog"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Topmost="True"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
FocusManager.FocusedElement="{Binding ElementName=WeightInput}"
|
||||
Title="Teillieferung extrahieren" Height="210" Width="380">
|
||||
<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="200"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Margin="10,10,0,10" TextWrapping="Wrap">
|
||||
Was soll mit der Teillieferung <Run x:Name="TextLsNr" FontWeight="Bold" Text="20201010A000/1"/><LineBreak/>
|
||||
von <Run x:Name="TextMember" FontWeight="Bold" Text="Max Mustermann"/> geschehen?
|
||||
</TextBlock>
|
||||
<RadioButton x:Name="NewDeliveryButton" Content="Neue Lieferung erstellen"
|
||||
Margin="10,80,0,10" HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||
Checked="Selection_Changed" Unchecked="Selection_Changed"/>
|
||||
<RadioButton x:Name="AddToDeliveryButton" Content="Zu Lieferung hinzufügen"
|
||||
Margin="10,100,0,10" HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||
Checked="Selection_Changed" Unchecked="Selection_Changed"/>
|
||||
|
||||
<ListBox x:Name="DeliveryList" Grid.Column="1" Margin="10,10,10,45"
|
||||
SelectionChanged="DeliveryList_SelectionChanged"/>
|
||||
|
||||
<Button x:Name="ConfirmButton" Content="Bestätigen" Margin="10,10,115,10" Grid.ColumnSpan="2" IsEnabled="False" IsDefault="True"
|
||||
Click="ConfirmButton_Click"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" Margin="10,10,10,10" Grid.ColumnSpan="2" IsCancel="True"/>
|
||||
</Grid>
|
||||
</Window>
|
37
Elwig/Dialogs/DeliveryExtractionDialog.xaml.cs
Normal file
37
Elwig/Dialogs/DeliveryExtractionDialog.xaml.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
|
||||
namespace Elwig.Dialogs {
|
||||
public partial class DeliveryExtractionDialog : Window {
|
||||
|
||||
public string? AddTo;
|
||||
|
||||
public DeliveryExtractionDialog(string lsnr, string name, bool single, IEnumerable<string> lsnrs) {
|
||||
InitializeComponent();
|
||||
TextLsNr.Text = lsnr;
|
||||
TextMember.Text = name;
|
||||
NewDeliveryButton.IsEnabled = !single;
|
||||
DeliveryList.IsEnabled = false;
|
||||
DeliveryList.ItemsSource = lsnrs;
|
||||
}
|
||||
|
||||
private void ConfirmButton_Click(object sender, RoutedEventArgs evt) {
|
||||
DialogResult = true;
|
||||
AddTo = NewDeliveryButton.IsChecked == true ? "new" : DeliveryList.SelectedItem as string;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void UpdateButtons() {
|
||||
ConfirmButton.IsEnabled = NewDeliveryButton.IsChecked == true || (AddToDeliveryButton.IsChecked == true && DeliveryList.SelectedItem != null);
|
||||
DeliveryList.IsEnabled = AddToDeliveryButton.IsChecked == true;
|
||||
}
|
||||
|
||||
private void Selection_Changed(object sender, RoutedEventArgs evt) {
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void DeliveryList_SelectionChanged(object sender, RoutedEventArgs evt) {
|
||||
UpdateButtons();
|
||||
}
|
||||
}
|
||||
}
|
53
Elwig/Dialogs/LinearPriceIncreaseDialog.xaml
Normal file
53
Elwig/Dialogs/LinearPriceIncreaseDialog.xaml
Normal file
@@ -0,0 +1,53 @@
|
||||
<Window x:Class="Elwig.Dialogs.LinearPriceIncreaseDialog"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Topmost="True"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
FocusManager.FocusedElement="{Binding ElementName=PriceInput}"
|
||||
Title="Linear wachsen" Height="140" Width="270">
|
||||
<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="55"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Preis:" Margin="10,20,10,10"/>
|
||||
<Grid Grid.Column="1" Width="145" Height="25" Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<TextBox x:Name="PriceInput" TextAlignment="Right" Padding="2,2,30,2"
|
||||
TextChanged="PriceInput_TextChanged"/>
|
||||
<Label Content="€/kg" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10" Padding="2,4,2,4"/>
|
||||
</Grid>
|
||||
|
||||
<Button x:Name="ConfirmButton" Content="Bestätigen" Margin="17,0,133,10" IsEnabled="False" IsDefault="True"
|
||||
Click="ConfirmButton_Click" Grid.ColumnSpan="2" HorizontalAlignment="Stretch"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" Margin="0,0,20,10" Grid.Column="1" IsCancel="True"/>
|
||||
</Grid>
|
||||
</Window>
|
30
Elwig/Dialogs/LinearPriceIncreaseDialog.xaml.cs
Normal file
30
Elwig/Dialogs/LinearPriceIncreaseDialog.xaml.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Elwig.Helpers;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Elwig.Dialogs {
|
||||
public partial class LinearPriceIncreaseDialog : Window {
|
||||
|
||||
public double Price = 0.0;
|
||||
|
||||
public LinearPriceIncreaseDialog() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ConfirmButton_Click(object sender, RoutedEventArgs evt) {
|
||||
DialogResult = true;
|
||||
Price = double.Parse(PriceInput.Text.Replace("\u202f", ""));
|
||||
Close();
|
||||
}
|
||||
|
||||
private void UpdateButtons(ValidationResult res) {
|
||||
ConfirmButton.IsEnabled = res.IsValid;
|
||||
}
|
||||
|
||||
private void PriceInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
var res = Validator.CheckDecimal(PriceInput, true, 2, 8);
|
||||
UpdateButtons(res);
|
||||
}
|
||||
}
|
||||
}
|
57
Elwig/Dialogs/ManualWeighingDialog.xaml
Normal file
57
Elwig/Dialogs/ManualWeighingDialog.xaml
Normal file
@@ -0,0 +1,57 @@
|
||||
<Window x:Class="Elwig.Dialogs.ManualWeighingDialog"
|
||||
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"
|
||||
mc:Ignorable="d"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Topmost="True"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
FocusManager.FocusedElement="{Binding ElementName=WeightInput}"
|
||||
Title="Handwiegung" Height="170" Width="400">
|
||||
<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="70"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<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">
|
||||
<TextBox x:Name="WeightInput" TextAlignment="Right" Padding="2,2,17,2"
|
||||
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"/>
|
||||
<TextBox x:Name="ReasonInput" Grid.Column="1" Margin="0,50,10,10"
|
||||
TextChanged="ReasonInput_TextChanged"/>
|
||||
|
||||
<Button x:Name="ConfirmButton" Content="Bestätigen" Margin="10,10,115,10" Grid.Column="1" IsEnabled="False" IsDefault="True"
|
||||
Click="ConfirmButton_Click"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" Margin="10,10,10,10" Grid.Column="1" IsCancel="True"/>
|
||||
</Grid>
|
||||
</Window>
|
41
Elwig/Dialogs/ManualWeighingDialog.xaml.cs
Normal file
41
Elwig/Dialogs/ManualWeighingDialog.xaml.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Elwig.Helpers;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Elwig.Dialogs {
|
||||
public partial class ManualWeighingDialog : Window {
|
||||
|
||||
public int Weight = 0;
|
||||
public string? Reason = null;
|
||||
|
||||
public ManualWeighingDialog() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ConfirmButton_Click(object sender, RoutedEventArgs evt) {
|
||||
DialogResult = true;
|
||||
Weight = int.Parse(WeightInput.Text);
|
||||
Reason = Regex.Replace(ReasonInput.Text, @"\s+", "").Trim();
|
||||
if (Reason == "") {
|
||||
Reason = null;
|
||||
} else if (!Reason.EndsWith(".") || !Reason.EndsWith("!") || !Reason.EndsWith("?")) {
|
||||
Reason += ".";
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
private void UpdateButtons() {
|
||||
ConfirmButton.IsEnabled = WeightInput.Text.Length > 0 && ReasonInput.Text.Trim().Length > 0;
|
||||
}
|
||||
|
||||
private void WeightInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
Validator.CheckInteger(WeightInput, true, 5);
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void ReasonInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
UpdateButtons();
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,12 +6,14 @@
|
||||
<div class="info-wrapper">
|
||||
<div class="address-wrapper">
|
||||
<div class="sender">
|
||||
<div>WG Matzen | Schloßstraße 6 | 2243 Matzen</div>
|
||||
<div>E Österreichische Post AG Eco Brief</div>
|
||||
@if (Model.IncludeSender) {
|
||||
<div>@Elwig.App.Client.Sender1</div>
|
||||
<div>@Elwig.App.Client.Sender2</div>
|
||||
}
|
||||
</div>
|
||||
<address>@Model.Address</address>
|
||||
</div>
|
||||
<aside></aside>
|
||||
<aside>@Raw(Model.Aside)</aside>
|
||||
</div>
|
||||
<main>
|
||||
@RenderBody()
|
||||
|
@@ -3,16 +3,33 @@ using Elwig.Models;
|
||||
namespace Elwig.Documents {
|
||||
public abstract class BusinessDocument : Document {
|
||||
|
||||
public BusinessDocument(string title, Member m) : base(title) {
|
||||
Member = m;
|
||||
}
|
||||
public Member Member;
|
||||
public bool IncludeSender = false;
|
||||
public string Aside { get; set; }
|
||||
public string? Location { get; set; }
|
||||
|
||||
public Member Member { get; set; }
|
||||
public BusinessDocument(string title, Member m, bool includeSender = false) : base(title) {
|
||||
Member = m;
|
||||
Location = App.BranchName;
|
||||
IncludeSender = includeSender;
|
||||
var uid = (m.UstIdNr ?? "-") + (m.IsBuchführend ? "" : " <i>(pauschaliert)</i>");
|
||||
Aside = $"<table><colgroup><col span='1' style='width: 2.25cm;'/><col span='1' style='width: 100%;'/></colgroup>" +
|
||||
$"<thead><tr><th colspan='2'>Mitglied</th></tr></thead><tbody>" +
|
||||
$"<tr><th>Mitglieds-Nr.</th><td>{m.MgNr}</td></tr>" +
|
||||
$"<tr><th>Betriebs-Nr.</th><td>{m.LfbisNr}</td></tr>" +
|
||||
$"<tr><th>UID</th><td>{uid}</td></tr>" +
|
||||
$"</tbody></table>";
|
||||
}
|
||||
|
||||
public string Address {
|
||||
get {
|
||||
// TODO Name/Rechnungsadresse
|
||||
return $"{Member.GivenName} {Member.FamilyName}\n{Member.Address}";
|
||||
var b = Member.BillingAddress;
|
||||
var plz = (b == null) ? Member.PostalDest.AtPlz : b.PostalDest.AtPlz;
|
||||
if (b != null) {
|
||||
return $"{b.Name}\n{Member.AdministrativeName}\n{b.Address}\n{plz.Plz} {plz.Dest}\nÖsterreich";
|
||||
} else {
|
||||
return $"{Member.AdministrativeName}\n{Member.Address}\n{plz.Plz} {plz.Dest}\nÖsterreich";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,6 @@ using Elwig.Models;
|
||||
|
||||
namespace Elwig.Documents {
|
||||
public class BusinessLetter : BusinessDocument {
|
||||
public BusinessLetter(string title, Member m) : base(title, m) {
|
||||
|
||||
}
|
||||
public BusinessLetter(string title, Member m) : base(title, m) { }
|
||||
}
|
||||
}
|
||||
|
165
Elwig/Documents/DeliveryNote.cshtml
Normal file
165
Elwig/Documents/DeliveryNote.cshtml
Normal file
@@ -0,0 +1,165 @@
|
||||
@using RazorLight
|
||||
@inherits TemplatePage<Elwig.Documents.DeliveryNote>
|
||||
@model Elwig.Documents.DeliveryNote
|
||||
@{ Layout = "BusinessDocument"; }
|
||||
|
||||
<div class="date">@Model.Location, am @($"{Model.Date:dd.MM.yyyy}")</div>
|
||||
<h1>@Model.Title</h1>
|
||||
@{
|
||||
bool displayStats = true; // Model.Delivery.Year == Model.CurrentNextSeason
|
||||
}
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const hidden = document.getElementsByClassName("hidden")[0];
|
||||
const bottom = hidden.offsetTop + hidden.offsetHeight;
|
||||
const cm = bottom * 2.54 / 96 * window.devicePixelRatio;
|
||||
|
||||
if (cm > 25.75) {
|
||||
// force page break
|
||||
const table = document.getElementsByClassName("delivery")[0];
|
||||
|
||||
const hr = document.createElement("hr");
|
||||
hr.classList.add("page-break");
|
||||
table.before(hr);
|
||||
|
||||
const stats = document.getElementById("delivery-stats");
|
||||
stats.getElementsByTagName("table")[0].classList.add("expanded");
|
||||
hr.before(stats);
|
||||
|
||||
const p = document.createElement("p");
|
||||
p.innerText = "Siehe nächste Seite."
|
||||
stats.before(p);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<table class="delivery">
|
||||
<colgroup>
|
||||
<col style="width: 1cm;"/>
|
||||
<col style="width: 25%;"/>
|
||||
<col style="width: 25%;"/>
|
||||
<col style="width: 25%;"/>
|
||||
<col style="width: 25%;"/>
|
||||
<col style="width: 3cm;"/>
|
||||
<col style="width: 1.25cm;"/>
|
||||
<col style="width: 1.25cm;"/>
|
||||
<col style="width: 1.5cm;"/>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="main" rowspan="2" style="text-align: center;">Pos.</th>
|
||||
<th class="main" rowspan="2" colspan="2">Sorte</th>
|
||||
<th class="main" rowspan="2" colspan="2">Attribut(e)</th>
|
||||
<th class="main" rowspan="2">Qualitätsstufe</th>
|
||||
<th colspan="2">Gradation</th>
|
||||
<th>Gewicht</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="font-size: 8pt;">[°Oe]</th>
|
||||
<th style="font-size: 8pt;">[°KMW]</th>
|
||||
<th style="font-size: 8pt;">[kg]</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var part in Model.Delivery.Parts.OrderBy(p => p.DPNr)) {
|
||||
<tr class="main">
|
||||
<td style="text-align: center;">@part.DPNr</td>
|
||||
<td colspan="2">@part.Variant.Name</td>
|
||||
<td colspan="2">@string.Join(" / ", part.Attributes)</td>
|
||||
<td>@part.Quality.Name</td>
|
||||
<td class="narrow" style="text-align: center;">@($"{part.Oe:N0}")</td>
|
||||
<td class="narrow" style="text-align: center;">@($"{part.Kmw:N1}")</td>
|
||||
<td class="narrow" style="text-align: right;">@($"{part.Weight:N0}")</td>
|
||||
</tr>
|
||||
<tr><td></td><td colspan="5" style="white-space: pre;"><i>Herkunft:</i> @part.OriginString</td></tr>
|
||||
@if (part.Modifiers.Count() > 0) {
|
||||
var first = true;
|
||||
foreach (var mod in part.Modifiers) {
|
||||
<tr class="tight @(first ? "first" : "")"><td></td><td>@Raw(first ? "<i>Zu-/Abschläge:</i>" : "")</td><td colspan="3"><b>@mod.Name</b></td><td style="white-space: pre;">@mod.ValueStr</td></tr>
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
<tr><td></td><td colspan="5">
|
||||
@Raw(part.ManualWeighing ? "<i>Handwiegung</i>" : $"<i>Waage:</i> {part.ScaleId ?? "?"}, <i>ID:</i> {part.WeighingId ?? "?"}") (@(part.IsGerebelt ? "gerebelt gewogen" : "nicht gerebelt gewogen"))
|
||||
</td></tr>
|
||||
@if (part.Comment != null) {
|
||||
<tr><td></td><td colspan="5"><i>Anmerkung:</i> @part.Comment</td></tr>
|
||||
}
|
||||
@if (part.Temperature != null || part.Acid != null) {
|
||||
<tr><td></td><td colspan="5">@Raw(part.Temperature != null ? $"<i>Temperatur:</i> {part.Temperature:N1} °C" : "")@(part.Temperature != null && part.Acid != null ? ", " : "")@Raw(part.Acid != null ? $"<i>Säure:</i> {part.Acid:N1} g/l" : "")</td></tr>
|
||||
}
|
||||
}
|
||||
@if (Model.Delivery.Parts.Count() > 1) {
|
||||
<tr class="main sum">
|
||||
<td colspan="6">Gesamt:</td>
|
||||
<td style="text-align: center;">@($"{Model.Delivery.Oe:N0}")</td>
|
||||
<td style="text-align: center;">@($"{Model.Delivery.Kmw:N1}")</td>
|
||||
<td style="text-align: right;">@($"{Model.Delivery.Weight:N0}")</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
@if (Model.Delivery.Comment != null) {
|
||||
<p class="comment">Amerkung zur Lieferung: @Model.Delivery.Comment</p>
|
||||
}
|
||||
@if (displayStats) {
|
||||
<div id="delivery-stats">
|
||||
<table class="delivery-stats">
|
||||
<colgroup>
|
||||
<col style="width: 100%;"/>
|
||||
<col style="width: 2cm;"/>
|
||||
<col style="width: 2cm;"/>
|
||||
<col style="width: 2cm;"/>
|
||||
<col style="width: 2cm;"/>
|
||||
<col style="width: 2cm;"/>
|
||||
<col style="width: 2cm;"/>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><b>Gesamtlieferung</b> [kg]</th>
|
||||
<th>Lieferpflicht</th>
|
||||
<th>Lieferrecht</th>
|
||||
<th>Unterliefert</th>
|
||||
<th>Noch zu liefern</th>
|
||||
<th>Überliefert</th>
|
||||
<th>Geliefert</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@{
|
||||
string FormatRow(int obligation, int right, int sum) {
|
||||
return $"<td>{obligation:N0}</td>" +
|
||||
$"<td>{right:N0}</td>" +
|
||||
$"<td>{(sum < obligation ? $"{obligation - sum:N0}" : "-")}</td>" +
|
||||
$"<td>{(sum >= obligation && sum <= right ? $"{right - sum:N0}" : "-")}</td>" +
|
||||
$"<td>{(sum > right ? $"{sum - right:N0}" : "-")}</td>" +
|
||||
$"<td>{sum:N0}</td>";
|
||||
}
|
||||
var sortids = Model.Delivery.Parts.Select(p => p.SortId).ToList();
|
||||
}
|
||||
<tr>
|
||||
<th>Geschäftsanteile</th>
|
||||
@Raw(FormatRow(Model.Member.DeliveryObligation, Model.Member.DeliveryRight, Model.Member.Deliveries.Where(d => d.Year == Model.Delivery.Year).Sum(d => d.Weight)))
|
||||
</tr>
|
||||
@foreach (var (id, name, right, obligation, sum) in Model.MemberBuckets.OrderBy(b => b.Item1)) {
|
||||
if (right > 0 && obligation > 0) {
|
||||
<tr class="@(sortids.Contains(id[..2]) ? "" : "optional")">
|
||||
<th>@name</th>
|
||||
@Raw(FormatRow(obligation, right, sum))
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@for (int i = 0; i < 2; i++) {
|
||||
<div class="@(i == 0 ? "hidden" : "bottom")">
|
||||
@if (Model.Text != null) {
|
||||
<p class="comment">@Model.Text</p>
|
||||
}
|
||||
<div class="signatures">
|
||||
<div>Genossenschaft</div>
|
||||
<div>Mitglied</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
25
Elwig/Documents/DeliveryNote.cshtml.cs
Normal file
25
Elwig/Documents/DeliveryNote.cshtml.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Elwig.Documents {
|
||||
public class DeliveryNote : BusinessDocument {
|
||||
|
||||
public Delivery Delivery;
|
||||
public string? Text;
|
||||
public IEnumerable<(string, string, int, int, int)> MemberBuckets;
|
||||
|
||||
public DeliveryNote(Delivery d, AppDbContext ctx) : base($"Traubenübernahmeschein Nr. {d.LsNr}", d.Member) {
|
||||
Delivery = d;
|
||||
Aside = Aside.Replace("</table>", "") +
|
||||
$"<thead><tr><th colspan='2'>Lieferung</th></tr></thead><tbody>" +
|
||||
$"<tr><th>LS-Nr.</th><td>{d.LsNr}</td></tr>" +
|
||||
$"<tr><th>Datum/Zeit</th><td>{d.Date:dd.MM.yyyy} / {d.Time:HH:mm}</td></tr>" +
|
||||
$"<tr><th>Zweigstelle</th><td>{d.Branch.Name}</td></tr>" +
|
||||
$"</tbody></table>";
|
||||
Text = App.Client.TextDeliveryNote;
|
||||
DocumentId = d.LsNr;
|
||||
MemberBuckets = ctx.GetMemberBuckets(d.Member, d.Year).GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,8 +5,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de-AT">
|
||||
<head>
|
||||
<title>@Model.Title</title>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>@Model.Title</title>
|
||||
<meta charset="UTF-8"/>
|
||||
<script>
|
||||
window.PagedConfig = { auto: false };
|
||||
if (!navigator.webdriver) {
|
||||
@@ -21,14 +21,15 @@
|
||||
<div class="m1"></div>
|
||||
<div class="m2"></div>
|
||||
<div class="m3"></div>
|
||||
<header>@Raw(Model.Header)</header>
|
||||
<div class="footer-wrapper">
|
||||
<div class="pre-footer">
|
||||
<span class="date">@Model.FullDateString</span>
|
||||
<span class="date">@($"{Model.Date:dddd, d. MMMM yyyy}")</span>
|
||||
<span class="doc-id">@Model.DocumentId</span>
|
||||
<span class="page"></span>
|
||||
</div>
|
||||
<footer>@Raw(Model.Footer)</footer>
|
||||
</div>
|
||||
<header>@Raw(Model.Header)</header>
|
||||
<div class="spacing"></div>
|
||||
<div class="main-wrapper">
|
||||
@RenderBody()
|
||||
|
@@ -9,10 +9,17 @@ namespace Elwig.Documents {
|
||||
private TempFile? PdfFile = null;
|
||||
|
||||
public Document(string title) {
|
||||
var c = App.Client;
|
||||
DataPath = App.DataPath;
|
||||
CurrentNextSeason = Utils.CurrentNextSeason;
|
||||
Title = title;
|
||||
Header = "<h1>Winzergenossenschaft Matzen</h1>";
|
||||
Footer = "Winzergenossenschaft für Matzen und Umgebung reg. Gen.m.b.H.";
|
||||
Header = $"<h1>{c.Name}</h1>";
|
||||
Footer = Utils.GenerateFooter("<br/>", " \u00b7 ")
|
||||
.Item(c.NameFull).NextLine()
|
||||
.Item(c.Address).Item($"{c.Plz} {c.Ort}").Item("Österreich").Item("Tel.", c.PhoneNr).Item("Fax", c.FaxNr).NextLine()
|
||||
.Item(c.EmailAddress).Item(c.Website).Item("Betriebs-Nr.", c.LfbisNr).Item("UID", c.UstIdNr).NextLine()
|
||||
.Item("BIC", c.Bic).Item("IBAN", c.Iban)
|
||||
.ToString();
|
||||
Date = DateTime.Today;
|
||||
}
|
||||
|
||||
@@ -23,28 +30,25 @@ namespace Elwig.Documents {
|
||||
public void Dispose() {
|
||||
PdfFile?.Dispose();
|
||||
PdfFile = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public string DataPath { get; set; }
|
||||
|
||||
public int CurrentNextSeason { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
public string Header { get; set; }
|
||||
|
||||
public string Footer { get; set; }
|
||||
|
||||
public string FullDateString {
|
||||
get => Date.ToString("dddd, d. MMMM yyyy");
|
||||
}
|
||||
|
||||
public DateTime Date { get; set; }
|
||||
public string? DocumentId { get; set; }
|
||||
|
||||
private async Task<string> Render() {
|
||||
string name;
|
||||
if (this is BusinessLetter) {
|
||||
name = "BusinessLetter";
|
||||
} else if (this is DeliveryNote) {
|
||||
name = "DeliveryNote";
|
||||
} else {
|
||||
throw new InvalidOperationException();
|
||||
throw new InvalidOperationException("Invalid document object");
|
||||
}
|
||||
return await Html.CompileRenderAsync(name, this);
|
||||
}
|
||||
@@ -55,7 +59,7 @@ namespace Elwig.Documents {
|
||||
await File.WriteAllTextAsync(tmpHtml.FilePath, await Render());
|
||||
await Pdf.Convert(tmpHtml.FilePath, pdf.FilePath);
|
||||
}
|
||||
Pdf.UpdateMetadata(pdf.FilePath, Title, "Winzergenossenschaft für Matzen und Umgebung reg. Gen.m.b.H.");
|
||||
Pdf.UpdateMetadata(pdf.FilePath, Title, App.Client.NameFull);
|
||||
PdfFile = pdf;
|
||||
}
|
||||
|
||||
@@ -64,9 +68,9 @@ namespace Elwig.Documents {
|
||||
File.Copy(PdfFile.FilePath, pdfPath);
|
||||
}
|
||||
|
||||
public async Task Print() {
|
||||
public async Task Print(int copies = 1) {
|
||||
if (PdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet");
|
||||
Pdf.Print(PdfFile.FilePath);
|
||||
await Pdf.Print(PdfFile.FilePath, copies);
|
||||
}
|
||||
|
||||
public void Show() {
|
||||
|
@@ -17,6 +17,7 @@ namespace Elwig.Documents {
|
||||
await e.CompileTemplateAsync("Document");
|
||||
await e.CompileTemplateAsync("BusinessDocument");
|
||||
await e.CompileTemplateAsync("BusinessLetter");
|
||||
await e.CompileTemplateAsync("DeliveryNote");
|
||||
|
||||
Engine = e;
|
||||
evtHandler();
|
||||
|
@@ -5,11 +5,13 @@ using PdfSharp.Pdf.IO;
|
||||
using PuppeteerSharp;
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Windows;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Elwig.Documents {
|
||||
public static class Pdf {
|
||||
|
||||
private static readonly string Chromium = @"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe";
|
||||
private static readonly string PdfToPrinter = App.ExePath + "PDFtoPrinter.exe";
|
||||
private static IBrowser? Browser = null;
|
||||
public static bool IsReady => Browser != null;
|
||||
|
||||
@@ -48,7 +50,7 @@ namespace Elwig.Documents {
|
||||
});
|
||||
}
|
||||
|
||||
private static void OnConsole(object sender, ConsoleEventArgs e) {
|
||||
private static void OnConsole(object? sender, ConsoleEventArgs e) {
|
||||
MessageBox.Show(e.Message.Text);
|
||||
}
|
||||
|
||||
@@ -73,8 +75,12 @@ namespace Elwig.Documents {
|
||||
});
|
||||
}
|
||||
|
||||
public static void Print(string path) {
|
||||
// TODO print pdf
|
||||
public static async Task Print(string path, int copies = 1) {
|
||||
var p = new Process() { StartInfo = new() { FileName = PdfToPrinter } };
|
||||
p.StartInfo.ArgumentList.Add(path);
|
||||
p.StartInfo.ArgumentList.Add($"copies={copies}");
|
||||
p.Start();
|
||||
await p.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,10 @@ body {
|
||||
.m2 {top: 148.5mm;}
|
||||
.m3 {top: 210mm;}
|
||||
|
||||
header, .address-wrapper, aside, main {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
height: 45mm;
|
||||
padding: 5mm;
|
||||
@@ -33,10 +37,19 @@ header {
|
||||
right: 0;
|
||||
text-align: center;
|
||||
}
|
||||
.spacing {height: 20mm;}
|
||||
|
||||
header h1{
|
||||
font-size: 18pt;
|
||||
margin-top: 1cm;
|
||||
}
|
||||
|
||||
.spacing {
|
||||
height: 20mm;
|
||||
}
|
||||
|
||||
.info-wrapper {
|
||||
width: 100%;
|
||||
height:45mm;
|
||||
height: 45mm;
|
||||
margin: 0 0 8.46mm 0;
|
||||
position: relative;
|
||||
}
|
||||
@@ -70,6 +83,11 @@ address {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
table td,
|
||||
table th {
|
||||
padding: 0.5mm 1mm;
|
||||
}
|
||||
|
||||
aside {
|
||||
height: 40mm;
|
||||
width: 75mm;
|
||||
@@ -79,6 +97,32 @@ aside {
|
||||
top: 5mm;
|
||||
}
|
||||
|
||||
aside table {
|
||||
border-collapse: collapse;
|
||||
border: 1pt solid #808080;
|
||||
width: calc(100% - 1cm);
|
||||
margin-right: 1cm;
|
||||
}
|
||||
|
||||
aside table thead:not(:first-child) tr {
|
||||
border-top: 1pt solid #808080;
|
||||
}
|
||||
|
||||
aside table thead th {
|
||||
background-color: #E0E0E0;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
aside table tbody th,
|
||||
aside table tbody td {
|
||||
text-align: left;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
aside table tbody th {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
main {
|
||||
margin: 8.46mm 20mm 4.23mm 25mm;
|
||||
}
|
||||
@@ -91,8 +135,12 @@ main h1, main p {
|
||||
font-size: 12pt;
|
||||
margin: 1em 0;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
main p {
|
||||
widows: 3;
|
||||
orphans: 3;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
main .date {
|
||||
@@ -104,6 +152,10 @@ main h1 {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
main p.comment {
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.footer-wrapper {
|
||||
padding: 0 20mm 0 25mm;
|
||||
position: running(page-footer);
|
||||
@@ -118,13 +170,24 @@ main h1 {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.pre-footer .date, .pre-footer .page {
|
||||
flex: 100px 1 1;
|
||||
.pre-footer > * {
|
||||
flex: 5cm 1 1;
|
||||
}
|
||||
|
||||
.pre-footer .date {text-align: left;}
|
||||
.pre-footer .page {text-align: right;}
|
||||
.page::after {
|
||||
.pre-footer .date {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.pre-footer .doc-id {
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.pre-footer .page {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.pre-fotter .page::after {
|
||||
content: "Seite 1 von 1";
|
||||
}
|
||||
|
||||
@@ -136,6 +199,134 @@ footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
table.delivery {
|
||||
margin-bottom: 5mm;
|
||||
}
|
||||
|
||||
table.delivery th {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
table.delivery th.main {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table.delivery tr.main td {
|
||||
font-weight: bold;
|
||||
padding-top: 2mm;
|
||||
}
|
||||
|
||||
table.delivery tbody tr:not(.main) td {
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
table.delivery tr.tight:not(.first) td {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
table.delivery tr.tight.first td {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
table.delivery tr.tight:has(+ tr:not(.tight)) td {
|
||||
padding-bottom: 0.5mm !important;
|
||||
}
|
||||
|
||||
table.delivery tr.sum {
|
||||
border-top: 1pt solid black;
|
||||
}
|
||||
|
||||
table.delivery tr.sum td {
|
||||
padding-top: 1mm;
|
||||
}
|
||||
|
||||
table.delivery-stats {
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
table.delivery-stats.expanded th,
|
||||
table.delivery-stats.expanded td {
|
||||
padding: 0.25mm 0;
|
||||
}
|
||||
|
||||
table.delivery-stats:not(.expanded) th,
|
||||
table.delivery-stats:not(.expanded) td {
|
||||
padding: 0.125mm 0;
|
||||
}
|
||||
|
||||
table.delivery-stats:not(.expanded) tr.optional {
|
||||
display: none;
|
||||
}
|
||||
|
||||
table.delivery-stats thead th {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
table.delivery-stats thead th:first-child {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table.delivery-stats.expanded tbody {
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
table.delivery-stats td {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
table.delivery-stats tbody th {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
main .bottom {
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
width: calc(100% - 25mm - 20mm);
|
||||
}
|
||||
|
||||
main .signatures {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin: 20mm 0 2mm 0;
|
||||
}
|
||||
|
||||
main .signatures > * {
|
||||
width: 5cm;
|
||||
border-top: 1pt solid black;
|
||||
padding-top: 1mm;
|
||||
text-align: center;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 1pt solid black;
|
||||
margin: 5mm 0;
|
||||
}
|
||||
|
||||
hr.page-break {
|
||||
display: none;
|
||||
break-after: page;
|
||||
}
|
||||
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 25mm 0 35mm 0;
|
||||
@@ -149,7 +340,7 @@ footer {
|
||||
width: 210mm;
|
||||
}
|
||||
header, .address-wrapper, aside, main {
|
||||
border: 1px solid lightgray;
|
||||
border: 1pt solid lightgray;
|
||||
}
|
||||
.m1, .m2, .m3 {display: none;}
|
||||
header {top: 0;}
|
||||
|
@@ -7,6 +7,8 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<ApplicationIcon>elwig.ico</ApplicationIcon>
|
||||
<Version>0.1.0</Version>
|
||||
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -14,20 +16,24 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.1" />
|
||||
<PackageReference Include="ini-parser" Version="2.5.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.16" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.5" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1722.45" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.21" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1938.49" />
|
||||
<PackageReference Include="PdfSharp" Version="1.50.5147" />
|
||||
<PackageReference Include="PuppeteerSharp" Version="9.1.0" />
|
||||
<PackageReference Include="PuppeteerSharp" Version="11.0.2" />
|
||||
<PackageReference Include="RazorLight" Version="2.3.1" />
|
||||
<PackageReference Include="ScottPlot.WPF" Version="4.1.67" />
|
||||
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Resource Include="elwig.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||
<Exec Command="call fetch-resources.bat" />
|
||||
</Target>
|
||||
|
@@ -6,34 +6,50 @@ using System.IO;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
public class AppDbContext : DbContext {
|
||||
|
||||
public DbSet<Country> Countries { get; set; }
|
||||
public DbSet<Currency> Currencies { get; set; }
|
||||
public DbSet<Member> Members { get; set; }
|
||||
public DbSet<BillingAddr> BillingAddresses { get; set; }
|
||||
public DbSet<AT_Gem> Gemeinden { get; set; }
|
||||
public DbSet<AT_Kg> Katastralgemeinden { get; set; }
|
||||
public DbSet<AT_Ort> Orte { get; set; }
|
||||
public DbSet<AT_Plz> Postleitzahlen { get; set; }
|
||||
public DbSet<AT_PlzDest> PlzDestinations { get; set; }
|
||||
public DbSet<PostalDest> PostalDestinations { get; set; }
|
||||
public DbSet<Branch> Branches { get; set; }
|
||||
public DbSet<WbKg> WbKgs { get; set; }
|
||||
public DbSet<WbRd> WbRde { get; set; }
|
||||
public DbSet<AreaCom> AreaCommitments { get; set; }
|
||||
public DbSet<AreaComParcel> AreaCommitmentParcels { get; set; }
|
||||
public DbSet<AreaComAttr> AreaCommitmentAttributes { get; set; }
|
||||
public DbSet<Contract> Contracts { get; set; }
|
||||
public DbSet<WineAttr> WineAttributes { get; set; }
|
||||
public DbSet<WineCult> WineCultivations { get; set; }
|
||||
public DbSet<WineQual> WineQualities { get; set; }
|
||||
public DbSet<WineVar> WineVarieties { get; set; }
|
||||
public DbSet<Season> Seasons { get; set; }
|
||||
public DbSet<Country> Countries { get; private set; }
|
||||
public DbSet<Currency> Currencies { get; private set; }
|
||||
public DbSet<AT_Gem> Gemeinden { get; private set; }
|
||||
public DbSet<AT_Kg> Katastralgemeinden { get; private set; }
|
||||
public DbSet<AT_Ort> Orte { get; private set; }
|
||||
public DbSet<AT_Plz> Postleitzahlen { get; private set; }
|
||||
public DbSet<AT_PlzDest> PlzDestinations { get; private set; }
|
||||
public DbSet<PostalDest> PostalDestinations { get; private set; }
|
||||
public DbSet<WineOrigin> WineOrigins { get; private set; }
|
||||
public DbSet<WineQualLevel> WineQualityLevels { get; private set; }
|
||||
public DbSet<WineVar> WineVarieties { get; private set; }
|
||||
|
||||
public DbSet<ClientParam> ClientParameters { get; private set; }
|
||||
public DbSet<WbKg> WbKgs { get; private set; }
|
||||
public DbSet<WbRd> WbRde { get; private set; }
|
||||
public DbSet<WineAttr> WineAttributes { get; private set; }
|
||||
public DbSet<WineCult> WineCultivations { get; private set; }
|
||||
public DbSet<Branch> Branches { get; private set; }
|
||||
public DbSet<AreaComType> AreaCommitmentTypes { get; private set; }
|
||||
public DbSet<Member> Members { get; private set; }
|
||||
public DbSet<BillingAddr> BillingAddresses { get; private set; }
|
||||
public DbSet<MemberTelNr> MemberTelephoneNrs { get; private set; }
|
||||
public DbSet<AreaCom> AreaCommitments { get; private set; }
|
||||
public DbSet<Season> Seasons { get; private set; }
|
||||
public DbSet<Modifier> Modifiers { get; private set; }
|
||||
public DbSet<Delivery> Deliveries { get; private set; }
|
||||
public DbSet<DeliveryPart> DeliveryParts { get; private set; }
|
||||
public DbSet<DeliveryPartAttr> DeliveryPartAttributes { get; private set; }
|
||||
public DbSet<DeliveryPartModifier> DeliveryPartModifiers { get; private set; }
|
||||
public DbSet<PaymentVar> PaymentVariants { get; private set; }
|
||||
|
||||
private readonly StreamWriter? LogFile = null;
|
||||
public static DateTime LastWriteTime => File.GetLastWriteTime(App.Config.DatabaseFile);
|
||||
public DateTime SavedLastWriteTime { get; private set; }
|
||||
public bool HasBackendChanged => SavedLastWriteTime != LastWriteTime;
|
||||
|
||||
public static string ConnectionString => $"Data Source=\"{App.Config.DatabaseFile}\"; Foreign Keys=True; Mode=ReadWrite; Cache=Default";
|
||||
|
||||
public AppDbContext() {
|
||||
if (App.Config.DatabaseLog != null) {
|
||||
@@ -46,10 +62,26 @@ namespace Elwig.Helpers {
|
||||
MessageBox.Show($"Unable to open database log file:\n\n{e.Message}", "Database Log", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
SavedLastWriteTime = LastWriteTime;
|
||||
SavedChanges += OnSavedChanges;
|
||||
}
|
||||
|
||||
public static SqliteConnection Connect() {
|
||||
var cnx = new SqliteConnection(ConnectionString);
|
||||
cnx.CreateFunction<string, string?, bool?>("REGEXP", (pattern, value) => value == null ? null : Regex.Match(value, pattern).Success, true);
|
||||
cnx.Open();
|
||||
return cnx;
|
||||
}
|
||||
|
||||
public static async Task<SqliteConnection> ConnectAsync() {
|
||||
var cnx = new SqliteConnection(ConnectionString);
|
||||
cnx.CreateFunction<string, string?, bool?>("REGEXP", (pattern, value) => value == null ? null : Regex.Match(value, pattern).Success, true);
|
||||
await cnx.OpenAsync();
|
||||
return cnx;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
|
||||
optionsBuilder.UseSqlite($"Data Source=\"{App.Config.DatabaseFile}\"; Foreign Keys=True; Mode=ReadWrite; Cache=Default");
|
||||
optionsBuilder.UseSqlite(ConnectionString);
|
||||
optionsBuilder.UseLazyLoadingProxies();
|
||||
optionsBuilder.LogTo(Log, LogLevel.Information);
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
@@ -61,6 +93,10 @@ namespace Elwig.Helpers {
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void OnSavedChanges(object? sender, SavedChangesEventArgs evt) {
|
||||
SavedLastWriteTime = LastWriteTime;
|
||||
}
|
||||
|
||||
protected void Log(string msg) {
|
||||
LogFile?.WriteLine(msg);
|
||||
}
|
||||
@@ -69,22 +105,125 @@ namespace Elwig.Helpers {
|
||||
return await Members.FindAsync(mgnr) != null;
|
||||
}
|
||||
|
||||
public async Task<bool> VNrExists(int vnr) {
|
||||
return await Contracts.FindAsync(vnr) != null;
|
||||
public async Task<bool> FbNrExists(int fbnr) {
|
||||
return await AreaCommitments.FindAsync(fbnr) != null;
|
||||
}
|
||||
|
||||
public async Task<bool> SortIdExists(string sortId) {
|
||||
return await WineVarieties.FindAsync(sortId) != null;
|
||||
}
|
||||
|
||||
public async Task<bool> AttrIdExists(string attrId) {
|
||||
return await WineAttributes.FindAsync(attrId) != null;
|
||||
}
|
||||
|
||||
public async Task<int> NextMgNr() {
|
||||
int c = await Members.Select(m => m.MgNr).MinAsync();
|
||||
(await Members.OrderBy(m => m.MgNr).Select(m => m.MgNr).ToListAsync())
|
||||
.ForEach(a => { if (a <= c + 1000) c = a; });
|
||||
return c + 1;
|
||||
}
|
||||
|
||||
public async Task<int> NextFbNr() {
|
||||
int c = await AreaCommitments.Select(ac => ac.FbNr).MinAsync();
|
||||
(await AreaCommitments.OrderBy(ac => ac.FbNr).Select(ac => ac.FbNr).ToListAsync())
|
||||
.ForEach(a => { if (a <= c + 1000) c = a; });
|
||||
return c + 1;
|
||||
}
|
||||
|
||||
public async Task<int> NextLNr(DateOnly date) {
|
||||
var dateStr = date.ToString("yyyy-MM-dd");
|
||||
int c = 0;
|
||||
(await Deliveries.Where(d => d.DateString == dateStr).Select(d => d.LNr).ToListAsync())
|
||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
||||
return c + 1;
|
||||
}
|
||||
|
||||
public async Task<int> NextVNr() {
|
||||
int c = await Contracts.Select(co => co.VNr).MinAsync();
|
||||
(await Contracts.OrderBy(co => co.VNr).Select(co => co.VNr).ToListAsync())
|
||||
public async Task<int> NextDId(int year) {
|
||||
int c = 0;
|
||||
(await Deliveries.Where(d => d.Year == year).Select(d => d.DId).ToListAsync())
|
||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
||||
return c + 1;
|
||||
}
|
||||
|
||||
public async Task<int> NextDPNr(int year, int did) {
|
||||
int c = 0;
|
||||
(await DeliveryParts.Where(p => p.Year == year && p.DId == did).Select(d => d.DPNr).ToListAsync())
|
||||
.ForEach(a => { if (a <= c + 100) c = a; });
|
||||
return c + 1;
|
||||
}
|
||||
|
||||
public async Task<WineQualLevel> GetWineQualityLevel(double kmw) {
|
||||
return await WineQualityLevels
|
||||
.Where(q => !q.IsPredicate && (q.MinKmw == null || q.MinKmw <= kmw))
|
||||
.OrderBy(q => q.MinKmw)
|
||||
.LastOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task UpdateDeliveryPartAttributes(DeliveryPart part, IEnumerable<WineAttr> attributes) {
|
||||
foreach (var a in WineAttributes) {
|
||||
var attr = part.PartAttributes.Where(pa => pa.AttrId == a.AttrId).FirstOrDefault();
|
||||
if (attributes.Contains(a)) {
|
||||
DeliveryPartAttr dpa = attr ?? this.CreateProxy<DeliveryPartAttr>();
|
||||
dpa.Year = part.Year;
|
||||
dpa.DId = part.DId;
|
||||
dpa.DPNr = part.DPNr;
|
||||
dpa.AttrId = a.AttrId;
|
||||
if (attr == null) {
|
||||
await AddAsync(dpa);
|
||||
} else {
|
||||
Update(dpa);
|
||||
}
|
||||
} else {
|
||||
if (attr != null) {
|
||||
Remove(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateDeliveryPartModifiers(DeliveryPart part, IEnumerable<Modifier> modifiers) {
|
||||
foreach (var m in Modifiers.Where(m => m.Year == part.Year)) {
|
||||
var mod = part.PartModifiers.Where(pa => pa.ModId == m.ModId).FirstOrDefault();
|
||||
if (modifiers.Contains(m)) {
|
||||
DeliveryPartModifier dpm = mod ?? this.CreateProxy<DeliveryPartModifier>();
|
||||
dpm.Year = part.Year;
|
||||
dpm.DId = part.DId;
|
||||
dpm.DPNr = part.DPNr;
|
||||
dpm.ModId = m.ModId;
|
||||
if (mod == null) {
|
||||
await AddAsync(dpm);
|
||||
} else {
|
||||
Update(dpm);
|
||||
}
|
||||
} else {
|
||||
if (mod != null) {
|
||||
Remove(mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<(string, string, int, int, int)>> GetMemberBuckets(Member m, int year) {
|
||||
using var cnx = await ConnectAsync();
|
||||
var (rights, obligations) = await Billing.Billing.GetMemberRightsObligations(m.MgNr, year, cnx);
|
||||
var buckets = await Billing.Billing.GetMemberBucketWeights(m.MgNr, year, cnx);
|
||||
|
||||
var list = new List<(string, string, int, int, int)>();
|
||||
foreach (var id in rights.Keys.Union(obligations.Keys).Union(buckets.Keys)) {
|
||||
var s = await WineVarieties.FindAsync(id[..2]);
|
||||
var attrIds = id[2..];
|
||||
var a = await WineAttributes.Where(a => attrIds.Contains(a.AttrId)).ToListAsync();
|
||||
var name = (s?.Name ?? "") + (a.Count > 0 ? $" ({string.Join(" / ", a.Select(a => a.Name))})" : "");
|
||||
list.Add((
|
||||
id, name,
|
||||
rights.TryGetValue(id, out var v1) ? v1 : 0,
|
||||
obligations.TryGetValue(id, out var v2) ? v2 : 0,
|
||||
buckets.TryGetValue(id, out var v3) ? v3 : 0
|
||||
));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
130
Elwig/Helpers/Billing/Billing.cs
Normal file
130
Elwig/Helpers/Billing/Billing.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Helpers.Billing {
|
||||
public class Billing {
|
||||
|
||||
private readonly int Year;
|
||||
private readonly int AvNr;
|
||||
private readonly AppDbContext Context;
|
||||
private readonly Dictionary<string, string> Attributes;
|
||||
private readonly Dictionary<string, (decimal?, decimal?)> Modifiers;
|
||||
private readonly Dictionary<string, (string, string?, string?, string?, int?, int?, decimal?)> AreaComTypes;
|
||||
|
||||
public Billing(int year, int avnr) {
|
||||
Year = year;
|
||||
AvNr = avnr;
|
||||
Context = new AppDbContext();
|
||||
Attributes = Context.WineAttributes.ToDictionary(a => a.AttrId, a => a.Name);
|
||||
Modifiers = Context.Modifiers.Where(m => m.Year == Year).ToDictionary(m => m.ModId, m => (m.Abs, m.Rel));
|
||||
AreaComTypes = Context.AreaCommitmentTypes.ToDictionary(v => v.VtrgId, v => (v.SortId, v.AttrId1, v.AttrId2, v.Discriminator, v.MinKgPerHa, v.MaxKgPerHa, v.PenaltyAmount));
|
||||
}
|
||||
|
||||
protected async Task DeleteInDb() {
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
using (var cmd = cnx.CreateCommand()) {
|
||||
cmd.CommandText = $"DELETE FROM payment_delivery_part WHERE (year, avnr) = ({Year}, {AvNr})";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
using (var cmd = cnx.CreateCommand()) {
|
||||
cmd.CommandText = $"DELETE FROM payment_member WHERE (year, avnr) = ({Year}, {AvNr})";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Calculate() {
|
||||
await DeleteInDb();
|
||||
var tasks = new List<Task>();
|
||||
foreach (var mgnr in Context.Members.Select(m => m.MgNr)) {
|
||||
tasks.Add(Task.Run(() => CalculateMember(mgnr)));
|
||||
}
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
public static async Task<(Dictionary<string, int>, Dictionary<string, int>)> GetMemberRightsObligations(int mgnr, int year, SqliteConnection cnx) {
|
||||
var rights = new Dictionary<string, int>();
|
||||
var obligations = new Dictionary<string, int>();
|
||||
|
||||
using var cmd = cnx.CreateCommand();
|
||||
cmd.CommandText = $"""
|
||||
SELECT t.vtrgid,
|
||||
SUM(COALESCE(area * min_kg_per_ha, 0)) / 10000 AS min_kg,
|
||||
SUM(COALESCE(area * max_kg_per_ha, 0)) / 10000 AS max_kg
|
||||
FROM area_commitment c
|
||||
JOIN area_commitment_type t ON t.vtrgid = c.vtrgid
|
||||
WHERE mgnr = {mgnr} AND (year_from IS NULL OR year_from <= {year}) AND (year_to IS NULL OR year_to >= {year})
|
||||
GROUP BY t.vtrgid
|
||||
ORDER BY LENGTH(t.vtrgid) DESC, t.vtrgid
|
||||
""";
|
||||
|
||||
var reader = await cmd.ExecuteReaderAsync();
|
||||
while (await reader.ReadAsync()) {
|
||||
var vtrgid = reader.GetString(0);
|
||||
obligations[vtrgid] = reader.GetInt32(1);
|
||||
rights[vtrgid] = reader.GetInt32(2);
|
||||
}
|
||||
|
||||
return (rights, obligations);
|
||||
}
|
||||
|
||||
public static async Task<Dictionary<string, int>> GetMemberBucketWeights(int mgnr, int year, SqliteConnection cnx) {
|
||||
var buckets = new Dictionary<string, int>();
|
||||
|
||||
using var cmd = cnx.CreateCommand();
|
||||
cmd.CommandText = $"""
|
||||
SELECT bucket, weight
|
||||
FROM v_bucket
|
||||
WHERE (year, mgnr) = ({year}, {mgnr})
|
||||
""";
|
||||
|
||||
var reader = await cmd.ExecuteReaderAsync();
|
||||
while (await reader.ReadAsync()) {
|
||||
var bucket = reader.GetString(0);
|
||||
buckets[bucket] = reader.GetInt32(1);
|
||||
}
|
||||
|
||||
return buckets;
|
||||
}
|
||||
|
||||
protected async Task CalculateMember(int mgnr) {
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
var (rights, obligations) = await GetMemberRightsObligations(mgnr, Year, cnx);
|
||||
|
||||
var deliveries = new List<(int, int, string, int, double, string, string[], string[])>();
|
||||
using (var cmd = cnx.CreateCommand()) {
|
||||
cmd.CommandText = $"""
|
||||
SELECT did, dpnr, sortid, weight, kmw, qualid, attributes, modifiers
|
||||
FROM v_delivery
|
||||
WHERE (year, mgnr) = ({Year}, {mgnr})
|
||||
ORDER BY kmw DESC, weight DESC, did, dpnr
|
||||
""";
|
||||
var reader = await cmd.ExecuteReaderAsync();
|
||||
while (await reader.ReadAsync()) {
|
||||
deliveries.Add((
|
||||
reader.GetInt32(0), reader.GetInt32(1), reader.GetString(2), reader.GetInt32(3),
|
||||
reader.GetDouble(4), reader.GetString(5), reader.GetString(6).Split(","), reader.GetString(7).Split(",")
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (did, dpnr, sortid, weight, kmw, qualid, attributes, modifiers) in deliveries) {
|
||||
if (qualid == "WEI" || qualid == "RSW" || qualid == "LDW") {
|
||||
// Nicht mindestens Qualitätswein (QUW)
|
||||
using var cmd = cnx.CreateCommand();
|
||||
// TODO
|
||||
cmd.CommandText = $"""
|
||||
INSERT INTO payment_delivery_part (year, did, dpnr, avnr, mod_abs, mod_rel, )
|
||||
VALUES ({Year}, {did}, {dpnr}, {AvNr}, )
|
||||
""";
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
139
Elwig/Helpers/ClientParameters.cs
Normal file
139
Elwig/Helpers/ClientParameters.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using Elwig.Models;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
public class ClientParameters {
|
||||
|
||||
public enum Type { Matzen, GWK };
|
||||
|
||||
public bool IsMatzen => Client == Type.Matzen;
|
||||
public bool IsGWK => Client == Type.GWK;
|
||||
|
||||
public string NameToken;
|
||||
public string NameShort;
|
||||
public string Name;
|
||||
public string? NameSuffix;
|
||||
public string NameType;
|
||||
public string NameFull => NameSuffix == null ? $"{Name} {NameType}" : $"{Name}, {NameSuffix}, {NameType}";
|
||||
public Type? Client;
|
||||
|
||||
public PostalDest PostalDest {
|
||||
set {
|
||||
Plz = value.AtPlz.Plz;
|
||||
Ort = value.AtPlz.Ort.Name;
|
||||
}
|
||||
}
|
||||
public int Plz;
|
||||
public string Ort;
|
||||
public string Address;
|
||||
public string Sender1 => $"{NameShort} | {Address} | {Plz} {Ort}";
|
||||
public string Sender2;
|
||||
|
||||
public string? Iban;
|
||||
public string? Bic;
|
||||
public string? UstIdNr;
|
||||
public string? LfbisNr;
|
||||
|
||||
public string? PhoneNr;
|
||||
public string? FaxNr;
|
||||
public string? EmailAddress;
|
||||
public string? Website;
|
||||
|
||||
public int DeliveryObligation;
|
||||
public int DeliveryRight;
|
||||
public decimal VatNormal;
|
||||
public decimal VatReduced;
|
||||
public decimal VatFlatRate;
|
||||
|
||||
public string? TextDeliveryNote;
|
||||
|
||||
public ClientParameters(AppDbContext ctx) : this(ctx.ClientParameters.ToDictionary(e => e.Param, e => e.Value)) { }
|
||||
|
||||
public ClientParameters(Dictionary<string, string?> parameters) {
|
||||
try {
|
||||
NameToken = parameters["CLIENT_NAME_TOKEN"] ?? throw new KeyNotFoundException();
|
||||
NameShort = parameters["CLIENT_NAME_SHORT"] ?? throw new KeyNotFoundException();
|
||||
Name = parameters["CLIENT_NAME"] ?? throw new KeyNotFoundException();
|
||||
NameSuffix = parameters.GetValueOrDefault("CLIENT_NAME_SUFFIX");
|
||||
NameType = parameters["CLIENT_NAME_TYPE"] ?? throw new KeyNotFoundException();
|
||||
switch (Name) {
|
||||
case "Winzergenossenschaft für Matzen und Umgebung": Client = Type.Matzen; break;
|
||||
case "Winzerkeller im Weinviertel": Client = Type.GWK; break;
|
||||
};
|
||||
|
||||
Plz = int.Parse(parameters["CLIENT_PLZ"] ?? "");
|
||||
Ort = parameters["CLIENT_ORT"] ?? throw new KeyNotFoundException();
|
||||
Address = parameters["CLIENT_ADDRESS"] ?? throw new KeyNotFoundException();
|
||||
PhoneNr = parameters.GetValueOrDefault("CLIENT_PHONE");
|
||||
FaxNr = parameters.GetValueOrDefault("CLIENT_FAX");
|
||||
EmailAddress = parameters.GetValueOrDefault("CLIENT_EMAIL");
|
||||
Website = parameters.GetValueOrDefault("CLIENT_WEBSITE");
|
||||
LfbisNr = parameters.GetValueOrDefault("CLIENT_LFBISNR");
|
||||
UstIdNr = parameters.GetValueOrDefault("CLIENT_USTIDNR");
|
||||
Bic = parameters.GetValueOrDefault("CLIENT_BIC");
|
||||
Iban = parameters.GetValueOrDefault("CLIENT_IBAN");
|
||||
|
||||
DeliveryObligation = int.Parse(parameters["DELIVERY_OBLIGATION"] ?? "");
|
||||
DeliveryRight = int.Parse(parameters["DELIVERY_RIGHT"] ?? "");
|
||||
VatNormal = decimal.Parse((parameters["VAT_NORMAL"] ?? "").Replace(".", ","));
|
||||
VatReduced = decimal.Parse((parameters["VAT_REDUCED"] ?? "").Replace(".", ","));
|
||||
VatFlatRate = decimal.Parse((parameters["VAT_FLATRATE"] ?? "").Replace(".", ","));
|
||||
|
||||
Sender2 = parameters.GetValueOrDefault("DOCUMENT_SENDER") ?? "";
|
||||
TextDeliveryNote = parameters.GetValueOrDefault("TEXT_DELIVERYNOTE");
|
||||
} catch {
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<(string, string?)> GetParamValues() {
|
||||
return new (string, string?)[] {
|
||||
("CLIENT_NAME_TOKEN", NameToken),
|
||||
("CLIENT_NAME_SHORT", NameShort),
|
||||
("CLIENT_NAME", Name),
|
||||
("CLIENT_NAME_SUFFIX", NameSuffix),
|
||||
("CLIENT_NAME_TYPE", NameType),
|
||||
("CLIENT_PLZ", Plz.ToString()),
|
||||
("CLIENT_ORT", Ort),
|
||||
("CLIENT_ADDRESS", Address),
|
||||
("CLIENT_PHONE", PhoneNr),
|
||||
("CLIENT_FAX", FaxNr),
|
||||
("CLIENT_EMAIL", EmailAddress),
|
||||
("CLIENT_WEBSITE", Website),
|
||||
("CLIENT_LFBISNR", LfbisNr),
|
||||
("CLIENT_USTIDNR", UstIdNr),
|
||||
("CLIENT_BIC", Bic),
|
||||
("CLIENT_IBAN", Iban),
|
||||
("DELIVERY_OBLIGATION", DeliveryObligation.ToString()),
|
||||
("DELIVERY_RIGHT", DeliveryRight.ToString()),
|
||||
("VAT_NORMAL", VatNormal.ToString().Replace(",", ".")),
|
||||
("VAT_REDUCED", VatReduced.ToString().Replace(",", ".")),
|
||||
("VAT_FLATRATE", VatFlatRate.ToString().Replace(",", ".")),
|
||||
("DOCUMENT_SENDER", Sender2),
|
||||
("TEXT_DELIVERYNOTE", TextDeliveryNote),
|
||||
};
|
||||
}
|
||||
|
||||
public async Task UpdateValues() {
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
using var cmd = cnx.CreateCommand();
|
||||
var pv = GetParamValues();
|
||||
cmd.CommandText = "INSERT INTO client_parameter (param, value) VALUES " +
|
||||
string.Join(", ", pv.Select((pv, i) => $"(@p{i}, " + (pv.Item2 != null ? $"@v{i}" : "NULL") + ")")) +
|
||||
" ON CONFLICT DO UPDATE SET value = excluded.value";
|
||||
|
||||
int i = 0;
|
||||
foreach (var (p, v) in pv) {
|
||||
cmd.Parameters.Add(new SqliteParameter($"@p{i}", p));
|
||||
if (v != null)
|
||||
cmd.Parameters.Add(new SqliteParameter($"@v{i}", v));
|
||||
i++;
|
||||
}
|
||||
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,8 +11,9 @@ namespace Elwig.Helpers {
|
||||
private readonly string FileName;
|
||||
public string DatabaseFile = App.DataPath + "database.sqlite3";
|
||||
public string? DatabaseLog = null;
|
||||
public IEnumerable<string[]> Scales;
|
||||
private readonly LinkedList<string[]> ScaleList = new();
|
||||
public string? Branch = null;
|
||||
public IList<string?[]> Scales;
|
||||
private readonly List<string?[]> ScaleList = new();
|
||||
|
||||
public Config(string filename) {
|
||||
FileName = filename;
|
||||
@@ -43,13 +44,26 @@ namespace Elwig.Helpers {
|
||||
DatabaseLog = App.DataPath + log;
|
||||
}
|
||||
|
||||
if (ini == null || !ini.TryGetKey("general.branch", out string branch)) {
|
||||
Branch = null;
|
||||
} else {
|
||||
Branch = branch;
|
||||
}
|
||||
|
||||
ScaleList.Clear();
|
||||
Scales = ScaleList;
|
||||
if (ini != null) {
|
||||
foreach (var s in ini.Sections.Where(s => s.SectionName.StartsWith("scale."))) {
|
||||
ScaleList.AddLast(new string[] {
|
||||
string? scaleLog = null;
|
||||
if (s.Keys["log"] != null) {
|
||||
scaleLog = s.Keys["log"];
|
||||
if (scaleLog.Length <= 1 || (scaleLog[1] != ':' && scaleLog[0] != '/' && scaleLog[0] != '\\')) {
|
||||
scaleLog = App.DataPath + scaleLog;
|
||||
}
|
||||
}
|
||||
ScaleList.Add(new string?[] {
|
||||
s.SectionName[6..], s.Keys["type"], s.Keys["model"], s.Keys["connection"],
|
||||
s.Keys["empty"], s.Keys["filling"], s.Keys["limit"]
|
||||
s.Keys["empty"], s.Keys["filling"], s.Keys["limit"], scaleLog
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -57,6 +71,8 @@ namespace Elwig.Helpers {
|
||||
|
||||
public void Write() {
|
||||
using var file = new StreamWriter(FileName, false, Encoding.UTF8);
|
||||
file.Write($"\r\n[general]\r\n");
|
||||
if (Branch != null) file.Write($"branch = {Branch}\r\n");
|
||||
file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n");
|
||||
if (DatabaseLog != null) file.Write($"log = {DatabaseLog}\r\n");
|
||||
foreach (var s in ScaleList) {
|
||||
@@ -64,6 +80,7 @@ namespace Elwig.Helpers {
|
||||
if (s[4] != null) file.Write($"empty = {s[4]}\r\n");
|
||||
if (s[5] != null) file.Write($"filling = {s[5]}\r\n");
|
||||
if (s[6] != null) file.Write($"limit = {s[6]}\r\n");
|
||||
if (s[7] != null) file.Write($"log = {s[7]}\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
223
Elwig/Helpers/ControlUtils.cs
Normal file
223
Elwig/Helpers/ControlUtils.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
public class ControlUtils {
|
||||
|
||||
public enum RenewSourceDefault {
|
||||
None,
|
||||
IfOnly,
|
||||
First
|
||||
}
|
||||
|
||||
private static void SetControlBrush(Control input, Brush brush) {
|
||||
if (input is ComboBox cb) {
|
||||
var border = GetComboBoxBorder(cb);
|
||||
if (border != null) border.BorderBrush = brush;
|
||||
} else {
|
||||
input.BorderBrush = brush;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetInputNotDefault(Control input) {
|
||||
SetControlBrush(input, Brushes.Gold);
|
||||
}
|
||||
|
||||
public static void SetInputChanged(Control input) {
|
||||
SetControlBrush(input, Brushes.Orange);
|
||||
}
|
||||
|
||||
public static void SetInputInvalid(Control input) {
|
||||
SetControlBrush(input, Brushes.Red);
|
||||
}
|
||||
|
||||
public static void ClearInputState(Control input) {
|
||||
if (input is ComboBox cb) {
|
||||
GetComboBoxBorder(cb)?.ClearValue(Border.BorderBrushProperty);
|
||||
} else {
|
||||
input.ClearValue(Control.BorderBrushProperty);
|
||||
}
|
||||
}
|
||||
|
||||
private static Border? GetComboBoxBorder(ComboBox cb) {
|
||||
var toggleButton = cb.Template.FindName("toggleButton", cb) as ToggleButton;
|
||||
return toggleButton?.Template.FindName("templateRoot", toggleButton) as Border;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> FindAllChildren<T>(DependencyObject depObj) where T : DependencyObject {
|
||||
if (depObj == null)
|
||||
yield return (T)Enumerable.Empty<T>();
|
||||
foreach (var child in LogicalTreeHelper.GetChildren(depObj)) {
|
||||
if (child == null) {
|
||||
continue;
|
||||
} else if (child is T t) {
|
||||
yield return t;
|
||||
} else if (child is DependencyObject childDepOpj) {
|
||||
foreach (T childOfChild in FindAllChildren<T>(childDepOpj)) {
|
||||
yield return childOfChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<T> FindAllChildren<T>(DependencyObject depObj, IEnumerable<DependencyObject> exempt) where T : DependencyObject {
|
||||
return FindAllChildren<T>(depObj).Where(c => !exempt.Contains(c));
|
||||
}
|
||||
|
||||
public static T? FindNextSibling<T>(Control me) where T : DependencyObject {
|
||||
var found = false;
|
||||
foreach (var child in LogicalTreeHelper.GetChildren(me.Parent)) {
|
||||
if (found && child is T c) {
|
||||
return c;
|
||||
} else if (child == me) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void RenewItemsSource(Selector selector, IEnumerable? source, Func<object?, object?> getId, SelectionChangedEventHandler? handler = null, RenewSourceDefault def = RenewSourceDefault.None) {
|
||||
if (selector.ItemsSource == source)
|
||||
return;
|
||||
var selectedId = getId(selector.SelectedItem);
|
||||
object? selItem = null;
|
||||
if (selectedId != null && source != null)
|
||||
selItem = source.Cast<object>().FirstOrDefault(i => selectedId.Equals(getId(i)));
|
||||
if (source != null && selItem == null) {
|
||||
if ((def == RenewSourceDefault.IfOnly && source.Cast<object>().Count() == 1) || def == RenewSourceDefault.First) {
|
||||
selItem = source.Cast<object>().First();
|
||||
}
|
||||
}
|
||||
if (handler != null && selItem != null) selector.SelectionChanged -= handler;
|
||||
selector.ItemsSource = source;
|
||||
if (handler != null && selItem != null) selector.SelectionChanged += handler;
|
||||
selector.SelectedItem = selItem;
|
||||
}
|
||||
|
||||
public static void RenewItemsSource(Xceed.Wpf.Toolkit.Primitives.Selector selector, IEnumerable? source, Func<object?, object?> getId) {
|
||||
if (selector.ItemsSource == source)
|
||||
return;
|
||||
var selectedIds = selector.SelectedItems.Cast<object>().Select(i => getId(i)).ToList();
|
||||
selector.ItemsSource = source;
|
||||
if (source != null) {
|
||||
selector.SelectedItems.Clear();
|
||||
foreach (var i in source.Cast<object>().Where(i => selectedIds.Contains(getId(i))))
|
||||
selector.SelectedItems.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void RenewItemsSource(DataGrid dataGrid, IEnumerable? source, Func<object?, object?> getId, SelectionChangedEventHandler? handler = null, RenewSourceDefault def = RenewSourceDefault.None, bool keepSort = true) {
|
||||
if (dataGrid.ItemsSource == source)
|
||||
return;
|
||||
var column = dataGrid.CurrentCell.Column;
|
||||
var sortColumns = dataGrid.Columns.Select(c => c.SortDirection).ToList();
|
||||
var sort = dataGrid.Items.SortDescriptions.ToList();
|
||||
var selectedId = getId(dataGrid.SelectedItem);
|
||||
object? selItem = null;
|
||||
if (selectedId != null && source != null)
|
||||
selItem = source.Cast<object>().FirstOrDefault(i => selectedId.Equals(getId(i)));
|
||||
if (source != null && selItem == null) {
|
||||
if ((def == RenewSourceDefault.IfOnly && source.Cast<object>().Count() == 1) || def == RenewSourceDefault.First) {
|
||||
selItem = source.Cast<object>().First();
|
||||
}
|
||||
}
|
||||
if (handler != null && selItem != null) dataGrid.SelectionChanged -= handler;
|
||||
dataGrid.ItemsSource = source;
|
||||
if (handler != null && selItem != null) dataGrid.SelectionChanged += handler;
|
||||
dataGrid.SelectedItem = selItem;
|
||||
if (keepSort) {
|
||||
for (int i = 0; i < dataGrid.Columns.Count; i++)
|
||||
dataGrid.Columns[i].SortDirection = sortColumns[i];
|
||||
foreach (var s in sort)
|
||||
dataGrid.Items.SortDescriptions.Add(s);
|
||||
}
|
||||
if (dataGrid.SelectedItem != null && column != null)
|
||||
dataGrid.CurrentCell = new(dataGrid.SelectedItem, column);
|
||||
}
|
||||
|
||||
public static void RenewItemsSource(ListBox listBox, IEnumerable? source, Func<object?, object?> getId, SelectionChangedEventHandler? handler = null, RenewSourceDefault def = RenewSourceDefault.None) {
|
||||
if (listBox.ItemsSource == source)
|
||||
return;
|
||||
var selectedId = getId(listBox.SelectedItem);
|
||||
object? selItem = null;
|
||||
if (selectedId != null && source != null)
|
||||
selItem = source.Cast<object>().FirstOrDefault(i => selectedId.Equals(getId(i)));
|
||||
if (source != null && selItem == null) {
|
||||
if ((def == RenewSourceDefault.IfOnly && source.Cast<object>().Count() == 1) || def == RenewSourceDefault.First) {
|
||||
selItem = source.Cast<object>().FirstOrDefault();
|
||||
}
|
||||
}
|
||||
if (handler != null && selItem != null) listBox.SelectionChanged -= handler;
|
||||
listBox.ItemsSource = source;
|
||||
if (handler != null && selItem != null) listBox.SelectionChanged += handler;
|
||||
listBox.SelectedItem = selItem;
|
||||
}
|
||||
|
||||
public static object? GetItemFromSource(IEnumerable source, Func<object?, object?> getId, object? id) {
|
||||
if (source == null)
|
||||
return null;
|
||||
var items = source.Cast<object>();
|
||||
var item = items.Where(i => getId(i)?.Equals(id) ?? false).FirstOrDefault();
|
||||
if (item == null && items.Any(i => i is NullItem))
|
||||
return items.Where(i => i is NullItem).First();
|
||||
return item;
|
||||
}
|
||||
|
||||
public static object? GetItemFromSource(IEnumerable source, object? item, Func<object?, object?> getId) {
|
||||
return GetItemFromSource(source, getId, getId(item));
|
||||
}
|
||||
|
||||
public static void SelectComboBoxItem(ComboBox cb, Func<object?, object?> getId, object? id) {
|
||||
cb.SelectedItem = GetItemFromSource(cb.ItemsSource, getId, id);
|
||||
}
|
||||
|
||||
public static void SelectComboBoxItem(ComboBox cb, object? item, Func<object?, object?> getId) {
|
||||
SelectComboBoxItem(cb, getId, getId(item));
|
||||
}
|
||||
|
||||
public static IEnumerable<object?> GetItemsFromSource(IEnumerable source, Func<object?, object?> getId, IEnumerable<object?> ids) {
|
||||
if (source == null)
|
||||
return Array.Empty<object>();
|
||||
return source.Cast<object>().Where(i => ids.Any(c => c?.Equals(getId(i)) ?? false));
|
||||
}
|
||||
|
||||
public static IEnumerable<object?> GetItemsFromSource(IEnumerable source, IEnumerable<object?>? items, Func<object?, object?> getId) {
|
||||
if (items == null)
|
||||
return Array.Empty<object>();
|
||||
return GetItemsFromSource(source, getId, items.Select(i => getId(i)));
|
||||
}
|
||||
|
||||
public static void SelectCheckComboBoxItems(Xceed.Wpf.Toolkit.CheckComboBox ccb, Func<object?, object?> getId, IEnumerable<object?>? ids) {
|
||||
ccb.SelectedItems.Clear();
|
||||
if (ids == null) return;
|
||||
foreach (var id in ids)
|
||||
ccb.SelectedItems.Add(GetItemFromSource(ccb.ItemsSource, getId, id));
|
||||
}
|
||||
|
||||
public static void SelectCheckComboBoxItems(Xceed.Wpf.Toolkit.CheckComboBox ccb, IEnumerable<object>? items, Func<object?, object?> getId) {
|
||||
SelectCheckComboBoxItems(ccb, getId, items?.Select(i => getId(i)));
|
||||
}
|
||||
|
||||
public static object? GetInputValue(Control input) {
|
||||
if (input is TextBox tb) {
|
||||
return tb.Text;
|
||||
} else if (input is ComboBox sb) {
|
||||
return sb.SelectedItem;
|
||||
} else if (input is Xceed.Wpf.Toolkit.CheckComboBox ccb) {
|
||||
return ccb.SelectedItems.Cast<object>().ToArray();
|
||||
} else if (input is CheckBox cb) {
|
||||
return cb.IsChecked?.ToString();
|
||||
} else if (input is RadioButton rb) {
|
||||
return rb.IsChecked?.ToString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
4
Elwig/Helpers/Export/Bki.cs
Normal file
4
Elwig/Helpers/Export/Bki.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
namespace Elwig.Helpers.Export {
|
||||
public class Bki {
|
||||
}
|
||||
}
|
4
Elwig/Helpers/Export/Csv.cs
Normal file
4
Elwig/Helpers/Export/Csv.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
namespace Elwig.Helpers.Export {
|
||||
public class Csv {
|
||||
}
|
||||
}
|
15
Elwig/Helpers/Export/Ebics.cs
Normal file
15
Elwig/Helpers/Export/Ebics.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Elwig.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Helpers.Export {
|
||||
public class Ebics : IBankingProvider {
|
||||
|
||||
public string FileExtension => "xml";
|
||||
|
||||
public Task Export(string filename, int avnr, IEnumerable<Member> members) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
15
Elwig/Helpers/Export/Elba.cs
Normal file
15
Elwig/Helpers/Export/Elba.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Elwig.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Helpers.Export {
|
||||
public class Elba : IBankingProvider {
|
||||
|
||||
public string FileExtension => "elba";
|
||||
|
||||
public Task Export(string filename, int avnr, IEnumerable<Member> members) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
24
Elwig/Helpers/Export/IBankingProvider.cs
Normal file
24
Elwig/Helpers/Export/IBankingProvider.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Elwig.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Helpers.Export {
|
||||
/// <summary>
|
||||
/// Interface for exporting banking data
|
||||
/// </summary>
|
||||
public interface IBankingProvider {
|
||||
/// <summary>
|
||||
/// The default file extension of the exported files to be used (whithout a preceding ".")
|
||||
/// </summary>
|
||||
string FileExtension { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Export the member payment data of the given payment variant to the given file.
|
||||
/// (The amount of the last payed variant is deducted from the calculated amount.)
|
||||
/// </summary>
|
||||
/// <param name="filename">The file to export the data to</param>
|
||||
/// <param name="avnr">The number of the payment variant to export</param>
|
||||
/// <param name="members">The members whose data to include in the export</param>
|
||||
Task Export(string filename, int avnr, IEnumerable<Member> members);
|
||||
}
|
||||
}
|
5
Elwig/Helpers/NullItem.cs
Normal file
5
Elwig/Helpers/NullItem.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace Elwig.Helpers {
|
||||
public class NullItem {
|
||||
public static string Name => "- Keine Angabe -";
|
||||
}
|
||||
}
|
@@ -8,7 +8,7 @@ namespace Elwig.Helpers {
|
||||
|
||||
public TempFile() : this(null) { }
|
||||
|
||||
public TempFile(string? ext) : this(Path.Combine(Path.GetTempPath(), "Elwig"), ext) { }
|
||||
public TempFile(string? ext) : this(App.TempPath, ext) { }
|
||||
|
||||
public TempFile(string dir, string? ext) {
|
||||
FilePath = Path.Combine(dir, Path.GetRandomFileName().Replace(".", "") + (ext != null ? $".{ext}" : ""));
|
||||
|
@@ -2,32 +2,82 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO.Ports;
|
||||
using PdfSharp.Charting;
|
||||
using System.Net.Sockets;
|
||||
using Elwig.Dialogs;
|
||||
using System.Text;
|
||||
using System.Numerics;
|
||||
using Elwig.Models;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
public static partial class Utils {
|
||||
|
||||
public static int CurrentSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0);
|
||||
public static int CurrentYear => DateTime.Now.Year;
|
||||
public static int CurrentNextSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0);
|
||||
public static int CurrentLastSeason => DateTime.Now.Year - (DateTime.Now.Month <= 7 ? 1 : 0);
|
||||
public static DateTime Today => (DateTime.Now.Hour >= 3) ? DateTime.Today : DateTime.Today.AddDays(-1);
|
||||
|
||||
public static readonly Regex SerialRegex = GeneratedSerialRegex();
|
||||
public static readonly Regex TcpRegex = GeneratedTcpRegex();
|
||||
public static readonly Regex PartialDateRegex = GeneratedPartialDateRegex();
|
||||
public static readonly Regex FromToRegex = GeneratedFromToRegex();
|
||||
public static readonly Regex FromToTimeRegex = GeneratedFromToTimeRegex();
|
||||
|
||||
[GeneratedRegex("^serial://([A-Za-z0-9]+):([0-9]+)(,([5-9]),([NOEMSnoems]),(0|1|1\\.5|2|))?$", RegexOptions.Compiled)]
|
||||
private static partial Regex GeneratedSerialRegex();
|
||||
|
||||
[GeneratedRegex("^tcp://[A-Za-z0-9:._-]+(:[0-9]+)?$", RegexOptions.Compiled)]
|
||||
[GeneratedRegex("^tcp://([A-Za-z0-9._-]+):([0-9]+)$", RegexOptions.Compiled)]
|
||||
private static partial Regex GeneratedTcpRegex();
|
||||
|
||||
[GeneratedRegex(@"^(0?[1-9]|[12][0-9]|3[01])\.(0?[1-9]|1[0-2])\.$", RegexOptions.Compiled)]
|
||||
private static partial Regex GeneratedPartialDateRegex();
|
||||
|
||||
[GeneratedRegex(@"^([0-9]+([\.,][0-9]+)?)?-([0-9]+([\.,][0-9]+)?)?$", RegexOptions.Compiled)]
|
||||
private static partial Regex GeneratedFromToRegex();
|
||||
|
||||
[GeneratedRegex(@"^([0-9]{1,2}:[0-9]{2})?-([0-9]{1,2}:[0-9]{2})?$", RegexOptions.Compiled)]
|
||||
private static partial Regex GeneratedFromToTimeRegex();
|
||||
|
||||
private static readonly ushort[] Crc16ModbusTable = {
|
||||
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
||||
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
||||
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
||||
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
||||
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
||||
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
||||
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
||||
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
||||
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
||||
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
||||
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
||||
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
||||
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
||||
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
||||
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
||||
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
||||
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
||||
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
||||
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
||||
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
||||
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
||||
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
||||
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
||||
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
||||
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
||||
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
||||
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
||||
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
||||
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
||||
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
||||
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
||||
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
|
||||
};
|
||||
|
||||
public static SerialPort OpenSerialConnection(string connection) {
|
||||
var m = Utils.SerialRegex.Match(connection);
|
||||
var m = SerialRegex.Match(connection);
|
||||
if (!m.Success)
|
||||
throw new ArgumentException("Invalid connection string for scheme \"serial\"");
|
||||
|
||||
@@ -45,93 +95,28 @@ namespace Elwig.Helpers {
|
||||
DataBits = data == "" ? 8 : int.Parse(data),
|
||||
StopBits = (StopBits)(stop == "" ? 1 : stop == "1.5" ? 3 : stop[0] - '0'),
|
||||
Handshake = Handshake.None,
|
||||
WriteTimeout = 250,
|
||||
ReadTimeout = 11000,
|
||||
};
|
||||
port.Open();
|
||||
return port;
|
||||
}
|
||||
|
||||
public static TcpClient OpenTcpConnection(string connection) {
|
||||
var m = Utils.TcpRegex.Match(connection);
|
||||
var m = TcpRegex.Match(connection);
|
||||
if (!m.Success)
|
||||
throw new ArgumentException("Invalid connection string for scheme \"tcp\"");
|
||||
|
||||
var client = new TcpClient() {
|
||||
SendTimeout = 250,
|
||||
ReceiveTimeout = 250,
|
||||
ReceiveTimeout = 11000,
|
||||
};
|
||||
client.Connect(m.Groups[1].Value, int.Parse(m.Groups[2].Value));
|
||||
return client;
|
||||
}
|
||||
|
||||
public static void SetInputChanged(Control input) {
|
||||
var brush = Brushes.Orange;
|
||||
if (input is ComboBox cb) {
|
||||
var border = GetComboBoxBorder(cb);
|
||||
if (border != null)
|
||||
border.BorderBrush = brush;
|
||||
} else {
|
||||
input.BorderBrush = brush;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetInputInvalid(Control input) {
|
||||
var brush = Brushes.Red;
|
||||
if (input is ComboBox cb) {
|
||||
var border = GetComboBoxBorder(cb);
|
||||
if (border != null)
|
||||
border.BorderBrush = brush;
|
||||
} else {
|
||||
input.BorderBrush = brush;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearInputState(Control input) {
|
||||
if (input is ComboBox cb) {
|
||||
GetComboBoxBorder(cb)?.ClearValue(Border.BorderBrushProperty);
|
||||
} else {
|
||||
input.ClearValue(Control.BorderBrushProperty);
|
||||
}
|
||||
}
|
||||
|
||||
private static Border? GetComboBoxBorder(ComboBox cb) {
|
||||
var toggleButton = cb.Template.FindName("toggleButton", cb) as ToggleButton;
|
||||
return toggleButton?.Template.FindName("templateRoot", toggleButton) as Border;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> FindAllChildren<T>(DependencyObject depObj) where T : DependencyObject {
|
||||
if (depObj == null)
|
||||
yield return (T)Enumerable.Empty<T>();
|
||||
foreach (var child in LogicalTreeHelper.GetChildren(depObj)) {
|
||||
if (child == null) {
|
||||
continue;
|
||||
} else if (child is T t) {
|
||||
yield return t;
|
||||
} else if (child is DependencyObject childDepOpj) {
|
||||
foreach (T childOfChild in FindAllChildren<T>(childDepOpj)) {
|
||||
yield return childOfChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<T> FindAllChildren<T>(DependencyObject depObj, IEnumerable<DependencyObject> exempt) where T : DependencyObject {
|
||||
return FindAllChildren<T>(depObj).Where(c => !exempt.Contains(c));
|
||||
}
|
||||
|
||||
public static T? FindNextSibling<T>(Control me) where T : DependencyObject {
|
||||
var found = false;
|
||||
foreach (var child in LogicalTreeHelper.GetChildren(me.Parent)) {
|
||||
if (found && child is T c) {
|
||||
return c;
|
||||
} else if (child == me) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int Modulo(string a, int b) {
|
||||
if (a.Length == 0 || !a.All(char.IsDigit)) {
|
||||
if (a.Length == 0 || !a.All(char.IsAsciiDigit)) {
|
||||
throw new ArgumentException("First argument has to be a decimal string");
|
||||
} else if (b < 2) {
|
||||
throw new ArgumentException("Second argument has to be greater than 1");
|
||||
@@ -139,6 +124,22 @@ namespace Elwig.Helpers {
|
||||
return a.Select(ch => ch - '0').Aggregate((sum, n) => (sum * 10 + n) % b);
|
||||
}
|
||||
|
||||
public static ushort CalcCrc16Modbus(byte[] data) {
|
||||
// https://www.modbustools.com/modbus_crc16.htm
|
||||
byte temp;
|
||||
ushort crc = 0xFFFF;
|
||||
foreach (byte b in data) {
|
||||
temp = (byte)(b ^ crc);
|
||||
crc >>= 8;
|
||||
crc ^= Crc16ModbusTable[temp];
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
public static ushort CalcCrc16Modbus(string data) {
|
||||
return CalcCrc16Modbus(Encoding.ASCII.GetBytes(data));
|
||||
}
|
||||
|
||||
public static void RunBackground(string title, Func<Task> a) {
|
||||
Task.Run(async () => {
|
||||
try {
|
||||
@@ -173,5 +174,123 @@ namespace Elwig.Helpers {
|
||||
public static long DecToDb(decimal value, byte precision) {
|
||||
return (long)decimal.Round(value * (decimal)Math.Pow(10, precision), 0);
|
||||
}
|
||||
|
||||
public static int GetAge(DateOnly birthday) {
|
||||
var today = DateTime.Today;
|
||||
var a = (today.Year * 100 + today.Month) * 100 + today.Day;
|
||||
var b = (birthday.Year * 100 + birthday.Month) * 100 + birthday.Day;
|
||||
return (a - b) / 10000;
|
||||
}
|
||||
|
||||
public static int GetSearchScore(IEnumerable<string?> words, IEnumerable<string> searchKeywords) {
|
||||
searchKeywords = searchKeywords.Where(s => s.Length >= 2 || (s.Length > 0 && s.All(c => char.IsAsciiDigit(c))));
|
||||
if (!searchKeywords.Any())
|
||||
return 0;
|
||||
|
||||
return words
|
||||
.Select(w => {
|
||||
w = w?.ToLower();
|
||||
var p = w?.ToLower()?.Split(" ");
|
||||
if (w == null || p == null)
|
||||
return 0;
|
||||
|
||||
var t1 = searchKeywords.Where(f => w == f).Select(f => f.Length).OrderDescending().FirstOrDefault(0);
|
||||
var t2 = searchKeywords.Where(f => p.Any(a => a == f)).Select(f => f.Length).OrderDescending().FirstOrDefault(0);
|
||||
var t3 = searchKeywords.Where(f => p.Any(a => a.StartsWith(f))).Select(f => f.Length).OrderDescending().FirstOrDefault(0);
|
||||
var t4 = searchKeywords.Where(f => w.Contains(f)).Select(f => f.Length).OrderDescending().FirstOrDefault(0);
|
||||
if (t1 > 0) {
|
||||
return 4 + t1;
|
||||
} else if (t2 > 0) {
|
||||
return 3 + t2;
|
||||
} else if (t3 > 0) {
|
||||
return 2 + t3;
|
||||
} else if (t4 > 0) {
|
||||
return 1 + t4;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
.Sum();
|
||||
}
|
||||
|
||||
public static (int, string?)? ShowManualWeighingDialog() {
|
||||
var d = new ManualWeighingDialog();
|
||||
return d.ShowDialog() == true ? (d.Weight, d.Reason) : null;
|
||||
}
|
||||
|
||||
public static int? ShowAbwertenDialog(string lsnr, string name, int weight) {
|
||||
var d = new AbwertenDialog(lsnr, name, weight);
|
||||
return d.ShowDialog() == true ? d.Weight : null;
|
||||
}
|
||||
|
||||
public static double? ShowLinearPriceIncreaseDialog() {
|
||||
var d = new LinearPriceIncreaseDialog();
|
||||
return d.ShowDialog() == true ? d.Price : null;
|
||||
}
|
||||
|
||||
public static string? ShowDeliveryExtractionDialog(string lsnr, string name, bool single, IEnumerable<string> lsnrs) {
|
||||
var d = new DeliveryExtractionDialog(lsnr, name, single, lsnrs);
|
||||
return d.ShowDialog() == true ? d.AddTo : null;
|
||||
}
|
||||
|
||||
public static Footer GenerateFooter(string lineBreak, string seperator) {
|
||||
return new Footer(lineBreak, seperator);
|
||||
}
|
||||
|
||||
public class Footer {
|
||||
private string Text = "";
|
||||
private readonly string LineBreak;
|
||||
private readonly string Seperator;
|
||||
private bool FirstLine = true;
|
||||
private bool FirstItemInLine = true;
|
||||
|
||||
public Footer(string lineBreak, string seperator) {
|
||||
LineBreak = lineBreak;
|
||||
Seperator = seperator;
|
||||
}
|
||||
|
||||
public Footer Item(string? text) {
|
||||
if (text == null) return this;
|
||||
Text += FirstItemInLine ? (FirstLine ? "" : LineBreak) : Seperator;
|
||||
Text += text;
|
||||
FirstLine = false;
|
||||
FirstItemInLine = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Footer Item(string name, string? text) {
|
||||
return text == null ? this : Item($"{name}: {text}");
|
||||
}
|
||||
|
||||
public Footer NextLine() {
|
||||
FirstItemInLine = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
return Text;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetSign<T>(T number) where T : INumber<T>
|
||||
=> T.Sign(number) switch {
|
||||
< 0 => "\u2212", // minus
|
||||
0 => "\u00b1", // plus minus
|
||||
> 0 => "+",
|
||||
};
|
||||
|
||||
public static double AggregateDeliveryPartsKmw(IEnumerable<DeliveryPart> parts)
|
||||
=> parts.Aggregate(
|
||||
(Weight: 0, Kmw: 0.0),
|
||||
(sum, item) => (
|
||||
sum.Weight + item.Weight,
|
||||
(sum.Kmw * sum.Weight + item.Kmw * item.Weight) / (sum.Weight + item.Weight)
|
||||
),
|
||||
sum => sum.Kmw
|
||||
);
|
||||
|
||||
public static string GenerateLsNr(Delivery d) => GenerateLsNr(d.Date, d.ZwstId, d.LNr);
|
||||
|
||||
public static string GenerateLsNr(DateOnly date, string zwstid, int lnr) => $"{date:yyyyMMdd}{zwstid}{lnr:000}";
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ using System.Windows.Controls;
|
||||
using Elwig.Models;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
static class Validator {
|
||||
public static class Validator {
|
||||
|
||||
private static readonly Dictionary<string, string[][]> PHONE_NRS = new() {
|
||||
{ "43", new string[][] {
|
||||
@@ -31,15 +31,15 @@ namespace Elwig.Helpers {
|
||||
};
|
||||
|
||||
public static ValidationResult CheckInteger(TextBox input, bool required) {
|
||||
return CheckNumeric(input, required, -1);
|
||||
return CheckInteger(input, required, -1);
|
||||
}
|
||||
|
||||
private static ValidationResult CheckNumeric(TextBox input, bool required, int maxLen) {
|
||||
public static ValidationResult CheckInteger(TextBox input, bool required, int maxLen) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
for (int i = 0; i < input.Text.Length; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (char.IsDigit(ch))
|
||||
if (char.IsAsciiDigit(ch))
|
||||
text += ch;
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
@@ -59,15 +59,80 @@ namespace Elwig.Helpers {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckDecimal(TextBox input, bool required) {
|
||||
return CheckDecimal(input, required, -1, -1);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckDecimal(TextBox input, bool required, int maxLen, int maxDecimal) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
int v1 = 0, v2 = -1;
|
||||
for (int i = 0; i < input.Text.Length; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (char.IsAsciiDigit(ch)) {
|
||||
if (v2 == -1 && v1 < maxLen) {
|
||||
text += ch; v1++;
|
||||
} else if (v2 != -1 && v2 < maxDecimal) {
|
||||
text += ch; v2++;
|
||||
}
|
||||
} else if (v2 == 0-1 && ch == ',' || ch == '.') {
|
||||
if (v1 == 0) { text += '0'; v1++; }
|
||||
text += ',';
|
||||
v2 = 0;
|
||||
}
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
}
|
||||
input.Text = text;
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (text.Length == 0) {
|
||||
return required ? new(false, "Wert ist nicht optional") : new(true, null);
|
||||
} else if (v2 == 0) {
|
||||
return new(false, "Ungültige Kommazahl");
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckUpperCase(TextBox input, bool required) {
|
||||
return CheckUpperCase(input, required, -1);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckUpperCase(TextBox input, bool required, int maxLen) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
for (int i = 0; i < input.Text.Length; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (char.IsAsciiLetter(ch))
|
||||
text += char.ToUpper(ch);
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
}
|
||||
input.Text = text;
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (text.Length == 0) {
|
||||
return required ? new(false, "Wert ist nicht optional") : new(true, null);
|
||||
}
|
||||
|
||||
if (maxLen >= 0 && input.Text.Length > maxLen) {
|
||||
input.Text = input.Text[..maxLen];
|
||||
input.CaretIndex = Math.Min(pos, maxLen);
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckPlz(TextBox input, bool required, AppDbContext ctx) {
|
||||
CheckNumeric(input, false, 4);
|
||||
CheckInteger(input, false, 4);
|
||||
if (!required && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
} else if (input.Text.Length != 4) {
|
||||
return new(false, "PLZ zu kurz");
|
||||
}
|
||||
int plz = int.Parse(input.Text);
|
||||
if (!ctx.Postleitzahlen.Any(p => p.Plz == plz)) {
|
||||
if (ctx.Postleitzahlen.Find(plz) == null) {
|
||||
return new(false, "Ungültige PLZ");
|
||||
}
|
||||
return new(true, null);
|
||||
@@ -76,7 +141,7 @@ namespace Elwig.Helpers {
|
||||
public static ValidationResult CheckPhoneNumber(TextBox input, bool required) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
for (int i = 0, v = 0; i < input.Text.Length && v < 30; i++) {
|
||||
for (int i = 0, v = 0; i < input.Text.Length && v <= 15; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (v == 0 && input.Text.Length - i >= 2 && ch == '0' && input.Text[i + 1] == '0') {
|
||||
v++; i++;
|
||||
@@ -89,21 +154,30 @@ namespace Elwig.Helpers {
|
||||
} else if (v == 0 && ch == '+') {
|
||||
v++;
|
||||
text += ch;
|
||||
} else if (v > 0 && char.IsDigit(ch)) {
|
||||
} else if (v > 0 && (char.IsAsciiDigit(ch) || ch == ' ' || ch == '-')) {
|
||||
if (PHONE_NRS.Any(kv => text == "+" + kv.Key))
|
||||
text += ' ';
|
||||
if (text.StartsWith("+43 ")) {
|
||||
var nr = text[4..];
|
||||
var vws = PHONE_NRS["43"];
|
||||
if (v >= 4 && v - 4 < vws.Length && vws[v - 4].Any(vw => nr.StartsWith(vw)))
|
||||
if (!text.EndsWith(" ") && v >= 4 && v - 4 < vws.Length && vws[v - 4].Any(vw => nr.StartsWith(vw))) {
|
||||
text += ' ';
|
||||
else if (nr == "1")
|
||||
} else if (nr == "1") {
|
||||
text += ' ';
|
||||
else if (v == 7 && nr.Length == 4)
|
||||
} else if (v == 7 && nr.Length == 4) {
|
||||
text += ' ';
|
||||
}
|
||||
var vw = text.Split(" ");
|
||||
if (char.IsAsciiDigit(ch)) {
|
||||
v++;
|
||||
text += ch;
|
||||
} else if (char.IsAsciiDigit(text[^1]) && vw.Length > 2 && v >= 10 && (vw[1].Length - 1 >= vws.Length || !vws[vw[1].Length - 1].Any(v => vw[1].StartsWith(v)))) {
|
||||
text += ch;
|
||||
}
|
||||
} else {
|
||||
v++;
|
||||
text += ch;
|
||||
}
|
||||
v++;
|
||||
text += ch;
|
||||
}
|
||||
if (i == input.CaretIndex - 1)
|
||||
pos = text.Length;
|
||||
@@ -117,7 +191,7 @@ namespace Elwig.Helpers {
|
||||
return new(false, "Telefonnummer zu kurz");
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
return new(char.IsAsciiDigit(text[^1]), null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckEmailAddress(TextBox input, bool required) {
|
||||
@@ -127,7 +201,7 @@ namespace Elwig.Helpers {
|
||||
for (int i = 0; i < input.Text.Length && text.Length < 256; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (domain) {
|
||||
if ((char.IsAscii(ch) && char.IsLetterOrDigit(ch)) || ".-_öäüßÖÄÜẞ".Any(c => c == ch)) {
|
||||
if ((char.IsAsciiLetterOrDigit(ch)) || ".-_öäüßÖÄÜẞ".Any(c => c == ch)) {
|
||||
if (!(text.Last() == '.' && ch == '.'))
|
||||
text += char.ToLower(ch);
|
||||
}
|
||||
@@ -145,13 +219,13 @@ namespace Elwig.Helpers {
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (text.Length == 0) {
|
||||
return required ? new(false, "E-Mail_Adresse ist nicht optional") : new(true, null);
|
||||
return required ? new(false, "E-Mail-Adresse ist nicht optional") : new(true, null);
|
||||
} else if (text[0] == '@' || !domain) {
|
||||
return new(false, "E-Mail-Adresse ungültig");
|
||||
}
|
||||
|
||||
var last = text.Split(".").Last();
|
||||
if (last.Length < 2 || !last.All(ch => char.IsAscii(ch) && char.IsLower(ch)))
|
||||
if (last.Length < 2 || !last.All(ch => char.IsAsciiLetterLower(ch)))
|
||||
return new(false, "E-Mail-Adresse ungültig");
|
||||
|
||||
return new(true, null);
|
||||
@@ -163,9 +237,9 @@ namespace Elwig.Helpers {
|
||||
int v = 0;
|
||||
for (int i = 0; i < input.Text.Length && v < 34; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (char.IsLetterOrDigit(ch) && char.IsAscii(ch)) {
|
||||
if (((v < 2 && char.IsLetter(ch)) || (v >= 2 && v < 4 && char.IsDigit(ch)) || v >= 4) &&
|
||||
((!text.StartsWith("AT") && !text.StartsWith("DE")) || char.IsDigit(ch)))
|
||||
if (char.IsAsciiLetterOrDigit(ch)) {
|
||||
if (((v < 2 && char.IsAsciiLetter(ch)) || (v >= 2 && v < 4 && char.IsAsciiDigit(ch)) || v >= 4) &&
|
||||
((!text.StartsWith("AT") && !text.StartsWith("DE")) || char.IsAsciiDigit(ch)))
|
||||
{
|
||||
if (v != 0 && v % 4 == 0)
|
||||
text += ' ';
|
||||
@@ -190,7 +264,7 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
var validation = (text[4..] + text[..4]).Replace(" ", "")
|
||||
.Select(ch => char.IsDigit(ch) ? ch.ToString() : (ch - 'A' + 10).ToString())
|
||||
.Select(ch => char.IsAsciiDigit(ch) ? ch.ToString() : (ch - 'A' + 10).ToString())
|
||||
.Aggregate((a, b) => a + b);
|
||||
if (Utils.Modulo(validation, 97) != 1)
|
||||
return new(false, "Prüfsumme der IBAN ist falsch");
|
||||
@@ -203,10 +277,10 @@ namespace Elwig.Helpers {
|
||||
int pos = input.CaretIndex;
|
||||
for (int i = 0, v = 0; i < input.Text.Length; i++) {
|
||||
char ch = input.Text[i];
|
||||
if ((v < 4 || v >= 6) && char.IsAscii(ch) && char.IsLetterOrDigit(ch)) {
|
||||
if ((v < 4 || v >= 6) && char.IsAsciiLetterOrDigit(ch)) {
|
||||
v++;
|
||||
text += char.ToUpper(ch);
|
||||
} else if (v >= 4 && v < 6 && char.IsAscii(ch) && char.IsLetter(ch)) {
|
||||
} else if (v >= 4 && v < 6 && char.IsAsciiLetter(ch)) {
|
||||
v++;
|
||||
text += char.ToUpper(ch);
|
||||
}
|
||||
@@ -237,7 +311,7 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
public static ValidationResult CheckLfbisNr(TextBox input, bool required) {
|
||||
var res = CheckNumeric(input, false, 7);
|
||||
var res = CheckInteger(input, false, 7);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
} else if (!required && input.Text.Length == 0) {
|
||||
@@ -247,7 +321,7 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
// https://statistik.at/fileadmin/shared/QM/Standarddokumentationen/RW/std_r_land-forstw_register.pdf#page=41
|
||||
int s = 0, v = 0;
|
||||
int s = 0, v;
|
||||
for (int i = 0; i < 6; i++)
|
||||
s += (input.Text[i] - '0') * (7 - i);
|
||||
v = (11 - (s % 11)) % 10;
|
||||
@@ -258,20 +332,20 @@ namespace Elwig.Helpers {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckUstId(TextBox input, bool required) {
|
||||
public static ValidationResult CheckUstIdNr(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 (v < 2 && char.IsAscii(ch) && char.IsLetter(ch)) {
|
||||
if (v < 2 && char.IsAsciiLetter(ch)) {
|
||||
v++;
|
||||
text += char.ToUpper(ch);
|
||||
} else if (v >= 2 && char.IsAscii(ch) && char.IsLetterOrDigit(ch)) {
|
||||
} else if (v >= 2 && char.IsAsciiLetterOrDigit(ch)) {
|
||||
if (text.StartsWith("AT")) {
|
||||
if (v == 2 && (ch == 'u' || ch == 'U')) {
|
||||
v++;
|
||||
text += 'U';
|
||||
} else if (v > 2 && char.IsDigit(ch)) {
|
||||
} else if (v > 2 && char.IsAsciiDigit(ch)) {
|
||||
v++;
|
||||
text += ch;
|
||||
}
|
||||
@@ -302,7 +376,7 @@ namespace Elwig.Helpers {
|
||||
|
||||
// http://www.pruefziffernberechnung.de/U/USt-IdNr.shtml
|
||||
int s = 0, v = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int i = 0; i < 7; i++)
|
||||
s += ((text[i + 3] - '0') * (i % 2 + 1)).ToString().Select(ch => ch - '0').Sum();
|
||||
v = (96 - s) % 10;
|
||||
|
||||
@@ -315,7 +389,23 @@ namespace Elwig.Helpers {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckMgNr(TextBox input, bool required, AppDbContext ctx, Member? m) {
|
||||
public static ValidationResult CheckMgNr(TextBox input, bool required, AppDbContext ctx) {
|
||||
var res = CheckInteger(input, required);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
} else if (!required && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
int nr = int.Parse(input.Text);
|
||||
if (!ctx.MgNrExists(nr).GetAwaiter().GetResult()) {
|
||||
return new(false, "Ungültige Mitgliedsnummer");
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckNewMgNr(TextBox input, bool required, AppDbContext ctx, Member? m) {
|
||||
var res = CheckInteger(input, required);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
@@ -331,6 +421,26 @@ namespace Elwig.Helpers {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckSortId(TextBox input, bool required, AppDbContext ctx) {
|
||||
var res = CheckUpperCase(input, required, 3);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
} else if (!required && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
if (input.Text.Length < 2 || !ctx.SortIdExists(input.Text[0..2]).GetAwaiter().GetResult()) {
|
||||
return new(false, "Ungültige Sorte");
|
||||
} else if (input.Text.Length >= 3) {
|
||||
var attr = input.Text[2..];
|
||||
if (!ctx.AttrIdExists(attr).GetAwaiter().GetResult()) {
|
||||
return new(false, "Ungültiges Attribut");
|
||||
}
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckPredecessorMgNr(TextBox input, bool required, AppDbContext ctx) {
|
||||
var res = CheckInteger(input, required);
|
||||
if (!res.IsValid) {
|
||||
@@ -345,16 +455,73 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
public static ValidationResult CheckDate(TextBox input, bool required) {
|
||||
// TODO
|
||||
return new(true, "Not implemented yet");
|
||||
return CheckDate(input, required, false);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckPartialDate(TextBox input, bool required) {
|
||||
// TODO
|
||||
return new(true, "Not implemented yet");
|
||||
return CheckDate(input, required, true);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckVNr(TextBox input, bool required, AppDbContext ctx, Contract? c) {
|
||||
private static ValidationResult CheckDate(TextBox input, bool required, bool partial) {
|
||||
string text = "";
|
||||
int pos = input.CaretIndex;
|
||||
int p = 0;
|
||||
var parts = new string?[3];
|
||||
parts[0] = "";
|
||||
for (int i = 0; i < input.Text.Length; i++) {
|
||||
char ch = input.Text[i];
|
||||
if (ch == '.') {
|
||||
if (p < 2 && (parts[p]?.Length > 0 || pos == text.Length)) {
|
||||
if (parts[p]?.Length == 1 && ((pos != text.Length && pos != text.Length - 1) || !input.IsFocused)) {
|
||||
parts[p] = "0" + parts[p];
|
||||
text = text[..(text.Length - 1)] + "0" + text[^1];
|
||||
}
|
||||
parts[++p] = "";
|
||||
text += '.';
|
||||
}
|
||||
} else if (char.IsAsciiDigit(ch)) {
|
||||
if ((partial && parts[p]?.Length < 4) || (!partial && ((p < 2 && parts[p]?.Length < 2) || (p == 2 && parts[2]?.Length < 4)))) {
|
||||
parts[p] += ch;
|
||||
text += ch;
|
||||
}
|
||||
if (p == 0 && pos == 1 && input.Text.Length >= 4 && input.Text.Length <= 9) {
|
||||
parts[++p] = "";
|
||||
text += '.';
|
||||
continue; // skip caret update
|
||||
}
|
||||
}
|
||||
|
||||
if (i == input.CaretIndex - 1) {
|
||||
pos = text.Length;
|
||||
}
|
||||
}
|
||||
|
||||
input.Text = text;
|
||||
input.CaretIndex = pos;
|
||||
|
||||
if (text.Length == 0)
|
||||
return required ? new(false, "Datum ist nicht optional") : new(true, null);
|
||||
|
||||
if (partial) {
|
||||
if (p == 0) {
|
||||
// only year provided
|
||||
return (parts[0]?.Length == 4) ? new(true, null) : new(false, "Datum ist ungültig");
|
||||
} else if (p == 1) {
|
||||
// only month and year provided
|
||||
int m = parts[0] != null && parts[0] != "" ? int.Parse(parts[0] ?? "0") : 0;
|
||||
if (parts[1]?.Length != 4 || parts[0]?.Length != 2 || m < 1 || m > 12)
|
||||
return new(false, "Datum ist ungültig");
|
||||
return new(true, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!DateOnly.TryParseExact(text, "dd.MM.yyyy", out _))
|
||||
return new(false, "Datum ist ungültig");
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckFbNr(TextBox input, bool required, AppDbContext ctx, AreaCom? c) {
|
||||
var res = CheckInteger(input, required);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
@@ -363,8 +530,8 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
int nr = int.Parse(input.Text);
|
||||
if (nr != c?.VNr && ctx.VNrExists(nr).GetAwaiter().GetResult()) {
|
||||
return new(false, "Vertragsnummer wird bereits verwendet");
|
||||
if (nr != c?.FbNr && ctx.FbNrExists(nr).GetAwaiter().GetResult()) {
|
||||
return new(false, "Flächenbindungsnummer wird bereits verwendet");
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
@@ -374,5 +541,37 @@ namespace Elwig.Helpers {
|
||||
// TODO
|
||||
return new(true, "Not implemented yet");
|
||||
}
|
||||
|
||||
public static ValidationResult CheckGradatoinOe(TextBox input, bool required) {
|
||||
var res = CheckInteger(input, required, 3);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
} else if (!required && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
var oe = double.Parse(input.Text);
|
||||
if (oe < 10 || oe >= 300) {
|
||||
return new(false, "Ungültiger Oechsle-Wert");
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
public static ValidationResult CheckGradationKmw(TextBox input, bool required) {
|
||||
var res = CheckDecimal(input, required, 2, 1);
|
||||
if (!res.IsValid) {
|
||||
return res;
|
||||
} else if (!required && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
var kmw = double.Parse(input.Text);
|
||||
if (kmw < 5 || kmw >= 50) {
|
||||
return new(false, "Ungültiger KMW-Wert");
|
||||
}
|
||||
|
||||
return new(true, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,13 +14,14 @@ namespace Elwig.Helpers.Weighing {
|
||||
public string Manufacturer => "Gassner";
|
||||
public int InternalScaleNr => 1;
|
||||
public string Model { get; private set; }
|
||||
public int ScaleNr { get; private set; }
|
||||
public string ScaleId { get; private set; }
|
||||
public bool IsReady { get; private set; }
|
||||
public bool HasFillingClearance { get; private set; }
|
||||
public int? WeightLimit { get; private set; }
|
||||
public string? LogPath { get; private set; }
|
||||
|
||||
public GassnerScale(int scaleNr, string model, string connection) {
|
||||
ScaleNr = scaleNr;
|
||||
public GassnerScale(string id, string model, string connection) {
|
||||
ScaleId = id;
|
||||
Model = model;
|
||||
IsReady = true;
|
||||
HasFillingClearance = false;
|
||||
|
@@ -17,9 +17,9 @@ namespace Elwig.Helpers.Weighing {
|
||||
string Model { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Unique number of the scale
|
||||
/// Unique identificator of the scale
|
||||
/// </summary>
|
||||
int ScaleNr { get; }
|
||||
string ScaleId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal identifying number of the scale in its system
|
||||
@@ -41,6 +41,11 @@ namespace Elwig.Helpers.Weighing {
|
||||
/// </summary>
|
||||
int? WeightLimit { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Where to log the requests and responses from the scale to
|
||||
/// </summary>
|
||||
string? LogPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the current weight on the scale without performing a weighing process
|
||||
/// </summary>
|
||||
|
@@ -7,11 +7,12 @@ namespace Elwig.Helpers.Weighing {
|
||||
|
||||
public string Manufacturer => "Schember";
|
||||
public string Model => throw new NotImplementedException();
|
||||
public int ScaleNr => throw new NotImplementedException();
|
||||
public string ScaleId => throw new NotImplementedException();
|
||||
public int InternalScaleNr => throw new NotImplementedException();
|
||||
public bool IsReady => throw new NotImplementedException();
|
||||
public bool HasFillingClearance => throw new NotImplementedException();
|
||||
public int? WeightLimit => throw new NotImplementedException();
|
||||
public string? LogPath => throw new NotImplementedException();
|
||||
|
||||
public void Dispose() {
|
||||
throw new NotImplementedException();
|
||||
|
@@ -11,9 +11,9 @@ namespace Elwig.Helpers.Weighing {
|
||||
protected enum Output { RTS, DTR, OUT1, OUT2 };
|
||||
|
||||
protected SerialPort? Serial = null;
|
||||
protected SerialPort? ControlSerialEmpty = null, ControlSerialFilling = null;
|
||||
protected TcpClient? Tcp = null;
|
||||
protected StreamReader Reader;
|
||||
protected StreamWriter Writer;
|
||||
protected Stream Stream;
|
||||
|
||||
protected readonly Output? EmptyMode = null;
|
||||
protected readonly Output? FillingClearanceMode = null;
|
||||
@@ -22,71 +22,89 @@ namespace Elwig.Helpers.Weighing {
|
||||
public string Manufacturer => "SysTec";
|
||||
public int InternalScaleNr => 1;
|
||||
public string Model { get; private set; }
|
||||
public int ScaleNr { get; private set; }
|
||||
public string ScaleId { get; private set; }
|
||||
public bool IsReady { get; private set; }
|
||||
public bool HasFillingClearance { get; private set; }
|
||||
public int? WeightLimit { get; private set; }
|
||||
public string? LogPath { get; private set; }
|
||||
|
||||
public SystecScale(int scaleNr, string model, string connection, string? empty = null, string? fill = null, int? limit = null) {
|
||||
ScaleNr = scaleNr;
|
||||
public SystecScale(string id, string model, string connection, string? empty = null, string? filling = null, int? limit = null, string? log = null) {
|
||||
ScaleId = id;
|
||||
Model = model;
|
||||
IsReady = true;
|
||||
HasFillingClearance = false;
|
||||
LogPath = log;
|
||||
|
||||
Stream stream;
|
||||
if (connection.StartsWith("serial:")) {
|
||||
Serial = Utils.OpenSerialConnection(connection);
|
||||
stream = Serial.BaseStream;
|
||||
Stream = Serial.BaseStream;
|
||||
} else if (connection.StartsWith("tcp:")) {
|
||||
Tcp = Utils.OpenTcpConnection(connection);
|
||||
stream = Tcp.GetStream();
|
||||
Stream = Tcp.GetStream();
|
||||
} else {
|
||||
throw new ArgumentException("Unsupported scheme");
|
||||
}
|
||||
|
||||
if (empty != null) {
|
||||
var parts = empty.Split(':');
|
||||
EmptyMode = ConvertOutput(parts[0]);
|
||||
EmptyDelay = int.Parse(parts[1]);
|
||||
if (parts.Length == 3) {
|
||||
if (parts[0] != Serial?.PortName)
|
||||
ControlSerialEmpty = Utils.OpenSerialConnection($"serial://{parts[0]}:9600");
|
||||
} else if (parts.Length != 2) {
|
||||
throw new ArgumentException("Invalid value for 'empty'");
|
||||
}
|
||||
EmptyMode = ConvertOutput(parts[^2]);
|
||||
EmptyDelay = int.Parse(parts[^1]);
|
||||
}
|
||||
FillingClearanceMode = ConvertOutput(fill);
|
||||
WeightLimit = limit;
|
||||
if (FillingClearanceMode != null && WeightLimit == null)
|
||||
throw new ArgumentException("Weight limit has to be set, if filling clearance supervision is enalbed");
|
||||
|
||||
Writer = new(stream, Encoding.ASCII, -1, true);
|
||||
Reader = new(stream, Encoding.ASCII, false, -1, true);
|
||||
WeightLimit = limit;
|
||||
if (filling != null) {
|
||||
var parts = filling.Split(':');
|
||||
if (parts.Length == 2) {
|
||||
if (parts[0] != Serial?.PortName)
|
||||
ControlSerialFilling = parts[0] != ControlSerialEmpty?.PortName ? Utils.OpenSerialConnection($"serial://{parts[0]}:9600") : ControlSerialEmpty;
|
||||
} else if (parts.Length != 1) {
|
||||
throw new ArgumentException("Invalid value for 'filling'");
|
||||
}
|
||||
FillingClearanceMode = ConvertOutput(parts[^1]);
|
||||
}
|
||||
|
||||
if (FillingClearanceMode != null && WeightLimit == null)
|
||||
throw new ArgumentException("Weight limit has to be set, if filling clearance supervision is enabled");
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
Writer.Close();
|
||||
Reader.Close();
|
||||
Stream.Close();
|
||||
Serial?.Close();
|
||||
ControlSerialEmpty?.Close();
|
||||
ControlSerialFilling?.Close();
|
||||
Tcp?.Close();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected static Output? ConvertOutput(string? value) {
|
||||
if (value == null) return null;
|
||||
value = value.ToUpper();
|
||||
if (value == "RTS") {
|
||||
return Output.RTS;
|
||||
} else if (value == "DTR") {
|
||||
return Output.DTR;
|
||||
} else if (value == "OUT1") {
|
||||
return Output.OUT1;
|
||||
} else if (value == "OUT2") {
|
||||
return Output.OUT2;
|
||||
return value switch {
|
||||
null => null,
|
||||
"RTS" => Output.RTS,
|
||||
"DTR" => Output.DTR,
|
||||
"OUT1" => Output.OUT1,
|
||||
"OUT2" => Output.OUT2,
|
||||
_ => throw new ArgumentException($"Invalid value for argument: '{value}'"),
|
||||
};
|
||||
}
|
||||
|
||||
protected async Task SendCommand(string command) {
|
||||
byte[] bytes = Encoding.ASCII.GetBytes($"<{command}>");
|
||||
await Stream.WriteAsync(bytes);
|
||||
if (LogPath != null) await File.AppendAllTextAsync(LogPath, $"<{command}>");
|
||||
}
|
||||
|
||||
protected async Task<string> ReceiveResponse() {
|
||||
string? line = null;
|
||||
using (var reader = new StreamReader(Stream, Encoding.ASCII, false, -1, true)) {
|
||||
line = await reader.ReadLineAsync();
|
||||
if (LogPath != null) await File.AppendAllTextAsync(LogPath, $"{line}\r\n");
|
||||
}
|
||||
throw new ArgumentException("Invalid value for argument empty");
|
||||
}
|
||||
|
||||
public async Task SendCommand(string command) {
|
||||
await Writer.WriteAsync($"<{command}>");
|
||||
}
|
||||
|
||||
public async Task<string> ReceiveResponse() {
|
||||
var line = await Reader.ReadLineAsync();
|
||||
if (line == null || line.Length < 4 || !line.StartsWith("<") || !line.EndsWith(">")) {
|
||||
throw new IOException("Invalid response from scale");
|
||||
}
|
||||
@@ -94,7 +112,7 @@ namespace Elwig.Helpers.Weighing {
|
||||
var error = line[1..3];
|
||||
if (error[0] == '0') {
|
||||
if (error[1] != '0') {
|
||||
throw new IOException($"Invalid response from scale (error code {error}");
|
||||
throw new IOException($"Invalid response from scale (error code {error})");
|
||||
}
|
||||
} else if (error[0] == '1') {
|
||||
string msg = $"Unbekannter Fehler (Fehler code {error})";
|
||||
@@ -119,32 +137,44 @@ namespace Elwig.Helpers.Weighing {
|
||||
throw new IOException($"Invalid response from scale (error code {error})");
|
||||
}
|
||||
|
||||
return line[3..(line.Length - 1)];
|
||||
return line[1..^1];
|
||||
}
|
||||
|
||||
protected async Task<WeighingResult> Weigh(bool incIdentNr) {
|
||||
await SendCommand(incIdentNr ? $"RM{InternalScaleNr}" : $"RN{InternalScaleNr}");
|
||||
string line = await ReceiveResponse();
|
||||
await SendCommand(incIdentNr ? $"RN{InternalScaleNr}" : $"RM{InternalScaleNr}");
|
||||
string record = await ReceiveResponse();
|
||||
if (record.Length != 62)
|
||||
throw new IOException("Invalid response from scale: Received record has invalid size");
|
||||
var line = record[2..];
|
||||
|
||||
var status = line[ 0.. 2];
|
||||
var date = line[ 2..10];
|
||||
var time = line[10..15];
|
||||
var identNr = line[15..19];
|
||||
var identNr = line[15..19].Trim();
|
||||
var scaleNr = line[19..20];
|
||||
var brutto = line[20..28];
|
||||
var tara = line[28..36];
|
||||
var netto = line[36..44];
|
||||
var brutto = line[20..28].Trim();
|
||||
var tara = line[28..36].Trim();
|
||||
var netto = line[36..44].Trim();
|
||||
var unit = line[44..46];
|
||||
var taraCode = line[46..48];
|
||||
var zone = line[48..49];
|
||||
var terminalNr = line[49..52];
|
||||
var crc16 = line[52..60];
|
||||
var zone = line[48..49].Trim();
|
||||
var terminalNr = line[49..52].Trim();
|
||||
var crc16 = line[52..60].Trim();
|
||||
|
||||
if (Utils.CalcCrc16Modbus(record[..54]) != ushort.Parse(crc16)) {
|
||||
throw new IOException($"Invalid response from scale: Invalid CRC16 checksum ({crc16} != {Utils.CalcCrc16Modbus(record[..54]).ToString()})");
|
||||
} else if (unit != "kg") {
|
||||
throw new IOException($"Unsupported unit in weighing response: '{unit}'");
|
||||
}
|
||||
|
||||
identNr = identNr.Length > 0 && identNr != "0" ? identNr : null;
|
||||
var parsedDate = DateOnly.Parse(date);
|
||||
return new() {
|
||||
Weight = int.TryParse(netto.Trim(), out int w) ? w : null,
|
||||
WeighingId = identNr.Trim().Length > 0 ? identNr.Trim() : null,
|
||||
Date = date,
|
||||
Time = time,
|
||||
Weight = int.Parse(netto),
|
||||
WeighingId = identNr,
|
||||
FullWeighingId = identNr != null ? $"{parsedDate:yyyy-MM-dd}/{identNr}" : null,
|
||||
Date = parsedDate,
|
||||
Time = TimeOnly.Parse(time),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -157,33 +187,35 @@ namespace Elwig.Helpers.Weighing {
|
||||
}
|
||||
|
||||
public async Task Empty() {
|
||||
if (EmptyMode == Output.RTS && Serial != null) {
|
||||
Serial.RtsEnable = true;
|
||||
SerialPort? p = ControlSerialEmpty ?? Serial;
|
||||
if (EmptyMode == Output.RTS && p != null) {
|
||||
p.RtsEnable = true;
|
||||
await Task.Delay(EmptyDelay);
|
||||
Serial.RtsEnable = false;
|
||||
} else if (EmptyMode == Output.DTR && Serial != null) {
|
||||
Serial.DtrEnable = true;
|
||||
p.RtsEnable = false;
|
||||
} else if (EmptyMode == Output.DTR && p != null) {
|
||||
p.DtrEnable = true;
|
||||
await Task.Delay(EmptyDelay);
|
||||
Serial.DtrEnable = false;
|
||||
p.DtrEnable = false;
|
||||
} else if (EmptyMode == Output.OUT1 || EmptyMode == Output.OUT2) {
|
||||
int output = EmptyMode == Output.OUT1 ? 1 : 2;
|
||||
await SendCommand($"OS{output:02i}");
|
||||
await SendCommand($"OS{output:00}");
|
||||
await ReceiveResponse();
|
||||
await Task.Delay(EmptyDelay);
|
||||
await SendCommand($"OC{output:02i}");
|
||||
await SendCommand($"OC{output:00}");
|
||||
await ReceiveResponse();
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task SetFillingClearance(bool status) {
|
||||
if (FillingClearanceMode == Output.RTS && Serial != null) {
|
||||
Serial.RtsEnable = status;
|
||||
} else if (FillingClearanceMode == Output.DTR && Serial != null) {
|
||||
Serial.DtrEnable = status;
|
||||
SerialPort? p = ControlSerialFilling ?? Serial;
|
||||
if (FillingClearanceMode == Output.RTS && p != null) {
|
||||
p.RtsEnable = status;
|
||||
} else if (FillingClearanceMode == Output.DTR && p != null) {
|
||||
p.DtrEnable = status;
|
||||
} else if (FillingClearanceMode == Output.OUT1 || FillingClearanceMode == Output.OUT2) {
|
||||
string cmd = status ? "OS" : "OC";
|
||||
int output = FillingClearanceMode == Output.OUT1 ? 1 : 2;
|
||||
await SendCommand($"{cmd}{output:02i}");
|
||||
await SendCommand($"{cmd}{output:00}");
|
||||
await ReceiveResponse();
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Elwig.Helpers.Weighing {
|
||||
/// <summary>
|
||||
/// Result of a weighing process on an industrial scale
|
||||
@@ -13,14 +15,25 @@ namespace Elwig.Helpers.Weighing {
|
||||
/// </summary>
|
||||
public string? WeighingId = null;
|
||||
|
||||
/// <summary>
|
||||
/// Wheighing id (or IdentNr) provided by the scale optionally combined with the current date
|
||||
/// </summary>
|
||||
public string? FullWeighingId = null;
|
||||
|
||||
/// <summary>
|
||||
/// Date string provided by the scale
|
||||
/// </summary>
|
||||
public string? Date = null;
|
||||
public DateOnly? Date = null;
|
||||
|
||||
/// <summary>
|
||||
/// Time string provided by the scale
|
||||
/// </summary>
|
||||
public string? Time = null;
|
||||
public TimeOnly? Time = null;
|
||||
|
||||
/// <returns><Weight/WeighingId/Date/Time></returns>
|
||||
override public string ToString() {
|
||||
var w = Weight != null ? $"{Weight}kg" : "";
|
||||
return $"<{w}/{WeighingId}/{Date:yyyy-MM-dd}/{Time:HH:mm}>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
@@ -9,5 +10,11 @@ namespace Elwig.Models {
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; private set; }
|
||||
|
||||
[InverseProperty("Gem")]
|
||||
public virtual ISet<AT_Kg> Kgs { get; private set; }
|
||||
|
||||
[InverseProperty("AtGem")]
|
||||
public virtual WbGem? WbGem { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@@ -15,5 +15,8 @@ namespace Elwig.Models {
|
||||
|
||||
[ForeignKey("Gkz")]
|
||||
public virtual AT_Gem Gem { get; private set; }
|
||||
|
||||
[InverseProperty("AtKg")]
|
||||
public virtual WbKg WbKg { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ namespace Elwig.Models {
|
||||
public int Okz { get; private set; }
|
||||
|
||||
[Column("country")]
|
||||
public string CountryCode { get; private set; }
|
||||
public int CountryNum { get; private set; }
|
||||
|
||||
[Column("id")]
|
||||
public string Id { get; private set; }
|
||||
@@ -25,7 +25,7 @@ namespace Elwig.Models {
|
||||
[ForeignKey("Okz")]
|
||||
public virtual AT_Ort Ort { get; private set; }
|
||||
|
||||
[ForeignKey("CountryCode")]
|
||||
[ForeignKey("CountryNum")]
|
||||
public virtual Country Country { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@@ -1,39 +1,55 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("area_commitment"), PrimaryKey("VNr")]
|
||||
[Table("area_commitment"), PrimaryKey("FbNr")]
|
||||
public class AreaCom {
|
||||
[Column("vnr")]
|
||||
public int VNr { get; set; }
|
||||
[Column("fbnr")]
|
||||
public int FbNr { get; set; }
|
||||
|
||||
[Column("area")]
|
||||
public int Area { get; set; }
|
||||
[Column("mgnr")]
|
||||
public int MgNr { get; set; }
|
||||
|
||||
[Column("sortid")]
|
||||
public string SortId { get; set; }
|
||||
[Column("vtrgid")]
|
||||
public string VtrgId { get; set; }
|
||||
|
||||
[Column("cultid")]
|
||||
public string CultId { get; set; }
|
||||
|
||||
[ForeignKey("VNr")]
|
||||
public virtual Contract Contract { get; private set; }
|
||||
[Column("area")]
|
||||
public int Area { get; set; }
|
||||
|
||||
[ForeignKey("SortId")]
|
||||
public virtual WineVar WineVar { get; private set; }
|
||||
[Column("kgnr")]
|
||||
public int KgNr { get; set; }
|
||||
|
||||
[Column("gstnr")]
|
||||
public string GstNr { get; set; }
|
||||
|
||||
[Column("rdnr")]
|
||||
public int? RdNr { get; set; }
|
||||
|
||||
[Column("year_from")]
|
||||
public int YearFrom { get; set; }
|
||||
|
||||
[Column("year_to")]
|
||||
public int? YearTo { get; set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[ForeignKey("MgNr")]
|
||||
public virtual Member Member { get; private set; }
|
||||
|
||||
[ForeignKey("VtrgId")]
|
||||
public virtual AreaComType AreaComType { get; private set; }
|
||||
|
||||
[ForeignKey("CultId")]
|
||||
public virtual WineCult WineCult { get; private set; }
|
||||
|
||||
[InverseProperty("AreaCom")]
|
||||
public virtual ISet<AreaComParcel> Parcels { get; private set; }
|
||||
[ForeignKey("KgNr")]
|
||||
public virtual WbKg Kg { get; private set; }
|
||||
|
||||
[InverseProperty("AreaCom")]
|
||||
public virtual ISet<AreaComAttr> AttributeEntries { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public IEnumerable<WineAttr> Attributes => AttributeEntries.Select(e => e.WineAttr);
|
||||
[ForeignKey("KgNr, RdNr")]
|
||||
public virtual WbRd? Rd { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@@ -1,19 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("area_commitment_attribute"), PrimaryKey("VNr", "AttrId")]
|
||||
public class AreaComAttr {
|
||||
[Column("vnr")]
|
||||
public int VNr { get; set; }
|
||||
|
||||
[Column("attrid")]
|
||||
public string AttrId { get; set; }
|
||||
|
||||
[ForeignKey("VNr")]
|
||||
public virtual AreaCom AreaCom { get; private set; }
|
||||
|
||||
[ForeignKey("AttrId")]
|
||||
public virtual WineAttr WineAttr { get; private set; }
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("area_commitment_parcel"), PrimaryKey("VNr", "KgNr", "GstNr")]
|
||||
public class AreaComParcel {
|
||||
[Column("vnr")]
|
||||
public int VNr { get; set; }
|
||||
|
||||
[Column("kgnr")]
|
||||
public int KgNr { get; set; }
|
||||
|
||||
[Column("gstnr")]
|
||||
public string? GstNr { get; set; }
|
||||
|
||||
[Column("rdnr")]
|
||||
public int? RdNr { get; set; }
|
||||
|
||||
[Column("area")]
|
||||
public int? Area { get; set; }
|
||||
|
||||
[ForeignKey("KgNr")]
|
||||
public virtual WbKg Kg { get; private set; }
|
||||
|
||||
[ForeignKey("KgNr, RdNr")]
|
||||
public virtual WbRd? Rd { get; private set; }
|
||||
|
||||
[ForeignKey("VNr")]
|
||||
public virtual AreaCom AreaCom { get; private set; }
|
||||
}
|
||||
}
|
51
Elwig/Models/AreaComType.cs
Normal file
51
Elwig/Models/AreaComType.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Elwig.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("area_commitment_type"), PrimaryKey("VtrgId"), Index("SortId", "AttrId1", "AttrId2", "Discriminator")]
|
||||
public class AreaComType {
|
||||
[Column("vtrgid")]
|
||||
public string VtrgId { get; set; }
|
||||
|
||||
[Column("sortid")]
|
||||
public string SortId { get; set; }
|
||||
|
||||
[Column("attrid_1")]
|
||||
public string? AttrId1 { get; set; }
|
||||
|
||||
[Column("attrid_2")]
|
||||
public string? AttrId2 { get; set; }
|
||||
|
||||
[Column("disc")]
|
||||
public string? Discriminator { get; set; }
|
||||
|
||||
[Column("min_kg_per_ha")]
|
||||
public int? MinKgPerHa { get; set; }
|
||||
|
||||
[Column("max_kg_per_ha")]
|
||||
public int? MaxKgPerHa { get; set; }
|
||||
|
||||
[Column("penalty_amount")]
|
||||
public long? PenaltyAmoutValue { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public decimal? PenaltyAmount {
|
||||
get => PenaltyAmoutValue != null ? Utils.DecFromDb(PenaltyAmoutValue.Value, 4) : null;
|
||||
set => PenaltyAmoutValue = value != null ? Utils.DecToDb(value.Value, 4) : null;
|
||||
}
|
||||
|
||||
[ForeignKey("SortId")]
|
||||
public virtual WineVar WineVar { get; private set; }
|
||||
|
||||
[ForeignKey("AttrId1")]
|
||||
public virtual WineAttr? WineAttr1 { get; private set; }
|
||||
|
||||
[ForeignKey("AttrId2")]
|
||||
public virtual WineAttr? WineAttr2 { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public string DisplayName => WineVar.Name + (WineAttr1 != null ? $" {WineAttr1.Name}" : "") +
|
||||
(WineAttr2 != null ? $" {WineAttr2.Name}" : "") + (Discriminator != null ? $" ({Discriminator})" : "");
|
||||
}
|
||||
}
|
@@ -11,7 +11,7 @@ namespace Elwig.Models {
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("country")]
|
||||
public string CountryCode { get; set; }
|
||||
public int CountryNum { get; set; }
|
||||
|
||||
[Column("postal_dest")]
|
||||
public string PostalDestId { get; set; }
|
||||
@@ -22,10 +22,10 @@ namespace Elwig.Models {
|
||||
[ForeignKey("MgNr")]
|
||||
public virtual Member Member { get; private set; }
|
||||
|
||||
[ForeignKey("CountryCode")]
|
||||
[ForeignKey("CountryNum")]
|
||||
public virtual Country Country { get; private set; }
|
||||
|
||||
[ForeignKey("CountryCode, PostalDestId")]
|
||||
[ForeignKey("CountryNum, PostalDestId")]
|
||||
public virtual PostalDest PostalDest { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,30 @@ namespace Elwig.Models {
|
||||
[Column("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("country")]
|
||||
public int? CountryNum { get; set; }
|
||||
|
||||
[Column("postal_dest")]
|
||||
public string? PostalDestId { get; set; }
|
||||
|
||||
[Column("address")]
|
||||
public string? Address { get; set; }
|
||||
|
||||
[ForeignKey("CountryNum")]
|
||||
public virtual Country? Country { get; private set; }
|
||||
|
||||
[ForeignKey("CountryNum, PostalDestId")]
|
||||
public virtual PostalDest? PostalDest { get; private set; }
|
||||
|
||||
[Column("phone_nr")]
|
||||
public string? PhoneNr { get; set; }
|
||||
|
||||
[Column("fax_nr")]
|
||||
public string? FaxNr { get; set; }
|
||||
|
||||
[Column("mobile_nr")]
|
||||
public string? MobileNr { get; set; }
|
||||
|
||||
[InverseProperty("Branch")]
|
||||
public virtual ISet<Member> Members { get; private set; }
|
||||
}
|
||||
|
13
Elwig/Models/ClientParam.cs
Normal file
13
Elwig/Models/ClientParam.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("client_parameter"), PrimaryKey("Param")]
|
||||
public class ClientParam {
|
||||
[Column("param")]
|
||||
public string Param { get; set; }
|
||||
|
||||
[Column("value")]
|
||||
public string? Value { get; set; }
|
||||
}
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("contract"), PrimaryKey("VNr")]
|
||||
public class Contract {
|
||||
[Column("vnr")]
|
||||
public int VNr { get; set; }
|
||||
|
||||
[Column("mgnr")]
|
||||
public int MgNr { get; set; }
|
||||
|
||||
[Column("date")]
|
||||
public string? DateString { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateOnly? Date {
|
||||
get {
|
||||
return DateString != null ? DateOnly.ParseExact(DateString, "yyyy-MM-dd") : null;
|
||||
}
|
||||
set {
|
||||
DateString = value?.ToString("yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
|
||||
[Column("year_from")]
|
||||
public int YearFrom { get; set; }
|
||||
|
||||
[Column("year_to")]
|
||||
public int? YearTo { get; set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[ForeignKey("MgNr")]
|
||||
public virtual Member Member { get; private set; }
|
||||
|
||||
[InverseProperty("Contract")]
|
||||
public virtual AreaCom? AreaCom { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public int? Area => AreaCom?.Area;
|
||||
}
|
||||
}
|
@@ -2,17 +2,17 @@ using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("country"), PrimaryKey("Alpha2")]
|
||||
[Table("country"), PrimaryKey("Num"), Index("Alpha2", IsUnique = true), Index("Alpha3", IsUnique = true)]
|
||||
public class Country {
|
||||
[Column("num")]
|
||||
public int Num { get; private set; }
|
||||
|
||||
[Column("alpha2")]
|
||||
public string Alpha2 { get; private set; }
|
||||
|
||||
[Column("alpha3")]
|
||||
public string Alpha3 { get; private set; }
|
||||
|
||||
[Column("num")]
|
||||
public int Num { get; private set; }
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; private set; }
|
||||
|
||||
|
@@ -18,6 +18,6 @@ namespace Elwig.Models {
|
||||
public long? OneEuroValue { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public decimal? OneEuro => OneEuroValue != null ? Utils.DecFromDb((long)OneEuroValue, 6) : null;
|
||||
public decimal? OneEuro => OneEuroValue != null ? Utils.DecFromDb(OneEuroValue.Value, 6) : null;
|
||||
}
|
||||
}
|
||||
|
101
Elwig/Models/Delivery.cs
Normal file
101
Elwig/Models/Delivery.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using Elwig.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("delivery"), PrimaryKey("Year", "DId"), Index("DateString", "ZwstId", "LNr", IsUnique = true), Index("LsNr", IsUnique = true)]
|
||||
public class Delivery {
|
||||
[Column("year")]
|
||||
public int Year { get; set; }
|
||||
|
||||
[Column("did")]
|
||||
public int DId { get; set; }
|
||||
|
||||
[Column("date")]
|
||||
public string DateString { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateOnly Date {
|
||||
get {
|
||||
return DateOnly.ParseExact(DateString, "yyyy-MM-dd");
|
||||
}
|
||||
set {
|
||||
DateString = value.ToString("yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
|
||||
[Column("time")]
|
||||
public string? TimeString { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public TimeOnly? Time {
|
||||
get {
|
||||
return (TimeString == null) ? null : TimeOnly.ParseExact(TimeString, "HH:mm:ss");
|
||||
}
|
||||
set {
|
||||
TimeString = value?.ToString("HH:mm:ss");
|
||||
}
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public DateTime DateTime {
|
||||
get {
|
||||
return Date.ToDateTime(Time ?? TimeOnly.MinValue);
|
||||
}
|
||||
set {
|
||||
Date = DateOnly.FromDateTime(value);
|
||||
Time = TimeOnly.FromDateTime(value);
|
||||
}
|
||||
}
|
||||
|
||||
[Column("zwstid")]
|
||||
public string ZwstId { get; set; }
|
||||
|
||||
[ForeignKey("ZwstId")]
|
||||
public virtual Branch Branch { get; private set; }
|
||||
|
||||
[Column("lnr")]
|
||||
public int LNr { get; set; }
|
||||
|
||||
[Column("lsnr")]
|
||||
public string LsNr { get; set; }
|
||||
|
||||
[Column("mgnr")]
|
||||
public int MgNr { get; set; }
|
||||
|
||||
[ForeignKey("MgNr")]
|
||||
public virtual Member Member { get; private set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[InverseProperty("Delivery")]
|
||||
public virtual ISet<DeliveryPart> Parts { get; private set; }
|
||||
|
||||
public int Weight => Parts.Select(p => p.Weight).Sum();
|
||||
|
||||
public IEnumerable<string> SortIds => Parts
|
||||
.GroupBy(p => p.SortId)
|
||||
.OrderByDescending(g => g.Select(p => p.Weight).Sum())
|
||||
.Select(g => g.Select(p => p.SortId).First());
|
||||
|
||||
public string SortIdString => string.Join(", ", SortIds);
|
||||
|
||||
public double Kmw => Utils.AggregateDeliveryPartsKmw(Parts);
|
||||
|
||||
public double Oe => Utils.KmwToOe(Kmw);
|
||||
|
||||
public int SearchScore(IEnumerable<string> keywords) {
|
||||
var list = new string?[] {
|
||||
LsNr, Time?.ToString("HH:mm"),
|
||||
Member.FamilyName, Member.MiddleName, Member.GivenName, Member.BillingAddress?.Name,
|
||||
Comment
|
||||
}.ToList();
|
||||
list.AddRange(Parts.Select(p => p.Comment).Distinct());
|
||||
return Utils.GetSearchScore(list, keywords);
|
||||
}
|
||||
}
|
||||
}
|
112
Elwig/Models/DeliveryPart.cs
Normal file
112
Elwig/Models/DeliveryPart.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using Elwig.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("delivery_part"), PrimaryKey("Year", "DId", "DPNr")]
|
||||
public class DeliveryPart {
|
||||
[Column("year")]
|
||||
public int Year { get; set; }
|
||||
|
||||
[Column("did")]
|
||||
public int DId { get; set; }
|
||||
|
||||
[ForeignKey("Year, DId")]
|
||||
public virtual Delivery Delivery { get; private set; }
|
||||
|
||||
[Column("dpnr")]
|
||||
public int DPNr { get; set; }
|
||||
|
||||
[Column("sortid")]
|
||||
public string SortId { get; set; }
|
||||
|
||||
[ForeignKey("SortId")]
|
||||
public virtual WineVar Variant { get; private set; }
|
||||
|
||||
[Column("weight")]
|
||||
public int Weight { get; set; }
|
||||
|
||||
[Column("kmw")]
|
||||
public double Kmw { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public double Oe {
|
||||
get {
|
||||
return Utils.KmwToOe(Kmw);
|
||||
}
|
||||
set {
|
||||
Kmw = Utils.OeToKmw(value);
|
||||
}
|
||||
}
|
||||
|
||||
[Column("qualid")]
|
||||
public string QualId { get; set; }
|
||||
|
||||
[ForeignKey("QualId")]
|
||||
public virtual WineQualLevel Quality { get; private set; }
|
||||
|
||||
[Column("hkid")]
|
||||
public string HkId { get; set; }
|
||||
|
||||
[ForeignKey("HkId")]
|
||||
public virtual WineOrigin Origin { get; private set; }
|
||||
|
||||
[Column("kgnr")]
|
||||
public int? KgNr { get; set; }
|
||||
|
||||
[ForeignKey("KgNr")]
|
||||
public virtual WbKg? Kg { get; private set; }
|
||||
|
||||
[Column("rdnr")]
|
||||
public int? RdNr { get; set; }
|
||||
|
||||
[ForeignKey("KgNr, RdNr")]
|
||||
public virtual WbRd? Rd { get; private set; }
|
||||
|
||||
[Column("gerebelt")]
|
||||
public bool IsGerebelt { get; set; }
|
||||
|
||||
[Column("manual_weighing")]
|
||||
public bool ManualWeighing { get; set; }
|
||||
|
||||
[Column("spl_check")]
|
||||
public bool SplCheck { get; set; }
|
||||
|
||||
[Column("hand_picked")]
|
||||
public bool? IsHandPicked { get; set; }
|
||||
|
||||
[Column("lesewagen")]
|
||||
public bool? IsLesewagen { get; set; }
|
||||
|
||||
[Column("temperature")]
|
||||
public double? Temperature { get; set; }
|
||||
|
||||
[Column("acid")]
|
||||
public double? Acid { get; set; }
|
||||
|
||||
[Column("scale_id")]
|
||||
public string? ScaleId { get; set; }
|
||||
|
||||
[Column("weighing_id")]
|
||||
public string? WeighingId { get; set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[InverseProperty("Part")]
|
||||
public virtual ISet<DeliveryPartAttr> PartAttributes { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public IEnumerable<WineAttr> Attributes => PartAttributes.Select(a => a.Attr);
|
||||
|
||||
[InverseProperty("Part")]
|
||||
public virtual ISet<DeliveryPartModifier> PartModifiers { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public IEnumerable<Modifier> Modifiers => PartModifiers.Select(m => m.Modifier).OrderBy(m => m.Ordering);
|
||||
|
||||
public string OriginString => Origin.OriginString + "\n" + (Kg?.Gl != null ? $" / {Kg.Gl.Name}" : "") + (Kg != null ? $" / {Kg.AtKg.Gem.Name} / KG {Kg.AtKg.Name}" : "") + (Rd != null ? $" / Ried {Rd.Name}" : "");
|
||||
}
|
||||
}
|
25
Elwig/Models/DeliveryPartAttr.cs
Normal file
25
Elwig/Models/DeliveryPartAttr.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("delivery_part_attribute"), PrimaryKey("Year", "DId", "DPNr", "AttrId")]
|
||||
public class DeliveryPartAttr {
|
||||
[Column("year")]
|
||||
public int Year { get; set; }
|
||||
|
||||
[Column("did")]
|
||||
public int DId { get; set; }
|
||||
|
||||
[Column("dpnr")]
|
||||
public int DPNr { get; set; }
|
||||
|
||||
[ForeignKey("Year, DId, DPNr")]
|
||||
public virtual DeliveryPart Part { get; private set; }
|
||||
|
||||
[Column("attrid")]
|
||||
public string AttrId { get; set; }
|
||||
|
||||
[ForeignKey("AttrId")]
|
||||
public virtual WineAttr Attr { get; private set; }
|
||||
}
|
||||
}
|
25
Elwig/Models/DeliveryPartModifier.cs
Normal file
25
Elwig/Models/DeliveryPartModifier.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("delivery_part_modifier"), PrimaryKey("Year", "DId", "DPNr", "ModId")]
|
||||
public class DeliveryPartModifier {
|
||||
[Column("year")]
|
||||
public int Year { get; set; }
|
||||
|
||||
[Column("did")]
|
||||
public int DId { get; set; }
|
||||
|
||||
[Column("dpnr")]
|
||||
public int DPNr { get; set; }
|
||||
|
||||
[ForeignKey("Year, DId, DPNr")]
|
||||
public virtual DeliveryPart Part { get; private set; }
|
||||
|
||||
[Column("modid")]
|
||||
public string ModId { get; set; }
|
||||
|
||||
[ForeignKey("Year, ModId")]
|
||||
public virtual Modifier Modifier { get; private set; }
|
||||
}
|
||||
}
|
123
Elwig/Models/Graph.cs
Normal file
123
Elwig/Models/Graph.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ScottPlot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Elwig.Models {
|
||||
public class Graph : ICloneable {
|
||||
|
||||
public string Type { get; set; }
|
||||
public int Num { get; set; }
|
||||
private int MinX { get; set; }
|
||||
private int MaxX { get; set; }
|
||||
public string Contracts { get; set; }
|
||||
public double[] DataX { get; set; }
|
||||
public double[] DataY { get; set; }
|
||||
|
||||
public Graph(int num, int minX, int maxX) {
|
||||
Type = "oe";
|
||||
Num = num;
|
||||
Contracts = "";
|
||||
MinX = minX;
|
||||
MaxX = maxX;
|
||||
|
||||
DataX = DataGen.Range(MinX, MaxX + 1);
|
||||
DataY = DataGen.Zeros(MaxX - MinX + 1);
|
||||
}
|
||||
|
||||
public Graph(string type, int num, JToken graphData, string contracts, int minX, int maxX) {
|
||||
Type = type;
|
||||
Num = num;
|
||||
Contracts = contracts;
|
||||
MinX = minX;
|
||||
MaxX = maxX;
|
||||
|
||||
DataX = DataGen.Range(MinX, MaxX + 1);
|
||||
DataY = DataGen.Zeros(MaxX - MinX + 1);
|
||||
ParseGraphData(graphData);
|
||||
}
|
||||
|
||||
public Graph(string type, int num, int minX, int maxX, string contracts, double[] dataX, double[] dataY) {
|
||||
Type = type;
|
||||
Num = num;
|
||||
MinX = minX;
|
||||
MaxX = maxX;
|
||||
Contracts = contracts;
|
||||
DataX = dataX;
|
||||
DataY = dataY;
|
||||
}
|
||||
|
||||
private void ParseGraphData(JToken graphData) {
|
||||
var GraphPoints = graphData.Children().OfType<JProperty>().ToDictionary(p => int.Parse(p.Name[..^2]), p => (double)p.Value);
|
||||
|
||||
if (GraphPoints.Keys.Count < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var minKey = GraphPoints.Keys.Order().First();
|
||||
var maxKey = GraphPoints.Keys.OrderDescending().First();
|
||||
|
||||
if (!GraphPoints.ContainsKey(MinX)) {
|
||||
GraphPoints.Add(MinX, GraphPoints.GetValueOrDefault(minKey));
|
||||
}
|
||||
if (!GraphPoints.ContainsKey(MaxX)) {
|
||||
GraphPoints.Add(MaxX, GraphPoints.GetValueOrDefault(maxKey));
|
||||
}
|
||||
|
||||
var keys = GraphPoints.Keys.Order().ToArray();
|
||||
|
||||
for (int i = 0; i < keys.Length; i++) {
|
||||
double point1Value = GraphPoints[keys[i]];
|
||||
if (i + 1 < keys.Length) {
|
||||
double point2Value = GraphPoints[keys[i + 1]];
|
||||
if (point1Value == point2Value) {
|
||||
for (int j = keys[i] - MinX; j < keys[i + 1] - MinX; j++) {
|
||||
DataY[j] = point1Value;
|
||||
}
|
||||
} else {
|
||||
int steps = Math.Abs(keys[i + 1] - keys[i]);
|
||||
double step = (point2Value - point1Value) / steps;
|
||||
|
||||
DataY[keys[i] - MinX] = point1Value;
|
||||
DataY[keys[i + 1] - MinX] = point2Value;
|
||||
|
||||
for (int j = keys[i] - MinX; j < keys[i + 1] - MinX - 1; j++) {
|
||||
DataY[j + 1] = Math.Round(DataY[j] + step, 4); // TODO richtig runden
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int j = keys[i] - MinX; j < DataX.Length; j++) {
|
||||
DataY[j] = point1Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JObject ToJson() {
|
||||
JObject graph = new();
|
||||
|
||||
if (DataY[0] != DataY[1]) {
|
||||
graph.Add(new JProperty(DataX[0] + Type.ToLower(), Math.Round(DataY[0], 4)));
|
||||
}
|
||||
for (int i = 1; i < DataX.Length - 1; i++) {
|
||||
if (Math.Round(DataY[i] - DataY[i - 1], 4) != Math.Round(DataY[i + 1] - DataY[i], 4)) {
|
||||
graph.Add(new JProperty(DataX[i] + Type.ToLower(), Math.Round(DataY[i], 4)));
|
||||
}
|
||||
}
|
||||
if (DataY[^1] != DataY[^2]) {
|
||||
graph.Add(new JProperty(DataX[^1] + Type.ToLower(), Math.Round(DataY[^1], 4)));
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
|
||||
public object Clone() {
|
||||
return new Graph(Type, Num, MinX, MaxX, Contracts, (double[])DataX.Clone(), (double[])DataY.Clone());
|
||||
}
|
||||
}
|
||||
}
|
@@ -35,6 +35,25 @@ namespace Elwig.Models {
|
||||
[Column("suffix")]
|
||||
public string? Suffix { get; set; }
|
||||
|
||||
public string Name =>
|
||||
(Prefix != null ? Prefix + " " : "") +
|
||||
GivenName + " " +
|
||||
(MiddleName != null ? MiddleName + " " : "") +
|
||||
FamilyName +
|
||||
(Suffix != null ? " " + Suffix : "");
|
||||
|
||||
public string ShortName => GivenName + " " + FamilyName;
|
||||
|
||||
public string AdministrativeName => AdministrativeName1 + " " + AdministrativeName2;
|
||||
|
||||
public string AdministrativeName1 => FamilyName.ToUpper();
|
||||
|
||||
public string AdministrativeName2 =>
|
||||
(Prefix != null ? Prefix + " " : "") +
|
||||
GivenName +
|
||||
(MiddleName != null ? " " + MiddleName : "") +
|
||||
(Suffix != null ? " " + Suffix : "");
|
||||
|
||||
[Column("birthday")]
|
||||
public string? Birthday { get; set; }
|
||||
|
||||
@@ -76,8 +95,8 @@ namespace Elwig.Models {
|
||||
[Column("lfbis_nr")]
|
||||
public string? LfbisNr { get; set; }
|
||||
|
||||
[Column("ustid")]
|
||||
public string? UstId { get; set; }
|
||||
[Column("ustid_nr")]
|
||||
public string? UstIdNr { get; set; }
|
||||
|
||||
[Column("volllieferant")]
|
||||
public bool IsVollLieferant { get; set; }
|
||||
@@ -91,6 +110,9 @@ namespace Elwig.Models {
|
||||
[Column("active")]
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
[Column("deceased")]
|
||||
public bool IsDeceased { get; set; }
|
||||
|
||||
[Column("iban")]
|
||||
public string? Iban { get; set; }
|
||||
|
||||
@@ -98,7 +120,7 @@ namespace Elwig.Models {
|
||||
public string? Bic { get; set; }
|
||||
|
||||
[Column("country")]
|
||||
public string CountryCode { get; set; }
|
||||
public int CountryNum { get; set; }
|
||||
|
||||
[Column("postal_dest")]
|
||||
public string PostalDestId { get; set; }
|
||||
@@ -109,20 +131,14 @@ namespace Elwig.Models {
|
||||
[Column("email")]
|
||||
public string? Email { get; set; }
|
||||
|
||||
[Column("phone_landline")]
|
||||
public string? PhoneLandline { get; set; }
|
||||
|
||||
[Column("phone_mobile_1")]
|
||||
public string? PhoneMobile1 { get; set; }
|
||||
|
||||
[Column("phone_mobile_2")]
|
||||
public string? PhoneMobile2 { get; set; }
|
||||
|
||||
[Column("default_kgnr")]
|
||||
public int? DefaultKgNr { get; set; }
|
||||
|
||||
[Column("default_contact")]
|
||||
public string DefaultContact { get; set; }
|
||||
[Column("contact_postal")]
|
||||
public bool ContactViaPost { get; set; }
|
||||
|
||||
[Column("contact_email")]
|
||||
public bool ContactViaEmail { get; set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
@@ -130,10 +146,10 @@ namespace Elwig.Models {
|
||||
[ForeignKey("PredecessorMgNr")]
|
||||
public virtual Member? Predecessor { get; private set; }
|
||||
|
||||
[ForeignKey("CountryCode")]
|
||||
[ForeignKey("CountryNum")]
|
||||
public virtual Country Country { get; private set; }
|
||||
|
||||
[ForeignKey("CountryCode, PostalDestId")]
|
||||
[ForeignKey("CountryNum, PostalDestId")]
|
||||
public virtual PostalDest PostalDest { get; private set; }
|
||||
|
||||
[ForeignKey("DefaultKgNr")]
|
||||
@@ -143,41 +159,33 @@ namespace Elwig.Models {
|
||||
public virtual Branch? Branch { get; private set; }
|
||||
|
||||
[InverseProperty("Member")]
|
||||
public virtual ISet<Contract> Contracts { get; private set; }
|
||||
public virtual ISet<AreaCom> AreaCommitments { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public virtual ISet<Contract> ActiveContracts => Contracts
|
||||
.Where(c => c.YearFrom <= Utils.CurrentSeason && (c.YearTo ?? int.MaxValue) >= Utils.CurrentSeason)
|
||||
.ToHashSet();
|
||||
public IEnumerable<AreaCom> ActiveAreaCommitments => AreaCommitments
|
||||
.Where(c => c.YearFrom <= Utils.CurrentNextSeason && (c.YearTo ?? int.MaxValue) >= Utils.CurrentNextSeason);
|
||||
|
||||
[InverseProperty("Member")]
|
||||
public virtual BillingAddr BillingAddress { get; private set; }
|
||||
public virtual BillingAddr? BillingAddress { get; private set; }
|
||||
|
||||
[InverseProperty("Member")]
|
||||
public virtual ISet<Delivery> Deliveries { get; private set; }
|
||||
|
||||
[InverseProperty("Member")]
|
||||
public virtual ISet<MemberTelNr> TelephoneNumbers { get; private set; }
|
||||
|
||||
public string FullAddress => $"{Address}, {PostalDest.AtPlz.Plz} {PostalDest.AtPlz.Ort.Name}";
|
||||
|
||||
public int DeliveryRight => BusinessShares * App.Client.DeliveryRight;
|
||||
public int DeliveryObligation => BusinessShares * App.Client.DeliveryObligation;
|
||||
|
||||
public int SearchScore(IEnumerable<string> keywords) {
|
||||
keywords = keywords.Where(s => s.Length >= 2 || (s.Length > 0 && s.All(c => char.IsDigit(c))));
|
||||
if (!keywords.Any())
|
||||
return 0;
|
||||
|
||||
string?[] check = new string?[] {
|
||||
return Utils.GetSearchScore(new string?[] {
|
||||
MgNr.ToString(),
|
||||
FamilyName.ToLower(), MiddleName?.ToLower(), GivenName.ToLower(),
|
||||
BillingAddress?.Name.ToLower(),
|
||||
Comment?.ToLower(),
|
||||
};
|
||||
|
||||
int i = 0;
|
||||
foreach (string? c in check) {
|
||||
if (c == null) {
|
||||
continue;
|
||||
} else if (keywords.Any(f => c == f)) {
|
||||
i += 100;
|
||||
} else if (keywords.Any(f => c.Split(" ").Any(a => a == f))) {
|
||||
i += 99;
|
||||
} else if (keywords.Any(f => f != null && c.Contains(f))) {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
FamilyName, MiddleName, GivenName,
|
||||
BillingAddress?.Name,
|
||||
Comment,
|
||||
}, keywords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
25
Elwig/Models/MemberTelNr.cs
Normal file
25
Elwig/Models/MemberTelNr.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("member_telephone_number"), PrimaryKey("MgNr", "Nr")]
|
||||
public class MemberTelNr {
|
||||
[Column("mgnr")]
|
||||
public int MgNr { get; set; }
|
||||
|
||||
[Column("nr")]
|
||||
public int Nr { get; set; }
|
||||
|
||||
[Column("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[Column("number")]
|
||||
public string Number { get; set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[ForeignKey("MgNr")]
|
||||
public virtual Member Member { get; private set; }
|
||||
}
|
||||
}
|
@@ -1,5 +1,8 @@
|
||||
using Elwig.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("modifier"), PrimaryKey("Year", "ModId")]
|
||||
@@ -10,6 +13,9 @@ namespace Elwig.Models {
|
||||
[Column("modid")]
|
||||
public string ModId { get; set; }
|
||||
|
||||
[Column("ordering")]
|
||||
public int Ordering { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
@@ -18,16 +24,18 @@ namespace Elwig.Models {
|
||||
|
||||
[NotMapped]
|
||||
public decimal? Abs {
|
||||
get {
|
||||
return AbsValue != null ? Season.DecFromDb((long)AbsValue) : null;
|
||||
}
|
||||
set {
|
||||
AbsValue = value != null ? Season.DecToDb((decimal)value) : null;
|
||||
}
|
||||
get => AbsValue != null ? Season.DecFromDb(AbsValue.Value) : null;
|
||||
set => AbsValue = value != null ? Season.DecToDb(value.Value) : null;
|
||||
}
|
||||
|
||||
[Column("rel")]
|
||||
public double? Rel { get; set; }
|
||||
public double? RelValue { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public decimal? Rel {
|
||||
get => (decimal?)RelValue;
|
||||
set => RelValue = (double?)value;
|
||||
}
|
||||
|
||||
[Column("standard")]
|
||||
public bool IsStandard { get; set; }
|
||||
@@ -38,5 +46,13 @@ namespace Elwig.Models {
|
||||
[ForeignKey("Year")]
|
||||
public virtual Season Season { get; private set; }
|
||||
|
||||
public string ValueStr =>
|
||||
(Abs != null) ? $"{Utils.GetSign(Abs.Value)}{Math.Abs(Abs.Value).ToString("0." + string.Concat(Enumerable.Repeat('0', Season.Precision)))}\u00a0{Season.Currency.Symbol}/kg" :
|
||||
(Rel != null) ? $"{Utils.GetSign(Rel.Value)}{(Math.Abs(Rel.Value) < 0.1m ? "\u2007" : "")}{Math.Abs(Rel.Value):0.00##\u00a0%}" :
|
||||
"";
|
||||
|
||||
public override string ToString() {
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
69
Elwig/Models/PaymentVar.cs
Normal file
69
Elwig/Models/PaymentVar.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("payment_variant"), PrimaryKey("Year", "AvNr")]
|
||||
public class PaymentVar {
|
||||
[Column("year")]
|
||||
public int Year { get; set; }
|
||||
|
||||
[Column("avnr")]
|
||||
public int AvNr { get; set; }
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("date")]
|
||||
public string DateString { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateOnly Date {
|
||||
get {
|
||||
return DateOnly.ParseExact(DateString, "yyyy-MM-dd");
|
||||
}
|
||||
set {
|
||||
DateString = value.ToString("yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
|
||||
[Column("test_variant")]
|
||||
public bool TestVariant { get; set; }
|
||||
|
||||
[Column("calc_time")]
|
||||
public int? CalcTime { get; set; }
|
||||
|
||||
[Column("bucket_1_name")]
|
||||
public string? Bucket1Name { get; set; }
|
||||
|
||||
[Column("bucket_2_name")]
|
||||
public string? Bucket2Name { get; set; }
|
||||
|
||||
[Column("bucket_3_name")]
|
||||
public string? Bucket3Name { get; set; }
|
||||
|
||||
[Column("bucket_4_name")]
|
||||
public string? Bucket4Name { get; set; }
|
||||
|
||||
[Column("bucket_5_name")]
|
||||
public string? Bucket5Name { get; set; }
|
||||
|
||||
[Column("bucket_6_name")]
|
||||
public string? Bucket6Name { get; set; }
|
||||
|
||||
[Column("bucket_7_name")]
|
||||
public string? Bucket7Name { get; set; }
|
||||
|
||||
[Column("bucket_8_name")]
|
||||
public string? Bucket8Name { get; set; }
|
||||
|
||||
[Column("bucket_9_name")]
|
||||
public string? Bucket9Name { get; set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[Column("data")]
|
||||
public string Data { get; set; }
|
||||
}
|
||||
}
|
@@ -2,15 +2,15 @@ using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("postal_dest"), PrimaryKey("CountryCode", "Id")]
|
||||
[Table("postal_dest"), PrimaryKey("CountryNum", "Id")]
|
||||
public class PostalDest {
|
||||
[Column("country")]
|
||||
public string CountryCode { get; private set; }
|
||||
public int CountryNum { get; private set; }
|
||||
|
||||
[Column("id")]
|
||||
public string Id { get; private set; }
|
||||
|
||||
[ForeignKey("CountryCode")]
|
||||
[ForeignKey("CountryNum")]
|
||||
public virtual Country Country { get; private set; }
|
||||
|
||||
[ForeignKey("Id")]
|
||||
|
19
Elwig/Models/WbGem.cs
Normal file
19
Elwig/Models/WbGem.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("wb_gem"), PrimaryKey("Gkz")]
|
||||
public class WbGem {
|
||||
[Column("gkz")]
|
||||
public int Gkz { get; private set; }
|
||||
|
||||
[Column("hkid")]
|
||||
public string HkId { get; private set; }
|
||||
|
||||
[ForeignKey("Gkz")]
|
||||
public virtual AT_Gem AtGem { get; private set; }
|
||||
|
||||
[ForeignKey("HkId")]
|
||||
public virtual WineOrigin Origin { get; private set; }
|
||||
}
|
||||
}
|
17
Elwig/Models/WbGl.cs
Normal file
17
Elwig/Models/WbGl.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("wb_gl"), PrimaryKey("GlNr")]
|
||||
public class WbGl {
|
||||
[Column("glnr")]
|
||||
public int GlNr { get; private set; }
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; private set; }
|
||||
|
||||
[InverseProperty("Gl")]
|
||||
public virtual ISet<WbKg> Kgs { get; private set; }
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
@@ -11,6 +12,18 @@ namespace Elwig.Models {
|
||||
public int? GlNr { get; set; }
|
||||
|
||||
[ForeignKey("KgNr")]
|
||||
public virtual AT_Kg Kg { get; private set; }
|
||||
public virtual AT_Kg AtKg { get; private set; }
|
||||
|
||||
[ForeignKey("GlNr")]
|
||||
public virtual WbGl Gl { get; private set; }
|
||||
|
||||
[InverseProperty("Kg")]
|
||||
public virtual ISet<WbRd> Rds { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public WbGem Gem => AtKg.Gem.WbGem;
|
||||
|
||||
[NotMapped]
|
||||
public WineOrigin Origin => Gem.Origin;
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,6 @@ namespace Elwig.Models {
|
||||
public string Name { get; set; }
|
||||
|
||||
[ForeignKey("KgNr")]
|
||||
public virtual WbKg WbKg { get; private set; }
|
||||
public virtual WbKg Kg { get; private set; }
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,13 @@ namespace Elwig.Models {
|
||||
[Column("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("kg_per_ha")]
|
||||
public int KgPerHa { get; set; }
|
||||
[Column("max_kg_per_ha")]
|
||||
public int? MaxKgPerHa { get; set; }
|
||||
|
||||
[Column("active")]
|
||||
public bool IsActive { get; set; }
|
||||
public override string ToString() {
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
Elwig/Models/WineOrigin.cs
Normal file
46
Elwig/Models/WineOrigin.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("wine_origin"), PrimaryKey("HkId"), Index("Name", IsUnique = true)]
|
||||
public class WineOrigin {
|
||||
[Column("hkid")]
|
||||
public string HkId { get; private set; }
|
||||
|
||||
[Column("parent_hkid")]
|
||||
public string? ParentHkId { get; private set; }
|
||||
|
||||
[ForeignKey("ParentHkId")]
|
||||
public virtual WineOrigin? Parent { get; private set; }
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; private set; }
|
||||
|
||||
[Column("blnr")]
|
||||
public int? BlNr { get; private set; }
|
||||
|
||||
[InverseProperty("Origin")]
|
||||
public virtual ISet<WbGem> Gems { get; private set; }
|
||||
|
||||
[InverseProperty("Parent")]
|
||||
public virtual ISet<WineOrigin> Children { get; private set; }
|
||||
|
||||
public int Level => (Parent?.Level + 1) ?? 0;
|
||||
|
||||
public string HkIdLevel => $"{new string(' ', Level * 2)}{HkId}";
|
||||
|
||||
public int TotalChildNum => 1 + Children.Select(c => c.TotalChildNum).Sum();
|
||||
|
||||
private int SortKey1 => (Parent?.SortKey1 ?? 0) | (TotalChildNum << ((3 - Level) * 8));
|
||||
public int SortKey => SortKey1 | ((Level < 3) ? (-1 >>> (Level * 8 + 8)) : 0);
|
||||
|
||||
public override string ToString() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
public string OriginString => (Parent != null ? $"{Parent.OriginString} / " : "") + Name;
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
using Elwig.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("wine_quality"), PrimaryKey("QualId")]
|
||||
public class WineQual {
|
||||
[Column("qualid")]
|
||||
public string QualId { get; private set; }
|
||||
|
||||
[Column("origin_level")]
|
||||
public int? OriginLevel { get; private set; }
|
||||
|
||||
[Column("predicate")]
|
||||
public bool IsPredicate { get; private set; }
|
||||
|
||||
[Column("min_kmw")]
|
||||
public double? MinKmw { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public double? MinOe => MinKmw != null ? Utils.KmwToOe((double)MinKmw) : null;
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; private set; }
|
||||
}
|
||||
}
|
47
Elwig/Models/WineQualLevel.cs
Normal file
47
Elwig/Models/WineQualLevel.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Elwig.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Configuration;
|
||||
using System.Security.Cryptography.Pkcs;
|
||||
|
||||
namespace Elwig.Models {
|
||||
[Table("wine_quality_level"), PrimaryKey("QualId")]
|
||||
public class WineQualLevel : IEquatable<WineQualLevel> {
|
||||
[Column("qualid")]
|
||||
public string QualId { get; private set; }
|
||||
|
||||
[Column("origin_level")]
|
||||
public int? OriginLevel { get; private set; }
|
||||
|
||||
[Column("predicate")]
|
||||
public bool IsPredicate { get; private set; }
|
||||
|
||||
[Column("min_kmw")]
|
||||
public double? MinKmw { get; private set; }
|
||||
|
||||
[NotMapped]
|
||||
public double? MinOe => MinKmw != null ? Utils.KmwToOe((double)MinKmw) : null;
|
||||
|
||||
[Column("name")]
|
||||
public string Name { get; private set; }
|
||||
|
||||
public string MinKmwStr => (MinKmw == null) ? "" : $"(mind. {MinKmw:#.0}°)";
|
||||
|
||||
public override bool Equals(object? obj) {
|
||||
return Equals(obj as WineQualLevel);
|
||||
}
|
||||
|
||||
public bool Equals(WineQualLevel? obj) {
|
||||
return QualId == obj?.QualId;
|
||||
}
|
||||
|
||||
public static bool operator ==(WineQualLevel? q1, WineQualLevel? q2) {
|
||||
return q1?.Equals(q2) ?? Equals(q1, q2);
|
||||
}
|
||||
|
||||
public static bool operator !=(WineQualLevel? q1, WineQualLevel? q2) {
|
||||
return !(q1?.Equals(q2) ?? Equals(q1, q2));
|
||||
}
|
||||
}
|
||||
}
|
@@ -15,5 +15,11 @@ namespace Elwig.Models {
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; private set; }
|
||||
|
||||
public string CommentFormat => (Comment != null) ? $" ({Comment})" : "";
|
||||
|
||||
public override string ToString() {
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
|
@@ -1,45 +1,100 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Threading;
|
||||
using Xceed.Wpf.Toolkit;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public abstract class AdministrationWindow : ContextWindow {
|
||||
|
||||
protected Control[] ExemptInputs { private get; set; }
|
||||
protected Control[] RequiredInputs { private get; set; }
|
||||
|
||||
private bool _IsEditing;
|
||||
private bool _IsCreating;
|
||||
protected bool IsEditing {
|
||||
get { return _IsEditing; }
|
||||
set {
|
||||
_IsEditing = value;
|
||||
LockContext = IsEditing;
|
||||
}
|
||||
}
|
||||
protected bool IsCreating {
|
||||
get { return _IsCreating; }
|
||||
set {
|
||||
_IsCreating = value;
|
||||
LockContext = IsEditing;
|
||||
}
|
||||
}
|
||||
protected bool IsClosing { get; private set; }
|
||||
|
||||
private TextBox[] TextBoxInputs;
|
||||
private TextBox[] PlzInputs;
|
||||
private ComboBox[] ComboBoxInputs;
|
||||
private ComboBox[] PlzOrtInputs;
|
||||
private CheckComboBox[] CheckComboBoxInputs;
|
||||
private CheckBox[] CheckBoxInputs;
|
||||
private RadioButton[] RadioButtonInputs;
|
||||
private readonly Dictionary<Control, bool> Valid;
|
||||
private readonly Dictionary<Control, object?> OriginalValues;
|
||||
private readonly Dictionary<Control, object?> DefaultValues;
|
||||
|
||||
public AdministrationWindow() : base() {
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
ExemptInputs = Array.Empty<Control>();
|
||||
RequiredInputs = Array.Empty<Control>();
|
||||
TextBoxInputs = Array.Empty<TextBox>();
|
||||
PlzInputs = Array.Empty<TextBox>();
|
||||
ComboBoxInputs = Array.Empty<ComboBox>();
|
||||
CheckComboBoxInputs = Array.Empty<CheckComboBox>();
|
||||
PlzOrtInputs = Array.Empty<ComboBox>();
|
||||
CheckBoxInputs = Array.Empty<CheckBox>();
|
||||
RadioButtonInputs = Array.Empty<RadioButton>();
|
||||
Valid = new();
|
||||
OriginalValues = new();
|
||||
DefaultValues = new();
|
||||
Closing += OnClosing;
|
||||
Loaded += OnLoaded;
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs evt) {
|
||||
TextBoxInputs = Utils.FindAllChildren<TextBox>(this, ExemptInputs).ToArray();
|
||||
ComboBoxInputs = Utils.FindAllChildren<ComboBox>(this, ExemptInputs).ToArray();
|
||||
CheckBoxInputs = Utils.FindAllChildren<CheckBox>(this, ExemptInputs).ToArray();
|
||||
RadioButtonInputs = Utils.FindAllChildren<RadioButton>(this, ExemptInputs).ToArray();
|
||||
TextBoxInputs = ControlUtils.FindAllChildren<TextBox>(this, ExemptInputs).ToArray();
|
||||
ComboBoxInputs = ControlUtils.FindAllChildren<ComboBox>(this, ExemptInputs).ToArray();
|
||||
CheckBoxInputs = ControlUtils.FindAllChildren<CheckBox>(this, ExemptInputs).ToArray();
|
||||
CheckComboBoxInputs = ControlUtils.FindAllChildren<CheckComboBox>(this, ExemptInputs).ToArray();
|
||||
RadioButtonInputs = ControlUtils.FindAllChildren<RadioButton>(this, ExemptInputs).ToArray();
|
||||
PlzInputs = TextBoxInputs.Where(tb => "PLZ".Equals(tb.Tag)).ToArray();
|
||||
PlzOrtInputs = PlzInputs.Select(tb => ControlUtils.FindNextSibling<ComboBox>(tb) ?? throw new MissingMemberException()).ToArray();
|
||||
foreach (var tb in TextBoxInputs)
|
||||
Valid[tb] = true;
|
||||
foreach (var cb in ComboBoxInputs)
|
||||
cb.SelectionChanged += ComboBox_SelectionChanged;
|
||||
foreach (var cb in CheckComboBoxInputs)
|
||||
cb.ItemSelectionChanged += ComboBox_SelectionChanged;
|
||||
}
|
||||
|
||||
private void OnClosing(object? sender, CancelEventArgs evt) {
|
||||
IsClosing = true;
|
||||
}
|
||||
|
||||
private ComboBox GetPlzOrtInput(TextBox input) {
|
||||
return PlzOrtInputs[Array.IndexOf(PlzInputs, input)];
|
||||
}
|
||||
|
||||
abstract protected void UpdateButtons();
|
||||
|
||||
protected override async Task RenewContext() {
|
||||
for (int i = 0; i < PlzInputs.Length; i++)
|
||||
UpdatePlz(PlzInputs[i], PlzOrtInputs[i]);
|
||||
}
|
||||
|
||||
protected void ValidateInput(Control input, bool valid) {
|
||||
Valid[input] = valid;
|
||||
}
|
||||
@@ -48,33 +103,58 @@ namespace Elwig.Windows {
|
||||
return (sender is Control c) && RequiredInputs.Contains(c);
|
||||
}
|
||||
|
||||
protected void FinishInputFilling() {
|
||||
FillOriginalValues();
|
||||
ValidateDefaultValues();
|
||||
ValidateRequiredInputs();
|
||||
}
|
||||
|
||||
protected void ClearInputStates() {
|
||||
foreach (var tb in TextBoxInputs)
|
||||
Utils.ClearInputState(tb);
|
||||
ControlUtils.ClearInputState(tb);
|
||||
foreach (var cb in ComboBoxInputs)
|
||||
Utils.ClearInputState(cb);
|
||||
ControlUtils.ClearInputState(cb);
|
||||
foreach (var ccb in CheckComboBoxInputs)
|
||||
ControlUtils.ClearInputState(ccb);
|
||||
foreach (var cb in CheckBoxInputs)
|
||||
Utils.ClearInputState(cb);
|
||||
ControlUtils.ClearInputState(cb);
|
||||
foreach (var rb in RadioButtonInputs)
|
||||
Utils.ClearInputState(rb);
|
||||
ControlUtils.ClearInputState(rb);
|
||||
}
|
||||
|
||||
protected void ValidateRequiredInputs() {
|
||||
foreach (var input in RequiredInputs) {
|
||||
if (input is TextBox tb && tb.Text.Length == 0) {
|
||||
Utils.SetInputInvalid(input);
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
Valid[input] = false;
|
||||
} else if (input is ComboBox cb && cb.SelectedItem == null && cb.ItemsSource != null) {
|
||||
Utils.SetInputInvalid(input);
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
} else if (input is CheckComboBox ccb && ccb.SelectedItem == null && ccb.ItemsSource != null) {
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
} else if (input is CheckBox ckb && ckb.IsChecked != true) {
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
Valid[input] = false;
|
||||
} else if (input is RadioButton rb && rb.IsChecked != true) {
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
Valid[input] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void ValidateDefaultValues() {
|
||||
foreach (var input in DefaultValues.Keys) {
|
||||
if (InputIsNotDefault(input))
|
||||
ControlUtils.SetInputNotDefault(input);
|
||||
}
|
||||
}
|
||||
|
||||
protected void LockInputs() {
|
||||
foreach (var tb in TextBoxInputs)
|
||||
tb.IsReadOnly = true;
|
||||
foreach (var cb in ComboBoxInputs)
|
||||
cb.IsEnabled = false;
|
||||
foreach (var ccb in CheckComboBoxInputs)
|
||||
ccb.IsEnabled = false;
|
||||
foreach (var cb in CheckBoxInputs)
|
||||
cb.IsEnabled = false;
|
||||
foreach (var rb in RadioButtonInputs)
|
||||
@@ -86,6 +166,8 @@ namespace Elwig.Windows {
|
||||
tb.IsReadOnly = false;
|
||||
foreach (var cb in ComboBoxInputs)
|
||||
cb.IsEnabled = true;
|
||||
foreach (var ccb in CheckComboBoxInputs)
|
||||
ccb.IsEnabled = true;
|
||||
foreach (var cb in CheckBoxInputs)
|
||||
cb.IsEnabled = true;
|
||||
foreach (var rb in RadioButtonInputs)
|
||||
@@ -96,31 +178,81 @@ namespace Elwig.Windows {
|
||||
OriginalValues.Clear();
|
||||
}
|
||||
|
||||
protected void ClearDefaultValues() {
|
||||
DefaultValues.Clear();
|
||||
}
|
||||
|
||||
protected void FillOriginalValues() {
|
||||
foreach (var tb in TextBoxInputs)
|
||||
OriginalValues[tb] = tb.Text;
|
||||
foreach (var cb in ComboBoxInputs)
|
||||
OriginalValues[cb] = cb.SelectedItem;
|
||||
foreach (var ccb in CheckComboBoxInputs)
|
||||
OriginalValues[ccb] = ccb.SelectedItems.Cast<object>().ToArray();
|
||||
foreach (var cb in CheckBoxInputs)
|
||||
OriginalValues[cb] = (cb.IsChecked ?? false) ? bool.TrueString : null;
|
||||
OriginalValues[cb] = cb.IsChecked?.ToString();
|
||||
foreach (var rb in RadioButtonInputs)
|
||||
OriginalValues[rb] = (rb.IsChecked ?? false) ? bool.TrueString : null;
|
||||
OriginalValues[rb] = rb.IsChecked?.ToString();
|
||||
}
|
||||
|
||||
protected void ClearInputs() {
|
||||
protected void SetOriginalValue(Control input, object? value) {
|
||||
OriginalValues[input] = value is bool b ? b.ToString() : value;
|
||||
if (InputHasChanged(input)) {
|
||||
ControlUtils.SetInputChanged(input);
|
||||
} else {
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetOriginalValue(Control input) {
|
||||
SetOriginalValue(input, ControlUtils.GetInputValue(input));
|
||||
}
|
||||
|
||||
protected void UnsetOriginalValue(Control input) {
|
||||
OriginalValues.Remove(input);
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
|
||||
protected void SetDefaultValue(Control input, object? value) {
|
||||
DefaultValues[input] = value is bool b ? b.ToString() : value;
|
||||
if (!InputHasChanged(input)) {
|
||||
if (InputIsNotDefault(input)) {
|
||||
ControlUtils.SetInputNotDefault(input);
|
||||
} else {
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetDefaultValue(Control input) {
|
||||
SetDefaultValue(input, ControlUtils.GetInputValue(input));
|
||||
}
|
||||
|
||||
protected void UnsetDefaultValue(Control input) {
|
||||
DefaultValues.Remove(input);
|
||||
if (!InputHasChanged(input)) {
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
}
|
||||
|
||||
protected void ClearInputs(bool validate = true) {
|
||||
foreach (var tb in TextBoxInputs)
|
||||
tb.Text = "";
|
||||
foreach (var cb in ComboBoxInputs)
|
||||
cb.SelectedItem = null;
|
||||
foreach (var ccb in CheckComboBoxInputs)
|
||||
ccb.SelectedItems.Clear();
|
||||
foreach (var cb in CheckBoxInputs)
|
||||
cb.IsChecked = false;
|
||||
foreach (var rb in RadioButtonInputs)
|
||||
rb.IsChecked = false;
|
||||
ValidateRequiredInputs();
|
||||
if (validate) ValidateRequiredInputs();
|
||||
}
|
||||
|
||||
protected bool IsValid() {
|
||||
return Valid.All(kv => kv.Value) && ComboBoxInputs.All(cb => cb.ItemsSource == null || cb.SelectedItem != null);
|
||||
protected bool IsValid => Valid.All(kv => kv.Value);
|
||||
|
||||
protected bool GetInputValid(Control input) {
|
||||
return Valid[input];
|
||||
}
|
||||
|
||||
protected bool InputHasChanged(Control input) {
|
||||
@@ -130,82 +262,122 @@ namespace Elwig.Windows {
|
||||
return OriginalValues[tb]?.ToString() != tb.Text;
|
||||
} else if (input is ComboBox sb) {
|
||||
return OriginalValues[sb] != sb.SelectedItem;
|
||||
} else if (input is CheckComboBox ccb) {
|
||||
return !ccb.SelectedItems.Cast<object>().ToArray().SequenceEqual(((object[]?)OriginalValues[ccb]) ?? Array.Empty<object>());
|
||||
} else if (input is CheckBox cb) {
|
||||
return (OriginalValues[cb] != null) != (cb.IsChecked ?? false);
|
||||
return (string?)OriginalValues[cb] != cb.IsChecked?.ToString();
|
||||
} else if (input is RadioButton rb) {
|
||||
return (OriginalValues[rb] != null) != (rb.IsChecked ?? false);
|
||||
return (string?)OriginalValues[rb] != rb.IsChecked?.ToString();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool HasChanged() {
|
||||
return !IsValid() ||
|
||||
TextBoxInputs.Any(InputHasChanged) ||
|
||||
ComboBoxInputs.Any(InputHasChanged) ||
|
||||
CheckBoxInputs.Any(InputHasChanged) ||
|
||||
RadioButtonInputs.Any(InputHasChanged);
|
||||
protected bool InputIsNotDefault(Control input) {
|
||||
if (!DefaultValues.ContainsKey(input)) {
|
||||
return false;
|
||||
} else if (input is TextBox tb) {
|
||||
return DefaultValues[tb]?.ToString() != tb.Text;
|
||||
} else if (input is ComboBox sb) {
|
||||
return DefaultValues[sb] != sb.SelectedItem;
|
||||
} else if (input is CheckComboBox ccb) {
|
||||
return !ccb.SelectedItems.Cast<object>().ToArray().SequenceEqual(((object[]?)DefaultValues[ccb]) ?? Array.Empty<object>());
|
||||
} else if (input is CheckBox cb) {
|
||||
return (string?)DefaultValues[cb] != cb.IsChecked?.ToString();
|
||||
} else if (input is RadioButton rb) {
|
||||
return (string?)DefaultValues[rb] != rb.IsChecked?.ToString();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool HasChanged =>
|
||||
!IsValid ||
|
||||
TextBoxInputs.Any(InputHasChanged) ||
|
||||
ComboBoxInputs.Any(InputHasChanged) ||
|
||||
CheckComboBoxInputs.Any(InputHasChanged) ||
|
||||
CheckBoxInputs.Any(InputHasChanged) ||
|
||||
RadioButtonInputs.Any(InputHasChanged);
|
||||
|
||||
protected void UpdatePlz(TextBox plzInput, ComboBox ortInput) {
|
||||
if (plzInput.Text.Length == 4) {
|
||||
ortInput.ItemsSource = Context.Postleitzahlen.Find(int.Parse(plzInput.Text))?.Orte.ToList();
|
||||
} else {
|
||||
ortInput.ItemsSource = null;
|
||||
}
|
||||
ortInput.SelectedItem = null;
|
||||
if (ortInput.ItemsSource != null) {
|
||||
Utils.SetInputInvalid(ortInput);
|
||||
} else {
|
||||
Utils.ClearInputState(ortInput);
|
||||
}
|
||||
ValidateInput(plzInput, SenderIsRequired(plzInput) || (ortInput.ItemsSource != null));
|
||||
UpdateButtons();
|
||||
var plzInputValid = GetInputValid(plzInput);
|
||||
var item = ortInput.SelectedItem;
|
||||
var list = plzInputValid && plzInput.Text.Length == 4 ? Context.Postleitzahlen.Find(int.Parse(plzInput.Text))?.Orte.ToList() : null;
|
||||
ControlUtils.RenewItemsSource(ortInput, list, i => (i as AT_PlzDest)?.Id);
|
||||
if (list != null && ortInput.SelectedItem == null && list.Count == 1)
|
||||
ortInput.SelectedItem = list[0];
|
||||
UpdateComboBox(ortInput);
|
||||
}
|
||||
|
||||
protected void InputTextChanged(TextBox input, Func<TextBox, bool, ValidationResult> checker) {
|
||||
InputTextChanged(input, (tb, required, ctx) => checker(tb, required));
|
||||
protected static void InitializeDelayTimer(TextBox tb, Action<object, TextChangedEventArgs> handler) {
|
||||
var timer = new DispatcherTimer {
|
||||
Interval = TimeSpan.FromMilliseconds(250)
|
||||
};
|
||||
timer.Tick += (object? sender, EventArgs evt) => {
|
||||
timer.Stop();
|
||||
var (oSender, oEvent) = ((object, TextChangedEventArgs))timer.Tag;
|
||||
handler(oSender, oEvent);
|
||||
};
|
||||
tb.TextChanged += (object sender, TextChangedEventArgs evt) => {
|
||||
timer.Stop();
|
||||
timer.Tag = (sender, evt);
|
||||
timer.Start();
|
||||
};
|
||||
}
|
||||
|
||||
protected void InputTextChanged(TextBox input, Func<TextBox, bool, AppDbContext, ValidationResult> checker) {
|
||||
InputTextChanged(input, checker(input, SenderIsRequired(input), Context));
|
||||
protected bool InputTextChanged(TextBox input) {
|
||||
return InputTextChanged(input, new ValidationResult(true, null));
|
||||
}
|
||||
|
||||
protected void InputTextChanged(TextBox input, ValidationResult res) {
|
||||
protected bool InputTextChanged(TextBox input, Func<TextBox, bool, ValidationResult> checker) {
|
||||
return InputTextChanged(input, (tb, required, ctx) => checker(tb, required));
|
||||
}
|
||||
|
||||
protected bool InputTextChanged(TextBox input, Func<TextBox, bool, AppDbContext, ValidationResult> checker) {
|
||||
return InputTextChanged(input, checker(input, SenderIsRequired(input), Context));
|
||||
}
|
||||
|
||||
protected bool InputTextChanged(TextBox input, ValidationResult res) {
|
||||
ValidateInput(input, res.IsValid);
|
||||
if (res.IsValid) {
|
||||
if (InputHasChanged(input)) {
|
||||
Utils.SetInputChanged(input);
|
||||
ControlUtils.SetInputChanged(input);
|
||||
} else if (InputIsNotDefault(input)) {
|
||||
ControlUtils.SetInputNotDefault(input);
|
||||
} else {
|
||||
Utils.ClearInputState(input);
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
} else {
|
||||
Utils.SetInputInvalid(input);
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
}
|
||||
UpdateButtons();
|
||||
return res.IsValid;
|
||||
}
|
||||
|
||||
protected void InputLostFocus(TextBox input, Func<TextBox, bool, ValidationResult> checker, string? msg = null) {
|
||||
InputLostFocus(input, (tb, requiered, ctx) => checker(tb, requiered), msg);
|
||||
protected bool InputLostFocus(TextBox input, Func<TextBox, bool, ValidationResult> checker, string? msg = null) {
|
||||
return InputLostFocus(input, (tb, requiered, ctx) => checker(tb, requiered), msg);
|
||||
}
|
||||
|
||||
protected void InputLostFocus(TextBox input, Func<TextBox, bool, AppDbContext, ValidationResult> checker, string? msg = null) {
|
||||
InputLostFocus(input, checker(input, SenderIsRequired(input), Context), msg);
|
||||
protected bool InputLostFocus(TextBox input, Func<TextBox, bool, AppDbContext, ValidationResult> checker, string? msg = null) {
|
||||
return InputLostFocus(input, checker(input, SenderIsRequired(input), Context), msg);
|
||||
}
|
||||
|
||||
protected void InputLostFocus(TextBox input, ValidationResult res, string? msg = null) {
|
||||
if (!res.IsValid)
|
||||
MessageBox.Show(res.ErrorContent.ToString(), msg ?? res.ErrorContent.ToString(), MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
protected bool InputLostFocus(TextBox input, ValidationResult res, string? msg = null) {
|
||||
if (!res.IsValid && !IsClosing && (IsEditing || IsCreating))
|
||||
System.Windows.MessageBox.Show(res.ErrorContent.ToString(), msg ?? res.ErrorContent.ToString(), MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return res.IsValid;
|
||||
}
|
||||
|
||||
protected void CheckBox_Changed(object sender, RoutedEventArgs evt) {
|
||||
var input = (CheckBox)sender;
|
||||
if (SenderIsRequired(input) && input.IsChecked != true) {
|
||||
Utils.SetInputInvalid(input);
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
} else if (InputHasChanged(input)) {
|
||||
Utils.SetInputChanged(input);
|
||||
ControlUtils.SetInputChanged(input);
|
||||
} else if (InputIsNotDefault(input)) {
|
||||
ControlUtils.SetInputNotDefault(input);
|
||||
} else {
|
||||
Utils.ClearInputState(input);
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
UpdateButtons();
|
||||
}
|
||||
@@ -213,11 +385,13 @@ namespace Elwig.Windows {
|
||||
protected void RadioButton_Changed(object sender, RoutedEventArgs evt) {
|
||||
var input = (RadioButton)sender;
|
||||
if (SenderIsRequired(input) && input.IsChecked != true) {
|
||||
Utils.SetInputInvalid(input);
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
} else if (InputHasChanged(input)) {
|
||||
Utils.SetInputChanged(input);
|
||||
ControlUtils.SetInputChanged(input);
|
||||
} else if (InputIsNotDefault(input)) {
|
||||
ControlUtils.SetInputNotDefault(input);
|
||||
} else {
|
||||
Utils.ClearInputState(input);
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
UpdateButtons();
|
||||
}
|
||||
@@ -226,30 +400,47 @@ namespace Elwig.Windows {
|
||||
var input = (TextBox)sender;
|
||||
if (SenderIsRequired(input) && input.Text.Length == 0) {
|
||||
ValidateInput(input, false);
|
||||
Utils.SetInputInvalid(input);
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
} else {
|
||||
ValidateInput(input, true);
|
||||
if (InputHasChanged(input)) {
|
||||
Utils.SetInputChanged(input);
|
||||
ControlUtils.SetInputChanged(input);
|
||||
} else if (InputIsNotDefault(input)) {
|
||||
ControlUtils.SetInputNotDefault(input);
|
||||
} else {
|
||||
Utils.ClearInputState(input);
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
}
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
protected void ComboBox_SelectionChanged(object sender, RoutedEventArgs evt) {
|
||||
var input = (ComboBox)sender;
|
||||
if (input.ItemsSource != null && input.SelectedItem == null) {
|
||||
Utils.SetInputInvalid(input);
|
||||
} else if (InputHasChanged(input)) {
|
||||
Utils.SetInputChanged(input);
|
||||
private void UpdateComboBox(Control input) {
|
||||
bool valid = false;
|
||||
if (input is ComboBox cb) {
|
||||
valid = cb.ItemsSource == null || cb.SelectedItem != null || !RequiredInputs.Contains(input);
|
||||
} else if (input is CheckComboBox ccb) {
|
||||
valid = ccb.ItemsSource == null || ccb.SelectedItem != null || !RequiredInputs.Contains(input);
|
||||
}
|
||||
if (valid) {
|
||||
ValidateInput(input, true);
|
||||
if (InputHasChanged(input)) {
|
||||
ControlUtils.SetInputChanged(input);
|
||||
} else if (InputIsNotDefault(input)) {
|
||||
ControlUtils.SetInputNotDefault(input);
|
||||
} else {
|
||||
ControlUtils.ClearInputState(input);
|
||||
}
|
||||
} else {
|
||||
Utils.ClearInputState(input);
|
||||
ValidateInput(input, false);
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
}
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
protected void ComboBox_SelectionChanged(object sender, RoutedEventArgs evt) {
|
||||
UpdateComboBox((Control)sender);
|
||||
}
|
||||
|
||||
protected void IntegerInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckInteger);
|
||||
}
|
||||
@@ -258,27 +449,37 @@ namespace Elwig.Windows {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckPartialDate);
|
||||
}
|
||||
|
||||
protected void PartialDateInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckPartialDate);
|
||||
}
|
||||
|
||||
protected void DateInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckDate);
|
||||
}
|
||||
|
||||
protected void DateInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckDate);
|
||||
}
|
||||
|
||||
protected void PlzInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
var plz = (TextBox)sender;
|
||||
InputTextChanged(plz, Validator.CheckPlz);
|
||||
UpdatePlz(plz, Utils.FindNextSibling<ComboBox>(plz));
|
||||
if ("PLZ".Equals(plz.Tag))
|
||||
UpdatePlz(plz, GetPlzOrtInput(plz));
|
||||
}
|
||||
|
||||
protected void PlzInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
var plz = (TextBox)sender;
|
||||
InputLostFocus(plz, Validator.CheckPlz);
|
||||
UpdatePlz(plz, Utils.FindNextSibling<ComboBox>(plz));
|
||||
if ("PLZ".Equals(plz.Tag))
|
||||
UpdatePlz(plz, GetPlzOrtInput(plz));
|
||||
}
|
||||
|
||||
protected void EmailInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
protected void EmailAddressInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckEmailAddress);
|
||||
}
|
||||
|
||||
protected void EmailInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
protected void EmailAddressInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckEmailAddress);
|
||||
}
|
||||
|
||||
@@ -306,12 +507,12 @@ namespace Elwig.Windows {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckBic);
|
||||
}
|
||||
|
||||
protected void UstIdInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckUstId);
|
||||
protected void UstIdNrInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckUstIdNr);
|
||||
}
|
||||
|
||||
protected void UstIdInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckUstId);
|
||||
protected void UstIdNrInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckUstIdNr);
|
||||
}
|
||||
|
||||
protected void LfbisNrInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
|
@@ -5,7 +5,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Elwig.Windows"
|
||||
mc:Ignorable="d"
|
||||
Title="Flächenbindugen - Elwig" Height="500" Width="950"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
Title="Flächenbindugen - Elwig" Height="480" Width="850"
|
||||
Loaded="Window_Loaded">
|
||||
<Window.Resources>
|
||||
<Style TargetType="Label">
|
||||
@@ -30,6 +31,13 @@
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style TargetType="xctk:CheckComboBox">
|
||||
<Setter Property="IsEnabled" Value="False"/>
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="9,3"/>
|
||||
@@ -39,153 +47,116 @@
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="19"/>
|
||||
<RowDefinition Height="120"/>
|
||||
<RowDefinition Height="190"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="620"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="330"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Menu Grid.ColumnSpan="3" BorderThickness="0,0,0,1" BorderBrush="LightGray" Background="White">
|
||||
<Menu Grid.ColumnSpan="2" BorderThickness="0,0,0,1" BorderBrush="LightGray" Background="White">
|
||||
<MenuItem Header="Flächenbindugen"/>
|
||||
</Menu>
|
||||
|
||||
<Grid Grid.RowSpan="4" Grid.Row="1">
|
||||
<Grid Grid.RowSpan="2" Grid.Row="1" Grid.Column="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="125"/>
|
||||
<ColumnDefinition Width="120"/>
|
||||
<ColumnDefinition Width="125"/>
|
||||
<ColumnDefinition Width="125"/>
|
||||
<ColumnDefinition Width="125"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<DataGrid x:Name="ContractList" AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single"
|
||||
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False" SelectionChanged="ContractList_SelectionChanged" Grid.Column="0" Grid.Row="1"
|
||||
Margin="10,10,5,47" FontSize="14" Grid.ColumnSpan="2" Background="#e2e2e2">
|
||||
<DataGrid x:Name="AreaCommitmentList" AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single"
|
||||
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False" SelectionChanged="AreaCommitmentList_SelectionChanged" Grid.Column="0" Grid.Row="1"
|
||||
Margin="5,10,5,42" FontSize="14" Grid.ColumnSpan="3" Background="#e2e2e2">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="VNr." Binding="{Binding VNr}" Width="*"/>
|
||||
<DataGridTextColumn Header="Von" Binding="{Binding YearFrom}" Width="*"/>
|
||||
<DataGridTextColumn Header="Bis" Binding="{Binding YearTo}" Width="*"/>
|
||||
<DataGridTextColumn Header="FbNr." Binding="{Binding FbNr}" Width="2*"/>
|
||||
<DataGridTextColumn Header="Katastralgemeinde" Binding="{Binding Kg.AtKg.Name}" Width="6*"/>
|
||||
<DataGridTextColumn Header="Ried" Binding="{Binding Rd.Name}" Width="4*"/>
|
||||
<DataGridTextColumn Header="Parzelle" Binding="{Binding GstNr}" Width="4*"/>
|
||||
<DataGridTextColumn Header="Fläche" Binding="{Binding Area, StringFormat='{}{0:N0} m²'}" Width="4*">
|
||||
<DataGridTextColumn.CellStyle>
|
||||
<Style>
|
||||
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.CellStyle>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
|
||||
<Button x:Name="NewContractButton" Content="Neu" Click="NewContractButton_Click"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="10,10,0,10" Width="110" Grid.Column="0"/>
|
||||
<Button x:Name="DeleteContractButton" Content="Löschen" Click="DeleteContractButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="5,10,0,10" Width="110" Grid.Column="1"/>
|
||||
|
||||
<Button x:Name="ContractSaveButton" Content="Speichern" Click="ContractSaveButton_Click" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="10,10,0,10" Width="110" Grid.Column="0"/>
|
||||
<Button x:Name="ContractCancelButton" Content="Abbrechen" Click="ContractCancelButton_Click" IsEnabled="False" Visibility="Hidden" IsCancel="True"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="5,10,0,10" Width="110" Grid.Column="1"/>
|
||||
|
||||
|
||||
|
||||
<Button x:Name="NewAreaCommitmentButton" Content="Neu" Click="NewAreaCommitmentButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="5,10,0,10" Width="110" Grid.Column="2"/>
|
||||
<Button x:Name="NewAreaCommitmentButton" Content="Neu" Click="NewAreaCommitmentButton_Click"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0"/>
|
||||
<Button x:Name="EditAreaCommitmentButton" Content="Bearbeiten" Click="EditAreaCommitmentButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="-5,10,0,10" Width="110" Grid.Column="3"/>
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1"/>
|
||||
<Button x:Name="DeleteAreaCommitmentButton" Content="Löschen" Click="DeleteAreaCommitmentButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,10,10,10" Width="110" Grid.Column="4"/>
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2"/>
|
||||
|
||||
<Button x:Name="AreaCommitmentSaveButton" Content="Speichern" Click="AreaCommitmentSaveButton_Click" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="10,10,0,10" Width="110" Grid.Column="2"/>
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0"/>
|
||||
<Button x:Name="AreaCommitmentResetButton" Content="Zurücksetzen" Click="AreaCommitmentResetButton_Click" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="-5,10,0,10" Width="110" Grid.Column="3"/>
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1"/>
|
||||
<Button x:Name="AreaCommitmentCancelButton" Content="Abbrechen" Click="AreaCommitmentCancelButton_Click" IsEnabled="False" Visibility="Hidden" IsCancel="True"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,10,10,10" Width="110" Grid.Column="4"/>
|
||||
|
||||
<DataGrid x:Name="AreaCommitmentList" AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single"
|
||||
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False" SelectionChanged="AreaCommitmentList_SelectionChanged" Grid.Column="2" Grid.Row="1"
|
||||
Margin="5,10,10,47" FontSize="14" Grid.ColumnSpan="3" Background="#e2e2e2">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Katastralgemeinde" Binding="{Binding Kg.Kg.Name}" Width="5*"/>
|
||||
<DataGridTextColumn Header="Ried" Binding="{Binding Rd.Name}" Width="4*"/>
|
||||
<DataGridTextColumn Header="Parzelle" Binding="{Binding GstNr}" Width="4*"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2"/>
|
||||
</Grid>
|
||||
|
||||
<GroupBox Header="Vertrag" Grid.Column="1" Grid.Row="1" Grid.RowSpan="1" Margin="5,5,5,5">
|
||||
<GroupBox Header="Vertrag" Grid.Column="2" Grid.Row="1" Grid.RowSpan="1" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="60"/>
|
||||
<ColumnDefinition Width="70"/>
|
||||
<ColumnDefinition Width="80"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="50"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="VNr.:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="VNrInput" Margin="0,10,0,0" Width="48" Grid.Column="1" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="VNrInput_TextChanged" LostFocus="VNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="FbNr.:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="FbNrInput" Margin="0,10,0,0" Width="48" Grid.Column="1" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="FbNrInput_TextChanged" LostFocus="FbNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="MgNr.:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="MgNrInput" Margin="0,40,0,0" Width="48" Grid.Column="1" TextAlignment="Right" HorizontalAlignment="Left"/>
|
||||
|
||||
<TextBox x:Name="MgNrInput" IsEnabled="False"
|
||||
Margin="0,40,0,0" Width="48" Grid.Column="1" TextAlignment="Right" HorizontalAlignment="Left"/>
|
||||
|
||||
<Label Content="Von:" Margin="10,10,0,0" Grid.Column="2"/>
|
||||
<TextBox x:Name="YearFromInput" Margin="0,10,0,0" Width="100" Grid.Column="3" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="YearFromInput_TextChanged"/>
|
||||
|
||||
<TextBox x:Name="YearFromInput" Margin="0,10,0,0" Width="41" Grid.Column="3" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="IntegerInput_TextChanged"/>
|
||||
|
||||
<Label Content="Bis:" Margin="10,40,0,0" Grid.Column="2"/>
|
||||
<TextBox x:Name="YearToInput" Margin="0,40,0,0" Width="100" Grid.Column="3" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="YearToInput_TextChanged"/>
|
||||
<TextBox x:Name="YearToInput" Margin="0,40,0,0" Width="41" Grid.Column="3" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="IntegerInput_TextChanged"/>
|
||||
|
||||
<Label Content="Vertragsart:" Margin="10,70,0,0" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||
<ComboBox x:Name="AreaComTypeInput" DisplayMemberPath="DisplayName" TextSearch.TextPath="DisplayName"
|
||||
HorizontalAlignment="Stretch" Margin="0,70,10,0" Grid.Column="1" Grid.ColumnSpan="3"/>
|
||||
|
||||
<Label Content="Bewirt.-Art:" Margin="10,100,0,0" Grid.Column="0" Grid.ColumnSpan="2"/>
|
||||
<ComboBox x:Name="WineCultivationInput" DisplayMemberPath="Name" TextSearch.TextPath="Name"
|
||||
HorizontalAlignment="Stretch" Margin="0,100,10,0" Grid.Column="1" Grid.ColumnSpan="3"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Lage" Grid.Column="1" Grid.Row="2" Grid.RowSpan="1" Margin="5,5,5,5">
|
||||
|
||||
<GroupBox Header="Lage" Grid.Column="2" Grid.Row="2" Grid.RowSpan="1" Margin="5,5,5,10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Gemeinde:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="KgInput" ItemTemplate="{StaticResource KgTemplate}" TextSearch.TextPath="Name"
|
||||
Width="200" HorizontalAlignment="Left" SelectionChanged="KgInput_SelectionChanged"
|
||||
Margin="0,10,10,0" Grid.Column="1"/>
|
||||
|
||||
<Label Content="KG:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="KgInput" ItemTemplate="{StaticResource KgNrTemplate}" TextSearch.TextPath="Name"
|
||||
HorizontalAlignment="Stretch" Margin="0,10,10,0" Grid.Column="1"
|
||||
SelectionChanged="KgInput_SelectionChanged"/>
|
||||
|
||||
<Label Content="Ried:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="RdInput" ItemTemplate="{StaticResource KgTemplate}" TextSearch.TextPath="Name"
|
||||
Width="200" HorizontalAlignment="Left" SelectionChanged="ComboBox_SelectionChanged"
|
||||
Margin="0,40,0,0" Grid.Column="1"/>
|
||||
|
||||
<Label Content="Parzelle:" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="GstNrInput" Margin="0,70,0,0" Width="100" Grid.Column="1" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
<ComboBox x:Name="RdInput" DisplayMemberPath="Name" TextSearch.TextPath="Name"
|
||||
HorizontalAlignment="Stretch" Margin="0,40,10,0" Grid.Column="1"/>
|
||||
|
||||
<Label Content="Parzelle(n):" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="GstNrInput" Margin="0,70,10,0" Grid.Column="1" HorizontalAlignment="Stretch"
|
||||
TextChanged="GstNrInput_TextChanged" LostFocus="GstNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="Fläche (m²):" Margin="10,100,0,0" Grid.Column="0"/>
|
||||
<Label Content="Fläche:" Margin="10,100,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="AreaInput" Margin="0,100,0,0" Width="100" Grid.Column="1" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="AreaInput_TextChanged"/>
|
||||
</Grid>
|
||||
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Eigenschaften" Grid.Column="1" Grid.Row="3" Grid.RowSpan="1" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="80"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Sorte:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="SortInput" ItemTemplate="{StaticResource KgTemplate}" TextSearch.TextPath="Name"
|
||||
Width="200" HorizontalAlignment="Left" SelectionChanged="ComboBox_SelectionChanged"
|
||||
Margin="0,10,10,0" Grid.Column="1"/>
|
||||
|
||||
<Label Content="Attribut:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="AttrInput" ItemTemplate="{StaticResource KgTemplate}" TextSearch.TextPath="Name"
|
||||
Width="200" HorizontalAlignment="Left" SelectionChanged="ComboBox_SelectionChanged"
|
||||
Margin="0,40,10,0" Grid.Column="1"/>
|
||||
|
||||
<Label Content="Bewirt. Art:" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="CultInput" ItemTemplate="{StaticResource KgTemplate}" TextSearch.TextPath="Name"
|
||||
Width="200" HorizontalAlignment="Left" SelectionChanged="ComboBox_SelectionChanged"
|
||||
Margin="0,70,10,0" Grid.Column="1"/>
|
||||
|
||||
TextChanged="IntegerInput_TextChanged"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -7,41 +6,31 @@ using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Xceed.Wpf.Toolkit.Primitives;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class AreaComAdminWindow : AdministrationWindow {
|
||||
private readonly Member member;
|
||||
private bool IsEditing = false;
|
||||
private bool IsCreating = false;
|
||||
private readonly Member Member;
|
||||
|
||||
public AreaComAdminWindow(Member member) {
|
||||
public AreaComAdminWindow(int mgnr) {
|
||||
InitializeComponent();
|
||||
this.member = member;
|
||||
Title = $"Flächenbindungen - {member.FamilyName} {member.GivenName} - Elwig";
|
||||
Member = Context.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
||||
Title = $"Flächenbindungen - {Member.AdministrativeName} - Elwig";
|
||||
ExemptInputs = new Control[] {
|
||||
MgNrInput, ContractList, AreaCommitmentList, NewContractButton, DeleteContractButton,
|
||||
ContractSaveButton, ContractCancelButton, NewAreaCommitmentButton,
|
||||
MgNrInput, AreaCommitmentList, NewAreaCommitmentButton,
|
||||
EditAreaCommitmentButton, DeleteAreaCommitmentButton, AreaCommitmentSaveButton,
|
||||
AreaCommitmentResetButton, AreaCommitmentCancelButton
|
||||
};
|
||||
RequiredInputs = new Control[] {
|
||||
VNrInput, YearFromInput, KgInput,
|
||||
GstNrInput, AreaInput, SortInput, CultInput
|
||||
FbNrInput, YearFromInput, KgInput,
|
||||
GstNrInput, AreaInput, AreaComTypeInput, WineCultivationInput
|
||||
};
|
||||
}
|
||||
|
||||
private async void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
await RefreshContractList();
|
||||
KgInput.ItemsSource = Context.WbKgs.Select(k => k.Kg).OrderBy(k => k.Name).ToList();
|
||||
SortInput.ItemsSource = Context.WineVarieties.OrderBy(s => s.Name).ToList();
|
||||
AttrInput.ItemsSource = Context.WineAttributes.OrderBy(a => a.Name).ToList();
|
||||
CultInput.ItemsSource = Context.WineCultivations.OrderBy(c => c.Name).ToList();
|
||||
}
|
||||
|
||||
private async Task RefreshContractList() {
|
||||
await Context.Contracts.LoadAsync();
|
||||
await RefreshContractListQuery();
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
||||
LockInputs();
|
||||
}
|
||||
|
||||
private async Task RefreshAreaCommitmentList() {
|
||||
@@ -49,94 +38,79 @@ namespace Elwig.Windows {
|
||||
await RefreshAreaCommitmentListQuery();
|
||||
}
|
||||
|
||||
private async Task RefreshContractListQuery() {
|
||||
List<Contract> contracts = await Context.Contracts.Where(c => c.MgNr == member.MgNr).ToListAsync();
|
||||
|
||||
ContractList.ItemsSource = contracts;
|
||||
if (contracts.Count == 1)
|
||||
ContractList.SelectedIndex = 0;
|
||||
|
||||
// TODO notwendig?
|
||||
await RefreshAreaCommitmentList();
|
||||
RefreshInputs();
|
||||
}
|
||||
|
||||
private async Task RefreshAreaCommitmentListQuery() {
|
||||
Contract? contract = (Contract)ContractList.SelectedItem;
|
||||
|
||||
if (contract == null) {
|
||||
AreaCommitmentList.ItemsSource = null;
|
||||
return;
|
||||
}
|
||||
List<AreaCom> areaComs = await Context.AreaCommitments.Where(a => a.MgNr == Member.MgNr).OrderBy(a => a.FbNr).ToListAsync();
|
||||
|
||||
List<AreaComParcel> parcels = (await Context.AreaCommitments.FindAsync(contract.VNr)).Parcels.ToList();
|
||||
|
||||
AreaCommitmentList.ItemsSource = parcels;
|
||||
if (parcels.Count == 1)
|
||||
ControlUtils.RenewItemsSource(AreaCommitmentList, areaComs, i => (i as AreaCom)?.FbNr);
|
||||
if (areaComs.Count == 1)
|
||||
AreaCommitmentList.SelectedIndex = 0;
|
||||
|
||||
RefreshInputs();
|
||||
}
|
||||
|
||||
private void RefreshInputs(bool validate = false) {
|
||||
ClearInputStates();
|
||||
Contract? c = (Contract)ContractList.SelectedItem;
|
||||
AreaComParcel? a = (AreaComParcel)AreaCommitmentList.SelectedItem;
|
||||
|
||||
if (c != null) {
|
||||
DeleteContractButton.IsEnabled = true;
|
||||
NewAreaCommitmentButton.IsEnabled = true;
|
||||
} else {
|
||||
DeleteContractButton.IsEnabled = false;
|
||||
NewAreaCommitmentButton.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (a != null) {
|
||||
if (AreaCommitmentList.SelectedItem is AreaCom a) {
|
||||
EditAreaCommitmentButton.IsEnabled = true;
|
||||
DeleteAreaCommitmentButton.IsEnabled = true;
|
||||
FillInputs(a);
|
||||
} else {
|
||||
EditAreaCommitmentButton.IsEnabled = false;
|
||||
DeleteAreaCommitmentButton.IsEnabled = false;
|
||||
ClearInputs();
|
||||
MgNrInput.Text = "";
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
ClearInputs(validate);
|
||||
ClearInputStates();
|
||||
}
|
||||
if (!validate) ClearInputStates();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void FillInputs(AreaComParcel a) {
|
||||
private void FillInputs(AreaCom a) {
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
|
||||
VNrInput.Text = a.VNr.ToString();
|
||||
MgNrInput.Text = a.AreaCom.Contract.MgNr.ToString();
|
||||
YearFromInput.Text = a.AreaCom.Contract.YearFrom.ToString();
|
||||
YearToInput.Text = a.AreaCom.Contract.YearTo.ToString();
|
||||
FbNrInput.Text = a.FbNr.ToString();
|
||||
MgNrInput.Text = a.MgNr.ToString();
|
||||
YearFromInput.Text = a.YearFrom.ToString();
|
||||
YearToInput.Text = a.YearTo.ToString();
|
||||
|
||||
KgInput.SelectedItem = a.Kg.Kg;
|
||||
KgInput.SelectedItem = a.Kg.AtKg;
|
||||
RdInput.SelectedItem = a.Rd;
|
||||
GstNrInput.Text = a.GstNr;
|
||||
AreaInput.Text = a.Area.ToString();
|
||||
|
||||
SortInput.SelectedItem = a.AreaCom.WineVar;
|
||||
// FIXME
|
||||
//AttrInput.SelectedItem = a.WineAttr;
|
||||
CultInput.SelectedItem = a.AreaCom.WineCult;
|
||||
AreaComTypeInput.SelectedItem = a.AreaComType;
|
||||
WineCultivationInput.SelectedItem = a.WineCult;
|
||||
|
||||
FillOriginalValues();
|
||||
FinishInputFilling();
|
||||
}
|
||||
|
||||
private async void InitInputs() {
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
|
||||
FbNrInput.Text = (await Context.NextFbNr()).ToString();
|
||||
MgNrInput.Text = Member.MgNr.ToString();
|
||||
|
||||
SetDefaultValue(FbNrInput);
|
||||
ValidateRequiredInputs();
|
||||
}
|
||||
|
||||
protected override async Task RenewContext() {
|
||||
await base.RenewContext();
|
||||
ControlUtils.RenewItemsSource(KgInput, await Context.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync(), i => (i as AT_Kg)?.KgNr);
|
||||
ControlUtils.RenewItemsSource(AreaComTypeInput, await Context.AreaCommitmentTypes.OrderBy(v => v.VtrgId).ToListAsync(), i => (i as AreaComType)?.VtrgId);
|
||||
ControlUtils.RenewItemsSource(WineCultivationInput, await Context.WineCultivations.OrderBy(c => c.Name).ToListAsync(), i => (i as WineCult)?.CultId);
|
||||
await RefreshAreaCommitmentList();
|
||||
}
|
||||
|
||||
private void NewAreaCommitmentButton_Click(object sender, RoutedEventArgs evt) {
|
||||
IsCreating = true;
|
||||
AreaCommitmentList.IsEnabled = false;
|
||||
AreaCommitmentList.SelectedItem = null;
|
||||
ContractList.IsEnabled = false;
|
||||
HideAreaCommitmentNewEditDeleteButtons();
|
||||
ShowAreaCommitmentSaveResetCancelButtons();
|
||||
DisableContractNewDeleteButtons();
|
||||
UnlockInputs();
|
||||
VNrInput.IsReadOnly = true;
|
||||
YearFromInput.IsReadOnly = true;
|
||||
YearToInput.IsReadOnly = true;
|
||||
InitInputs();
|
||||
}
|
||||
|
||||
@@ -146,21 +120,19 @@ namespace Elwig.Windows {
|
||||
|
||||
IsEditing = true;
|
||||
AreaCommitmentList.IsEnabled = false;
|
||||
ContractList.IsEnabled = false;
|
||||
|
||||
HideAreaCommitmentNewEditDeleteButtons();
|
||||
ShowAreaCommitmentSaveResetCancelButtons();
|
||||
DisableContractNewDeleteButtons();
|
||||
UnlockInputs();
|
||||
}
|
||||
|
||||
private async void DeleteAreaCommitmentButton_Click(object sender, RoutedEventArgs evt) {
|
||||
AreaComParcel a = (AreaComParcel)AreaCommitmentList.SelectedItem;
|
||||
AreaCom a = (AreaCom)AreaCommitmentList.SelectedItem;
|
||||
if (a == null) return;
|
||||
|
||||
var r = MessageBox.Show(
|
||||
$"Soll die Parzelle {a.GstNr} ({a.Area} m²) wirklich unwiderruflich gelöscht werden?",
|
||||
"Parzelle löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
|
||||
$"Soll die Flächenbindung {a.GstNr} ({a.Area} m²) wirklich unwiderruflich gelöscht werden?",
|
||||
"Flächenbindung löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
|
||||
if (r == MessageBoxResult.Yes) {
|
||||
Context.Remove(a);
|
||||
Context.SaveChanges();
|
||||
@@ -168,86 +140,44 @@ namespace Elwig.Windows {
|
||||
}
|
||||
}
|
||||
|
||||
private void NewContractButton_Click(object sender, RoutedEventArgs evt) {
|
||||
IsCreating = true;
|
||||
ContractList.IsEnabled = false;
|
||||
ContractList.SelectedItem = null;
|
||||
AreaCommitmentList.IsEnabled = false;
|
||||
AreaCommitmentList.SelectedItem = null;
|
||||
HideContractNewDeleteButtons();
|
||||
ShowContractSaveCancelButtons();
|
||||
DisableAreaCommitmentNewEditDeleteButtons();
|
||||
UnlockInputs();
|
||||
InitInputs();
|
||||
}
|
||||
|
||||
private async void DeleteContractButton_Click(object sender, RoutedEventArgs evt) {
|
||||
Contract c = (Contract)ContractList.SelectedItem;
|
||||
if (c == null) return;
|
||||
|
||||
var r = MessageBox.Show(
|
||||
$"Soll der Vertrag {c.VNr} und alle enthaltenen Parzellen wirklich unwiderruflich gelöscht werden?",
|
||||
"Vertrag löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
|
||||
if (r == MessageBoxResult.Yes) {
|
||||
Context.Remove(c);
|
||||
Context.SaveChanges();
|
||||
await RefreshContractList();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Contract> UpdateContract(Contract c) {
|
||||
int newVNr = int.Parse(VNrInput.Text);
|
||||
c.MgNr = int.Parse(MgNrInput.Text);
|
||||
c.YearFrom = int.Parse(YearFromInput.Text);
|
||||
c.YearTo = (YearToInput.Text == "") ? null : int.Parse(YearToInput.Text);
|
||||
|
||||
EntityEntry<Contract>? tr = null;
|
||||
try {
|
||||
if (IsEditing) {
|
||||
tr = Context.Update(c);
|
||||
} else if (IsCreating) {
|
||||
c.VNr = newVNr;
|
||||
tr = (await Context.AddAsync(c));
|
||||
}
|
||||
await Context.SaveChangesAsync();
|
||||
|
||||
if (newVNr != c.VNr) {
|
||||
await Context.Database.ExecuteSqlAsync($"UPDATE contract SET vnr = {newVNr} WHERE mgnr = {c.VNr}");
|
||||
await Context.Contracts.LoadAsync();
|
||||
c = await Context.Contracts.FindAsync(newVNr);
|
||||
}
|
||||
} catch (Exception exc) {
|
||||
if (tr != null) await tr.ReloadAsync();
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||
MessageBox.Show(str, "Vertrag aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private async Task<AreaComParcel> UpdateaAreaComParcel(AreaComParcel a) {
|
||||
a.VNr = int.Parse(VNrInput.Text);
|
||||
private async Task<AreaCom> UpdateAreaCom(AreaCom a) {
|
||||
int newFbNr = int.Parse(FbNrInput.Text);
|
||||
a.MgNr = int.Parse(MgNrInput.Text);
|
||||
a.YearFrom = int.Parse(YearFromInput.Text);
|
||||
a.YearTo = (YearToInput.Text == "") ? null : int.Parse(YearToInput.Text);
|
||||
a.KgNr = ((AT_Kg)KgInput.SelectedItem).KgNr;
|
||||
a.RdNr = ((WbRd)RdInput.SelectedItem).RdNr;
|
||||
a.RdNr = RdInput.SelectedItem.GetType() == typeof(NullItem) ? null : ((WbRd)RdInput.SelectedItem).RdNr;
|
||||
a.GstNr = GstNrInput.Text;
|
||||
a.Area = int.Parse(AreaInput.Text);
|
||||
a.AreaCom.SortId = ((WineVar)SortInput.SelectedItem).SortId;
|
||||
// FIXME
|
||||
//a.AttrId = ((WineAttr)AttrInput.SelectedItem).AttrId;
|
||||
a.AreaCom.CultId = ((WineCult)CultInput.SelectedItem).CultId;
|
||||
a.VtrgId = (AreaComTypeInput.SelectedItem as AreaComType)?.VtrgId;
|
||||
a.CultId = (WineCultivationInput.SelectedItem as WineCult)?.CultId;
|
||||
|
||||
EntityEntry<AreaComParcel>? tr = null;
|
||||
EntityEntry<AreaCom>? tr = null;
|
||||
try {
|
||||
if (IsEditing) {
|
||||
tr = Context.Update(a);
|
||||
} else if (IsCreating) {
|
||||
a.FbNr = newFbNr;
|
||||
tr = (await Context.AddAsync(a));
|
||||
} else {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
await Context.SaveChangesAsync();
|
||||
|
||||
if (newFbNr != a.FbNr) {
|
||||
await Context.Database.ExecuteSqlAsync($"UPDATE area_commitment SET fbnr = {newFbNr} WHERE fbnr = {a.FbNr}");
|
||||
tr.State = EntityState.Detached;
|
||||
await Context.SaveChangesAsync();
|
||||
await tr.ReloadAsync();
|
||||
a = await Context.AreaCommitments.FindAsync(newFbNr);
|
||||
}
|
||||
|
||||
} catch (Exception exc) {
|
||||
if (tr != null) await tr.ReloadAsync();
|
||||
if (tr != null) {
|
||||
tr.State = EntityState.Detached;
|
||||
await tr.ReloadAsync();
|
||||
}
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||
MessageBox.Show(str, "Flächenbindung aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
@@ -257,20 +187,14 @@ namespace Elwig.Windows {
|
||||
}
|
||||
|
||||
private async void AreaCommitmentSaveButton_Click(object sender, RoutedEventArgs evt) {
|
||||
Contract c = await UpdateContract((Contract)ContractList.SelectedItem);
|
||||
AreaComParcel a = await UpdateaAreaComParcel(IsEditing ? (AreaComParcel)AreaCommitmentList.SelectedItem : Context.CreateProxy<AreaComParcel>());
|
||||
|
||||
AreaCom a = await UpdateAreaCom(IsEditing ? (AreaCom)AreaCommitmentList.SelectedItem : Context.CreateProxy<AreaCom>());
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
AreaCommitmentList.IsEnabled = true;
|
||||
ContractList.IsEnabled = true;
|
||||
HideAreaCommitmentSaveResetCancelButtons();
|
||||
ShowAreaCommitmentNewEditDeleteButtons();
|
||||
EnableContractNewDeleteButtons();
|
||||
LockInputs();
|
||||
await RefreshContractList();
|
||||
await RefreshAreaCommitmentList();
|
||||
ContractList.SelectedItem = c;
|
||||
AreaCommitmentList.SelectedItem = a;
|
||||
}
|
||||
|
||||
@@ -287,41 +211,8 @@ namespace Elwig.Windows {
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
AreaCommitmentList.IsEnabled = true;
|
||||
ContractList.IsEnabled = true;
|
||||
HideAreaCommitmentSaveResetCancelButtons();
|
||||
ShowAreaCommitmentNewEditDeleteButtons();
|
||||
EnableContractNewDeleteButtons();
|
||||
RefreshInputs();
|
||||
ClearInputStates();
|
||||
LockInputs();
|
||||
}
|
||||
|
||||
private async void ContractSaveButton_Click(object sender, RoutedEventArgs evt) {
|
||||
Contract c = await UpdateContract(Context.CreateProxy<Contract>());
|
||||
AreaComParcel a = await UpdateaAreaComParcel(Context.CreateProxy<AreaComParcel>());
|
||||
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
AreaCommitmentList.IsEnabled = true;
|
||||
ContractList.IsEnabled = true;
|
||||
HideContractSaveCancelButtons();
|
||||
ShowContractNewDeleteButtons();
|
||||
EnableAreaCommitmentNewEditDeleteButtons();
|
||||
LockInputs();
|
||||
await RefreshContractList();
|
||||
await RefreshAreaCommitmentList();
|
||||
ContractList.SelectedItem = c;
|
||||
AreaCommitmentList.SelectedItem = a;
|
||||
}
|
||||
|
||||
private void ContractCancelButton_Click(object sender, RoutedEventArgs evt) {
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
ContractList.IsEnabled = true;
|
||||
AreaCommitmentList.IsEnabled = true;
|
||||
HideContractSaveCancelButtons();
|
||||
ShowContractNewDeleteButtons();
|
||||
EnableAreaCommitmentNewEditDeleteButtons();
|
||||
RefreshInputs();
|
||||
ClearInputStates();
|
||||
LockInputs();
|
||||
@@ -329,27 +220,9 @@ namespace Elwig.Windows {
|
||||
|
||||
override protected void UpdateButtons() {
|
||||
if (!IsEditing && !IsCreating) return;
|
||||
bool ch = HasChanged(), v = IsValid();
|
||||
ContractSaveButton.IsEnabled = (v && ch);
|
||||
bool ch = HasChanged, v = IsValid;
|
||||
AreaCommitmentResetButton.IsEnabled = (ch);
|
||||
AreaCommitmentSaveButton.IsEnabled = (v && ch);
|
||||
}
|
||||
|
||||
private async void InitInputs() {
|
||||
VNrInput.Text = ContractList.SelectedItem == null ? (await Context.NextVNr()).ToString() : ((Contract)ContractList.SelectedItem).VNr.ToString();
|
||||
MgNrInput.Text = member.MgNr.ToString();
|
||||
FillOriginalValues();
|
||||
ValidateRequiredInputs();
|
||||
}
|
||||
|
||||
private void EnableContractNewDeleteButtons() {
|
||||
NewContractButton.IsEnabled = true;
|
||||
DeleteContractButton.IsEnabled = ContractList.SelectedItem != null;
|
||||
}
|
||||
|
||||
private void DisableContractNewDeleteButtons() {
|
||||
NewContractButton.IsEnabled = false;
|
||||
DeleteContractButton.IsEnabled = false;
|
||||
AreaCommitmentSaveButton.IsEnabled = (ch && v);
|
||||
}
|
||||
|
||||
private void DisableAreaCommitmentNewEditDeleteButtons() {
|
||||
@@ -359,37 +232,11 @@ namespace Elwig.Windows {
|
||||
}
|
||||
|
||||
private void EnableAreaCommitmentNewEditDeleteButtons() {
|
||||
NewAreaCommitmentButton.IsEnabled = ContractList.SelectedItem != null;
|
||||
NewAreaCommitmentButton.IsEnabled = true;
|
||||
EditAreaCommitmentButton.IsEnabled = AreaCommitmentList.SelectedItem != null;
|
||||
DeleteAreaCommitmentButton.IsEnabled = AreaCommitmentList.SelectedItem != null;
|
||||
}
|
||||
|
||||
private void ShowContractSaveCancelButtons() {
|
||||
ContractSaveButton.IsEnabled = false;
|
||||
ContractCancelButton.IsEnabled = true;
|
||||
ContractSaveButton.Visibility = Visibility.Visible;
|
||||
ContractCancelButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideContractSaveCancelButtons() {
|
||||
ContractSaveButton.IsEnabled = false;
|
||||
ContractCancelButton.IsEnabled = false;
|
||||
ContractSaveButton.Visibility = Visibility.Hidden;
|
||||
ContractCancelButton.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void ShowContractNewDeleteButtons() {
|
||||
EnableContractNewDeleteButtons();
|
||||
NewContractButton.Visibility = Visibility.Visible;
|
||||
DeleteContractButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideContractNewDeleteButtons() {
|
||||
DisableContractNewDeleteButtons();
|
||||
NewContractButton.Visibility = Visibility.Hidden;
|
||||
DeleteContractButton.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void ShowAreaCommitmentSaveResetCancelButtons() {
|
||||
AreaCommitmentSaveButton.IsEnabled = false;
|
||||
AreaCommitmentResetButton.IsEnabled = false;
|
||||
@@ -422,51 +269,42 @@ namespace Elwig.Windows {
|
||||
DeleteAreaCommitmentButton.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private async void ContractList_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||||
//await RefreshContractListQuery();
|
||||
await RefreshAreaCommitmentList();
|
||||
}
|
||||
|
||||
private void AreaCommitmentList_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||||
RefreshInputs();
|
||||
}
|
||||
|
||||
private void KgInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||||
AT_Kg? curr_kg = (AT_Kg)KgInput.SelectedItem;
|
||||
if (curr_kg != null) {
|
||||
RdInput.ItemsSource = Context.WbRde.Where(r => r.KgNr == curr_kg.KgNr).OrderBy(r => r.Name).ToList();
|
||||
private void AttributesInput_SelectionChanged(object sender, ItemSelectionChangedEventArgs evt) {
|
||||
|
||||
}
|
||||
|
||||
private async void KgInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||||
if (KgInput.SelectedItem is AT_Kg curr_kg) {
|
||||
var rdList = await Context.WbRde.Where(r => r.KgNr == curr_kg.KgNr).OrderBy(r => r.Name).Cast<object>().ToListAsync();
|
||||
rdList.Insert(0, new NullItem());
|
||||
ControlUtils.RenewItemsSource(RdInput, rdList, i => (i as WbRd)?.RdNr);
|
||||
} else {
|
||||
var rdList = new object[] { new NullItem() };
|
||||
ControlUtils.RenewItemsSource(RdInput, rdList, i => (i as WbRd)?.RdNr);
|
||||
}
|
||||
ComboBox_SelectionChanged(sender, evt);
|
||||
}
|
||||
|
||||
protected void InputTextChanged(TextBox input, Func<TextBox, bool, AppDbContext, Contract?, ValidationResult> checker) {
|
||||
InputTextChanged(input, checker(input, SenderIsRequired(input), Context, (Contract)ContractList.SelectedItem));
|
||||
protected void InputTextChanged(TextBox input, Func<TextBox, bool, AppDbContext, AreaCom?, ValidationResult> checker) {
|
||||
InputTextChanged(input, checker(input, SenderIsRequired(input), Context, (AreaCom)AreaCommitmentList.SelectedItem));
|
||||
}
|
||||
|
||||
protected void InputLostFocus(TextBox input, Func<TextBox, bool, AppDbContext, Contract?, ValidationResult> checker, string? msg = null) {
|
||||
InputLostFocus(input, checker(input, SenderIsRequired(input), Context, (Contract)ContractList.SelectedItem), msg);
|
||||
protected void InputLostFocus(TextBox input, Func<TextBox, bool, AppDbContext, AreaCom?, ValidationResult> checker, string? msg = null) {
|
||||
InputLostFocus(input, checker(input, SenderIsRequired(input), Context, (AreaCom)AreaCommitmentList.SelectedItem), msg);
|
||||
}
|
||||
|
||||
private void NumericInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckInteger);
|
||||
private void FbNrInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckFbNr);
|
||||
}
|
||||
|
||||
private void VNrInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckVNr);
|
||||
private void FbNrInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckFbNr);
|
||||
}
|
||||
|
||||
private void VNrInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckVNr);
|
||||
}
|
||||
|
||||
private void YearFromInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckInteger);
|
||||
}
|
||||
|
||||
private void YearToInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckInteger);
|
||||
}
|
||||
|
||||
|
||||
private void GstNrInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckGstNr);
|
||||
}
|
||||
@@ -474,9 +312,5 @@ namespace Elwig.Windows {
|
||||
private void GstNrInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckGstNr);
|
||||
}
|
||||
|
||||
private void AreaInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckInteger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
235
Elwig/Windows/BaseDataWindow.xaml
Normal file
235
Elwig/Windows/BaseDataWindow.xaml
Normal file
@@ -0,0 +1,235 @@
|
||||
<local:AdministrationWindow x:Class="Elwig.Windows.BaseDataWindow"
|
||||
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.Windows"
|
||||
mc:Ignorable="d"
|
||||
Title="Stammdaten - Elwig" Height="500" MinHeight="400" Width="800" MinWidth="800"
|
||||
Loaded="Window_Loaded">
|
||||
<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="ComboBox">
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="9,3"/>
|
||||
<Setter Property="Height" Value="27"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<TabControl Margin="10,10,10,42">
|
||||
<TabItem Header="Mandant">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="130"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="90"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Vollständiger Name:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="0" Margin="10,10,0,10"/>
|
||||
<TextBox x:Name="ClientNameFull" IsEnabled="False"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Stretch" Grid.Column="1" Grid.ColumnSpan="3" Margin="0,10,10,10"/>
|
||||
|
||||
<Label Content="Name:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="0" Margin="10,40,0,10"/>
|
||||
<TextBox x:Name="ClientNameInput"
|
||||
TextChanged="ClientNames_TextChanged"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Stretch" Grid.Column="1" Grid.ColumnSpan="3" Margin="0,40,10,10"/>
|
||||
|
||||
<Label Content="Namenszusatz:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="0" Margin="10,70,0,10"/>
|
||||
<TextBox x:Name="ClientNameSuffixInput"
|
||||
TextChanged="ClientNames_TextChanged"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Stretch" Grid.Column="1" Grid.ColumnSpan="3" Margin="0,70,10,10"/>
|
||||
|
||||
<Label Content="Gesellschaftsform:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="0" Margin="10,100,0,10"/>
|
||||
<TextBox x:Name="ClientNameTypeInput"
|
||||
TextChanged="ClientNames_TextChanged"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Stretch" Grid.Column="1" Margin="0,100,10,10"/>
|
||||
|
||||
<Label Content="Kürzel/Kurzform:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="0" Margin="10,130,0,10"/>
|
||||
<TextBox x:Name="ClientNameTokenInput"
|
||||
TextChanged="TextBox_TextChanged"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="1" Margin="0,130,10,10" Width="70"/>
|
||||
<TextBox x:Name="ClientNameShortInput"
|
||||
TextChanged="TextBox_TextChanged"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Stretch" Grid.Column="1" Margin="75,130,10,10"/>
|
||||
|
||||
<Label Content="Adresse:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="0" Margin="10,160,0,10"/>
|
||||
<TextBox x:Name="ClientAddressInput"
|
||||
TextChanged="TextBox_TextChanged"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Stretch" Grid.Column="1" Margin="0,160,10,10"/>
|
||||
|
||||
<Label Content="PLZ/Ort:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="0" Margin="10,190,0,10"/>
|
||||
<TextBox x:Name="ClientPlzInput"
|
||||
Margin="0,190,0,0" Width="42" Grid.Column="1" HorizontalAlignment="Left"
|
||||
TextChanged="PlzInput_TextChanged" LostFocus="PlzInput_LostFocus"/>
|
||||
<TextBox x:Name="ClientOrtInput" Margin="47,190,10,0" Grid.Column="1"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="IBAN:" Margin="10,220,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="ClientIbanInput" Margin="0,220,10,0" Grid.Column="1"
|
||||
TextChanged="IbanInput_TextChanged" LostFocus="IbanInput_LostFocus"/>
|
||||
|
||||
<Label Content="BIC:" Margin="10,250,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="ClientBicInput" Margin="0,250,10,0" Grid.Column="1"
|
||||
TextChanged="BicInput_TextChanged" LostFocus="BicInput_LostFocus"/>
|
||||
|
||||
<Label Content="UID:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="2" Margin="10,100,0,10"/>
|
||||
<TextBox x:Name="ClientUstIdNrInput"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="3" Margin="0,100,10,10" Width="96"
|
||||
TextChanged="UstIdNrInput_TextChanged" LostFocus="UstIdNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="Betriebs-Nr.:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="2" Margin="10,130,0,10"/>
|
||||
<TextBox x:Name="ClientLfbisNrInput"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="3" Margin="0,130,10,10" Width="64"
|
||||
TextChanged="LfbisNrInput_TextChanged" LostFocus="LfbisNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="Telefon-Nr.:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="2" Margin="10,160,0,10"/>
|
||||
<TextBox x:Name="ClientPhoneNrInput" Margin="0,160,10,10" Grid.Column="3"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="Fax-Nr.:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="2" Margin="10,190,0,10"/>
|
||||
<TextBox x:Name="ClientFaxNrInput" Margin="0,190,10,10" Grid.Column="3"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="E-Mail-Adr.:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="2" Margin="10,220,0,10"/>
|
||||
<TextBox x:Name="ClientEmailAddressInput" Margin="0,220,10,0" Grid.Column="3"
|
||||
TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/>
|
||||
|
||||
<Label Content="Website:"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="2" Margin="10,250,0,10"/>
|
||||
<TextBox x:Name="ClientWebsiteInput" Margin="0,250,10,0" Grid.Column="3"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Header="Zweigstellen">
|
||||
|
||||
</TabItem>
|
||||
<TabItem Header="Sortenattribute">
|
||||
|
||||
</TabItem>
|
||||
<TabItem Header="Bewirtschaftungsarten">
|
||||
|
||||
</TabItem>
|
||||
<TabItem Header="Flächenbindungsverträge">
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Saisons">
|
||||
<Grid>
|
||||
<ListBox x:Name="SeasonList" HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="150" Margin="10,10,10,10"
|
||||
SelectionChanged="SeasonList_SelectionChanged">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding Year}" Width="40"/>
|
||||
<TextBlock Text="{Binding Currency.Name}" Width="60"/>
|
||||
<TextBlock Text="{Binding Precision}" Width="10"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<GroupBox Header="Zu-/Abschläge" Margin="170,150,10,10" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="400"/>
|
||||
<ColumnDefinition Width="70"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListBox x:Name="SeasonModifierList" SelectionChanged="SeasonModifierList_SelectionChanged"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Stretch" Width="350" Margin="10,10,10,10">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding ModId}" Width="30"/>
|
||||
<TextBlock Text="{Binding Name}" Width="200" Margin="0,0,10,0"/>
|
||||
<TextBlock Text="{Binding ValueStr}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<Button x:Name="SeasonModifierUpButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="0,0,0,0" IsEnabled="False"
|
||||
Click="SeasonModifierUpButton_Click"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Left" Width="25" Height="25" Margin="365,0,0,90"/>
|
||||
<Button x:Name="SeasonModifierDownButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="0,2,0,0" IsEnabled="False"
|
||||
Click="SeasonModifierDownButton_Click"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Left" Width="25" Height="25" Margin="365,0,0,30"/>
|
||||
<Button x:Name="SeasonModifierAddButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False"
|
||||
Click="SeasonModifierAddButton_Click"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Left" Width="25" Height="25" Margin="365,30,0,0"/>
|
||||
<Button x:Name="SeasonModifierDeleteButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False"
|
||||
Click="SeasonModifierDeleteButton_Click"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Left" Width="25" Height="25" Margin="365,90,0,0"/>
|
||||
|
||||
<Label Content="ID:" Grid.Column="1" Margin="10,10,10,10"/>
|
||||
<TextBox x:Name="SeasonModifierIdInput" Grid.Column="2" Margin="0,10,10,10" Width="50" HorizontalAlignment="Left"
|
||||
TextChanged="SeasonModifierIdInput_TextChanged"/>
|
||||
|
||||
<Label Content="Name:" Grid.Column="1" Margin="10,40,10,10"/>
|
||||
<TextBox x:Name="SeasonModifierNameInput" Grid.Column="2" Margin="0,40,10,10"
|
||||
TextChanged="SeasonModifierNameInput_TextChanged"/>
|
||||
|
||||
<Label Content="Relativ:" Grid.Column="1" Margin="10,70,10,10"/>
|
||||
<TextBox x:Name="SeasonModifierRelInput" Grid.Column="2" Margin="0,70,10,10"
|
||||
TextChanged="SeasonModifierRelInput_TextChanged"/>
|
||||
|
||||
<Label Content="Absolut:" Grid.Column="1" Margin="10,100,10,10"/>
|
||||
<TextBox x:Name="SeasonModifierAbsInput" Grid.Column="2" Margin="0,100,10,10"
|
||||
TextChanged="SeasonModifierAbsInput_TextChanged"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Header="Parameter">
|
||||
|
||||
</TabItem>
|
||||
<TabItem Header="Textelemente">
|
||||
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
<Button x:Name="EditButton" Content="Bearbeiten"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,10" Width="120"
|
||||
Click="EditButton_Click"/>
|
||||
<Button x:Name="SaveButton" Content="Speichern" IsEnabled="False"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,250,10" Width="120"
|
||||
Click="SaveButton_Click"/>
|
||||
<Button x:Name="ResetButton" Content="Zurücksetzen" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,10" Width="120"
|
||||
Click="ResetButton_Click"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" IsEnabled="False" IsCancel="True"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="250,0,0,10" Width="120"
|
||||
Click="CancelButton_Click"/>
|
||||
</Grid>
|
||||
</local:AdministrationWindow>
|
343
Elwig/Windows/BaseDataWindow.xaml.cs
Normal file
343
Elwig/Windows/BaseDataWindow.xaml.cs
Normal file
@@ -0,0 +1,343 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class BaseDataWindow : AdministrationWindow {
|
||||
|
||||
private Dictionary<string, string?>? Modifiers = null;
|
||||
private Dictionary<Modifier, string>? ModifierIds = null;
|
||||
private ObservableCollection<Modifier>? ModifierList = null;
|
||||
private bool ModifiersChanged = false;
|
||||
private bool ModifierUpdate = false;
|
||||
|
||||
public BaseDataWindow() {
|
||||
InitializeComponent();
|
||||
RequiredInputs = new Control[] {
|
||||
ClientNameInput, ClientNameTypeInput, ClientNameTokenInput, ClientNameShortInput,
|
||||
ClientAddressInput, ClientPlzInput, ClientOrtInput,
|
||||
};
|
||||
ExemptInputs = new Control[] {
|
||||
ClientNameFull,
|
||||
SeasonModifierIdInput, SeasonModifierNameInput, SeasonModifierRelInput, SeasonModifierAbsInput,
|
||||
};
|
||||
}
|
||||
|
||||
new protected void LockInputs() {
|
||||
base.LockInputs();
|
||||
SeasonModifierIdInput.IsReadOnly = true;
|
||||
SeasonModifierNameInput.IsReadOnly = true;
|
||||
SeasonModifierRelInput.IsReadOnly = true;
|
||||
SeasonModifierAbsInput.IsReadOnly = true;
|
||||
}
|
||||
|
||||
new protected void UnlockInputs() {
|
||||
base.UnlockInputs();
|
||||
SeasonModifierIdInput.IsReadOnly = false;
|
||||
SeasonModifierNameInput.IsReadOnly = false;
|
||||
SeasonModifierRelInput.IsReadOnly = false;
|
||||
SeasonModifierAbsInput.IsReadOnly = false;
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
||||
LockInputs();
|
||||
FillInputs(App.Client);
|
||||
}
|
||||
|
||||
protected override async Task RenewContext() {
|
||||
await base.RenewContext();
|
||||
ControlUtils.RenewItemsSource(SeasonList, await Context.Seasons.OrderByDescending(s => s.Year).ToListAsync(), s => (s as Season)?.Year, null, ControlUtils.RenewSourceDefault.First);
|
||||
var year = (SeasonList.SelectedItem as Season)?.Year;
|
||||
ControlUtils.RenewItemsSource(SeasonModifierList, await Context.Modifiers.Where(m => m.Year == year).OrderBy(m => m.Ordering).ToListAsync(), m => (m as Modifier)?.ModId);
|
||||
}
|
||||
|
||||
protected override void UpdateButtons() {
|
||||
if (!IsEditing && !IsCreating) return;
|
||||
bool ch = ModifiersChanged || HasChanged, v = IsValid;
|
||||
CancelButton.IsEnabled = true;
|
||||
ResetButton.IsEnabled = ch;
|
||||
SaveButton.IsEnabled = ch && v;
|
||||
SeasonModifierUpButton.IsEnabled = SeasonModifierList.SelectedIndex >= 1;
|
||||
SeasonModifierDownButton.IsEnabled = SeasonModifierList.SelectedIndex != -1 && SeasonModifierList.SelectedIndex < (ModifierList?.Count - 1 ?? 0);
|
||||
SeasonModifierAddButton.IsEnabled = true;
|
||||
SeasonModifierDeleteButton.IsEnabled = SeasonModifierList.SelectedIndex != -1;
|
||||
}
|
||||
|
||||
private void ModifiersInitEditing() {
|
||||
var year = (SeasonList.SelectedItem as Season)?.Year;
|
||||
Context.ChangeTracker.Clear();
|
||||
ModifierList = new(Context.Modifiers.Where(m => m.Year == year).OrderBy(m => m.Ordering).ToList());
|
||||
Modifiers = ModifierList.ToDictionary(m => m.ModId, m => m.ModId);
|
||||
ModifierIds = ModifierList.ToDictionary(m => m, m => m.ModId);
|
||||
ControlUtils.RenewItemsSource(SeasonModifierList, ModifierList, m => (m as Modifier)?.ModId);
|
||||
}
|
||||
|
||||
private void ModifiersFinishEditing() {
|
||||
var year = (SeasonList.SelectedItem as Season)?.Year;
|
||||
ControlUtils.RenewItemsSource(SeasonModifierList, Context.Modifiers.Where(m => m.Year == year).OrderBy(m => m.Ordering).ToList(), m => (m as Modifier)?.ModId);
|
||||
ModifierList = null;
|
||||
Modifiers = null;
|
||||
ModifierIds = null;
|
||||
ModifiersChanged = false;
|
||||
|
||||
SeasonModifierUpButton.IsEnabled = false;
|
||||
SeasonModifierDownButton.IsEnabled = false;
|
||||
SeasonModifierAddButton.IsEnabled = false;
|
||||
SeasonModifierDeleteButton.IsEnabled = false;
|
||||
}
|
||||
|
||||
private async Task ModifiersSave() {
|
||||
if (!ModifiersChanged || ModifierList == null || Modifiers == null || ModifierIds == null) return;
|
||||
int i = 0;
|
||||
foreach (var mod in ModifierList) mod.Ordering = ++i;
|
||||
|
||||
var year = (SeasonList.SelectedItem as Season)?.Year;
|
||||
foreach (var (modid, _) in Modifiers.Where(m => m.Value == null)) {
|
||||
Context.Remove(Context.Modifiers.Find(new object?[] { year, modid }));
|
||||
}
|
||||
foreach (var (mod, old) in ModifierIds) {
|
||||
mod.ModId = old;
|
||||
}
|
||||
foreach (var (old, modid) in Modifiers.Where(m => m.Value != null)) {
|
||||
Context.Update(Context.Modifiers.Find(new object?[] { year, old }));
|
||||
}
|
||||
await Context.SaveChangesAsync();
|
||||
|
||||
foreach (var (old, modid) in Modifiers.Where(m => m.Value != null)) {
|
||||
await Context.Database.ExecuteSqlAsync($"UPDATE modifier SET modid = {modid} WHERE (year, modid) = ({year}, {old})");
|
||||
}
|
||||
await Context.SaveChangesAsync();
|
||||
|
||||
foreach (var mod in ModifierList.Where(m => !ModifierIds.ContainsKey(m))) {
|
||||
await Context.AddAsync(mod);
|
||||
}
|
||||
await Context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private void EditButton_Click(object sender, RoutedEventArgs evt) {
|
||||
IsEditing = true;
|
||||
EditButton.Visibility = Visibility.Hidden;
|
||||
ResetButton.Visibility = Visibility.Visible;
|
||||
|
||||
ModifiersInitEditing();
|
||||
UnlockInputs();
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs evt) {
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
EditButton.Visibility = Visibility.Visible;
|
||||
ResetButton.Visibility = Visibility.Hidden;
|
||||
CancelButton.IsEnabled = false;
|
||||
SaveButton.IsEnabled = false;
|
||||
ResetButton.IsEnabled = false;
|
||||
ModifiersFinishEditing();
|
||||
|
||||
ClearInputStates();
|
||||
FillInputs(App.Client);
|
||||
LockInputs();
|
||||
}
|
||||
|
||||
private void ResetButton_Click(object sender, RoutedEventArgs evt) {
|
||||
ModifiersChanged = false;
|
||||
ModifiersInitEditing();
|
||||
ClearInputStates();
|
||||
FillInputs(App.Client);
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private async void SaveButton_Click(object sender, RoutedEventArgs evt) {
|
||||
try {
|
||||
await UpdateClientParameters(App.Client);
|
||||
await ModifiersSave();
|
||||
} catch (Exception exc) {
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||
MessageBox.Show(str, "Stammdaten aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
EditButton.Visibility = Visibility.Visible;
|
||||
ResetButton.Visibility = Visibility.Hidden;
|
||||
CancelButton.IsEnabled = false;
|
||||
SaveButton.IsEnabled = false;
|
||||
ResetButton.IsEnabled = false;
|
||||
ModifiersFinishEditing();
|
||||
|
||||
ClearInputStates();
|
||||
FillInputs(App.Client);
|
||||
LockInputs();
|
||||
}
|
||||
|
||||
private void FillInputs(ClientParameters p) {
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
|
||||
ClientNameInput.Text = p.Name;
|
||||
ClientNameSuffixInput.Text = p.NameSuffix;
|
||||
ClientNameTypeInput.Text = p.NameType;
|
||||
ClientNameTokenInput.Text = p.NameToken;
|
||||
ClientNameShortInput.Text = p.NameShort;
|
||||
ClientAddressInput.Text = p.Address;
|
||||
ClientPlzInput.Text = p.Plz.ToString();
|
||||
ClientOrtInput.Text = p.Ort;
|
||||
ClientIbanInput.Text = p.Iban;
|
||||
ClientBicInput.Text = p.Bic;
|
||||
ClientUstIdNrInput.Text = p.UstIdNr;
|
||||
ClientLfbisNrInput.Text = p.LfbisNr;
|
||||
ClientPhoneNrInput.Text = p.PhoneNr;
|
||||
ClientFaxNrInput.Text = p.FaxNr;
|
||||
ClientEmailAddressInput.Text = p.EmailAddress;
|
||||
ClientWebsiteInput.Text = p.Website;
|
||||
|
||||
FinishInputFilling();
|
||||
}
|
||||
|
||||
private async Task UpdateClientParameters(ClientParameters p) {
|
||||
p.Name = ClientNameInput.Text;
|
||||
p.NameSuffix = ClientNameSuffixInput.Text.Length > 0 ? ClientNameSuffixInput.Text : null;
|
||||
p.NameType = ClientNameTypeInput.Text;
|
||||
p.NameToken = ClientNameTokenInput.Text;
|
||||
p.NameShort = ClientNameShortInput.Text;
|
||||
p.Address = ClientAddressInput.Text;
|
||||
p.Plz = int.Parse(ClientPlzInput.Text);
|
||||
p.Ort = ClientOrtInput.Text;
|
||||
p.Iban = ClientIbanInput.Text.Length > 0 ? ClientIbanInput.Text.Replace(" ", "") : null;
|
||||
p.Bic = ClientBicInput.Text.Length > 0 ? ClientBicInput.Text : null;
|
||||
p.UstIdNr = ClientUstIdNrInput.Text.Length > 0 ? ClientUstIdNrInput.Text : null;
|
||||
p.LfbisNr = ClientLfbisNrInput.Text.Length > 0 ? ClientLfbisNrInput.Text : null;
|
||||
p.PhoneNr = ClientPhoneNrInput.Text.Length > 0 ? ClientPhoneNrInput.Text : null;
|
||||
p.FaxNr = ClientFaxNrInput.Text.Length > 0 ? ClientFaxNrInput.Text : null;
|
||||
p.EmailAddress = ClientEmailAddressInput.Text.Length > 0 ? ClientEmailAddressInput.Text : null;
|
||||
p.Website = ClientWebsiteInput.Text.Length > 0 ? ClientWebsiteInput.Text : null;
|
||||
|
||||
await p.UpdateValues();
|
||||
}
|
||||
|
||||
private void SeasonModifierUpButton_Click(object sender, RoutedEventArgs evt) {
|
||||
if (ModifierList == null) return;
|
||||
ModifiersChanged = true;
|
||||
var idx = SeasonModifierList.SelectedIndex;
|
||||
var item = ModifierList[idx];
|
||||
ModifierList.RemoveAt(idx);
|
||||
idx--;
|
||||
ModifierList.Insert(idx, item);
|
||||
SeasonModifierList.SelectedIndex = idx;
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void SeasonModifierDownButton_Click(object sender, RoutedEventArgs evt) {
|
||||
if (ModifierList == null) return;
|
||||
ModifiersChanged = true;
|
||||
var idx = SeasonModifierList.SelectedIndex;
|
||||
var item = ModifierList[idx];
|
||||
ModifierList.RemoveAt(idx);
|
||||
idx++;
|
||||
ModifierList.Insert(idx, item);
|
||||
SeasonModifierList.SelectedIndex = idx;
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void SeasonModifierAddButton_Click(object sender, RoutedEventArgs evt) {
|
||||
if (ModifierList == null || SeasonList.SelectedItem is not Season s) return;
|
||||
ModifiersChanged = true;
|
||||
var idx = (SeasonModifierList.SelectedIndex != -1) ? SeasonModifierList.SelectedIndex + 1 : ModifierList.Count;
|
||||
var item = Context.CreateProxy<Modifier>();
|
||||
item.Year = s.Year;
|
||||
ModifierList.Insert(idx, item);
|
||||
SeasonModifierList.SelectedIndex = idx;
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void SeasonModifierDeleteButton_Click(object sender, RoutedEventArgs evt) {
|
||||
if (ModifierList == null || Modifiers == null) return;
|
||||
ModifiersChanged = true;
|
||||
var idx = SeasonModifierList.SelectedIndex;
|
||||
var item = ModifierList[idx];
|
||||
Modifiers[item.ModId] = null;
|
||||
ModifierList.RemoveAt(idx);
|
||||
SeasonModifierList.SelectedIndex = idx < ModifierList.Count ? idx : idx - 1;
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
|
||||
private void ClientNames_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
var suffix = ClientNameSuffixInput.Text.Length > 0 ? ClientNameSuffixInput.Text : null;
|
||||
ClientNameFull.Text = $"{ClientNameInput.Text}{(suffix != null ? $", {suffix}," : "")} {ClientNameTypeInput.Text}";
|
||||
TextBox_TextChanged(sender, evt);
|
||||
}
|
||||
|
||||
private async void SeasonList_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||||
var year = (SeasonList.SelectedItem as Season)?.Year;
|
||||
SeasonModifierList.ItemsSource = await Context.Modifiers.Where(m => m.Year == year).OrderBy(m => m.Ordering).ToListAsync();
|
||||
}
|
||||
|
||||
private void SeasonModifierList_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||||
UpdateButtons();
|
||||
ModifierUpdate = true;
|
||||
if (SeasonModifierList.SelectedItem is not Modifier mod) {
|
||||
SeasonModifierIdInput.Text = "";
|
||||
SeasonModifierNameInput.Text = "";
|
||||
SeasonModifierRelInput.Text = "";
|
||||
SeasonModifierAbsInput.Text = "";
|
||||
} else {
|
||||
SeasonModifierIdInput.Text = mod.ModId;
|
||||
SeasonModifierNameInput.Text = mod.Name;
|
||||
SeasonModifierRelInput.Text = (mod.Rel * 100)?.ToString();
|
||||
SeasonModifierAbsInput.Text = mod.Abs?.ToString();
|
||||
}
|
||||
ModifierUpdate = false;
|
||||
}
|
||||
|
||||
private void SeasonModifierIdInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod || Modifiers == null || ModifierIds == null) return;
|
||||
ModifiersChanged = ModifiersChanged || (SeasonModifierIdInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.ModId ?? "");
|
||||
if (ModifierUpdate) return;
|
||||
var old = ModifierIds.GetValueOrDefault(mod);
|
||||
var id = SeasonModifierIdInput.Text ?? "";
|
||||
if (old != null) Modifiers[old] = id;
|
||||
mod.ModId = id;
|
||||
CollectionViewSource.GetDefaultView(ModifierList).Refresh();
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void SeasonModifierNameInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod) return;
|
||||
ModifiersChanged = ModifiersChanged || (SeasonModifierNameInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Name ?? "");
|
||||
if (ModifierUpdate) return;
|
||||
mod.Name = SeasonModifierNameInput.Text ?? "";
|
||||
CollectionViewSource.GetDefaultView(ModifierList).Refresh();
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void SeasonModifierRelInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod) return;
|
||||
ModifiersChanged = ModifiersChanged || (SeasonModifierRelInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Rel?.ToString() ?? "");
|
||||
if (ModifierUpdate) return;
|
||||
mod.Rel = decimal.TryParse(SeasonModifierRelInput.Text, out var v) ? v / 100 : null;
|
||||
if (mod.Rel != null) SeasonModifierAbsInput.Text = "";
|
||||
CollectionViewSource.GetDefaultView(ModifierList).Refresh();
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void SeasonModifierAbsInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod) return;
|
||||
ModifiersChanged = ModifiersChanged || (SeasonModifierAbsInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Abs?.ToString() ?? "");
|
||||
if (ModifierUpdate) return;
|
||||
mod.Abs = decimal.TryParse(SeasonModifierAbsInput.Text, out var v) ? v : null;
|
||||
if (mod.Abs != null) SeasonModifierRelInput.Text = "";
|
||||
CollectionViewSource.GetDefaultView(ModifierList).Refresh();
|
||||
UpdateButtons();
|
||||
}
|
||||
}
|
||||
}
|
188
Elwig/Windows/ChartWindow.xaml
Normal file
188
Elwig/Windows/ChartWindow.xaml
Normal file
@@ -0,0 +1,188 @@
|
||||
<local:AdministrationWindow x:Class="Elwig.Windows.ChartWindow"
|
||||
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.Windows"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
xmlns:ScottPlot="clr-namespace:ScottPlot;assembly=ScottPlot.WPF"
|
||||
mc:Ignorable="d"
|
||||
Title="Auszahlung - Elwig" Height="700" Width="1500"
|
||||
Loaded="Window_Loaded">
|
||||
|
||||
<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="IsReadOnly" Value="True"/>
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="TextWrapping" Value="NoWrap"/>
|
||||
</Style>
|
||||
<Style TargetType="ComboBox">
|
||||
<Setter Property="IsEnabled" Value="False"/>
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="9,3"/>
|
||||
<Setter Property="Height" Value="27"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="19"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="330"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="200"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid Grid.Row="1" Margin="5,0,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="42"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<DataGrid x:Name="GraphList" AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single"
|
||||
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False"
|
||||
SelectionChanged="GraphList_SelectionChanged"
|
||||
Margin="5,15,5,0" Grid.Row="0" FontSize="14" Grid.ColumnSpan="3">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Nr." Binding="{Binding Num}" Width="40">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style>
|
||||
<Setter Property="TextBlock.TextWrapping" Value="Wrap" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Header="Typ" Binding="{Binding Type}" Width="40"/>
|
||||
<DataGridTextColumn Header="Angewandte Verträge" Binding="{Binding Contracts}" Width="4*"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<Button x:Name="NewButton" Content="Neu"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="NewButton_Click"/>
|
||||
<Button x:Name="EditButton" Content="Bearbeiten" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="EditButton_Click"/>
|
||||
<Button x:Name="DeleteButton" Content="Löschen" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="DeleteButton_Click"/>
|
||||
|
||||
<Button x:Name="SaveButton" Content="Speichern" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="SaveButton_Click"/>
|
||||
<Button x:Name="ResetButton" Content="Zurücksetzen" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="ResetButton_Click"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" IsEnabled="False" Visibility="Hidden" IsCancel="True"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="CancelButton_Click"/>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1" Grid.Column="1">
|
||||
<ScottPlot:WpfPlot x:Name="OechslePricePlot" MouseMove="OechslePricePlot_MouseMove" MouseDown="OechslePricePlot_MouseDown" IsEnabled="False"/>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="1" Grid.Column="2" Margin="0,0,5,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="120"/>
|
||||
<RowDefinition Height="120"/>
|
||||
<RowDefinition Height="210"/>
|
||||
<RowDefinition Height="110"/>
|
||||
<RowDefinition Height="42"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox Header="Graph" Grid.Row="0" Margin="0,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="85"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Nummer:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="GraphNumberInput" Grid.Column="1" HorizontalAlignment="Left" Margin="0,10,0,0" Text="" Width="90" TextChanged="GraphNumberInput_TextChanged" LostFocus="GraphNumberInput_LostFocus"/>
|
||||
|
||||
<Label Content="Typ:" Margin="10,45,0,0" Grid.Column="0"/>
|
||||
<RadioButton x:Name="OechsleGraphType_Input" GroupName="GraphType" Grid.Column="1" Margin="0,45,0,0">Oechsle</RadioButton>
|
||||
<RadioButton x:Name="KmwGraphType_Input" GroupName="GraphType" Grid.Column="1" Margin="0,60,0,0">KMW</RadioButton>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Datenpunkt" Grid.Row="1" Margin="0,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="85"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Oechsle:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="OechsleInput" Grid.Column="1" HorizontalAlignment="Left" Margin="0,10,0,0" Text="" Width="90" TextChanged="OechsleInput_TextChanged" LostFocus="OechsleInput_LostFocus"/>
|
||||
|
||||
<Label Content="Preis pro kg:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="PriceInput" Grid.Column="1" HorizontalAlignment="Left" Margin="0,40,0,0" Text="" Width="90" TextChanged="PriceInput_TextChanged" LostFocus="PriceInput_LostFocus"/>
|
||||
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Aktionen" Grid.Row="2" Margin="0,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="LeftFlatButton" Content="Links flach" Click="LeftFlatButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="10,10,10,10"/>
|
||||
|
||||
<Button x:Name="RightFlatButton" Content="Rechts flach" Click="RightFlatButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="10,50,10,10"/>
|
||||
|
||||
<Button x:Name="InterpolateButton" Content="Interpolieren" Click="InterpolateButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="10,90,10,10"/>
|
||||
|
||||
<Button x:Name="LinearIncreaseButton" Content="Linear wachsen" Click="LinearIncreaseButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="10,130,10,10"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Optionen" Grid.Row="3" Margin="0,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<CheckBox x:Name="FreeZoomInput" Content="Freier Zoom" IsEnabled="False"
|
||||
Checked="FreeZoomInput_Changed" Unchecked="FreeZoomInput_Changed"
|
||||
HorizontalAlignment="Left" Margin="10,10,10,0" VerticalAlignment="Top"/>
|
||||
|
||||
<CheckBox x:Name="GradationLinesInput" Content="Gradationslinien anzeigen" IsEnabled="False"
|
||||
Checked="GradationLinesInput_Changed" Unchecked="GradationLinesInput_Changed"
|
||||
HorizontalAlignment="Left" Margin="10,30,10,0" VerticalAlignment="Top" IsChecked="True"/>
|
||||
|
||||
<CheckBox x:Name="TooltipInput" Content="Tooltips anzeigen" IsEnabled="False"
|
||||
HorizontalAlignment="Left" Margin="10,50,10,0" VerticalAlignment="Top" IsChecked="True"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</local:AdministrationWindow>
|
750
Elwig/Windows/ChartWindow.xaml.cs
Normal file
750
Elwig/Windows/ChartWindow.xaml.cs
Normal file
@@ -0,0 +1,750 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ScottPlot;
|
||||
using ScottPlot.Plottable;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class ChartWindow : AdministrationWindow {
|
||||
|
||||
private readonly int Year = 2021;
|
||||
private readonly int AvNr = 2;
|
||||
|
||||
private ScatterPlot OechslePricePlotScatter;
|
||||
private MarkerPlot HighlightedPoint;
|
||||
private MarkerPlot PrimaryMarkedPoint;
|
||||
private MarkerPlot SecondaryMarkedPoint;
|
||||
private Tooltip Tooltip;
|
||||
|
||||
private int LastHighlightedIndex = -1;
|
||||
private int HighlightedIndex = -1;
|
||||
private int PrimaryMarkedPointIndex = -1;
|
||||
private int SecondaryMarkedPointIndex = -1;
|
||||
private bool HoverChanged = false;
|
||||
private bool HoverActive = false;
|
||||
|
||||
private const int MinOechsle = 50;
|
||||
private const int MaxOechsle = 140;
|
||||
|
||||
private Graph? Graph;
|
||||
|
||||
public ChartWindow() {
|
||||
InitializeComponent();
|
||||
|
||||
ExemptInputs = new Control[] {
|
||||
GraphList, OechsleInput, PriceInput, FreeZoomInput, GradationLinesInput, TooltipInput
|
||||
};
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
||||
LockInputs();
|
||||
OechslePricePlot.IsEnabled = false;
|
||||
}
|
||||
|
||||
private async Task RefreshGraphList() {
|
||||
await Context.PaymentVariants.LoadAsync();
|
||||
await RefreshGraphListQuery();
|
||||
}
|
||||
|
||||
private async Task RefreshGraphListQuery(bool updateSort = false) {
|
||||
List<PaymentVar> paymentVars = await Context.PaymentVariants.Where(p => p.Year == Year && p.AvNr == AvNr).ToListAsync();
|
||||
|
||||
if (paymentVars.Count != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
PaymentVar paymentVar = paymentVars[0];
|
||||
var data = JToken.Parse(paymentVar.Data);
|
||||
|
||||
var auszahlungsSorten = data["AuszahlungSorten"];
|
||||
if (auszahlungsSorten == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var Graphs = auszahlungsSorten["Kurven"];
|
||||
|
||||
if (Graphs == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Graph> GraphsList = new();
|
||||
|
||||
int i = 1;
|
||||
foreach (var graph in Graphs) {
|
||||
GraphsList.Add(new Graph("Oe", i, graph, ParseContracts(auszahlungsSorten, i - 1), 50, 140));
|
||||
i++;
|
||||
}
|
||||
|
||||
ControlUtils.RenewItemsSource(GraphList, GraphsList, g => (g as Graph)?.Num);
|
||||
if (GraphsList.Count == 1) {
|
||||
GraphList.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
RefreshInputs();
|
||||
}
|
||||
|
||||
private String ParseContracts(JToken auszahlungsSorten, int num) {
|
||||
List<string> contracts = new();
|
||||
|
||||
foreach (var sorte in auszahlungsSorten.Children().OfType<JToken>()) {
|
||||
if (((JProperty)sorte).Name == "Kurven") {
|
||||
continue;
|
||||
}
|
||||
foreach (var attribut in sorte.Values().OfType<JToken>()) {
|
||||
foreach (var bindung in attribut.Values().OfType<JProperty>()) {
|
||||
if ((int)(bindung).Value == num) {
|
||||
contracts.Add($"{((JProperty)sorte).Name}/{((JProperty)attribut).Name}/{bindung.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join("\n", contracts.ToArray());
|
||||
}
|
||||
|
||||
private async Task<bool> RemoveGraph(int num) {
|
||||
List<PaymentVar> paymentVars = await Context.PaymentVariants.Where(p => p.Year == Year && p.AvNr == AvNr).ToListAsync();
|
||||
|
||||
if (paymentVars.Count != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PaymentVar paymentVar = paymentVars[0];
|
||||
var data = JToken.Parse(paymentVar.Data);
|
||||
|
||||
var auszahlungsSorten = data["AuszahlungSorten"];
|
||||
if (auszahlungsSorten == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var Graphs = auszahlungsSorten["Kurven"];
|
||||
|
||||
if (Graphs == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
foreach (var graph in Graphs) {
|
||||
if (i == num) {
|
||||
graph.Remove();
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
foreach (var sorte in auszahlungsSorten.Children().OfType<JToken>()) {
|
||||
if (((JProperty)sorte).Name == "Kurven") {
|
||||
continue;
|
||||
}
|
||||
foreach (var attribut in sorte.Values().OfType<JToken>()) {
|
||||
List<JProperty> itemsToRemove = new();
|
||||
foreach (var bindung in attribut.Values().OfType<JProperty>()) {
|
||||
if ((int)bindung.Value == num - 1) {
|
||||
itemsToRemove.Add(bindung);
|
||||
} else if ((int)bindung.Value > num - 1) {
|
||||
bindung.Value = (int)bindung.Value - 1;
|
||||
}
|
||||
}
|
||||
itemsToRemove.ForEach(i => i.Remove());
|
||||
}
|
||||
}
|
||||
|
||||
EntityEntry<PaymentVar>? tr = null;
|
||||
try {
|
||||
paymentVar.Data = data.ToString();
|
||||
tr = Context.Update(paymentVar);
|
||||
|
||||
await Context.SaveChangesAsync();
|
||||
} catch (Exception exc) {
|
||||
if (tr != null) await tr.ReloadAsync();
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message;
|
||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||
MessageBox.Show(str, "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void RefreshInputs(bool validate = false) {
|
||||
ResetPlot();
|
||||
ClearInputStates();
|
||||
if (GraphList.SelectedItem is Graph g) {
|
||||
EditButton.IsEnabled = true;
|
||||
DeleteButton.IsEnabled = true;
|
||||
EnableOptionButtons();
|
||||
FillInputs(g);
|
||||
} else {
|
||||
EditButton.IsEnabled = false;
|
||||
DeleteButton.IsEnabled = false;
|
||||
DisableOptionButtons();
|
||||
ClearOriginalValues();
|
||||
ClearInputs(validate);
|
||||
ClearInputStates();
|
||||
}
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void FillInputs(Graph g) {
|
||||
ClearOriginalValues();
|
||||
|
||||
Graph = (Graph)g.Clone();
|
||||
|
||||
GraphNumberInput.Text = Graph.Num.ToString();
|
||||
if (Graph.Type == "oe") {
|
||||
OechsleGraphType_Input.IsChecked = true;
|
||||
} else if (Graph.Type == "kmw") {
|
||||
KmwGraphType_Input.IsChecked = true;
|
||||
}
|
||||
|
||||
InitPlot();
|
||||
OechslePricePlot.IsEnabled = true;
|
||||
|
||||
FinishInputFilling();
|
||||
}
|
||||
|
||||
private void InitInputs() {
|
||||
GraphNumberInput.Text = (GraphList.Items.Count + 1).ToString();
|
||||
OechsleGraphType_Input.IsChecked = true;
|
||||
FinishInputFilling();
|
||||
}
|
||||
|
||||
protected override async Task RenewContext() {
|
||||
await base.RenewContext();
|
||||
await RefreshGraphList();
|
||||
}
|
||||
|
||||
private void InitPlot() {
|
||||
OechslePricePlotScatter = OechslePricePlot.Plot.AddScatter(Graph.DataX, Graph.DataY);
|
||||
|
||||
OechslePricePlotScatter.LineColor = Color.Blue;
|
||||
OechslePricePlotScatter.MarkerColor = Color.Blue;
|
||||
OechslePricePlotScatter.MarkerSize = 9;
|
||||
|
||||
//OechslePricePlot.Plot.XAxis.ManualTickSpacing(1);
|
||||
OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1);
|
||||
OechslePricePlot.Plot.SetAxisLimits(MinOechsle - 1, MaxOechsle + 1, -0.1, 2);
|
||||
|
||||
OechslePricePlot.Plot.Layout(padding: 0);
|
||||
OechslePricePlot.Plot.XAxis2.Layout(padding: 0);
|
||||
OechslePricePlot.Plot.YAxis.Layout(padding: 0);
|
||||
OechslePricePlot.Plot.YAxis2.Layout(padding: 0);
|
||||
|
||||
HighlightedPoint = OechslePricePlot.Plot.AddPoint(0, 0);
|
||||
HighlightedPoint.Color = Color.Red;
|
||||
HighlightedPoint.MarkerSize = 10;
|
||||
HighlightedPoint.MarkerShape = MarkerShape.openCircle;
|
||||
HighlightedPoint.IsVisible = false;
|
||||
|
||||
PrimaryMarkedPoint = OechslePricePlot.Plot.AddPoint(0, 0);
|
||||
PrimaryMarkedPoint.Color = Color.Red;
|
||||
PrimaryMarkedPoint.MarkerSize = 6;
|
||||
PrimaryMarkedPoint.MarkerShape = MarkerShape.filledCircle;
|
||||
PrimaryMarkedPoint.IsVisible = false;
|
||||
|
||||
SecondaryMarkedPoint = OechslePricePlot.Plot.AddPoint(0, 0);
|
||||
SecondaryMarkedPoint.Color = Color.Red;
|
||||
SecondaryMarkedPoint.MarkerSize = 6;
|
||||
SecondaryMarkedPoint.MarkerShape = MarkerShape.filledCircle;
|
||||
SecondaryMarkedPoint.IsVisible = false;
|
||||
|
||||
OechslePricePlot.Refresh();
|
||||
|
||||
RefreshFreeZoom();
|
||||
RefreshGradationLines();
|
||||
}
|
||||
|
||||
private void ResetPlot() {
|
||||
Graph = null;
|
||||
PrimaryMarkedPointIndex = -1;
|
||||
OechslePricePlot.Plot.Remove(OechslePricePlotScatter);
|
||||
OechslePricePlot.Plot.Clear();
|
||||
OechslePricePlot.Reset();
|
||||
OechslePricePlot.Refresh();
|
||||
}
|
||||
|
||||
private void ChangeMarker(MarkerPlot point, bool visible, double x = 0, double y = 0) {
|
||||
point.X = x;
|
||||
point.Y = y;
|
||||
point.IsVisible = visible;
|
||||
}
|
||||
|
||||
private void FlattenGraph(int begin, int end, double value) {
|
||||
for (int i = begin; i <= end; i++) {
|
||||
Graph.DataY[i] = value;
|
||||
}
|
||||
OechslePricePlot.Render();
|
||||
}
|
||||
|
||||
private void LinearIncreaseGraph(int begin, int end, double inc) {
|
||||
for (int i = begin; i < end; i++) {
|
||||
Graph.DataY[i + 1] = Graph.DataY[i] + inc;
|
||||
}
|
||||
OechslePricePlot.Render();
|
||||
}
|
||||
|
||||
private void EnableActionButtons() {
|
||||
LeftFlatButton.IsEnabled = true;
|
||||
RightFlatButton.IsEnabled = true;
|
||||
LinearIncreaseButton.IsEnabled = true;
|
||||
}
|
||||
|
||||
private void DisableActionButtons() {
|
||||
LeftFlatButton.IsEnabled = false;
|
||||
RightFlatButton.IsEnabled = false;
|
||||
InterpolateButton.IsEnabled = false;
|
||||
LinearIncreaseButton.IsEnabled = false;
|
||||
}
|
||||
|
||||
private void FreeZoomInput_Changed(object sender, RoutedEventArgs evt) {
|
||||
RefreshFreeZoom();
|
||||
}
|
||||
|
||||
private void RefreshFreeZoom() {
|
||||
if (FreeZoomInput.IsChecked == true) {
|
||||
UnlockZoom();
|
||||
} else {
|
||||
LockZoom();
|
||||
}
|
||||
OechslePricePlot.Refresh();
|
||||
}
|
||||
|
||||
private void LockZoom() {
|
||||
OechslePricePlot.Plot.XAxis.SetBoundary(MinOechsle - 1, MaxOechsle + 1);
|
||||
OechslePricePlot.Plot.YAxis.SetBoundary(-0.1, 2);
|
||||
OechslePricePlot.Plot.XAxis.SetZoomOutLimit(MaxOechsle - MinOechsle + 2);
|
||||
OechslePricePlot.Plot.YAxis.SetZoomOutLimit(2.1);
|
||||
OechslePricePlot.Plot.SetAxisLimits(MinOechsle - 1, MaxOechsle + 1, -0.1, 2);
|
||||
}
|
||||
|
||||
private void UnlockZoom() {
|
||||
OechslePricePlot.Plot.XAxis.SetBoundary();
|
||||
OechslePricePlot.Plot.YAxis.SetBoundary();
|
||||
OechslePricePlot.Plot.XAxis.SetZoomOutLimit((MaxOechsle - MinOechsle) * 1.5);
|
||||
OechslePricePlot.Plot.YAxis.SetZoomOutLimit(3.5);
|
||||
}
|
||||
|
||||
private void EnableOptionButtons() {
|
||||
FreeZoomInput.IsEnabled = true;
|
||||
GradationLinesInput.IsEnabled = true;
|
||||
TooltipInput.IsEnabled = true;
|
||||
}
|
||||
|
||||
private void DisableOptionButtons() {
|
||||
FreeZoomInput.IsEnabled = false;
|
||||
GradationLinesInput.IsEnabled = false;
|
||||
TooltipInput.IsEnabled = false;
|
||||
}
|
||||
|
||||
private void GradationLinesInput_Changed(object sender, RoutedEventArgs evt) {
|
||||
RefreshGradationLines();
|
||||
}
|
||||
|
||||
private void RefreshGradationLines() {
|
||||
if (GradationLinesInput.IsChecked == true) {
|
||||
ShowGradationLines();
|
||||
ShowLegend();
|
||||
} else {
|
||||
HideGradationLines();
|
||||
HideLegend();
|
||||
}
|
||||
OechslePricePlot.Refresh();
|
||||
}
|
||||
|
||||
private void ShowGradationLines() {
|
||||
OechslePricePlot.Plot.AddVerticalLine(68, Color.Red, 2, label: "68 Oechsle (LDW)");
|
||||
OechslePricePlot.Plot.AddVerticalLine(73, Color.Orange, 2, label: "73 Oechsle (QUW)");
|
||||
OechslePricePlot.Plot.AddVerticalLine(84, Color.Green, 2, label: "84 Oechsle (KAB)");
|
||||
}
|
||||
|
||||
private void HideGradationLines() {
|
||||
OechslePricePlot.Plot.Clear(typeof(VLine));
|
||||
}
|
||||
|
||||
private void ShowLegend() {
|
||||
OechslePricePlot.Plot.Legend(true, Alignment.UpperRight);
|
||||
}
|
||||
|
||||
private void HideLegend() {
|
||||
OechslePricePlot.Plot.Legend(false, Alignment.UpperRight);
|
||||
}
|
||||
|
||||
private void OechsleInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
IntegerInput_TextChanged(sender, evt);
|
||||
|
||||
bool success = int.TryParse(OechsleInput.Text, out int oechsle);
|
||||
|
||||
SecondaryMarkedPointIndex = -1;
|
||||
ChangeMarker(SecondaryMarkedPoint, false);
|
||||
|
||||
if (success) {
|
||||
if (oechsle >= MinOechsle && oechsle <= MaxOechsle) {
|
||||
PrimaryMarkedPointIndex = oechsle - MinOechsle;
|
||||
ChangeMarker(PrimaryMarkedPoint, true, Graph.DataX[PrimaryMarkedPointIndex], Graph.DataY[PrimaryMarkedPointIndex]);
|
||||
|
||||
PriceInput.Text = Graph.DataY[PrimaryMarkedPointIndex].ToString();
|
||||
|
||||
EnableActionButtons();
|
||||
OechslePricePlot.Render();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryMarkedPointIndex = -1;
|
||||
ChangeMarker(PrimaryMarkedPoint, false);
|
||||
DisableActionButtons();
|
||||
PriceInput.Text = "";
|
||||
OechslePricePlot.Render();
|
||||
}
|
||||
|
||||
private void PriceInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
if (PrimaryMarkedPointIndex != -1) {
|
||||
bool success = Double.TryParse(PriceInput.Text, out double price);
|
||||
|
||||
if (success) {
|
||||
Graph.DataY[PrimaryMarkedPointIndex] = price;
|
||||
PrimaryMarkedPoint.Y = price;
|
||||
SaveButton.IsEnabled = true;
|
||||
ResetButton.IsEnabled = true;
|
||||
OechslePricePlot.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LeftFlatButton_Click(object sender, RoutedEventArgs evt) {
|
||||
if (PrimaryMarkedPointIndex == -1) {
|
||||
return;
|
||||
}
|
||||
FlattenGraph(0, PrimaryMarkedPointIndex, Graph.DataY[PrimaryMarkedPointIndex]);
|
||||
}
|
||||
|
||||
private void RightFlatButton_Click(object sender, RoutedEventArgs evt) {
|
||||
if (PrimaryMarkedPointIndex == -1) {
|
||||
return;
|
||||
}
|
||||
FlattenGraph(PrimaryMarkedPointIndex, Graph.DataY.Length - 1, Graph.DataY[PrimaryMarkedPointIndex]);
|
||||
}
|
||||
|
||||
private void InterpolateButton_Click(object sender, RoutedEventArgs evt) {
|
||||
int steps = Math.Abs(PrimaryMarkedPointIndex - SecondaryMarkedPointIndex);
|
||||
if (PrimaryMarkedPointIndex == -1 || SecondaryMarkedPointIndex == -1 || steps < 2) {
|
||||
return;
|
||||
}
|
||||
var (lowIndex, highIndex) = PrimaryMarkedPointIndex < SecondaryMarkedPointIndex ? (PrimaryMarkedPointIndex, SecondaryMarkedPointIndex): (SecondaryMarkedPointIndex, PrimaryMarkedPointIndex);
|
||||
|
||||
double step = (Graph.DataY[highIndex] - Graph.DataY[lowIndex]) / steps;
|
||||
|
||||
for (int i = lowIndex; i < highIndex - 1; i++) {
|
||||
Graph.DataY[i + 1] = Math.Round(Graph.DataY[i] + step, 4); // TODO richtig runden
|
||||
}
|
||||
}
|
||||
|
||||
private void LinearIncreaseButton_Click(object sender, RoutedEventArgs e) {
|
||||
if (PrimaryMarkedPointIndex == -1) {
|
||||
return;
|
||||
}
|
||||
double? priceIncrease = Utils.ShowLinearPriceIncreaseDialog();
|
||||
if (priceIncrease == null) {
|
||||
return;
|
||||
}
|
||||
LinearIncreaseGraph(PrimaryMarkedPointIndex, Graph.DataY.Length - 1, priceIncrease.Value);
|
||||
}
|
||||
|
||||
private void OechslePricePlot_MouseDown(object sender, MouseEventArgs e) {
|
||||
if (!IsCreating && GraphList.SelectedItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (HoverActive) {
|
||||
if ((IsEditing || IsCreating) && Keyboard.IsKeyDown(Key.LeftCtrl)) {
|
||||
if (PrimaryMarkedPointIndex == -1) {
|
||||
return;
|
||||
}
|
||||
SecondaryMarkedPointIndex = HighlightedIndex;
|
||||
ChangeMarker(SecondaryMarkedPoint, true, Graph.DataX[SecondaryMarkedPointIndex], Graph.DataY[SecondaryMarkedPointIndex]);
|
||||
|
||||
InterpolateButton.IsEnabled = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PrimaryMarkedPointIndex = HighlightedIndex;
|
||||
ChangeMarker(PrimaryMarkedPoint, true, Graph.DataX[PrimaryMarkedPointIndex], Graph.DataY[PrimaryMarkedPointIndex]);
|
||||
|
||||
OechsleInput.Text = Graph.DataX[HighlightedIndex].ToString();
|
||||
PriceInput.Text = Graph.DataY[HighlightedIndex].ToString();
|
||||
|
||||
if (IsEditing || IsCreating) {
|
||||
EnableActionButtons();
|
||||
}
|
||||
} else {
|
||||
PrimaryMarkedPointIndex = -1;
|
||||
SecondaryMarkedPointIndex = -1;
|
||||
ChangeMarker(PrimaryMarkedPoint, false);
|
||||
ChangeMarker(SecondaryMarkedPoint, false);
|
||||
|
||||
OechsleInput.Text = "";
|
||||
PriceInput.Text = "";
|
||||
|
||||
DisableActionButtons();
|
||||
}
|
||||
}
|
||||
|
||||
private void OechslePricePlot_MouseMove(object sender, MouseEventArgs e) {
|
||||
if (!IsCreating && GraphList.SelectedItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
(double mouseCoordX, double mouseCoordY) = OechslePricePlot.GetMouseCoordinates();
|
||||
double xyRatio = OechslePricePlot.Plot.XAxis.Dims.PxPerUnit / OechslePricePlot.Plot.YAxis.Dims.PxPerUnit;
|
||||
(double pointX, double pointY, int pointIndex) = OechslePricePlotScatter.GetPointNearest(mouseCoordX, mouseCoordY, xyRatio);
|
||||
|
||||
(double mousePixelX, double mousePixelY) = OechslePricePlot.GetMousePixel();
|
||||
(double pointPixelX, double pointPixelY) = OechslePricePlot.Plot.GetPixel(pointX, pointY);
|
||||
|
||||
HighlightedIndex = LastHighlightedIndex;
|
||||
|
||||
if (Math.Abs(mousePixelX - pointPixelX) < 3 && Math.Abs(mousePixelY - pointPixelY) < 3) {
|
||||
ChangeMarker(HighlightedPoint, true, pointX, pointY);
|
||||
HighlightedPoint.IsVisible = true;
|
||||
HoverChanged = true ^ HoverActive;
|
||||
HoverActive = true;
|
||||
} else {
|
||||
ChangeMarker(HighlightedPoint, false);
|
||||
HoverChanged= false ^ HoverActive;
|
||||
HoverActive= false;
|
||||
OechslePricePlot.Plot.Remove(Tooltip);
|
||||
OechslePricePlot.Render();
|
||||
}
|
||||
|
||||
if (LastHighlightedIndex != HighlightedIndex || HoverChanged) {
|
||||
OechslePricePlot.Plot.Remove(Tooltip);
|
||||
if (TooltipInput.IsChecked == true) {
|
||||
Tooltip = OechslePricePlot.Plot.AddTooltip($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, 4)})", pointX, pointY);
|
||||
}
|
||||
LastHighlightedIndex = pointIndex;
|
||||
HoverChanged = false;
|
||||
OechslePricePlot.Render();
|
||||
}
|
||||
}
|
||||
|
||||
override protected void UpdateButtons() {
|
||||
if (!IsEditing && !IsCreating) return;
|
||||
bool ch = HasChanged, v = IsValid;
|
||||
}
|
||||
|
||||
private void DisableNewEditDeleteButtons() {
|
||||
NewButton.IsEnabled = false;
|
||||
EditButton.IsEnabled = false;
|
||||
DeleteButton.IsEnabled = false;
|
||||
}
|
||||
|
||||
private void EnableNewEditDeleteButtons() {
|
||||
NewButton.IsEnabled = true;
|
||||
EditButton.IsEnabled = GraphList.SelectedItem != null;
|
||||
DeleteButton.IsEnabled = GraphList.SelectedItem != null;
|
||||
}
|
||||
|
||||
private void ShowSaveResetCancelButtons() {
|
||||
SaveButton.IsEnabled = false;
|
||||
ResetButton.IsEnabled = false;
|
||||
CancelButton.IsEnabled = true;
|
||||
SaveButton.Visibility = Visibility.Visible;
|
||||
ResetButton.Visibility = Visibility.Visible;
|
||||
CancelButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideSaveResetCancelButtons() {
|
||||
SaveButton.IsEnabled = false;
|
||||
ResetButton.IsEnabled = false;
|
||||
CancelButton.IsEnabled = false;
|
||||
SaveButton.Visibility = Visibility.Hidden;
|
||||
ResetButton.Visibility = Visibility.Hidden;
|
||||
CancelButton.Visibility = Visibility.Hidden;
|
||||
}
|
||||
private void ShowNewEditDeleteButtons() {
|
||||
EnableNewEditDeleteButtons();
|
||||
NewButton.Visibility = Visibility.Visible;
|
||||
EditButton.Visibility = Visibility.Visible;
|
||||
DeleteButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideNewEditDeleteButtons() {
|
||||
DisableNewEditDeleteButtons();
|
||||
NewButton.Visibility = Visibility.Hidden;
|
||||
EditButton.Visibility = Visibility.Hidden;
|
||||
DeleteButton.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void NewButton_Click(object sender, RoutedEventArgs e) {
|
||||
IsCreating = true;
|
||||
GraphList.IsEnabled = false;
|
||||
GraphList.SelectedItem = null;
|
||||
HideNewEditDeleteButtons();
|
||||
ShowSaveResetCancelButtons();
|
||||
UnlockInputs();
|
||||
PriceInput.IsReadOnly = false;
|
||||
OechsleInput.IsReadOnly = false;
|
||||
InitInputs();
|
||||
FillInputs(new Graph(GraphList.Items.Count + 1, MinOechsle, MaxOechsle));
|
||||
EnableOptionButtons();
|
||||
}
|
||||
|
||||
private void EditButton_Click(object sender, RoutedEventArgs e) {
|
||||
if (GraphList.SelectedItem == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
IsEditing = true;
|
||||
GraphList.IsEnabled = false;
|
||||
|
||||
HideNewEditDeleteButtons();
|
||||
ShowSaveResetCancelButtons();
|
||||
UnlockInputs();
|
||||
PriceInput.IsReadOnly = false;
|
||||
OechsleInput.IsReadOnly = false;
|
||||
if (PrimaryMarkedPointIndex != -1) EnableActionButtons();
|
||||
}
|
||||
|
||||
private async void DeleteButton_Click(object sender, RoutedEventArgs e) {
|
||||
Graph g = (Graph)GraphList.SelectedItem;
|
||||
if (g == null) return;
|
||||
|
||||
var r = MessageBox.Show(
|
||||
$"Soll der Graph {g.Num} (verwendet in folgenden Verträgen: {g.Contracts}) wirklich unwiderruflich gelöscht werden?",
|
||||
"Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
|
||||
if (r == MessageBoxResult.Yes) {
|
||||
bool success = await RemoveGraph(g.Num);
|
||||
if (!success) {
|
||||
MessageBox.Show("Der Graph konnte nicht gelöscht werden", "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
await RefreshGraphList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async void SaveButton_Click(object sender, RoutedEventArgs e) {
|
||||
int? index = await UpdateGraph(Graph);
|
||||
if (index == null) {
|
||||
MessageBox.Show("Der Graph konnte nicht gespeichert werden", "Graph speichern", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
GraphList.IsEnabled = true;
|
||||
HideSaveResetCancelButtons();
|
||||
ShowNewEditDeleteButtons();
|
||||
LockInputs();
|
||||
PriceInput.IsReadOnly = true;
|
||||
OechsleInput.IsReadOnly = true;
|
||||
await RefreshGraphList();
|
||||
GraphList.SelectedIndex = index.Value;
|
||||
}
|
||||
|
||||
private async Task<int?> UpdateGraph(Graph g) {
|
||||
List<PaymentVar> paymentVars = await Context.PaymentVariants.Where(p => p.Year == Year && p.AvNr == AvNr).ToListAsync();
|
||||
|
||||
if (paymentVars.Count != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PaymentVar paymentVar = paymentVars[0];
|
||||
var data = JToken.Parse(paymentVar.Data);
|
||||
|
||||
var auszahlungsSorten = data["AuszahlungSorten"];
|
||||
if (auszahlungsSorten == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var Graphs = auszahlungsSorten["Kurven"];
|
||||
|
||||
if (Graphs == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (IsEditing) {
|
||||
((JArray)Graphs)[g.Num - 1] = g.ToJson();
|
||||
} else if(IsCreating) {
|
||||
((JArray)Graphs).Add(g.ToJson());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
EntityEntry<PaymentVar>? tr = null;
|
||||
try {
|
||||
paymentVar.Data = data.ToString();
|
||||
tr = Context.Update(paymentVar);
|
||||
|
||||
await Context.SaveChangesAsync();
|
||||
} catch (Exception exc) {
|
||||
if (tr != null) await tr.ReloadAsync();
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message;
|
||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||
MessageBox.Show(str, "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
return g.Num - 1;
|
||||
}
|
||||
|
||||
private void ResetButton_Click(object sender, RoutedEventArgs e) {
|
||||
if (IsEditing) {
|
||||
RefreshInputs();
|
||||
} else if (IsCreating) {
|
||||
InitInputs();
|
||||
}
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs e) {
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
GraphList.IsEnabled = true;
|
||||
HideSaveResetCancelButtons();
|
||||
ShowNewEditDeleteButtons();
|
||||
DisableActionButtons();
|
||||
RefreshInputs();
|
||||
PriceInput.Text = "";
|
||||
OechsleInput.Text = "";
|
||||
ClearInputStates();
|
||||
LockInputs();
|
||||
PriceInput.IsReadOnly = true;
|
||||
OechsleInput.IsReadOnly = true;
|
||||
}
|
||||
|
||||
private void GraphList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
|
||||
RefreshInputs();
|
||||
|
||||
//var x = OechslePricePlot.Plot.GetPlottables().OfType<ScatterPlot>();
|
||||
//MessageBox.Show($"SelectionChanged\nLength: {x.ToList().Count}, Ys: {string.Join(", ", ((ScatterPlot)x.First()).Ys)}");
|
||||
}
|
||||
|
||||
private void PriceInput_LostFocus(object sender, RoutedEventArgs e) {
|
||||
|
||||
}
|
||||
|
||||
private void OechsleInput_LostFocus(object sender, RoutedEventArgs e) {
|
||||
|
||||
}
|
||||
|
||||
private void GraphNumberInput_TextChanged(object sender, TextChangedEventArgs e) {
|
||||
|
||||
}
|
||||
|
||||
private void GraphNumberInput_LostFocus(object sender, RoutedEventArgs e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,19 +1,43 @@
|
||||
using Elwig.Helpers;
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public abstract class ContextWindow : Window {
|
||||
|
||||
protected readonly AppDbContext Context;
|
||||
protected AppDbContext Context { get; private set; }
|
||||
protected bool LockContext { get; set; } = false;
|
||||
|
||||
private readonly DispatcherTimer ContextRenewTimer;
|
||||
private static readonly int ContextRenewSec = 10;
|
||||
|
||||
public ContextWindow() : base() {
|
||||
ContextRenewTimer = new DispatcherTimer();
|
||||
ContextRenewTimer.Tick += new EventHandler(OnRenewContext);
|
||||
ContextRenewTimer.Interval = new TimeSpan(0, 0, ContextRenewSec);
|
||||
ContextRenewTimer.Start();
|
||||
Context = new();
|
||||
Loaded += OnLoaded;
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs evt) {
|
||||
private void OnRenewContext(object? sender, EventArgs evt) {
|
||||
if (LockContext || !Context.HasBackendChanged) return;
|
||||
Context.Dispose();
|
||||
base.OnClosing(evt);
|
||||
Context = new();
|
||||
RenewContext().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs evt) {
|
||||
RenewContext().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs evt) {
|
||||
base.OnClosed(evt);
|
||||
Context.Dispose();
|
||||
}
|
||||
|
||||
abstract protected Task RenewContext();
|
||||
}
|
||||
}
|
||||
|
427
Elwig/Windows/DeliveryAdminWindow.xaml
Normal file
427
Elwig/Windows/DeliveryAdminWindow.xaml
Normal file
@@ -0,0 +1,427 @@
|
||||
<local:AdministrationWindow x:Class="Elwig.Windows.DeliveryAdminWindow"
|
||||
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.Windows"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
Title="Lieferungsverwaltung - Elwig" Height="720" Width="1100" MinHeight="700" MinWidth="1000"
|
||||
Loaded="Window_Loaded">
|
||||
<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="ComboBox">
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style TargetType="xctk:CheckComboBox">
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="9,3"/>
|
||||
<Setter Property="Height" Value="27"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="19"/>
|
||||
<RowDefinition Height="0.625*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="24"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" MinWidth="400"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Menu Grid.ColumnSpan="3" BorderThickness="0,0,0,1" BorderBrush="LightGray" Background="White">
|
||||
<MenuItem Header="Lieferung">
|
||||
</MenuItem>
|
||||
<MenuItem Header="Drucken">
|
||||
<MenuItem x:Name="Menu_Print_ShowDeliveryNote" Header="Lieferschein anzeigen" IsEnabled="False"
|
||||
Click="Menu_Print_ShowDeliveryNote_Click"/>
|
||||
<MenuItem x:Name="Menu_Print_PrintDeliveryNote" Header="Lieferschein drucken" IsEnabled="False"
|
||||
Click="Menu_Print_PrintDeliveryNote_Click"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Exportieren">
|
||||
<MenuItem x:Name="Menu_Export_Bki" Header="Traubentransportscheinliste (BKI)"
|
||||
Click="Menu_Export_Bki_Click"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Werkzeuge">
|
||||
<MenuItem Header="Alle Lieferscheine überprüfen"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<Grid Grid.RowSpan="4" Grid.Row="1" Margin="5,0,5,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="42"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="42"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox x:Name="SearchInput" Grid.ColumnSpan="3" Margin="5,10,161,0" IsReadOnly="False"
|
||||
TextChanged="SearchInput_TextChanged"/>
|
||||
<xctk:IntegerUpDown Name="SeasonInput" Grid.ColumnSpan="3" Height="25" Width="56" FontSize="14" Minimum="1000" Maximum="9999"
|
||||
Margin="0,10,100,0" VerticalAlignment="Top" HorizontalAlignment="Right"
|
||||
ValueChanged="SeasonInput_ValueChanged"/>
|
||||
<CheckBox x:Name="TodayOnlyInput" Content="Nur heute"
|
||||
HorizontalAlignment="Right" Margin="0,7,18,0" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Checked="TodayOnlyInput_Changed" Unchecked="TodayOnlyInput_Changed"/>
|
||||
<CheckBox x:Name="AllSeasonsInput" Content="Jede Saison" IsEnabled="False"
|
||||
HorizontalAlignment="Right" Margin="0,24,10,0" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Checked="AllSeasonsInput_Changed" Unchecked="AllSeasonsInput_Changed"/>
|
||||
<DataGrid x:Name="DeliveryList" AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single"
|
||||
SelectionChanged="DeliveryList_SelectionChanged"
|
||||
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False"
|
||||
Margin="5,0,5,0" Grid.Row="1" FontSize="14" Grid.ColumnSpan="3">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="MgNr." Binding="{Binding MgNr}" Width="70"/>
|
||||
<DataGridTextColumn Header="Datum" Binding="{Binding Date, StringFormat='dd.MM.yy'}" Width="70"/>
|
||||
<DataGridTextColumn Header="Zeit" Binding="{Binding Time, StringFormat='HH:mm'}" Width="70"/>
|
||||
<DataGridTextColumn Header="Sorte" Binding="{Binding SortIdString}" Width="60"/>
|
||||
<DataGridTextColumn Header="Gewicht" Binding="{Binding Weight, StringFormat='{}{0:N0} kg'}" Width="70">
|
||||
<DataGridTextColumn.CellStyle>
|
||||
<Style>
|
||||
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.CellStyle>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<Button x:Name="FinishButton" Content="Abschließen" IsEnabled="False" Visibility="Hidden"
|
||||
ToolTip="Übernahme abschließen und Lieferschein drucken"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="FinishButton_Click"/>
|
||||
<Button x:Name="NewDeliveryPartButton" Content="Neue Teil-Lfrg." IsEnabled="False" Visibility="Hidden"
|
||||
ToolTip="Neue Teillieferung auf selben Lieferschein hinzufügen"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="NewDeliveryPartButton_Click"/>
|
||||
<Button x:Name="CancelCreatingButton" Content="Abbrechen" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="CancelCreatingButton_Click"/>
|
||||
|
||||
<Button x:Name="NewDeliveryButton" Content="Neu" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="NewDeliveryButton_Click"/>
|
||||
<Button x:Name="AbwertenButton" Content="Abwerten" IsEnabled="False"
|
||||
ToolTip="Ausgewählte Teillieferung vollständig oder teilweise abwerten"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="AbwertenButton_Click"/>
|
||||
<Button x:Name="EditDeliveryButton" Content="Bearbeiten" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="EditDeliveryButton_Click"/>
|
||||
<Button x:Name="DeleteDeliveryButton" Content="Löschen" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="DeleteDeliveryButton_Click"/>
|
||||
|
||||
<Button x:Name="SaveButton" Content="Speichern" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="SaveButton_Click"/>
|
||||
<Button x:Name="ResetButton" Content="Zurücksetzen" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="ResetButton_Click"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" IsEnabled="False" Visibility="Hidden" IsCancel="True"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="CancelButton_Click"/>
|
||||
</Grid>
|
||||
|
||||
<GroupBox Header="Mitglied" Grid.Column="1" Grid.Row="1" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="70"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Mitglied:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="MgNrInput" Width="48" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="MgNrInput_TextChanged" LostFocus="MgNrInput_LostFocus"/>
|
||||
<ComboBox x:Name="MemberInput" Grid.Column="1" Margin="53,10,10,10" IsEditable="True"
|
||||
ItemTemplate="{StaticResource MemberAdminNameTemplate}" TextSearch.TextPath="AdministrativeName"
|
||||
SelectionChanged="MemberInput_SelectionChanged"/>
|
||||
|
||||
<Label Content="Wohnort:" Margin="10,38,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="MemberAddressField" Grid.Column="1" Margin="0,40,10,10" FontSize="12" Height="22"
|
||||
IsReadOnly="True" IsTabStop="False"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Lieferung" Grid.Column="1" Grid.Row="2" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="LieferscheinNr.:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="LsNrInput" Width="126" Grid.Column="1" HorizontalAlignment="Left" Margin="0,10,0,0"
|
||||
IsReadOnly="True" IsTabStop="False"/>
|
||||
|
||||
<Label Content="Datum/Uhrzeit:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="DateInput" Width="77" Grid.Column="1" HorizontalAlignment="Left" Margin="0,40,0,0"
|
||||
IsReadOnly="True" IsTabStop="False"
|
||||
TextChanged="DateInput_TextChanged"/>
|
||||
<TextBox x:Name="TimeInput" Width="44" Grid.Column="1" HorizontalAlignment="Left" Margin="82,40,0,0"
|
||||
IsReadOnly="True" IsTabStop="False"/>
|
||||
|
||||
<Label Content="Zweigstelle:" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="BranchInput" Width="126" Margin="0,70,10,0" Grid.Column="1" HorizontalAlignment="Left"
|
||||
IsEnabled="False"
|
||||
DisplayMemberPath="Name" TextSearch.TextPath="Name"/>
|
||||
|
||||
<Label Content="Anmerkung:" Margin="10,100,0,10"/>
|
||||
<TextBox x:Name="CommentInput" Grid.Column="1" Margin="0,100,10,10"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Sorte" Grid.Column="2" Grid.Row="1" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="70"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Sorte:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="SortIdInput" Width="36" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left"
|
||||
TextChanged="SortIdInput_TextChanged" LostFocus="SortIdInput_LostFocus"/>
|
||||
<ComboBox x:Name="WineVarietyInput" Grid.Row="1" Grid.Column="1" Margin="41,10,10,10"
|
||||
ItemTemplate="{StaticResource WineVarietyTemplate}" TextSearch.TextPath="Name"
|
||||
SelectionChanged="WineVarietyInput_SelectionChanged"/>
|
||||
|
||||
<Label Content="Attribute:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<xctk:CheckComboBox x:Name="AttributesInput" Grid.Row="1" Grid.Column="1" Margin="0,40,10,10"
|
||||
DisplayMemberPath="Name" Delimiter=", " AllItemsSelectedContent="Alle"
|
||||
ItemSelectionChanged="AttributesInput_SelectionChanged"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Gradation" Grid.Column="2" Grid.Row="2" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Content="Gradation:" Margin="10,10,10,10"/>
|
||||
<Grid Grid.Column="1" Width="54" Height="25" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<TextBox x:Name="GradationOeInput" TextAlignment="Right" Padding="2,2,23,2"
|
||||
TextChanged="GradationOeInput_TextChanged" LostFocus="GradationOeInput_LostFocus"/>
|
||||
<Label Content="°Oe" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
|
||||
</Grid>
|
||||
<Label Content="=" Margin="60,10,10,10" Grid.Column="1"/>
|
||||
<Grid Grid.Column="1" Width="68" Height="25" Margin="78,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<TextBox x:Name="GradationKmwInput" TextAlignment="Right" Padding="2,2,34,2" SnapsToDevicePixels="True"
|
||||
TextChanged="GradationKmwInput_TextChanged" LostFocus="GradationKmwInput_LostFocus"/>
|
||||
<Label Content="°KMW" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
|
||||
</Grid>
|
||||
|
||||
<Label Content="Qualitätsstufe:" Margin="10,40,10,10"/>
|
||||
<ComboBox x:Name="WineQualityLevelInput" Width="146" Margin="0,40,10,10" Grid.Column="1" HorizontalAlignment="Left"
|
||||
ItemTemplate="{StaticResource WineQualityLevelTemplate}"
|
||||
SelectionChanged="WineQualityLevelInput_SelectionChanged"/>
|
||||
|
||||
<CheckBox x:Name="AbgewertetInput" Content="Abgewertet" IsEnabled="False"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,75,10,10" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Gewicht" Grid.Column="2" Grid.Row="3" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="70"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Gewicht:" Margin="10,10,10,10"/>
|
||||
<Grid Grid.Column="1" Width="70" Height="25" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<TextBox x:Name="WeightInput" TextAlignment="Right" Padding="2,2,17,2" IsReadOnly="True"
|
||||
TextChanged="WeightInput_TextChanged"/>
|
||||
<Label Content="kg" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
|
||||
</Grid>
|
||||
|
||||
<CheckBox x:Name="ManualWeighingInput" Content="Handwiegung" IsEnabled="False"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,45,10,10" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
||||
|
||||
<CheckBox x:Name="GerebeltGewogenInput" Content="Gerebelt gewogen"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left" Margin="10,75,10,10" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
||||
|
||||
<Button x:Name="WeighingManualButton" Content="Handwiegung" Width="120"
|
||||
Click="WeighingManualButton_Click"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,10,10,10" Grid.Column="2"/>
|
||||
<Button x:Name="WeighingAButton" Content="Wiegen A" Width="120"
|
||||
Click="WeighingButton_Click"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,42,10,10" Grid.Column="2"/>
|
||||
<Button x:Name="WeighingBButton" Content="Wiegen B" Width="120"
|
||||
Click="WeighingButton_Click"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,74,10,10" Grid.Column="2"/>
|
||||
<Button x:Name="WeighingCButton" Content="Wiegen C" Width="120"
|
||||
Click="WeighingButton_Click"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,106,10,10" Grid.Column="2"/>
|
||||
<Button x:Name="WeighingDButton" Content="Wiegen D" Width="120"
|
||||
Click="WeighingButton_Click"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,138,10,10" Grid.Column="2"/>
|
||||
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Sonstiges" Grid.Column="2" Grid.Row="4" Margin="5,5,5,10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="65"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Zu-/Abschläge:" Margin="10,10,0,10"/>
|
||||
<xctk:CheckComboBox x:Name="ModifiersInput" Margin="0,10,10,10" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
ItemTemplate="{StaticResource ModifierTemplate}" Delimiter=", " AllItemsSelectedContent="Alle"
|
||||
ItemSelectionChanged="ModifiersInput_SelectionChanged"/>
|
||||
|
||||
<Label Content="Anmerkung:" Margin="10,40,0,10"/>
|
||||
<TextBox x:Name="PartCommentInput" Grid.Column="1" Margin="0,40,10,10" Grid.ColumnSpan="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Temperatur:" Margin="10,70,0,10"/>
|
||||
<Grid Grid.Column="1" Height="25" Margin="0,70,10,10" VerticalAlignment="Top">
|
||||
<TextBox x:Name="TemperatureInput" TextAlignment="Right" Padding="2,2,16,2"
|
||||
TextChanged="TemperatureAcidInput_TextChanged" LostFocus="TemperatureAcidInput_LostFocus"/>
|
||||
<Label Content="°C" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
|
||||
</Grid>
|
||||
|
||||
<Label Content="Säure:" Margin="10,100,0,10"/>
|
||||
<Grid Grid.Column="1" Height="25" Margin="0,100,10,10" VerticalAlignment="Top">
|
||||
<TextBox x:Name="AcidInput" TextAlignment="Right" Padding="2,2,19,2"
|
||||
TextChanged="TemperatureAcidInput_TextChanged" LostFocus="TemperatureAcidInput_LostFocus"/>
|
||||
<Label Content="g/l" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/>
|
||||
</Grid>
|
||||
|
||||
<CheckBox x:Name="LesewagenInput" Content="Lesewagen" Margin="10,75,0,0" Grid.Column="2"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left"
|
||||
Checked="LesewagenInput_Changed" Unchecked="LesewagenInput_Changed"/>
|
||||
<CheckBox x:Name="HandPickedInput" Content="Handlese" Margin="10,105,0,0" Grid.Column="2" IsThreeState="True"
|
||||
VerticalAlignment="Top" HorizontalAlignment="Left"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Teillieferungen" Grid.Column="1" Grid.Row="3" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListBox x:Name="DeliveryPartList" Margin="5,5,5,38" Grid.ColumnSpan="2"
|
||||
SelectionChanged="DeliveryPartList_SelectionChanged">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding DPNr}" Width="20"/>
|
||||
<TextBlock Text="{Binding SortId}" Width="30"/>
|
||||
<TextBlock Text="{Binding Kmw, StringFormat='{}{0:0.0}°'}" Width="40" TextAlignment="Right" Padding="0,0,10,0"/>
|
||||
<TextBlock Text="{Binding QualId}" Width="30"/>
|
||||
<TextBlock Text="{Binding Weight, StringFormat='{}{0:N0} kg'}" Width="60" TextAlignment="Right"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<Button x:Name="ExtractDeliveryPartButton" Content="Extrahieren" IsEnabled="False"
|
||||
ToolTip="Ausgewählte Teillieferung aus aktueller Lieferung entfernen und entweder anderer oder neuer Lieferung zuordnen"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,10,2.5,5" Grid.Column="0" Grid.Row="2"
|
||||
Click="ExtractDeliveryPartButton_Click"/>
|
||||
<Button x:Name="DeleteDeliveryPartButton" Content="Löschen" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,10,5,5" Grid.Column="1" Grid.Row="2"
|
||||
Click="DeleteDeliveryPartButton_Click"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Herkunft" Grid.Column="1" Grid.Row="4" Margin="5,5,5,10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Weinbaugebiet:" Margin="10,10,0,10" Grid.Column="0"/>
|
||||
<ComboBox x:Name="WineOriginInput" Margin="0,10,10,10" Grid.Column="1"
|
||||
ItemTemplate="{StaticResource WineOriginTemplate}"/>
|
||||
|
||||
<Label Content="Weinbau-KG:" Margin="10,40,0,10" Grid.Column="0"/>
|
||||
<ComboBox x:Name="WineKgInput" Margin="0,40,10,10" Grid.Column="1"
|
||||
DisplayMemberPath="Name"
|
||||
SelectionChanged="WineKgInput_SelectionChanged"/>
|
||||
|
||||
<Label Content="Ried:" Margin="10,70,0,10" Grid.Column="0"/>
|
||||
<ComboBox x:Name="WineRdInput" Margin="0,70,10,10" Grid.Column="1"
|
||||
DisplayMemberPath="Name"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<StatusBar Grid.Row="5" Grid.ColumnSpan="3" BorderThickness="0,1,0,0" BorderBrush="Gray">
|
||||
<StatusBar.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="150"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
</Grid>
|
||||
</ItemsPanelTemplate>
|
||||
</StatusBar.ItemsPanel>
|
||||
<StatusBarItem>
|
||||
<TextBlock Name="StatusMembers" Text="Mitglieder: -"/>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="1"/>
|
||||
<StatusBarItem Grid.Column="2">
|
||||
<TextBlock Name="StatusDeliveries" Text="Lieferungen: -"/>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="3"/>
|
||||
<StatusBarItem Grid.Column="4">
|
||||
<TextBlock Name="StatusVarieties" Text="Sorten: -"/>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="5"/>
|
||||
<StatusBarItem Grid.Column="6">
|
||||
<TextBlock Name="StatusWeight" Text="Gewicht: -"/>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="7"/>
|
||||
<StatusBarItem Grid.Column="8">
|
||||
<TextBlock Name="StatusGradation" Text="Gradation: -"/>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
</Grid>
|
||||
</local:AdministrationWindow>
|
1286
Elwig/Windows/DeliveryAdminWindow.xaml.cs
Normal file
1286
Elwig/Windows/DeliveryAdminWindow.xaml.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
||||
<Window x:Class="Elwig.Windows.DeliveryReceptionWindow"
|
||||
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.Windows"
|
||||
mc:Ignorable="d"
|
||||
Title="Übernahme" Height="450" Width="800">
|
||||
<Grid>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
@@ -1,9 +0,0 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class DeliveryReceptionWindow : Window {
|
||||
public DeliveryReceptionWindow() {
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,11 +6,21 @@ namespace Elwig.Windows {
|
||||
public partial class DocumentViewerWindow : Window {
|
||||
|
||||
private TempFile? PdfFile = null;
|
||||
private string? PdfPath = null;
|
||||
|
||||
public DocumentViewerWindow(string title, string path) {
|
||||
InitializeComponent();
|
||||
Title = $"{title} - {Title}";
|
||||
WebView.Source = new($"file://{path}#view=FitH");
|
||||
PdfPath = path;
|
||||
InitializeWebView();
|
||||
}
|
||||
|
||||
public async void InitializeWebView() {
|
||||
WebView.CreationProperties = new() {
|
||||
UserDataFolder = App.TempPath,
|
||||
};
|
||||
await WebView.EnsureCoreWebView2Async();
|
||||
WebView.Source = new($"file://{PdfPath}#view=FitH");
|
||||
}
|
||||
|
||||
public DocumentViewerWindow(string title, TempFile file) : this(title, file.FilePath) {
|
||||
@@ -22,6 +32,7 @@ namespace Elwig.Windows {
|
||||
WebView.Dispose();
|
||||
PdfFile?.Dispose();
|
||||
PdfFile = null;
|
||||
PdfPath = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,12 +4,60 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Elwig.Windows"
|
||||
mc:Ignorable="d"
|
||||
Title="Elwig" Height="450" Width="800" ResizeMode="CanResize" SizeToContent="Manual"
|
||||
Title="Elwig" MinHeight="400" MinWidth="325" Height="450" Width="800" ResizeMode="CanResize"
|
||||
Loaded="Window_Loaded">
|
||||
<Window.Resources>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="9,3"/>
|
||||
<Setter Property="Height" Value="32"/>
|
||||
<Setter Property="Width" Value="200"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button2" Content="Mitgliederverwaltung" Margin="472,182,178,0" VerticalAlignment="Top" Click="Button2_Click"/>
|
||||
<Button x:Name="Button3" Content="Mitgliederliste" Margin="472,217,178,0" VerticalAlignment="Top" Click="Button3_Click"/>
|
||||
<Button x:Name="Button4" Content="Generate" Margin="425,300,225,0" VerticalAlignment="Top" Click="Button4_Click" Tag="Print"/>
|
||||
<Menu BorderThickness="0,0,0,1" VerticalAlignment="Top" Height="19" BorderBrush="LightGray" Background="White">
|
||||
<MenuItem Header="Datenbank">
|
||||
<MenuItem Header="Backup erstellen"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Hilfe">
|
||||
<MenuItem Header="Über"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Grid Height="100" VerticalAlignment="Top" Margin="0,25,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Source="/elwig.png" RenderOptions.BitmapScalingMode="HighQuality" Grid.Column="0"
|
||||
HorizontalAlignment="Left" Margin="5,5,5,5" VerticalAlignment="Top"/>
|
||||
<Label Grid.Column="1" Content="Elwig" FontSize="32"
|
||||
HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top"/>
|
||||
<Label Grid.Column="1" Content="Elektonische Winzer-"
|
||||
HorizontalAlignment="Left" Margin="0,55,0,0" VerticalAlignment="Top"/>
|
||||
<Label Grid.Column="1" Content="genossenschaftsverwaltung"
|
||||
HorizontalAlignment="Left" Margin="0,70,0,0" VerticalAlignment="Top"/>
|
||||
</Grid>
|
||||
|
||||
<Button x:Name="MemberAdminButton" Content="Mitgliederverwaltung" Click="MemberAdminButton_Click"
|
||||
Margin="50,160,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<Button x:Name="MemberListButton" Content="Mitgliederliste" Click="MemberListButton_Click"
|
||||
Margin="50,200,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<Button x:Name="ReceiptButton" Content="Übernahme" Click="ReceiptButton_Click"
|
||||
Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<Button x:Name="DeliveryAdminButton" Content="Lieferungsverwaltung" Click="DeliveryAdminButton_Click"
|
||||
Margin="50,280,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<Button x:Name="DeliveryListButton" Content="Lieferungungen" Click="DeliveryListButton_Click" IsEnabled="False"
|
||||
Margin="50,320,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
|
||||
<Button x:Name="BaseDataButton" Content="Stammdaten" Click="BaseDataButton_Click"
|
||||
Margin="260,160,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<Button x:Name="PdfButton" Content="PDF Erzeugen" Click="PdfButton_Click" Tag="Print"
|
||||
Margin="260,200,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<Button x:Name="TestWindowButton" Content="Test Fenster" Click="TestWindowButton_Click"
|
||||
Margin="260,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<Button x:Name="QueryWindowButton" Content="Datenbankabfragen" Click="QueryWindowButton_Click"
|
||||
Margin="260,280,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<Button x:Name="PaymentWindowButton" Content="Auszahlung" Click="PaymentWindowButton_Click"
|
||||
Margin="260,320,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
@@ -1,48 +1,70 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Elwig.Documents;
|
||||
using Elwig.Helpers;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class MainWindow : Window {
|
||||
private readonly AppDbContext Context = new();
|
||||
|
||||
public MainWindow() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
||||
Button4.IsEnabled = App.IsPrintingReady;
|
||||
PdfButton.IsEnabled = App.IsPrintingReady;
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs evt) {
|
||||
Context.Dispose();
|
||||
base.OnClosing(evt);
|
||||
}
|
||||
|
||||
private void Button2_Click(object sender, RoutedEventArgs evt) {
|
||||
private void MemberAdminButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new MemberAdminWindow();
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private void Button3_Click(object sender, RoutedEventArgs evt) {
|
||||
private void MemberListButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new MemberListWindow();
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private void Button4_Click(object sender, RoutedEventArgs evt) {
|
||||
private void ReceiptButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new DeliveryAdminWindow(true);
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private void DeliveryAdminButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new DeliveryAdminWindow();
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private void DeliveryListButton_Click(object sender, RoutedEventArgs evt) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
private void PdfButton_Click(object sender, RoutedEventArgs evt) {
|
||||
Utils.RunBackground("PDF Generation", async () => {
|
||||
using var letter = new BusinessLetter("Test Dokument", Context.Members.First());
|
||||
await letter.Generate();
|
||||
letter.Show();
|
||||
using var ctx = new AppDbContext();
|
||||
using var doc = new DeliveryNote(ctx.Deliveries.OrderBy(d => d.Parts.Count).ThenBy(d => d.Year).ThenBy(d => d.DId).Last(), ctx);
|
||||
await doc.Generate();
|
||||
doc.Show();
|
||||
});
|
||||
}
|
||||
|
||||
private void TestWindowButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new TestWindow();
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private void QueryWindowButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new QueryWindow();
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private void BaseDataButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new BaseDataWindow();
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private void PaymentWindowButton_Click(object sender, RoutedEventArgs e) {
|
||||
var w = new ChartWindow();
|
||||
w.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Elwig.Windows"
|
||||
Title="Mitgliederverwaltung - Elwig" Height="650" Width="1200" MinHeight="600" MinWidth="1000"
|
||||
Title="Mitgliederverwaltung - Elwig" Height="670" Width="1250" MinHeight="600" MinWidth="1000"
|
||||
Loaded="Window_Loaded">
|
||||
<Window.Resources>
|
||||
<Style TargetType="Label">
|
||||
@@ -18,12 +18,10 @@
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="2"/>
|
||||
<Setter Property="IsReadOnly" Value="True"/>
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="TextWrapping" Value="NoWrap"/>
|
||||
</Style>
|
||||
<Style TargetType="ComboBox">
|
||||
<Setter Property="IsEnabled" Value="False"/>
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
@@ -39,9 +37,10 @@
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="19"/>
|
||||
<RowDefinition Height="0.8*"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
<RowDefinition Height="0.8*"/>
|
||||
<RowDefinition Height="0.2*"/>
|
||||
<RowDefinition Height="1.3*"/>
|
||||
<RowDefinition Height="0.9*"/>
|
||||
<RowDefinition Height="0.8*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="370"/>
|
||||
@@ -67,14 +66,19 @@
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
<Grid Grid.RowSpan="4" Grid.Row="1">
|
||||
<Grid Grid.RowSpan="5" Grid.Row="1" Margin="5,0,5,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="39"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="42"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="125"/>
|
||||
<ColumnDefinition Width="120"/>
|
||||
<ColumnDefinition Width="125"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox x:Name="SearchInput" Grid.ColumnSpan="3" Margin="10,7,145,0" IsReadOnly="False"
|
||||
<TextBox x:Name="SearchInput" Grid.ColumnSpan="3" Margin="5,7,145,0" IsReadOnly="False"
|
||||
TextChanged="SearchInput_TextChanged"/>
|
||||
<CheckBox x:Name="ActiveMemberInput" Content="Nur aktive anzeigen"
|
||||
Checked="ActiveMemberInput_Changed" Unchecked="ActiveMemberInput_Changed"
|
||||
@@ -82,7 +86,7 @@
|
||||
<DataGrid x:Name="MemberList" AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single"
|
||||
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False"
|
||||
SelectionChanged="MemberList_SelectionChanged"
|
||||
Margin="10,39,10,47" FontSize="14" Grid.ColumnSpan="3">
|
||||
Margin="5,0,5,0" Grid.Row="1" FontSize="14" Grid.ColumnSpan="3">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="MgNr." Binding="{Binding MgNr}" Width="70"/>
|
||||
<DataGridTextColumn Header="Nachname" Binding="{Binding FamilyName}" Width="4*"/>
|
||||
@@ -90,19 +94,25 @@
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<Button x:Name="NewMemberButton" Content="Neu" Click="NewMemberButton_Click"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="10,10,0,10" Width="110" Grid.Column="0"/>
|
||||
<Button x:Name="EditMemberButton" Content="Bearbeiten" Click="EditMemberButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,10,0,10" Width="110" Grid.Column="1"/>
|
||||
<Button x:Name="DeleteMemberButton" Content="Löschen" Click="DeleteMemberButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,10,10,10" Width="110" Grid.Column="2"/>
|
||||
<Button x:Name="NewMemberButton" Content="Neu"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="NewMemberButton_Click"/>
|
||||
<Button x:Name="EditMemberButton" Content="Bearbeiten" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="EditMemberButton_Click"/>
|
||||
<Button x:Name="DeleteMemberButton" Content="Löschen" IsEnabled="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="DeleteMemberButton_Click"/>
|
||||
|
||||
<Button x:Name="SaveButton" Content="Speichern" Click="SaveButton_Click" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="10,10,0,10" Width="110" Grid.Column="0"/>
|
||||
<Button x:Name="ResetButton" Content="Zurücksetzen" Click="ResetButton_Click" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,10,0,10" Width="110" Grid.Column="1"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" Click="CancelButton_Click" IsEnabled="False" Visibility="Hidden" IsCancel="True"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,10,10,10" Width="110" Grid.Column="2"/>
|
||||
<Button x:Name="SaveButton" Content="Speichern" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="SaveButton_Click"/>
|
||||
<Button x:Name="ResetButton" Content="Zurücksetzen" IsEnabled="False" Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="ResetButton_Click"/>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" IsEnabled="False" Visibility="Hidden" IsCancel="True"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="CancelButton_Click"/>
|
||||
</Grid>
|
||||
|
||||
<GroupBox Header="Persönliche Daten" Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Margin="5,5,5,5">
|
||||
@@ -122,14 +132,14 @@
|
||||
<TextBox x:Name="PredecessorMgNrInput" Margin="0,10,10,0" Width="48" Grid.Column="3" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="PredecessorMgNrInput_TextChanged" LostFocus="PredecessorMgNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="Vorname:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="GivenNameInput" Margin="0,40,0,0" Grid.Column="1"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Präfix:" Margin="10,40,0,0" Grid.Column="2"/>
|
||||
<TextBox x:Name="PrefixInput" Margin="0,40,10,0" Grid.Column="3"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Vorname:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="GivenNameInput" Margin="0,40,0,0" Grid.Column="1"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Nachname:" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="FamilyNameInput" Margin="0,70,0,0" Grid.Column="1"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
@@ -140,7 +150,14 @@
|
||||
|
||||
<Label Content="Geburtstag:" Margin="10,100,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="BirthdayInput" Margin="0,100,0,0" Grid.Column="1" Width="78" TextAlignment="Right" HorizontalAlignment="Left"
|
||||
TextChanged="PartialDateInput_TextChanged"/>
|
||||
TextChanged="PartialDateInput_TextChanged" LostFocus="PartialDateInput_LostFocus"/>
|
||||
|
||||
<Label Content="Alter:" Margin="85,100,0,0" Grid.Column="1" Grid.ColumnSpan="3"/>
|
||||
<TextBlock x:Name="Age" Text="-" Margin="119,104,0,0" Grid.Column="1" Grid.ColumnSpan="3" TextWrapping="NoWrap" VerticalAlignment="Top"/>
|
||||
|
||||
<CheckBox x:Name="DeceasedInput" Content="Verstorben" IsEnabled="False"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"
|
||||
Grid.Column="3" HorizontalAlignment="Left" Margin="0,105,0,0" VerticalAlignment="Top" IsChecked="False"/>
|
||||
|
||||
<Label Content="Adresse:" Margin="10,130,0,0"/>
|
||||
<TextBox x:Name="AddressInput" Margin="0,130,10,0" Grid.Column="1" Grid.ColumnSpan="3"
|
||||
@@ -148,37 +165,79 @@
|
||||
|
||||
<Label Content="PLZ/Ort:" Margin="10,160,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="PlzInput" Margin="0,160,0,0" Width="42" Grid.Column="1" HorizontalAlignment="Left"
|
||||
TextChanged="PlzInput_TextChanged" LostFocus="PlzInput_LostFocus"/>
|
||||
<ComboBox x:Name="OrtInput" ItemTemplate="{StaticResource PostalDestComboBoxTemplate}" TextSearch.TextPath="Ort.Name"
|
||||
SelectionChanged="ComboBox_SelectionChanged"
|
||||
TextChanged="PlzInput_TextChanged" LostFocus="PlzInput_LostFocus" Tag="PLZ"/>
|
||||
<ComboBox x:Name="OrtInput" ItemTemplate="{StaticResource PostalDestTemplate}" TextSearch.TextPath="Ort.Name"
|
||||
Margin="47,160,10,0" Grid.Column="1" Grid.ColumnSpan="3"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<GroupBox Header="Kontaktdaten" Grid.Column="1" Grid.Row="3" Margin="5,5,5,5">
|
||||
<GroupBox Header="Kontaktdaten" Grid.Column="1" Grid.Row="3" Grid.RowSpan="2" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="115"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="135"/>
|
||||
<ColumnDefinition Width="*" MinWidth="180"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="E-Mail-Adresse:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="EmailInput" Margin="0,10,10,0" Grid.Column="1"
|
||||
TextChanged="EmailInput_TextChanged" LostFocus="EmailInput_LostFocus"/>
|
||||
<TextBox x:Name="EmailAddressInput" Margin="0,10,10,0" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/>
|
||||
|
||||
<Label Content="Tel.-Nr. (Festnetz):" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="PhoneLandlineInput" Margin="0,40,10,0" Grid.Column="1"
|
||||
<ComboBox x:Name="PhoneNr1TypeInput" DisplayMemberPath="Value" Margin="6,40,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr1Input" Margin="0,40,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr1CommentInput" Margin="0,40,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Tel.-Nr. (mobil):" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="PhoneMobile1Input" Margin="0,70,10,0" Grid.Column="1"
|
||||
<ComboBox x:Name="PhoneNr2TypeInput" DisplayMemberPath="Value" Margin="6,70,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr2Input" Margin="0,70,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr2CommentInput" Margin="0,70,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Tel.-Nr. (mobil):" Margin="10,100,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="PhoneMobile2Input" Margin="0,100,10,0" Grid.Column="1"
|
||||
<ComboBox x:Name="PhoneNr3TypeInput" DisplayMemberPath="Value" Margin="6,100,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr3Input" Margin="0,100,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr3CommentInput" Margin="0,100,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<ComboBox x:Name="PhoneNr4TypeInput" DisplayMemberPath="Value" Margin="6,130,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr4Input" Margin="0,130,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr4CommentInput" Margin="0,130,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<ComboBox x:Name="PhoneNr5TypeInput" DisplayMemberPath="Value" Margin="6,160,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr5Input" Margin="0,160,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr5CommentInput" Margin="0,160,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<ComboBox x:Name="PhoneNr6TypeInput" DisplayMemberPath="Value" Margin="6,190,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr6Input" Margin="0,190,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr6CommentInput" Margin="0,190,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<ComboBox x:Name="PhoneNr7TypeInput" DisplayMemberPath="Value" Margin="6,220,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr7Input" Margin="0,220,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr7CommentInput" Margin="0,220,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<ComboBox x:Name="PhoneNr8TypeInput" DisplayMemberPath="Value" Margin="6,250,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr8Input" Margin="0,250,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr8CommentInput" Margin="0,250,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<ComboBox x:Name="PhoneNr9TypeInput" DisplayMemberPath="Value" Margin="6,280,5,0" FontSize="12" Padding="6,4,4,4"/>
|
||||
<TextBox x:Name="PhoneNr9Input" Margin="0,280,5,0" Grid.Column="1"
|
||||
TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/>
|
||||
<TextBox x:Name="PhoneNr9CommentInput" Margin="0,280,10,0" Grid.Column="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<GroupBox Header="Bankverbindung" Grid.Column="1" Grid.Row="4" Margin="5,5,5,10">
|
||||
<GroupBox Header="Bankverbindung" Grid.Column="1" Grid.Row="5" Margin="5,5,5,10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="65"/>
|
||||
@@ -203,10 +262,10 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="UID:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="UstIdInput" Margin="0,10,10,0" Grid.Column="1" Width="120" HorizontalAlignment="Left"
|
||||
TextChanged="UstIdInput_TextChanged" LostFocus="UstIdInput_LostFocus"/>
|
||||
<TextBox x:Name="UstIdNrInput" Margin="0,10,10,0" Grid.Column="1" Width="96" HorizontalAlignment="Left"
|
||||
TextChanged="UstIdNrInput_TextChanged" LostFocus="UstIdNrInput_LostFocus"/>
|
||||
|
||||
<Label Content="BetriebsNr.:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<Label Content="Betriebs-Nr.:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="LfbisNrInput" Margin="0,40,10,0" Grid.Column="1" Width="64" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="LfbisNrInput_TextChanged" LostFocus="LfbisNrInput_LostFocus"/>
|
||||
|
||||
@@ -215,7 +274,7 @@
|
||||
Grid.Column="2" HorizontalAlignment="Left" Margin="10,15,0,0" VerticalAlignment="Top" IsChecked="False"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<GroupBox Header="Rechnungsadresse (optional)" Grid.Column="2" Grid.Row="2" Grid.RowSpan="1" Margin="5,5,5,5">
|
||||
<GroupBox Header="Rechnungsadresse (optional)" Grid.Column="2" Grid.Row="2" Grid.RowSpan="2" Margin="5,5,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="65"/>
|
||||
@@ -223,7 +282,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Name:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="BillingName" Margin="0,10,10,10" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
<TextBox x:Name="BillingNameInput" Margin="0,10,10,10" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Adresse:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
@@ -232,13 +291,12 @@
|
||||
|
||||
<Label Content="PLZ/Ort:" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="BillingPlzInput" Margin="0,70,0,0" Width="42" Grid.Column="1" HorizontalAlignment="Left"
|
||||
TextChanged="PlzInput_TextChanged" LostFocus="PlzInput_LostFocus"/>
|
||||
<ComboBox x:Name="BillingOrtInput" ItemTemplate="{StaticResource PostalDestComboBoxTemplate}" TextSearch.TextPath="Ort.Name"
|
||||
SelectionChanged="ComboBox_SelectionChanged"
|
||||
TextChanged="PlzInput_TextChanged" LostFocus="PlzInput_LostFocus" Tag="PLZ"/>
|
||||
<ComboBox x:Name="BillingOrtInput" ItemTemplate="{StaticResource PostalDestTemplate}" TextSearch.TextPath="Ort.Name"
|
||||
Margin="47,70,10,0" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<GroupBox Header="Genossenschaft" Grid.Column="2" Grid.Row="3" Grid.RowSpan="2" Margin="5,5,5,10">
|
||||
<GroupBox Header="Genossenschaft" Grid.Column="2" Grid.Row="4" Grid.RowSpan="2" Margin="5,5,5,10">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="120"/>
|
||||
@@ -248,11 +306,11 @@
|
||||
|
||||
<Label Content="Eintritt:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="EntryDateInput" Margin="0,10,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="DateInput_TextChanged"/>
|
||||
TextChanged="DateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
||||
|
||||
<Label Content="Austritt:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="ExitDateInput" Margin="0,40,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="DateInput_TextChanged"/>
|
||||
TextChanged="DateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
||||
|
||||
<Label Content="Geschäftsanteile:" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="BusinessSharesInput" Margin="0,70,10,0" Width="48" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
@@ -274,14 +332,12 @@
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"
|
||||
Grid.Column="2" HorizontalAlignment="Left" Margin="10,75,0,0" VerticalAlignment="Top" IsChecked="False"/>
|
||||
|
||||
<Label Content="StammZwst.:" Margin="10,130,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="BranchInput" ItemTemplate="{StaticResource BranchTemplate}" TextSearch.TextPath="Name"
|
||||
SelectionChanged="ComboBox_SelectionChanged"
|
||||
<Label Content="Stamm-Zwst.:" Margin="10,130,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="BranchInput" DisplayMemberPath="Name" TextSearch.TextPath="Name"
|
||||
Margin="0,130,10,0" Grid.Column="1" Grid.ColumnSpan="2"/>
|
||||
|
||||
<Label Content="Stammgemeinde:" Margin="10,160,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="DefaultKgInput" ItemTemplate="{StaticResource KgTemplate}" TextSearch.TextPath="Name"
|
||||
SelectionChanged="ComboBox_SelectionChanged"
|
||||
<ComboBox x:Name="DefaultKgInput" DisplayMemberPath="Name" TextSearch.TextPath="Name"
|
||||
Margin="0,160,10,0" Grid.Column="1" Grid.ColumnSpan="2"/>
|
||||
|
||||
<Label Content="Anmerkung:" Margin="10,190,0,0" Grid.Column="0"/>
|
||||
@@ -289,19 +345,21 @@
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Kontaktart:" Margin="10,220,0,0" Grid.Column="0"/>
|
||||
<RadioButton x:Name="ContactPostInput" GroupName="DefaultContact" Content="Post" IsEnabled="False"
|
||||
Checked="RadioButton_Changed" Unchecked="RadioButton_Changed"
|
||||
HorizontalAlignment="Left" Margin="0,225,0,0" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"/>
|
||||
<RadioButton x:Name="ContactEmailInput" GroupName="DefaultContact" Content="E-Mail" IsEnabled="False"
|
||||
Checked="RadioButton_Changed" Unchecked="RadioButton_Changed"
|
||||
HorizontalAlignment="Left" Margin="60,225,0,0" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"/>
|
||||
<CheckBox x:Name="ContactPostalInput" Content="Post" IsEnabled="False"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"
|
||||
HorizontalAlignment="Left" Margin="0,225,0,0" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"/>
|
||||
<CheckBox x:Name="ContactEmailInput" Content="E-Mail" IsEnabled="False"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"
|
||||
HorizontalAlignment="Left" Margin="60,225,0,0" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="2"/>
|
||||
|
||||
<Label Content="Gebundene Fläche:" Margin="10,250,0,0" Grid.Column="0"/>
|
||||
<TextBlock x:Name="AreaCommitment" Text="- m²"
|
||||
Grid.Column="1" HorizontalAlignment="Stretch" Margin="5,252,5,0" TextWrapping="NoWrap" VerticalAlignment="Top" FontSize="14" TextAlignment="Right"/>
|
||||
|
||||
<Button x:Name="DeliveryButton" Content="Lieferungen" Click="DeliveryButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Right" Margin="10,00,10,37" Width="150" VerticalAlignment="Bottom" Grid.ColumnSpan="3"/>
|
||||
<Button x:Name="AreaCommitmentButton" Content="Flächenbindungen" Click="AreaCommitmentButton_Click" IsEnabled="False"
|
||||
HorizontalAlignment="Right" Margin="10,10,10,10" VerticalAlignment="Bottom" Grid.ColumnSpan="3"/>
|
||||
HorizontalAlignment="Right" Margin="10,10,10,5" Width="150" VerticalAlignment="Bottom" Grid.ColumnSpan="3"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
@@ -9,13 +9,20 @@ using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class MemberAdminWindow : AdministrationWindow {
|
||||
private bool IsEditing = false;
|
||||
private bool IsCreating = false;
|
||||
|
||||
private List<string> TextFilter = new();
|
||||
private readonly RoutedCommand CtrlF = new();
|
||||
private readonly (ComboBox, TextBox, TextBox)[] PhoneNrInputs;
|
||||
|
||||
private static ObservableCollection<KeyValuePair<string, string>> PhoneNrTypes { get; set; } = new() {
|
||||
new("landline", "Tel.-Nr. (Festnetz)"),
|
||||
new("mobile", "Tel.-Nr. (mobil)"),
|
||||
new("fax", "Fax-Nr."),
|
||||
};
|
||||
|
||||
public MemberAdminWindow() {
|
||||
InitializeComponent();
|
||||
@@ -23,20 +30,33 @@ namespace Elwig.Windows {
|
||||
CommandBindings.Add(new CommandBinding(CtrlF, FocusSearchInput));
|
||||
ExemptInputs = new Control[] {
|
||||
SearchInput, ActiveMemberInput, MemberList,
|
||||
NewMemberButton, EditMemberButton, DeleteMemberButton,
|
||||
ResetButton, SaveButton, CancelButton
|
||||
};
|
||||
RequiredInputs = new Control[] {
|
||||
MgNrInput, GivenNameInput, FamilyNameInput,
|
||||
AddressInput, PlzInput, OrtInput, BillingOrtInput,
|
||||
BusinessSharesInput, BranchInput, DefaultKgInput
|
||||
};
|
||||
PhoneNrInputs = new (ComboBox, TextBox, TextBox)[] {
|
||||
(PhoneNr1TypeInput, PhoneNr1Input, PhoneNr1CommentInput),
|
||||
(PhoneNr2TypeInput, PhoneNr2Input, PhoneNr2CommentInput),
|
||||
(PhoneNr3TypeInput, PhoneNr3Input, PhoneNr3CommentInput),
|
||||
(PhoneNr4TypeInput, PhoneNr4Input, PhoneNr4CommentInput),
|
||||
(PhoneNr5TypeInput, PhoneNr5Input, PhoneNr5CommentInput),
|
||||
(PhoneNr6TypeInput, PhoneNr6Input, PhoneNr6CommentInput),
|
||||
(PhoneNr7TypeInput, PhoneNr7Input, PhoneNr7CommentInput),
|
||||
(PhoneNr8TypeInput, PhoneNr8Input, PhoneNr8CommentInput),
|
||||
(PhoneNr9TypeInput, PhoneNr9Input, PhoneNr9CommentInput),
|
||||
};
|
||||
foreach (var input in PhoneNrInputs) input.Item1.ItemsSource = PhoneNrTypes;
|
||||
|
||||
InitializeDelayTimer(SearchInput, SearchInput_TextChanged);
|
||||
SearchInput.TextChanged -= SearchInput_TextChanged;
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
||||
ActiveMemberInput.IsChecked = true;
|
||||
BranchInput.ItemsSource = Context.Branches.OrderBy(b => b.Name).ToList();
|
||||
DefaultKgInput.ItemsSource = Context.WbKgs.Select(k => k.Kg).OrderBy(k => k.Name).ToList();
|
||||
UpdatePhoneNrInputVisibility();
|
||||
LockInputs();
|
||||
}
|
||||
|
||||
private async Task RefreshMemberList() {
|
||||
@@ -44,7 +64,7 @@ namespace Elwig.Windows {
|
||||
await RefreshMemberListQuery();
|
||||
}
|
||||
|
||||
private async Task RefreshMemberListQuery() {
|
||||
private async Task RefreshMemberListQuery(bool updateSort = false) {
|
||||
IQueryable<Member> memberQuery = Context.Members;
|
||||
if (ActiveMemberInput.IsChecked == true)
|
||||
memberQuery = memberQuery.Where(m => m.IsActive);
|
||||
@@ -52,12 +72,14 @@ namespace Elwig.Windows {
|
||||
List<Member> members = await memberQuery.ToListAsync();
|
||||
|
||||
if (TextFilter.Count > 0) {
|
||||
members = members
|
||||
var dict = members.AsParallel()
|
||||
.ToDictionary(m => m, m => m.SearchScore(TextFilter))
|
||||
.OrderByDescending(a => a.Value)
|
||||
.ThenBy(a => a.Key.FamilyName)
|
||||
.ThenBy(a => a.Key.GivenName)
|
||||
.Where(a => a.Value > 0)
|
||||
.ThenBy(a => a.Key.GivenName);
|
||||
var threshold = dict.Select(a => a.Value).Max() * 3 / 4;
|
||||
members = dict
|
||||
.Where(a => a.Value > threshold)
|
||||
.Select(a => a.Key)
|
||||
.ToList();
|
||||
} else {
|
||||
@@ -67,43 +89,79 @@ namespace Elwig.Windows {
|
||||
.ToList();
|
||||
}
|
||||
|
||||
MemberList.ItemsSource = members;
|
||||
if (members.Count == 1)
|
||||
MemberList.SelectedIndex = 0;
|
||||
|
||||
RefreshInputs();
|
||||
ControlUtils.RenewItemsSource(MemberList, members, i => (i as Member)?.MgNr, MemberList_SelectionChanged, ControlUtils.RenewSourceDefault.IfOnly, !updateSort);
|
||||
}
|
||||
|
||||
private void RefreshInputs(bool validate = false) {
|
||||
ClearInputStates();
|
||||
Member m = (Member)MemberList.SelectedItem;
|
||||
if (m != null) {
|
||||
if (MemberList.SelectedItem is Member m) {
|
||||
EditMemberButton.IsEnabled = true;
|
||||
DeleteMemberButton.IsEnabled = true;
|
||||
AreaCommitmentButton.IsEnabled = true;
|
||||
DeliveryButton.IsEnabled = true;
|
||||
FillInputs(m);
|
||||
} else {
|
||||
EditMemberButton.IsEnabled = false;
|
||||
DeleteMemberButton.IsEnabled = false;
|
||||
AreaCommitmentButton.IsEnabled = false;
|
||||
DeliveryButton.IsEnabled = false;
|
||||
ClearOriginalValues();
|
||||
ClearInputs();
|
||||
ClearDefaultValues();
|
||||
ClearInputs(validate);
|
||||
ClearInputStates();
|
||||
}
|
||||
if (!validate) ClearInputStates();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private async void InitInputs() {
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
|
||||
MgNrInput.Text = (await Context.NextMgNr()).ToString();
|
||||
EntryDateInput.Text = DateTime.Now.ToString("dd.MM.yyyy");
|
||||
if (Context.Branches.Count() == 1)
|
||||
BranchInput.SelectedItem = Context.Branches.First();
|
||||
ActiveInput.IsChecked = true;
|
||||
ContactPostInput.IsChecked = true;
|
||||
FillOriginalValues();
|
||||
ContactPostalInput.IsChecked = true;
|
||||
|
||||
SetDefaultValue(MgNrInput);
|
||||
SetDefaultValue(EntryDateInput);
|
||||
SetDefaultValue(ActiveInput);
|
||||
ValidateRequiredInputs();
|
||||
}
|
||||
|
||||
protected override async Task RenewContext() {
|
||||
await base.RenewContext();
|
||||
ControlUtils.RenewItemsSource(BranchInput, await Context.Branches.OrderBy(b => b.Name).ToListAsync(), i => (i as Branch)?.ZwstId);
|
||||
ControlUtils.RenewItemsSource(DefaultKgInput, await Context.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync(), i => (i as AT_Kg)?.KgNr);
|
||||
await RefreshMemberList();
|
||||
}
|
||||
|
||||
private void SetPhoneNrInput(int nr, string? type, string? number, string? comment) {
|
||||
var inputs = PhoneNrInputs[nr];
|
||||
inputs.Item1.SelectedItem = (type == null) ? null : inputs.Item1.ItemsSource.Cast<KeyValuePair<string, string>>().FirstOrDefault(p => p.Key == type);
|
||||
inputs.Item2.Text = number;
|
||||
inputs.Item3.Text = comment;
|
||||
}
|
||||
|
||||
private (string, string, string?)? GetPhoneNrInput(int nr) {
|
||||
var inputs = PhoneNrInputs[nr];
|
||||
var number = inputs.Item2.Text;
|
||||
if (string.IsNullOrEmpty(number))
|
||||
return null;
|
||||
var type = (inputs.Item1.SelectedItem as KeyValuePair<string, string>?)?.Key ?? (number.StartsWith("+43 ") && number[4] == '6' ? "mobile" : "landline");
|
||||
var comment = inputs.Item3.Text;
|
||||
return (type, number, comment == "" ? null : comment);
|
||||
}
|
||||
|
||||
private void SetPhoneNrInputVisible(int nr, bool visible) {
|
||||
var inputs = PhoneNrInputs[nr];
|
||||
var vis = visible ? Visibility.Visible : Visibility.Hidden;
|
||||
inputs.Item1.Visibility = vis;
|
||||
inputs.Item2.Visibility = vis;
|
||||
inputs.Item3.Visibility = vis;
|
||||
}
|
||||
|
||||
private void MemberList_SelectionChanged(object sender, RoutedEventArgs evt) {
|
||||
RefreshInputs();
|
||||
}
|
||||
@@ -119,6 +177,7 @@ namespace Elwig.Windows {
|
||||
HideNewEditDeleteButtons();
|
||||
ShowSaveResetCancelButtons();
|
||||
UnlockInputs();
|
||||
UpdatePhoneNrInputVisibility(true);
|
||||
InitInputs();
|
||||
LockSearchInputs();
|
||||
}
|
||||
@@ -133,17 +192,16 @@ namespace Elwig.Windows {
|
||||
HideNewEditDeleteButtons();
|
||||
ShowSaveResetCancelButtons();
|
||||
UnlockInputs();
|
||||
UpdatePhoneNrInputVisibility(true);
|
||||
LockSearchInputs();
|
||||
}
|
||||
|
||||
private async void DeleteMemberButton_Click(object sender, RoutedEventArgs evt) {
|
||||
Member m = (Member)MemberList.SelectedItem;
|
||||
if (m == null) return;
|
||||
if (MemberList.SelectedItem is not Member m)
|
||||
return;
|
||||
|
||||
DeleteMemberButton.IsEnabled = false;
|
||||
EditMemberButton.IsEnabled = false;
|
||||
var r = MessageBox.Show(
|
||||
$"Soll das Mitglied \"{m.FamilyName} {m.GivenName}\" (MgNr. {m.MgNr}) wirklich unwiderruflich gelöscht werden?",
|
||||
$"Soll das Mitglied \"{m.AdministrativeName}\" (MgNr. {m.MgNr}) wirklich unwiderruflich gelöscht werden?",
|
||||
"Mitglied löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
|
||||
if (r == MessageBoxResult.Yes) {
|
||||
Context.Remove(m);
|
||||
@@ -153,15 +211,18 @@ namespace Elwig.Windows {
|
||||
}
|
||||
|
||||
private async void SaveButton_Click(object sender, RoutedEventArgs evt) {
|
||||
Member m = await UpdateMember(IsEditing ? (Member)MemberList.SelectedItem : Context.CreateProxy<Member>());
|
||||
Member m = await UpdateMember(MemberList.SelectedItem as Member);
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
MemberList.IsEnabled = true;
|
||||
HideSaveResetCancelButtons();
|
||||
ShowNewEditDeleteButtons();
|
||||
LockInputs();
|
||||
UpdatePhoneNrInputVisibility();
|
||||
UnlockSearchInputs();
|
||||
FinishInputFilling();
|
||||
await RefreshMemberList();
|
||||
RefreshInputs();
|
||||
SearchInput.Text = "";
|
||||
MemberList.SelectedItem = m;
|
||||
}
|
||||
@@ -183,19 +244,24 @@ namespace Elwig.Windows {
|
||||
HideSaveResetCancelButtons();
|
||||
ShowNewEditDeleteButtons();
|
||||
RefreshInputs();
|
||||
ClearInputStates();
|
||||
LockInputs();
|
||||
UpdatePhoneNrInputVisibility();
|
||||
UnlockSearchInputs();
|
||||
}
|
||||
|
||||
private void AreaCommitmentButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new AreaComAdminWindow((Member)MemberList.SelectedItem);
|
||||
var w = new AreaComAdminWindow(((Member)MemberList.SelectedItem).MgNr);
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private void DeliveryButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new DeliveryAdminWindow(((Member)MemberList.SelectedItem).MgNr);
|
||||
w.Show();
|
||||
}
|
||||
|
||||
private async void SearchInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
TextFilter = SearchInput.Text.ToLower().Split(" ").ToList().FindAll(e => e.Length > 0);
|
||||
await RefreshMemberListQuery();
|
||||
await RefreshMemberListQuery(true);
|
||||
}
|
||||
|
||||
private void Menu_Member_SendEmail_Click(object sender, RoutedEventArgs evt) {
|
||||
@@ -255,7 +321,21 @@ namespace Elwig.Windows {
|
||||
ActiveMemberInput.IsEnabled = true;
|
||||
}
|
||||
|
||||
private async Task<Member> UpdateMember(Member m) {
|
||||
private void UpdatePhoneNrInputVisibility(bool extra = false) {
|
||||
bool lastVisible = true;
|
||||
var m = (Member)MemberList.SelectedItem;
|
||||
for (int i = 0; i < PhoneNrInputs.Length; i++) {
|
||||
var input = PhoneNrInputs[i];
|
||||
var vis = !string.IsNullOrEmpty(input.Item2.Text) || (m?.TelephoneNumbers.Any(p => p.Nr - 1 == i) ?? false);
|
||||
SetPhoneNrInputVisible(i, vis || (extra && lastVisible));
|
||||
lastVisible = vis;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Member> UpdateMember(Member? m) {
|
||||
bool memberNew = (m == null);
|
||||
m ??= Context.CreateProxy<Member>();
|
||||
|
||||
int newMgNr = int.Parse(MgNrInput.Text);
|
||||
m.PredecessorMgNr = (PredecessorMgNrInput.Text == "") ? null : int.Parse(PredecessorMgNrInput.Text);
|
||||
m.Prefix = (PrefixInput.Text == "") ? null : PrefixInput.Text;
|
||||
@@ -263,24 +343,20 @@ namespace Elwig.Windows {
|
||||
m.FamilyName = FamilyNameInput.Text;
|
||||
m.Suffix = (SuffixInput.Text == "") ? null : SuffixInput.Text;
|
||||
m.Birthday = (BirthdayInput.Text == "") ? null : string.Join("-", BirthdayInput.Text.Split(".").Reverse());
|
||||
m.CountryCode = "AT";
|
||||
m.IsDeceased = DeceasedInput.IsChecked ?? false;
|
||||
m.CountryNum = 40; // Austria AT AUT
|
||||
m.PostalDestId = ((AT_PlzDest)OrtInput.SelectedItem).Id;
|
||||
m.Address = AddressInput.Text;
|
||||
|
||||
m.Email = (EmailInput.Text == "") ? null : EmailInput.Text;
|
||||
m.PhoneLandline = (PhoneLandlineInput.Text == "") ? null : PhoneLandlineInput.Text.Replace(" ", "");
|
||||
m.PhoneMobile1 = (PhoneMobile1Input.Text == "") ? null : PhoneMobile1Input.Text.Replace(" ", "");
|
||||
m.PhoneMobile2 = (PhoneMobile2Input.Text == "") ? null : PhoneMobile2Input.Text.Replace(" ", "");
|
||||
m.Email = (EmailAddressInput.Text == "") ? null : EmailAddressInput.Text;
|
||||
|
||||
m.Iban = (IbanInput.Text == "") ? null : IbanInput.Text.Replace(" ", "");
|
||||
m.Bic = (BicInput.Text == "") ? null : BicInput.Text;
|
||||
|
||||
m.UstId = (UstIdInput.Text == "") ? null : UstIdInput.Text;
|
||||
m.UstIdNr = (UstIdNrInput.Text == "") ? null : UstIdNrInput.Text;
|
||||
m.LfbisNr = (LfbisNrInput.Text == "") ? null : LfbisNrInput.Text;
|
||||
m.IsBuchführend = BuchführendInput.IsChecked ?? false;
|
||||
|
||||
// TODO Rechnungsadresse
|
||||
|
||||
m.EntryDateString = (EntryDateInput.Text == "") ? null : string.Join("-", EntryDateInput.Text.Split(".").Reverse());
|
||||
m.ExitDateString = (ExitDateInput.Text == "") ? null : string.Join("-", ExitDateInput.Text.Split(".").Reverse());
|
||||
m.BusinessShares = (BusinessSharesInput.Text == "") ? 0 : int.Parse(BusinessSharesInput.Text);
|
||||
@@ -291,9 +367,8 @@ namespace Elwig.Windows {
|
||||
m.ZwstId = ((Branch)BranchInput.SelectedItem).ZwstId;
|
||||
m.DefaultKgNr = ((AT_Kg)DefaultKgInput.SelectedItem).KgNr;
|
||||
m.Comment = (CommentInput.Text == "") ? null : CommentInput.Text;
|
||||
m.DefaultContact = "post";
|
||||
if (ContactPostInput.IsChecked ?? false) m.DefaultContact = "post";
|
||||
if (ContactEmailInput.IsChecked ?? false) m.DefaultContact = "email";
|
||||
m.ContactViaPost = ContactPostalInput.IsChecked ?? false;
|
||||
m.ContactViaEmail = ContactEmailInput.IsChecked ?? false;
|
||||
|
||||
EntityEntry<Member>? tr = null;
|
||||
try {
|
||||
@@ -302,16 +377,66 @@ namespace Elwig.Windows {
|
||||
} else if (IsCreating) {
|
||||
m.MgNr = newMgNr;
|
||||
tr = (await Context.AddAsync(m));
|
||||
} else {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
if (BillingOrtInput.SelectedItem == null) {
|
||||
if (m.BillingAddress != null) {
|
||||
Context.Remove(m.BillingAddress);
|
||||
}
|
||||
} else {
|
||||
BillingAddr b = m.BillingAddress ?? Context.CreateProxy<BillingAddr>();
|
||||
b.Name = BillingNameInput.Text;
|
||||
b.Address = BillingAddressInput.Text;
|
||||
var p = (AT_PlzDest)BillingOrtInput.SelectedItem;
|
||||
b.CountryNum = p.CountryNum;
|
||||
b.PostalDestId = p.Id;
|
||||
if (m.BillingAddress == null) {
|
||||
b.MgNr = newMgNr;
|
||||
await Context.AddAsync(b);
|
||||
} else {
|
||||
Context.Update(b);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, j = 0; i < PhoneNrInputs.Length; i++) {
|
||||
var input = GetPhoneNrInput(i);
|
||||
var phoneNr = m.TelephoneNumbers.FirstOrDefault(p => p.Nr - 1 == i);
|
||||
if (input == null) {
|
||||
if (phoneNr != null) {
|
||||
Context.Remove(phoneNr);
|
||||
}
|
||||
} else {
|
||||
var pInput = input.Value;
|
||||
MemberTelNr p = phoneNr ?? Context.CreateProxy<MemberTelNr>();
|
||||
p.Nr = ++j;
|
||||
p.Type = pInput.Item1;
|
||||
p.Number = pInput.Item2;
|
||||
p.Comment = pInput.Item3;
|
||||
if (phoneNr == null) {
|
||||
p.MgNr = newMgNr;
|
||||
await Context.AddAsync(p);
|
||||
} else {
|
||||
Context.Update(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Context.SaveChangesAsync();
|
||||
|
||||
if (newMgNr != m.MgNr) {
|
||||
await Context.Database.ExecuteSqlAsync($"UPDATE member SET mgnr = {newMgNr} WHERE mgnr = {m.MgNr}");
|
||||
await Context.Members.LoadAsync();
|
||||
tr.State = EntityState.Detached;
|
||||
await Context.SaveChangesAsync();
|
||||
await tr.ReloadAsync();
|
||||
m = await Context.Members.FindAsync(newMgNr);
|
||||
}
|
||||
} catch (Exception exc) {
|
||||
if (tr != null) await tr.ReloadAsync();
|
||||
if (tr != null) {
|
||||
tr.State = EntityState.Detached;
|
||||
await tr.ReloadAsync();
|
||||
}
|
||||
var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message;
|
||||
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
|
||||
MessageBox.Show(str, "Mitglied aktualisieren", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
@@ -322,6 +447,7 @@ namespace Elwig.Windows {
|
||||
|
||||
private void FillInputs(Member m) {
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
|
||||
MgNrInput.Text = m.MgNr.ToString();
|
||||
PredecessorMgNrInput.Text = m.PredecessorMgNr.ToString();
|
||||
@@ -330,45 +456,56 @@ namespace Elwig.Windows {
|
||||
FamilyNameInput.Text = m.FamilyName;
|
||||
SuffixInput.Text = m.Suffix;
|
||||
BirthdayInput.Text = (m.Birthday != null) ? string.Join(".", m.Birthday.Split("-").Reverse()) : null;
|
||||
if (m.Birthday?.Length == 10) {
|
||||
Age.Text = Utils.GetAge(DateOnly.ParseExact(m.Birthday, "yyyy-MM-dd")).ToString();
|
||||
} else if (m.Birthday != null) {
|
||||
Age.Text = "ca. " + (DateTime.Now.Year - int.Parse(m.Birthday[^4..])).ToString();
|
||||
} else {
|
||||
Age.Text = "-";
|
||||
}
|
||||
DeceasedInput.IsChecked = m.IsDeceased;
|
||||
AddressInput.Text = m.Address;
|
||||
AT_PlzDest? p = m.PostalDest.AtPlz;
|
||||
if (p != null) {
|
||||
PlzInput.Text = p.Plz.ToString();
|
||||
OrtInput.ItemsSource = p.AtPlz.Orte;
|
||||
OrtInput.SelectedItem = p;
|
||||
} else {
|
||||
PlzInput.Text = null;
|
||||
OrtInput.ItemsSource = null;
|
||||
OrtInput.SelectedItem = null;
|
||||
}
|
||||
|
||||
EmailInput.Text = m.Email;
|
||||
PhoneLandlineInput.Text = m.PhoneLandline;
|
||||
PhoneMobile1Input.Text = m.PhoneMobile1;
|
||||
PhoneMobile2Input.Text = m.PhoneMobile2;
|
||||
EmailAddressInput.Text = m.Email;
|
||||
var phoneNrs = m.TelephoneNumbers.OrderBy(p => p.Nr).ToList();
|
||||
for (int i = 0; i < PhoneNrInputs.Length; i++) {
|
||||
if (i < phoneNrs.Count) {
|
||||
var phoneNr = phoneNrs[i];
|
||||
SetPhoneNrInput(i, phoneNr.Type, phoneNr.Number, phoneNr.Comment);
|
||||
} else {
|
||||
SetPhoneNrInput(i, null, null, null);
|
||||
}
|
||||
}
|
||||
UpdatePhoneNrInputVisibility(IsEditing || IsCreating);
|
||||
|
||||
IbanInput.Text = m.Iban;
|
||||
BicInput.Text = m.Bic;
|
||||
|
||||
UstIdInput.Text = m.UstId;
|
||||
UstIdNrInput.Text = m.UstIdNr;
|
||||
LfbisNrInput.Text = m.LfbisNr;
|
||||
BuchführendInput.IsChecked = m.IsBuchführend;
|
||||
|
||||
var billingAddr = m.BillingAddress;
|
||||
if (billingAddr != null) {
|
||||
BillingName.Text = billingAddr.Name;
|
||||
BillingNameInput.Text = billingAddr.Name;
|
||||
BillingAddressInput.Text = billingAddr.Address;
|
||||
AT_PlzDest? b = billingAddr.PostalDest.AtPlz;
|
||||
if (b != null) {
|
||||
BillingPlzInput.Text = b.Plz.ToString();
|
||||
BillingOrtInput.ItemsSource = b.AtPlz.Orte;
|
||||
BillingOrtInput.SelectedItem = b;
|
||||
}
|
||||
} else {
|
||||
BillingName.Text = "";
|
||||
BillingNameInput.Text = "";
|
||||
BillingAddressInput.Text = "";
|
||||
BillingPlzInput.Text = "";
|
||||
BillingOrtInput.ItemsSource = null;
|
||||
BillingOrtInput.SelectedItem = null;
|
||||
}
|
||||
|
||||
@@ -382,29 +519,28 @@ namespace Elwig.Windows {
|
||||
ActiveInput.IsChecked = m.IsActive;
|
||||
VollLieferantInput.IsChecked = m.IsVollLieferant;
|
||||
FunkionärInput.IsChecked = m.IsFunktionär;
|
||||
switch (m.DefaultContact) {
|
||||
case "post": ContactPostInput.IsChecked = true; break;
|
||||
case "email": ContactEmailInput.IsChecked = true; break;
|
||||
}
|
||||
ContactPostalInput.IsChecked = m.ContactViaPost;
|
||||
ContactEmailInput.IsChecked = m.ContactViaEmail;
|
||||
|
||||
AreaCommitment.Text = $"{m.ActiveContracts.Select(c => c.Area).Sum():N0} m²";
|
||||
AreaCommitment.Text = $"{m.ActiveAreaCommitments.Select(c => c.Area).Sum():N0} m²";
|
||||
|
||||
Menu_Member_SendEmail.IsEnabled = m.Email != null;
|
||||
|
||||
FillOriginalValues();
|
||||
FinishInputFilling();
|
||||
}
|
||||
|
||||
new protected void ClearInputs() {
|
||||
new protected void ClearInputs(bool validate = false) {
|
||||
Menu_Member_SendEmail.IsEnabled = false;
|
||||
AreaCommitment.Text = "- m²";
|
||||
base.ClearInputs();
|
||||
Age.Text = "-";
|
||||
base.ClearInputs(validate);
|
||||
}
|
||||
|
||||
override protected void UpdateButtons() {
|
||||
if (!IsEditing && !IsCreating) return;
|
||||
bool ch = HasChanged(), v = IsValid();
|
||||
ResetButton.IsEnabled = (ch);
|
||||
SaveButton.IsEnabled = (v && ch);
|
||||
bool ch = HasChanged, v = IsValid;
|
||||
ResetButton.IsEnabled = ch;
|
||||
SaveButton.IsEnabled = v && ch;
|
||||
}
|
||||
|
||||
protected void InputTextChanged(TextBox input, Func<TextBox, bool, AppDbContext, Member?, ValidationResult> checker) {
|
||||
@@ -416,11 +552,11 @@ namespace Elwig.Windows {
|
||||
}
|
||||
|
||||
private void MgNrInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckMgNr);
|
||||
InputTextChanged((TextBox)sender, Validator.CheckNewMgNr);
|
||||
}
|
||||
|
||||
private void MgNrInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckMgNr);
|
||||
InputLostFocus((TextBox)sender, Validator.CheckNewMgNr);
|
||||
}
|
||||
|
||||
private void PredecessorMgNrInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
@@ -430,5 +566,10 @@ namespace Elwig.Windows {
|
||||
private void PredecessorMgNrInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
InputLostFocus((TextBox)sender, Validator.CheckPredecessorMgNr);
|
||||
}
|
||||
|
||||
private new void PhoneNrInput_TextChanged(object sender, RoutedEventArgs evt) {
|
||||
base.PhoneNrInput_TextChanged(sender, evt);
|
||||
UpdatePhoneNrInputVisibility(IsEditing || IsCreating);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
19
Elwig/Windows/QueryWindow.xaml
Normal file
19
Elwig/Windows/QueryWindow.xaml
Normal file
@@ -0,0 +1,19 @@
|
||||
<Window x:Class="Elwig.Windows.QueryWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Datenbankabfragen - Elwig" Height="450" Width="800">
|
||||
<Grid>
|
||||
<TextBox x:Name="QueryInput" Text="SELECT * FROM v_delivery"
|
||||
AcceptsReturn="True" VerticalScrollBarVisibility="Visible" TextWrapping="Wrap"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Top" Margin="10,10,120,10" Height="100"
|
||||
FontFamily="Cascadia Code Light" FontSize="13"/>
|
||||
<Button x:Name="QueryButton" Content="Abfragen"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Top" Margin="10,10,10,10"
|
||||
Click="QueryButton_Click" Height="100" Width="100"
|
||||
FontSize="14"/>
|
||||
<DataGrid x:Name="DataList"
|
||||
AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single"
|
||||
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,120,10,10"/>
|
||||
</Grid>
|
||||
</Window>
|
55
Elwig/Windows/QueryWindow.xaml.cs
Normal file
55
Elwig/Windows/QueryWindow.xaml.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Elwig.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class QueryWindow : Window {
|
||||
public QueryWindow() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void QueryButton_Click(object sender, RoutedEventArgs evt) {
|
||||
try {
|
||||
await ExecuteQuery(QueryInput.Text);
|
||||
} catch (Exception e) {
|
||||
MessageBox.Show(e.Message, "Fehler beim Ausführen", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteQuery(string sqlQuery) {
|
||||
var rows = new List<object[]>();
|
||||
IList<DbColumn> header;
|
||||
|
||||
using (var cnx = await AppDbContext.ConnectAsync()) {
|
||||
var cmd = cnx.CreateCommand();
|
||||
cmd.CommandText = sqlQuery;
|
||||
using var reader = await cmd.ExecuteReaderAsync();
|
||||
header = await reader.GetColumnSchemaAsync();
|
||||
while (await reader.ReadAsync()) {
|
||||
var values = new object[reader.FieldCount];
|
||||
reader.GetValues(values);
|
||||
rows.Add(values);
|
||||
}
|
||||
}
|
||||
|
||||
var styleRight = new Style();
|
||||
styleRight.Setters.Add(new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Right));
|
||||
|
||||
DataList.Columns.Clear();
|
||||
for (int i = 0; i < header.Count; i++) {
|
||||
var h = header[i];
|
||||
DataList.Columns.Add(new DataGridTextColumn {
|
||||
Header = h.ColumnName,
|
||||
Binding = new Binding($"[{i}]"),
|
||||
CellStyle = (h.DataTypeName == "INTEGER" || h.DataTypeName == "REAL") ? styleRight : null,
|
||||
});
|
||||
}
|
||||
DataList.ItemsSource = rows;
|
||||
}
|
||||
}
|
||||
}
|
22
Elwig/Windows/TestWindow.xaml
Normal file
22
Elwig/Windows/TestWindow.xaml
Normal file
@@ -0,0 +1,22 @@
|
||||
<Window x:Class="Elwig.Windows.TestWindow"
|
||||
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.Windows"
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
Title="Test Fenster - Elwig" MinHeight="400" MinWidth="325" Height="450" Width="800" ResizeMode="CanResize">
|
||||
<Grid>
|
||||
<xctk:CheckComboBox x:Name="MyComboBox" HorizontalAlignment="Left" Margin="216,186,0,0" VerticalAlignment="Top" Delimiter=", "
|
||||
SelectedValue="{Binding SelectedValue}"
|
||||
SelectedItemsOverride="{Binding SelectedItems}"
|
||||
ItemSelectionChanged="OnItemSelectionChanged"/>
|
||||
<TextBlock x:Name="MyText" HorizontalAlignment="Left" Margin="318,246,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/>
|
||||
<ListBox x:Name="MyListBox" HorizontalAlignment="Left" Margin="492,125,0,0" VerticalAlignment="Top"/>
|
||||
<Button x:Name="WeighingButton1" Click="WeighingButton1_Click" Height="30" Content="Aktuelles Gewicht" Width="110" Margin="515,246,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<Button x:Name="WeighingButton2" Click="WeighingButton2_Click" Height="30" Content="Wiegen" Width="110" Margin="515,285,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<TextBlock x:Name="Output" Height="20" Width="200" Margin="470,329,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<Button x:Name="ChartButton" Content="Chart" Click="ChartButton_Click"
|
||||
Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</Window>
|
43
Elwig/Windows/TestWindow.xaml.cs
Normal file
43
Elwig/Windows/TestWindow.xaml.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using Xceed.Wpf.Toolkit.Primitives;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class TestWindow : Window {
|
||||
public TestWindow() {
|
||||
InitializeComponent();
|
||||
MyComboBox.ItemsSource = new string[] { "Klasse A" , "Klasse B", "Klasse C", "Klasse D", "Klasse E", "Klasse F" };
|
||||
MyListBox.ItemsSource = new string[] { "Test 1", "Test 2", "Test 3", "Test 4" };
|
||||
}
|
||||
|
||||
private void OnItemSelectionChanged(object sender, ItemSelectionChangedEventArgs e) {
|
||||
MyText.Text = string.Join(", ", MyComboBox.SelectedItems.Cast<string>());
|
||||
}
|
||||
|
||||
private async void WeighingButton1_Click(object sender, RoutedEventArgs evt) {
|
||||
try {
|
||||
var res = await App.Scales[0].GetCurrentWeight();
|
||||
Output.Text = res.ToString();
|
||||
} catch (Exception e) {
|
||||
MessageBox.Show($"Beim Wiegen ist ein Fehler aufgetreten:\n\n{e.Message}", "Waagenfehler",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void WeighingButton2_Click(object sender, RoutedEventArgs evt) {
|
||||
try {
|
||||
var res = await App.Scales[0].Weigh();
|
||||
Output.Text = res.ToString();
|
||||
} catch (Exception e) {
|
||||
MessageBox.Show($"Beim Wiegen ist ein Fehler aufgetreten:\n\n{e.Message}", "Waagenfehler",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ChartButton_Click(object sender, RoutedEventArgs evt) {
|
||||
var w = new ChartWindow();
|
||||
w.Show();
|
||||
}
|
||||
}
|
||||
}
|
BIN
Elwig/elwig.png
Normal file
BIN
Elwig/elwig.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@@ -1,4 +1,6 @@
|
||||
mkdir "C:\ProgramData\Elwig\resources""
|
||||
::mkdir "C:\Program Files\Elwig"
|
||||
::curl -s "http://www.columbia.edu/~em36/PDFtoPrinter.exe" -z "C:\Program Files\Elwig\PDFtoPrinter.exe" -o "C:\Program Files\Elwig\PDFtoPrinter.exe"
|
||||
mkdir "C:\ProgramData\Elwig\resources"
|
||||
curl -s -L "https://unpkg.com/pagedjs/dist/paged.polyfill.js" -o "C:\ProgramData\Elwig\resources\paged.polyfill.js"
|
||||
copy /y "Documents\style.css" "C:\ProgramData\Elwig\resources\style.css"
|
||||
copy /y Documents\*.cshtml "C:\ProgramData\Elwig\resources"
|
||||
copy /b /y "Documents\style.css" "C:\ProgramData\Elwig\resources\style.css"
|
||||
copy /b /y Documents\*.cshtml "C:\ProgramData\Elwig\resources"
|
||||
|
50
Installer/BuildFilesTransform.xslt
Normal file
50
Installer/BuildFilesTransform.xslt
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"
|
||||
xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
||||
|
||||
version="1.0"
|
||||
exclude-result-prefixes="xsl wix">
|
||||
|
||||
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
|
||||
|
||||
<xsl:strip-space elements="*" />
|
||||
|
||||
<!--
|
||||
Find all <Component> elements with <File> elements with Source="" attributes ending in ".exe" and tag it with the "ExeToRemove" key.
|
||||
|
||||
<Component Id="cmpSYYKP6B1M7WSD5KLEQ7PZW4YLOPYG61L" Directory="INSTALLDIR" Guid="*">
|
||||
<File Id="filKUS7ZRMJ0AOKDU6ATYY6IRUSR2ECPDFO" KeyPath="yes" Source="!(wix.StagingAreaPath)\ProofOfPEqualsNP.exe" />
|
||||
</Component>
|
||||
|
||||
Because WiX's Heat.exe only supports XSLT 1.0 and not XSLT 2.0 we cannot use `ends-with( haystack, needle )` (e.g. `ends-with( wix:File/@Source, '.exe' )`...
|
||||
...but we can use this longer `substring` expression instead (see https://github.com/wixtoolset/issues/issues/5609 )
|
||||
-->
|
||||
<xsl:key
|
||||
name="ExeToRemove"
|
||||
match="wix:Component[ substring( wix:File/@Source, string-length( wix:File/@Source ) - 3 ) = '.exe' ]"
|
||||
use="@Id"
|
||||
/>
|
||||
<!-- Get the last 4 characters of a string using `substring( s, len(s) - 3 )`, it uses -3 and not -4 because XSLT uses 1-based indexes, not 0-based indexes. -->
|
||||
|
||||
<!-- We can also remove .pdb files too, for example: -->
|
||||
<xsl:key
|
||||
name="PdbToRemove"
|
||||
match="wix:Component[ substring( wix:File/@Source, string-length( wix:File/@Source ) - 3 ) = '.pdb' ]"
|
||||
use="@Id"
|
||||
/>
|
||||
|
||||
<!-- By default, copy all elements and nodes into the output... -->
|
||||
<xsl:template match="@*|node()">
|
||||
<xsl:copy>
|
||||
<xsl:apply-templates select="@*|node()" />
|
||||
</xsl:copy>
|
||||
</xsl:template>
|
||||
|
||||
<!-- ...but if the element has the "ExeToRemove" key then don't render anything (i.e. removing it from the output) -->
|
||||
<xsl:template match="*[ self::wix:Component or self::wix:ComponentRef ][ key( 'ExeToRemove', @Id ) ]" />
|
||||
|
||||
<xsl:template match="*[ self::wix:Component or self::wix:ComponentRef ][ key( 'PdbToRemove', @Id ) ]" />
|
||||
|
||||
</xsl:stylesheet>
|
12
Installer/DocumentTemplateComponents.wxs
Normal file
12
Installer/DocumentTemplateComponents.wxs
Normal file
@@ -0,0 +1,12 @@
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||
<Fragment>
|
||||
<ComponentGroup Id="DocumentTemplateComponents" Directory="ConfigFolderResources">
|
||||
<Component>
|
||||
<File Source="$(TargetDir)\paged.polyfill.js" />
|
||||
</Component>
|
||||
<Component>
|
||||
<File Source="$(var.ElwigProjectDir)\Documents\style.css" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
</Wix>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user