using DigitalData.Modules.Interfaces; using Microsoft.AspNetCore.Http; 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; 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 { [Route("api/[controller]")] [ApiController] public class ValidationController : ControllerBase { public const string RESPONSE_OK = "OK"; public const string RESPONSE_ERROR = "ERROR"; 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; private readonly IDatabase _database; private readonly DigitalData.Modules.Logging.LogConfig _logConfig; private readonly DigitalData.Modules.Logging.Logger _logger; 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(); private int _MaxFileSizeInMegabytes; private bool _AllowFacturX; private bool _AllowXRechnung; private bool _AllowZugferd2x; private bool _AllowZugferd23x; private bool _AllowZugferd10; private bool _AllowPeppolBISBill3x; private string _GDPictureVersion; public ValidationController(ILogging logging, IDatabase database, IConfiguration Config) { _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 // - Zugferd files // - Filesizes ParseConfig(Config); _database = database; var oGDPictureKey = database.GetGDPictureKey(); _zugferd = new ZUGFeRDInterface(_logConfig, oGDPictureKey, new ZugferdOptions() { AllowFacturX_Filename = _AllowFacturX, AllowXRechnung_Filename = _AllowXRechnung, AllowZugferd_1_0_Schema = _AllowZugferd10, AllowZugferd_2_x_Schema = _AllowZugferd2x, AllowZugferd_2_3_x_Schema = _AllowZugferd23x, AllowPeppol_3_x_Schema = _AllowPeppolBISBill3x }); _props = new PropertyValues(_logConfig); var oPropertyMapList = database.GetPropertyMapList(); _propertyMapList.AddRange(oPropertyMapList); _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!"); } private void ParseConfig(IConfiguration Config) { var oAppConfig = Config.GetSection("Config"); var oZugferdConfig = oAppConfig.GetSection("Zugferd"); if (!bool.TryParse(oZugferdConfig["AllowFacturX"], out _AllowFacturX)) { _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}]", true); _AllowXRechnung = true; } if (!bool.TryParse(oZugferdConfig["AllowZugferd2x"], out _AllowZugferd2x)) { _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}]", true); _AllowZugferd23x = true; } if (!bool.TryParse(oZugferdConfig["AllowZugferd10"], out _AllowZugferd10)) { _logger.Info("Configuration Zugferd10 was not set. Using default value [{0}]", false); _AllowZugferd10 = false; } if (!bool.TryParse(oZugferdConfig["AllowPeppolBISBill3x"], out _AllowPeppolBISBill3x)) { _logger.Info("Configuration AllowPeppolBISBill3x was not set. Using default value [{0}]", false); _AllowPeppolBISBill3x = false; } _GDPictureVersion = oAppConfig["GDPictureVersion"]; if (string.IsNullOrEmpty(_GDPictureVersion)) { _logger.Info("Configuration GDPictureVersion was not set. Using default value [string.Empty]"); _GDPictureVersion = string.Empty; } if (!int.TryParse(oAppConfig["MaxFileSizeInMegabytes"], out _MaxFileSizeInMegabytes)) { _logger.Info("Configuration MaxFileSizeInMegabytes was not set. Using default value [{0}]", MAX_FILE_SIZE_DEFAULT); _MaxFileSizeInMegabytes = MAX_FILE_SIZE_DEFAULT; } } /// /// POST: /api/validation /// /// This parameter's name needs to correspond to the html form's file-input name /// This is the email address which the user supplied [HttpPost] public ValidationResponse Post(IFormFile file, string user_id) { _logger.Info("Start processing request to ValidationController"); ZugferdResult oZugferdResult = null; CheckPropertyValuesResult oPropertyResult = new CheckPropertyValuesResult(); try { using Stream oStream = file.OpenReadStream(); { _logger.Info("Checking Filesize of file [{0}]", file.FileName); long maxFileSize = _MaxFileSizeInMegabytes * 1024 * 1024; bool oFileSizeIsOK = file.Length < maxFileSize; if (oFileSizeIsOK == false) { throw new ZUGFeRDExecption(ErrorCodes.FileSizeLimitReachedException, _MaxFileSizeInMegabytes.ToString(), string.Empty, "FileTooBig"); } _logger.Info("Extracting ZUGFeRD Data from file [{0}]", file.FileName); if (file.FileName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase)) { oZugferdResult = _zugferd.ExtractZUGFeRDFileWithGDPicture(oStream); oZugferdResult.ReceiptFileType = "PDF"; } else if (file.FileName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase)) { // Für die Verarbeitung von XML-Belegen var oResult = new ZugferdResult() { DataFileName = file.FileName, XElementObject = XElement.Load(oStream) }; oZugferdResult = _zugferd.SerializeZUGFeRDDocument(oResult); oZugferdResult.ReceiptFileType = "XML"; } _logger.Info("Detected Specification was: [{0}]", 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(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"); var oRequiredProperties = oFilteredPropertyMap. Where(prop => { return prop.Value.IsRequired == true; }). Select(prop => { return prop.Value.Description; }). ToList(); _logger.Debug("Found [{0}] required properties", oRequiredProperties.Count); _logger.Debug(string.Join(",", oRequiredProperties.ToArray())); _logger.Info("Result of checking against the database: {0} valid properties, {1} missing properties", oPropertyResult.ValidProperties.Count, oPropertyResult.MissingProperties.Count); if (oPropertyResult.MissingProperties.Count > 0) { throw new ZUGFeRDExecption(ErrorCodes.MissingValueException, "Missing Properties"); } Tuple oValidateResult = ValidateBuyerOrderReference(oPropertyResult.ValidProperties, oZugferdResult); if (oValidateResult.Item1 == false) { throw new ZUGFeRDExecption(ErrorCodes.UnhandledException, "Unknown Error"); } string oValidateResultString = oValidateResult.Item2; 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() { status = RESPONSE_OK, message = oMessage }; } else { string oMessage = oValidateResultString; _logger.Info($"Responding with message: [{oMessage}]"); return new ValidationResponse() { status = RESPONSE_ERROR, message = oMessage }; } } } catch (ZUGFeRDExecption ex) { _logger.Error(ex); string oMessage; var oErrors = new List(); if (ex.ErrorCode != ErrorCodes.NotInUse) { 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}]"); return new ValidationResponse() { status = RESPONSE_ERROR, message = oMessage, errors = oErrors }; } catch (ValidationException ex) { _logger.Error(ex); 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.ErrorMessageDE}"; }).ToList(); return new ValidationResponse() { status = RESPONSE_ERROR, message = oMessage, errors = oErrors }; } catch (Exception ex) { _logger.Error(ex); string oMessage = "Die hochgeladene Datei kann nicht validiert werden, weil ein unbekannter Fehler aufgetreten ist."; _logger.Info($"Responding with message: [{oMessage}]"); return new ValidationResponse() { status = RESPONSE_ERROR, message = oMessage }; } } /// /// Hier wird eine externe Prozedur gerufen, PRCUST_INV_CHECK_FROM_PORTAL, /// die das Ergebnis der Referenzpruefung liefert. /// private Tuple ValidateBuyerOrderReference(List pProperties, ZugferdResult pZugferdResult) { var oMessageId = GetMessageId(); _logger.Debug("Created new MessageId: [{0}]", oMessageId); _logger.Debug("Inserting properties into database."); if (!BulkInsertDataToDatabase(oMessageId, pProperties, pZugferdResult)) { _logger.Warn("Error while Inserting properties into database!"); return new Tuple(false, string.Empty); } _logger.Debug("Calling validation prodecure."); try { using SqlCommand oCommand = new SqlCommand("PRCUST_INV_CHECK_FROM_PORTAL"); oCommand.CommandType = System.Data.CommandType.StoredProcedure; oCommand.Parameters.Clear(); oCommand.Parameters.Add("@REF_GUID", System.Data.SqlDbType.VarChar, 250).Value = oMessageId; oCommand.Parameters.Add("@MSG_OUTPUT", System.Data.SqlDbType.VarChar, 500).Direction = System.Data.ParameterDirection.Output; 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; } // 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; } } } _logger.Debug("Validation terminal Result message: " + oReturnValue); return new Tuple(true, oReturnValue); } else { return new Tuple(false, string.Empty); } } catch (Exception e) { _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 = "
      " + 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 = "
      " + 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 = "
      " + oReplaceParam1 + "
    "; _logger.Debug("oReplaceParam1-Text: " + oReplaceParam1); return oReplaceParam1; } public string GetMessageId() { return $"{Guid.NewGuid()}@{MESSAGEID_DOMAIN}"; } 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 { var delItemValueSQL = "DELETE FROM TBEDMI_ITEM_VALUE WHERE REFERENCE_GUID = '" + pMessageId + "';"; var oCommand = new SqlCommand(delItemValueSQL); 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) { _logger.Error(ex); return false; } try { var delItemFilesSQL = "DELETE FROM TBEDMI_ITEM_FILES WHERE REFERENCE_GUID = '" + pMessageId + "';"; var oCommand = new SqlCommand(delItemFilesSQL); 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) { _logger.Error(ex); return false; } return true; } /// /// 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 = 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) { _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"; } } private string GetRejectionCodeNumber(string rejectionCode) { if (rejectionCode.StartsWith("REFERENCES_Rejection_")) { var retValue = rejectionCode.Replace("REFERENCES_Rejection_", ""); return retValue; } return rejectionCode; } } }