diff --git a/Elwig/Documents/DeliveryConfirmation.cs b/Elwig/Documents/DeliveryConfirmation.cs index 4fa1947..f5fe519 100644 --- a/Elwig/Documents/DeliveryConfirmation.cs +++ b/Elwig/Documents/DeliveryConfirmation.cs @@ -10,7 +10,7 @@ namespace Elwig.Documents { public Season Season; public DeliveryConfirmationData Data; public string? Text = App.Client.TextDeliveryConfirmation; - public Dictionary MemberBuckets; + public Dictionary MemberBuckets; public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationData data) : base($"Anlieferungsbestätigung {year}", m) { diff --git a/Elwig/Documents/DeliveryConfirmation.cshtml b/Elwig/Documents/DeliveryConfirmation.cshtml index 152cd72..b467ed0 100644 --- a/Elwig/Documents/DeliveryConfirmation.cshtml +++ b/Elwig/Documents/DeliveryConfirmation.cshtml @@ -125,11 +125,11 @@ $"{(mode != 2 ? "" : obligation == 0 && right == 0 ? "-" : $"{payment:N0}")}" + $"{sum:N0}"; } - var mBuckets = Model.MemberBuckets.Where(b => b.Value.Item2 > 0 || b.Value.Item3 > 0 || b.Value.Item4 > 0).ToList(); - var fbVars = mBuckets.Where(b => b.Value.Item2 > 0 || b.Value.Item3 > 0).Select(b => b.Key.Replace("_", "")).Order().ToArray(); - var fbs = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length == 2).OrderBy(b => b.Value.Item1); - var vtr = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length > 2).OrderBy(b => b.Value.Item1); - var rem = mBuckets.Where(b => !fbVars.Contains(b.Key)).OrderBy(b => b.Value.Item1); + var mBuckets = Model.MemberBuckets.Where(b => b.Value.Right > 0 || b.Value.Obligation > 0 || b.Value.Delivery > 0).ToList(); + var fbVars = mBuckets.Where(b => b.Value.Right > 0 || b.Value.Obligation > 0).Select(b => b.Key.Replace("_", "")).Order().ToArray(); + var fbs = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length == 2).OrderBy(b => b.Value.Name); + var vtr = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length > 2).OrderBy(b => b.Value.Name); + var rem = mBuckets.Where(b => !fbVars.Contains(b.Key)).OrderBy(b => b.Value.Name); } Gesamtlieferung lt. gez. GA @@ -143,28 +143,28 @@ @if (rem.Any()) { Sortenaufteilung: } - @foreach (var (id, (name, right, obligation, sum, payment)) in rem) { + @foreach (var (id, b) in rem) { - @name - @Raw(FormatRow(1, obligation, right, sum, payment)) + @b.Name + @Raw(FormatRow(1, b.Obligation, b.Right, b.Delivery, b.Payment)) } @if (fbs.Any()){ Flächenbindungen: } - @foreach (var (id, (name, right, obligation, sum, payment)) in fbs) { + @foreach (var (id, b) in fbs) { - @name - @Raw(FormatRow(2, obligation, right, sum, payment)) + @b.Name + @Raw(FormatRow(2, b.Obligation, b.Right, b.Delivery, b.Payment)) } @if (vtr.Any()) { Verträge: } - @foreach (var (id, (name, right, obligation, sum, payment)) in vtr) { + @foreach (var (id, b) in vtr) { - @name - @Raw(FormatRow(2, obligation, right, sum, payment)) + @b.Name + @Raw(FormatRow(2, b.Obligation, b.Right, b.Delivery, b.Payment)) } diff --git a/Elwig/Documents/DeliveryNote.cs b/Elwig/Documents/DeliveryNote.cs index 3eebc50..8c069c9 100644 --- a/Elwig/Documents/DeliveryNote.cs +++ b/Elwig/Documents/DeliveryNote.cs @@ -7,7 +7,7 @@ namespace Elwig.Documents { public Delivery Delivery; public string? Text; - public Dictionary MemberBuckets; + public Dictionary MemberBuckets; // 0 - none // 1 - GA only diff --git a/Elwig/Documents/DeliveryNote.cshtml b/Elwig/Documents/DeliveryNote.cshtml index beba3fb..463413f 100644 --- a/Elwig/Documents/DeliveryNote.cshtml +++ b/Elwig/Documents/DeliveryNote.cshtml @@ -122,11 +122,11 @@ Flächenbindungen: - @foreach (var (id, (name, right, obligation, sum, _)) in Model.MemberBuckets.OrderBy(b => b.Key)) { - if (right > 0 || obligation > 0 || (sum > 0 && buckets[id[..2]] > 1 && !id.EndsWith('_'))) { + @foreach (var (id, b) in Model.MemberBuckets.OrderBy(b => b.Key)) { + if (b.Right > 0 || b.Obligation > 0 || (b.Delivery > 0 && buckets[id[..2]] > 1 && !id.EndsWith('_'))) { - @name - @Raw(FormatRow(obligation, right, sum)) + @b.Name + @Raw(FormatRow(b.Obligation, b.Right, b.Delivery)) } } diff --git a/Elwig/Documents/MemberDataSheet.cs b/Elwig/Documents/MemberDataSheet.cs index c671fd1..9960e23 100644 --- a/Elwig/Documents/MemberDataSheet.cs +++ b/Elwig/Documents/MemberDataSheet.cs @@ -8,14 +8,12 @@ namespace Elwig.Documents { public Season Season; public int Year = Utils.CurrentYear; - public Dictionary MemberBuckets; - public Dictionary BucketAreas; + public Dictionary MemberBuckets; public MemberDataSheet(Member m, AppDbContext ctx) : base($"Stammdatenblatt {m.AdministrativeName}", m) { DocumentId = $"Stammdatenblatt {m.MgNr}"; Season = ctx.Seasons.Find(Year) ?? throw new ArgumentException("invalid season"); MemberBuckets = ctx.GetMemberBuckets(Year, m.MgNr).GetAwaiter().GetResult(); - BucketAreas = ctx.GetMemberBucketAreas(Year, m.MgNr).GetAwaiter().GetResult(); } } } \ No newline at end of file diff --git a/Elwig/Documents/MemberDataSheet.cshtml b/Elwig/Documents/MemberDataSheet.cshtml index 98b6675..4278b75 100644 --- a/Elwig/Documents/MemberDataSheet.cshtml +++ b/Elwig/Documents/MemberDataSheet.cshtml @@ -259,10 +259,10 @@ $"{(mode == 1 ? "" : obligation == 0 ? "-" : $"{obligation:N0}")}" + $"{(mode == 1 ? "" : right == 0 ? "-" : $"{right:N0}")}"; } - var mBuckets = Model.MemberBuckets.Where(b => b.Value.Item2 > 0 || b.Value.Item3 > 0 || b.Value.Item4 > 0).ToList(); - var fbVars = mBuckets.Where(b => b.Value.Item2 > 0 || b.Value.Item3 > 0).Select(b => b.Key.Replace("_", "")).Order().ToArray(); - var fbs = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length == 2).OrderBy(b => b.Value.Item1); - var vtr = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length > 2).OrderBy(b => b.Value.Item1); + var mBuckets = Model.MemberBuckets.Where(b => b.Value.Right > 0 || b.Value.Obligation > 0 || b.Value.Delivery > 0).ToList(); + var fbVars = mBuckets.Where(b => b.Value.Right > 0 || b.Value.Obligation > 0).Select(b => b.Key.Replace("_", "")).Order().ToArray(); + var fbs = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length == 2).OrderBy(b => b.Value.Name); + var vtr = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length > 2).OrderBy(b => b.Value.Name); } Laut gezeichneten GA @@ -271,24 +271,24 @@ 0, Model.Member.BusinessShares * Model.Season.MinKgPerBusinessShare, Model.Member.BusinessShares * Model.Season.MaxKgPerBusinessShare - )) + )) @if (fbs.Any()) { Flächenbindungen: } - @foreach (var (id, (name, right, obligation, _, _)) in fbs) { + @foreach (var (id, b) in fbs) { - @name - @Raw(FormatRow(2, Model.BucketAreas[id], obligation, right)) + @b.Name + @Raw(FormatRow(2, b.Area, b.Obligation, b.Right)) } @if (vtr.Any()) { Verträge: } - @foreach (var (id, (name, right, obligation, _, _)) in vtr) { + @foreach (var (id, b) in vtr) { - @name - @Raw(FormatRow(2, Model.BucketAreas[id], obligation, right)) + @b.Name + @Raw(FormatRow(2, b.Area, b.Obligation, b.Right)) } diff --git a/Elwig/Helpers/AppDbContext.cs b/Elwig/Helpers/AppDbContext.cs index c62270b..c4accdf 100644 --- a/Elwig/Helpers/AppDbContext.cs +++ b/Elwig/Helpers/AppDbContext.cs @@ -12,6 +12,10 @@ using System.Collections.Generic; using Elwig.Models.Dtos; namespace Elwig.Helpers { + + public record struct AreaComBucket(int Area, int Obligation, int Right); + public record struct MemberBucket(string Name, int Area, int Obligation, int Right, int Delivery, int Payment); + public class AppDbContext : DbContext { public DbSet Countries { get; private set; } @@ -60,10 +64,9 @@ namespace Elwig.Helpers { public static string ConnectionString => $"Data Source=\"{App.Config.DatabaseFile}\"; Foreign Keys=True; Mode=ReadWrite; Cache=Default"; - private readonly Dictionary>> _memberRightsAndObligations = new(); + private readonly Dictionary>> _memberAreaCommitmentBuckets = new(); private readonly Dictionary>> _memberDeliveryBuckets = new(); private readonly Dictionary>> _memberPaymentBuckets = new(); - private readonly Dictionary>> _memberBucketAreas = new(); public AppDbContext() { if (App.Config.DatabaseLog != null) { @@ -203,22 +206,22 @@ namespace Elwig.Helpers { } } - private async Task FetchMemberRightsAndObligations(int year, SqliteConnection? cnx = null) { + private async Task FetchMemberAreaCommitmentBuckets(int year, SqliteConnection? cnx = null) { var ownCnx = cnx == null; cnx ??= await ConnectAsync(); - var buckets = new Dictionary>(); + var buckets = new Dictionary>(); using (var cmd = cnx.CreateCommand()) { - cmd.CommandText = $"SELECT mgnr, bucket, min_kg, max_kg FROM v_area_commitment_bucket WHERE year = {year}"; + cmd.CommandText = $"SELECT mgnr, bucket, area, min_kg, max_kg FROM v_area_commitment_bucket WHERE year = {year}"; using var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var mgnr = reader.GetInt32(0); var vtrgid = reader.GetString(1); if (!buckets.ContainsKey(mgnr)) buckets[mgnr] = new(); - buckets[mgnr][vtrgid] = (reader.GetInt32(3), reader.GetInt32(2)); + buckets[mgnr][vtrgid] = new(reader.GetInt32(2), reader.GetInt32(3), reader.GetInt32(4)); } } if (ownCnx) await cnx.DisposeAsync(); - _memberRightsAndObligations[year] = buckets; + _memberAreaCommitmentBuckets[year] = buckets; } private async Task FetchMemberDeliveryBuckets(int year, SqliteConnection? cnx = null) { @@ -257,32 +260,10 @@ namespace Elwig.Helpers { _memberPaymentBuckets[year] = buckets; } - private async Task FetchMemberBucketAreas(int year, SqliteConnection? cnx = null) { - var ownCnx = cnx == null; - cnx ??= await ConnectAsync(); - var buckets = new Dictionary>(); - using (var cmd = cnx.CreateCommand()) { - cmd.CommandText = $"SELECT mgnr, bucket, area FROM v_area_commitment_bucket_strict WHERE year = {year}"; - using var reader = await cmd.ExecuteReaderAsync(); - while (await reader.ReadAsync()) { - var mgnr = reader.GetInt32(0); - var bucket = reader.GetString(1); - var v = reader.GetInt32(2); - if (!buckets.ContainsKey(mgnr)) buckets[mgnr] = new(); - buckets[mgnr][bucket] = v; - if (bucket.Length > 2) { - buckets[mgnr][bucket[..2]] = buckets[mgnr].GetValueOrDefault(bucket[..2], 0) + v; - } - } - } - if (ownCnx) await cnx.DisposeAsync(); - _memberBucketAreas[year] = buckets; - } - - public async Task> GetMemberRightsAndObligations(int year, int mgnr, SqliteConnection? cnx = null) { - if (!_memberRightsAndObligations.ContainsKey(year)) - await FetchMemberRightsAndObligations(year, cnx); - return _memberRightsAndObligations[year].GetValueOrDefault(mgnr, new()); + public async Task> GetMemberAreaCommitmentBuckets(int year, int mgnr, SqliteConnection? cnx = null) { + if (!_memberAreaCommitmentBuckets.ContainsKey(year)) + await FetchMemberAreaCommitmentBuckets(year, cnx); + return _memberAreaCommitmentBuckets[year].GetValueOrDefault(mgnr, new()); } public async Task> GetMemberDeliveryBuckets(int year, int mgnr, SqliteConnection? cnx = null) { @@ -297,30 +278,25 @@ namespace Elwig.Helpers { return _memberPaymentBuckets[year].GetValueOrDefault(mgnr, new()); } - public async Task> GetMemberBucketAreas(int year, int mgnr, SqliteConnection? cnx = null) { - if (!_memberBucketAreas.ContainsKey(year)) - await FetchMemberBucketAreas(year, cnx); - return _memberBucketAreas[year].GetValueOrDefault(mgnr, new()); - } - - public async Task> GetMemberBuckets(int year, int mgnr, SqliteConnection? cnx = null) { + public async Task> GetMemberBuckets(int year, int mgnr, SqliteConnection? cnx = null) { var ownCnx = cnx == null; cnx ??= await ConnectAsync(); - var rightsAndObligations = await GetMemberRightsAndObligations(year, mgnr, cnx); + var rightsAndObligations = await GetMemberAreaCommitmentBuckets(year, mgnr, cnx); var deliveryBuckets = await GetMemberDeliveryBuckets(year, mgnr, cnx); var paymentBuckets = await GetMemberPaymentBuckets(year, mgnr, cnx); if (ownCnx) await cnx.DisposeAsync(); - var buckets = new Dictionary(); + var buckets = new Dictionary(); foreach (var id in rightsAndObligations.Keys.Union(deliveryBuckets.Keys).Union(paymentBuckets.Keys)) { var variety = await WineVarieties.FindAsync(id[..2]); var attrIds = id[2..]; var attrs = await WineAttributes.Where(a => attrIds.Contains(a.AttrId)).ToListAsync(); var name = (variety?.Name ?? "") + (attrIds == "_" ? " (kein Qual.Wein)" : attrs.Count > 0 ? $" ({string.Join(" / ", attrs.Select(a => a.Name))})" : ""); - buckets[id] = ( + buckets[id] = new( name, - rightsAndObligations.GetValueOrDefault(id).Item1, - rightsAndObligations.GetValueOrDefault(id).Item2, + rightsAndObligations.GetValueOrDefault(id).Area, + rightsAndObligations.GetValueOrDefault(id).Obligation, + rightsAndObligations.GetValueOrDefault(id).Right, deliveryBuckets.GetValueOrDefault(id), paymentBuckets.GetValueOrDefault(id) ); diff --git a/Elwig/Helpers/AppDbUpdater.cs b/Elwig/Helpers/AppDbUpdater.cs index 36f4f36..4d192db 100644 --- a/Elwig/Helpers/AppDbUpdater.cs +++ b/Elwig/Helpers/AppDbUpdater.cs @@ -5,12 +5,13 @@ using System.Windows; namespace Elwig.Helpers { public static class AppDbUpdater { - public static readonly int RequiredSchemaVersion = 9; + public static readonly int RequiredSchemaVersion = 10; private static int _versionOffset = 0; private static readonly Action[] _updaters = new[] { UpdateDbSchema_1_To_2, UpdateDbSchema_2_To_3, UpdateDbSchema_3_To_4, UpdateDbSchema_4_To_5, UpdateDbSchema_5_To_6, UpdateDBSchema_6_To_7, UpdateDbSchema_7_To_8, UpdateDbSchema_8_To_9, + UpdateDbSchema_9_To_10, }; private static void ExecuteNonQuery(SqliteConnection cnx, string sql) { @@ -714,5 +715,26 @@ namespace Elwig.Helpers { END; """); } + + private static void UpdateDbSchema_9_To_10(SqliteConnection cnx) { + ExecuteNonQuery(cnx, "UPDATE wine_quality_level SET min_kmw = 10.6 WHERE qualid = 'RSW'"); + ExecuteNonQuery(cnx, "DROP VIEW v_area_commitment_bucket"); + ExecuteNonQuery(cnx, """ + CREATE VIEW v_area_commitment_bucket AS + SELECT year, mgnr, bucket, area, min_kg, max_kg + FROM v_area_commitment_bucket_strict + WHERE attrid IS NOT NULL + UNION ALL + SELECT b.year, b.mgnr, b.sortid, + SUM(b.area) AS area, + SUM(b.min_kg) AS min_kg, + SUM(b.upper_max_kg) AS max_kg + FROM v_area_commitment_bucket_strict b + LEFT JOIN wine_attribute a ON a.attrid = b.attrid + WHERE a.strict IS NULL OR a.strict = FALSE + GROUP BY b.year, b.mgnr, b.sortid + ORDER BY year, mgnr, bucket; + """); + } } } diff --git a/Elwig/Helpers/Billing/Billing.cs b/Elwig/Helpers/Billing/Billing.cs index f277da4..6c67344 100644 --- a/Elwig/Helpers/Billing/Billing.cs +++ b/Elwig/Helpers/Billing/Billing.cs @@ -41,7 +41,7 @@ namespace Elwig.Helpers.Billing { var attrVals = Context.WineAttributes.ToDictionary(a => a.AttrId, a => (a.IsStrict, a.FillLower)); var attrForced = attrVals.Where(a => a.Value.IsStrict && a.Value.FillLower == 0).Select(a => a.Key).ToArray(); using var cnx = await AppDbContext.ConnectAsync(); - await Context.GetMemberRightsAndObligations(Year, 0, cnx); + await Context.GetMemberAreaCommitmentBuckets(Year, 0, cnx); var inserts = new List<(int, int, int, string, int)>(); var deliveries = new List<(int, int, int, string, int, double, string, string?, string[], bool?)>(); @@ -66,11 +66,11 @@ namespace Elwig.Helpers.Billing { } int lastMgNr = 0; - Dictionary? rightsAndObligations = null; + Dictionary? rightsAndObligations = null; Dictionary used = new(); foreach (var (mgnr, did, dpnr, sortid, weight, kmw, qualid, attrid, modifiers, gebunden) in deliveries) { if (lastMgNr != mgnr) { - rightsAndObligations = await Context.GetMemberRightsAndObligations(Year, mgnr); + rightsAndObligations = await Context.GetMemberAreaCommitmentBuckets(Year, mgnr); used = new(); } if ((honorGebunden && gebunden == false) || @@ -94,8 +94,8 @@ namespace Elwig.Helpers.Billing { if (rightsAndObligations.ContainsKey(key)) { int i = (c == 0) ? 1 : 2; var u = used.GetValueOrDefault(key, 0); - var vr = Math.Max(0, Math.Min(rightsAndObligations[key].Item1 - u, w)); - var vo = Math.Max(0, Math.Min(rightsAndObligations[key].Item2 - u, w)); + var vr = Math.Max(0, Math.Min(rightsAndObligations[key].Right - u, w)); + var vo = Math.Max(0, Math.Min(rightsAndObligations[key].Obligation - u, w)); var v = (attributes.Length == c || attributes.Select(a => !attrVals[a].IsStrict ? 2 : attrVals[a].FillLower).Min() == 2) ? vr : vo; used[key] = u + v; if (key.Length > 2 && !isStrict) used[key[..2]] = used.GetValueOrDefault(key[..2], 0) + v;