[#20] MemberAdminWindow: Add MemberBusinessSharesAdminWindow to manage member shares
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Models;
|
||||
using Elwig.Models.Entities;
|
||||
using iText.Kernel.Colors;
|
||||
using iText.Kernel.Pdf;
|
||||
@@ -40,7 +41,7 @@ namespace Elwig.Documents {
|
||||
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.DateString).ThenBy(h => h.HistNr)
|
||||
.OrderBy(h => h.DateNoticeString).ThenBy(h => h.HistNr)
|
||||
.ToListAsync();
|
||||
MemberBuckets = await ctx.GetMemberBuckets(Utils.CurrentYear, Member.MgNr);
|
||||
ActiveAreaCommitments = await Member.ActiveAreaCommitments(ctx)
|
||||
@@ -245,15 +246,16 @@ namespace Elwig.Documents {
|
||||
}
|
||||
|
||||
protected Table NewMemberBusinessSharesTable(IEnumerable<MemberHistory> history) {
|
||||
var tbl = new Table(ColsMM(18, 111, 12, 12, 12), true)
|
||||
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("Datum", rowspan: 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"))
|
||||
@@ -264,26 +266,29 @@ namespace Elwig.Documents {
|
||||
.AddHeaderCell(NewTh("ruhend"));
|
||||
}
|
||||
|
||||
if (!history.Any() || Member.EntryDate <= history.First().Date) {
|
||||
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 == 1 ? h.Shares : 0) - (h.FromMgNr == Member.MgNr && h.FromType == 1 ? h.Shares : 0),
|
||||
s.SharesRed + (h.ToMgNr == Member.MgNr && h.ToType == 2 ? h.Shares : 0) - (h.FromMgNr == Member.MgNr && h.FromType == 2 ? h.Shares : 0),
|
||||
s.SharesWhite + (h.ToMgNr == Member.MgNr && h.ToType == 3 ? h.Shares : 0) - (h.FromMgNr == Member.MgNr && h.FromType == 3 ? h.Shares : 0),
|
||||
s.SharesDormant + (h.ToMgNr == Member.MgNr && h.ToType == 9 ? h.Shares : 0) - (h.FromMgNr == Member.MgNr && h.FromType == 9 ? h.Shares : 0)));
|
||||
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 erfasst", colspan: tw, italic: true))
|
||||
.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().Date.Year - 1}", borderTop: true, colspan: tw, bold: 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));
|
||||
}
|
||||
}
|
||||
@@ -293,62 +298,65 @@ namespace Elwig.Documents {
|
||||
int s = 0, r = 0, w = 0, d = 0;
|
||||
if (row.FromMgNr == Member.MgNr) {
|
||||
switch (row.FromType) {
|
||||
case 1: s -= row.Shares; break;
|
||||
case 2: r -= row.Shares; break;
|
||||
case 3: w -= row.Shares; break;
|
||||
case 9: d -= row.Shares; break;
|
||||
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 1: s += row.Shares; break;
|
||||
case 2: r += row.Shares; break;
|
||||
case 3: w += row.Shares; break;
|
||||
case 9: d += row.Shares; break;
|
||||
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.Date <= Member.EntryDate) {
|
||||
|
||||
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.Date.Year != lastDate?.Year) {
|
||||
if (lastDate != null && row.DateNotice.Year != lastDate?.Year) {
|
||||
tbl.AddCell(NewTd(borderTop: true))
|
||||
.AddCell(NewTd(lastDate?.Year == row.Date.Year - 1 ? $"Lese {lastDate?.Year}" : $"Lese {lastDate?.Year}–{row.Date.Year - 1}", borderTop: true, colspan: tw, bold: 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.Date <= Member.ExitDate) {
|
||||
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);
|
||||
|
||||
var reason = row.Reason;
|
||||
if (reason == "auto") {
|
||||
reason = "Automatische Nachzeichnung";
|
||||
} else if (reason == "transfer") {
|
||||
if (row.ToMgNr == Member.MgNr) {
|
||||
reason = $"Übertragen von {row.FromMember.AdministrativeName} (MgNr. {row.FromMgNr})";
|
||||
} else {
|
||||
reason = $"Übertragen an {row.ToMember.AdministrativeName} (MgNr. {row.ToMgNr})";
|
||||
}
|
||||
}
|
||||
|
||||
tbl.AddCell(NewTd($"{row.Date:dd.MM.yyyy}"))
|
||||
.AddCell(NewTd(reason, colspan: tw))
|
||||
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.Date;
|
||||
lastDate = row.DateNotice;
|
||||
}
|
||||
|
||||
if (Member.ExitDate != null && (!history.Any() || Member.ExitDate > history.Last().Date)) {
|
||||
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) {
|
||||
|
||||
@@ -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 deduct_year = {Year};
|
||||
INSERT INTO member_history (histnr, from_mgnr, from_type, to_mgnr, to_type, date, reason, source, deduct_year, 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', s.year,
|
||||
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 deduct_year = {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>(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
@@ -56,11 +99,27 @@ namespace Elwig.Models.Entities {
|
||||
[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,11 +23,13 @@ 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,
|
||||
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,
|
||||
@@ -45,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, deduct_year, 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, IIF(h.type = 'auto', s.year, NULL), 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);
|
||||
|
||||
@@ -70,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;
|
||||
@@ -247,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;
|
||||
|
||||
@@ -307,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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -205,14 +205,12 @@ namespace Elwig.Windows {
|
||||
if (rA > 0) a.Add((rA, Brushes.DarkRed));
|
||||
if (wA > 0) a.Add((wA, Brushes.DarkGreen));
|
||||
if (a.Count == 0) a.Add((0, null));
|
||||
if (dA > 0) a.Add((dA, 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));
|
||||
if (stat.SharesDormant > 0) b.Add((stat.SharesDormant, null));
|
||||
|
||||
Run[] inlines = [
|
||||
new("Geschäftsanteile: "),
|
||||
@@ -605,8 +603,7 @@ namespace Elwig.Windows {
|
||||
}
|
||||
|
||||
private void BusinessSharesButton_Click(object sender, RoutedEventArgs evt) {
|
||||
// TODO
|
||||
// App.FocusBusinessSharesWindow(ViewModel.SelectedMember!.MgNr);
|
||||
App.FocusMemberBusinessSharesWindow(ViewModel.SelectedMember!.MgNr);
|
||||
}
|
||||
|
||||
private void AreaCommitmentButton_Click(object sender, RoutedEventArgs evt) {
|
||||
@@ -851,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;
|
||||
@@ -859,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;
|
||||
@@ -928,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user