using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Threading.Tasks; namespace Elwig.Models.Dtos { public class OverUnderDeliveryData : DataTable { private static readonly (string, string, int)[] FieldNames = new[] { ("MgNr", "MgNr.", 12), ("Name", "Name", 40), ("GivenName", "Vorname", 40), ("Address", "Adresse", 60), ("Plz", "PLZ", 10), ("Locality", "Ort", 60), ("BusinessShares", "GA", 10), ("DeliveryObligation", "Lieferpflicht", 22), ("DeliveryRight", "Lieferrecht", 22), ("Weight", "Geliefert", 22), ("OverUnderDelivery", "Über-/Unterliefert", 35), ("Percent", "Prozent", 16), }; public OverUnderDeliveryData(IEnumerable rows, int year) : base($"Über-Unterlieferungen", $"Über- und Unterlieferungen laut gezeichneten Geschäftsanteilen {year}", rows, FieldNames) { } public static async Task ForSeason(DbSet table, int year) { var rows = await table.FromSqlRaw($""" SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name AS ort, m.address, m.business_shares, m.business_shares * s.min_kg_per_bs AS min_kg, m.business_shares * s.max_kg_per_bs AS max_kg, COALESCE(SUM(d.weight), 0) AS sum FROM member m LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest LEFT JOIN AT_ort o ON o.okz = p.okz LEFT JOIN season s ON s.year = {year} LEFT JOIN v_delivery d ON d.mgnr = m.mgnr AND d.year = s.year WHERE m.active = 1 GROUP BY d.year, m.mgnr ORDER BY 100.0 * sum / max_kg, m.mgnr; """).ToListAsync(); return new OverUnderDeliveryData(rows, year); } } [Keyless] public class OverUnderDeliveryRow { [Column("mgnr")] public int MgNr { get; set; } [Column("family_name")] public string Name { get; set; } [Column("given_name")] public string GivenName { get; set; } [Column("address")] public string Address { get; set; } [Column("plz")] public int Plz { get; set; } [Column("ort")] public string LocalityFull { get; set; } [NotMapped] public string Locality => LocalityFull.Split(",")[0]; [Column("business_shares")] public int BusinessShares { get; set; } [Column("min_kg")] public int DeliveryObligation { get; set; } [Column("max_kg")] public int DeliveryRight { get; set; } [Column("sum")] public int Weight { get; set; } [NotMapped] public int? OverUnderDelivery => Weight < DeliveryObligation ? Weight - DeliveryObligation : Weight > DeliveryRight ? Weight - DeliveryRight : null; [NotMapped] public double? Percent => Weight < DeliveryObligation ? Math.Round(Weight * 100.0 / DeliveryObligation - 100.0, 1) : Weight > DeliveryRight ? Math.Round(Weight * 100.0 / DeliveryRight - 100, 1) : null; } }