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), ("Name1", "Name", null, 40), ("Name2", "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), ("Custom", "Weitere", "€", 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.FromSqlRaw($""" SELECT m.mgnr, m.name AS name_1, COALESCE(m.prefix || ' ', '') || m.given_name || COALESCE(' ' || m.middle_names, '') || COALESCE(' ' || m.suffix, '') AS name_2, 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(b.total_penalty / POW(10, s.precision - 2)) AS bs_penalty, ROUND(u.total_penalty / POW(10, 4 - 2)) AS fb_penalty, ROUND(-a.total_amount / POW(10, s.precision - 2)) AS auto_bs, x.amount AS custom_mod 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_business_shares b ON (b.year, b.mgnr) = (s.year, m.mgnr) LEFT JOIN v_penalty_area_commitments u ON (u.year, u.mgnr) = (s.year, m.mgnr) LEFT JOIN v_auto_business_shares a ON (a.year, a.mgnr) = (s.year, m.mgnr) LEFT JOIN payment_custom x ON (x.year, x.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 Name1; public string Name2; 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? Custom; public decimal? Others; public decimal? Considered; public decimal Amount; public CreditNoteRow(CreditNoteRowSingle row, BillingData data) { byte prec1 = 2, prec2 = row.Precision; MgNr = row.MgNr; Name1 = row.Name1; Name2 = row.Name2; Address = row.Address; Plz = row.Plz; Locality = row.Locality; Iban = row.Iban != null ? Utils.FormatIban(row.Iban) : null; 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) ? null : Utils.DecFromDb((long)row.FbPenalty, prec1); if (data.ConsiderTotalPenalty) Penalty = (row.BsPenalty == null) ? null : Utils.DecFromDb((long)row.BsPenalty, prec1); if (data.ConsiderAutoBusinessShares) AutoBs = (row.AutoBs == null) ? null : Utils.DecFromDb((long)row.AutoBs, prec1); if (data.ConsiderCustomModifiers) Custom = (row.CustomMod == null) ? null : Utils.DecFromDb((long)row.CustomMod, prec1); mod -= (Penalties ?? 0) + (Penalty ?? 0) + (AutoBs ?? 0) + (Custom ?? 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("name_1")] public required string Name1 { get; set; } [Column("name_2")] public required string Name2 { get; set; } [Column("address")] public required string Address { get; set; } [Column("plz")] public int Plz { get; set; } [Column("ort")] public required 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 required 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("bs_penalty")] public long? BsPenalty { get; set; } [Column("fb_penalty")] public long? FbPenalty { get; set; } [Column("auto_bs")] public long? AutoBs { get; set; } [Column("custom_mod")] public long? CustomMod { get; set; } } }