Compare commits
	
		
			5 Commits
		
	
	
		
			f9d95a48f2
			...
			f5f00a7739
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f5f00a7739 | |||
| 2de4739e9d | |||
| 47e8ab7e62 | |||
| 8a678509c5 | |||
| de53bfdd2b | 
| @@ -2,7 +2,6 @@ using System; | |||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.IO; | using System.IO; | ||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using System.Text; |  | ||||||
|  |  | ||||||
| namespace Elwig.Documents { | namespace Elwig.Documents { | ||||||
|     public abstract class Document : IDisposable { |     public abstract class Document : IDisposable { | ||||||
| @@ -63,7 +62,7 @@ namespace Elwig.Documents { | |||||||
|         public async Task Generate() { |         public async Task Generate() { | ||||||
|             var pdf = new TempFile("pdf"); |             var pdf = new TempFile("pdf"); | ||||||
|             using (var tmpHtml = new TempFile("html")) { |             using (var tmpHtml = new TempFile("html")) { | ||||||
|                 await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Encoding.UTF8); |                 await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Utils.UTF8); | ||||||
|                 await Pdf.Convert(tmpHtml.FilePath, pdf.FilePath); |                 await Pdf.Convert(tmpHtml.FilePath, pdf.FilePath); | ||||||
|             } |             } | ||||||
|             PdfFile = pdf; |             PdfFile = pdf; | ||||||
|   | |||||||
| @@ -1,14 +1,35 @@ | |||||||
| using Elwig.Models; | using Elwig.Models; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  |  | ||||||
| namespace Elwig.Helpers.Billing { | namespace Elwig.Helpers.Billing { | ||||||
|     public class Transaction { |     public class Transaction { | ||||||
|  |  | ||||||
|         public readonly Member Member; |         public readonly Member Member; | ||||||
|         public readonly int AmountCent; |         public readonly long AmountCent; | ||||||
|  |         public readonly string Currency; | ||||||
|  |         public readonly int Nr; | ||||||
|  |  | ||||||
|         public Transaction(Member m, decimal amount) { |         public Transaction(Member m, decimal amount, string currency, int nr) { | ||||||
|             Member = m; |             Member = m; | ||||||
|             AmountCent = (int)(amount * 100); |             AmountCent = (long)Math.Round(amount * 100); | ||||||
|  |             Currency = currency; | ||||||
|  |             Nr = nr; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public static IEnumerable<Transaction> FromPaymentVariant(PaymentVar variant) { | ||||||
|  |             var last = variant.Season.PaymentVariants.Where(v => v.TransferDate != null).OrderBy(v => v.TransferDate).LastOrDefault(); | ||||||
|  |             var dict = last?.MemberPayments.ToDictionary(m => m.MgNr, m => m.Amount) ?? new(); | ||||||
|  |             return variant.MemberPayments | ||||||
|  |                 .OrderBy(m => m.MgNr) | ||||||
|  |                 .Select(m => { | ||||||
|  |                     var amt = Math.Round(dict.GetValueOrDefault(m.MgNr, 0), 2); | ||||||
|  |                     return new Transaction(m.Member, m.Amount - amt, m.Variant.Season.CurrencyCode, m.TgNr ?? 0); | ||||||
|  |                 }) | ||||||
|  |                 .ToList(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static string FormatAmountCent(long cents) => $"{cents / 100}.{cents % 100:00}"; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,7 +1,6 @@ | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Text; |  | ||||||
| using IniParser; | using IniParser; | ||||||
| using IniParser.Model; | using IniParser.Model; | ||||||
|  |  | ||||||
| @@ -25,7 +24,7 @@ namespace Elwig.Helpers { | |||||||
|             var parser = new FileIniDataParser(); |             var parser = new FileIniDataParser(); | ||||||
|             IniData? ini = null; |             IniData? ini = null; | ||||||
|             try { |             try { | ||||||
|                 ini = parser.ReadFile(FileName, Encoding.UTF8); |                 ini = parser.ReadFile(FileName, Utils.UTF8); | ||||||
|             } catch {} |             } catch {} | ||||||
|  |  | ||||||
|             if (ini == null || !ini.TryGetKey("database.file", out string db)) { |             if (ini == null || !ini.TryGetKey("database.file", out string db)) { | ||||||
| @@ -70,7 +69,7 @@ namespace Elwig.Helpers { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void Write() { |         public void Write() { | ||||||
|             using var file = new StreamWriter(FileName, false, Encoding.UTF8); |             using var file = new StreamWriter(FileName, false, Utils.UTF8); | ||||||
|             file.Write($"\r\n[general]\r\n"); |             file.Write($"\r\n[general]\r\n"); | ||||||
|             if (Branch != null) file.Write($"branch = {Branch}\r\n"); |             if (Branch != null) file.Write($"branch = {Branch}\r\n"); | ||||||
|             file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n"); |             file.Write($"\r\n[database]\r\nfile = {DatabaseFile}\r\n"); | ||||||
|   | |||||||
| @@ -1,11 +1,14 @@ | |||||||
| using Elwig.Models; | using System.Collections.Generic; | ||||||
| using Microsoft.EntityFrameworkCore; |  | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Text; | using System.Text; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  | using System; | ||||||
|  |  | ||||||
| namespace Elwig.Helpers.Export { | namespace Elwig.Helpers.Export { | ||||||
|     public class Bki : Csv<DeliveryPart> { |  | ||||||
|  |     using Row = Tuple<(string, string?, string?, string?, string, int, string, int), (string, int, string, string, string, int, string, double, double)>; | ||||||
|  |  | ||||||
|  |     public class Bki : Csv<Row> { | ||||||
|  |  | ||||||
|         private readonly string _clientData; |         private readonly string _clientData; | ||||||
|  |  | ||||||
| @@ -22,29 +25,42 @@ namespace Elwig.Helpers.Export { | |||||||
|             _clientData = $"{c.LfbisNr};{c.NameFull};;{a1};{a2};{c.Plz};{c.Ort}"; |             _clientData = $"{c.LfbisNr};{c.NameFull};;{a1};{a2};{c.Plz};{c.Ort}"; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task ExportAsync(AppDbContext ctx, int year) { |         public async Task ExportAsync(int year) { | ||||||
|             await ExportAsync(await ctx.DeliveryParts.Where(p => p.Year == year).ToListAsync()); |             using var cnx = await AppDbContext.ConnectAsync(); | ||||||
|  |             using var cmd = cnx.CreateCommand(); | ||||||
|  |             cmd.CommandText = $""" | ||||||
|  |                 SELECT lfbis_nr, family_name, name, billing_name, address, plz, ort, area, | ||||||
|  |                        date, weight, type, sortid, qualid, year, hkid, kmw, oe | ||||||
|  |                 FROM v_bki_delivery | ||||||
|  |                 WHERE year = {year} | ||||||
|  |                 """; | ||||||
|  |             var r = await cmd.ExecuteReaderAsync(); | ||||||
|  |             List<Row> rows = new(); | ||||||
|  |             while (await r.ReadAsync()) { | ||||||
|  |                 rows.Add(new( | ||||||
|  |                     (r.GetString(0), r.IsDBNull(1) ? null : r.GetString(1), r.IsDBNull(2) ? null : r.GetString(2), r.IsDBNull(3) ? null : r.GetString(3), r.GetString(4), r.GetInt32(5), r.GetString(6), r.GetInt32(7)), | ||||||
|  |                     (r.GetString(8), r.GetInt32(9), r.GetString(10), r.GetString(11), r.GetString(12), r.GetInt32(13), r.GetString(14), r.GetDouble(15), r.GetDouble(16)) | ||||||
|  |                 )); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         public void Export(AppDbContext ctx, int year) { |             await ExportAsync(rows); | ||||||
|             ExportAsync(ctx, year).GetAwaiter().GetResult(); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public override string FormatRow(DeliveryPart p) { |         public void Export(int year) { | ||||||
|             var d = p.Delivery; |             ExportAsync(year).GetAwaiter().GetResult(); | ||||||
|             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}"; |         public override string FormatRow(Row row) { | ||||||
|             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}"; |             var (member, delivery) = row; | ||||||
|  |             var (lfBisNr, familyName, name, billingName, address, plz, ort, area) = member; | ||||||
|  |             var (date, weight, type, sortid, qualid, year, hkid, kmw, oe) = delivery; | ||||||
|  |  | ||||||
|  |             var (n1, n2) = billingName == null ? (familyName, name) : Utils.SplitName(billingName, familyName); | ||||||
|  |             var (a1, a2) = Utils.SplitAddress(address); | ||||||
|  |             var memberData = $"{lfBisNr};{n1};{n2};{a1};{a2};{plz};{ort}"; | ||||||
|  |             var deliveryData = $"{string.Join(".", date.Split("-").Reverse())};{weight};TB;{(type == "W" ? "J" : "")};{(type == "R" ? "J" : "")};{sortid};;;{qualid};{year};{hkid};{kmw:0.0};{oe:0}"; | ||||||
|  |             var vollData = $"N;;;{area / 10_000.0}"; | ||||||
|  |  | ||||||
|             return $"{_clientData};{memberData};{deliveryData};{vollData}"; |             return $"{_clientData};{memberData};{deliveryData};{vollData}"; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2,43 +2,54 @@ using System; | |||||||
| using System.Collections; | using System.Collections; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.IO; | using System.IO; | ||||||
|  | using System.Linq; | ||||||
| using System.Text; | using System.Text; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace Elwig.Helpers.Export { | namespace Elwig.Helpers.Export { | ||||||
|     public abstract class Csv<T> : IExporter<T> { |     public abstract class Csv<T> : IExporter<T> { | ||||||
|  |  | ||||||
|         public static string FileExtension => "csv"; |         public static string FileExtension => "csv"; | ||||||
|  |  | ||||||
|         protected readonly StreamWriter Writer; |         private readonly StreamWriter _writer; | ||||||
|         protected readonly char Separator; |         protected readonly char Separator; | ||||||
|         protected string? Header; |         protected string? Header; | ||||||
|  |  | ||||||
|         public Csv(string filename, char separator = ';') : this(filename, separator, Encoding.UTF8) { } |         public Csv(string filename, char separator = ';') : this(filename, separator, Utils.UTF8) { } | ||||||
|  |  | ||||||
|         public Csv(string filename, char separator, Encoding encoding) { |         public Csv(string filename, char separator, Encoding encoding) { | ||||||
|             Writer = new StreamWriter(filename, false, encoding); |             _writer = new StreamWriter(filename, false, encoding); | ||||||
|             Separator = separator; |             Separator = separator; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void Dispose() { |         public void Dispose() { | ||||||
|             GC.SuppressFinalize(this); |             GC.SuppressFinalize(this); | ||||||
|             Writer.Dispose(); |             _writer.Dispose(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public ValueTask DisposeAsync() { |         public ValueTask DisposeAsync() { | ||||||
|             GC.SuppressFinalize(this); |             GC.SuppressFinalize(this); | ||||||
|             return Writer.DisposeAsync(); |             return _writer.DisposeAsync(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task ExportAsync(IEnumerable<T> data) { |         public async Task ExportAsync(IEnumerable<T> data, IProgress<double>? progress = null) { | ||||||
|             if (Header != null) await Writer.WriteLineAsync(Header); |             progress?.Report(0.0); | ||||||
|  |             int count = data.Count() + 2, i = 0; | ||||||
|  |  | ||||||
|  |             if (Header != null) await _writer.WriteLineAsync(Header); | ||||||
|  |             progress?.Report(100.0 * ++i / count); | ||||||
|  |  | ||||||
|             foreach (var row in data) { |             foreach (var row in data) { | ||||||
|                 await Writer.WriteLineAsync(FormatRow(row)); |                 await _writer.WriteLineAsync(FormatRow(row)); | ||||||
|             } |                 progress?.Report(100.0 * ++i / count); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         public void Export(IEnumerable<T> data) { |             await _writer.FlushAsync(); | ||||||
|             ExportAsync(data).GetAwaiter().GetResult(); |             progress?.Report(100.0); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void Export(IEnumerable<T> data, IProgress<double>? progress = null) { | ||||||
|  |             ExportAsync(data, progress).GetAwaiter().GetResult(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public string FormatRow(IEnumerable row) { |         public string FormatRow(IEnumerable row) { | ||||||
|   | |||||||
| @@ -1,6 +1,9 @@ | |||||||
| using Elwig.Helpers.Billing; | using Elwig.Helpers.Billing; | ||||||
|  | using Elwig.Models; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace Elwig.Helpers.Export { | namespace Elwig.Helpers.Export { | ||||||
| @@ -8,20 +11,99 @@ namespace Elwig.Helpers.Export { | |||||||
|  |  | ||||||
|         public static string FileExtension => "xml"; |         public static string FileExtension => "xml"; | ||||||
|  |  | ||||||
|  |         private readonly StreamWriter _writer; | ||||||
|  |         private readonly DateOnly _date; | ||||||
|  |         private readonly int _year; | ||||||
|  |         private readonly string _name; | ||||||
|  |         private readonly int _nr; | ||||||
|  |  | ||||||
|  |         public Ebics(PaymentVar variant, string filename) { | ||||||
|  |             _writer = new(filename, false, Utils.UTF8); | ||||||
|  |             _date = variant.TransferDate ?? DateOnly.Parse("2021-01-10"); //throw new ArgumentException("TransferDate has to be set in PaymentVar"); | ||||||
|  |             _year = variant.Year; | ||||||
|  |             _name = variant.Name; | ||||||
|  |             _nr = variant.AvNr; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         public void Dispose() { |         public void Dispose() { | ||||||
|             throw new NotImplementedException(); |             GC.SuppressFinalize(this); | ||||||
|  |             _writer.Dispose(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public ValueTask DisposeAsync() { |         public ValueTask DisposeAsync() { | ||||||
|             throw new NotImplementedException(); |             GC.SuppressFinalize(this); | ||||||
|  |             return _writer.DisposeAsync(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void Export(IEnumerable<Transaction> data) { |         public void Export(IEnumerable<Transaction> transactions, IProgress<double>? progress = null) { | ||||||
|             throw new NotImplementedException(); |             ExportAsync(transactions, progress).GetAwaiter().GetResult(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public Task ExportAsync(IEnumerable<Transaction> data) { |         public async Task ExportAsync(IEnumerable<Transaction> transactions, IProgress<double>? progress = null) { | ||||||
|             throw new NotImplementedException(); |             progress?.Report(0.0); | ||||||
|  |             var nbOfTxs = transactions.Count(); | ||||||
|  |             int count = nbOfTxs + 2, i = 0; | ||||||
|  |             var ctrlSum = Transaction.FormatAmountCent(transactions.Sum(tx => tx.AmountCent)); | ||||||
|  |             var msgId = $"ELWIG-{App.Client.NameToken}-{_year}-AV{_nr:00}"; | ||||||
|  |             var pmtInfId = $"{msgId}-1"; | ||||||
|  |  | ||||||
|  |             await _writer.WriteLineAsync($""" | ||||||
|  |                 <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  |                 <Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09" | ||||||
|  |                           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  |                           xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 pain.001.001.09.xsd"> | ||||||
|  |                   <CstmrCdtTrfInitn> | ||||||
|  |                     <GrpHdr> | ||||||
|  |                       <MsgId>{msgId}</MsgId> | ||||||
|  |                       <CreDtTm>{DateTime.UtcNow:o}</CreDtTm> | ||||||
|  |                       <NbOfTxs>{nbOfTxs}</NbOfTxs> | ||||||
|  |                       <CtrlSum>{ctrlSum}</CtrlSum> | ||||||
|  |                       <InitgPty><Nm>{App.Client.NameFull}</Nm></InitgPty> | ||||||
|  |                     </GrpHdr> | ||||||
|  |                     <PmtInf> | ||||||
|  |                       <PmtInfId>{pmtInfId}</PmtInfId> | ||||||
|  |                       <PmtMtd>TRF</PmtMtd> | ||||||
|  |                       <NbOfTxs>{nbOfTxs}</NbOfTxs> | ||||||
|  |                       <CtrlSum>{ctrlSum}</CtrlSum> | ||||||
|  |                       <ReqdExctnDt><Dt>{_date:yyyy-MM-dd}</Dt></ReqdExctnDt> | ||||||
|  |                       <Dbtr><Nm>{App.Client.NameFull}</Nm></Dbtr> | ||||||
|  |                       <DbtrAcct><Id><IBAN>{App.Client.Iban?.Replace(" ", "")}</IBAN></Id></DbtrAcct> | ||||||
|  |                       <DbtrAgt><FinInstnId><BICFI>{App.Client.Bic ?? "NOTPROVIDED"}</BICFI></FinInstnId></DbtrAgt> | ||||||
|  |                 """); | ||||||
|  |             progress?.Report(100.0 * ++i / count); | ||||||
|  |  | ||||||
|  |             foreach (var tx in transactions) { | ||||||
|  |                 var a = (IAddress?)tx.Member.BillingAddress ?? tx.Member; | ||||||
|  |                 var (a1, a2) = Utils.SplitAddress(a.Address); | ||||||
|  |                 var id = $"ELWIG-{App.Client.NameToken}-{_year}-TG{tx.Nr:0000}"; | ||||||
|  |                 var info = $"{_name} - Traubengutschrift {_year}/{tx.Nr:000}"; | ||||||
|  |                 await _writer.WriteLineAsync($""" | ||||||
|  |                           <CdtTrfTxInf> | ||||||
|  |                             <PmtId><EndToEndId>{id}</EndToEndId></PmtId> | ||||||
|  |                             <Amt><InstdAmt Ccy="{tx.Currency}">{Transaction.FormatAmountCent(tx.AmountCent)}</InstdAmt></Amt> | ||||||
|  |                             <Cdtr> | ||||||
|  |                               <Nm>{a.Name}</Nm> | ||||||
|  |                               <PstlAdr> | ||||||
|  |                                 <StrtNm>{a1}</StrtNm><BldgNb>{a2}</BldgNb> | ||||||
|  |                                 <PstCd>{a.PostalDest.AtPlz?.Plz}</PstCd><TwnNm>{a.PostalDest.AtPlz?.Ort.Name}</TwnNm> | ||||||
|  |                                 <Ctry>{a.PostalDest.Country.Alpha2}</Ctry> | ||||||
|  |                               </PstlAdr> | ||||||
|  |                             </Cdtr> | ||||||
|  |                             <CdtrAcct><Id><IBAN>{tx.Member.Iban}</IBAN></Id><CdtrAcct> | ||||||
|  |                             <CdtrAgt><FinInstnId><BICFI>{tx.Member.Bic ?? "NOTPROVIDED"}</BICFI></FinInstnId></CdtrAgt> | ||||||
|  |                             <RmtInf><Ustrd>{info}</Ustrd></RmtInf> | ||||||
|  |                           </CdtTrfTxInf> | ||||||
|  |                     """); | ||||||
|  |                 progress?.Report(100.0 * ++i / count); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             await _writer.WriteLineAsync(""" | ||||||
|  |                     </PmtInf> | ||||||
|  |                   </CstmrCdtTrfInitn> | ||||||
|  |                 </Document> | ||||||
|  |                 """); | ||||||
|  |             await _writer.FlushAsync(); | ||||||
|  |             progress?.Report(100.0); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,18 +7,20 @@ namespace Elwig.Helpers.Export { | |||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// The default file extension of the exported files to be used (whithout a preceding ".") |         /// The default file extension of the exported files to be used (whithout a preceding ".") | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         static string FileExtension { get; } |         static abstract string FileExtension { get; } | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Export the given data to the given file. |         /// Export the given data to the given file. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="data">The data to be exported</param> |         /// <param name="data">The data to be exported</param> | ||||||
|         void Export(IEnumerable<T> data); |         /// <param name="progress">The progress object to report to</param> | ||||||
|  |         void Export(IEnumerable<T> data, IProgress<double>? progress = null); | ||||||
|  |  | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         /// Export the given data to the given file. |         /// Asynchronosly export the given data to the given file. | ||||||
|         /// </summary> |         /// </summary> | ||||||
|         /// <param name="data">The data to be exported</param> |         /// <param name="data">The data to be exported</param> | ||||||
|         Task ExportAsync(IEnumerable<T> data); |         /// <param name="progress">The progress object to report to</param> | ||||||
|  |         Task ExportAsync(IEnumerable<T> data, IProgress<double>? progress = null); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								Elwig/Helpers/IAddress.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Elwig/Helpers/IAddress.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | using Elwig.Models; | ||||||
|  |  | ||||||
|  | namespace Elwig.Helpers { | ||||||
|  |     public interface IAddress { | ||||||
|  |         string Name { get; } | ||||||
|  |         string Address { get; } | ||||||
|  |         PostalDest PostalDest { get; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -15,6 +15,8 @@ using Elwig.Models; | |||||||
| namespace Elwig.Helpers { | namespace Elwig.Helpers { | ||||||
|     public static partial class Utils { |     public static partial class Utils { | ||||||
|  |  | ||||||
|  |         public static readonly Encoding UTF8 = new UTF8Encoding(false, true); | ||||||
|  |  | ||||||
|         public static int CurrentYear => DateTime.Now.Year; |         public static int CurrentYear => DateTime.Now.Year; | ||||||
|         public static int CurrentNextSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0); |         public static int CurrentNextSeason => DateTime.Now.Year - (DateTime.Now.Month <= 3 ? 1 : 0); | ||||||
|         public static int CurrentLastSeason => DateTime.Now.Year - (DateTime.Now.Month <= 7 ? 1 : 0); |         public static int CurrentLastSeason => DateTime.Now.Year - (DateTime.Now.Month <= 7 ? 1 : 0); | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
|  | using Elwig.Helpers; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  |  | ||||||
| namespace Elwig.Models { | namespace Elwig.Models { | ||||||
|     [Table("member_billing_address"), PrimaryKey("MgNr")] |     [Table("member_billing_address"), PrimaryKey("MgNr")] | ||||||
|     public class BillingAddr { |     public class BillingAddr : IAddress { | ||||||
|         [Column("mgnr")] |         [Column("mgnr")] | ||||||
|         public int MgNr { get; set; } |         public int MgNr { get; set; } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ using System.Linq; | |||||||
|  |  | ||||||
| namespace Elwig.Models { | namespace Elwig.Models { | ||||||
|     [Table("member"), PrimaryKey("MgNr")] |     [Table("member"), PrimaryKey("MgNr")] | ||||||
|     public class Member { |     public class Member : IAddress { | ||||||
|         [Column("mgnr")] |         [Column("mgnr")] | ||||||
|         public int MgNr { get; set; } |         public int MgNr { get; set; } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  |  | ||||||
| namespace Elwig.Models { | namespace Elwig.Models { | ||||||
|     [Table("payment_member"), PrimaryKey("Year", "AvNr", "MgNr")] |     [Table("payment_member"), PrimaryKey("Year", "AvNr", "MgNr"), Index("Year", "TgNr", IsUnique = true)] | ||||||
|     public class PaymentMember { |     public class PaymentMember { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
|         public int Year { get; set; } |         public int Year { get; set; } | ||||||
| @@ -16,6 +16,9 @@ namespace Elwig.Models { | |||||||
|         [Column("amount")] |         [Column("amount")] | ||||||
|         public long AmountValue { get; set; } |         public long AmountValue { get; set; } | ||||||
|  |  | ||||||
|  |         [Column("tgnr")] | ||||||
|  |         public int? TgNr { get; set; } | ||||||
|  |  | ||||||
|         [NotMapped] |         [NotMapped] | ||||||
|         public decimal Amount { |         public decimal Amount { | ||||||
|             get => Variant.Season.DecFromDb(AmountValue); |             get => Variant.Season.DecFromDb(AmountValue); | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System; | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  |  | ||||||
| namespace Elwig.Models { | namespace Elwig.Models { | ||||||
| @@ -19,12 +20,17 @@ namespace Elwig.Models { | |||||||
|  |  | ||||||
|         [NotMapped] |         [NotMapped] | ||||||
|         public DateOnly Date { |         public DateOnly Date { | ||||||
|             get { |             get => DateOnly.ParseExact(DateString, "yyyy-MM-dd"); | ||||||
|                 return DateOnly.ParseExact(DateString, "yyyy-MM-dd"); |             set => DateString = value.ToString("yyyy-MM-dd"); | ||||||
|             } |  | ||||||
|             set { |  | ||||||
|                 DateString = value.ToString("yyyy-MM-dd"); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [Column("transfer_date")] | ||||||
|  |         public string? TransferDateString { get; set; } | ||||||
|  |  | ||||||
|  |         [NotMapped] | ||||||
|  |         public DateOnly? TransferDate { | ||||||
|  |             get => TransferDateString != null ? DateOnly.ParseExact(TransferDateString, "yyyy-MM-dd") : null; | ||||||
|  |             set => TransferDateString = value?.ToString("yyyy-MM-dd"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         [Column("test_variant")] |         [Column("test_variant")] | ||||||
| @@ -68,5 +74,8 @@ namespace Elwig.Models { | |||||||
|  |  | ||||||
|         [ForeignKey("Year")] |         [ForeignKey("Year")] | ||||||
|         public virtual Season Season { get; private set; } |         public virtual Season Season { get; private set; } | ||||||
|  |  | ||||||
|  |         [InverseProperty("Variant")] | ||||||
|  |         public virtual ISet<PaymentMember> MemberPayments { get; private set; } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -48,6 +48,12 @@ namespace Elwig.Models { | |||||||
|         [InverseProperty("Season")] |         [InverseProperty("Season")] | ||||||
|         public virtual ISet<Modifier> Modifiers { get; private set; } |         public virtual ISet<Modifier> Modifiers { get; private set; } | ||||||
|  |  | ||||||
|  |         [InverseProperty("Season")] | ||||||
|  |         public virtual ISet<PaymentVar> PaymentVariants { get; private set; } | ||||||
|  |  | ||||||
|  |         [InverseProperty("Season")] | ||||||
|  |         public virtual ISet<Delivery> Deliveries { get; private set; } | ||||||
|  |  | ||||||
|         public decimal DecFromDb(long value) { |         public decimal DecFromDb(long value) { | ||||||
|             return Utils.DecFromDb(value, Precision); |             return Utils.DecFromDb(value, Precision); | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user