AppDbContext: Use records instead of unnamed tuples for buckets
This commit is contained in:
@ -10,7 +10,7 @@ namespace Elwig.Documents {
|
||||
public Season Season;
|
||||
public DeliveryConfirmationData Data;
|
||||
public string? Text = App.Client.TextDeliveryConfirmation;
|
||||
public Dictionary<string, (string, int, int, int, int)> MemberBuckets;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets;
|
||||
|
||||
public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationData data) :
|
||||
base($"Anlieferungsbestätigung {year}", m) {
|
||||
|
@ -125,11 +125,11 @@
|
||||
$"<td>{(mode != 2 ? "" : obligation == 0 && right == 0 ? "-" : $"{payment:N0}")}</td>" +
|
||||
$"<td>{sum:N0}</td>";
|
||||
}
|
||||
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);
|
||||
}
|
||||
<tr>
|
||||
<th>Gesamtlieferung lt. gez. GA</th>
|
||||
@ -143,28 +143,28 @@
|
||||
@if (rem.Any()) {
|
||||
<tr class="subheading"><th colspan="8">Sortenaufteilung:</th></tr>
|
||||
}
|
||||
@foreach (var (id, (name, right, obligation, sum, payment)) in rem) {
|
||||
@foreach (var (id, b) in rem) {
|
||||
<tr>
|
||||
<th>@name</th>
|
||||
@Raw(FormatRow(1, obligation, right, sum, payment))
|
||||
<th>@b.Name</th>
|
||||
@Raw(FormatRow(1, b.Obligation, b.Right, b.Delivery, b.Payment))
|
||||
</tr>
|
||||
}
|
||||
@if (fbs.Any()){
|
||||
<tr class="subheading"><th colspan="8">Flächenbindungen:</th></tr>
|
||||
}
|
||||
@foreach (var (id, (name, right, obligation, sum, payment)) in fbs) {
|
||||
@foreach (var (id, b) in fbs) {
|
||||
<tr>
|
||||
<th>@name</th>
|
||||
@Raw(FormatRow(2, obligation, right, sum, payment))
|
||||
<th>@b.Name</th>
|
||||
@Raw(FormatRow(2, b.Obligation, b.Right, b.Delivery, b.Payment))
|
||||
</tr>
|
||||
}
|
||||
@if (vtr.Any()) {
|
||||
<tr class="subheading"><th colspan="8">Verträge:</th></tr>
|
||||
}
|
||||
@foreach (var (id, (name, right, obligation, sum, payment)) in vtr) {
|
||||
@foreach (var (id, b) in vtr) {
|
||||
<tr>
|
||||
<th>@name</th>
|
||||
@Raw(FormatRow(2, obligation, right, sum, payment))
|
||||
<th>@b.Name</th>
|
||||
@Raw(FormatRow(2, b.Obligation, b.Right, b.Delivery, b.Payment))
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
@ -7,7 +7,7 @@ namespace Elwig.Documents {
|
||||
|
||||
public Delivery Delivery;
|
||||
public string? Text;
|
||||
public Dictionary<string, (string, int, int, int, int)> MemberBuckets;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets;
|
||||
|
||||
// 0 - none
|
||||
// 1 - GA only
|
||||
|
@ -122,11 +122,11 @@
|
||||
<tr class="subheading">
|
||||
<th>Flächenbindungen:</th>
|
||||
</tr>
|
||||
@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('_'))) {
|
||||
<tr class="@(sortids.Contains(id[..2]) ? "" : "optional")">
|
||||
<th>@name</th>
|
||||
@Raw(FormatRow(obligation, right, sum))
|
||||
<th>@b.Name</th>
|
||||
@Raw(FormatRow(b.Obligation, b.Right, b.Delivery))
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,12 @@ namespace Elwig.Documents {
|
||||
|
||||
public Season Season;
|
||||
public int Year = Utils.CurrentYear;
|
||||
public Dictionary<string, (string, int, int, int, int)> MemberBuckets;
|
||||
public Dictionary<string, int> BucketAreas;
|
||||
public Dictionary<string, MemberBucket> 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -259,10 +259,10 @@
|
||||
$"<td>{(mode == 1 ? "" : obligation == 0 ? "-" : $"{obligation:N0}")}</td>" +
|
||||
$"<td>{(mode == 1 ? "" : right == 0 ? "-" : $"{right:N0}")}</td>";
|
||||
}
|
||||
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);
|
||||
}
|
||||
<tr>
|
||||
<th>Laut gezeichneten GA</th>
|
||||
@ -276,19 +276,19 @@
|
||||
@if (fbs.Any()) {
|
||||
<tr class="subheading"><th colspan="8">Flächenbindungen:</th></tr>
|
||||
}
|
||||
@foreach (var (id, (name, right, obligation, _, _)) in fbs) {
|
||||
@foreach (var (id, b) in fbs) {
|
||||
<tr>
|
||||
<th>@name</th>
|
||||
@Raw(FormatRow(2, Model.BucketAreas[id], obligation, right))
|
||||
<th>@b.Name</th>
|
||||
@Raw(FormatRow(2, b.Area, b.Obligation, b.Right))
|
||||
</tr>
|
||||
}
|
||||
@if (vtr.Any()) {
|
||||
<tr class="subheading"><th colspan="8">Verträge:</th></tr>
|
||||
}
|
||||
@foreach (var (id, (name, right, obligation, _, _)) in vtr) {
|
||||
@foreach (var (id, b) in vtr) {
|
||||
<tr>
|
||||
<th>@name</th>
|
||||
@Raw(FormatRow(2, Model.BucketAreas[id], obligation, right))
|
||||
<th>@b.Name</th>
|
||||
@Raw(FormatRow(2, b.Area, b.Obligation, b.Right))
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
@ -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<Country> 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<int, Dictionary<int, Dictionary<string, (int, int)>>> _memberRightsAndObligations = new();
|
||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, AreaComBucket>>> _memberAreaCommitmentBuckets = new();
|
||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberDeliveryBuckets = new();
|
||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberPaymentBuckets = new();
|
||||
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _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<int, Dictionary<string, (int, int)>>();
|
||||
var buckets = new Dictionary<int, Dictionary<string, AreaComBucket>>();
|
||||
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<int, Dictionary<string, int>>();
|
||||
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<Dictionary<string, (int, int)>> 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<Dictionary<string, AreaComBucket>> 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<Dictionary<string, int>> GetMemberDeliveryBuckets(int year, int mgnr, SqliteConnection? cnx = null) {
|
||||
@ -297,30 +278,25 @@ namespace Elwig.Helpers {
|
||||
return _memberPaymentBuckets[year].GetValueOrDefault(mgnr, new());
|
||||
}
|
||||
|
||||
public async Task<Dictionary<string, int>> 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<Dictionary<string, (string, int, int, int, int)>> GetMemberBuckets(int year, int mgnr, SqliteConnection? cnx = null) {
|
||||
public async Task<Dictionary<string, MemberBucket>> 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<string, (string, int, int, int, int)>();
|
||||
var buckets = new Dictionary<string, MemberBucket>();
|
||||
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)
|
||||
);
|
||||
|
@ -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<SqliteConnection>[] _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;
|
||||
""");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<string, (int, int)>? rightsAndObligations = null;
|
||||
Dictionary<string, AreaComBucket>? rightsAndObligations = null;
|
||||
Dictionary<string, int> 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;
|
||||
|
Reference in New Issue
Block a user