diff --git a/Elwig/Helpers/Billing/Transaction.cs b/Elwig/Helpers/Billing/Transaction.cs new file mode 100644 index 0000000..0c79498 --- /dev/null +++ b/Elwig/Helpers/Billing/Transaction.cs @@ -0,0 +1,14 @@ +using Elwig.Models; + +namespace Elwig.Helpers.Billing { + public class Transaction { + + public readonly Member Member; + public readonly int AmountCent; + + public Transaction(Member m, decimal amount) { + Member = m; + AmountCent = (int)(amount * 100); + } + } +} diff --git a/Elwig/Helpers/Export/Bki.cs b/Elwig/Helpers/Export/Bki.cs index fedea4a..e043bd1 100644 --- a/Elwig/Helpers/Export/Bki.cs +++ b/Elwig/Helpers/Export/Bki.cs @@ -1,4 +1,51 @@ +using Elwig.Models; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + namespace Elwig.Helpers.Export { - public class Bki { + public class Bki : Csv { + + private readonly string _clientData; + + public Bki(string filename) : base(filename, ';', Encoding.Latin1) { + Header = """ + EDV-Liste zum automatischen Einlesen in die Weindatenbank;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + Stammdaten;;;;;;;;;;;;;;Transportschein;;;;;;;;;;;;;;;; + Empfänger:;;;;;;;Versender:;;;;;;;;;;;;;;;;;;;;;;; + Betriebsnr;Name od. Firmenname;Vorname;Straße;Hausnr;Plz;Ort;Betriebsnr;Name od. Firmenname;Vorname;Straße;Hausnr;Plz;Ort;Datum der Lieferung;Menge in kg;Art;Weiß;Rot;Sorte1;Sorte2;Sorte3;Qualitätsstufe;Jahrgang;Herkunft;°KMW;°Oe;Vollablieferer;Ha Gesamt;Ha Ertragsfähig;Flächenbindung in Ha für AMA + """; + var c = App.Client; + var (a1, a2) = Utils.SplitAddress(c.Address); + _clientData = $"{c.LfbisNr};{c.NameFull};;{a1};{a2};{c.Plz};{c.Ort}"; + } + + public async Task ExportAsync(AppDbContext ctx, int year) { + await ExportAsync(await ctx.DeliveryParts.Where(p => p.Year == year).ToListAsync()); + } + + public void Export(AppDbContext ctx, int year) { + ExportAsync(ctx, year).GetAwaiter().GetResult(); + } + + public override string FormatRow(DeliveryPart p) { + var d = p.Delivery; + var m = d.Member; + string memberData; + if (m.BillingAddress is BillingAddr a) { + var (n1, n2) = Utils.SplitName(a.Name, m.FamilyName); + var (a1, a2) = Utils.SplitAddress(a.Address); + memberData = $"{m.LfbisNr};{n1};{n2};{a1};{a2};{a.PostalDest.AtPlz?.Plz};{a.PostalDest.AtPlz?.Ort.Name}"; + } else { + var (a1, a2) = Utils.SplitAddress(m.Address); + memberData = $"{m.LfbisNr};{m.FamilyName};{m.AdministrativeName2};{a1};{a2};{m.PostalDest.AtPlz?.Plz};{m.PostalDest.AtPlz?.Ort.Name}"; + } + var s = p.Variant; + var deliveryData = $"{d.Date:dd.MM.yyyy};{p.Weight};TB;{(s.IsWhite ? "J" : "")};{(s.IsRed ? "J" : "")};{s.SortId};;;{p.QualId};{d.Year};{p.HkId};{p.Kmw};{p.Oe}"; + var vollData = $"N;;;{m.AreaCommitments.Where(a => a.YearFrom <= d.Year && (a.YearTo == null || a.YearTo >= d.Year)).Sum(a => a.Area) / 10_000.0}"; + return $"{_clientData};{memberData};{deliveryData};{vollData}"; + } } } diff --git a/Elwig/Helpers/Export/Csv.cs b/Elwig/Helpers/Export/Csv.cs index 79f91ab..e34691c 100644 --- a/Elwig/Helpers/Export/Csv.cs +++ b/Elwig/Helpers/Export/Csv.cs @@ -1,4 +1,50 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading.Tasks; + namespace Elwig.Helpers.Export { - public class Csv { + public abstract class Csv : IExporter { + public static string FileExtension => "csv"; + + protected readonly StreamWriter Writer; + protected readonly char Separator; + protected string? Header; + + public Csv(string filename, char separator = ';') : this(filename, separator, Encoding.UTF8) { } + + public Csv(string filename, char separator, Encoding encoding) { + Writer = new StreamWriter(filename, false, encoding); + Separator = separator; + } + + public void Dispose() { + GC.SuppressFinalize(this); + Writer.Dispose(); + } + + public ValueTask DisposeAsync() { + GC.SuppressFinalize(this); + return Writer.DisposeAsync(); + } + + public async Task ExportAsync(IEnumerable data) { + if (Header != null) await Writer.WriteLineAsync(Header); + foreach (var row in data) { + await Writer.WriteLineAsync(FormatRow(row)); + } + } + + public void Export(IEnumerable data) { + ExportAsync(data).GetAwaiter().GetResult(); + } + + public string FormatRow(IEnumerable row) { + return string.Join(Separator, row); + } + + public abstract string FormatRow(T row); } } diff --git a/Elwig/Helpers/Export/Ebics.cs b/Elwig/Helpers/Export/Ebics.cs index 337e001..f454ccb 100644 --- a/Elwig/Helpers/Export/Ebics.cs +++ b/Elwig/Helpers/Export/Ebics.cs @@ -1,14 +1,26 @@ -using Elwig.Models; +using Elwig.Helpers.Billing; using System; using System.Collections.Generic; using System.Threading.Tasks; namespace Elwig.Helpers.Export { - public class Ebics : IBankingProvider { + public class Ebics : IBankingExporter { - public string FileExtension => "xml"; + public static string FileExtension => "xml"; - public Task Export(string filename, int avnr, IEnumerable members) { + public void Dispose() { + throw new NotImplementedException(); + } + + public ValueTask DisposeAsync() { + throw new NotImplementedException(); + } + + public void Export(IEnumerable data) { + throw new NotImplementedException(); + } + + public Task ExportAsync(IEnumerable data) { throw new NotImplementedException(); } } diff --git a/Elwig/Helpers/Export/Elba.cs b/Elwig/Helpers/Export/Elba.cs index 15be0c8..8894332 100644 --- a/Elwig/Helpers/Export/Elba.cs +++ b/Elwig/Helpers/Export/Elba.cs @@ -1,14 +1,14 @@ -using Elwig.Models; +using Elwig.Helpers.Billing; using System; -using System.Collections.Generic; -using System.Threading.Tasks; namespace Elwig.Helpers.Export { - public class Elba : IBankingProvider { + public class Elba : Csv, IBankingExporter { - public string FileExtension => "elba"; + public static new string FileExtension => "elba"; - public Task Export(string filename, int avnr, IEnumerable members) { + public Elba(string filename) : base(filename) { } + + public override string FormatRow(Transaction row) { throw new NotImplementedException(); } } diff --git a/Elwig/Helpers/Export/IBankingExporter.cs b/Elwig/Helpers/Export/IBankingExporter.cs new file mode 100644 index 0000000..30a89e0 --- /dev/null +++ b/Elwig/Helpers/Export/IBankingExporter.cs @@ -0,0 +1,8 @@ +using Elwig.Helpers.Billing; + +namespace Elwig.Helpers.Export { + /// + /// Interface for exporting banking data + /// + public interface IBankingExporter : IExporter { } +} diff --git a/Elwig/Helpers/Export/IBankingProvider.cs b/Elwig/Helpers/Export/IBankingProvider.cs deleted file mode 100644 index a50282a..0000000 --- a/Elwig/Helpers/Export/IBankingProvider.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Elwig.Models; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Elwig.Helpers.Export { - /// - /// Interface for exporting banking data - /// - public interface IBankingProvider { - /// - /// The default file extension of the exported files to be used (whithout a preceding ".") - /// - string FileExtension { get; } - - /// - /// Export the member payment data of the given payment variant to the given file. - /// (The amount of the last payed variant is deducted from the calculated amount.) - /// - /// The file to export the data to - /// The number of the payment variant to export - /// The members whose data to include in the export - Task Export(string filename, int avnr, IEnumerable members); - } -} diff --git a/Elwig/Helpers/Export/IExporter.cs b/Elwig/Helpers/Export/IExporter.cs new file mode 100644 index 0000000..8f9b92e --- /dev/null +++ b/Elwig/Helpers/Export/IExporter.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Elwig.Helpers.Export { + public interface IExporter : IDisposable, IAsyncDisposable { + /// + /// The default file extension of the exported files to be used (whithout a preceding ".") + /// + static string FileExtension { get; } + + /// + /// Export the given data to the given file. + /// + /// The data to be exported + void Export(IEnumerable data); + + /// + /// Export the given data to the given file. + /// + /// The data to be exported + Task ExportAsync(IEnumerable data); + } +}