diff --git a/Elwig/Documents/Document.cs b/Elwig/Documents/Document.cs index a16e970..4b24506 100644 --- a/Elwig/Documents/Document.cs +++ b/Elwig/Documents/Document.cs @@ -88,6 +88,8 @@ namespace Elwig.Documents { name = "MemberList"; } else if (this is WineQualityStatistics) { name = "WineQualityStatistics"; + } else if (this is PaymentVariantSummary) { + name = "PaymentVariantSummary"; } else { throw new InvalidOperationException("Invalid document object"); } diff --git a/Elwig/Documents/PaymentVariantSummary.cs b/Elwig/Documents/PaymentVariantSummary.cs new file mode 100644 index 0000000..df73960 --- /dev/null +++ b/Elwig/Documents/PaymentVariantSummary.cs @@ -0,0 +1,19 @@ +using Elwig.Models.Dtos; +using Elwig.Models.Entities; + +namespace Elwig.Documents { + public class PaymentVariantSummary : Document { + + public new static string Name => "Auszahlungsvariante"; + + public PaymentVariantSummaryData Data; + public PaymentVar Variant; + public string CurrencySymbol; + + public PaymentVariantSummary(PaymentVar v, PaymentVariantSummaryData data) : base(v.Name) { + Variant = v; + Data = data; + CurrencySymbol = v.Season.Currency.Symbol ?? v.Season.Currency.Code; + } + } +} diff --git a/Elwig/Documents/PaymentVariantSummary.cshtml b/Elwig/Documents/PaymentVariantSummary.cshtml new file mode 100644 index 0000000..097c6fa --- /dev/null +++ b/Elwig/Documents/PaymentVariantSummary.cshtml @@ -0,0 +1,70 @@ +@using RazorLight +@using Elwig.Helpers +@inherits TemplatePage +@model Elwig.Documents.PaymentVariantSummary +@{ Layout = "Document"; } + +
+

Auszahlungsvariante

+

