diff --git a/Elwig/Helpers/AppDbContext.cs b/Elwig/Helpers/AppDbContext.cs index 926a7f5..2fbe390 100644 --- a/Elwig/Helpers/AppDbContext.cs +++ b/Elwig/Helpers/AppDbContext.cs @@ -58,6 +58,7 @@ namespace Elwig.Helpers { public DbSet OverUnderDeliveryRows { get; private set; } public DbSet AreaComUnderDeliveryRows { get; private set; } public DbSet MemberDeliveryPerVariantRows { get; private set; } + public DbSet CreditNoteDeliveryRows { get; private set; } public DbSet CreditNoteRows { get; private set; } private readonly StreamWriter? LogFile = null; diff --git a/Elwig/Models/Dtos/AreaComUnderDeliveyData.cs b/Elwig/Models/Dtos/AreaComUnderDeliveyData.cs index 4989f79..7214b92 100644 --- a/Elwig/Models/Dtos/AreaComUnderDeliveyData.cs +++ b/Elwig/Models/Dtos/AreaComUnderDeliveyData.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; @@ -8,7 +7,7 @@ using System.Threading.Tasks; namespace Elwig.Models.Dtos { public class AreaComUnderDeliveryData : DataTable { - private static readonly (string, string, string?, int)[] FieldNames = new[] { + private static readonly (string, string, string?, int)[] FieldNames = [ ("MgNr", "MgNr.", null, 12), ("Name", "Name", null, 40), ("GivenName", "Vorname", null, 40), @@ -20,7 +19,7 @@ namespace Elwig.Models.Dtos { ("DeliveryObligations", "Lieferpflicht", "kg", 22), ("Weights", "Geliefert", "kg", 22), ("UnderDeliveries", "Unterliefert", "kg|%", 34), - }; + ]; public AreaComUnderDeliveryData(IEnumerable rows, int year) : base($"Unterlieferungen FB", $"Unterlieferungen laut Flächenbindungen {year}", rows, FieldNames) { diff --git a/Elwig/Models/Dtos/CreditNoteData.cs b/Elwig/Models/Dtos/CreditNoteData.cs new file mode 100644 index 0000000..aa46c01 --- /dev/null +++ b/Elwig/Models/Dtos/CreditNoteData.cs @@ -0,0 +1,180 @@ +using Elwig.Helpers; +using Elwig.Helpers.Billing; +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 CreditNoteData : DataTable { + + private static readonly (string, string, string?, int)[] FieldNames = [ + ("MgNr", "MgNr.", null, 12), + ("Name", "Name", null, 40), + ("GivenName", "Vorname", null, 40), + ("Address", "Adresse", null, 60), + ("Plz", "PLZ", null, 10), + ("Locality", "Ort", null, 60), + ("Iban", "IBAN", null, 45), + ("TgNr", "TG-Nr.", null, 20), + ("Sum", "Zwischens.", "€", 20), + ("Surcharge", "Zuschlag", "€", 20), + ("Total", "Gesamt", "€", 20), + ("ConsideredSum", "Berückstgt.", "€", 20), + ("Net", "Netto", "€", 20), + ("Vat1", "10% MwSt.", "€", 20), + ("Vat2", "13% MwSt.", "€", 20), + ("Gross", "Brutto", "€", 20), + ("Penalties", "Pönalen FB", "€", 20), + ("Penalty", "Unterl. GA", "€", 20), + ("AutoBs", "GA Nachz.", "€", 20), + ("Others", "Sonstige", "€", 20), + ("Considered", "Berückstgt.", "€", 20), + ("Amount", "Betrag", "€", 20), + ]; + + public CreditNoteData(IEnumerable rows, int year, string name) : + base($"Buchungsliste", $"Buchungsliste {name} {year}", rows, FieldNames) { + } + + public static async Task ForPaymentVariant(AppDbContext ctx, int year, int avnr) { + var variant = await ctx.PaymentVariants.FindAsync(year, avnr); + var name = variant!.Name; + var data = BillingData.FromJson(variant!.Data); + var rows = (await FromDbSet(ctx.CreditNoteRows, year, avnr)).Select(r => new CreditNoteRow(r, data)).ToList(); + return new CreditNoteData(rows, year, name); + } + + private static async Task> FromDbSet(DbSet table, int year, int avnr) { + return await table.FromSql($""" + SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name AS ort, m.address, m.iban, c.tgnr, s.year, s.precision, + p.amount - p.net_amount AS surcharge, + c.net_amount, c.prev_net_amount, c.vat, c.vat_amount, c.gross_amount, c.modifiers, c.prev_modifiers, c.amount, + ROUND(COALESCE(u.total_penalty, 0) / POW(10, 4 - 2)) AS fb_penalty, + ROUND(COALESCE(b.total_penalty, 0) / POW(10, s.precision - 2)) AS bs_penalty, + ROUND(COALESCE(a.total_amount, 0) / POW(10, s.precision - 2)) AS auto_bs + FROM credit c + LEFT JOIN member m ON m.mgnr = c.mgnr + LEFT JOIN payment_member p ON (p.year, p.avnr, p.mgnr) = (c.year, c.avnr, c.mgnr) + 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 = c.year + LEFT JOIN v_penalty_area_commitments u ON (u.year, u.mgnr) = (s.year, m.mgnr) + LEFT JOIN v_penalty_business_shares b ON (b.year, b.mgnr) = (s.year, m.mgnr) + LEFT JOIN v_auto_business_shares a ON (a.year, a.mgnr) = (s.year, m.mgnr) + WHERE c.year = {year} AND c.avnr = {avnr} + ORDER BY m.mgnr + """).ToListAsync(); + } + } + + public class CreditNoteRow { + public int MgNr; + public string Name; + public string GivenName; + public string Address; + public int Plz; + public string Locality; + public string Iban; + public string TgNr; + public decimal Sum; + public decimal? Surcharge; + public decimal Total; + public decimal? ConsideredSum; + public decimal Net; + public decimal? Vat1, Vat2; + public decimal Gross; + public decimal? Penalties; + public decimal? Penalty; + public decimal? AutoBs; + public decimal? Others; + public decimal? Considered; + public decimal Amount; + + public CreditNoteRow(CreditNoteRowSingle row, BillingData data) { + byte prec1 = 2, prec2 = row.Precision; + MgNr = row.MgNr; + Name = row.Name; + GivenName = row.GivenName; + Address = row.Address; + Plz = row.Plz; + Locality = row.Locality; + Iban = Utils.FormatIban(row.Iban); + TgNr = $"{row.Year}/{row.TgNr}"; + Total = Utils.DecFromDb(row.NetAmount, prec1); + Surcharge = (row.Surcharge == null || row.Surcharge == 0) ? null : Utils.DecFromDb((long)row.Surcharge, prec2); + Sum = Total - (Surcharge ?? 0); + ConsideredSum = (row.PrevNetAmount == null ||row.PrevNetAmount == 0) ? null : -Utils.DecFromDb((long)row.PrevNetAmount, prec1); + Net = Total + (ConsideredSum ?? 0); + if (row.Vat == 0.10) { + Vat1 = Utils.DecFromDb(row.VatAmount, prec1); + } else if (row.Vat == 0.13) { + Vat2 = Utils.DecFromDb(row.VatAmount, prec1); + } + decimal mod = (row.Modifiers == null) ? 0 : Utils.DecFromDb((long)row.Modifiers, prec1); + if (data.ConsiderContractPenalties) + Penalties = (row.FbPenalty == null || row.FbPenalty == 0) ? null : Utils.DecFromDb((long)row.FbPenalty, prec1); + if (data.ConsiderTotalPenalty) + Penalty = (row.BsPealty == null || row.BsPealty == 0) ? null : Utils.DecFromDb((long)row.BsPealty, prec1); + if (data.ConsiderAutoBusinessShares) + AutoBs = (row.AutoBs == null || row.AutoBs == 0) ? null : -Utils.DecFromDb((long)row.AutoBs, prec1); + mod -= (Penalties ?? 0) + (Penalty ?? 0) + (AutoBs ?? 0); + Others = (mod == 0) ? null : mod; + Gross = Utils.DecFromDb(row.GrossAmount, prec1); + Considered = (row.PrevModifiers == null || row.PrevModifiers == 0) ? null : -Utils.DecFromDb((long)row.PrevModifiers, prec1); + Amount = Utils.DecFromDb(row.Amount, prec1); + } + } + + [Keyless] + public class CreditNoteRowSingle { + [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("iban")] + public string Iban { get; set; } + [Column("year")] + public int Year { get; set; } + [Column("precision")] + public byte Precision { get; set; } + [Column("tgnr")] + public string TgNr { get; set; } + [Column("surcharge")] + public long? Surcharge { get; set; } + [Column("net_amount")] + public long NetAmount { get; set; } + [Column("prev_net_amount")] + public long? PrevNetAmount { get; set; } + [Column("vat")] + public double Vat { get; set; } + [Column("vat_amount")] + public long VatAmount { get; set; } + [Column("gross_amount")] + public long GrossAmount { get; set; } + [Column("modifiers")] + public long? Modifiers { get; set; } + [Column("prev_modifiers")] + public long? PrevModifiers { get; set; } + [Column("amount")] + public long Amount { get; set; } + [Column("fb_penalty")] + public long? FbPenalty { get; set; } + [Column("bs_penalty")] + public long? BsPealty { get; set; } + [Column("auto_bs")] + public long? AutoBs { get; set; } + } +} diff --git a/Elwig/Models/Dtos/CreditNoteDeliveryData.cs b/Elwig/Models/Dtos/CreditNoteDeliveryData.cs index c5a906a..0b2be48 100644 --- a/Elwig/Models/Dtos/CreditNoteDeliveryData.cs +++ b/Elwig/Models/Dtos/CreditNoteDeliveryData.cs @@ -8,9 +8,9 @@ using System.Threading.Tasks; namespace Elwig.Models.Dtos { public class CreditNoteDeliveryData : DataTable { - private static readonly (string, string, string?)[] FieldNames = new[] { - ("", "", (string?)null), // TODO - }; + private static readonly (string, string, string?)[] FieldNames = [ + ("", "", null), // TODO + ]; private readonly int Year; private readonly int? TgNr; @@ -25,7 +25,7 @@ namespace Elwig.Models.Dtos { MgNr = mgnr; } - public static async Task> ForPaymentVariant(DbSet table, DbSet seasons, int year, int avnr) { + public static async Task> ForPaymentVariant(DbSet table, DbSet seasons, int year, int avnr) { return (await FromDbSet(table, year, avnr)) .GroupBy( r => new { r.Year, r.AvNr, r.MgNr, r.TgNr, r.DId, r.DPNr }, @@ -36,7 +36,7 @@ namespace Elwig.Models.Dtos { .ToDictionary(d => d.MgNr ?? 0); } - private static async Task> FromDbSet(DbSet table, int? year = null, int? avnr = null, int? mgnr = null) { + private static async Task> FromDbSet(DbSet table, int? year = null, int? avnr = null, int? mgnr = null) { var y = year?.ToString() ?? "NULL"; var v = avnr?.ToString() ?? "NULL"; var m = mgnr?.ToString() ?? "NULL"; @@ -77,7 +77,7 @@ namespace Elwig.Models.Dtos { public decimal? TotalModifiers; public decimal? Amount; - public CreditNoteDeliveryRow(IEnumerable rows, DbSet seasons) { + public CreditNoteDeliveryRow(IEnumerable rows, DbSet seasons) { var f = rows.First(); Year = f.Year; TgNr = f.TgNr; @@ -110,7 +110,7 @@ namespace Elwig.Models.Dtos { } [Keyless] - public class CreditNoteRowSingle { + public class CreditNoteDeliveryRowSingle { [Column("year")] public int Year { get; set; } [Column("tgnr")] diff --git a/Elwig/Windows/PaymentVariantsWindow.xaml b/Elwig/Windows/PaymentVariantsWindow.xaml index 345037f..3e7b809 100644 --- a/Elwig/Windows/PaymentVariantsWindow.xaml +++ b/Elwig/Windows/PaymentVariantsWindow.xaml @@ -6,7 +6,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Elwig.Windows" mc:Ignorable="d" - Title="Auszahlungsvarianten - Elwig" Height="500" Width="820" MinHeight="500" MinWidth="820"> + Title="Auszahlungsvarianten - Elwig" Height="510" Width="820" MinHeight="500" MinWidth="820">