Compare commits

..

11 Commits

Author SHA1 Message Date
94db0723c5 Bump version to 0.10.4
All checks were successful
Test / Run tests (push) Successful in 2m2s
Deploy / Build and Deploy (push) Successful in 2m48s
2024-08-22 13:36:38 +02:00
f54677d429 DeliveryAncmtAdminWindow: Display stats in status bar
All checks were successful
Test / Run tests (push) Successful in 2m27s
2024-08-22 13:32:08 +02:00
49e4b65c27 MemberAdminWindow: Display currently shown member count and business shares
All checks were successful
Test / Run tests (push) Successful in 2m25s
2024-08-22 12:29:41 +02:00
ada5085cae Validator: Add some syntax sugar
All checks were successful
Test / Run tests (push) Successful in 2m51s
2024-08-22 11:04:24 +02:00
85931e62e8 DeliveryAncmtAdminWindow: Show weekday also in ComboBox
All checks were successful
Test / Run tests (push) Successful in 11m7s
2024-08-21 16:57:21 +02:00
39956cbcbd Bump version to 0.10.3
All checks were successful
Test / Run tests (push) Successful in 2m25s
Deploy / Build and Deploy (push) Successful in 3m20s
2024-08-21 00:01:47 +02:00
84d8d0cecb DeliveryScheduleAdminWindow: Fix AncmtToDateInput input bug
All checks were successful
Test / Run tests (push) Successful in 2m3s
2024-08-20 23:39:08 +02:00
fe7f9d675b DeliveryAncmtAdminWindow: Add day of week to delivery schedule list
All checks were successful
Test / Run tests (push) Successful in 3m0s
2024-08-20 23:31:37 +02:00
9d1ee8638c Bump version to 0.10.2
All checks were successful
Test / Run tests (push) Successful in 1m59s
Deploy / Build and Deploy (push) Successful in 2m41s
2024-08-16 21:31:43 +02:00
cd40075702 ElwigData: Allow legacy field family_name to be used and other fixes
All checks were successful
Test / Run tests (push) Successful in 2m50s
2024-08-16 21:24:04 +02:00
204dfe8745 MemberService: Include area commitments when uploading export data 2024-08-16 21:23:32 +02:00
12 changed files with 134 additions and 37 deletions

View File

