104 lines
4.9 KiB
C#
104 lines
4.9 KiB
C#
using Elwig.Models.Dtos;
|
|
using Elwig.Models.Entities;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Security;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Elwig.Helpers.Export {
|
|
public class Ebics(PaymentVar variant, string filename, int version) : IBankingExporter {
|
|
|
|
public static string FileExtension => "xml";
|
|
|
|
private readonly StreamWriter Writer = new(filename, false, Utils.UTF8);
|
|
private readonly DateOnly Date = variant.TransferDate ?? throw new ArgumentException("TransferDate has to be set in PaymentVar");
|
|
private readonly int Year = variant.Year;
|
|
private readonly string Name = variant.Name;
|
|
private readonly int AvNr = variant.AvNr;
|
|
private readonly int Version = version;
|
|
|
|
public void Dispose() {
|
|
GC.SuppressFinalize(this);
|
|
Writer.Dispose();
|
|
}
|
|
|
|
public ValueTask DisposeAsync() {
|
|
GC.SuppressFinalize(this);
|
|
return Writer.DisposeAsync();
|
|
}
|
|
|
|
public void Export(IEnumerable<Transaction> transactions, IProgress<double>? progress = null) {
|
|
ExportAsync(transactions, progress).GetAwaiter().GetResult();
|
|
}
|
|
|
|
public async Task ExportAsync(IEnumerable<Transaction> transactions, IProgress<double>? progress = null) {
|
|
if (transactions.Any(tx => tx.Amount < 0))
|
|
throw new ArgumentException("Tranaction amount may not be negative");
|
|
progress?.Report(0.0);
|
|
var nbOfTxs = transactions.Count();
|
|
int count = nbOfTxs + 2, i = 0;
|
|
var ctrlSum = transactions.Sum(tx => tx.Amount);
|
|
var msgId = $"ELWIG-{App.Client.NameToken}-{Year}-AV{AvNr: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.{Version:00}">
|
|
<CstmrCdtTrfInitn>
|
|
<GrpHdr>
|
|
<MsgId>{msgId}</MsgId>
|
|
<CreDtTm>{DateTime.UtcNow:o}</CreDtTm>
|
|
<NbOfTxs>{nbOfTxs}</NbOfTxs>
|
|
<CtrlSum>{Transaction.FormatAmount(ctrlSum)}</CtrlSum>
|
|
<InitgPty><Nm>{SecurityElement.Escape(App.Client.NameFull)}</Nm></InitgPty>
|
|
</GrpHdr>
|
|
<PmtInf>
|
|
<PmtInfId>{pmtInfId}</PmtInfId>
|
|
<PmtMtd>TRF</PmtMtd>
|
|
<NbOfTxs>{nbOfTxs}</NbOfTxs>
|
|
<CtrlSum>{Transaction.FormatAmount(ctrlSum)}</CtrlSum>
|
|
<ReqdExctnDt>{(Version >= 8 ? "<Dt>" : "")}{Date:yyyy-MM-dd}{(Version >= 8 ? "</Dt>" : "")}</ReqdExctnDt>
|
|
<Dbtr><Nm>{SecurityElement.Escape(App.Client.NameFull)}</Nm></Dbtr>
|
|
<DbtrAcct><Id><IBAN>{App.Client.Iban!.Replace(" ", "")}</IBAN></Id></DbtrAcct>
|
|
<DbtrAgt><FinInstnId>{(Version >= 4 ? "<BICFI>" : "<BIC>")}{App.Client.Bic ?? "NOTPROVIDED"}{(Version >= 4 ? "</BICFI>" : "</BIC>")}</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 Nr. {Year}/{tx.Nr:000}";
|
|
await Writer.WriteLineAsync($"""
|
|
<CdtTrfTxInf>
|
|
<PmtId><EndToEndId>{id}</EndToEndId></PmtId>
|
|
<Amt><InstdAmt Ccy="{tx.Currency}">{Transaction.FormatAmount(tx.Amount)}</InstdAmt></Amt>
|
|
<Cdtr>
|
|
<Nm>{SecurityElement.Escape(a.Name[..Math.Min(140, a.Name.Length)])}</Nm>
|
|
<PstlAdr>
|
|
<StrtNm>{a1?[..Math.Min(70, a1.Length)]}</StrtNm><BldgNb>{SecurityElement.Escape(a2?[..Math.Min(16, a2.Length)])}</BldgNb>
|
|
<PstCd>{a.PostalDest.AtPlz?.Plz}</PstCd><TwnNm>{SecurityElement.Escape(a.PostalDest.AtPlz?.Ort.Name)}</TwnNm>
|
|
<Ctry>{a.PostalDest.Country.Alpha2}</Ctry>
|
|
</PstlAdr>
|
|
</Cdtr>
|
|
<CdtrAcct><Id><IBAN>{tx.Member.Iban!}</IBAN></Id></CdtrAcct>
|
|
<RmtInf><Ustrd>{SecurityElement.Escape(info)}</Ustrd></RmtInf>
|
|
</CdtTrfTxInf>
|
|
""");
|
|
progress?.Report(100.0 * ++i / count);
|
|
}
|
|
|
|
await Writer.WriteLineAsync("""
|
|
</PmtInf>
|
|
</CstmrCdtTrfInitn>
|
|
</Document>
|
|
""");
|
|
await Writer.FlushAsync();
|
|
progress?.Report(100.0);
|
|
}
|
|
}
|
|
}
|