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 DigitalData.Modules.Config
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Interfaces
Imports DigitalData.Modules.Interfaces.ZUGFeRDInterface
Imports DigitalData.Modules.Jobs
Imports DigitalData.Modules.Logging
@ -154,6 +155,10 @@ Public Class Form1
Dim oDoc = _zugferd.ValidateZUGFeRDFileWithGDPicture(OpenFileDialog1.FileName)
Dim oZUGFERD = _zugferd.SerializeZUGFeRDDocument(oDoc)
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
MsgBox(ex.Message)
End Try
@ -207,7 +212,9 @@ Public Class Form1
Dim oArgs As New WorkerArgs() With {
.AllowFacturX = True,
.AllowXRechnung = True,
.AllowPeppolBISBill3x = True
.AllowPeppolBISBill3x = True,
.AllowZugferd23x = True,
.AllowZugferd2x = True
}
oArgs = LoadPropertyMapListFor(oArgs)
@ -242,6 +249,7 @@ Public Class Form1
End If
Next
WriteLog("--------------------------------")
WriteLog("Missing Properties: [{0}]", oResult2.MissingProperties.Count)
For Each Prop In oResult2.MissingProperties
WriteLog("Missing Property: [{0}]", Prop.ToString) ''Prop.Description
@ -249,6 +257,10 @@ Public Class Form1
WriteLog("--------------------------------")
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
MsgBox(ex.Message)
End Try
@ -331,5 +343,34 @@ Public Class Form1
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

View File

@ -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<string, XmlItemProperty> _propertyMap = new Dictionary<string, XmlItemProperty>();
private readonly List<XmlItemProperty> _propertyMapList = new List<XmlItemProperty>();
private readonly List<RejectionStringRow> _RecjectionMessageList = new List<RejectionStringRow>();
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<bool, string> 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<string>();
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<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();
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 string _gdPictureKey = null;
private List<XmlItemProperty> _propertyMapList = null;
private List<RejectionStringRow> _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<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 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",
"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"
}
}
}
}
}

View File

@ -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
}
}