Compare commits

...

3 Commits

6 changed files with 249 additions and 62 deletions

View File

@ -1,9 +1,10 @@
Imports System.Globalization Imports System.IO
Imports System.IO Imports System.Reflection
Imports System.Security.Cryptography Imports System.Security.Cryptography
Imports DigitalData.Modules.Config Imports DigitalData.Modules.Config
Imports DigitalData.Modules.Database Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Interfaces Imports DigitalData.Modules.Interfaces
Imports DigitalData.Modules.Interfaces.ZUGFeRDInterface
Imports DigitalData.Modules.Jobs Imports DigitalData.Modules.Jobs
Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Logging
@ -154,6 +155,10 @@ Public Class Form1
Dim oDoc = _zugferd.ValidateZUGFeRDFileWithGDPicture(OpenFileDialog1.FileName) Dim oDoc = _zugferd.ValidateZUGFeRDFileWithGDPicture(OpenFileDialog1.FileName)
Dim oZUGFERD = _zugferd.SerializeZUGFeRDDocument(oDoc) Dim oZUGFERD = _zugferd.SerializeZUGFeRDDocument(oDoc)
Console.WriteLine() Console.WriteLine()
Catch ex As DigitalData.Modules.Interfaces.Exceptions.ZUGFeRDExecption
Dim oErrorCode = GetRejectionCodeNumber(ex.ErrorCode)
Dim oMessage = oErrorCode + " - (" + ex.ErrorCode.ToString() + ") - " + ex.Message
MsgBox(oMessage, MsgBoxStyle.OkOnly, "ZUGFeRDExecption")
Catch ex As Exception Catch ex As Exception
MsgBox(ex.Message) MsgBox(ex.Message)
End Try End Try
@ -207,7 +212,9 @@ Public Class Form1
Dim oArgs As New WorkerArgs() With { Dim oArgs As New WorkerArgs() With {
.AllowFacturX = True, .AllowFacturX = True,
.AllowXRechnung = True, .AllowXRechnung = True,
.AllowPeppolBISBill3x = True .AllowPeppolBISBill3x = True,
.AllowZugferd23x = True,
.AllowZugferd2x = True
} }
oArgs = LoadPropertyMapListFor(oArgs) oArgs = LoadPropertyMapListFor(oArgs)
@ -242,6 +249,7 @@ Public Class Form1
End If End If
Next Next
WriteLog("--------------------------------")
WriteLog("Missing Properties: [{0}]", oResult2.MissingProperties.Count) WriteLog("Missing Properties: [{0}]", oResult2.MissingProperties.Count)
For Each Prop In oResult2.MissingProperties For Each Prop In oResult2.MissingProperties
WriteLog("Missing Property: [{0}]", Prop.ToString) ''Prop.Description WriteLog("Missing Property: [{0}]", Prop.ToString) ''Prop.Description
@ -249,6 +257,10 @@ Public Class Form1
WriteLog("--------------------------------") WriteLog("--------------------------------")
End If End If
Catch ex As DigitalData.Modules.Interfaces.Exceptions.ZUGFeRDExecption
Dim oErrorCode = GetRejectionCodeNumber(ex.ErrorCode)
Dim oMessage = oErrorCode + " - (" + ex.ErrorCode.ToString() + ") - " + ex.Message
MsgBox(oMessage, MsgBoxStyle.OkOnly, "ZUGFeRDExecption")
Catch ex As Exception Catch ex As Exception
MsgBox(ex.Message) MsgBox(ex.Message)
End Try End Try
@ -331,5 +343,34 @@ Public Class Form1
End Sub End Sub
Private Function GetRejectionCodeNumber(pErrorCode As ErrorCodes) As String
Select Case pErrorCode
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"
Case Else
Return "20010"
End Select
End Function
End Class End Class

View File

