diff --git a/Elwig/Helpers/Billing/Billing.cs b/Elwig/Helpers/Billing/Billing.cs index 6b6a81d..545367b 100644 --- a/Elwig/Helpers/Billing/Billing.cs +++ b/Elwig/Helpers/Billing/Billing.cs @@ -55,7 +55,7 @@ namespace Elwig.Helpers.Billing { COALESCE(LENGTH(attributes), 0) ASC, attribute_prio DESC, COALESCE(attributes, '~'), kmw DESC, lsnr, dpnr """; - var reader = await cmd.ExecuteReaderAsync(); + using var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { deliveries.Add(( reader.GetInt32(0), reader.GetInt32(1), reader.GetInt32(2), reader.GetString(3), reader.GetInt32(4), @@ -125,7 +125,81 @@ namespace Elwig.Helpers.Billing { await cmd.ExecuteNonQueryAsync(); } - // TODO add second round to avoid under deliveries + if (!avoidUnderDeliveries) + return; + + var underDeliveries = new Dictionary<(int, string), int>(); + using (var cmd = cnx.CreateCommand()) { + cmd.CommandText = $""" + SELECT c.mgnr, c.bin, COALESCE(p.weight, 0) - c.min_kg AS diff + FROM v_area_commitment_bin c + LEFT JOIN v_payment_bin p ON (p.year, p.mgnr, p.bin) = (c.year, c.mgnr, c.bin) + WHERE c.year = {Year} AND LENGTH(c.bin) = 2 AND diff < 0 + """; + using var reader = await cmd.ExecuteReaderAsync(); + while (await reader.ReadAsync()) { + underDeliveries[(reader.GetInt32(0), reader.GetString(1))] = reader.GetInt32(2); + } + } + + var fittingBins = new Dictionary<(int, string), int>(); + using (var cmd = cnx.CreateCommand()) { + cmd.CommandText = $""" + SELECT c.mgnr, c.bin, COALESCE(p.weight, 0) - c.min_kg AS diff + FROM v_area_commitment_bin c + LEFT JOIN v_payment_bin p ON (p.year, p.mgnr, p.bin) = (c.year, c.mgnr, c.bin) + WHERE c.year = {Year} AND LENGTH(c.bin) = 3 AND diff > 0 + """; + using var reader = await cmd.ExecuteReaderAsync(); + while (await reader.ReadAsync()) { + fittingBins[(reader.GetInt32(0), reader.GetString(1))] = reader.GetInt32(2); + } + } + + foreach (var item in fittingBins) { + var mgnr = item.Key.Item1; + var id = item.Key.Item2[..2]; + var attr = item.Key.Item2[2..]; + var available = item.Value; + var needed = -underDeliveries.GetValueOrDefault((mgnr, id), 0); + if (needed <= 0) continue; + + var fittingDeliveries = new List<(int, int, int, int)>(); + using (var cmd = cnx.CreateCommand()) { + cmd.CommandText = $""" + SELECT d.did, d.dpnr, d.weight, b.value + FROM v_delivery d + JOIN delivery_part_bin b ON (b.year, b.did, b.dpnr) = (d.year, d.did, d.dpnr) AND b.discr = '{attr}' + WHERE d.year = {Year} AND mgnr = {mgnr} AND sortid = '{id}' AND attributes = '{attr}' + ORDER BY kmw ASC, lsnr DESC, d.dpnr DESC + """; + using var reader = await cmd.ExecuteReaderAsync(); + while (await reader.ReadAsync()) { + fittingDeliveries.Add(( + reader.GetInt32(0), reader.GetInt32(1), reader.GetInt32(2), reader.GetInt32(3) + )); + } + } + + var changes = new List<(int, int, int, int)>(); + foreach (var (did, dpnr, _, w) in fittingDeliveries) { + int v = Math.Min(needed, w); + needed -= v; + changes.Add((did, dpnr, 1, v)); + changes.Add((did, dpnr, 2, w - v)); + if (needed == 0) break; + } + + using (var cmd = cnx.CreateCommand()) { + cmd.CommandText = $""" + INSERT INTO delivery_part_bin (year, did, dpnr, binnr, discr, value) + VALUES {string.Join(",\n ", changes.Select(i => $"({Year}, {i.Item1}, {i.Item2}, {i.Item3}, '', {i.Item4})"))} + ON CONFLICT DO UPDATE + SET value = excluded.value + """; + await cmd.ExecuteNonQueryAsync(); + } + } } } } diff --git a/Elwig/Windows/SeasonFinishWindow.xaml b/Elwig/Windows/SeasonFinishWindow.xaml index b338edc..6f4e2f4 100644 --- a/Elwig/Windows/SeasonFinishWindow.xaml +++ b/Elwig/Windows/SeasonFinishWindow.xaml @@ -29,7 +29,7 @@ Margin="50,80,0,0"/> - Bei Lieferungen das Feld Gebunden berücksichtigen