diff --git a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs index 5ee0d56c..598aaf88 100644 --- a/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs +++ b/WEBSERVICES/ZUGFeRDRESTService/Controllers/ValidationController.cs @@ -12,6 +12,7 @@ using System.Data.SqlClient; using Microsoft.Extensions.Configuration; using System.Xml.Linq; using Newtonsoft.Json.Linq; +using System.Text.RegularExpressions; namespace ZUGFeRDRESTService.Controllers { @@ -37,6 +38,7 @@ namespace ZUGFeRDRESTService.Controllers private readonly PropertyValues _props; //private readonly Dictionary _propertyMap = new Dictionary(); private readonly List _propertyMapList = new List(); + private readonly List _RecjectionMessageList = new List(); private int _MaxFileSizeInMegabytes; private bool _AllowFacturX; @@ -79,6 +81,8 @@ namespace ZUGFeRDRESTService.Controllers _propertyMapList.AddRange(oPropertyMapList); _logger.Debug("Property Map list initial: [{0}] entries found. [{1}] entries will be available.", oPropertyMapList.Count, _propertyMapList.Count); + _RecjectionMessageList = database.GetRejectionMessageList(); + _logger.Debug("Validation Controller initialized!"); } @@ -89,32 +93,32 @@ namespace ZUGFeRDRESTService.Controllers if (!bool.TryParse(oZugferdConfig["AllowFacturX"], out _AllowFacturX)) { - _logger.Info("Configuration AllowFacturX was not set. Using default value [{0}]", false); - _AllowFacturX = false; + _logger.Info("Configuration AllowFacturX was not set. Using default value [{0}]", true); + _AllowFacturX = true; } if (!bool.TryParse(oZugferdConfig["AllowXRechnung"], out _AllowXRechnung)) { - _logger.Info("Configuration AllowXRechnung was not set. Using default value [{0}]", false); - _AllowXRechnung = false; + _logger.Info("Configuration AllowXRechnung was not set. Using default value [{0}]", true); + _AllowXRechnung = true; } if (!bool.TryParse(oZugferdConfig["AllowZugferd2x"], out _AllowZugferd2x)) { - _logger.Info("Configuration Zugferd2x was not set. Using default value [{0}]", false); - _AllowZugferd2x = false; + _logger.Info("Configuration Zugferd2x was not set. Using default value [{0}]", true); + _AllowZugferd2x = true; } if (!bool.TryParse(oZugferdConfig["AllowZugferd23x"], out _AllowZugferd23x)) { - _logger.Info("Configuration Zugferd23x was not set. Using default value [{0}]", false); - _AllowZugferd23x = false; + _logger.Info("Configuration Zugferd23x was not set. Using default value [{0}]", true); + _AllowZugferd23x = true; } if (!bool.TryParse(oZugferdConfig["AllowZugferd10"], out _AllowZugferd10)) { - _logger.Info("Configuration Zugferd10 was not set. Using default value [{0}]", true); - _AllowZugferd10 = true; + _logger.Info("Configuration Zugferd10 was not set. Using default value [{0}]", false); + _AllowZugferd10 = false; } if (!bool.TryParse(oZugferdConfig["AllowPeppolBISBill3x"], out _AllowPeppolBISBill3x)) @@ -161,7 +165,8 @@ namespace ZUGFeRDRESTService.Controllers if (oFileSizeIsOK == false) { - throw new ZUGFeRDExecption(ErrorType.FileTooBig, "FileTooBig"); + //throw new ZUGFeRDExecption(ErrorType.FileTooBig, "FileTooBig"); + throw new ZUGFeRDExecption(ErrorCodes.FileSizeLimitReachedException, _MaxFileSizeInMegabytes.ToString(), string.Empty, "FileTooBig"); } _logger.Info("Extracting ZUGFeRD Data from file [{0}]", file.FileName); @@ -189,7 +194,8 @@ 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(ErrorType.UnsupportedFormat, "Unsupported Format"); + throw new ZUGFeRDExecption(ErrorCodes.UnsupportedFerdException, "Unsupported Format"); } else { @@ -213,14 +219,16 @@ namespace ZUGFeRDRESTService.Controllers if (oPropertyResult.MissingProperties.Count > 0) { - throw new ZUGFeRDExecption(ErrorType.MissingProperties, "Missing Properties"); + //throw new ZUGFeRDExecption(ErrorType.MissingProperties, "Missing Properties"); + throw new ZUGFeRDExecption(ErrorCodes.MissingValueException, "Missing Properties"); } Tuple oValidateResult = ValidateBuyerOrderReference(oPropertyResult.ValidProperties); if (oValidateResult.Item1 == false) { - throw new ZUGFeRDExecption(ErrorType.UnknownError, "Unknown Error"); + //throw new ZUGFeRDExecption(ErrorType.UnknownError, "Unknown Error"); + throw new ZUGFeRDExecption(ErrorCodes.UnhandledException, "Unknown Error"); } string oValidateResultString = oValidateResult.Item2; @@ -254,28 +262,46 @@ namespace ZUGFeRDRESTService.Controllers { _logger.Error(ex); - // Determine which message should be sent in the response - string oMessage = ex.ErrorType switch - { - ErrorType.NoValidFile => "Die hochgeladene Datei ist keine gültige Datei.", - ErrorType.NoZugferd => "Die hochgeladene Datei ist keine ZUGFeRD-Rechnung.", - ErrorType.NoValidZugferd => "Die hochgeladene Datei ist keine gültige ZUGFeRD-Rechnung.", - ErrorType.MissingProperties => "Die hochgeladene Datei ist keine gültige ZUGFeRD-Rechnung, es fehlen einige Metadaten.", - ErrorType.FileTooBig => string.Format("Die hochgeladene Datei überschreitet die zulässige Dateigröße [{0}].", _MaxFileSizeInMegabytes), - ErrorType.UnsupportedFormat => "Die hochgeladene Datei enthält ein falsches oder nicht unterstütztes ZUGFeRD Format.", - _ => "Die hochgeladene Datei kann nicht validiert werden.", - }; - - // Determine if any errors should be sent in the response + string oMessage; var oErrors = new List(); - switch (ex.ErrorType) + if (ex.ErrorCode != ErrorCodes.NotInUse) { - case ErrorType.MissingProperties: - oErrors.AddRange(from item in oPropertyResult.MissingProperties - select item.Description); - break; - default: - break; + var rejectionCodeNumber = this.GetRejectionCodeNumber(ex.ErrorCode); + + // Der gesamte Ausgabetext muss anhand des ErrorCodes ermittelt werden + oMessage = this.GetRejectionMessage(rejectionCodeNumber); + + // Ersetze jetzt die Platzhalter @REPLACE_PARAM1 und @REPLACE_PARAM2 + if (!string.IsNullOrEmpty(ex.Param1) && oMessage.Contains("@REPLACE_PARAM1", StringComparison.OrdinalIgnoreCase)) + { + oMessage = Regex.Replace(oMessage, "@REPLACE_PARAM1", ex.Param1, RegexOptions.IgnoreCase); + } + + if (!string.IsNullOrEmpty(ex.Param2) && oMessage.Contains("@REPLACE_PARAM2", StringComparison.OrdinalIgnoreCase)) + { + 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)) + { + oMessage = Regex.Replace(oMessage, "@REJECTION_CODE", "Ablehnungscode: " + rejectionCodeNumber, RegexOptions.IgnoreCase); + } + + // Determine if any errors should be sent in the response + switch (ex.ErrorCode) + { + case ErrorCodes.MissingValueException: + oErrors.AddRange(from item in oPropertyResult.MissingProperties + select (item.EN16931_ID + "(" + item.Description + ")")); + break; + default: + break; + } + } + else + { + oMessage = "Alte Logik. Meldung nicht gefunden"; } _logger.Info($"Responding with message: [{oMessage}]"); @@ -289,10 +315,14 @@ namespace ZUGFeRDRESTService.Controllers } catch (ValidationException ex) { - string oMessage = "Die hochgeladene Datei enthält ungültige Werte."; + var rejectionCodeNumber = this.GetRejectionCodeNumber(ex.ErrorCode); + + // 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.ErrorMessage}"; + return $"Element '{e.ElementName}' mit Wert '{e.ElementValue}': {e.ErrorMessageDE}"; }).ToList(); return new ValidationResponse() @@ -422,5 +452,61 @@ namespace ZUGFeRDRESTService.Controllers } } + /// + /// Ermittelt die Ausgabe-nachricht für einen Fehlercode + /// + public 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 = "ZUGFERD_Rejection_" + pErrorCode + "_Web"; + + var messageItem = _RecjectionMessageList.Where(i => i.Title.Equals(searchTitle, StringComparison.OrdinalIgnoreCase) && i.Language == language).FirstOrDefault(); + if (messageItem != null) + { + _logger.Info("GetRejectionMessage() - messageItem: '" + messageItem.String1 + "'"); + return messageItem.String1; + } + else + { + _logger.Info("GetRejectionMessage() - Es wurde kein passender Text gefunden."); + return string.Empty; + } + } + + private string GetRejectionCodeNumber(ErrorCodes rejectionCode) + { + switch (rejectionCode) + { + case ErrorCodes.ValidationException: + return "20001"; + case ErrorCodes.MD5HashException: + return "20002"; + case ErrorCodes.UnsupportedFerdException: + return "20003"; + case ErrorCodes.InvalidFerdException: + return "20004"; + case ErrorCodes.TooMuchFerdsException: + return "20005"; + case ErrorCodes.InvalidFerdNoXMLAttachmentFound: + return "20006"; + case ErrorCodes.MissingValueException: + return "20007"; + case ErrorCodes.FileSizeLimitReachedException: + return "20008"; + case ErrorCodes.OutOfMemoryException: + return "20009"; + case ErrorCodes.UnhandledException: + return "20010"; + case ErrorCodes.FileMoveException: + return "20011"; + default: + return "20010"; + } + } } } diff --git a/WEBSERVICES/ZUGFeRDRESTService/Database.cs b/WEBSERVICES/ZUGFeRDRESTService/Database.cs index c04bdb28..c7fd7940 100644 --- a/WEBSERVICES/ZUGFeRDRESTService/Database.cs +++ b/WEBSERVICES/ZUGFeRDRESTService/Database.cs @@ -14,6 +14,7 @@ namespace ZUGFeRDRESTService private DigitalData.Modules.Logging.Logger _Logger = null; private string _gdPictureKey = null; private List _propertyMapList = null; + private List _RejectionStringList = null; private LogConfig _logConfig = null; private string _connString; @@ -22,6 +23,7 @@ namespace ZUGFeRDRESTService private const string QUERY_GET_GDPICTURE_KEY = "SELECT LICENSE FROM TBDD_3RD_PARTY_MODULES WHERE NAME = 'GDPICTURE'"; private const string QUERY_GET_PROPERTY_MAP = "SELECT * FROM TBDD_ZUGFERD_XML_ITEMS WHERE ACTIVE = 1 ORDER BY XML_PATH"; + private const string QUERY_GET_REJECTION_MESSAGES = "SELECT * FROM TBDD_GUI_LANGUAGE_PHRASE WHERE CAPT_TYPE = 'RejectionCodeWeb'"; public MSSQLServer MSSQL { get; set; } @@ -85,5 +87,52 @@ namespace ZUGFeRDRESTService return _propertyMapList; } + + public List GetRejectionMessageList() + { + try + { + if (_RejectionStringList == null) + { + var oDatatable = MSSQL.GetDatatable(QUERY_GET_REJECTION_MESSAGES); + + _Logger.Debug("Datatable Rows: [{0}]", oDatatable.Rows.Count); + if (oDatatable != null && oDatatable.Rows.Count > 0) + { + _RejectionStringList = new List(); + foreach (DataRow oRow in oDatatable.Rows) + { + var newRejectionItem = new RejectionStringRow + { + Title = oRow["Title"].ToString(), + ModuleName = oRow["Module"].ToString(), + Caption = oRow["CAPT_TYPE"].ToString(), + Language = oRow["Language"].ToString(), + String1 = oRow["String1"].ToString() + }; + _RejectionStringList.Add(newRejectionItem); + } + + _Logger.Debug("Returning Rejections messages list with [{0}] entries.", _RejectionStringList.Count); + } + else + { + _RejectionStringList = null; + _Logger.Warn("No Rejections messages found in Table TBDD_GUI_LANGUAGE_PHRASE with CAPT_TYPE = 'RejectionCodeWeb'!!!"); + } + } + else + { + _Logger.Debug("Rejections messages list already exists, returning list with [{0}] entries.", _RejectionStringList.Count); + } + } + catch (Exception ex) + { + _RejectionStringList = null; + _Logger.Error("Database Error: [{0}]", ex); + } + + return _RejectionStringList; + } } } diff --git a/WEBSERVICES/ZUGFeRDRESTService/IDatabase.cs b/WEBSERVICES/ZUGFeRDRESTService/IDatabase.cs index 20e2e55d..5b1b9b76 100644 --- a/WEBSERVICES/ZUGFeRDRESTService/IDatabase.cs +++ b/WEBSERVICES/ZUGFeRDRESTService/IDatabase.cs @@ -12,5 +12,7 @@ namespace ZUGFeRDRESTService public string GetGDPictureKey(); public List GetPropertyMapList(); + + public List GetRejectionMessageList(); } } diff --git a/WEBSERVICES/ZUGFeRDRESTService/Properties/launchSettings.json b/WEBSERVICES/ZUGFeRDRESTService/Properties/launchSettings.json index 3e1562b7..01417564 100644 --- a/WEBSERVICES/ZUGFeRDRESTService/Properties/launchSettings.json +++ b/WEBSERVICES/ZUGFeRDRESTService/Properties/launchSettings.json @@ -1,4 +1,21 @@ -{ +{ + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "ZUGFeRDRESTService": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + }, "$schema": "http://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, @@ -7,24 +24,5 @@ "applicationUrl": "http://localhost:52235", "sslPort": 44388 } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "ZUGFeRDRESTService": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "api/zugferdvalidation", - "applicationUrl": "https://localhost:5001;http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } } -} +} \ No newline at end of file diff --git a/WEBSERVICES/ZUGFeRDRESTService/appsettings.Development.json b/WEBSERVICES/ZUGFeRDRESTService/appsettings.Development.json index 589fadad..b6613161 100644 --- a/WEBSERVICES/ZUGFeRDRESTService/appsettings.Development.json +++ b/WEBSERVICES/ZUGFeRDRESTService/appsettings.Development.json @@ -6,16 +6,27 @@ "Microsoft.Hosting.Lifetime": "Information" } }, + "AllowedHosts": "*", "Config": { "LogPath": "E:\\ZUGFeRDRESTService", "LogDebug": true, "Name": "ZUGFeRD REST API", - "MSSQLConnectionString": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM_TEST;User Id=sa;Password=dd;", + "MSSQLConnectionString": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;", "Firebird": { "Datasource": "172.24.12.41", "Database": "172.24.12.41:E:\\DB\\Firebird\\Databases\\EDMI_TEMPLATE\\EDMI_MASTER.FDB", "Username": "SYSDBA", "Password": "dd" - } + }, + "Zugferd": { + "AllowZugferd10": true, + "AllowZugferd2x": false, + "AllowZugferd23x": false, + "AllowFacturX": false, + "AllowXRechnung": false, + "AllowPeppolBISBill3x": false + }, + "GDPictureVersion": "", + "MaxFileSizeInMegabytes": 25 } }