@ -12,6 +12,7 @@ using System.Data.SqlClient;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using System.Xml.Linq; using System.Xml.Linq;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Text.RegularExpressions;
namespace ZUGFeRDRESTService.Controllers namespace ZUGFeRDRESTService.Controllers
{ {
@ -37,6 +38,7 @@ namespace ZUGFeRDRESTService.Controllers
private readonly PropertyValues _props; private readonly PropertyValues _props;
//private readonly Dictionary<string, XmlItemProperty> _propertyMap = new Dictionary<string, XmlItemProperty>(); //private readonly Dictionary<string, XmlItemProperty> _propertyMap = new Dictionary<string, XmlItemProperty>();
private readonly List<XmlItemProperty> _propertyMapList = new List<XmlItemProperty>(); private readonly List<XmlItemProperty> _propertyMapList = new List<XmlItemProperty>();
private readonly List<RejectionStringRow> _RecjectionMessageList = new List<RejectionStringRow>();
private int _MaxFileSizeInMegabytes; private int _MaxFileSizeInMegabytes;
private bool _AllowFacturX; private bool _AllowFacturX;
@ -79,6 +81,8 @@ namespace ZUGFeRDRESTService.Controllers
_propertyMapList.AddRange(oPropertyMapList); _propertyMapList.AddRange(oPropertyMapList);
_logger.Debug("Property Map list initial: [{0}] entries found. [{1}] entries will be available.", oPropertyMapList.Count, _propertyMapList.Count); _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!"); _logger.Debug("Validation Controller initialized!");
} }
@ -89,32 +93,32 @@ namespace ZUGFeRDRESTService.Controllers
if (!bool.TryParse(oZugferdConfig["AllowFacturX"], out _AllowFacturX)) if (!bool.TryParse(oZugferdConfig["AllowFacturX"], out _AllowFacturX))
{ {
_logger.Info("Configuration AllowFacturX was not set. Using default value [{0}]", false); _logger.Info("Configuration AllowFacturX was not set. Using default value [{0}]", true);
_AllowFacturX = false; _AllowFacturX = true;
} }
if (!bool.TryParse(oZugferdConfig["AllowXRechnung"], out _AllowXRechnung)) if (!bool.TryParse(oZugferdConfig["AllowXRechnung"], out _AllowXRechnung))
{ {
_logger.Info("Configuration AllowXRechnung was not set. Using default value [{0}]", false); _logger.Info("Configuration AllowXRechnung was not set. Using default value [{0}]", true);
_AllowXRechnung = false; _AllowXRechnung = true;
} }
if (!bool.TryParse(oZugferdConfig["AllowZugferd2x"], out _AllowZugferd2x)) if (!bool.TryParse(oZugferdConfig["AllowZugferd2x"], out _AllowZugferd2x))
{ {
_logger.Info("Configuration Zugferd2x was not set. Using default value [{0}]", false); _logger.Info("Configuration Zugferd2x was not set. Using default value [{0}]", true);
_AllowZugferd2x = false; _AllowZugferd2x = true;
} }
if (!bool.TryParse(oZugferdConfig["AllowZugferd23x"], out _AllowZugferd23x)) if (!bool.TryParse(oZugferdConfig["AllowZugferd23x"], out _AllowZugferd23x))
{ {
_logger.Info("Configuration Zugferd23x was not set. Using default value [{0}]", false); _logger.Info("Configuration Zugferd23x was not set. Using default value [{0}]", true);
_AllowZugferd23x = false; _AllowZugferd23x = true;
} }
if (!bool.TryParse(oZugferdConfig["AllowZugferd10"], out _AllowZugferd10)) if (!bool.TryParse(oZugferdConfig["AllowZugferd10"], out _AllowZugferd10))
{ {
_logger.Info("Configuration Zugferd10 was not set. Using default value [{0}]", true); _logger.Info("Configuration Zugferd10 was not set. Using default value [{0}]", false);
_AllowZugferd10 = true; _AllowZugferd10 = false;
} }
if (!bool.TryParse(oZugferdConfig["AllowPeppolBISBill3x"], out _AllowPeppolBISBill3x)) if (!bool.TryParse(oZugferdConfig["AllowPeppolBISBill3x"], out _AllowPeppolBISBill3x))
@ -161,7 +165,8 @@ namespace ZUGFeRDRESTService.Controllers
if (oFileSizeIsOK == false) 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); _logger.Info("Extracting ZUGFeRD Data from file [{0}]", file.FileName);
@ -189,7 +194,8 @@ namespace ZUGFeRDRESTService.Controllers
if (oFilteredPropertyMap.Count == 0) if (oFilteredPropertyMap.Count == 0)
{ {
_logger.Warn("No properties found in property map for specification [{0}]", oZugferdResult.Specification); _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 else
{ {
@ -213,14 +219,16 @@ namespace ZUGFeRDRESTService.Controllers
if (oPropertyResult.MissingProperties.Count > 0) 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<bool, string> oValidateResult = ValidateBuyerOrderReference(oPropertyResult.ValidProperties); Tuple<bool, string> oValidateResult = ValidateBuyerOrderReference(oPropertyResult.ValidProperties);
if (oValidateResult.Item1 == false) 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; string oValidateResultString = oValidateResult.Item2;
@ -254,28 +262,46 @@ namespace ZUGFeRDRESTService.Controllers
{ {
_logger.Error(ex); _logger.Error(ex);
// Determine which message should be sent in the response string oMessage;
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
var oErrors = new List<string>(); var oErrors = new List<string>();
switch (ex.ErrorType) if (ex.ErrorCode != ErrorCodes.NotInUse)
{ {
case ErrorType.MissingProperties: var rejectionCodeNumber = this.GetRejectionCodeNumber(ex.ErrorCode);
oErrors.AddRange(from item in oPropertyResult.MissingProperties
select item.Description); // Der gesamte Ausgabetext muss anhand des ErrorCodes ermittelt werden
break; oMessage = this.GetRejectionMessage(rejectionCodeNumber);
default:
break; // 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}]"); _logger.Info($"Responding with message: [{oMessage}]");
@ -289,10 +315,14 @@ namespace ZUGFeRDRESTService.Controllers
} }
catch (ValidationException ex) 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<string> oErrors = ex.ValidationErrors.Select(e => List<string> 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(); }).ToList();
return new ValidationResponse() return new ValidationResponse()
@ -422,5 +452,61 @@ namespace ZUGFeRDRESTService.Controllers
} }
} }
/// <summary>
/// Ermittelt die Ausgabe-nachricht für einen Fehlercode
/// </summary>
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";
}
}
} }
} }

