[#20][#80] Elwig: Update member_history and add different types of shares
Test / Run tests (push) Successful in 2m0s
Test / Run tests (push) Successful in 2m0s
This commit is contained in:
@@ -18,6 +18,7 @@ namespace Elwig.Documents {
|
||||
public class BusinessDocument : Document {
|
||||
|
||||
public Member Member;
|
||||
public MemberHistoryPoint MemberHistory;
|
||||
public string? Location;
|
||||
public bool IncludeSender = false;
|
||||
public bool UseBillingAddress = false;
|
||||
@@ -51,6 +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);
|
||||
Location = App.BranchLocation;
|
||||
IncludeSender = includeSender;
|
||||
DateFrom = dateFrom;
|
||||
@@ -263,7 +265,7 @@ namespace Elwig.Documents {
|
||||
}
|
||||
|
||||
protected Table NewBucketTable(
|
||||
Season season, Dictionary<string, MemberBucket> buckets, int deliveredWeight,
|
||||
Season season, Dictionary<string, MemberBucket> buckets, int deliveredWeightRed, int deliveredWeightWhite,
|
||||
bool includeDelivery = true, bool includePayment = false,
|
||||
bool isTiny = false, IEnumerable<string>? filter = null
|
||||
) {
|
||||
@@ -316,9 +318,21 @@ namespace Elwig.Documents {
|
||||
.Where(b => !fbVars.Contains(b.Key))
|
||||
.OrderBy(b => b.Value.Name);
|
||||
|
||||
tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA", isTiny: isTiny));
|
||||
tbl.AddCells(FormatRow(Member.BusinessShares * season.MinKgPerBusinessShare, Member.BusinessShares * season.MaxKgPerBusinessShare,
|
||||
deliveredWeight, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
|
||||
if (MemberHistory.Shares != 0 || (MemberHistory.SharesRed == 0 && MemberHistory.SharesWhite == 0)) {
|
||||
tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA", isTiny: isTiny));
|
||||
tbl.AddCells(FormatRow(MemberHistory.Shares * (season.MinKgPerShare ?? 0), MemberHistory.Shares * (season.MaxKgPerShare ?? 0),
|
||||
deliveredWeightRed + deliveredWeightWhite, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
|
||||
}
|
||||
|
||||
if (MemberHistory.SharesRed != 0 || MemberHistory.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),
|
||||
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),
|
||||
deliveredWeightWhite, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
|
||||
}
|
||||
|
||||
if (fbs.Any()) {
|
||||
tbl.AddCell(NewBucketSubHdr("Flächenbindungen" + (vtr.Any() ? " (inkl. Verträge)" : "") + ":", includePayment ? 8 : 7, isTiny: isTiny));
|
||||
|
||||
@@ -86,19 +86,27 @@ namespace Elwig.Documents {
|
||||
}
|
||||
|
||||
if (ConsiderTotalPenalty) {
|
||||
var total = _data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value);
|
||||
var totalUnderDelivery = total - Member.BusinessShares * season.MinKgPerBusinessShare;
|
||||
MemberTotalUnderDelivery = totalUnderDelivery < 0 ? totalUnderDelivery * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) - (season.PenaltyPerBsAmount * Math.Floor(-(decimal)totalUnderDelivery / season.MinKgPerBusinessShare) ?? 0) : 0;
|
||||
var weights = _data.Rows.Select(r => new {r.Type, Weight = r.Buckets.Sum(b => b.Value)}).GroupBy(r => r.Type).ToDictionary(r => r.Key, g => g.Sum(r => r.Weight));
|
||||
var red = weights.GetValueOrDefault("R", 0);
|
||||
var white = weights.GetValueOrDefault("W", 0);
|
||||
var total = red + white;
|
||||
var underDeliveryTotal = total - Member.Shares * (season.MinKgPerShare ?? 0);
|
||||
var underDeliveryRed = red - Member.SharesRed * (season.MinKgPerShareRed ?? season.MinKgPerShare ?? 0);
|
||||
var underDeliveryWhite = white - Member.SharesWhite * (season.MinKgPerShareWhite ?? season.MinKgPerShare ?? 0);
|
||||
MemberTotalUnderDelivery =
|
||||
(underDeliveryTotal < 0 ? underDeliveryTotal * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) - (season.PenaltyPerShareAmount * Math.Floor(-(decimal)underDeliveryTotal / (season.MinKgPerShare ?? 0)) ?? 0) : 0) +
|
||||
(underDeliveryRed < 0 ? underDeliveryRed * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) - (season.PenaltyPerShareAmount * Math.Floor(-(decimal)underDeliveryRed / (season.MinKgPerShareRed ?? season.MinKgPerShare ?? 0)) ?? 0) : 0) +
|
||||
(underDeliveryWhite < 0 ? underDeliveryWhite * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) - (season.PenaltyPerShareAmount * Math.Floor(-(decimal)underDeliveryWhite / (season.MinKgPerShareWhite ?? season.MinKgPerShare ?? 0)) ?? 0) : 0);
|
||||
if (total == 0)
|
||||
MemberTotalUnderDelivery -= (season.PenaltyNone ?? 0) + (season.PenaltyPerBsNone * Member.BusinessShares ?? 0);
|
||||
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.MgNr == Member.MgNr && h.Type == "auto")
|
||||
.Where(h => h.ToMgNr == Member.MgNr && h.Reason == "auto")
|
||||
.Where(h => h.DateString.CompareTo(fromDate) >= 0 && h.DateString.CompareTo(toDate) <= 0)
|
||||
.SumAsync(h => h.BusinessShares);
|
||||
.SumAsync(h => h.Shares);
|
||||
MemberAutoBusinessSharesAmount = MemberAutoBusinessShares * (-season.BusinessShareValue ?? 0);
|
||||
}
|
||||
if (ConsiderContractPenalties) {
|
||||
|
||||
@@ -18,7 +18,8 @@ namespace Elwig.Documents {
|
||||
|
||||
private readonly int _year;
|
||||
public Season? Season;
|
||||
public int MemberDeliveredWeight;
|
||||
public int MemberDeliveredWeightRed;
|
||||
public int MemberDeliveredWeightWhite;
|
||||
public DeliveryConfirmationDeliveryData? Data;
|
||||
public string? Text = App.Client.TextDeliveryConfirmation;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
||||
@@ -36,10 +37,14 @@ namespace Elwig.Documents {
|
||||
protected override async Task LoadData(AppDbContext ctx) {
|
||||
await base.LoadData(ctx);
|
||||
Season = await ctx.FetchSeasons(_year).SingleOrDefaultAsync() ?? throw new ArgumentException("Invalid season");
|
||||
MemberDeliveredWeight = await ctx.Deliveries
|
||||
var weights = await ctx.Deliveries
|
||||
.Where(d => d.Year == Season.Year && d.MgNr == Member.MgNr)
|
||||
.SelectMany(d => d.Parts)
|
||||
.SumAsync(p => p.Weight);
|
||||
.GroupBy(p => p.Variety.Type)
|
||||
.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);
|
||||
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);
|
||||
@@ -63,7 +68,7 @@ namespace Elwig.Documents {
|
||||
doc.Add(NewDeliveryListTable(Data));
|
||||
doc.Add(NewWeightsTable(MemberStats)
|
||||
.SetMarginTopMM(10).SetKeepTogether(true));
|
||||
doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includePayment: true)
|
||||
doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeightRed, MemberDeliveredWeightWhite, includePayment: true)
|
||||
.SetMarginTopMM(10).SetKeepTogether(true));
|
||||
|
||||
if (Text != null) {
|
||||
|
||||
@@ -19,7 +19,8 @@ namespace Elwig.Documents {
|
||||
|
||||
public Delivery Delivery;
|
||||
public string? Text;
|
||||
public int MemberDeliveredWeight;
|
||||
public int MemberDeliveredWeightRed;
|
||||
public int MemberDeliveredWeightWhite;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
||||
|
||||
// 0 - none
|
||||
@@ -59,9 +60,13 @@ namespace Elwig.Documents {
|
||||
|
||||
protected override async Task LoadData(AppDbContext ctx) {
|
||||
await base.LoadData(ctx);
|
||||
MemberDeliveredWeight = await ctx.DeliveryParts
|
||||
var weights = await ctx.DeliveryParts
|
||||
.Where(d => d.Year == Delivery.Year && d.Delivery.MgNr == Member.MgNr)
|
||||
.SumAsync(p => p.Weight);
|
||||
.GroupBy(p => p.Variety.Type)
|
||||
.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);
|
||||
MemberBuckets = await ctx.GetMemberBuckets(Delivery.Year, Member.MgNr) ?? [];
|
||||
}
|
||||
|
||||
@@ -81,7 +86,7 @@ namespace Elwig.Documents {
|
||||
doc.Add(new KernedParagraph($"Anmerkung zur Lieferung: {Delivery.Comment}", 10).SetMarginsMM(5, 0, 0, 0));
|
||||
}
|
||||
if (DisplayStats > 0) {
|
||||
doc.Add(NewBucketTable(Delivery.Season, MemberBuckets, MemberDeliveredWeight, isTiny: true,
|
||||
doc.Add(NewBucketTable(Delivery.Season, MemberBuckets, MemberDeliveredWeightRed, MemberDeliveredWeightWhite, isTiny: true,
|
||||
filter: DisplayStats > 2 ? null : DisplayStats == 1 ? [] : Delivery.Parts.Select(p => p.SortId).Distinct().ToList())
|
||||
.SetKeepTogether(true)
|
||||
.SetMarginsMM(5, 0, 0, 0));
|
||||
|
||||
@@ -18,7 +18,8 @@ namespace Elwig.Documents {
|
||||
public new static string Name => "Stammdatenblatt";
|
||||
|
||||
public Season? Season;
|
||||
public int MemberDeliveredWeight;
|
||||
public int MemberDeliveredWeightRed;
|
||||
public int MemberDeliveredWeightWhite;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
||||
public List<AreaCom> ActiveAreaCommitments = [];
|
||||
|
||||
@@ -40,17 +41,20 @@ namespace Elwig.Documents {
|
||||
ActiveAreaCommitments = await Member.ActiveAreaCommitments(ctx)
|
||||
.Include(c => c.Contract).ThenInclude(c => c.Revisions)
|
||||
.ToListAsync();
|
||||
MemberDeliveredWeight = await ctx.Deliveries
|
||||
var weights = await ctx.Deliveries
|
||||
.Where(d => d.Year == Season.Year && d.MgNr == Member.MgNr)
|
||||
.SelectMany(d => d.Parts)
|
||||
.SumAsync(p => p.Weight);
|
||||
.GroupBy(p => p.Variety.Type)
|
||||
.ToDictionaryAsync(g => g.Key, g => g.Sum(p => p.Weight));
|
||||
MemberDeliveredWeightRed = weights.GetValueOrDefault("R", 0);
|
||||
MemberDeliveredWeightWhite = weights.GetValueOrDefault("W", 0);
|
||||
}
|
||||
|
||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||
if (Season == null) throw new Exception("Call LoadData before RenderBody");
|
||||
base.RenderBody(doc, pdf);
|
||||
doc.Add(NewMemberData(Season).SetMarginBottomMM(5));
|
||||
doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includeDelivery: false));
|
||||
doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeightRed, MemberDeliveredWeightWhite, includeDelivery: false));
|
||||
if (ActiveAreaCommitments.Count != 0) {
|
||||
bool firstOnPage = false;
|
||||
if (pdf.GetNumberOfPages() == 1) {
|
||||
@@ -132,6 +136,9 @@ namespace Elwig.Documents {
|
||||
.AddCell(NewTd(i < subTbl2.Count ? subTbl2[i][1] : "", colspan: 2));
|
||||
}
|
||||
|
||||
var shares = (Member.Shares != 0 || (Member.SharesRed == 0 && Member.SharesWhite == 0) ? $"{Member.Shares:N0}" : "") +
|
||||
(Member.SharesRed != 0 || Member.SharesWhite != 0 ? (Member.Shares != 0 ? " / " : "") + $"{Member.SharesRed:N0} (rot) / {Member.SharesWhite:N0} (weiß)" : "") +
|
||||
(Member.SharesDormant != 0 ? $" / {Member.SharesDormant:N0} (ruhend)" : "");
|
||||
tbl.AddCell(NewDataHdr("Betrieb", colspan: 6))
|
||||
.AddCell(NewDataTh("Betriebs-Nr.:")).AddCell(NewTd(Member.LfbisNr))
|
||||
.AddCell(NewDataTh("UID:", colspan: 2)).AddCell(NewTd(Member.UstIdNr, colspan: 2))
|
||||
@@ -143,7 +150,7 @@ namespace Elwig.Documents {
|
||||
.AddCell(NewDataHdr("Genossenschaft", colspan: 6))
|
||||
.AddCell(NewDataTh("Status:")).AddCell(NewTd(new KernedParagraph(Member.IsActive ? "Aktiv " : "Nicht aktiv ", 10)
|
||||
.Add(Normal("(" + (Member.ExitDate != null ? $"{Member.EntryDate:dd.MM.yyyy}\u2013{Member.ExitDate:dd.MM.yyyy}" : $"seit {Member.EntryDate:dd.MM.yyyy}") + ")", 8))))
|
||||
.AddCell(NewDataTh("Geschäftsanteile:", colspan: 2)).AddCell(NewTd($"{Member.BusinessShares:N0}", colspan: 2))
|
||||
.AddCell(NewDataTh("Geschäftsanteile:", colspan: 2)).AddCell(NewTd(shares, colspan: 2))
|
||||
.AddCell(NewDataTh("Stamm-Zweigstelle:")).AddCell(NewTd(Member.Branch?.Name))
|
||||
.AddCell(NewDataTh("Volllieferant:", colspan: 2)).AddCell(NewTd(Member.IsVollLieferant ? "Ja" : "Nein", colspan: 2))
|
||||
.AddCell(NewDataTh("Zusendungen per\u2026")).AddCell(NewTd(new KernedParagraph(10)
|
||||
|
||||
@@ -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.BusinessShares:N0}", 8, right: true).SetPaddingLeft(0).SetPaddingRight(0))
|
||||
.AddCell(NewTd($"{m.SharesTotal:N0}", 8, right: true).SetPaddingLeft(0).SetPaddingRight(0))
|
||||
.AddCell(NewTd(m.DefaultKg ?? "", 6));
|
||||
if (AreaComFilters.Length > 0) {
|
||||
foreach (var v in AreaComFilters) {
|
||||
|
||||
@@ -14,6 +14,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Helpers {
|
||||
|
||||
public record struct MemberHistoryPoint(int Shares, int SharesRed, int SharesWhite, int SharesDormant);
|
||||
public record struct AreaComBucket(int Area, int Obligation, int Right);
|
||||
public record struct UnderDelivery(int Weight, int Diff);
|
||||
public record struct MemberBucket(string Name, int Area, int Obligation, int Right, int Delivery, int DeliveryStrict, int DeliveryTotal, int Payment);
|
||||
@@ -146,6 +147,7 @@ namespace Elwig.Helpers {
|
||||
.Include(s => s.Modifiers)
|
||||
.OrderByDescending(s => s.Year));
|
||||
|
||||
private readonly Dictionary<int, Dictionary<int, MemberHistoryPoint>> _memberHistory = [];
|
||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, AreaComBucket>>> _memberAreaCommitmentBuckets = [];
|
||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBuckets = [];
|
||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBucketsStrict = [];
|
||||
@@ -230,6 +232,9 @@ namespace Elwig.Helpers {
|
||||
modelBuilder.Entity<DeliveryAncmt>().Navigation(a => a.Schedule).AutoInclude();
|
||||
modelBuilder.Entity<DeliveryAncmt>().Navigation(a => a.Variety).AutoInclude();
|
||||
modelBuilder.Entity<DeliverySchedule>().Navigation(s => s.Branch).AutoInclude();
|
||||
modelBuilder.Entity<MemberHistory>().Navigation(s => s.FromMember).AutoInclude();
|
||||
modelBuilder.Entity<MemberHistory>().Navigation(s => s.ToMember).AutoInclude();
|
||||
modelBuilder.Entity<MemberHistory>().Navigation(s => s.Currency).AutoInclude();
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
@@ -397,6 +402,22 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
}
|
||||
|
||||
private async Task FetchMemberHistory(int year, SqliteConnection? cnx = null) {
|
||||
var ownCnx = cnx == null;
|
||||
cnx ??= await ConnectAsync();
|
||||
var history = new Dictionary<int, MemberHistoryPoint>();
|
||||
using (var cmd = cnx.CreateCommand()) {
|
||||
cmd.CommandText = $"SELECT mgnr, shares, shares_red, shares_white, shares_dormant FROM v_member_history WHERE year = {year}";
|
||||
using var reader = await cmd.ExecuteReaderAsync();
|
||||
while (await reader.ReadAsync()) {
|
||||
var mgnr = reader.GetInt32(0);
|
||||
history[mgnr] = new(reader.GetInt32(1), reader.GetInt32(2), reader.GetInt32(3), reader.GetInt32(4));
|
||||
}
|
||||
}
|
||||
if (ownCnx) await cnx.DisposeAsync();
|
||||
_memberHistory[year] = history;
|
||||
}
|
||||
|
||||
private async Task FetchMemberAreaCommitmentBuckets(int year, SqliteConnection? cnx = null) {
|
||||
var ownCnx = cnx == null;
|
||||
cnx ??= await ConnectAsync();
|
||||
@@ -487,6 +508,12 @@ namespace Elwig.Helpers {
|
||||
_memberUnderDelivery[year] = buckets;
|
||||
}
|
||||
|
||||
public async Task<MemberHistoryPoint> GetMemberHistory(int year, int mgnr, SqliteConnection? cnx = null) {
|
||||
if (!_memberHistory.ContainsKey(year))
|
||||
await FetchMemberHistory(year, cnx);
|
||||
return _memberHistory[year].GetValueOrDefault(mgnr, new());
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, AreaComBucket>> GetMemberAreaCommitmentBuckets(int year, int mgnr, SqliteConnection? cnx = null) {
|
||||
if (!_memberAreaCommitmentBuckets.ContainsKey(year))
|
||||
await FetchMemberAreaCommitmentBuckets(year, cnx);
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Elwig.Helpers {
|
||||
public static class AppDbUpdater {
|
||||
|
||||
// Don't forget to update value in Tests/fetch-resources.bat!
|
||||
public static readonly int RequiredSchemaVersion = 39;
|
||||
public static readonly int RequiredSchemaVersion = 40;
|
||||
|
||||
private static int VersionOffset = 0;
|
||||
|
||||
|
||||
@@ -50,45 +50,29 @@ namespace Elwig.Helpers.Billing {
|
||||
""");
|
||||
}
|
||||
|
||||
public async Task AutoAdjustBusinessShares(DateOnly date, int allowanceKg = 0, double allowanceBs = 0, int allowanceKgPerBs = 0, double allowanceRel = 0, int addMinBs = 1) {
|
||||
if (addMinBs < 1) addMinBs = 1;
|
||||
public async Task AutoAdjustBusinessShares(DateOnly date, int allowanceKg = 0, double allowanceShares = 0, int allowanceKgPerShare = 0, double allowanceRel = 0, int addMinShares = 1) {
|
||||
if (addMinShares < 1) addMinShares = 1;
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
await cnx.ExecuteBatch($"""
|
||||
UPDATE member
|
||||
SET business_shares = member.business_shares - h.business_shares
|
||||
FROM member_history h
|
||||
WHERE h.date = '{Year}-11-30' AND h.type = 'auto' AND h.mgnr = member.mgnr AND member.active;
|
||||
|
||||
INSERT INTO member_history (mgnr, date, type, business_shares)
|
||||
SELECT u.mgnr,
|
||||
'{date:yyyy-MM-dd}',
|
||||
'auto',
|
||||
CEIL((u.diff - {allowanceKg}.0 - {allowanceKgPerBs}.0 * u.business_shares) / s.max_kg_per_bs
|
||||
- {allowanceBs.ToString(CultureInfo.InvariantCulture)}
|
||||
- {allowanceRel.ToString(CultureInfo.InvariantCulture)} * u.business_shares) AS bs
|
||||
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)
|
||||
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',
|
||||
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
|
||||
FROM v_total_under_delivery u
|
||||
JOIN season s ON s.year = u.year
|
||||
JOIN member m ON m.mgnr = u.mgnr
|
||||
WHERE s.year = {Year} AND bs >= {addMinBs} AND m.active
|
||||
ON CONFLICT DO UPDATE
|
||||
SET business_shares = excluded.business_shares;
|
||||
|
||||
UPDATE member
|
||||
SET business_shares = member.business_shares + h.business_shares
|
||||
FROM member_history h
|
||||
WHERE h.date = '{Year}-11-30' AND h.type = 'auto' AND h.mgnr = member.mgnr;
|
||||
WHERE s.year = {Year} AND adjust_shares >= {addMinShares} AND m.active
|
||||
""");
|
||||
}
|
||||
|
||||
public async Task UnAdjustBusinessShares() {
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
await cnx.ExecuteBatch($"""
|
||||
UPDATE member
|
||||
SET business_shares = member.business_shares - h.business_shares
|
||||
FROM member_history h
|
||||
WHERE h.date = '{Year}-11-30' AND h.type = 'auto' AND h.mgnr = member.mgnr AND member.active;
|
||||
|
||||
DELETE FROM member_history WHERE date = '{Year}-11-30' AND type = 'auto';
|
||||
DELETE FROM member_history WHERE source = 'elwig' AND reason = 'auto' AND SUBSTR(date, 1, 4) = '{Year}';
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Elwig.Helpers.Billing {
|
||||
IIF(m.buchführend, s.vat_normal, s.vat_flatrate) AS vat,
|
||||
ROUND(IIF({Data.ConsiderTotalPenalty}, COALESCE(b.total_penalty, 0), 0) / POW(10, s.precision - 2)) +
|
||||
ROUND(IIF({Data.ConsiderContractPenalties}, COALESCE(u.total_penalty, 0), 0) / POW(10, 4 - 2)) +
|
||||
ROUND(IIF({Data.ConsiderAutoBusinessShares}, -COALESCE(a.total_amount, 0), 0) / POW(10, s.precision - 2)) +
|
||||
ROUND(IIF({Data.ConsiderAutoBusinessShares}, -COALESCE(a.total_amount, 0), 0)) +
|
||||
IIF({Data.ConsiderCustomModifiers}, COALESCE(x.amount, 0), 0)
|
||||
AS modifiers,
|
||||
IIF(lc.amount < 0, 0, lc.modifiers) AS prev_modifiers
|
||||
@@ -137,11 +137,11 @@ namespace Elwig.Helpers.Billing {
|
||||
await cnx.ExecuteBatch($"""
|
||||
INSERT INTO payment_member (year, avnr, mgnr, net_amount, mod_abs, mod_rel)
|
||||
SELECT c.year, {AvNr}, s.mgnr, 0,
|
||||
ROUND(s.sum * COALESCE(m.abs, 0)),
|
||||
ROUND(s.weight_total * COALESCE(m.abs, 0)),
|
||||
COALESCE(m.rel, 0)
|
||||
FROM (SELECT {Year} AS year, m.mgnr,
|
||||
ROUND(AVG(COALESCE(a.sum, b.sum)) * {multiplier}) AS baseline,
|
||||
COUNT(*) = {lastYears} AND MIN(COALESCE(a.sum, b.sum)) > 0 AS allowed
|
||||
ROUND(AVG(COALESCE(a.weight_total, b.weight_total)) * {multiplier}) AS baseline,
|
||||
COUNT(*) = {lastYears} AND MIN(COALESCE(a.weight_total, b.weight_total)) > 0 AS allowed
|
||||
FROM member m
|
||||
LEFT JOIN v_stat_member a ON a.mgnr = m.mgnr
|
||||
FULL OUTER JOIN v_stat_member b ON b.mgnr = m.predecessor_mgnr AND b.year = a.year AND {(includePredecessor ? "TRUE" : "FALSE")}
|
||||
@@ -150,7 +150,7 @@ namespace Elwig.Helpers.Billing {
|
||||
HAVING allowed) c
|
||||
JOIN v_stat_member s ON (s.year, s.mgnr) = (c.year, c.mgnr)
|
||||
LEFT JOIN modifier m ON m.year = c.year AND m.name LIKE '{modName}'
|
||||
WHERE sum >= baseline
|
||||
WHERE weight_total >= baseline
|
||||
ON CONFLICT DO UPDATE
|
||||
SET mod_abs = mod_abs + excluded.mod_abs,
|
||||
mod_rel = mod_rel + excluded.mod_rel
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Elwig.Helpers {
|
||||
public int ExportEbicsVersion;
|
||||
public int ExportEbicsAddress;
|
||||
|
||||
public (int? AllowanceKg, double? AllowanceBs, int? AllowanceKgPerBs, double? AllowancePercent, int? MinBs) AutoAdjustBs;
|
||||
public (int? AllowanceKg, double? AllowanceShares, int? AllowanceKgPerShare, double? AllowancePercent, int? MinShares) AutoAdjustShares;
|
||||
|
||||
public ClientParameters(AppDbContext ctx) : this(ctx.ClientParameters.ToDictionary(e => e.Param, e => e.Value)) { }
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace Elwig.Helpers {
|
||||
}
|
||||
|
||||
var autoAdjust = (parameters.GetValueOrDefault("AUTOADJUST_BUSINESSSHARES") ?? "").Split(';');
|
||||
AutoAdjustBs = autoAdjust.Length == 5 ? (
|
||||
AutoAdjustShares = autoAdjust.Length == 5 ? (
|
||||
int.TryParse(autoAdjust[0], out var v1) ? v1 : null,
|
||||
double.TryParse(autoAdjust[1], out var v2) ? v2 : null,
|
||||
int.TryParse(autoAdjust[2], out var v3) ? v3 : null,
|
||||
@@ -235,9 +235,9 @@ namespace Elwig.Helpers {
|
||||
case 1: exportEbicsAddress = "LINES"; break;
|
||||
case 2: exportEbicsAddress = "FULL"; break;
|
||||
}
|
||||
string autoAdjust = $"{AutoAdjustBs.AllowanceKg};{AutoAdjustBs.AllowanceBs?.ToString(CultureInfo.InvariantCulture)};" +
|
||||
$"{AutoAdjustBs.AllowanceKgPerBs};{AutoAdjustBs.AllowancePercent?.ToString(CultureInfo.InvariantCulture)};" +
|
||||
$"{AutoAdjustBs.MinBs}";
|
||||
string autoAdjust = $"{AutoAdjustShares.AllowanceKg};{AutoAdjustShares.AllowanceShares?.ToString(CultureInfo.InvariantCulture)};" +
|
||||
$"{AutoAdjustShares.AllowanceKgPerShare};{AutoAdjustShares.AllowancePercent?.ToString(CultureInfo.InvariantCulture)};" +
|
||||
$"{AutoAdjustShares.MinShares}";
|
||||
return [
|
||||
("CLIENT_NAME_TOKEN", NameToken),
|
||||
("CLIENT_NAME_SHORT", NameShort),
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace Elwig.Helpers.Export {
|
||||
List<BillingAddr> BillingAddresses,
|
||||
List<MemberTelNr> TelephoneNumbers,
|
||||
List<MemberEmailAddr> EmailAddresses,
|
||||
List<MemberHistory> MemberHistory,
|
||||
List<AreaCom> AreaCommitments,
|
||||
List<AreaComContract> Contracts,
|
||||
List<WbRd> Riede,
|
||||
@@ -76,7 +77,7 @@ namespace Elwig.Helpers.Export {
|
||||
|
||||
foreach (var filename in filenames) {
|
||||
try {
|
||||
data.Add(new([], [], [], [], [], [], [], new([], [], [], [], [], new() {
|
||||
data.Add(new([], [], [], [], [], [], [], new([], [], [], [], [], [], new() {
|
||||
["member"] = [],
|
||||
["area_commitment_contract"] = [],
|
||||
["area_commitment"] = [],
|
||||
@@ -142,6 +143,17 @@ namespace Elwig.Helpers.Export {
|
||||
}
|
||||
}
|
||||
|
||||
var historyJson = zip.GetEntry("member_history.json");
|
||||
if (historyJson != null) {
|
||||
using var reader = new StreamReader(historyJson.Open(), Utils.UTF8);
|
||||
string? line;
|
||||
while ((line = await reader.ReadLineAsync()) != null) {
|
||||
var obj = JsonNode.Parse(line)!.AsObject();
|
||||
var h = obj.ToMemberHistory();
|
||||
r.MemberHistory.Add(h);
|
||||
}
|
||||
}
|
||||
|
||||
// legacy area commitments
|
||||
var areaComsJson = zip.GetEntry("area_commitments.json");
|
||||
if (areaComsJson != null) {
|
||||
@@ -222,7 +234,7 @@ namespace Elwig.Helpers.Export {
|
||||
var importedAreaComs = new List<(string FileName, string ZwstId, string Device, int New, int Overwritten, int NotImported, string? Filters)>();
|
||||
var importedDeliveries = new List<(string FileName, string ZwstId, string Device, int New, int Overwritten, int NotImported, string? Filters)>();
|
||||
|
||||
foreach (var ((members, billingAddresses, telephoneNumbers, emailAddresses, areaCommitments, contracts, riede, wbKgs, wbGls, deliveries, deliveryParts, modifiers, timestamps), meta) in data.Zip(metaData)) {
|
||||
foreach (var ((members, billingAddresses, telephoneNumbers, emailAddresses, history, areaCommitments, contracts, riede, wbKgs, wbGls, deliveries, deliveryParts, modifiers, timestamps), meta) in data.Zip(metaData)) {
|
||||
var branch = branches[meta.ZwstId];
|
||||
var device = meta.Device;
|
||||
|
||||
@@ -234,6 +246,12 @@ namespace Elwig.Helpers.Export {
|
||||
.Select(k => k.KgNr)
|
||||
.ToListAsync();
|
||||
|
||||
var histNrs = history.Select(h => h.HistNr).ToList();
|
||||
var duplicateHistNrs = await ctx.MemberHistory
|
||||
.Where(h => histNrs.Contains(h.HistNr))
|
||||
.Select(h => h.HistNr)
|
||||
.ToListAsync();
|
||||
|
||||
var mgnrs = members.Select(m => m.MgNr).ToList();
|
||||
var duplicateMgNrs = await ctx.Members
|
||||
.Where(m => mgnrs.Contains(m.MgNr))
|
||||
@@ -323,6 +341,11 @@ namespace Elwig.Helpers.Export {
|
||||
importedMembers.Add((meta.FileName, meta.ZwstId, meta.Device, n, o, members.Count - n - o, meta.MemberFilters));
|
||||
}
|
||||
|
||||
if (importDuplicateMembers || importNewMembers) {
|
||||
ctx.UpdateRange(history.Where(h => duplicateHistNrs.Contains(h.HistNr)));
|
||||
ctx.AddRange(history.Where(h => !duplicateHistNrs.Contains(h.HistNr)));
|
||||
}
|
||||
|
||||
if (importDuplicateContracts) {
|
||||
ctx.RemoveRange(ctx.AreaCommitments.IgnoreAutoIncludes().Where(c => duplicateFbNrs.Contains(c.FbNr)));
|
||||
ctx.UpdateRange(contracts.Where(c => duplicateFbNrs.Contains(c.FbNr)));
|
||||
@@ -379,7 +402,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'");
|
||||
|
||||
var primaryKeys = new Dictionary<string, string>() {
|
||||
["member"] = "mgnr, 0, 0",
|
||||
@@ -442,16 +467,18 @@ namespace Elwig.Helpers.Export {
|
||||
$"{branch} (Gerät {device}) {(duplicate ? "überschrieben" : "importiert")} werden?", true);
|
||||
}
|
||||
|
||||
public static Task Export(string filename, IEnumerable<Member> members, IEnumerable<WbKg> wbKgs, IEnumerable<string> filters) {
|
||||
public static Task Export(string filename, IEnumerable<Member> members, IEnumerable<MemberHistory> history, IEnumerable<WbKg> wbKgs, IEnumerable<string> filters) {
|
||||
return new ElwigExport {
|
||||
Members = (members, filters),
|
||||
History = (history, ["von exportierten Mitgliedern"]),
|
||||
WbKgs = (wbKgs, ["von exportierten Mitgliedern"]),
|
||||
}.Export(filename);
|
||||
}
|
||||
|
||||
public static Task Export(string filename, IEnumerable<Member> members, IEnumerable<AreaComContract> areaComs, IEnumerable<WbKg> wbKgs, IEnumerable<string> filters) {
|
||||
public static Task Export(string filename, IEnumerable<Member> members, IEnumerable<MemberHistory> history, IEnumerable<AreaComContract> areaComs, IEnumerable<WbKg> wbKgs, IEnumerable<string> filters) {
|
||||
return new ElwigExport {
|
||||
Members = (members, filters),
|
||||
History = (history, ["von exportierten Mitgliedern"]),
|
||||
AreaComs = (areaComs, ["von exportierten Mitgliedern"]),
|
||||
WbKgs = (wbKgs, ["von exportierten Mitgliedern und Flächenbindungen"]),
|
||||
}.Export(filename);
|
||||
@@ -467,6 +494,7 @@ namespace Elwig.Helpers.Export {
|
||||
public class ElwigExport {
|
||||
public (IEnumerable<WbKg> WbKgs, IEnumerable<string> Filters)? WbKgs { get; set; }
|
||||
public (IEnumerable<Member> Members, IEnumerable<string> Filters)? Members { get; set; }
|
||||
public (IEnumerable<MemberHistory> History, IEnumerable<string> Filters)? History { get; set; }
|
||||
public (IEnumerable<AreaComContract> AreaComs, IEnumerable<string> Filters)? AreaComs { get; set; }
|
||||
public (IEnumerable<Delivery> Deliveries, IEnumerable<string> Filters)? Deliveries { get; set; }
|
||||
|
||||
@@ -486,17 +514,21 @@ namespace Elwig.Helpers.Export {
|
||||
["zwstid"] = App.ZwstId,
|
||||
["device"] = Environment.MachineName,
|
||||
};
|
||||
if (WbKgs != null) {
|
||||
if (WbKgs != null)
|
||||
obj["wb_kgs"] = new JsonObject {
|
||||
["count"] = WbKgs.Value.WbKgs.Count(),
|
||||
["filters"] = new JsonArray(WbKgs.Value.Filters.Select(f => (JsonNode)f).ToArray()),
|
||||
};
|
||||
}
|
||||
if (Members != null)
|
||||
obj["members"] = new JsonObject {
|
||||
["count"] = Members.Value.Members.Count(),
|
||||
["filters"] = new JsonArray(Members.Value.Filters.Select(f => (JsonNode)f).ToArray()),
|
||||
};
|
||||
if (History != null)
|
||||
obj["member_history"] = new JsonObject {
|
||||
["count"] = History.Value.History.Count(),
|
||||
["filters"] = new JsonArray(History.Value.Filters.Select(f => (JsonNode)f).ToArray()),
|
||||
};
|
||||
if (AreaComs != null)
|
||||
obj["area_commitment_contracts"] = new JsonObject {
|
||||
["count"] = AreaComs.Value.AreaComs.Count(),
|
||||
@@ -527,6 +559,13 @@ namespace Elwig.Helpers.Export {
|
||||
await writer.WriteLineAsync(m.ToJson().ToJsonString(Utils.JsonOpts));
|
||||
}
|
||||
}
|
||||
if (History != null) {
|
||||
var json = zip.CreateEntry("member_history.json", CompressionLevel.SmallestSize);
|
||||
using var writer = new StreamWriter(json.Open(), Utils.UTF8);
|
||||
foreach (var h in History.Value.History) {
|
||||
await writer.WriteLineAsync(h.ToJson().ToJsonString(Utils.JsonOpts));
|
||||
}
|
||||
}
|
||||
if (AreaComs != null) {
|
||||
var json = zip.CreateEntry("area_commitment_contracts.json", CompressionLevel.SmallestSize);
|
||||
using var writer = new StreamWriter(json.Open(), Utils.UTF8);
|
||||
@@ -585,7 +624,10 @@ namespace Elwig.Helpers.Export {
|
||||
["birthday"] = m.Birthday,
|
||||
["entry_date"] = m.EntryDate != null ? $"{m.EntryDate:yyyy-MM-dd}" : null,
|
||||
["exit_date"] = m.ExitDate != null ? $"{m.ExitDate:yyyy-MM-dd}" : null,
|
||||
["business_shares"] = m.BusinessShares,
|
||||
["shares"] = m.Shares,
|
||||
["shares_red"] = m.SharesRed,
|
||||
["shares_white"] = m.SharesWhite,
|
||||
["shares_dormant"] = m.SharesDormant,
|
||||
["accounting_nr"] = m.AccountingNr,
|
||||
["zwstid"] = m.ZwstId,
|
||||
["lfbis_nr"] = m.LfbisNr,
|
||||
@@ -654,7 +696,10 @@ namespace Elwig.Helpers.Export {
|
||||
Birthday = json["birthday"]?.AsValue().GetValue<string>(),
|
||||
EntryDateString = json["entry_date"]?.AsValue().GetValue<string>(),
|
||||
ExitDateString = json["exit_date"]?.AsValue().GetValue<string>(),
|
||||
BusinessShares = json["business_shares"]?.AsValue().GetValue<int>() ?? 0,
|
||||
Shares = json["shares"]?.AsValue().GetValue<int>() ?? json["business_shares"]?.AsValue().GetValue<int>() ?? 0,
|
||||
SharesRed = json["shares_red"]?.AsValue().GetValue<int>() ?? 0,
|
||||
SharesWhite = json["shares_white"]?.AsValue().GetValue<int>() ?? 0,
|
||||
SharesDormant = json["shares_dormant"]?.AsValue().GetValue<int>() ?? 0,
|
||||
AccountingNr = json["accounting_nr"]?.AsValue().GetValue<string>(),
|
||||
ZwstId = json["zwstid"]?.AsValue().GetValue<string>(),
|
||||
LfbisNr = json["lfbis_nr"]?.AsValue().GetValue<string>(),
|
||||
@@ -699,6 +744,40 @@ namespace Elwig.Helpers.Export {
|
||||
DateTime.ParseExact(modifiedAt, "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.None)));
|
||||
}
|
||||
|
||||
public static JsonObject ToJson(this MemberHistory h) {
|
||||
return new JsonObject {
|
||||
["histnr"] = h.HistNr,
|
||||
["from_mgnr"] = h.FromMgNr,
|
||||
["from_type"] = h.FromType,
|
||||
["to_mgnr"] = h.ToMgNr,
|
||||
["to_type"] = h.ToType,
|
||||
["date"] = h.DateString,
|
||||
["reason"] = h.Reason,
|
||||
["source"] = h.Source,
|
||||
["shares"] = h.Shares,
|
||||
["value_per_share"] = h.ValuePerShare,
|
||||
["currency"] = h.CurrencyCode,
|
||||
["comment"] = h.Comment,
|
||||
};
|
||||
}
|
||||
|
||||
public static MemberHistory ToMemberHistory(this JsonNode json) {
|
||||
return new MemberHistory {
|
||||
HistNr = json["histnr"]!.AsValue().GetValue<int>(),
|
||||
FromMgNr = json["from_mgnr"]?.AsValue().GetValue<int>(),
|
||||
FromType = json["from_type"]?.AsValue().GetValue<int>(),
|
||||
ToMgNr = json["to_mgnr"]?.AsValue().GetValue<int>(),
|
||||
ToType = json["to_type"]?.AsValue().GetValue<int>(),
|
||||
DateString = json["date"]!.AsValue().GetValue<string>(),
|
||||
Reason = json["reason"]!.AsValue().GetValue<string>(),
|
||||
Source = json["source"]!.AsValue().GetValue<string>(),
|
||||
Shares = json["shares"]!.AsValue().GetValue<int>(),
|
||||
ValuePerShare = json["value_per_share"]?.AsValue().GetValue<decimal>(),
|
||||
CurrencyCode = json["currency"]?.AsValue().GetValue<string>(),
|
||||
Comment = json["comment"]?.AsValue().GetValue<string>(),
|
||||
};
|
||||
}
|
||||
|
||||
public static JsonObject ToJson(this AreaComContract c) {
|
||||
return new JsonObject {
|
||||
["fbnr"] = c.FbNr,
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Elwig.Models.Dtos {
|
||||
("Gross", "Brutto", "€", 20),
|
||||
("Penalties", "Pönalen FB", "€", 20),
|
||||
("Penalty", "Unterl. GA", "€", 20),
|
||||
("AutoBs", "GA Nachz.", "€", 20),
|
||||
("AutoShares", "GA Nachz.", "€", 20),
|
||||
("Custom", "Weitere", "€", 20),
|
||||
("Others", "Sonstige", "€", 20),
|
||||
("Considered", "Berückstgt.", "€", 20),
|
||||
@@ -56,9 +56,9 @@ namespace Elwig.Models.Dtos {
|
||||
p.plz, o.name AS ort, m.address, 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 bs_penalty,
|
||||
ROUND(u.total_penalty / POW(10, 4 - 2)) AS fb_penalty,
|
||||
ROUND(-a.total_amount / POW(10, s.precision - 2)) AS auto_bs,
|
||||
ROUND(b.total_penalty / POW(10, s.precision - 2)) AS shares_penalty,
|
||||
ROUND(u.total_penalty / POW(10, 4 - 2)) AS ac_penalty,
|
||||
-a.total_amount AS auto_shares,
|
||||
x.amount AS custom_mod
|
||||
FROM credit c
|
||||
LEFT JOIN member m ON m.mgnr = c.mgnr
|
||||
@@ -94,7 +94,7 @@ namespace Elwig.Models.Dtos {
|
||||
public decimal Gross;
|
||||
public decimal? Penalties;
|
||||
public decimal? Penalty;
|
||||
public decimal? AutoBs;
|
||||
public decimal? AutoShares;
|
||||
public decimal? Custom;
|
||||
public decimal? Others;
|
||||
public decimal? Considered;
|
||||
@@ -122,14 +122,14 @@ namespace Elwig.Models.Dtos {
|
||||
}
|
||||
decimal mod = (row.Modifiers == null) ? 0 : Utils.DecFromDb((long)row.Modifiers, prec1);
|
||||
if (data.ConsiderContractPenalties)
|
||||
Penalties = (row.FbPenalty == null) ? null : Utils.DecFromDb((long)row.FbPenalty, prec1);
|
||||
Penalties = (row.AcPenalty == null) ? null : Utils.DecFromDb((long)row.AcPenalty, prec1);
|
||||
if (data.ConsiderTotalPenalty)
|
||||
Penalty = (row.BsPenalty == null) ? null : Utils.DecFromDb((long)row.BsPenalty, prec1);
|
||||
Penalty = (row.SharesPenalty == null) ? null : Utils.DecFromDb((long)row.SharesPenalty, prec1);
|
||||
if (data.ConsiderAutoBusinessShares)
|
||||
AutoBs = (row.AutoBs == null) ? null : Utils.DecFromDb((long)row.AutoBs, prec1);
|
||||
AutoShares = (row.AutoShares == null) ? null : Utils.DecFromDb((long)row.AutoShares, prec1);
|
||||
if (data.ConsiderCustomModifiers)
|
||||
Custom = (row.CustomMod == null) ? null : Utils.DecFromDb((long)row.CustomMod, prec1);
|
||||
mod -= (Penalties ?? 0) + (Penalty ?? 0) + (AutoBs ?? 0) + (Custom ?? 0);
|
||||
mod -= (Penalties ?? 0) + (Penalty ?? 0) + (AutoShares ?? 0) + (Custom ?? 0);
|
||||
Others = (mod == 0) ? null : mod;
|
||||
Gross = Utils.DecFromDb(row.GrossAmount, prec1);
|
||||
Considered = (row.PrevModifiers == null || row.PrevModifiers == 0) ? null : -Utils.DecFromDb((long)row.PrevModifiers, prec1);
|
||||
@@ -179,12 +179,12 @@ namespace Elwig.Models.Dtos {
|
||||
public long? PrevModifiers { get; set; }
|
||||
[Column("amount")]
|
||||
public long Amount { get; set; }
|
||||
[Column("bs_penalty")]
|
||||
public long? BsPenalty { get; set; }
|
||||
[Column("fb_penalty")]
|
||||
public long? FbPenalty { get; set; }
|
||||
[Column("auto_bs")]
|
||||
public long? AutoBs { get; set; }
|
||||
[Column("shares_penalty")]
|
||||
public long? SharesPenalty { get; set; }
|
||||
[Column("ac_penalty")]
|
||||
public long? AcPenalty { get; set; }
|
||||
[Column("auto_shares")]
|
||||
public long? AutoShares { get; set; }
|
||||
[Column("custom_mod")]
|
||||
public long? CustomMod { get; set; }
|
||||
}
|
||||
|
||||
@@ -42,13 +42,10 @@ namespace Elwig.Models.Dtos {
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<CreditNoteDeliveryRowSingle>> FromDbSet(DbSet<CreditNoteDeliveryRowSingle> table, int? year = null, int? avnr = null, int? mgnr = null) {
|
||||
var y = year?.ToString() ?? "NULL";
|
||||
var v = avnr?.ToString() ?? "NULL";
|
||||
var m = mgnr?.ToString() ?? "NULL";
|
||||
return await table.FromSqlRaw($"""
|
||||
return await table.FromSql($"""
|
||||
SELECT d.year, c.tgnr, v.avnr, d.mgnr, d.did, d.lsnr, d.dpnr, d.weight, d.modifiers,
|
||||
b.bktnr, d.sortid, b.discr, b.value, pb.price, pb.amount, p.net_amount, p.amount AS total_amount,
|
||||
s.name AS variety, a.name AS attribute, c.name AS cultivation, q.qualid AS qualid, q.name AS quality_level, d.oe, d.kmw, d.net_weight
|
||||
s.name AS variety, s.type AS type, a.name AS attribute, c.name AS cultivation, q.qualid AS qualid, q.name AS quality_level, d.oe, d.kmw, d.net_weight
|
||||
FROM v_delivery d
|
||||
JOIN wine_variety s ON s.sortid = d.sortid
|
||||
LEFT JOIN wine_attribute a ON a.attrid = d.attrid
|
||||
@@ -59,7 +56,7 @@ namespace Elwig.Models.Dtos {
|
||||
LEFT JOIN payment_delivery_part p ON (p.year, p.did, p.dpnr, p.avnr) = (d.year, d.did, d.dpnr, v.avnr)
|
||||
LEFT JOIN payment_delivery_part_bucket pb ON (pb.year, pb.did, pb.dpnr, pb.bktnr, pb.avnr) = (b.year, b.did, b.dpnr, b.bktnr, v.avnr)
|
||||
LEFT JOIN credit c ON (c.year, c.avnr, c.mgnr) = (d.year, v.avnr, d.mgnr)
|
||||
WHERE b.value > 0 AND (d.year = {y} OR {y} IS NULL) AND (v.avnr = {v} OR {v} IS NULL) AND (d.mgnr = {m} OR {m} IS NULL)
|
||||
WHERE b.value > 0 AND (d.year = {year} OR {year} IS NULL) AND (v.avnr = {avnr} OR {avnr} IS NULL) AND (d.mgnr = {mgnr} OR {mgnr} IS NULL)
|
||||
ORDER BY d.year, v.avnr, d.mgnr, d.lsnr, d.dpnr
|
||||
""").ToListAsync();
|
||||
}
|
||||
@@ -75,6 +72,7 @@ namespace Elwig.Models.Dtos {
|
||||
public string LsNr;
|
||||
public int DPNr;
|
||||
public string Variety;
|
||||
public string Type;
|
||||
public string? Attribute;
|
||||
public string? Cultivation;
|
||||
public string[] Modifiers;
|
||||
@@ -97,24 +95,24 @@ namespace Elwig.Models.Dtos {
|
||||
LsNr = f.LsNr;
|
||||
DPNr = f.DPNr;
|
||||
Variety = f.Variety;
|
||||
Type = f.Type;
|
||||
Attribute = f.Attribute;
|
||||
Cultivation = f.Cultivation;
|
||||
var modifiers = (IEnumerable<Modifier>)(f.Modifiers ?? "").Split(',')
|
||||
.Select(m => season?.Modifiers.FirstOrDefault(s => s.ModId == m))
|
||||
.Where(m => m != null)
|
||||
.OrderBy(m => m.Ordering)
|
||||
.OrderBy(m => m!.Ordering)
|
||||
.ToList();
|
||||
Modifiers = modifiers.Select(m => m.Name).ToArray();
|
||||
Modifiers = [.. modifiers.Select(m => m.Name)];
|
||||
QualId = f.QualId;
|
||||
QualityLevel = f.QualityLevel;
|
||||
Gradation = (f.Oe, f.Kmw);
|
||||
Buckets = rows
|
||||
Buckets = [.. rows
|
||||
.Where(b => b.Value > 0)
|
||||
.OrderByDescending(b => b.BktNr)
|
||||
.Select(b => (b.Discr == "_" ? "ungeb." : $"geb. {f.SortId}{b.Discr}", b.Value,
|
||||
b.Price != null ? season?.DecFromDb((long)b.Price) : null,
|
||||
b.Amount != null ? season?.DecFromDb((long)b.Amount) : null))
|
||||
.ToArray();
|
||||
b.Amount != null ? season?.DecFromDb((long)b.Amount) : null))];
|
||||
WeighingModifier = (varData == null || !varData.ConsiderDelieryModifiers) ? 0 : f.NetWeight ? varData.NetWeightModifier : varData.GrossWeightModifier;
|
||||
Amount = f.TotalAmount != null ? season?.DecFromDb((long)f.TotalAmount) : null;
|
||||
var netAmount = f.NetAmount != null ? season?.DecFromDb((long)f.NetAmount) : null;
|
||||
@@ -161,6 +159,8 @@ namespace Elwig.Models.Dtos {
|
||||
public long? TotalAmount { get; set; }
|
||||
[Column("variety")]
|
||||
public required string Variety { get; set; }
|
||||
[Column("type")]
|
||||
public required string Type { get; set; }
|
||||
[Column("attribute")]
|
||||
public string? Attribute { get; set; }
|
||||
[Column("cultivation")]
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Elwig.Models.Dtos {
|
||||
public class MemberDeliveryData : DataTable<MemberDeliveryRow> {
|
||||
|
||||
private static readonly (string, string, string?, int?)[] FieldNames = [
|
||||
("MgNr", "MgNr.", null, 12),
|
||||
("MgNr", "MgNr.", null, 12),
|
||||
("Name1", "Name", null, 40),
|
||||
("Name2", "Vorname", null, 40),
|
||||
("Address", "Adresse", null, 60),
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Elwig.Models.Dtos {
|
||||
("Locality", "Ort", null, 60),
|
||||
("DefaultKg", "Stammgemeinde", null, 60),
|
||||
("Branch", "Zweigstelle", null, 40),
|
||||
("BusinessShares", "GA", null, 10),
|
||||
("SharesTotal", "GA", null, 10),
|
||||
("BillingName", "Rechnungsname", null, 60),
|
||||
("BillingAddress", "Rechnungsadresse", null, 60),
|
||||
("BillingPlz", "PLZ", null, 10),
|
||||
@@ -66,7 +66,11 @@ namespace Elwig.Models.Dtos {
|
||||
public string? Name2;
|
||||
public string? DefaultKg;
|
||||
public string? Branch;
|
||||
public int BusinessShares;
|
||||
public int Shares;
|
||||
public int SharesRed;
|
||||
public int SharesWhite;
|
||||
public int SharesDormant;
|
||||
public int SharesTotal;
|
||||
public string Address;
|
||||
public int Plz;
|
||||
public string Locality;
|
||||
@@ -98,7 +102,11 @@ namespace Elwig.Models.Dtos {
|
||||
Name2 = m.AdministrativeName2;
|
||||
DefaultKg = m.DefaultKg?.Name;
|
||||
Branch = m.Branch?.Name;
|
||||
BusinessShares = m.BusinessShares;
|
||||
Shares = m.Shares;
|
||||
SharesRed = m.SharesRed;
|
||||
SharesWhite = m.SharesWhite;
|
||||
SharesDormant = m.SharesDormant;
|
||||
SharesTotal = Shares + SharesRed + SharesWhite + SharesDormant;
|
||||
Address = m.Address;
|
||||
Plz = m.PostalDest.AtPlz!.Plz;
|
||||
Locality = m.PostalDest.AtPlz!.Ort.Name;
|
||||
|
||||
@@ -13,33 +13,72 @@ namespace Elwig.Models.Dtos {
|
||||
("Address", "Adresse", null, 60),
|
||||
("Plz", "PLZ", null, 10),
|
||||
("Locality", "Ort", null, 60),
|
||||
("BusinessShares", "GA", null, 10),
|
||||
("Shares", "GA", null, 10),
|
||||
("DeliveryObligation", "Lieferpflicht", "kg", 22),
|
||||
("DeliveryRight", "Lieferrecht", "kg", 22),
|
||||
("Weight", "Geliefert", "kg", 22),
|
||||
("WeightTotal", "Geliefert", "kg", 22),
|
||||
("OverUnderDelivery", "Über-/Unterliefert", "kg|%", 34),
|
||||
];
|
||||
|
||||
private static readonly (string, string, string?, int)[] FieldNamesRed = [
|
||||
("MgNr", "MgNr.", null, 12),
|
||||
("Name1", "Name", null, 40),
|
||||
("Name2", "Vorname", null, 40),
|
||||
("Address", "Adresse", null, 60),
|
||||
("Plz", "PLZ", null, 10),
|
||||
("Locality", "Ort", null, 60),
|
||||
("SharesRed", "GA", null, 10),
|
||||
("DeliveryObligationRed", "Lieferpflicht", "kg", 22),
|
||||
("DeliveryRightRed", "Lieferrecht", "kg", 22),
|
||||
("WeightRed", "Geliefert", "kg", 22),
|
||||
("OverUnderDeliveryRed", "Über-/Unterliefert", "kg|%", 34),
|
||||
];
|
||||
|
||||
private static readonly (string, string, string?, int)[] FieldNamesWhite = [
|
||||
("MgNr", "MgNr.", null, 12),
|
||||
("Name1", "Name", null, 40),
|
||||
("Name2", "Vorname", null, 40),
|
||||
("Address", "Adresse", null, 60),
|
||||
("Plz", "PLZ", null, 10),
|
||||
("Locality", "Ort", null, 60),
|
||||
("SharesWhite", "GA", null, 10),
|
||||
("DeliveryObligationWhite", "Lieferpflicht", "kg", 22),
|
||||
("DeliveryRightWhite", "Lieferrecht", "kg", 22),
|
||||
("WeightWhite", "Geliefert", "kg", 22),
|
||||
("OverUnderDeliveryWhite", "Über-/Unterliefert", "kg|%", 34),
|
||||
];
|
||||
|
||||
public OverUnderDeliveryData(IEnumerable<OverUnderDeliveryRow> rows, int year) :
|
||||
base($"Über-Unterlieferungen", $"Über- und Unterlieferungen laut gezeichneten Geschäftsanteilen {year}", rows, FieldNames) {
|
||||
}
|
||||
|
||||
public OverUnderDeliveryData(IEnumerable<OverUnderDeliveryRow> rows, int year, string mode) :
|
||||
base($"Über-Unterlieferungen", $"Über- und Unterlieferungen laut gezeichneten Geschäftsanteilen {(mode == "R" ? "rot" : "weiß")} {year}", rows,
|
||||
mode == "R" ? FieldNamesRed : FieldNamesWhite) {
|
||||
}
|
||||
|
||||
public static async Task<OverUnderDeliveryData> ForSeason(DbSet<OverUnderDeliveryRow> table, int year) {
|
||||
var rows = await table.FromSql($"""
|
||||
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.business_shares,
|
||||
m.business_shares * s.min_kg_per_bs AS min_kg,
|
||||
m.business_shares * s.max_kg_per_bs AS max_kg,
|
||||
COALESCE(SUM(d.weight), 0) AS sum
|
||||
p.plz, o.name AS ort, m.address, h.shares, h.shares_red, h.shares_white,
|
||||
h.shares * COALESCE(s.min_kg_per_share, 0) AS min_kg,
|
||||
h.shares * COALESCE(s.max_kg_per_share, 0) AS max_kg,
|
||||
h.shares_red * COALESCE(s.min_kg_per_share_red, s.min_kg_per_share, 0) AS min_kg_red,
|
||||
h.shares_red * COALESCE(s.max_kg_per_share_red, s.max_kg_per_share, 0) AS max_kg_red,
|
||||
h.shares_white * COALESCE(s.min_kg_per_share_white, s.min_kg_per_share, 0) AS min_kg_white,
|
||||
h.shares_white * COALESCE(s.max_kg_per_share_white, s.max_kg_per_share, 0) AS max_kg_white,
|
||||
COALESCE(d.weight_total, 0) AS weight_total,
|
||||
COALESCE(d.weight_red, 0) AS weight_red,
|
||||
COALESCE(d.weight_white, 0) AS weight_white
|
||||
FROM season s, member m
|
||||
LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest
|
||||
LEFT JOIN AT_ort o ON o.okz = p.okz
|
||||
LEFT JOIN v_delivery d ON (d.year, d.mgnr) = (s.year, m.mgnr)
|
||||
WHERE s.year = {year} AND (m.active = TRUE OR d.weight > 0)
|
||||
GROUP BY s.year, m.mgnr
|
||||
ORDER BY 100.0 * sum / max_kg, m.mgnr
|
||||
LEFT JOIN v_member_history h ON (h.year, h.mgnr) = (s.year, m.mgnr)
|
||||
LEFT JOIN v_stat_member d ON (d.year, d.mgnr) = (s.year, m.mgnr)
|
||||
WHERE s.year = {year} AND (m.active = TRUE OR d.weight_total > 0)
|
||||
ORDER BY 100.0 * weight_total / (max_kg + max_kg_red + max_kg_white), m.mgnr
|
||||
""").ToListAsync();
|
||||
return new OverUnderDeliveryData(rows, year);
|
||||
}
|
||||
@@ -61,17 +100,41 @@ namespace Elwig.Models.Dtos {
|
||||
public required string LocalityFull { get; set; }
|
||||
[NotMapped]
|
||||
public string Locality => LocalityFull.Split(",")[0];
|
||||
[Column("business_shares")]
|
||||
public int BusinessShares { get; set; }
|
||||
[Column("shares")]
|
||||
public int Shares { get; set; }
|
||||
[Column("shares_red")]
|
||||
public int SharesRed { get; set; }
|
||||
[Column("shares_white")]
|
||||
public int SharesWhite { get; set; }
|
||||
[Column("min_kg")]
|
||||
public int DeliveryObligation { get; set; }
|
||||
[Column("max_kg")]
|
||||
public int DeliveryRight { get; set; }
|
||||
[Column("sum")]
|
||||
public int Weight { get; set; }
|
||||
[NotMapped]
|
||||
public (int? Kg, double? Percent) OverUnderDelivery =>
|
||||
Weight < DeliveryObligation ? (Weight - DeliveryObligation, Weight * 100.0 / DeliveryObligation - 100.0) :
|
||||
Weight > DeliveryRight ? (Weight - DeliveryRight, Weight * 100.0 / DeliveryRight - 100.0) : (null, null);
|
||||
WeightTotal < DeliveryObligation ? (WeightTotal - DeliveryObligation, WeightTotal * 100.0 / DeliveryObligation - 100.0) :
|
||||
WeightTotal > DeliveryRight ? (WeightTotal - DeliveryRight, WeightTotal * 100.0 / DeliveryRight - 100.0) : (null, null);
|
||||
[Column("min_kg_red")]
|
||||
public int DeliveryObligationRed { get; set; }
|
||||
[Column("max_kg_red")]
|
||||
public int DeliveryRightRed { get; set; }
|
||||
[NotMapped]
|
||||
public (int? Kg, double? Percent) OverUnderDeliveryRed =>
|
||||
WeightRed < DeliveryObligationRed ? (WeightRed - DeliveryObligationRed, WeightRed * 100.0 / DeliveryObligationRed - 100.0) :
|
||||
WeightRed > DeliveryRightRed ? (WeightRed - DeliveryRightRed, WeightRed * 100.0 / DeliveryRightRed - 100.0) : (null, null);
|
||||
[Column("min_kg_white")]
|
||||
public int DeliveryObligationWhite { get; set; }
|
||||
[Column("max_kg_white")]
|
||||
public int DeliveryRightWhite { get; set; }
|
||||
[NotMapped]
|
||||
public (int? Kg, double? Percent) OverUnderDeliveryWhite =>
|
||||
WeightWhite < DeliveryObligationWhite ? (WeightWhite - DeliveryObligationWhite, WeightWhite * 100.0 / DeliveryObligationWhite - 100.0) :
|
||||
WeightWhite > DeliveryRightWhite ? (WeightWhite - DeliveryRightWhite, WeightWhite * 100.0 / DeliveryRightWhite - 100.0) : (null, null);
|
||||
[Column("weight_total")]
|
||||
public int WeightTotal { get; set; }
|
||||
[Column("weight_red")]
|
||||
public int WeightRed { get; set; }
|
||||
[Column("weight_white")]
|
||||
public int WeightWhite { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +67,22 @@ namespace Elwig.Models.Entities {
|
||||
set => ExitDateString = value?.ToString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
[Column("business_shares")]
|
||||
public int BusinessShares { get; set; }
|
||||
[Column("shares")]
|
||||
public int Shares { get; set; }
|
||||
|
||||
[Column("shares_red")]
|
||||
public int SharesRed { get; set; }
|
||||
|
||||
[Column("shares_white")]
|
||||
public int SharesWhite { get; set; }
|
||||
|
||||
[Column("shares_dormant")]
|
||||
public int SharesDormant { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public int SharesTotal => Shares + SharesRed + SharesWhite + SharesDormant;
|
||||
[NotMapped]
|
||||
public int SharesActive => Shares + SharesRed + SharesWhite;
|
||||
|
||||
[Column("accounting_nr")]
|
||||
public string? AccountingNr { get; set; }
|
||||
@@ -189,9 +203,14 @@ namespace Elwig.Models.Entities {
|
||||
[InverseProperty(nameof(BillingAddr.Member))]
|
||||
public virtual BillingAddr? BillingAddress { get; private set; }
|
||||
|
||||
[InverseProperty(nameof(Delivery.Member))]
|
||||
[InverseProperty(nameof(DeliveryAncmt.Member))]
|
||||
public virtual ICollection<DeliveryAncmt> Announcements { get; private set; } = null!;
|
||||
|
||||
[InverseProperty(nameof(MemberHistory.FromMember))]
|
||||
public virtual ICollection<MemberHistory> HistoryFrom { get; private set; } = null!;
|
||||
[InverseProperty(nameof(MemberHistory.ToMember))]
|
||||
public virtual ICollection<MemberHistory> HistoryTo { get; private set; } = null!;
|
||||
|
||||
[InverseProperty(nameof(Delivery.Member))]
|
||||
public virtual ICollection<Delivery> Deliveries { get; private set; } = null!;
|
||||
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
using Elwig.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Elwig.Models.Entities {
|
||||
[Table("member_history"), PrimaryKey("MgNr", "DateString", "Type")]
|
||||
[Table("member_history"), PrimaryKey("HistNr")]
|
||||
public class MemberHistory {
|
||||
[Column("mgnr")]
|
||||
public int MgNr { get; set; }
|
||||
[Column("histnr")]
|
||||
public int HistNr { get; set; }
|
||||
|
||||
[Column("from_mgnr")]
|
||||
public int? FromMgNr { get; set; }
|
||||
[Column("from_type")]
|
||||
public int? FromType { get; set; }
|
||||
|
||||
[Column("to_mgnr")]
|
||||
public int? ToMgNr { get; set; }
|
||||
[Column("to_type")]
|
||||
public int? ToType { get; set; }
|
||||
|
||||
[Column("date")]
|
||||
public required string DateString { get; set; }
|
||||
@@ -16,16 +27,39 @@ namespace Elwig.Models.Entities {
|
||||
set => value.ToString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
[Column("type")]
|
||||
public required string Type { get; set; }
|
||||
[Column("reason")]
|
||||
public required string Reason { get; set; }
|
||||
|
||||
[Column("business_shares")]
|
||||
public int BusinessShares { get; set; }
|
||||
[Column("source")]
|
||||
public required string Source { get; set; }
|
||||
|
||||
[Column("shares")]
|
||||
public int Shares { get; set; }
|
||||
|
||||
[Column("value_per_share")]
|
||||
public long? ValuePerShareValue { get; set; }
|
||||
[NotMapped]
|
||||
public decimal? ValuePerShare {
|
||||
get => ValuePerShareValue != null ? Utils.DecFromDb(ValuePerShareValue.Value, 2) : null;
|
||||
set => ValuePerShareValue = value != null ? Utils.DecToDb(value.Value, 2) : null;
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public decimal? TotalValue => Shares * ValuePerShare;
|
||||
|
||||
[Column("currency")]
|
||||
public string? CurrencyCode { get; set; }
|
||||
|
||||
[Column("comment")]
|
||||
public string? Comment { get; set; }
|
||||
|
||||
[ForeignKey("MgNr")]
|
||||
public virtual Member Member { get; private set; } = null!;
|
||||
[ForeignKey("FromMgNr")]
|
||||
public virtual Member FromMember { get; private set; } = null!;
|
||||
|
||||
[ForeignKey("ToMgNr")]
|
||||
public virtual Member ToMember { get; private set; } = null!;
|
||||
|
||||
[ForeignKey("CurrencyCode")]
|
||||
public virtual Currency Currency { get; private set; } = null!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,20 @@ namespace Elwig.Models.Entities {
|
||||
[Column("vat_flatrate")]
|
||||
public double VatFlatrate { get; set; }
|
||||
|
||||
[Column("min_kg_per_bs")]
|
||||
public int MinKgPerBusinessShare { get; set; }
|
||||
[Column("min_kg_per_share")]
|
||||
public int? MinKgPerShare { get; set; }
|
||||
[Column("max_kg_per_share")]
|
||||
public int? MaxKgPerShare { get; set; }
|
||||
|
||||
[Column("max_kg_per_bs")]
|
||||
public int MaxKgPerBusinessShare { get; set; }
|
||||
[Column("min_kg_per_share_red")]
|
||||
public int? MinKgPerShareRed { get; set; }
|
||||
[Column("max_kg_per_share_red")]
|
||||
public int? MaxKgPerShareRed { get; set; }
|
||||
|
||||
[Column("min_kg_per_share_white")]
|
||||
public int? MinKgPerShareWhite { get; set; }
|
||||
[Column("max_kg_per_share_white")]
|
||||
public int? MaxKgPerShareWhite { get; set; }
|
||||
|
||||
[Column("penalty_per_kg")]
|
||||
public long? PenaltyPerKgValue { get; set; }
|
||||
@@ -55,23 +64,23 @@ namespace Elwig.Models.Entities {
|
||||
set => PenaltyNoneValue = value != null ? DecToDb(value.Value) : null;
|
||||
}
|
||||
|
||||
[Column("penalty_per_bs_amount")]
|
||||
public long? PenaltyPerBsAmountValue { get; set; }
|
||||
[Column("penalty_per_share_amount")]
|
||||
public long? PenaltyPerShareAmountValue { get; set; }
|
||||
[NotMapped]
|
||||
public decimal? PenaltyPerBsAmount {
|
||||
get => PenaltyPerBsAmountValue != null ? DecFromDb(PenaltyPerBsAmountValue.Value) : null;
|
||||
set => PenaltyPerBsAmountValue = value != null ? DecToDb(value.Value) : null;
|
||||
public decimal? PenaltyPerShareAmount {
|
||||
get => PenaltyPerShareAmountValue != null ? DecFromDb(PenaltyPerShareAmountValue.Value) : null;
|
||||
set => PenaltyPerShareAmountValue = value != null ? DecToDb(value.Value) : null;
|
||||
}
|
||||
|
||||
[Column("penalty_per_bs_none")]
|
||||
public long? PenaltyPerBsNoneValue { get; set; }
|
||||
[Column("penalty_per_share_none")]
|
||||
public long? PenaltyPerShareNoneValue { get; set; }
|
||||
[NotMapped]
|
||||
public decimal? PenaltyPerBsNone {
|
||||
get => PenaltyPerBsNoneValue != null ? DecFromDb(PenaltyPerBsNoneValue.Value) : null;
|
||||
set => PenaltyPerBsNoneValue = value != null ? DecToDb(value.Value) : null;
|
||||
public decimal? PenaltyPerShareNone {
|
||||
get => PenaltyPerShareNoneValue != null ? DecFromDb(PenaltyPerShareNoneValue.Value) : null;
|
||||
set => PenaltyPerShareNoneValue = value != null ? DecToDb(value.Value) : null;
|
||||
}
|
||||
|
||||
[Column("bs_value")]
|
||||
[Column("share_value")]
|
||||
public long? BusinessShareValueValue { get; set; }
|
||||
[NotMapped]
|
||||
public decimal? BusinessShareValue {
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
-- schema version 39 to 40
|
||||
|
||||
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;
|
||||
|
||||
UPDATE client_parameter SET value = '0' WHERE param = 'ENABLE_TIME_TRIGGERS';
|
||||
UPDATE member
|
||||
SET shares_dormant = shares + shares_red + shares_white,
|
||||
shares = 0, shares_red = 0, shares_white = 0
|
||||
WHERE NOT active;
|
||||
UPDATE client_parameter SET value = '1' WHERE param = 'ENABLE_TIME_TRIGGERS';
|
||||
|
||||
CREATE TABLE member_history_new (
|
||||
histnr INTEGER NOT NULL,
|
||||
from_mgnr INTEGER,
|
||||
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_]+$'),
|
||||
|
||||
shares INTEGER NOT NULL,
|
||||
value_per_share INTEGER DEFAULT NULL,
|
||||
currency TEXT DEFAULT NULL,
|
||||
comment TEXT DEFAULT NULL,
|
||||
|
||||
CONSTRAINT pk_member_history PRIMARY KEY (histnr),
|
||||
CONSTRAINT fk_member_history_member_from FOREIGN KEY (from_mgnr) REFERENCES member (mgnr)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE RESTRICT,
|
||||
CONSTRAINT fk_member_history_member_to FOREIGN KEY (to_mgnr) REFERENCES member (mgnr)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE RESTRICT,
|
||||
CONSTRAINT fk_member_history_currency FOREIGN KEY (currency) REFERENCES currency (code)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE RESTRICT,
|
||||
CONSTRAINT c_member_history CHECK ((from_mgnr IS NOT NULL OR to_mgnr IS NOT NULL) AND
|
||||
((from_mgnr IS NULL AND from_type IS NULL) OR (from_mgnr IS NOT NULL AND from_type IS NOT NULL)) AND
|
||||
((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
|
||||
FROM member_history h
|
||||
JOIN season s ON s.year = SUBSTR(h.date, 1, 4);
|
||||
|
||||
PRAGMA foreign_keys = OFF;
|
||||
DROP TABLE member_history;
|
||||
ALTER TABLE member_history_new RENAME TO member_history;
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TRIGGER t_member_history_i_member
|
||||
AFTER INSERT 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 - NEW.shares WHERE mgnr = NEW.from_mgnr AND NEW.from_type = 1;
|
||||
UPDATE member SET shares_red = shares_red - NEW.shares WHERE mgnr = NEW.from_mgnr AND NEW.from_type = 2;
|
||||
UPDATE member SET shares_white = shares_white - NEW.shares WHERE mgnr = NEW.from_mgnr AND NEW.from_type = 3;
|
||||
UPDATE member SET shares_dormant = shares_dormant - NEW.shares WHERE mgnr = NEW.from_mgnr AND NEW.from_type = 9;
|
||||
UPDATE member SET shares = shares + NEW.shares WHERE mgnr = NEW.to_mgnr AND NEW.to_type = 1;
|
||||
UPDATE member SET shares_red = shares_red + NEW.shares WHERE mgnr = NEW.to_mgnr AND NEW.to_type = 2;
|
||||
UPDATE member SET shares_white = shares_white + NEW.shares WHERE mgnr = NEW.to_mgnr AND NEW.to_type = 3;
|
||||
UPDATE member SET shares_dormant = shares_dormant + NEW.shares WHERE mgnr = NEW.to_mgnr AND NEW.to_type = 9;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t_member_history_u_member
|
||||
AFTER UPDATE 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;
|
||||
UPDATE member SET shares_red = shares_red + OLD.shares WHERE mgnr = OLD.from_mgnr AND OLD.from_type = 2;
|
||||
UPDATE member SET shares_white = shares_white + OLD.shares WHERE mgnr = OLD.from_mgnr AND OLD.from_type = 3;
|
||||
UPDATE member SET shares_dormant = shares_dormant + OLD.shares WHERE mgnr = OLD.from_mgnr AND OLD.from_type = 9;
|
||||
UPDATE member SET shares = shares - OLD.shares WHERE mgnr = OLD.to_mgnr AND OLD.to_type = 1;
|
||||
UPDATE member SET shares_red = shares_red - OLD.shares WHERE mgnr = OLD.to_mgnr AND OLD.to_type = 2;
|
||||
UPDATE member SET shares_white = shares_white - OLD.shares WHERE mgnr = OLD.to_mgnr AND OLD.to_type = 3;
|
||||
UPDATE member SET shares_dormant = shares_dormant - OLD.shares WHERE mgnr = OLD.to_mgnr AND OLD.to_type = 9;
|
||||
UPDATE member SET shares = shares - NEW.shares WHERE mgnr = NEW.from_mgnr AND NEW.from_type = 1;
|
||||
UPDATE member SET shares_red = shares_red - NEW.shares WHERE mgnr = NEW.from_mgnr AND NEW.from_type = 2;
|
||||
UPDATE member SET shares_white = shares_white - NEW.shares WHERE mgnr = NEW.from_mgnr AND NEW.from_type = 3;
|
||||
UPDATE member SET shares_dormant = shares_dormant - NEW.shares WHERE mgnr = NEW.from_mgnr AND NEW.from_type = 9;
|
||||
UPDATE member SET shares = shares + NEW.shares WHERE mgnr = NEW.to_mgnr AND NEW.to_type = 1;
|
||||
UPDATE member SET shares_red = shares_red + NEW.shares WHERE mgnr = NEW.to_mgnr AND NEW.to_type = 2;
|
||||
UPDATE member SET shares_white = shares_white + NEW.shares WHERE mgnr = NEW.to_mgnr AND NEW.to_type = 3;
|
||||
UPDATE member SET shares_dormant = shares_dormant + NEW.shares WHERE mgnr = NEW.to_mgnr AND NEW.to_type = 9;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER t_member_history_d_member
|
||||
AFTER DELETE 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;
|
||||
UPDATE member SET shares_red = shares_red + OLD.shares WHERE mgnr = OLD.from_mgnr AND OLD.from_type = 2;
|
||||
UPDATE member SET shares_white = shares_white + OLD.shares WHERE mgnr = OLD.from_mgnr AND OLD.from_type = 3;
|
||||
UPDATE member SET shares_dormant = shares_dormant + OLD.shares WHERE mgnr = OLD.from_mgnr AND OLD.from_type = 9;
|
||||
UPDATE member SET shares = shares - OLD.shares WHERE mgnr = OLD.to_mgnr AND OLD.to_type = 1;
|
||||
UPDATE member SET shares_red = shares_red - OLD.shares WHERE mgnr = OLD.to_mgnr AND OLD.to_type = 2;
|
||||
UPDATE member SET shares_white = shares_white - OLD.shares WHERE mgnr = OLD.to_mgnr AND OLD.to_type = 3;
|
||||
UPDATE member SET shares_dormant = shares_dormant - OLD.shares WHERE mgnr = OLD.to_mgnr AND OLD.to_type = 9;
|
||||
END;
|
||||
|
||||
INSERT INTO client_parameter (param, value) VALUES ('ENABLE_MEMBER_HISTORY_TRIGGERS', '1');
|
||||
|
||||
CREATE TABLE season_new (
|
||||
year INTEGER NOT NULL CHECK (year >= 1000 AND year <= 9999),
|
||||
currency TEXT NOT NULL,
|
||||
precision INTEGER NOT NULL DEFAULT 4,
|
||||
|
||||
max_kg_per_ha INTEGER NOT NULL DEFAULT 10000,
|
||||
vat_normal REAL NOT NULL DEFAULT 0.10,
|
||||
vat_flatrate REAL NOT NULL DEFAULT 0.13,
|
||||
|
||||
min_kg_per_share INTEGER DEFAULT NULL,
|
||||
max_kg_per_share INTEGER DEFAULT NULL,
|
||||
min_kg_per_share_red INTEGER DEFAULT NULL,
|
||||
max_kg_per_share_red INTEGER DEFAULT NULL,
|
||||
min_kg_per_share_white INTEGER DEFAULT NULL,
|
||||
max_kg_per_share_white INTEGER DEFAULT NULL,
|
||||
penalty_per_kg INTEGER DEFAULT NULL,
|
||||
penalty_amount INTEGER DEFAULT NULL,
|
||||
penalty_none INTEGER DEFAULT NULL,
|
||||
penalty_per_share_amount INTEGER DEFAULT NULL,
|
||||
penalty_per_share_none INTEGER DEFAULT NULL,
|
||||
share_value INTEGER,
|
||||
|
||||
start_date TEXT CHECK (start_date REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$'),
|
||||
end_date TEXT CHECK (end_date REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$'),
|
||||
calc_mode INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
CONSTRAINT pk_season PRIMARY KEY (year),
|
||||
CONSTRAINT fk_season_currency FOREIGN KEY (currency) REFERENCES currency (code)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE RESTRICT
|
||||
) STRICT;
|
||||
|
||||
INSERT INTO season_new (year, currency, precision, max_kg_per_ha, vat_normal, vat_flatrate, min_kg_per_share, max_kg_per_share, penalty_per_kg, penalty_amount, penalty_none, penalty_per_share_amount, penalty_per_share_none, share_value, start_date, end_date, calc_mode)
|
||||
SELECT year, currency, precision, max_kg_per_ha, vat_normal, vat_flatrate, min_kg_per_bs, max_kg_per_bs, penalty_per_kg, penalty_amount, penalty_none, penalty_per_bs_amount, penalty_per_bs_none, bs_value, start_date, end_date, calc_mode
|
||||
FROM season;
|
||||
|
||||
PRAGMA foreign_keys = OFF;
|
||||
DROP TABLE season;
|
||||
ALTER TABLE season_new RENAME TO season;
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
DROP VIEW v_delivery;
|
||||
CREATE VIEW v_delivery AS
|
||||
SELECT p.year, p.did, p.dpnr,
|
||||
d.date, d.time, d.zwstid, d.lnr, d.lsnr,
|
||||
m.mgnr, m.name, m.given_name,
|
||||
v.sortid, v.type, a.attrid, p.cultid,
|
||||
p.weight, p.kmw, ROUND(p.kmw * (4.54 + 0.022 * p.kmw), 0) AS oe, p.qualid,
|
||||
p.hkid, p.kgnr, p.rdnr,
|
||||
p.net_weight, p.gebunden,
|
||||
p.qualid IN (SELECT l.qualid FROM wine_quality_level l WHERE NOT l.predicate AND (p.kmw >= l.min_kmw OR l.min_kmw IS NULL) ORDER BY l.min_kmw DESC LIMIT 1,100) AS abgewertet,
|
||||
p.qualid NOT IN ('WEI', 'RSW', 'LDW') AS min_quw,
|
||||
IIF(a.strict, COALESCE(a.fill_lower, 0), 0) AS attribute_prio,
|
||||
GROUP_CONCAT(o.modid) AS modifiers,
|
||||
d.comment, p.comment AS part_comment
|
||||
FROM delivery_part p
|
||||
JOIN delivery d ON (d.year, d.did) = (p.year, p.did)
|
||||
JOIN member m ON m.mgnr = d.mgnr
|
||||
LEFT JOIN wine_variety v ON v.sortid = p.sortid
|
||||
LEFT JOIN wine_attribute a ON a.attrid = p.attrid
|
||||
LEFT JOIN delivery_part_modifier o ON (o.year, o.did, o.dpnr) = (p.year, p.did, p.dpnr)
|
||||
GROUP BY p.year, p.did, p.dpnr
|
||||
ORDER BY p.year, p.did, p.dpnr, o.modid;
|
||||
|
||||
DROP VIEW v_stat_season;
|
||||
CREATE VIEW v_stat_season AS
|
||||
SELECT year,
|
||||
SUM(weight) AS weight_total,
|
||||
SUM(IIF(type = 'R', weight, 0)) AS weight_red,
|
||||
SUM(IIF(type = 'W', weight, 0)) AS weight_white,
|
||||
ROUND(SUM(kmw * weight) / SUM(weight), 2) AS kmw,
|
||||
ROUND(SUM(oe * weight) / SUM(weight), 1) AS oe,
|
||||
COUNT(DISTINCT did) AS lieferungen,
|
||||
COUNT(DISTINCT mgnr) AS mitglieder
|
||||
FROM v_delivery
|
||||
GROUP BY year
|
||||
ORDER BY year;
|
||||
|
||||
DROP VIEW v_stat_sort;
|
||||
CREATE VIEW v_stat_variety AS
|
||||
SELECT year, sortid,
|
||||
SUM(weight) AS weight_total,
|
||||
SUM(IIF(type = 'R', weight, 0)) AS weight_red,
|
||||
SUM(IIF(type = 'W', weight, 0)) AS weight_white,
|
||||
ROUND(SUM(kmw * weight) / SUM(weight), 2) AS kmw,
|
||||
ROUND(SUM(oe * weight) / SUM(weight), 1) AS oe,
|
||||
COUNT(DISTINCT did) AS lieferungen,
|
||||
COUNT(DISTINCT mgnr) AS mitglieder
|
||||
FROM v_delivery
|
||||
GROUP BY year, sortid
|
||||
ORDER BY year, sortid;
|
||||
|
||||
DROP VIEW v_stat_attr;
|
||||
CREATE VIEW v_stat_attr AS
|
||||
SELECT year, attrid,
|
||||
SUM(weight) AS weight_total,
|
||||
SUM(IIF(type = 'R', weight, 0)) AS weight_red,
|
||||
SUM(IIF(type = 'W', weight, 0)) AS weight_white,
|
||||
ROUND(SUM(kmw * weight) / SUM(weight), 2) AS kmw,
|
||||
ROUND(SUM(oe * weight) / SUM(weight), 1) AS oe,
|
||||
COUNT(DISTINCT did) AS lieferungen,
|
||||
COUNT(DISTINCT mgnr) AS mitglieder
|
||||
FROM v_delivery
|
||||
GROUP BY year, attrid
|
||||
ORDER BY year, attrid;
|
||||
|
||||
DROP VIEW v_stat_sort_attr;
|
||||
CREATE VIEW v_stat_variety_attr AS
|
||||
SELECT year, sortid, attrid,
|
||||
SUM(weight) AS weight_total,
|
||||
SUM(IIF(type = 'R', weight, 0)) AS weight_red,
|
||||
SUM(IIF(type = 'W', weight, 0)) AS weight_white,
|
||||
ROUND(SUM(kmw * weight) / SUM(weight), 2) AS kmw,
|
||||
ROUND(SUM(oe * weight) / SUM(weight), 1) AS oe,
|
||||
COUNT(DISTINCT did) AS lieferungen,
|
||||
COUNT(DISTINCT mgnr) AS mitglieder
|
||||
FROM v_delivery
|
||||
GROUP BY year, sortid, attrid
|
||||
ORDER BY year, sortid, attrid;
|
||||
|
||||
DROP VIEW v_stat_member;
|
||||
CREATE VIEW v_stat_member AS
|
||||
SELECT year, mgnr,
|
||||
SUM(weight) AS weight_total,
|
||||
SUM(IIF(type = 'R', weight, 0)) AS weight_red,
|
||||
SUM(IIF(type = 'W', weight, 0)) AS weight_white,
|
||||
ROUND(SUM(kmw * weight) / SUM(weight), 2) AS kmw,
|
||||
ROUND(SUM(oe * weight) / SUM(weight), 1) AS oe,
|
||||
COUNT(DISTINCT did) AS lieferungen
|
||||
FROM v_delivery
|
||||
GROUP BY year, mgnr
|
||||
ORDER BY year, mgnr;
|
||||
|
||||
CREATE VIEW v_member_history AS
|
||||
SELECT m.mgnr, s.year,
|
||||
m.shares + SUM(IIF(h1.from_type = 1, h1.shares, 0)) - SUM(IIF(h2.to_type = 1, h2.shares, 0)) AS shares,
|
||||
m.shares_red + SUM(IIF(h1.from_type = 2, h1.shares, 0)) - SUM(IIF(h2.to_type = 2, h2.shares, 0)) AS shares_red,
|
||||
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
|
||||
GROUP BY m.mgnr, s.year
|
||||
ORDER BY m.mgnr, s.year;
|
||||
|
||||
DROP VIEW v_total_under_delivery;
|
||||
CREATE VIEW v_total_under_delivery AS
|
||||
SELECT s.year, m.mgnr,
|
||||
h.shares,
|
||||
h.shares * COALESCE(s.min_kg_per_share, 0) AS min_kg,
|
||||
h.shares * COALESCE(s.max_kg_per_share, 0) AS max_kg,
|
||||
COALESCE(d.weight_total, 0) AS weight_total,
|
||||
IIF(COALESCE(d.weight_total, 0) < h.shares * COALESCE(s.min_kg_per_share, 0),
|
||||
COALESCE(d.weight_total, 0) - h.shares * COALESCE(s.min_kg_per_share, 0),
|
||||
IIF(COALESCE(d.weight_total, 0) > h.shares * COALESCE(s.max_kg_per_share, 0),
|
||||
COALESCE(d.weight_total, 0) - h.shares * COALESCE(s.max_kg_per_share, 0),
|
||||
0)) AS diff,
|
||||
h.shares_red,
|
||||
h.shares_red * COALESCE(s.min_kg_per_share_red, s.min_kg_per_share, 0) AS min_kg_red,
|
||||
h.shares_red * COALESCE(s.max_kg_per_share_red, s.max_kg_per_share, 0) AS max_kg_red,
|
||||
COALESCE(d.weight_red, 0) AS weight_red,
|
||||
IIF(COALESCE(d.weight_red, 0) < h.shares_red * COALESCE(s.min_kg_per_share_red, s.min_kg_per_share, 0),
|
||||
COALESCE(d.weight_red, 0) - h.shares_red * COALESCE(s.min_kg_per_share_red, s.min_kg_per_share, 0),
|
||||
IIF(COALESCE(d.weight_red, 0) > h.shares_red * COALESCE(s.max_kg_per_share_red, s.max_kg_per_share, 0),
|
||||
COALESCE(d.weight_red, 0) - h.shares_red * COALESCE(s.max_kg_per_share_red, s.max_kg_per_share, 0),
|
||||
0)) AS diff_red,
|
||||
h.shares_white,
|
||||
h.shares_white * COALESCE(s.min_kg_per_share_white, s.min_kg_per_share, 0) AS min_kg_white,
|
||||
h.shares_white * COALESCE(s.max_kg_per_share_white, s.max_kg_per_share, 0) AS max_kg_white,
|
||||
COALESCE(d.weight_white, 0) AS weight_white,
|
||||
IIF(COALESCE(d.weight_white, 0) < h.shares_white * COALESCE(s.min_kg_per_share_white, s.min_kg_per_share, 0),
|
||||
COALESCE(d.weight_white, 0) - h.shares_white * COALESCE(s.min_kg_per_share_white, s.min_kg_per_share, 0),
|
||||
IIF(COALESCE(d.weight_white, 0) > h.shares_white * COALESCE(s.max_kg_per_share_white, s.max_kg_per_share, 0),
|
||||
COALESCE(d.weight_white, 0) - h.shares_white * COALESCE(s.max_kg_per_share_white, s.max_kg_per_share, 0),
|
||||
0)) AS diff_white
|
||||
FROM member m, season s
|
||||
LEFT JOIN v_member_history h ON (h.year, h.mgnr) = (s.year, m.mgnr)
|
||||
LEFT JOIN v_stat_member d ON (d.year, d.mgnr) = (s.year, m.mgnr)
|
||||
ORDER BY s.year, m.mgnr;
|
||||
|
||||
DROP VIEW v_penalty_business_shares;
|
||||
CREATE VIEW v_penalty_business_shares AS
|
||||
SELECT u.year, u.mgnr,
|
||||
SUM(IIF(u.weight_total = 0, COALESCE(-s.penalty_none, 0) + COALESCE(-(u.shares + u.shares_red + u.shares_white) * s.penalty_per_share_none, 0), 0) +
|
||||
IIF(u.diff < 0 OR u.diff_red < 0 OR u.diff_white < 0, COALESCE(-s.penalty_amount, 0), 0) +
|
||||
COALESCE((u.diff + u.diff_red + u.diff_white) * s.penalty_per_kg, 0) +
|
||||
COALESCE(CEIL(CAST(u.diff AS REAL) / s.min_kg_per_share) * s.penalty_per_share_amount, 0) +
|
||||
COALESCE(CEIL(CAST(u.diff_red AS REAL) / s.min_kg_per_share_red) * s.penalty_per_share_amount, 0) +
|
||||
COALESCE(CEIL(CAST(u.diff_white AS REAL) / s.min_kg_per_share_white) * s.penalty_per_share_amount, 0)
|
||||
) AS total_penalty
|
||||
FROM v_total_under_delivery u
|
||||
JOIN season s ON u.year = s.year
|
||||
JOIN member m ON m.mgnr = u.mgnr
|
||||
WHERE m.active
|
||||
GROUP BY u.year, u.mgnr
|
||||
HAVING total_penalty < 0
|
||||
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,
|
||||
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'
|
||||
GROUP BY year, h.to_mgnr
|
||||
ORDER BY year, h.to_mgnr;
|
||||
|
||||
PRAGMA writable_schema = OFF;
|
||||
@@ -126,7 +126,7 @@ namespace Elwig.Services {
|
||||
|
||||
vm.EntryDate = (m.EntryDateString != null) ? string.Join(".", m.EntryDateString.Split("-").Reverse()) : null;
|
||||
vm.ExitDate = (m.ExitDateString != null) ? string.Join(".", m.ExitDateString.Split("-").Reverse()) : null;
|
||||
vm.BusinessShares = m.BusinessShares;
|
||||
vm.BusinessShares = m.Shares;
|
||||
vm.AccountingNr = m.AccountingNr;
|
||||
vm.Branch = (Branch?)ControlUtils.GetItemFromSourceWithPk(vm.BranchSource, m.ZwstId);
|
||||
vm.DefaultKg = (AT_Kg?)ControlUtils.GetItemFromSourceWithPk(vm.DefaultKgSource, m.DefaultKgNr);
|
||||
@@ -487,6 +487,13 @@ namespace Elwig.Services {
|
||||
.Include(m => m.TelephoneNumbers)
|
||||
.Include(m => m.EmailAddresses)
|
||||
.ToListAsync();
|
||||
var history1 = await query.IgnoreAutoIncludes()
|
||||
.SelectMany(m => m.HistoryFrom)
|
||||
.ToListAsync();
|
||||
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 areaComs = await query
|
||||
.SelectMany(m => m.AreaCommitments)
|
||||
.Select(c => c.Contract).Distinct()
|
||||
@@ -499,7 +506,7 @@ namespace Elwig.Services {
|
||||
.Distinct()
|
||||
.OrderBy(k => k.KgNr)
|
||||
.ToList();
|
||||
await ElwigData.Export(filename, members, areaComs, wbKgs, filterNames);
|
||||
await ElwigData.Export(filename, members, history, areaComs, wbKgs, filterNames);
|
||||
});
|
||||
}
|
||||
} else if (mode == ExportMode.Upload && App.Config.SyncUrl != null) {
|
||||
@@ -542,7 +549,7 @@ namespace Elwig.Services {
|
||||
|
||||
EntryDateString = string.IsNullOrEmpty(vm.EntryDate) ? null : string.Join("-", vm.EntryDate.Split(".").Reverse()),
|
||||
ExitDateString = string.IsNullOrEmpty(vm.ExitDate) ? null : string.Join("-", vm.ExitDate.Split(".").Reverse()),
|
||||
BusinessShares = (int)vm.BusinessShares!,
|
||||
Shares = (int)vm.BusinessShares!,
|
||||
AccountingNr = string.IsNullOrEmpty(vm.AccountingNr) ? null : vm.AccountingNr,
|
||||
IsActive = vm.IsActive,
|
||||
IsVollLieferant = vm.IsVollLieferant,
|
||||
|
||||
@@ -27,6 +27,13 @@ namespace Elwig.Services {
|
||||
.Include(m => m.TelephoneNumbers)
|
||||
.Include(m => m.EmailAddresses)
|
||||
.ToListAsync();
|
||||
var history1 = await query.IgnoreAutoIncludes()
|
||||
.SelectMany(m => m.HistoryFrom)
|
||||
.ToListAsync();
|
||||
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 areaComs = await query
|
||||
.SelectMany(m => m.AreaCommitments)
|
||||
.Select(c => c.Contract).Distinct()
|
||||
@@ -44,7 +51,7 @@ namespace Elwig.Services {
|
||||
InteractionService.ShowError("Mitglieder hochladen", "Es wurden keine Mitglieder zum Hochladen ausgewählt!");
|
||||
} else {
|
||||
var exportedAt = DateTime.Now;
|
||||
await ElwigData.Export(path, members, areaComs, wbKgs, filterNames);
|
||||
await ElwigData.Export(path, members, history, areaComs, wbKgs, filterNames);
|
||||
await Utils.UploadExportData(path, url, username, password);
|
||||
await UpdateExportedAt(members, areaComs, [], exportedAt);
|
||||
InteractionService.ShowInformation("Mitglieder hochgeladen", $"Hochladen von {members.Count:N0} Mitgliedern erfolgreich!");
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Elwig.ViewModels {
|
||||
[ObservableProperty]
|
||||
private string? _businessSharesString;
|
||||
public int? BusinessShares {
|
||||
get => int.TryParse(BusinessSharesString, out var bs) ? bs : null;
|
||||
get => int.TryParse(BusinessSharesString, out var shares) ? shares : null;
|
||||
set => BusinessSharesString = $"{value}";
|
||||
}
|
||||
[ObservableProperty]
|
||||
|
||||
@@ -453,13 +453,13 @@
|
||||
HorizontalAlignment="Left"/>
|
||||
|
||||
<Label Content="Lieferpflicht/-recht:" Margin="10,10,0,10" Grid.Column="2"/>
|
||||
<ctrl:UnitTextBox x:Name="SeasonMinKgPerBsInput" Unit="kg/GA" TextChanged="SeasonMinMaxKgInput_TextChanged"
|
||||
<ctrl:UnitTextBox x:Name="SeasonMinKgPerShareInput" Unit="kg/GA" TextChanged="SeasonMinMaxKgInput_TextChanged"
|
||||
Grid.Column="3" Width="80" Margin="0,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<ctrl:UnitTextBox x:Name="SeasonMaxKgPerBsInput" Unit="kg/GA" TextChanged="SeasonMinMaxKgInput_TextChanged"
|
||||
<ctrl:UnitTextBox x:Name="SeasonMaxKgPerShareInput" Unit="kg/GA" TextChanged="SeasonMinMaxKgInput_TextChanged"
|
||||
Grid.Column="3" Width="80" Margin="85,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
|
||||
<Label Content="GA-Wert (Nachz.):" Margin="10,40,0,10" Grid.Column="2"/>
|
||||
<ctrl:UnitTextBox x:Name="SeasonBsValueInput" Unit="€/GA" TextChanged="SeasonPenaltyInput_TextChanged"
|
||||
<ctrl:UnitTextBox x:Name="SeasonShareValueInput" Unit="€/GA" TextChanged="SeasonPenaltyInput_TextChanged"
|
||||
Grid.Column="3" Width="85" Margin="0,40,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
|
||||
<GroupBox Header="Strafen bei Unterlieferung lt. GA" Grid.Column="2" Grid.ColumnSpan="2" Margin="0,70,10,0">
|
||||
@@ -468,13 +468,13 @@
|
||||
Width="80" Margin="65,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<ctrl:UnitTextBox x:Name="SeasonPenaltyInput" Unit="€" TextChanged="SeasonPenaltyInput_TextChanged"
|
||||
Width="68" Margin="150,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<ctrl:UnitTextBox x:Name="SeasonPenaltyPerBsInput" Unit="€/GA" TextChanged="SeasonPenaltyPerBsInput_TextChanged"
|
||||
<ctrl:UnitTextBox x:Name="SeasonPenaltyPerShareInput" Unit="€/GA" TextChanged="SeasonPenaltyPerShareInput_TextChanged"
|
||||
Width="100" Margin="222,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
|
||||
<Label Content="Zzgl. bei Nicht-Lieferung:" Margin="10,40,0,10"/>
|
||||
<ctrl:UnitTextBox x:Name="SeasonPenaltyNoneInput" Unit="€" TextChanged="SeasonPenaltyInput_TextChanged"
|
||||
Width="68" Margin="150,40,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<ctrl:UnitTextBox x:Name="SeasonPenaltyPerBsNoneInput" Unit="€/GA" TextChanged="SeasonPenaltyPerBsInput_TextChanged"
|
||||
<ctrl:UnitTextBox x:Name="SeasonPenaltyPerShareNoneInput" Unit="€/GA" TextChanged="SeasonPenaltyPerShareInput_TextChanged"
|
||||
Width="100" Margin="222,40,10,10" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
@@ -47,23 +47,23 @@ namespace Elwig.Windows {
|
||||
SeasonVatFlatrateInput.Text = (s.VatFlatrate * 100).ToString();
|
||||
SeasonStartInput.Text = $"{s.StartDate:dd.MM.yyyy}";
|
||||
SeasonEndInput.Text = $"{s.EndDate:dd.MM.yyyy}";
|
||||
SeasonMinKgPerBsInput.Text = s.MinKgPerBusinessShare.ToString();
|
||||
SeasonMaxKgPerBsInput.Text = s.MaxKgPerBusinessShare.ToString();
|
||||
SeasonMinKgPerShareInput.Text = s.MinKgPerShare.ToString();
|
||||
SeasonMaxKgPerShareInput.Text = s.MaxKgPerShare.ToString();
|
||||
SeasonPenaltyPerKgInput.Text = s.PenaltyPerKg?.ToString() ?? "";
|
||||
SeasonPenaltyInput.Text = s.PenaltyAmount?.ToString() ?? "";
|
||||
SeasonPenaltyNoneInput.Text = s.PenaltyNone?.ToString() ?? "";
|
||||
SeasonPenaltyPerBsInput.Text = s.PenaltyPerBsAmount?.ToString() ?? "";
|
||||
SeasonPenaltyPerBsNoneInput.Text = s.PenaltyPerBsNone?.ToString() ?? "";
|
||||
SeasonBsValueInput.Text = s.BusinessShareValue?.ToString() ?? "";
|
||||
SeasonPenaltyPerShareInput.Text = s.PenaltyPerShareAmount?.ToString() ?? "";
|
||||
SeasonPenaltyPerShareNoneInput.Text = s.PenaltyPerShareNone?.ToString() ?? "";
|
||||
SeasonShareValueInput.Text = s.BusinessShareValue?.ToString() ?? "";
|
||||
|
||||
var sym = s.Currency.Symbol ?? s.Currency.Code;
|
||||
SeasonModifierAbsInput.Unit = $"{sym}/kg";
|
||||
SeasonPenaltyPerKgInput.Unit = $"{sym}/kg";
|
||||
SeasonPenaltyInput.Unit = sym;
|
||||
SeasonPenaltyNoneInput.Unit = sym;
|
||||
SeasonPenaltyPerBsInput.Unit = $"{sym}/GA";
|
||||
SeasonPenaltyPerBsNoneInput.Unit = $"{sym}/GA";
|
||||
SeasonBsValueInput.Unit = $"{sym}/GA";
|
||||
SeasonPenaltyPerShareInput.Unit = $"{sym}/GA";
|
||||
SeasonPenaltyPerShareNoneInput.Unit = $"{sym}/GA";
|
||||
SeasonShareValueInput.Unit = $"{sym}/GA";
|
||||
AreaCommitmentTypePenaltyPerKgInput.Unit = $"{sym}/kg";
|
||||
AreaCommitmentTypePenaltyInput.Unit = sym;
|
||||
AreaCommitmentTypePenaltyNoneInput.Unit = sym;
|
||||
@@ -74,14 +74,14 @@ namespace Elwig.Windows {
|
||||
SeasonVatFlatrateInput.Text = "";
|
||||
SeasonStartInput.Text = "";
|
||||
SeasonEndInput.Text = "";
|
||||
SeasonMinKgPerBsInput.Text = "";
|
||||
SeasonMaxKgPerBsInput.Text = "";
|
||||
SeasonMinKgPerShareInput.Text = "";
|
||||
SeasonMaxKgPerShareInput.Text = "";
|
||||
SeasonPenaltyPerKgInput.Text = "";
|
||||
SeasonPenaltyInput.Text = "";
|
||||
SeasonPenaltyNoneInput.Text = "";
|
||||
SeasonPenaltyPerBsInput.Text = "";
|
||||
SeasonPenaltyPerBsNoneInput.Text = "";
|
||||
SeasonBsValueInput.Text = "";
|
||||
SeasonPenaltyPerShareInput.Text = "";
|
||||
SeasonPenaltyPerShareNoneInput.Text = "";
|
||||
SeasonShareValueInput.Text = "";
|
||||
}
|
||||
_seasonUpdate = false;
|
||||
}
|
||||
@@ -96,16 +96,16 @@ namespace Elwig.Windows {
|
||||
s.VatNormal = double.Parse(SeasonVatNormalInput.Text) / 100;
|
||||
if (SeasonVatFlatrateInput.Text.Length > 0)
|
||||
s.VatFlatrate = double.Parse(SeasonVatFlatrateInput.Text) / 100;
|
||||
if (SeasonMinKgPerBsInput.Text.Length > 0)
|
||||
s.MinKgPerBusinessShare = int.Parse(SeasonMinKgPerBsInput.Text);
|
||||
if (SeasonMaxKgPerBsInput.Text.Length > 0)
|
||||
s.MaxKgPerBusinessShare = int.Parse(SeasonMaxKgPerBsInput.Text);
|
||||
if (SeasonMinKgPerShareInput.Text.Length > 0)
|
||||
s.MinKgPerShare = int.Parse(SeasonMinKgPerShareInput.Text);
|
||||
if (SeasonMaxKgPerShareInput.Text.Length > 0)
|
||||
s.MaxKgPerShare = int.Parse(SeasonMaxKgPerShareInput.Text);
|
||||
s.PenaltyPerKg = (SeasonPenaltyPerKgInput.Text.Length > 0) ? decimal.Parse(SeasonPenaltyPerKgInput.Text) : null;
|
||||
s.PenaltyAmount = (SeasonPenaltyInput.Text.Length > 0) ? decimal.Parse(SeasonPenaltyInput.Text) : null;
|
||||
s.PenaltyNone = (SeasonPenaltyNoneInput.Text.Length > 0) ? decimal.Parse(SeasonPenaltyNoneInput.Text) : null;
|
||||
s.PenaltyPerBsAmount = (SeasonPenaltyPerBsInput.Text.Length > 0) ? decimal.Parse(SeasonPenaltyPerBsInput.Text) : null;
|
||||
s.PenaltyPerBsNone = (SeasonPenaltyPerBsNoneInput.Text.Length > 0) ? decimal.Parse(SeasonPenaltyPerBsNoneInput.Text) : null;
|
||||
s.BusinessShareValue = (SeasonBsValueInput.Text.Length > 0) ? decimal.Parse(SeasonBsValueInput.Text) : null;
|
||||
s.PenaltyPerShareAmount = (SeasonPenaltyPerShareInput.Text.Length > 0) ? decimal.Parse(SeasonPenaltyPerShareInput.Text) : null;
|
||||
s.PenaltyPerShareNone = (SeasonPenaltyPerShareNoneInput.Text.Length > 0) ? decimal.Parse(SeasonPenaltyPerShareNoneInput.Text) : null;
|
||||
s.BusinessShareValue = (SeasonShareValueInput.Text.Length > 0) ? decimal.Parse(SeasonShareValueInput.Text) : null;
|
||||
|
||||
UpdateButtons();
|
||||
}
|
||||
@@ -131,7 +131,7 @@ namespace Elwig.Windows {
|
||||
Season_Changed(sender, evt);
|
||||
}
|
||||
|
||||
private void SeasonPenaltyPerBsInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
private void SeasonPenaltyPerShareInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
if (SeasonList.SelectedItem is not Season s) return;
|
||||
InputTextChanged((TextBox)sender, Validator.CheckDecimal((TextBox)sender, false, 4, s.Precision));
|
||||
Season_Changed(sender, evt);
|
||||
@@ -160,13 +160,13 @@ namespace Elwig.Windows {
|
||||
MaxKgPerHa = s?.MaxKgPerHa ?? 10000,
|
||||
VatNormal = s?.VatNormal ?? 0.10,
|
||||
VatFlatrate = s?.VatFlatrate ?? 0.13,
|
||||
MinKgPerBusinessShare = s?.MinKgPerBusinessShare ?? 500,
|
||||
MaxKgPerBusinessShare = s?.MaxKgPerBusinessShare ?? 1000,
|
||||
MinKgPerShare = s?.MinKgPerShare ?? 500,
|
||||
MaxKgPerShare = s?.MaxKgPerShare ?? 1000,
|
||||
PenaltyPerKgValue = s?.PenaltyPerKgValue,
|
||||
PenaltyAmoutValue = s?.PenaltyAmoutValue,
|
||||
PenaltyNoneValue = s?.PenaltyNoneValue,
|
||||
PenaltyPerBsAmountValue = s?.PenaltyPerBsAmountValue,
|
||||
PenaltyPerBsNoneValue = s?.PenaltyPerBsNoneValue,
|
||||
PenaltyPerShareAmountValue = s?.PenaltyPerShareAmountValue,
|
||||
PenaltyPerShareNoneValue = s?.PenaltyPerShareNoneValue,
|
||||
BusinessShareValueValue = s?.BusinessShareValueValue,
|
||||
CalcMode = s?.CalcMode ?? 0,
|
||||
});
|
||||
|
||||
@@ -32,9 +32,9 @@ namespace Elwig.Windows {
|
||||
AreaCommitmentTypeMinKgPerHaInput, AreaCommitmentTypePenaltyPerKgInput,
|
||||
AreaCommitmentTypePenaltyInput, AreaCommitmentTypePenaltyNoneInput,
|
||||
SeasonMaxKgPerHaInput, SeasonVatNormalInput, SeasonVatFlatrateInput, SeasonStartInput, SeasonEndInput,
|
||||
SeasonMinKgPerBsInput, SeasonMaxKgPerBsInput, SeasonBsValueInput,
|
||||
SeasonMinKgPerShareInput, SeasonMaxKgPerShareInput, SeasonShareValueInput,
|
||||
SeasonPenaltyPerKgInput, SeasonPenaltyInput, SeasonPenaltyNoneInput,
|
||||
SeasonPenaltyPerBsInput, SeasonPenaltyPerBsNoneInput,
|
||||
SeasonPenaltyPerShareInput, SeasonPenaltyPerShareNoneInput,
|
||||
SeasonModifierIdInput, SeasonModifierNameInput, SeasonModifierRelInput, SeasonModifierAbsInput,
|
||||
];
|
||||
WineAttributeFillLowerInput.Visibility = Visibility.Hidden;
|
||||
@@ -79,14 +79,14 @@ namespace Elwig.Windows {
|
||||
SeasonMaxKgPerHaInput.IsReadOnly = true;
|
||||
SeasonVatNormalInput.IsReadOnly = true;
|
||||
SeasonVatFlatrateInput.IsReadOnly = true;
|
||||
SeasonMinKgPerBsInput.IsReadOnly = true;
|
||||
SeasonMaxKgPerBsInput.IsReadOnly = true;
|
||||
SeasonMinKgPerShareInput.IsReadOnly = true;
|
||||
SeasonMaxKgPerShareInput.IsReadOnly = true;
|
||||
SeasonPenaltyPerKgInput.IsReadOnly = true;
|
||||
SeasonPenaltyInput.IsReadOnly = true;
|
||||
SeasonPenaltyNoneInput.IsReadOnly = true;
|
||||
SeasonPenaltyPerBsInput.IsReadOnly = true;
|
||||
SeasonPenaltyPerBsNoneInput.IsReadOnly = true;
|
||||
SeasonBsValueInput.IsReadOnly = true;
|
||||
SeasonPenaltyPerShareInput.IsReadOnly = true;
|
||||
SeasonPenaltyPerShareNoneInput.IsReadOnly = true;
|
||||
SeasonShareValueInput.IsReadOnly = true;
|
||||
|
||||
SeasonModifierIdInput.IsReadOnly = true;
|
||||
SeasonModifierNameInput.IsReadOnly = true;
|
||||
@@ -133,14 +133,14 @@ namespace Elwig.Windows {
|
||||
SeasonMaxKgPerHaInput.IsReadOnly = false;
|
||||
SeasonVatNormalInput.IsReadOnly = false;
|
||||
SeasonVatFlatrateInput.IsReadOnly = false;
|
||||
SeasonMinKgPerBsInput.IsReadOnly = false;
|
||||
SeasonMaxKgPerBsInput.IsReadOnly = false;
|
||||
SeasonMinKgPerShareInput.IsReadOnly = false;
|
||||
SeasonMaxKgPerShareInput.IsReadOnly = false;
|
||||
SeasonPenaltyPerKgInput.IsReadOnly = false;
|
||||
SeasonPenaltyInput.IsReadOnly = false;
|
||||
SeasonPenaltyNoneInput.IsReadOnly = false;
|
||||
SeasonPenaltyPerBsInput.IsReadOnly = false;
|
||||
SeasonPenaltyPerBsNoneInput.IsReadOnly = false;
|
||||
SeasonBsValueInput.IsReadOnly = false;
|
||||
SeasonPenaltyPerShareInput.IsReadOnly = false;
|
||||
SeasonPenaltyPerShareNoneInput.IsReadOnly = false;
|
||||
SeasonShareValueInput.IsReadOnly = false;
|
||||
|
||||
SeasonModifierIdInput.IsReadOnly = false;
|
||||
SeasonModifierNameInput.IsReadOnly = false;
|
||||
|
||||
@@ -104,10 +104,10 @@ namespace Elwig.Windows {
|
||||
|
||||
try {
|
||||
var data = EditBillingData.FromJson(PaymentVar.Data, await Utils.GetVaributes(ctx, Year));
|
||||
var paymentEntries = await data.GetPaymentGraphEntries(ctx, Season);
|
||||
var paymentEntries = (await data.GetPaymentGraphEntries(ctx, Season)).ToList();
|
||||
GraphEntries = [
|
||||
..paymentEntries,
|
||||
..await data.GetQualityGraphEntries(ctx, Season, paymentEntries.Any() ? paymentEntries.Max(e => e.Id) : 0)
|
||||
..await data.GetQualityGraphEntries(ctx, Season, paymentEntries.Count != 0 ? paymentEntries.Max(e => e.Id) : 0)
|
||||
];
|
||||
} catch (KeyNotFoundException exc) {
|
||||
var key = exc.Message.Split('\'')[1].Split('\'')[0];
|
||||
|
||||
@@ -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 BusinessShares, StringFormat='{}{0} '}" Width="40">
|
||||
<DataGridTextColumn Header="GA" Binding="{Binding SharesTotal, StringFormat='{}{0} '}" Width="40">
|
||||
<DataGridTextColumn.CellStyle>
|
||||
<Style>
|
||||
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace Elwig.Windows {
|
||||
}
|
||||
|
||||
var totalMemberCount = await ctx.Members.CountAsync();
|
||||
var totalBusinessShares = await ctx.Members.SumAsync(m => m.BusinessShares);
|
||||
var totalBusinessShares = await ctx.Members.SumAsync(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant);
|
||||
|
||||
return (members, totalMemberCount, totalBusinessShares);
|
||||
});
|
||||
@@ -155,7 +155,7 @@ namespace Elwig.Windows {
|
||||
MemberList.ScrollIntoView(MemberList.SelectedItem);
|
||||
|
||||
ViewModel.StatusMembers = $"{members.Count:N0} ({totalMemberCount:N0})";
|
||||
ViewModel.StatusBusinessShares = $"{members.Sum(m => m.BusinessShares):N0} ({totalBusinessShares:N0})";
|
||||
ViewModel.StatusBusinessShares = $"{members.Sum(m => m.Shares + m.SharesRed + m.SharesWhite + m.SharesDormant):N0} ({totalBusinessShares:N0})";
|
||||
}
|
||||
|
||||
private void RefreshInputs(bool validate = false) {
|
||||
@@ -279,9 +279,9 @@ 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.BusinessShares):N0}";
|
||||
var bI = $"{await ctx.Members.Where(m => !m.IsActive).SumAsync(m => m.BusinessShares):N0}";
|
||||
var bT = $"{await ctx.Members.SumAsync(m => m.BusinessShares):N0}";
|
||||
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--;
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Header="Nachname" Binding="{Binding Name}" Width="100"/>
|
||||
<DataGridTextColumn Header="Vorname" Binding="{Binding GivenName}" Width="90"/>
|
||||
<DataGridTextColumn Header="GA" Binding="{Binding BusinessShares, StringFormat='{}{0:N0} '}" Width="35">
|
||||
<DataGridTextColumn Header="GA" Binding="{Binding SharesActive, StringFormat='{}{0:N0} '}" Width="35">
|
||||
<DataGridTextColumn.CellStyle>
|
||||
<Style>
|
||||
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
|
||||
@@ -104,7 +104,7 @@
|
||||
</Style>
|
||||
</DataGridTextColumn.CellStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn Header="Strafe GA" Binding="{Binding PenaltyBs, Converter={StaticResource CurrencyConverter}, StringFormat='{}{0} '}" Width="65">
|
||||
<DataGridTextColumn Header="Strafe GA" Binding="{Binding PenaltyShares, Converter={StaticResource CurrencyConverter}, StringFormat='{}{0} '}" Width="65">
|
||||
<DataGridTextColumn.CellStyle>
|
||||
<Style>
|
||||
<Setter Property="TextBlock.TextAlignment" Value="Right"/>
|
||||
@@ -204,28 +204,28 @@
|
||||
<Label Content="Absoluter Freibetrag:" Margin="10,10,0,0" Grid.ColumnSpan="2"/>
|
||||
<ctrl:UnitTextBox x:Name="AllowanceKgInput" Unit="kg" Margin="128,10,0,0" Width="70"
|
||||
TextChanged="KgInput_TextChanged" Grid.Column="1"/>
|
||||
<ctrl:UnitTextBox x:Name="AllowanceBsInput" Unit="GA" Margin="203,10,0,0" Width="60"
|
||||
<ctrl:UnitTextBox x:Name="AllowanceShareInput" Unit="GA" Margin="203,10,0,0" Width="60"
|
||||
TextChanged="PercentInput_TextChanged" Grid.Column="1"/>
|
||||
|
||||
<Label Content="Relativer Freibetrag:" Margin="10,40,0,0" Grid.ColumnSpan="2"/>
|
||||
<ctrl:UnitTextBox x:Name="AllowanceKgPerBsInput" Unit="kg/GA" Margin="128,40,0,0" Width="87"
|
||||
<ctrl:UnitTextBox x:Name="AllowanceKgPerShareInput" Unit="kg/GA" Margin="128,40,0,0" Width="87"
|
||||
TextChanged="KgInput_TextChanged" Grid.Column="1"/>
|
||||
<ctrl:UnitTextBox x:Name="AllowancePercentInput" Unit="%" Margin="220,40,0,0" Width="60"
|
||||
TextChanged="PercentInput_TextChanged" Grid.Column="1"/>
|
||||
|
||||
<Label Content="Nur mind. nachz.:" Margin="10,70,0,0" Grid.ColumnSpan="2"/>
|
||||
<ctrl:UnitTextBox x:Name="MinBsInput" Unit="GA" Margin="128,70,0,0" Width="50"
|
||||
TextChanged="BsInput_TextChanged" Grid.Column="1"/>
|
||||
<ctrl:UnitTextBox x:Name="MinSharesInput" Unit="GA" Margin="128,70,0,0" Width="50"
|
||||
TextChanged="SharesInput_TextChanged" Grid.Column="1"/>
|
||||
|
||||
<Button x:Name="SeasonButton" Content="GA-Wert" Margin="0,0,10,42" Width="120"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||||
Click="SeasonButton_Click" Grid.Column="1"/>
|
||||
<Button x:Name="AutoAdjustBsButton" Content="Nachzeichnen" Margin="0,0,135,10" Width="120"
|
||||
<Button x:Name="AutoAdjustSharesButton" Content="Nachzeichnen" Margin="0,0,135,10" Width="120"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||||
Click="AutoAdjustBsButton_Click" Grid.Column="1"/>
|
||||
<Button x:Name="UnAdjustBsButton" Content="Rückgängig" Margin="0,0,10,10" Width="120"
|
||||
Click="AutoAdjustSharesButton_Click" Grid.Column="1"/>
|
||||
<Button x:Name="UnAdjustSharesButton" Content="Rückgängig" Margin="0,0,10,10" Width="120"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||||
Click="UnAdjustBsButton_Click" Grid.Column="1"/>
|
||||
Click="UnAdjustSharesButton_Click" Grid.Column="1"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
||||
@@ -26,18 +26,18 @@ namespace Elwig.Windows {
|
||||
Year = year;
|
||||
// using (var ctx = new AppDbContext()) { SeasonLocked = ctx.Seasons.Find(Year + 1) != null; }
|
||||
Title = $"Auszahlung anpassen - Lese {Year} - Elwig";
|
||||
AutoAdjustBsButton.IsEnabled = !SeasonLocked;
|
||||
UnAdjustBsButton.IsEnabled = !SeasonLocked;
|
||||
AutoAdjustSharesButton.IsEnabled = !SeasonLocked;
|
||||
UnAdjustSharesButton.IsEnabled = !SeasonLocked;
|
||||
SaveCustomButton.IsEnabled = !SeasonLocked;
|
||||
RemoveCustomButton.IsEnabled = !SeasonLocked;
|
||||
CustomAmountInput.IsEnabled = !SeasonLocked;
|
||||
CustomCommentInput.IsEnabled = !SeasonLocked;
|
||||
|
||||
AllowanceKgInput.Text = $"{App.Client.AutoAdjustBs.AllowanceKg}";
|
||||
AllowanceBsInput.Text = $"{App.Client.AutoAdjustBs.AllowanceBs}";
|
||||
AllowanceKgPerBsInput.Text = $"{App.Client.AutoAdjustBs.AllowanceKgPerBs}";
|
||||
AllowancePercentInput.Text = $"{App.Client.AutoAdjustBs.AllowancePercent}";
|
||||
MinBsInput.Text = $"{App.Client.AutoAdjustBs.MinBs}";
|
||||
AllowanceKgInput.Text = $"{App.Client.AutoAdjustShares.AllowanceKg}";
|
||||
AllowanceShareInput.Text = $"{App.Client.AutoAdjustShares.AllowanceShares}";
|
||||
AllowanceKgPerShareInput.Text = $"{App.Client.AutoAdjustShares.AllowanceKgPerShare}";
|
||||
AllowancePercentInput.Text = $"{App.Client.AutoAdjustShares.AllowancePercent}";
|
||||
MinSharesInput.Text = $"{App.Client.AutoAdjustShares.MinShares}";
|
||||
}
|
||||
|
||||
protected override async Task OnRenewContext(AppDbContext ctx) {
|
||||
@@ -46,7 +46,7 @@ namespace Elwig.Windows {
|
||||
m.MgNr,
|
||||
m.Name,
|
||||
m.GivenName,
|
||||
m.BusinessShares,
|
||||
m.SharesActive,
|
||||
m.IsActive,
|
||||
})
|
||||
.ToListAsync();
|
||||
@@ -55,27 +55,27 @@ namespace Elwig.Windows {
|
||||
|
||||
var tbl1 = await OverUnderDeliveryData.ForSeason(ctx.OverUnderDeliveryRows, Year);
|
||||
var tbl2 = await AreaComUnderDeliveryData.ForSeason(ctx.AreaComUnderDeliveryRows, Year);
|
||||
var weight = tbl1.Rows.ToDictionary(r => r.MgNr, r => r.Weight);
|
||||
var weight = tbl1.Rows.ToDictionary(r => r.MgNr, r => r.WeightTotal);
|
||||
var areaComs = tbl2.Rows.ToDictionary(r => r.MgNr, r => r.VtrgIds.Zip(r.UnderDeliveries).ToDictionary(r => r.First, r => r.Second));
|
||||
CustomPayments = await ctx.CustomPayments.Where(p => p.Year == Year).ToDictionaryAsync(p => p.MgNr, p => p);
|
||||
|
||||
var history = await ctx.MemberHistory
|
||||
.Where(h => h.DateString.CompareTo($"{Year}-01-01") >= 0 && h.DateString.CompareTo($"{Year}-12-31") <= 0 && h.Type == "auto" && h.BusinessShares > 0)
|
||||
.GroupBy(h => h.Member)
|
||||
.ToDictionaryAsync(h => h.Key.MgNr, h => h.Sum(g => g.BusinessShares));
|
||||
.Where(h => h.DateString.CompareTo($"{Year}-01-01") >= 0 && h.DateString.CompareTo($"{Year}-12-31") <= 0 && h.Reason == "auto" && h.Shares > 0)
|
||||
.GroupBy(h => h.ToMember)
|
||||
.ToDictionaryAsync(h => h.Key.MgNr, h => h.Sum(g => g.Shares));
|
||||
|
||||
var list = members
|
||||
.Select(m => new {
|
||||
m.MgNr, m.Name, m.GivenName,
|
||||
m.IsActive,
|
||||
BusinessShares = m.BusinessShares - history.GetValueOrDefault(m.MgNr, 0),
|
||||
DeliveryObligation = (m.BusinessShares - history.GetValueOrDefault(m.MgNr, 0)) * season.MinKgPerBusinessShare,
|
||||
DeliveryRight = (m.BusinessShares - history.GetValueOrDefault(m.MgNr, 0)) * season.MaxKgPerBusinessShare,
|
||||
SharesActive = m.SharesActive - history.GetValueOrDefault(m.MgNr, 0),
|
||||
DeliveryObligation = (m.SharesActive - history.GetValueOrDefault(m.MgNr, 0)) * season.MinKgPerShare,
|
||||
DeliveryRight = (m.SharesActive - history.GetValueOrDefault(m.MgNr, 0)) * season.MaxKgPerShare,
|
||||
Adjust = history.TryGetValue(m.MgNr, out int v2) ? (int?)v2 : null,
|
||||
})
|
||||
.Select(m => new {
|
||||
m.MgNr, m.Name, m.GivenName,
|
||||
m.BusinessShares,
|
||||
m.SharesActive,
|
||||
Weight = weight.GetValueOrDefault(m.MgNr, 0),
|
||||
OverUnder = weight.TryGetValue(m.MgNr, out int v1) ?
|
||||
(v1 < m.DeliveryObligation ? (int?)v1 - m.DeliveryObligation :
|
||||
@@ -86,12 +86,12 @@ namespace Elwig.Windows {
|
||||
})
|
||||
.Select(m => new {
|
||||
m.MgNr, m.Name, m.GivenName,
|
||||
m.BusinessShares, m.Weight, m.OverUnder,
|
||||
PenaltyBs = m.OverUnder != null && m.OverUnder < 0 ?
|
||||
m.SharesActive, m.Weight, m.OverUnder,
|
||||
PenaltyShares = m.OverUnder != null && m.OverUnder < 0 ?
|
||||
(season.PenaltyPerKg * m.OverUnder ?? 0) +
|
||||
(-season.PenaltyAmount ?? 0) +
|
||||
(season.PenaltyPerBsAmount * Math.Floor(m.OverUnder / season.MinKgPerBusinessShare ?? 0m) ?? 0) +
|
||||
(m.Weight == 0 ? (-season.PenaltyNone ?? 0) + (-season.PenaltyPerBsNone * m.BusinessShares ?? 0) : 0)
|
||||
(season.PenaltyPerShareAmount * Math.Floor(m.OverUnder / season.MinKgPerShare ?? 0m) ?? 0) +
|
||||
(m.Weight == 0 ? (-season.PenaltyNone ?? 0) + (-season.PenaltyPerShareNone * m.SharesActive ?? 0) : 0)
|
||||
: (decimal?)null,
|
||||
PenaltyAc = areaComs.TryGetValue(m.MgNr, out var c) ? c.Select(r => {
|
||||
var con = contracts[r.Key];
|
||||
@@ -103,30 +103,30 @@ namespace Elwig.Windows {
|
||||
})
|
||||
.Select(m => new {
|
||||
m.MgNr, m.Name, m.GivenName,
|
||||
m.BusinessShares, m.Weight, m.OverUnder,
|
||||
PenaltyBs = m.PenaltyBs == null || m.PenaltyBs == 0 ? (decimal?)null : Math.Round((decimal)m.PenaltyBs, 2),
|
||||
m.SharesActive, m.Weight, m.OverUnder,
|
||||
PenaltyShares = m.PenaltyShares == null || m.PenaltyShares == 0 ? (decimal?)null : Math.Round((decimal)m.PenaltyShares, 2),
|
||||
PenaltyAc = m.PenaltyAc == null ? (decimal?)null : Math.Round((decimal)m.PenaltyAc, 2),
|
||||
m.Adjust,
|
||||
AdjustAmount = m.AdjustAmount == null ? (decimal?)null : Math.Round((decimal)m.AdjustAmount, 2),
|
||||
CustomAmount = m.Custom?.Amount,
|
||||
ModAbs = m.Custom?.ModAbs,
|
||||
ModRel = m.Custom?.ModRel,
|
||||
m.Custom?.ModAbs,
|
||||
m.Custom?.ModRel,
|
||||
})
|
||||
.Select(m => new {
|
||||
m.MgNr, m.Name, m.GivenName,
|
||||
m.BusinessShares, m.Weight, m.OverUnder,
|
||||
m.PenaltyBs, m.PenaltyAc, m.Adjust, m.AdjustAmount, m.CustomAmount, m.ModAbs, m.ModRel,
|
||||
Total = (m.PenaltyBs ?? 0) + (m.PenaltyAc ?? 0) + (m.AdjustAmount ?? 0) + (m.CustomAmount ?? 0),
|
||||
m.SharesActive, m.Weight, m.OverUnder,
|
||||
m.PenaltyShares, m.PenaltyAc, m.Adjust, m.AdjustAmount, m.CustomAmount, m.ModAbs, m.ModRel,
|
||||
Total = (m.PenaltyShares ?? 0) + (m.PenaltyAc ?? 0) + (m.AdjustAmount ?? 0) + (m.CustomAmount ?? 0),
|
||||
})
|
||||
.Select(m => new {
|
||||
m.MgNr, m.Name, m.GivenName,
|
||||
m.BusinessShares, m.Weight, m.OverUnder,
|
||||
m.PenaltyBs, m.PenaltyAc, m.Adjust, m.AdjustAmount, m.CustomAmount, m.ModAbs, m.ModRel,
|
||||
m.SharesActive, m.Weight, m.OverUnder,
|
||||
m.PenaltyShares, m.PenaltyAc, m.Adjust, m.AdjustAmount, m.CustomAmount, m.ModAbs, m.ModRel,
|
||||
m.Total,
|
||||
Background = m.Weight == 0 ? Brushes.Orange : m.Weight / 2 < -m.Total ? Brushes.Red : Brushes.White,
|
||||
Foreground = m.Total == 0 ? Brushes.Gray : Brushes.Black,
|
||||
})
|
||||
.Where(m => m.OverUnder != null || m.Adjust != null || m.PenaltyBs != null || m.PenaltyAc != null || m.CustomAmount != null || m.ModAbs != null || m.ModRel != null)
|
||||
.Where(m => m.OverUnder != null || m.Adjust != null || m.PenaltyShares != null || m.PenaltyAc != null || m.CustomAmount != null || m.ModAbs != null || m.ModRel != null)
|
||||
.OrderByDescending(m => m.OverUnder ?? 0)
|
||||
.ThenBy(m => m.Name)
|
||||
.ThenBy(m => m.GivenName)
|
||||
@@ -136,7 +136,7 @@ namespace Elwig.Windows {
|
||||
MemberList.ItemsSource = list;
|
||||
|
||||
var sym = season.Currency.Symbol ?? season.Currency.Code;
|
||||
PenaltyBusinessShares.Text = $"{list.Count(r => r.PenaltyBs != null && r.PenaltyBs != 0)} Mg. / {list.Sum(r => r.PenaltyBs):N2} {sym}";
|
||||
PenaltyBusinessShares.Text = $"{list.Count(r => r.PenaltyShares != null && r.PenaltyShares != 0)} Mg. / {list.Sum(r => r.PenaltyShares):N2} {sym}";
|
||||
PenaltyAreaCommitments.Text = $"{list.Count(r => r.PenaltyAc != null && r.PenaltyAc != 0)} Mg. / {list.Sum(r => r.PenaltyAc):N2} {sym}";
|
||||
AutoBusinessShareAdjustment.Text = $"{list.Count(r => r.Adjust > 0)} Mg. / {list.Sum(r => r.Adjust)} GA / {list.Sum(r => r.AdjustAmount):N2} {sym}";
|
||||
CustomModifiers.Text = $"{list.Count(r => r.CustomAmount != null)} Mg. / {list.Sum(r => r.CustomAmount):N2} {sym}";
|
||||
@@ -147,25 +147,25 @@ namespace Elwig.Windows {
|
||||
CustomAmountInput.Unit = sym;
|
||||
}
|
||||
|
||||
private async void AutoAdjustBsButton_Click(object sender, RoutedEventArgs evt) {
|
||||
private async void AutoAdjustSharesButton_Click(object sender, RoutedEventArgs evt) {
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
try {
|
||||
int? kg = AllowanceKgInput.Text == "" ? null : int.Parse(AllowanceKgInput.Text);
|
||||
double? bs = AllowanceBsInput.Text == "" ? null : double.Parse(AllowanceBsInput.Text);
|
||||
int? kgPerBs = AllowanceKgPerBsInput.Text == "" ? null : int.Parse(AllowanceKgPerBsInput.Text);
|
||||
double? shares = AllowanceShareInput.Text == "" ? null : double.Parse(AllowanceShareInput.Text);
|
||||
int? kgPerShare = AllowanceKgPerShareInput.Text == "" ? null : int.Parse(AllowanceKgPerShareInput.Text);
|
||||
double? percent = AllowancePercentInput.Text == "" ? null : double.Parse(AllowancePercentInput.Text);
|
||||
int? minBs = MinBsInput.Text == "" ? null : int.Parse(MinBsInput.Text);
|
||||
int? minShares = MinSharesInput.Text == "" ? null : int.Parse(MinSharesInput.Text);
|
||||
|
||||
App.Client.AutoAdjustBs.AllowanceKg = kg;
|
||||
App.Client.AutoAdjustBs.AllowanceBs = bs;
|
||||
App.Client.AutoAdjustBs.AllowanceKgPerBs = kgPerBs;
|
||||
App.Client.AutoAdjustBs.AllowancePercent = percent;
|
||||
App.Client.AutoAdjustBs.MinBs = minBs;
|
||||
App.Client.AutoAdjustShares.AllowanceKg = kg;
|
||||
App.Client.AutoAdjustShares.AllowanceShares = shares;
|
||||
App.Client.AutoAdjustShares.AllowanceKgPerShare = kgPerShare;
|
||||
App.Client.AutoAdjustShares.AllowancePercent = percent;
|
||||
App.Client.AutoAdjustShares.MinShares = minShares;
|
||||
|
||||
await Task.Run(async () => {
|
||||
await App.Client.UpdateValues();
|
||||
var b = await Billing.Create(Year);
|
||||
await b.AutoAdjustBusinessShares(new DateOnly(Year, 11, 30), kg ?? default, bs ?? default, kgPerBs ?? default, percent / 100.0 ?? default, minBs ?? default);
|
||||
await b.AutoAdjustBusinessShares(new DateOnly(Year, 11, 30), kg ?? default, shares ?? default, kgPerShare ?? default, percent / 100.0 ?? default, minShares ?? default);
|
||||
});
|
||||
App.HintContextChange();
|
||||
} catch (Exception exc) {
|
||||
@@ -174,7 +174,7 @@ namespace Elwig.Windows {
|
||||
Mouse.OverrideCursor = null;
|
||||
}
|
||||
|
||||
private async void UnAdjustBsButton_Click(object sender, RoutedEventArgs evt) {
|
||||
private async void UnAdjustSharesButton_Click(object sender, RoutedEventArgs evt) {
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
try {
|
||||
await Task.Run(async () => {
|
||||
@@ -196,7 +196,7 @@ namespace Elwig.Windows {
|
||||
Validator.CheckInteger((TextBox)sender, false, 6);
|
||||
}
|
||||
|
||||
private void BsInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
private void SharesInput_TextChanged(object sender, TextChangedEventArgs evt) {
|
||||
Validator.CheckInteger((TextBox)sender, false, 3);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ INSERT INTO area_commitment (fbnr, revnr, mgnr, vtrgid, cultid, area, gstnr, yea
|
||||
( 2, 1, 101, 'GV', 'KIP', 10000, '123/5', 2025, 2030),
|
||||
( 3, 1, 101, 'GV', 'KIP', 10000, '123/6', 2021, 2031);
|
||||
|
||||
INSERT INTO season (year, currency, min_kg_per_bs, max_kg_per_bs, penalty_per_kg, penalty_amount, penalty_none, start_date, end_date) VALUES
|
||||
(2020, 'EUR', 1000, 2000, NULL, NULL, NULL, NULL, NULL),
|
||||
(2021, 'EUR', 2000, 4000, NULL, NULL, NULL, NULL, NULL);
|
||||
INSERT INTO season (year, currency, min_kg_per_share, max_kg_per_share, start_date, end_date) VALUES
|
||||
(2020, 'EUR', 1000, 2000, NULL, NULL),
|
||||
(2021, 'EUR', 2000, 4000, NULL, NULL);
|
||||
|
||||
INSERT INTO modifier (year, modid, ordering, name, abs, rel, active) VALUES
|
||||
(2020, 'S', 0, 'Geschädigte Trauben', NULL, -0.1, TRUE),
|
||||
|
||||
@@ -6,8 +6,8 @@ INSERT INTO wine_cultivation (cultid, name, description) VALUES
|
||||
INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES
|
||||
('K', 'Kabinett', TRUE, NULL, FALSE, 0);
|
||||
|
||||
INSERT INTO season (year, currency, min_kg_per_bs, max_kg_per_bs, penalty_per_kg, penalty_amount, penalty_none, start_date, end_date) VALUES
|
||||
(2020, 'EUR', 1000, 2000, NULL, NULL, NULL, NULL, NULL);
|
||||
INSERT INTO season (year, currency, min_kg_per_share, max_kg_per_share, start_date, end_date) VALUES
|
||||
(2020, 'EUR', 1000, 2000, NULL, NULL);
|
||||
|
||||
INSERT INTO delivery_schedule (year, dsnr, date, zwstid, description, max_weight, ancmt_from, ancmt_to) VALUES
|
||||
(2020, 1, '2020-10-01', 'X', 'GV Kabinettaktion', 100000, NULL, NULL);
|
||||
|
||||
@@ -42,10 +42,10 @@ INSERT INTO area_commitment (fbnr, revnr, mgnr, vtrgid, cultid, area, gstnr, yea
|
||||
( 4, 1, 204, 'GV', NULL, 10000, '123/3', 2021, 2031);
|
||||
|
||||
|
||||
INSERT INTO season (year, currency, min_kg_per_bs, max_kg_per_bs, penalty_per_kg, penalty_amount, penalty_none, start_date, end_date) VALUES
|
||||
(2021, 'EUR', 2000, 4000, NULL, NULL, NULL, NULL, NULL),
|
||||
(2022, 'EUR', 2000, 4000, NULL, NULL, NULL, NULL, NULL),
|
||||
(2023, 'EUR', 2000, 4000, NULL, NULL, NULL, NULL, NULL);
|
||||
INSERT INTO season (year, currency, min_kg_per_share, max_kg_per_share, start_date, end_date) VALUES
|
||||
(2021, 'EUR', 2000, 4000, NULL, NULL),
|
||||
(2022, 'EUR', 2000, 4000, NULL, NULL),
|
||||
(2023, 'EUR', 2000, 4000, NULL, NULL);
|
||||
|
||||
INSERT INTO modifier (year, modid, ordering, name, abs, rel, active) VALUES
|
||||
(2021, 'S', 0, 'Geschädigte Trauben', NULL, -0.1, TRUE),
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Tests.UnitTests.ServiceTests {
|
||||
Assert.That(m.Address, Is.EqualTo("Neubaugasse 1"));
|
||||
Assert.That(m.PostalDest.AtPlz?.Plz, Is.EqualTo(2120));
|
||||
Assert.That(m.PostalDest.AtPlz?.Ort.Name, Is.EqualTo("Wolkersdorf im Weinviertel"));
|
||||
Assert.That(m.BusinessShares, Is.EqualTo(1));
|
||||
Assert.That(m.Shares, Is.EqualTo(1));
|
||||
Assert.That(m.DefaultKg?.Name, Is.EqualTo("Wolkersdorf"));
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Tests.UnitTests.ServiceTests {
|
||||
Assert.That(m.BillingAddress?.PostalDest.AtPlz?.Plz, Is.EqualTo(2120));
|
||||
Assert.That(m.BillingAddress?.PostalDest.AtPlz?.Ort.Name, Is.EqualTo("Wolkersdorf im Weinviertel"));
|
||||
|
||||
Assert.That(m.BusinessShares, Is.EqualTo(10));
|
||||
Assert.That(m.Shares, Is.EqualTo(10));
|
||||
Assert.That(m.AccountingNr, Is.EqualTo("330999"));
|
||||
Assert.That(m.DefaultKg?.Name, Is.EqualTo("Wolkersdorf"));
|
||||
Assert.That(m.Comment, Is.EqualTo("Ich bin eine Anmerkung"));
|
||||
|
||||
@@ -1 +1 @@
|
||||
curl --fail -s -L "https://elwig.at/files/create.sql?v=39" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"
|
||||
curl --fail -s -L "https://elwig.at/files/create.sql?v=40" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"
|
||||
|
||||
Reference in New Issue
Block a user