Compare commits

...

7 Commits

Author SHA1 Message Date
lorenz.stechauner 70129695ae Bump version to 0.8.5
Test / Run tests (push) Successful in 1m41s
Deploy / Build and Deploy (push) Successful in 2m21s
2024-06-17 11:31:26 +02:00
lorenz.stechauner 51b9799b56 [#46] PaymentAdjustmentWindow: Persist parameters in ClientParameters
Test / Run tests (push) Successful in 1m53s
2024-06-17 11:25:35 +02:00
lorenz.stechauner c1903b1f36 [#46] PaymentAdjustmentWindow: Refine DataGrid
Test / Run tests (push) Successful in 1m55s
2024-06-17 11:03:32 +02:00
lorenz.stechauner 66eb177fbf [#46] Billing: Only adjust business shares for active members 2024-06-17 10:51:48 +02:00
lorenz.stechauner 87467bbe75 Export/Ebics: Remove blank line for not shown <Ctry/> 2024-06-17 10:47:14 +02:00
lorenz.stechauner abf465f821 OverUnderDeliveryData: Also show inactive members
Test / Run tests (push) Successful in 1m42s
2024-06-17 10:24:58 +02:00
lorenz.stechauner 792c18365e MailWindow: Send DeliveryConfirmations and CreditNotes also to inactive members
Test / Run tests (push) Successful in 2m16s
2024-06-17 10:17:28 +02:00
8 changed files with 132 additions and 37 deletions
+1 -1
View File
@@ -7,7 +7,7 @@
<UseWPF>true</UseWPF>
<PreserveCompilationContext>true</PreserveCompilationContext>
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
<Version>0.8.4</Version>
<Version>0.8.5</Version>
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationManifest>app.manifest</ApplicationManifest>
+4 -3
View File
@@ -41,7 +41,7 @@ namespace Elwig.Helpers.Billing {
UPDATE member
SET business_shares = member.business_shares - h.business_shares
FROM member_history h
WHERE h.date = '{Year}-11-30' AND h.type = 'auto' AND h.mgnr = member.mgnr;
WHERE h.date = '{Year}-11-30' AND h.type = 'auto' AND h.mgnr = member.mgnr AND member.active;
INSERT INTO member_history (mgnr, date, type, business_shares)
SELECT u.mgnr,
@@ -52,7 +52,8 @@ namespace Elwig.Helpers.Billing {
- {allowanceRel.ToString(CultureInfo.InvariantCulture)} * u.business_shares) AS bs
FROM v_total_under_delivery u
JOIN season s ON s.year = u.year
WHERE s.year = {Year} AND bs >= {addMinBs}
JOIN member m ON m.mgnr = u.mgnr
WHERE s.year = {Year} AND bs >= {addMinBs} AND m.active
ON CONFLICT DO UPDATE
SET business_shares = excluded.business_shares;
@@ -69,7 +70,7 @@ namespace Elwig.Helpers.Billing {
UPDATE member
SET business_shares = member.business_shares - h.business_shares
FROM member_history h
WHERE h.date = '{Year}-11-30' AND h.type = 'auto' AND h.mgnr = member.mgnr;
WHERE h.date = '{Year}-11-30' AND h.type = 'auto' AND h.mgnr = member.mgnr AND member.active;
DELETE FROM member_history WHERE date = '{Year}-11-30' AND type = 'auto';
""");
+16
View File
@@ -1,6 +1,7 @@
using Elwig.Models.Entities;
using Microsoft.Data.Sqlite;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
@@ -69,6 +70,8 @@ namespace Elwig.Helpers {
public int ExportEbicsVersion;
public int ExportEbicsAddress;
public (int? AllowanceKg, double? AllowanceBs, int? AllowanceKgPerBs, double? AllowancePercent, int? MinBs) AutoAdjustBs;
public ClientParameters(AppDbContext ctx) : this(ctx.ClientParameters.ToDictionary(e => e.Param, e => e.Value)) { }
public ClientParameters(Dictionary<string, string?> parameters) {
@@ -138,6 +141,15 @@ namespace Elwig.Helpers {
case "LINES": ExportEbicsAddress = 1; break;
case "FULL": ExportEbicsAddress = 2; break;
}
var autoAdjust = (parameters.GetValueOrDefault("AUTOADJUST_BUSINESSSHARES") ?? "").Split(';');
AutoAdjustBs = autoAdjust.Length == 5 ? (
int.TryParse(autoAdjust[0], out var v1) ? v1 : null,
double.TryParse(autoAdjust[1], out var v2) ? v2 : null,
int.TryParse(autoAdjust[2], out var v3) ? v3 : null,
double.TryParse(autoAdjust[3], out var v4) ? v4 : null,
int.TryParse(autoAdjust[4], out var v5) ? v5 : null
) : (null, null, null, null, null);
} catch {
throw new KeyNotFoundException();
}
@@ -171,6 +183,9 @@ namespace Elwig.Helpers {
case 1: exportEbicsAddress = "LINES"; break;
case 2: exportEbicsAddress = "FULL"; break;
}
string autoAdjust = $"{AutoAdjustBs.AllowanceKg};{AutoAdjustBs.AllowanceBs?.ToString(CultureInfo.InvariantCulture)};" +
$"{AutoAdjustBs.AllowanceKgPerBs};{AutoAdjustBs.AllowancePercent?.ToString(CultureInfo.InvariantCulture)};" +
$"{AutoAdjustBs.MinBs}";
return [
("CLIENT_NAME_TOKEN", NameToken),
("CLIENT_NAME_SHORT", NameShort),
@@ -199,6 +214,7 @@ namespace Elwig.Helpers {
("TEXT_EMAIL_BODY", TextEmailBody),
("EXPORT_EBICS_VERSION", ExportEbicsVersion.ToString()),
("EXPORT_EBICS_ADDRESS", exportEbicsAddress),
("AUTOADJUST_BUSINESSSHARES", autoAdjust),
];
}
+2 -4
View File
@@ -88,13 +88,11 @@ namespace Elwig.Helpers.Export {
if (ShowAddresses != AddressMode.Omit) {
var full = ShowAddresses == AddressMode.Full;
await Writer.WriteLineAsync($"""
<PstlAdr>
{(full ? "" : $"<Ctry>{a.PostalDest.Country.Alpha2}</Ctry>")}
<PstlAdr>{(full ? "" : $"\r\n <Ctry>{a.PostalDest.Country.Alpha2}</Ctry>")}
{(full ? $"<StrtNm>{SecurityElement.Escape(a1?[..Math.Min(70, a1.Length)])}</StrtNm> <BldgNb>{SecurityElement.Escape(a2?[..Math.Min(16, a2.Length)])}</BldgNb>" :
$"<AdrLine>{SecurityElement.Escape(a.Address[..Math.Min(70, a.Address.Length)])}</AdrLine>")}
<{(full ? "PstCd" : "AdrLine")}>{a.PostalDest.AtPlz?.Plz}{(full ? "</PstCd> <TwnNm>" : " ")}{SecurityElement.Escape(a.PostalDest.AtPlz?.Ort.Name)}</{(full ? "TwnNm" : "AdrLine")}>
{(full ? $"<Ctry>{a.PostalDest.Country.Alpha2}</Ctry>" : "")}
</PstlAdr>
{(full ? $" <Ctry>{a.PostalDest.Country.Alpha2}</Ctry>\r\n " : "")}</PstlAdr>
""");
}
await Writer.WriteLineAsync($"""
+1 -1
View File
@@ -38,7 +38,7 @@ namespace Elwig.Models.Dtos {
LEFT JOIN AT_ort o ON o.okz = p.okz
LEFT JOIN season s ON s.year = {year}
LEFT JOIN v_delivery d ON d.mgnr = m.mgnr AND d.year = s.year
WHERE m.active = 1
WHERE m.active = TRUE OR d.weight > 0
GROUP BY d.year, m.mgnr
ORDER BY 100.0 * sum / max_kg, m.mgnr;
""").ToListAsync();
+9 -3
View File
@@ -254,11 +254,13 @@ namespace Elwig.Windows {
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;
}
@@ -305,7 +307,7 @@ namespace Elwig.Windows {
if (RecipientsCustomInput.IsChecked == true) {
Recipients = MemberCustomInput.SelectedItems.Cast<Member>().ToList();
} else {
IQueryable<Member> query = ctx.Members.Where(m => m.IsActive);
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!));
@@ -317,11 +319,13 @@ namespace Elwig.Windows {
if (RecipientsAreaComMembersInput.IsChecked == true) {
var vtrg = MemberAreaComInput.SelectedItems.Cast<AreaComType>().Select(a => a.VtrgId).ToList();
query = query.Where(m => m.AreaCommitments.AsQueryable().Where(Utils.ActiveAreaCommitments(Year)).Any(c => vtrg.Contains(c.VtrgId)));
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.Deliveries.Any(d => d.Year == Year));
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)
@@ -715,6 +719,7 @@ namespace Elwig.Windows {
return;
SelectedDocs.Add(new(DocType.DeliveryConfirmation, s, (Year, DocumentNonDeliverersInput.IsChecked == true)));
SelectedDocumentsList.SelectedIndex = SelectedDocs.Count - 1;
RecipientsDeliveryMembersInput.IsChecked = true;
}
public void AddCreditNote(int index) {
@@ -726,6 +731,7 @@ namespace Elwig.Windows {
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;
}
}
}
+38 -15
View File
@@ -6,7 +6,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Elwig.Windows"
xmlns:ctrl="clr-namespace:Elwig.Controls"
Title="Auszahlung anpassen - Elwig" Height="500" Width="800" MinHeight="400" MinWidth="700">
Title="Auszahlung anpassen - Elwig" Height="500" Width="850" MinHeight="400" MinWidth="850">
<Window.Resources>
<Style TargetType="Label">
<Setter Property="HorizontalAlignment" Value="Left"/>
@@ -44,7 +44,7 @@
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="450"/>
<ColumnDefinition Width="2.5*"/>
</Grid.ColumnDefinitions>
@@ -52,18 +52,41 @@
</Menu>
<Grid Grid.Row="1">
<ListBox x:Name="MemberList" Margin="10,10,10,10">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding MgNr}" Width="30" TextAlignment="Right" Margin="0,0,10,0"/>
<TextBlock Text="{Binding FamilyName}" Width="100"/>
<TextBlock Text="{Binding GivenName}" Width="60"/>
<TextBlock Text="{Binding BusinessShares}" Width="40" TextAlignment="Right"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<DataGrid x:Name="MemberList" AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single"
CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False" Margin="10,10,10,10">
<DataGrid.Columns>
<DataGridTextColumn Header="MgNr." Binding="{Binding MgNr, StringFormat='{}{0} '}" Width="45">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Nachname" Binding="{Binding FamilyName}" Width="100"/>
<DataGridTextColumn Header="Vorname" Binding="{Binding GivenName}" Width="100"/>
<DataGridTextColumn Header="GA" Binding="{Binding BusinessShares, StringFormat='{}{0} '}" Width="35">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Ü.-/U.-Lfrg." Binding="{Binding OverUnder, StringFormat='{}{0} kg '}" Width="70">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Nachz." Binding="{Binding Adjust, StringFormat='{}{0} '}" Width="45">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
<Grid Grid.Column="1" Grid.Row="1">
@@ -86,7 +109,7 @@
<ctrl:UnitTextBox x:Name="MinBsInput" Unit="GA" Margin="140,70,10,10" Width="50"
TextChanged="BsInput_TextChanged"/>
<Button x:Name="SeasonButton" Content="GA-Wert" Margin="10,10,10,40" Width="120"
<Button x:Name="SeasonButton" Content="GA-Wert" Margin="10,10,10,42" Width="120"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Click="SeasonButton_Click"/>
<Button x:Name="AutoAdjustBsButton" Content="Nachzeichnen" Margin="10,10,135,10" Width="120"
+61 -10
View File
@@ -1,7 +1,9 @@
using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Models.Dtos;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
@@ -21,22 +23,64 @@ namespace Elwig.Windows {
SeasonLocked = ctx.Seasons.Find(Year + 1) != null;
}
Title = $"Auszahlung anpassen - Lese {Year} - Elwig";
AllowanceKgInput.Text = $"{App.Client.AutoAdjustBs.AllowanceKg}";
AllowanceBsInput.Text = $"{App.Client.AutoAdjustBs.AllowanceBs}";
AllowanceKgPerBsInput.Text = $"{App.Client.AutoAdjustBs.AllowanceKgPerBs}";
AllowancePercentInput.Text = $"{App.Client.AutoAdjustBs.AllowancePercent}";
MinBsInput.Text = $"{App.Client.AutoAdjustBs.MinBs}";
}
protected override async Task OnRenewContext(AppDbContext ctx) {
MemberList.ItemsSource = await ctx.MemberHistory
var members = await ctx.Members
.Select(m => new {
m.MgNr,
m.FamilyName,
m.GivenName,
m.BusinessShares,
})
.OrderBy(m => m.FamilyName)
.ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr)
.ToListAsync();
var season = (await ctx.Seasons.FindAsync(Year))!;
var tbl = await OverUnderDeliveryData.ForSeason(ctx.OverUnderDeliveryRows, Year);
var weight = tbl.Rows.ToDictionary(r => r.MgNr, r => r.Weight);
var history = await ctx.MemberHistory
.Where(h => h.DateString.CompareTo($"{Year}-01-01") >= 0 && h.DateString.CompareTo($"{Year}-12-31") <= 0 && h.Type == "auto" && h.BusinessShares > 0)
.GroupBy(h => h.Member)
.Select(h => new {
h.Key.MgNr,
h.Key.FamilyName,
h.Key.GivenName,
BusinessShares = h.Sum(g => g.BusinessShares),
.ToDictionaryAsync(h => h.Key.MgNr, h => h.Sum(g => g.BusinessShares));
var list = members
.Select(m => new {
m.MgNr,
m.FamilyName,
m.GivenName,
BusinessShares = m.BusinessShares - history.GetValueOrDefault(m.MgNr, 0),
DeliveryObligation = (m.BusinessShares - history.GetValueOrDefault(m.MgNr, 0)) * season.MinKgPerBusinessShare,
DeliveryRight = (m.BusinessShares - history.GetValueOrDefault(m.MgNr, 0)) * season.MaxKgPerBusinessShare,
})
.OrderBy(h => h.FamilyName)
.ThenBy(h => h.GivenName)
.ThenBy(h => h.MgNr)
.ToListAsync();
.Select(m => new {
m.MgNr,
m.FamilyName,
m.GivenName,
m.BusinessShares,
OverUnder = weight.TryGetValue(m.MgNr, out int v1) ?
(v1 < m.DeliveryObligation ? (int?)v1 - m.DeliveryObligation :
v1 > m.DeliveryRight ? (int?)v1 - m.DeliveryRight : null)
: null,
Adjust = history.TryGetValue(m.MgNr, out int v2) ? (int?)v2 : null
})
.Where(m => m.OverUnder != null || m.Adjust != null)
.OrderByDescending(m => m.OverUnder)
.ThenBy(m => m.FamilyName)
.ThenBy(m => m.GivenName)
.ThenBy(m => m.MgNr)
.ToList();
MemberList.ItemsSource = list;
}
private async void AutoAdjustBsButton_Click(object sender, RoutedEventArgs evt) {
@@ -48,6 +92,13 @@ namespace Elwig.Windows {
double? percent = AllowancePercentInput.Text == "" ? null : double.Parse(AllowancePercentInput.Text);
int? minBs = MinBsInput.Text == "" ? null : int.Parse(MinBsInput.Text);
App.Client.AutoAdjustBs.AllowanceKg = kg;
App.Client.AutoAdjustBs.AllowanceBs = bs;
App.Client.AutoAdjustBs.AllowanceKgPerBs = kgPerBs;
App.Client.AutoAdjustBs.AllowancePercent = percent;
App.Client.AutoAdjustBs.MinBs = minBs;
await App.Client.UpdateValues();
var b = new Billing(Year);
await b.AutoAdjustBusinessShares(new DateOnly(Year, 11, 30), kg ?? default, bs ?? default, kgPerBs ?? default, percent / 100.0 ?? default, minBs ?? default);
await App.HintContextChange();