/// <summary>
        /// This method does all the validation, retrieving data and writing to sepa and marking as handle for the given <paramref name="order"/>
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        private RefundQueueElement ProcessRefundOrder(RefundQueueElement order, Func <RefundQueueElement, CustomerInfo> httpReuest,
                                                      Action <SepaRowElement> AddToSepaCollection)
        {
            // Retrieve customer info + refund data for this order
            Task <CustomerInfo> httpRequestToMagento = Task <CustomerInfo> .Factory.StartNew(() => httpReuest(order));

            httpRequestToMagento.Wait();
            CustomerInfo customerData = httpRequestToMagento.Result;

            currentCustomer.ValidationFailures.Clear();

            // Validate customer info + refund data.
            customerData.Validate();

            // Found the correct customer!!!
            if (order.OrderID == currentCustomer.OrderID)
            {
                // if both "processingOrder" and "customerData" objects are validated,
                // Merge "processingOrder" and "customerData" in a SepaRowElement object and write to Sepa document.
                if (order.IsValid && customerData.IsValid)
                {
                    SepaRowElement sepaRow = new SepaRowElement
                    {
                        OrderDescription = order.OrderDescription,
                        OrderID          = currentCustomer.OrderID, // This customer order ID came back from Magento.
                        AccountName      = customerData.AccountName,
                        ConnectorID      = order.ConnectorID,
                        Email            = customerData.Email,
                        IBAN             = customerData.IBAN,
                        RefundAmount     = customerData.RefundAmount,
                        OrderResponseID  = order.OrderResponseID,
                        BIC     = currentCustomer.BIC,
                        Address = currentCustomer.Address,
                        Country = currentCustomer.CountryCode
                    };

                    // Log valid order data
                    if (!test)
                    {
                        TraceListenerObject.TraceInformation("OrderID: {0} description: {1}, from connector: {2}, state: {3} is being added to the Sepa collection to be processed.", order.OrderID, order.OrderDescription, order.ConnectorID, order.IsValid);
                    }

                    // Send to Sepa colllection
                    AddToSepaCollection(sepaRow);
                }
                else // Log failures
                {
                }
            }
            else
            {
                // Logging the wrong customer data is retrieved from Magento.
                if (!test)
                {
                    TraceListenerObject.TraceWarning(string.Format("Request of OrderID {0} has resulted in a Customer info mismatch. Customer info OrderID {1}.", order.OrderID, currentCustomer.OrderID));
                }
            }
            return(order);
        }
 /// <summary>
 /// This method insert an order into the RefundQueueHistory in the Concentrator Database.
 /// </summary>
 /// <param name=""></param>
 /// <returns></returns>
 private void InsertOrderHistory(RefundQueueElement order)
 {
     try
     {
         Database.Execute(InsertIntoRefundQueueHistory, order);
         TraceListenerObject.TraceInformation(string.Format("OrderID: {0} description: {1} with State: {2} is logged into the RefeundQueueHistory table", order.OrderID, order.OrderDescription, order.IsValid));
     }
     catch (Exception e)
     {
         TraceListenerObject.TraceWarning(string.Format("OrderID: {0} description: {1} with State: {2} failed to insert in the RefeundQueueHistory table", order.OrderID, order.OrderDescription, order.IsValid));
     }
 }
 /// <summary>
 /// This method deletes an order by a given orderID from the RefundQueue in the Concentrator Database.
 /// </summary>
 /// <param name=""></param>
 /// <returns></returns>
 private void RemoveRefundOrder(RefundQueueElement order)
 {
     try
     {
         Database.Execute(RemoveFromRefundQueue, order.OrderID, order.ConnectorID);
         TraceListenerObject.TraceInformation(string.Format("OrderID: {0} description: {1} with State: {2} is removed from the RefundQueue table", order.OrderID, order.OrderDescription, order.IsValid));
     }
     catch (Exception e)
     {
         TraceListenerObject.TraceWarning(string.Format("OrderID: {0} description: {1} with State: {2} failed to remove from the RefundQueue table", order.OrderID, order.OrderDescription, order.IsValid));
     }
 }
        /// <summary>
        /// Read settings from App.config
        /// </summary>
        /// <param name="key"></param>
        static string ReadSetting(string key)
        {
            string setting = string.Empty;

            try
            {
                System.Collections.Specialized.NameValueCollection appSettings = ConfigurationManager.AppSettings;
                setting = appSettings[key] ?? "Not Found";
            }
            catch (ConfigurationErrorsException)
            {
                TraceListenerObject.TraceError(string.Format("SepaExportedTask setting: {0} value: {1}", key, setting));
            }

            return(setting);
        }
        /// <summary>
        /// This method validates a specific Refund order.
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        private RefundQueueElement Validate(RefundQueueElement order)
        {
            order.Validate();

            if (!order.IsValid)
            {
                foreach (var errors in order.ValidationFailures)
                {
                    foreach (var member in errors.MemberNames)
                    {
                        TraceListenerObject.TraceInformation(string.Format("Member: {0} from sepa Order: {1} did not pass validation, reason: {2}", member, order.OrderID, errors.ErrorMessage));
                    }
                }
            }
            return(order);
        }
        /// <summary>
        /// Validate generated sepa document according Pain.xsd.
        /// </summary>
        public void ValidateSepaDoc(string sepaPath, string xsdPath)
        {
            XmlSchemaSet schemas = new XmlSchemaSet();

            schemas.Add(sepaPath, xsdPath);

            try
            {
                XDocument validateDoc = XDocument.Load(sepaPath);
                validateDoc.Validate(schemas, ValidationEventhandler, true);
                TraceListenerObject.TraceInformation(string.Format("Validating {0} based on {1} succeeded.", sepaPath, xsdPath));
            }
            catch (Exception e)
            {
                TraceListenerObject.TraceWarning(string.Format("There was no Sepa document found, validation process is aborted, {0}, {1}", e.Message, e.InnerException));
            }
        }
        /// <summary>
        /// Save sepa document to file system.
        /// </summary>
        /// <param name="sepaPath"></param>
        public void SaveSepaDoc(string sepaPath)
        {
            if (xdoc == null)
            {
                TraceListenerObject.TraceWarning(string.Format("There were no orders found in the queue, Sepa document could is not being generated."));
                return;
            }

            try
            {
                xdoc.Save(sepaPath);
                TraceListenerObject.TraceInformation(string.Format("Saving {0} succeeded.", sepaPath));
            }
            catch (Exception e)
            {
                TraceListenerObject.TraceWarning(string.Format("During saving the Sepa document an exception occured, saving process is aborted, {0}, {1}", e.Message, e.InnerException));
            }
        }
        //=========================================================================
        // Private routines (private methods)
        //=========================================================================

        #region Private routines

        /// <summary>
        /// This method validates a specific Refund order.
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        private CustomerInfo Validate(CustomerInfo customer)
        {
            customer.Validate();
            if (!test)
            {
                if (!customer.IsValid)
                {
                    foreach (var errors in customer.ValidationFailures)
                    {
                        foreach (var member in errors.MemberNames)
                        {
                            TraceListenerObject.TraceInformation(string.Format("Member: {0} from customer info: {1} did not pass validation, reason: {2}", member, customer.OrderID, errors.ErrorMessage));
                        }
                    }
                }
            }
            return(customer);
        }
        /// <summary>
        /// This method generates the complete Sepa document.
        /// </summary>
        public void GenerateSepa()
        {
            if (ValidatedSepaData.Count == 0)
            {
                if (!test)
                {
                    TraceListenerObject.TraceWarning(string.Format("The SepaExporterTask initiated generating a Sepa document, but {0} are found", ValidatedSepaData.Count));
                }
                return;
            }

            xdoc = GenerateSepaDocument(XmlDocumentDescription);
            XElement   body        = new XElement(BodyElement);
            XElement   headerGroup = GenerateHeaderGroup();
            XNamespace ns          = SepaNameSpace;

            var DebitGroup = GenerateDebtorGroup();

            // Add Crediters (Customers) to Debit Group (Coolcat)
            var enumerator = ValidatedSepaData.GetEnumerator();

            while (enumerator.MoveNext())
            {
                try
                {
                    XElement CreditGroup = GenerateCreditGroup(enumerator.Current);
                    DebitGroup.Add(CreditGroup);
                }
                catch (Exception)
                {
                    TraceListenerObject.TraceWarning(string.Format("Failed to add Separow with oderID: {0} to Sepa document.", enumerator.Current.OrderID));
                    Action a = () => { FailedToWriteOrder(this, new WriteSepaOrderEventArgs(enumerator.Current)); };
                    a.Invoke();
                }
            }

            ValidatedSepaData.Clear();
            headerGroup.Add(DebitGroup);
            body.Add(headerGroup);
            xdoc.Add(body);
        }