@ -3,6 +3,49 @@ Changelog
=========
[v0.10.4][v0.10.4] (2024-08-22) {#v0.10.4}
------------------------------------------
### Sonstiges {#v0.10.4-misc}
* Im Anmeldungen-Fenster (`DeliveryAncmtAdminWindow`) wird der Wochentag auch beim Bearbeiten angezeigt. (85931e62e8)
* Im Mitglieder-Fenster (`MemberAdminWindow`) werden Anzahl der Mitglieder und Geschäftsanteile nicht mehr von allen aktiven angezeigt, sonder von den momentan gefilterten. (49e4b65c27)
* Statusleiste im Anmeldungen-Fenster (`DeliveryAncmtAdminWindow`). (f54677d429)
[v0.10.4]: https://git.necronda.net/winzer/elwig/releases/tag/v0.10.4
[v0.10.3][v0.10.3] (2024-08-21) {#v0.10.3}
------------------------------------------
### Behobene Fehler {#v0.10.3-bugfixes}
* Datum für _Anmeldungen bis_ im Leseplan-Fenster (`DeliveryScheduleAdminWindow`) ab jetzt änderbar. (84d8d0cecb)
### Sonstiges {#v0.10.3-misc}
* Wochentag bei Leseplan-Liste im Anmeldungen-Fenster (`DeliveryAncmtAdminWindow`) anzeigen. (fe7f9d675b)
[v0.10.3]: https://git.necronda.net/winzer/elwig/releases/tag/v0.10.3
[v0.10.2][v0.10.2] (2024-08-16) {#v0.10.2}
------------------------------------------
### Behobene Fehler {#v0.10.2-bugfixes}
* Beim Hochladen der Mitgliederdaten sind Flächenbindungen nicht mitexportiert worden. (204dfe8745)
* Beim Importieren von älteren Exportdaten kam es zu einem Fehler. (cd40075702)
[v0.10.2]: https://git.necronda.net/winzer/elwig/releases/tag/v0.10.2
[v0.10.1][v0.10.1] (2024-08-14) {#v0.10.1}
------------------------------------------

View File

@ -7,7 +7,7 @@
<UseWPF>true</UseWPF>
<PreserveCompilationContext>true</PreserveCompilationContext>
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
<Version>0.10.1</Version>
<Version>0.10.4</Version>
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationManifest>app.manifest</ApplicationManifest>

View File

@ -39,6 +39,7 @@ namespace Elwig.Helpers.Export {
Dictionary<int, int> currentDids;
Dictionary<string, int> currentLsNrs;
Dictionary<int, List<WbRd>> currentWbRde;
Dictionary<int, AT_Kg> kgs;
using (var ctx = new AppDbContext()) {
branches = await ctx.Branches.ToDictionaryAsync(b => b.ZwstId);
@ -50,6 +51,7 @@ namespace Elwig.Helpers.Export {
currentWbRde = await ctx.WbRde
.GroupBy(r => r.KgNr)
.ToDictionaryAsync(g => g.Key, g => g.ToList());
kgs = await ctx.Katastralgemeinden.Include(k => k.WbKg).ToDictionaryAsync(k => k.KgNr);
}
var data = new List<(
@ -101,9 +103,9 @@ namespace Elwig.Helpers.Export {
string? line;
while ((line = await reader.ReadLineAsync()) != null) {
var obj = JsonNode.Parse(line)!.AsObject();
var (m, b, telNrs, emailAddrs) = obj.ToMember();
var (m, b, telNrs, emailAddrs) = obj.ToMember(kgs);
r.Members.Add(m);
if (b != null) data[^1].BillingAddresses.Add(b);
if (b != null) r.BillingAddresses.Add(b);
r.TelephoneNumbers.AddRange(telNrs);
r.EmailAddresses.AddRange(emailAddrs);
}
@ -115,9 +117,12 @@ namespace Elwig.Helpers.Export {
string? line;
while ((line = await reader.ReadLineAsync()) != null) {
var obj = JsonNode.Parse(line)!.AsObject();
var (areaCom, wbrd) = obj.ToAreaCom(currentWbRde);
var (areaCom, wbrd) = obj.ToAreaCom(kgs, currentWbRde);
r.AreaCommitments.Add(areaCom);
if (wbrd != null) r.Riede.Add(wbrd);
if (wbrd != null) {
currentWbRde[wbrd.KgNr].Add(wbrd);
r.Riede.Add(wbrd);
}
}
}
@ -223,6 +228,7 @@ namespace Elwig.Helpers.Export {
importedMembers.Add((meta.FileName, meta.ZwstId, meta.Device, n, o, members.Count - n - o, meta.MemberFilters));
}
if (areaCommitments.Count > 0) {
ctx.AddRange(riede);
var imported = areaCommitments.Where(c => (importNewMembers && !duplicateMgNrs.Contains(c.MgNr)) || (importDuplicateMembers && duplicateMgNrs.Contains(c.MgNr))).ToList();
importedAreaComs.Add((meta.FileName, meta.ZwstId, meta.Device, imported.Count, areaCommitments.Count - imported.Count, meta.AreaComFilters));
}
@ -457,12 +463,16 @@ namespace Elwig.Helpers.Export {
};
}
public static (Member, BillingAddr?, List<MemberTelNr>, List<MemberEmailAddr>) ToMember(this JsonNode json) {
public static (Member, BillingAddr?, List<MemberTelNr>, List<MemberEmailAddr>) ToMember(this JsonNode json, Dictionary<int, AT_Kg> kgs) {
var mgnr = json["mgnr"]!.AsValue().GetValue<int>();
var kgnr = json["default_kgnr"]?.AsValue().GetValue<int>();
if (kgnr != null && !kgs.Values.Any(k => k.WbKg?.KgNr == kgnr)) {
throw new ArgumentException($"Für KG {(kgs.TryGetValue(kgnr.Value, out var k) ? k.Name : "?")} ({kgnr:00000}) ist noch keine Großlage festgelegt!\n(Stammdaten → Herkunftshierarchie)");
}
return (new Member {
MgNr = mgnr,
PredecessorMgNr = json["predecessor_mgnr"]?.AsValue().GetValue<int>(),
Name = json["name"]!.AsValue().GetValue<string>(),
Name = json["name"]?.AsValue().GetValue<string>() ?? json["family_name"]!.AsValue().GetValue<string>(),
Prefix = json["prefix"]?.AsValue().GetValue<string>(),
GivenName = json["given_name"]?.AsValue().GetValue<string>(),
MiddleName = json["middle_names"]?.AsValue().GetValue<string>(),
@ -488,7 +498,7 @@ namespace Elwig.Helpers.Export {
CountryNum = json["address"]!["country"]!.AsValue().GetValue<int>(),
PostalDestId = json["address"]!["postal_dest"]!.AsValue().GetValue<string>(),
Address = json["address"]!["address"]!.AsValue().GetValue<string>(),
DefaultKgNr = json["default_kgnr"]?.AsValue().GetValue<int>(),
DefaultKgNr = kgnr,
ContactViaPost = json["contact_postal"]?.AsValue().GetValue<bool>() ?? false,
ContactViaEmail = json["contact_email"]?.AsValue().GetValue<bool>() ?? false,
Comment = json["comment"]?.AsValue().GetValue<string>(),
@ -528,13 +538,13 @@ namespace Elwig.Helpers.Export {
};
}
public static (AreaCom, WbRd?) ToAreaCom(this JsonNode json, Dictionary<int, List<WbRd>> riede) {
public static (AreaCom, WbRd?) ToAreaCom(this JsonNode json, Dictionary<int, AT_Kg> kgs, Dictionary<int, List<WbRd>> riede) {
var kgnr = json["kgnr"]!.AsValue().GetValue<int>();
var ried = json["ried"]?.AsValue().GetValue<string>();
WbRd? rd = null;
bool newRd = false;
if (ried != null) {
var rde = riede[kgnr] ?? throw new ArgumentException($"KG {kgnr:00000} is no WbKg");
var rde = riede[kgnr] ?? throw new ArgumentException($"Für KG {(kgs.TryGetValue(kgnr, out var k) ? k.Name : "?")} ({kgnr:00000}) ist noch keine Großlage festgelegt!\n(Stammdaten → Herkunftshierarchie)");
rd = rde.FirstOrDefault(r => r.Name == ried);
if (rd == null) {
newRd = true;

View File

@ -8,7 +8,7 @@ namespace Elwig.Helpers {
public static class Validator {
private static readonly Dictionary<string, string[][]> PHONE_NRS = new() {
{ "43", new string[][] {
{ "43", [
[],
["57", "59"],
[
@ -17,17 +17,17 @@ namespace Elwig.Helpers {
"650", "651", "652", "653", "655", "657", "659", "660", "661",
"663", "664", "665", "666", "667", "668", "669", "67", "68", "69"
]
} },
{ "49", Array.Empty<string[]>() },
{ "48", Array.Empty<string[]>() },
{ "420", Array.Empty<string[]>() },
{ "421", Array.Empty<string[]>() },
{ "36", Array.Empty<string[]>() },
{ "386", Array.Empty<string[]>() },
{ "39", Array.Empty<string[]>() },
{ "33", Array.Empty<string[]>() },
{ "41", Array.Empty<string[]>() },
{ "423", Array.Empty<string[]>() },
] },
{ "49", [] },
{ "48", [] },
{ "420", [] },
{ "421", [] },
{ "36", [] },
{ "386", [] },
{ "39", [] },
{ "33", [] },
{ "41", [] },
{ "423", [] },
};
public static ValidationResult CheckInteger(TextBox input, bool required) {

View File

@ -9,7 +9,6 @@ using Elwig.Documents;
using Elwig.Helpers.Export;
using Elwig.Models.Dtos;
using Microsoft.Win32;
using System.Net.Http;
using System.Windows.Input;
using System.Windows;
using System;
@ -27,6 +26,8 @@ namespace Elwig.Services {
}
public static void ClearInputs(this DeliveryAncmtAdminViewModel vm) {
vm.StatusAncmtCreated = "-";
vm.StatusAncmtModified = "-";
}
public static async Task FillInputs(this DeliveryAncmtAdminViewModel vm, DeliveryAncmt a) {
@ -34,6 +35,8 @@ namespace Elwig.Services {
vm.DeliverySchedule = (DeliverySchedule?)ControlUtils.GetItemFromSourceWithPk(vm.DeliveryScheduleSource, a.Year, a.DsNr);
vm.SortId = a.SortId;
vm.Weight = a.Weight;
vm.StatusAncmtCreated = $"{a.CreatedTimestamp:dd.MM.yyyy, HH:mm} ({a.Type})";
vm.StatusAncmtModified = a.ModifiedTimestamp != a.CreatedTimestamp ? $"{a.ModifiedTimestamp:dd.MM.yyyy, HH:mm}" : "-";
}
public static async Task<(List<string>, IQueryable<DeliveryAncmt>, List<string>)> GetFilters(this DeliveryAncmtAdminViewModel vm, AppDbContext ctx) {

View File

@ -460,26 +460,30 @@ namespace Elwig.Services {
try {
var filename = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{App.ZwstId}.elwig.zip";
var path = Path.Combine(App.TempPath, filename);
var list = await query
var members = await query
.OrderBy(m => m.MgNr)
.Include(m => m.BillingAddress)
.Include(m => m.TelephoneNumbers)
.Include(m => m.EmailAddresses)
.AsSplitQuery()
.ToListAsync();
if (list.Count == 0) {
var areaComs = await query
.SelectMany(m => m.AreaCommitments)
.Include(c => c.Rd)
.ToListAsync();
if (members.Count == 0) {
MessageBox.Show("Es wurden keine Mitglieder zum Hochladen ausgewählt!", "Mitglieder hochladen",
MessageBoxButton.OK, MessageBoxImage.Error);
} else {
await ElwigData.Export(path, list, filterNames);
await ElwigData.Export(path, members, areaComs, filterNames);
await Utils.UploadExportData(path, App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword);
MessageBox.Show($"Hochladen von {list.Count} Mitgliedern erfolgreich!", "Mitglieder hochgeladen",
MessageBox.Show($"Hochladen von {members.Count} Mitgliedern erfolgreich!", "Mitglieder hochgeladen",
MessageBoxButton.OK, MessageBoxImage.Information);
}
} catch (HttpRequestException exc) {
MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Lieferungen hochladen", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Mitglieder hochladen", MessageBoxButton.OK, MessageBoxImage.Error);
} catch (TaskCanceledException exc) {
MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Mitglieder hochladen", MessageBoxButton.OK, MessageBoxImage.Error);
} catch (Exception exc) {
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
}

View File

@ -62,6 +62,15 @@ namespace Elwig.ViewModels {
set => WeightString = $"{value}";
}
[ObservableProperty]
private string _statusAncmts = "-";
[ObservableProperty]
private string _statusWeight = "-";
[ObservableProperty]
private string _statusAncmtCreated = "-";
[ObservableProperty]
private string _statusAncmtModified = "-";
[ObservableProperty]
private Visibility _controlButtonsVisibility = Visibility.Visible;
[ObservableProperty]

View File

@ -61,7 +61,7 @@
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="250"/>
<ColumnDefinition Width="1.25*" MinWidth="250"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="1*" MinWidth="300"/>
</Grid.ColumnDefinitions>
@ -123,6 +123,7 @@
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Date, StringFormat='ddd.'}" Width="24"/>
<TextBlock Text="{Binding Date, StringFormat='dd.MM.'}" Width="32"/>
<TextBlock Text="{Binding ZwstId}" Width="25" TextAlignment="Center"/>
<TextBlock Text="{Binding Description}" Width="200"/>
@ -267,6 +268,7 @@
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Date, StringFormat='ddd.'}" Width="28"/>
<TextBlock Text="{Binding Date, StringFormat='dd.MM.'}" Width="35"/>
<TextBlock Text="{Binding ZwstId}" Width="30" TextAlignment="Center"/>
<TextBlock Text="{Binding Description}"/>
@ -305,9 +307,11 @@
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="1.125*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
@ -315,7 +319,27 @@
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem>
<TextBlock>
Anmeldungen: <Run Text="{Binding StatusAncmts}"/>
</TextBlock>
</StatusBarItem>
<Separator Grid.Column="1"/>
<StatusBarItem Grid.Column="2">
<TextBlock>
Gewicht: <Run Text="{Binding StatusWeight}"/>
</TextBlock>
</StatusBarItem>
<Separator Grid.Column="3"/>
<StatusBarItem Grid.Column="4">
<TextBlock>
Anmldg. erstellt: <Run Text="{Binding StatusAncmtCreated}"/>
</TextBlock>
</StatusBarItem>
<Separator Grid.Column="5"/>
<StatusBarItem Grid.Column="6">
<TextBlock>
Anmldg. geändert: <Run Text="{Binding StatusAncmtModified}"/>
</TextBlock>
</StatusBarItem>
</StatusBar>
</Grid>

View File

@ -127,6 +127,9 @@ namespace Elwig.Windows {
DeliveryAncmtList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
if (updateSort && DeliveryAncmtList.SelectedItem != null)
DeliveryAncmtList.ScrollIntoView(DeliveryAncmtList.SelectedItem);
ViewModel.StatusAncmts = $"{deliveryAncmts.Count:N0}";
ViewModel.StatusWeight = $"{deliveryAncmts.Sum(a => a.Weight):N0} kg";
}
private async Task RefreshInputs(bool validate = false) {

View File

@ -200,7 +200,7 @@
<Label Content="Datum/Zwst.:" Margin="10,10,0,10"/>
<TextBox x:Name="DateInput" Text="{Binding DateString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="0,10,10,10" Width="77" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
TextChanged="DateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
TextChanged="ScheduleDateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
<ComboBox x:Name="BranchInput" SelectedItem="{Binding Branch, Mode=TwoWay}" ItemsSource="{Binding BranchSource, Mode=TwoWay}"
DisplayMemberPath="Name" TextSearch.TextPath="Name"
Margin="82,10,10,10" Width="150" Grid.Column="1" HorizontalAlignment="Left"/>

View File

@ -297,8 +297,8 @@ namespace Elwig.Windows {
ViewModel.ControlButtonsVisibility = Visibility.Hidden;
}
private new void DateInput_TextChanged(object sender, TextChangedEventArgs evt) {
base.DateInput_TextChanged(sender, evt);
private void ScheduleDateInput_TextChanged(object sender, TextChangedEventArgs evt) {
DateInput_TextChanged(sender, evt);
if (ViewModel.Date is DateOnly date) {
ViewModel.AncmtToDate = date.AddDays(-2);
}

View File

@ -150,6 +150,9 @@ namespace Elwig.Windows {
MemberList_SelectionChanged, ViewModel.TextFilter.Count > 0 ? ControlUtils.RenewSourceDefault.IfOnly : ControlUtils.RenewSourceDefault.None, !updateSort);
if (updateSort && MemberList.SelectedItem != null)
MemberList.ScrollIntoView(MemberList.SelectedItem);
ViewModel.StatusMembers = $"{members.Count:N0} ({await ctx.Members.CountAsync():N0})";
ViewModel.StatusBusinessShares = $"{members.Sum(m => m.BusinessShares):N0} ({await ctx.Members.SumAsync(m => m.BusinessShares):N0})";
}
private async Task RefreshInputs(bool validate = false) {
@ -237,7 +240,6 @@ namespace Elwig.Windows {
var mM = Math.Max(mA.Length, Math.Max(mI.Length, mT.Length));
var mS = mM > 3;
if (mS) mM--;
ViewModel.StatusMembers = $"{mA} ({mT})";
ViewModel.StatusMembersToolTip =
$"{new string(s1, Math.Max(0, mM - mA.Length))}{(mS && mA.Length < 4 ? s2 : "")}{mA} aktive Mitglieder\n" +
$"{new string(s1, Math.Max(0, mM - mI.Length))}{(mS && mI.Length < 4 ? s2 : "")}{mI} nicht aktive Mitglieder\n" +
@ -249,7 +251,6 @@ namespace Elwig.Windows {
var bM = Math.Max(bA.Length, Math.Max(bI.Length, bT.Length));
var bS = bM > 3;
if (bS) bM--;
ViewModel.StatusBusinessShares = $"{bA} ({bT})";
ViewModel.StatusBusinessSharesToolTip =
$"{new string(s1, Math.Max(0, bM - bA.Length))}{(bS && bA.Length < 4 ? s2 : "")}{bA} Geschäftsanteile von aktiven Mitgliedern\n" +
$"{new string(s1, Math.Max(0, bM - bI.Length))}{(bS && bI.Length < 4 ? s2 : "")}{bI} Geschäftsanteile von nicht aktiven Mitgliedern\n" +