diff --git a/Elwig/Services/DeliveryService.cs b/Elwig/Services/DeliveryService.cs index 9d63fda..b1e5a55 100644 --- a/Elwig/Services/DeliveryService.cs +++ b/Elwig/Services/DeliveryService.cs @@ -1180,5 +1180,104 @@ namespace Elwig.Services { await ctx.SaveChangesAsync(); }); } + + public static async Task<(int Year, int DId, int DPNr)[]> GetDidsFromFilters(this DeliveryAdminViewModel vm) { + using var ctx = new AppDbContext(); + var (_, _, parts, _, _) = await vm.GetFilters(ctx); + return [.. (await parts.Select(p => new { p.Year, p.DId, p.DPNr }).ToListAsync()).Select(p => (p.Year, p.DId, p.DPNr))]; + } + + public static async Task BulkSetAttribute(this DeliveryAdminViewModel vm, string? attributeName) { + try { + string attrid; + if (attributeName == null) { + attrid = "NULL"; + } else { + using var ctx = new AppDbContext(); + var attr = await ctx.WineAttributes.Where(a => a.Name == attributeName).SingleAsync(); + attrid = $"'{attr.AttrId}'"; + } + var dids = await vm.GetDidsFromFilters(); + var res = MessageBox.Show($"Soll wirklich für {dids.Length:N0} Teillieferung(en) das Attribut\n'{attributeName}' gesetz werden?", + "Massenaktion: Attribut setzen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); + if (res != MessageBoxResult.OK) return; + + Mouse.OverrideCursor = Cursors.Wait; + await Task.Run(async () => { + using (var cnx = await AppDbContext.ConnectAsync()) { + await cnx.ExecuteBatch($""" + UPDATE delivery_part SET attrid = {attrid} + WHERE (year, did, dpnr) IN ({string.Join(", ", dids.Select(d => $"({d.Year},{d.DId},{d.DPNr})"))}) + """); + } + App.HintContextChange(); + }); + } catch (Exception exc) { + MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); + } finally { + Mouse.OverrideCursor = null; + } + } + + public static async Task BulkAddModifier(this DeliveryAdminViewModel vm, string modifierName) { + try { + string modid; + using (var ctx = new AppDbContext()) { + var attr = await ctx.Modifiers.Where(a => a.Name == modifierName).FirstAsync(); + modid = $"'{attr.ModId}'"; + } + + var dids = await vm.GetDidsFromFilters(); + var res = MessageBox.Show($"Soll wirklich für {dids.Length:N0} Teillieferung(en) der Zu-/Abschlag\n'{modifierName}' hinzugefügt werden?", + "Massenaktion: Zu-/Abschlag hinzufügen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); + if (res != MessageBoxResult.OK) return; + + Mouse.OverrideCursor = Cursors.Wait; + await Task.Run(async () => { + using (var cnx = await AppDbContext.ConnectAsync()) { + await cnx.ExecuteBatch($""" + INSERT INTO delivery_part_modifier (year, did, dpnr, modid) + VALUES {string.Join(", ", dids.Select(d => $"({d.Year},{d.DId},{d.DPNr},{modid})"))} + ON CONFLICT DO NOTHING + """); + } + App.HintContextChange(); + }); + } catch (Exception exc) { + MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); + } finally { + Mouse.OverrideCursor = null; + } + } + + public static async Task BulkRemoveModifier(this DeliveryAdminViewModel vm, string modifierName) { + try { + string modid; + using (var ctx = new AppDbContext()) { + var attr = await ctx.Modifiers.Where(a => a.Name == modifierName).FirstAsync(); + modid = $"'{attr.ModId}'"; + } + + var dids = await vm.GetDidsFromFilters(); + var res = MessageBox.Show($"Soll wirklich für {dids.Length:N0} Teillieferung(en) der Zu-/Abschlag\n'{modifierName}' entfernt werden?", + "Massenaktion: Zu-/Abschlag entfernen", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); + if (res != MessageBoxResult.OK) return; + + Mouse.OverrideCursor = Cursors.Wait; + await Task.Run(async () => { + using (var cnx = await AppDbContext.ConnectAsync()) { + await cnx.ExecuteBatch($""" + DELETE FROM delivery_part_modifier + WHERE (year, did, dpnr, modid) IN ({string.Join(", ", dids.Select(d => $"({d.Year},{d.DId},{d.DPNr},{modid})"))}) + """); + } + App.HintContextChange(); + }); + } catch (Exception exc) { + MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); + } finally { + Mouse.OverrideCursor = null; + } + } } } diff --git a/Elwig/Windows/DeliveryAdminWindow.xaml b/Elwig/Windows/DeliveryAdminWindow.xaml index 6c60e12..c3ba734 100644 --- a/Elwig/Windows/DeliveryAdminWindow.xaml +++ b/Elwig/Windows/DeliveryAdminWindow.xaml @@ -131,7 +131,11 @@ + Click="Menu_DeliveryDataList_SaveFilters_Click"> + + + + @@ -162,7 +166,11 @@ + Click="Menu_Statistic_Locality_SaveFilters_Click"> + + + + @@ -184,6 +192,23 @@ + + + + + + + + + + + + + + + + + diff --git a/Elwig/Windows/DeliveryAdminWindow.xaml.cs b/Elwig/Windows/DeliveryAdminWindow.xaml.cs index 4f30a2d..98fc474 100644 --- a/Elwig/Windows/DeliveryAdminWindow.xaml.cs +++ b/Elwig/Windows/DeliveryAdminWindow.xaml.cs @@ -14,6 +14,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; +using System.Windows.Media; using System.Windows.Threading; namespace Elwig.Windows { @@ -283,6 +284,21 @@ namespace Elwig.Windows { private async void Menu_DeliveryDataList_SaveFilters_Click(object sender, RoutedEventArgs evt) => await ViewModel.GenerateDeliveryDataList(DeliveryService.ExportSubject.FromFilters, ExportMode.SaveList); + private async void Menu_BulkAction_SetAttribute_Click(object sender, RoutedEventArgs evt) { + if (sender is not MenuItem item) return; + await ViewModel.BulkSetAttribute(item.Header as string); + } + + private async void Menu_BulkAction_AddModifier_Click(object sender, RoutedEventArgs evt) { + if (sender is not MenuItem item || item.Header is not string name) return; + await ViewModel.BulkAddModifier(name); + } + + private async void Menu_BulkAction_RemoveModifier_Click(object sender, RoutedEventArgs evt) { + if (sender is not MenuItem item || item.Header is not string name) return; + await ViewModel.BulkRemoveModifier(name); + } + private void Menu_Settings_EnableFreeEditing_Checked(object sender, RoutedEventArgs evt) { if (IsEditing || IsCreating) { DateInput.IsReadOnly = false; @@ -468,8 +484,10 @@ namespace Elwig.Windows { ViewModel.Title = $"Lieferungen - {ViewModel.FilterMember.AdministrativeName} - Elwig"; } + int year = 0; Menu_Bki_SaveList.Items.Clear(); foreach (var s in await ctx.Seasons.OrderByDescending(s => s.Year).ToListAsync()) { + if (s.Year > year) year = s.Year; var i = new MenuItem { Header = $"Saison {s.Year}", }; @@ -477,6 +495,37 @@ namespace Elwig.Windows { Menu_Bki_SaveList.Items.Add(i); } + var font = new FontFamily("Segoe MDL2 Assets"); + Menu_BulkAction_SetAttribute.Items.Clear(); + var noAttr = new MenuItem { + Header = new TextBlock() { Text = "Kein Attribut", FontStyle = FontStyles.Italic }, + Icon = new TextBlock() { Text = "\ue75c", FontFamily = font, FontSize = 16 }, + }; + noAttr.Click += Menu_BulkAction_SetAttribute_Click; + Menu_BulkAction_SetAttribute.Items.Add(noAttr); + foreach (var attr in await ctx.WineAttributes.OrderBy(a => a.AttrId).ToListAsync()) { + var i = new MenuItem { + Header = attr.Name, + }; + i.Click += Menu_BulkAction_SetAttribute_Click; + Menu_BulkAction_SetAttribute.Items.Add(i); + } + + Menu_BulkAction_AddModifier.Items.Clear(); + Menu_BulkAction_RemoveModifier.Items.Clear(); + foreach (var mod in await ctx.Modifiers.Where(m => m.Year == year).OrderBy(m => m.ModId).ToListAsync()) { + var i1 = new MenuItem { + Header = mod.Name, + }; + i1.Click += Menu_BulkAction_AddModifier_Click; + Menu_BulkAction_AddModifier.Items.Add(i1); + var i2 = new MenuItem { + Header = mod.Name, + }; + i2.Click += Menu_BulkAction_RemoveModifier_Click; + Menu_BulkAction_RemoveModifier.Items.Add(i2); + } + await RefreshList(); var d = DeliveryList.SelectedItem as Delivery; var y = d?.Year ?? ViewModel.FilterSeason;