Compare commits
	
		
			2 Commits
		
	
	
		
			9f67448b72
			...
			6b6373238a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6b6373238a | |||
| eebddf0527 | 
| @@ -10,7 +10,7 @@ namespace Elwig.Documents { | |||||||
|         public Credit Credit; |         public Credit Credit; | ||||||
|         public string? Text; |         public string? Text; | ||||||
|         public string CurrencySymbol; |         public string CurrencySymbol; | ||||||
|         public string[] BinNames; |         public string[] BucketNames; | ||||||
|         public int Precision; |         public int Precision; | ||||||
|         public IEnumerable<DeliveryPart> Parts; |         public IEnumerable<DeliveryPart> Parts; | ||||||
|  |  | ||||||
| @@ -27,7 +27,7 @@ namespace Elwig.Documents { | |||||||
|             Text = App.Client.TextDeliveryNote; |             Text = App.Client.TextDeliveryNote; | ||||||
|             DocumentId = $"Tr.-Gutschr. {c.TgId}"; |             DocumentId = $"Tr.-Gutschr. {c.TgId}"; | ||||||
|             CurrencySymbol = c.Payment.Variant.Season.Currency.Symbol ?? c.Payment.Variant.Season.Currency.Code; |             CurrencySymbol = c.Payment.Variant.Season.Currency.Symbol ?? c.Payment.Variant.Season.Currency.Code; | ||||||
|             BinNames = new string[0]; // FIXME |             BucketNames = new string[0]; // FIXME | ||||||
|             Precision = c.Payment.Variant.Season.Precision; |             Precision = c.Payment.Variant.Season.Precision; | ||||||
|             Parts = ctx.DeliveryParts.FromSql($""" |             Parts = ctx.DeliveryParts.FromSql($""" | ||||||
|                 SELECT p.* |                 SELECT p.* | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| @{ Layout = "BusinessDocument"; } | @{ Layout = "BusinessDocument"; } | ||||||
| <link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\CreditNote.css"/> | <link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\CreditNote.css"/> | ||||||
| @{ | @{ | ||||||
|     var binNum = Model.BinNames.Length; |     var bucketNum = Model.BucketNames.Length; | ||||||
| } | } | ||||||
| <main> | <main> | ||||||
|     <h1>@Model.Title</h1> |     <h1>@Model.Title</h1> | ||||||
| @@ -30,7 +30,7 @@ | |||||||
|                 <th rowspan="3" style="text-align: left;">Attribut</th> |                 <th rowspan="3" style="text-align: left;">Attribut</th> | ||||||
|                 <th rowspan="2" colspan="2">Gradation</th> |                 <th rowspan="2" colspan="2">Gradation</th> | ||||||
|                 <th colspan="2">Zu-/Abschläge</th> |                 <th colspan="2">Zu-/Abschläge</th> | ||||||
|                 <th colspan="2">@Raw(string.Join("<br/>", Model.BinNames))</th> |                 <th colspan="2">@Raw(string.Join("<br/>", Model.BucketNames))</th> | ||||||
|                 <th rowspan="2">Betrag</th> |                 <th rowspan="2">Betrag</th> | ||||||
|             </tr> |             </tr> | ||||||
|             <tr> |             <tr> | ||||||
| @@ -61,23 +61,23 @@ | |||||||
|                 var pmt = part.Payment; |                 var pmt = part.Payment; | ||||||
|                 var abs = pmt?.ModAbs == null || pmt?.ModAbs == 0 ? "-" : pmt?.ModAbs.ToString("0." + string.Concat(Enumerable.Repeat('0', Model.Precision))); |                 var abs = pmt?.ModAbs == null || pmt?.ModAbs == 0 ? "-" : pmt?.ModAbs.ToString("0." + string.Concat(Enumerable.Repeat('0', Model.Precision))); | ||||||
|                 var rel = pmt?.ModRel == null || pmt?.ModRel == 0 ? "-" : $"{pmt?.ModRel * 100:0.00##}"; |                 var rel = pmt?.ModRel == null || pmt?.ModRel == 0 ? "-" : $"{pmt?.ModRel * 100:0.00##}"; | ||||||
|                 <tr class="first @(binNum <= 1 ? "last" : "") @(last != null && last != part.SortId ? "new" : "")"> |                 <tr class="first @(bucketNum <= 1 ? "last" : "") @(last != null && last != part.SortId ? "new" : "")"> | ||||||
|                     <td rowspan="@binNum" class="lsnr">@part.Delivery.LsNr</td> |                     <td rowspan="@bucketNum" class="lsnr">@part.Delivery.LsNr</td> | ||||||
|                     <td rowspan="@binNum" class="dpnr">@part.DPNr</td> |                     <td rowspan="@bucketNum" class="dpnr">@part.DPNr</td> | ||||||
|                     <td rowspan="@binNum" class="variant">@part.Variant.Name</td> |                     <td rowspan="@bucketNum" class="variant">@part.Variant.Name</td> | ||||||
|                     <td rowspan="@binNum" class="attribute">@part.Attribute?.Name</td> |                     <td rowspan="@bucketNum" class="attribute">@part.Attribute?.Name</td> | ||||||
|                     <td rowspan="@binNum" class="oe">@($"{part.Oe:N0}")</td> |                     <td rowspan="@bucketNum" class="oe">@($"{part.Oe:N0}")</td> | ||||||
|                     <td rowspan="@binNum" class="kmw">@($"{part.Kmw:N1}")</td> |                     <td rowspan="@bucketNum" class="kmw">@($"{part.Kmw:N1}")</td> | ||||||
|                     <td rowspan="@binNum" class="abs">@abs</td> |                     <td rowspan="@bucketNum" class="abs">@abs</td> | ||||||
|                     <td rowspan="@binNum" class="rel">@rel</td> |                     <td rowspan="@bucketNum" class="rel">@rel</td> | ||||||
|                     <!--FIXME price--> |                     <!--FIXME price--> | ||||||
|                     @Raw(FormatRow(pmt?.DeliveryPart.Bins?.ElementAtOrDefault(0)?.Value, 0)) |                     @Raw(FormatRow(pmt?.DeliveryPart.Buckets?.ElementAtOrDefault(0)?.Value, 0)) | ||||||
|                     <td rowspan="@binNum" class="amount sum">@($"{pmt?.Amount:N2}")</td> |                     <td rowspan="@bucketNum" class="amount sum">@($"{pmt?.Amount:N2}")</td> | ||||||
|                 </tr> |                 </tr> | ||||||
|                 @for (int i = 1; i < binNum; i++) { |                 @for (int i = 1; i < bucketNum; i++) { | ||||||
|                     <tr class="@(i == binNum - 1 ? "last" : "")"> |                     <tr class="@(i == bucketNum - 1 ? "last" : "")"> | ||||||
|                         <!--FIXME price--> |                         <!--FIXME price--> | ||||||
|                         @Raw(FormatRow(pmt?.DeliveryPart.Bins?.ElementAtOrDefault(i)?.Value, 0)) |                         @Raw(FormatRow(pmt?.DeliveryPart.Buckets?.ElementAtOrDefault(i)?.Value, 0)) | ||||||
|                     </tr> |                     </tr> | ||||||
|                 } |                 } | ||||||
|                 last = part.SortId; |                 last = part.SortId; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ namespace Elwig.Documents { | |||||||
|         public Season Season; |         public Season Season; | ||||||
|         public IEnumerable<DeliveryPart> Deliveries; |         public IEnumerable<DeliveryPart> Deliveries; | ||||||
|         public string? Text = App.Client.TextDeliveryConfirmation; |         public string? Text = App.Client.TextDeliveryConfirmation; | ||||||
|         public Dictionary<string, (string, int, int, int, int)> MemberBins; |         public Dictionary<string, (string, int, int, int, int)> MemberBuckets; | ||||||
|  |  | ||||||
|         public DeliveryConfirmation(AppDbContext ctx, int year, Member m, IEnumerable<DeliveryPart>? deliveries = null) : |         public DeliveryConfirmation(AppDbContext ctx, int year, Member m, IEnumerable<DeliveryPart>? deliveries = null) : | ||||||
|             base($"Anlieferungsbestätigung {year}", m) { |             base($"Anlieferungsbestätigung {year}", m) { | ||||||
| @@ -28,7 +28,7 @@ namespace Elwig.Documents { | |||||||
|                 ORDER BY v.sortid, v.abgewertet ASC, v.attribute_prio DESC, COALESCE(v.attrid, '~'), v.kmw DESC, v.lsnr, v.dpnr |                 ORDER BY v.sortid, v.abgewertet ASC, v.attribute_prio DESC, COALESCE(v.attrid, '~'), v.kmw DESC, v.lsnr, v.dpnr | ||||||
|                 """) |                 """) | ||||||
|                 .ToList(); |                 .ToList(); | ||||||
|             MemberBins = ctx.GetMemberBins(Season.Year, m.MgNr).GetAwaiter().GetResult(); |             MemberBuckets = ctx.GetMemberBuckets(Season.Year, m.MgNr).GetAwaiter().GetResult(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -44,11 +44,11 @@ | |||||||
|                 var lastSortId = ""; |                 var lastSortId = ""; | ||||||
|             } |             } | ||||||
|             @foreach (var p in Model.Deliveries) { |             @foreach (var p in Model.Deliveries) { | ||||||
|                 var bins = p.Bins.Where(b => b.Value > 0).OrderByDescending(b => b.BktNr).ToArray(); |                 var buckets = p.Buckets.Where(b => b.Value > 0).OrderByDescending(b => b.BktNr).ToArray(); | ||||||
|                 var rowsBins = bins.Length; |                 var rowsBuckets = buckets.Length; | ||||||
|                 var mods = p.Modifiers.Select(m => m.Name).ToArray(); |                 var mods = p.Modifiers.Select(m => m.Name).ToArray(); | ||||||
|                 var rowsMod = mods.Length + 1; |                 var rowsMod = mods.Length + 1; | ||||||
|                 var rows = Math.Max(rowsBins, rowsMod); |                 var rows = Math.Max(rowsBuckets, rowsMod); | ||||||
|                 var first = true; |                 var first = true; | ||||||
|                 @for (int i = 0; i < rows; i++) { |                 @for (int i = 0; i < rows; i++) { | ||||||
|                     <tr class="@(first ? "first" : "") @(p.SortId != lastSortId && lastSortId != "" ? "new": "") @(rows > i + 1 ? "trailing" : "")"> |                     <tr class="@(first ? "first" : "") @(p.SortId != lastSortId && lastSortId != "" ? "new": "") @(rows > i + 1 ? "trailing" : "")"> | ||||||
| @@ -66,14 +66,14 @@ | |||||||
|                         } else if (i > 0) { |                         } else if (i > 0) { | ||||||
|                             <td colspan="3"></td> |                             <td colspan="3"></td> | ||||||
|                         } |                         } | ||||||
|                         @if (i < bins.Length) { |                         @if (i < buckets.Length) { | ||||||
|                             var bin = bins[i]; |                             var bucket = buckets[i]; | ||||||
|                             <td class="geb">@(bin.Discr == "_" ? "ungeb." : $"geb. {p.SortId}{bin.Discr}"):</td> |                             <td class="geb">@(bucket.Discr == "_" ? "ungeb." : $"geb. {p.SortId}{bucket.Discr}"):</td> | ||||||
|                             <td class="weight">@($"{bin.Value:N0}")</td> |                             <td class="weight">@($"{bucket.Value:N0}")</td> | ||||||
|                         } else { |                         } else { | ||||||
|                             <td colspan="2"></td> |                             <td colspan="2"></td> | ||||||
|                         } |                         } | ||||||
|                         @if (i == bins.Length - 1) { |                         @if (i == buckets.Length - 1) { | ||||||
|                             <td class="weight">@($"{p.Weight:N0}")</td> |                             <td class="weight">@($"{p.Weight:N0}")</td> | ||||||
|                         } else { |                         } else { | ||||||
|                             <td></td> |                             <td></td> | ||||||
| @@ -129,11 +129,11 @@ | |||||||
|                         $"<td>{(mode != 2 ? "" : obligation == 0 && right == 0 ? "-" : $"{payment:N0}")}</td>" + |                         $"<td>{(mode != 2 ? "" : obligation == 0 && right == 0 ? "-" : $"{payment:N0}")}</td>" + | ||||||
|                         $"<td>{sum:N0}</td>"; |                         $"<td>{sum:N0}</td>"; | ||||||
|                 } |                 } | ||||||
|                 var mBins = Model.MemberBins.Where(b => b.Value.Item2 > 0 || b.Value.Item3 > 0 || b.Value.Item4 > 0).ToList(); |                 var mBuckets = Model.MemberBuckets.Where(b => b.Value.Item2 > 0 || b.Value.Item3 > 0 || b.Value.Item4 > 0).ToList(); | ||||||
|                 var fbVars = mBins.Where(b => b.Value.Item2 > 0 || b.Value.Item3 > 0).Select(b => b.Key.Replace("_", "")).Order().ToArray(); |                 var fbVars = mBuckets.Where(b => b.Value.Item2 > 0 || b.Value.Item3 > 0).Select(b => b.Key.Replace("_", "")).Order().ToArray(); | ||||||
|                 var fbs = mBins.Where(b => fbVars.Contains(b.Key) && b.Key.Length == 2).OrderBy(b => b.Value.Item1); |                 var fbs = mBuckets.Where(b => fbVars.Contains(b.Key) && b.Key.Length == 2).OrderBy(b => b.Value.Item1); | ||||||
|                 var vtr = mBins.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 = mBins.Where(b => !fbVars.Contains(b.Key)).OrderBy(b => b.Value.Item1); |                 var rem = mBuckets.Where(b => !fbVars.Contains(b.Key)).OrderBy(b => b.Value.Item1); | ||||||
|             } |             } | ||||||
|             <tr> |             <tr> | ||||||
|                 <th>Gesamtlieferung lt. gez. GA</th> |                 <th>Gesamtlieferung lt. gez. GA</th> | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ namespace Elwig.Documents { | |||||||
|  |  | ||||||
|         public Delivery Delivery; |         public Delivery Delivery; | ||||||
|         public string? Text; |         public string? Text; | ||||||
|         public Dictionary<string, (string, int, int, int, int)> MemberBins; |         public Dictionary<string, (string, int, int, int, int)> MemberBuckets; | ||||||
|  |  | ||||||
|         // 0 - none |         // 0 - none | ||||||
|         // 1 - GA only |         // 1 - GA only | ||||||
| @@ -27,7 +27,7 @@ namespace Elwig.Documents { | |||||||
|                 $"</tbody></table>"; |                 $"</tbody></table>"; | ||||||
|             Text = App.Client.TextDeliveryNote; |             Text = App.Client.TextDeliveryNote; | ||||||
|             DocumentId = d.LsNr; |             DocumentId = d.LsNr; | ||||||
|             MemberBins = ctx.GetMemberBins(d.Year, d.Member.MgNr).GetAwaiter().GetResult(); |             MemberBuckets = ctx.GetMemberBuckets(d.Year, d.Member.MgNr).GetAwaiter().GetResult(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -108,7 +108,7 @@ | |||||||
|                         $"<td>{sum:N0}</td>"; |                         $"<td>{sum:N0}</td>"; | ||||||
|                 } |                 } | ||||||
|                 var sortids = Model.Delivery.Parts.Select(p => p.SortId).ToList(); |                 var sortids = Model.Delivery.Parts.Select(p => p.SortId).ToList(); | ||||||
|                 var bins = Model.MemberBins.GroupBy(b => b.Key[..2]).ToDictionary(g => g.Key, g => g.Count()); |                 var buckets = Model.MemberBuckets.GroupBy(b => b.Key[..2]).ToDictionary(g => g.Key, g => g.Count()); | ||||||
|             } |             } | ||||||
|             <tr> |             <tr> | ||||||
|                 <th>Gesamtlieferung lt. gez. GA</th> |                 <th>Gesamtlieferung lt. gez. GA</th> | ||||||
| @@ -122,8 +122,8 @@ | |||||||
|                 <tr class="subheading"> |                 <tr class="subheading"> | ||||||
|                     <th>Flächenbindungen:</th> |                     <th>Flächenbindungen:</th> | ||||||
|                 </tr> |                 </tr> | ||||||
|                 @foreach (var (id, (name, right, obligation, sum, _)) in Model.MemberBins.OrderBy(b => b.Key)) { |                     @foreach (var (id, (name, right, obligation, sum, _)) in Model.MemberBuckets.OrderBy(b => b.Key)) { | ||||||
|                     if (right > 0 || obligation > 0 || (sum > 0 && bins[id[..2]] > 1 && !id.EndsWith('_'))) { |                     if (right > 0 || obligation > 0 || (sum > 0 && buckets[id[..2]] > 1 && !id.EndsWith('_'))) { | ||||||
|                         <tr class="@(sortids.Contains(id[..2]) ? "" : "optional")"> |                         <tr class="@(sortids.Contains(id[..2]) ? "" : "optional")"> | ||||||
|                             <th>@name</th> |                             <th>@name</th> | ||||||
|                             @Raw(FormatRow(obligation, right, sum)) |                             @Raw(FormatRow(obligation, right, sum)) | ||||||
|   | |||||||
| @@ -53,8 +53,8 @@ namespace Elwig.Helpers { | |||||||
|         public static string ConnectionString => $"Data Source=\"{App.Config.DatabaseFile}\"; Foreign Keys=True; Mode=ReadWrite; Cache=Default"; |         public static string ConnectionString => $"Data Source=\"{App.Config.DatabaseFile}\"; Foreign Keys=True; Mode=ReadWrite; Cache=Default"; | ||||||
|  |  | ||||||
|         private readonly Dictionary<int, Dictionary<int, Dictionary<string, (int, int)>>> _memberRightsAndObligations = new(); |         private readonly Dictionary<int, Dictionary<int, Dictionary<string, (int, int)>>> _memberRightsAndObligations = new(); | ||||||
|         private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBins = new(); |         private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBuckets = new(); | ||||||
|         private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberPaymentBins = new(); |         private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberPaymentBuckets = new(); | ||||||
|  |  | ||||||
|         public AppDbContext() { |         public AppDbContext() { | ||||||
|             if (App.Config.DatabaseLog != null) { |             if (App.Config.DatabaseLog != null) { | ||||||
| @@ -190,55 +190,55 @@ namespace Elwig.Helpers { | |||||||
|         private async Task FetchMemberRightsAndObligations(int year, SqliteConnection? cnx = null) { |         private async Task FetchMemberRightsAndObligations(int year, SqliteConnection? cnx = null) { | ||||||
|             var ownCnx = cnx == null; |             var ownCnx = cnx == null; | ||||||
|             cnx ??= await ConnectAsync(); |             cnx ??= await ConnectAsync(); | ||||||
|             var bins = new Dictionary<int, Dictionary<string, (int, int)>>(); |             var buckets = new Dictionary<int, Dictionary<string, (int, int)>>(); | ||||||
|             using (var cmd = cnx.CreateCommand()) { |             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, min_kg, max_kg FROM v_area_commitment_bucket WHERE year = {year}"; | ||||||
|                 using var reader = await cmd.ExecuteReaderAsync(); |                 using var reader = await cmd.ExecuteReaderAsync(); | ||||||
|                 while (await reader.ReadAsync()) { |                 while (await reader.ReadAsync()) { | ||||||
|                     var mgnr = reader.GetInt32(0); |                     var mgnr = reader.GetInt32(0); | ||||||
|                     var vtrgid = reader.GetString(1); |                     var vtrgid = reader.GetString(1); | ||||||
|                     if (!bins.ContainsKey(mgnr)) bins[mgnr] = new(); |                     if (!buckets.ContainsKey(mgnr)) buckets[mgnr] = new(); | ||||||
|                     bins[mgnr][vtrgid] = (reader.GetInt32(3), reader.GetInt32(2)); |                     buckets[mgnr][vtrgid] = (reader.GetInt32(3), reader.GetInt32(2)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (ownCnx) await cnx.DisposeAsync(); |             if (ownCnx) await cnx.DisposeAsync(); | ||||||
|             _memberRightsAndObligations[year] = bins; |             _memberRightsAndObligations[year] = buckets; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private async Task FetchMemberDeliveryBins(int year, SqliteConnection? cnx = null) { |         private async Task FetchMemberDeliveryBuckets(int year, SqliteConnection? cnx = null) { | ||||||
|             var ownCnx = cnx == null; |             var ownCnx = cnx == null; | ||||||
|             cnx ??= await ConnectAsync(); |             cnx ??= await ConnectAsync(); | ||||||
|             var bins = new Dictionary<int, Dictionary<string, int>>(); |             var buckets = new Dictionary<int, Dictionary<string, int>>(); | ||||||
|             using (var cmd = cnx.CreateCommand()) { |             using (var cmd = cnx.CreateCommand()) { | ||||||
|                 cmd.CommandText = $"SELECT mgnr, bucket, weight FROM v_delivery_bucket WHERE year = {year}"; |                 cmd.CommandText = $"SELECT mgnr, bucket, weight FROM v_delivery_bucket WHERE year = {year}"; | ||||||
|                 using var reader = await cmd.ExecuteReaderAsync(); |                 using var reader = await cmd.ExecuteReaderAsync(); | ||||||
|                 while (await reader.ReadAsync()) { |                 while (await reader.ReadAsync()) { | ||||||
|                     var mgnr = reader.GetInt32(0); |                     var mgnr = reader.GetInt32(0); | ||||||
|                     var bin = reader.GetString(1); |                     var bucket = reader.GetString(1); | ||||||
|                     if (!bins.ContainsKey(mgnr)) bins[mgnr] = new(); |                     if (!buckets.ContainsKey(mgnr)) buckets[mgnr] = new(); | ||||||
|                     bins[mgnr][bin] = reader.GetInt32(2); |                     buckets[mgnr][bucket] = reader.GetInt32(2); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (ownCnx) await cnx.DisposeAsync(); |             if (ownCnx) await cnx.DisposeAsync(); | ||||||
|             _memberDeliveryBins[year] = bins; |             _memberDeliveryBuckets[year] = buckets; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private async Task FetchMemberPaymentBins(int year, SqliteConnection? cnx = null) { |         private async Task FetchMemberPaymentBuckets(int year, SqliteConnection? cnx = null) { | ||||||
|             var ownCnx = cnx == null; |             var ownCnx = cnx == null; | ||||||
|             cnx ??= await ConnectAsync(); |             cnx ??= await ConnectAsync(); | ||||||
|             var bins = new Dictionary<int, Dictionary<string, int>>(); |             var buckets = new Dictionary<int, Dictionary<string, int>>(); | ||||||
|             using (var cmd = cnx.CreateCommand()) { |             using (var cmd = cnx.CreateCommand()) { | ||||||
|                 cmd.CommandText = $"SELECT mgnr, bucket, weight FROM v_payment_bucket WHERE year = {year}"; |                 cmd.CommandText = $"SELECT mgnr, bucket, weight FROM v_payment_bucket WHERE year = {year}"; | ||||||
|                 using var reader = await cmd.ExecuteReaderAsync(); |                 using var reader = await cmd.ExecuteReaderAsync(); | ||||||
|                 while (await reader.ReadAsync()) { |                 while (await reader.ReadAsync()) { | ||||||
|                     var mgnr = reader.GetInt32(0); |                     var mgnr = reader.GetInt32(0); | ||||||
|                     var bin = reader.GetString(1); |                     var bucket = reader.GetString(1); | ||||||
|                     if (!bins.ContainsKey(mgnr)) bins[mgnr] = new(); |                     if (!buckets.ContainsKey(mgnr)) buckets[mgnr] = new(); | ||||||
|                     bins[mgnr][bin] = reader.GetInt32(2); |                     buckets[mgnr][bucket] = reader.GetInt32(2); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (ownCnx) await cnx.DisposeAsync(); |             if (ownCnx) await cnx.DisposeAsync(); | ||||||
|             _memberPaymentBins[year] = bins; |             _memberPaymentBuckets[year] = buckets; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task<Dictionary<string, (int, int)>> GetMemberRightsAndObligations(int year, int mgnr, SqliteConnection? cnx = null) { |         public async Task<Dictionary<string, (int, int)>> GetMemberRightsAndObligations(int year, int mgnr, SqliteConnection? cnx = null) { | ||||||
| @@ -247,41 +247,41 @@ namespace Elwig.Helpers { | |||||||
|             return _memberRightsAndObligations[year].GetValueOrDefault(mgnr, new()); |             return _memberRightsAndObligations[year].GetValueOrDefault(mgnr, new()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task<Dictionary<string, int>> GetMemberDeliveryBins(int year, int mgnr, SqliteConnection? cnx = null) { |         public async Task<Dictionary<string, int>> GetMemberDeliveryBuckets(int year, int mgnr, SqliteConnection? cnx = null) { | ||||||
|             if (!_memberDeliveryBins.ContainsKey(year)) |             if (!_memberDeliveryBuckets.ContainsKey(year)) | ||||||
|                 await FetchMemberDeliveryBins(year, cnx); |                 await FetchMemberDeliveryBuckets(year, cnx); | ||||||
|             return _memberDeliveryBins[year].GetValueOrDefault(mgnr, new()); |             return _memberDeliveryBuckets[year].GetValueOrDefault(mgnr, new()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task<Dictionary<string, int>> GetMemberPaymentBins(int year, int mgnr, SqliteConnection? cnx = null) { |         public async Task<Dictionary<string, int>> GetMemberPaymentBuckets(int year, int mgnr, SqliteConnection? cnx = null) { | ||||||
|             if (!_memberPaymentBins.ContainsKey(year)) |             if (!_memberPaymentBuckets.ContainsKey(year)) | ||||||
|                 await FetchMemberPaymentBins(year, cnx); |                 await FetchMemberPaymentBuckets(year, cnx); | ||||||
|             return _memberPaymentBins[year].GetValueOrDefault(mgnr, new()); |             return _memberPaymentBuckets[year].GetValueOrDefault(mgnr, new()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task<Dictionary<string, (string, int, int, int, int)>> GetMemberBins(int year, int mgnr, SqliteConnection? cnx = null) { |         public async Task<Dictionary<string, (string, int, int, int, int)>> GetMemberBuckets(int year, int mgnr, SqliteConnection? cnx = null) { | ||||||
|             var ownCnx = cnx == null; |             var ownCnx = cnx == null; | ||||||
|             cnx ??= await ConnectAsync(); |             cnx ??= await ConnectAsync(); | ||||||
|             var rightsAndObligations = await GetMemberRightsAndObligations(year, mgnr, cnx); |             var rightsAndObligations = await GetMemberRightsAndObligations(year, mgnr, cnx); | ||||||
|             var deliveryBins = await GetMemberDeliveryBins(year, mgnr, cnx); |             var deliveryBuckets = await GetMemberDeliveryBuckets(year, mgnr, cnx); | ||||||
|             var paymentBins = await GetMemberPaymentBins(year, mgnr, cnx); |             var paymentBuckets = await GetMemberPaymentBuckets(year, mgnr, cnx); | ||||||
|             if (ownCnx) await cnx.DisposeAsync(); |             if (ownCnx) await cnx.DisposeAsync(); | ||||||
|  |  | ||||||
|             var bins = new Dictionary<string, (string, int, int, int, int)>(); |             var buckets = new Dictionary<string, (string, int, int, int, int)>(); | ||||||
|             foreach (var id in rightsAndObligations.Keys.Union(deliveryBins.Keys).Union(paymentBins.Keys)) { |             foreach (var id in rightsAndObligations.Keys.Union(deliveryBuckets.Keys).Union(paymentBuckets.Keys)) { | ||||||
|                 var variety = await WineVarieties.FindAsync(id[..2]); |                 var variety = await WineVarieties.FindAsync(id[..2]); | ||||||
|                 var attrIds = id[2..]; |                 var attrIds = id[2..]; | ||||||
|                 var attrs = await WineAttributes.Where(a => attrIds.Contains(a.AttrId)).ToListAsync(); |                 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))})" : ""); |                 var name = (variety?.Name ?? "") + (attrIds == "_" ? " (kein Qual.Wein)" : attrs.Count > 0 ? $" ({string.Join(" / ", attrs.Select(a => a.Name))})" : ""); | ||||||
|                 bins[id] = ( |                 buckets[id] = ( | ||||||
|                     name, |                     name, | ||||||
|                     rightsAndObligations.GetValueOrDefault(id).Item1, |                     rightsAndObligations.GetValueOrDefault(id).Item1, | ||||||
|                     rightsAndObligations.GetValueOrDefault(id).Item2, |                     rightsAndObligations.GetValueOrDefault(id).Item2, | ||||||
|                     deliveryBins.GetValueOrDefault(id), |                     deliveryBuckets.GetValueOrDefault(id), | ||||||
|                     paymentBins.GetValueOrDefault(id) |                     paymentBuckets.GetValueOrDefault(id) | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|             return bins; |             return buckets; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -414,7 +414,7 @@ namespace Elwig.Helpers { | |||||||
|                        t.sortid || COALESCE(a.attrid, '') AS bucket, |                        t.sortid || COALESCE(a.attrid, '') AS bucket, | ||||||
|                        t.sortid, a.attrid, |                        t.sortid, a.attrid, | ||||||
|                        CAST(ROUND(SUM(area) * COALESCE(t.min_kg_per_ha, 0) / 10000.0, 0) AS INTEGER) AS min_kg, |                        CAST(ROUND(SUM(area) * COALESCE(t.min_kg_per_ha, 0) / 10000.0, 0) AS INTEGER) AS min_kg, | ||||||
|                        CAST(ROUND(SUM(area) * COALESCE(a.max_kg_per_ha, s.max_kg_per_ha) / 10000.0, 0) AS INTEGER) AS max_kg, |                        CAST(ROUND(SUM(area) * MIN(COALESCE(a.max_kg_per_ha, s.max_kg_per_ha), s.max_kg_per_ha) / 10000.0, 0) AS INTEGER) AS max_kg, | ||||||
|                        CAST(ROUND(SUM(area) * s.max_kg_per_ha / 10000.0, 0) AS INTEGER) AS upper_max_kg |                        CAST(ROUND(SUM(area) * s.max_kg_per_ha / 10000.0, 0) AS INTEGER) AS upper_max_kg | ||||||
|                 FROM season s, area_commitment c |                 FROM season s, area_commitment c | ||||||
|                     JOIN area_commitment_type t ON t.vtrgid = c.vtrgid |                     JOIN area_commitment_type t ON t.vtrgid = c.vtrgid | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task CalculateBins(bool allowAttrsIntoLowerBins, bool avoidUnderDeliveries, bool honorGebunden) { |         public async Task CalculateBuckets(bool allowAttrsIntoLower, bool avoidUnderDeliveries, bool honorGebunden) { | ||||||
|             var attrVals = Context.WineAttributes.ToDictionary(a => a.AttrId, a => (a.IsStrict, a.FillLower)); |             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(); |             var attrForced = attrVals.Where(a => a.Value.IsStrict && a.Value.FillLower == 0).Select(a => a.Key).ToArray(); | ||||||
|             using var cnx = await AppDbContext.ConnectAsync(); |             using var cnx = await AppDbContext.ConnectAsync(); | ||||||
| @@ -97,13 +97,13 @@ namespace Elwig.Helpers.Billing { | |||||||
|                         var u = used.GetValueOrDefault(key, 0); |                         var u = used.GetValueOrDefault(key, 0); | ||||||
|                         var vr = Math.Max(0, Math.Min(rightsAndObligations[key].Item1 - u, w)); |                         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 vo = Math.Max(0, Math.Min(rightsAndObligations[key].Item2 - u, w)); | ||||||
|                         var v = (attributes.Length == 0 || attributes.Select(a => !attrVals[a].IsStrict ? 2 : attrVals[a].FillLower).Min() == 2) ? vr : vo; |                         var v = (attributes.Length == c || attributes.Select(a => !attrVals[a].IsStrict ? 2 : attrVals[a].FillLower).Min() == 2) ? vr : vo; | ||||||
|                         used[key] = u + v; |                         used[key] = u + v; | ||||||
|                         if (key.Length > 2 && !isStrict) used[key[..2]] = used.GetValueOrDefault(key[..2], 0) + v; |                         if (key.Length > 2 && !isStrict) used[key[..2]] = used.GetValueOrDefault(key[..2], 0) + v; | ||||||
|                         inserts.Add((did, dpnr, i, key[2..], v)); |                         inserts.Add((did, dpnr, i, key[2..], v)); | ||||||
|                         w -= v; |                         w -= v; | ||||||
|                     } |                     } | ||||||
|                     if (w == 0 || (!allowAttrsIntoLowerBins && isStrict)) break; |                     if (w == 0 || (!allowAttrsIntoLower && isStrict)) break; | ||||||
|                 } |                 } | ||||||
|                 inserts.Add((did, dpnr, 0, "_", w)); |                 inserts.Add((did, dpnr, 0, "_", w)); | ||||||
|                 lastMgNr = mgnr; |                 lastMgNr = mgnr; | ||||||
| @@ -138,7 +138,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             var fittingBins = new Dictionary<(int, string), int>(); |             var fittingBuckets = new Dictionary<(int, string), int>(); | ||||||
|             using (var cmd = cnx.CreateCommand()) { |             using (var cmd = cnx.CreateCommand()) { | ||||||
|                 cmd.CommandText = $""" |                 cmd.CommandText = $""" | ||||||
|                     SELECT c.mgnr, c.bucket, COALESCE(p.weight, 0) - c.min_kg AS diff |                     SELECT c.mgnr, c.bucket, COALESCE(p.weight, 0) - c.min_kg AS diff | ||||||
| @@ -148,11 +148,11 @@ namespace Elwig.Helpers.Billing { | |||||||
|                     """; |                     """; | ||||||
|                 using var reader = await cmd.ExecuteReaderAsync(); |                 using var reader = await cmd.ExecuteReaderAsync(); | ||||||
|                 while (await reader.ReadAsync()) { |                 while (await reader.ReadAsync()) { | ||||||
|                     fittingBins[(reader.GetInt32(0), reader.GetString(1))] = reader.GetInt32(2); |                     fittingBuckets[(reader.GetInt32(0), reader.GetString(1))] = reader.GetInt32(2); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             foreach (var item in fittingBins) { |             foreach (var item in fittingBuckets) { | ||||||
|                 var mgnr = item.Key.Item1; |                 var mgnr = item.Key.Item1; | ||||||
|                 var id = item.Key.Item2[..2]; |                 var id = item.Key.Item2[..2]; | ||||||
|                 var attr = item.Key.Item2[2..]; |                 var attr = item.Key.Item2[2..]; | ||||||
|   | |||||||
| @@ -115,6 +115,6 @@ namespace Elwig.Models { | |||||||
|         public string OriginString => Origin.OriginString + "\n" + (Kg?.Gl != null ? $" / {Kg.Gl.Name}" : "") + (Kg != null ? $" / {Kg.AtKg.Gem.Name} / KG {Kg.AtKg.Name}" : "") + (Rd != null ? $" / Ried {Rd.Name}" : ""); |         public string OriginString => Origin.OriginString + "\n" + (Kg?.Gl != null ? $" / {Kg.Gl.Name}" : "") + (Kg != null ? $" / {Kg.AtKg.Gem.Name} / KG {Kg.AtKg.Name}" : "") + (Rd != null ? $" / Ried {Rd.Name}" : ""); | ||||||
|  |  | ||||||
|         [InverseProperty("Part")] |         [InverseProperty("Part")] | ||||||
|         public virtual ISet<DeliveryPartBucket> Bins { get; private set; } |         public virtual ISet<DeliveryPartBucket> Buckets { get; private set; } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -24,10 +24,10 @@ | |||||||
|                             Margin="110,40,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" |                             Margin="110,40,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" | ||||||
|                             ValueChanged="SeasonInput_ValueChanged"/> |                             ValueChanged="SeasonInput_ValueChanged"/> | ||||||
|  |  | ||||||
|         <Button x:Name="CalculateBinsButton" Content="Aufteilung Berechnen" |         <Button x:Name="CalculateBucketsButton" Content="Aufteilung Berechnen" | ||||||
|                 Click="CalculateBinsButton_Click" |                 Click="CalculateBucketsButton_Click" | ||||||
|                 Margin="50,80,0,0"/> |                 Margin="50,80,0,0"/> | ||||||
|         <CheckBox x:Name="AllowAttrIntoLowerBinsInput" Content="Erlauben Lieferungen auch auf (konfigurierte) "schlechtere" Flächenbindungen aufzuteilen" |         <CheckBox x:Name="AllowAttrIntoLowerInput" Content="Erlauben Lieferungen auch auf (konfigurierte) "schlechtere" Flächenbindungen aufzuteilen" | ||||||
|                   VerticalAlignment="Top" HorizontalAlignment="Left" Margin="255,68,0,0"/> |                   VerticalAlignment="Top" HorizontalAlignment="Left" Margin="255,68,0,0"/> | ||||||
|         <CheckBox x:Name="AvoidUnderDeliveriesInput" Content="Unterlieferungen durch Abzug bei "besseren" Flächenbindungen vermeiden" |         <CheckBox x:Name="AvoidUnderDeliveriesInput" Content="Unterlieferungen durch Abzug bei "besseren" Flächenbindungen vermeiden" | ||||||
|                   VerticalAlignment="Top" HorizontalAlignment="Left" Margin="255,88,0,0"/> |                   VerticalAlignment="Top" HorizontalAlignment="Left" Margin="255,88,0,0"/> | ||||||
|   | |||||||
| @@ -28,24 +28,24 @@ namespace Elwig.Windows { | |||||||
|             var s1 = await Context.Seasons.FindAsync(SeasonInput.Value + 1); |             var s1 = await Context.Seasons.FindAsync(SeasonInput.Value + 1); | ||||||
|             var valid = (s0 != null); |             var valid = (s0 != null); | ||||||
|             var last = (s1 == null); |             var last = (s1 == null); | ||||||
|             CalculateBinsButton.IsEnabled = valid && last; |             CalculateBucketsButton.IsEnabled = valid && last; | ||||||
|             DeliveryConfirmationButton.IsEnabled = valid; |             DeliveryConfirmationButton.IsEnabled = valid; | ||||||
|             OverUnderDeliveryButton.IsEnabled = valid; |             OverUnderDeliveryButton.IsEnabled = valid; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private async void CalculateBinsButton_Click(object sender, RoutedEventArgs evt) { |         private async void CalculateBucketsButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|             if (SeasonInput.Value is not int year) |             if (SeasonInput.Value is not int year) | ||||||
|                 return; |                 return; | ||||||
|             CalculateBinsButton.IsEnabled = false; |             CalculateBucketsButton.IsEnabled = false; | ||||||
|             Mouse.OverrideCursor = Cursors.AppStarting; |             Mouse.OverrideCursor = Cursors.AppStarting; | ||||||
|             var b = new Billing(year); |             var b = new Billing(year); | ||||||
|             await b.FinishSeason(); |             await b.FinishSeason(); | ||||||
|             await b.CalculateBins( |             await b.CalculateBuckets( | ||||||
|                 AllowAttrIntoLowerBinsInput.IsChecked ?? false, |                 AllowAttrIntoLowerInput.IsChecked ?? false, | ||||||
|                 AvoidUnderDeliveriesInput.IsChecked ?? false, |                 AvoidUnderDeliveriesInput.IsChecked ?? false, | ||||||
|                 HonorGebundenInput.IsChecked ?? false); |                 HonorGebundenInput.IsChecked ?? false); | ||||||
|             Mouse.OverrideCursor = null; |             Mouse.OverrideCursor = null; | ||||||
|             CalculateBinsButton.IsEnabled = true; |             CalculateBucketsButton.IsEnabled = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void DeliveryConfirmationButton_Click(object sender, RoutedEventArgs evt) { |         private void DeliveryConfirmationButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user