View File

@ -14,6 +14,7 @@ namespace ZUGFeRDRESTService
private DigitalData.Modules.Logging.Logger _Logger = null; private DigitalData.Modules.Logging.Logger _Logger = null;
private string _gdPictureKey = null; private string _gdPictureKey = null;
private List<XmlItemProperty> _propertyMapList = null; private List<XmlItemProperty> _propertyMapList = null;
private List<RejectionStringRow> _RejectionStringList = null;
private LogConfig _logConfig = null; private LogConfig _logConfig = null;
private string _connString; 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_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_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; } public MSSQLServer MSSQL { get; set; }
@ -85,5 +87,52 @@ namespace ZUGFeRDRESTService
return _propertyMapList; return _propertyMapList;
} }
public List<RejectionStringRow> 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<RejectionStringRow>();
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;
}
} }
} }

View File

@ -12,5 +12,7 @@ namespace ZUGFeRDRESTService
public string GetGDPictureKey(); public string GetGDPictureKey();
public List<XmlItemProperty> GetPropertyMapList(); public List<XmlItemProperty> GetPropertyMapList();
public List<RejectionStringRow> GetRejectionMessageList();
} }
} }

View File

@ -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", "$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": { "iisSettings": {
"windowsAuthentication": false, "windowsAuthentication": false,
@ -7,24 +24,5 @@
"applicationUrl": "http://localhost:52235", "applicationUrl": "http://localhost:52235",
"sslPort": 44388 "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"
}
}
} }
} }

View File

@ -6,16 +6,27 @@
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
}, },
"AllowedHosts": "*",
"Config": { "Config": {
"LogPath": "E:\\ZUGFeRDRESTService", "LogPath": "E:\\ZUGFeRDRESTService",
"LogDebug": true, "LogDebug": true,
"Name": "ZUGFeRD REST API", "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": { "Firebird": {
"Datasource": "172.24.12.41", "Datasource": "172.24.12.41",
"Database": "172.24.12.41:E:\\DB\\Firebird\\Databases\\EDMI_TEMPLATE\\EDMI_MASTER.FDB", "Database": "172.24.12.41:E:\\DB\\Firebird\\Databases\\EDMI_TEMPLATE\\EDMI_MASTER.FDB",
"Username": "SYSDBA", "Username": "SYSDBA",
"Password": "dd" "Password": "dd"
} },
"Zugferd": {
"AllowZugferd10": true,
"AllowZugferd2x": false,
"AllowZugferd23x": false,
"AllowFacturX": false,
"AllowXRechnung": false,
"AllowPeppolBISBill3x": false
},
"GDPictureVersion": "",
"MaxFileSizeInMegabytes": 25
} }
} }