context: //
  // DO NOT REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  //
  // @Authors:
  //       timop
  //
  // Copyright 2004-2016 by OM International
  //
  // This file is part of OpenPetra.org.
  //
  // OpenPetra.org is free software: you can redistribute it and/or modify
  // it under the terms of the GNU General Public License as published by
  // the Free Software Foundation, either version 3 of the License, or
  // (at your option) any later version.
  //
  // OpenPetra.org is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  // GNU General Public License for more details.
  //
  // You should have received a copy of the GNU General Public License
  // along with OpenPetra.org.  If not, see <http://www.gnu.org/licenses/>.
  //
  using System;
  using System.IO;
  using System.Data;
  using System.Windows.Forms;
  using System.Threading;
  using System.Text.RegularExpressions;
  using Ict.Common;
  using Ict.Common.Data; // Implicit reference
  using Ict.Common.Verification;
  using Ict.Common.Remoting.Shared;
  using Ict.Common.Remoting.Client;
  using Ict.Petra.Client.CommonDialogs;
  using Ict.Petra.Shared.MFinance;
  using Ict.Petra.Shared.MFinance.Account.Data;
  using Ict.Petra.Shared.MFinance.Gift.Data;
  using Ict.Petra.Plugins.Bankimport.Data;
  using Ict.Petra.Client.App.Core.RemoteObjects;
  using Ict.Petra.Plugins.Bankimport.Client;
  using GNU.Gettext;
  using Ict.Petra.Plugins.Bankimport.RemoteObjects;
  
  namespace Ict.Petra.Plugins.BankimportCAMT.Client
  {
      /// <summary>
      /// import a bank statement from a CAMT Swift file
      /// </summary>
      public class TBankStatementImport : IImportBankStatement
      {
          /// <summary>
          /// asks the user to open a csv file and imports the contents according to the config file
          /// </summary>
          /// <param name="AStatementKey">this returns the first key of a statement that was imported. depending on the implementation, several statements can be created from one file</param>
          /// <param name="ALedgerNumber">the current ledger number</param>
          /// <param name="ABankAccountCode">the bank account against which the statement should be stored</param>
          /// <returns></returns>
          public bool ImportBankStatement(out Int32 AStatementKey, Int32 ALedgerNumber, string ABankAccountCode)
          {
              AStatementKey = -1;
  
              // each time the button btnImportNewStatement is clicked, do a split and move action
              SplitFilesAndMove();
              ArchiveFilesLastMonth(ALedgerNumber);
  
  
              OpenFileDialog DialogOpen = new OpenFileDialog();
  
              DialogOpen.Filter = Catalog.GetString("bank statement CAMT (*.xml)|*.xml");
  
              if (TAppSettingsManager.HasValue("BankimportPath" + ALedgerNumber.ToString()))
              {
                  DialogOpen.InitialDirectory = TAppSettingsManager.GetValue("BankimportPath" + ALedgerNumber.ToString());
              }
              else
              {
                  DialogOpen.RestoreDirectory = true;
              }
  
              DialogOpen.Multiselect = true;
              DialogOpen.Title = Catalog.GetString("Please select the bank statement to import");
  
              if (DialogOpen.ShowDialog() != DialogResult.OK)
              {
                  return false;
              }
  
              BankImportTDS MainDS = new BankImportTDS();
  
              // import several files at once
              foreach (string BankStatementFilename in DialogOpen.FileNames)
              {
                  if (!ImportFromFile(BankStatementFilename,
                          ABankAccountCode,
                          ref MainDS))
                  {
                      return false;
                  }
              }
  
              if (MainDS.AEpStatement.Count > 0)
              {
                  foreach (AEpStatementRow stmt in MainDS.AEpStatement.Rows)
                  {
                      MainDS.AEpTransaction.DefaultView.RowFilter =
                          String.Format("{0}={1}",
                              AEpTransactionTable.GetStatementKeyDBName(),
                              stmt.StatementKey);
  
                      stmt.LedgerNumber = ALedgerNumber;
                  }
  
                  Thread t = new Thread(() => ProcessStatementsOnServer(MainDS));
  
                  using (TProgressDialog dialog = new TProgressDialog(t))
                  {
                      if (dialog.ShowDialog() == DialogResult.Cancel)
                      {
                          return false;
                      }
                      else
                      {
                          AStatementKey = FStatementKey;
                          return FStatementKey != -1;
                      }
                  }
              }
  
              return false;
          }
  
          /// <summary>
          /// this non interactive function can be used from the unit tests
          /// </summary>
          public BankImportTDS ImportBankStatementNonInteractive(Int32 ALedgerNumber, string ABankAccountCode,
              string ABankStatementFilename)
          {
              BankImportTDS MainDS = new BankImportTDS();
  
              // import file
              if (!ImportFromFile(ABankStatementFilename,
                      ABankAccountCode,
                      ref MainDS))
              {
                  return null;
              }
  
              foreach (AEpStatementRow stmt in MainDS.AEpStatement.Rows)
              {
                  stmt.LedgerNumber = ALedgerNumber;
              }
  
              return MainDS;
          }
  
          private int FStatementKey = -1;
  
          private void ProcessStatementsOnServer(BankImportTDS AMainDS)
          {
              TMBankimportNamespace PluginRemote = new TMBankimportNamespace();
  
              if (PluginRemote.WebConnectors.StoreNewBankStatement(
                      AMainDS,
                      out FStatementKey) == TSubmitChangesResult.scrOK)
              {
              }
          }
  
          /// <summary>
          /// open the file and return a typed datatable
          /// </summary>
          private bool ImportFromFile(string AFilename,
              string ABankAccountCode,
              ref BankImportTDS AMainDS)
          {
              TCAMTParser parser = new TCAMTParser();
  
              parser.ProcessFile(AFilename);
  
              Int32 statementCounter = AMainDS.AEpStatement.Rows.Count;
  
              foreach (TStatement stmt in parser.statements)
              {
                  Int32 transactionCounter = 0;
  
                  foreach (TTransaction tr in stmt.transactions)
                  {
                      BankImportTDSAEpTransactionRow row = AMainDS.AEpTransaction.NewRowTyped();
  
                      row.StatementKey = (statementCounter + 1) * -1;
                      row.Order = transactionCounter;
                      row.DetailKey = -1;
                      row.AccountName = tr.partnerName;
  
                      if ((tr.accountCode != null) && Regex.IsMatch(tr.accountCode, "^[A-Z]"))
                      {
                          // this is an iban
                          row.Iban = tr.accountCode;
                          row.Bic = tr.bankCode;
                          row.BranchCode = tr.accountCode.Substring(4, 8).TrimStart(new char[] { '0' });
                          row.BankAccountNumber = tr.accountCode.Substring(12).TrimStart(new char[] { '0' });
                      }
                      else if (tr.accountCode != null)
                      {
                          row.BankAccountNumber = tr.accountCode.TrimStart(new char[] { '0' });
                          row.BranchCode = tr.bankCode == null ? string.Empty : tr.bankCode.TrimStart(new char[] { '0' });
                          row.Iban = string.Empty;
                          row.Bic = string.Empty;
                      }
  
                      row.DateEffective = tr.valueDate;
                      row.TransactionAmount = tr.amount;
                      row.Description = tr.description;
                      row.TransactionTypeCode = tr.typecode;
  
                      // see the codes: https://www.wgzbank.de/export/sites/wgzbank/de/wgzbank/downloads/produkte_leistungen/firmenkunden/zv_aktuelles/Uebersicht-GVC-und-Buchungstexte-WGZ-BANK_V062015.pdf
                      if ((row.TransactionTypeCode == "052")
                          || (row.TransactionTypeCode == "051")
                          || (row.TransactionTypeCode == "053")
  
gt:                         || (row.TransactionTypeCode == "067")