From 24dbed32ccd6ee79754de2c6ec54a3084ca39773 Mon Sep 17 00:00:00 2001
From: pitzm
Date: Mon, 2 Feb 2026 14:40:55 +0100
Subject: [PATCH 01/11] ZUGFeRdRESTService - Validation Controller:
REFERENCES_Rejection-Messages auswerten und als WebMessage ausgeben
---
.../Controllers/ValidationController.cs | 292 ++++++++++++++++--
.../appsettings.Development.json | 10 +-
2 files changed, 269 insertions(+), 33 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index 0ac2c0e8..ae616ab0 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -1,18 +1,17 @@
-using System;
-using System.IO;
-using System.Linq;
-using System.Collections.Generic;
+using DigitalData.Modules.Interfaces;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
-using DigitalData.Modules.Interfaces;
-using static DigitalData.Modules.Interfaces.Exceptions;
-using static DigitalData.Modules.Interfaces.ZUGFeRDInterface;
-using static DigitalData.Modules.Interfaces.PropertyValues;
-using System.Data.SqlClient;
using Microsoft.Extensions.Configuration;
-using System.Xml.Linq;
-using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.IO;
+using System.Linq;
using System.Text.RegularExpressions;
+using System.Xml.Linq;
+using static DigitalData.Modules.Interfaces.Exceptions;
+using static DigitalData.Modules.Interfaces.PropertyValues;
+using static DigitalData.Modules.Interfaces.ZUGFeRDInterface;
namespace ZUGFeRDRESTService.Controllers
{
@@ -26,6 +25,29 @@ namespace ZUGFeRDRESTService.Controllers
public const string ADDED_WHO = "ZUGFeRD REST Service";
public const string MESSAGEID_DOMAIN = "test.wisag.de";
+ public const string VALIDATION_SUCCESS = "VALIDATION SUCCESS";
+ public const string REFERENCES_Rejection_30001 = "REFERENCES_Rejection_30001";
+ public const string REFERENCES_Rejection_30002 = "REFERENCES_Rejection_30002";
+ public const string REFERENCES_Rejection_30003_1 = "REFERENCES_Rejection_30003_1";
+ public const string REFERENCES_Rejection_30003_2 = "REFERENCES_Rejection_30003_2";
+ public const string REFERENCES_Rejection_30003_3 = "REFERENCES_Rejection_30003_3";
+ public const string REFERENCES_Rejection_30004_1 = "REFERENCES_Rejection_30004_1";
+ public const string REFERENCES_Rejection_30004_2 = "REFERENCES_Rejection_30004_2";
+ public const string REFERENCES_Rejection_30004_3 = "REFERENCES_Rejection_30004_3";
+ public const string REFERENCES_Rejection_30005_1 = "REFERENCES_Rejection_30005_1";
+ public const string REFERENCES_Rejection_30005_2 = "REFERENCES_Rejection_30005_2";
+ public const string REFERENCES_Rejection_30006 = "REFERENCES_Rejection_30006" ;
+ public const string REFERENCES_Rejection_30007 = "REFERENCES_Rejection_30007" ;
+ public const string REFERENCES_Rejection_30007_1 = "REFERENCES_Rejection_30007_1";
+ public const string REFERENCES_Rejection_30008 = "REFERENCES_Rejection_30008" ;
+ public const string REFERENCES_Rejection_30009 = "REFERENCES_Rejection_30009" ;
+ public const string REFERENCES_Rejection_30010 = "REFERENCES_Rejection_30010" ;
+ public const string REFERENCES_Rejection_30011 = "REFERENCES_Rejection_30011" ;
+ public const string REFERENCES_Rejection_30012 = "REFERENCES_Rejection_30012" ;
+ public const string AMOUNT_CALC_REJECTION = "AMOUNT_CALC_REJECTION";
+
+ private List _ValidationErrors;
+
private const int MAX_FILE_SIZE_DEFAULT = 25;
private readonly ZUGFeRDInterface _zugferd;
@@ -82,7 +104,29 @@ namespace ZUGFeRDRESTService.Controllers
_logger.Debug("Property Map list initial: [{0}] entries found. [{1}] entries will be available.", oPropertyMapList.Count, _propertyMapList.Count);
_RecjectionMessageList = database.GetRejectionMessageList();
-
+
+ _ValidationErrors = new List() {
+ REFERENCES_Rejection_30001,
+ REFERENCES_Rejection_30002,
+ REFERENCES_Rejection_30003_1,
+ REFERENCES_Rejection_30003_2,
+ REFERENCES_Rejection_30003_3,
+ REFERENCES_Rejection_30004_1,
+ REFERENCES_Rejection_30004_2,
+ REFERENCES_Rejection_30004_3,
+ REFERENCES_Rejection_30005_1,
+ REFERENCES_Rejection_30005_2,
+ REFERENCES_Rejection_30006,
+ REFERENCES_Rejection_30007,
+ REFERENCES_Rejection_30007_1,
+ REFERENCES_Rejection_30008,
+ REFERENCES_Rejection_30009,
+ REFERENCES_Rejection_30010,
+ REFERENCES_Rejection_30011,
+ REFERENCES_Rejection_30012,
+ AMOUNT_CALC_REJECTION
+ };
+
_logger.Debug("Validation Controller initialized!");
}
@@ -189,19 +233,19 @@ namespace ZUGFeRDRESTService.Controllers
_logger.Info("Detected Specification was: [{0}]", oZugferdResult.Specification);
- var oFilteredPropertyMap = _zugferd.FilterPropertyMap(_propertyMapList, oZugferdResult.Specification);
+ var oFilteredPropertyMap = _zugferd.FilterPropertyMap(_propertyMapList, oZugferdResult.Specification);
if (oFilteredPropertyMap.Count == 0)
{
_logger.Warn("No properties found in property map for specification [{0}]", oZugferdResult.Specification);
//throw new ZUGFeRDExecption(ErrorType.UnsupportedFormat, "Unsupported Format");
throw new ZUGFeRDExecption(ErrorCodes.UnsupportedFerdException, "Unsupported Format");
- }
+ }
else
{
_logger.Debug("Property map contains [{0}] entries for specification [{1}]", oFilteredPropertyMap.Count, oZugferdResult.Specification);
}
-
+
_logger.Info("Starting structural check against the database.");
oPropertyResult = _props.CheckPropertyValues(oZugferdResult.SchemaObject, oFilteredPropertyMap, "MESSAGEID");
@@ -221,7 +265,7 @@ namespace ZUGFeRDRESTService.Controllers
{
//throw new ZUGFeRDExecption(ErrorType.MissingProperties, "Missing Properties");
throw new ZUGFeRDExecption(ErrorCodes.MissingValueException, "Missing Properties");
- }
+ }
Tuple oValidateResult = ValidateBuyerOrderReference(oPropertyResult.ValidProperties);
@@ -233,10 +277,9 @@ namespace ZUGFeRDRESTService.Controllers
string oValidateResultString = oValidateResult.Item2;
- if (oValidateResultString == "ALL REFERENCES CHECKED POSITIVE")
+ if (oValidateResultString.Equals(VALIDATION_SUCCESS))
{
string oMessage = "Die hochgeladene Datei ist eine gültige-ZUGFeRD Rechnung";
-
_logger.Info($"Responding with message: [{oMessage}]");
return new ValidationResponse()
@@ -244,10 +287,10 @@ namespace ZUGFeRDRESTService.Controllers
status = RESPONSE_OK,
message = oMessage
};
- } else
+ }
+ else
{
string oMessage = oValidateResultString;
-
_logger.Info($"Responding with message: [{oMessage}]");
return new ValidationResponse()
@@ -256,7 +299,8 @@ namespace ZUGFeRDRESTService.Controllers
message = oMessage
};
}
- };
+ }
+
}
catch (ZUGFeRDExecption ex)
{
@@ -299,9 +343,9 @@ namespace ZUGFeRDRESTService.Controllers
break;
}
}
- else
+ else
{
- oMessage = "Alte Logik. Meldung nicht gefunden";
+ oMessage = "Alte Logik. Meldung nicht gefunden";
}
_logger.Info($"Responding with message: [{oMessage}]");
@@ -315,6 +359,8 @@ namespace ZUGFeRDRESTService.Controllers
}
catch (ValidationException ex)
{
+ _logger.Error(ex);
+
var rejectionCodeNumber = this.GetRejectionCodeNumber(ex.ErrorCode);
// Der gesamte Ausgabetext muss anhand des ErrorCodes ermittelt werden
@@ -348,10 +394,14 @@ namespace ZUGFeRDRESTService.Controllers
}
}
+ ///
+ /// Hier wird eine externe Prozedur gerufen, PRCUST_INV_CHECK_FROM_PORTAL,
+ /// die das Ergebnis der Referenzpruefung liefert.
+ ///
private Tuple ValidateBuyerOrderReference(List pProperties)
{
var oMessageId = GetMessageId();
- _logger.Debug("Created new MessageId: [{0}]", oMessageId);
+ _logger.Debug("Created new MessageId: [{0}]", oMessageId);
_logger.Debug("Inserting properties into database.");
foreach (var oItem in pProperties)
@@ -377,6 +427,59 @@ namespace ZUGFeRDRESTService.Controllers
if (_database.MSSQL.ExecuteNonQuery(oCommand))
{
string oReturnValue = (string)oCommand.Parameters["@MSG_OUTPUT"].Value;
+
+ _logger.Debug("Validation Result message from DB: " + oReturnValue);
+
+ if (oReturnValue.Equals("ALL REFERENCES CHECKED POSITIVE", StringComparison.OrdinalIgnoreCase))
+ {
+ _logger.Debug("Validation Success");
+ oReturnValue = VALIDATION_SUCCESS;
+ }
+ else
+ {
+ // Gehe durch die möglichen Fehler, und ermittle Rückmeldung
+ foreach (var oRejectionItem in _ValidationErrors)
+ {
+ if (oReturnValue.Contains(oRejectionItem, StringComparison.OrdinalIgnoreCase))
+ {
+ _logger.Debug("oRejectionItem match: " + oRejectionItem);
+
+ var oDbMessage = this.GetRejectionMessage(oRejectionItem);
+
+ //Jetzt müssen ggf Platzhalter ersetzt werden.
+ if (oRejectionItem == REFERENCES_Rejection_30003_2)
+ {
+ string oReplaceParam1 = GetReplaceText1_30003_2(pProperties);
+ string oReplaceParam2 = GetReplaceText2_30003_2(pProperties);
+
+ oReturnValue = oDbMessage.Replace("@REPLACE_PARAM1", oReplaceParam1);
+ oReturnValue = oReturnValue.Replace("@REPLACE_PARAM2", oReplaceParam2);
+
+ }
+ else if (oRejectionItem == REFERENCES_Rejection_30003_3)
+ {
+ string oReplaceParam1 = GetReplaceText1_30003_3(pProperties);
+
+ oReturnValue = oDbMessage.Replace("@REPLACE_PARAM1", oReplaceParam1);
+ }
+ else if (oRejectionItem == REFERENCES_Rejection_30001)
+ {
+ // TODO - BUKR?
+ oReturnValue = oDbMessage.Replace("@REPLACE_PARAM1", "9999");
+ }
+ else
+ {
+ oReturnValue = oDbMessage;
+ }
+
+ // Für alle den RejectionCode setzen
+ oReturnValue = oReturnValue.Replace("@REJECTION_CODE", oRejectionItem);
+ break;
+ }
+ }
+ }
+
+ _logger.Debug("Validation terminal Result message: " + oReturnValue);
return new Tuple(true, oReturnValue);
}
@@ -390,7 +493,122 @@ namespace ZUGFeRDRESTService.Controllers
{
_logger.Error(e);
return new Tuple(false, string.Empty);
- }
+ }
+ }
+
+ private string GetReplaceText1_30003_3(List pProperties)
+ {
+ string oReplaceParam1 = string.Empty;
+
+ // BuyerOrderReferencedDocument
+ var itemBT13 = pProperties.Where(i => i.TableColumn == "INVOICE_REFERENCE").FirstOrDefault();
+ string valueBt13 = "-";
+ if (itemBT13 != null)
+ {
+ valueBt13 = string.IsNullOrEmpty(itemBT13.Value) ? "-" : itemBT13.Value;
+ }
+ oReplaceParam1 += "[BuyerOrderReferencedDocument] (BT-13) = [" + valueBt13 + "]";
+
+
+ // BuyerReference
+ var itemBT10 = pProperties.Where(i => i.TableColumn == "INVOICE_REFERENCE3").FirstOrDefault();
+ string valueBt10 = "-";
+ if (itemBT10 != null)
+ {
+ valueBt10 = string.IsNullOrEmpty(itemBT10.Value) ? "-" : itemBT10.Value;
+ }
+ oReplaceParam1 += "[BuyerReference] (BT-10) = [" + valueBt10 + "]";
+
+
+ // CostCenter
+ var itemBT19 = pProperties.Where(i => i.TableColumn == "INVOICE_COST_CENTER").FirstOrDefault();
+ string valueBt19 = "-";
+ if (itemBT19 != null)
+ {
+ valueBt19 = string.IsNullOrEmpty(itemBT19.Value) ? "-" : itemBT19.Value;
+ }
+ oReplaceParam1 += "[CostCenter] (BT-19) = [" + valueBt19 + "]";
+
+ // BuyerID
+ var itemBT46 = pProperties.Where(i => i.TableColumn == "INVOICE_BUYER_ID").FirstOrDefault();
+ string valueBt46 = "-";
+ if (itemBT46 != null)
+ {
+ valueBt46 = string.IsNullOrEmpty(itemBT46.Value) ? "-" : itemBT46.Value;
+ }
+ oReplaceParam1 += "[BuyerTradeParty] (BT-46) = [" + valueBt46 + "]";
+
+ oReplaceParam1 = "";
+ _logger.Debug("oReplaceParam1-Text: " + oReplaceParam1);
+
+ return oReplaceParam1;
+ }
+
+ private string GetReplaceText2_30003_2(List pProperties)
+ {
+ string oReplaceParam2 = string.Empty;
+
+ // BuyerTradeParty.Name
+ var itemBT44 = pProperties.Where(i => i.TableColumn == "INVOICE_BUYER_NAME").FirstOrDefault();
+ string valueBt44 = "-";
+ if (itemBT44 != null)
+ {
+ valueBt44 = string.IsNullOrEmpty(itemBT44.Value) ? "-" : itemBT44.Value;
+ }
+ oReplaceParam2 += "[BuyerTradeParty.Name] (BT-44) = [" + valueBt44 + "]";
+
+ // BuyerTradeParty.PostalTradeAddress.LineTwo
+ var itemBT51 = pProperties.Where(i => i.TableColumn == "INVOICE_BUYER_ADRESS2").FirstOrDefault();
+ string valueBt51 = "-";
+ if (itemBT51 != null)
+ {
+ valueBt51 = string.IsNullOrEmpty(itemBT51.Value) ? "-" : itemBT51.Value;
+ }
+ oReplaceParam2 += "[BuyerTradeParty.PostalTradeAddress.LineTwo] (BT-51) = [" + valueBt51 + "]";
+
+ oReplaceParam2 = "";
+ _logger.Debug("oReplaceParam2-Text: " + oReplaceParam2);
+
+ return oReplaceParam2;
+ }
+
+ private string GetReplaceText1_30003_2(List pProperties)
+ {
+ string oReplaceParam1 = string.Empty;
+
+ // BuyerOrderReferencedDocument
+ var itemBT13 = pProperties.Where(i => i.TableColumn == "INVOICE_REFERENCE").FirstOrDefault();
+ string valueBt13 = "-";
+ if (itemBT13 != null)
+ {
+ valueBt13 = string.IsNullOrEmpty(itemBT13.Value) ? "-" : itemBT13.Value;
+ }
+ oReplaceParam1 += "[BuyerOrderReferencedDocument] (BT-13) = [" + valueBt13 + "]";
+
+
+ // BuyerReference
+ var itemBT10 = pProperties.Where(i => i.TableColumn == "INVOICE_REFERENCE3").FirstOrDefault();
+ string valueBt10 = "-";
+ if (itemBT10 != null)
+ {
+ valueBt10 = string.IsNullOrEmpty(itemBT10.Value) ? "-" : itemBT10.Value;
+ }
+ oReplaceParam1 += "[BuyerReference] (BT-10) = [" + valueBt10 + "]";
+
+
+ // CostCenter
+ var itemBT19 = pProperties.Where(i => i.TableColumn == "INVOICE_COST_CENTER").FirstOrDefault();
+ string valueBt19 = "-";
+ if (itemBT19 != null)
+ {
+ valueBt19 = string.IsNullOrEmpty(itemBT19.Value) ? "-" : itemBT19.Value;
+ }
+ oReplaceParam1 += "[CostCenter] (BT-19) = [" + valueBt19 + "]";
+
+ oReplaceParam1 = "";
+ _logger.Debug("oReplaceParam1-Text: " + oReplaceParam1);
+
+ return oReplaceParam1;
}
public string GetMessageId()
@@ -428,7 +646,7 @@ namespace ZUGFeRDRESTService.Controllers
{
itemValue = pProperty.Value;
}
-
+
var oParams = new SqlParameter[]
{
new SqlParameter("@REFERENCE_GUID", pMessageId),
@@ -449,7 +667,7 @@ namespace ZUGFeRDRESTService.Controllers
{
_logger.Error(ex);
return false;
- }
+ }
}
///
@@ -463,7 +681,25 @@ namespace ZUGFeRDRESTService.Controllers
// Sprache wird man vielleicht mal auswählen können
var language = "de-DE";
- var searchTitle = "ZUGFERD_Rejection_" + pErrorCode + "_Web";
+ var searchTitle = string.Empty;
+
+ if (pErrorCode.Contains("2000"))
+ {
+ searchTitle = "ZUGFERD_Rejection_" + pErrorCode + "_Web";
+ }
+ else if (pErrorCode.Contains("REFERENCES_Rejection_3000"))
+ {
+ searchTitle = pErrorCode + "_Web";
+ }
+ else if (pErrorCode.Contains("AMOUNT_CALC"))
+ {
+ searchTitle = "AMOUNT_CALC_REJECTION_Web";
+ }
+ else
+ {
+ // else-Fall muss noch geklärt werden.
+ searchTitle = "AMOUNT_CALC_REJECTION_Web";
+ }
var messageItem = _RecjectionMessageList.Where(i => i.Title.Equals(searchTitle, StringComparison.OrdinalIgnoreCase) && i.Language.Equals(language, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
if (messageItem != null)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/appsettings.Development.json b/WEBSERVICES/ZUGFeRDRESTService/appsettings.Development.json
index b6613161..1bf7cf67 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/appsettings.Development.json
+++ b/WEBSERVICES/ZUGFeRDRESTService/appsettings.Development.json
@@ -20,11 +20,11 @@
},
"Zugferd": {
"AllowZugferd10": true,
- "AllowZugferd2x": false,
- "AllowZugferd23x": false,
- "AllowFacturX": false,
- "AllowXRechnung": false,
- "AllowPeppolBISBill3x": false
+ "AllowZugferd2x": true,
+ "AllowZugferd23x": true,
+ "AllowFacturX": true,
+ "AllowXRechnung": true,
+ "AllowPeppolBISBill3x": true
},
"GDPictureVersion": "",
"MaxFileSizeInMegabytes": 25
From d1dbe8096d73955588b02af355154a94cb9fd4d5 Mon Sep 17 00:00:00 2001
From: pitzm
Date: Wed, 4 Feb 2026 14:13:11 +0100
Subject: [PATCH 02/11] =?UTF-8?q?ValidationController:=20BulkInsert,=20XML?=
=?UTF-8?q?-Schema=20etc=20f=C3=BCr=20die=20Datenbank=20mitnehmen.=20Korre?=
=?UTF-8?q?kturen?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Controllers/ValidationController.cs | 275 +++++++++++++-----
1 file changed, 210 insertions(+), 65 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index ae616ab0..49ff5c5d 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
+using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
@@ -36,14 +37,14 @@ namespace ZUGFeRDRESTService.Controllers
public const string REFERENCES_Rejection_30004_3 = "REFERENCES_Rejection_30004_3";
public const string REFERENCES_Rejection_30005_1 = "REFERENCES_Rejection_30005_1";
public const string REFERENCES_Rejection_30005_2 = "REFERENCES_Rejection_30005_2";
- public const string REFERENCES_Rejection_30006 = "REFERENCES_Rejection_30006" ;
- public const string REFERENCES_Rejection_30007 = "REFERENCES_Rejection_30007" ;
+ public const string REFERENCES_Rejection_30006 = "REFERENCES_Rejection_30006";
+ public const string REFERENCES_Rejection_30007 = "REFERENCES_Rejection_30007";
public const string REFERENCES_Rejection_30007_1 = "REFERENCES_Rejection_30007_1";
- public const string REFERENCES_Rejection_30008 = "REFERENCES_Rejection_30008" ;
- public const string REFERENCES_Rejection_30009 = "REFERENCES_Rejection_30009" ;
- public const string REFERENCES_Rejection_30010 = "REFERENCES_Rejection_30010" ;
- public const string REFERENCES_Rejection_30011 = "REFERENCES_Rejection_30011" ;
- public const string REFERENCES_Rejection_30012 = "REFERENCES_Rejection_30012" ;
+ public const string REFERENCES_Rejection_30008 = "REFERENCES_Rejection_30008";
+ public const string REFERENCES_Rejection_30009 = "REFERENCES_Rejection_30009";
+ public const string REFERENCES_Rejection_30010 = "REFERENCES_Rejection_30010";
+ public const string REFERENCES_Rejection_30011 = "REFERENCES_Rejection_30011";
+ public const string REFERENCES_Rejection_30012 = "REFERENCES_Rejection_30012";
public const string AMOUNT_CALC_REJECTION = "AMOUNT_CALC_REJECTION";
private List _ValidationErrors;
@@ -209,7 +210,6 @@ namespace ZUGFeRDRESTService.Controllers
if (oFileSizeIsOK == false)
{
- //throw new ZUGFeRDExecption(ErrorType.FileTooBig, "FileTooBig");
throw new ZUGFeRDExecption(ErrorCodes.FileSizeLimitReachedException, _MaxFileSizeInMegabytes.ToString(), string.Empty, "FileTooBig");
}
@@ -218,6 +218,7 @@ namespace ZUGFeRDRESTService.Controllers
if (file.FileName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
{
oZugferdResult = _zugferd.ExtractZUGFeRDFileWithGDPicture(oStream);
+ oZugferdResult.ReceiptFileType = "PDF";
}
else if (file.FileName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
@@ -229,6 +230,7 @@ namespace ZUGFeRDRESTService.Controllers
};
oZugferdResult = _zugferd.SerializeZUGFeRDDocument(oResult);
+ oZugferdResult.ReceiptFileType = "XML";
}
_logger.Info("Detected Specification was: [{0}]", oZugferdResult.Specification);
@@ -238,7 +240,6 @@ namespace ZUGFeRDRESTService.Controllers
if (oFilteredPropertyMap.Count == 0)
{
_logger.Warn("No properties found in property map for specification [{0}]", oZugferdResult.Specification);
- //throw new ZUGFeRDExecption(ErrorType.UnsupportedFormat, "Unsupported Format");
throw new ZUGFeRDExecption(ErrorCodes.UnsupportedFerdException, "Unsupported Format");
}
else
@@ -263,15 +264,13 @@ namespace ZUGFeRDRESTService.Controllers
if (oPropertyResult.MissingProperties.Count > 0)
{
- //throw new ZUGFeRDExecption(ErrorType.MissingProperties, "Missing Properties");
throw new ZUGFeRDExecption(ErrorCodes.MissingValueException, "Missing Properties");
}
- Tuple oValidateResult = ValidateBuyerOrderReference(oPropertyResult.ValidProperties);
+ Tuple oValidateResult = ValidateBuyerOrderReference(oPropertyResult.ValidProperties, oZugferdResult);
if (oValidateResult.Item1 == false)
{
- //throw new ZUGFeRDExecption(ErrorType.UnknownError, "Unknown Error");
throw new ZUGFeRDExecption(ErrorCodes.UnhandledException, "Unknown Error");
}
@@ -398,20 +397,16 @@ namespace ZUGFeRDRESTService.Controllers
/// Hier wird eine externe Prozedur gerufen, PRCUST_INV_CHECK_FROM_PORTAL,
/// die das Ergebnis der Referenzpruefung liefert.
///
- private Tuple ValidateBuyerOrderReference(List pProperties)
+ private Tuple ValidateBuyerOrderReference(List pProperties, ZugferdResult pZugferdResult)
{
var oMessageId = GetMessageId();
_logger.Debug("Created new MessageId: [{0}]", oMessageId);
_logger.Debug("Inserting properties into database.");
- foreach (var oItem in pProperties)
+ if (!BulkInsertDataToDatabase(oMessageId, pProperties, pZugferdResult))
{
- var oResult = InsertPropertyMap(oItem, oMessageId);
-
- if (oResult == false)
- {
- _logger.Warn("Error while inserting the Property [{0}] into the Database!", oItem.Description);
- }
+ _logger.Warn("Error while Inserting properties into database!");
+ return new Tuple(false, string.Empty);
}
_logger.Debug("Calling validation prodecure.");
@@ -472,8 +467,13 @@ namespace ZUGFeRDRESTService.Controllers
oReturnValue = oDbMessage;
}
- // Für alle den RejectionCode setzen
- oReturnValue = oReturnValue.Replace("@REJECTION_CODE", oRejectionItem);
+ // Der REJECTION-Code wird in alle Meldungen eingefügt.
+ if (!string.IsNullOrEmpty(oRejectionItem) && oReturnValue.Contains("@REJECTION_CODE", StringComparison.OrdinalIgnoreCase))
+ {
+ var rejectionCodeNumber = GetRejectionCodeNumber(oRejectionItem);
+ oReturnValue = Regex.Replace(oReturnValue, "@REJECTION_CODE", "Ablehnungscode: " + rejectionCodeNumber, RegexOptions.IgnoreCase);
+ }
+
break;
}
}
@@ -616,60 +616,194 @@ namespace ZUGFeRDRESTService.Controllers
return $"{Guid.NewGuid()}@{MESSAGEID_DOMAIN}";
}
- public bool InsertPropertyMap(ValidProperty pProperty, string pMessageId)
+ private bool BulkInsertDataToDatabase(string pMessageId, List pProperties, ZugferdResult pZugferdResult)
+ {
+ if (string.IsNullOrEmpty(pMessageId))
+ {
+ return false;
+ }
+
+ if (!DeleteExistingPropertyValues(pMessageId))
+ {
+ return false;
+ }
+
+ DataTable oDataTable = PrepareDataTable(pMessageId, pProperties, pZugferdResult);
+
+ // ColumnList initialisieren
+ List oColumnNames = new List {
+ "REFERENCE_GUID",
+ "ITEM_DESCRIPTION",
+ "ITEM_VALUE",
+ "GROUP_COUNTER",
+ "SPEC_NAME",
+ "IS_REQUIRED"
+ };
+
+ bool oBulkResult = BulkInsert(oDataTable, "TBEDMI_ITEM_VALUE", oColumnNames);
+
+ if (!oBulkResult)
+ {
+ _logger.Error("Bulk Insert for MessageId [{0}] failed!", pMessageId);
+ return false;
+ }
+
+ _logger.Info("Bulk Insert finished. [{0}] rows inserted for MessageId [{1}].", oDataTable.Rows.Count, pMessageId);
+ return true;
+ }
+
+ private bool BulkInsert(DataTable pDataTable, string pDestinationTable, List pColumnNames)
+ {
+ using (var oSqlBulkCopy = new SqlBulkCopy(_database.MSSQL.GetConnection()))
+ {
+ oSqlBulkCopy.DestinationTableName = pDestinationTable;
+ foreach (var columnItem in pColumnNames)
+ {
+ oSqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(columnItem, columnItem));
+ }
+
+ try
+ {
+ oSqlBulkCopy.WriteToServer(pDataTable);
+ }
+ catch (Exception ex)
+ {
+ _logger.Error(ex);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private DataTable PrepareDataTable(string pMessageId, List pProperties, ZugferdResult pDocument)
+ {
+ DataTable oDataTable = new DataTable();
+ oDataTable.Columns.Add(new DataColumn("REFERENCE_GUID", typeof(string)));
+ oDataTable.Columns.Add(new DataColumn("ITEM_DESCRIPTION", typeof(string)));
+ oDataTable.Columns.Add(new DataColumn("ITEM_VALUE", typeof(string)));
+ oDataTable.Columns.Add(new DataColumn("GROUP_COUNTER", typeof(Int32)));
+ oDataTable.Columns.Add(new DataColumn("SPEC_NAME", typeof(string)));
+ oDataTable.Columns.Add(new DataColumn("IS_REQUIRED", typeof(bool)));
+
+ // Erste Zeile enthält die Spezifikation
+ DataRow oFirstRow = oDataTable.NewRow();
+ oFirstRow["REFERENCE_GUID"] = pMessageId;
+ oFirstRow["ITEM_DESCRIPTION"] = "Verwendete Spezifikation der E-Rechnung";
+ oFirstRow["ITEM_VALUE"] = pDocument.Specification;
+ oFirstRow["GROUP_COUNTER"] = 0;
+ oFirstRow["SPEC_NAME"] = "ZUGFERD_SPECIFICATION";
+ oFirstRow["IS_REQUIRED"] = false;
+
+ _logger.Debug("Mapping Property [ZUGFERD_SPECIFICATION] with value [{0}]", pDocument.Specification);
+ oDataTable.Rows.Add(oFirstRow);
+
+ //' Zweite Zeile enthält das verwendete XML Schema
+ DataRow oSecondRow = oDataTable.NewRow();
+ oSecondRow["REFERENCE_GUID"] = pMessageId;
+ oSecondRow["ITEM_DESCRIPTION"] = "Verwendetes XML-Schema (XSD) der E-Rechnung";
+ oSecondRow["ITEM_VALUE"] = pDocument.UsedXMLSchema;
+ oSecondRow["GROUP_COUNTER"] = 0;
+ oSecondRow["SPEC_NAME"] = "ZUGFERD_XML_SCHEMA";
+ oSecondRow["IS_REQUIRED"] = false;
+
+ _logger.Debug("Mapping Property [ZUGFERD_XML_SCHEMA] with value [{0}]", pDocument.UsedXMLSchema);
+ oDataTable.Rows.Add(oSecondRow);
+
+ //' Dritte Zeile enthält das verwendete Datei-Format des Belegs (PDF/XML)
+ if (pDocument.ReceiptFileType != null)
+ {
+ DataRow oThirdRow = oDataTable.NewRow();
+ oThirdRow["REFERENCE_GUID"] = pMessageId;
+ oThirdRow["ITEM_DESCRIPTION"] = "Dateityp der E-Rechnung";
+ oThirdRow["ITEM_VALUE"] = pDocument.ReceiptFileType;
+ oThirdRow["GROUP_COUNTER"] = 0;
+ oThirdRow["SPEC_NAME"] = "RECEIPT_FILE_TYPE";
+ oThirdRow["IS_REQUIRED"] = false;
+
+ _logger.Debug("Mapping Property [RECEIPT_FILE_TYPE] with value [{0}]", pDocument.ReceiptFileType);
+ oDataTable.Rows.Add(oThirdRow);
+ }
+
+ foreach (var propertyItem in pProperties)
+ {
+
+ // ItemType = 3 => eingebettete Datei, nicht den base64 speichern
+ if (propertyItem.ItemType == 3)
+ {
+ continue;
+ }
+
+ // ItemType = 0 (normale texte) dürfen nicht leer sein - leere Werte werden überlesen
+ if (propertyItem.ItemType == 0 && string.IsNullOrEmpty(propertyItem.Value))
+ {
+ continue;
+ }
+
+ // If GroupCounter is -1, it means this is a default property that can only occur once.
+ // Set the actual inserted value to 0
+ var oGroupCounterValue = propertyItem.GroupCounter < 0 ? 0 : propertyItem.GroupCounter;
+
+ if (propertyItem.Value.Length > 4000)
+ {
+ _logger.Warn("Value for field [{0}] is longer than 4000 characters, will be truncated!", propertyItem.TableColumn);
+ propertyItem.Value = propertyItem.Value.Substring(0, 4000);
+ }
+
+ // Description mit BT-Feld aufbereiten
+ var betterDescription = propertyItem.Description;
+ if (!string.IsNullOrEmpty(propertyItem.EN16931_ID))
+ {
+ betterDescription = propertyItem.EN16931_ID + " (" + propertyItem.Description + ")";
+ }
+
+ DataRow newRow = oDataTable.NewRow();
+ newRow["REFERENCE_GUID"] = pMessageId;
+ newRow["ITEM_DESCRIPTION"] = betterDescription;
+ newRow["ITEM_VALUE"] = propertyItem.Value;
+ newRow["GROUP_COUNTER"] = oGroupCounterValue;
+ newRow["SPEC_NAME"] = propertyItem.TableColumn;
+ newRow["IS_REQUIRED"] = propertyItem.IsRequired;
+
+ _logger.Debug("Mapping Property [{0}] with value [{1}]", propertyItem.TableColumn, propertyItem.Value);
+ oDataTable.Rows.Add(newRow);
+ }
+
+ return oDataTable;
+ }
+
+ public bool DeleteExistingPropertyValues(string pMessageId)
{
try
{
- if (pProperty.ItemType == 3)
- {
- // Wir speichern keine Attachment-Werte in die DB
- return true;
- }
-
- if (pProperty.ItemType == 0 && string.IsNullOrEmpty(pProperty.Value.ToString()))
- {
- // Leere Texte speichern wir nicht in der DB
- return true;
- }
-
- var oSql = $"INSERT INTO {pProperty.TableName} " +
- "(REFERENCE_GUID, ITEM_DESCRIPTION, ITEM_VALUE, CREATEDWHO, SPEC_NAME, GROUP_COUNTER, IS_REQUIRED) VALUES " +
- "(@REFERENCE_GUID, @ITEM_DESCRIPTION, @ITEM_VALUE, @CREATEDWHO, @SPEC_NAME, @GROUP_COUNTER, @IS_REQUIRED)";
-
- string itemValue = string.Empty;
- if (pProperty.Value.Length > 4000)
- {
- itemValue = pProperty.Value.Substring(1, 4000);
- _logger.Warn("Value for field [{0}] is longer than 4000 characters, will be truncated!", pProperty.TableColumn);
- }
- else
- {
- itemValue = pProperty.Value;
- }
-
- var oParams = new SqlParameter[]
- {
- new SqlParameter("@REFERENCE_GUID", pMessageId),
- new SqlParameter("@ITEM_DESCRIPTION", pProperty.Description),
- new SqlParameter("@ITEM_VALUE", itemValue.Replace("'", "''")),
- new SqlParameter("@CREATEDWHO", ADDED_WHO),
- new SqlParameter("@GROUP_COUNTER", pProperty.GroupCounter),
- new SqlParameter("@SPEC_NAME", pProperty.TableColumn),
- new SqlParameter("@IS_REQUIRED", pProperty.IsRequired)
- };
-
- var oCommand = new SqlCommand(oSql);
- oCommand.Parameters.AddRange(oParams);
-
- return _database.MSSQL.ExecuteNonQuery(oCommand);
+ var delItemValueSQL = "DELETE FROM TBEDMI_ITEM_VALUE WHERE REFERENCE_GUID '" + pMessageId + "';";
+ var oCommand = new SqlCommand(delItemValueSQL);
+ _database.MSSQL.ExecuteNonQuery(oCommand);
+ _logger.Debug("DELETE FROM TBEDMI_ITEM_VALUE successfull");
}
catch (Exception ex)
{
_logger.Error(ex);
return false;
}
+
+ try
+ {
+ var delItemFilesSQL = "DELETE FROM TBEDMI_ITEM_FILES WHERE REFERENCE_GUID '" + pMessageId + "';";
+ var oCommand = new SqlCommand(delItemFilesSQL);
+ _database.MSSQL.ExecuteNonQuery(oCommand);
+ _logger.Debug("DELETE FROM TBEDMI_ITEM_FILES successfull");
+ }
+ catch (Exception ex)
+ {
+ _logger.Error(ex);
+ return false;
+ }
+
+ return true;
}
+
///
/// Ermittelt die Ausgabe-nachricht für einen Fehlercode
///
@@ -744,5 +878,16 @@ namespace ZUGFeRDRESTService.Controllers
return "20010";
}
}
+
+ private string GetRejectionCodeNumber(string rejectionCode)
+ {
+ if (rejectionCode.StartsWith("REFERENCES_Rejection_"))
+ {
+ var retValue = rejectionCode.Replace("REFERENCES_Rejection_", "");
+ return retValue;
+ }
+
+ return rejectionCode;
+ }
}
}
From 538e2fcde14cb965b192fd19a4cee40d837ec294 Mon Sep 17 00:00:00 2001
From: pitzm
Date: Wed, 4 Feb 2026 15:09:46 +0100
Subject: [PATCH 03/11] ValidationController: Korrekturen
---
.../Controllers/ValidationController.cs | 21 +++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index 49ff5c5d..b629122b 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -776,9 +776,16 @@ namespace ZUGFeRDRESTService.Controllers
{
try
{
- var delItemValueSQL = "DELETE FROM TBEDMI_ITEM_VALUE WHERE REFERENCE_GUID '" + pMessageId + "';";
+ var delItemValueSQL = "DELETE FROM TBEDMI_ITEM_VALUE WHERE REFERENCE_GUID = '" + pMessageId + "';";
var oCommand = new SqlCommand(delItemValueSQL);
- _database.MSSQL.ExecuteNonQuery(oCommand);
+ var retValue = _database.MSSQL.ExecuteNonQuery(oCommand);
+
+ if (!retValue)
+ {
+ _logger.Warn("DELETE FROM TBEDMI_ITEM_VALUE NOT successfull");
+ return false;
+ }
+
_logger.Debug("DELETE FROM TBEDMI_ITEM_VALUE successfull");
}
catch (Exception ex)
@@ -789,9 +796,15 @@ namespace ZUGFeRDRESTService.Controllers
try
{
- var delItemFilesSQL = "DELETE FROM TBEDMI_ITEM_FILES WHERE REFERENCE_GUID '" + pMessageId + "';";
+ var delItemFilesSQL = "DELETE FROM TBEDMI_ITEM_FILES WHERE REFERENCE_GUID = '" + pMessageId + "';";
var oCommand = new SqlCommand(delItemFilesSQL);
- _database.MSSQL.ExecuteNonQuery(oCommand);
+ var retValue = _database.MSSQL.ExecuteNonQuery(oCommand);
+
+ if (!retValue)
+ {
+ _logger.Warn("DELETE FROM TBEDMI_ITEM_FILES NOT successfull");
+ return false;
+ }
_logger.Debug("DELETE FROM TBEDMI_ITEM_FILES successfull");
}
catch (Exception ex)
From 7173c89b772d8897bf7d0bf4bb1b64ad7ced14f5 Mon Sep 17 00:00:00 2001
From: pitzm
Date: Fri, 6 Mar 2026 11:17:06 +0100
Subject: [PATCH 04/11] =?UTF-8?q?GUIs.Common:=20Formatierbare=20Datumsspal?=
=?UTF-8?q?ten-Funktionen=20erg=C3=A4nzt?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
GUIs.Common/GridBuilder.vb | 54 +++++++++++++++++++++++++++++++++-----
1 file changed, 48 insertions(+), 6 deletions(-)
diff --git a/GUIs.Common/GridBuilder.vb b/GUIs.Common/GridBuilder.vb
index 3ab51893..9a0226f6 100644
--- a/GUIs.Common/GridBuilder.vb
+++ b/GUIs.Common/GridBuilder.vb
@@ -82,7 +82,7 @@ Public Class GridBuilder
ToList()
For Each oDateCol In oDateColumns
- SetDateTimeColumn(oDateCol)
+ SetDateTimeColumn(oDateCol, "g")
Next
End Sub
@@ -96,19 +96,61 @@ Public Class GridBuilder
ToList()
For Each oDateCol In oDateColumns
- SetDateTimeColumn(oDateCol)
+ SetDateTimeColumn(oDateCol, "g")
Next
End Sub
- Private Sub SetDateTimeColumn(pColumn As GridColumn)
+ '''
+ ''' Applies a proper datetime format string to all columns of the view.
+ '''
+ ''' The view's columns need to be loaded for this to work!
+ Public Sub SetDateTimeColumns(pView As GridView, pFormatString As String)
+ If pView.Columns Is Nothing Then
+ Exit Sub
+ End If
+
+ Dim oDateColumns = pView.Columns.AsEnumerable.
+ Where(Function(column As GridColumn) column.ColumnType = GetType(Date)).
+ ToList()
+
+ For Each oDateCol In oDateColumns
+ SetDateTimeColumn(oDateCol, pFormatString)
+ Next
+ End Sub
+
+ Public Sub SetDateTimeColumns(pTreeList As TreeList, pFormatString As String)
+ If pTreeList.Columns Is Nothing Then
+ Exit Sub
+ End If
+
+ Dim oDateColumns = pTreeList.Columns.AsEnumerable.
+ Where(Function(column As TreeListColumn) column.ColumnType = GetType(Date)).
+ ToList()
+
+ For Each oDateCol In oDateColumns
+ SetDateTimeColumn(oDateCol, pFormatString)
+ Next
+ End Sub
+
+ Private Sub SetDateTimeColumn(pColumn As GridColumn, pFormatString As String)
+
+ If String.IsNullOrEmpty(pFormatString) Then
+ pFormatString = "g"
+ End If
+
pColumn.DisplayFormat.FormatType = FormatType.Custom
- pColumn.DisplayFormat.FormatString = "g"
+ pColumn.DisplayFormat.FormatString = pFormatString
pColumn.DisplayFormat.Format = DateTimeFormatInfo.CurrentInfo
End Sub
- Private Sub SetDateTimeColumn(pColumn As TreeListColumn)
+ Private Sub SetDateTimeColumn(pColumn As TreeListColumn, pFormatString As String)
+
+ If String.IsNullOrEmpty(pFormatString) Then
+ pFormatString = "g"
+ End If
+
pColumn.Format.FormatType = FormatType.Custom
- pColumn.Format.FormatString = "g"
+ pColumn.Format.FormatString = pFormatString
pColumn.Format.Format = DateTimeFormatInfo.CurrentInfo
End Sub
From 6936d452092be716c45551fa1edd8fec3d4ec642 Mon Sep 17 00:00:00 2001
From: pitzm
Date: Fri, 6 Mar 2026 11:18:04 +0100
Subject: [PATCH 05/11] GUIs.Common: Version 2.7.1.0
---
GUIs.Common/My Project/AssemblyInfo.vb | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/GUIs.Common/My Project/AssemblyInfo.vb b/GUIs.Common/My Project/AssemblyInfo.vb
index 497148cb..8e3be4b5 100644
--- a/GUIs.Common/My Project/AssemblyInfo.vb
+++ b/GUIs.Common/My Project/AssemblyInfo.vb
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
-
+
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
' übernehmen, indem Sie "*" eingeben:
'
-
-
+
+
From 64ae4e9c7683b95d3759b23f142f49e497b4b69f Mon Sep 17 00:00:00 2001
From: pitzm
Date: Tue, 17 Mar 2026 10:30:08 +0100
Subject: [PATCH 06/11] ZUGFeRD REST Service: LanguageID in HTTPPost-Methode
---
.../Controllers/ValidationController.cs | 74 ++++++++++++++++---
.../ZUGFeRDRESTService/Pages/Index.cshtml | 7 +-
2 files changed, 69 insertions(+), 12 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index b629122b..c7029f79 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -1,6 +1,7 @@
using DigitalData.Modules.Interfaces;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
@@ -47,7 +48,14 @@ namespace ZUGFeRDRESTService.Controllers
public const string REFERENCES_Rejection_30012 = "REFERENCES_Rejection_30012";
public const string AMOUNT_CALC_REJECTION = "AMOUNT_CALC_REJECTION";
+ public const string GERMAN = "de-DE";
+ public const string ENGLISH = "en-US";
+ public const string FRENCH = "fr-FR";
+ public const string SPAIN = "es-ES";
+
private List _ValidationErrors;
+ private List _AllowedLanguageCodes;
+ private string _UserLanguageCode = "de-DE";
private const int MAX_FILE_SIZE_DEFAULT = 25;
@@ -128,6 +136,14 @@ namespace ZUGFeRDRESTService.Controllers
AMOUNT_CALC_REJECTION
};
+ _AllowedLanguageCodes = new List()
+ {
+ GERMAN,
+ ENGLISH,
+ FRENCH,
+ SPAIN,
+ };
+
_logger.Debug("Validation Controller initialized!");
}
@@ -191,14 +207,41 @@ namespace ZUGFeRDRESTService.Controllers
///
/// This parameter's name needs to correspond to the html form's file-input name
/// This is the email address which the user supplied
+ /// This is language code which the user supplied (en-US, de-DE)
[HttpPost]
- public ValidationResponse Post(IFormFile file, string user_id)
+ public ValidationResponse Post(IFormFile file, string user_id, string language_id = null)
{
_logger.Info("Start processing request to ValidationController");
ZugferdResult oZugferdResult = null;
CheckPropertyValuesResult oPropertyResult = new CheckPropertyValuesResult();
+ if (!string.IsNullOrEmpty(user_id))
+ {
+ _logger.Info("UserID set to [{0}].", user_id);
+ }
+ else
+ {
+ _logger.Info("UserID is empty!");
+ }
+
+ if (string.IsNullOrEmpty(language_id))
+ {
+ _logger.Info("Language code was empty. Set to default 'de-DE'");
+ // DEFAULT-Sprache = Deutsch de-DE
+ _UserLanguageCode = GERMAN;
+ }
+ else if (_AllowedLanguageCodes.Contains(language_id))
+ {
+ _logger.Info("Language code is allowed. Set to [{0}].", language_id);
+ _UserLanguageCode = language_id;
+ }
+ else
+ {
+ _logger.Info("Language code was unknown: [{0}]. Set to default 'de-DE'", language_id);
+ _UserLanguageCode = GERMAN;
+ }
+
try
{
using Stream oStream = file.OpenReadStream();
@@ -299,7 +342,7 @@ namespace ZUGFeRDRESTService.Controllers
};
}
}
-
+
}
catch (ZUGFeRDExecption ex)
{
@@ -611,7 +654,7 @@ namespace ZUGFeRDRESTService.Controllers
return oReplaceParam1;
}
- public string GetMessageId()
+ private string GetMessageId()
{
return $"{Guid.NewGuid()}@{MESSAGEID_DOMAIN}";
}
@@ -772,7 +815,7 @@ namespace ZUGFeRDRESTService.Controllers
return oDataTable;
}
- public bool DeleteExistingPropertyValues(string pMessageId)
+ private bool DeleteExistingPropertyValues(string pMessageId)
{
try
{
@@ -816,18 +859,15 @@ namespace ZUGFeRDRESTService.Controllers
return true;
}
-
///
/// Ermittelt die Ausgabe-nachricht für einen Fehlercode
///
- public string GetRejectionMessage(string pErrorCode)
+ private string GetRejectionMessage(string pErrorCode)
{
_logger.Info("GetRejectionMessage() - errorCode.ToString(): '" + pErrorCode.ToString() + "'");
if (_RecjectionMessageList == null) return string.Empty;
- // Sprache wird man vielleicht mal auswählen können
- var language = "de-DE";
var searchTitle = string.Empty;
if (pErrorCode.Contains("2000"))
@@ -844,11 +884,23 @@ namespace ZUGFeRDRESTService.Controllers
}
else
{
- // else-Fall muss noch geklärt werden.
- searchTitle = "AMOUNT_CALC_REJECTION_Web";
+ searchTitle = "ZUGFERD_Rejection_20006_Web";
+ }
+
+ // Sprachgenauen Text suchen.
+ var messageItem = _RecjectionMessageList.Where(i => i.Title.Equals(searchTitle, StringComparison.OrdinalIgnoreCase) &&
+ i.Language.Equals(_UserLanguageCode, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
+
+ if (messageItem == null &&
+ !_UserLanguageCode.Equals(GERMAN, StringComparison.OrdinalIgnoreCase)) {
+
+ _logger.Info("GetRejectionMessage() - Es wurde kein passender Text für die Sprache [{0}] gefunden.", _UserLanguageCode);
+
+ // Wenn kein sprachgenauer Text vorliegt, hole den deutschen Text.
+ messageItem = _RecjectionMessageList.Where(i => i.Title.Equals(searchTitle, StringComparison.OrdinalIgnoreCase) &&
+ i.Language.Equals(GERMAN, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
}
- var messageItem = _RecjectionMessageList.Where(i => i.Title.Equals(searchTitle, StringComparison.OrdinalIgnoreCase) && i.Language.Equals(language, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
if (messageItem != null)
{
_logger.Info("GetRejectionMessage() - messageItem: '" + messageItem.String1 + "'");
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Pages/Index.cshtml b/WEBSERVICES/ZUGFeRDRESTService/Pages/Index.cshtml
index d941e9ef..1b7cf371 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Pages/Index.cshtml
+++ b/WEBSERVICES/ZUGFeRDRESTService/Pages/Index.cshtml
@@ -15,7 +15,12 @@
-
+
+
+
+
+
+
From 25e0eddfdb2d5ba3d99b5e0a4025e932c43a122d Mon Sep 17 00:00:00 2001
From: pitzm
Date: Tue, 17 Mar 2026 11:29:03 +0100
Subject: [PATCH 07/11] =?UTF-8?q?ZUGFeRDRESTService:=20HttpPost-Parameter?=
=?UTF-8?q?=20anders=20abfragen.=20Es=20ist=20immer=20nur=20ein=20Paramete?=
=?UTF-8?q?r=20m=C3=B6glich?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Controllers/ValidationController.cs | 35 ++++++++++++++-----
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index c7029f79..4bd3751c 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -9,6 +9,7 @@ using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
+using System.Net.Http;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using static DigitalData.Modules.Interfaces.Exceptions;
@@ -209,36 +210,54 @@ namespace ZUGFeRDRESTService.Controllers
/// This is the email address which the user supplied
/// This is language code which the user supplied (en-US, de-DE)
[HttpPost]
- public ValidationResponse Post(IFormFile file, string user_id, string language_id = null)
+ //public ValidationResponse Post(IFormFile file, StringContent user_id, StringContent language_id = null)
+ public ValidationResponse Post(IFormCollection collection)
{
_logger.Info("Start processing request to ValidationController");
ZugferdResult oZugferdResult = null;
CheckPropertyValuesResult oPropertyResult = new CheckPropertyValuesResult();
- if (!string.IsNullOrEmpty(user_id))
+ var oUserId = string.Empty; // user_id == null ? string.Empty : user_id.ToString();
+ var oLanguageId = GERMAN; // language_id == null ? GERMAN : language_id.ToString();
+
+ IFormFile file = collection.Files[0];
+
+ foreach (var keyItem in collection.Keys)
{
- _logger.Info("UserID set to [{0}].", user_id);
+ if (keyItem == "user_id")
+ {
+ oUserId = collection[keyItem];
+ }
+ else if (keyItem == "language_id")
+ {
+ oLanguageId = collection[keyItem];
+ }
+ }
+
+ if (!string.IsNullOrEmpty(oUserId))
+ {
+ _logger.Info("UserID set to [{0}].", oUserId);
}
else
{
_logger.Info("UserID is empty!");
}
- if (string.IsNullOrEmpty(language_id))
+ if (string.IsNullOrEmpty(oLanguageId))
{
_logger.Info("Language code was empty. Set to default 'de-DE'");
// DEFAULT-Sprache = Deutsch de-DE
_UserLanguageCode = GERMAN;
}
- else if (_AllowedLanguageCodes.Contains(language_id))
+ else if (_AllowedLanguageCodes.Contains(oLanguageId))
{
- _logger.Info("Language code is allowed. Set to [{0}].", language_id);
- _UserLanguageCode = language_id;
+ _logger.Info("Language code is allowed. Set to [{0}].", oLanguageId);
+ _UserLanguageCode = oLanguageId;
}
else
{
- _logger.Info("Language code was unknown: [{0}]. Set to default 'de-DE'", language_id);
+ _logger.Info("Language code was unknown: [{0}]. Set to default 'de-DE'", oLanguageId);
_UserLanguageCode = GERMAN;
}
From dc56d783b3c35281b583a9b756822256f0b867ee Mon Sep 17 00:00:00 2001
From: pitzm
Date: Mon, 23 Mar 2026 13:36:43 +0100
Subject: [PATCH 08/11] ZUGFeRD REST Service: "Ablehnungscode" mehrsprachige
Ausgabe
---
.../Controllers/ValidationController.cs | 30 +++++++++++++++----
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index 4bd3751c..50e0f5ff 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -31,6 +31,7 @@ namespace ZUGFeRDRESTService.Controllers
public const string VALIDATION_SUCCESS = "VALIDATION SUCCESS";
public const string REFERENCES_Rejection_30001 = "REFERENCES_Rejection_30001";
public const string REFERENCES_Rejection_30002 = "REFERENCES_Rejection_30002";
+ public const string REFERENCES_Rejection_30002_1 = "REFERENCES_Rejection_30002_1";
public const string REFERENCES_Rejection_30003_1 = "REFERENCES_Rejection_30003_1";
public const string REFERENCES_Rejection_30003_2 = "REFERENCES_Rejection_30003_2";
public const string REFERENCES_Rejection_30003_3 = "REFERENCES_Rejection_30003_3";
@@ -56,7 +57,7 @@ namespace ZUGFeRDRESTService.Controllers
private List _ValidationErrors;
private List _AllowedLanguageCodes;
- private string _UserLanguageCode = "de-DE";
+ private string _UserLanguageCode = GERMAN;
private const int MAX_FILE_SIZE_DEFAULT = 25;
@@ -65,10 +66,9 @@ namespace ZUGFeRDRESTService.Controllers
private readonly DigitalData.Modules.Logging.LogConfig _logConfig;
private readonly DigitalData.Modules.Logging.Logger _logger;
- private readonly DigitalData.Modules.Filesystem.File _file;
+ //private readonly DigitalData.Modules.Filesystem.File _file;
private readonly PropertyValues _props;
- //private readonly Dictionary _propertyMap = new Dictionary();
private readonly List _propertyMapList = new List();
private readonly List _RecjectionMessageList = new List();
@@ -86,7 +86,7 @@ namespace ZUGFeRDRESTService.Controllers
{
_logConfig = logging.LogConfig;
_logger = _logConfig.GetLogger();
- _file = new DigitalData.Modules.Filesystem.File(_logConfig);
+ //_file = new DigitalData.Modules.Filesystem.File(_logConfig);
_logger.Debug("Validation Controller initializing");
@@ -390,7 +390,11 @@ namespace ZUGFeRDRESTService.Controllers
// Der REJECTION-Code wird in alle Meldungen eingefügt.
if (!string.IsNullOrEmpty(rejectionCodeNumber) && oMessage.Contains("@REJECTION_CODE", StringComparison.OrdinalIgnoreCase))
{
- oMessage = Regex.Replace(oMessage, "@REJECTION_CODE", "Ablehnungscode: " + rejectionCodeNumber, RegexOptions.IgnoreCase);
+ var substituteText = this.GetLabelText("Ablehnungscode", _UserLanguageCode);
+ substituteText = string.IsNullOrEmpty(substituteText) ? "Ablehnungscode" : substituteText;
+ substituteText = substituteText + ": " + rejectionCodeNumber;
+
+ oMessage = Regex.Replace(oMessage, "@REJECTION_CODE", substituteText, RegexOptions.IgnoreCase);
}
// Determine if any errors should be sent in the response
@@ -533,7 +537,12 @@ namespace ZUGFeRDRESTService.Controllers
if (!string.IsNullOrEmpty(oRejectionItem) && oReturnValue.Contains("@REJECTION_CODE", StringComparison.OrdinalIgnoreCase))
{
var rejectionCodeNumber = GetRejectionCodeNumber(oRejectionItem);
- oReturnValue = Regex.Replace(oReturnValue, "@REJECTION_CODE", "Ablehnungscode: " + rejectionCodeNumber, RegexOptions.IgnoreCase);
+
+ var substituteText = this.GetLabelText("Ablehnungscode", _UserLanguageCode);
+ substituteText = string.IsNullOrEmpty(substituteText) ? "Ablehnungscode" : substituteText;
+ substituteText = substituteText + ": " + rejectionCodeNumber;
+
+ oReturnValue = Regex.Replace(oReturnValue, "@REJECTION_CODE", substituteText, RegexOptions.IgnoreCase);
}
break;
@@ -932,6 +941,15 @@ namespace ZUGFeRDRESTService.Controllers
}
}
+ private string GetLabelText(string pLabel, string pLanguage)
+ {
+ // Sprachgenauen Text suchen.
+ var messageItem = _RecjectionMessageList.Where(i => i.Title.Equals(pLabel, StringComparison.OrdinalIgnoreCase) &&
+ i.Language.Equals(pLanguage, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
+
+ return messageItem != null ? messageItem.String1 : string.Empty;
+ }
+
private string GetRejectionCodeNumber(ErrorCodes rejectionCode)
{
switch (rejectionCode)
From 4cfc8cd46b95296a47816683f55f72c2e046173b Mon Sep 17 00:00:00 2001
From: pitzm
Date: Wed, 25 Mar 2026 08:47:45 +0100
Subject: [PATCH 09/11] Texte austauschen
---
.../Controllers/ValidationController.cs | 45 +++++++++----------
1 file changed, 20 insertions(+), 25 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index 50e0f5ff..2e625d83 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.Configuration;
+using Microsoft.VisualStudio.Web.CodeGeneration.Contracts.Messaging;
using System;
using System.Collections.Generic;
using System.Data;
@@ -387,16 +388,6 @@ namespace ZUGFeRDRESTService.Controllers
oMessage = Regex.Replace(oMessage, "@REPLACE_PARAM2", ex.Param2, RegexOptions.IgnoreCase);
}
- // Der REJECTION-Code wird in alle Meldungen eingefügt.
- if (!string.IsNullOrEmpty(rejectionCodeNumber) && oMessage.Contains("@REJECTION_CODE", StringComparison.OrdinalIgnoreCase))
- {
- var substituteText = this.GetLabelText("Ablehnungscode", _UserLanguageCode);
- substituteText = string.IsNullOrEmpty(substituteText) ? "Ablehnungscode" : substituteText;
- substituteText = substituteText + ": " + rejectionCodeNumber;
-
- oMessage = Regex.Replace(oMessage, "@REJECTION_CODE", substituteText, RegexOptions.IgnoreCase);
- }
-
// Determine if any errors should be sent in the response
switch (ex.ErrorCode)
{
@@ -533,18 +524,6 @@ namespace ZUGFeRDRESTService.Controllers
oReturnValue = oDbMessage;
}
- // Der REJECTION-Code wird in alle Meldungen eingefügt.
- if (!string.IsNullOrEmpty(oRejectionItem) && oReturnValue.Contains("@REJECTION_CODE", StringComparison.OrdinalIgnoreCase))
- {
- var rejectionCodeNumber = GetRejectionCodeNumber(oRejectionItem);
-
- var substituteText = this.GetLabelText("Ablehnungscode", _UserLanguageCode);
- substituteText = string.IsNullOrEmpty(substituteText) ? "Ablehnungscode" : substituteText;
- substituteText = substituteText + ": " + rejectionCodeNumber;
-
- oReturnValue = Regex.Replace(oReturnValue, "@REJECTION_CODE", substituteText, RegexOptions.IgnoreCase);
- }
-
break;
}
}
@@ -929,10 +908,26 @@ namespace ZUGFeRDRESTService.Controllers
i.Language.Equals(GERMAN, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
}
- if (messageItem != null)
+ if (messageItem != null && !string.IsNullOrEmpty(pErrorCode))
{
- _logger.Info("GetRejectionMessage() - messageItem: '" + messageItem.String1 + "'");
- return messageItem.String1;
+ var resultText = string.Empty;
+
+ // Der REJECTION-Code wird in allen Meldungen ausgetauscht.
+ if (messageItem.String1.Contains("@REJECTION_CODE", StringComparison.OrdinalIgnoreCase))
+ {
+ var substituteText = this.GetLabelText("Ablehnungscode", _UserLanguageCode);
+ substituteText = string.IsNullOrEmpty(substituteText) ? "Ablehnungscode" : substituteText;
+ substituteText = substituteText + ": " + pErrorCode;
+
+ resultText = Regex.Replace(messageItem.String1, "@REJECTION_CODE", substituteText, RegexOptions.IgnoreCase);
+ }
+ else
+ {
+ resultText = messageItem.String1;
+ }
+
+ _logger.Info("GetRejectionMessage() - messageItem: '" + resultText + "'");
+ return resultText;
}
else
{
From 3f58acea7a24e0810acb977831122dc69f44f727 Mon Sep 17 00:00:00 2001
From: pitzm
Date: Wed, 25 Mar 2026 14:41:58 +0100
Subject: [PATCH 10/11] ValidationException - Auswertung der Exception-Items -
mehrsprachig
---
.../Controllers/ValidationController.cs | 101 ++++++++++++++----
1 file changed, 79 insertions(+), 22 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index 2e625d83..fb4e33be 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -87,8 +87,6 @@ namespace ZUGFeRDRESTService.Controllers
{
_logConfig = logging.LogConfig;
_logger = _logConfig.GetLogger();
- //_file = new DigitalData.Modules.Filesystem.File(_logConfig);
-
_logger.Debug("Validation Controller initializing");
// Read config file and assign all option flags related to
@@ -211,7 +209,6 @@ namespace ZUGFeRDRESTService.Controllers
/// This is the email address which the user supplied
/// This is language code which the user supplied (en-US, de-DE)
[HttpPost]
- //public ValidationResponse Post(IFormFile file, StringContent user_id, StringContent language_id = null)
public ValidationResponse Post(IFormCollection collection)
{
_logger.Info("Start processing request to ValidationController");
@@ -219,8 +216,8 @@ namespace ZUGFeRDRESTService.Controllers
ZugferdResult oZugferdResult = null;
CheckPropertyValuesResult oPropertyResult = new CheckPropertyValuesResult();
- var oUserId = string.Empty; // user_id == null ? string.Empty : user_id.ToString();
- var oLanguageId = GERMAN; // language_id == null ? GERMAN : language_id.ToString();
+ var oUserId = string.Empty;
+ var oLanguageId = GERMAN;
IFormFile file = collection.Files[0];
@@ -422,16 +419,54 @@ namespace ZUGFeRDRESTService.Controllers
// Der gesamte Ausgabetext muss anhand des ErrorCodes ermittelt werden
string oMessage = this.GetRejectionMessage(rejectionCodeNumber);
- List oErrors = ex.ValidationErrors.Select(e =>
- {
- return $"Element '{e.ElementName}' mit Wert '{e.ElementValue}': {e.ErrorMessageDE}";
- }).ToList();
+ // Wenn es ValidationErrors gibt, werden diese nun übersetzt und in eine Liste übertragen werden
+ var mainText = GetTextByToken("ItemValueText");
+ var resultList = new List();
+ foreach (var errorItem in ex.ValidationErrors)
+ {
+ var resultString = mainText;
+
+ if (!string.IsNullOrEmpty(errorItem.ElementName))
+ {
+ // replace @ITEM_NAME => e.ElementName
+ resultString = resultString.Replace("@ITEM_NAME", errorItem.ElementName, StringComparison.OrdinalIgnoreCase);
+ }
+
+ if (!string.IsNullOrEmpty(errorItem.ElementValue))
+ {
+ // replace ITEM_VALUE => e.ElementValue
+ resultString = resultString.Replace("@ITEM_VALUE", errorItem.ElementValue, StringComparison.OrdinalIgnoreCase);
+ }
+
+ var itemErrorText = GetTextByToken(errorItem.ErrorMessageToken);
+ if (!string.IsNullOrEmpty(itemErrorText))
+ {
+ // attach itemErrorText
+ resultString += " " + itemErrorText;
+ }
+
+ _logger.Debug($"resultString: [{resultString}]");
+ resultList.Add(resultString);
+ }
+
+ // wenn ergebnisse vorliegen, in html transformieren und anhängen
+ if (resultList.Count > 0)
+ {
+ var htmlResultString = "";
+ foreach (var resultItem in resultList)
+ {
+ htmlResultString += " - " + resultItem + "
" + Environment.NewLine;
+ }
+ htmlResultString += "
";
+
+ oMessage += " " + htmlResultString;
+ }
+
return new ValidationResponse()
{
status = RESPONSE_ERROR,
- message = oMessage,
- errors = oErrors
+ message = oMessage
};
}
catch (Exception ex)
@@ -450,6 +485,39 @@ namespace ZUGFeRDRESTService.Controllers
}
}
+ ///
+ /// Holt sprachgenauen Text anhand eines Titel-Tokens
+ ///
+ ///
+ private string GetTextByToken(string tokenValue)
+ {
+ RejectionStringRow stringRow = null;
+
+ if (!string.IsNullOrEmpty(tokenValue))
+ {
+ stringRow = _RecjectionMessageList.Where(i => i.Title.Equals(tokenValue, StringComparison.OrdinalIgnoreCase) &&
+ i.Language.Equals(_UserLanguageCode, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
+
+ if (stringRow == null &&
+ !_UserLanguageCode.Equals(GERMAN, StringComparison.OrdinalIgnoreCase))
+ {
+ // Wenn kein sprachgenauer Text vorliegt, hole den deutschen Text.
+ stringRow = _RecjectionMessageList.Where(i => i.Title.Equals(tokenValue, StringComparison.OrdinalIgnoreCase) &&
+ i.Language.Equals(GERMAN, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
+ }
+ }
+
+ string retValue = string.Empty;
+
+ if (stringRow != null)
+ {
+ retValue = !string.IsNullOrEmpty(stringRow.String1) ? stringRow.String1.Trim() : string.Empty;
+ }
+
+ _logger.Debug($"Token [{tokenValue}] - String1 [{retValue}]");
+ return retValue;
+ }
+
///
/// Hier wird eine externe Prozedur gerufen, PRCUST_INV_CHECK_FROM_PORTAL,
/// die das Ergebnis der Referenzpruefung liefert.
@@ -975,16 +1043,5 @@ namespace ZUGFeRDRESTService.Controllers
return "20010";
}
}
-
- private string GetRejectionCodeNumber(string rejectionCode)
- {
- if (rejectionCode.StartsWith("REFERENCES_Rejection_"))
- {
- var retValue = rejectionCode.Replace("REFERENCES_Rejection_", "");
- return retValue;
- }
-
- return rejectionCode;
- }
}
}
From b4eecbdb86f650af00a400c1d2759ef4dcb4b9dd Mon Sep 17 00:00:00 2001
From: pitzm
Date: Thu, 2 Apr 2026 11:46:20 +0200
Subject: [PATCH 11/11] ZUGFERD 20007 - BT-Felder-Liste anzeigen, mehrsprachig
---
.../Controllers/ValidationController.cs | 30 +++++++++++++++++--
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
index fb4e33be..790c3623 100644
--- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
+++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs
@@ -248,7 +248,7 @@ namespace ZUGFeRDRESTService.Controllers
// DEFAULT-Sprache = Deutsch de-DE
_UserLanguageCode = GERMAN;
}
- else if (_AllowedLanguageCodes.Contains(oLanguageId))
+ else if (_AllowedLanguageCodes.Where(i => i.Equals(oLanguageId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault() != null)
{
_logger.Info("Language code is allowed. Set to [{0}].", oLanguageId);
_UserLanguageCode = oLanguageId;
@@ -389,8 +389,12 @@ namespace ZUGFeRDRESTService.Controllers
switch (ex.ErrorCode)
{
case ErrorCodes.MissingValueException:
- oErrors.AddRange(from item in oPropertyResult.MissingProperties
- select (item.EN16931_ID + " (" + item.Description + ")"));
+
+ var oErrorsText = GetMissingValuesListString(oPropertyResult.MissingProperties);
+ if (!string.IsNullOrEmpty(oErrorsText) && oMessage.Contains("@REPLACE_PARAM3", StringComparison.OrdinalIgnoreCase))
+ {
+ oMessage = Regex.Replace(oMessage, "@REPLACE_PARAM3", oErrorsText, RegexOptions.IgnoreCase);
+ }
break;
default:
break;
@@ -485,6 +489,26 @@ namespace ZUGFeRDRESTService.Controllers
}
}
+ private string GetMissingValuesListString(List missingProperties)
+ {
+ if (missingProperties == null || missingProperties.Count == 0)
+ {
+ return string.Empty;
+ }
+
+ string retValue = "";
+ foreach (var missingProperty in missingProperties)
+ {
+ var searchToken = missingProperty.EN16931_ID + "_Description";
+ var descriptionTranslated = GetTextByToken(searchToken);
+ var rowString = "- " + missingProperty.EN16931_ID + " (" + descriptionTranslated + ")
";
+ retValue += rowString;
+ }
+ retValue += "
";
+
+ return retValue;
+ }
+
///
/// Holt sprachgenauen Text anhand eines Titel-Tokens
///