@Model.Variant.Name

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @{ + string? lastHdr = null; + } + @foreach (var row in Model.Data.Rows) { + var hdr = $"{row.Variety}{(row.Attribute != null ? " / " : "")}{row.Attribute}{(row.Cultivation != null ? " / " : "")}{row.Cultivation}"; + if (lastHdr != hdr) { + var rows = Model.Data.Rows + .Where(r => r.Variety == row.Variety && r.Attribute == row.Attribute && r.Cultivation == row.Cultivation) + .ToList(); + + + + + + + + + } + + + + + + + + + + lastHdr = hdr; + } + +
QualitätsstufeGradationungebundengebundenGesamt
[@(true ? "°Oe" : "°KMW")][kg][@(Model.CurrencySymbol)/kg][kg][@(Model.CurrencySymbol)/kg][@(Model.CurrencySymbol)]
@hdr@($"{rows.Sum(r => r.WeightUngeb):N0}")@($"{rows.Sum(r => r.WeightGeb):N0}")@($"{rows.Sum(r => r.Amount):N2}")
@(row.QualityLevel)@($"{row.Oe:N0}")@(row.WeightUngeb != 0 ? $"{row.WeightUngeb:N0}" : "-")@(row.PriceUngeb != null ? $"{row.PriceUngeb:N4}" : "-")@(row.WeightGeb != 0 ? $"{row.WeightGeb:N0}" : "-")@(row.PriceGeb != null ? $"{row.PriceGeb:N4}" : "-")@($"{row.Amount:N2}")
+
diff --git a/Elwig/Documents/PaymentVariantSummary.css b/Elwig/Documents/PaymentVariantSummary.css new file mode 100644 index 0000000..617bd4c --- /dev/null +++ b/Elwig/Documents/PaymentVariantSummary.css @@ -0,0 +1,17 @@ + +h1 { + text-align: center; + font-size: 24pt; + margin-top: 10mm; + margin-bottom: 2mm; +} + +h2 { + text-align: center; + font-size: 14pt; + margin-top: 2mm; +} + +table.payment-variant { + break-before: page; +} diff --git a/Elwig/Helpers/AppDbContext.cs b/Elwig/Helpers/AppDbContext.cs index f2a2e8e..5be3128 100644 --- a/Elwig/Helpers/AppDbContext.cs +++ b/Elwig/Helpers/AppDbContext.cs @@ -65,6 +65,7 @@ namespace Elwig.Helpers { public DbSet CreditNoteDeliveryRows { get; private set; } public DbSet CreditNoteRows { get; private set; } public DbSet WeightBreakDownRows { get; private set; } + public DbSet PaymentVariantSummaryRows { get; private set; } private readonly StreamWriter? LogFile = null; public static DateTime LastWriteTime => File.GetLastWriteTime(App.Config.DatabaseFile); diff --git a/Elwig/Models/Dtos/PaymentVariantSummaryData.cs b/Elwig/Models/Dtos/PaymentVariantSummaryData.cs new file mode 100644 index 0000000..66cd341 --- /dev/null +++ b/Elwig/Models/Dtos/PaymentVariantSummaryData.cs @@ -0,0 +1,83 @@ +using Elwig.Helpers; +using Elwig.Models.Entities; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder; +using System.Linq; +using System.Threading.Tasks; + +namespace Elwig.Models.Dtos { + public class PaymentVariantSummaryData { + + public record struct PaymentRow(string Type, string Variety, string? Attribute, string? Cultivation, string QualityLevel, double Oe, int WeightUngeb, decimal? PriceUngeb, int WeightGeb, decimal? PriceGeb, decimal Amount); + + public PaymentRow[] Rows; + + public PaymentVariantSummaryData(PaymentRow[] rows) { + Rows = rows; + } + + public static async Task ForPaymentVariant(PaymentVar v, DbSet table) { + return new((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, + Utils.DecFromDb(r.Amount, v.Season.Precision))) + .ToArray()); + } + + private static async Task> FromDbSet(DbSet table, int year, int avnr) { + return await table.FromSqlRaw($""" + SELECT v.type AS type, + v.name AS variety, + a.name AS attribute, + c.name AS cultivation, + 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, + 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} + GROUP BY variety, attribute, cultivation, q.min_kmw, oe + ORDER BY variety, attribute, cultivation, q.min_kmw, oe + """).ToListAsync(); + } + } + + [Keyless] + public class PaymentVariantSummaryRow { + [Column("type")] + public required string Type { get; set; } + [Column("variety")] + public required string Variety { get; set; } + [Column("attribute")] + public string? Attribute { get; set; } + [Column("cultivation")] + public string? Cultivation { get; set; } + [Column("quality_level")] + public required string QualityLevel { get; set; } + [Column("oe")] + public double Oe { get; set; } + [Column("weight_ungeb")] + public int WeightUngeb { get; set; } + [Column("price_ungeb")] + public long? PriceUngeb { get; set; } + [Column("weight_geb")] + public int WeightGeb { get; set; } + [Column("price_geb")] + public long? PriceGeb { get; set; } + [Column("amount")] + public long Amount { get; set; } + } +} diff --git a/Elwig/Models/Dtos/WineQualityStatisticsData.cs b/Elwig/Models/Dtos/WineQualityStatisticsData.cs index 27e4aab..010cf73 100644 --- a/Elwig/Models/Dtos/WineQualityStatisticsData.cs +++ b/Elwig/Models/Dtos/WineQualityStatisticsData.cs @@ -19,7 +19,7 @@ namespace Elwig.Models.Dtos { Sections = sections; } - private static QualitySection[] GetQualitySections(IEnumerable rows) { + private static QualitySection[] GetSections(IEnumerable rows) { var data = new List(); var currentQual = new Dictionary(); var current = new Dictionary(); @@ -88,7 +88,7 @@ namespace Elwig.Models.Dtos { .Select(r => new QualityRow(r.Key.Variety, r.Key.Attribute, r.Key.Cultivation, r.Key.Type, r.Key.QualId, r.AvgKmw, r.Key.Grad, r.Num, r.Weight)) .ToList(); - var data = GetQualitySections(rows); + var data = GetSections(rows); if (data.Length <= 1) return new(data); @@ -105,7 +105,7 @@ namespace Elwig.Models.Dtos { .ThenBy(g => g.QualId) .ThenBy(g => g.Grad) .ToList(); - var typeData = GetQualitySections(typeRows); + var typeData = GetSections(typeRows); if (typeData.Length <= 1) return new([.. typeData, .. data]); @@ -121,7 +121,7 @@ namespace Elwig.Models.Dtos { .OrderBy(g => g.QualId) .ThenBy(g => g.Grad) .ToList(); - var totalData = GetQualitySections(totalRows); + var totalData = GetSections(totalRows); return new([.. totalData, .. typeData, .. data]) { UseOe = mode == 0 }; } }