DeliveryConfirmation: Add Statistics table

This commit is contained in:
2023-10-16 22:23:42 +02:00
parent 8c49cc8ef2
commit ff2968c989
8 changed files with 268 additions and 147 deletions

View File

@ -53,6 +53,10 @@ 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, int>>> _memberDeliveryBins = new();
private readonly Dictionary<int, Dictionary<int, Dictionary<string, int>>> _memberPaymentBins = new();
public AppDbContext() {
if (App.Config.DatabaseLog != null) {
try {
@ -206,26 +210,111 @@ namespace Elwig.Helpers {
}
}
public async Task<IEnumerable<(string, string, int, int, int)>> GetMemberBins(Member m, int year) {
using var cnx = await ConnectAsync();
var (rights, obligations) = await Billing.Billing.GetMemberRightsObligations(cnx, year, m.MgNr);
var bins = await Billing.Billing.GetMemberBinWeights(m.MgNr, year, cnx);
var list = new List<(string, string, int, int, int)>();
foreach (var id in rights.Keys.Union(obligations.Keys).Union(bins.Keys)) {
var s = await WineVarieties.FindAsync(id[..2]);
var attrIds = id[2..];
var a = await WineAttributes.Where(a => attrIds.Contains(a.AttrId)).ToListAsync();
var name = (s?.Name ?? "") + (a.Count > 0 ? $" ({string.Join(" / ", a.Select(a => a.Name))})" : "");
list.Add((
id, name,
rights.TryGetValue(id, out var v1) ? v1 : 0,
obligations.TryGetValue(id, out var v2) ? v2 : 0,
bins.TryGetValue(id, out var v3) ? v3 : 0
));
private async Task FetchMemberRightsAndObligations(int year, SqliteConnection? cnx = null) {
var ownCnx = cnx == null;
cnx ??= await ConnectAsync();
var bins = new Dictionary<int, Dictionary<string, (int, int)>>();
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"""
SELECT mgnr, t.vtrgid,
ROUND(SUM(COALESCE(area * min_kg_per_ha, 0)) / 10000.0) AS min_kg,
ROUND(SUM(COALESCE(area * max_kg_per_ha, 0)) / 10000.0) AS max_kg
FROM area_commitment c
JOIN area_commitment_type t ON t.vtrgid = c.vtrgid
WHERE (year_from IS NULL OR year_from <= {year}) AND
(year_to IS NULL OR year_to >= {year})
GROUP BY mgnr, t.vtrgid
ORDER BY LENGTH(t.vtrgid) DESC, t.vtrgid
""";
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync()) {
var mgnr = reader.GetInt32(0);
var vtrgid = reader.GetString(1);
if (!bins.ContainsKey(mgnr)) bins[mgnr] = new();
bins[mgnr][vtrgid] = (reader.GetInt32(3), reader.GetInt32(2));
}
}
if (ownCnx) await cnx.DisposeAsync();
_memberRightsAndObligations[year] = bins;
}
return list;
private async Task FetchMemberDeliveryBins(int year, SqliteConnection? cnx = null) {
var ownCnx = cnx == null;
cnx ??= await ConnectAsync();
var bins = new Dictionary<int, Dictionary<string, int>>();
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"SELECT mgnr, bin, weight FROM v_delivery_bin WHERE year = {year}";
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync()) {
var mgnr = reader.GetInt32(0);
var bin = reader.GetString(1);
if (!bins.ContainsKey(mgnr)) bins[mgnr] = new();
bins[mgnr][bin] = reader.GetInt32(2);
}
}
if (ownCnx) await cnx.DisposeAsync();
_memberDeliveryBins[year] = bins;
}
private async Task FetchMemberPaymentBins(int year, SqliteConnection? cnx = null) {
var ownCnx = cnx == null;
cnx ??= await ConnectAsync();
var bins = new Dictionary<int, Dictionary<string, int>>();
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"SELECT mgnr, bin, weight FROM v_payment_bin WHERE year = {year}";
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync()) {
var mgnr = reader.GetInt32(0);
var bin = reader.GetString(1);
if (!bins.ContainsKey(mgnr)) bins[mgnr] = new();
bins[mgnr][bin] = reader.GetInt32(2);
}
}
if (ownCnx) await cnx.DisposeAsync();
_memberPaymentBins[year] = bins;
}
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, int>> GetMemberDeliveryBins(int year, int mgnr, SqliteConnection? cnx = null) {
if (!_memberDeliveryBins.ContainsKey(year))
await FetchMemberDeliveryBins(year, cnx);
return _memberDeliveryBins[year].GetValueOrDefault(mgnr, new());
}
public async Task<Dictionary<string, int>> GetMemberPaymentBins(int year, int mgnr, SqliteConnection? cnx = null) {
if (!_memberPaymentBins.ContainsKey(year))
await FetchMemberPaymentBins(year, cnx);
return _memberPaymentBins[year].GetValueOrDefault(mgnr, new());
}
public async Task<Dictionary<string, (string, int, int, int, int)>> GetMemberBins(int year, int mgnr, SqliteConnection? cnx = null) {
var ownCnx = cnx == null;
cnx ??= await ConnectAsync();
var rightsAndObligations = await GetMemberRightsAndObligations(year, mgnr, cnx);
var deliveryBins = await GetMemberDeliveryBins(year, mgnr, cnx);
var paymentBins = await GetMemberPaymentBins(year, mgnr, cnx);
if (ownCnx) await cnx.DisposeAsync();
var bins = new Dictionary<string, (string, int, int, int, int)>();
foreach (var id in rightsAndObligations.Keys.Union(deliveryBins.Keys).Union(paymentBins.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 ?? "") + (attrs.Count > 0 ? $" ({string.Join(" / ", attrs.Select(a => a.Name))})" : "");
bins[id] = (
name,
rightsAndObligations.GetValueOrDefault(id).Item1,
rightsAndObligations.GetValueOrDefault(id).Item2,
deliveryBins.GetValueOrDefault(id),
paymentBins.GetValueOrDefault(id)
);
}
return bins;
}
}
}