Compare commits
10 Commits
af8334a912
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d8cdd5d6e | |||
| 2350b55cea | |||
| e8789aff37 | |||
| 918555f2b8 | |||
| 1169ba5101 | |||
| 76da392f5f | |||
| 000117dc67 | |||
| 314a0d37a8 | |||
| 765edbdae6 | |||
| 9a0a422c8a |
@@ -2,6 +2,32 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
[v1.1.0.0][v1.1.0.0] (2026-07-09) {#v1.1.0.0}
|
||||
---------------------------------------------
|
||||
|
||||
### Neue Funktionen {#v1.1.0.0-features}
|
||||
|
||||
* Per Opt-In Einstellung in den Stammdaten ist es nun möglich Mitgliederbewegungen und Verläufe von Geschäftsanteilen mit Elwig zu erfassen. ([#20][i20])
|
||||
* Es wird nun unterstützt verschiedene Typen von Geschäftsanteilen pro Mitglied zu erfassen (normal, rot, weiß, ruhend). ([#80][i80])
|
||||
|
||||
### Behobene Fehler {#v1.1.0.0-bugfixes}
|
||||
|
||||
* Falls die Datenbank für die momentan verwndete Elwig-Version zu neu war kam es beim Überprüfen auf ein Update zu einem Fehler. (4ebe07f579)
|
||||
* Im Stammdatenblatt (`MemberDataSheet`) wurde die Stamm-Zweigstelle nicht angeführt. (a71c41af5c)
|
||||
|
||||
### Sonstiges {#v1.1.0.0-misc}
|
||||
|
||||
* In der Buchungsliste (`CreditNoteData`) wird nun auch das Buchhaltungskonto der Mitglieder angeführt. (000117dc67)
|
||||
* Viele kleine Verbesserungen der Code-Qualität. (u.a. fcd0555e4d, 69efca1cc3, beacba6bd9, 1169ba5101)
|
||||
* Abhängigkeiten aktualisiert. (e8789aff37, 2350b55cea)
|
||||
|
||||
[v1.1.0.0]: https://git.necronda.net/winzer/elwig/releases/tag/v1.1.0.0
|
||||
[i20]: https://git.necronda.net/winzer/elwig/issues/20
|
||||
[i80]: https://git.necronda.net/winzer/elwig/issues/80
|
||||
|
||||
|
||||
|
||||
|
||||
[v1.0.5.6][v1.0.5.6] (2026-06-25) {#v1.0.5.6}
|
||||
---------------------------------------------
|
||||
|
||||
|
||||
@@ -344,6 +344,10 @@ namespace Elwig {
|
||||
return FocusWindow<DeliveryAdminWindow>(() => new(true), w => w.ViewModel.IsReceipt);
|
||||
}
|
||||
|
||||
public static MemberBusinessSharesAdminWindow FocusMemberBusinessSharesWindow(int mgnr) {
|
||||
return FocusWindow<MemberBusinessSharesAdminWindow>(() => new(mgnr), w => w.ViewModel.FilterMember?.MgNr == mgnr);
|
||||
}
|
||||
|
||||
public static DeliveryAdminWindow FocusMemberDeliveries(int mgnr) {
|
||||
return FocusWindow<DeliveryAdminWindow>(() => new(mgnr), w => w.ViewModel.FilterMember?.MgNr == mgnr);
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace Elwig.Controls {
|
||||
|
||||
private void OnSelectionChanged(object sender, SelectionChangedEventArgs evt) {
|
||||
SelectItemsReverse();
|
||||
var dmp = !string.IsNullOrEmpty(ListDisplayMemberPath) ? ListDisplayMemberPath : !string.IsNullOrEmpty(DisplayMemberPath) ? DisplayMemberPath : null;
|
||||
var dmp = !string.IsNullOrWhiteSpace(ListDisplayMemberPath) ? ListDisplayMemberPath : !string.IsNullOrWhiteSpace(DisplayMemberPath) ? DisplayMemberPath : null;
|
||||
if (SelectedItems.Count == ItemsSource.Cast<object>().Count() && AllItemsSelectedContent != null) {
|
||||
AllItemsSelected = true;
|
||||
} else if (SelectedItems.Count == 0) {
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Elwig.Documents {
|
||||
public class BusinessDocument : Document {
|
||||
|
||||
public Member Member;
|
||||
public MemberHistoryPoint MemberHistory;
|
||||
public MemberHistoryPoint MemberShares;
|
||||
public string? Location;
|
||||
public bool IncludeSender = false;
|
||||
public bool UseBillingAddress = false;
|
||||
@@ -52,7 +52,7 @@ namespace Elwig.Documents {
|
||||
public BusinessDocument(string title, Member m, DateOnly? dateFrom, bool includeSender = false) :
|
||||
base(title) {
|
||||
Member = m;
|
||||
MemberHistory = new(m.Shares, m.SharesRed, m.SharesWhite, m.SharesDormant);
|
||||
MemberShares = new(m.Shares, m.SharesRed, m.SharesWhite, m.SharesDormant);
|
||||
Location = App.BranchLocation;
|
||||
IncludeSender = includeSender;
|
||||
DateFrom = dateFrom;
|
||||
@@ -318,19 +318,19 @@ namespace Elwig.Documents {
|
||||
.Where(b => !fbVars.Contains(b.Key))
|
||||
.OrderBy(b => b.Value.Name);
|
||||
|
||||
if (MemberHistory.Shares != 0 || (MemberHistory.SharesRed == 0 && MemberHistory.SharesWhite == 0)) {
|
||||
if (MemberShares.Shares != 0 || (MemberShares.SharesRed == 0 && MemberShares.SharesWhite == 0)) {
|
||||
tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA", isTiny: isTiny));
|
||||
tbl.AddCells(FormatRow(MemberHistory.Shares * (season.MinKgPerShare ?? 0), MemberHistory.Shares * (season.MaxKgPerShare ?? 0),
|
||||
tbl.AddCells(FormatRow(MemberShares.Shares * (season.MinKgPerShare ?? 0), MemberShares.Shares * (season.MaxKgPerShare ?? 0),
|
||||
deliveredWeightRed + deliveredWeightWhite, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
|
||||
}
|
||||
|
||||
if (MemberHistory.SharesRed != 0 || MemberHistory.SharesWhite != 0) {
|
||||
if (MemberShares.SharesRed != 0 || MemberShares.SharesWhite != 0) {
|
||||
tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA (rot)", isTiny: isTiny));
|
||||
tbl.AddCells(FormatRow(MemberHistory.SharesRed * (season.MinKgPerShareRed ?? season.MinKgPerShare ?? 0), MemberHistory.SharesRed * (season.MaxKgPerShareRed ?? season.MaxKgPerShare ?? 0),
|
||||
tbl.AddCells(FormatRow(MemberShares.SharesRed * (season.MinKgPerShareRed ?? season.MinKgPerShare ?? 0), MemberShares.SharesRed * (season.MaxKgPerShareRed ?? season.MaxKgPerShare ?? 0),
|
||||
deliveredWeightRed, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
|
||||
|
||||
tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA (weiß)", isTiny: isTiny));
|
||||
tbl.AddCells(FormatRow(MemberHistory.SharesWhite * (season.MinKgPerShareWhite ?? season.MinKgPerShare ?? 0), MemberHistory.SharesWhite * (season.MaxKgPerShareWhite ?? season.MaxKgPerShare ?? 0),
|
||||
tbl.AddCells(FormatRow(MemberShares.SharesWhite * (season.MinKgPerShareWhite ?? season.MinKgPerShare ?? 0), MemberShares.SharesWhite * (season.MaxKgPerShareWhite ?? season.MaxKgPerShare ?? 0),
|
||||
deliveredWeightWhite, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
|
||||
}
|
||||
|
||||
|
||||
@@ -101,11 +101,8 @@ namespace Elwig.Documents {
|
||||
MemberTotalUnderDelivery -= (season.PenaltyNone ?? 0) + (season.PenaltyPerShareNone * (Member.Shares + Member.SharesRed + Member.SharesWhite) ?? 0);
|
||||
}
|
||||
if (ConsiderAutoBusinessShares) {
|
||||
var fromDate = $"{season.Year}-01-01";
|
||||
var toDate = $"{season.Year}-12-31";
|
||||
MemberAutoBusinessShares = await ctx.MemberHistory
|
||||
.Where(h => h.ToMgNr == Member.MgNr && h.Reason == "auto")
|
||||
.Where(h => h.DateString.CompareTo(fromDate) >= 0 && h.DateString.CompareTo(toDate) <= 0)
|
||||
.Where(h => h.ToMgNr == Member.MgNr && h.DeductYear == season.Year)
|
||||
.SumAsync(h => h.Shares);
|
||||
MemberAutoBusinessSharesAmount = MemberAutoBusinessShares * (-season.BusinessShareValue ?? 0);
|
||||
}
|
||||
@@ -205,7 +202,7 @@ namespace Elwig.Documents {
|
||||
penalty += MemberTotalUnderDelivery;
|
||||
}
|
||||
if (MemberAutoBusinessSharesAmount != 0) {
|
||||
tbl2.AddCells(FormatRow($"Autom. Nachz. von GA ({MemberAutoBusinessShares})", MemberAutoBusinessSharesAmount, add: true));
|
||||
tbl2.AddCells(FormatRow($"Nachzeichnung von GA ({MemberAutoBusinessShares})", MemberAutoBusinessSharesAmount, add: true));
|
||||
penalty += MemberAutoBusinessSharesAmount;
|
||||
}
|
||||
if (CustomPayment?.Amount != null) {
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Elwig.Documents {
|
||||
.ToDictionaryAsync(g => g.Key, g => g.Sum(p => p.Weight));
|
||||
MemberDeliveredWeightRed = weights.GetValueOrDefault("R", 0);
|
||||
MemberDeliveredWeightWhite = weights.GetValueOrDefault("W", 0);
|
||||
MemberHistory = await ctx.GetMemberHistory(Season.Year, Member.MgNr);
|
||||
MemberShares = await ctx.GetMemberHistory(Season.Year, Member.MgNr);
|
||||
MemberBuckets = await ctx.GetMemberBuckets(Season.Year, Member.MgNr);
|
||||
MemberStats = await AppDbContext.GetMemberStats(Season.Year, Member.MgNr);
|
||||
Data ??= await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, Season.Year, Member);
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Elwig.Documents {
|
||||
.ToDictionaryAsync(g => g.Key, g => g.Sum(p => p.Weight));
|
||||
MemberDeliveredWeightRed = weights.GetValueOrDefault("R", 0);
|
||||
MemberDeliveredWeightWhite = weights.GetValueOrDefault("W", 0);
|
||||
MemberHistory = await ctx.GetMemberHistory(Delivery.Year, Member.MgNr);
|
||||
MemberShares = await ctx.GetMemberHistory(Delivery.Year, Member.MgNr);
|
||||
MemberBuckets = await ctx.GetMemberBuckets(Delivery.Year, Member.MgNr) ?? [];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using Elwig.Models.Entities;
|
||||
using iText.Kernel.Colors;
|
||||
using iText.Kernel.Pdf;
|
||||
@@ -20,6 +21,7 @@ namespace Elwig.Documents {
|
||||
public Season? Season;
|
||||
public int MemberDeliveredWeightRed;
|
||||
public int MemberDeliveredWeightWhite;
|
||||
public List<MemberHistory> MemberHistory = [];
|
||||
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
||||
public List<AreaCom> ActiveAreaCommitments = [];
|
||||
|
||||
@@ -37,6 +39,10 @@ namespace Elwig.Documents {
|
||||
protected override async Task LoadData(AppDbContext ctx) {
|
||||
await base.LoadData(ctx);
|
||||
Season = await ctx.FetchSeasons().FirstOrDefaultAsync() ?? throw new ArgumentException("Invalid season");
|
||||
MemberHistory = await ctx.MemberHistory
|
||||
.Where(h => h.FromMgNr == Member.MgNr || h.ToMgNr == Member.MgNr)
|
||||
.OrderBy(h => h.DateNoticeString).ThenBy(h => h.HistNr)
|
||||
.ToListAsync();
|
||||
MemberBuckets = await ctx.GetMemberBuckets(Utils.CurrentYear, Member.MgNr);
|
||||
ActiveAreaCommitments = await Member.ActiveAreaCommitments(ctx)
|
||||
.Include(c => c.Contract).ThenInclude(c => c.Revisions)
|
||||
@@ -61,9 +67,18 @@ namespace Elwig.Documents {
|
||||
doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
|
||||
firstOnPage = true;
|
||||
}
|
||||
doc.Add(new KernedParagraph(12).Add(Bold($"Flächenbindungen per {Date:dd.MM.yyyy}")).SetMargins(firstOnPage ? 0 : 24, 0, 12, 0));
|
||||
doc.Add(new KernedParagraph(12).Add(Bold($"Flächenbindungen per {Date:dd.MM.yyyy}")).SetMargins(firstOnPage ? 0 : 24, 0, 6, 0));
|
||||
doc.Add(NewAreaComTable(ActiveAreaCommitments));
|
||||
}
|
||||
if (App.Client.EnableMemberHistory) {
|
||||
bool firstOnPage = false;
|
||||
if (pdf.GetNumberOfPages() == 1) {
|
||||
doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
|
||||
firstOnPage = true;
|
||||
}
|
||||
doc.Add(new KernedParagraph(12).Add(Bold($"Verlauf der Geschäftsanteile per {Date:dd.MM.yyyy}")).SetMargins(firstOnPage ? 0 : 24, 0, 6, 0));
|
||||
doc.Add(NewMemberBusinessSharesTable(MemberHistory));
|
||||
}
|
||||
}
|
||||
|
||||
protected Cell NewDataHdr(string title, int colspan) {
|
||||
@@ -169,10 +184,10 @@ namespace Elwig.Documents {
|
||||
}).OrderByDescending(a => a.Size).ToList();
|
||||
|
||||
var tbl = new Table(ColsMM(40, 30, 35, 15, 25, 20), true)
|
||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||
.SetBorder(Border.NO_BORDER)
|
||||
.SetFontSize(10);
|
||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||
.SetBorder(Border.NO_BORDER)
|
||||
.SetFontSize(10);
|
||||
|
||||
tbl.AddHeaderCell(NewTh("Katastralgemeinde", rowspan: 2, left: true))
|
||||
.AddHeaderCell(NewTh("Ried", rowspan: 2, left: true))
|
||||
@@ -209,5 +224,142 @@ namespace Elwig.Documents {
|
||||
|
||||
return tbl;
|
||||
}
|
||||
|
||||
protected Cell[] NewBusinessSharesCells(MemberHistoryPoint p, bool isDiff = true) {
|
||||
if (App.Client.HasRedWhite) {
|
||||
return [
|
||||
NewTd(isDiff ? (p.SharesRed == 0 ? "" : p.SharesRed < 0 ? $"–{-p.SharesRed:N0}" : $"+{p.SharesRed:N0}") : $"{p.SharesRed:N0}",
|
||||
right: true, bold: !isDiff, borderTop: !isDiff),
|
||||
NewTd(isDiff ? (p.SharesWhite == 0 ? "" : p.SharesWhite < 0 ? $"–{-p.SharesWhite:N0}" : $"+{p.SharesWhite:N0}") : $"{p.SharesWhite:N0}",
|
||||
right: true, bold: !isDiff, borderTop: !isDiff),
|
||||
NewTd(isDiff ? (p.SharesDormant == 0 ? "" : p.SharesDormant < 0 ? $"–{-p.SharesDormant:N0}" : $"+{p.SharesDormant:N0}") : $"{p.SharesDormant:N0}",
|
||||
right: true, bold: !isDiff, borderTop: !isDiff),
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
NewTd(isDiff ? (p.Shares == 0 ? "" : p.Shares < 0 ? $"–{-p.Shares:N0}" : $"+{p.Shares:N0}") : $"{p.Shares:N0}",
|
||||
right: true, bold: !isDiff, borderTop: !isDiff),
|
||||
NewTd(isDiff ? (p.SharesDormant == 0 ? "" : p.SharesDormant < 0 ? $"–{-p.SharesDormant:N0}" : $"+{p.SharesDormant:N0}") : $"{p.SharesDormant:N0}",
|
||||
right : true, bold: !isDiff, borderTop: !isDiff),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
protected Table NewMemberBusinessSharesTable(IEnumerable<MemberHistory> history) {
|
||||
var tbl = new Table(ColsMM(18, 93, App.Client.HasRedWhite ? 18 : 12, App.Client.HasRedWhite ? 12 : 18, 12, 12), true)
|
||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||
.SetBorder(Border.NO_BORDER)
|
||||
.SetFontSize(10);
|
||||
|
||||
var tw = App.Client.HasRedWhite ? 1 : 2;
|
||||
tbl.AddHeaderCell(NewTh("Meldung am", rowspan: 2))
|
||||
.AddHeaderCell(NewTh("Text", rowspan: 2, colspan: tw, left: true))
|
||||
.AddHeaderCell(NewTh("Wirksam ab", rowspan: 2))
|
||||
.AddHeaderCell(NewTh("Geschäftsanteile", colspan: App.Client.HasRedWhite ? 3 : 2));
|
||||
if (App.Client.HasRedWhite) {
|
||||
tbl.AddHeaderCell(NewTh("rot"))
|
||||
.AddHeaderCell(NewTh("weiß"))
|
||||
.AddHeaderCell(NewTh("ruhend"));
|
||||
} else {
|
||||
tbl.AddHeaderCell(NewTh("normal"))
|
||||
.AddHeaderCell(NewTh("ruhend"));
|
||||
}
|
||||
|
||||
if (!history.Any() || Member.EntryDate <= history.First().DateNotice) {
|
||||
tbl.AddCell(NewTd($"{Member.EntryDate:dd.MM.yyyy}"))
|
||||
.AddCell(NewTd("Eintritt", colspan: tw, bold: true))
|
||||
.AddCell(NewTd($"{Member.EntryDate:dd.MM.yyyy}"))
|
||||
.AddCells(NewBusinessSharesCells(new()));
|
||||
}
|
||||
|
||||
var recorded = history.Aggregate(new MemberHistoryPoint(), (s, h) => new(
|
||||
s.Shares + (h.ToMgNr == Member.MgNr && h.ToType == BusinessShareType.Normal ? h.Shares : 0) - (h.FromMgNr == Member.MgNr && h.FromType == BusinessShareType.Normal ? h.Shares : 0),
|
||||
s.SharesRed + (h.ToMgNr == Member.MgNr && h.ToType == BusinessShareType.Red ? h.Shares : 0) - (h.FromMgNr == Member.MgNr && h.FromType == BusinessShareType.Red ? h.Shares : 0),
|
||||
s.SharesWhite + (h.ToMgNr == Member.MgNr && h.ToType == BusinessShareType.White ? h.Shares : 0) - (h.FromMgNr == Member.MgNr && h.FromType == BusinessShareType.White ? h.Shares : 0),
|
||||
s.SharesDormant + (h.ToMgNr == Member.MgNr && h.ToType == BusinessShareType.Dormant ? h.Shares : 0) - (h.FromMgNr == Member.MgNr && h.FromType == BusinessShareType.Dormant ? h.Shares : 0)));
|
||||
var cur = new MemberHistoryPoint(Member.Shares - recorded.Shares, Member.SharesRed - recorded.SharesRed, Member.SharesWhite - recorded.SharesWhite, Member.SharesDormant - recorded.SharesDormant);
|
||||
|
||||
if (cur.Shares != 0 || cur.SharesRed != 0 || cur.SharesWhite != 0 || cur.SharesDormant != 0) {
|
||||
tbl.AddCell(NewTd())
|
||||
.AddCell(NewTd("Nicht in Software erfasst", colspan: tw, italic: true))
|
||||
.AddCell(NewTd())
|
||||
.AddCells(NewBusinessSharesCells(cur));
|
||||
if (history.Any()) {
|
||||
tbl.AddCell(NewTd(borderTop: true))
|
||||
.AddCell(NewTd($"Bis Lese {history.First().DateNotice.Year - 1}", borderTop: true, colspan: tw, bold: true))
|
||||
.AddCell(NewTd(borderTop: true))
|
||||
.AddCells(NewBusinessSharesCells(cur, isDiff: false));
|
||||
}
|
||||
}
|
||||
|
||||
DateOnly? lastDate = null;
|
||||
foreach (var row in history) {
|
||||
int s = 0, r = 0, w = 0, d = 0;
|
||||
if (row.FromMgNr == Member.MgNr) {
|
||||
switch (row.FromType) {
|
||||
case BusinessShareType.Normal: s -= row.Shares; break;
|
||||
case BusinessShareType.Red: r -= row.Shares; break;
|
||||
case BusinessShareType.White: w -= row.Shares; break;
|
||||
case BusinessShareType.Dormant: d -= row.Shares; break;
|
||||
}
|
||||
}
|
||||
if (row.ToMgNr == Member.MgNr) {
|
||||
switch (row.ToType) {
|
||||
case BusinessShareType.Normal: s += row.Shares; break;
|
||||
case BusinessShareType.Red: r += row.Shares; break;
|
||||
case BusinessShareType.White: w += row.Shares; break;
|
||||
case BusinessShareType.Dormant: d += row.Shares; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDate < Member.EntryDate && row.DateNotice <= Member.EntryDate) {
|
||||
tbl.AddCell(NewTd($"{Member.EntryDate:dd.MM.yyyy}"))
|
||||
.AddCell(NewTd("Eintritt", colspan: tw, bold: true))
|
||||
.AddCell(NewTd($"{Member.EntryDate:dd.MM.yyyy}"))
|
||||
.AddCells(NewBusinessSharesCells(new()));
|
||||
}
|
||||
if (lastDate != null && row.DateNotice.Year != lastDate?.Year) {
|
||||
tbl.AddCell(NewTd(borderTop: true))
|
||||
.AddCell(NewTd(lastDate?.Year == row.DateNotice.Year - 1 ? $"Lese {lastDate?.Year}" : $"Lese {lastDate?.Year}–{row.DateNotice.Year - 1}", borderTop: true, colspan: tw, bold: true))
|
||||
.AddCell(NewTd(borderTop: true))
|
||||
.AddCells(NewBusinessSharesCells(cur, isDiff: false));
|
||||
}
|
||||
if (lastDate < Member.ExitDate && row.DateNotice <= Member.ExitDate) {
|
||||
tbl.AddCell(NewTd($"{Member.ExitDate:dd.MM.yyyy}"))
|
||||
.AddCell(NewTd("Austritt", colspan: tw, bold: true))
|
||||
.AddCell(NewTd($"31.12.{Member.ExitDate.Value.Year + 1}")) // FIXME
|
||||
.AddCells(NewBusinessSharesCells(new()));
|
||||
}
|
||||
cur = new(cur.Shares + s, cur.SharesRed + r, cur.SharesWhite + w, cur.SharesDormant + d);
|
||||
|
||||
tbl.AddCell(NewTd($"{row.DateNotice:dd.MM.yyyy}"))
|
||||
.AddCell(NewTd(row.FormatReasonPhrase(Member.MgNr), colspan: tw))
|
||||
.AddCell(NewTd($"{row.DateEffective:dd.MM.yyyy}"))
|
||||
.AddCells(NewBusinessSharesCells(new(s, r, w, d)));
|
||||
lastDate = row.DateNotice;
|
||||
}
|
||||
|
||||
if (Member.EntryDate != null && history.Any() && Member.EntryDate > lastDate) {
|
||||
tbl.AddCell(NewTd($"{Member.EntryDate:dd.MM.yyyy}"))
|
||||
.AddCell(NewTd("Eintritt", colspan: tw, bold: true))
|
||||
.AddCell(NewTd($"{Member.EntryDate:dd.MM.yyyy}"))
|
||||
.AddCells(NewBusinessSharesCells(new()));
|
||||
}
|
||||
|
||||
if (Member.ExitDate != null && (!history.Any() || Member.ExitDate > lastDate)) {
|
||||
tbl.AddCell(NewTd($"{Member.ExitDate:dd.MM.yyyy}"))
|
||||
.AddCell(NewTd("Austritt", colspan: tw, bold: true))
|
||||
.AddCell(NewTd($"31.12.{Member.ExitDate.Value.Year + 1}")) // FIXME
|
||||
.AddCells(NewBusinessSharesCells(new()));
|
||||
}
|
||||
|
||||
tbl.AddCell(NewTd(borderTop: true))
|
||||
.AddCell(NewTd(lastDate == null ? "Aktuell" : $"Ab Lese {lastDate?.Year}", borderTop: true, colspan: tw, bold: true))
|
||||
.AddCell(NewTd(borderTop: true))
|
||||
.AddCells(NewBusinessSharesCells(cur, isDiff: false));
|
||||
|
||||
return tbl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Elwig.Documents {
|
||||
.AddCell(NewTd($"{m.Plz}", 8))
|
||||
.AddCell(NewTd(m.Locality, 6))
|
||||
.AddCell(NewTd(m.LfbisNr ?? "", 8))
|
||||
.AddCell(NewTd($"{m.SharesTotal:N0}", 8, right: true).SetPaddingLeft(0).SetPaddingRight(0))
|
||||
.AddCell(NewTd($"{m.SharesActive:N0}", 8, right: true).SetPaddingLeft(0).SetPaddingRight(0))
|
||||
.AddCell(NewTd(m.DefaultKg ?? "", 6));
|
||||
if (AreaComFilters.Length > 0) {
|
||||
foreach (var v in AreaComFilters) {
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace Elwig.Documents {
|
||||
|
||||
.AddCell(NewSectionTh("Datum/Überw.:", overflow: true))
|
||||
.AddCell(NewTd($"{Variant.Date:dd.MM.yyyy} / {Variant.TransferDate:dd.MM.yyyy}", colspan: 4, center: true))
|
||||
.AddCell(NewSectionTh("Automatische Nachzeichnung der GA:", colspan: 2, borderLeft: true))
|
||||
.AddCell(NewSectionTh("(Automatische) Nachzeichnung von GA:", colspan: 2, borderLeft: true))
|
||||
.AddCell(NewTd(BillingData.ConsiderAutoBusinessShares ? "Ja" : "Nein", center: true))
|
||||
|
||||
.AddCell(NewSectionTh("Berechnung:"))
|
||||
|
||||
+5
-5
@@ -9,7 +9,7 @@
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
|
||||
<Version>1.0.5.6</Version>
|
||||
<Version>1.1.0.0</Version>
|
||||
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
@@ -23,15 +23,15 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="bblanchon.PDFium.Win32" Version="151.0.7906" />
|
||||
<PackageReference Include="bblanchon.PDFium.Win32" Version="152.0.7934" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
||||
<PackageReference Include="itext" Version="9.6.0" />
|
||||
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.6.0" />
|
||||
<PackageReference Include="itext" Version="9.7.0" />
|
||||
<PackageReference Include="itext.bouncy-castle-adapter" Version="9.7.0" />
|
||||
<PackageReference Include="LinqKit" Version="1.3.11" />
|
||||
<PackageReference Include="MailKit" Version="4.17.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.4022.49" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.4078.44" />
|
||||
<PackageReference Include="NJsonSchema" Version="11.6.1" />
|
||||
<PackageReference Include="ScottPlot.WPF" Version="5.1.59" />
|
||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.3" />
|
||||
|
||||
@@ -315,6 +315,10 @@ namespace Elwig.Helpers {
|
||||
return (await DeliverySchedules.Where(s => s.Year == year).Select(v => (int?)v.DsNr).MaxAsync() ?? 0) + 1;
|
||||
}
|
||||
|
||||
public async Task<int> NextHistNr() {
|
||||
return (await MemberHistory.Select(c => (int?)c.HistNr).MaxAsync() ?? 0) + 1;
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Branch> FetchBranches(string? zwstid = null, bool includeWithoutMembers = true) {
|
||||
return _compiledQueryBranches.Invoke(this, zwstid, includeWithoutMembers);
|
||||
}
|
||||
|
||||
@@ -54,14 +54,14 @@ namespace Elwig.Helpers.Billing {
|
||||
if (addMinShares < 1) addMinShares = 1;
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
await cnx.ExecuteBatch($"""
|
||||
DELETE FROM member_history WHERE source = 'elwig' AND reason = 'auto' AND SUBSTR(date, 1, 4) = '{Year}';
|
||||
INSERT INTO member_history (histnr, from_mgnr, from_type, to_mgnr, to_type, date, reason, source, shares, value_per_share, currency)
|
||||
DELETE FROM member_history WHERE source = 'elwig' AND reason = '{MemberHistory.REASON_PRESCRIPTION}' AND deduct_year = {Year};
|
||||
INSERT INTO member_history (histnr, from_mgnr, from_type, to_mgnr, to_type, date_notice, date_effective, reason, source, deduct_year, shares, value_per_share, currency, comment)
|
||||
SELECT COALESCE((SELECT MAX(histnr) AS histnr FROM member_history), 0) + ROW_NUMBER() OVER(ORDER BY m.mgnr),
|
||||
NULL, NULL, u.mgnr, 1, '{date:yyyy-MM-dd}', 'auto', 'elwig',
|
||||
NULL, NULL, u.mgnr, 1, '{date:yyyy-MM-dd}', '{date:yyyy-MM-dd}', '{MemberHistory.REASON_PRESCRIPTION}', 'elwig', s.year,
|
||||
CEIL((u.diff - {allowanceKg}.0 - {allowanceKgPerShare}.0 * u.shares) / s.max_kg_per_share
|
||||
- {allowanceShares.ToString(CultureInfo.InvariantCulture)}
|
||||
- {allowanceRel.ToString(CultureInfo.InvariantCulture)} * u.shares) AS adjust_shares,
|
||||
s.share_value / POW(10, s.precision - 2), s.currency
|
||||
s.share_value / POW(10, s.precision - 2), s.currency, 'durch automatische Nachzeichnung'
|
||||
FROM v_total_under_delivery u
|
||||
JOIN season s ON s.year = u.year
|
||||
JOIN member m ON m.mgnr = u.mgnr
|
||||
@@ -72,7 +72,7 @@ namespace Elwig.Helpers.Billing {
|
||||
public async Task UnAdjustBusinessShares() {
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
await cnx.ExecuteBatch($"""
|
||||
DELETE FROM member_history WHERE source = 'elwig' AND reason = 'auto' AND SUBSTR(date, 1, 4) = '{Year}';
|
||||
DELETE FROM member_history WHERE source = 'elwig' AND reason = '{MemberHistory.REASON_PRESCRIPTION}' AND deduct_year = {Year};
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Elwig.Models;
|
||||
using Elwig.Models.Entities;
|
||||
using Elwig.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -9,6 +10,7 @@ using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Elwig.Helpers.Export {
|
||||
public static class ElwigData {
|
||||
@@ -239,6 +241,8 @@ namespace Elwig.Helpers.Export {
|
||||
var device = meta.Device;
|
||||
|
||||
using var ctx = new AppDbContext();
|
||||
var tx = await ctx.Database.BeginTransactionAsync();
|
||||
await ctx.Database.ExecuteSqlAsync($"UPDATE client_parameter SET value = '0' WHERE param = 'ENABLE_MEMBER_HISTORY_TRIGGERS'");
|
||||
|
||||
var kgnrs = wbKgs.Select(k => k.KgNr).ToList();
|
||||
var duplicateKgNrs = await ctx.WbKgs
|
||||
@@ -402,9 +406,9 @@ namespace Elwig.Helpers.Export {
|
||||
importedDeliveries.Add((meta.FileName, meta.ZwstId, meta.Device, n, o, deliveries.Count - n - o, meta.DeliveryFilters));
|
||||
}
|
||||
|
||||
await ctx.Database.ExecuteSqlAsync($"UPDATE client_parameter SET value = '0' WHERE param = 'ENABLE_MEMBER_HISTORY_TRIGGERS'");
|
||||
await ctx.SaveChangesAsync();
|
||||
await ctx.Database.ExecuteSqlAsync($"UPDATE client_parameter SET value = '1' WHERE param = 'ENABLE_MEMBER_HISTORY_TRIGGERS'");
|
||||
await tx.CommitAsync();
|
||||
|
||||
var primaryKeys = new Dictionary<string, string>() {
|
||||
["member"] = "mgnr, 0, 0",
|
||||
@@ -748,15 +752,18 @@ namespace Elwig.Helpers.Export {
|
||||
return new JsonObject {
|
||||
["histnr"] = h.HistNr,
|
||||
["from_mgnr"] = h.FromMgNr,
|
||||
["from_type"] = h.FromType,
|
||||
["from_type"] = h.FromType?.ToString().ToLower(),
|
||||
["to_mgnr"] = h.ToMgNr,
|
||||
["to_type"] = h.ToType,
|
||||
["date"] = h.DateString,
|
||||
["to_type"] = h.ToType?.ToString().ToLower(),
|
||||
["date_notice"] = h.DateNoticeString,
|
||||
["date_effective"] = h.DateEffectiveString,
|
||||
["reason"] = h.Reason,
|
||||
["source"] = h.Source,
|
||||
["shares"] = h.Shares,
|
||||
["signed"] = h.MemberHasSigned,
|
||||
["value_per_share"] = h.ValuePerShare,
|
||||
["currency"] = h.CurrencyCode,
|
||||
["deduct_year"] = h.DeductYear,
|
||||
["comment"] = h.Comment,
|
||||
};
|
||||
}
|
||||
@@ -765,15 +772,18 @@ namespace Elwig.Helpers.Export {
|
||||
return new MemberHistory {
|
||||
HistNr = json["histnr"]!.AsValue().GetValue<int>(),
|
||||
FromMgNr = json["from_mgnr"]?.AsValue().GetValue<int>(),
|
||||
FromType = json["from_type"]?.AsValue().GetValue<int>(),
|
||||
FromType = Enum.TryParse<BusinessShareType>(json["from_type"]?.AsValue().GetValue<string>(), true, out var from) ? from : null,
|
||||
ToMgNr = json["to_mgnr"]?.AsValue().GetValue<int>(),
|
||||
ToType = json["to_type"]?.AsValue().GetValue<int>(),
|
||||
DateString = json["date"]!.AsValue().GetValue<string>(),
|
||||
ToType = Enum.TryParse<BusinessShareType>(json["to_type"]?.AsValue().GetValue<string>(), true, out var to) ? to : null,
|
||||
DateNoticeString = json["date_notice"]!.AsValue().GetValue<string>(),
|
||||
DateEffectiveString = json["date_effective"]!.AsValue().GetValue<string>(),
|
||||
Reason = json["reason"]!.AsValue().GetValue<string>(),
|
||||
Source = json["source"]!.AsValue().GetValue<string>(),
|
||||
Shares = json["shares"]!.AsValue().GetValue<int>(),
|
||||
MemberHasSigned = json["signed"]?.AsValue().GetValue<bool>() ?? false,
|
||||
ValuePerShare = json["value_per_share"]?.AsValue().GetValue<decimal>(),
|
||||
CurrencyCode = json["currency"]?.AsValue().GetValue<string>(),
|
||||
DeductYear = json["deduct_year"]?.AsValue().GetValue<int>(),
|
||||
Comment = json["comment"]?.AsValue().GetValue<string>(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,11 +4,14 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.IO.Hashing;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
public static partial class Extensions {
|
||||
@@ -145,5 +148,28 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
return [.. list];
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Join<T>(this IEnumerable<T> src, Func<T> separatorFactory) {
|
||||
var srcArr = src.ToArray();
|
||||
for (int i = 0; i < srcArr.Length; i++) {
|
||||
yield return srcArr[i];
|
||||
if (i < srcArr.Length - 1) {
|
||||
yield return separatorFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddToolTipCell(this Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) {
|
||||
var tb = new TextBlock() {
|
||||
Text = text,
|
||||
TextAlignment = alignRight ? TextAlignment.Right : alignCenter ? TextAlignment.Center : TextAlignment.Left,
|
||||
Margin = new(0, 12 * row, 0, 0),
|
||||
FontWeight = bold ? FontWeights.Bold : FontWeights.Normal,
|
||||
};
|
||||
tb.SetValue(Grid.ColumnProperty, col);
|
||||
tb.SetValue(Grid.ColumnSpanProperty, colSpan);
|
||||
grid.Children.Add(tb);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,8 +136,7 @@ namespace Elwig.Helpers {
|
||||
return new(false, "PLZ zu kurz");
|
||||
}
|
||||
using var ctx = new AppDbContext();
|
||||
int plz = int.Parse(input.Text);
|
||||
if (ctx.Postleitzahlen.Find(plz) == null) {
|
||||
if (!int.TryParse(input.Text, out var plz) || ctx.Postleitzahlen.Find(plz) == null) {
|
||||
return new(false, "Ungültige PLZ");
|
||||
}
|
||||
return new(true, null);
|
||||
@@ -423,8 +422,7 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
using var ctx = new AppDbContext();
|
||||
int nr = int.Parse(input.Text);
|
||||
if (!ctx.MgNrExists(nr).GetAwaiter().GetResult()) {
|
||||
if (!int.TryParse(input.Text, out var nr) || !ctx.MgNrExists(nr).GetAwaiter().GetResult()) {
|
||||
return new(false, "Ungültige Mitgliedsnummer");
|
||||
}
|
||||
|
||||
@@ -440,8 +438,7 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
using var ctx = new AppDbContext();
|
||||
int nr = int.Parse(input.Text);
|
||||
if (nr != m?.MgNr && ctx.MgNrExists(nr).GetAwaiter().GetResult()) {
|
||||
if (!int.TryParse(input.Text, out var nr) || nr != m?.MgNr && ctx.MgNrExists(nr).GetAwaiter().GetResult()) {
|
||||
return new(false, "Mitgliedsnummer wird bereits verwendet");
|
||||
}
|
||||
|
||||
@@ -476,7 +473,7 @@ namespace Elwig.Helpers {
|
||||
return res;
|
||||
} else if (!required && input.Text.Length == 0) {
|
||||
return new(true, null);
|
||||
} else if (!ctx.MgNrExists(int.Parse(input.Text)).GetAwaiter().GetResult()) {
|
||||
} else if (!int.TryParse(input.Text, out var nr) ||!ctx.MgNrExists(nr).GetAwaiter().GetResult()) {
|
||||
return new(false, "Ein Mitglied mit dieser Mitgliedsnummer existiert nicht");
|
||||
}
|
||||
|
||||
@@ -537,7 +534,7 @@ namespace Elwig.Helpers {
|
||||
return (parts[0]?.Length == 4) ? new(true, null) : new(false, "Datum ist ungültig");
|
||||
} else if (p == 1) {
|
||||
// only month and year provided
|
||||
int m = parts[0] != null && parts[0] != "" ? int.Parse(parts[0] ?? "0") : 0;
|
||||
int m = parts[0] != null && parts[0] != "" && int.TryParse(parts[0], out var v) ? v : 0;
|
||||
if (parts[1]?.Length != 4 || parts[0]?.Length != 2 || m < 1 || m > 12)
|
||||
return new(false, "Datum ist ungültig");
|
||||
return new(true, null);
|
||||
@@ -589,8 +586,7 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
using var ctx = new AppDbContext();
|
||||
int nr = int.Parse(input.Text);
|
||||
if (nr != c?.FbNr && ctx.FbNrExists(nr).GetAwaiter().GetResult()) {
|
||||
if (!int.TryParse(input.Text, out var nr) || (nr != c?.FbNr && ctx.FbNrExists(nr).GetAwaiter().GetResult())) {
|
||||
return new(false, "Flächenbindungsnummer wird bereits verwendet");
|
||||
}
|
||||
|
||||
@@ -605,8 +601,7 @@ namespace Elwig.Helpers {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
var oe = double.Parse(input.Text);
|
||||
if (oe < 10 || oe >= 300) {
|
||||
if (!double.TryParse(input.Text, out var oe) || oe < 10 || oe >= 300) {
|
||||
return new(false, "Ungültiger Oechsle-Wert");
|
||||
}
|
||||
|
||||
@@ -621,8 +616,7 @@ namespace Elwig.Helpers {
|
||||
return new(true, null);
|
||||
}
|
||||
|
||||
var kmw = double.Parse(input.Text);
|
||||
if (kmw < 5 || kmw >= 50) {
|
||||
if (!double.TryParse(input.Text, out var kmw) || kmw < 5 || kmw >= 50) {
|
||||
return new(false, "Ungültiger KMW-Wert");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Elwig.Models {
|
||||
public enum BusinessShareType {
|
||||
Normal = 1, Red = 2, White = 3, Dormant = 9,
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ namespace Elwig.Models.Dtos {
|
||||
("Address", "Adresse", null, 60),
|
||||
("Plz", "PLZ", null, 10),
|
||||
("Locality", "Ort", null, 60),
|
||||
("AccountingNr", "BH-Konto", null, 20),
|
||||
("Iban", "IBAN", null, 45),
|
||||
("TgNr", "TG-Nr.", null, 20),
|
||||
("Sum", "Zwischens.", "€", 20),
|
||||
@@ -53,7 +54,7 @@ namespace Elwig.Models.Dtos {
|
||||
SELECT m.mgnr, m.name AS name_1,
|
||||
COALESCE(m.prefix || ' ', '') || m.given_name ||
|
||||
COALESCE(' ' || m.middle_names, '') || COALESCE(' ' || m.suffix, '') AS name_2,
|
||||
p.plz, o.name AS ort, m.address, m.iban, c.tgnr, s.year, s.precision,
|
||||
p.plz, o.name AS ort, m.address, m.accounting_nr, m.iban, c.tgnr, s.year, s.precision,
|
||||
p.amount - p.net_amount AS surcharge,
|
||||
c.net_amount, c.prev_net_amount, c.vat, c.vat_amount, c.gross_amount, c.modifiers, c.prev_modifiers, c.amount,
|
||||
ROUND(b.total_penalty / POW(10, s.precision - 2)) AS shares_penalty,
|
||||
@@ -83,6 +84,7 @@ namespace Elwig.Models.Dtos {
|
||||
public string Address;
|
||||
public int Plz;
|
||||
public string Locality;
|
||||
public string? AccountingNr;
|
||||
public string? Iban;
|
||||
public string TgNr;
|
||||
public decimal Sum;
|
||||
@@ -108,6 +110,7 @@ namespace Elwig.Models.Dtos {
|
||||
Address = row.Address;
|
||||
Plz = row.Plz;
|
||||
Locality = row.Locality;
|
||||
AccountingNr = row.AccountingNr;
|
||||
Iban = row.Iban != null ? Utils.FormatIban(row.Iban) : null;
|
||||
TgNr = $"{row.Year}/{row.TgNr}";
|
||||
Total = Utils.DecFromDb(row.NetAmount, prec1);
|
||||
@@ -153,6 +156,8 @@ namespace Elwig.Models.Dtos {
|
||||
public required string LocalityFull { get; set; }
|
||||
[NotMapped]
|
||||
public string Locality => LocalityFull.Split(",")[0];
|
||||
[Column("accounting_nr")]
|
||||
public string? AccountingNr { get; set; }
|
||||
[Column("iban")]
|
||||
public string? Iban { get; set; }
|
||||
[Column("year")]
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Elwig.Models.Dtos {
|
||||
("Locality", "Ort", null, 60),
|
||||
("DefaultKg", "Stammgemeinde", null, 60),
|
||||
("Branch", "Zweigstelle", null, 40),
|
||||
("SharesTotal", "GA", null, 10),
|
||||
("SharesActive", "GA", null, 10),
|
||||
("BillingName", "Rechnungsname", null, 60),
|
||||
("BillingAddress", "Rechnungsadresse", null, 60),
|
||||
("BillingPlz", "PLZ", null, 10),
|
||||
@@ -69,8 +69,7 @@ namespace Elwig.Models.Dtos {
|
||||
public int Shares;
|
||||
public int SharesRed;
|
||||
public int SharesWhite;
|
||||
public int SharesDormant;
|
||||
public int SharesTotal;
|
||||
public int SharesActive;
|
||||
public string Address;
|
||||
public int Plz;
|
||||
public string Locality;
|
||||
@@ -105,8 +104,7 @@ namespace Elwig.Models.Dtos {
|
||||
Shares = m.Shares;
|
||||
SharesRed = m.SharesRed;
|
||||
SharesWhite = m.SharesWhite;
|
||||
SharesDormant = m.SharesDormant;
|
||||
SharesTotal = Shares + SharesRed + SharesWhite + SharesDormant;
|
||||
SharesActive = Shares + SharesRed + SharesWhite;
|
||||
Address = m.Address;
|
||||
Plz = m.PostalDest.AtPlz!.Plz;
|
||||
Locality = m.PostalDest.AtPlz!.Ort.Name;
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Elwig.Models.Entities {
|
||||
[NotMapped]
|
||||
public string ShortName => (!string.IsNullOrWhiteSpace(GivenName) ? $"{GivenName} " : "") + Name;
|
||||
[NotMapped]
|
||||
public string FullAdministrativeName => $"{AdministrativeName} ({MgNr})";
|
||||
[NotMapped]
|
||||
public string AdministrativeName => AdministrativeName1 + (!string.IsNullOrWhiteSpace(AdministrativeName2) ? $" {AdministrativeName2}" : "");
|
||||
[NotMapped]
|
||||
public string AdministrativeName1 => IsJuridicalPerson ? Name : Name.Replace('ß', 'ẞ').ToUpper();
|
||||
@@ -79,8 +81,6 @@ namespace Elwig.Models.Entities {
|
||||
[Column("shares_dormant")]
|
||||
public int SharesDormant { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public int SharesTotal => Shares + SharesRed + SharesWhite + SharesDormant;
|
||||
[NotMapped]
|
||||
public int SharesActive => Shares + SharesRed + SharesWhite;
|
||||
|
||||
|
||||
@@ -6,29 +6,69 @@ using System.ComponentModel.DataAnnotations.Schema;
|
||||
namespace Elwig.Models.Entities {
|
||||
[Table("member_history"), PrimaryKey("HistNr")]
|
||||
public class MemberHistory {
|
||||
|
||||
public const string REASON_PURCHASE = "purchase"; // Kauf
|
||||
public const string REASON_CONVERT = "convert"; // Änderung
|
||||
public const string REASON_TRANSFER = "transfer"; // Übertragung
|
||||
public const string REASON_PRESCRIPTION = "prescription"; // Vorschreibung
|
||||
public const string REASON_EXCLUSION = "exclusion"; // Ausschluss
|
||||
public const string REASON_DECEASED = "deceased"; // Tod
|
||||
public const string REASON_RETIREMENT = "retirement"; // Kündigung/stilllegen
|
||||
public const string REASON_PAYOUT = "payout"; // Auszahlung
|
||||
|
||||
[Column("histnr")]
|
||||
public int HistNr { get; set; }
|
||||
|
||||
[Column("from_mgnr")]
|
||||
public int? FromMgNr { get; set; }
|
||||
[Column("from_type")]
|
||||
public int? FromType { get; set; }
|
||||
public int? FromTypeValue { get; set; }
|
||||
[NotMapped]
|
||||
public BusinessShareType? FromType {
|
||||
get => (BusinessShareType?)FromTypeValue;
|
||||
set => FromTypeValue = (int?)value;
|
||||
}
|
||||
|
||||
[Column("to_mgnr")]
|
||||
public int? ToMgNr { get; set; }
|
||||
[Column("to_type")]
|
||||
public int? ToType { get; set; }
|
||||
|
||||
[Column("date")]
|
||||
public required string DateString { get; set; }
|
||||
public int? ToTypeValue { get; set; }
|
||||
[NotMapped]
|
||||
public DateOnly Date {
|
||||
get => DateOnly.ParseExact(DateString, "yyyy-MM-dd");
|
||||
public BusinessShareType? ToType {
|
||||
get => (BusinessShareType?)ToTypeValue;
|
||||
set => ToTypeValue = (int?)value;
|
||||
}
|
||||
|
||||
[Column("date_notice")]
|
||||
public required string DateNoticeString { get; set; }
|
||||
[NotMapped]
|
||||
public DateOnly DateNotice {
|
||||
get => DateOnly.ParseExact(DateNoticeString, "yyyy-MM-dd");
|
||||
set => value.ToString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
[Column("date_effective")]
|
||||
public required string DateEffectiveString { get; set; }
|
||||
[NotMapped]
|
||||
public DateOnly DateEffective {
|
||||
get => DateOnly.ParseExact(DateEffectiveString, "yyyy-MM-dd");
|
||||
set => value.ToString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
[Column("reason")]
|
||||
public required string Reason { get; set; }
|
||||
[NotMapped]
|
||||
public string ReasonPretty => Reason switch {
|
||||
REASON_PURCHASE => "Kauf",
|
||||
REASON_CONVERT => "Änderung",
|
||||
REASON_TRANSFER => "Übertragung",
|
||||
REASON_PRESCRIPTION => "Vorschreibung",
|
||||
REASON_EXCLUSION => "Ausschluss",
|
||||
REASON_DECEASED => "Tod",
|
||||
REASON_RETIREMENT => "Kündigung",
|
||||
REASON_PAYOUT => "Auszahlung",
|
||||
_ => Reason,
|
||||
};
|
||||
|
||||
[Column("source")]
|
||||
public required string Source { get; set; }
|
||||
@@ -36,6 +76,9 @@ namespace Elwig.Models.Entities {
|
||||
[Column("shares")]
|
||||
public int Shares { get; set; }
|
||||
|
||||
[Column("signed")]
|
||||
public bool MemberHasSigned { get; set; }
|
||||
|
||||
[Column("value_per_share")]
|
||||
public long? ValuePerShareValue { get; set; }
|
||||
[NotMapped]
|
||||
@@ -50,14 +93,33 @@ namespace Elwig.Models.Entities {
|
||||
[Column("currency")]
|
||||
public string? CurrencyCode { get; set; }
|
||||
|
||||
[Column("deduct_year")]
|
||||
public int? DeductYear { get; set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
public string FormatReasonPhrase(int mgnr) {
|
||||
if (Reason == REASON_TRANSFER) {
|
||||
if (FromMgNr == mgnr) {
|
||||
return $"{ReasonPretty} an {ToMember?.FullAdministrativeName ?? "Nachfolger"}" + (Comment != null ? $", {Comment}" : "");
|
||||
} else if (ToMgNr == mgnr) {
|
||||
return $"{ReasonPretty} von {FromMember?.FullAdministrativeName ?? "Vorgänger"}" + (Comment != null ? $", {Comment}" : "");
|
||||
}
|
||||
}
|
||||
return ReasonPretty + (Comment != null ? $", {Comment}" : "");
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public int? PoVMgNr { get; set; }
|
||||
[NotMapped]
|
||||
public string PoVReasonPhrase => FormatReasonPhrase(PoVMgNr ?? 0);
|
||||
|
||||
[ForeignKey("FromMgNr")]
|
||||
public virtual Member FromMember { get; private set; } = null!;
|
||||
public virtual Member? FromMember { get; private set; } = null!;
|
||||
|
||||
[ForeignKey("ToMgNr")]
|
||||
public virtual Member ToMember { get; private set; } = null!;
|
||||
public virtual Member? ToMember { get; private set; } = null!;
|
||||
|
||||
[ForeignKey("CurrencyCode")]
|
||||
public virtual Currency Currency { get; private set; } = null!;
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
PRAGMA writable_schema = ON;
|
||||
|
||||
ALTER TABLE member RENAME COLUMN business_shares TO shares;
|
||||
ALTER TABLE member ADD COLUMN shares_red INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE member ADD COLUMN shares_white INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE member ADD COLUMN shares_dormant INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE member ADD COLUMN shares_red INTEGER NOT NULL DEFAULT 0 CHECK (shares_red >= 0);
|
||||
ALTER TABLE member ADD COLUMN shares_white INTEGER NOT NULL DEFAULT 0 CHECK (shares_white >= 0);
|
||||
ALTER TABLE member ADD COLUMN shares_dormant INTEGER NOT NULL DEFAULT 0 CHECK (shares_dormant >= 0);
|
||||
|
||||
UPDATE sqlite_schema SET sql = REPLACE(sql, 'shares INTEGER NOT NULL DEFAULT 0', 'shares INTEGER NOT NULL DEFAULT 0 CHECK (shares >= 0)')
|
||||
WHERE type = 'table' AND name = 'member';
|
||||
|
||||
UPDATE client_parameter SET value = '0' WHERE param = 'ENABLE_TIME_TRIGGERS';
|
||||
UPDATE member
|
||||
@@ -20,13 +23,16 @@ CREATE TABLE member_history_new (
|
||||
from_type INTEGER,
|
||||
to_mgnr INTEGER,
|
||||
to_type INTEGER,
|
||||
date TEXT NOT NULL CHECK (date REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$') DEFAULT CURRENT_DATE,
|
||||
reason TEXT NOT NULL CHECK (reason REGEXP '^[a-z_]+$'),
|
||||
source TEXT NOT NULL CHECK (source REGEXP '^[a-z_]+$'),
|
||||
date_notice TEXT NOT NULL CHECK (date_notice REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$') DEFAULT CURRENT_DATE,
|
||||
date_effective TEXT NOT NULL CHECK (date_effective REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$') DEFAULT CURRENT_DATE,
|
||||
reason TEXT NOT NULL CHECK (reason REGEXP '^[a-z_]+$'),
|
||||
source TEXT NOT NULL CHECK (source REGEXP '^[a-z_]+$'),
|
||||
|
||||
shares INTEGER NOT NULL,
|
||||
shares INTEGER NOT NULL CHECK (shares > 0),
|
||||
signed INTEGER NOT NULL CHECK (signed IN (TRUE, FALSE)) DEFAULT FALSE,
|
||||
value_per_share INTEGER DEFAULT NULL,
|
||||
currency TEXT DEFAULT NULL,
|
||||
deduct_year INTEGER DEFAULT NULL,
|
||||
comment TEXT DEFAULT NULL,
|
||||
|
||||
CONSTRAINT pk_member_history PRIMARY KEY (histnr),
|
||||
@@ -44,8 +50,10 @@ CREATE TABLE member_history_new (
|
||||
((to_mgnr IS NULL AND to_type IS NULL) OR (to_mgnr IS NOT NULL AND to_type IS NOT NULL)))
|
||||
) STRICT;
|
||||
|
||||
INSERT INTO member_history_new (histnr, from_mgnr, from_type, to_mgnr, to_type, date, reason, source, shares, value_per_share, currency, comment)
|
||||
SELECT ROW_NUMBER() OVER(ORDER BY h.date, h.mgnr), NULL, NULL, h.mgnr, 1, h.date, h.type, 'elwig', h.business_shares, s.bs_value / POW(10, s.precision - 2), s.currency, comment
|
||||
INSERT INTO member_history_new (histnr, from_mgnr, from_type, to_mgnr, to_type, date_notice, date_effective, reason, source, shares, value_per_share, currency, deduct_year, comment)
|
||||
SELECT ROW_NUMBER() OVER(ORDER BY h.date, h.mgnr), NULL, NULL, h.mgnr, 1, h.date, h.date,
|
||||
IIF(h.type = 'auto', 'prescription', h.type), 'elwig', h.business_shares, s.bs_value / POW(10, s.precision - 2), s.currency,
|
||||
IIF(h.type = 'auto', s.year, NULL), 'automatische Nachzeichnung'
|
||||
FROM member_history h
|
||||
JOIN season s ON s.year = SUBSTR(h.date, 1, 4);
|
||||
|
||||
@@ -69,7 +77,7 @@ BEGIN
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t_member_history_u_member
|
||||
AFTER UPDATE ON member_history FOR EACH ROW
|
||||
AFTER UPDATE OF from_mgnr, from_type, to_mgnr, to_type, shares ON member_history FOR EACH ROW
|
||||
WHEN (SELECT value FROM client_parameter WHERE param = 'ENABLE_MEMBER_HISTORY_TRIGGERS') = 1
|
||||
BEGIN
|
||||
UPDATE member SET shares = shares + OLD.shares WHERE mgnr = OLD.from_mgnr AND OLD.from_type = 1;
|
||||
@@ -246,8 +254,8 @@ SELECT m.mgnr, s.year,
|
||||
m.shares_white + SUM(IIF(h1.from_type = 3, h1.shares, 0)) - SUM(IIF(h2.to_type = 3, h2.shares, 0)) AS shares_white,
|
||||
m.shares_dormant + SUM(IIF(h1.from_type = 9, h1.shares, 0)) - SUM(IIF(h2.to_type = 9, h2.shares, 0)) AS shares_dormant
|
||||
FROM member m, v_virtual_season s
|
||||
LEFT JOIN member_history h1 ON (SUBSTR(h1.date, 1, 4) + 0) > s.year AND h1.from_mgnr = m.mgnr
|
||||
LEFT JOIN member_history h2 ON (SUBSTR(h2.date, 1, 4) + 0) > s.year AND h2.to_mgnr = m.mgnr
|
||||
LEFT JOIN member_history h1 ON (SUBSTR(h1.date_notice, 1, 4) + 0) > s.year AND h1.from_mgnr = m.mgnr
|
||||
LEFT JOIN member_history h2 ON (SUBSTR(h2.date_notice, 1, 4) + 0) > s.year AND h2.to_mgnr = m.mgnr
|
||||
GROUP BY m.mgnr, s.year
|
||||
ORDER BY m.mgnr, s.year;
|
||||
|
||||
@@ -306,12 +314,12 @@ ORDER BY u.year, u.mgnr;
|
||||
|
||||
DROP VIEW v_auto_business_shares;
|
||||
CREATE VIEW v_auto_business_shares AS
|
||||
SELECT (SUBSTR(h.date, 1, 4) + 0) AS year,
|
||||
SELECT (SUBSTR(h.date_notice, 1, 4) + 0) AS year,
|
||||
h.to_mgnr AS mgnr,
|
||||
SUM(h.shares) AS shares,
|
||||
SUM(h.shares * COALESCE(h.value_per_share, 0)) AS total_amount
|
||||
FROM member_history h
|
||||
WHERE h.reason = 'auto' AND h.source = 'elwig'
|
||||
WHERE h.reason = 'prescription' AND h.source = 'elwig'
|
||||
GROUP BY year, h.to_mgnr
|
||||
ORDER BY year, h.to_mgnr;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows;
|
||||
|
||||
namespace Elwig.Services {
|
||||
public static class AreaComService {
|
||||
@@ -115,7 +114,7 @@ namespace Elwig.Services {
|
||||
using var ctx = new AppDbContext();
|
||||
var c = new AreaComContract {
|
||||
FbNr = oldFbNr ?? newFbNr,
|
||||
Comment = string.IsNullOrEmpty(vm.Comment) ? null : vm.Comment,
|
||||
Comment = string.IsNullOrWhiteSpace(vm.Comment) ? null : vm.Comment,
|
||||
KgNr = vm.Kg!.KgNr,
|
||||
RdNr = vm.Rd?.RdNr,
|
||||
};
|
||||
@@ -158,25 +157,13 @@ namespace Elwig.Services {
|
||||
});
|
||||
}
|
||||
|
||||
private static void AddToolTipCell(Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) {
|
||||
var tb = new TextBlock() {
|
||||
Text = text,
|
||||
TextAlignment = alignRight ? TextAlignment.Right : alignCenter ? TextAlignment.Center : TextAlignment.Left,
|
||||
Margin = new(0, 12 * row, 0, 0),
|
||||
FontWeight = bold ? FontWeights.Bold : FontWeights.Normal,
|
||||
};
|
||||
tb.SetValue(Grid.ColumnProperty, col);
|
||||
tb.SetValue(Grid.ColumnSpanProperty, colSpan);
|
||||
grid.Children.Add(tb);
|
||||
}
|
||||
|
||||
private static void AddToolTipRow(Grid grid, int row, string? h1, string? h2, int area, int? min, int? max) {
|
||||
var bold = h2 == null;
|
||||
if (h1 != null) AddToolTipCell(grid, h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||||
if (h2 != null) AddToolTipCell(grid, h2 + ":", row, 1, 1, bold);
|
||||
AddToolTipCell(grid, $"{area:N0} m²", row, 2, 1, bold, true);
|
||||
AddToolTipCell(grid, min == null ? "" : $"{min:N0} kg", row, 3, 1, bold, true);
|
||||
AddToolTipCell(grid, max == null ? "" : $"{max:N0} kg", row, 4, 1, bold, true);
|
||||
if (h1 != null) grid.AddToolTipCell(h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||||
if (h2 != null) grid.AddToolTipCell(h2 + ":", row, 1, bold: bold);
|
||||
grid.AddToolTipCell($"{area:N0} m²", row, 2, bold: bold, alignRight: true);
|
||||
grid.AddToolTipCell(min == null ? "" : $"{min:N0} kg", row, 3, bold: bold, alignRight: true);
|
||||
grid.AddToolTipCell(max == null ? "" : $"{max:N0} kg", row, 4, bold: bold, alignRight: true);
|
||||
}
|
||||
|
||||
public static async Task<(string, (string?, string?, int, int?, int?)[])> GenerateToolTipData(IQueryable<AreaCom> areaComs, int maxKgPerHa) {
|
||||
@@ -255,8 +242,8 @@ namespace Elwig.Services {
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(80) });
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(80) });
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(80) });
|
||||
AddToolTipCell(grid, "Lieferpflicht", 0, 3, 1, false, false, true);
|
||||
AddToolTipCell(grid, "Lieferrecht", 0, 4, 1, false, false, true);
|
||||
grid.AddToolTipCell("Lieferpflicht", 0, 3, alignCenter: true);
|
||||
grid.AddToolTipCell("Lieferrecht", 0, 4, 1, alignCenter: true);
|
||||
int rowNum = 1;
|
||||
foreach (var row in data) {
|
||||
if (rowNum == 2 || (rowNum != 1 && row.Item1 != null)) rowNum++;
|
||||
|
||||
@@ -8,7 +8,6 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Elwig.Documents;
|
||||
using Elwig.Helpers.Export;
|
||||
using Elwig.Models.Dtos;
|
||||
using System.Windows;
|
||||
using System;
|
||||
using LinqKit;
|
||||
using System.Windows.Controls;
|
||||
@@ -276,27 +275,15 @@ namespace Elwig.Services {
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddToolTipCell(Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) {
|
||||
var tb = new TextBlock() {
|
||||
Text = text,
|
||||
TextAlignment = alignRight ? TextAlignment.Right : alignCenter ? TextAlignment.Center : TextAlignment.Left,
|
||||
Margin = new(0, 12 * row, 0, 0),
|
||||
FontWeight = bold ? FontWeights.Bold : FontWeights.Normal,
|
||||
};
|
||||
tb.SetValue(Grid.ColumnProperty, col);
|
||||
tb.SetValue(Grid.ColumnSpanProperty, colSpan);
|
||||
grid.Children.Add(tb);
|
||||
}
|
||||
|
||||
private static void AddToolTipRow(Grid grid, int row, string? h1, string? h2, int weight, int? total1, int total2) {
|
||||
var bold = h2 == null;
|
||||
if (h1 != null) AddToolTipCell(grid, h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||||
if (h2 != null) AddToolTipCell(grid, h2 + ":", row, 1, 1, bold);
|
||||
AddToolTipCell(grid, $"{weight:N0} kg", row, 2, 1, bold, true);
|
||||
if (h1 != null) grid.AddToolTipCell(h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||||
if (h2 != null) grid.AddToolTipCell(h2 + ":", row, 1, 1, bold);
|
||||
grid.AddToolTipCell($"{weight:N0} kg", row, 2, bold: bold, alignRight: true);
|
||||
if (total1 != null && total1 != 0)
|
||||
AddToolTipCell(grid, $"{weight * 100.0 / total1:N1} %", row, 3, 1, bold, true);
|
||||
grid.AddToolTipCell($"{weight * 100.0 / total1:N1} %", row, 3, bold: bold, alignRight: true);
|
||||
if (total2 != 0)
|
||||
AddToolTipCell(grid, $"{weight * 100.0 / total2:N1} %", row, 4, 1, bold, true);
|
||||
grid.AddToolTipCell($"{weight * 100.0 / total2:N1} %", row, 4, bold: bold, alignRight: true);
|
||||
}
|
||||
|
||||
public static async Task<(string Text, (string?, string?, int, int?, int)[] Grid)> GenerateToolTipData(IQueryable<DeliveryAncmt> deliveryAncmts) {
|
||||
|
||||
@@ -6,7 +6,6 @@ using Elwig.Models.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System;
|
||||
using Elwig.ViewModels;
|
||||
using LinqKit;
|
||||
@@ -23,15 +22,6 @@ namespace Elwig.Services {
|
||||
FromFilters, FromToday, FromSeason, FromSeasonAndBranch, Selected,
|
||||
};
|
||||
|
||||
public static async Task<Member?> GetMemberAsync(int mgnr) {
|
||||
using var ctx = new AppDbContext();
|
||||
return await ctx.FetchMembers(mgnr).SingleOrDefaultAsync();
|
||||
}
|
||||
|
||||
public static Member? GetMember(int mgnr) {
|
||||
return GetMemberAsync(mgnr).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public static void ClearInputs(this DeliveryAdminViewModel vm) {
|
||||
}
|
||||
|
||||
@@ -486,7 +476,7 @@ namespace Elwig.Services {
|
||||
if (partNew && timeIsDefault) {
|
||||
newTimeString = DateTime.Now.ToString("HH:mm:ss");
|
||||
} else if (partNew || timeHasChanged) {
|
||||
newTimeString = string.IsNullOrEmpty(vm.Time) ? null : vm.Time + ":00";
|
||||
newTimeString = string.IsNullOrWhiteSpace(vm.Time) ? null : vm.Time + ":00";
|
||||
}
|
||||
|
||||
var d = new Delivery {
|
||||
@@ -498,7 +488,7 @@ namespace Elwig.Services {
|
||||
ZwstId = vm.Branch!.ZwstId,
|
||||
LsNr = newLsNr ?? vm.LsNr!,
|
||||
MgNr = vm.MgNr!.Value,
|
||||
Comment = string.IsNullOrEmpty(vm.Comment) ? null : vm.Comment,
|
||||
Comment = string.IsNullOrWhiteSpace(vm.Comment) ? null : vm.Comment,
|
||||
};
|
||||
|
||||
p = new DeliveryPart {
|
||||
@@ -521,7 +511,7 @@ namespace Elwig.Services {
|
||||
Unloading = vm.Unloading,
|
||||
Temperature = vm.Temperature,
|
||||
Acid = vm.Acid,
|
||||
Comment = string.IsNullOrEmpty(vm.PartComment) ? null : vm.PartComment,
|
||||
Comment = string.IsNullOrWhiteSpace(vm.PartComment) ? null : vm.PartComment,
|
||||
|
||||
Weight = vm.Weight!.Value,
|
||||
IsManualWeighing = vm.IsManualWeighing,
|
||||
@@ -940,36 +930,24 @@ namespace Elwig.Services {
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddToolTipCell(Grid grid, string text, int row, int col, int colSpan = 1, bool bold = false, bool alignRight = false, bool alignCenter = false) {
|
||||
var tb = new TextBlock() {
|
||||
Text = text,
|
||||
TextAlignment = alignRight ? TextAlignment.Right : alignCenter ? TextAlignment.Center : TextAlignment.Left,
|
||||
Margin = new(0, 12 * row, 0, 0),
|
||||
FontWeight = bold ? FontWeights.Bold : FontWeights.Normal,
|
||||
};
|
||||
tb.SetValue(Grid.ColumnProperty, col);
|
||||
tb.SetValue(Grid.ColumnSpanProperty, colSpan);
|
||||
grid.Children.Add(tb);
|
||||
}
|
||||
|
||||
private static void AddWeightToolTipRow(Grid grid, int row, string? h1, string? h2, int weight, int? total1, int total2) {
|
||||
var bold = h2 == null;
|
||||
if (h1 != null) AddToolTipCell(grid, h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||||
if (h2 != null) AddToolTipCell(grid, h2 + ":", row, 1, 1, bold);
|
||||
AddToolTipCell(grid, $"{weight:N0} kg", row, 2, 1, bold, true);
|
||||
if (h1 != null) grid.AddToolTipCell(h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||||
if (h2 != null) grid.AddToolTipCell(h2 + ":", row, 1, 1, bold);
|
||||
grid.AddToolTipCell($"{weight:N0} kg", row, 2, bold: bold, alignRight: true);
|
||||
if (total1 != null && total1 != 0)
|
||||
AddToolTipCell(grid, $"{weight * 100.0 / total1:N1} %", row, 3, 1, bold, true);
|
||||
grid.AddToolTipCell($"{weight * 100.0 / total1:N1} %", row, 3, bold: bold, alignRight: true);
|
||||
if (total2 != 0)
|
||||
AddToolTipCell(grid, $"{weight * 100.0 / total2:N1} %", row, 4, 1, bold, true);
|
||||
grid.AddToolTipCell($"{weight * 100.0 / total2:N1} %", row, 4, bold: bold, alignRight: true);
|
||||
}
|
||||
|
||||
private static void AddGradationToolTipRow(Grid grid, int row, string? h1, string? h2, double min, double avg, double max) {
|
||||
var bold = h2 == null;
|
||||
if (h1 != null) AddToolTipCell(grid, h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||||
if (h2 != null) AddToolTipCell(grid, h2 + ":", row, 1, 1, bold);
|
||||
AddToolTipCell(grid, $"{min:N1}°", row, 2, 1, bold, true);
|
||||
AddToolTipCell(grid, $"{avg:N1}°", row, 3, 1, bold, true);
|
||||
AddToolTipCell(grid, $"{max:N1}°", row, 4, 1, bold, true);
|
||||
if (h1 != null) grid.AddToolTipCell(h1 + ":", row, 0, (h2 == null) ? 2 : 1, bold);
|
||||
if (h2 != null) grid.AddToolTipCell(h2 + ":", row, 1, bold: bold);
|
||||
grid.AddToolTipCell($"{min:N1}°", row, 2, bold: bold, alignRight: true);
|
||||
grid.AddToolTipCell($"{avg:N1}°", row, 3, bold: bold, alignRight: true);
|
||||
grid.AddToolTipCell($"{max:N1}°", row, 4, bold: bold, alignRight: true);
|
||||
}
|
||||
|
||||
public static async Task<(string WeightText, (string?, string?, int, int?, int)[] WeightGrid, string GradationText, (string?, string?, double, double, double)[] GradationGrid)> GenerateToolTipData(IQueryable<DeliveryPart> deliveryParts) {
|
||||
@@ -1098,9 +1076,9 @@ namespace Elwig.Services {
|
||||
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
||||
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
||||
gGrid.ColumnDefinitions.Add(new() { Width = new(35) });
|
||||
AddToolTipCell(gGrid, "Min.", 0, 2, 1, false, false, true);
|
||||
AddToolTipCell(gGrid, "⌀", 0, 3, 1, false, false, true);
|
||||
AddToolTipCell(gGrid, "Max.", 0, 4, 1, false, false, true);
|
||||
gGrid.AddToolTipCell("Min.", 0, 2, alignCenter: true);
|
||||
gGrid.AddToolTipCell("⌀", 0, 3, alignCenter: true);
|
||||
gGrid.AddToolTipCell("Max.", 0, 4, alignCenter: true);
|
||||
rowNum = 1;
|
||||
foreach (var row in gradationData) {
|
||||
if (rowNum != 1 && row.Item2 == null) rowNum++;
|
||||
|
||||
@@ -48,6 +48,19 @@ namespace Elwig.Services {
|
||||
}
|
||||
}
|
||||
|
||||
public static bool? AskContinueYesNo(string title, string text) {
|
||||
if (NextContinue != null) {
|
||||
var r = NextContinue(title, text);
|
||||
NextContinue = null;
|
||||
return r;
|
||||
} else if (Override != null) {
|
||||
return Override("continue", title, text) != null;
|
||||
} else {
|
||||
var r = MessageBox.Show(text, title, MessageBoxButton.YesNoCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
|
||||
return r == MessageBoxResult.Yes ? true : r == MessageBoxResult.No ? false : null;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool AskConfirmation(string title, string text) {
|
||||
if (NextConfirmation != null) {
|
||||
var r = NextConfirmation(title, text);
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using Elwig.Models.Entities;
|
||||
using Elwig.ViewModels;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Services {
|
||||
public static class MemberBusinessSharesService {
|
||||
|
||||
public static async Task InitInputs(this MemberBusinessSharesViewModel vm) {
|
||||
using var ctx = new AppDbContext();
|
||||
vm.DateNoticeString = $"{Utils.Today:dd.MM.yyyy}";
|
||||
vm.ValuePerShare = (await ctx.Seasons.OrderBy(s => s.Year).LastOrDefaultAsync())?.BusinessShareValue;
|
||||
}
|
||||
|
||||
public static void ClearInputs(this MemberBusinessSharesViewModel vm) {
|
||||
|
||||
}
|
||||
|
||||
public static void FillInputs(this MemberBusinessSharesViewModel vm, MemberHistory h) {
|
||||
var mgnr = vm.FilterMember.MgNr;
|
||||
vm.DateNotice = h.DateNotice;
|
||||
vm.DateEffective = h.DateEffective;
|
||||
vm.Reason = h.Reason + (h.Reason == MemberHistory.REASON_TRANSFER ? $"_{(h.ToMgNr == mgnr ? "from" : "to")}" : "");
|
||||
vm.Shares = h.Shares;
|
||||
vm.MemberHasSigned = h.MemberHasSigned;
|
||||
vm.ValuePerShare = h.ValuePerShare;
|
||||
vm.OtherMgNr = h.FromMgNr != null && h.FromMgNr != mgnr ? h.FromMgNr : h.ToMgNr != null && h.ToMgNr != mgnr ? h.ToMgNr : null;
|
||||
vm.DeductYear = h.DeductYear ?? h.DateNotice.Year;
|
||||
vm.Deduct = h.DeductYear != null;
|
||||
vm.Comment = h.Comment;
|
||||
}
|
||||
|
||||
public static async Task<int> UpdateMemberHistory(this MemberBusinessSharesViewModel vm, int? oldHistNr, bool enableTriggers) {
|
||||
return await Task.Run(async () => {
|
||||
using var ctx = new AppDbContext();
|
||||
var tx = await ctx.Database.BeginTransactionAsync();
|
||||
await ctx.Database.ExecuteSqlAsync($"UPDATE client_parameter SET value = {(enableTriggers ? "1" : "0")} WHERE param = 'ENABLE_MEMBER_HISTORY_TRIGGERS'");
|
||||
|
||||
var h = new MemberHistory {
|
||||
HistNr = oldHistNr ?? await ctx.NextHistNr(),
|
||||
FromMgNr =
|
||||
vm.Reason == $"{MemberHistory.REASON_TRANSFER}_from" ? vm.OtherMgNr :
|
||||
vm.Reason == MemberHistory.REASON_PURCHASE || vm.Reason == MemberHistory.REASON_PRESCRIPTION ? null :
|
||||
vm.FilterMember.MgNr,
|
||||
FromType =
|
||||
vm.Reason == MemberHistory.REASON_PAYOUT ? BusinessShareType.Dormant :
|
||||
vm.Reason == MemberHistory.REASON_PURCHASE || vm.Reason == MemberHistory.REASON_PRESCRIPTION ? null :
|
||||
BusinessShareType.Normal,
|
||||
ToMgNr =
|
||||
vm.Reason == MemberHistory.REASON_PAYOUT || vm.Reason == MemberHistory.REASON_EXCLUSION ? null :
|
||||
vm.Reason == $"{MemberHistory.REASON_TRANSFER}_to" ? vm.OtherMgNr :
|
||||
vm.FilterMember.MgNr,
|
||||
ToType =
|
||||
vm.Reason == MemberHistory.REASON_PAYOUT || vm.Reason == MemberHistory.REASON_EXCLUSION ? null :
|
||||
vm.Reason == MemberHistory.REASON_RETIREMENT || vm.Reason == MemberHistory.REASON_DECEASED ? BusinessShareType.Dormant :
|
||||
BusinessShareType.Normal,
|
||||
DateNoticeString = $"{vm.DateNotice:yyyy-MM-dd}",
|
||||
DateEffectiveString = $"{vm.DateEffective:yyyy-MM-dd}",
|
||||
Reason = vm.Reason?.Split("_")[0] ?? MemberHistory.REASON_CONVERT,
|
||||
Source = "manual",
|
||||
Shares = vm.Shares ?? 0,
|
||||
MemberHasSigned = vm.MemberHasSigned,
|
||||
ValuePerShare = vm.ValuePerShare,
|
||||
CurrencyCode = vm.ValuePerShare != null ? "EUR" : null,
|
||||
DeductYear = vm.Deduct ? vm.DeductYear : null,
|
||||
Comment = string.IsNullOrWhiteSpace(vm.Comment) ? null : vm.Comment.Trim(),
|
||||
};
|
||||
|
||||
if (oldHistNr != null) {
|
||||
ctx.Update(h);
|
||||
} else {
|
||||
ctx.Add(h);
|
||||
}
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
await ctx.Database.ExecuteSqlAsync($"UPDATE client_parameter SET value = '1' WHERE param = 'ENABLE_MEMBER_HISTORY_TRIGGERS'");
|
||||
await tx.CommitAsync();
|
||||
|
||||
return h.HistNr;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static async Task DeleteMemberHistory(int histnr, bool enableTriggers) {
|
||||
await Task.Run(async () => {
|
||||
using var ctx = new AppDbContext();
|
||||
var tx = await ctx.Database.BeginTransactionAsync();
|
||||
await ctx.Database.ExecuteSqlAsync($"UPDATE client_parameter SET value = {(enableTriggers ? "1" : "0")} WHERE param = 'ENABLE_MEMBER_HISTORY_TRIGGERS'");
|
||||
await ctx.MemberHistory.Where(h => h.HistNr == histnr).ExecuteDeleteAsync();
|
||||
await ctx.Database.ExecuteSqlAsync($"UPDATE client_parameter SET value = '1' WHERE param = 'ENABLE_MEMBER_HISTORY_TRIGGERS'");
|
||||
await tx.CommitAsync();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -501,7 +501,10 @@ namespace Elwig.Services {
|
||||
var history2 = await query.IgnoreAutoIncludes()
|
||||
.SelectMany(m => m.HistoryTo)
|
||||
.ToListAsync();
|
||||
var history = history1.Union(history2).DistinctBy(h => h.HistNr).OrderBy(h => h.HistNr).ToList();
|
||||
var history = history1.Union(history2)
|
||||
.DistinctBy(h => h.HistNr)
|
||||
.OrderBy(h => h.DateNotice).ThenBy(h => h.HistNr)
|
||||
.ToList();
|
||||
var areaComs = await query
|
||||
.SelectMany(m => m.AreaCommitments)
|
||||
.Select(c => c.Contract).Distinct()
|
||||
@@ -541,33 +544,33 @@ namespace Elwig.Services {
|
||||
Name = vm.Name!,
|
||||
Suffix = vm.IsJuridicalPerson || string.IsNullOrWhiteSpace(vm.Suffix) ? null : vm.Suffix,
|
||||
ForTheAttentionOf = !vm.IsJuridicalPerson || string.IsNullOrWhiteSpace(vm.ForTheAttentionOf) ? null : vm.ForTheAttentionOf,
|
||||
Birthday = string.IsNullOrEmpty(vm.Birthday) ? null : string.Join("-", vm.Birthday!.Split(".").Reverse()),
|
||||
Birthday = string.IsNullOrWhiteSpace(vm.Birthday) ? null : string.Join("-", vm.Birthday!.Split(".").Reverse()),
|
||||
IsDeceased = vm.IsDeceased,
|
||||
CountryNum = 40, // Austria AT AUT
|
||||
PostalDestId = vm.Ort!.Id,
|
||||
Address = vm.Address!,
|
||||
|
||||
Iban = string.IsNullOrEmpty(vm.Iban) ? null : vm.Iban?.Replace(" ", ""),
|
||||
Bic = string.IsNullOrEmpty(vm.Bic) ? null : vm.Bic,
|
||||
Iban = string.IsNullOrWhiteSpace(vm.Iban) ? null : vm.Iban?.Replace(" ", ""),
|
||||
Bic = string.IsNullOrWhiteSpace(vm.Bic) ? null : vm.Bic,
|
||||
|
||||
UstIdNr = string.IsNullOrEmpty(vm.UstIdNr) ? null : vm.UstIdNr,
|
||||
LfbisNr = string.IsNullOrEmpty(vm.LfbisNr) ? null : vm.LfbisNr,
|
||||
UstIdNr = string.IsNullOrWhiteSpace(vm.UstIdNr) ? null : vm.UstIdNr,
|
||||
LfbisNr = string.IsNullOrWhiteSpace(vm.LfbisNr) ? null : vm.LfbisNr,
|
||||
IsBuchführend = vm.IsBuchführend,
|
||||
IsOrganic = vm.IsOrganic,
|
||||
|
||||
EntryDateString = string.IsNullOrEmpty(vm.EntryDate) ? null : string.Join("-", vm.EntryDate.Split(".").Reverse()),
|
||||
ExitDateString = string.IsNullOrEmpty(vm.ExitDate) ? null : string.Join("-", vm.ExitDate.Split(".").Reverse()),
|
||||
EntryDateString = string.IsNullOrWhiteSpace(vm.EntryDate) ? null : string.Join("-", vm.EntryDate.Split(".").Reverse()),
|
||||
ExitDateString = string.IsNullOrWhiteSpace(vm.ExitDate) ? null : string.Join("-", vm.ExitDate.Split(".").Reverse()),
|
||||
Shares = App.Client.HasRedWhite ? 0 : vm.BusinessShares1 ?? 0,
|
||||
SharesRed = App.Client.HasRedWhite ? vm.BusinessShares1 ?? 0 : 0,
|
||||
SharesWhite = App.Client.HasRedWhite ? vm.BusinessShares2 ?? 0 : 0,
|
||||
SharesDormant = App.Client.HasRedWhite ? vm.BusinessShares3 ?? 0 : vm.BusinessShares2 ?? 0,
|
||||
AccountingNr = string.IsNullOrEmpty(vm.AccountingNr) ? null : vm.AccountingNr,
|
||||
AccountingNr = string.IsNullOrWhiteSpace(vm.AccountingNr) ? null : vm.AccountingNr,
|
||||
IsActive = vm.IsActive,
|
||||
IsVollLieferant = vm.IsVollLieferant,
|
||||
IsFunktionär = vm.IsFunktionär,
|
||||
ZwstId = vm.Branch?.ZwstId,
|
||||
DefaultKgNr = vm.DefaultKg?.KgNr,
|
||||
Comment = string.IsNullOrEmpty(vm.Comment) ? null : vm.Comment,
|
||||
Comment = string.IsNullOrWhiteSpace(vm.Comment) ? null : vm.Comment,
|
||||
ContactViaPost = vm.ContactViaPost,
|
||||
ContactViaEmail = vm.ContactViaEmail,
|
||||
};
|
||||
|
||||
@@ -300,7 +300,7 @@ namespace Elwig.Services {
|
||||
TransferDate = vm.TransferDate,
|
||||
TestVariant = vm.SelectedPaymentVariant?.TestVariant ?? true,
|
||||
CalcTimeUnix = vm.SelectedPaymentVariant?.CalcTimeUnix,
|
||||
Comment = string.IsNullOrEmpty(vm.Comment) ? null : vm.Comment,
|
||||
Comment = string.IsNullOrWhiteSpace(vm.Comment) ? null : vm.Comment,
|
||||
Data = JsonSerializer.Serialize(d.Data),
|
||||
};
|
||||
avnr = v.AvNr;
|
||||
|
||||
@@ -33,7 +33,10 @@ namespace Elwig.Services {
|
||||
var history2 = await query.IgnoreAutoIncludes()
|
||||
.SelectMany(m => m.HistoryTo)
|
||||
.ToListAsync();
|
||||
var history = history1.Union(history2).DistinctBy(h => h.HistNr).OrderBy(h => h.HistNr).ToList();
|
||||
var history = history1.Union(history2)
|
||||
.DistinctBy(h => h.HistNr)
|
||||
.OrderBy(h => h.DateNotice).ThenBy(h => h.HistNr)
|
||||
.ToList();
|
||||
var areaComs = await query
|
||||
.SelectMany(m => m.AreaCommitments)
|
||||
.Select(c => c.Contract).Distinct()
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace Elwig.ViewModels {
|
||||
public partial class MemberAdminViewModel : ObservableObject {
|
||||
@@ -200,9 +201,7 @@ namespace Elwig.ViewModels {
|
||||
[ObservableProperty]
|
||||
private string? _statusMembersToolTip;
|
||||
[ObservableProperty]
|
||||
private string _statusBusinessShares = "-";
|
||||
[ObservableProperty]
|
||||
private string? _statusBusinessSharesToolTip;
|
||||
private TextBlock? _statusBusinessShares;
|
||||
[ObservableProperty]
|
||||
private string _statusDeliveriesLastSeason = "-";
|
||||
[ObservableProperty]
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Elwig.Models.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
|
||||
namespace Elwig.ViewModels {
|
||||
public partial class MemberBusinessSharesViewModel : ObservableObject {
|
||||
|
||||
[ObservableProperty]
|
||||
private string _title = "Geschäftsanteilbewegungen - Elwig";
|
||||
|
||||
public required Member FilterMember { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
private MemberHistory? _selectedHistoryEntry;
|
||||
[ObservableProperty]
|
||||
private IEnumerable<MemberHistory> _history = [];
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _dateNoticeString;
|
||||
public DateOnly? DateNotice {
|
||||
get => DateOnly.TryParseExact(DateNoticeString, "dd.MM.yyyy", out var d) ? d : null;
|
||||
set => DateNoticeString = $"{value:dd.MM.yyyy}";
|
||||
}
|
||||
[ObservableProperty]
|
||||
private string? _dateEffectiveString;
|
||||
public DateOnly? DateEffective {
|
||||
get => DateOnly.TryParseExact(DateEffectiveString, "dd.MM.yyyy", out var d) ? d : null;
|
||||
set => DateEffectiveString = $"{value:dd.MM.yyyy}";
|
||||
}
|
||||
[ObservableProperty]
|
||||
private string? _reason;
|
||||
[ObservableProperty]
|
||||
private string? _sharesString;
|
||||
public int? Shares {
|
||||
get => int.TryParse(SharesString, out var shares) ? shares : null;
|
||||
set => SharesString = $"{value}";
|
||||
}
|
||||
[ObservableProperty]
|
||||
private string? _otherMgNrString;
|
||||
public int? OtherMgNr {
|
||||
get => int.TryParse(OtherMgNrString, out var mgnr) ? mgnr : null;
|
||||
set => OtherMgNrString = $"{value}";
|
||||
}
|
||||
[ObservableProperty]
|
||||
private string? _deductYearString;
|
||||
public int? DeductYear {
|
||||
get => int.TryParse(DeductYearString, out var year) ? year : null;
|
||||
set => DeductYearString = $"{value}";
|
||||
}
|
||||
[ObservableProperty]
|
||||
private bool _deduct;
|
||||
[ObservableProperty]
|
||||
private bool _memberHasSigned;
|
||||
[ObservableProperty]
|
||||
private string? _valuePerShareString;
|
||||
public decimal? ValuePerShare {
|
||||
get => decimal.TryParse(ValuePerShareString, out var v) ? v : null;
|
||||
set => ValuePerShareString = $"{value:0.00}";
|
||||
}
|
||||
[ObservableProperty]
|
||||
private string? _totalAmount;
|
||||
[ObservableProperty]
|
||||
private string? _comment;
|
||||
|
||||
[ObservableProperty]
|
||||
private Visibility _controlButtonsVisibility = Visibility.Visible;
|
||||
[ObservableProperty]
|
||||
private Visibility _editingButtonsVisibility = Visibility.Hidden;
|
||||
[ObservableProperty]
|
||||
private Visibility _personalNameVisibility = Visibility.Visible;
|
||||
[ObservableProperty]
|
||||
private Visibility _juridicalNameVisibility = Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
@@ -164,10 +164,10 @@ namespace Elwig.Windows {
|
||||
} else if (input is TextBox tb && tb.Text.Length == 0) {
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
Valid[input] = false;
|
||||
} else if (input is ComboBox cb && cb.SelectedItem == null && cb.ItemsSource != null && cb.ItemsSource.Cast<object>().Any()) {
|
||||
} else if (input is ComboBox cb && cb.SelectedItem == null && cb.HasItems) {
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
Valid[input] = false;
|
||||
} else if (input is ListBox lb && lb.SelectedItem == null && lb.ItemsSource != null && lb.ItemsSource.Cast<object>().Any()) {
|
||||
} else if (input is ListBox lb && lb.SelectedItem == null && lb.HasItems) {
|
||||
ControlUtils.SetInputInvalid(input);
|
||||
Valid[input] = false;
|
||||
} else if (input is CheckBox ckb && ((ckb.IsThreeState && ckb.IsChecked == null) || (!ckb.IsThreeState && ckb.IsChecked != true))) {
|
||||
@@ -285,8 +285,13 @@ namespace Elwig.Windows {
|
||||
var binding = cb.GetBindingExpression(ComboBox.SelectedItemProperty);
|
||||
binding?.UpdateSource();
|
||||
}
|
||||
foreach (var lb in ListBoxInputs)
|
||||
lb.SelectedItems.Clear();
|
||||
foreach (var lb in ListBoxInputs) {
|
||||
if (lb.SelectionMode == SelectionMode.Single) {
|
||||
lb.SelectedItem = null;
|
||||
} else {
|
||||
lb.SelectedItems.Clear();
|
||||
}
|
||||
}
|
||||
foreach (var cb in CheckBoxInputs) {
|
||||
cb.IsChecked = cb.IsThreeState ? null : false;
|
||||
var binding = cb.GetBindingExpression(CheckBox.IsCheckedProperty);
|
||||
|
||||
@@ -552,7 +552,8 @@
|
||||
|
||||
<Label Content="Mitgliederbewegungen:" Margin="10,40,10,10"/>
|
||||
<CheckBox x:Name="ParameterBusinessShareHistoryInput" Content="Mit Elwig erfassen" Margin="160,45,10,15"
|
||||
HorizontalAlignment="Left"/>
|
||||
HorizontalAlignment="Left"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
<GroupBox x:Name="ParameterAreaComGroup" Header="Berechnung Flächenbindungen (aktuelle Saison)" Margin="10,10,10,0" VerticalAlignment="Top">
|
||||
|
||||
@@ -361,29 +361,29 @@ namespace Elwig.Windows {
|
||||
|
||||
private async Task UpdateClientParameters(ClientParameters p) {
|
||||
p.Name = ClientNameInput.Text;
|
||||
p.NameSuffix = string.IsNullOrEmpty(ClientNameSuffixInput.Text) ? null : ClientNameSuffixInput.Text;
|
||||
p.NameSuffix = string.IsNullOrWhiteSpace(ClientNameSuffixInput.Text) ? null : ClientNameSuffixInput.Text;
|
||||
p.NameType = ClientNameTypeInput.Text;
|
||||
p.NameToken = ClientNameTokenInput.Text;
|
||||
p.NameShort = ClientNameShortInput.Text;
|
||||
p.Address = ClientAddressInput.Text;
|
||||
p.Plz = int.Parse(ClientPlzInput.Text);
|
||||
p.Ort = ClientOrtInput.Text;
|
||||
p.Iban = string.IsNullOrEmpty(ClientIbanInput.Text) ? null : ClientIbanInput.Text;
|
||||
p.Bic = string.IsNullOrEmpty(ClientBicInput.Text) ? null : ClientBicInput.Text;
|
||||
p.UstIdNr = string.IsNullOrEmpty(ClientUstIdNrInput.Text) ? null : ClientUstIdNrInput.Text;
|
||||
p.LfbisNr = string.IsNullOrEmpty(ClientLfbisNrInput.Text) ? null : ClientLfbisNrInput.Text;
|
||||
p.OrganicAuthority = string.IsNullOrEmpty(ClientOrganicAuthorityInput.Text) ? null : ClientOrganicAuthorityInput.Text;
|
||||
p.PhoneNr = string.IsNullOrEmpty(ClientPhoneNrInput.Text) ? null : ClientPhoneNrInput.Text;
|
||||
p.FaxNr = string.IsNullOrEmpty(ClientFaxNrInput.Text) ? null : ClientFaxNrInput.Text;
|
||||
p.EmailAddress = string.IsNullOrEmpty(ClientEmailAddressInput.Text) ? null : ClientEmailAddressInput.Text;
|
||||
p.Website = string.IsNullOrEmpty(ClientWebsiteInput.Text) ? null : ClientWebsiteInput.Text;
|
||||
p.Iban = string.IsNullOrWhiteSpace(ClientIbanInput.Text) ? null : ClientIbanInput.Text;
|
||||
p.Bic = string.IsNullOrWhiteSpace(ClientBicInput.Text) ? null : ClientBicInput.Text;
|
||||
p.UstIdNr = string.IsNullOrWhiteSpace(ClientUstIdNrInput.Text) ? null : ClientUstIdNrInput.Text;
|
||||
p.LfbisNr = string.IsNullOrWhiteSpace(ClientLfbisNrInput.Text) ? null : ClientLfbisNrInput.Text;
|
||||
p.OrganicAuthority = string.IsNullOrWhiteSpace(ClientOrganicAuthorityInput.Text) ? null : ClientOrganicAuthorityInput.Text;
|
||||
p.PhoneNr = string.IsNullOrWhiteSpace(ClientPhoneNrInput.Text) ? null : ClientPhoneNrInput.Text;
|
||||
p.FaxNr = string.IsNullOrWhiteSpace(ClientFaxNrInput.Text) ? null : ClientFaxNrInput.Text;
|
||||
p.EmailAddress = string.IsNullOrWhiteSpace(ClientEmailAddressInput.Text) ? null : ClientEmailAddressInput.Text;
|
||||
p.Website = string.IsNullOrWhiteSpace(ClientWebsiteInput.Text) ? null : ClientWebsiteInput.Text;
|
||||
|
||||
p.ModeBusinessShares = ParameterBusinessShareModeInput.SelectedIndex;
|
||||
p.EnableMemberHistory = ParameterBusinessShareHistoryInput.IsChecked ?? false;
|
||||
p.TextDeliveryNote = string.IsNullOrEmpty(TextElementDeliveryNote.Text) ? null : TextElementDeliveryNote.Text;
|
||||
p.TextDeliveryNote = string.IsNullOrWhiteSpace(TextElementDeliveryNote.Text) ? null : TextElementDeliveryNote.Text;
|
||||
p.ModeDeliveryNoteStats = (ModeDeliveryNoteNone.IsChecked == true) ? 0 : (ModeDeliveryNoteGaOnly.IsChecked == true) ? 1 : (ModeDeliveryNoteShort.IsChecked == true) ? 2 : (ModeDeliveryNoteFull.IsChecked == true) ? 3 : 2;
|
||||
p.TextDeliveryConfirmation = string.IsNullOrEmpty(TextElementDeliveryConfirmation.Text) ? null : TextElementDeliveryConfirmation.Text;
|
||||
p.TextCreditNote = string.IsNullOrEmpty(TextElementCreditNote.Text) ? null : TextElementCreditNote.Text;
|
||||
p.TextDeliveryConfirmation = string.IsNullOrWhiteSpace(TextElementDeliveryConfirmation.Text) ? null : TextElementDeliveryConfirmation.Text;
|
||||
p.TextCreditNote = string.IsNullOrWhiteSpace(TextElementCreditNote.Text) ? null : TextElementCreditNote.Text;
|
||||
|
||||
p.ExportEbicsVersion = ParameterExportEbicsVersion.SelectedIndex + 3;
|
||||
p.ExportEbicsAddress = ParameterExportEbicsAddress.SelectedIndex;
|
||||
|
||||
@@ -26,12 +26,12 @@ namespace Elwig.Windows {
|
||||
private bool HasChanged = false;
|
||||
private bool Updating = false;
|
||||
|
||||
private Scatter DataPlot;
|
||||
private Scatter? DataPlot;
|
||||
private Scatter? GebundenPlot;
|
||||
private Marker HighlightedPointPlot;
|
||||
private Marker PrimaryMarkedPointPlot;
|
||||
private Marker SecondaryMarkedPointPlot;
|
||||
private Text TooltipPlot;
|
||||
private Marker? HighlightedPointPlot;
|
||||
private Marker? PrimaryMarkedPointPlot;
|
||||
private Marker? SecondaryMarkedPointPlot;
|
||||
private Text? TooltipPlot;
|
||||
|
||||
private static readonly LegendItem
|
||||
UngebundenLegend = new() {
|
||||
@@ -77,7 +77,7 @@ namespace Elwig.Windows {
|
||||
PriceInput.Unit = $"{CurrencySymbol}/kg";
|
||||
GebundenFlatBonus.Unit = $"{CurrencySymbol}/kg";
|
||||
PaymentVar = ctx.PaymentVariants.Find(year, avnr) ?? throw new ArgumentException("PaymentVar not found");
|
||||
Title = $"{PaymentVar?.Name} - Lese {year} - Elwig";
|
||||
Title = $"{PaymentVar.Name} - Lese {year} - Elwig";
|
||||
LockContext = true;
|
||||
}
|
||||
|
||||
@@ -215,10 +215,12 @@ namespace Elwig.Windows {
|
||||
GebundenPlot.MarkerStyle = new MarkerStyle(MarkerShape.FilledCircle, 9, ColorGebunden);
|
||||
}
|
||||
|
||||
DataPlot = OechslePricePlot.Plot.Add.Scatter(SelectedGraphEntry!.DataGraph.DataX, SelectedGraphEntry!.DataGraph.DataY);
|
||||
DataPlot.LineStyle.Color = ColorUngebunden;
|
||||
DataPlot.Color = ColorUngebunden;
|
||||
DataPlot.MarkerStyle = new MarkerStyle(MarkerShape.FilledCircle, 9, ColorUngebunden);
|
||||
if (SelectedGraphEntry != null) {
|
||||
DataPlot = OechslePricePlot.Plot.Add.Scatter(SelectedGraphEntry.DataGraph.DataX, SelectedGraphEntry.DataGraph.DataY);
|
||||
DataPlot.LineStyle.Color = ColorUngebunden;
|
||||
DataPlot.Color = ColorUngebunden;
|
||||
DataPlot.MarkerStyle = new MarkerStyle(MarkerShape.FilledCircle, 9, ColorUngebunden);
|
||||
}
|
||||
|
||||
OechslePricePlot.Plot.Axes.SetLimits(Math.Min(GraphEntry.MinX, GraphEntry.MinXGeb) - 1, GraphEntry.MaxX + 1, -0.1, 1.5);
|
||||
|
||||
@@ -244,7 +246,10 @@ namespace Elwig.Windows {
|
||||
SecondaryMarkedPoint = -1;
|
||||
ChangeActiveGraph(null);
|
||||
HideGradationLines();
|
||||
OechslePricePlot.Plot.Remove(DataPlot);
|
||||
if (DataPlot != null) {
|
||||
OechslePricePlot.Plot.Remove(DataPlot);
|
||||
DataPlot = null;
|
||||
}
|
||||
if (GebundenPlot != null) {
|
||||
OechslePricePlot.Plot.Remove(GebundenPlot);
|
||||
GebundenPlot = null;
|
||||
@@ -254,9 +259,9 @@ namespace Elwig.Windows {
|
||||
OechslePricePlot.Refresh();
|
||||
}
|
||||
|
||||
private void ChangeMarker(Marker point, bool visible, double x = 0, double y = 0) {
|
||||
point.Location = new Coordinates(x, y);
|
||||
point.IsVisible = visible;
|
||||
private static void ChangeMarker(Marker? point, bool visible, double x = 0, double y = 0) {
|
||||
point?.Location = new Coordinates(x, y);
|
||||
point?.IsVisible = visible;
|
||||
}
|
||||
|
||||
private void EnableActionButtons() {
|
||||
@@ -416,7 +421,7 @@ namespace Elwig.Windows {
|
||||
var res = Validator.CheckDecimal(PriceInput, true, 2, Season.Precision);
|
||||
if (res.IsValid && double.TryParse(PriceInput.Text, out double price)) {
|
||||
ActiveGraph.SetPriceAt(PrimaryMarkedPoint, price);
|
||||
PrimaryMarkedPointPlot.Location = new Coordinates(PrimaryMarkedPointPlot.Location.X, price);
|
||||
PrimaryMarkedPointPlot?.Location = new Coordinates(PrimaryMarkedPointPlot.Location.X, price);
|
||||
SetHasChanged();
|
||||
OechslePricePlot.Refresh();
|
||||
CheckGebundenTypeFixed();
|
||||
@@ -492,17 +497,19 @@ namespace Elwig.Windows {
|
||||
|
||||
ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint));
|
||||
|
||||
Updating = true;
|
||||
OechsleInput.Text = Highlighted.Graph!.GetOechsleAt(Highlighted.Index).ToString();
|
||||
GebInput.IsChecked = Highlighted.Graph == SelectedGraphEntry?.GebundenGraph;
|
||||
PriceInput.Text = Math.Round(Highlighted.Graph.GetPriceAt(Highlighted.Index), Season.Precision).ToString();
|
||||
Updating = false;
|
||||
if (Highlighted.Graph != null) {
|
||||
Updating = true;
|
||||
OechsleInput.Text = Highlighted.Graph.GetOechsleAt(Highlighted.Index).ToString();
|
||||
GebInput.IsChecked = Highlighted.Graph == SelectedGraphEntry?.GebundenGraph;
|
||||
PriceInput.Text = Math.Round(Highlighted.Graph.GetPriceAt(Highlighted.Index), Season.Precision).ToString();
|
||||
Updating = false;
|
||||
}
|
||||
|
||||
EnableActionButtons();
|
||||
} else {
|
||||
PrimaryMarkedPoint = -1;
|
||||
SecondaryMarkedPoint = -1;
|
||||
if (SelectedGraphEntry!.GebundenGraph != null) {
|
||||
if (SelectedGraphEntry?.GebundenGraph != null) {
|
||||
ChangeActiveGraph(null);
|
||||
}
|
||||
ChangeMarker(PrimaryMarkedPointPlot, false);
|
||||
@@ -548,21 +555,26 @@ namespace Elwig.Windows {
|
||||
|
||||
if (mouseOnData != null) {
|
||||
ChangeMarker(HighlightedPointPlot, true, mouseOnData.Value.X, mouseOnData.Value.Y);
|
||||
HighlightedPointPlot.IsVisible = true;
|
||||
HighlightedPointPlot?.IsVisible = true;
|
||||
HoverChanged = true ^ HoverActive;
|
||||
HoverActive = true;
|
||||
HandleTooltip(mouseOnData.Value.X, mouseOnData.Value.Y, mouseOnData.Value.Index, SelectedGraphEntry!.DataGraph, e.GetPosition(OechslePricePlot), e is MouseWheelEventArgs);
|
||||
if (SelectedGraphEntry?.DataGraph is Graph g)
|
||||
HandleTooltip(mouseOnData.Value.X, mouseOnData.Value.Y, mouseOnData.Value.Index, g, e.GetPosition(OechslePricePlot), e is MouseWheelEventArgs);
|
||||
} else if (mouseOnGebunden != null) {
|
||||
ChangeMarker(HighlightedPointPlot, true, mouseOnGebunden.Value.X, mouseOnGebunden.Value.Y);
|
||||
HighlightedPointPlot.IsVisible = true;
|
||||
HighlightedPointPlot?.IsVisible = true;
|
||||
HoverChanged = true ^ HoverActive;
|
||||
HoverActive = true;
|
||||
HandleTooltip(mouseOnGebunden.Value.X, mouseOnGebunden.Value.Y, mouseOnGebunden.Value.Index, SelectedGraphEntry!.GebundenGraph!, e.GetPosition(OechslePricePlot), e is MouseWheelEventArgs);
|
||||
if (SelectedGraphEntry?.GebundenGraph is Graph g)
|
||||
HandleTooltip(mouseOnGebunden.Value.X, mouseOnGebunden.Value.Y, mouseOnGebunden.Value.Index, g, e.GetPosition(OechslePricePlot), e is MouseWheelEventArgs);
|
||||
} else {
|
||||
ChangeMarker(HighlightedPointPlot, false);
|
||||
HoverChanged = false ^ HoverActive;
|
||||
HoverActive = false;
|
||||
OechslePricePlot.Plot.PlottableList.Remove(TooltipPlot);
|
||||
if (TooltipPlot != null) {
|
||||
OechslePricePlot.Plot.PlottableList.Remove(TooltipPlot);
|
||||
TooltipPlot = null;
|
||||
}
|
||||
OechslePricePlot.Refresh();
|
||||
}
|
||||
}
|
||||
@@ -577,7 +589,10 @@ namespace Elwig.Windows {
|
||||
|
||||
private void HandleTooltip(double pointX, double pointY, int pointIndex, Graph g, Point p, bool force) {
|
||||
if (force || LastHighlighted != Highlighted || HoverChanged) {
|
||||
OechslePricePlot.Plot.PlottableList.Remove(TooltipPlot);
|
||||
if (TooltipPlot != null) {
|
||||
OechslePricePlot.Plot.PlottableList.Remove(TooltipPlot);
|
||||
TooltipPlot = null;
|
||||
}
|
||||
if (TooltipInput.IsChecked == true) {
|
||||
Coordinates mouseLocation = GetMouseCoordinates(new(p.X, p.Y - 30));
|
||||
TooltipPlot = OechslePricePlot.Plot.Add.Text($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, Season.Precision)} {CurrencySymbol}/kg", mouseLocation.X, mouseLocation.Y);
|
||||
@@ -676,7 +691,7 @@ namespace Elwig.Windows {
|
||||
}
|
||||
}
|
||||
|
||||
private void DisableTextBox(TextBox u) {
|
||||
private static void DisableTextBox(TextBox u) {
|
||||
u.IsEnabled = false;
|
||||
u.IsReadOnly = true;
|
||||
}
|
||||
@@ -707,10 +722,8 @@ namespace Elwig.Windows {
|
||||
ActiveGraph = g;
|
||||
}
|
||||
|
||||
private void ChangeLineWidth(Scatter? p, double lineWidth) {
|
||||
if (p != null) {
|
||||
p.LineWidth = (float)lineWidth;
|
||||
}
|
||||
private static void ChangeLineWidth(Scatter? p, double lineWidth) {
|
||||
p?.LineWidth = (float)lineWidth;
|
||||
}
|
||||
|
||||
private void GraphList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
@@ -752,7 +765,7 @@ namespace Elwig.Windows {
|
||||
}
|
||||
}
|
||||
|
||||
SelectedGraphEntry!.Vaributes = VaributeInput.SelectedItems.Cast<Varibute>().ToList();
|
||||
SelectedGraphEntry?.Vaributes = [.. VaributeInput.SelectedItems.Cast<Varibute>()];
|
||||
SetHasChanged();
|
||||
GraphList.Items.Refresh();
|
||||
VaributeInput.Items.Refresh();
|
||||
|
||||
@@ -124,7 +124,8 @@ namespace Elwig.Windows {
|
||||
|
||||
public DeliveryAdminWindow(int mgnr) :
|
||||
this() {
|
||||
ViewModel.FilterMember = DeliveryService.GetMember(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
||||
using var ctx = new AppDbContext();
|
||||
ViewModel.FilterMember = ctx.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
||||
ViewModel.Title = $"Lieferungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
||||
ViewModel.EnableAllSeasons = true;
|
||||
}
|
||||
@@ -482,7 +483,7 @@ namespace Elwig.Windows {
|
||||
await base.OnRenewContext(ctx);
|
||||
|
||||
if (ViewModel.FilterMember != null) {
|
||||
if (await DeliveryService.GetMemberAsync(ViewModel.FilterMember.MgNr) is not Member m) {
|
||||
if (await ctx.FetchMembers(ViewModel.FilterMember.MgNr).SingleOrDefaultAsync() is not Member m) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
@@ -1200,7 +1201,7 @@ namespace Elwig.Windows {
|
||||
}
|
||||
|
||||
private async Task UpdateLsNr() {
|
||||
if (string.IsNullOrEmpty(ViewModel.Date) || ViewModel.Branch == null) {
|
||||
if (string.IsNullOrWhiteSpace(ViewModel.Date) || ViewModel.Branch == null) {
|
||||
ViewModel.LsNr = "";
|
||||
} else {
|
||||
try {
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Header="Nachname" Binding="{Binding Name}" Width="140"/>
|
||||
<DataGridTextColumn Header="Vorname" Binding="{Binding GivenName}" Width="140"/>
|
||||
<DataGridTextColumn Header="GA" Binding="{Binding SharesTotal, StringFormat='{}{0} '}" Width="40">
|
||||
<DataGridTextColumn Header="GA" Binding="{Binding SharesActive, StringFormat='{}{0} '}" Width="40">
|
||||
<DataGridTextColumn.CellStyle>
|
||||
<Style>
|
||||
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
|
||||
@@ -619,22 +619,26 @@
|
||||
Margin="0,40,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="DateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
||||
|
||||
<Label Content="Geschäftsanteile:" Margin="10,65,0,0" Grid.Column="0"/>
|
||||
<Label x:Name="BusinessSharesLabel" Content="(rot/weiß/ruhend)" Margin="10,78,0,0" Grid.Column="0" FontSize="10"/>
|
||||
<Label Content="BH-Konto:" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="AccountingNrInput" Text="{Binding AccountingNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,70,10,0" Width="63" Grid.Column="1" HorizontalAlignment="Left"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
|
||||
<Label Content="Geschäftsanteile:" Margin="10,95,0,0" Grid.Column="0"/>
|
||||
<Label x:Name="BusinessSharesLabel" Content="(rot/weiß/ruhend)" Margin="10,108,0,0" Grid.Column="0" FontSize="10"/>
|
||||
<TextBox x:Name="BusinessShares1Input" Text="{Binding BusinessShares1String, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,70,10,0" Width="32" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
Margin="0,100,10,0" Width="32" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="IntegerInput_TextChanged"/>
|
||||
<TextBox x:Name="BusinessShares2Input" Text="{Binding BusinessShares2String, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="37,70,10,0" Width="32" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
Margin="37,100,10,0" Width="32" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="IntegerInput_TextChanged"/>
|
||||
<TextBox x:Name="BusinessShares3Input" Text="{Binding BusinessShares3String, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="74,70,10,0" Width="32" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
Margin="74,100,10,0" Width="32" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="IntegerInput_TextChanged"/>
|
||||
|
||||
<Label Content="BH-Konto:" Margin="10,100,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="AccountingNrInput" Text="{Binding AccountingNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,100,10,0" Grid.Column="1"
|
||||
TextChanged="TextBox_TextChanged"/>
|
||||
<Button x:Name="BusinessSharesButton" FontFamily="Segoe MDL2 Assets" Content="" FontSize="16" Padding="0.5,0,0,0" IsEnabled="{Binding IsMemberSelected}"
|
||||
Margin="111,100,10,0" Width="25" Height="25" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||
ToolTip="Geschäftsanteile bearbeiten"
|
||||
Click="BusinessSharesButton_Click"/>
|
||||
|
||||
<CheckBox x:Name="ActiveInput" Content="Aktiv" IsChecked="{Binding IsActive, Mode=TwoWay}" IsEnabled="False"
|
||||
Checked="ActiveInput_Changed" Unchecked="ActiveInput_Changed"
|
||||
@@ -663,7 +667,7 @@
|
||||
|
||||
<Label Content="Anmerkung:" Margin="10,190,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="CommentInput" Text="{Binding Comment, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,190,10,70" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Margin="0,190,10,70" Grid.Column="1" Grid.ColumnSpan="2" FontSize="12"
|
||||
TextChanged="TextBox_TextChanged"
|
||||
VerticalAlignment="Stretch" Height="auto" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible"/>
|
||||
|
||||
@@ -719,7 +723,7 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="200"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
@@ -736,11 +740,7 @@
|
||||
</TextBlock>
|
||||
</StatusBarItem>
|
||||
<Separator Grid.Column="1"/>
|
||||
<StatusBarItem Grid.Column="2">
|
||||
<TextBlock ToolTip="{Binding StatusBusinessSharesToolTip}">
|
||||
Geschäftsanteile: <Run Text="{Binding StatusBusinessShares}"/>
|
||||
</TextBlock>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem Grid.Column="2" Content="{Binding StatusBusinessShares}"/>
|
||||
<Separator Grid.Column="3"/>
|
||||
<StatusBarItem Grid.Column="4">
|
||||
<TextBlock ToolTip="{Binding StatusAreaCommitmentToolTip}">
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Elwig.Dialogs;
|
||||
using Elwig.Documents;
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models.Entities;
|
||||
using System.Threading.Tasks;
|
||||
using Elwig.Documents;
|
||||
using System.Diagnostics;
|
||||
using Elwig.Dialogs;
|
||||
using Elwig.Services;
|
||||
using Elwig.ViewModels;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
@@ -38,9 +40,16 @@ namespace Elwig.Windows {
|
||||
CommandBindings.Add(new CommandBinding(CtrlO, Menu_List_ShowActive_Click));
|
||||
CommandBindings.Add(new CommandBinding(CtrlShiftP, Menu_MemberDataSheet_Print_Click));
|
||||
CommandBindings.Add(new CommandBinding(CtrlShiftO, Menu_List_PrintActive_Click));
|
||||
ExemptInputs = [
|
||||
List<Control> exempt = [
|
||||
SearchInput, ActiveMemberInput, MemberList,
|
||||
];
|
||||
if (App.Client.EnableMemberHistory) {
|
||||
exempt.AddRange([BusinessShares1Input, BusinessShares2Input, BusinessShares3Input]);
|
||||
BusinessShares1Input.IsReadOnly = true;
|
||||
BusinessShares2Input.IsReadOnly = true;
|
||||
BusinessShares3Input.IsReadOnly = true;
|
||||
}
|
||||
ExemptInputs = [.. exempt];
|
||||
RequiredInputs = [
|
||||
MgNrInput, GivenNameInput, NameInput,
|
||||
AddressInput, PlzInput, OrtInput, BillingOrtInput,
|
||||
@@ -101,6 +110,11 @@ namespace Elwig.Windows {
|
||||
BusinessShares2Input.Background = Brushes.WhiteSmoke;
|
||||
BusinessShares2Input.ToolTip = "Geschäftsanteile (ruhend)";
|
||||
BusinessShares3Input.Visibility = Visibility.Hidden;
|
||||
BusinessSharesButton.Margin = new(74, 100, 10, 0);
|
||||
}
|
||||
|
||||
if (!App.Client.EnableMemberHistory) {
|
||||
BusinessSharesButton.Visibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
UpdateContactInfoVisibility();
|
||||
@@ -133,7 +147,7 @@ namespace Elwig.Windows {
|
||||
var cursor = Mouse.OverrideCursor != null;
|
||||
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||
var query = (vm.SearchQuery, vm.ShowOnlyActiveMembers);
|
||||
var (members, totalMemberCount, totalBusinessShares) = await Task.Run(async () => {
|
||||
var (members, stat) = await Task.Run(async () => {
|
||||
using var ctx = new AppDbContext();
|
||||
var (_, memberQuery, filter) = await vm.GetFilters(ctx);
|
||||
var members = await memberQuery
|
||||
@@ -160,10 +174,17 @@ namespace Elwig.Windows {
|
||||
.ThenBy(m => m.MgNr)];
|
||||
}
|
||||
|
||||
var totalMemberCount = await ctx.Members.CountAsync();
|
||||
var totalBusinessShares = await ctx.Members.SumAsync(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant);
|
||||
var stat = (await ctx.Members.GroupBy(m => 1).Select(g => new {
|
||||
Count = g.Count(),
|
||||
Shares = g.Sum(m => m.Shares),
|
||||
SharesRed = g.Sum(m => m.SharesRed),
|
||||
SharesWhite = g.Sum(m => m.SharesWhite),
|
||||
SharesDormant = g.Sum(m => m.SharesDormant),
|
||||
SharesTotal = g.Sum(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant),
|
||||
SharesActive = g.Sum(m => m.Shares + m.SharesRed + m.SharesWhite),
|
||||
}).ToListAsync()).Select(g => (g.Count, g.Shares, g.SharesRed, g.SharesWhite, g.SharesDormant, g.SharesTotal, g.SharesActive)).ToList();
|
||||
|
||||
return (members, totalMemberCount, totalBusinessShares);
|
||||
return (members, stat[0]);
|
||||
});
|
||||
if (!cursor) Mouse.OverrideCursor = null;
|
||||
if (query != (ViewModel.SearchQuery, ViewModel.ShowOnlyActiveMembers)) return;
|
||||
@@ -173,8 +194,37 @@ namespace Elwig.Windows {
|
||||
if (updateSort && MemberList.SelectedItem != null)
|
||||
MemberList.ScrollIntoView(MemberList.SelectedItem);
|
||||
|
||||
ViewModel.StatusMembers = $"{members.Count:N0} ({totalMemberCount:N0})";
|
||||
ViewModel.StatusBusinessShares = $"{members.Sum(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant):N0} ({totalBusinessShares:N0})";
|
||||
ViewModel.StatusMembers = $"{members.Count:N0} ({stat.Count:N0})";
|
||||
|
||||
var sA = members.Sum(m => m.Shares);
|
||||
var rA = members.Sum(m => m.SharesRed);
|
||||
var wA = members.Sum(m => m.SharesWhite);
|
||||
var dA = members.Sum(m => m.SharesDormant);
|
||||
List<(int Count, Brush? Color)> a = [];
|
||||
if (sA > 0) a.Add((sA, null));
|
||||
if (rA > 0) a.Add((rA, Brushes.DarkRed));
|
||||
if (wA > 0) a.Add((wA, Brushes.DarkGreen));
|
||||
if (a.Count == 0) a.Add((0, null));
|
||||
|
||||
List<(int Count, Brush? Color)> b = [];
|
||||
if (stat.Shares > 0) b.Add((stat.Shares, null));
|
||||
if (stat.SharesRed > 0) b.Add((stat.SharesRed, Brushes.DarkRed));
|
||||
if (stat.SharesWhite > 0) b.Add((stat.SharesWhite, Brushes.DarkGreen));
|
||||
if (a.Count == 0) b.Add((0, null));
|
||||
|
||||
Run[] inlines = [
|
||||
new("Geschäftsanteile: "),
|
||||
.. a.Select(i => new Run($"{i.Count:N0}") { Foreground = i.Color ?? Brushes.Black }).Join(() => new("+")),
|
||||
new(" ("),
|
||||
.. b.Select(i => new Run($"{i.Count:N0}") { Foreground = i.Color ?? Brushes.Black }).Join(() => new("+")),
|
||||
new(")")
|
||||
];
|
||||
if (ViewModel.StatusBusinessShares == null) {
|
||||
ViewModel.StatusBusinessShares = new();
|
||||
} else {
|
||||
ViewModel.StatusBusinessShares.Inlines.Clear();
|
||||
}
|
||||
ViewModel.StatusBusinessShares.Inlines.AddRange(inlines);
|
||||
}
|
||||
|
||||
private void RefreshInputs(bool validate = false) {
|
||||
@@ -198,6 +248,17 @@ namespace Elwig.Windows {
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
await ViewModel.InitInputs();
|
||||
if (App.Client.EnableMemberHistory) {
|
||||
BusinessShares1Input.Text = "0";
|
||||
BusinessShares2Input.Text = "0";
|
||||
BusinessShares3Input.Text = "0";
|
||||
} else if (App.Client.HasRedWhite) {
|
||||
BusinessShares3Input.Text = "0";
|
||||
SetDefaultValue(BusinessShares3Input);
|
||||
} else {
|
||||
BusinessShares2Input.Text = "0";
|
||||
SetDefaultValue(BusinessShares2Input);
|
||||
}
|
||||
SetDefaultValue(MgNrInput);
|
||||
SetDefaultValue(EntryDateInput);
|
||||
SetDefaultValue(ActiveInput);
|
||||
@@ -209,7 +270,7 @@ namespace Elwig.Windows {
|
||||
ControlUtils.RenewItemsSource(BranchInput, await ctx.FetchBranches().ToListAsync());
|
||||
ControlUtils.RenewItemsSource(DefaultKgInput, await ctx.WbKgs.Select(k => k.AtKg).OrderBy(k => k.Name).ToListAsync());
|
||||
|
||||
var font = new System.Windows.Media.FontFamily("Segoe MDL2 Assets");
|
||||
var font = new FontFamily("Segoe MDL2 Assets");
|
||||
MenuItem? temp = null;
|
||||
var seasons = await ctx.Seasons.Include(s => s.PaymentVariants).OrderByDescending(s => s.Year).ToListAsync();
|
||||
Menu_DeliveryConfirmation.Items.Clear();
|
||||
@@ -286,10 +347,21 @@ namespace Elwig.Windows {
|
||||
|
||||
await RefreshList();
|
||||
|
||||
var stat = await ctx.Members.GroupBy(m => m.IsActive).Select(g => new {
|
||||
IsActive = g.Key,
|
||||
Count = g.Count(),
|
||||
Shares = g.Sum(m => m.Shares),
|
||||
SharesRed = g.Sum(m => m.SharesRed),
|
||||
SharesWhite = g.Sum(m => m.SharesWhite),
|
||||
SharesDormant = g.Sum(m => m.SharesDormant),
|
||||
SharesTotal = g.Sum(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant),
|
||||
SharesActive = g.Sum(m => m.Shares + m.SharesRed + m.SharesWhite),
|
||||
}).ToDictionaryAsync(g => g.IsActive);
|
||||
|
||||
var (s1, s2) = ('\u2007', '\u202f');
|
||||
var mA = $"{await ctx.Members.CountAsync(m => m.IsActive):N0}";
|
||||
var mI = $"{await ctx.Members.CountAsync(m => !m.IsActive):N0}";
|
||||
var mT = $"{await ctx.Members.CountAsync():N0}";
|
||||
var mA = $"{stat.GetValueOrDefault(true)?.Count ?? 0:N0}";
|
||||
var mI = $"{stat.GetValueOrDefault(false)?.Count ?? 0:N0}";
|
||||
var mT = $"{stat.Sum(g => g.Value.Count):N0}";
|
||||
var mM = Math.Max(mA.Length, Math.Max(mI.Length, mT.Length));
|
||||
var mS = mM > 3;
|
||||
if (mS) mM--;
|
||||
@@ -298,16 +370,53 @@ namespace Elwig.Windows {
|
||||
$"{new string(s1, Math.Max(0, mM - mI.Length))}{(mS && mI.Length < 4 ? s2 : "")}{mI} nicht aktive Mitglieder\n" +
|
||||
$"{new string(s1, Math.Max(0, mM - mT.Length))}{(mS && mT.Length < 4 ? s2 : "")}{mT} Mitglieder gesamt";
|
||||
|
||||
var bA = $"{await ctx.Members.Where(m => m.IsActive).SumAsync(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant):N0}";
|
||||
var bI = $"{await ctx.Members.Where(m => !m.IsActive).SumAsync(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant):N0}";
|
||||
var bT = $"{await ctx.Members.SumAsync(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant):N0}";
|
||||
var bM = Math.Max(bA.Length, Math.Max(bI.Length, bT.Length));
|
||||
var bS = bM > 3;
|
||||
if (bS) bM--;
|
||||
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" +
|
||||
$"{new string(s1, Math.Max(0, bM - bT.Length))}{(bS && bT.Length < 4 ? s2 : "")}{bT} Geschäftsanteile gesamt";
|
||||
var grid = new Grid();
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(100) });
|
||||
grid.AddToolTipCell("Geschäftsanteile:", 0, 0, bold: true);
|
||||
grid.AddToolTipCell("Aktive Mitglieder", 1, 0);
|
||||
grid.AddToolTipCell("Nicht aktive Mg.", 2, 0);
|
||||
grid.AddToolTipCell("Alle Mitglieder", 3, 0, bold: true);
|
||||
if (App.Client.HasRedWhite) {
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||
grid.AddToolTipCell("rot", 0, 1, alignRight: true);
|
||||
grid.AddToolTipCell("weiß", 0, 2, alignRight: true);
|
||||
grid.AddToolTipCell("ruhend", 0, 3, alignRight: true);
|
||||
grid.AddToolTipCell("gesamt", 0, 4, alignRight: true);
|
||||
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(true)?.SharesRed ?? 0:N0}", 1, 1, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(true)?.SharesWhite ?? 0:N0}", 1, 2, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(true)?.SharesDormant ?? 0:N0}", 1, 3, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(true)?.SharesTotal ?? 0:N0}", 1, 4, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(false)?.SharesRed ?? 0:N0}", 2, 1, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(false)?.SharesWhite ?? 0:N0}", 2, 2, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(false)?.SharesDormant ?? 0:N0}", 2, 3, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(false)?.SharesTotal ?? 0:N0}", 2, 4, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.Sum(g => g.Value.SharesRed):N0}", 3, 1, alignRight: true, bold: true);
|
||||
grid.AddToolTipCell($"{stat.Sum(g => g.Value.SharesWhite):N0}", 3, 2, alignRight: true, bold: true);
|
||||
grid.AddToolTipCell($"{stat.Sum(g => g.Value.SharesDormant):N0}", 3, 3, alignRight: true, bold: true);
|
||||
grid.AddToolTipCell($"{stat.Sum(g => g.Value.SharesTotal):N0}", 3, 4, alignRight: true, bold: true);
|
||||
} else {
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||
grid.ColumnDefinitions.Add(new() { Width = new(50) });
|
||||
grid.AddToolTipCell("normal", 0, 1, alignRight: true);
|
||||
grid.AddToolTipCell("ruhend", 0, 2, alignRight: true);
|
||||
grid.AddToolTipCell("gesamt", 0, 3, alignRight: true);
|
||||
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(true)?.Shares ?? 0:N0}", 1, 1, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(true)?.SharesDormant ?? 0:N0}", 1, 2, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(true)?.SharesTotal ?? 0:N0}", 1, 3, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(false)?.Shares ?? 0:N0}", 2, 1, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(false)?.SharesDormant ?? 0:N0}", 2, 2, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.GetValueOrDefault(false)?.SharesTotal ?? 0:N0}", 2, 3, alignRight: true);
|
||||
grid.AddToolTipCell($"{stat.Sum(g => g.Value.Shares):N0}", 3, 1, alignRight: true, bold: true);
|
||||
grid.AddToolTipCell($"{stat.Sum(g => g.Value.SharesDormant):N0}", 3, 2, alignRight: true, bold: true);
|
||||
grid.AddToolTipCell($"{stat.Sum(g => g.Value.SharesTotal):N0}", 3, 3, alignRight: true, bold: true);
|
||||
}
|
||||
ViewModel.StatusBusinessShares?.ToolTip = grid;
|
||||
}
|
||||
|
||||
private void SetPhoneNrInputVisible(int nr, bool visible, int? position = null) {
|
||||
@@ -493,6 +602,10 @@ namespace Elwig.Windows {
|
||||
ViewModel.EnableSearchInputs = true;
|
||||
}
|
||||
|
||||
private void BusinessSharesButton_Click(object sender, RoutedEventArgs evt) {
|
||||
App.FocusMemberBusinessSharesWindow(ViewModel.SelectedMember!.MgNr);
|
||||
}
|
||||
|
||||
private void AreaCommitmentButton_Click(object sender, RoutedEventArgs evt) {
|
||||
App.FocusMemberAreaComs(ViewModel.SelectedMember!.MgNr);
|
||||
}
|
||||
@@ -735,7 +848,7 @@ namespace Elwig.Windows {
|
||||
lastVisible = true;
|
||||
for (int i = 0; i < EmailAddressInputs.Length; i++) {
|
||||
var input = EmailAddressInputs[i];
|
||||
var vis = !string.IsNullOrEmpty(input.Address.Text) || (m?.EmailAddresses.Any(a => a.Nr - 1 == i) ?? false);
|
||||
var vis = !string.IsNullOrWhiteSpace(input.Address.Text) || (m?.EmailAddresses.Any(a => a.Nr - 1 == i) ?? false);
|
||||
var cVis = vis || (extra && lastVisible);
|
||||
SetEmailAddressInputVisible(i, cVis, cVis ? num++ : null);
|
||||
lastVisible = vis;
|
||||
@@ -743,7 +856,7 @@ namespace Elwig.Windows {
|
||||
lastVisible = true;
|
||||
for (int i = 0; i < PhoneNrInputs.Length; i++) {
|
||||
var input = PhoneNrInputs[i];
|
||||
var vis = !string.IsNullOrEmpty(input.Number.Text) || (m?.TelephoneNumbers.Any(n => n.Nr - 1 == i) ?? false);
|
||||
var vis = !string.IsNullOrWhiteSpace(input.Number.Text) || (m?.TelephoneNumbers.Any(n => n.Nr - 1 == i) ?? false);
|
||||
var cVis = vis || (extra && lastVisible);
|
||||
SetPhoneNrInputVisible(i, cVis, cVis ? num++ : null);
|
||||
lastVisible = vis;
|
||||
@@ -760,6 +873,14 @@ namespace Elwig.Windows {
|
||||
|
||||
new protected void ClearInputs(bool validate = false) {
|
||||
ViewModel.ClearInputs();
|
||||
if (App.Client.EnableMemberHistory) {
|
||||
BusinessShares1Input.Text = "";
|
||||
BusinessShares2Input.Text = "";
|
||||
BusinessShares3Input.Text = "";
|
||||
ControlUtils.ClearInputState(BusinessShares1Input);
|
||||
ControlUtils.ClearInputState(BusinessShares2Input);
|
||||
ControlUtils.ClearInputState(BusinessShares3Input);
|
||||
}
|
||||
base.ClearInputs(validate);
|
||||
}
|
||||
|
||||
@@ -804,9 +925,9 @@ namespace Elwig.Windows {
|
||||
|
||||
var oldMember = await ctx.FetchMembers(mgnr).SingleAsync();
|
||||
var newName = $"{ViewModel.Name?.Replace('ß', 'ẞ').ToUpper()} " +
|
||||
$"{ViewModel.Prefix}{(!string.IsNullOrEmpty(ViewModel.Prefix) ? " " : "")}" +
|
||||
$"{ViewModel.GivenName}{(!string.IsNullOrEmpty(ViewModel.GivenName) ? " " : "")}" +
|
||||
$"{ViewModel.Suffix}{(!string.IsNullOrEmpty(ViewModel.Suffix) ? " " : "")}";
|
||||
$"{ViewModel.Prefix}{(!string.IsNullOrWhiteSpace(ViewModel.Prefix) ? " " : "")}" +
|
||||
$"{ViewModel.GivenName}{(!string.IsNullOrWhiteSpace(ViewModel.GivenName) ? " " : "")}" +
|
||||
$"{ViewModel.Suffix}{(!string.IsNullOrWhiteSpace(ViewModel.Suffix) ? " " : "")}";
|
||||
var d = new AreaComTransferDialog(oldMember.AdministrativeName, newName, areaComs.Count, areaComs.Sum(c => c.Area));
|
||||
if (d.ShowDialog() != true)
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
<local:AdministrationWindow
|
||||
x:Class="Elwig.Windows.MemberBusinessSharesAdminWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Elwig.Windows"
|
||||
xmlns:ctrl="clr-namespace:Elwig.Controls"
|
||||
xmlns:vm="clr-namespace:Elwig.ViewModels"
|
||||
Title="{Binding Title}" Height="450" Width="800" MinHeight="400" MinWidth="700">
|
||||
<Window.DataContext>
|
||||
<vm:MemberBusinessSharesViewModel/>
|
||||
</Window.DataContext>
|
||||
<Window.Resources>
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
<Setter Property="Padding" Value="2,4,2,4"/>
|
||||
<Setter Property="Height" Value="25"/>
|
||||
</Style>
|
||||
<Style TargetType="TextBox">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="2"/>
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="TextWrapping" Value="NoWrap"/>
|
||||
</Style>
|
||||
<Style TargetType="ctrl:UnitTextBox">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="2"/>
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="TextWrapping" Value="NoWrap"/>
|
||||
</Style>
|
||||
<Style TargetType="ComboBox">
|
||||
<Setter Property="Height" Value="25"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||
</Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="9,3"/>
|
||||
<Setter Property="Height" Value="27"/>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" MinWidth="300"/>
|
||||
<ColumnDefinition Width="5"/>
|
||||
<ColumnDefinition Width="1*" MinWidth="350"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid Margin="5,0,0,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="42"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ListBox x:Name="MemberHistoryList" Margin="5,10,5,0" Grid.ColumnSpan="3"
|
||||
ItemsSource="{Binding History, Mode=TwoWay}" SelectedItem="{Binding SelectedHistoryEntry, Mode=TwoWay}"
|
||||
SelectionChanged="MemberHistoryList_SelectionChanged">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding DateNotice, StringFormat='{}{0:dd.MM.yy}'}" Width="55" TextAlignment="Left" Margin="0,0,0,0"/>
|
||||
<TextBlock Text="{Binding DateEffective, StringFormat='{}{0:dd.MM.yy}'}" Width="55" TextAlignment="Left" Margin="0,0,0,0"/>
|
||||
<TextBlock Text="{Binding Shares, StringFormat='{}{0:N0}'}" Width="15" TextAlignment="Right" Margin="0,0,10,0"/>
|
||||
<TextBlock Text="{Binding PoVReasonPhrase}" TextAlignment="Left" Margin="0,0,0,0"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<Button x:Name="NewHistoryButton" Content="Neu" Visibility="{Binding ControlButtonsVisibility}"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="NewHistoryButton_Click">
|
||||
<Button.ToolTip>
|
||||
<TextBlock FontWeight="Bold">Alt+Einfg</TextBlock>
|
||||
</Button.ToolTip>
|
||||
</Button>
|
||||
<Button x:Name="EditHistoryButton" Content="Bearbeiten" IsEnabled="False" Visibility="{Binding ControlButtonsVisibility}"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="EditHistoryButton_Click">
|
||||
<Button.ToolTip>
|
||||
<TextBlock FontWeight="Bold">Strg+B</TextBlock>
|
||||
</Button.ToolTip>
|
||||
</Button>
|
||||
<Button x:Name="DeleteHistoryButton" Content="Löschen" IsEnabled="False" Visibility="{Binding ControlButtonsVisibility}"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="DeleteHistoryButton_Click">
|
||||
<Button.ToolTip>
|
||||
<TextBlock FontWeight="Bold">Alt+Entf</TextBlock>
|
||||
</Button.ToolTip>
|
||||
</Button>
|
||||
|
||||
<Button x:Name="SaveButton" Content="Speichern" IsEnabled="False" Visibility="{Binding EditingButtonsVisibility}"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="5,5,2.5,10" Grid.Column="0" Grid.Row="2"
|
||||
Click="SaveButton_Click">
|
||||
<Button.ToolTip>
|
||||
<TextBlock FontWeight="Bold">Strg+S</TextBlock>
|
||||
</Button.ToolTip>
|
||||
</Button>
|
||||
<Button x:Name="ResetButton" Content="Zurücksetzen" IsEnabled="False" Visibility="{Binding EditingButtonsVisibility}"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,2.5,10" Grid.Column="1" Grid.Row="2"
|
||||
Click="ResetButton_Click">
|
||||
<Button.ToolTip>
|
||||
<TextBlock FontWeight="Bold">Strg+Z</TextBlock>
|
||||
</Button.ToolTip>
|
||||
</Button>
|
||||
<Button x:Name="CancelButton" Content="Abbrechen" IsEnabled="False" Visibility="{Binding EditingButtonsVisibility}" IsCancel="True"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2.5,5,5,10" Grid.Column="2" Grid.Row="2"
|
||||
Click="CancelButton_Click">
|
||||
<Button.ToolTip>
|
||||
<TextBlock FontWeight="Bold">Esc</TextBlock>
|
||||
</Button.ToolTip>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
|
||||
|
||||
<Grid Grid.Column="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="95"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox Header="Geschäftsanteilbewegung" Margin="5,10,5,5">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="110"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Label Content="Grund:" Margin="10,10,0,0" Grid.Column="0"/>
|
||||
<ComboBox x:Name="ReasonInput" SelectedValue="{Binding Reason, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,10,10,0" Grid.Column="1"
|
||||
SelectedValuePath="Tag"
|
||||
SelectionChanged="ReasonInput_SelectionChanged">
|
||||
<ComboBoxItem Tag="purchase">Kauf</ComboBoxItem>
|
||||
<ComboBoxItem Tag="transfer_to">Übertragung an...</ComboBoxItem>
|
||||
<ComboBoxItem Tag="transfer_from">Übertragung von...</ComboBoxItem>
|
||||
<ComboBoxItem Tag="prescription">Vorschreibung</ComboBoxItem>
|
||||
<ComboBoxItem Tag="exclusion">Ausschluss</ComboBoxItem>
|
||||
<ComboBoxItem Tag="deceased">Tod</ComboBoxItem>
|
||||
<ComboBoxItem Tag="retirement">Kündigung</ComboBoxItem>
|
||||
<ComboBoxItem Tag="payout">Auszahlung</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<Label Content="Anderes Mitgl.:" Margin="10,40,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="OtherMgNrInput" Text="{Binding OtherMgNrString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Width="48" Grid.Column="1" Margin="0,40,0,0" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="OtherMgNrInput_TextChanged" LostFocus="OtherMgNrInput_LostFocus"/>
|
||||
<ComboBox x:Name="OtherMemberInput"
|
||||
Grid.Column="1" Margin="53,40,40,10" IsEditable="True"
|
||||
ItemTemplate="{StaticResource MemberAdminNameTemplate}" TextSearch.TextPath="AdministrativeName"
|
||||
SelectionChanged="OtherMemberInput_SelectionChanged"/>
|
||||
<Button x:Name="OtherMemberReferenceButton" Grid.Column="1" Height="25" Width="25" FontFamily="Segoe MDL2 Assets" Content="" Padding="0,0,0,0"
|
||||
Margin="10,40,10,10" VerticalAlignment="Top" HorizontalAlignment="Right" ToolTip="Zu Mitglied springen"
|
||||
Click="OtherMemberReferenceButton_Click"/>
|
||||
|
||||
<Label Content="Anmerkung:" Margin="10,70,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="CommentInput" Text="{Binding Comment, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,70,10,0" Grid.Column="1"/>
|
||||
|
||||
<Label Content="Meldung:" Margin="10,100,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="DateNoticeInput" Text="{Binding DateNoticeString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,100,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="DateNoticeInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
||||
|
||||
<CheckBox x:Name="HasMemberSignedInput" IsChecked="{Binding MemberHasSigned, Mode=TwoWay}" Content="Von Mg. unterfertigt"
|
||||
Margin="88,105,10,0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="TOp"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed"/>
|
||||
|
||||
<Label Content="Wirksam:" Margin="10,130,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="DateEffeciveInput" Text="{Binding DateEffectiveString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,130,10,0" Width="78" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="DateInput_TextChanged" LostFocus="DateInput_LostFocus"/>
|
||||
|
||||
<Label Content="Geschäftsanteile:" Margin="10,160,0,0" Grid.Column="0"/>
|
||||
<TextBox x:Name="SharesInput" Text="{Binding SharesString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="0,160,10,0" Width="32" Grid.Column="1" HorizontalAlignment="Left" TextAlignment="Right"
|
||||
TextChanged="SharesInput_TextChanged"/>
|
||||
|
||||
<CheckBox x:Name="DeductInput" IsChecked="{Binding Deduct, Mode=TwoWay}"
|
||||
Margin="42,165,10,0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="TOp"
|
||||
Checked="CheckBox_Changed" Unchecked="CheckBox_Changed">
|
||||
<TextBlock>
|
||||
bei Auszahlung <Run Text="{Binding DeductYearString}"/> abziehen
|
||||
</TextBlock>
|
||||
</CheckBox>
|
||||
|
||||
<Label Content="Betrag:" Margin="10,190,0,10"/>
|
||||
<ctrl:UnitTextBox x:Name="ValuePerShareInput" Text="{Binding ValuePerShareString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Unit="€/GA" TextChanged="AmountPerShareInput_TextChanged"
|
||||
Grid.Column="1" Width="76" Margin="0,190,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<ctrl:UnitTextBox x:Name="TotalAmountInput" Text="{Binding TotalAmount}" Unit="€" IsEnabled="False"
|
||||
Grid.Column="1" Width="77" Margin="81,190,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Mitglied" Grid.Row="1" Margin="5,5,5,10">
|
||||
<Grid>
|
||||
<TextBlock x:Name="MemberInfo" Text="Name (1234)"
|
||||
FontSize="14" Margin="10,10,10,10"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</local:AdministrationWindow>
|
||||
@@ -0,0 +1,347 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models.Entities;
|
||||
using Elwig.Services;
|
||||
using Elwig.ViewModels;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Elwig.Windows {
|
||||
public partial class MemberBusinessSharesAdminWindow : AdministrationWindow {
|
||||
|
||||
public MemberBusinessSharesViewModel ViewModel => (MemberBusinessSharesViewModel)DataContext;
|
||||
|
||||
public MemberBusinessSharesAdminWindow(int mgnr) {
|
||||
InitializeComponent();
|
||||
using var ctx = new AppDbContext();
|
||||
ViewModel.FilterMember = ctx.Members.Find(mgnr) ?? throw new ArgumentException("MgNr argument has invalid value");
|
||||
ViewModel.Title = $"Geschäftsanteilbewegungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
||||
ExemptInputs = [
|
||||
MemberHistoryList, TotalAmountInput
|
||||
];
|
||||
RequiredInputs = [
|
||||
ReasonInput, DateNoticeInput, DateEffeciveInput, SharesInput
|
||||
];
|
||||
}
|
||||
|
||||
public void FocusMemberHistory(int histnr) {
|
||||
if (IsEditing || IsCreating) return;
|
||||
var item = ViewModel.History.FirstOrDefault(h => h.HistNr == histnr);
|
||||
if (item != null) {
|
||||
ControlUtils.SelectItem(MemberHistoryList, item);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RefreshList() {
|
||||
var vm = ViewModel;
|
||||
var cursor = Mouse.OverrideCursor != null;
|
||||
if (!cursor) Mouse.OverrideCursor = Cursors.Wait;
|
||||
var history = await Task.Run(async () => {
|
||||
using var ctx = new AppDbContext();
|
||||
return await ctx.MemberHistory
|
||||
.Where(h => h.FromMgNr == vm.FilterMember.MgNr || h.ToMgNr == vm.FilterMember.MgNr)
|
||||
.OrderBy(h => h.DateNoticeString).ThenBy(h => h.HistNr)
|
||||
.ToListAsync();
|
||||
});
|
||||
if (!cursor) Mouse.OverrideCursor = null;
|
||||
history.ForEach(h => h.PoVMgNr = vm.FilterMember.MgNr);
|
||||
|
||||
ControlUtils.RenewItemsSource(MemberHistoryList, history,
|
||||
MemberHistoryList_SelectionChanged, ControlUtils.RenewSourceDefault.None);
|
||||
RefreshInputs();
|
||||
}
|
||||
|
||||
|
||||
private void RefreshInputs(bool validate = false) {
|
||||
ClearInputStates();
|
||||
if (ViewModel.SelectedHistoryEntry is MemberHistory h) {
|
||||
EditHistoryButton.IsEnabled = true;
|
||||
DeleteHistoryButton.IsEnabled = true;
|
||||
FillInputs(h);
|
||||
} else {
|
||||
EditHistoryButton.IsEnabled = false;
|
||||
DeleteHistoryButton.IsEnabled = false;
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
ClearInputs(validate);
|
||||
ClearInputStates();
|
||||
}
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void FillInputs(MemberHistory h) {
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
ViewModel.FillInputs(h);
|
||||
ReasonInput.SelectedValue = h.Reason + (h.Reason == MemberHistory.REASON_TRANSFER ? $"_{(h.FromMgNr == ViewModel.FilterMember.MgNr ? "to" : "from")}" : "");
|
||||
FinishInputFilling();
|
||||
}
|
||||
|
||||
private async Task InitInputs() {
|
||||
ClearOriginalValues();
|
||||
ClearDefaultValues();
|
||||
await ViewModel.InitInputs();
|
||||
SetDefaultValue(DateNoticeInput);
|
||||
if (ViewModel.ValuePerShare != null)
|
||||
SetDefaultValue(ValuePerShareInput);
|
||||
ValidateRequiredInputs();
|
||||
}
|
||||
|
||||
new protected void ClearInputs(bool validate = false) {
|
||||
ViewModel.ClearInputs();
|
||||
base.ClearInputs(validate);
|
||||
}
|
||||
|
||||
override protected void UpdateButtons() {
|
||||
if (!IsEditing && !IsCreating) return;
|
||||
bool ch = HasChanged, v = IsValid;
|
||||
ResetButton.IsEnabled = ch;
|
||||
SaveButton.IsEnabled = v && ch;
|
||||
}
|
||||
|
||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||
await base.OnRenewContext(ctx);
|
||||
|
||||
if (await ctx.FetchMembers(ViewModel.FilterMember.MgNr).SingleOrDefaultAsync() is not Member m) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
ViewModel.FilterMember = m;
|
||||
ViewModel.Title = $"Geschäftsanteilbewegungen - {ViewModel.FilterMember.AdministrativeName} - Elwig";
|
||||
|
||||
ControlUtils.RenewItemsSource(OtherMemberInput, await ctx.FetchMembers(includeNotActive: true).ToListAsync());
|
||||
|
||||
MemberInfo.Text = $"{m.FullAdministrativeName}\nGA: {m.Shares:N0} (normal) / {m.SharesRed:N0} (rot) / {m.SharesWhite:N0} (weiß) / {m.SharesDormant:N0} (ruhend)";
|
||||
|
||||
await RefreshList();
|
||||
}
|
||||
|
||||
private void MemberHistoryList_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
||||
RefreshInputs();
|
||||
}
|
||||
|
||||
protected override void ShortcutNew() {
|
||||
if (!NewHistoryButton.IsEnabled || NewHistoryButton.Visibility != Visibility.Visible)
|
||||
return;
|
||||
NewHistoryButton_Click(null, null);
|
||||
}
|
||||
|
||||
private async void NewHistoryButton_Click(object? sender, RoutedEventArgs? evt) {
|
||||
IsCreating = true;
|
||||
MemberHistoryList.IsEnabled = false;
|
||||
ViewModel.SelectedHistoryEntry = null;
|
||||
HideNewEditDeleteButtons();
|
||||
ShowSaveResetCancelButtons();
|
||||
UnlockInputs();
|
||||
await InitInputs();
|
||||
DeductInput.IsEnabled = false;
|
||||
OtherMgNrInput.IsEnabled = false;
|
||||
OtherMemberInput.IsEnabled = false;
|
||||
}
|
||||
|
||||
protected override void ShortcutEdit() {
|
||||
if (!EditHistoryButton.IsEnabled || EditHistoryButton.Visibility != Visibility.Visible)
|
||||
return;
|
||||
EditHistoryButton_Click(null, null);
|
||||
}
|
||||
|
||||
private void EditHistoryButton_Click(object? sender, RoutedEventArgs? evt) {
|
||||
if (ViewModel.SelectedHistoryEntry == null) return;
|
||||
|
||||
IsEditing = true;
|
||||
MemberHistoryList.IsEnabled = false;
|
||||
|
||||
HideNewEditDeleteButtons();
|
||||
ShowSaveResetCancelButtons();
|
||||
UnlockInputs();
|
||||
|
||||
DeductInput.IsEnabled = ViewModel.Reason == MemberHistory.REASON_PURCHASE || ViewModel.Reason == MemberHistory.REASON_PRESCRIPTION;
|
||||
OtherMgNrInput.IsEnabled = ViewModel.Reason?.StartsWith(MemberHistory.REASON_TRANSFER) ?? false;
|
||||
OtherMemberInput.IsEnabled = OtherMgNrInput.IsEnabled;
|
||||
}
|
||||
|
||||
protected override void ShortcutDelete() {
|
||||
if (!DeleteHistoryButton.IsEnabled || DeleteHistoryButton.Visibility != Visibility.Visible)
|
||||
return;
|
||||
DeleteHistoryButton_Click(null, null);
|
||||
}
|
||||
|
||||
private async void DeleteHistoryButton_Click(object? sender, RoutedEventArgs? evt) {
|
||||
if (ViewModel.SelectedHistoryEntry is not MemberHistory h)
|
||||
return;
|
||||
|
||||
if (InteractionService.AskContinueYesNo("Geschäftsanteilbewegung löschen", $"Soll die Geschäftsanteilbewegung wirklich unwiderruflich\ngelöscht werden?\n\nFalls ja:\nSoll die Änderung der aktuellen GA wieder rückgängig gemacht werden?") is bool enableTriggers) {
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
try {
|
||||
await MemberBusinessSharesService.DeleteMemberHistory(h.HistNr, enableTriggers);
|
||||
App.HintContextChange();
|
||||
} catch (Exception exc) {
|
||||
InteractionService.ShowDbException("Geschäftsanteilbewegung löschen", exc);
|
||||
}
|
||||
Mouse.OverrideCursor = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ShortcutSave() {
|
||||
if (!SaveButton.IsEnabled || SaveButton.Visibility != Visibility.Visible)
|
||||
return;
|
||||
SaveButton_Click(null, null);
|
||||
}
|
||||
|
||||
private async void SaveButton_Click(object? sender, RoutedEventArgs? evt) {
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
SaveButton.IsEnabled = false;
|
||||
|
||||
int mgnr;
|
||||
try {
|
||||
mgnr = await ViewModel.UpdateMemberHistory(ViewModel.SelectedHistoryEntry?.HistNr, IsEditing || ViewModel.DateNotice >= DateOnly.FromDateTime(Utils.Today).AddDays(-14));
|
||||
App.HintContextChange();
|
||||
} catch (Exception exc) {
|
||||
InteractionService.ShowDbException("Geschäftsanteilbewegung aktualisieren", exc);
|
||||
SaveButton.IsEnabled = true;
|
||||
Mouse.OverrideCursor = null;
|
||||
return;
|
||||
}
|
||||
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
MemberHistoryList.IsEnabled = true;
|
||||
OtherMgNrInput.IsEnabled = true;
|
||||
HideSaveResetCancelButtons();
|
||||
ShowNewEditDeleteButtons();
|
||||
LockInputs();
|
||||
FinishInputFilling();
|
||||
await EnsureContextRenewed();
|
||||
Mouse.OverrideCursor = null;
|
||||
if (mgnr is int m)
|
||||
FocusMemberHistory(m);
|
||||
}
|
||||
|
||||
protected override void ShortcutReset() {
|
||||
if (!ResetButton.IsEnabled || ResetButton.Visibility != Visibility.Visible)
|
||||
return;
|
||||
ResetButton_Click(null, null);
|
||||
}
|
||||
|
||||
private async void ResetButton_Click(object? sender, RoutedEventArgs? evt) {
|
||||
if (IsEditing) {
|
||||
RefreshInputs();
|
||||
} else if (IsCreating) {
|
||||
ClearInputs();
|
||||
await InitInputs();
|
||||
}
|
||||
UpdateButtons();
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs evt) {
|
||||
IsEditing = false;
|
||||
IsCreating = false;
|
||||
MemberHistoryList.IsEnabled = true;
|
||||
OtherMgNrInput.IsEnabled = true;
|
||||
HideSaveResetCancelButtons();
|
||||
ShowNewEditDeleteButtons();
|
||||
RefreshInputs();
|
||||
LockInputs();
|
||||
}
|
||||
|
||||
private void ShowSaveResetCancelButtons() {
|
||||
SaveButton.IsEnabled = false;
|
||||
ResetButton.IsEnabled = false;
|
||||
CancelButton.IsEnabled = true;
|
||||
ViewModel.EditingButtonsVisibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideSaveResetCancelButtons() {
|
||||
SaveButton.IsEnabled = false;
|
||||
ResetButton.IsEnabled = false;
|
||||
CancelButton.IsEnabled = false;
|
||||
ViewModel.EditingButtonsVisibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void ShowNewEditDeleteButtons() {
|
||||
NewHistoryButton.IsEnabled = true;
|
||||
EditHistoryButton.IsEnabled = ViewModel.SelectedHistoryEntry != null;
|
||||
DeleteHistoryButton.IsEnabled = ViewModel.SelectedHistoryEntry != null;
|
||||
ViewModel.ControlButtonsVisibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideNewEditDeleteButtons() {
|
||||
NewHistoryButton.IsEnabled = false;
|
||||
EditHistoryButton.IsEnabled = false;
|
||||
DeleteHistoryButton.IsEnabled = false;
|
||||
ViewModel.ControlButtonsVisibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void OtherMgNrInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
var valid = InputTextChanged((TextBox)sender, Validator.CheckMgNr);
|
||||
var text = OtherMgNrInput.Text;
|
||||
var caret = OtherMgNrInput.CaretIndex;
|
||||
ControlUtils.SelectItemWithPk(OtherMemberInput, valid ? ViewModel.OtherMgNr : null);
|
||||
OtherMgNrInput.Text = text;
|
||||
OtherMgNrInput.CaretIndex = caret;
|
||||
}
|
||||
|
||||
private void OtherMgNrInput_LostFocus(object sender, RoutedEventArgs evt) {
|
||||
var valid = InputLostFocus((TextBox)sender, Validator.CheckMgNr);
|
||||
ControlUtils.SelectItemWithPk(OtherMemberInput, valid ? ViewModel.OtherMgNr : null);
|
||||
}
|
||||
|
||||
private void OtherMemberInput_SelectionChanged(object? sender, SelectionChangedEventArgs? evt) {
|
||||
var m = OtherMemberInput.SelectedItem as Member;
|
||||
ViewModel.OtherMgNr = m?.MgNr;
|
||||
}
|
||||
|
||||
private void OtherMemberReferenceButton_Click(object sender, RoutedEventArgs evt) {
|
||||
if (OtherMemberInput.SelectedItem is not Member m) return;
|
||||
App.FocusMember(m.MgNr);
|
||||
}
|
||||
|
||||
private void ReasonInput_SelectionChanged(object sender, RoutedEventArgs evt) {
|
||||
ComboBox_SelectionChanged(sender, evt);
|
||||
if (!IsEditing && !IsCreating) return;
|
||||
if (ViewModel.DateNotice is not DateOnly d) return;
|
||||
if (ViewModel.Reason == MemberHistory.REASON_EXCLUSION || ViewModel.Reason == MemberHistory.REASON_DECEASED || ViewModel.Reason == MemberHistory.REASON_RETIREMENT) {
|
||||
ViewModel.DateEffectiveString = $"31.12.{d.Year + 1}";
|
||||
} else {
|
||||
ViewModel.DateEffectiveString = ViewModel.DateNoticeString;
|
||||
}
|
||||
DeductInput.IsEnabled = ViewModel.Reason == MemberHistory.REASON_PURCHASE || ViewModel.Reason == MemberHistory.REASON_PRESCRIPTION;
|
||||
if (!DeductInput.IsEnabled) DeductInput.IsChecked = false;
|
||||
OtherMgNrInput.IsEnabled = ViewModel.Reason?.StartsWith(MemberHistory.REASON_TRANSFER) ?? false;
|
||||
OtherMemberInput.IsEnabled = OtherMgNrInput.IsEnabled;
|
||||
if (!OtherMgNrInput.IsEnabled) OtherMgNrInput.Text = "";
|
||||
}
|
||||
|
||||
private void DateNoticeInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
DateInput_TextChanged(sender, evt);
|
||||
if (!IsEditing && !IsCreating) return;
|
||||
if (ViewModel.DateNotice is not DateOnly d) return;
|
||||
ViewModel.DeductYear = d.Year;
|
||||
if (ViewModel.DateEffective == null && ViewModel.Reason != null) {
|
||||
if (ViewModel.Reason == MemberHistory.REASON_EXCLUSION || ViewModel.Reason == MemberHistory.REASON_DECEASED || ViewModel.Reason == MemberHistory.REASON_RETIREMENT) {
|
||||
ViewModel.DateEffectiveString = $"31.12.{d.Year + 1}";
|
||||
} else {
|
||||
ViewModel.DateEffectiveString = ViewModel.DateNoticeString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAmount() {
|
||||
ViewModel.TotalAmount = $"{ViewModel.Shares * ViewModel.ValuePerShare:N2}";
|
||||
}
|
||||
|
||||
private void SharesInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
IntegerInput_TextChanged(sender, evt);
|
||||
UpdateAmount();
|
||||
}
|
||||
|
||||
private void AmountPerShareInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
InputTextChanged((TextBox)sender, Validator.CheckDecimal((TextBox)sender, false, 3, 2));
|
||||
UpdateAmount();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,7 +194,7 @@
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="Automatische Nachzeichnung der Geschäftsanteile" Margin="5,10,10,10" Height="180" Width="365"
|
||||
<GroupBox Header="Automatische Nachzeichnung von Geschäftsanteilen" Margin="5,10,10,10" Height="180" Width="365"
|
||||
VerticalAlignment="Bottom" HorizontalAlignment="Left">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Elwig.Windows {
|
||||
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.Reason == "auto" && h.Shares > 0)
|
||||
.Where(h => h.DeductYear == Year)
|
||||
.GroupBy(h => h.ToMember)
|
||||
.ToDictionaryAsync(h => h.Key.MgNr, h => h.Sum(g => g.Shares));
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
Margin="110,135,10,10" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||
Checked="ConsiderPenaltyInput_Changed" Unchecked="ConsiderPenaltyInput_Changed"/>
|
||||
<CheckBox x:Name="ConsiderAutoInput" IsChecked="{Binding ConsiderAuto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}"
|
||||
Content="Automatische Nachzeichnungen der GA"
|
||||
Content="(Automatische) Nachzeichnungen von GA"
|
||||
Margin="110,155,10,10" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||
Checked="ConsiderAutoInput_Changed" Unchecked="ConsiderAutoInput_Changed"/>
|
||||
<CheckBox x:Name="ConsiderCustomInput" IsChecked="{Binding ConsiderCustom, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding IsEnabled}"
|
||||
|
||||
@@ -13,7 +13,7 @@ About
|
||||
**Product:** Elwig
|
||||
**Description:** Electronic Management for Vintners' Cooperatives
|
||||
**Type:** ERP system
|
||||
**Version:** 1.0.5.6 ([Changelog](./CHANGELOG.md))
|
||||
**Version:** 1.1.0.0 ([Changelog](./CHANGELOG.md))
|
||||
**License:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
||||
**Website:** https://elwig.at/
|
||||
**Source code:** https://git.necronda.net/winzer/elwig
|
||||
@@ -33,7 +33,7 @@ Packaging: [WiX Toolset](https://www.firegiant.com/wixtoolset/)
|
||||
**Produkt:** Elwig
|
||||
**Beschreibung:** Elektronische Winzergenossenschaftsverwaltung
|
||||
**Typ:** Warenwirtschaftssystem (ERP-System)
|
||||
**Version:** 1.0.5.6 ([Änderungsprotokoll](./CHANGELOG.md))
|
||||
**Version:** 1.1.0.0 ([Änderungsprotokoll](./CHANGELOG.md))
|
||||
**Lizenz:** [GNU General Public License 3.0 (GPLv3)](./LICENSE)
|
||||
**Website:** https://elwig.at/
|
||||
**Quellcode:** https://git.necronda.net/winzer/elwig
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
|
||||
<PackageReference Include="Appium.WebDriver" Version="4.4.5" />
|
||||
<PackageReference Include="NReco.PdfRenderer" Version="1.6.0" />
|
||||
<PackageReference Include="NUnit" Version="4.6.1" />
|
||||
|
||||
Reference in New Issue
Block a user