dmdb/model/money/BankTransfer.cs

155 lines
6.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
namespace dezentrale.model.money
{
[XmlType("BankTransfer")]
public class BankTransfer : MoneyTransfer
{
//This resembles an 1:1 data image from CSV entries.
[XmlElement] public string AccountInCharge { get; set; } = "";
[XmlElement] public DateTime BookingDate { get; set; }
[XmlElement] public string BookingText { get; set; } = "";
[XmlElement] public string CreditorID { get; set; } = "";
[XmlElement] public string MandateReference { get; set; } = "";
[XmlElement] public string ClientReference { get; set; } = "";
[XmlElement] public string Sammlerreferenz { get; set; } = "";
[XmlElement] public string LastschriftUrsprungsbetrag { get; set; } = "";
[XmlElement] public string AuslagenersatzRuecklastschrift { get; set; } = "";
[XmlElement] public string RecipientOrDebitor { get; set; } = "";
[XmlElement] public string IBAN { get; set; } = "";
[XmlElement] public string BIC { get; set; } = "";
[XmlElement] public string Info { get; set; } = "";
//During the CSV import process, generated BankTransfer objects will hold CsvFile/Line for later
//logging into member data / Main log (i.e. it is possible to track a MoneyTransfer from a
//Member object to a line from a specific csv file)
[XmlIgnore] public string CsvFile { get; set; } = null;
[XmlIgnore] public int CsvLine { get; set; } = 0;
public BankTransfer() : base() { }
public BankTransfer(List<string> csvHeadline, List<string> csvEntry, string csvFile = "", int csvLineNumber = 0) : base()
{
CsvFile = csvFile;
CsvLine = csvLineNumber;
int lc = csvEntry.Count;
if (lc > csvHeadline.Count) lc = csvHeadline.Count;
for (int i = 0; i < lc; i++)
{
switch (csvHeadline[i])
{
case "Auftragskonto": AccountInCharge = csvEntry[i]; break;
case "Buchungstag": BookingDate = DateTime.Parse(csvEntry[i]); break;
case "Valutadatum": ValutaDate = DateTime.Parse(csvEntry[i]); break;
case "Buchungstext": BookingText = csvEntry[i]; break;
case "Verwendungszweck": TransferReason = csvEntry[i]; break;
case "Glaeubiger ID": CreditorID = csvEntry[i]; break;
case "Mandatsreferenz": MandateReference = csvEntry[i]; break;
case "Kundenreferenz (End-to-End)": ClientReference = csvEntry[i]; break;
case "Sammlerreferenz": Sammlerreferenz = csvEntry[i]; break;
case "Lastschrift Ursprungsbetrag": LastschriftUrsprungsbetrag = csvEntry[i]; break;
case "Auslagenersatz Ruecklastschrift": AuslagenersatzRuecklastschrift = csvEntry[i]; break;
case "Beguenstigter/Zahlungspflichtiger": RecipientOrDebitor = csvEntry[i]; break;
case "Kontonummer/IBAN":
case "Kontonummer": IBAN = csvEntry[i].Trim(); break;
case "BIC (SWIFT-Code)":
case "BLZ": BIC = csvEntry[i].Trim(); break;
case "Betrag":
{
string sAmount = csvEntry[i].Replace(',', '.');
float fAmount = float.Parse(sAmount, System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
Amount = Convert.ToInt64(fAmount * 100);
} break;
case "Waehrung": Currency = csvEntry[i]; break;
case "Info": Info = csvEntry[i]; break;
default:
throw new Exception($"invalid csv headline field: \"{csvHeadline[i]}\" csvFile {csvFile} line {csvLineNumber}");
}
}
}
private const string ibanPattern = "^[A-Z]{2}\\d{2}\\d{8}\\d{10}$";
public static string IbanRegexAssert(string iban, bool checkPz = true)
{
iban = iban.Replace(" ", "").Replace("-", "");
if (!Regex.IsMatch(iban, ibanPattern))
{
throw new FormatException("IBAN format invalid");
}
if(checkPz)
{
if(!_PzOk(iban))
{
throw new Exception("IBAN checksum error");
}
}
return iban;
}
private static int _CCodeToInt(string cCode)
{
char[] c = cCode.ToCharArray();
string ret = String.Format("{0}{1}", c[0] + 10 - 'A', c[1] + 10 - 'A');
return Convert.ToInt32(ret);
}
private static string _CalcPz(string cCode, string blz, string kto)
{
//https://www.iban.de/iban-pruefsumme.html
int cci = _CCodeToInt(cCode);
string modBaseS = String.Format("{0}{1}{2}00", blz, kto, cci);
//760909001234567890131400
BigInteger mod = BigInteger.Parse(modBaseS);
mod = BigInteger.Remainder(mod, new BigInteger(97));
string pz = String.Format("{0:D2}", 98 - mod);
return pz;
}
private static string _CalcPz(string iban)
{
return _CalcPz(iban.Substring(0, 2), iban.Substring(4, 8), iban.Substring(12,10));
}
public static string CalcPz(string iban)
{
iban = IbanRegexAssert(iban, false);
return _CalcPz(iban);
}
private static bool _PzOk(string iban)
{
return _CalcPz(iban).Equals(iban.Substring(2, 2));
}
public static bool PzOk(string iban)
{
iban = IbanRegexAssert(iban, false);
return _PzOk(iban);
}
public static string GetKtoFromIban(string iban)
{
iban = IbanRegexAssert(iban);
return iban.Substring(12);
}
public static string GetBlzFromIban(string iban)
{
iban = IbanRegexAssert(iban);
return iban.Substring(4, 8);
}
public static string GetCCodeFromIban(string iban)
{
iban = IbanRegexAssert(iban);
return iban.Substring(0,2);
}
public static string GetIbanFromKtoBlz(string cCode, string blz, string kto)
{
//build iban
string Pz = _CalcPz(cCode, blz, kto);
string iban = String.Format("{0}{1}{2}{3}", cCode, Pz, blz, kto);
return IbanRegexAssert(iban);
}
}
}