From 6a5f4cefa9a1ecb28c006a1fc0892cfe699761d8 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 23 May 2025 15:39:44 +0200 Subject: [PATCH] [#58] PaymentVariantSummary: Add 'attributlos gebunden' columns --- Elwig/Documents/PaymentVariantSummary.cshtml | 37 +++++++++------ Elwig/Helpers/Export/Ods.cs | 2 +- .../Models/Dtos/PaymentVariantSummaryData.cs | 47 +++++++++++++------ .../PaymentVariantSummaryTest.cs | 15 +++--- 4 files changed, 64 insertions(+), 37 deletions(-) diff --git a/Elwig/Documents/PaymentVariantSummary.cshtml b/Elwig/Documents/PaymentVariantSummary.cshtml index c3cfd3d..3846ff7 100644 --- a/Elwig/Documents/PaymentVariantSummary.cshtml +++ b/Elwig/Documents/PaymentVariantSummary.cshtml @@ -111,8 +111,8 @@ @Model.CurrencySymbol@($"{Math.Abs(payed):N2}") @{ var weiRows = Model.Data.Rows.Where(r => r.QualityLevel == "Wein"); - var minWei = weiRows.Min(r => r.Ungeb.Price); - var maxWei = weiRows.Max(r => r.Ungeb.Price); + var minWei = weiRows.Min(r => r.Ungeb.MinPrice); + var maxWei = weiRows.Max(r => r.Ungeb.MaxPrice); } Preis (abgewertet): @(minWei != maxWei ? $"{minWei:N4}–{maxWei:N4}" : $"{minWei:N4}") @Model.CurrencySymbol/kg @@ -123,8 +123,8 @@ @Model.CurrencySymbol@($"{netSum:N2}") @{ var quwRows = Model.Data.Rows.Where(r => r.QualityLevel != "Wein"); - var minPrice = quwRows.Min(r => r.Ungeb.Price); - var maxPrice = quwRows.Max(r => r.Ungeb.Price); + var minPrice = quwRows.Min(r => r.Ungeb.MinPrice); + var maxPrice = quwRows.Max(r => r.Ungeb.MaxPrice); } Preis (ungeb., nicht abgew.): @(minPrice != maxPrice ? $"{minPrice:N4}–{maxPrice:N4}" : $"{minPrice:N4}") @Model.CurrencySymbol/kg @@ -135,8 +135,8 @@ @Model.CurrencySymbol@($"{Math.Abs(vat):N2}") @{ var gebRows = Model.Data.Rows - .Where(r => r.Geb.Price != null && r.Ungeb.Price != null) - .Select(r => r.Geb.Price - r.Ungeb.Price); + .Where(r => r.Geb.MaxPrice != null && r.Ungeb.MinPrice != null) + .Select(r => r.Geb.MaxPrice - r.Ungeb.MinPrice); var minGeb = gebRows.Min(); var maxGeb = gebRows.Max(); } @@ -219,19 +219,22 @@ - - - - - - + + + + + + + + + @@ -241,6 +244,8 @@ + + @@ -258,6 +263,8 @@ + + @@ -267,9 +274,11 @@ - + + + - + lastHdr = hdr; diff --git a/Elwig/Helpers/Export/Ods.cs b/Elwig/Helpers/Export/Ods.cs index 7e1c892..4bbd7c1 100644 --- a/Elwig/Helpers/Export/Ods.cs +++ b/Elwig/Helpers/Export/Ods.cs @@ -317,7 +317,7 @@ namespace Elwig.Helpers.Export { c = $"<{ct} office:value-type=\"string\" calcext:value-type=\"string\"{add}>{SecurityElement.Escape(data.ToString())}"; } - return $" {c}\r\n" + (colSpan > 1 ? $" \r\n" : ""); + return $" {c}\r\n" + (colSpan > 1 ? $" \r\n" : ""); } } } diff --git a/Elwig/Models/Dtos/PaymentVariantSummaryData.cs b/Elwig/Models/Dtos/PaymentVariantSummaryData.cs index 2f09e4e..5c54a5f 100644 --- a/Elwig/Models/Dtos/PaymentVariantSummaryData.cs +++ b/Elwig/Models/Dtos/PaymentVariantSummaryData.cs @@ -18,8 +18,9 @@ namespace Elwig.Models.Dtos { ("Cultivation", "Bewirt.", null, 20), ("QualityLevel", "Qualitätsstufe", null, 30), ("Oe", "Gradation", "°Oe", 20), - ("Ungeb", "ungebunden", "kg|€/kg", 40), - ("Geb", "gebunden", "kg|€/kg", 40), + ("Ungeb", "ungebunden", "kg|€/kg|€/kg", 60), + ("LowGeb", "attributlos gebunden", "kg|€/kg|€/kg", 60), + ("Geb", "gebunden", "kg|€/kg|€/kg", 60), ("Amount", "Gesamt", "€", 25), ]; @@ -30,8 +31,9 @@ namespace Elwig.Models.Dtos { string? Cultivation, string QualityLevel, double Oe, - (int Weight, decimal? Price) Ungeb, - (int Weight, decimal? Price) Geb, + (int Weight, decimal? MinPrice, decimal? MaxPrice) Ungeb, + (int Weight, decimal? MinPrice, decimal? MaxPrice) LowGeb, + (int Weight, decimal? MinPrice, decimal? MaxPrice) Geb, decimal Amount ); @@ -42,8 +44,9 @@ namespace Elwig.Models.Dtos { public static async Task ForPaymentVariant(PaymentVar v, DbSet table) { return new(v, (await FromDbSet(table, v.Year, v.AvNr)) .Select(r => new PaymentRow(r.Type, r.Variety, r.Attribute, r.Cultivation, r.QualityLevel, r.Oe, - (r.WeightUngeb, r.PriceUngeb != null ? Utils.DecFromDb(r.PriceUngeb.Value, v.Season.Precision) : null), - (r.WeightGeb, r.PriceGeb != null ? Utils.DecFromDb(r.PriceGeb.Value, v.Season.Precision) : null), + (r.WeightUngeb, r.MinPriceUngeb != null ? Utils.DecFromDb(r.MinPriceUngeb.Value, v.Season.Precision) : null, r.MaxPriceUngeb != null ? Utils.DecFromDb(r.MaxPriceUngeb.Value, v.Season.Precision) : null), + (r.WeightLowGeb, r.MinPriceLowGeb != null ? Utils.DecFromDb(r.MinPriceLowGeb.Value, v.Season.Precision) : null, r.MaxPriceLowGeb != null ? Utils.DecFromDb(r.MaxPriceLowGeb.Value, v.Season.Precision) : null), + (r.WeightGeb, r.MinPriceGeb != null ? Utils.DecFromDb(r.MinPriceGeb.Value, v.Season.Precision) : null, r.MaxPriceGeb != null ? Utils.DecFromDb(r.MaxPriceGeb.Value, v.Season.Precision) : null), Utils.DecFromDb(r.Amount, v.Season.Precision))) .ToArray()); } @@ -57,19 +60,23 @@ namespace Elwig.Models.Dtos { q.name AS quality_level, ROUND(kmw * (4.54 + 0.022 * kmw)) AS oe, SUM(IIF(w.discr = '_', w.value, 0)) AS weight_ungeb, - MAX(IIF(w.discr = '_', b.price, NULL)) AS price_ungeb, - SUM(IIF(w.discr != '_', w.value, 0)) AS weight_geb, - MAX(IIF(w.discr != '_', b.price, NULL)) AS price_geb, + MIN(IIF(w.discr = '_', b.price, NULL)) AS min_price_ungeb, + MAX(IIF(w.discr = '_', b.price, NULL)) AS max_price_ungeb, + SUM(IIF(w.discr NOT IN (COALESCE(p.attrid, ''), '_'), w.value, 0)) AS weight_lowgeb, + MIN(IIF(w.discr NOT IN (COALESCE(p.attrid, ''), '_'), b.price, NULL)) AS min_price_lowgeb, + MAX(IIF(w.discr NOT IN (COALESCE(p.attrid, ''), '_'), b.price, NULL)) AS max_price_lowgeb, + SUM(IIF(w.discr = COALESCE(p.attrid, ''), w.value, 0)) AS weight_geb, + MIN(IIF(w.discr = COALESCE(p.attrid, ''), b.price, NULL)) AS min_price_geb, + MAX(IIF(w.discr = COALESCE(p.attrid, ''), b.price, NULL)) AS max_price_geb, SUM(b.amount) AS amount FROM payment_delivery_part_bucket b LEFT JOIN delivery_part_bucket w ON (w.year, w.did, w.dpnr, w.bktnr) = (b.year, b.did, b.dpnr, b.bktnr) LEFT JOIN delivery_part p ON (p.year, p.did, p.dpnr) = (b.year, b.did, b.dpnr) - LEFT JOIN delivery d ON (d.year, d.did) = (p.year, p.did) LEFT JOIN wine_variety v ON v.sortid = p.sortid LEFT JOIN wine_attribute a ON a.attrid = p.attrid LEFT JOIN wine_cultivation c ON c.cultid = p.cultid LEFT JOIN wine_quality_level q ON q.qualid = p.qualid - WHERE d.year = {year} AND b.avnr = {avnr} + WHERE p.year = {year} AND b.avnr = {avnr} GROUP BY variety, attribute, cultivation, q.min_kmw, oe ORDER BY variety, attribute, cultivation, q.min_kmw, oe """).ToListAsync(); @@ -92,12 +99,22 @@ namespace Elwig.Models.Dtos { public double Oe { get; set; } [Column("weight_ungeb")] public int WeightUngeb { get; set; } - [Column("price_ungeb")] - public long? PriceUngeb { get; set; } + [Column("min_price_ungeb")] + public long? MinPriceUngeb { get; set; } + [Column("max_price_ungeb")] + public long? MaxPriceUngeb { get; set; } + [Column("weight_lowgeb")] + public int WeightLowGeb { get; set; } + [Column("min_price_lowgeb")] + public long? MinPriceLowGeb { get; set; } + [Column("max_price_lowgeb")] + public long? MaxPriceLowGeb { get; set; } [Column("weight_geb")] public int WeightGeb { get; set; } - [Column("price_geb")] - public long? PriceGeb { get; set; } + [Column("min_price_geb")] + public long? MinPriceGeb { get; set; } + [Column("max_price_geb")] + public long? MaxPriceGeb { get; set; } [Column("amount")] public long Amount { get; set; } } diff --git a/Tests/DocumentTests/PaymentVariantSummaryTest.cs b/Tests/DocumentTests/PaymentVariantSummaryTest.cs index a17a9c9..75132a9 100644 --- a/Tests/DocumentTests/PaymentVariantSummaryTest.cs +++ b/Tests/DocumentTests/PaymentVariantSummaryTest.cs @@ -12,16 +12,17 @@ namespace Tests.DocumentTests { var v = (await ctx.PaymentVariants.FindAsync(2020, 1))!; var data = await PaymentVariantSummaryData.ForPaymentVariant(v, ctx.PaymentVariantSummaryRows); using var doc = new PaymentVariantSummary(v, data); - var text = await Utils.GeneratePdfText(doc); + var text = await Utils.GeneratePdfText(doc, true); + var table = Utils.ExtractTable(text); Assert.Multiple(() => { Assert.That(text, Contains.Substring("Auszahlungsvariante")); Assert.That(text, Contains.Substring(v.Name)); - Assert.That(text, Contains.Substring(""" - Gradation ungebunden gebunden Gesamt - [°Oe] [kg] [€/kg] [kg] [€/kg] [€] - Grüner Veltliner 3 219 0 1 609,50 - Qualitätswein 73 3 219 0,5000 - - 1 609,50 - """)); + Assert.That(table.Skip(17).ToArray(), Is.EqualTo(new string[][] { + [ "Gradation", "ungebunden", "attributlos gebunden", "gebunden", "Gesamt" ], + [ "[°Oe]", "[kg]", "[€/kg]", "[kg]", "[€/kg]", "[kg]", "[€/kg]", "[€]" ], + ["Grüner Veltliner", "3 219", "0", "0", "1 609,50"], + ["Qualitätswein", "73", "3 219", "0,5000", "-", "-", "-", "-", "1 609,50"] + })); }); } }
Qualitätsstufe Gradation ungebundenattributlos gebunden gebunden Gesamt
[@(Model.CurrencySymbol)/kg] [kg] [@(Model.CurrencySymbol)/kg][kg][@(Model.CurrencySymbol)/kg] [@(Model.CurrencySymbol)]
@hdr @($"{rows.Sum(r => r.Ungeb.Weight):N0}") @($"{rows.Sum(r => r.LowGeb.Weight):N0}") @($"{rows.Sum(r => r.Geb.Weight):N0}") @($"{rows.Sum(r => r.Amount):N2}")@(row.QualityLevel) @($"{row.Oe:N0}") @(row.Ungeb.Weight != 0 ? $"{row.Ungeb.Weight:N0}" : "-")@(row.Ungeb.Price != null ? $"{row.Ungeb.Price:N4}" : "-")@(row.Ungeb.MaxPrice != null ? $"{row.Ungeb.MaxPrice:N4}" : "-")@(row.LowGeb.Weight != 0 ? $"{row.LowGeb.Weight:N0}" : "-")@(row.LowGeb.MaxPrice != null ? $"{row.LowGeb.MaxPrice:N4}" : "-") @(row.Geb.Weight != 0 ? $"{row.Geb.Weight:N0}" : "-")@(row.Geb.Price != null ? $"{row.Geb.Price:N4}" : "-")@(row.Geb.MaxPrice != null ? $"{row.Geb.MaxPrice:N4}" : "-") @($"{row.Amount:N2}")