Enhance banking transaction data structure and validation
Playwright Tests / test (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
- Increased the length of the NameOfPayer field from NVARCHAR(60) to NVARCHAR(140) in the banking transactions function, table, temporary table, and user-defined type to accommodate longer names. - Expanded the SepaRemittanceInformation field from VARCHAR(150) to VARCHAR(200) in the banking transactions function for more detailed remittance information. - Modified the stored procedure fds__setBankingtransaction_done to return additional transaction data (ValueDate and Amount) along with the success flag for improved notification messaging. - Added validation in MFRClientConfig constructor to ensure the provided URL is not null or empty, enhancing error handling for configuration settings.
This commit is contained in:
@@ -129,4 +129,51 @@ public class BankingParseToDatatableTests
|
||||
var ex = Record.Exception(() => Svc.ParseToDatatable(stream));
|
||||
Assert.Null(ex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("AccountIdentification", 50)]
|
||||
[InlineData("NameOfPayer", 140)]
|
||||
[InlineData("SepaRemittanceInformation", 200)]
|
||||
[InlineData("DebitCreditMark", 2)]
|
||||
[InlineData("UnstructuredData", 390)]
|
||||
public void ParseToDatatable_DefaultSchema_EnforcesKnownColumnWidth(string column, int expectedMaxLength)
|
||||
{
|
||||
using var stream = ToStream(MinimalMT940);
|
||||
var table = Svc.ParseToDatatable(stream);
|
||||
Assert.Equal(expectedMaxLength, table.Columns[column]!.MaxLength);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseToDatatable_SchemaWithoutMaxLength_StillEnforcesKnownWidths()
|
||||
{
|
||||
// Mirrors the real bug: SELECT TOP(0) * FROM @tmp (a table-type variable) comes back
|
||||
// from ADO.NET with MaxLength = -1 for every string column, so a schema built purely
|
||||
// from that fetch cannot truncate on its own. ApplyKnownColumnWidths must patch it up
|
||||
// regardless of what the caller-supplied schema carries.
|
||||
var schema = new DataTable();
|
||||
schema.Columns.Add("AccountIdentification", typeof(string));
|
||||
schema.Columns.Add("Amount", typeof(decimal));
|
||||
schema.Columns.Add("DebitCreditMark", typeof(string));
|
||||
Assert.Equal(-1, schema.Columns["AccountIdentification"]!.MaxLength);
|
||||
|
||||
using var stream = ToStream(MinimalMT940);
|
||||
var table = Svc.ParseToDatatable(stream, schemaDatatable: schema);
|
||||
|
||||
Assert.Equal(50, table.Columns["AccountIdentification"]!.MaxLength);
|
||||
Assert.Equal(2, table.Columns["DebitCreditMark"]!.MaxLength);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseToDatatable_OverlongAccountIdentification_TruncatesInsteadOfThrowing()
|
||||
{
|
||||
string longAccount = "DE" + new string('9', 60); // 62 chars, over the 50-char column width
|
||||
string mt940 = MinimalMT940.Replace("DE12345678901234567890", longAccount);
|
||||
|
||||
using var stream = ToStream(mt940);
|
||||
var table = Svc.ParseToDatatable(stream);
|
||||
|
||||
Assert.Equal(1, table.Rows.Count);
|
||||
Assert.Equal(50, ((string)table.Rows[0]["AccountIdentification"]).Length);
|
||||
Assert.Equal(longAccount[..50], table.Rows[0]["AccountIdentification"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ public class BankingDualFormatTests
|
||||
t.Columns.Add("Amount", typeof(decimal));
|
||||
t.Columns.Add("ValueDate", typeof(DateTime));
|
||||
t.Columns.Add("FundsCode", typeof(string)).MaxLength = 1; // VARCHAR(1) — currency "EUR" must not land here
|
||||
t.Columns.Add("NameOfPayer", typeof(string)).MaxLength = 60;
|
||||
t.Columns.Add("NameOfPayer", typeof(string)).MaxLength = 140;
|
||||
t.Columns.Add("PostingText", typeof(string)).MaxLength = 30;
|
||||
t.Columns.Add("TransactionTypeIdCode", typeof(string)).MaxLength = 3;
|
||||
t.Columns.Add("SepaRemittanceInformation", typeof(string)).MaxLength = 200;
|
||||
@@ -418,7 +418,9 @@ public class BankingDualFormatTests
|
||||
[Fact]
|
||||
public void ParseToDatatable_Camt_OverlongFields_AreTruncatedNotDropped()
|
||||
{
|
||||
const string longName = "Ein sehr langer Zahlungspflichtiger Name der weit ueber sechzig Zeichen hinausgeht GmbH Co KG";
|
||||
// Some banks put the full postal address into <Nm>, not just a name — real-world case
|
||||
// that exceeds even the ISO 20022 Max140Text width this column is now sized to.
|
||||
const string longName = "Ein sehr langer Zahlungspflichtiger Name der weit ueber hundertvierzig Zeichen hinausgeht GmbH Co KG, Musterstrasse 123, 12345 Musterstadt, Deutschland";
|
||||
string camt = """
|
||||
<?xml version="1.0"?>
|
||||
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02">
|
||||
@@ -440,7 +442,7 @@ public class BankingDualFormatTests
|
||||
var t = Svc.ParseToDatatable(s, schemaDatatable: DbLikeSchema());
|
||||
|
||||
Assert.Equal(1, t.Rows.Count);
|
||||
Assert.Equal(60, ((string)t.Rows[0]["NameOfPayer"]).Length); // truncated to column width, row kept
|
||||
Assert.Equal(longName[..60], t.Rows[0]["NameOfPayer"]);
|
||||
Assert.Equal(140, ((string)t.Rows[0]["NameOfPayer"]).Length); // truncated to column width, row kept
|
||||
Assert.Equal(longName[..140], t.Rows[0]["NameOfPayer"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,18 @@ public class MFRClientConfigTests
|
||||
Assert.Equal("", config.LogoutAddress);
|
||||
Assert.Equal("", config.TokenCookieName);
|
||||
}
|
||||
|
||||
// Regression: an empty/missing host used to be silently turned into "https:///odata/"
|
||||
// (empty authority), which only failed much later inside RestSharp with a cryptic
|
||||
// "Invalid URI: The hostname could not be parsed." Fail fast at construction instead.
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void Constructor_WithMissingHost_ThrowsArgumentException(string? url)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => new MFRClientConfig(url!));
|
||||
}
|
||||
}
|
||||
|
||||
public class MFRClientCredentialsTests
|
||||
|
||||
Reference in New Issue
Block a user