Files
elwig/Elwig/Windows/MailWindow.xaml.cs
Lorenz Stechauner f09753ccc2
All checks were successful
Test / Run tests (push) Successful in 2m4s
Remove byte order marks
2024-07-26 19:44:41 +02:00

749 lines
36 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Elwig.Documents;
using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Models.Dtos;
using Elwig.Models.Entities;
using MailKit.Net.Smtp;
using Microsoft.EntityFrameworkCore;
using Microsoft.Win32;
using MimeKit;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace Elwig.Windows {
public partial class MailWindow : ContextWindow {
// used for document sorting while generating!
public enum DocType { Undefined, Custom, MemberDataSheet, DeliveryConfirmation, CreditNote }
public class SelectedDoc(DocType type, string name, object? details = null) {
public DocType Type = type;
public string Name { get; set; } = name;
public object? Details = details;
}
public class GeneratedDoc {
public DocType Type;
public Document Doc;
public GeneratedDoc(string pdfPath) {
Type = DocType.Custom;
Doc = Document.FromPdf(pdfPath);
}
public GeneratedDoc(Document doc) {
Type = doc is MemberDataSheet ? DocType.MemberDataSheet :
doc is DeliveryConfirmation ? DocType.DeliveryConfirmation :
doc is CreditNote ? DocType.CreditNote : DocType.Undefined;
Doc = doc;
}
}
public static readonly string[] AvaiableDocuments = [
MemberDataSheet.Name,
DeliveryConfirmation.Name,
CreditNote.Name,
];
public readonly int Year;
public ObservableCollection<SelectedDoc> SelectedDocs = [];
public IEnumerable<Member> Recipients = [];
protected Document? PrintDocument;
protected Dictionary<Member, List<Document>>? EmailDocuments;
public static readonly DependencyProperty PostalAllCountProperty = DependencyProperty.Register(nameof(PostalAllCount), typeof(int), typeof(MailWindow));
public int PostalAllCount {
get => (int)GetValue(PostalAllCountProperty);
private set => SetValue(PostalAllCountProperty, value);
}
public static readonly DependencyProperty PostalWishCountProperty = DependencyProperty.Register(nameof(PostalWishCount), typeof(int), typeof(MailWindow));
public int PostalWishCount {
get => (int)GetValue(PostalWishCountProperty);
private set => SetValue(PostalWishCountProperty, value);
}
public static readonly DependencyProperty PostalNoEmailCountProperty = DependencyProperty.Register(nameof(PostalNoEmailCount), typeof(int), typeof(MailWindow));
public int PostalNoEmailCount {
get => (int)GetValue(PostalNoEmailCountProperty);
private set => SetValue(PostalNoEmailCountProperty, value);
}
public static readonly DependencyProperty EmailAllCountProperty = DependencyProperty.Register(nameof(EmailAllCount), typeof(int), typeof(MailWindow));
public int EmailAllCount {
get => (int)GetValue(EmailAllCountProperty);
private set => SetValue(EmailAllCountProperty, value);
}
public static readonly DependencyProperty EmailWishCountProperty = DependencyProperty.Register(nameof(EmailWishCount), typeof(int), typeof(MailWindow));
public int EmailWishCount {
get => (int)GetValue(EmailWishCountProperty);
private set => SetValue(EmailWishCountProperty, value);
}
private ICommand? _deleteCommand;
public ICommand DeleteCommand => _deleteCommand ??= new ActionCommand(() => {
var idx = SelectedDocumentsList.SelectedIndex;
if (idx == -1)
return;
SelectedDocs.RemoveAt(SelectedDocumentsList.SelectedIndex);
SelectedDocumentsList.SelectedIndex = idx < SelectedDocumentsList.Items.Count ? idx : idx - 1;
});
// powershell -Command "$(Get-WmiObject -Class Win32_Printer | Where-Object {$_.Default -eq $True}).Name"
public MailWindow(int? year = null) {
InitializeComponent();
using (var ctx = new AppDbContext()) {
Year = year ?? ctx.Seasons.OrderBy(s => s.Year).LastOrDefault()?.Year ?? Utils.Today.Year;
Title = $"Rundschreiben - Lese {Year} - Elwig";
}
AvaiableDocumentsList.ItemsSource = AvaiableDocuments;
SelectedDocumentsList.ItemsSource = SelectedDocs;
DocumentNonDeliverersInput.Visibility = Visibility.Hidden;
DocumentFooterLabel.Visibility = Visibility.Hidden;
DeliveryConfirmationFooterInput.Visibility = Visibility.Hidden;
CreditNoteFooterInput.Visibility = Visibility.Hidden;
RecipientsActiveMembersInput.IsChecked = true;
DeliveryConfirmationFooterInput.Text = App.Client.TextDeliveryConfirmation;
CreditNoteFooterInput.Text = App.Client.TextCreditNote;
PostalSender1.Text = App.Client.Sender1;
PostalSender2.Text = App.Client.Sender2;
PostalLocation.Text = App.BranchLocation;
PostalDate.Text = $"{Utils.Today:dd.MM.yyyy}";
EmailSubjectInput.Text = App.Client.TextEmailSubject ?? "Rundschreiben";
EmailBodyInput.Text = App.Client.TextEmailBody ?? "Sehr geehrtes Mitglied,\n\nim Anhang finden Sie das aktuelle Rundschreiben.\n\nIhre Winzergenossenschaft\n";
}
protected override async Task OnRenewContext(AppDbContext ctx) {
var season = await ctx.Seasons.FindAsync(Year);
var l = new List<string> {
MemberDataSheet.Name
};
if (season != null) {
l.Add($"{DeliveryConfirmation.Name} {Year}");
l.AddRange(season.PaymentVariants.OrderBy(v => v.AvNr).Select(v => $"{CreditNote.Name} {v.Name}"));
}
AvaiableDocumentsList.ItemsSource = l;
ControlUtils.RenewItemsSource(MemberBranchInput, await ctx.Branches
.Where(b => b.Members.Count != 0)
.OrderBy(b => b.Name)
.ToListAsync(), MemberInput_SelectionChanged);
if (MemberBranchInput.SelectedItems.Count == 0) {
MemberBranchInput.SelectionChanged -= MemberInput_SelectionChanged;
MemberBranchInput.SelectAll();
MemberBranchInput.SelectionChanged += MemberInput_SelectionChanged;
}
ControlUtils.RenewItemsSource(MemberKgInput, await ctx.Katastralgemeinden
.Where(k => k.WbKg!.Members.Count != 0)
.OrderBy(k => k.Name)
.ToListAsync(), MemberInput_SelectionChanged);
if (MemberKgInput.SelectedItems.Count == 0) {
MemberKgInput.SelectionChanged -= MemberInput_SelectionChanged;
MemberKgInput.SelectAll();
MemberKgInput.SelectionChanged += MemberInput_SelectionChanged;
}
ControlUtils.RenewItemsSource(MemberAreaComInput, await ctx.AreaCommitmentTypes
.OrderBy(a => a.VtrgId)
.ToListAsync(), MemberInput_SelectionChanged);
if (MemberAreaComInput.SelectedItems.Count == 0) {
MemberAreaComInput.SelectionChanged -= MemberInput_SelectionChanged;
MemberAreaComInput.SelectAll();
MemberAreaComInput.SelectionChanged += MemberInput_SelectionChanged;
}
ControlUtils.RenewItemsSource(MemberCustomInput, await ctx.Members
.Where(m => m.IsActive)
.OrderBy(m => m.FamilyName)
.ThenBy(m => m.GivenName)
.Include(m => m.Branch)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Country)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country)
.ToListAsync(), MemberInput_SelectionChanged);
if (MemberCustomInput.SelectedItems.Count == 0) {
MemberCustomInput.SelectionChanged -= MemberInput_SelectionChanged;
MemberCustomInput.SelectAll();
MemberCustomInput.SelectionChanged += MemberInput_SelectionChanged;
}
await UpdateRecipients(ctx);
}
private void ContinueButton_Click(object sender, RoutedEventArgs evt) {
TabControl.SelectedIndex = 1;
TabControl.AllowDrop = false;
}
private void BackButton_Click(object sender, RoutedEventArgs evt) {
TabControl.SelectedIndex = 0;
TabControl.AllowDrop = true;
}
private void Document_Drop(object sender, DragEventArgs evt) {
if (evt.Data.GetDataPresent(DataFormats.FileDrop)) {
var files = (string[])evt.Data.GetData(DataFormats.FileDrop);
foreach (var file in files) {
if (Path.GetExtension(file) == ".pdf") {
SelectedDocs.Add(new(DocType.Custom, Path.GetFileName(file), file));
}
}
}
}
private void Document_PreviwDragOver(object sender, DragEventArgs evt) {
evt.Handled = TabControl.SelectedIndex == 0;
}
private void AvaiableDocumentsList_SelectionChanged(object sender, RoutedEventArgs evt) {
DocumentAddButton.IsEnabled = AvaiableDocumentsList.SelectedIndex != -1;
}
private void SelectedDocumentsList_SelectionChanged(object sender, RoutedEventArgs evt) {
DocumentRemoveButton.IsEnabled = SelectedDocumentsList.SelectedIndex != -1;
if (SelectedDocumentsList.SelectedItem is SelectedDoc doc) {
DocumentBox.Header = doc.Name;
if (doc.Type == DocType.DeliveryConfirmation) {
DocumentNonDeliverersInput.Visibility = Visibility.Visible;
DocumentFooterLabel.Visibility = Visibility.Visible;
DeliveryConfirmationFooterInput.Visibility = Visibility.Visible;
CreditNoteFooterInput.Visibility = Visibility.Hidden;
DocumentFooterLabel.Margin = new(10, 40, 0, 10);
} else if (doc.Type == DocType.CreditNote) {
DocumentNonDeliverersInput.Visibility = Visibility.Hidden;
DocumentFooterLabel.Visibility = Visibility.Visible;
DeliveryConfirmationFooterInput.Visibility = Visibility.Hidden;
CreditNoteFooterInput.Visibility = Visibility.Visible;
DocumentFooterLabel.Margin = new(10, 10, 0, 10);
} else {
DocumentNonDeliverersInput.Visibility = Visibility.Hidden;
DocumentFooterLabel.Visibility = Visibility.Hidden;
DeliveryConfirmationFooterInput.Visibility = Visibility.Hidden;
CreditNoteFooterInput.Visibility = Visibility.Hidden;
}
} else {
DocumentBox.Header = "Dokument";
DocumentNonDeliverersInput.Visibility = Visibility.Hidden;
DocumentFooterLabel.Visibility = Visibility.Hidden;
DeliveryConfirmationFooterInput.Visibility = Visibility.Hidden;
CreditNoteFooterInput.Visibility = Visibility.Hidden;
}
}
private void DocumentAddButton_Click(object sender, RoutedEventArgs evt) {
var idx = AvaiableDocumentsList.SelectedIndex;
if (AvaiableDocumentsList.SelectedItem is not string s)
return;
if (idx == 0) {
SelectedDocs.Add(new(DocType.MemberDataSheet, s, null));
} else if (idx == 1) {
SelectedDocs.Add(new(DocType.DeliveryConfirmation, s, (Year, DocumentNonDeliverersInput.IsChecked == true)));
RecipientsDeliveryMembersInput.IsChecked = true;
} else if (idx >= 2) {
using var ctx = new AppDbContext();
var name = s.Split(" ")[^1];
var pv = ctx.PaymentVariants.Single(v => v.Year == Year && v.Name == name)!;
SelectedDocs.Add(new(DocType.CreditNote, s, (pv.Year, pv.AvNr)));
RecipientsDeliveryMembersInput.IsChecked = true;
}
SelectedDocumentsList.SelectedIndex = SelectedDocs.Count - 1;
}
private void DocumentRemoveButton_Click(object sender, RoutedEventArgs evt) {
DeleteCommand.Execute(null);
}
private void SelectDocumentButton_Click(object sender, RoutedEventArgs evt) {
var d = new OpenFileDialog() {
Title = "Dokument auswählen - Elwig",
DefaultExt = ".pdf",
Filter = "PDF-Dokument (*.pdf)|*.pdf",
Multiselect = true,
};
if (d.ShowDialog() == true) {
foreach (var file in d.FileNames) {
if (Path.GetExtension(file) == ".pdf") {
SelectedDocs.Add(new(DocType.Custom, Path.GetFileName(file), file));
}
}
}
}
private async void RecipientsInput_Changed(object sender, RoutedEventArgs evt) {
var vis = RecipientsCustomInput.IsChecked == true ? Visibility.Hidden : Visibility.Visible;
MemberBranchLabel.Visibility = vis;
MemberBranchInput.Visibility = vis;
MemberKgLabel.Visibility = vis;
MemberKgInput.Visibility = vis;
MemberAreaComInput.Visibility = RecipientsAreaComMembersInput.IsChecked == true ? Visibility.Visible : Visibility.Hidden;
MemberAreaComLabel.Visibility = RecipientsAreaComMembersInput.IsChecked == true ? Visibility.Visible : Visibility.Hidden;
MemberCustomInput.Visibility = RecipientsCustomInput.IsChecked == true ? Visibility.Visible : Visibility.Hidden;
using var ctx = new AppDbContext();
await UpdateRecipients(ctx);
}
private async void MemberInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
using var ctx = new AppDbContext();
await UpdateRecipients(ctx);
}
private void Date_TextChanged(object sender, RoutedEventArgs evt) {
Validator.CheckDate((TextBox)sender, true);
}
private void Date_LostFocus(object sender, RoutedEventArgs evt) {
var res = Validator.CheckDate((TextBox)sender, true);
if (!res.IsValid) ((TextBox)sender).Text = $"{Utils.Today:dd.MM.yyyy}";
}
private async Task UpdateRecipients(AppDbContext ctx) {
if (RecipientsCustomInput.IsChecked == true) {
Recipients = MemberCustomInput.SelectedItems.Cast<Member>().ToList();
} else {
IQueryable<Member> query = ctx.Members;
if (MemberBranchInput.SelectedItems.Count != MemberBranchInput.Items.Count) {
var zwst = MemberBranchInput.SelectedItems.Cast<Branch>().Select(b => b.ZwstId).ToList();
query = query.Where(m => zwst.Contains(m.ZwstId!));
}
if (MemberKgInput.SelectedItems.Count != MemberKgInput.Items.Count) {
var kgs = MemberKgInput.SelectedItems.Cast<AT_Kg>().Select(k => k.KgNr).ToList();
query = query.Where(m => kgs.Contains((int)m.DefaultKgNr!));
}
if (RecipientsAreaComMembersInput.IsChecked == true) {
var vtrg = MemberAreaComInput.SelectedItems.Cast<AreaComType>().Select(a => a.VtrgId).ToList();
query = query.Where(m => m.IsActive && m.AreaCommitments.AsQueryable().Where(Utils.ActiveAreaCommitments(Year)).Any(c => vtrg.Contains(c.VtrgId)));
} else if (RecipientsDeliveryMembersInput.IsChecked == true) {
query = query.Where(m => m.Deliveries.Any(d => d.Year == Year));
} else if (RecipientsNonDeliveryMembersInput.IsChecked == true) {
query = query.Where(m => m.IsActive && !m.Deliveries.Any(d => d.Year == Year));
} else {
query = query.Where(m => m.IsActive);
}
Recipients = await query
.Include(m => m.Branch)
.Include(m => m.DefaultWbKg!.AtKg)
.Include(m => m.EmailAddresses)
.Include(m => m.TelephoneNumbers)
.Include(m => m.PostalDest.AtPlz!.Ort)
.Include(m => m.PostalDest.AtPlz!.Country)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Ort)
.Include(m => m.BillingAddress!.PostalDest.AtPlz!.Country)
.ToListAsync();
}
UpdatePostalEmailRecipients();
}
private void EmailInput_Changed(object sender, RoutedEventArgs evt) {
UpdatePostalEmailRecipients();
}
private void UpdatePostalEmailRecipients() {
EmailAllCount = Recipients.Count(m => m.EmailAddresses.Count > 0);
EmailWishCount = Recipients.Count(m => m.EmailAddresses.Count > 0 && m.ContactViaEmail);
PostalAllCount = Recipients.Count();
PostalWishCount = Recipients.Count(m => m.ContactViaPost);
var m = EmailAllInput.IsChecked == true ? 3 : EmailWishInput.IsChecked == true ? 2 : 1;
PostalNoEmailCount = PostalAllCount - (m == 3 ? EmailAllCount : m == 2 ? EmailWishCount : 0);
}
private async Task UpdateTextParameters() {
var changed = false;
var dcText = DeliveryConfirmationFooterInput.Text.Trim();
if (dcText.Length == 0) dcText = null;
if (dcText != App.Client.TextDeliveryConfirmation) {
App.Client.TextDeliveryConfirmation = dcText;
changed = true;
}
var cdText = CreditNoteFooterInput.Text.Trim();
if (cdText.Length == 0) cdText = null;
if (cdText != App.Client.TextCreditNote) {
App.Client.TextCreditNote = cdText;
changed = true;
}
var emailSubject = EmailSubjectInput.Text.Trim();
if (emailSubject.Length == 0) emailSubject = null;
if (emailSubject != App.Client.TextEmailSubject) {
App.Client.TextEmailSubject = emailSubject;
changed = true;
}
var emailBody = EmailBodyInput.Text.Trim();
if (emailBody.Length == 0) emailBody = null;
if (emailBody != App.Client.TextEmailBody) {
App.Client.TextEmailBody = emailBody;
changed = true;
}
if (changed)
await App.Client.UpdateValues();
}
private void DisposeDocs() {
PrintDocument?.Dispose();
PrintDocument = null;
if (EmailDocuments != null) {
foreach (var (m, docs) in EmailDocuments) {
foreach (var d in docs) {
d.Dispose();
}
}
EmailDocuments = null;
}
}
private void Window_Closed(object sender, EventArgs evt) {
DisposeDocs();
}
private async void GenerateButton_Click(object sender, RoutedEventArgs evt) {
PreviewButton.IsEnabled = false;
PrintButton.IsEnabled = false;
EmailButton.IsEnabled = false;
Mouse.OverrideCursor = Cursors.AppStarting;
GenerateButton.IsEnabled = false;
DisposeDocs();
await UpdateTextParameters();
using var ctx = new AppDbContext();
var doublePaged = DoublePagedInput.IsChecked == true;
var location = PostalLocation.Text.Trim();
var docs = SelectedDocs.OrderByDescending(d => d.Type).ToList();
IEnumerable<Member> recipients = Recipients;
if (OrderMgNrInput.IsChecked == true) {
recipients = recipients
.OrderBy(m => m.MgNr)
.ToList();
} else if (OrderNameInput.IsChecked == true) {
recipients = recipients
.OrderBy(m => m.FamilyName)
.ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr)
.ToList();
} else if (OrderPlzInput.IsChecked == true) {
if (docs.Any(d => d.Type == DocType.DeliveryConfirmation || d.Type == DocType.CreditNote)) {
recipients = recipients
.OrderBy(m => m.BillingAddress?.PostalDest.AtPlz?.Plz ?? m.PostalDest.AtPlz?.Plz)
.ThenBy(m => m.BillingAddress?.PostalDest.AtPlz?.Ort.Name ?? m.PostalDest.AtPlz?.Ort.Name)
.ThenBy(m => m.FamilyName)
.ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr)
.ToList();
} else {
recipients = recipients
.OrderBy(m => m.PostalDest.AtPlz?.Plz)
.ThenBy(m => m.PostalDest.AtPlz?.Ort.Name)
.ThenBy(m => m.FamilyName)
.ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr)
.ToList();
}
}
Dictionary<int, IDictionary<int, DeliveryConfirmationDeliveryData>> dcData = [];
Dictionary<(int, int), (IDictionary<int, CreditNoteDeliveryData>, IDictionary<int, PaymentMember>, BillingData)> cnData = [];
foreach (var doc in docs) {
if (doc.Type == DocType.DeliveryConfirmation) {
var details = ((int, bool))doc.Details!;
var year = details.Item1;
try {
var b = new Billing(year);
await b.FinishSeason();
await b.CalculateBuckets();
await App.HintContextChange();
dcData[year] = await DeliveryConfirmationDeliveryData.ForSeason(ctx.DeliveryParts, year);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
GenerateButton.IsEnabled = true;
Mouse.OverrideCursor = null;
return;
}
} else if (doc.Type == DocType.CreditNote) {
var details = ((int, int))doc.Details!;
var year = details.Item1;
var avnr = details.Item2;
try {
cnData[(year, avnr)] = (
await CreditNoteDeliveryData.ForPaymentVariant(ctx.CreditNoteDeliveryRows, ctx.Seasons, year, avnr),
await ctx.MemberPayments.Where(p => p.Year == year && p.AvNr == avnr).ToDictionaryAsync(c => c.MgNr),
BillingData.FromJson((await ctx.PaymentVariants.FindAsync(year, avnr))!.Data)
);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
GenerateButton.IsEnabled = true;
Mouse.OverrideCursor = null;
return;
}
await ctx.GetMemberAreaCommitmentBuckets(year, 0);
}
}
var postalDate = DateOnly.ParseExact(PostalDate.Text, "dd.MM.yyyy");
var memberDocs = recipients.Select(m => new {
Member = m,
Docs = docs.SelectMany<SelectedDoc, GeneratedDoc>(doc => {
try {
if (doc.Type == DocType.Custom) {
return [new GeneratedDoc((string)doc.Details!)];
} else if (doc.Type == DocType.MemberDataSheet) {
return [new GeneratedDoc(new MemberDataSheet(m, ctx) { Date = postalDate })];
} else if (doc.Type == DocType.DeliveryConfirmation) {
var details = ((int, bool))doc.Details!;
var year = details.Item1;
var include = details.Item2;
DeliveryConfirmationDeliveryData data;
if (dcData[year].TryGetValue(m.MgNr, out var d)) {
data = d;
} else if (include) {
data = DeliveryConfirmationDeliveryData.CreateEmpty(year, m);
} else {
return [];
}
return [new GeneratedDoc(new DeliveryConfirmation(ctx, year, m, data) { Date = postalDate })];
} else if (doc.Type == DocType.CreditNote) {
var details = ((int, int))doc.Details!;
var year = details.Item1;
var avnr = details.Item2;
var data = cnData[(year, avnr)];
try {
return [new GeneratedDoc(new CreditNote(
ctx, data.Item2[m.MgNr], data.Item1[m.MgNr],
data.Item3.ConsiderContractPenalties,
data.Item3.ConsiderTotalPenalty,
data.Item3.ConsiderAutoBusinessShares,
data.Item3.ConsiderCustomModifiers,
ctx.GetMemberUnderDelivery(year, m.MgNr).GetAwaiter().GetResult()
) { Date = postalDate })];
} catch (Exception) {
return [];
}
} else {
throw new NotImplementedException("Invalid DocType");
}
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
return [];
}
}).ToList()
}).ToList();
var printMode = PostalAllInput.IsChecked == true ? 3 :
PostalWishInput.IsChecked == true ? 2 :
PostalNoEmailInput.IsChecked == true ? 1 : 0;
var emailMode = EmailAllInput.IsChecked == true ? 2 : EmailWishInput.IsChecked == true ? 1 : 0;
double printNum = printMode == 3 ? PostalAllCount : printMode == 2 ? PostalWishCount : printMode == 2 ? PostalNoEmailCount : 0;
double emailNum = emailMode == 2 ? EmailAllCount : emailMode == 1 ? EmailWishCount : 0;
double totalNum = printNum + emailNum;
var email = memberDocs
.Where(d => d.Docs.Count > 0 && d.Member.EmailAddresses.Count > 0 && (emailMode == 2 || (emailMode == 1 && d.Member.ContactViaEmail)))
.ToDictionary(d => d.Member, m => {
var docs = m.Docs.Select(d => d.Doc).ToList();
foreach (var doc in docs) {
doc!.DoublePaged = false;
if (doc is BusinessDocument b) {
b.IncludeSender = false;
b.Location = location;
}
};
return docs;
});
var emailRecipients = email.Select(d => d.Key.MgNr).ToHashSet();
try {
foreach (var item1 in email.Select((e, i) => new { Index = i, e.Key, e.Value })) {
foreach (var item2 in item1.Value.Select((d, i) => new { Index = i, Doc = d })) {
await item2.Doc.Generate(new Progress<double>(v => {
ProgressBar.Value = v * (item2.Index + 1) / item1.Value.Count / totalNum + 100.0 * item1.Index / totalNum;
}));
}
}
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
GenerateButton.IsEnabled = true;
Mouse.OverrideCursor = null;
return;
}
if (email.Count > 0) {
EmailDocuments = email;
}
var printDocs = memberDocs
.Where(d =>
printMode == 3 ||
(printMode == 2 && d.Member.ContactViaPost) ||
(printMode == 1 && !emailRecipients.Contains(d.Member.MgNr)))
.SelectMany(m => {
var docs = m.Docs.Select(d => d.Doc).ToList();
if (docs.Count == 0 || m.Docs[0].Type == DocType.Custom) {
docs.Insert(0, new Letterhead(m.Member));
}
docs.ForEach(doc => {
doc.DoublePaged = doublePaged;
if (doc is BusinessDocument b)
b.Location = location;
});
if (docs.Count > 0 && docs[0] is BusinessDocument b)
b.IncludeSender = true;
return docs;
})
.ToList();
if (printDocs.Count > 0) {
try {
var print = Document.Merge(printDocs);
print.DoublePaged = doublePaged;
await print.Generate(new Progress<double>(v => {
ProgressBar.Value = 100.0 * emailNum / totalNum + v * printNum / totalNum;
}));
PrintDocument = print;
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
GenerateButton.IsEnabled = true;
Mouse.OverrideCursor = null;
return;
}
}
ProgressBar.Value = 100.0;
GenerateButton.IsEnabled = true;
Mouse.OverrideCursor = null;
PreviewButton.IsEnabled = true;
PrintButton.IsEnabled = PrintDocument != null;
EmailButton.IsEnabled = EmailDocuments != null && App.Config.Smtp != null;
}
private void PreviewButton_Click(object sender, RoutedEventArgs evt) {
var d = new OpenFolderDialog() {
Title = "Ordner auswählen - Elwig",
};
if (d.ShowDialog() == true) {
Mouse.OverrideCursor = Cursors.AppStarting;
PrintDocument?.SaveTo($"{d.FolderName}/Print.pdf");
if (EmailDocuments != null) {
foreach (var (m, docs) in EmailDocuments) {
var folder = $"{d.FolderName}/E-Mail/{m.AdministrativeName.Trim()}";
Directory.CreateDirectory(folder);
foreach (var item in docs.Select((d, i) => new { Index = i, Doc = d })) {
var doc = item.Doc;
var name = Utils.NormalizeFileName(doc.Title);
doc.SaveTo($"{folder}/{item.Index + 1:00}.{name}.pdf");
}
}
}
Mouse.OverrideCursor = null;
Process.Start("explorer.exe", d.FolderName);
}
}
private async void PrintButton_Click(object sender, RoutedEventArgs evt) {
if (PrintDocument == null) return;
PrintButton.IsEnabled = false;
var res = MessageBox.Show($"Sollen {PrintDocument.Pages} Blätter ({PrintDocument.TotalPages} Seiten) gedruckt werden?\n" +
$"Sind die \"Duplex-Einstellungen\" des Standarddruckers entsprechend eingestellt (doppelseitig bzw. einseitig)?",
"Rundschreiben drucken", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
if (res == MessageBoxResult.Yes) {
Mouse.OverrideCursor = Cursors.AppStarting;
if (App.Config.Debug) {
PrintDocument.Show();
} else {
await PrintDocument.Print();
}
Mouse.OverrideCursor = null;
}
PrintButton.IsEnabled = true;
}
private async void EmailButton_Click(object sender, RoutedEventArgs evt) {
if (App.Config.Smtp == null || EmailDocuments == null) return;
EmailButton.IsEnabled = false;
SmtpClient? client = null;
try {
Mouse.OverrideCursor = Cursors.AppStarting;
client = await Utils.GetSmtpClient();
Mouse.OverrideCursor = null;
var res = MessageBox.Show($"Sollen {EmailDocuments.Count} E-Mails verschickt werden?",
"Rundschreiben verschicken", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
if (res != MessageBoxResult.Yes) {
return;
}
Mouse.OverrideCursor = Cursors.AppStarting;
var subject = EmailSubjectInput.Text;
var text = EmailBodyInput.Text;
foreach (var (m, docs) in EmailDocuments) {
using var msg = new MimeMessage();
msg.From.Add(new MailboxAddress(App.Client.NameFull, App.Config.Smtp.Value.From));
msg.To.AddRange(m.EmailAddresses.OrderBy(a => a.Nr).Select(a => new MailboxAddress(m.AdministrativeName, a.Address)));
msg.Subject = subject;
var body = new Multipart("mixed") {
new TextPart("plain") { Text = text }
};
foreach (var doc in docs) {
var name = Utils.NormalizeFileName(doc.Title);
body.Add(doc.AsEmailAttachment($"{name}.pdf"));
}
msg.Body = body;
await client!.SendAsync(msg);
}
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
} finally {
if (client != null)
await client.DisconnectAsync(true);
client?.Dispose();
EmailButton.IsEnabled = true;
Mouse.OverrideCursor = null;
}
}
public void AddDeliveryConfirmation() {
AvaiableDocumentsList.SelectedIndex = 1;
if (AvaiableDocumentsList.SelectedItem is not string s || SelectedDocs.Any(d => d.Type == DocType.DeliveryConfirmation))
return;
SelectedDocs.Add(new(DocType.DeliveryConfirmation, s, (Year, DocumentNonDeliverersInput.IsChecked == true)));
SelectedDocumentsList.SelectedIndex = SelectedDocs.Count - 1;
RecipientsDeliveryMembersInput.IsChecked = true;
}
public void AddCreditNote(int index) {
AvaiableDocumentsList.SelectedIndex = 2 + index;
if (AvaiableDocumentsList.SelectedItem is not string s || SelectedDocs.Any(d => d.Type == DocType.CreditNote))
return;
var name = s.Split(" ")[^1];
using var ctx = new AppDbContext();
var pv = ctx.PaymentVariants.Single(v => v.Year == Year && v.Name == name)!;
SelectedDocs.Add(new(DocType.CreditNote, s, (pv.Year, pv.AvNr)));
SelectedDocumentsList.SelectedIndex = SelectedDocs.Count - 1;
RecipientsDeliveryMembersInput.IsChecked = true;
}
}
}