Billing: Implement feature 'avoid under deliveries'
This commit is contained in:
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user