using Elwig.Helpers; using Elwig.Helpers.Billing; using Microsoft.Data.Sqlite; using System.Reflection; namespace Tests.HelperTests { [TestFixture] public class BillingTest { private const int Year1 = 2020, Year2 = 2021; private const int MgNr1 = 101, MgNr2 = 102, MgNr3 = 103, MgNr4 = 104; private const decimal GV_ungeb = 0.50m, GV_geb = 0.60m, GVB_ungeb = 0.54m, GVB_geb = 0.64m, GVK_ungeb = 0.61m, GVK_geb = 0.71m, WEI = 0.10m; private SqliteConnection? Connection; [OneTimeSetUp] public async Task SetupDatabase() { Connection = await AppDbContext.ConnectAsync(); await AppDbContext.ExecuteEmbeddedScript(Connection, Assembly.GetExecutingAssembly(), "Tests.Resources.Sql.BillingInsert.sql"); } [OneTimeTearDown] public async Task TeardownDatabase() { if (Connection == null) return; await AppDbContext.ExecuteEmbeddedScript(Connection, Assembly.GetExecutingAssembly(), "Tests.Resources.Sql.BillingDelete.sql"); await Connection.DisposeAsync(); Connection = null; } [SetUp] public async Task CreatePaymentVariant() { var json = """ { "mode": "elwig", "version": 1, "payment": { "GV": "curve:0", "GV-B": "curve:1", "GV/K": "curve:2" }, "quality": {"WEI": 0.1}, "curves": [{ "id": 0, "mode": "oe", "data": {"15kmw": 0.5}, "geb": 0.1 }, { "id": 1, "mode": "oe", "data": {"15kmw": 0.54}, "geb": 0.1 }, { "id": 2, "mode": "oe", "data": {"15kmw": 0.61}, "geb": 0.1 }] } """; await InsertPaymentVariant(Year1, 1, json); await InsertPaymentVariant(Year2, 1, json); } [TearDown] public async Task CleanupDatabasePayment() { if (Connection == null) return; await AppDbContext.ExecuteBatch(Connection, """ DELETE FROM credit; DELETE FROM payment_variant; DELETE FROM delivery_part_bucket; """); } private Task> GetMemberAreaCommitmentBuckets(int year, int mgnr) { var ctx = new AppDbContext(); return ctx.GetMemberAreaCommitmentBuckets(year, mgnr, Connection); } private Task> GetMemberDeliveryBuckets(int year, int mgnr) { var ctx = new AppDbContext(); return ctx.GetMemberDeliveryBuckets(year, mgnr, Connection); } private Task> GetMemberPaymentBuckets(int year, int mgnr) { var ctx = new AppDbContext(); return ctx.GetMemberPaymentBuckets(year, mgnr, Connection); } private async Task> GetMemberDeliveryPrices(int year, int mgnr) { var buckets = new Dictionary<(string, string), (int, decimal)>(); using (var cmd = Connection!.CreateCommand()) { cmd.CommandText = $""" SELECT lsnr || '/' || d.dpnr, d.sortid || b.discr, b.value, p.price FROM v_delivery d LEFT JOIN payment_delivery_part_bucket p ON (p.year, p.did, p.dpnr) = (d.year, d.did, d.dpnr) LEFT JOIN delivery_part_bucket b ON (b.year, b.did, b.dpnr, b.bktnr) = (p.year, p.did, p.dpnr, p.bktnr) WHERE d.year = {year} AND mgnr = {mgnr} """; using var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var lsnr = reader.GetString(0); var bucket = reader.GetString(1); buckets[(lsnr, bucket)] = (reader.GetInt32(2), Utils.DecFromDb(reader.GetInt32(3), 4)); } } return buckets; } private Task InsertPaymentVariant(int year, int avnr, string data) { return AppDbContext.ExecuteBatch(Connection!, $""" INSERT INTO payment_variant (year, avnr, name, date, transfer_date, test_variant, calc_time, data) VALUES ({year}, {avnr}, 'Test', '2021-01-15', NULL, TRUE, NULL, '{data}'); """); } [Test] public async Task Test_01_NoActiveAreaComs() { int mgnr = MgNr1, year = Year1; var areaCom = await GetMemberAreaCommitmentBuckets(year, mgnr); Assert.That(areaCom, Is.Empty); var delivery = await GetMemberDeliveryBuckets(year, mgnr); Assert.Multiple(() => { Assert.That(delivery, Has.Count.EqualTo(3)); Assert.That(delivery["GV"], Is.EqualTo(16_000)); Assert.That(delivery["GV_"], Is.EqualTo( 1_000)); Assert.That(delivery["GVK"], Is.EqualTo( 4_000)); }); BillingVariant b = new(year, 1); await b.CalculateBuckets(false, false, false); var payment = await GetMemberPaymentBuckets(year, mgnr); Assert.Multiple(() => { Assert.That(payment, Has.Count.EqualTo(1)); Assert.That(payment["GV_"], Is.EqualTo(17_000)); }); await b.Calculate(); var prices = await GetMemberDeliveryPrices(year, mgnr); Assert.Multiple(() => { Assert.That(prices, Has.Count.EqualTo(6)); // Kabinett Assert.That(prices[("20201001X001/1", "GV_")], Is.EqualTo((4_000, GV_ungeb))); // ohne Attribut Assert.That(prices[("20201001X001/2", "GV_")], Is.EqualTo((4_000, GV_ungeb))); // Bio Assert.That(prices[("20201001X002/1", "GV_")], Is.EqualTo((4_000, GVB_ungeb))); // Bio Assert.That(prices[("20201001X002/2", "GV_")], Is.EqualTo((4_000, GVB_ungeb))); // ohne Attribut Assert.That(prices[("20201001X003/1", "GV_")], Is.EqualTo(( 500, WEI))); // ohne Attribut Assert.That(prices[("20201001X003/2", "GV_")], Is.EqualTo(( 500, GV_ungeb))); }); } [Test] public async Task Test_02_SimpleNotStrictAreaComs() { int mgnr = MgNr1, year = Year2; var areaCom = await GetMemberAreaCommitmentBuckets(year, mgnr); Assert.Multiple(() => { Assert.That(areaCom, Has.Count.EqualTo(1)); Assert.That(areaCom["GV"], Is.EqualTo(new AreaComBucket(10_000, 5_000, 10_000))); }); var delivery = await GetMemberDeliveryBuckets(year, mgnr); Assert.Multiple(() => { Assert.That(delivery, Has.Count.EqualTo(3)); Assert.That(delivery["GV"], Is.EqualTo(16_000)); Assert.That(delivery["GV_"], Is.EqualTo( 1_000)); Assert.That(delivery["GVK"], Is.EqualTo( 4_000)); }); BillingVariant b = new(year, 1); await b.CalculateBuckets(false, false, false, Connection); var payment = await GetMemberPaymentBuckets(year, mgnr); Assert.Multiple(() => { Assert.That(payment, Has.Count.EqualTo(2)); Assert.That(payment["GV_"], Is.EqualTo( 7_000)); Assert.That(payment["GV"], Is.EqualTo(10_000)); }); await b.Calculate(false, false, false); var prices = await GetMemberDeliveryPrices(year, mgnr); Assert.Multiple(() => { Assert.That(prices, Has.Count.EqualTo(7)); // Kabinett Assert.That(prices[("20211001X001/1", "GV")] , Is.EqualTo((4_000, GV_geb))); // ohne Attribut Assert.That(prices[("20211001X001/2", "GV")], Is.EqualTo((4_000, GV_geb))); // Bio Assert.That(prices[("20211001X002/1", "GV_")], Is.EqualTo((4_000, GVB_ungeb))); // Bio Assert.That(prices[("20211001X002/2", "GV_")], Is.EqualTo((2_000, GVB_ungeb))); Assert.That(prices[("20211001X002/2", "GV")], Is.EqualTo((2_000, GVB_geb))); // ohne Attribut Assert.That(prices[("20211001X003/1", "GV_")], Is.EqualTo(( 500, WEI))); // ohne Attribut Assert.That(prices[("20211001X003/2", "GV_")], Is.EqualTo(( 500, GV_ungeb))); }); } [Test] public async Task Test_03_SimpleNotStrictAreaComs_HonorGebunden() { int mgnr = MgNr1, year = Year2; var areaCom = await GetMemberAreaCommitmentBuckets(year, mgnr); Assert.Multiple(() => { Assert.That(areaCom, Has.Count.EqualTo(1)); Assert.That(areaCom["GV"], Is.EqualTo(new AreaComBucket(10_000, 5_000, 10_000))); }); var delivery = await GetMemberDeliveryBuckets(year, mgnr); Assert.Multiple(() => { Assert.That(delivery, Has.Count.EqualTo(3)); Assert.That(delivery["GV"], Is.EqualTo(16_000)); Assert.That(delivery["GV_"], Is.EqualTo( 1_000)); Assert.That(delivery["GVK"], Is.EqualTo( 4_000)); }); BillingVariant b = new(year, 1); await b.CalculateBuckets(true, false, false, Connection); var payment = await GetMemberPaymentBuckets(year, mgnr); Assert.Multiple(() => { Assert.That(payment, Has.Count.EqualTo(2)); Assert.That(payment["GV_"], Is.EqualTo(9_000)); Assert.That(payment["GV"], Is.EqualTo(8_000)); }); await b.Calculate(true, false, false); var prices = await GetMemberDeliveryPrices(year, mgnr); Assert.Multiple(() => { Assert.That(prices, Has.Count.EqualTo(6)); // Kabinett Assert.That(prices[("20211001X001/1", "GV")], Is.EqualTo((4_000, GV_geb))); // ohne Attribut Assert.That(prices[("20211001X001/2", "GV_")], Is.EqualTo((4_000, GV_ungeb))); // Bio Assert.That(prices[("20211001X002/1", "GV")], Is.EqualTo((4_000, GVB_geb))); // Bio Assert.That(prices[("20211001X002/2", "GV_")], Is.EqualTo((4_000, GVB_ungeb))); // ohne Attribut Assert.That(prices[("20211001X003/1", "GV_")], Is.EqualTo(( 500, WEI))); // ohne Attribut Assert.That(prices[("20211001X003/2", "GV_")], Is.EqualTo(( 500, GV_ungeb))); }); } [Test] [Ignore("Not implemented yet")] public Task Test_04_ComplexNotStrictAreaComs() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_05_ComplexNotStrictAreaComs_HonorGebunden() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_06_StrictAreaComs_NoFillLower_NotAllowed() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_07_StrictAreaComs_NoFillLower_Allowed() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_08_StrictAreaComs_NoFillLower_Allowed_AvoidUnderDeliveries() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_09_StrictAreaComs_FillLowerUntilObligation_NotAllowed() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_10_StrictAreaComs_FillLowerUntilObligation_Allowed() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_11_StrictAreaComs_FillLowerUntilObligation_Allowed_AvoidUnderDeliveries() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_12_StrictAreaComs_FillLowerUntilObligation_NotAllowed() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_13_StrictAreaComs_FillLowerUntilObligation_Allowed() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_14_StrictAreaComs_FillLowerUntilObligation_Allowed_AvoidUnderDeliveries() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_15_StrictAreaComs_FillLowerUntilRight_NotAllowed() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_16_StrictAreaComs_FillLowerUntilRight_Allowed() { // TODO return Task.CompletedTask; } [Test] [Ignore("Not implemented yet")] public Task Test_17_StrictAreaComs_FillLowerUntilRight_Allowed_AvoidUnderDeliveries() { // TODO return Task.CompletedTask; } } }