diff --git a/Elwig/Models/Dtos/MemberDeliveryData.cs b/Elwig/Models/Dtos/MemberDeliveryData.cs new file mode 100644 index 0000000..ca27407 --- /dev/null +++ b/Elwig/Models/Dtos/MemberDeliveryData.cs @@ -0,0 +1,59 @@ +using Elwig.Models.Entities; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Elwig.Models.Dtos { + public class MemberDeliveryData : DataTable { + + private static readonly (string, string, string?, int?)[] FieldNames = [ + ("MgNr", "MgNr.", null, 12), + ("Name1", "Name", null, 40), + ("Name2", "Vorname", null, 40), + ("Address", "Adresse", null, 60), + ("Plz", "PLZ", null, 10), + ("Locality", "Ort", null, 60), + ("Weight", "Geliefert", "kg", 22), + ]; + + public MemberDeliveryData(IEnumerable rows, List filterNames) : + base("Liefermengen Gesamt", "Liefermengen pro Mitglied", string.Join(" / ", filterNames), rows, FieldNames) { + } + + public static async Task FromQuery(IQueryable query, List filterNames) { + return new((await query + .GroupBy(p => new { + p.Delivery.MgNr, + p.Delivery.Member.Name, + p.Delivery.Member.GivenName, + p.Delivery.Member.Address, + p.Delivery.Member.PostalDest.AtPlz!.Plz, + Ort = p.Delivery.Member.PostalDest.AtPlz!.Ort.Name, + }) + .Select(g => new { + g.Key, + Weight = g.Sum(p => p.Weight), + }).ToListAsync()) + .Select(g => new MemberDeliveryRow { + MgNr = g.Key.MgNr, + Name1 = g.Key.Name, + Name2 = g.Key.GivenName, + Address = g.Key.Address, + Plz = g.Key.Plz, + Locality = g.Key.Ort, + Weight = g.Weight, + }), filterNames); + } + } + + public class MemberDeliveryRow { + public required int MgNr; + public required string Name1; + public required string? Name2; + public required string Address; + public required int Plz; + public required string Locality; + public required int Weight; + } +} diff --git a/Elwig/Models/Dtos/MemberDeliveryPerVarietyData.cs b/Elwig/Models/Dtos/MemberDeliveryPerVarietyData.cs new file mode 100644 index 0000000..0170732 --- /dev/null +++ b/Elwig/Models/Dtos/MemberDeliveryPerVarietyData.cs @@ -0,0 +1,78 @@ +using Elwig.Models.Entities; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Elwig.Models.Dtos { + public class MemberDeliveryPerVarietyData : DataTable { + + private static readonly (string, string, string?, int?)[] FieldNames = [ + ("MgNr", "MgNr.", null, 12), + ("Name1", "Name", null, 40), + ("Name2", "Vorname", null, 40), + ("Address", "Adresse", null, 60), + ("Plz", "PLZ", null, 10), + ("Locality", "Ort", null, 60), + ("SortIds", "Sorte", null, 12), + ("AttrIds", "Attribut", null, 16), + ("CultIds", "Bewirt.", null, 16), + ("Weights", "Geliefert", "kg", 22), + ]; + + public MemberDeliveryPerVarietyData(IEnumerable rows, List filterNames) : + base("Liefermengen pro Sorte", "Liefermengen pro Mitglied, Sorte, Attribut und Bewirtschaftungsart", string.Join(" / ", filterNames), rows, FieldNames) { + } + + public static async Task FromQuery(IQueryable query, List filterNames) { + return new((await query + .GroupBy(p => new { + p.Delivery.MgNr, + p.Delivery.Member.Name, + p.Delivery.Member.GivenName, + p.Delivery.Member.Address, + p.Delivery.Member.PostalDest.AtPlz!.Plz, + Ort = p.Delivery.Member.PostalDest.AtPlz!.Ort.Name, + p.SortId, + p.AttrId, + p.CultId, + }) + .Select(g => new { + g.Key, + Weight = g.Sum(p => p.Weight), + }) + .ToListAsync()).GroupBy(g => new { + g.Key.MgNr, + g.Key.Name, + g.Key.GivenName, + g.Key.Address, + g.Key.Plz, + g.Key.Ort, + }).Select(g => new MemberDeliveryPerVarietyRow { + MgNr = g.Key.MgNr, + Name1 = g.Key.Name, + Name2 = g.Key.GivenName, + Address = g.Key.Address, + Plz = g.Key.Plz, + Locality = g.Key.Ort, + SortIds = [.. g.Select(d => d.Key.SortId)], + AttrIds = [.. g.Select(d => d.Key.AttrId)], + CultIds = [.. g.Select(d => d.Key.CultId)], + Weights = [.. g.Select(d => d.Weight)], + }), filterNames); + } + } + + public class MemberDeliveryPerVarietyRow { + public required int MgNr; + public required string Name1; + public required string? Name2; + public required string Address; + public required int Plz; + public required string Locality; + public required string[] SortIds; + public required string?[] AttrIds; + public required string?[] CultIds; + public required int[] Weights; + } +} diff --git a/Elwig/Services/DeliveryService.cs b/Elwig/Services/DeliveryService.cs index eb3dfe7..fb9e803 100644 --- a/Elwig/Services/DeliveryService.cs +++ b/Elwig/Services/DeliveryService.cs @@ -962,6 +962,52 @@ namespace Elwig.Services { } } + public static async Task GenerateDeliveryDataList(this DeliveryAdminViewModel vm, ExportSubject subject, ExportMode mode) { + using var ctx = new AppDbContext(); + IQueryable query; + List filterNames = []; + if (subject == ExportSubject.FromFilters) { + var (f, _, q, _, _) = await vm.GetFilters(ctx); + query = q; + filterNames.AddRange(f); + } else if (subject == ExportSubject.FromSeason) { + var year = vm.FilterSeason ?? Utils.CurrentLastSeason; + query = ctx.DeliveryParts + .Where(p => p.Year == year); + filterNames.Add($"{year}"); + } else { + throw new ArgumentException("Invalid value for ExportSubject"); + } + + query = query + .OrderBy(p => p.Delivery.MgNr) + .ThenBy(p => p.SortId) + .ThenBy(p => p.AttrId) + .ThenBy(p => p.CultId); + + var d = new SaveFileDialog() { + FileName = $"Liefermengen.ods", + DefaultExt = "ods", + Filter = "OpenDocument Format Spreadsheet (*.ods)|*.ods", + Title = $"Liefermengen speichern unter - Elwig" + }; + if (d.ShowDialog() == true) { + Mouse.OverrideCursor = Cursors.Wait; + await Task.Run(async () => { + try { + using var ods = new OdsFile(d.FileName); + var tblTotal = await MemberDeliveryData.FromQuery(query, filterNames); + var tbl = await MemberDeliveryPerVarietyData.FromQuery(query, filterNames); + await ods.AddTable(tblTotal); + await ods.AddTable(tbl); + } catch (Exception exc) { + MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); + } + }); + Mouse.OverrideCursor = null; + } + } + private static void AddToolTipCell(Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) { var tb = new TextBlock() { Text = text, diff --git a/Elwig/Windows/DeliveryAdminWindow.xaml b/Elwig/Windows/DeliveryAdminWindow.xaml index 06f120b..90185a6 100644 --- a/Elwig/Windows/DeliveryAdminWindow.xaml +++ b/Elwig/Windows/DeliveryAdminWindow.xaml @@ -129,6 +129,10 @@ + + + + private async void Menu_Statistic_Locality_SaveFilters_Click(object sender, RoutedEventArgs evt) => await ViewModel.GenerateLocalityStatistics(DeliveryService.ExportSubject.FromFilters); private async void Menu_DeliveryDepreciationList_SaveFilters_Click(object sender, RoutedEventArgs evt) => @@ -280,6 +280,9 @@ namespace Elwig.Windows { private async void Menu_DeliveryDepreciationList_PrintSeason_Click(object sender, RoutedEventArgs evt) => await ViewModel.GenerateDeliveryDepreciationList(DeliveryService.ExportSubject.FromSeason, ExportMode.Print); + private async void Menu_DeliveryDataList_SaveFilters_Click(object sender, RoutedEventArgs evt) => + await ViewModel.GenerateDeliveryDataList(DeliveryService.ExportSubject.FromFilters, ExportMode.SaveList); + private void Menu_Settings_EnableFreeEditing_Checked(object sender, RoutedEventArgs evt) { if (IsEditing || IsCreating) { DateInput.IsReadOnly = false;