diff --git a/Elwig/Models/WineCult.cs b/Elwig/Models/WineCult.cs index 4c66c05..eeb1341 100644 --- a/Elwig/Models/WineCult.cs +++ b/Elwig/Models/WineCult.cs @@ -12,6 +12,6 @@ namespace Elwig.Models { public string Name { get; set; } [Column("description")] - public string Description { get; set; } + public string? Description { get; set; } } } diff --git a/Elwig/Windows/AdministrationWindow.cs b/Elwig/Windows/AdministrationWindow.cs index e0ad153..532b0d4 100644 --- a/Elwig/Windows/AdministrationWindow.cs +++ b/Elwig/Windows/AdministrationWindow.cs @@ -71,7 +71,7 @@ namespace Elwig.Windows { 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(); + PlzInputs = ControlUtils.FindAllChildren<TextBox>(this).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; @@ -317,7 +317,7 @@ namespace Elwig.Windows { ); protected void UpdatePlz(TextBox plzInput, ComboBox ortInput) { - var plzInputValid = GetInputValid(plzInput); + var plzInputValid = Validator.CheckPlz(plzInput, RequiredInputs.Contains(plzInput), Context).IsValid; 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); @@ -551,5 +551,13 @@ namespace Elwig.Windows { protected void LfbisNrInput_LostFocus(object sender, RoutedEventArgs evt) { InputLostFocus((TextBox)sender, Validator.CheckLfbisNr); } + + protected void UpperCaseInput_TextChanged(object sender, RoutedEventArgs evt) { + InputTextChanged((TextBox)sender, Validator.CheckUpperCase); + } + + protected void UpperCaseInput_LostFocus(object sender, RoutedEventArgs evt) { + InputLostFocus((TextBox)sender, Validator.CheckUpperCase); + } } } diff --git a/Elwig/Windows/BaseDataWindow.xaml b/Elwig/Windows/BaseDataWindow.xaml index 690782e..bbafb13 100644 --- a/Elwig/Windows/BaseDataWindow.xaml +++ b/Elwig/Windows/BaseDataWindow.xaml @@ -133,13 +133,181 @@ </Grid> </TabItem> <TabItem Header="Zweigstellen"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="260"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <ListBox x:Name="BranchList" Margin="10,10,35,10" + SelectionChanged="BranchList_SelectionChanged" Grid.Column="0"> + <ListBox.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal"> + <TextBlock Text="{Binding ZwstId}" Width="20"/> + <TextBlock Text="{Binding Name}"/> + </StackPanel> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + <Button x:Name="BranchAddButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" + Click="BranchAddButton_Click" + VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,0,5,30" Grid.Column="0"/> + <Button x:Name="BranchDeleteButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" + Click="BranchDeleteButton_Click" + VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,30,5,0" Grid.Column="0"/> + <Grid Grid.Column="1" Margin="0,10,0,10"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="110"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + + <Label Content="Identifikator:" Margin="10,10,0,10"/> + <TextBox x:Name="BranchIdInput" Grid.Column="1" Margin="0,10,10,10" Width="50" HorizontalAlignment="Left" + TextChanged="Branch_Changed"/> + + <Label Content="Name:" Margin="10,40,0,10"/> + <TextBox x:Name="BranchNameInput" Grid.Column="1" Margin="0,40,10,10" Width="150" HorizontalAlignment="Left" + TextChanged="Branch_Changed"/> + + <Label Content="PLZ/Ort:" Margin="10,70,0,10"/> + <TextBox x:Name="BranchPlzInput" Margin="0,70,0,0" Width="42" Grid.Column="1" HorizontalAlignment="Left" + TextChanged="BranchPlzInput_TextChanged" LostFocus="PlzInput_LostFocus" Tag="PLZ"/> + <ComboBox x:Name="BranchOrtInput" ItemTemplate="{StaticResource PostalDestTemplate}" TextSearch.TextPath="Ort.Name" + Margin="47,70,10,0" Grid.Column="1" Grid.ColumnSpan="3" Width="253" HorizontalAlignment="Left" + SelectionChanged="Branch_Changed"/> + + <Label Content="Adresse:" Margin="10,100,0,10"/> + <TextBox x:Name="BranchAddressInput" Grid.Column="1" Margin="0,100,10,10" Width="300" HorizontalAlignment="Left" + TextChanged="Branch_Changed"/> + + <Label Content="Tel.-Nr. (Festnetz):" Margin="10,130,0,10"/> + <TextBox x:Name="BranchPhoneNrInput" Grid.Column="1" Margin="0,130,10,10" Width="200" HorizontalAlignment="Left" + TextChanged="BranchPhoneNr_TextChanged"/> + + <Label Content="Fax-Nr.:" Margin="10,160,0,10"/> + <TextBox x:Name="BranchFaxNrInput" Grid.Column="1" Margin="0,160,10,10" Width="200" HorizontalAlignment="Left" + TextChanged="BranchPhoneNr_TextChanged"/> + + <Label Content="Tel.-Nr. (mobil):" Margin="10,190,0,10"/> + <TextBox x:Name="BranchMobileNrInput" Grid.Column="1" Margin="0,190,10,10" Width="200" HorizontalAlignment="Left" + TextChanged="BranchPhoneNr_TextChanged"/> + </Grid> + </Grid> </TabItem> <TabItem Header="Sortenattribute"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="260"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <ListBox x:Name="WineAttributeList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,10,35,10" + SelectionChanged="WineAttributeList_SelectionChanged"> + <ListBox.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal"> + <TextBlock Text="{Binding AttrId}" Width="30"/> + <TextBlock Text="{Binding Name}" Width="80"/> + <TextBlock Text="{Binding MaxKgPerHa, StringFormat='{}{0:N0} kg'}" Width="60" TextAlignment="Right" Margin="0,0,5,0"/> + <CheckBox IsChecked="{Binding IsActive}" IsEnabled="False" Margin="10,0,10,0"/> + </StackPanel> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + <Button x:Name="WineAttributeAddButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" + Click="WineAttributeAddButton_Click" + VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,0,5,30"/> + <Button x:Name="WineAttributeDeleteButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" + Click="WineAttributeDeleteButton_Click" + VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,30,5,0"/> + <Grid Grid.Column="1" Margin="0,10,0,10"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + + <Label Content="Identifikator:" Margin="10,10,0,10"/> + <TextBox x:Name="WineAttributeIdInput" Grid.Column="1" Margin="0,10,10,10" Width="50" HorizontalAlignment="Left" + TextChanged="WineAttributeIdInput_TextChanged"/> + + <Label Content="Name:" Margin="10,40,0,10"/> + <TextBox x:Name="WineAttributeNameInput" Grid.Column="1" Margin="0,40,10,10" Width="150" HorizontalAlignment="Left" + TextChanged="WineAttribute_Changed"/> + + <CheckBox x:Name="WineAttributeActiveInput" Content="In Übernahme-Fenster anzeigen" + Grid.Column="1" Margin="0,74,10,10" HorizontalAlignment="Left" VerticalAlignment="Top" + Checked="WineAttribute_Changed" Unchecked="WineAttribute_Changed"/> + + <GroupBox Header="Auszahlung" Grid.ColumnSpan="2" Margin="10,100,10,10"> + <Grid> + <Label Content="Max. Ertrag:" Margin="10,10,0,10"/> + <Grid Grid.Column="1" Width="80" Height="25" Margin="84,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"> + <TextBox x:Name="WineAttributeMaxKgPerHaInput" TextAlignment="Right" Padding="2,2,30,2" + TextChanged="WineAttributeMaxKgPerHaInput_TextChanged"/> + <Label Content="kg/ha" Margin="0,4,3,0" HorizontalAlignment="Right" FontSize="10"/> + </Grid> + + <CheckBox x:Name="WineAttributeStrictInput" Content="Strikte Trennung zu Flächenbindung ohne Attribut" + Margin="10,50,10,10" HorizontalAlignment="Left" VerticalAlignment="Top" + Checked="WineAttributeStrictInput_Changed" Unchecked="WineAttributeStrictInput_Changed"/> + + <Label x:Name="WineAttributeFillLowerLabel" Content="Wenn möglich, Flächenbindung ohne Attribut..." Margin="10,75,10,10"/> + <ComboBox x:Name="WineAttributeFillLowerInput" Width="300" + Margin="10,100,10,10" HorizontalAlignment="Left" + SelectionChanged="WineAttribute_Changed"> + <ComboBoxItem>...nicht auffüllen</ComboBoxItem> + <ComboBoxItem>...bis Lieferpflicht auffüllen</ComboBoxItem> + <ComboBoxItem>...bis Lieferrecht auffüllen</ComboBoxItem> + </ComboBox> + </Grid> + </GroupBox> + </Grid> + </Grid> </TabItem> <TabItem Header="Bewirtschaftungsarten"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="260"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + <ListBox x:Name="WineCultivationList" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,10,35,10" + SelectionChanged="WineCultivationList_SelectionChanged"> + <ListBox.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal"> + <TextBlock Text="{Binding CultId}" Width="30"/> + <TextBlock Text="{Binding Name}"/> + </StackPanel> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + <Button x:Name="WineCultivationAddButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" + Click="WineCultivationAddButton_Click" + VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,0,5,30"/> + <Button x:Name="WineCultivationDeleteButton" Content="" FontFamily="Segoe MDL2 Assets" FontSize="11" Padding="0,1.5,0,0" IsEnabled="False" + Click="WineCultivationDeleteButton_Click" + VerticalAlignment="Center" HorizontalAlignment="Right" Width="25" Height="25" Margin="5,30,5,0"/> + <Grid Grid.Column="1" Margin="0,10,0,10"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="100"/> + <ColumnDefinition Width="*"/> + </Grid.ColumnDefinitions> + + <Label Content="Identifikator:" Margin="10,10,0,10"/> + <TextBox x:Name="WineCultivationIdInput" Grid.Column="1" Margin="0,10,10,10" Width="50" HorizontalAlignment="Left" + TextChanged="WineCultivationIdInput_TextChanged"/> + + <Label Content="Name:" Margin="10,40,0,10"/> + <TextBox x:Name="WineCultivationNameInput" Grid.Column="1" Margin="0,40,10,10" Width="150" HorizontalAlignment="Left" + TextChanged="WineCultivation_Changed"/> + + <Label Content="Beschreibung:" Margin="10,70,0,10"/> + <TextBox x:Name="WineCultivationDescriptionInput" Grid.Column="1" Margin="0,70,10,10" + TextChanged="WineCultivation_Changed"/> + </Grid> + </Grid> </TabItem> <TabItem Header="Flächenbindungsverträge"> @@ -198,7 +366,7 @@ <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"/> + TextChanged="SeasonModifier_Changed"/> <Label Content="Relativ:" Grid.Column="1" Margin="10,70,10,10"/> <TextBox x:Name="SeasonModifierRelInput" Grid.Column="2" Margin="0,70,10,10" diff --git a/Elwig/Windows/BaseDataWindow.xaml.Branch.cs b/Elwig/Windows/BaseDataWindow.xaml.Branch.cs new file mode 100644 index 0000000..c230dfe --- /dev/null +++ b/Elwig/Windows/BaseDataWindow.xaml.Branch.cs @@ -0,0 +1,150 @@ +using Elwig.Models; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Windows.Controls; +using System.Windows; +using Elwig.Helpers; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace Elwig.Windows { + public partial class BaseDataWindow { + + private Dictionary<string, string?>? _branches = null; + private Dictionary<Branch, string>? _branchIds = null; + private ObservableCollection<Branch>? _branchList = null; + private bool _branchChanged = false; + private bool _branchUpdate = false; + + private void BranchesInitEditing() { + _branchList = new(Context.Branches.OrderBy(b => b.Name).ToList()); + _branches = _branchList.ToDictionary(b => b.ZwstId, b => (string?)b.ZwstId); + _branchIds = _branchList.ToDictionary(b => b, b => b.ZwstId); + ControlUtils.RenewItemsSource(BranchList, _branchList, b => (b as Branch)?.ZwstId); + } + + private void BranchesFinishEditing() { + ControlUtils.RenewItemsSource(BranchList, Context.Branches.OrderBy(b => b.Name).ToList(), b => (b as Branch)?.ZwstId); + _branchList = null; + _branches = null; + _branchIds = null; + _branchChanged = false; + + BranchAddButton.IsEnabled = false; + BranchDeleteButton.IsEnabled = false; + } + + private async Task BranchesSave() { + if (!_branchChanged || _branchList == null || _branches == null || _branchIds == null) + return; + + foreach (var (zwstid, _) in _branches.Where(b => b.Value == null)) { + Context.Remove(Context.Branches.Find(zwstid)); + } + foreach (var (branch, old) in _branchIds) { + branch.ZwstId = old; + } + foreach (var (old, zwstid) in _branches.Where(b => b.Value != null)) { + Context.Update(Context.Branches.Find(old)); + } + await Context.SaveChangesAsync(); + + foreach (var (old, zwstid) in _branches.Where(b => b.Value != null)) { + await Context.Database.ExecuteSqlAsync($"UPDATE branch SET zwstid = {zwstid} WHERE zwstid = {old}"); + } + await Context.SaveChangesAsync(); + + foreach (var branch in _branchList.Where(b => !_branchIds.ContainsKey(b))) { + if (branch.ZwstId == null) continue; + await Context.AddAsync(branch); + } + await Context.SaveChangesAsync(); + } + + private void BranchList_SelectionChanged(object sender, SelectionChangedEventArgs evt) { + UpdateButtons(); + _branchUpdate = true; + if (BranchList.SelectedItem is not Branch branch) { + BranchIdInput.Text = ""; + BranchNameInput.Text = ""; + BranchPlzInput.Text = ""; + BranchAddressInput.Text = ""; + BranchPhoneNrInput.Text = ""; + BranchFaxNrInput.Text = ""; + BranchMobileNrInput.Text = ""; + } else { + BranchIdInput.Text = branch.ZwstId; + BranchNameInput.Text = branch.Name; + BranchPlzInput.Text = branch.PostalDest?.AtPlz?.Plz.ToString() ?? ""; + ControlUtils.SelectComboBoxItem(BranchOrtInput, o => (o as AT_PlzDest)?.Okz, branch.PostalDest?.AtPlz?.Okz); + BranchAddressInput.Text = branch.Address; + BranchPhoneNrInput.Text = branch.PhoneNr; + BranchFaxNrInput.Text = branch.FaxNr; + BranchMobileNrInput.Text = branch.MobileNr; + } + _branchUpdate = false; + } + + private void BranchAddButton_Click(object sender, RoutedEventArgs evt) { + if (_branchList == null) return; + _branchChanged = true; + var item = Context.CreateProxy<Branch>(); + _branchList.Add(item); + BranchList.SelectedItem = item; + UpdateButtons(); + } + + private void BranchDeleteButton_Click(object sender, RoutedEventArgs evt) { + if (_branchList == null || _branches == null) return; + _branchChanged = true; + var idx = BranchList.SelectedIndex; + var item = _branchList[idx]; + _branches[item.ZwstId] = null; + _branchList.RemoveAt(idx); + BranchList.SelectedIndex = idx < _branchList.Count ? idx : idx - 1; + UpdateButtons(); + } + + private void Branch_Changed(object? sender, RoutedEventArgs? evt) { + if (_branchUpdate || (!IsEditing && !IsCreating) || BranchList.SelectedItem is not Branch branch || _branches == null || _branchIds == null) return; + _branchChanged = _branchChanged || + BranchIdInput.Text != branch.ZwstId || + BranchNameInput.Text != branch.Name || + BranchPlzInput.Text != (branch.PostalDest?.AtPlz?.Plz.ToString() ?? "") || + (BranchOrtInput.SelectedItem as AT_PlzDest)?.Okz != branch.PostalDest?.AtPlz?.Okz || + BranchAddressInput.Text != branch.Address || + BranchPhoneNrInput.Text != (branch.PhoneNr ?? "") || + BranchFaxNrInput.Text != (branch.FaxNr ?? "") || + BranchMobileNrInput.Text != (branch.MobileNr ?? ""); + + var old = _branchIds.GetValueOrDefault(branch); + var id = BranchIdInput.Text; + if (old != null) _branches[old] = id; + branch.ZwstId = id; + branch.Name = BranchNameInput.Text; + branch.PostalDestId = (BranchOrtInput.SelectedItem as AT_PlzDest)?.Id; + branch.Address = BranchAddressInput.Text; + branch.PhoneNr = BranchPhoneNrInput.Text; + branch.FaxNr = BranchFaxNrInput.Text; + branch.MobileNr = BranchMobileNrInput.Text; + if (branch.PhoneNr.Length == 0) branch.PhoneNr = null; + if (branch.FaxNr.Length == 0) branch.FaxNr = null; + if (branch.MobileNr.Length == 0) branch.MobileNr = null; + + CollectionViewSource.GetDefaultView(_branchList).Refresh(); + UpdateButtons(); + } + + private void BranchPlzInput_TextChanged(object sender, TextChangedEventArgs evt) { + PlzInput_TextChanged(sender, evt); + Branch_Changed(sender, evt); + } + + private void BranchPhoneNr_TextChanged(object sender, TextChangedEventArgs evt) { + PhoneNrInput_TextChanged(sender, evt); + Branch_Changed(sender, evt); + } + } +} diff --git a/Elwig/Windows/BaseDataWindow.xaml.Mod.cs b/Elwig/Windows/BaseDataWindow.xaml.Mod.cs new file mode 100644 index 0000000..b610def --- /dev/null +++ b/Elwig/Windows/BaseDataWindow.xaml.Mod.cs @@ -0,0 +1,170 @@ +using Elwig.Helpers; +using Elwig.Models; +using Microsoft.EntityFrameworkCore; +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 { + + private Dictionary<string, string?>? _mods = null; + private Dictionary<Modifier, string>? _modIds = null; + private ObservableCollection<Modifier>? _modList = null; + private bool _modChanged = false; + private bool _modUpdate = false; + + private void ModifiersInitEditing() { + var year = (SeasonList.SelectedItem as Season)?.Year; + _modList = new(Context.Modifiers.Where(m => m.Year == year).OrderBy(m => m.Ordering).ToList()); + _mods = _modList.ToDictionary(m => m.ModId, m => (string?)m.ModId); + _modIds = _modList.ToDictionary(m => m, m => m.ModId); + ControlUtils.RenewItemsSource(SeasonModifierList, _modList, 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); + _modList = null; + _mods = null; + _modIds = null; + _modChanged = false; + + SeasonModifierUpButton.IsEnabled = false; + SeasonModifierDownButton.IsEnabled = false; + SeasonModifierAddButton.IsEnabled = false; + SeasonModifierDeleteButton.IsEnabled = false; + } + + private async Task ModifiersSave() { + if (!_modChanged || _modList == null || _mods == null || _modIds == null) + return; + + int i = 0; + foreach (var mod in _modList) mod.Ordering = ++i; + + var year = (SeasonList.SelectedItem as Season)?.Year; + foreach (var (modid, _) in _mods.Where(m => m.Value == null)) { + Context.Remove(Context.Modifiers.Find(new object?[] { year, modid })); + } + foreach (var (mod, old) in _modIds) { + mod.ModId = old; + } + foreach (var (old, modid) in _mods.Where(m => m.Value != null)) { + Context.Update(Context.Modifiers.Find(new object?[] { year, old })); + } + await Context.SaveChangesAsync(); + + foreach (var (old, modid) in _mods.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 _modList.Where(m => !_modIds.ContainsKey(m))) { + if (mod.ModId == null) continue; + await Context.AddAsync(mod); + } + await Context.SaveChangesAsync(); + } + + private void SeasonModifierUpButton_Click(object sender, RoutedEventArgs evt) { + if (_modList == null) return; + _modChanged = true; + var idx = SeasonModifierList.SelectedIndex; + var item = _modList[idx]; + _modList.RemoveAt(idx); + idx--; + _modList.Insert(idx, item); + SeasonModifierList.SelectedIndex = idx; + UpdateButtons(); + } + + private void SeasonModifierDownButton_Click(object sender, RoutedEventArgs evt) { + if (_modList == null) return; + _modChanged = true; + var idx = SeasonModifierList.SelectedIndex; + var item = _modList[idx]; + _modList.RemoveAt(idx); + idx++; + _modList.Insert(idx, item); + SeasonModifierList.SelectedIndex = idx; + UpdateButtons(); + } + + private void SeasonModifierAddButton_Click(object sender, RoutedEventArgs evt) { + if (_modList == null || SeasonList.SelectedItem is not Season s) return; + _modChanged = true; + var idx = (SeasonModifierList.SelectedIndex != -1) ? SeasonModifierList.SelectedIndex + 1 : _modList.Count; + var item = Context.CreateProxy<Modifier>(); + item.Year = s.Year; + _modList.Insert(idx, item); + SeasonModifierList.SelectedIndex = idx; + UpdateButtons(); + } + + private void SeasonModifierDeleteButton_Click(object sender, RoutedEventArgs evt) { + if (_modList == null || _mods == null) return; + _modChanged = true; + var idx = SeasonModifierList.SelectedIndex; + var item = _modList[idx]; + _mods[item.ModId] = null; + _modList.RemoveAt(idx); + SeasonModifierList.SelectedIndex = idx < _modList.Count ? idx : idx - 1; + UpdateButtons(); + } + + private void SeasonModifierList_SelectionChanged(object sender, SelectionChangedEventArgs evt) { + UpdateButtons(); + _modUpdate = 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(); + } + _modUpdate = false; + } + + private void SeasonModifier_Changed(object? sender, RoutedEventArgs evt) { + if (_modUpdate || (!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod || SeasonList.SelectedItem is not Season s || _mods == null || _modIds == null) return; + _modChanged = _modChanged || + SeasonModifierIdInput.Text != mod.ModId; + + var old = _modIds.GetValueOrDefault(mod); + var id = SeasonModifierIdInput.Text ?? ""; + if (old != null) _mods[old] = id; + mod.ModId = id; + mod.Rel = decimal.TryParse(SeasonModifierRelInput.Text, out var vRel) ? vRel / 100 : null; + if (mod.Rel != null) SeasonModifierAbsInput.Text = ""; + mod.AbsValue = decimal.TryParse(SeasonModifierAbsInput.Text, out var vAbs) ? Utils.DecToDb(vAbs, s.Precision) : null; + if (mod.AbsValue != null) SeasonModifierRelInput.Text = ""; + + CollectionViewSource.GetDefaultView(_modList).Refresh(); + UpdateButtons(); + } + + private void SeasonModifierIdInput_TextChanged(object sender, TextChangedEventArgs evt) { + UpperCaseInput_TextChanged(sender, evt); + SeasonModifier_Changed(sender, evt); + } + + private void SeasonModifierRelInput_TextChanged(object sender, TextChangedEventArgs evt) { + // DecimalInput_TextChanged(sender, evt); FIXME '-' is ignored + SeasonModifier_Changed(sender, evt); + } + + private void SeasonModifierAbsInput_TextChanged(object sender, TextChangedEventArgs evt) { + // DecimalInput_TextChanged(sender, evt); FIXME '-' is ignored + SeasonModifier_Changed(sender, evt); + } + } +} diff --git a/Elwig/Windows/BaseDataWindow.xaml.WineAttr.cs b/Elwig/Windows/BaseDataWindow.xaml.WineAttr.cs new file mode 100644 index 0000000..449881a --- /dev/null +++ b/Elwig/Windows/BaseDataWindow.xaml.WineAttr.cs @@ -0,0 +1,150 @@ +using Elwig.Helpers; +using Elwig.Models; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows; + +namespace Elwig.Windows { + public partial class BaseDataWindow { + + private Dictionary<string, string?>? _attrs = null; + private Dictionary<WineAttr, string>? _attrIds = null; + private ObservableCollection<WineAttr>? _attrList = null; + private bool _attrChanged = false; + private bool _attrUpdate = false; + + private void WineAttributesInitEditing() { + SeasonList.IsEnabled = false; + _attrList = new(Context.WineAttributes.OrderBy(a => a.Name).ToList()); + _attrs = _attrList.ToDictionary(a => a.AttrId, a => (string?)a.AttrId); + _attrIds = _attrList.ToDictionary(a => a, a => a.AttrId); + ControlUtils.RenewItemsSource(WineAttributeList, _attrList, a => (a as WineAttr)?.AttrId); + } + + private void WineAttributesFinishEditing() { + ControlUtils.RenewItemsSource(WineAttributeList, Context.WineAttributes.OrderBy(a => a.Name).ToList(), a => (a as WineAttr)?.AttrId); + _attrList = null; + _attrs = null; + _attrIds = null; + _attrChanged = false; + + WineAttributeAddButton.IsEnabled = false; + WineAttributeDeleteButton.IsEnabled = false; + SeasonList.IsEnabled = true; + } + + private async Task WineAttributesSave() { + if (!_attrChanged || _attrList == null || _attrs == null || _attrIds == null) + return; + + foreach (var (attrid, _) in _attrs.Where(a => a.Value == null)) { + Context.Remove(Context.WineAttributes.Find(attrid)); + } + foreach (var (attr, old) in _attrIds) { + attr.AttrId = old; + } + foreach (var (old, attrid) in _attrs.Where(a => a.Value != null)) { + Context.Update(Context.WineAttributes.Find(old)); + } + await Context.SaveChangesAsync(); + + foreach (var (old, attrid) in _attrs.Where(a => a.Value != null)) { + await Context.Database.ExecuteSqlAsync($"UPDATE wine_attribute SET attrid = {attrid} WHERE attrid = {old}"); + } + await Context.SaveChangesAsync(); + + foreach (var attr in _attrList.Where(a => !_attrIds.ContainsKey(a))) { + if (attr.AttrId == null) continue; + await Context.AddAsync(attr); + } + await Context.SaveChangesAsync(); + } + + private void WineAttributeList_SelectionChanged(object sender, SelectionChangedEventArgs evt) { + UpdateButtons(); + _attrUpdate = true; + if (WineAttributeList.SelectedItem is not WineAttr attr) { + WineAttributeIdInput.Text = ""; + WineAttributeNameInput.Text = ""; + WineAttributeActiveInput.IsChecked = false; + WineAttributeMaxKgPerHaInput.Text = ""; + WineAttributeStrictInput.IsChecked = false; + WineAttributeFillLowerInput.SelectedItem = null; + } else { + WineAttributeIdInput.Text = attr.AttrId; + WineAttributeNameInput.Text = attr.Name; + WineAttributeActiveInput.IsChecked = attr.IsActive; + WineAttributeMaxKgPerHaInput.Text = attr.MaxKgPerHa?.ToString() ?? ""; + WineAttributeStrictInput.IsChecked = attr.IsStrict; + WineAttributeFillLowerInput.SelectedIndex = attr.FillLower; + } + _attrUpdate = false; + } + + private void WineAttributeAddButton_Click(object sender, RoutedEventArgs evt) { + if (_attrList == null) return; + _attrChanged = true; + var item = Context.CreateProxy<WineAttr>(); + _attrList.Add(item); + WineAttributeList.SelectedItem = item; + UpdateButtons(); + } + + private void WineAttributeDeleteButton_Click(object sender, RoutedEventArgs evt) { + if (_attrList == null || _attrs == null) return; + _attrChanged = true; + var idx = WineAttributeList.SelectedIndex; + var item = _attrList[idx]; + _attrs[item.AttrId] = null; + _attrList.RemoveAt(idx); + WineAttributeList.SelectedIndex = idx < _attrList.Count ? idx : idx - 1; + UpdateButtons(); + } + + private void WineAttribute_Changed(object? sender, RoutedEventArgs? evt) { + if (_attrUpdate || (!IsEditing && !IsCreating) || WineAttributeList.SelectedItem is not WineAttr attr || _attrs == null || _attrIds == null) return; + _attrChanged = _attrChanged || + WineAttributeIdInput.Text != attr.AttrId || + WineAttributeNameInput.Text != attr.Name || + WineAttributeActiveInput.IsChecked != attr.IsActive || + WineAttributeMaxKgPerHaInput.Text != attr.MaxKgPerHa?.ToString() || + WineAttributeStrictInput.IsChecked != attr.IsStrict || + WineAttributeFillLowerInput.SelectedIndex != attr.FillLower; + + var old = _attrIds.GetValueOrDefault(attr); + var id = WineAttributeIdInput.Text; + if (old != null) _attrs[old] = id; + attr.AttrId = id; + attr.Name = WineAttributeNameInput.Text ?? ""; + attr.IsActive = WineAttributeActiveInput.IsChecked ?? false; + attr.MaxKgPerHa = WineAttributeMaxKgPerHaInput.Text.Length > 0 ? int.Parse(WineAttributeMaxKgPerHaInput.Text) : null; + attr.IsStrict = WineAttributeStrictInput.IsChecked ?? false; + attr.FillLower = WineAttributeFillLowerInput.SelectedIndex; + + CollectionViewSource.GetDefaultView(_attrList).Refresh(); + CollectionViewSource.GetDefaultView(_attrList).Refresh(); + UpdateButtons(); + } + + private void WineAttributeIdInput_TextChanged(object sender, TextChangedEventArgs evt) { + UpperCaseInput_TextChanged(sender, evt); + WineAttribute_Changed(sender, evt); + } + + private void WineAttributeMaxKgPerHaInput_TextChanged(object sender, TextChangedEventArgs evt) { + InputTextChanged((TextBox)sender, Validator.CheckInteger((TextBox)sender, false, 5)); + WineAttribute_Changed(sender, evt); + } + + private void WineAttributeStrictInput_Changed(object sender, RoutedEventArgs evt) { + WineAttributeFillLowerInput.Visibility = WineAttributeStrictInput.IsChecked == true ? Visibility.Visible : Visibility.Hidden; + WineAttributeFillLowerLabel.Visibility = WineAttributeFillLowerInput.Visibility; + WineAttribute_Changed(sender, evt); + } + } +} diff --git a/Elwig/Windows/BaseDataWindow.xaml.WineCult.cs b/Elwig/Windows/BaseDataWindow.xaml.WineCult.cs new file mode 100644 index 0000000..035b54b --- /dev/null +++ b/Elwig/Windows/BaseDataWindow.xaml.WineCult.cs @@ -0,0 +1,125 @@ +using Elwig.Helpers; +using Elwig.Models; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows; + +namespace Elwig.Windows { + public partial class BaseDataWindow { + + private Dictionary<string, string?>? _cults = null; + private Dictionary<WineCult, string>? _cultIds = null; + private ObservableCollection<WineCult>? _cultList = null; + private bool _cultChanged = false; + private bool _cultUpdate = false; + + private void WineCultivationsInitEditing() { + _cultList = new(Context.WineCultivations.OrderBy(c => c.Name).ToList()); + _cults = _cultList.ToDictionary(c => c.CultId, c => (string?)c.CultId); + _cultIds = _cultList.ToDictionary(c => c, c => c.CultId); + ControlUtils.RenewItemsSource(WineCultivationList, _cultList, c => (c as WineCult)?.CultId); + } + + private void WineCultivationsFinishEditing() { + ControlUtils.RenewItemsSource(WineCultivationList, Context.WineCultivations.OrderBy(c => c.Name).ToList(), c => (c as WineCult)?.CultId); + _cultList = null; + _cults = null; + _cultIds = null; + _cultChanged = false; + + WineCultivationAddButton.IsEnabled = false; + WineCultivationDeleteButton.IsEnabled = false; + } + + private async Task WineCultivationsSave() { + if (!_cultChanged || _cultList == null || _cults == null || _cultIds == null) + return; + + foreach (var (cultid, _) in _cults.Where(c => c.Value == null)) { + Context.Remove(Context.WineCultivations.Find(cultid)); + } + foreach (var (cult, old) in _cultIds) { + cult.CultId = old; + } + foreach (var (old, cultid) in _cults.Where(c => c.Value != null)) { + Context.Update(Context.WineCultivations.Find(old)); + } + await Context.SaveChangesAsync(); + + foreach (var (old, cultid) in _cults.Where(c => c.Value != null)) { + await Context.Database.ExecuteSqlAsync($"UPDATE wine_cultivation SET cultid = {cultid} WHERE cultid = {old}"); + } + await Context.SaveChangesAsync(); + + foreach (var cult in _cultList.Where(c => !_cultIds.ContainsKey(c))) { + if (cult.CultId == null) continue; + await Context.AddAsync(cult); + } + await Context.SaveChangesAsync(); + } + + private void WineCultivationList_SelectionChanged(object sender, SelectionChangedEventArgs evt) { + UpdateButtons(); + _cultUpdate = true; + if (WineCultivationList.SelectedItem is not WineCult cult) { + WineCultivationIdInput.Text = ""; + WineCultivationNameInput.Text = ""; + WineCultivationDescriptionInput.Text = ""; + } else { + WineCultivationIdInput.Text = cult.CultId; + WineCultivationNameInput.Text = cult.Name; + WineCultivationDescriptionInput.Text = cult.Description; + } + _cultUpdate = false; + } + + private void WineCultivationAddButton_Click(object sender, RoutedEventArgs evt) { + if (_cultList == null) return; + _cultChanged = true; + var item = Context.CreateProxy<WineCult>(); + _cultList.Add(item); + WineCultivationList.SelectedItem = item; + UpdateButtons(); + } + + private void WineCultivationDeleteButton_Click(object sender, RoutedEventArgs evt) { + if (_cultList == null || _cults == null) return; + _cultChanged = true; + var idx = WineCultivationList.SelectedIndex; + var item = _cultList[idx]; + _cults[item.CultId] = null; + _cultList.RemoveAt(idx); + WineCultivationList.SelectedIndex = idx < _cultList.Count ? idx : idx - 1; + UpdateButtons(); + } + + private void WineCultivation_Changed(object? sender, RoutedEventArgs? evt) { + if (_cultUpdate || (!IsEditing && !IsCreating) || WineCultivationList.SelectedItem is not WineCult cult || _cults == null || _cultIds == null) return; + _cultChanged = _cultChanged || + WineCultivationIdInput.Text != cult.CultId || + WineCultivationNameInput.Text != cult.Name || + WineCultivationDescriptionInput.Text != (cult.Description ?? ""); + + var old = _cultIds.GetValueOrDefault(cult); + var id = WineCultivationIdInput.Text ?? ""; + if (old != null) _cults[old] = id; + cult.CultId = id; + cult.Name = WineCultivationNameInput.Text ?? ""; + cult.Description = WineCultivationDescriptionInput.Text ?? ""; + if (cult.Description.Length == 0) cult.Description = null; + + CollectionViewSource.GetDefaultView(_cultList).Refresh(); + UpdateButtons(); + } + + private void WineCultivationIdInput_TextChanged(object sender, TextChangedEventArgs evt) { + UpperCaseInput_TextChanged(sender, evt); + WineCultivation_Changed(sender, evt); + } + } +} diff --git a/Elwig/Windows/BaseDataWindow.xaml.cs b/Elwig/Windows/BaseDataWindow.xaml.cs index 898b3f6..1b25e6b 100644 --- a/Elwig/Windows/BaseDataWindow.xaml.cs +++ b/Elwig/Windows/BaseDataWindow.xaml.cs @@ -2,23 +2,14 @@ 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[] { @@ -27,12 +18,40 @@ namespace Elwig.Windows { }; ExemptInputs = new Control[] { ClientNameFull, + BranchIdInput, BranchNameInput, BranchPlzInput, BranchOrtInput, + BranchAddressInput, BranchPhoneNrInput, BranchFaxNrInput, BranchMobileNrInput, + WineAttributeIdInput, WineAttributeNameInput, WineAttributeActiveInput, + WineAttributeMaxKgPerHaInput, WineAttributeStrictInput, WineAttributeFillLowerInput, + WineCultivationIdInput, WineCultivationNameInput, WineCultivationDescriptionInput, SeasonModifierIdInput, SeasonModifierNameInput, SeasonModifierRelInput, SeasonModifierAbsInput, }; + WineAttributeFillLowerInput.Visibility = Visibility.Hidden; + WineAttributeFillLowerLabel.Visibility = Visibility.Hidden; } new protected void LockInputs() { base.LockInputs(); + + BranchIdInput.IsReadOnly = true; + BranchNameInput.IsReadOnly = true; + BranchPlzInput.IsReadOnly = true; + BranchOrtInput.IsEnabled = false; + BranchAddressInput.IsReadOnly = true; + BranchPhoneNrInput.IsReadOnly = true; + BranchFaxNrInput.IsReadOnly = true; + BranchMobileNrInput.IsReadOnly = true; + + WineAttributeIdInput.IsReadOnly = true; + WineAttributeNameInput.IsReadOnly = true; + WineAttributeActiveInput.IsEnabled = false; + WineAttributeMaxKgPerHaInput.IsReadOnly = true; + WineAttributeStrictInput.IsEnabled = false; + WineAttributeFillLowerInput.IsEnabled = false; + + WineCultivationIdInput.IsReadOnly = true; + WineCultivationNameInput.IsReadOnly = true; + WineCultivationDescriptionInput.IsReadOnly = true; + SeasonModifierIdInput.IsReadOnly = true; SeasonModifierNameInput.IsReadOnly = true; SeasonModifierRelInput.IsReadOnly = true; @@ -41,6 +60,27 @@ namespace Elwig.Windows { new protected void UnlockInputs() { base.UnlockInputs(); + + BranchIdInput.IsReadOnly = false; + BranchNameInput.IsReadOnly = false; + BranchPlzInput.IsReadOnly = false; + BranchOrtInput.IsEnabled = true; + BranchAddressInput.IsReadOnly = false; + BranchPhoneNrInput.IsReadOnly = false; + BranchFaxNrInput.IsReadOnly = false; + BranchMobileNrInput.IsReadOnly = false; + + WineAttributeIdInput.IsReadOnly = false; + WineAttributeNameInput.IsReadOnly = false; + WineAttributeActiveInput.IsEnabled = true; + WineAttributeMaxKgPerHaInput.IsReadOnly = false; + WineAttributeStrictInput.IsEnabled = true; + WineAttributeFillLowerInput.IsEnabled = true; + + WineCultivationIdInput.IsReadOnly = false; + WineCultivationNameInput.IsReadOnly = false; + WineCultivationDescriptionInput.IsReadOnly = false; + SeasonModifierIdInput.IsReadOnly = false; SeasonModifierNameInput.IsReadOnly = false; SeasonModifierRelInput.IsReadOnly = false; @@ -54,80 +94,43 @@ namespace Elwig.Windows { protected override async Task OnRenewContext() { await base.OnRenewContext(); - 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(SeasonList, await Context.Seasons.OrderByDescending(s => s.Year).ToListAsync(), s => (s as Season)?.Year, null, ControlUtils.RenewSourceDefault.First); + ControlUtils.RenewItemsSource(BranchList, await Context.Branches.OrderBy(b => b.Name).ToListAsync(), b => (b as Branch)?.ZwstId); + ControlUtils.RenewItemsSource(WineAttributeList, await Context.WineAttributes.OrderBy(a => a.Name).ToListAsync(), a => (a as WineAttr)?.AttrId); + ControlUtils.RenewItemsSource(WineCultivationList, await Context.WineCultivations.OrderBy(c => c.Name).ToListAsync(), c=> (c as WineCult)?.CultId); 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; + bool ch = _branchChanged || _attrChanged || _cultChanged || _modChanged || HasChanged, + v = IsValid; CancelButton.IsEnabled = true; ResetButton.IsEnabled = ch; SaveButton.IsEnabled = ch && v; + + BranchAddButton.IsEnabled = true; + BranchDeleteButton.IsEnabled = BranchList.SelectedIndex != -1; + WineAttributeAddButton.IsEnabled = true; + WineAttributeDeleteButton.IsEnabled = WineAttributeList.SelectedIndex != -1; + WineCultivationAddButton.IsEnabled = true; + WineCultivationDeleteButton.IsEnabled = WineCultivationList.SelectedIndex != -1; + SeasonModifierUpButton.IsEnabled = SeasonModifierList.SelectedIndex >= 1; - SeasonModifierDownButton.IsEnabled = SeasonModifierList.SelectedIndex != -1 && SeasonModifierList.SelectedIndex < (ModifierList?.Count - 1 ?? 0); + SeasonModifierDownButton.IsEnabled = SeasonModifierList.SelectedIndex != -1 && SeasonModifierList.SelectedIndex < (_modList?.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))) { - if (mod.ModId == null) continue; - 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; + BranchesInitEditing(); + WineAttributesInitEditing(); + WineCultivationsInitEditing(); ModifiersInitEditing(); UnlockInputs(); UpdateButtons(); @@ -141,6 +144,11 @@ namespace Elwig.Windows { CancelButton.IsEnabled = false; SaveButton.IsEnabled = false; ResetButton.IsEnabled = false; + + Context.ChangeTracker.Clear(); + BranchesFinishEditing(); + WineCultivationsFinishEditing(); + WineAttributesFinishEditing(); ModifiersFinishEditing(); ClearInputStates(); @@ -149,8 +157,17 @@ namespace Elwig.Windows { } private void ResetButton_Click(object sender, RoutedEventArgs evt) { - ModifiersChanged = false; + _branchChanged = false; + _attrChanged = false; + _cultChanged = false; + _modChanged = false; + Context.ChangeTracker.Clear(); + + BranchesInitEditing(); + WineAttributesInitEditing(); + WineCultivationsInitEditing(); ModifiersInitEditing(); + ClearInputStates(); FillInputs(App.Client); UpdateButtons(); @@ -159,6 +176,9 @@ namespace Elwig.Windows { private async void SaveButton_Click(object sender, RoutedEventArgs evt) { try { await UpdateClientParameters(App.Client); + await BranchesSave(); + await WineAttributesSave(); + await WineCultivationsSave(); await ModifiersSave(); } catch (Exception exc) { var str = "Der Eintrag konnte nicht in der Datenbank aktualisiert werden!\n\n" + exc.Message; @@ -173,6 +193,10 @@ namespace Elwig.Windows { CancelButton.IsEnabled = false; SaveButton.IsEnabled = false; ResetButton.IsEnabled = false; + + BranchesFinishEditing(); + WineAttributesFinishEditing(); + WineCultivationsFinishEditing(); ModifiersFinishEditing(); ClearInputStates(); @@ -238,53 +262,6 @@ namespace Elwig.Windows { 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}"; @@ -295,66 +272,5 @@ namespace Elwig.Windows { 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) { - // DecimalInput_TextChanged(sender, evt); FIXME '-' is ignored - if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod) return; - ModifiersChanged = ModifiersChanged || (SeasonModifierRelInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Rel?.ToString() ?? ""); - if (ModifierUpdate) return; - 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) { - // DecimalInput_TextChanged(sender, evt); FIXME '-' is ignored - if ((!IsEditing && !IsCreating) || SeasonModifierList.SelectedItem is not Modifier mod || SeasonList.SelectedItem is not Season s) return; - ModifiersChanged = ModifiersChanged || (SeasonModifierAbsInput.Text ?? "") != ((SeasonModifierList.SelectedItem as Modifier)?.Abs?.ToString() ?? ""); - if (ModifierUpdate) return; - // FIXME ValueStr does not work in ModifierList when modifier is newly created - mod.AbsValue = decimal.TryParse(SeasonModifierAbsInput.Text, out var v) ? Utils.DecToDb(v, s.Precision) : null; - if (mod.AbsValue != null) SeasonModifierRelInput.Text = ""; - CollectionViewSource.GetDefaultView(ModifierList).Refresh(); - UpdateButtons(); - } } }