using Microsoft.Data.Sqlite; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Elwig.Helpers.Billing { public class Billing { private readonly int Year; private readonly int AvNr; private readonly AppDbContext Context; private readonly Dictionary Attributes; private readonly Dictionary Modifiers; private readonly Dictionary AreaComTypes; public Billing(int year, int avnr) { Year = year; AvNr = avnr; Context = new AppDbContext(); Attributes = Context.WineAttributes.ToDictionary(a => a.AttrId, a => a.Name); Modifiers = Context.Modifiers.Where(m => m.Year == Year).ToDictionary(m => m.ModId, m => (m.Abs, m.Rel)); AreaComTypes = Context.AreaCommitmentTypes.ToDictionary(v => v.VtrgId, v => (v.SortId, v.AttrId1, v.AttrId2, v.Discriminator, v.MinKgPerHa, v.MaxKgPerHa, v.PenaltyAmount)); } protected async Task DeleteInDb() { using var cnx = await AppDbContext.ConnectAsync(); using (var cmd = cnx.CreateCommand()) { cmd.CommandText = $"DELETE FROM payment_delivery_part WHERE (year, avnr) = ({Year}, {AvNr})"; await cmd.ExecuteNonQueryAsync(); } using (var cmd = cnx.CreateCommand()) { cmd.CommandText = $"DELETE FROM payment_member WHERE (year, avnr) = ({Year}, {AvNr})"; await cmd.ExecuteNonQueryAsync(); } } public async Task Calculate() { await DeleteInDb(); var tasks = new List(); foreach (var mgnr in Context.Members.Select(m => m.MgNr)) { tasks.Add(Task.Run(() => CalculateMember(mgnr))); } await Task.WhenAll(tasks); } public static async Task<(Dictionary, Dictionary)> GetMemberRightsObligations(int mgnr, int year, SqliteConnection cnx) { var rights = new Dictionary(); var obligations = new Dictionary(); using var cmd = cnx.CreateCommand(); cmd.CommandText = $""" SELECT t.vtrgid, SUM(COALESCE(area * min_kg_per_ha, 0)) / 10000 AS min_kg, SUM(COALESCE(area * max_kg_per_ha, 0)) / 10000 AS max_kg FROM area_commitment c JOIN area_commitment_type t ON t.vtrgid = c.vtrgid WHERE mgnr = {mgnr} AND (year_from IS NULL OR year_from <= {year}) AND (year_to IS NULL OR year_to >= {year}) GROUP BY t.vtrgid ORDER BY LENGTH(t.vtrgid) DESC, t.vtrgid """; var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var vtrgid = reader.GetString(0); obligations[vtrgid] = reader.GetInt32(1); rights[vtrgid] = reader.GetInt32(2); } return (rights, obligations); } public static async Task> GetMemberBucketWeights(int mgnr, int year, SqliteConnection cnx) { var buckets = new Dictionary(); using var cmd = cnx.CreateCommand(); cmd.CommandText = $""" SELECT bucket, weight FROM v_bucket WHERE (year, mgnr) = ({year}, {mgnr}) """; var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var bucket = reader.GetString(0); buckets[bucket] = reader.GetInt32(1); } return buckets; } protected async Task CalculateMember(int mgnr) { using var cnx = await AppDbContext.ConnectAsync(); var (rights, obligations) = await GetMemberRightsObligations(mgnr, Year, cnx); var deliveries = new List<(int, int, string, int, double, string, string[], string[])>(); using (var cmd = cnx.CreateCommand()) { cmd.CommandText = $""" SELECT did, dpnr, sortid, weight, kmw, qualid, attributes, modifiers FROM v_delivery WHERE (year, mgnr) = ({Year}, {mgnr}) ORDER BY kmw DESC, weight DESC, did, dpnr """; var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { deliveries.Add(( reader.GetInt32(0), reader.GetInt32(1), reader.GetString(2), reader.GetInt32(3), reader.GetDouble(4), reader.GetString(5), reader.GetString(6).Split(","), reader.GetString(7).Split(",") )); } } foreach (var (did, dpnr, sortid, weight, kmw, qualid, attributes, modifiers) in deliveries) { if (qualid == "WEI" || qualid == "RSW" || qualid == "LDW") { // Nicht mindestens Qualitätswein (QUW) using var cmd = cnx.CreateCommand(); // TODO cmd.CommandText = $""" INSERT INTO payment_delivery_part (year, did, dpnr, avnr, mod_abs, mod_rel, ) VALUES ({Year}, {did}, {dpnr}, {AvNr}, ) """; await cmd.ExecuteNonQueryAsync(); continue; } // TODO } } } }