Compare commits
19 Commits
8c56717b9c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cfbcd0ab4 | ||
|
|
b82473ada2 | ||
|
|
1cba67253a | ||
|
|
63c1559110 | ||
|
|
b670ba11fa | ||
|
|
1ad57543d1 | ||
|
|
6cd4ea2df6 | ||
|
|
30e42afe35 | ||
|
|
70e127b2f0 | ||
|
|
7c73170b46 | ||
|
|
290f69e976 | ||
|
|
6ce08d7d4a | ||
|
|
86df6f6a63 | ||
|
|
eae0568ae0 | ||
|
|
4ebd6bc407 | ||
|
|
2c22306fef | ||
|
|
174223ba9e | ||
|
|
8e5709c215 | ||
|
|
b70bd5e324 |
@@ -5,7 +5,7 @@ namespace Logof_Client;
|
||||
|
||||
public class KasAddressList //Address-Set
|
||||
{
|
||||
public List<KasPersonError> errors = new();
|
||||
//public List<KasPersonError> errors = new();
|
||||
public List<KasPerson> KasPersons;
|
||||
|
||||
public KasAddressList(string name)
|
||||
@@ -13,12 +13,9 @@ public class KasAddressList //Address-Set
|
||||
KasPersons = new List<KasPerson>();
|
||||
Name = name;
|
||||
foreach (var set in Settings._instance.addressSets.addresses)
|
||||
{
|
||||
if (Name == set.Name)
|
||||
{
|
||||
Name = name + "-new";
|
||||
}
|
||||
}
|
||||
|
||||
var highest = 0;
|
||||
foreach (var k in Settings._instance.addressSets.addresses)
|
||||
if (highest <= k.ID)
|
||||
@@ -37,17 +34,20 @@ public class KasAddressList //Address-Set
|
||||
|
||||
public static string GenerateName(string basic_type, bool? is_rest = false)
|
||||
{
|
||||
if(is_rest == true)
|
||||
if (is_rest == true)
|
||||
return basic_type + " - " + DateTime.Now.ToShortDateString() + " - Rest";
|
||||
else
|
||||
return basic_type + " - " + DateTime.Now.ToShortDateString();
|
||||
}
|
||||
|
||||
public void UpdateErrorList(List<(int, List<AddressCheck.ErrorTypes>, List<AddressCheck.WarningTypes>)> errorList)
|
||||
{
|
||||
errors.Clear();
|
||||
foreach (var error in errorList) errors.Add(new KasPersonError(error));
|
||||
}
|
||||
// public void UpdateErrorList(List<KasPersonError> errorList)
|
||||
// {
|
||||
// //errors.Clear();
|
||||
// // foreach (KasPersonError err in errorList)
|
||||
// // {
|
||||
// //
|
||||
// // }
|
||||
// //foreach (var error in errorList) errors.Add(new KasPersonError(error));
|
||||
// }
|
||||
|
||||
public static int GetIDByAddressSetListItem(string listItemName)
|
||||
{
|
||||
@@ -58,6 +58,8 @@ public class KasAddressList //Address-Set
|
||||
|
||||
public class KasPerson
|
||||
{
|
||||
public KasPersonError PersonError = null;
|
||||
|
||||
public KasPerson()
|
||||
{
|
||||
refsid = 0;
|
||||
@@ -165,37 +167,24 @@ public class KasPerson
|
||||
|
||||
public class KasPersonError
|
||||
{
|
||||
public KasPersonError((int, List<AddressCheck.ErrorTypes>, List<AddressCheck.WarningTypes>) single_result)
|
||||
public KasPersonError((List<AddressCheck.ErrorTypes>, List<AddressCheck.WarningTypes>) single_result)
|
||||
{
|
||||
refsid = single_result.Item1;
|
||||
errors = single_result.Item2;
|
||||
warnings = single_result.Item3;
|
||||
// try
|
||||
// {
|
||||
// foreach (var err in single_result.Item2) errors += err + ", ";
|
||||
// errors = errors.Trim();
|
||||
// errors = errors.TrimEnd(',');
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// if (single_result.Item3 != null)
|
||||
// {
|
||||
// foreach (var err in single_result.Item3) warnings += err + ", ";
|
||||
// warnings = warnings.Trim();
|
||||
// warnings = warnings.TrimEnd(',');
|
||||
// }
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Console.WriteLine(e.Message);
|
||||
// }
|
||||
//refsid = single_result.Item1;
|
||||
errors = single_result.Item1;
|
||||
warnings = single_result.Item2;
|
||||
}
|
||||
|
||||
public int refsid { get; set; }
|
||||
//public int refsid { get; set; }
|
||||
public List<AddressCheck.ErrorTypes> errors { get; set; } = new();
|
||||
public List<AddressCheck.WarningTypes> warnings { get; set; } = new();
|
||||
|
||||
public string GetString()
|
||||
{
|
||||
var output = "";
|
||||
foreach (var error in errors) output += error + ", ";
|
||||
|
||||
foreach (var warning in warnings) output += warning + ", ";
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Lucide.Avalonia" Version="0.1.35"/>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4"/>
|
||||
<PackageReference Include="PdfSharp" Version="6.1.1"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
114
MainWindow.axaml
114
MainWindow.axaml
@@ -135,6 +135,7 @@
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button HorizontalAlignment="Stretch" IsEnabled="False"
|
||||
Click="BtnGenerateLabels_OnClick"
|
||||
HorizontalContentAlignment="Center" x:Name="BtnGenerateLabels"
|
||||
Margin="0,0,0,10">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -160,10 +161,12 @@
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<LucideIcon Kind="SquaresUnite" Width="36" Height="36" />
|
||||
<Label Content="Vereinigung" VerticalContentAlignment="Center" FontSize="15"
|
||||
<Label Content="Vereinigung" VerticalContentAlignment="Center"
|
||||
FontSize="15"
|
||||
FontWeight="Bold" />
|
||||
</StackPanel>
|
||||
<Label FontSize="9" Content="Fügt Elemente beider Mengen in eine Menge zusammen"></Label>
|
||||
<Label FontSize="9"
|
||||
Content="Fügt Elemente beider Mengen in eine Menge zusammen" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button HorizontalAlignment="Stretch" MinWidth="240"
|
||||
@@ -177,7 +180,8 @@
|
||||
FontSize="15"
|
||||
FontWeight="Bold" />
|
||||
</StackPanel>
|
||||
<Label FontSize="9" Content="Überträgt nur doppelte Elemente in die neue Menge"></Label>
|
||||
<Label FontSize="9"
|
||||
Content="Überträgt nur doppelte Elemente in die neue Menge" />
|
||||
</StackPanel>
|
||||
|
||||
</Button>
|
||||
@@ -192,7 +196,8 @@
|
||||
FontSize="15"
|
||||
FontWeight="Bold" />
|
||||
</StackPanel>
|
||||
<Label FontSize="9" Content="Elemente der ersten Menge ohne Elemente der zweiten Menge"></Label>
|
||||
<Label FontSize="9"
|
||||
Content="Elemente der ersten Menge ohne Elemente der zweiten Menge" />
|
||||
</StackPanel>
|
||||
|
||||
</Button>
|
||||
@@ -203,11 +208,12 @@
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<LucideIcon Kind="SquaresExclude" Width="36" Height="36" />
|
||||
<Label Content="Symmetrische Differenz" VerticalContentAlignment="Center"
|
||||
<Label Content="Symmetrische Differenz"
|
||||
VerticalContentAlignment="Center"
|
||||
FontSize="15"
|
||||
FontWeight="Bold" />
|
||||
</StackPanel>
|
||||
<Label FontSize="9" Content="Nur Elemente, die NICHT doppelt sind"></Label>
|
||||
<Label FontSize="9" Content="Nur Elemente, die NICHT doppelt sind" />
|
||||
</StackPanel>
|
||||
|
||||
</Button>
|
||||
@@ -241,6 +247,14 @@
|
||||
</StackPanel>
|
||||
</TabItem.Header>
|
||||
</TabItem>
|
||||
<TabItem IsEnabled="False">
|
||||
<TabItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<LucideIcon Kind="LibraryBig" Width="32" Height="32" Size="32" />
|
||||
<Label FontSize="20" Content="Wiki" VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TabItem.Header>
|
||||
</TabItem>
|
||||
<TabItem IsEnabled="True">
|
||||
<TabItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -315,6 +329,13 @@
|
||||
TextChanged="TbSettingsCustomerDescription_OnTextChanged"
|
||||
x:Name="TbSettingsCustomerDescription" />
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="150,*">
|
||||
<Label Content="Absenderadresse" />
|
||||
<TextBox Grid.Column="1" Watermark="Absenderadresse"
|
||||
HorizontalAlignment="Stretch"
|
||||
TextChanged="TbSettingsCustomerSenderAddress_OnTextChanged"
|
||||
x:Name="TbSettingsCustomerSenderAddress" />
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="150,*">
|
||||
<Label Content="CSV-Trennzeichen" />
|
||||
<TextBox Grid.Column="1" Watermark=","
|
||||
@@ -357,6 +378,87 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<LucideIcon Kind="Globe" Width="16" Height="16" Size="16" />
|
||||
<Label FontSize="16" Content="Länder" VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TabItem.Header>
|
||||
<Grid ColumnDefinitions="*,*">
|
||||
<Grid Grid.Column="0" Margin="5">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ListBox x:Name="CountryList" Grid.Row="0"
|
||||
SelectionChanged="CountryList_OnSelectionChanged" />
|
||||
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,250" Margin="0,5,0,0">
|
||||
<TextBox x:Name="TbSettingsNewCountry" />
|
||||
<Button Grid.Column="1" x:Name="BtnSettingsNewCountry"
|
||||
HorizontalAlignment="Stretch" Click="BtnSettingsNewCountry_OnClick"
|
||||
HorizontalContentAlignment="Center" Content="+ Hinzufügen"
|
||||
Margin="5,0,0,0" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Column="1" Margin="5">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid ColumnDefinitions="300,*" Margin="0,0,0,5">
|
||||
<TextBlock Text="Name:" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Column="1" x:Name="TbSettingsCountryName"
|
||||
TextChanged="TbSettingsCountryName_OnTextChanged" />
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="300,*" Margin="0,0,0,5" Grid.Row="1">
|
||||
<TextBlock Text="Übersetzung:" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Column="1" x:Name="TbSettingsCountryTranslation"
|
||||
TextChanged="TbSettingsCountryTranslation_OnTextChanged" />
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ListBox x:Name="LbSettingsAlternatives" Grid.Row="0" SelectionMode="Multiple" />
|
||||
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,200" Margin="0,5,0,0">
|
||||
<TextBox x:Name="TbSettingsNewCountryAlternative"
|
||||
Watermark="Kürzel/Alternative" />
|
||||
<Button Grid.Column="1" x:Name="BtnSettingsNewCountryAlternative"
|
||||
Content="+ Hinzufügen" Margin="5 0 0 0"
|
||||
HorizontalContentAlignment="Center"
|
||||
Click="BtnSettingsNewCountryAlternative_OnClick"
|
||||
HorizontalAlignment="Stretch" />
|
||||
</Grid>
|
||||
|
||||
<Button x:Name="BtnSettingsRemoveSelectedAlternatives" Grid.Row="2"
|
||||
Content="Ausgewählte Entfernen" Background="#99963434"
|
||||
HorizontalContentAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="BtnSettingsRemoveSelectedAlternatives_OnClick"
|
||||
Margin="0,5,0,0" />
|
||||
|
||||
<Button Grid.Row="3"
|
||||
Content="Land Entfernen" Background="#99963434"
|
||||
HorizontalContentAlignment="Center" x:Name="BtnSettingsRemoveCountry"
|
||||
HorizontalAlignment="Stretch" Click="BtnSettingsRemoveCountry_OnClick"
|
||||
Margin="0,5,0,0" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
@@ -11,6 +11,9 @@ namespace Logof_Client;
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public static MainWindow _instance;
|
||||
|
||||
private Country _selectedCountry;
|
||||
private bool _suppressCountryRefresh = false;
|
||||
public Uri filePath;
|
||||
|
||||
public MainWindow()
|
||||
@@ -26,6 +29,8 @@ public partial class MainWindow : Window
|
||||
Global.Load();
|
||||
Settings.Load();
|
||||
|
||||
RefreshCountryView();
|
||||
|
||||
//Thread.Sleep(3000);
|
||||
//Show();
|
||||
}
|
||||
@@ -249,13 +254,13 @@ public partial class MainWindow : Window
|
||||
var processor = new CombineAddresses(progressWindow);
|
||||
var result = await processor.Perform(address_lists, type, CbMergeExportUnmerged.IsChecked);
|
||||
|
||||
if(result.Item1 != null)
|
||||
if (result.Item1 != null)
|
||||
result.Item1.owner_id = owner_id;
|
||||
if(result.Item2 != null)
|
||||
if (result.Item2 != null)
|
||||
result.Item2.owner_id = owner_id;
|
||||
if(result.Item1 != null)
|
||||
if (result.Item1 != null)
|
||||
Settings._instance.addressSets.addresses.Add(result.Item1);
|
||||
if(result.Item2 != null)
|
||||
if (result.Item2 != null)
|
||||
Settings._instance.addressSets.addresses.Add(result.Item2);
|
||||
Settings.Save();
|
||||
progressWindow.Close();
|
||||
@@ -303,6 +308,7 @@ public partial class MainWindow : Window
|
||||
{
|
||||
TbSettingsCustomerDescription.Text = customer.description;
|
||||
TbSettingsCustomerName.Text = customer.name;
|
||||
TbSettingsCustomerSenderAddress.Text = customer.sender_address;
|
||||
TbSettingsCustomerCsvSeparator.Text = customer.separator.ToString();
|
||||
if (customer.patch != null)
|
||||
TbSettingsCustomerPatchInfo.Text = customer.patch.ToString();
|
||||
@@ -457,8 +463,8 @@ public partial class MainWindow : Window
|
||||
{
|
||||
BtnCheck.IsEnabled = true;
|
||||
BtnCombine.IsEnabled = true;
|
||||
BtnGenerateLabels.IsEnabled = true;
|
||||
|
||||
// BtnGenerateLabels.IsEnabled = true;
|
||||
// BtnRepair.IsEnabled = true;
|
||||
// BtnShorten.IsEnabled = true;
|
||||
}
|
||||
@@ -554,4 +560,163 @@ public partial class MainWindow : Window
|
||||
|
||||
StartCombine(list, Convert.ToInt32(LstCustomers.SelectedItem.ToString().Split(" - ")[0]), "symdiff");
|
||||
}
|
||||
|
||||
private async void BtnGenerateLabels_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var saveDialog = new SaveFileDialog
|
||||
{
|
||||
DefaultExtension = "pdf",
|
||||
Filters = { new FileDialogFilter { Name = "PDF-Dateien", Extensions = { "pdf" } } }
|
||||
};
|
||||
var filePath = await saveDialog.ShowAsync(this);
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
var builder = new PdfBuilder();
|
||||
|
||||
builder.CreateAddressLabelPdfFromAddressSetWithPlaceholder(
|
||||
Convert.ToInt32(LstCustomerAdressSets.SelectedItems[0].ToString().Split(" - ")[0]),
|
||||
"Company Logo/Info",
|
||||
filePath
|
||||
);
|
||||
//return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void TbSettingsCustomerSenderAddress_OnTextChanged(object? sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (LstSettingsCustomers.SelectedIndex == null || LstSettingsCustomers.SelectedIndex == -1) return;
|
||||
foreach (var customer in Settings._instance.customers.customers)
|
||||
if (customer.ID == Settings._instance.customers.current)
|
||||
customer.sender_address = TbSettingsCustomerSenderAddress.Text;
|
||||
}
|
||||
|
||||
|
||||
// Country Section
|
||||
private void BtnSettingsRemoveCountry_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedCountry != null)
|
||||
{
|
||||
Global._instance.countries.Remove(_selectedCountry);
|
||||
_selectedCountry = null;
|
||||
}
|
||||
|
||||
RefreshCountryView();
|
||||
}
|
||||
|
||||
public void RefreshCountryView()
|
||||
{
|
||||
if (_suppressCountryRefresh) return;
|
||||
try
|
||||
{
|
||||
_suppressCountryRefresh = true;
|
||||
|
||||
Global.Save();
|
||||
var alt_index = LbSettingsAlternatives.SelectedIndex;
|
||||
var country_index = CountryList.SelectedIndex;
|
||||
|
||||
LbSettingsAlternatives.Items.Clear();
|
||||
try
|
||||
{
|
||||
CountryList.Items.Clear();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
foreach (var c in Global._instance.countries) CountryList.Items.Add(c.name);
|
||||
try
|
||||
{
|
||||
CountryList.SelectedIndex = country_index;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_selectedCountry = Country.GetByName(CountryList.SelectedItems[0].ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
_selectedCountry = null;
|
||||
}
|
||||
|
||||
if (_selectedCountry == null) return;
|
||||
//Console.WriteLine("Refreshing alternatives...");
|
||||
foreach (var a in _selectedCountry.alternatives)
|
||||
{
|
||||
LbSettingsAlternatives.Items.Add(a);
|
||||
//Console.WriteLine(a);
|
||||
}
|
||||
|
||||
TbSettingsCountryName.Text = _selectedCountry.name;
|
||||
TbSettingsCountryTranslation.Text = _selectedCountry.translation;
|
||||
|
||||
try
|
||||
{
|
||||
LbSettingsAlternatives.SelectedIndex = alt_index;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_suppressCountryRefresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnSettingsRemoveSelectedAlternatives_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
foreach (var selected in LbSettingsAlternatives.SelectedItems)
|
||||
try
|
||||
{
|
||||
_selectedCountry.alternatives.Remove(selected.ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Error while removing country alternative");
|
||||
}
|
||||
|
||||
RefreshCountryView();
|
||||
}
|
||||
|
||||
private void BtnSettingsNewCountryAlternative_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(TbSettingsNewCountryAlternative.Text)) return;
|
||||
_selectedCountry.alternatives.Add(TbSettingsNewCountryAlternative.Text.Trim());
|
||||
RefreshCountryView();
|
||||
}
|
||||
|
||||
private void TbSettingsCountryTranslation_OnTextChanged(object? sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(TbSettingsCountryTranslation.Text))
|
||||
{
|
||||
_selectedCountry.translation = TbSettingsCountryTranslation.Text.Trim();
|
||||
RefreshCountryView();
|
||||
}
|
||||
}
|
||||
|
||||
private void TbSettingsCountryName_OnTextChanged(object? sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(TbSettingsCountryName.Text))
|
||||
{
|
||||
_selectedCountry.name = TbSettingsCountryName.Text.Trim();
|
||||
RefreshCountryView();
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnSettingsNewCountry_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(TbSettingsNewCountry.Text)) return;
|
||||
Global._instance.countries.Add(new Country(TbSettingsNewCountry.Text));
|
||||
RefreshCountryView();
|
||||
}
|
||||
|
||||
private void CountryList_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
_selectedCountry = Country.GetByName(CountryList.SelectedItems[0].ToString());
|
||||
RefreshCountryView();
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,9 @@
|
||||
x:Name="BtnShowSelected" Click="BtnShowSelected_OnClick"
|
||||
Margin="10,10,10,10" />
|
||||
</Grid>
|
||||
<DataGrid x:Name="DgResult" Grid.Column="1" AutoGenerateColumns="True" />
|
||||
<ScrollViewer Grid.Column="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel x:Name="StkResults" Orientation="Vertical" Margin="10" />
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace Logof_Client;
|
||||
|
||||
@@ -11,10 +13,10 @@ public partial class ResultWindow : Window
|
||||
{
|
||||
public List<CheckBox> errortypecheckboxes = new();
|
||||
public KasAddressList ur_addresses = new("Ergebnis_" + DateTime.Now.ToString("ddMMyy_HHmmss"));
|
||||
public List<KasPersonError> ur_result;
|
||||
public List<KasPerson> ur_result;
|
||||
public List<CheckBox> warningtypecheckboxes = new();
|
||||
|
||||
public ResultWindow(List<KasPersonError> result,
|
||||
public ResultWindow(List<KasPerson> result,
|
||||
int addressSetID)
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -24,12 +26,48 @@ public partial class ResultWindow : Window
|
||||
//ViewSingle(200552426);
|
||||
}
|
||||
|
||||
private void GenerateView(List<KasPersonError> result)
|
||||
private void GenerateView(List<KasPerson> result)
|
||||
{
|
||||
// var errors = new List<KasPersonError>();
|
||||
//foreach (var single_result in result) errors.Add(single_result);
|
||||
LblResultCount.Content = $"{result.Count}/{ur_result.Count} Ergebnisse";
|
||||
DgResult.ItemsSource = result;
|
||||
// Filter to only show persons with errors
|
||||
var result_with_errors = result.Where(p => p.PersonError != null).ToList();
|
||||
LblResultCount.Content = $"{result_with_errors.Count}/{ur_result.Count} Ergebnisse";
|
||||
|
||||
StkResults.Children.Clear();
|
||||
foreach (var person in result_with_errors) StkResults.Children.Add(CreatePersonGrid(person));
|
||||
}
|
||||
|
||||
private Grid CreatePersonGrid(KasPerson person)
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
ColumnDefinitions = ColumnDefinitions.Parse("100,*,100,*,100,*"),
|
||||
RowDefinitions = RowDefinitions.Parse("Auto"),
|
||||
Margin = new Thickness(0, 5, 0, 5),
|
||||
Background = new SolidColorBrush(Color.Parse("#F0F0F0"))
|
||||
};
|
||||
|
||||
// Refsid
|
||||
grid.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "refsid: ",
|
||||
FontWeight = FontWeight.Bold, Margin = new Thickness(5)
|
||||
});
|
||||
grid.Children.Add(new TextBlock { Text = person.refsid.ToString(), Margin = new Thickness(5) });
|
||||
Grid.SetColumn(grid.Children[1], 1);
|
||||
|
||||
// PLZ
|
||||
grid.Children.Add(new TextBlock { Text = "plz:", FontWeight = FontWeight.Bold, Margin = new Thickness(5) });
|
||||
Grid.SetColumn(grid.Children[2], 2);
|
||||
grid.Children.Add(new TextBlock { Text = person.plz, Margin = new Thickness(5) });
|
||||
Grid.SetColumn(grid.Children[3], 3);
|
||||
|
||||
// PPLZ
|
||||
grid.Children.Add(new TextBlock { Text = "errors:", FontWeight = FontWeight.Bold, Margin = new Thickness(5) });
|
||||
Grid.SetColumn(grid.Children[4], 4);
|
||||
grid.Children.Add(new TextBlock { Text = person.PersonError.GetString(), Margin = new Thickness(5) });
|
||||
Grid.SetColumn(grid.Children[5], 5);
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
private void ViewSingle(int refsid)
|
||||
@@ -62,18 +100,20 @@ public partial class ResultWindow : Window
|
||||
}
|
||||
}
|
||||
|
||||
private void Load(List<KasPersonError> result)
|
||||
private void Load(List<KasPerson> result)
|
||||
{
|
||||
var knownErrors = new List<AddressCheck.ErrorTypes>();
|
||||
var knownWarnings = new List<AddressCheck.WarningTypes>();
|
||||
|
||||
foreach (var single_result in result)
|
||||
foreach (var person in result)
|
||||
{
|
||||
foreach (var errtyp in single_result.errors)
|
||||
if (person.PersonError == null) continue;
|
||||
|
||||
foreach (var errtyp in person.PersonError.errors)
|
||||
if (!knownErrors.Contains(errtyp))
|
||||
knownErrors.Add(errtyp);
|
||||
|
||||
foreach (var wartyp in single_result.warnings)
|
||||
foreach (var wartyp in person.PersonError.warnings)
|
||||
if (!knownWarnings.Contains(wartyp))
|
||||
knownWarnings.Add(wartyp);
|
||||
}
|
||||
@@ -108,49 +148,75 @@ public partial class ResultWindow : Window
|
||||
|
||||
private void UpdateFilter()
|
||||
{
|
||||
var temp_result = new List<KasPersonError>();
|
||||
var checked_types = new List<AddressCheck.ErrorTypes>();
|
||||
var checked_types_war = new List<AddressCheck.WarningTypes>();
|
||||
var temp_result = new List<KasPerson>();
|
||||
|
||||
var checkedErrors = new HashSet<AddressCheck.ErrorTypes>();
|
||||
var checkedWarnings = new HashSet<AddressCheck.WarningTypes>();
|
||||
|
||||
// safer parsing: use TryParse and trim the Content string
|
||||
foreach (var cb in errortypecheckboxes)
|
||||
if (cb.IsChecked == true)
|
||||
checked_types.Add(
|
||||
(AddressCheck.ErrorTypes)Enum.Parse(typeof(AddressCheck.ErrorTypes), cb.Content.ToString()));
|
||||
{
|
||||
var s = cb.Content?.ToString()?.Trim();
|
||||
if (!string.IsNullOrEmpty(s) &&
|
||||
Enum.TryParse<AddressCheck.ErrorTypes>(s, true, out var et))
|
||||
checkedErrors.Add(et);
|
||||
}
|
||||
|
||||
foreach (var cb in warningtypecheckboxes)
|
||||
if (cb.IsChecked == true)
|
||||
checked_types_war.Add(
|
||||
(AddressCheck.WarningTypes)Enum.Parse(typeof(AddressCheck.WarningTypes), cb.Content.ToString()));
|
||||
|
||||
foreach (var sres in ur_result)
|
||||
{
|
||||
foreach (var err in sres.errors)
|
||||
if (checked_types.Contains(err) && !temp_result.Contains(sres))
|
||||
temp_result.Add(sres);
|
||||
|
||||
foreach (var war in sres.warnings)
|
||||
if (checked_types_war.Contains(war) && !temp_result.Contains(sres))
|
||||
temp_result.Add(sres);
|
||||
var s = cb.Content?.ToString()?.Trim();
|
||||
if (!string.IsNullOrEmpty(s) &&
|
||||
Enum.TryParse<AddressCheck.WarningTypes>(s, true, out var wt))
|
||||
checkedWarnings.Add(wt);
|
||||
}
|
||||
|
||||
// If no checkboxes are selected, show all persons with errors (default behavior)
|
||||
if (checkedErrors.Count == 0 && checkedWarnings.Count == 0)
|
||||
temp_result = ur_result.Where(p => p.PersonError != null).ToList();
|
||||
else
|
||||
foreach (var person in ur_result)
|
||||
{
|
||||
if (person.PersonError == null) continue;
|
||||
|
||||
//var errors = new List<KasPersonError>();
|
||||
//foreach (var single_result in temp_result) errors.Add(new KasPersonError(single_result));
|
||||
var personErrors = person.PersonError.errors ?? Enumerable.Empty<AddressCheck.ErrorTypes>();
|
||||
var personWarnings = person.PersonError.warnings ?? Enumerable.Empty<AddressCheck.WarningTypes>();
|
||||
|
||||
var matchesError = false;
|
||||
var matchesWarning = false;
|
||||
|
||||
// only test errors if the user selected error-types
|
||||
if (checkedErrors.Count > 0)
|
||||
matchesError = personErrors.Any(err => checkedErrors.Contains(err));
|
||||
|
||||
// only test warnings if the user selected warning-types
|
||||
if (checkedWarnings.Count > 0)
|
||||
matchesWarning = personWarnings.Any(war => checkedWarnings.Contains(war));
|
||||
|
||||
// If at least one category matches (OR across categories), include person
|
||||
if ((matchesError || matchesWarning) && !temp_result.Contains(person))
|
||||
temp_result.Add(person);
|
||||
}
|
||||
|
||||
LblResultCount.Content = $"{temp_result.Count}/{ur_result.Count} Ergebnisse";
|
||||
DgResult.ItemsSource = temp_result;
|
||||
|
||||
StkResults.Children.Clear();
|
||||
foreach (var person in temp_result) StkResults.Children.Add(CreatePersonGrid(person));
|
||||
}
|
||||
|
||||
|
||||
private void BtnShowSelected_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
foreach (var selected in DgResult.SelectedItems)
|
||||
try
|
||||
{
|
||||
var _asKas = (KasPersonError)selected;
|
||||
ViewSingle(_asKas.refsid);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
// foreach (var selected in DgResult.SelectedItems)
|
||||
// try
|
||||
// {
|
||||
// var _asKas = (KasPerson)selected;
|
||||
// ViewSingle(_asKas.refsid);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Console.WriteLine(ex.Message);
|
||||
// }
|
||||
}
|
||||
}
|
||||
37
Settings.cs
37
Settings.cs
@@ -62,6 +62,7 @@ public class Global
|
||||
}
|
||||
|
||||
public string config_path { get; set; } = "";
|
||||
public List<Country> countries { get; set; } = new();
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
@@ -121,10 +122,12 @@ public class Customer
|
||||
|
||||
public string name { get; set; } = "";
|
||||
public string description { get; set; } = "";
|
||||
public string sender_address { get; set; } = "";
|
||||
public AddressPatch patch { get; set; }
|
||||
public char separator { get; set; } = ',';
|
||||
public int ID { get; }
|
||||
|
||||
|
||||
public static int GetIDByCustomerListItem(string item_content)
|
||||
{
|
||||
var id = item_content.Split(" - ")[0];
|
||||
@@ -145,3 +148,37 @@ public class AddressSets
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class Country
|
||||
{
|
||||
public Country(string name, string translation, List<string> alternatives)
|
||||
{
|
||||
this.name = name;
|
||||
this.translation = translation;
|
||||
this.alternatives = alternatives;
|
||||
}
|
||||
|
||||
public Country(string name)
|
||||
{
|
||||
this.name = name;
|
||||
translation = "";
|
||||
alternatives = new List<string>();
|
||||
}
|
||||
|
||||
public Country()
|
||||
{
|
||||
}
|
||||
|
||||
public string? name { get; set; }
|
||||
public string translation { get; set; }
|
||||
public List<string> alternatives { get; set; }
|
||||
|
||||
public static Country GetByName(string name)
|
||||
{
|
||||
foreach (var country in Global._instance.countries)
|
||||
if (country.name == name)
|
||||
return country;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Threading;
|
||||
@@ -35,12 +36,20 @@ public class AddressCheck
|
||||
_progress = progressWindow;
|
||||
}
|
||||
|
||||
public async Task<List<KasPersonError>> Perform(int id)
|
||||
public async Task<List<KasPerson>> Perform(int id)
|
||||
{
|
||||
foreach (var adset in Settings._instance.addressSets.addresses)
|
||||
if (adset.ID == id)
|
||||
// Find the index of the address set with the given id
|
||||
var adset_index = -1;
|
||||
for (var i = 0; i < Settings._instance.addressSets.addresses.Count; i++)
|
||||
if (Settings._instance.addressSets.addresses[i].ID == id)
|
||||
{
|
||||
var failed_refsids = new List<KasPersonError>();
|
||||
adset_index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (adset_index == -1) return new List<KasPerson>();
|
||||
|
||||
var adset = Settings._instance.addressSets.addresses[adset_index];
|
||||
var total = adset.KasPersons.Count;
|
||||
var current = 0;
|
||||
|
||||
@@ -92,7 +101,6 @@ public class AddressCheck
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (!AddressCreator.CheckPLZ(person.pplz, person.land))
|
||||
{
|
||||
hasFaults = true;
|
||||
@@ -224,9 +232,13 @@ public class AddressCheck
|
||||
}
|
||||
|
||||
if (hasFaults)
|
||||
lock (failed_refsids)
|
||||
lock (Settings._instance.addressSets.addresses)
|
||||
{
|
||||
failed_refsids.Add(new KasPersonError((person.refsid, errors, warnings)));
|
||||
// Directly set PersonError in the address set
|
||||
var person_index = adset.KasPersons.IndexOf(person);
|
||||
if (person_index >= 0)
|
||||
Settings._instance.addressSets.addresses[adset_index].KasPersons[person_index].PersonError =
|
||||
new KasPersonError((errors, warnings));
|
||||
}
|
||||
|
||||
// Fortschritt aktualisieren
|
||||
@@ -241,11 +253,12 @@ public class AddressCheck
|
||||
});
|
||||
}
|
||||
});
|
||||
adset.errors = failed_refsids;
|
||||
Settings.Save();
|
||||
return failed_refsids;
|
||||
}
|
||||
|
||||
return null;
|
||||
Settings.Save();
|
||||
|
||||
// Return only the persons with errors from the address set
|
||||
return Settings._instance.addressSets.addresses[adset_index].KasPersons
|
||||
.Where(p => p.PersonError != null)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,50 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.JavaScript;
|
||||
|
||||
namespace Logof_Client;
|
||||
|
||||
public static class AddressCreator
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates max-seven-lines-long markdown address-string. Analyzes the KasPerson-Instance to find the best result.
|
||||
/// Creates max-seven-lines-long Markdown address-string. Analyzes the KasPerson-Instance to find the best result.
|
||||
/// </summary>
|
||||
/// <param name="refsid">KasPerson-ID</param>
|
||||
/// <returns>A markdown string with the address that is maximum seven lines long</returns>
|
||||
/// <returns>A Markdown string with the address that is maximum seven lines long</returns>
|
||||
public static string? CreateFinalMarkdownString2(int refsid)
|
||||
{
|
||||
// Maximum seven lines of information
|
||||
|
||||
// find the address
|
||||
KasPerson address = new KasPerson();
|
||||
string string_address = "";
|
||||
int address_line_count = 0;
|
||||
KasPerson? address = null;
|
||||
var string_address = "";
|
||||
var address_line_count = 0;
|
||||
foreach (var set in Settings._instance.addressSets.addresses)
|
||||
{
|
||||
var temp = set.KasPersons.FirstOrDefault(obj => obj.refsid == refsid);
|
||||
if (temp != null) break;
|
||||
if (temp != null)
|
||||
{
|
||||
address = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// no address found
|
||||
if (address == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (address == null) return null;
|
||||
|
||||
// let's get started: the name (and anrede), block-line-count: 1
|
||||
if (!string.IsNullOrEmpty(address.anrede))
|
||||
{
|
||||
if(address.anrede == "Herr") string_address += "Herrn";
|
||||
if (address.anrede == "Herr") string_address += "Herrn";
|
||||
else string_address += address.anrede;
|
||||
address_line_count++;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(address.name) && !string.IsNullOrEmpty(address.vorname))
|
||||
{
|
||||
string_address += " " + address.vorname + " " + address.name;
|
||||
} else if (!string.IsNullOrEmpty(address.name))
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(address.name))
|
||||
{
|
||||
|
||||
}
|
||||
else // Anrede but no name? to the trash!
|
||||
{
|
||||
@@ -85,94 +86,159 @@ public static class AddressCreator
|
||||
// Auswurf PDF mit PvSt.
|
||||
|
||||
/// <summary>
|
||||
/// Creates max-seven-lines-long markdown address-string. Analyzes the KasPerson-Instance to find the best result.
|
||||
/// Creates max-seven-lines-long Markdown address-string. Analyzes the KasPerson-Instance to find the best result.
|
||||
/// </summary>
|
||||
/// <param name="refsid">KasPerson-ID</param>
|
||||
/// <returns>A markdown string with the address that is maximum seven lines long</returns>
|
||||
/// <returns>A Markdown string with the address that is maximum seven lines long</returns>
|
||||
public static string? CreateFinalMarkdownString(int refsid)
|
||||
{
|
||||
// Maximum seven lines of information
|
||||
|
||||
// find the address
|
||||
KasPerson address = new KasPerson();
|
||||
string string_address = "";
|
||||
int address_line_count = 0;
|
||||
KasPerson? address = null;
|
||||
var string_address = "";
|
||||
var address_line_count = 0;
|
||||
foreach (var set in Settings._instance.addressSets.addresses)
|
||||
{
|
||||
var temp = set.KasPersons.FirstOrDefault(obj => obj.refsid == refsid);
|
||||
if (temp != null) break;
|
||||
if (temp != null)
|
||||
{
|
||||
address = temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// no address found
|
||||
if (address == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (address == null) return null;
|
||||
|
||||
// let's get started: we start from the bottom
|
||||
// if the country is not germany, set it
|
||||
// LAND: GER oder DE
|
||||
if (address.land.ToLower().Trim() != "germany" && address.land.ToLower().Trim() != "ger" && address.land.ToLower().Trim() != "" && address.land.ToLower().Trim() != "de" && address.land.ToLower().Trim() != "deutschland")
|
||||
if (address.land.ToLower().Trim() != "germany" && address.land.ToLower().Trim() != "ger" &&
|
||||
address.land.ToLower().Trim() != "" && address.land.ToLower().Trim() != "de" &&
|
||||
address.land.ToLower().Trim() != "deutschland")
|
||||
{
|
||||
string_address = "**" + address.land.Trim() + "**"; // Needs to be bold
|
||||
string_address = "\n**" + address.land.Trim() + "**"; // Needs to be bold
|
||||
address_line_count++;
|
||||
}
|
||||
|
||||
// Alternative A: pplz valid and city existing
|
||||
if (!string.IsNullOrEmpty(address.ort) && CheckPLZ(address.pplz, address.land))
|
||||
{
|
||||
string_address = address.pplz + " " + address.ort + "\n" + string_address;
|
||||
string_address = address.pplz + " " + address.ort + string_address;
|
||||
address_line_count++;
|
||||
if (!string.IsNullOrWhiteSpace(address.postfach))
|
||||
{
|
||||
string_address = address.postfach.Trim() + "\n" + string_address;
|
||||
string_address = "Postfach " + address.postfach.Trim() + "\n" + string_address;
|
||||
address_line_count++;
|
||||
}
|
||||
else
|
||||
else if (!string.IsNullOrWhiteSpace(address.strasse.Trim()))
|
||||
{
|
||||
string_address = address.strasse.Trim() + "\n" + string_address;
|
||||
address_line_count++;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(address.anredzus))
|
||||
var nameline = CreateNameLine(address.anredzus, address.anrede, address.titel, address.vorname,
|
||||
address.adel, address.name, address.namezus);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(nameline))
|
||||
{
|
||||
string_address = address.anredzus.Trim() + " " + address.titel.Trim()+ " " + address.vorname.Trim()+ " " + address.adel.Trim() + " " + address.name.Trim()+ " (" + address.namezus.Trim() + ")\n" + string_address;
|
||||
address_line_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
string_address = address.anrede.Trim() + " " + address.titel.Trim()+ " " + address.vorname.Trim()+ " " + address.adel.Trim() + " " + address.name.Trim()+ " (" + address.namezus.Trim() + ")\n" + string_address;
|
||||
string_address = nameline + string_address;
|
||||
address_line_count++;
|
||||
}
|
||||
|
||||
string[] nameattribs = new[] { address.name1, address.name2, address.name3, address.name4, address.name5 };
|
||||
// REIHENFOLGE
|
||||
var nameattribs = new[]
|
||||
{ address.name1, address.name2, address.name3, address.name4, address.name5, address.abteilung };
|
||||
|
||||
for (int i = 0; i < nameattribs.Length-1; i++)
|
||||
{
|
||||
if (address_line_count < 7)
|
||||
var names = "";
|
||||
for (var i = 0; i < nameattribs.Length; i++)
|
||||
try
|
||||
{
|
||||
if (address_line_count >= 7) break;
|
||||
if (!string.IsNullOrWhiteSpace(nameattribs[i]))
|
||||
{
|
||||
string_address += nameattribs[i] + "\n" + string_address;
|
||||
names += "\n" + nameattribs[i];
|
||||
address_line_count++;
|
||||
}
|
||||
}
|
||||
else break;
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("ERROR 15821");
|
||||
}
|
||||
|
||||
string_address = names + "\n" + string_address;
|
||||
} // Alternative B: plz valid and city existing
|
||||
else if (!string.IsNullOrEmpty(address.ort) && CheckPLZ(address.plz, address.land))
|
||||
{
|
||||
|
||||
}
|
||||
else // Error-Handling?
|
||||
string_address = address.plz + " " + address.ort + "\n" + string_address;
|
||||
address_line_count++;
|
||||
if (!string.IsNullOrWhiteSpace(address.strasse))
|
||||
{
|
||||
|
||||
string_address = address.strasse.Trim() + "\n" + string_address;
|
||||
address_line_count++;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(address.postfach.Trim()))
|
||||
{
|
||||
string_address = "Postfach " + address.postfach.Trim() + "\n" + string_address;
|
||||
address_line_count++;
|
||||
}
|
||||
|
||||
var nameline = CreateNameLine(address.anredzus, address.anrede, address.titel, address.vorname,
|
||||
address.adel, address.name, address.namezus);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(nameline))
|
||||
{
|
||||
string_address = nameline + string_address;
|
||||
address_line_count++;
|
||||
}
|
||||
|
||||
var nameattribs = new[]
|
||||
{ address.name1, address.name2, address.name3, address.name4, address.name5, address.abteilung };
|
||||
|
||||
var names = "";
|
||||
for (var i = 0; i < nameattribs.Length; i++)
|
||||
try
|
||||
{
|
||||
if (address_line_count >= 7) break;
|
||||
if (!string.IsNullOrWhiteSpace(nameattribs[i]))
|
||||
{
|
||||
names += "\n" + nameattribs[i];
|
||||
address_line_count++;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("ERROR 15821");
|
||||
}
|
||||
|
||||
string_address = names + "\n" + string_address;
|
||||
} // Error-Handling?
|
||||
|
||||
return string_address;
|
||||
return "Hier könnte eine\nAdresse stehen";
|
||||
}
|
||||
|
||||
public static string CreateNameLine(string anredezus, string anrede, string titel, string vorname, string adel,
|
||||
string name, string namezus)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(anredezus))
|
||||
return string.Join(" ",
|
||||
new[] { anredezus, titel, vorname, adel, name }
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||
)
|
||||
+ (string.IsNullOrWhiteSpace(namezus) ? "" : $" ({namezus.Trim()})")
|
||||
+ "\n";
|
||||
|
||||
// else
|
||||
return string.Join(" ",
|
||||
new[] { anrede, titel, vorname, adel, name }
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||
)
|
||||
+ (string.IsNullOrWhiteSpace(namezus) ? "" : $" ({namezus.Trim()})")
|
||||
+ "\n";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if a plz (or pplz) is valid
|
||||
/// </summary>
|
||||
@@ -181,28 +247,29 @@ public static class AddressCreator
|
||||
/// <returns>true or faslse, depending on result :+1:</returns>
|
||||
public static bool CheckPLZ(string plz, string land)
|
||||
{
|
||||
if (plz == null) return false;
|
||||
if (land.ToLower().Trim() != "germany" && land.ToLower().Trim() != "ger" && land.ToLower().Trim() != "" && land.ToLower().Trim() != "de" && land.ToLower().Trim() != "deutschland")
|
||||
{
|
||||
// if country is not germany... how should we check for a valid plz?
|
||||
if (string.IsNullOrWhiteSpace(plz)) return false;
|
||||
|
||||
// temporarily accept all of them
|
||||
return true;
|
||||
}
|
||||
var trimmedPlz = plz.Trim();
|
||||
var trimmedLand = land.ToLower().Trim();
|
||||
|
||||
// Check if it's a German country code
|
||||
var isGermany = trimmedLand == "germany" || trimmedLand == "ger" || trimmedLand == "de" ||
|
||||
trimmedLand == "deutschland" || trimmedLand == "";
|
||||
|
||||
if (isGermany)
|
||||
// For Germany (including empty land), accept numeric postal codes with 5 digits
|
||||
try
|
||||
{
|
||||
int iplz = Convert.ToInt32(plz);
|
||||
if (iplz > 999999 || iplz < 10000)
|
||||
var iplz = Convert.ToInt32(trimmedPlz);
|
||||
if (trimmedPlz.Length == 5) return true;
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// For non-German countries, accept any non-empty postal code
|
||||
return true;
|
||||
|
||||
} catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
391
Tasks/PdfBuilder.cs
Normal file
391
Tasks/PdfBuilder.cs
Normal file
@@ -0,0 +1,391 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PdfSharp;
|
||||
using PdfSharp.Drawing;
|
||||
using PdfSharp.Pdf;
|
||||
|
||||
namespace Logof_Client;
|
||||
|
||||
public class PdfBuilder
|
||||
{
|
||||
// Table layout
|
||||
private const int CellsPerRow = 3;
|
||||
private const int CellsPerPage = 21; // 3 columns × 7 rows
|
||||
private readonly XFont _boldFont = new("Arial", 9, XFontStyleEx.Bold);
|
||||
private readonly double _cellHeight = 42.43; // mm
|
||||
private readonly double _cellPaddingBottom = 5; // mm
|
||||
|
||||
// Padding inside cells
|
||||
private readonly double _cellPaddingLeft = 5; // mm
|
||||
private readonly double _cellPaddingTop = 5; // mm
|
||||
|
||||
// Cell dimensions (in mm)
|
||||
private readonly double _cellWidth = 70; // mm
|
||||
|
||||
// Font settings
|
||||
private readonly double _fontSize = 9;
|
||||
|
||||
private readonly double _marginBottom = 1; // mm
|
||||
|
||||
// Paper and layout settings
|
||||
private readonly double _marginLeft = 0; // mm
|
||||
private readonly double _marginRight = 0; // mm
|
||||
private readonly double _marginTop = 0; // mm
|
||||
private readonly XFont _regularFont = new("Arial", 9, XFontStyleEx.Regular);
|
||||
private readonly XFont _smallFont = new("Arial", 6, XFontStyleEx.Regular);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a PDF document with address stickers from an AddressSet in a 3×7 grid layout on A4 pages.
|
||||
/// </summary>
|
||||
/// <param name="addressSetId">The ID of the AddressSet to use</param>
|
||||
/// <param name="outputPath">Path where the PDF should be saved</param>
|
||||
public void CreateAddressLabelPdfFromAddressSet(int addressSetId, string outputPath)
|
||||
{
|
||||
// Find the AddressSet by ID
|
||||
var addressSet = Settings._instance.addressSets.GetAddressSetByID(addressSetId);
|
||||
if (addressSet == null)
|
||||
throw new ArgumentException($"AddressSet with ID {addressSetId} not found");
|
||||
|
||||
if (addressSet.KasPersons == null || addressSet.KasPersons.Count == 0)
|
||||
throw new ArgumentException($"AddressSet with ID {addressSetId} contains no addresses");
|
||||
|
||||
// Generate markdown addresses from all KasPersons in the set
|
||||
//var addresses = new string?[addressSet.KasPersons.Count];
|
||||
var addresses = new List<string>();
|
||||
|
||||
// find customer (owner) to include sender_address
|
||||
string senderLine = null;
|
||||
try
|
||||
{
|
||||
var owner = Settings._instance.customers.customers.FirstOrDefault(c => c.ID == addressSet.owner_id);
|
||||
if (owner != null && !string.IsNullOrWhiteSpace(owner.sender_address))
|
||||
// ensure single line and wrap in a small-font tag
|
||||
senderLine = "<font6>" + owner.sender_address.Replace("\n", " ").Trim() + "</font6>\n";
|
||||
}
|
||||
catch
|
||||
{
|
||||
senderLine = null;
|
||||
}
|
||||
|
||||
for (var i = 0; i < addressSet.KasPersons.Count; i++)
|
||||
{
|
||||
var addr = AddressCreator.CreateFinalMarkdownString(addressSet.KasPersons[i].refsid);
|
||||
if (string.IsNullOrWhiteSpace(addr.Trim())) continue;
|
||||
if (!string.IsNullOrEmpty(senderLine))
|
||||
addresses.Add(senderLine + addr);
|
||||
else
|
||||
addresses.Add(addr);
|
||||
}
|
||||
|
||||
CreateAddressLabelPdf(addresses, outputPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a PDF document with address stickers from an AddressSet with a placeholder in the first cell.
|
||||
/// </summary>
|
||||
/// <param name="addressSetId">The ID of the AddressSet to use</param>
|
||||
/// <param name="placeholderText">Text for the first cell (top-left)</param>
|
||||
/// <param name="outputPath">Path where the PDF should be saved</param>
|
||||
public void CreateAddressLabelPdfFromAddressSetWithPlaceholder(int addressSetId, string placeholderText,
|
||||
string outputPath)
|
||||
{
|
||||
// Find the AddressSet by ID
|
||||
var addressSet = Settings._instance.addressSets.GetAddressSetByID(addressSetId);
|
||||
if (addressSet == null)
|
||||
throw new ArgumentException($"AddressSet with ID {addressSetId} not found");
|
||||
|
||||
if (addressSet.KasPersons == null || addressSet.KasPersons.Count == 0)
|
||||
throw new ArgumentException($"AddressSet with ID {addressSetId} contains no addresses");
|
||||
|
||||
// Generate markdown addresses from all KasPersons in the set
|
||||
//var addresses = new string?[addressSet.KasPersons.Count];
|
||||
var addresses = new List<string>();
|
||||
|
||||
// find customer (owner) to include sender_address
|
||||
string senderLine = null;
|
||||
try
|
||||
{
|
||||
var owner = Settings._instance.customers.customers.FirstOrDefault(c => c.ID == addressSet.owner_id);
|
||||
if (owner != null && !string.IsNullOrWhiteSpace(owner.sender_address))
|
||||
senderLine = "<font6>" + owner.sender_address.Replace("\n", " ").Trim() + "</font6>\n";
|
||||
}
|
||||
catch
|
||||
{
|
||||
senderLine = null;
|
||||
}
|
||||
|
||||
for (var i = 0; i < addressSet.KasPersons.Count; i++)
|
||||
{
|
||||
var addr = AddressCreator.CreateFinalMarkdownString(addressSet.KasPersons[i].refsid);
|
||||
if (string.IsNullOrWhiteSpace(addr.Trim())) continue;
|
||||
if (!string.IsNullOrEmpty(senderLine))
|
||||
addresses.Add(senderLine + (addr ?? ""));
|
||||
else
|
||||
addresses.Add(addr);
|
||||
}
|
||||
|
||||
CreateAddressLabelPdfWithPlaceholder(addresses, placeholderText, outputPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a PDF document with address stickers in a 3×7 grid layout on A4 pages.
|
||||
/// </summary>
|
||||
/// <param name="addresses">Array of addresses (from CreateFinalMarkdownString)</param>
|
||||
/// <param name="outputPath">Path where the PDF should be saved</param>
|
||||
public void CreateAddressLabelPdf(List<string> addresses, string outputPath)
|
||||
{
|
||||
if (addresses == null || addresses.Count == 0)
|
||||
throw new ArgumentException("Addresses array cannot be null or empty");
|
||||
|
||||
var document = new PdfDocument();
|
||||
|
||||
var addressIndex = 0;
|
||||
while (addressIndex < addresses.Count)
|
||||
{
|
||||
var page = document.AddPage();
|
||||
page.Size = PageSize.A4;
|
||||
|
||||
using (var gfx = XGraphics.FromPdfPage(page))
|
||||
{
|
||||
// Draw the grid and fill cells
|
||||
DrawPage(gfx, addresses, ref addressIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the document
|
||||
document.Save(outputPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a PDF document with a single placeholder cell for other information.
|
||||
/// </summary>
|
||||
/// <param name="addresses">Array of addresses</param>
|
||||
/// <param name="placeholderText">Text for the first cell (top-left)</param>
|
||||
/// <param name="outputPath">Path where the PDF should be saved</param>
|
||||
public void CreateAddressLabelPdfWithPlaceholder(List<string> addresses, string placeholderText, string outputPath)
|
||||
{
|
||||
if (addresses == null || addresses.Count == 0)
|
||||
throw new ArgumentException("Addresses array cannot be null or empty");
|
||||
|
||||
var document = new PdfDocument();
|
||||
|
||||
var addressIndex = 0;
|
||||
var isFirstCell = true;
|
||||
|
||||
while (addressIndex < addresses.Count || isFirstCell)
|
||||
{
|
||||
var page = document.AddPage();
|
||||
page.Size = PageSize.A4;
|
||||
|
||||
using (var gfx = XGraphics.FromPdfPage(page))
|
||||
{
|
||||
DrawPageWithPlaceholder(gfx, addresses, ref addressIndex, ref isFirstCell, placeholderText);
|
||||
}
|
||||
}
|
||||
|
||||
document.Save(outputPath);
|
||||
}
|
||||
|
||||
private void DrawPage(XGraphics gfx, List<string> addresses, ref int addressIndex)
|
||||
{
|
||||
var cellCount = 0;
|
||||
|
||||
for (var row = 0; row < 7; row++)
|
||||
{
|
||||
for (var col = 0; col < 3; col++)
|
||||
{
|
||||
if (addressIndex >= addresses.Count) break;
|
||||
|
||||
var x = MmToPoints(_marginLeft + col * _cellWidth);
|
||||
var y = MmToPoints(_marginTop + row * _cellHeight);
|
||||
|
||||
DrawCell(gfx, x, y, addresses[addressIndex]);
|
||||
addressIndex++;
|
||||
cellCount++;
|
||||
}
|
||||
|
||||
if (addressIndex >= addresses.Count) break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPageWithPlaceholder(XGraphics gfx, List<string> addresses, ref int addressIndex,
|
||||
ref bool isFirstCell, string placeholderText)
|
||||
{
|
||||
var cellCount = 0;
|
||||
|
||||
for (var row = 0; row < 7; row++)
|
||||
for (var col = 0; col < 3; col++)
|
||||
{
|
||||
var x = MmToPoints(_marginLeft + col * _cellWidth);
|
||||
var y = MmToPoints(_marginTop + row * _cellHeight);
|
||||
|
||||
// First cell: placeholder
|
||||
if (isFirstCell)
|
||||
{
|
||||
DrawCell(gfx, x, y, placeholderText);
|
||||
isFirstCell = false;
|
||||
}
|
||||
else if (addressIndex < addresses.Count)
|
||||
{
|
||||
DrawCell(gfx, x, y, addresses[addressIndex]);
|
||||
addressIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawEmptyCell(gfx, x, y);
|
||||
}
|
||||
|
||||
cellCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCell(XGraphics gfx, double x, double y, string? address)
|
||||
{
|
||||
var cellWidthPoints = MmToPoints(_cellWidth);
|
||||
var cellHeightPoints = MmToPoints(_cellHeight);
|
||||
|
||||
// Draw cell border
|
||||
var rect = new XRect(x, y, cellWidthPoints, cellHeightPoints);
|
||||
gfx.DrawRectangle(XPens.Black, rect);
|
||||
|
||||
// Draw address content if available
|
||||
if (!string.IsNullOrEmpty(address)) DrawMarkdownText(gfx, address, x, y, cellWidthPoints, cellHeightPoints);
|
||||
}
|
||||
|
||||
private void DrawEmptyCell(XGraphics gfx, double x, double y)
|
||||
{
|
||||
var cellWidthPoints = MmToPoints(_cellWidth);
|
||||
var cellHeightPoints = MmToPoints(_cellHeight);
|
||||
|
||||
var rect = new XRect(x, y, cellWidthPoints, cellHeightPoints);
|
||||
gfx.DrawRectangle(XPens.Black, rect);
|
||||
}
|
||||
|
||||
private void DrawMarkdownText(XGraphics gfx, string text, double x, double y, double cellWidth, double cellHeight)
|
||||
{
|
||||
var paddingLeftPoints = MmToPoints(_cellPaddingLeft);
|
||||
var paddingTopPoints = MmToPoints(_cellPaddingTop);
|
||||
var paddingBottomPoints = MmToPoints(_cellPaddingBottom);
|
||||
|
||||
var maxWidth = cellWidth - paddingLeftPoints * 2;
|
||||
|
||||
// Split text by newlines and remove empty trailing lines
|
||||
var rawLines = text.Split(new[] { "\n" }, StringSplitOptions.None);
|
||||
var lines = rawLines.Where(l => l != null).ToArray();
|
||||
|
||||
// Use a conservative line height in points
|
||||
var lineHeight = _regularFont.Size * 1.2;
|
||||
|
||||
// Calculate total height of the text block
|
||||
var totalHeight = lines.Length * lineHeight;
|
||||
|
||||
// Start drawing from the top of the cell (align addresses to top)
|
||||
var startY = y + paddingTopPoints;
|
||||
|
||||
var currentY = startY;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
// Stop if we've reached the top boundary
|
||||
if (currentY + lineHeight > y + cellHeight - paddingBottomPoints + 0.001)
|
||||
break;
|
||||
|
||||
// Parse and draw the line with markdown support
|
||||
DrawLineWithMarkdown(gfx, line, x + paddingLeftPoints, currentY, maxWidth);
|
||||
currentY += lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawLineWithMarkdown(XGraphics gfx, string line, double x, double y, double maxWidth)
|
||||
{
|
||||
var currentX = x;
|
||||
var i = 0;
|
||||
|
||||
while (i < line.Length)
|
||||
{
|
||||
// Check for small-font tag <font6> ... </font6>
|
||||
if (i <= line.Length - 7 && line.Substring(i, 7) == "<font6>")
|
||||
{
|
||||
var endTag = line.IndexOf("</font6>", i + 7, StringComparison.Ordinal);
|
||||
if (endTag != -1)
|
||||
{
|
||||
var inner = line.Substring(i + 7, endTag - (i + 7));
|
||||
if (!string.IsNullOrEmpty(inner))
|
||||
{
|
||||
gfx.DrawString(inner, _smallFont, XBrushes.Black,
|
||||
new XRect(currentX, y, maxWidth - (currentX - x), _smallFont.Size * 1.2),
|
||||
XStringFormats.TopLeft);
|
||||
var measuredSmall = gfx.MeasureString(inner, _smallFont);
|
||||
currentX += measuredSmall.Width;
|
||||
}
|
||||
|
||||
i = endTag + 8; // move past </font6>
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for bold marker (**)
|
||||
if (i < line.Length - 1 && line[i] == '*' && line[i + 1] == '*')
|
||||
{
|
||||
// Find closing **
|
||||
var endIndex = line.IndexOf("**", i + 2, StringComparison.Ordinal);
|
||||
if (endIndex != -1)
|
||||
{
|
||||
var boldText = line.Substring(i + 2, endIndex - (i + 2));
|
||||
// Draw bold text and measure width accurately
|
||||
gfx.DrawString(boldText, _boldFont, XBrushes.Black,
|
||||
new XRect(currentX, y, maxWidth - (currentX - x), _boldFont.Size * 1.2),
|
||||
XStringFormats.TopLeft);
|
||||
var measured = gfx.MeasureString(boldText, _boldFont);
|
||||
currentX += measured.Width;
|
||||
i = endIndex + 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Regular text until next ** or end of line
|
||||
var nextBoldIndex = line.IndexOf("**", i, StringComparison.Ordinal);
|
||||
var textEnd = nextBoldIndex == -1 ? line.Length : nextBoldIndex;
|
||||
var regularText = line.Substring(i, textEnd - i);
|
||||
|
||||
if (!string.IsNullOrEmpty(regularText))
|
||||
{
|
||||
gfx.DrawString(regularText, _regularFont, XBrushes.Black,
|
||||
new XRect(currentX, y, maxWidth - (currentX - x), _regularFont.Size * 1.2), XStringFormats.TopLeft);
|
||||
var measured = gfx.MeasureString(regularText, _regularFont);
|
||||
currentX += measured.Width;
|
||||
}
|
||||
|
||||
i = textEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts millimeters to points (1 mm = 2.834645669 points)
|
||||
/// </summary>
|
||||
private double MmToPoints(double mm)
|
||||
{
|
||||
return mm * 2.834645669;
|
||||
}
|
||||
|
||||
// Configuration methods to allow customization
|
||||
|
||||
/// <summary>
|
||||
/// Sets the cell dimensions in millimeters
|
||||
/// </summary>
|
||||
public void SetCellDimensions(double width, double height)
|
||||
{
|
||||
if (width <= 0 || height <= 0)
|
||||
throw new ArgumentException("Cell dimensions must be positive");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the page margins in millimeters
|
||||
/// </summary>
|
||||
public void SetMargins(double left, double top, double right, double bottom)
|
||||
{
|
||||
if (left < 0 || top < 0 || right < 0 || bottom < 0)
|
||||
throw new ArgumentException("Margins cannot be negative");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user