[#20][#80] Elwig: Update member_history and add different types of shares
Test / Run tests (push) Successful in 2m52s

This commit is contained in:
2026-07-01 11:01:15 +02:00
parent 4ebe07f579
commit 8f76d5158e
37 changed files with 857 additions and 264 deletions
+43 -43
View File
@@ -26,18 +26,18 @@ namespace Elwig.Windows {
Year = year;
// using (var ctx = new AppDbContext()) { SeasonLocked = ctx.Seasons.Find(Year + 1) != null; }
Title = $"Auszahlung anpassen - Lese {Year} - Elwig";
AutoAdjustBsButton.IsEnabled = !SeasonLocked;
UnAdjustBsButton.IsEnabled = !SeasonLocked;
AutoAdjustSharesButton.IsEnabled = !SeasonLocked;
UnAdjustSharesButton.IsEnabled = !SeasonLocked;
SaveCustomButton.IsEnabled = !SeasonLocked;
RemoveCustomButton.IsEnabled = !SeasonLocked;
CustomAmountInput.IsEnabled = !SeasonLocked;
CustomCommentInput.IsEnabled = !SeasonLocked;
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}";
AllowanceKgInput.Text = $"{App.Client.AutoAdjustShares.AllowanceKg}";
AllowanceShareInput.Text = $"{App.Client.AutoAdjustShares.AllowanceShares}";
AllowanceKgPerShareInput.Text = $"{App.Client.AutoAdjustShares.AllowanceKgPerShare}";
AllowancePercentInput.Text = $"{App.Client.AutoAdjustShares.AllowancePercent}";
MinSharesInput.Text = $"{App.Client.AutoAdjustShares.MinShares}";
}
protected override async Task OnRenewContext(AppDbContext ctx) {
@@ -46,7 +46,7 @@ namespace Elwig.Windows {
m.MgNr,
m.Name,
m.GivenName,
m.BusinessShares,
m.SharesActive,
m.IsActive,
})
.ToListAsync();
@@ -55,27 +55,27 @@ namespace Elwig.Windows {
var tbl1 = await OverUnderDeliveryData.ForSeason(ctx.OverUnderDeliveryRows, Year);
var tbl2 = await AreaComUnderDeliveryData.ForSeason(ctx.AreaComUnderDeliveryRows, Year);
var weight = tbl1.Rows.ToDictionary(r => r.MgNr, r => r.Weight);
var weight = tbl1.Rows.ToDictionary(r => r.MgNr, r => r.WeightTotal);
var areaComs = tbl2.Rows.ToDictionary(r => r.MgNr, r => r.VtrgIds.Zip(r.UnderDeliveries).ToDictionary(r => r.First, r => r.Second));
CustomPayments = await ctx.CustomPayments.Where(p => p.Year == Year).ToDictionaryAsync(p => p.MgNr, p => p);
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)
.ToDictionaryAsync(h => h.Key.MgNr, h => h.Sum(g => g.BusinessShares));
.Where(h => h.DateString.CompareTo($"{Year}-01-01") >= 0 && h.DateString.CompareTo($"{Year}-12-31") <= 0 && h.Reason == "auto" && h.Shares > 0)
.GroupBy(h => h.ToMember)
.ToDictionaryAsync(h => h.Key.MgNr, h => h.Sum(g => g.Shares));
var list = members
.Select(m => new {
m.MgNr, m.Name, m.GivenName,
m.IsActive,
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,
SharesActive = m.SharesActive - history.GetValueOrDefault(m.MgNr, 0),
DeliveryObligation = (m.SharesActive - history.GetValueOrDefault(m.MgNr, 0)) * season.MinKgPerShare,
DeliveryRight = (m.SharesActive - history.GetValueOrDefault(m.MgNr, 0)) * season.MaxKgPerShare,
Adjust = history.TryGetValue(m.MgNr, out int v2) ? (int?)v2 : null,
})
.Select(m => new {
m.MgNr, m.Name, m.GivenName,
m.BusinessShares,
m.SharesActive,
Weight = weight.GetValueOrDefault(m.MgNr, 0),
OverUnder = weight.TryGetValue(m.MgNr, out int v1) ?
(v1 < m.DeliveryObligation ? (int?)v1 - m.DeliveryObligation :
@@ -86,12 +86,12 @@ namespace Elwig.Windows {
})
.Select(m => new {
m.MgNr, m.Name, m.GivenName,
m.BusinessShares, m.Weight, m.OverUnder,
PenaltyBs = m.OverUnder != null && m.OverUnder < 0 ?
m.SharesActive, m.Weight, m.OverUnder,
PenaltyShares = m.OverUnder != null && m.OverUnder < 0 ?
(season.PenaltyPerKg * m.OverUnder ?? 0) +
(-season.PenaltyAmount ?? 0) +
(season.PenaltyPerBsAmount * Math.Floor(m.OverUnder / season.MinKgPerBusinessShare ?? 0m) ?? 0) +
(m.Weight == 0 ? (-season.PenaltyNone ?? 0) + (-season.PenaltyPerBsNone * m.BusinessShares ?? 0) : 0)
(season.PenaltyPerShareAmount * Math.Floor(m.OverUnder / season.MinKgPerShare ?? 0m) ?? 0) +
(m.Weight == 0 ? (-season.PenaltyNone ?? 0) + (-season.PenaltyPerShareNone * m.SharesActive ?? 0) : 0)
: (decimal?)null,
PenaltyAc = areaComs.TryGetValue(m.MgNr, out var c) ? c.Select(r => {
var con = contracts[r.Key];
@@ -103,30 +103,30 @@ namespace Elwig.Windows {
})
.Select(m => new {
m.MgNr, m.Name, m.GivenName,
m.BusinessShares, m.Weight, m.OverUnder,
PenaltyBs = m.PenaltyBs == null || m.PenaltyBs == 0 ? (decimal?)null : Math.Round((decimal)m.PenaltyBs, 2),
m.SharesActive, m.Weight, m.OverUnder,
PenaltyShares = m.PenaltyShares == null || m.PenaltyShares == 0 ? (decimal?)null : Math.Round((decimal)m.PenaltyShares, 2),
PenaltyAc = m.PenaltyAc == null ? (decimal?)null : Math.Round((decimal)m.PenaltyAc, 2),
m.Adjust,
AdjustAmount = m.AdjustAmount == null ? (decimal?)null : Math.Round((decimal)m.AdjustAmount, 2),
CustomAmount = m.Custom?.Amount,
ModAbs = m.Custom?.ModAbs,
ModRel = m.Custom?.ModRel,
m.Custom?.ModAbs,
m.Custom?.ModRel,
})
.Select(m => new {
m.MgNr, m.Name, m.GivenName,
m.BusinessShares, m.Weight, m.OverUnder,
m.PenaltyBs, m.PenaltyAc, m.Adjust, m.AdjustAmount, m.CustomAmount, m.ModAbs, m.ModRel,
Total = (m.PenaltyBs ?? 0) + (m.PenaltyAc ?? 0) + (m.AdjustAmount ?? 0) + (m.CustomAmount ?? 0),
m.SharesActive, m.Weight, m.OverUnder,
m.PenaltyShares, m.PenaltyAc, m.Adjust, m.AdjustAmount, m.CustomAmount, m.ModAbs, m.ModRel,
Total = (m.PenaltyShares ?? 0) + (m.PenaltyAc ?? 0) + (m.AdjustAmount ?? 0) + (m.CustomAmount ?? 0),
})
.Select(m => new {
m.MgNr, m.Name, m.GivenName,
m.BusinessShares, m.Weight, m.OverUnder,
m.PenaltyBs, m.PenaltyAc, m.Adjust, m.AdjustAmount, m.CustomAmount, m.ModAbs, m.ModRel,
m.SharesActive, m.Weight, m.OverUnder,
m.PenaltyShares, m.PenaltyAc, m.Adjust, m.AdjustAmount, m.CustomAmount, m.ModAbs, m.ModRel,
m.Total,
Background = m.Weight == 0 ? Brushes.Orange : m.Weight / 2 < -m.Total ? Brushes.Red : Brushes.White,
Foreground = m.Total == 0 ? Brushes.Gray : Brushes.Black,
})
.Where(m => m.OverUnder != null || m.Adjust != null || m.PenaltyBs != null || m.PenaltyAc != null || m.CustomAmount != null || m.ModAbs != null || m.ModRel != null)
.Where(m => m.OverUnder != null || m.Adjust != null || m.PenaltyShares != null || m.PenaltyAc != null || m.CustomAmount != null || m.ModAbs != null || m.ModRel != null)
.OrderByDescending(m => m.OverUnder ?? 0)
.ThenBy(m => m.Name)
.ThenBy(m => m.GivenName)
@@ -136,7 +136,7 @@ namespace Elwig.Windows {
MemberList.ItemsSource = list;
var sym = season.Currency.Symbol ?? season.Currency.Code;
PenaltyBusinessShares.Text = $"{list.Count(r => r.PenaltyBs != null && r.PenaltyBs != 0)} Mg. / {list.Sum(r => r.PenaltyBs):N2} {sym}";
PenaltyBusinessShares.Text = $"{list.Count(r => r.PenaltyShares != null && r.PenaltyShares != 0)} Mg. / {list.Sum(r => r.PenaltyShares):N2} {sym}";
PenaltyAreaCommitments.Text = $"{list.Count(r => r.PenaltyAc != null && r.PenaltyAc != 0)} Mg. / {list.Sum(r => r.PenaltyAc):N2} {sym}";
AutoBusinessShareAdjustment.Text = $"{list.Count(r => r.Adjust > 0)} Mg. / {list.Sum(r => r.Adjust)} GA / {list.Sum(r => r.AdjustAmount):N2} {sym}";
CustomModifiers.Text = $"{list.Count(r => r.CustomAmount != null)} Mg. / {list.Sum(r => r.CustomAmount):N2} {sym}";
@@ -147,25 +147,25 @@ namespace Elwig.Windows {
CustomAmountInput.Unit = sym;
}
private async void AutoAdjustBsButton_Click(object sender, RoutedEventArgs evt) {
private async void AutoAdjustSharesButton_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.Wait;
try {
int? kg = AllowanceKgInput.Text == "" ? null : int.Parse(AllowanceKgInput.Text);
double? bs = AllowanceBsInput.Text == "" ? null : double.Parse(AllowanceBsInput.Text);
int? kgPerBs = AllowanceKgPerBsInput.Text == "" ? null : int.Parse(AllowanceKgPerBsInput.Text);
double? shares = AllowanceShareInput.Text == "" ? null : double.Parse(AllowanceShareInput.Text);
int? kgPerShare = AllowanceKgPerShareInput.Text == "" ? null : int.Parse(AllowanceKgPerShareInput.Text);
double? percent = AllowancePercentInput.Text == "" ? null : double.Parse(AllowancePercentInput.Text);
int? minBs = MinBsInput.Text == "" ? null : int.Parse(MinBsInput.Text);
int? minShares = MinSharesInput.Text == "" ? null : int.Parse(MinSharesInput.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;
App.Client.AutoAdjustShares.AllowanceKg = kg;
App.Client.AutoAdjustShares.AllowanceShares = shares;
App.Client.AutoAdjustShares.AllowanceKgPerShare = kgPerShare;
App.Client.AutoAdjustShares.AllowancePercent = percent;
App.Client.AutoAdjustShares.MinShares = minShares;
await Task.Run(async () => {
await App.Client.UpdateValues();
var b = await Billing.Create(Year);
await b.AutoAdjustBusinessShares(new DateOnly(Year, 11, 30), kg ?? default, bs ?? default, kgPerBs ?? default, percent / 100.0 ?? default, minBs ?? default);
await b.AutoAdjustBusinessShares(new DateOnly(Year, 11, 30), kg ?? default, shares ?? default, kgPerShare ?? default, percent / 100.0 ?? default, minShares ?? default);
});
App.HintContextChange();
} catch (Exception exc) {
@@ -174,7 +174,7 @@ namespace Elwig.Windows {
Mouse.OverrideCursor = null;
}
private async void UnAdjustBsButton_Click(object sender, RoutedEventArgs evt) {
private async void UnAdjustSharesButton_Click(object sender, RoutedEventArgs evt) {
Mouse.OverrideCursor = Cursors.Wait;
try {
await Task.Run(async () => {
@@ -196,7 +196,7 @@ namespace Elwig.Windows {
Validator.CheckInteger((TextBox)sender, false, 6);
}
private void BsInput_TextChanged(object sender, TextChangedEventArgs evt) {
private void SharesInput_TextChanged(object sender, TextChangedEventArgs evt) {
Validator.CheckInteger((TextBox)sender, false, 3);
}